diff mbox

drm/i915: make sure plane control reg changes take effect

Message ID 1311878883-9946-1-git-send-email-jbarnes@virtuousgeek.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jesse Barnes July 28, 2011, 6:48 p.m. UTC
After writing to the plane control reg we need to write to the surface
reg to trigger the double buffered register latch.

v2: write DSPADDR too to cover pre-965 chipsets

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_drv.c      |    2 +-
 drivers/gpu/drm/i915/i915_drv.h      |    2 +
 drivers/gpu/drm/i915/i915_reg.h      |    7 ++
 drivers/gpu/drm/i915/intel_display.c |  143 ++++++++++++++++++++++++----------
 4 files changed, 112 insertions(+), 42 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index ce045a8..60e4b9e 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -62,7 +62,7 @@  module_param_named(semaphores, i915_semaphores, int, 0600);
 MODULE_PARM_DESC(semaphores,
 		"Use semaphores for inter-ring sync (default: false)");
 
-unsigned int i915_enable_rc6 __read_mostly = 0;
+unsigned int i915_enable_rc6 __read_mostly = 1;
 module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
 MODULE_PARM_DESC(i915_enable_rc6,
 		"Enable power-saving render C-state 6 (default: true)");
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 78cdd15..4f24e72 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -337,6 +337,8 @@  typedef struct drm_i915_private {
 	int cfb_y;
 	struct intel_fbc_work *fbc_work;
 
+	int planes_enabled;
+
 	struct intel_opregion opregion;
 
 	/* overlay */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7377ae4..ae28549 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3081,6 +3081,13 @@ 
 #define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
 #define   TRANS_AUTOTRAIN_GEN_STALL_DIS	(1<<31)
 
+#define SOUTH_CHICKEN1		0xc2000
+#define  FDIA_PHASE_SYNC_OVR	(1<<19)
+#define  FDIA_PHASE_SYNC_EN	(1<<18)
+#define  FDIB_PHASE_SYNC_OVR	(1<<17)
+#define  FDIB_PHASE_SYNC_EN	(1<<16)
+#define  FDIC_PHASE_SYNC_OVR	(1<<15)
+#define  FDIC_PHASE_SYNC_EN	(1<<14)
 #define SOUTH_CHICKEN2		0xc2004
 #define  DPLS_EDP_PPS_FIX_DIS	(1<<0)
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 32ffde2..30379df 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1333,6 +1333,9 @@  static void intel_disable_plane(struct drm_i915_private *dev_priv,
 		return;
 
 	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
+	/* Flush out the double buffered plane control reg */
+	I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane)));
+	I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane)));
 	intel_flush_display_plane(dev_priv, plane);
 	intel_wait_for_vblank(dev_priv->dev, pipe);
 }
@@ -1370,7 +1373,7 @@  static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
 	val = I915_READ(reg);
 	if (ADPA_PIPE_ENABLED(val, pipe))
 		I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
-
+#if 0
 	reg = PCH_LVDS;
 	val = I915_READ(reg);
 	if (LVDS_PIPE_ENABLED(val, pipe)) {
@@ -1378,7 +1381,7 @@  static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
 		POSTING_READ(reg);
 		udelay(100);
 	}
-
+#endif
 	disable_pch_hdmi(dev_priv, pipe, HDMIB);
 	disable_pch_hdmi(dev_priv, pipe, HDMIC);
 	disable_pch_hdmi(dev_priv, pipe, HDMID);
@@ -2295,6 +2298,23 @@  static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
 		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR |
 			   FDI_RX_PHASE_SYNC_POINTER_EN);
+	} else if (HAS_PCH_CPT(dev)) {
+		u32 flags;
+		switch (pipe) {
+		case 0:
+			flags = FDIA_PHASE_SYNC_OVR | FDIA_PHASE_SYNC_EN;
+			break;
+		case 2:
+			flags = FDIA_PHASE_SYNC_OVR | FDIA_PHASE_SYNC_EN;
+			break;
+		case 3:
+			flags = FDIA_PHASE_SYNC_OVR | FDIA_PHASE_SYNC_EN;
+			break;
+		default:
+			break;
+		}
+		I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */
+		I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */
 	}
 
 	reg = FDI_RX_IIR(pipe);
@@ -2652,6 +2672,23 @@  static void ironlake_fdi_disable(struct drm_crtc *crtc)
 		I915_WRITE(FDI_RX_CHICKEN(pipe),
 			   I915_READ(FDI_RX_CHICKEN(pipe) &
 				     ~FDI_RX_PHASE_SYNC_POINTER_EN));
