drm/i915: Disable SSC for outputs other than LVDS or DP
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 19 Jan 2011 13:29:42 +0000 (13:29 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 19 Jan 2011 13:33:27 +0000 (13:33 +0000)
For CRT and SDVO/HDMI, we need to use a normal, non-SSC, clock and so we
must clear any enabling bits left-over from earlier outputs. And also
seems to correct the LVDS panel on the Lenovo U160.

However, at one point, it did cause an "ERROR failed to disable
trancoder". So prolonged testing on top of Jesse's refactored and
error-checking CRTC logic is desired.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_display.c

index eaec56ef12b649dacdc87bc0df0836c3f1958155..52ceae5713975d4a655ad13d4601c51e59dfcdf0 100644 (file)
@@ -350,6 +350,7 @@ typedef struct drm_i915_private {
        unsigned int lvds_vbt:1;
        unsigned int int_crt_support:1;
        unsigned int lvds_use_ssc:1;
+       unsigned int display_clock_mode:1;
        int lvds_ssc_freq;
        struct {
                int rate;
index 4b95295ab04ab2d08ae367261052bfdd6422a7d1..35c3b1442ba9de9bc382f739c891a598738da53c 100644 (file)
@@ -279,6 +279,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
                dev_priv->lvds_use_ssc = general->enable_ssc;
                dev_priv->lvds_ssc_freq =
                        intel_bios_ssc_frequency(dev, general->ssc_freq);
+               dev_priv->display_clock_mode = general->display_clock_mode;
        }
 }
 
index 5f8e4edcbbb901937a20a522f60057ea762a0a9d..02b1b62415df5759697d712c4135513707043207 100644 (file)
@@ -120,7 +120,9 @@ struct bdb_general_features {
        u8 ssc_freq:1;
        u8 enable_lfp_on_override:1;
        u8 disable_ssc_ddt:1;
-       u8 rsvd8:3; /* finish byte */
+       u8 rsvd7:1;
+       u8 display_clock_mode:1;
+       u8 rsvd8:1; /* finish byte */
 
         /* bits 3 */
        u8 disable_smooth_vision:1;
index 2c7e90f12657ae01e113ee1094f1a322d29ec74d..2f58d97972db99d0c1c399346059ef2c7c262b63 100644 (file)
@@ -4506,44 +4506,50 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
         * ignoring this setting.
         */
        if (HAS_PCH_SPLIT(dev)) {
+               /*XXX BIOS treats 16:31 as a mask for 0:15 */
+
                temp = I915_READ(PCH_DREF_CONTROL);
-               /* Always enable nonspread source */
+
+               /* First clear the current state for output switching */
+               temp &= ~DREF_SSC1_ENABLE;
+               temp &= ~DREF_SSC4_ENABLE;
+               temp &= ~DREF_SUPERSPREAD_SOURCE_MASK;
                temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-               temp |= DREF_NONSPREAD_SOURCE_ENABLE;
                temp &= ~DREF_SSC_SOURCE_MASK;
-               temp |= DREF_SSC_SOURCE_ENABLE;
+               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
                I915_WRITE(PCH_DREF_CONTROL, temp);
 
                POSTING_READ(PCH_DREF_CONTROL);
                udelay(200);
 
-               if (has_edp_encoder) {
-                       if (intel_panel_use_ssc(dev_priv)) {
-                               temp |= DREF_SSC1_ENABLE;
-                               I915_WRITE(PCH_DREF_CONTROL, temp);
-
-                               POSTING_READ(PCH_DREF_CONTROL);
-                               udelay(200);
-                       }
-                       temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-
-                       /* Enable CPU source on CPU attached eDP */
-                       if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-                               if (intel_panel_use_ssc(dev_priv))
+               if ((is_lvds || has_edp_encoder) &&
+                   intel_panel_use_ssc(dev_priv)) {
+                       temp |= DREF_SSC_SOURCE_ENABLE;
+                       if (has_edp_encoder) {
+                               if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+                                       /* Enable CPU source on CPU attached eDP */
                                        temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
-                               else
-                                       temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
-                       } else {
-                               /* Enable SSC on PCH eDP if needed */
-                               if (intel_panel_use_ssc(dev_priv)) {
-                                       DRM_ERROR("enabling SSC on PCH\n");
+                               } else {
+                                       /* Enable SSC on PCH eDP if needed */
                                        temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
                                }
+                               I915_WRITE(PCH_DREF_CONTROL, temp);
                        }
-                       I915_WRITE(PCH_DREF_CONTROL, temp);
-                       POSTING_READ(PCH_DREF_CONTROL);
-                       udelay(200);
+                       if (!dev_priv->display_clock_mode)
+                               temp |= DREF_SSC1_ENABLE;
+               } else {
+                       if (dev_priv->display_clock_mode)
+                               temp |= DREF_NONSPREAD_CK505_ENABLE;
+                       else
+                               temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+                       if (has_edp_encoder &&
+                           !intel_encoder_is_pch_edp(&has_edp_encoder->base))
+                               temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
                }
+
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
        }
 
        if (IS_PINEVIEW(dev)) {