aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter2013-04-12 11:48:43 -0500
committerGreg Kroah-Hartman2013-05-11 15:54:03 -0500
commit9f75bb3137659e678ccdfe353f73adb0d7f6cb68 (patch)
tree858058cb0464ca20d3cec265e910b9053ce41a52
parent99367f6b937fd2cd0148c933b76ce7b4883d6501 (diff)
downloadkernel-omap-9f75bb3137659e678ccdfe353f73adb0d7f6cb68.tar.gz
kernel-omap-9f75bb3137659e678ccdfe353f73adb0d7f6cb68.tar.xz
kernel-omap-9f75bb3137659e678ccdfe353f73adb0d7f6cb68.zip
drm/i915: Fixup Oops in the pipe config computation
commit b6c5164d7bf624f3e1b750787ddb983150c5117c upstream. Yet again our current confusion between doing the modeset globally, but only having the new parameters for one crtc at a time. So that intel_set_mode essentially already does a global modeset: intel_modeset_affected_pipes compares the current state with where we want to go to (which is carefully set up by intel_crtc_set_config) and then goes through the modeset sequence for any crtc which needs updating. Now the issue is that the actual interface with the remaining code still only works on one crtc, and so we only pass in one fb and one mode. In intel_set_mode we also only compute one intel_crtc_config (which should be the one for the crtc we're doing a modeset on). The reason for that mismatch is twofold: - We want to eventually do all modeset as global state changes, so it's just infrastructure prep. - But even the old semantics can change more than one crtc when you e.g. move a connector from crtc A to crtc B, then both crtc A and B need to be updated. Usually that means one pipe is disabled and the other enabled. This is also the reason why the hack doesn't touch the disable_pipes mask. Now hilarity ensued in our kms config restore paths when we actually try to do a modeset on all crtcs: If the first crtc should be off and the second should be on, then the call on the first crtc will notice that the 2nd one should be switched on and so tries to compute the pipe_config. But due to a lack of passed-in fb (crtc 1 should be off after all) it only results in tears. This case is ridiculously easy to hit on gen2/3 where the lvds output is restricted to pipe B. Note that before the pipe_config bpp rework gen2/3 didn't care really about the fb->depth, so this is a regression brought to light with commit 4e53c2e010e531b4a014692199e978482d471c7e Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Wed Mar 27 00:44:58 2013 +0100 drm/i915: precompute pipe bpp before touching the hw But apparently Ajax also managed to blow up pch platforms, probably with some randomized configs, and pch platforms trip up over the lack of an fb even in the old code. So this actually goes back to the first introduction of the new modeset restore code in commit 45e2b5f640b3766da3eda48f6c35f088155c06f3 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Fri Nov 23 18:16:34 2012 +0100 drm/i915: force restore on lid open Fix this mess by now by justing shunting all the cool new global modeset logic in intel_modeset_affected_pipes. v2: Improve commit message and clean up all the comments in intel_modeset_affected_pipes - since the introduction of the modeset restore code they've been a bit outdated. Bugzill: https://bugzilla.redhat.com/show_bug.cgi?id=917725 References: http://www.mail-archive.com/stable@vger.kernel.org/msg38084.html Tested-by: Richard Cochran <richardcochran@gmail.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6c9535967166..faeaebc719ad 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7732,22 +7732,25 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
7732 if (crtc->enabled) 7732 if (crtc->enabled)
7733 *prepare_pipes |= 1 << intel_crtc->pipe; 7733 *prepare_pipes |= 1 << intel_crtc->pipe;
7734 7734
7735 /* We only support modeset on one single crtc, hence we need to do that 7735 /*
7736 * only for the passed in crtc iff we change anything else than just 7736 * For simplicity do a full modeset on any pipe where the output routing
7737 * disable crtcs. 7737 * changed. We could be more clever, but that would require us to be
7738 * 7738 * more careful with calling the relevant encoder->mode_set functions.
7739 * This is actually not true, to be fully compatible with the old crtc 7739 */
7740 * helper we automatically disable _any_ output (i.e. doesn't need to be
7741 * connected to the crtc we're modesetting on) if it's disconnected.
7742 * Which is a rather nutty api (since changed the output configuration
7743 * without userspace's explicit request can lead to confusion), but
7744 * alas. Hence we currently need to modeset on all pipes we prepare. */
7745 if (*prepare_pipes) 7740 if (*prepare_pipes)
7746 *modeset_pipes = *prepare_pipes; 7741 *modeset_pipes = *prepare_pipes;
7747 7742
7748 /* ... and mask these out. */ 7743 /* ... and mask these out. */
7749 *modeset_pipes &= ~(*disable_pipes); 7744 *modeset_pipes &= ~(*disable_pipes);
7750 *prepare_pipes &= ~(*disable_pipes); 7745 *prepare_pipes &= ~(*disable_pipes);
7746
7747 /*
7748 * HACK: We don't (yet) fully support global modesets. intel_set_config
7749 * obies this rule, but the modeset restore mode of
7750 * intel_modeset_setup_hw_state does not.
7751 */
7752 *modeset_pipes &= 1 << intel_crtc->pipe;
7753 *prepare_pipes &= 1 << intel_crtc->pipe;
7751} 7754}
7752 7755
7753static bool intel_crtc_in_use(struct drm_crtc *crtc) 7756static bool intel_crtc_in_use(struct drm_crtc *crtc)