1450N/A/*
1450N/A * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
1450N/A */
1450N/A
1450N/A/*
1450N/A * Copyright (c) 2012, 2013, Intel Corporation. All rights reserved.
1450N/A */
1450N/A
1450N/A/*
1450N/A * Copyright © 2007 David Airlie
1450N/A *
1450N/A * Permission is hereby granted, free of charge, to any person obtaining a
1450N/A * copy of this software and associated documentation files (the "Software"),
1450N/A * to deal in the Software without restriction, including without limitation
1450N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1450N/A * and/or sell copies of the Software, and to permit persons to whom the
1450N/A * Software is furnished to do so, subject to the following conditions:
1450N/A *
1450N/A * The above copyright notice and this permission notice (including the next
1450N/A * paragraph) shall be included in all copies or substantial portions of the
1450N/A * Software.
1450N/A *
1450N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1450N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1450N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1450N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1450N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1450N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1450N/A * DEALINGS IN THE SOFTWARE.
1450N/A *
1450N/A * Authors:
1450N/A * David Airlie
1450N/A */
1450N/A
1450N/A#include "drmP.h"
1450N/A#include "drm.h"
1450N/A#include "drm_crtc.h"
1450N/A#include "drm_fb_helper.h"
1450N/A#include "intel_drv.h"
1450N/A#include "i915_drm.h"
1450N/A#include "i915_drv.h"
1450N/A
1450N/Astatic int intelfb_create(struct drm_fb_helper *helper,
1450N/A struct drm_fb_helper_surface_size *sizes)
1450N/A{
1450N/A struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper;
1450N/A struct drm_device *dev = ifbdev->helper.dev;
1450N/A struct drm_i915_private *dev_priv = dev->dev_private;
1450N/A struct drm_framebuffer *fb;
1450N/A struct drm_mode_fb_cmd2 mode_cmd;
1450N/A struct drm_i915_gem_object *obj;
1450N/A int size, ret;
1450N/A
1450N/A /* we don't do packed 24bpp */
1450N/A if (sizes->surface_bpp == 24)
1450N/A sizes->surface_bpp = 32;
1450N/A
1450N/A (void) memset(&mode_cmd, 0, sizeof(struct drm_mode_fb_cmd2));
1450N/A
1450N/A mode_cmd.width = sizes->surface_width;
1450N/A mode_cmd.height = sizes->surface_height;
1450N/A
1450N/A mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) /
1450N/A 8), 64);
1450N/A mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
1450N/A sizes->surface_depth);
1450N/A
1450N/A size = mode_cmd.pitches[0] * mode_cmd.height;
1450N/A size = ALIGN(size, PAGE_SIZE);
1450N/A
1450N/A obj = dev_priv->fbcon_obj;
1450N/A
1450N/A if (!obj) {
1450N/A DRM_ERROR("There is no framebuffer for console");
1450N/A ret = -ENOMEM;
1450N/A goto out;
1450N/A }
1450N/A
1450N/A mutex_lock(&dev->struct_mutex);
1450N/A
1450N/A ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
1450N/A if (ret)
1450N/A goto out_unpin;
1450N/A
1450N/A fb = &ifbdev->ifb.base;
1450N/A
1450N/A ifbdev->helper.fb = fb;
1450N/A
1450N/A mutex_unlock(&dev->struct_mutex);
1450N/A
1450N/A return 0;
1450N/A
1450N/Aout_unpin:
1450N/A i915_gem_object_unpin(obj);
1450N/Aout_unref:
1450N/A drm_gem_object_unreference(&obj->base);
1450N/A mutex_unlock(&dev->struct_mutex);
1450N/Aout:
1450N/A return ret;
1450N/A}
1450N/A
1450N/Astatic struct drm_fb_helper_funcs intel_fb_helper_funcs = {
1450N/A .gamma_set = intel_crtc_fb_gamma_set,
1450N/A .gamma_get = intel_crtc_fb_gamma_get,
1450N/A .fb_probe = intelfb_create,
1450N/A};
1450N/A
1450N/Astatic void intel_fbdev_destroy(struct drm_device *dev,
1450N/A struct intel_fbdev *ifbdev)
1450N/A{
1450N/A struct intel_framebuffer *ifb = &ifbdev->ifb;
1450N/A
1450N/A drm_fb_helper_fini(&ifbdev->helper);
1450N/A
1450N/A drm_framebuffer_unregister_private(&ifb->base);
1450N/A drm_framebuffer_cleanup(&ifb->base);
1450N/A if (ifb->obj) {
1450N/A drm_gem_object_unreference_unlocked(&ifb->obj->base);
1450N/A ifb->obj = NULL;
1450N/A }
1450N/A}
1450N/A
1450N/Aint intel_fbdev_init(struct drm_device *dev)
1450N/A{
1450N/A struct intel_fbdev *ifbdev;
1450N/A struct drm_i915_private *dev_priv = dev->dev_private;
1450N/A int ret;
1450N/A
1450N/A ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
1450N/A if (!ifbdev)
1450N/A return -ENOMEM;
1450N/A
1450N/A dev_priv->fbdev = ifbdev;
1450N/A ifbdev->helper.funcs = &intel_fb_helper_funcs;
1450N/A
1450N/A ret = drm_fb_helper_init(dev, &ifbdev->helper,
1450N/A INTEL_INFO(dev)->num_pipes,
1450N/A INTELFB_CONN_LIMIT);
1450N/A if (ret) {
1450N/A kfree(ifbdev, sizeof(struct intel_fbdev));
1450N/A return ret;
1450N/A }
1450N/A
1450N/A (void) drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
1450N/A return 0;
1450N/A}
1450N/A
1450N/Avoid intel_fbdev_initial_config(struct drm_device *dev)
1450N/A{
1450N/A struct drm_i915_private *dev_priv = dev->dev_private;
1450N/A
1450N/A /* Due to peculiar init order wrt to hpd handling this is separate. */
1450N/A (void) drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 16);
1450N/A}
1450N/A
1450N/Avoid intel_fbdev_fini(struct drm_device *dev)
1450N/A{
1450N/A struct drm_i915_private *dev_priv = dev->dev_private;
1450N/A if (!dev_priv->fbdev)
1450N/A return;
1450N/A
1450N/A intel_fbdev_destroy(dev, dev_priv->fbdev);
1450N/A kfree(dev_priv->fbdev, sizeof(struct intel_fbdev));
1450N/A dev_priv->fbdev = NULL;
1450N/A}
1450N/A
1450N/Avoid intel_fb_output_poll_changed(struct drm_device *dev)
1450N/A{
1450N/A struct drm_i915_private *dev_priv = dev->dev_private;
1450N/A if (dev_priv->fbdev != NULL)
1450N/A (void) drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
1450N/A}
1450N/A
1450N/Avoid intel_fb_restore_mode(struct drm_device *dev)
1450N/A{
1450N/A int ret;
1450N/A struct drm_i915_private *dev_priv = dev->dev_private;
1450N/A
1450N/A if (INTEL_INFO(dev)->num_pipes == 0)
1450N/A return;
1450N/A
1450N/A drm_modeset_lock_all(dev);
1450N/A
1450N/A ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
1450N/A if (ret)
1450N/A DRM_DEBUG("failed to restore crtc mode\n");
1450N/A
1450N/A drm_modeset_unlock_all(dev);
1450N/A}