diff mbox

[2/2] drm/i915: enable/disable spread spectrum as needed on mode set

Message ID 1312401561-4879-3-git-send-email-jbarnes@virtuousgeek.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jesse Barnes Aug. 3, 2011, 7:59 p.m. UTC
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.

Signed-off-by: Jesse Barnes <jbarnes@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 mbox

Patch

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..0f627a5 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,