From: Animesh Manna <[email protected]> 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 | 21 +++++++++++++---- .../drm/i915/display/intel_display_power.c | 23 +++++++++++++++++++ .../drm/i915/display/intel_display_power.h | 2 ++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c b/drivers/gpu/drm/i915/display/intel_cmtg.c index 8684d2ec2f83..ae59d7e755f3 100644 --- a/drivers/gpu/drm/i915/display/intel_cmtg.c +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c @@ -391,20 +391,33 @@ static void intel_cmtg_set_hwgb(const struct intel_crtc_state *crtc_state) intel_de_write(display, CMTG_HW_GB(cpu_transcoder), val); } +static void intel_cmtg_restore(const struct intel_crtc_state *crtc_state) +{ + intel_cmtg_set_clk_select(crtc_state); + intel_cmtg_set_timings(crtc_state, MODESET); + intel_cmtg_set_vrr_timings(crtc_state); + intel_cmtg_set_vrr_ctl(crtc_state); + intel_cmtg_set_m_n(crtc_state); +} + void intel_cmtg_program(struct intel_atomic_state *state) { + struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; struct intel_crtc_state *new_crtc_state; + bool dc3co_to_dc6 = intel_display_power_get_and_reset_dc3co_to_dc6(display); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) { bool modeset = intel_crtc_needs_modeset(new_crtc_state); if (!intel_cmtg_is_allowed(new_crtc_state)) continue; - /* - * TODO: CMTG needs to be restored on DC6 exit. - */ - 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_enable_sync(new_crtc_state); intel_cmtg_set_hwgb(new_crtc_state); intel_cmtg_enable_ddi(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..9783257651d2 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 @@ -300,6 +313,7 @@ void intel_display_power_set_target_dc_state(struct intel_display *display, struct i915_power_well *power_well; bool dc_off_enabled; struct i915_power_domains *power_domains = &display->power.domains; + u32 old_target_dc_state; mutex_lock(&power_domains->lock); power_well = lookup_power_well(display, SKL_DISP_DC_OFF); @@ -320,8 +334,17 @@ void intel_display_power_set_target_dc_state(struct intel_display *display, if (!dc_off_enabled) intel_power_well_enable(display, power_well); + old_target_dc_state = power_domains->target_dc_state; power_domains->target_dc_state = state; + /* + * CMTG must be restored explicitly after DC6 exit. The dc3co_to_dc6 + * flag helps CMTG determine whether restoration is required. + */ + if (old_target_dc_state == DC_STATE_EN_DC3CO && + power_domains->target_dc_state == DC_STATE_EN_UPTO_DC6) + power_domains->dc3co_to_dc6 = true; + if (!dc_off_enabled) intel_power_well_disable(display, power_well); 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.43.0
