From patchwork Sun Jun 16 14:57:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 2728421 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CAA0A9F39E for ; Sun, 16 Jun 2013 14:40:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 349AC20169 for ; Sun, 16 Jun 2013 14:40:18 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 5D6842016B for ; Sun, 16 Jun 2013 14:40:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 41DA7E5EE3 for ; Sun, 16 Jun 2013 07:40:16 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-ea0-f178.google.com (mail-ea0-f178.google.com [209.85.215.178]) by gabe.freedesktop.org (Postfix) with ESMTP id 7FE85E5D58 for ; Sun, 16 Jun 2013 07:35:56 -0700 (PDT) Received: by mail-ea0-f178.google.com with SMTP id l15so1243127eak.23 for ; Sun, 16 Jun 2013 07:35:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=4TnoaMz6sPL4eACCgViMs/2OJk6LhqkEe/krAoFgI7g=; b=b3FAut2TjD2wV1P6eiVlF/novOWWfYnpt64JRVYlSQlu3RM9bJYRQ4T2gzZG53Zian Qq2fMfkyhFa+qdL29gowmL+VwhHmVhcr/abPJGNoX2A38b/5ce8m6fZJzL8hmjZQg6mH ItxMcT8GuJXML7WmYNyAtH9B/u6zrcJUV02VI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=4TnoaMz6sPL4eACCgViMs/2OJk6LhqkEe/krAoFgI7g=; b=NeLyntJJsQlvqLDsyhwRLyzldrmP1mXmiwHvf3Cf+F6aEIV2YhDZuDlABUFrKO8BfF JK0ADh/6H3OQA9thISFzs0nezq11njQ6Y02ue0likc/Mx70uiuNO7Wr2MFW8hZY8cCuN EXzbofwqw5PqI/DHV845QIUA9o2iKMTlCAe1fFtoEbtkYYfFgS1plU8e/Upi6ALRfhIr /Hn533GqyN/8qVFRauYUO9cZ5FhVserjZWIv/lxuoHTX7u8V96orkaJvbttM04i97BF3 cUHJd2ExGWBHDkpath6ciNOLz1LXKdJohmxyalS+Uypb1UUD7uv92TGDnEk276a6r28O 8kSQ== X-Received: by 10.14.149.141 with SMTP id x13mr12384838eej.77.1371393355623; Sun, 16 Jun 2013 07:35:55 -0700 (PDT) Received: from hummel.ffwll.local (178-83-130-250.dynamic.hispeed.ch. [178.83.130.250]) by mx.google.com with ESMTPSA id u11sm17179573eev.12.2013.06.16.07.35.54 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 16 Jun 2013 07:35:54 -0700 (PDT) From: Daniel Vetter To: DRI Development Date: Sun, 16 Jun 2013 16:57:20 +0200 Message-Id: <1371394640-1130-4-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1371394640-1130-1-git-send-email-daniel.vetter@ffwll.ch> References: <1371394640-1130-1-git-send-email-daniel.vetter@ffwll.ch> MIME-Version: 1.0 X-Gm-Message-State: ALoCoQklBYWGe4NUK+10jrl/2dC4+fR8J+JHt6TaXK+WRkF4UcnAzVAhDf4/okqPzwOTvOe1N4gI Cc: Daniel Vetter , Intel Graphics Development Subject: [Intel-gfx] =?utf-8?q?=5BPATCH_3/3=5D_drm/i915=3A_rename_intel=5F?= =?utf-8?q?fb=2Ec_to_intel=5Ffbdev=2Ec?= X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This file is all about the legacy fbdev support. If we want to extract framebuffer functions, we better put those into a separate file. Also rename functions accordingly, only two have used the intel_fb_ prefix anyway. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 4 +- drivers/gpu/drm/i915/intel_drv.h | 6 +- drivers/gpu/drm/i915/intel_fb.c | 314 ----------------------------------- drivers/gpu/drm/i915/intel_fbdev.c | 314 +++++++++++++++++++++++++++++++++++ 6 files changed, 321 insertions(+), 321 deletions(-) delete mode 100644 drivers/gpu/drm/i915/intel_fb.c create mode 100644 drivers/gpu/drm/i915/intel_fbdev.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 0ed990e..8c67e48 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -48,7 +48,7 @@ i915-$(CONFIG_COMPAT) += i915_ioc32.o i915-$(CONFIG_ACPI) += intel_acpi.o -i915-$(CONFIG_DRM_I915_FBDEV) += intel_fb.o +i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o obj-$(CONFIG_DRM_I915) += i915.o diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a2cbe29..c612536 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1823,7 +1823,7 @@ void i915_driver_lastclose(struct drm_device * dev) return; if (drm_core_check_feature(dev, DRIVER_MODESET)) { - intel_fb_restore_mode(dev); + intel_fbdev_restore_mode(dev); vga_switcheroo_process_delayed_switch(); return; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2ab939b9..326861f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9172,14 +9172,14 @@ intel_user_framebuffer_create(struct drm_device *dev, } #ifndef CONFIG_DRM_I915_FBDEV -static inline void intel_fb_output_poll_changed(struct drm_device *dev) +static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) { } #endif static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_create = intel_user_framebuffer_create, - .output_poll_changed = intel_fb_output_poll_changed, + .output_poll_changed = intel_fbdev_output_poll_changed, }; /* Set up chip specific display functions */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8bcb8d3..e845ce2 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -840,8 +840,8 @@ extern int intel_fbdev_init(struct drm_device *dev); extern void intel_fbdev_initial_config(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev); extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); -extern void intel_fb_output_poll_changed(struct drm_device *dev); -extern void intel_fb_restore_mode(struct drm_device *dev); +extern void intel_fbdev_output_poll_changed(struct drm_device *dev); +extern void intel_fbdev_restore_mode(struct drm_device *dev); #else static inline int intel_fbdev_init(struct drm_device *dev) { @@ -860,7 +860,7 @@ static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state) { } -static inline void intel_fb_restore_mode(struct drm_device *dev) +static inline void intel_fbdev_restore_mode(struct drm_device *dev) { } #endif diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c deleted file mode 100644 index 244060a..0000000 --- a/drivers/gpu/drm/i915/intel_fb.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright © 2007 David Airlie - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * David Airlie - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "intel_drv.h" -#include -#include "i915_drv.h" - -static struct fb_ops intelfb_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, - .fb_debug_enter = drm_fb_helper_debug_enter, - .fb_debug_leave = drm_fb_helper_debug_leave, -}; - -static int intelfb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct intel_fbdev *ifbdev = - container_of(helper, struct intel_fbdev, helper); - struct drm_device *dev = helper->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct fb_info *info; - struct drm_framebuffer *fb; - struct drm_mode_fb_cmd2 mode_cmd = {}; - struct drm_i915_gem_object *obj; - struct device *device = &dev->pdev->dev; - int size, ret; - - /* we don't do packed 24bpp */ - if (sizes->surface_bpp == 24) - sizes->surface_bpp = 32; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / - 8), 64); - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - size = mode_cmd.pitches[0] * mode_cmd.height; - size = ALIGN(size, PAGE_SIZE); - obj = i915_gem_object_create_stolen(dev, size); - if (obj == NULL) - obj = i915_gem_alloc_object(dev, size); - if (!obj) { - DRM_ERROR("failed to allocate framebuffer\n"); - ret = -ENOMEM; - goto out; - } - - mutex_lock(&dev->struct_mutex); - - /* Flush everything out, we'll be doing GTT only from now on */ - ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); - if (ret) { - DRM_ERROR("failed to pin fb: %d\n", ret); - goto out_unref; - } - - info = framebuffer_alloc(0, device); - if (!info) { - ret = -ENOMEM; - goto out_unpin; - } - - info->par = helper; - - ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); - if (ret) - goto out_unpin; - - fb = &ifbdev->ifb.base; - - ifbdev->helper.fb = fb; - ifbdev->helper.fbdev = info; - - strcpy(info->fix.id, "inteldrmfb"); - - info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; - info->fbops = &intelfb_ops; - - ret = fb_alloc_cmap(&info->cmap, 256, 0); - if (ret) { - ret = -ENOMEM; - goto out_unpin; - } - /* setup aperture base/size for vesafb takeover */ - info->apertures = alloc_apertures(1); - if (!info->apertures) { - ret = -ENOMEM; - goto out_unpin; - } - info->apertures->ranges[0].base = dev->mode_config.fb_base; - info->apertures->ranges[0].size = dev_priv->gtt.mappable_end; - - info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; - info->fix.smem_len = size; - - info->screen_base = - ioremap_wc(dev_priv->gtt.mappable_base + obj->gtt_offset, - size); - if (!info->screen_base) { - ret = -ENOSPC; - goto out_unpin; - } - info->screen_size = size; - - /* This driver doesn't need a VT switch to restore the mode on resume */ - info->skip_vt_switch = true; - - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); - - /* If the object is shmemfs backed, it will have given us zeroed pages. - * If the object is stolen however, it will be full of whatever - * garbage was left in there. - */ - if (ifbdev->ifb.obj->stolen) - memset_io(info->screen_base, 0, info->screen_size); - - /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ - - DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", - fb->width, fb->height, - obj->gtt_offset, obj); - - - mutex_unlock(&dev->struct_mutex); - vga_switcheroo_client_fb_set(dev->pdev, info); - return 0; - -out_unpin: - i915_gem_object_unpin(obj); -out_unref: - drm_gem_object_unreference(&obj->base); - mutex_unlock(&dev->struct_mutex); -out: - return ret; -} - -static struct drm_fb_helper_funcs intel_fb_helper_funcs = { - .gamma_set = intel_crtc_fb_gamma_set, - .gamma_get = intel_crtc_fb_gamma_get, - .fb_probe = intelfb_create, -}; - -static void intel_fbdev_destroy(struct drm_device *dev, - struct intel_fbdev *ifbdev) -{ - struct fb_info *info; - struct intel_framebuffer *ifb = &ifbdev->ifb; - - if (ifbdev->helper.fbdev) { - info = ifbdev->helper.fbdev; - unregister_framebuffer(info); - iounmap(info->screen_base); - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } - - drm_fb_helper_fini(&ifbdev->helper); - - drm_framebuffer_unregister_private(&ifb->base); - drm_framebuffer_cleanup(&ifb->base); - if (ifb->obj) { - drm_gem_object_unreference_unlocked(&ifb->obj->base); - ifb->obj = NULL; - } -} - -int intel_fbdev_init(struct drm_device *dev) -{ - struct intel_fbdev *ifbdev; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); - if (!ifbdev) - return -ENOMEM; - - dev_priv->fbdev = ifbdev; - ifbdev->helper.funcs = &intel_fb_helper_funcs; - - ret = drm_fb_helper_init(dev, &ifbdev->helper, - INTEL_INFO(dev)->num_pipes, - INTELFB_CONN_LIMIT); - if (ret) { - kfree(ifbdev); - return ret; - } - - drm_fb_helper_single_add_all_connectors(&ifbdev->helper); - - return 0; -} - -void intel_fbdev_initial_config(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - /* Due to peculiar init order wrt to hpd handling this is separate. */ - drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32); -} - -void intel_fbdev_fini(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - if (!dev_priv->fbdev) - return; - - intel_fbdev_destroy(dev, dev_priv->fbdev); - kfree(dev_priv->fbdev); - dev_priv->fbdev = NULL; -} - -void intel_fbdev_set_suspend(struct drm_device *dev, int state) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_fbdev *ifbdev = dev_priv->fbdev; - struct fb_info *info; - - if (!ifbdev) - return; - - info = ifbdev->helper.fbdev; - - /* On resume from hibernation: If the object is shmemfs backed, it has - * been restored from swap. If the object is stolen however, it will be - * full of whatever garbage was left in there. - */ - if (state == FBINFO_STATE_RUNNING && ifbdev->ifb.obj->stolen) - memset_io(info->screen_base, 0, info->screen_size); - - fb_set_suspend(info, state); -} - -MODULE_LICENSE("GPL and additional rights"); - -void intel_fb_output_poll_changed(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); -} - -void intel_fb_restore_mode(struct drm_device *dev) -{ - int ret; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_mode_config *config = &dev->mode_config; - struct drm_plane *plane; - - if (INTEL_INFO(dev)->num_pipes == 0) - return; - - drm_modeset_lock_all(dev); - - ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); - if (ret) - DRM_DEBUG("failed to restore crtc mode\n"); - - /* Be sure to shut off any planes that may be active */ - list_for_each_entry(plane, &config->plane_list, head) - if (plane->enabled) - plane->funcs->disable_plane(plane); - - drm_modeset_unlock_all(dev); -} diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c new file mode 100644 index 0000000..4c8a6b7 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -0,0 +1,314 @@ +/* + * Copyright © 2007 David Airlie + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * David Airlie + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "intel_drv.h" +#include +#include "i915_drv.h" + +static struct fb_ops intelfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_blank = drm_fb_helper_blank, + .fb_setcmap = drm_fb_helper_setcmap, + .fb_debug_enter = drm_fb_helper_debug_enter, + .fb_debug_leave = drm_fb_helper_debug_leave, +}; + +static int intelfb_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct intel_fbdev *ifbdev = + container_of(helper, struct intel_fbdev, helper); + struct drm_device *dev = helper->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct fb_info *info; + struct drm_framebuffer *fb; + struct drm_mode_fb_cmd2 mode_cmd = {}; + struct drm_i915_gem_object *obj; + struct device *device = &dev->pdev->dev; + int size, ret; + + /* we don't do packed 24bpp */ + if (sizes->surface_bpp == 24) + sizes->surface_bpp = 32; + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / + 8), 64); + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + size = mode_cmd.pitches[0] * mode_cmd.height; + size = ALIGN(size, PAGE_SIZE); + obj = i915_gem_object_create_stolen(dev, size); + if (obj == NULL) + obj = i915_gem_alloc_object(dev, size); + if (!obj) { + DRM_ERROR("failed to allocate framebuffer\n"); + ret = -ENOMEM; + goto out; + } + + mutex_lock(&dev->struct_mutex); + + /* Flush everything out, we'll be doing GTT only from now on */ + ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); + if (ret) { + DRM_ERROR("failed to pin fb: %d\n", ret); + goto out_unref; + } + + info = framebuffer_alloc(0, device); + if (!info) { + ret = -ENOMEM; + goto out_unpin; + } + + info->par = helper; + + ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); + if (ret) + goto out_unpin; + + fb = &ifbdev->ifb.base; + + ifbdev->helper.fb = fb; + ifbdev->helper.fbdev = info; + + strcpy(info->fix.id, "inteldrmfb"); + + info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; + info->fbops = &intelfb_ops; + + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (ret) { + ret = -ENOMEM; + goto out_unpin; + } + /* setup aperture base/size for vesafb takeover */ + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto out_unpin; + } + info->apertures->ranges[0].base = dev->mode_config.fb_base; + info->apertures->ranges[0].size = dev_priv->gtt.mappable_end; + + info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; + info->fix.smem_len = size; + + info->screen_base = + ioremap_wc(dev_priv->gtt.mappable_base + obj->gtt_offset, + size); + if (!info->screen_base) { + ret = -ENOSPC; + goto out_unpin; + } + info->screen_size = size; + + /* This driver doesn't need a VT switch to restore the mode on resume */ + info->skip_vt_switch = true; + + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); + + /* If the object is shmemfs backed, it will have given us zeroed pages. + * If the object is stolen however, it will be full of whatever + * garbage was left in there. + */ + if (ifbdev->ifb.obj->stolen) + memset_io(info->screen_base, 0, info->screen_size); + + /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ + + DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", + fb->width, fb->height, + obj->gtt_offset, obj); + + + mutex_unlock(&dev->struct_mutex); + vga_switcheroo_client_fb_set(dev->pdev, info); + return 0; + +out_unpin: + i915_gem_object_unpin(obj); +out_unref: + drm_gem_object_unreference(&obj->base); + mutex_unlock(&dev->struct_mutex); +out: + return ret; +} + +static struct drm_fb_helper_funcs intel_fb_helper_funcs = { + .gamma_set = intel_crtc_fb_gamma_set, + .gamma_get = intel_crtc_fb_gamma_get, + .fb_probe = intelfb_create, +}; + +static void intel_fbdev_destroy(struct drm_device *dev, + struct intel_fbdev *ifbdev) +{ + struct fb_info *info; + struct intel_framebuffer *ifb = &ifbdev->ifb; + + if (ifbdev->helper.fbdev) { + info = ifbdev->helper.fbdev; + unregister_framebuffer(info); + iounmap(info->screen_base); + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } + + drm_fb_helper_fini(&ifbdev->helper); + + drm_framebuffer_unregister_private(&ifb->base); + drm_framebuffer_cleanup(&ifb->base); + if (ifb->obj) { + drm_gem_object_unreference_unlocked(&ifb->obj->base); + ifb->obj = NULL; + } +} + +int intel_fbdev_init(struct drm_device *dev) +{ + struct intel_fbdev *ifbdev; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + + ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); + if (!ifbdev) + return -ENOMEM; + + dev_priv->fbdev = ifbdev; + ifbdev->helper.funcs = &intel_fb_helper_funcs; + + ret = drm_fb_helper_init(dev, &ifbdev->helper, + INTEL_INFO(dev)->num_pipes, + INTELFB_CONN_LIMIT); + if (ret) { + kfree(ifbdev); + return ret; + } + + drm_fb_helper_single_add_all_connectors(&ifbdev->helper); + + return 0; +} + +void intel_fbdev_initial_config(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* Due to peculiar init order wrt to hpd handling this is separate. */ + drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32); +} + +void intel_fbdev_fini(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + if (!dev_priv->fbdev) + return; + + intel_fbdev_destroy(dev, dev_priv->fbdev); + kfree(dev_priv->fbdev); + dev_priv->fbdev = NULL; +} + +void intel_fbdev_set_suspend(struct drm_device *dev, int state) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_fbdev *ifbdev = dev_priv->fbdev; + struct fb_info *info; + + if (!ifbdev) + return; + + info = ifbdev->helper.fbdev; + + /* On resume from hibernation: If the object is shmemfs backed, it has + * been restored from swap. If the object is stolen however, it will be + * full of whatever garbage was left in there. + */ + if (state == FBINFO_STATE_RUNNING && ifbdev->ifb.obj->stolen) + memset_io(info->screen_base, 0, info->screen_size); + + fb_set_suspend(info, state); +} + +MODULE_LICENSE("GPL and additional rights"); + +void intel_fbdev_output_poll_changed(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); +} + +void intel_fbdev_restore_mode(struct drm_device *dev) +{ + int ret; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_mode_config *config = &dev->mode_config; + struct drm_plane *plane; + + if (INTEL_INFO(dev)->num_pipes == 0) + return; + + drm_modeset_lock_all(dev); + + ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); + if (ret) + DRM_DEBUG("failed to restore crtc mode\n"); + + /* Be sure to shut off any planes that may be active */ + list_for_each_entry(plane, &config->plane_list, head) + if (plane->enabled) + plane->funcs->disable_plane(plane); + + drm_modeset_unlock_all(dev); +}