On random machines, the BIOS changes the hardware state of the display when it detects a lid event. In return, we have to then do a forced restore of the users requested configuration as soon as we handle the lid event. Currently, this is done by calling the lowlevel CRTC configuration functions directly with the old state. This results in a flash on all connected displays. However, since we probe the state of the hardware left by the BIOS, we can instead hook into the higher level modeset code which evaluates the minimum changes required to setup the requested state. This converts the modeset back into a no-op on sane machines, and eliminates the screen blanking. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65486 Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk> --- drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 5 +++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ba7e311..5b727a3b2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9632,11 +9632,33 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, * checking (bogus) intermediate states. */ for_each_pipe(pipe) { + struct drm_mode_set set; + struct drm_connector *connector, *connectors[16]; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, - crtc->fb); + set.crtc = crtc; + set.x = crtc->x; + set.y = crtc->y; + set.mode = crtc->fb ? &crtc->mode : NULL; + set.fb = crtc->fb; + set.connectors = connectors; + set.num_connectors = 0; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, + head) { + if (&intel_attached_crtc(connector)->base != crtc) + continue; + + connectors[set.num_connectors++] = connector; + if (set.num_connectors == ARRAY_SIZE(connectors)) + break; + } + + if (intel_crtc_set_config(&set)) + __intel_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, crtc->fb); } list_for_each_entry(plane, &dev->mode_config.plane_list, head) intel_plane_restore(plane); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1f04b7f..ef3f809 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -648,6 +648,11 @@ static inline struct intel_encoder *intel_attached_encoder(struct drm_connector return to_intel_connector(connector)->encoder; } +static inline struct intel_crtc *intel_attached_crtc(struct drm_connector *connector) +{ + return to_intel_crtc(to_intel_connector(connector)->encoder->base.crtc); +} + static inline struct intel_digital_port * enc_to_dig_port(struct drm_encoder *encoder) { -- 1.7.10.4