diff mbox

drm/i915: the PCH reference clocks are global, so don't clobber unconditionally

Message ID 1296855428-1206-1-git-send-email-jbarnes@virtuousgeek.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jesse Barnes Feb. 4, 2011, 9:37 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fec84f4..a05fd76 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4520,6 +4520,84 @@  static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 	return dev_priv->lvds_use_ssc && i915_panel_use_ssc;
 }
 
+static void intel_update_dref(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct intel_encoder *encoder;
+	struct intel_crtc *intel_crtc;
+	u32 temp;
+	bool lvds_on, edp_on, pch_edp_on = false, other_on;
+
+	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+		if (!encoder->base.crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(encoder->base.crtc);
+
+		if (!intel_crtc->active)
+			continue;
+
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			lvds_on = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			edp_on = true;
+			if (!pch_edp_on)
+				pch_edp_on = intel_encoder_is_pch_edp(&encoder->base);
+			break;
+		default:
+			other_on = true;
+			break;
+		}
+	}
+
+	/*XXX BIOS treats 16:31 as a mask for 0:15 */
+
+	temp = I915_READ(PCH_DREF_CONTROL);
+
+	/* 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_SSC_SOURCE_MASK;
+	temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+	I915_WRITE(PCH_DREF_CONTROL, temp);
+
+	POSTING_READ(PCH_DREF_CONTROL);
+	udelay(200);
+
+	if ((lvds_on || edp_on) && intel_panel_use_ssc(dev_priv)) {
+		temp |= DREF_SSC_SOURCE_ENABLE;
+		if (edp_on) {
+			if (!pch_edp_on) {
+				/* Enable CPU source on CPU attached eDP */
+				temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+			} else {
+				/* Enable SSC on PCH eDP if needed */
+				temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
+			}
+			I915_WRITE(PCH_DREF_CONTROL, temp);
+		}
+		if (!dev_priv->display_clock_mode)
+			temp |= DREF_SSC1_ENABLE;
+	}
+
+	if (other_on && dev_priv->display_clock_mode)
+		temp |= DREF_NONSPREAD_CK505_ENABLE;
+	else if (other_on) {
+		temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+		if (edp_on && !pch_edp_on)
+			temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+	}
+
+	I915_WRITE(PCH_DREF_CONTROL, temp);
+	POSTING_READ(PCH_DREF_CONTROL);
+	udelay(200);
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
@@ -4745,52 +4823,8 @@  static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	 * PCH B stepping, previous chipset stepping should be
 	 * 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);
-
-		/* 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_SSC_SOURCE_MASK;
-		temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-		I915_WRITE(PCH_DREF_CONTROL, temp);
-
-		POSTING_READ(PCH_DREF_CONTROL);
-		udelay(200);
-
-		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 {
-					/* Enable SSC on PCH eDP if needed */
-					temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
-				}
-				I915_WRITE(PCH_DREF_CONTROL, temp);
-			}
-			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 (HAS_PCH_SPLIT(dev))
+		intel_update_dref(dev_priv);
 
 	if (IS_PINEVIEW(dev)) {
 		fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;