On 26-05-2026 19:08, Animesh Manna wrote:
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]
Signed-off-by: Animesh Manna <[email protected]>
---
drivers/gpu/drm/i915/display/intel_cmtg.c | 4 ++++
drivers/gpu/drm/i915/display/intel_display.c | 24 +++++++++++++++++++
.../drm/i915/display/intel_display_types.h | 4 ++++
3 files changed, 32 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c
b/drivers/gpu/drm/i915/display/intel_cmtg.c
index a0413013ec43..d808c62e14b1 100644
--- a/drivers/gpu/drm/i915/display/intel_cmtg.c
+++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
@@ -173,6 +173,7 @@ static void intel_cmtg_disable_all(struct intel_display
*display,
void intel_cmtg_disable(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;
enum transcoder cmtg_transcoder =
to_cmtg_transcoder(crtc_state->cpu_transcoder);
u32 clk_sel_clr = 0;
@@ -180,6 +181,7 @@ void intel_cmtg_disable(const struct intel_crtc_state
*crtc_state)
if (!intel_cmtg_is_allowed(crtc_state))
return;
+ crtc->cmtg.enabled = false;
intel_de_rmw(display, TRANS_VRR_CTL(display, cmtg_transcoder),
VRR_CTL_VRR_ENABLE | VRR_CTL_FLIP_LINE_EN, 0);
@@ -395,6 +397,7 @@ void intel_cmtg_enable_sync(const struct intel_crtc_state *crtc_state)
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))
@@ -403,6 +406,7 @@ void intel_cmtg_enable_ddi(const struct intel_crtc_state
*crtc_state)
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;
drm_dbg_kms(display->drm, "CMTG: %s enabled\n",
transcoder_name(cpu_transcoder));
}
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 354eca79bac0..36ff17b88be7 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1771,6 +1771,9 @@ static void hsw_crtc_disable(struct intel_atomic_state
*state,
struct intel_crtc *pipe_crtc;
int i;
+ if (crtc->cmtg.enabled)
+ intel_cmtg_disable(old_crtc_state);
Should interrupt disable handling also be done here?
Also, since CMTG registers including clock select may be
lost on DC6 entry, could `intel_cmtg_disable()` timeout
during suspend/shutdown?
Would restoring the clock select before disable help here?
+
/*
* FIXME collapse everything to one hook.
* Need care with mst->ddi interactions.
@@ -6868,6 +6871,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_is_allowed(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,
@@ -7545,6 +7554,21 @@ 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, i) {
+ 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.
+ */
+ 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);
+ intel_cmtg_enable_interrupt(new_crtc_state);
+ }
+ }
+
intel_wait_for_vblank_workers(state);
/* FIXME: We should call drm_atomic_helper_commit_hw_done() here
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 1c0c32c4e43a..74c719b52759 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1573,6 +1573,10 @@ struct intel_crtc {
#endif
bool vblank_psr_notify;
+
+ struct {
+ bool enabled;
+ } cmtg;
};
struct intel_plane_error {