From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chris Wilson Subject: [PATCH 17/17] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon Date: Sat, 21 Apr 2012 17:36:01 +0100 Message-ID: <1335026161-15054-18-git-send-email-chris@chris-wilson.co.uk> References: <1335026161-15054-1-git-send-email-chris@chris-wilson.co.uk> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from fireflyinternet.com (smtp.fireflyinternet.com [109.228.6.236]) by gabe.freedesktop.org (Postfix) with ESMTP id 9ABEC9E864 for ; Sat, 21 Apr 2012 09:36:44 -0700 (PDT) In-Reply-To: <1335026161-15054-1-git-send-email-chris@chris-wilson.co.uk> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org To: intel-gfx@lists.freedesktop.org List-Id: intel-gfx@lists.freedesktop.org Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_dma.c | 4 ++ drivers/gpu/drm/i915/intel_display.c | 3 - drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_fb.c | 121 ++++++++++++++++++++++++++++++++-- 4 files changed, 122 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9e80d5a..591b8a6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1104,6 +1104,9 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_modeset_init(dev); + /* Wrap existing BIOS mode configuration prior to GEM takeover */ + intel_fbdev_init_bios(dev); + ret = i915_gem_init(dev); if (ret) goto cleanup_gem_stolen; @@ -1118,6 +1121,7 @@ static int i915_load_modeset_init(struct drm_device *dev) /* FIXME: do pre/post-mode set stuff in core KMS code */ dev->vblank_disable_allowed = 1; + /* Install a default KMS/GEM fbcon if we failed to wrap the BIOS fb */ ret = intel_fbdev_init(dev); if (ret) goto cleanup_irq; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fd4bfbe..2aab4d8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6482,9 +6482,6 @@ static void intel_setup_outputs(struct drm_device *dev) intel_encoder_clones(dev, encoder->clone_mask); } - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - if (HAS_PCH_SPLIT(dev)) ironlake_init_pch_refclk(dev); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4015027..538366b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -424,6 +424,7 @@ extern int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *ifb, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj); +extern void intel_fbdev_init_bios(struct drm_device *dev); extern int intel_fbdev_init(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); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index f131a2b..3b6e0b8 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -231,19 +231,130 @@ static void intel_fbdev_destroy(struct drm_device *dev, } } -int intel_fbdev_init(struct drm_device *dev) +void intel_fbdev_init_bios(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_fbdev *ifbdev; + int pipe, ret; + + for_each_pipe(pipe) { + struct intel_crtc *crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); + struct drm_mode_fb_cmd2 mode_cmd; + struct drm_i915_gem_object *obj; + struct fb_info *info; + u32 bpp, depth; + u32 size, offset; + u32 reg, val; + + val = I915_READ(PIPECONF(crtc->pipe)); + if ((val & PIPECONF_ENABLE) == 0) + continue; + + reg = DSPCNTR(crtc->plane); + val = I915_READ(reg); + WARN_ON(val & DISPPLANE_TILED); + + switch (val & DISPPLANE_PIXFORMAT_MASK) { + case DISPPLANE_8BPP: + depth = bpp = 8; + break; + case DISPPLANE_15_16BPP: + depth = 15; bpp = 16; + break; + case DISPPLANE_16BPP: + depth = bpp = 16; + break; + case DISPPLANE_32BPP_NO_ALPHA: + depth = 24; bpp = 32; + break; + default: + continue; + } + + if (INTEL_INFO(dev)->gen >= 4) + offset = I915_READ(DSPSURF(crtc->plane)); + else + offset = I915_READ(DSPADDR(crtc->plane)); + mode_cmd.pitches[0] = I915_READ(DSPSTRIDE(crtc->plane)); + + val = I915_READ(PIPESRC(crtc->pipe)); + mode_cmd.width = ((val >> 16) & 0xfff) + 1; + mode_cmd.height = ((val >> 0) & 0xfff) + 1; + mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); + + DRM_DEBUG_KMS("Found active pipe [%d/%d]: size=%dx%d@%d, offset=%x\n", + crtc->pipe, crtc->plane, + mode_cmd.width, mode_cmd.height, depth, offset); + + size = mode_cmd.pitches[0] * mode_cmd.height; + size = ALIGN(size, PAGE_SIZE); + + ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); + if (!ifbdev) + continue; + + ifbdev->helper.funcs = &intel_fb_helper_funcs; + ret = drm_fb_helper_init(dev, &ifbdev->helper, + dev_priv->num_pipe, + INTELFB_CONN_LIMIT); + if (ret) { + kfree(ifbdev); + continue; + } + + /* assume a 1:1 linear mapping between stolen and GTT */ + obj = i915_gem_object_create_for_stolen(dev, + offset, offset, + size); + if (obj == NULL) { + kfree(ifbdev); + continue; + } + + ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); + if (ret) { + drm_gem_object_unreference(&obj->base); + kfree(ifbdev); + continue; + } + + info = intelfb_create_info(ifbdev); + if (info == NULL) { + drm_gem_object_unreference(&obj->base); + kfree(ifbdev); + continue; + } + + crtc->base.fb = &ifbdev->ifb.base; + obj->pin_count++; + + drm_fb_helper_single_add_all_connectors(&ifbdev->helper); + drm_fb_helper_hotplug_event(&ifbdev->helper); + + vga_switcheroo_client_fb_set(dev->pdev, info); + dev_priv->fbdev = ifbdev; + return; + } + + /* otherwise disable all the possible crtcs before KMS */ + DRM_DEBUG_KMS("No active pipes found\n"); + drm_helper_disable_unused_functions(dev); +} + +int intel_fbdev_init(struct drm_device *dev) +{ drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_fbdev *ifbdev; int ret; + if (dev_priv->fbdev) + return 0; + ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); - if (!ifbdev) + if (ifbdev == NULL) return -ENOMEM; - dev_priv->fbdev = ifbdev; ifbdev->helper.funcs = &intel_fb_helper_funcs; - ret = drm_fb_helper_init(dev, &ifbdev->helper, dev_priv->num_pipe, INTELFB_CONN_LIMIT); @@ -252,6 +363,8 @@ int intel_fbdev_init(struct drm_device *dev) return ret; } + dev_priv->fbdev = ifbdev; + drm_fb_helper_single_add_all_connectors(&ifbdev->helper); drm_fb_helper_initial_config(&ifbdev->helper, 32); return 0; -- 1.7.10