On 13-05-2026 22:08, Animesh Manna wrote:
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);

In the restore path, will the `lrr` argument always be false?
In patch 4, the same function is called with `lrr = true`.

+                               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);

As this path also executes after DC6 exit, please also follow the BSpec
CMTG enable sequence for the PSR2 deep sleep case.

CMTG will not start running until PSR2 deep sleep exit completes, so this
sequence can fail here for the non-modeset case.

                        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..a0ea46895e2e 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_DC3CO &&
+           state == DC_STATE_EN_UPTO_DC6)
+               power_domains->dc3co_to_dc6 = true;
+

This only updates the software target DC state and does not guarantee an
actual DC6 entry or exit.
If the intent is to detect a real DC6 exit transition, then
gen9_disable_dc_states() looks like the more appropriate place for this.
I can also see existing PHY restore related comments there.

        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);

Reply via email to