diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eaec56ef12b649dacdc87bc0df0836c3f1958155..52ceae5713975d4a655ad13d4601c51e59dfcdf0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -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; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4b95295ab04ab2d08ae367261052bfdd6422a7d1..35c3b1442ba9de9bc382f739c891a598738da53c 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -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; } } diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 5f8e4edcbbb901937a20a522f60057ea762a0a9d..02b1b62415df5759697d712c4135513707043207 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -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; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2c7e90f12657ae01e113ee1094f1a322d29ec74d..2f58d97972db99d0c1c399346059ef2c7c262b63 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -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)) {