Restore CMTG registers after DC6 exit, as they lose their values
in the low-power state.

Signed-off-by: Animesh Manna <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_display.c  | 12 ++++++++-
 .../drm/i915/display/intel_display_power.c    | 25 +++++++++++++++++++
 .../drm/i915/display/intel_display_power.h    |  3 +++
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 6dc561713c35..324a2c722422 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7544,9 +7544,19 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
 
        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
                bool modeset = intel_crtc_needs_modeset(new_crtc_state);
+               bool dc3co_to_dc6 = 
intel_display_power_get_dc3co_to_dc6(display);
 
                /* CMTG needs to be restored on DC6 exit and on modset*/
-               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_set_clk_select(new_crtc_state);
+                               intel_cmtg_set_timings(new_crtc_state, false);
+                               intel_cmtg_set_vrr_timings(new_crtc_state);
+                               intel_cmtg_set_vrr_ctl(new_crtc_state);
+                               intel_cmtg_set_m_n(new_crtc_state);
+                               intel_display_power_reset_dc3co_to_dc6(display);
+                       }
+
                        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 80ecf373fb19..94f6f4b1f388 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -285,6 +285,27 @@ sanitize_target_dc_state(struct intel_display *display,
        return target_dc_state;
 }
 
+bool intel_display_power_get_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;
+       mutex_unlock(&power_domains->lock);
+
+       return ret;
+}
+
+void intel_display_power_reset_dc3co_to_dc6(struct intel_display *display)
+{
+       struct i915_power_domains *power_domains = &display->power.domains;
+
+       mutex_lock(&power_domains->lock);
+       power_domains->dc3co_to_dc6 = false;
+       mutex_unlock(&power_domains->lock);
+}
+
 /**
  * intel_display_power_set_target_dc_state - Set target dc state.
  * @display: display device
@@ -320,6 +341,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_UPTO_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 d616d5d09cbe..ce1225bbc789 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;
@@ -183,6 +184,8 @@ void intel_display_power_suspend_late(struct intel_display 
*display, bool s2idle
 void intel_display_power_resume_early(struct intel_display *display);
 void intel_display_power_suspend(struct intel_display *display);
 void intel_display_power_resume(struct intel_display *display);
+bool intel_display_power_get_dc3co_to_dc6(struct intel_display *display);
+void intel_display_power_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

Reply via email to