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.

Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Link: https://patch.msgid.link/20260615200339.885190-21-animesh.manna@intel.com
This commit is contained in:
Animesh Manna 2026-06-16 01:33:37 +05:30
parent 81c7da958f
commit c588a32418
3 changed files with 41 additions and 15 deletions

View File

@ -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);
}
}
}

View File

@ -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__ */

View File

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