Restore CMTG registers after DC6 exit, as they lose their values in the low-power state.
v2: Introduce intel_cmtg_restore() instead of calling multiple cmtg functions. [Uma] Signed-off-by: Animesh Manna <[email protected]> --- drivers/gpu/drm/i915/display/intel_cmtg.c | 9 +++++++++ drivers/gpu/drm/i915/display/intel_cmtg.h | 1 + drivers/gpu/drm/i915/display/intel_display.c | 10 +++++++--- .../gpu/drm/i915/display/intel_display_power.c | 17 +++++++++++++++++ .../gpu/drm/i915/display/intel_display_power.h | 2 ++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c b/drivers/gpu/drm/i915/display/intel_cmtg.c index b7f4be33ce2e..8be6f7f28e35 100644 --- a/drivers/gpu/drm/i915/display/intel_cmtg.c +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c @@ -434,3 +434,12 @@ void intel_cmtg_program(const struct intel_crtc_state *crtc_state) intel_cmtg_set_hwgb(crtc_state); intel_cmtg_enable_ddi(crtc_state); } + +void intel_cmtg_restore(const struct intel_crtc_state *crtc_state) +{ + intel_cmtg_set_clk_select(crtc_state); + intel_cmtg_set_timings(crtc_state, false); + intel_cmtg_set_vrr_timings(crtc_state); + intel_cmtg_set_vrr_ctl(crtc_state); + intel_cmtg_set_m_n(crtc_state); +} diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.h b/drivers/gpu/drm/i915/display/intel_cmtg.h index 51fc3f5a89f4..37f90123c397 100644 --- a/drivers/gpu/drm/i915/display/intel_cmtg.h +++ b/drivers/gpu/drm/i915/display/intel_cmtg.h @@ -22,5 +22,6 @@ bool intel_cmtg_is_allowed(const struct intel_crtc_state *crtc_state); void intel_cmtg_enable_interrupt(const struct intel_crtc_state *crtc_state); void intel_cmtg_disable_interrupt(const struct intel_crtc_state *crtc_state); void intel_cmtg_program(const struct intel_crtc_state *crtc_state); +void intel_cmtg_restore(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_CMTG_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e751a4c37842..35fbf1ae210e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7560,12 +7560,16 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { bool modeset = intel_crtc_needs_modeset(new_crtc_state); + bool dc3co_to_dc6 = intel_display_power_get_and_reset_dc3co_to_dc6(display); /* - * TODO: CMTG needs to be restored on DC6 exit and DC3co entry condition - * need to be checked before calling CMTG functions. + * TODO: DC3co entry condition need to be checked before calling CMTG functions. */ - if (modeset && new_crtc_state->hw.active && !crtc->cmtg.enabled) { + if ((modeset || dc3co_to_dc6) && + new_crtc_state->hw.active && !crtc->cmtg.enabled) { + if (dc3co_to_dc6) + intel_cmtg_restore(new_crtc_state); + intel_cmtg_program(new_crtc_state); intel_cmtg_enable_interrupt(new_crtc_state); } diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 2e51dfcd5dce..e75002819bf5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -285,6 +285,19 @@ sanitize_target_dc_state(struct intel_display *display, return target_dc_state; } +bool intel_display_power_get_and_reset_dc3co_to_dc6(struct intel_display *display) +{ + struct i915_power_domains *power_domains = &display->power.domains; + bool ret; + + mutex_lock(&power_domains->lock); + ret = power_domains->dc3co_to_dc6; + power_domains->dc3co_to_dc6 = false; + mutex_unlock(&power_domains->lock); + + return ret; +} + /** * intel_display_power_set_target_dc_state - Set target dc state. * @display: display device @@ -320,6 +333,10 @@ void intel_display_power_set_target_dc_state(struct intel_display *display, if (!dc_off_enabled) intel_power_well_enable(display, power_well); + if (power_domains->target_dc_state == DC_STATE_EN_DC3CO && + state == DC_STATE_EN_UPTO_DC6) + power_domains->dc3co_to_dc6 = true; + power_domains->target_dc_state = state; if (!dc_off_enabled) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 56dc89eed3f8..b9c9b68072af 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -138,6 +138,7 @@ struct i915_power_domains { */ bool initializing; bool display_core_suspended; + bool dc3co_to_dc6; int power_well_count; u32 dc_state; @@ -179,6 +180,7 @@ void intel_display_power_sanitize_state(struct intel_display *display); void intel_display_power_suspend_late(struct intel_display *display, bool s2idle); void intel_display_power_resume_early(struct intel_display *display); +bool intel_display_power_get_and_reset_dc3co_to_dc6(struct intel_display *display); void intel_display_power_set_target_dc_state(struct intel_display *display, u32 state); u32 intel_display_power_get_current_dc_state(struct intel_display *display); -- 2.29.0
