> -----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 15/20] drm/i915/cmtg: Add CMTG interrupt handling
>
> Add support for the CMTG vblank interrupt, which is delivered through the DE
> port
> interrupt block. Enable/disable the interrupt via the DE port IMR around CMTG
> enable/disable, and dispatch the CMTG_VBLANK_{A,B} bits to the corresponding
> pipe vblank handler in the gen8 DE IRQ handler.
>
> Wired up for DISPLAY_VER 35. The CMTG interrupt is not enabled via IER today
> because CMTG is brought up together with the eDP transcoder; this can be
> revisited later.
>
> v2:
> - Use consistent DC3co check as used in earlier patches. [Uma]
> - Use else-if instead of separate if block. [Uma]
> - Merge mask and unmask function as it is similar. [Uma]
> - Modify DISPLAY_VER() check. [Uma]
>
> v3:
> - Enable only vblank interrupt. [Dibin]
>
> Signed-off-by: Animesh Manna <[email protected]>
> ---
> drivers/gpu/drm/i915/display/intel_cmtg.c | 47 +++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_cmtg.h | 2 +
> .../gpu/drm/i915/display/intel_display_irq.c | 12 +++++
> .../gpu/drm/i915/display/intel_display_regs.h | 2 +
> 4 files changed, 63 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c
> b/drivers/gpu/drm/i915/display/intel_cmtg.c
> index 20b74c2856c4..fb57fa41f721 100644
> --- a/drivers/gpu/drm/i915/display/intel_cmtg.c
> +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
> @@ -13,6 +13,7 @@
> #include "intel_crtc.h"
> #include "intel_de.h"
> #include "intel_display_device.h"
> +#include "intel_display_irq.h"
> #include "intel_display_power.h"
> #include "intel_display_regs.h"
> #include "intel_display_types.h"
> @@ -353,3 +354,49 @@ void intel_cmtg_enable_ddi(const struct intel_crtc_state
> *crtc_state)
> crtc->cmtg.enabled = true;
> drm_dbg_kms(display->drm, "CMTG: %s enabled\n",
> transcoder_name(cpu_transcoder)); }
> +
> +static void intel_cmtg_mask_interrupt(const struct intel_crtc_state
> +*crtc_state, bool mask) {
> + struct intel_display *display = to_intel_display(crtc_state);
> + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> + u32 interrupt_mask = 0;
> +
> + if (cpu_transcoder == TRANSCODER_A)
> + interrupt_mask = CMTG_VBLANK_A;
> + else if (cpu_transcoder == TRANSCODER_B)
> + interrupt_mask = CMTG_VBLANK_B;
> +
> + if (mask)
> + bdw_update_port_irq(display, interrupt_mask, 0);
> + else
> + bdw_update_port_irq(display, interrupt_mask, interrupt_mask); }
>
Agree with Jani, this can be abstracted better.
Something like:
Add in intel_display_irq.c
void intel_de_port_interrupt_mask(struct intel_display *display, u32 bits, bool
mask)
{
spin_lock_irq(&display->irq.lock);
bdw_update_port_irq(display, bits, mask ? 0 : bits);
spin_unlock_irq(&display->irq.lock);
}
and call from various places instead of using the function directly.
> +void intel_cmtg_enable_interrupt(const struct intel_crtc_state
> +*crtc_state) {
> + struct intel_display *display = to_intel_display(crtc_state);
> +
> + if (!intel_cmtg_is_allowed(crtc_state))
> + return;
> +
> + /*
> + * TODO: Currently cmtg is enabled along with eDP transcoder so cmtg
> + * interrupt is not enabled through IER, need to do some fine
> + * tuning in future.
> + */
> + spin_lock_irq(&display->irq.lock);
> + intel_cmtg_mask_interrupt(crtc_state, false);
> + spin_unlock_irq(&display->irq.lock);
> +}
> +
> +void intel_cmtg_disable_interrupt(const struct intel_crtc_state
> +*crtc_state) {
> + struct intel_display *display = to_intel_display(crtc_state);
> +
> + if (!intel_cmtg_is_allowed(crtc_state))
> + return;
> +
> + spin_lock_irq(&display->irq.lock);
> + intel_cmtg_mask_interrupt(crtc_state, true);
> + spin_unlock_irq(&display->irq.lock);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.h
> b/drivers/gpu/drm/i915/display/intel_cmtg.h
> index 79785afccc51..8fcb44d6398f 100644
> --- a/drivers/gpu/drm/i915/display/intel_cmtg.h
> +++ b/drivers/gpu/drm/i915/display/intel_cmtg.h
> @@ -21,5 +21,7 @@ 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);
> +void intel_cmtg_enable_interrupt(const struct intel_crtc_state
> +*crtc_state); void intel_cmtg_disable_interrupt(const struct
> +intel_crtc_state *crtc_state);
>
> #endif /* __INTEL_CMTG_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c
> b/drivers/gpu/drm/i915/display/intel_display_irq.c
> index 4a821b0674fd..7ad722024c87 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_irq.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
> @@ -1469,6 +1469,18 @@ static void gen8_de_irq_handler(struct intel_display
> *display, u32 master_ctl)
> found = true;
> }
>
> + if (DISPLAY_VER(display) == 35) {
> + if (iir & (CMTG_VBLANK_A)) {
Redundant parenthesis
> + intel_handle_vblank(display, PIPE_A);
> + found = true;
> + }
> +
> + if (iir & (CMTG_VBLANK_B)) {
Here as well
> + intel_handle_vblank(display, PIPE_B);
> + found = true;
> + }
> + }
> +
> if (DISPLAY_VER(display) >= 11) {
> u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h
> b/drivers/gpu/drm/i915/display/intel_display_regs.h
> index 4321f8b529da..fe851fe39222 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h
> @@ -1458,6 +1458,8 @@
> #define GEN9_AUX_CHANNEL_B (1 << 25)
> #define DSI1_TE (1 << 24)
> #define DSI0_TE (1 << 23)
> +#define CMTG_VBLANK_B (1 << 17)
> +#define CMTG_VBLANK_A (1 << 14)
> #define GEN8_DE_PORT_HOTPLUG(hpd_pin) REG_BIT(3 +
> _HPD_PIN_DDI(hpd_pin))
> #define BXT_DE_PORT_HOTPLUG_MASK
> (GEN8_DE_PORT_HOTPLUG(HPD_PORT_A) | \
>
> GEN8_DE_PORT_HOTPLUG(HPD_PORT_B) | \
> --
> 2.29.0