[Intel-gfx] [RFC 02/30] drm/i915: disable DDI pipes and ports when initializing

Paulo Zanoni przanoni at gmail.com
Wed Aug 29 00:06:33 CEST 2012


From: Paulo Zanoni <paulo.r.zanoni at intel.com>

This is required to prevent hanging the machine on Haswell. We need to
disable everything so when we start using we only enable/disable
exactly what we are using.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |  2 +
 drivers/gpu/drm/i915/intel_ddi.c     | 74 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |  7 ++--
 drivers/gpu/drm/i915/intel_drv.h     |  4 ++
 drivers/gpu/drm/i915/intel_sprite.c  |  6 +--
 5 files changed, 86 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2eed9d4..ee70588 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4375,6 +4375,7 @@
 #define  PIPE_DDI_FUNC_ENABLE		(1<<31)
 /* Those bits are ignored by pipe EDP since it can only connect to DDI A */
 #define  PIPE_DDI_PORT_MASK		(7<<28)
+#define  PIPE_DDI_PORT_NONE		(0<<28)
 #define  PIPE_DDI_SELECT_PORT(x)	((x)<<28)
 #define  PIPE_DDI_MODE_SELECT_MASK	(7<<24)
 #define  PIPE_DDI_MODE_SELECT_HDMI	(0<<24)
@@ -4503,6 +4504,7 @@
 #define  PORT_CLK_SEL_SPLL		(3<<29)
 #define  PORT_CLK_SEL_WRPLL1		(4<<29)
 #define  PORT_CLK_SEL_WRPLL2		(5<<29)
+#define  PORT_CLK_SEL_NONE		(7<<29)
 
 /* Pipe clock selection */
 #define PIPE_CLK_SEL_A			0x46140
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 18ebf15..b8b7670 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -751,6 +751,20 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
+static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
+				    enum port port)
+{
+	uint32_t reg = DDI_BUF_CTL(port);
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		udelay(1);
+		if (I915_READ(reg) & DDI_BUF_IS_IDLE)
+			return;
+	}
+	DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));
+}
+
 void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -775,11 +789,71 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 			temp);
 }
 
+static void intel_ddi_disable_pipe(struct drm_i915_private *dev_priv,
+				   enum pipe pipe)
+{
+	uint32_t temp;
+
+	temp = I915_READ(DDI_FUNC_CTL(pipe));
+	temp &= ~(PIPE_DDI_FUNC_ENABLE | PIPE_DDI_PORT_MASK);
+	temp |= PIPE_DDI_PORT_NONE;
+	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+
+	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_DISABLED);
+}
+
+static void intel_ddi_disable_port(struct drm_i915_private *dev_priv,
+				   enum port port)
+{
+	uint32_t reg, val;
+
+	reg = DDI_BUF_CTL(port);
+	val = I915_READ(reg);
+	if (val & DDI_BUF_CTL_ENABLE) {
+		val &= ~DDI_BUF_CTL_ENABLE;
+		I915_WRITE(reg, val);
+		intel_wait_ddi_buf_idle(dev_priv, port);
+	}
+
+	switch (I915_READ(PORT_CLK_SEL(port))) {
+	case PORT_CLK_SEL_WRPLL1:
+		reg = WRPLL_CTL1;
+		val = I915_READ(reg) & ~WRPLL_PLL_ENABLE;
+		break;
+	case PORT_CLK_SEL_WRPLL2:
+		reg = WRPLL_CTL2;
+		val = I915_READ(reg) & ~WRPLL_PLL_ENABLE;
+		break;
+	case PORT_CLK_SEL_SPLL:
+		reg = SPLL_CTL;
+		val = I915_READ(reg) & ~SPLL_PLL_ENABLE;
+		break;
+	default: /* LCPLL or none or reserved */
+		reg = 0;
+	}
+
+	if (reg)
+		I915_WRITE(reg, val);
+
+	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+}
+
 void intel_ddi_pll_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t lcpll_val, clk_val, temp;
 	bool lcpll_needs_change = false;
+	int i;
+
+	/* Reset all pipe clocks and ports so we don't hang the machine later */
+	for (i = PIPE_A; i <= PIPE_C; i++) {
+		intel_disable_plane(dev_priv, i, i);
+		intel_disable_pipe(dev_priv, i);
+		intel_ddi_disable_pipe(dev_priv, i);
+	}
+
+	for (i = PORT_A; i <= PORT_E; i++)
+		intel_ddi_disable_port(dev_priv, i);
 
 	/* Check the LCPLL state and fix it if needed. */
 	lcpll_val = I915_READ(LCPLL_CTL);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 11687d2..33eebcb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1773,8 +1773,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
  *
  * Will wait until the pipe has shut down before returning.
  */
-static void intel_disable_pipe(struct drm_i915_private *dev_priv,
-			       enum pipe pipe)
+void intel_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
 	int reg;
 	u32 val;
@@ -1844,8 +1843,8 @@ static void intel_enable_plane(struct drm_i915_private *dev_priv,
  *
  * Disable @plane; should be an independent operation.
  */
-static void intel_disable_plane(struct drm_i915_private *dev_priv,
-				enum plane plane, enum pipe pipe)
+void intel_disable_plane(struct drm_i915_private *dev_priv,
+			 enum plane plane, enum pipe pipe)
 {
 	int reg;
 	u32 val;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cf9a1ad..2578158 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -390,6 +390,10 @@ extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
 extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
 				      enum plane plane);
+extern void intel_disable_plane(struct drm_i915_private *dev_priv,
+				enum plane plane, enum pipe pipe);
+extern void intel_disable_pipe(struct drm_i915_private *dev_priv,
+			       enum pipe pipe);
 
 /* intel_panel.c */
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index cc8df4d..4737303 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -531,7 +531,7 @@ out:
 }
 
 static int
-intel_disable_plane(struct drm_plane *plane)
+intel_disable_drm_plane(struct drm_plane *plane)
 {
 	struct drm_device *dev = plane->dev;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -556,7 +556,7 @@ out:
 static void intel_destroy_plane(struct drm_plane *plane)
 {
 	struct intel_plane *intel_plane = to_intel_plane(plane);
-	intel_disable_plane(plane);
+	intel_disable_drm_plane(plane);
 	drm_plane_cleanup(plane);
 	kfree(intel_plane);
 }
@@ -625,7 +625,7 @@ out_unlock:
 
 static const struct drm_plane_funcs intel_plane_funcs = {
 	.update_plane = intel_update_plane,
-	.disable_plane = intel_disable_plane,
+	.disable_plane = intel_disable_drm_plane,
 	.destroy = intel_destroy_plane,
 };
 
-- 
1.7.11.2




More information about the Intel-gfx mailing list