From patchwork Tue Sep 15 00:30:46 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 47553 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8F0Upfv017549 for ; Tue, 15 Sep 2009 00:30:52 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 480C19E790; Mon, 14 Sep 2009 17:30:51 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from outbound-mail-03.bluehost.com (outbound-mail-03.bluehost.com [69.89.21.13]) by gabe.freedesktop.org (Postfix) with SMTP id A05EE9E730 for ; Mon, 14 Sep 2009 17:30:49 -0700 (PDT) Received: (qmail 15895 invoked by uid 0); 15 Sep 2009 00:30:49 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by outboundproxy1.bluehost.com with SMTP; 15 Sep 2009 00:30:49 -0000 Received: from [75.111.28.251] (helo=jbarnes-g45) by box514.bluehost.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69) (envelope-from ) id 1MnLwW-0001q8-Pp; Mon, 14 Sep 2009 18:30:49 -0600 Date: Mon, 14 Sep 2009 17:30:46 -0700 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org, eric@anholt.net Message-ID: <20090914173046.1e64b10f@jbarnes-g45> X-Mailer: Claws Mail 3.7.2 (GTK+ 2.17.5; i486-pc-linux-gnu) Mime-Version: 1.0 X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 75.111.28.251 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH] drm/i915: framebuffer compression for GM45+ X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Add FBC support for GM45+ chips. Based on the "split display functions" patch. --- From 2d1d8ba64a23f6dd6a1f57bf05f1a188b1b124a7 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 14 Sep 2009 15:39:40 -0700 Subject: [PATCH] drm/i915: framebuffer compression for GM45+ Add support for framebuffer compression on GM45 and above. Signed-off-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_dma.c | 51 ++++++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 27 ++++++++++++ drivers/gpu/drm/i915/intel_display.c | 79 +++++++++++++++++++++++++++++++--- 4 files changed, 133 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5a6b731..8569e60 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1119,34 +1119,49 @@ static void i915_setup_compression(struct drm_device *dev, int size) return; } - compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096, 4096, 0); - if (!compressed_llb) { - i915_warn_stolen(dev); + cfb_base = i915_gtt_to_phys(dev, compressed_fb->start); + if (!cfb_base) { + DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); + drm_mm_put_block(compressed_fb); return; } - compressed_llb = drm_mm_get_block(compressed_fb, 4096, 4096); - if (!compressed_llb) { - i915_warn_stolen(dev); - return; + if (!IS_GM45(dev)) { + compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096, + 4096, 0); + if (!compressed_llb) { + i915_warn_stolen(dev); + return; + } + + compressed_llb = drm_mm_get_block(compressed_fb, 4096, 4096); + if (!compressed_llb) { + i915_warn_stolen(dev); + return; + } + ll_base = i915_gtt_to_phys(dev, compressed_llb->start); + if (!ll_base) { + DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); + drm_mm_put_block(compressed_fb); + drm_mm_put_block(compressed_llb); + return; + } } dev_priv->cfb_size = size; - cfb_base = i915_gtt_to_phys(dev, compressed_fb->start); - ll_base = i915_gtt_to_phys(dev, compressed_llb->start); - if (!cfb_base || !ll_base) { - DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); - drm_mm_put_block(compressed_fb); - drm_mm_put_block(compressed_llb); + /* Display funcs haven't been set up yet */ + if (IS_GM45(dev)) { + g4x_disable_fbc(dev); + I915_WRITE(DPFC_CB_BASE, compressed_fb->start); + } else { + i8xx_disable_fbc(dev); + I915_WRITE(FBC_CFB_BASE, cfb_base); + I915_WRITE(FBC_LL_BASE, ll_base); } - i8xx_disable_fbc(dev); - DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base, ll_base, size >> 20); - I915_WRITE(FBC_CFB_BASE, cfb_base); - I915_WRITE(FBC_LL_BASE, ll_base); } static int i915_load_modeset_init(struct drm_device *dev, @@ -1189,7 +1204,7 @@ static int i915_load_modeset_init(struct drm_device *dev, goto out; /* Try to set up FBC with a reasonable compressed buffer size */ - if (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev)) && + if (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev) || IS_GM45(dev)) && i915_powersave) { int cfb_size; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f1740f4..a174e5e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -799,6 +799,7 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; } extern void intel_modeset_init(struct drm_device *dev); extern void intel_modeset_cleanup(struct drm_device *dev); extern void i8xx_disable_fbc(struct drm_device *dev); +extern void g4x_disable_fbc(struct drm_device *dev); /** * Lock test for when it's just for synchronization of ring access. diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f7c2de8..88df88f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -347,6 +347,33 @@ #define FBC_LL_SIZE (1536) +/* Framebuffer compression for GM45+ */ +#define DPFC_CB_BASE 0x3200 +#define DPFC_CONTROL 0x3208 +#define DPFC_CTL_EN (1<<31) +#define DPFC_CTL_PLANEA (0<<30) +#define DPFC_CTL_PLANEB (1<<30) +#define DPFC_CTL_FENCE_EN (1<<29) +#define DPFC_SR_EN (1<<10) +#define DPFC_CTL_LIMIT_1X (0<<6) +#define DPFC_CTL_LIMIT_2X (1<<6) +#define DPFC_CTL_LIMIT_4X (2<<6) +#define DPFC_RECOMP_CTL 0x320c +#define DPFC_RECOMP_STALL_EN (1<<27) +#define DPFC_RECOMP_STALL_WM_SHIFT (16) +#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000) +#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0) +#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f) +#define DPFC_STATUS 0x3210 +#define DPFC_INVAL_SEG_SHIFT (16) +#define DPFC_INVAL_SEG_MASK (0x07ff0000) +#define DPFC_COMP_SEG_SHIFT (0) +#define DPFC_COMP_SEG_MASK (0x000003ff) +#define DPFC_STATUS2 0x3214 +#define DPFC_FENCE_YOFF 0x3218 +#define DPFC_CHICKEN 0x3224 +#define DPFC_HT_MODIFY (1<<31) + /* * GPIO regs */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 446bc1e..421150a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1030,6 +1030,65 @@ static bool i8xx_fbc_enabled(struct drm_crtc *crtc) return I915_READ(FBC_CONTROL) & FBC_CTL_EN; } +static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_framebuffer *fb = crtc->fb; + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_i915_gem_object *obj_priv = intel_fb->obj->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : + DPFC_CTL_PLANEB); + unsigned long stall_watermark = 200; + u32 dpfc_ctl; + + dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; + dev_priv->cfb_fence = obj_priv->fence_reg; + dev_priv->cfb_plane = intel_crtc->plane; + + dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; + if (obj_priv->tiling_mode != I915_TILING_NONE) { + dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence; + I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); + } else { + I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY); + } + + I915_WRITE(DPFC_CONTROL, dpfc_ctl); + I915_WRITE(DPFC_RECOMP_CTL, // DPFC_RECOMP_STALL_EN | + //(stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | + (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); + I915_WRITE(DPFC_FENCE_YOFF, crtc->y); + + /* enable it... */ + I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); + + DRM_DEBUG("enabled fbc on plane %d\n", intel_crtc->plane); +} + +void g4x_disable_fbc(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 dpfc_ctl; + + /* Disable compression */ + dpfc_ctl = I915_READ(DPFC_CONTROL); + dpfc_ctl &= ~DPFC_CTL_EN; + I915_WRITE(DPFC_CONTROL, dpfc_ctl); + intel_wait_for_vblank(dev); + + DRM_DEBUG("disabled FBC\n"); +} + +static bool g4x_fbc_enabled(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; +} + /** * intel_update_fbc - enable/disable FBC as needed * @crtc: CRTC to point the compressor at @@ -1097,7 +1156,7 @@ static void intel_update_fbc(struct drm_crtc *crtc, DRM_DEBUG("mode too large for compression, disabling\n"); goto out_disable; } - if (IS_I9XX(dev) && plane != 0) { + if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) { DRM_DEBUG("plane not 0, disabling compression\n"); goto out_disable; } @@ -1291,7 +1350,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, master_priv->sarea_priv->pipeA_y = y; } - if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) + if ((IS_I965G(dev) || plane == 0)) intel_update_fbc(crtc, &crtc->mode); return 0; @@ -1760,7 +1819,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) intel_crtc_load_lut(crtc); - intel_update_fbc(crtc, &crtc->mode); + if ((IS_I965G(dev) || plane == 0)) + intel_update_fbc(crtc, &crtc->mode); /* Give the overlay scaler a chance to enable if it's on this pipe */ //intel_crtc_dpms_video(crtc, true); TODO @@ -2968,7 +3028,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* Flush the plane changes */ ret = intel_pipe_set_base(crtc, x, y, old_fb); - intel_update_fbc(crtc, &crtc->mode); + if ((IS_I965G(dev) || plane == 0)) + intel_update_fbc(crtc, &crtc->mode); intel_update_watermarks(dev); @@ -3101,7 +3162,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, drm_gem_object_unreference(intel_crtc->cursor_bo); } - if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) + if ((IS_I965G(dev) || plane == 0)) intel_update_fbc(crtc, &crtc->mode); mutex_unlock(&dev->struct_mutex); @@ -4088,12 +4149,16 @@ static void intel_init_display(struct drm_device *dev) /* Only mobile has FBC, leave pointers NULL for other chips */ if (IS_MOBILE(dev)) { - /* 855GM needs testing */ - if (IS_I965GM(dev) || IS_I945GM(dev) || IS_I915GM(dev)) { + if (IS_GM45(dev)) { + dev_priv->display.fbc_enabled = g4x_fbc_enabled; + dev_priv->display.enable_fbc = g4x_enable_fbc; + dev_priv->display.disable_fbc = g4x_disable_fbc; + } else if (IS_I965GM(dev) || IS_I945GM(dev) || IS_I915GM(dev)) { dev_priv->display.fbc_enabled = i8xx_fbc_enabled; dev_priv->display.enable_fbc = i8xx_enable_fbc; dev_priv->display.disable_fbc = i8xx_disable_fbc; } + /* 855GM needs testing */ } /* Returns the core display clock speed */