> -----Original Message-----
> From: Manna, Animesh <[email protected]>
> Sent: Tuesday, June 16, 2026 1:34 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 v9 20/22] 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]
> - Got R-b from Uma.
>
> v4:
> - Simplify the code further by moving for_each_new_intel_crtc_in_state inside
> intel_cmtg.c.
Looks Good to me.
Reviewed-by: Uma Shankar <[email protected]>
> Signed-off-by: Animesh Manna <[email protected]>
> ---
> drivers/gpu/drm/i915/display/intel_cmtg.c | 37 +++++++++++++-------
> drivers/gpu/drm/i915/display/intel_cmtg.h | 5 ++-
> drivers/gpu/drm/i915/display/intel_display.c | 14 ++++++++
> 3 files changed, 41 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c
> b/drivers/gpu/drm/i915/display/intel_cmtg.c
> index 96c7608144b9..8684d2ec2f83 100644
> --- a/drivers/gpu/drm/i915/display/intel_cmtg.c
> +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
> @@ -12,6 +12,7 @@
> #include "intel_cmtg_regs.h"
> #include "intel_crtc.h"
> #include "intel_de.h"
> +#include "intel_display.h"
> #include "intel_display_device.h"
> #include "intel_display_power.h"
> #include "intel_display_regs.h"
> @@ -333,15 +334,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);
> @@ -352,15 +350,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;
> @@ -371,7 +366,7 @@ void intel_cmtg_enable_ddi(const struct intel_crtc_state
> *crtc_state)
> #define DC3CO_ENTRY_LATENCY_US 55
> #define DC3CO_EXIT_LATENCY_US 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; @@ -
> 380,9 +375,6 @@ void intel_cmtg_set_hwgb(const struct intel_crtc_state
> *crtc_state)
> u32 line_time_us = 75; /* Max default initialization value */
> u32 val;
>
> - if (!intel_cmtg_is_allowed(crtc_state))
> - return;
> -
> if (crtc_state->linetime)
> line_time_us = DIV_ROUND_UP(crtc_state->linetime, 8);
>
> @@ -398,3 +390,24 @@ 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(struct intel_atomic_state *state) {
> + struct intel_crtc *crtc;
> + struct intel_crtc_state *new_crtc_state;
> +
> + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state) {
> + bool modeset = intel_crtc_needs_modeset(new_crtc_state);
> +
> + if (!intel_cmtg_is_allowed(new_crtc_state))
> + continue;
> + /*
> + * TODO: CMTG needs to be restored on DC6 exit.
> + */
> + if (modeset && new_crtc_state->hw.active && !crtc-
> >cmtg.enabled) {
> + intel_cmtg_enable_sync(new_crtc_state);
> + intel_cmtg_set_hwgb(new_crtc_state);
> + intel_cmtg_enable_ddi(new_crtc_state);
> + }
> + }
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.h
> b/drivers/gpu/drm/i915/display/intel_cmtg.h
> index b2b68b38b7e3..a08cb2dcee67 100644
> --- a/drivers/gpu/drm/i915/display/intel_cmtg.h
> +++ b/drivers/gpu/drm/i915/display/intel_cmtg.h
> @@ -8,6 +8,7 @@
>
> #include <linux/types.h>
>
> +struct intel_atomic_state;
> struct intel_display;
> struct intel_crtc_state;
>
> @@ -17,8 +18,6 @@ enum set_timing_type { };
>
> 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); @@ -26,6
> +25,6
> @@ void intel_cmtg_set_timings(const struct intel_crtc_state *crtc_state, enum
> set_ void intel_cmtg_set_clk_select(const struct intel_crtc_state
> *crtc_state);
> void intel_cmtg_sanitize(struct intel_display *display); bool
> intel_cmtg_is_allowed(const struct intel_crtc_state *crtc_state); -void
> intel_cmtg_set_hwgb(const struct intel_crtc_state *crtc_state);
> +void intel_cmtg_program(struct intel_atomic_state *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 62dc2b414f3c..e76aa6c8dab6 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -1790,6 +1790,10 @@ 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) {
> + intel_cmtg_set_clk_select(old_crtc_state);
> + intel_cmtg_disable(old_crtc_state);
> + }
> /*
> * FIXME collapse everything to one hook.
> * Need care with mst->ddi interactions.
> @@ -6898,6 +6902,11 @@ 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);
> + }
> }
>
> static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
> @@ -
> 7567,6 +7576,11 @@ static void intel_atomic_commit_tail(struct
> intel_atomic_state *state)
> /* FIXME probably need to sequence this properly */
> intel_program_dpkgc_latency(state);
>
> + /*
> + * TODO: DC3co entry condition need to be checked before calling CMTG
> functions.
> + */
> + intel_cmtg_program(state);
> +
> intel_wait_for_vblank_workers(state);
>
> /* FIXME: We should call drm_atomic_helper_commit_hw_done() here
> --
> 2.29.0