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

Reply via email to