On Mon, Jul 13, 2015 at 04:30:29PM +0200, Maarten Lankhorst wrote: > Calculate all state using a normal transition, but afterwards fudge > crtc->state->active back to its old value. This should still allow > state restore in setup_hw_state to work properly. > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> Ok merged up to this patch with the exception of patch 8. I think reworking that logic to use mode->private_flags to make sure we do a modeset when userspace changes the mode, but not earlier is a sound approach which will address all my concerns. -Daniel > --- > drivers/gpu/drm/i915/intel_display.c | 52 +++++++++++++++++++++++++++++++++--- > drivers/gpu/drm/i915/intel_drv.h | 2 +- > 2 files changed, 50 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 599af76d34f6..6e3df10a43b9 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -6224,12 +6224,58 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) > * turn all crtc's off, but do not adjust state > * This has to be paired with a call to intel_modeset_setup_hw_state. > */ > -void intel_display_suspend(struct drm_device *dev) > +int intel_display_suspend(struct drm_device *dev) > { > + struct drm_mode_config *config = &dev->mode_config; > + struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx; > + struct drm_atomic_state *state; > struct drm_crtc *crtc; > + unsigned crtc_mask = 0; > + int ret = 0; > + > + if (WARN_ON(!ctx)) > + return 0; > + > + lockdep_assert_held(&ctx->ww_ctx); > + state = drm_atomic_state_alloc(dev); > + if (WARN_ON(!state)) > + return -ENOMEM; > + > + state->acquire_ctx = ctx; > + state->allow_modeset = true; > + > + for_each_crtc(dev, crtc) { > + struct drm_crtc_state *crtc_state = > + drm_atomic_get_crtc_state(state, crtc); > > - for_each_crtc(dev, crtc) > - intel_crtc_disable_noatomic(crtc); > + ret = PTR_ERR_OR_ZERO(crtc_state); > + if (ret) > + goto free; > + > + if (!crtc_state->active) > + continue; > + > + crtc_state->active = false; > + crtc_mask |= 1 << drm_crtc_index(crtc); > + } > + > + if (crtc_mask) { > + ret = intel_set_mode(state); > + > + if (!ret) { > + for_each_crtc(dev, crtc) > + if (crtc_mask & (1 << drm_crtc_index(crtc))) > + crtc->state->active = true; > + > + return ret; > + } > + } > + > +free: > + if (ret) > + DRM_ERROR("Suspending crtc's failed with %i\n", ret); > + drm_atomic_state_free(state); > + return ret; > } > > /* Master function to enable/disable CRTC and corresponding power wells */ > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 217b773e0673..f4abce103221 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -988,7 +988,7 @@ int intel_pch_rawclk(struct drm_device *dev); > void intel_mark_busy(struct drm_device *dev); > void intel_mark_idle(struct drm_device *dev); > void intel_crtc_restore_mode(struct drm_crtc *crtc); > -void intel_display_suspend(struct drm_device *dev); > +int intel_display_suspend(struct drm_device *dev); > int intel_crtc_control(struct drm_crtc *crtc, bool enable); > void intel_crtc_update_dpms(struct drm_crtc *crtc); > void intel_encoder_destroy(struct drm_encoder *encoder); > -- > 2.1.0 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx