On Sun, 19 Aug 2012 21:13:07 +0200 Daniel Vetter <daniel.vetter at ffwll.ch> wrote: > 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 on 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. > > 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). > > Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch> > --- > drivers/gpu/drm/i915/intel_display.c | 89 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 89 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index c59569e..4334400 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -6706,6 +6706,91 @@ fail: > return ERR_PTR(-EINVAL); > } > > +/* Computes which crtcs are affected and sets the relevant bits in the mask. For > + * simplicity we use the crtc's pipe number (because it's easier to obtain). */ > +static void > +intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes, > + unsigned *prepare_pipes, unsigned *disable_pipes) > +{ > + struct intel_crtc *intel_crtc; > + struct drm_device *dev = crtc->dev; > + struct intel_encoder *encoder; > + struct intel_connector *connector; > + struct drm_crtc *tmp_crtc; > + > + *disable_pipes = *modeset_pipes = *prepare_pipes = 0; > + > + /* Check which crtcs have changed outputs connected to them, these need > + * to be part of the prepare_pipes mask. We don't (yet) support global > + * modeset across multiple crtcs, so modeset_pipes will only have one > + * bit set at most. */ > + list_for_each_entry(connector, &dev->mode_config.connector_list, > + base.head) { > + if (connector->base.encoder == &connector->new_encoder->base) > + continue; > + > + if (connector->base.encoder) { > + tmp_crtc = connector->base.encoder->crtc; > + > + *prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe; > + } > + > + if (connector->new_encoder) > + *prepare_pipes |= > + 1 << connector->new_encoder->new_crtc->pipe; > + } > + > + list_for_each_entry(encoder, &dev->mode_config.encoder_list, > + base.head) { > + if (encoder->base.crtc == &encoder->new_crtc->base) > + continue; > + > + if (encoder->base.crtc) { > + tmp_crtc = encoder->base.crtc; > + > + *prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe; > + } > + > + if (encoder->new_crtc) > + *prepare_pipes |= 1 << encoder->new_crtc->pipe; > + } > + > + /* Check for any pipes that will be fully disabled ... */ > + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, > + base.head) { > + bool used = false; > + > + /* Don't try to disable disabled crtcs. */ > + if (!intel_crtc->base.enabled) > + continue; > + > + list_for_each_entry(encoder, &dev->mode_config.encoder_list, > + base.head) { > + if (encoder->new_crtc == intel_crtc) > + used = true; > + } > + > + if (!used) > + *disable_pipes |= 1 << intel_crtc->pipe; > + } > + > + > + /* set_mode is also used to update properties on life display pipes. */ > + intel_crtc = to_intel_crtc(crtc); > + if (!*disable_pipes && crtc->enabled) > + *prepare_pipes |= 1 << intel_crtc->pipe; > + > + /* We only support modeset on one single crtc, hence we need to do that > + * only for the passed in crtc iff we change anything else than just > + * disable crtcs. */ > + if (*prepare_pipes) > + *modeset_pipes |= 1 << intel_crtc->pipe; > + > + /* ... and mask these out. */ > + *modeset_pipes &= ~(*disable_pipes); > + *prepare_pipes &= ~(*disable_pipes); > +} > + > bool intel_set_mode(struct drm_crtc *crtc, > struct drm_display_mode *mode, > int x, int y, struct drm_framebuffer *fb) > @@ -6715,8 +6800,12 @@ bool intel_set_mode(struct drm_crtc *crtc, > struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; > struct drm_encoder_helper_funcs *encoder_funcs; > struct drm_encoder *encoder; > + unsigned disable_pipe, prepare_pipes, modeset_pipes; > bool ret = true; > > + intel_modeset_affected_pipes(crtc, &modeset_pipes, > + &prepare_pipes, &disable_pipe); > + > intel_modeset_commit_output_state(dev); > > crtc->enabled = drm_helper_crtc_in_use(crtc); Reviewed-by: Jesse Barnes <jbarnes at virtuousgeek.org> -- Jesse Barnes, Intel Open Source Technology Center