On Tue, May 26, 2026 at 07:08:00PM +0530, Animesh Manna wrote: > Timing registers are separate for CMTG, read transcoder register > and program cmtg transcoder with those values. > > v2: > - Use sw state instead of reading directly from hardware. [Jani] > - Move set_timing later after encoder enable. [Dibin] > > v3: > - Replace id with trans. [Jani] > - Program cmtg set_timing() along with primary transcoder timing. > > v4: > - Use _MMIO_TRANS() for cmtg registers instead of direct > multiplication. [Jani] > > v5: > - Modify register definition approach and match existing > transcoder definition. [Ville] > > Signed-off-by: Animesh Manna <[email protected]> > --- > drivers/gpu/drm/i915/display/intel_cmtg.c | 74 ++++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_cmtg.h | 1 + > drivers/gpu/drm/i915/display/intel_display.c | 4 ++ > 3 files changed, 79 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c > b/drivers/gpu/drm/i915/display/intel_cmtg.c > index fbc8a4f2b9cb..0e730afbb4ab 100644 > --- a/drivers/gpu/drm/i915/display/intel_cmtg.c > +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c > @@ -219,3 +219,77 @@ void intel_cmtg_set_clk_select(const struct > intel_crtc_state *crtc_state) > if (clk_sel_set) > intel_de_rmw(display, CMTG_CLK_SEL, clk_sel_clr, clk_sel_set); > } > + > +static inline enum transcoder to_cmtg_transcoder(enum transcoder > cpu_transcoder) > +{ > + switch (cpu_transcoder) { > + case TRANSCODER_A: > + return TRANSCODER_CMTG0; > + case TRANSCODER_B: > + return TRANSCODER_CMTG1; > + default: > + return INVALID_TRANSCODER; > + } > +} > + > +void intel_cmtg_set_timings(const struct intel_crtc_state *crtc_state, bool > lrr) > +{ > + struct intel_display *display = to_intel_display(crtc_state); > + const struct drm_display_mode *adjusted_mode = > &crtc_state->hw.adjusted_mode; > + enum transcoder cmtg_transcoder = > to_cmtg_transcoder(crtc_state->cpu_transcoder); > + u32 crtc_vdisplay, crtc_vtotal, crtc_vblank_start, crtc_vblank_end; > + > + if (!intel_cmtg_is_allowed(crtc_state)) > + return; > + > + crtc_vdisplay = adjusted_mode->crtc_vdisplay; > + > + /* > + * For platforms that always use VRR Timing Generator, the VTOTAL.Vtotal > + * bits are not required. Since the support for these bits is going to > + * be deprecated in upcoming platforms, avoid writing these bits for the > + * platforms that do not use legacy Timing Generator. > + */ > + crtc_vtotal = 1; > + > + /* > + * VBLANK_START not used by hw, just clear it > + * to make it stand out in register dumps. > + */ > + crtc_vblank_start = 1; > + > + crtc_vblank_end = adjusted_mode->crtc_vblank_end; > + > + if (lrr) { > + intel_de_write(display, TRANS_SET_CONTEXT_LATENCY(display, > cmtg_transcoder), > + crtc_state->set_context_latency); > + intel_de_write(display, TRANS_VBLANK(display, cmtg_transcoder), > + VBLANK_START(crtc_vblank_start - 1) | > + VBLANK_END(crtc_vblank_end - 1)); > + intel_de_write(display, TRANS_VTOTAL(display, cmtg_transcoder), > + VACTIVE(crtc_vdisplay - 1) | > + VTOTAL(crtc_vtotal - 1)); > + return; > + } > + > + intel_de_write(display, TRANS_HTOTAL(display, cmtg_transcoder), > + HACTIVE(adjusted_mode->crtc_hdisplay - 1) | > + HTOTAL(adjusted_mode->crtc_htotal - 1)); > + intel_de_write(display, TRANS_HBLANK(display, cmtg_transcoder), > + HBLANK_START(adjusted_mode->crtc_hblank_start - 1) | > + HBLANK_END(adjusted_mode->crtc_hblank_end - 1)); > + intel_de_write(display, TRANS_HSYNC(display, cmtg_transcoder), > + HSYNC_START(adjusted_mode->crtc_hsync_start - 1) | > + HSYNC_END(adjusted_mode->crtc_hsync_end - 1)); > + intel_de_write(display, TRANS_VTOTAL(display, cmtg_transcoder), > + VACTIVE(crtc_vdisplay - 1) | > + VTOTAL(crtc_vtotal - 1)); > + intel_de_write(display, TRANS_VBLANK(display, cmtg_transcoder), > + VBLANK_START(crtc_vblank_start - 1) | > + VBLANK_END(crtc_vblank_end - 1)); > + intel_de_write(display, TRANS_VSYNC(display, cmtg_transcoder), > + VSYNC_START(adjusted_mode->crtc_vsync_start - 1) | > + VSYNC_END(adjusted_mode->crtc_vsync_end - 1)); > + intel_de_write(display, TRANS_SET_CONTEXT_LATENCY(display, > cmtg_transcoder), > + crtc_state->set_context_latency); > +}
We already have functions to configure the timing registers. Why can't we just reuse those (as in pass the transcoder from the caller)? > diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.h > b/drivers/gpu/drm/i915/display/intel_cmtg.h > index 87092ce6d67b..53a44f505dd2 100644 > --- a/drivers/gpu/drm/i915/display/intel_cmtg.h > +++ b/drivers/gpu/drm/i915/display/intel_cmtg.h > @@ -11,6 +11,7 @@ > struct intel_display; > struct intel_crtc_state; > > +void intel_cmtg_set_timings(const struct intel_crtc_state *crtc_state, bool > lrr); > 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); > diff --git a/drivers/gpu/drm/i915/display/intel_display.c > b/drivers/gpu/drm/i915/display/intel_display.c > index 6c8935f69db1..f8bcd1fcddca 100644 > --- a/drivers/gpu/drm/i915/display/intel_display.c > +++ b/drivers/gpu/drm/i915/display/intel_display.c > @@ -60,6 +60,7 @@ > #include "intel_bw.h" > #include "intel_cdclk.h" > #include "intel_clock_gating.h" > +#include "intel_cmtg.h" > #include "intel_color.h" > #include "intel_crt.h" > #include "intel_crtc.h" > @@ -2753,6 +2754,8 @@ static void intel_set_transcoder_timings(const struct > intel_crtc_state *crtc_sta > intel_de_write(display, DP_MIN_HBLANK_CTL(cpu_transcoder), > crtc_state->min_hblank); > } > + > + intel_cmtg_set_timings(crtc_state, false); > } > > static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state > *crtc_state) > @@ -2814,6 +2817,7 @@ static void intel_set_transcoder_timings_lrr(const > struct intel_crtc_state *crtc > VACTIVE(crtc_vdisplay - 1) | > VTOTAL(crtc_vtotal - 1)); > > + intel_cmtg_set_timings(crtc_state, true); > intel_vrr_set_fixed_rr_timings(crtc_state); > intel_vrr_transcoder_enable(crtc_state); > } > -- > 2.29.0 -- Ville Syrjälä Intel
