diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 32 | 
1 files changed, 29 insertions, 3 deletions
| diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d3994e2a7d63..63b4b73f47c6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1209,6 +1209,9 @@ static void intel_post_plane_update(struct intel_atomic_state *state,  	if (needs_cursorclk_wa(old_crtc_state) &&  	    !needs_cursorclk_wa(new_crtc_state))  		icl_wa_cursorclkgating(dev_priv, pipe, false); + +	if (intel_crtc_needs_color_update(new_crtc_state)) +		intel_color_post_update(new_crtc_state);  }  static void intel_crtc_enable_flip_done(struct intel_atomic_state *state, @@ -5145,6 +5148,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,  	 * only fields that are know to not cause problems are preserved. */  	saved_state->uapi = crtc_state->uapi; +	saved_state->inherited = crtc_state->inherited;  	saved_state->scaler_state = crtc_state->scaler_state;  	saved_state->shared_dpll = crtc_state->shared_dpll;  	saved_state->dpll_hw_state = crtc_state->dpll_hw_state; @@ -7090,6 +7094,8 @@ static void intel_update_crtc(struct intel_atomic_state *state,  	intel_fbc_update(state, crtc); +	drm_WARN_ON(&i915->drm, !intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF)); +  	if (!modeset &&  	    intel_crtc_needs_color_update(new_crtc_state))  		intel_color_commit_noarm(new_crtc_state); @@ -7457,8 +7463,28 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  	drm_atomic_helper_wait_for_dependencies(&state->base);  	drm_dp_mst_atomic_wait_for_dependencies(&state->base); -	if (state->modeset) -		wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET); +	/* +	 * During full modesets we write a lot of registers, wait +	 * for PLLs, etc. Doing that while DC states are enabled +	 * is not a good idea. +	 * +	 * During fastsets and other updates we also need to +	 * disable DC states due to the following scenario: +	 * 1. DC5 exit and PSR exit happen +	 * 2. Some or all _noarm() registers are written +	 * 3. Due to some long delay PSR is re-entered +	 * 4. DC5 entry -> DMC saves the already written new +	 *    _noarm() registers and the old not yet written +	 *    _arm() registers +	 * 5. DC5 exit -> DMC restores a mixture of old and +	 *    new register values and arms the update +	 * 6. PSR exit -> hardware latches a mixture of old and +	 *    new register values -> corrupted frame, or worse +	 * 7. New _arm() registers are finally written +	 * 8. Hardware finally latches a complete set of new +	 *    register values, and subsequent frames will be OK again +	 */ +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DC_OFF);  	intel_atomic_prepare_plane_clear_colors(state); @@ -7607,8 +7633,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  		 * the culprit.  		 */  		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore); -		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);  	} +	intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, wakeref);  	intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);  	/* |