drm/i915: Disable SSC for outputs other than LVDS or DP
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>
This commit is contained in:
parent
9a4114ffa7
commit
633f2ea266
4 changed files with 36 additions and 26 deletions
|
@ -350,6 +350,7 @@ typedef struct drm_i915_private {
|
||||||
unsigned int lvds_vbt:1;
|
unsigned int lvds_vbt:1;
|
||||||
unsigned int int_crt_support:1;
|
unsigned int int_crt_support:1;
|
||||||
unsigned int lvds_use_ssc:1;
|
unsigned int lvds_use_ssc:1;
|
||||||
|
unsigned int display_clock_mode:1;
|
||||||
int lvds_ssc_freq;
|
int lvds_ssc_freq;
|
||||||
struct {
|
struct {
|
||||||
int rate;
|
int rate;
|
||||||
|
|
|
@ -279,6 +279,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
||||||
dev_priv->lvds_use_ssc = general->enable_ssc;
|
dev_priv->lvds_use_ssc = general->enable_ssc;
|
||||||
dev_priv->lvds_ssc_freq =
|
dev_priv->lvds_ssc_freq =
|
||||||
intel_bios_ssc_frequency(dev, general->ssc_freq);
|
intel_bios_ssc_frequency(dev, general->ssc_freq);
|
||||||
|
dev_priv->display_clock_mode = general->display_clock_mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,9 @@ struct bdb_general_features {
|
||||||
u8 ssc_freq:1;
|
u8 ssc_freq:1;
|
||||||
u8 enable_lfp_on_override:1;
|
u8 enable_lfp_on_override:1;
|
||||||
u8 disable_ssc_ddt: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 */
|
/* bits 3 */
|
||||||
u8 disable_smooth_vision:1;
|
u8 disable_smooth_vision:1;
|
||||||
|
|
|
@ -4506,44 +4506,50 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
* ignoring this setting.
|
* ignoring this setting.
|
||||||
*/
|
*/
|
||||||
if (HAS_PCH_SPLIT(dev)) {
|
if (HAS_PCH_SPLIT(dev)) {
|
||||||
|
/*XXX BIOS treats 16:31 as a mask for 0:15 */
|
||||||
|
|
||||||
temp = I915_READ(PCH_DREF_CONTROL);
|
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_MASK;
|
||||||
temp |= DREF_NONSPREAD_SOURCE_ENABLE;
|
|
||||||
temp &= ~DREF_SSC_SOURCE_MASK;
|
temp &= ~DREF_SSC_SOURCE_MASK;
|
||||||
temp |= DREF_SSC_SOURCE_ENABLE;
|
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
|
||||||
I915_WRITE(PCH_DREF_CONTROL, temp);
|
I915_WRITE(PCH_DREF_CONTROL, temp);
|
||||||
|
|
||||||
POSTING_READ(PCH_DREF_CONTROL);
|
POSTING_READ(PCH_DREF_CONTROL);
|
||||||
udelay(200);
|
udelay(200);
|
||||||
|
|
||||||
if (has_edp_encoder) {
|
if ((is_lvds || has_edp_encoder) &&
|
||||||
if (intel_panel_use_ssc(dev_priv)) {
|
intel_panel_use_ssc(dev_priv)) {
|
||||||
temp |= DREF_SSC1_ENABLE;
|
temp |= DREF_SSC_SOURCE_ENABLE;
|
||||||
I915_WRITE(PCH_DREF_CONTROL, temp);
|
if (has_edp_encoder) {
|
||||||
|
if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
|
||||||
POSTING_READ(PCH_DREF_CONTROL);
|
/* Enable CPU source on CPU attached eDP */
|
||||||
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))
|
|
||||||
temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
|
temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
|
||||||
else
|
} else {
|
||||||
temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
|
/* Enable SSC on PCH eDP if needed */
|
||||||
} else {
|
|
||||||
/* Enable SSC on PCH eDP if needed */
|
|
||||||
if (intel_panel_use_ssc(dev_priv)) {
|
|
||||||
DRM_ERROR("enabling SSC on PCH\n");
|
|
||||||
temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
|
temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
|
||||||
}
|
}
|
||||||
|
I915_WRITE(PCH_DREF_CONTROL, temp);
|
||||||
}
|
}
|
||||||
I915_WRITE(PCH_DREF_CONTROL, temp);
|
if (!dev_priv->display_clock_mode)
|
||||||
POSTING_READ(PCH_DREF_CONTROL);
|
temp |= DREF_SSC1_ENABLE;
|
||||||
udelay(200);
|
} 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)) {
|
if (IS_PINEVIEW(dev)) {
|
||||||
|
|
Loading…
Reference in a new issue