drm/i915: rewrite the LCPLL code
authorPaulo Zanoni <paulo.r.zanoni@intel.com>
Fri, 5 Oct 2012 15:05:52 +0000 (12:05 -0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 10 Oct 2012 13:47:39 +0000 (15:47 +0200)
Right now, we're trying to enable LCPLL at every mode set, but we're
never disabling it. Also, we really don't want to be disabling LCPLL
since it requires a very complex disable/enable sequence. This
register should really be set by the BIOS and we shouldn't be touching
it. Still, let's try to check its value and print some errors in case
we find something wrong. We're also adding intel_ddi_get_cdclk_freq
which will be used later in other places.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h

index f3a06b421be4a3a8fbaa168c7898fb8c250e1c70..5107ceece3b032757dbe264630c881860a6f0fd6 100644 (file)
 #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG         0x9030
 #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB      (1<<11)
 
+#define HSW_FUSE_STRAP         0x42014
+#define  HSW_CDCLK_LIMIT       (1 << 24)
+
 /* PCH */
 
 /* south display engine interrupt: IBX */
 #define LCPLL_CTL                      0x130040
 #define  LCPLL_PLL_DISABLE             (1<<31)
 #define  LCPLL_PLL_LOCK                        (1<<30)
+#define  LCPLL_CLK_FREQ_MASK           (3<<26)
+#define  LCPLL_CLK_FREQ_450            (0<<26)
 #define  LCPLL_CD_CLOCK_DISABLE                (1<<25)
 #define  LCPLL_CD2X_CLOCK_DISABLE      (1<<23)
+#define  LCPLL_CD_SOURCE_FCLK          (1<<21)
 
 /* Pipe WM_LINETIME - watermark line time */
 #define PIPE_WM_LINETIME_A             0x45270
index bfe375466a0e03b953022248e65cfafdf3a17874..187ea3bdc6630cc0cb8430aa3a08a4c437227a47 100644 (file)
@@ -682,12 +682,6 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
        DRM_DEBUG_KMS("WR PLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
                      crtc->mode.clock, p, n2, r2);
 
-       /* Enable LCPLL if disabled */
-       temp = I915_READ(LCPLL_CTL);
-       if (temp & LCPLL_PLL_DISABLE)
-               I915_WRITE(LCPLL_CTL,
-                               temp & ~LCPLL_PLL_DISABLE);
-
        /* Configure WR PLL 1, program the correct divider values for
         * the desired frequency and wait for warmup */
        I915_WRITE(WRPLL_CTL1,
@@ -817,3 +811,34 @@ void intel_disable_ddi(struct intel_encoder *encoder)
 
        I915_WRITE(DDI_BUF_CTL(port), temp);
 }
+
+static int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
+{
+       if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT)
+               return 450;
+       else if ((I915_READ(LCPLL_CTL) & LCPLL_CLK_FREQ_MASK) ==
+                LCPLL_CLK_FREQ_450)
+               return 450;
+       else
+               return 540;
+}
+
+void intel_ddi_pll_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t val = I915_READ(LCPLL_CTL);
+
+       /* The LCPLL register should be turned on by the BIOS. For now let's
+        * just check its state and print errors in case something is wrong.
+        * Don't even try to turn it on.
+        */
+
+       DRM_DEBUG_KMS("CDCLK running at %dMHz\n",
+                     intel_ddi_get_cdclk_freq(dev_priv));
+
+       if (val & LCPLL_CD_SOURCE_FCLK)
+               DRM_ERROR("CDCLK source is not LCPLL\n");
+
+       if (val & LCPLL_PLL_DISABLE)
+               DRM_ERROR("LCPLL is disabled\n");
+}
index 6cf0d003d7150925c5bc688eb620f26c225d0c0e..40f98d179d80dc9fad03273da65105c83ff24172 100644 (file)
@@ -7477,6 +7477,12 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
        .page_flip = intel_crtc_page_flip,
 };
 
+static void intel_cpu_pll_init(struct drm_device *dev)
+{
+       if (IS_HASWELL(dev))
+               intel_ddi_pll_init(dev);
+}
+
 static void intel_pch_pll_init(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -8085,6 +8091,7 @@ void intel_modeset_init(struct drm_device *dev)
                        DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
        }
 
+       intel_cpu_pll_init(dev);
        intel_pch_pll_init(dev);
 
        /* Just disable it once at startup */
index 79f8ed66574e3339b600535f6e07596fa1b5f27c..57566b713a7a6555ba8ccb25879aa9f134418204 100644 (file)
@@ -580,5 +580,6 @@ extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 extern void intel_ddi_mode_set(struct drm_encoder *encoder,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode);
+extern void intel_ddi_pll_init(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */