[Intel-gfx] [PATCH 2/2] drm/i915: Add the support of frame buffer compression on Ironlake

Zhenyu Wang zhenyuw at linux.intel.com
Mon Mar 15 07:37:58 CET 2010


From: Zhao Yakui <yakui.zhao at intel.com>

Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c      |   10 ++--
 drivers/gpu/drm/i915/i915_drv.c      |    2 +-
 drivers/gpu/drm/i915/i915_drv.h      |    1 +
 drivers/gpu/drm/i915/i915_reg.h      |   20 +++++++
 drivers/gpu/drm/i915/i915_suspend.c  |   11 +++-
 drivers/gpu/drm/i915/intel_display.c |   92 +++++++++++++++++++++++++++++++++-
 6 files changed, 128 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index b63638a..09ced60 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1331,7 +1331,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 		drm_mm_put_block(compressed_fb);
 	}
 
-	if (!IS_GM45(dev)) {
+	if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) {
 		compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
 						    4096, 0);
 		if (!compressed_llb) {
@@ -1354,8 +1354,10 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 	}
 
 	dev_priv->cfb_size = size;
-
-	if (IS_GM45(dev)) {
+	if (IS_IRONLAKE_M(dev)) {
+		ironlake_disable_fbc(dev);
+		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
+	} else if (IS_GM45(dev)) {
 		g4x_disable_fbc(dev);
 		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
 	} else {
@@ -1364,7 +1366,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 		I915_WRITE(FBC_LL_BASE, ll_base);
 	}
 
-	DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
+	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
 		  ll_base, size >> 20);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 85ad020..3801d4d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -133,7 +133,7 @@ const static struct intel_device_info intel_ironlake_d_info = {
 
 const static struct intel_device_info intel_ironlake_m_info = {
 	.is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
-	.need_gfx_hws = 1, .has_rc6 = 1,
+	.need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
 	.has_hotplug = 1,
 };
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d8dd7b2..0ea1902 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -986,6 +986,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void i8xx_disable_fbc(struct drm_device *dev);
 extern void g4x_disable_fbc(struct drm_device *dev);
+extern void ironlake_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 8244080..9686955 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -417,6 +417,26 @@
 #define DPFC_CHICKEN		0x3224
 #define   DPFC_HT_MODIFY	(1<<31)
 
+/* Framebuffer compression for Ironlake */
+#define ILK_DPFC_CB_BASE	0x43200
+#define ILK_DPFC_CONTROL	0x43208
+/* The bit 28-8 is reserved */
+#define   DPFC_RESERVED		(0x1FFFFF00)
+#define ILK_DPFC_RECOMP_CTL	0x4320c
+#define ILK_DPFC_STATUS		0x43210
+#define ILK_DPFC_FENCE_YOFF	0x43218
+#define ILK_DPFC_CHICKEN	0x43224
+#define ILK_FBC_RT_BASE		0x2128
+#define   ILK_FBC_RT_VALID	(1<<0)
+
+#define ILK_DISPLAY_CHICKEN1	0x42000
+#define   ILK_FBCQ_DIS		(1<<22)
+#define ILK_DISPLAY_CHICKEN2	0x42004
+/* According to the spec this bit 22 of 0x420004 should be enabled */
+#define   ILK_DPARB_GATE	(1<<22)
+#define ILK_DSPCLK_GATE		0x42020
+/* This bit 7 of 0x42020 should be enabled to enable the FBC */
+#define   ILK_CLK_FBC		(1<<7)
 /*
  * GPIO regs
  */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 45f25c2..7ef722e 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -602,7 +602,10 @@ void i915_save_display(struct drm_device *dev)
 
 	/* Only save FBC register on Mobile platform */
 	if (IS_MOBILE(dev)) {
-		if (IS_GM45(dev)) {
+		if (IS_IRONLAKE_M(dev))
+			dev_priv->saveDPFC_CB_BASE =
+						I915_READ(ILK_DPFC_CB_BASE);
+		else if (IS_GM45(dev)) {
 			dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
 		} else {
 			dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
@@ -706,7 +709,11 @@ void i915_restore_display(struct drm_device *dev)
 
 	/* Restore FBC info on Mobile platform */
 	if (IS_MOBILE(dev)) {
-		if (IS_GM45(dev)) {
+		if (IS_IRONLAKE_M(dev)) {
+			ironlake_disable_fbc(dev);
+			I915_WRITE(ILK_DPFC_CB_BASE,
+						dev_priv->saveDPFC_CB_BASE);
+		} else if (IS_GM45(dev)) {
 			g4x_disable_fbc(dev);
 			I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
 		} else {
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f9a32a4..fe15fa1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1130,6 +1130,68 @@ static bool g4x_fbc_enabled(struct drm_crtc *crtc)
 	return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
+static void ironlake_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 = I915_READ(ILK_DPFC_CONTROL);
+	dpfc_ctl &= DPFC_RESERVED;
+	dpfc_ctl |= plane | DPFC_CTL_LIMIT_1X;
+	if (obj_priv->tiling_mode != I915_TILING_NONE) {
+		dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence;
+		I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
+	} else {
+		I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY);
+	}
+
+	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
+	I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
+		   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
+		   (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
+	I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
+	I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID);
+	/* enable it... */
+	I915_WRITE(ILK_DPFC_CONTROL, I915_READ(ILK_DPFC_CONTROL) |
+					DPFC_CTL_EN);
+
+	DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
+}
+
+void ironlake_disable_fbc(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 dpfc_ctl;
+
+	/* Disable compression */
+	dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
+	dpfc_ctl &= ~DPFC_CTL_EN;
+	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
+	intel_wait_for_vblank(dev);
+
+	DRM_DEBUG_KMS("disabled FBC\n");
+}
+
+static bool ironlake_fbc_enabled(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
+}
+
 /**
  * intel_update_fbc - enable/disable FBC as needed
  * @crtc: CRTC to point the compressor at
@@ -1756,6 +1818,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 
 		intel_crtc_load_lut(crtc);
 
+		intel_update_fbc(crtc, &crtc->mode);
+
 	break;
 	case DRM_MODE_DPMS_OFF:
 		DRM_DEBUG_KMS("crtc %d dpms off\n", pipe);
@@ -1770,6 +1834,10 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 			I915_READ(dspbase_reg);
 		}
 
+		if (dev_priv->cfb_plane == plane &&
+		    dev_priv->display.disable_fbc)
+			dev_priv->display.disable_fbc(dev);
+
 		i915_disable_vga(dev);
 
 		/* disable cpu pipe, disable after all planes disabled */
@@ -4716,6 +4784,24 @@ void intel_init_clock_gating(struct drm_device *dev)
 	 * specs, but enable as much else as we can.
 	 */
 	if (HAS_PCH_SPLIT(dev)) {
+		/*
+		 * According to the spec the following bits should be set in
+		 * order to enable FBC
+		 * The bit 22 of 0x42000
+		 * The bit 22 of 0x42004
+		 * The bit 7 of 0x42020
+		 */
+		if (IS_IRONLAKE_M(dev)) {
+			I915_WRITE(ILK_DISPLAY_CHICKEN1,
+					(I915_READ(ILK_DISPLAY_CHICKEN1) |
+						ILK_FBCQ_DIS));
+			I915_WRITE(ILK_DISPLAY_CHICKEN2,
+					(I915_READ(ILK_DISPLAY_CHICKEN2) |
+						ILK_DPARB_GATE));
+			I915_WRITE(ILK_DSPCLK_GATE,
+					(I915_READ(ILK_DSPCLK_GATE) |
+						ILK_CLK_FBC));
+		}
 		return;
 	} else if (IS_G4X(dev)) {
 		uint32_t dspclk_gate;
@@ -4795,7 +4881,11 @@ static void intel_init_display(struct drm_device *dev)
 
 	/* Only mobile has FBC, leave pointers NULL for other chips */
 	if (IS_MOBILE(dev)) {
-		if (IS_GM45(dev)) {
+		if (IS_IRONLAKE_M(dev)) {
+			dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
+			dev_priv->display.enable_fbc = ironlake_enable_fbc;
+			dev_priv->display.disable_fbc = ironlake_disable_fbc;
+		} else 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;
-- 
1.6.3.3




More information about the Intel-gfx mailing list