This is a horrible layering violation; we should be doing this in the connector/encoder ->prepare instead, but we don't always have enough information there about the config to know whether it will actually be necessary or just cause unnecessary flicker.
-- Jesse Barnes, Intel Open Source Technology Center >From 5600b8266132dc704079757c2f513fe4fef5eb21 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbar...@virtuousgeek.org> Date: Wed, 2 Feb 2011 13:37:07 -0800 Subject: [PATCH 1/3] drm/i915: disable PCH ports if needed when disabling a CRTC Disable any PCH ports associated with a pipe when disabling it. This should prevent transcoder disable failures due to ports still being on. Signed-off-by: Jesse Barnes <jbar...@virtuousgeek.org> --- drivers/gpu/drm/i915/intel_display.c | 75 ++++++++++++++++++++++++++++++---- 1 files changed, 67 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cc431f4..a22483e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -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); -- 1.7.2.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx