drm/i915: add PCH DPLL enable/disable functions
authorJesse Barnes <jbarnes@virtuousgeek.org>
Tue, 4 Jan 2011 23:09:34 +0000 (15:09 -0800)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 19 Jan 2011 12:36:41 +0000 (12:36 +0000)
With assertions to check transcoder and reference clock state.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c

index c739a4bbf005f38d1c37c3dcd65d38f406e4e8d2..53ddacc907b98817a08d0dfe1d01050db834d4ba 100644 (file)
 #define  DREF_NONSPREAD_SOURCE_MASK            (3<<9)
 #define  DREF_SUPERSPREAD_SOURCE_DISABLE        (0<<7)
 #define  DREF_SUPERSPREAD_SOURCE_ENABLE         (2<<7)
+#define  DREF_SUPERSPREAD_SOURCE_MASK          (3<<7)
 #define  DREF_SSC4_DOWNSPREAD                   (0<<6)
 #define  DREF_SSC4_CENTERSPREAD                 (1<<6)
 #define  DREF_SSC1_DISABLE                      (0<<1)
index 607bd2fd21b9fd0798c9024b2963f0b1360becff..515e0b99f32ee3e547f49b8abcc5102e6ee9ba85 100644 (file)
@@ -1159,6 +1159,30 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
        }
 }
 
+static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+{
+       u32 val;
+       bool enabled;
+
+       val = I915_READ(PCH_DREF_CONTROL);
+       enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
+                           DREF_SUPERSPREAD_SOURCE_MASK));
+       WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
+}
+
+static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
+                                      enum pipe pipe)
+{
+       int reg;
+       u32 val;
+       bool enabled;
+
+       reg = TRANSCONF(pipe);
+       val = I915_READ(reg);
+       enabled = !!(val & TRANS_ENABLE);
+       WARN(enabled, "transcoder assertion failed, should be off on pipe %c but is still active\n", pipe ? 'B' :'A');
+}
+
 /**
  * intel_enable_pll - enable a PLL
  * @dev_priv: i915 private structure
@@ -1226,6 +1250,54 @@ static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
        POSTING_READ(reg);
 }
 
+/**
+ * intel_enable_pch_pll - enable PCH PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to enable
+ *
+ * The PCH PLL needs to be enabled before the PCH transcoder, since it
+ * drives the transcoder clock.
+ */
+static void intel_enable_pch_pll(struct drm_i915_private *dev_priv,
+                                enum pipe pipe)
+{
+       int reg;
+       u32 val;
+
+       /* PCH only available on ILK+ */
+       BUG_ON(dev_priv->info->gen < 5);
+
+       /* PCH refclock must be enabled first */
+       assert_pch_refclk_enabled(dev_priv);
+
+       reg = PCH_DPLL(pipe);
+       val = I915_READ(reg);
+       val |= DPLL_VCO_ENABLE;
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+       udelay(200);
+}
+
+static void intel_disable_pch_pll(struct drm_i915_private *dev_priv,
+                                 enum pipe pipe)
+{
+       int reg;
+       u32 val;
+
+       /* PCH only available on ILK+ */
+       BUG_ON(dev_priv->info->gen < 5);
+
+       /* Make sure transcoder isn't still depending on us */
+       assert_transcoder_disabled(dev_priv, pipe);
+
+       reg = PCH_DPLL(pipe);
+       val = I915_READ(reg);
+       val &= ~DPLL_VCO_ENABLE;
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
+       udelay(200);
+}
+
 /**
  * intel_enable_pipe - enable a pipe, assertiing requirements
  * @dev_priv: i915 private structure
@@ -2360,14 +2432,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        else
                ironlake_fdi_link_train(crtc);
 
-       /* enable PCH DPLL */
-       reg = PCH_DPLL(pipe);
-       temp = I915_READ(reg);
-       if ((temp & DPLL_VCO_ENABLE) == 0) {
-               I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
-               POSTING_READ(reg);
-               udelay(200);
-       }
+       intel_enable_pch_pll(dev_priv, pipe);
 
        if (HAS_PCH_CPT(dev)) {
                /* Be sure PCH DPLL SEL is set */
@@ -2553,9 +2618,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
        }
 
        /* disable PCH DPLL */
-       reg = PCH_DPLL(pipe);
-       temp = I915_READ(reg);
-       I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
+       intel_disable_pch_pll(dev_priv, pipe);
 
        /* Switch from PCDclk to Rawclk */
        reg = FDI_RX_CTL(pipe);