From cb02099d4ab00f87d7039e717e6fc46715b231f0 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Fri, 19 Dec 2014 13:32:55 +0200 Subject: [PATCH] drm/i915: Fix all pipe->plane mappings before sanitizing crtc If QUIRK_PIPEA_FORCE is necessary, intel_sanitize_crtc() might trigger a mode set. In that case, if pipe A is disabled and pipe B is mapped to plane B, that mode set happens before the mapping is fixed. Due to the wrong state, the call to disable pipe B disables plane A (which is already disabled) and later an assertion for plane B being enabled (while it should have been disabled) is triggered. References: https://bugs.freedesktop.org/show_bug.cgi?id=72782 Signed-off-by: Ander Conselvan de Oliveira --- drivers/gpu/drm/i915/intel_display.c | 50 +++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d01db1b..cf87528 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13127,30 +13127,22 @@ intel_check_plane_mapping(struct intel_crtc *crtc) return true; } -static void intel_sanitize_crtc(struct intel_crtc *crtc) +static void intel_fix_plane_mapping(struct drm_device *dev) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg; - - /* Clear any frame start delays used for debugging left by the BIOS */ - reg = PIPECONF(crtc->config.cpu_transcoder); - I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc; - /* restore vblank interrupts to correct state */ - if (crtc->active) { - update_scanline_offset(crtc); - drm_vblank_on(dev, crtc->pipe); - } else - drm_vblank_off(dev, crtc->pipe); + /* gen4+ has a fixed plane -> pipe mapping.*/ + if (INTEL_INFO(dev)->gen >= 4) + return; - /* We need to sanitize the plane -> pipe mapping first because this will - * disable the crtc (and hence change the state) if it is wrong. Note - * that gen4+ has a fixed plane -> pipe mapping. */ - if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) { + for_each_intel_crtc(dev, crtc) { struct intel_connector *connector; bool plane; + if (intel_check_plane_mapping(crtc)) + continue; + DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n", crtc->base.base.id); @@ -13184,6 +13176,24 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) WARN_ON(crtc->active); crtc->base.enabled = false; } +} + +static void intel_sanitize_crtc(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 reg; + + /* Clear any frame start delays used for debugging left by the BIOS */ + reg = PIPECONF(crtc->config.cpu_transcoder); + I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); + + /* restore vblank interrupts to correct state */ + if (crtc->active) { + update_scanline_offset(crtc); + drm_vblank_on(dev, crtc->pipe); + } else + drm_vblank_off(dev, crtc->pipe); if (dev_priv->quirks & QUIRK_PIPEA_FORCE && crtc->pipe == PIPE_A && !crtc->active) { @@ -13442,6 +13452,10 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, intel_sanitize_encoder(encoder); } + /* We need to sanitize the plane -> pipe mapping first because this will + * disable the crtc (and hence change the state) if it is wrong. */ + intel_fix_plane_mapping(dev); + for_each_pipe(dev_priv, pipe) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); intel_sanitize_crtc(crtc); -- 1.9.1