> -----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 22/22] 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]
> 
> v4:
> - Keep irq related code to intel_display_irq.c. [Jani, Uma]

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     | 24 ++++++++++++++++++-
>  .../gpu/drm/i915/display/intel_display_irq.c  | 19 +++++++++++++++
> .../gpu/drm/i915/display/intel_display_irq.h  |  2 ++
> .../gpu/drm/i915/display/intel_display_regs.h |  2 ++
>  4 files changed, 46 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cmtg.c
> b/drivers/gpu/drm/i915/display/intel_cmtg.c
> index ae59d7e755f3..6da28c185080 100644
> --- a/drivers/gpu/drm/i915/display/intel_cmtg.c
> +++ b/drivers/gpu/drm/i915/display/intel_cmtg.c
> @@ -14,6 +14,7 @@
>  #include "intel_de.h"
>  #include "intel_display.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"
> @@ -177,7 +178,7 @@ void intel_cmtg_disable(const struct intel_crtc_state
> *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;
> +     u32 clk_sel_clr = 0, interrupt_mask = 0;
> 
>       if (!crtc->cmtg.enabled)
>               return;
> @@ -210,6 +211,13 @@ void intel_cmtg_disable(const struct intel_crtc_state
> *crtc_state)
>       intel_de_rmw(display, CMTG_CLK_SEL, clk_sel_clr, 0);
> 
>       drm_dbg_kms(display->drm, "CMTG: %s disabled\n",
> transcoder_name(cpu_transcoder));
> +
> +     if (cpu_transcoder == TRANSCODER_A)
> +             interrupt_mask = CMTG_VBLANK_A;
> +     else if (cpu_transcoder == TRANSCODER_B)
> +             interrupt_mask = CMTG_VBLANK_B;
> +
> +     intel_display_irq_port_interrupt_mask(display, interrupt_mask, true);
>  }
> 
>  /*
> @@ -355,11 +363,25 @@ 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;
> +     u32 interrupt_mask = 0;
> 
>       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));
> +
> +     /*
> +      * 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.
> +      */
> +
> +     if (cpu_transcoder == TRANSCODER_A)
> +             interrupt_mask = CMTG_VBLANK_A;
> +     else if (cpu_transcoder == TRANSCODER_B)
> +             interrupt_mask = CMTG_VBLANK_B;
> +
> +     intel_display_irq_port_interrupt_mask(display, interrupt_mask, false);
>  }
> 
>  /* Bspec: 75253 */
> diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c
> b/drivers/gpu/drm/i915/display/intel_display_irq.c
> index 4a821b0674fd..bcb0ee22fb56 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) {
> +                                     intel_handle_vblank(display, PIPE_A);
> +                                     found = true;
> +                             }
> +
> +                             if (iir & CMTG_VBLANK_B) {
> +                                     intel_handle_vblank(display, PIPE_B);
> +                                     found = true;
> +                             }
> +                     }
> +
>                       if (DISPLAY_VER(display) >= 11) {
>                               u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
> 
> @@ -2666,3 +2678,10 @@ void intel_display_irq_snapshot_print(const struct
> intel_display_irq_snapshot *s
>       drm_printf(p, "DERRMR: 0x%08x\n", snapshot->derrmr);
>       drm_printf(p, "ERR_INT: 0x%08x\n", snapshot->err_int);  }
> +
> +void intel_display_irq_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);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.h
> b/drivers/gpu/drm/i915/display/intel_display_irq.h
> index a1227cee885a..84446bf53401 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_irq.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_irq.h
> @@ -82,4 +82,6 @@ void i915gm_irq_cstate_wa(struct intel_display *display,
> bool enable);  struct intel_display_irq_snapshot
> *intel_display_irq_snapshot_capture(struct intel_display *display);  void
> intel_display_irq_snapshot_print(const struct intel_display_irq_snapshot
> *snapshot, struct drm_printer *p);
> 
> +void intel_display_irq_port_interrupt_mask(struct intel_display
> +*display, u32 bits, bool mask);
> +
>  #endif /* __INTEL_DISPLAY_IRQ_H__ */
> 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

Reply via email to