[Intel-gfx] [PATCH 2/2] drm/i915: enable/disable spread spectrum as needed on mode set
Jesse Barnes
jbarnes at virtuousgeek.org
Thu Aug 11 22:38:51 CEST 2011
This resurrects Chris's old code to better manage the PCH reference
clock. With some previous mode setting bugs fixed, it appears work work
now.
v2: fix compile error
Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/intel_bios.c | 1 +
drivers/gpu/drm/i915/intel_bios.h | 4 ++-
drivers/gpu/drm/i915/intel_display.c | 63 +++++++++++++++++++---------------
4 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index feb4f16..303e4b3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -356,6 +356,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 61abef8..de3460e 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -309,6 +309,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 5f8e4ed..02b1b624 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 644fd4cb..2465ad8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5057,6 +5057,7 @@ static void ironlake_update_pch_refclk(struct drm_device *dev)
struct intel_encoder *encoder;
struct intel_encoder *has_edp_encoder = NULL;
u32 temp;
+ int num_connectors = 0;
bool has_lvds = false;
/* We need to take the global config into account */
@@ -5076,6 +5077,7 @@ static void ironlake_update_pch_refclk(struct drm_device *dev)
has_edp_encoder = encoder;
break;
}
+ num_connectors++;
}
}
@@ -5085,43 +5087,48 @@ static void ironlake_update_pch_refclk(struct drm_device *dev)
* ignoring this setting.
*/
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;
- I915_WRITE(PCH_DREF_CONTROL, temp);
-
- POSTING_READ(PCH_DREF_CONTROL);
- udelay(200);
+ temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
- 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;
+ if (!num_connectors)
+ goto out;
- /* 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 ((has_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))
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");
temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
- }
}
- I915_WRITE(PCH_DREF_CONTROL, temp);
- POSTING_READ(PCH_DREF_CONTROL);
- udelay(200);
+ if (!dev_priv->display_clock_mode)
+ temp |= DREF_SSC1_ENABLE;
+ num_connectors--;
+ }
+
+ /* Unhandled outputs need non-SSC clock */
+ if (num_connectors) {
+ 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) &&
+ !intel_panel_use_ssc(dev_priv))
+ temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
}
+
+out:
+ I915_WRITE(PCH_DREF_CONTROL, temp);
+ POSTING_READ(PCH_DREF_CONTROL);
+ udelay(200);
}
static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
--
1.7.4.1
More information about the Intel-gfx
mailing list