[Intel-gfx] [PATCH 01/31] drm/i915: fix up pch pll handling in ->mode_set

Daniel Vetter daniel.vetter at ffwll.ch
Wed Jun 5 13:34:03 CEST 2013


We ->mode_set is called we can't just blindly reuse an existing pll
since that might be shared with a different, still active pch output.

v2: Only update the pll settings when the pch pll is know to be
unused, otherwise we can wreak havoc with a running pipe. Which in the
case of DP will likely result in a black screen due to loss of link
lock.

v3: Tighten up the asserts a bit more, especially make sure that the
pch pll is still enabled when we try to disable it. This would have
caught the bug fixed in this patch.

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f29063b..3bdb695 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1397,7 +1397,8 @@ static void ironlake_enable_pch_pll(struct intel_crtc *intel_crtc)
 	/* PCH refclock must be enabled first */
 	assert_pch_refclk_enabled(dev_priv);
 
-	if (pll->active++ && pll->on) {
+	if (pll->active++) {
+		WARN_ON(!pll->on);
 		assert_pch_pll_enabled(dev_priv, pll, NULL);
 		return;
 	}
@@ -1438,10 +1439,9 @@ static void intel_disable_pch_pll(struct intel_crtc *intel_crtc)
 		return;
 	}
 
-	if (--pll->active) {
-		assert_pch_pll_enabled(dev_priv, pll, NULL);
+	assert_pch_pll_enabled(dev_priv, pll, NULL);
+	if (--pll->active)
 		return;
-	}
 
 	DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg);
 
@@ -3048,9 +3048,9 @@ static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u3
 
 	pll = intel_crtc->pch_pll;
 	if (pll) {
-		DRM_DEBUG_KMS("CRTC:%d reusing existing PCH PLL %x\n",
+		DRM_DEBUG_KMS("CRTC:%d dropping existing PCH PLL %x\n",
 			      intel_crtc->base.base.id, pll->pll_reg);
-		goto prepare;
+		intel_put_pch_pll(intel_crtc);
 	}
 
 	if (HAS_PCH_IBX(dev_priv->dev)) {
@@ -3095,19 +3095,22 @@ static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u3
 
 found:
 	intel_crtc->pch_pll = pll;
-	pll->refcount++;
 	DRM_DEBUG_DRIVER("using pll %d for pipe %c\n", i, pipe_name(intel_crtc->pipe));
-prepare: /* separate function? */
-	DRM_DEBUG_DRIVER("switching PLL %x off\n", pll->pll_reg);
+	if (pll->active == 0) {
+		DRM_DEBUG_DRIVER("setting up pll %d\n", i);
+		WARN_ON(pll->on);
+		assert_pch_pll_disabled(dev_priv, pll, NULL);
 
-	/* Wait for the clocks to stabilize before rewriting the regs */
-	I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
-	POSTING_READ(pll->pll_reg);
-	udelay(150);
+		/* Wait for the clocks to stabilize before rewriting the regs */
+		I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
+		POSTING_READ(pll->pll_reg);
+		udelay(150);
+
+		I915_WRITE(pll->fp0_reg, fp);
+		I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
+	}
+	pll->refcount++;
 
-	I915_WRITE(pll->fp0_reg, fp);
-	I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
-	pll->on = false;
 	return pll;
 }
 
-- 
1.7.11.7




More information about the Intel-gfx mailing list