> -----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 18/20] drm/i915/cmtg: Add trigger to enable/disable cmtg
> 
> Enable CMTG with fixed refresh rate mode and with dynamic dc state enabled.
> 
> Disable CMTG with transcoder disable or if there is a transition to vrr mode 
> from
> fixed refresh rate mode.
> 
> v2:
> - Move the enabled flag update to avoid issue in the disable timeout path. 
> [Uma]
> 
> v3:
> - Introduce intel_cmtg_program() rather calling multiple cmtg functions. 
> [Dibin]
> - Set clock select before cmtg disable as can lost during dc6 entry. [Dibin]
> - Disable cmtg interrupt in crtc-disable(). [Dibin]


> Signed-off-by: Animesh Manna <[email protected]>
> ---
>  drivers/gpu/drm/i915/display/intel_cmtg.c    | 25 ++++++++++----------
>  drivers/gpu/drm/i915/display/intel_cmtg.h    |  4 +---
>  drivers/gpu/drm/i915/display/intel_display.c | 24 +++++++++++++++++++
>  3 files changed, 38 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c
> b/drivers/gpu/drm/i915/display/intel_cmtg.c
> index 1d63b612c44b..b7f4be33ce2e 100644
> --- a/drivers/gpu/drm/i915/display/intel_cmtg.c
> +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
> @@ -323,15 +323,12 @@ void intel_cmtg_set_m_n(const struct intel_crtc_state
> *crtc_state)
>       intel_de_write(display, PIPE_LINK_N1(display, cmtg_transcoder), m_n-
> >link_n);  }
> 
> -void intel_cmtg_enable_sync(const struct intel_crtc_state *crtc_state)
> +static void intel_cmtg_enable_sync(const struct intel_crtc_state
> +*crtc_state)
>  {
>       struct intel_display *display = to_intel_display(crtc_state);
>       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
>       u32 cmtg_ctl;
> 
> -     if (!intel_cmtg_is_allowed(crtc_state))
> -             return;
> -
>       cmtg_ctl = CMTG_SYNC_TO_PORT | CMTG_ENABLE;
> 
>       intel_de_rmw(display, TRANS_CMTG_CTL(cpu_transcoder), 0, cmtg_ctl);
> @@ -342,15 +339,12 @@ void intel_cmtg_enable_sync(const struct
> intel_crtc_state *crtc_state)
>       }
>  }
> 
> -void intel_cmtg_enable_ddi(const struct intel_crtc_state *crtc_state)
> +static void intel_cmtg_enable_ddi(const struct intel_crtc_state
> +*crtc_state)
>  {
>       struct intel_display *display = to_intel_display(crtc_state);
>       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> 
> -     if (!intel_cmtg_is_allowed(crtc_state))
> -             return;
> -
>       intel_de_rmw(display, TRANS_DDI_FUNC_CTL2(display,
> cpu_transcoder), 0, CMTG_SECONDARY_MODE);
>       intel_de_rmw(display, CMTG_SCANLINE_GB1(cpu_transcoder), 0,
> CMTG_HW_GB_ENABLE);
>       crtc->cmtg.enabled = true;
> @@ -406,7 +400,7 @@ void intel_cmtg_disable_interrupt(const struct
> intel_crtc_state *crtc_state)
>  #define DC3CO_ENTRY_LATENCY  55
>  #define DC3CO_EXIT_LATENCY   40
> 
> -void intel_cmtg_set_hwgb(const struct intel_crtc_state *crtc_state)
> +static void intel_cmtg_set_hwgb(const struct intel_crtc_state
> +*crtc_state)
>  {
>       struct intel_display *display = to_intel_display(crtc_state);
>       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -
> 415,9 +409,6 @@ void intel_cmtg_set_hwgb(const struct intel_crtc_state
> *crtc_state)
>       u32 line_time_us = 75;
>       u32 val;
> 
> -     if (!intel_cmtg_is_allowed(crtc_state))
> -             return;
> -
>       if (crtc_state->linetime)
>               line_time_us = DIV_ROUND_UP(crtc_state->linetime, 8);
> 
> @@ -433,3 +424,13 @@ void intel_cmtg_set_hwgb(const struct intel_crtc_state
> *crtc_state)
> 
>       intel_de_write(display, CMTG_HW_GB(cpu_transcoder), val);  }
> +
> +void intel_cmtg_program(const struct intel_crtc_state *crtc_state) {
> +     if (!intel_cmtg_is_allowed(crtc_state))
> +             return;
> +
> +     intel_cmtg_enable_sync(crtc_state);
> +     intel_cmtg_set_hwgb(crtc_state);
> +     intel_cmtg_enable_ddi(crtc_state);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.h
> b/drivers/gpu/drm/i915/display/intel_cmtg.h
> index 2c801a74acf9..51fc3f5a89f4 100644
> --- a/drivers/gpu/drm/i915/display/intel_cmtg.h
> +++ b/drivers/gpu/drm/i915/display/intel_cmtg.h
> @@ -12,8 +12,6 @@ struct intel_display;
>  struct intel_crtc_state;
> 
>  void intel_cmtg_disable(const struct intel_crtc_state *crtc_state); -void
> intel_cmtg_enable_ddi(const struct intel_crtc_state *crtc_state); -void
> intel_cmtg_enable_sync(const struct intel_crtc_state *crtc_state);  void
> intel_cmtg_set_m_n(const struct intel_crtc_state *crtc_state);  void
> intel_cmtg_set_vrr_timings(const struct intel_crtc_state *crtc_state);  void
> intel_cmtg_set_vrr_ctl(const struct intel_crtc_state *crtc_state); @@ -23,6 
> +21,6
> @@ void intel_cmtg_sanitize(struct intel_display *display);  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_set_hwgb(const struct intel_crtc_state *crtc_state);
> +void intel_cmtg_program(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 e4763ac81c39..e751a4c37842 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -1790,6 +1790,11 @@ static void hsw_crtc_disable(struct intel_atomic_state
> *state,
>               intel_atomic_get_old_crtc_state(state, crtc);
>       struct intel_crtc *pipe_crtc;
> 
> +     if (crtc->cmtg.enabled) {

In this path we differ from enable where we check for cmtg_is_allowed as well.
We can make both enable and disable consistent.

> +             intel_cmtg_set_clk_select(old_crtc_state);
> +             intel_cmtg_disable(old_crtc_state);
> +             intel_cmtg_disable_interrupt(old_crtc_state);
> +     }
>       /*
>        * FIXME collapse everything to one hook.
>        * Need care with mst->ddi interactions.
> @@ -6878,6 +6883,12 @@ static void intel_update_crtc(struct intel_atomic_state
> *state,
>       if (intel_crtc_needs_fastset(new_crtc_state) &&
>           old_crtc_state->inherited)
>               intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);
> +
> +     if (crtc->cmtg.enabled && (intel_crtc_vrr_enabling(state, crtc))) {
> +             intel_cmtg_set_clk_select(new_crtc_state);
> +             intel_cmtg_disable(new_crtc_state);
> +             intel_cmtg_disable_interrupt(new_crtc_state);
> +     }
>  }
> 
>  static void intel_old_crtc_state_disables(struct intel_atomic_state *state, 
> @@ -
> 7547,6 +7558,19 @@ static void intel_atomic_commit_tail(struct
> intel_atomic_state *state)
>       /* FIXME probably need to sequence this properly */
>       intel_program_dpkgc_latency(state);
> 
> +     for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
> +             bool modeset = intel_crtc_needs_modeset(new_crtc_state);
> +
> +             /*
> +              * TODO: CMTG needs to be restored on DC6 exit and DC3co
> entry condition
> +              * need to be checked before calling CMTG functions.
> +              */

Assuming this is going to be taken care as part of DC3Co enabling.

With above addressed, this is
Reviewed-by: Uma Shankar <[email protected]>

> +             if (modeset && new_crtc_state->hw.active && !crtc-
> >cmtg.enabled) {
> +                     intel_cmtg_program(new_crtc_state);
> +                     intel_cmtg_enable_interrupt(new_crtc_state);
> +             }
> +     }
> +
>       intel_wait_for_vblank_workers(state);
> 
>       /* FIXME: We should call drm_atomic_helper_commit_hw_done() here
> --
> 2.29.0

Reply via email to