+	} else if (HAS_PCH_CPT(dev)) {
+		u32 flags;
+		switch (pipe) {
+		case 0:
+			flags = FDIA_PHASE_SYNC_OVR;
+			break;
+		case 2:
+			flags = FDIA_PHASE_SYNC_OVR;
+			break;
+		case 3:
+			flags = FDIA_PHASE_SYNC_OVR;
+			break;
+		default:
+			break;
+		}
+		I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */
+		I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */
 	}
 
 	/* still set train pattern 1 */
@@ -2919,6 +2956,10 @@  static void ironlake_crtc_disable(struct drm_crtc *crtc)
 		/* disable TRANS_DP_CTL */
 		reg = TRANS_DP_CTL(pipe);
 		temp = I915_READ(reg);
+		temp &= ~TRANS_DP_PORT_SEL_MASK;
+		temp |=  TRANS_DP_PORT_SEL_NONE;
+		I915_WRITE(reg, temp);
+		intel_wait_for_vblank(dev, pipe);
 		temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
 		temp |= TRANS_DP_PORT_SEL_NONE;
 		I915_WRITE(reg, temp);
@@ -4328,51 +4369,20 @@  static void ironlake_update_wm(struct drm_device *dev)
 	 */
 }
 
-static void sandybridge_update_wm(struct drm_device *dev)
+static void snb_disable_lpwm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
-	int fbc_wm, plane_wm, cursor_wm;
-	unsigned int enabled;
 
-	enabled = 0;
-	if (g4x_compute_wm0(dev, 0,
-			    &sandybridge_display_wm_info, latency,
-			    &sandybridge_cursor_wm_info, latency,
-			    &plane_wm, &cursor_wm)) {
-		I915_WRITE(WM0_PIPEA_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-			      " plane %d, " "cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 1;
-	}
-
-	if (g4x_compute_wm0(dev, 1,
-			    &sandybridge_display_wm_info, latency,
-			    &sandybridge_cursor_wm_info, latency,
-			    &plane_wm, &cursor_wm)) {
-		I915_WRITE(WM0_PIPEB_ILK,
-			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-			      " plane %d, cursor: %d\n",
-			      plane_wm, cursor_wm);
-		enabled |= 2;
-	}
-
-	/*
-	 * Calculate and update the self-refresh watermark only when one
-	 * display plane is used.
-	 *
-	 * SNB support 3 levels of watermark.
-	 *
-	 * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
-	 * and disabled in the descending order
-	 *
-	 */
 	I915_WRITE(WM3_LP_ILK, 0);
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
+}
+
+void snb_enable_lpwm(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int fbc_wm, plane_wm, cursor_wm;
+	int enabled = dev_priv->planes_enabled;
 
 	if (!single_plane_enabled(enabled))
 		return;
@@ -4424,6 +4434,55 @@  static void sandybridge_update_wm(struct drm_device *dev)
 		   cursor_wm);
 }
 
+static void sandybridge_update_wm(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
+	int plane_wm, cursor_wm;
+	unsigned int enabled;
+
+	enabled = 0;
+	if (g4x_compute_wm0(dev, 0,
+			    &sandybridge_display_wm_info, latency,
+			    &sandybridge_cursor_wm_info, latency,
+			    &plane_wm, &cursor_wm)) {
+		I915_WRITE(WM0_PIPEA_ILK,
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
+			      " plane %d, " "cursor: %d\n",
+			      plane_wm, cursor_wm);
+		enabled |= 1;
+	}
+
+	if (g4x_compute_wm0(dev, 1,
+			    &sandybridge_display_wm_info, latency,
+			    &sandybridge_cursor_wm_info, latency,
+			    &plane_wm, &cursor_wm)) {
+		I915_WRITE(WM0_PIPEB_ILK,
+			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
+		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
+			      " plane %d, cursor: %d\n",
+			      plane_wm, cursor_wm);
+		enabled |= 2;
+	}
+
+	/*
+	 * Calculate and update the self-refresh watermark only when one
+	 * display plane is used.
+	 *
+	 * SNB support 3 levels of watermark.
+	 *
+	 * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
+	 * and disabled in the descending order
+	 *
+	 */
+	snb_disable_lpwm(dev);
+
+	dev_priv->planes_enabled = enabled;
+
+	snb_enable_lpwm(dev);
+}
+
 /**
  * intel_update_watermarks - update FIFO watermark values based on current modes
  *
@@ -5515,6 +5574,8 @@  static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
 	drm_vblank_post_modeset(dev, pipe);
 
+	intel_crtc->dpms_mode = DRM_MODE_DPMS_ON;
+
 	return ret;
 }