aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-07-08 15:14:38 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-09-06 02:21:26 -0400
commite2e1ed41ed6e3012464e8a8e7cf7bbcb6d3f7412 (patch)
tree3b1d331247cadc8bcd965b42c3e61aa0913240f2 /drivers/gpu/drm/i915/intel_display.c
parente24c5c2900ba45e2fa5ed8575ab75f6d4c7e8156 (diff)
drm/i915: compute masks of crtcs affected in set_mode
This is definetely a bit more generic than currently required, but if we keep track of all crtcs that need to be disabled/enable (because they loose an encoder or something similar), crtcs that get completely disabled and those that we need to do an actual mode change nicely prepares us for global modeset operations on multiple crtcs. The only big thing missing here would be a global resource allocation step (for e.g. pch plls), which would equally frob these bitmasks if e.g. a crtc only needs a new pll. Or if we need to enable dithering on an another pipe due to bandwidth constrains somewhere. These masks aren't yet put to use in this patch, this will follow in the next one. v2-v5: Fix up the computations for good (hopefully). v6: Fixup a confusion reported by Damien Lespiau: I've conserved the (imo braindead) behaviour of the crtc helper to disable _any_ disconnected outputs if we do a modeset, even when that newly disabled connector isn't connected to the crtc being changed by the modeset. The effect of that is that we could disable an arbitrary number of unrelated crtcs, which I haven't taken into account when writing this code. Fix this up. Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3eec29c75d2e..d354aa0b8eed 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6706,6 +6706,98 @@ fail:
6706 return ERR_PTR(-EINVAL); 6706 return ERR_PTR(-EINVAL);
6707} 6707}
6708 6708
6709/* Computes which crtcs are affected and sets the relevant bits in the mask. For
6710 * simplicity we use the crtc's pipe number (because it's easier to obtain). */
6711static void
6712intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
6713 unsigned *prepare_pipes, unsigned *disable_pipes)
6714{
6715 struct intel_crtc *intel_crtc;
6716 struct drm_device *dev = crtc->dev;
6717 struct intel_encoder *encoder;
6718 struct intel_connector *connector;
6719 struct drm_crtc *tmp_crtc;
6720
6721 *disable_pipes = *modeset_pipes = *prepare_pipes = 0;
6722
6723 /* Check which crtcs have changed outputs connected to them, these need
6724 * to be part of the prepare_pipes mask. We don't (yet) support global
6725 * modeset across multiple crtcs, so modeset_pipes will only have one
6726 * bit set at most. */
6727 list_for_each_entry(connector, &dev->mode_config.connector_list,
6728 base.head) {
6729 if (connector->base.encoder == &connector->new_encoder->base)
6730 continue;
6731
6732 if (connector->base.encoder) {
6733 tmp_crtc = connector->base.encoder->crtc;
6734
6735 *prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
6736 }
6737
6738 if (connector->new_encoder)
6739 *prepare_pipes |=
6740 1 << connector->new_encoder->new_crtc->pipe;
6741 }
6742
6743 list_for_each_entry(encoder, &dev->mode_config.encoder_list,
6744 base.head) {
6745 if (encoder->base.crtc == &encoder->new_crtc->base)
6746 continue;
6747
6748 if (encoder->base.crtc) {
6749 tmp_crtc = encoder->base.crtc;
6750
6751 *prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
6752 }
6753
6754 if (encoder->new_crtc)
6755 *prepare_pipes |= 1 << encoder->new_crtc->pipe;
6756 }
6757
6758 /* Check for any pipes that will be fully disabled ... */
6759 list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
6760 base.head) {
6761 bool used = false;
6762
6763 /* Don't try to disable disabled crtcs. */
6764 if (!intel_crtc->base.enabled)
6765 continue;
6766
6767 list_for_each_entry(encoder, &dev->mode_config.encoder_list,
6768 base.head) {
6769 if (encoder->new_crtc == intel_crtc)
6770 used = true;
6771 }
6772
6773 if (!used)
6774 *disable_pipes |= 1 << intel_crtc->pipe;
6775 }
6776
6777
6778 /* set_mode is also used to update properties on life display pipes. */
6779 intel_crtc = to_intel_crtc(crtc);
6780 if (crtc->enabled)
6781 *prepare_pipes |= 1 << intel_crtc->pipe;
6782
6783 /* We only support modeset on one single crtc, hence we need to do that
6784 * only for the passed in crtc iff we change anything else than just
6785 * disable crtcs.
6786 *
6787 * This is actually not true, to be fully compatible with the old crtc
6788 * helper we automatically disable _any_ output (i.e. doesn't need to be
6789 * connected to the crtc we're modesetting on) if it's disconnected.
6790 * Which is a rather nutty api (since changed the output configuration
6791 * without userspace's explicit request can lead to confusion), but
6792 * alas. Hence we currently need to modeset on all pipes we prepare. */
6793 if (*prepare_pipes)
6794 *modeset_pipes = *prepare_pipes;
6795
6796 /* ... and mask these out. */
6797 *modeset_pipes &= ~(*disable_pipes);
6798 *prepare_pipes &= ~(*disable_pipes);
6799}
6800
6709bool intel_set_mode(struct drm_crtc *crtc, 6801bool intel_set_mode(struct drm_crtc *crtc,
6710 struct drm_display_mode *mode, 6802 struct drm_display_mode *mode,
6711 int x, int y, struct drm_framebuffer *fb) 6803 int x, int y, struct drm_framebuffer *fb)
@@ -6715,8 +6807,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
6715 struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; 6807 struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
6716 struct drm_encoder_helper_funcs *encoder_funcs; 6808 struct drm_encoder_helper_funcs *encoder_funcs;
6717 struct drm_encoder *encoder; 6809 struct drm_encoder *encoder;
6810 unsigned disable_pipe, prepare_pipes, modeset_pipes;
6718 bool ret = true; 6811 bool ret = true;
6719 6812
6813 intel_modeset_affected_pipes(crtc, &modeset_pipes,
6814 &prepare_pipes, &disable_pipe);
6815
6720 intel_modeset_commit_output_state(dev); 6816 intel_modeset_commit_output_state(dev);
6721 6817
6722 crtc->enabled = drm_helper_crtc_in_use(crtc); 6818 crtc->enabled = drm_helper_crtc_in_use(crtc);