From 333f7ec9797b62a4e6003abbf614873951e2435c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 3 Dec 2010 15:37:31 +0000 Subject: [PATCH] drm/i915: Clean conflicting modesetting registers upon init If we leaves the registers in a conflicting state then when we attempt to teardown the current mode, we will not disable the pipes and planes in the correct order -- leaving a plane reading from a disabled pipe and possibly leading to undefined behaviour. Reported-by: Andy Whitcroft Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=32078 Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f7962b7..a41f675 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5248,6 +5248,43 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .page_flip = intel_crtc_page_flip, }; +static void intel_sanitize_modesetting(struct drm_device *dev, + int pipe, int plane) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 reg, val; + + if (HAS_PCH_SPLIT(dev)) + return; + + /* Who knows what state these registers were left in by the BIOS or + * grub? If they don't match our expectations then we will likely fail + * to switch modes correctly. + */ + + reg = DSPCNTR(plane); + val = I915_READ(reg); + if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe) + return; + + /* This display plane is therefore attached to the other CPU pipe. */ + pipe = !pipe; + + if (val & DISPLAY_PLANE_ENABLE) { + I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); + intel_flush_display_plane(dev, plane); + + if (IS_GEN2(dev)) + intel_wait_for_vblank(dev, pipe); + } + + reg = PIPECONF(pipe); + val = I915_READ(reg); + if (val & PIPECONF_ENABLE) { + I915_WRITE(reg, val & ~PIPECONF_ENABLE); + intel_wait_for_pipe_off(dev, pipe); + } +} static void intel_crtc_init(struct drm_device *dev, int pipe) { @@ -5299,6 +5336,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer, (unsigned long)intel_crtc); + + intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane); } int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, -- 1.7.2.3