> -----Original Message-----
> From: Manna, Animesh <[email protected]>
> Sent: Thursday, June 4, 2026 1:24 AM
> To: [email protected]; [email protected]
> Cc: Shankar, Uma <[email protected]>; Dibin Moolakadan Subrahmanian
> <[email protected]>; [email protected];
> Nikula, Jani <[email protected]>; Manna, Animesh
> <[email protected]>
> Subject: [PATCH v8 19/20] drm/i915/cmtg: Restore CMTG after DC6 exit
> 
> 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.
>                */

Would request @Dibin Moolakadan Subrahmanian to please check this as well.

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

Since this is called in loop for all crtc's, only the first crtc will get this 
as true.
For all else, this will be false. Can you check this once.

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

I think this looks a bit off, we are moving from DC6 to DC3Co while the 
variable being
made true is reverse. Can you re-check the logic again.

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