From: Animesh Manna <[email protected]> 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] 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.43.0
