@@ -1626,6 +1626,72 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv,
intel_wait_for_vblank(dev_priv->dev, pipe);
}
+static void disable_pch_dp(struct drm_i915_private *dev_priv,
+ enum pipe pipe, int reg)
+{
+ u32 val;
+ u32 sel_pipe;
+
+ val = I915_READ(reg);
+ sel_pipe = (val & DP_PIPEB_SELECT) >> 30;
+ if ((val & DP_PORT_EN) && sel_pipe == pipe) {
+ I915_WRITE(reg, val & ~DP_PORT_EN);
+ POSTING_READ(reg);
+ }
+}
+
+static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
+ enum pipe pipe, int reg)
+{
+ u32 val;
+ u32 sel_pipe;
+
+ val = I915_READ(reg);
+ sel_pipe = (val & TRANSCODER_B) >> 30;
+ if ((val & PORT_ENABLE) && sel_pipe == pipe) {
+ I915_WRITE(reg, val & ~PORT_ENABLE);
+ POSTING_READ(reg);
+ }
+}
+
+/* Disable any ports connected to this transcoder */
+static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
+ enum pipe pipe)
+{
+ int reg;
+ u32 val;
+ u32 sel_pipe;
+
+ val = I915_READ(PCH_PP_CONTROL);
+ I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS);
+ POSTING_READ(PCH_PP_CONTROL);
+
+ disable_pch_dp(dev_priv, pipe, PCH_DP_B);
+ disable_pch_dp(dev_priv, pipe, PCH_DP_C);
+ disable_pch_dp(dev_priv, pipe, PCH_DP_D);
+
+ reg = PCH_ADPA;
+ val = I915_READ(reg);
+ sel_pipe = (val & ADPA_TRANS_B_SELECT) >> 30;
+ if ((val & ADPA_DAC_ENABLE) && sel_pipe == pipe) {
+ I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
+ POSTING_READ(reg);
+ }
+
+ reg = PCH_LVDS;
+ val = I915_READ(reg);
+ sel_pipe = (val & LVDS_PIPEB_SELECT) >> 30;
+ if ((val & LVDS_PORT_EN) && sel_pipe == pipe) {
+ I915_WRITE(reg, val & ~LVDS_PORT_EN);
+ POSTING_READ(reg);
+ udelay(100);
+ }
+
+ disable_pch_hdmi(dev_priv, pipe, HDMIB);
+ disable_pch_hdmi(dev_priv, pipe, HDMIC);
+ disable_pch_hdmi(dev_priv, pipe, HDMID);
+}
+
static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
{
struct drm_device *dev = crtc->dev;
@@ -2865,14 +2931,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
ironlake_fdi_disable(crtc);
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
- temp = I915_READ(PCH_LVDS);
- if (temp & LVDS_PORT_EN) {
- I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN);
- POSTING_READ(PCH_LVDS);
- udelay(100);
- }
- }
+ intel_disable_pch_ports(dev_priv, pipe);
intel_disable_transcoder(dev_priv, pipe);