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