diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_display_irq.c | 839 |
1 files changed, 638 insertions, 201 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index e1547ebce60e..aa23bb817805 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -10,11 +10,13 @@ #include "i915_irq.h" #include "i915_reg.h" #include "icl_dsi_regs.h" +#include "intel_atomic_plane.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_trace.h" #include "intel_display_types.h" +#include "intel_dmc_wl.h" #include "intel_dp_aux.h" #include "intel_dsb.h" #include "intel_fdi_regs.h" @@ -25,6 +27,92 @@ #include "intel_pmdemand.h" #include "intel_psr.h" #include "intel_psr_regs.h" +#include "intel_uncore.h" + +static void +intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs regs, + u32 imr_val, u32 ier_val) +{ + intel_dmc_wl_get(display, regs.imr); + intel_dmc_wl_get(display, regs.ier); + intel_dmc_wl_get(display, regs.iir); + + gen2_irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); + + intel_dmc_wl_put(display, regs.iir); + intel_dmc_wl_put(display, regs.ier); + intel_dmc_wl_put(display, regs.imr); +} + +static void +intel_display_irq_regs_reset(struct intel_display *display, struct i915_irq_regs regs) +{ + intel_dmc_wl_get(display, regs.imr); + intel_dmc_wl_get(display, regs.ier); + intel_dmc_wl_get(display, regs.iir); + + gen2_irq_reset(to_intel_uncore(display->drm), regs); + + intel_dmc_wl_put(display, regs.iir); + intel_dmc_wl_put(display, regs.ier); + intel_dmc_wl_put(display, regs.imr); +} + +static void +intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_reg_t reg) +{ + intel_dmc_wl_get(display, reg); + + gen2_assert_iir_is_zero(to_intel_uncore(display->drm), reg); + + intel_dmc_wl_put(display, reg); +} + +struct pipe_fault_handler { + bool (*handle)(struct intel_crtc *crtc, enum plane_id plane_id); + u32 fault; + enum plane_id plane_id; +}; + +static bool handle_plane_fault(struct intel_crtc *crtc, enum plane_id plane_id) +{ + struct intel_display *display = to_intel_display(crtc); + struct intel_plane_error error = {}; + struct intel_plane *plane; + + plane = intel_crtc_get_plane(crtc, plane_id); + if (!plane || !plane->capture_error) + return false; + + plane->capture_error(crtc, plane, &error); + + drm_err_ratelimited(display->drm, + "[CRTC:%d:%s][PLANE:%d:%s] fault (CTL=0x%x, SURF=0x%x, SURFLIVE=0x%x)\n", + crtc->base.base.id, crtc->base.name, + plane->base.base.id, plane->base.name, + error.ctl, error.surf, error.surflive); + + return true; +} + +static void intel_pipe_fault_irq_handler(struct intel_display *display, + const struct pipe_fault_handler *handlers, + enum pipe pipe, u32 fault_errors) +{ + struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); + const struct pipe_fault_handler *handler; + + for (handler = handlers; handler && handler->fault; handler++) { + if ((fault_errors & handler->fault) == 0) + continue; + + if (handler->handle(crtc, handler->plane_id)) + fault_errors &= ~handler->fault; + } + + WARN_ONCE(fault_errors, "[CRTC:%d:%s] unreported faults 0x%x\n", + crtc->base.base.id, crtc->base.name, fault_errors); +} static void intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) @@ -44,6 +132,7 @@ intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) void ilk_update_display_irq(struct drm_i915_private *dev_priv, u32 interrupt_mask, u32 enabled_irq_mask) { + struct intel_display *display = &dev_priv->display; u32 new_val; lockdep_assert_held(&dev_priv->irq_lock); @@ -56,8 +145,8 @@ void ilk_update_display_irq(struct drm_i915_private *dev_priv, if (new_val != dev_priv->irq_mask && !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { dev_priv->irq_mask = new_val; - intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask); - intel_uncore_posting_read(&dev_priv->uncore, DEIMR); + intel_de_write(display, DEIMR, dev_priv->irq_mask); + intel_de_posting_read(display, DEIMR); } } @@ -80,6 +169,7 @@ void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits) void bdw_update_port_irq(struct drm_i915_private *dev_priv, u32 interrupt_mask, u32 enabled_irq_mask) { + struct intel_display *display = &dev_priv->display; u32 new_val; u32 old_val; @@ -90,15 +180,15 @@ void bdw_update_port_irq(struct drm_i915_private *dev_priv, if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) return; - old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); + old_val = intel_de_read(display, GEN8_DE_PORT_IMR); new_val = old_val; new_val &= ~interrupt_mask; new_val |= (~enabled_irq_mask & interrupt_mask); if (new_val != old_val) { - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val); - intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); + intel_de_write(display, GEN8_DE_PORT_IMR, new_val); + intel_de_posting_read(display, GEN8_DE_PORT_IMR); } } @@ -113,6 +203,7 @@ static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, enum pipe pipe, u32 interrupt_mask, u32 enabled_irq_mask) { + struct intel_display *display = &dev_priv->display; u32 new_val; lockdep_assert_held(&dev_priv->irq_lock); @@ -128,9 +219,8 @@ static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, if (new_val != dev_priv->display.irq.de_irq_mask[pipe]) { dev_priv->display.irq.de_irq_mask[pipe] = new_val; - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), - dev_priv->display.irq.de_irq_mask[pipe]); - intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); + intel_de_write(display, GEN8_DE_PIPE_IMR(pipe), display->irq.de_irq_mask[pipe]); + intel_de_posting_read(display, GEN8_DE_PIPE_IMR(pipe)); } } @@ -156,7 +246,8 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, u32 interrupt_mask, u32 enabled_irq_mask) { - u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR); + struct intel_display *display = &dev_priv->display; + u32 sdeimr = intel_de_read(display, SDEIMR); sdeimr &= ~interrupt_mask; sdeimr |= (~enabled_irq_mask & interrupt_mask); @@ -168,8 +259,8 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) return; - intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr); - intel_uncore_posting_read(&dev_priv->uncore, SDEIMR); + intel_de_write(display, SDEIMR, sdeimr); + intel_de_posting_read(display, SDEIMR); } void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits) @@ -182,29 +273,30 @@ void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits) ibx_display_interrupt_update(i915, bits, 0); } -u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, +u32 i915_pipestat_enable_mask(struct intel_display *display, enum pipe pipe) { - u32 status_mask = dev_priv->display.irq.pipestat_irq_mask[pipe]; + struct drm_i915_private *dev_priv = to_i915(display->drm); + u32 status_mask = display->irq.pipestat_irq_mask[pipe]; u32 enable_mask = status_mask << 16; lockdep_assert_held(&dev_priv->irq_lock); - if (DISPLAY_VER(dev_priv) < 5) + if (DISPLAY_VER(display) < 5) goto out; /* * On pipe A we don't support the PSR interrupt yet, * on pipe B and C the same bit MBZ. */ - if (drm_WARN_ON_ONCE(&dev_priv->drm, + if (drm_WARN_ON_ONCE(display->drm, status_mask & PIPE_A_PSR_STATUS_VLV)) return 0; /* * On pipe B and C we don't support the PSR interrupt yet, on pipe * A the same bit is for perf counters which we don't use either. */ - if (drm_WARN_ON_ONCE(&dev_priv->drm, + if (drm_WARN_ON_ONCE(display->drm, status_mask & PIPE_B_PSR_STATUS_VLV)) return 0; @@ -217,7 +309,7 @@ u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; out: - drm_WARN_ONCE(&dev_priv->drm, + drm_WARN_ONCE(display->drm, enable_mask & ~PIPESTAT_INT_ENABLE_MASK || status_mask & ~PIPESTAT_INT_STATUS_MASK, "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", @@ -229,6 +321,7 @@ out: void i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask) { + struct intel_display *display = &dev_priv->display; i915_reg_t reg = PIPESTAT(dev_priv, pipe); u32 enable_mask; @@ -243,15 +336,16 @@ void i915_enable_pipestat(struct drm_i915_private *dev_priv, return; dev_priv->display.irq.pipestat_irq_mask[pipe] |= status_mask; - enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + enable_mask = i915_pipestat_enable_mask(display, pipe); - intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); - intel_uncore_posting_read(&dev_priv->uncore, reg); + intel_de_write(display, reg, enable_mask | status_mask); + intel_de_posting_read(display, reg); } void i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask) { + struct intel_display *display = &dev_priv->display; i915_reg_t reg = PIPESTAT(dev_priv, pipe); u32 enable_mask; @@ -266,10 +360,10 @@ void i915_disable_pipestat(struct drm_i915_private *dev_priv, return; dev_priv->display.irq.pipestat_irq_mask[pipe] &= ~status_mask; - enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + enable_mask = i915_pipestat_enable_mask(display, pipe); - intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); - intel_uncore_posting_read(&dev_priv->uncore, reg); + intel_de_write(display, reg, enable_mask | status_mask); + intel_de_posting_read(display, reg); } static bool i915_has_legacy_blc_interrupt(struct intel_display *display) @@ -373,55 +467,58 @@ static void flip_done_handler(struct drm_i915_private *i915, static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_display *display = &dev_priv->display; + display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_HSW(pipe)), + intel_de_read(display, PIPE_CRC_RES_HSW(pipe)), 0, 0, 0, 0); } static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_display *display = &dev_priv->display; + display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe))); + intel_de_read(display, PIPE_CRC_RES_1_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_2_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_3_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_4_IVB(pipe)), + intel_de_read(display, PIPE_CRC_RES_5_IVB(pipe))); } static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_display *display = &dev_priv->display; u32 res1, res2; if (DISPLAY_VER(dev_priv) >= 3) - res1 = intel_uncore_read(&dev_priv->uncore, - PIPE_CRC_RES_RES1_I915(dev_priv, pipe)); + res1 = intel_de_read(display, PIPE_CRC_RES_RES1_I915(dev_priv, pipe)); else res1 = 0; if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) - res2 = intel_uncore_read(&dev_priv->uncore, - PIPE_CRC_RES_RES2_G4X(dev_priv, pipe)); + res2 = intel_de_read(display, PIPE_CRC_RES_RES2_G4X(dev_priv, pipe)); else res2 = 0; display_pipe_crc_irq_handler(dev_priv, pipe, - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(dev_priv, pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(dev_priv, pipe)), - intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(dev_priv, pipe)), + intel_de_read(display, PIPE_CRC_RES_RED(dev_priv, pipe)), + intel_de_read(display, PIPE_CRC_RES_GREEN(dev_priv, pipe)), + intel_de_read(display, PIPE_CRC_RES_BLUE(dev_priv, pipe)), res1, res2); } static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; enum pipe pipe; for_each_pipe(dev_priv, pipe) { - intel_uncore_write(&dev_priv->uncore, - PIPESTAT(dev_priv, pipe), - PIPESTAT_INT_STATUS_MASK | - PIPE_FIFO_UNDERRUN_STATUS); + intel_de_write(display, + PIPESTAT(dev_priv, pipe), + PIPESTAT_INT_STATUS_MASK | PIPE_FIFO_UNDERRUN_STATUS); dev_priv->display.irq.pipestat_irq_mask[pipe] = 0; } @@ -430,11 +527,13 @@ static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, u32 iir, u32 pipe_stats[I915_MAX_PIPES]) { + struct intel_display *display = &dev_priv->display; enum pipe pipe; spin_lock(&dev_priv->irq_lock); - if (!dev_priv->display.irq.display_irqs_enabled) { + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && + !dev_priv->display.irq.vlv_display_irqs_enabled) { spin_unlock(&dev_priv->irq_lock); return; } @@ -473,8 +572,8 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, continue; reg = PIPESTAT(dev_priv, pipe); - pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; - enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + pipe_stats[pipe] = intel_de_read(display, reg) & status_mask; + enable_mask = i915_pipestat_enable_mask(display, pipe); /* * Clear the PIPE*STAT regs before the IIR @@ -486,8 +585,8 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, * an interrupt is still pending. */ if (pipe_stats[pipe]) { - intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]); - intel_uncore_write(&dev_priv->uncore, reg, enable_mask); + intel_de_write(display, reg, pipe_stats[pipe]); + intel_de_write(display, reg, enable_mask); } } spin_unlock(&dev_priv->irq_lock); @@ -511,7 +610,7 @@ void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, i9xx_pipe_crc_irq_handler(dev_priv, pipe); if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + intel_cpu_fifo_underrun_irq_handler(display, pipe); } if (blc_event || (iir & I915_ASLE_INTERRUPT)) @@ -536,7 +635,7 @@ void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, i9xx_pipe_crc_irq_handler(dev_priv, pipe); if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + intel_cpu_fifo_underrun_irq_handler(display, pipe); } if (blc_event || (iir & I915_ASLE_INTERRUPT)) @@ -563,7 +662,7 @@ void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, i9xx_pipe_crc_irq_handler(dev_priv, pipe); if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + intel_cpu_fifo_underrun_irq_handler(display, pipe); } if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) @@ -604,7 +703,7 @@ static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) for_each_pipe(dev_priv, pipe) drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), - intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); + intel_de_read(display, FDI_RX_IIR(pipe))); } if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) @@ -615,23 +714,65 @@ static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) "PCH transcoder CRC error interrupt\n"); if (pch_iir & SDE_TRANSA_FIFO_UNDER) - intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); + intel_pch_fifo_underrun_irq_handler(display, PIPE_A); if (pch_iir & SDE_TRANSB_FIFO_UNDER) - intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); + intel_pch_fifo_underrun_irq_handler(display, PIPE_B); +} + +static u32 ivb_err_int_pipe_fault_mask(enum pipe pipe) +{ + switch (pipe) { + case PIPE_A: + return ERR_INT_SPRITE_A_FAULT | + ERR_INT_PRIMARY_A_FAULT | + ERR_INT_CURSOR_A_FAULT; + case PIPE_B: + return ERR_INT_SPRITE_B_FAULT | + ERR_INT_PRIMARY_B_FAULT | + ERR_INT_CURSOR_B_FAULT; + case PIPE_C: + return ERR_INT_SPRITE_C_FAULT | + ERR_INT_PRIMARY_C_FAULT | + ERR_INT_CURSOR_C_FAULT; + default: + return 0; + } } +static const struct pipe_fault_handler ivb_pipe_fault_handlers[] = { + { .fault = ERR_INT_SPRITE_A_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = ERR_INT_PRIMARY_A_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = ERR_INT_CURSOR_A_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + { .fault = ERR_INT_SPRITE_B_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = ERR_INT_PRIMARY_B_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = ERR_INT_CURSOR_B_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + { .fault = ERR_INT_SPRITE_C_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = ERR_INT_PRIMARY_C_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = ERR_INT_CURSOR_C_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + static void ivb_err_int_handler(struct drm_i915_private *dev_priv) { - u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT); + struct intel_display *display = &dev_priv->display; + u32 err_int = intel_de_read(display, GEN7_ERR_INT); enum pipe pipe; if (err_int & ERR_INT_POISON) drm_err(&dev_priv->drm, "Poison interrupt\n"); + if (err_int & ERR_INT_INVALID_GTT_PTE) + drm_err_ratelimited(display->drm, "Invalid GTT PTE\n"); + + if (err_int & ERR_INT_INVALID_PTE_DATA) + drm_err_ratelimited(display->drm, "Invalid PTE data\n"); + for_each_pipe(dev_priv, pipe) { + u32 fault_errors; + if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + intel_cpu_fifo_underrun_irq_handler(display, pipe); if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { if (IS_IVYBRIDGE(dev_priv)) @@ -639,14 +780,20 @@ static void ivb_err_int_handler(struct drm_i915_private *dev_priv) else hsw_pipe_crc_irq_handler(dev_priv, pipe); } + + fault_errors = err_int & ivb_err_int_pipe_fault_mask(pipe); + if (fault_errors) + intel_pipe_fault_irq_handler(display, ivb_pipe_fault_handlers, + pipe, fault_errors); } - intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int); + intel_de_write(display, GEN7_ERR_INT, err_int); } static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) { - u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT); + struct intel_display *display = &dev_priv->display; + u32 serr_int = intel_de_read(display, SERR_INT); enum pipe pipe; if (serr_int & SERR_INT_POISON) @@ -654,9 +801,9 @@ static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) for_each_pipe(dev_priv, pipe) if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) - intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); + intel_pch_fifo_underrun_irq_handler(display, pipe); - intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int); + intel_de_write(display, SERR_INT, serr_int); } static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) @@ -690,13 +837,63 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) for_each_pipe(dev_priv, pipe) drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), - intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); + intel_de_read(display, FDI_RX_IIR(pipe))); } if (pch_iir & SDE_ERROR_CPT) cpt_serr_int_handler(dev_priv); } +static u32 ilk_gtt_fault_pipe_fault_mask(enum pipe pipe) +{ + switch (pipe) { + case PIPE_A: + return GTT_FAULT_SPRITE_A_FAULT | + GTT_FAULT_PRIMARY_A_FAULT | + GTT_FAULT_CURSOR_A_FAULT; + case PIPE_B: + return GTT_FAULT_SPRITE_B_FAULT | + GTT_FAULT_PRIMARY_B_FAULT | + GTT_FAULT_CURSOR_B_FAULT; + default: + return 0; + } +} + +static const struct pipe_fault_handler ilk_pipe_fault_handlers[] = { + { .fault = GTT_FAULT_SPRITE_A_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = GTT_FAULT_SPRITE_B_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = GTT_FAULT_PRIMARY_A_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = GTT_FAULT_PRIMARY_B_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = GTT_FAULT_CURSOR_A_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + { .fault = GTT_FAULT_CURSOR_B_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + +static void ilk_gtt_fault_irq_handler(struct intel_display *display) +{ + enum pipe pipe; + u32 gtt_fault; + + gtt_fault = intel_de_read(display, ILK_GTT_FAULT); + intel_de_write(display, ILK_GTT_FAULT, gtt_fault); + + if (gtt_fault & GTT_FAULT_INVALID_GTT_PTE) + drm_err_ratelimited(display->drm, "Invalid GTT PTE\n"); + + if (gtt_fault & GTT_FAULT_INVALID_PTE_DATA) + drm_err_ratelimited(display->drm, "Invalid PTE data\n"); + + for_each_pipe(display, pipe) { + u32 fault_errors; + + fault_errors = gtt_fault & ilk_gtt_fault_pipe_fault_mask(pipe); + if (fault_errors) + intel_pipe_fault_irq_handler(display, ilk_pipe_fault_handlers, + pipe, fault_errors); + } +} + void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) { struct intel_display *display = &dev_priv->display; @@ -715,6 +912,9 @@ void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) if (de_iir & DE_POISON) drm_err(&dev_priv->drm, "Poison interrupt\n"); + if (de_iir & DE_GTT_FAULT) + ilk_gtt_fault_irq_handler(display); + for_each_pipe(dev_priv, pipe) { if (de_iir & DE_PIPE_VBLANK(pipe)) intel_handle_vblank(dev_priv, pipe); @@ -723,7 +923,7 @@ void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) flip_done_handler(dev_priv, pipe); if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + intel_cpu_fifo_underrun_irq_handler(display, pipe); if (de_iir & DE_PIPE_CRC_DONE(pipe)) i9xx_pipe_crc_irq_handler(dev_priv, pipe); @@ -731,7 +931,7 @@ void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) /* check event from PCH */ if (de_iir & DE_PCH_EVENT) { - u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); + u32 pch_iir = intel_de_read(display, SDEIIR); if (HAS_PCH_CPT(dev_priv)) cpt_irq_handler(dev_priv, pch_iir); @@ -739,7 +939,7 @@ void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) ibx_irq_handler(dev_priv, pch_iir); /* should clear PCH hotplug event before clear CPU irq */ - intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); + intel_de_write(display, SDEIIR, pch_iir); } if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT) @@ -765,8 +965,7 @@ void ivb_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) struct intel_dp *intel_dp = enc_to_intel_dp(encoder); u32 psr_iir; - psr_iir = intel_uncore_rmw(&dev_priv->uncore, - EDP_PSR_IIR, 0, 0); + psr_iir = intel_de_rmw(display, EDP_PSR_IIR, 0, 0); intel_psr_irq_handler(intel_dp, psr_iir); break; } @@ -788,12 +987,12 @@ void ivb_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) /* check event from PCH */ if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { - u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); + u32 pch_iir = intel_de_read(display, SDEIIR); cpt_irq_handler(dev_priv, pch_iir); /* clear PCH hotplug event before clear CPU irq */ - intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); + intel_de_write(display, SDEIIR, pch_iir); } } @@ -843,7 +1042,9 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) { - if (DISPLAY_VER(dev_priv) >= 14) + struct intel_display *display = &dev_priv->display; + + if (DISPLAY_VER(display) >= 14) return MTL_PIPEDMC_ATS_FAULT | MTL_PLANE_ATS_FAULT | GEN12_PIPEDMC_FAULT | @@ -853,7 +1054,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) GEN9_PIPE_PLANE3_FAULT | GEN9_PIPE_PLANE2_FAULT | GEN9_PIPE_PLANE1_FAULT; - if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv)) + else if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display)) return GEN12_PIPEDMC_FAULT | GEN9_PIPE_CURSOR_FAULT | GEN11_PIPE_PLANE5_FAULT | @@ -861,7 +1062,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) GEN9_PIPE_PLANE3_FAULT | GEN9_PIPE_PLANE2_FAULT | GEN9_PIPE_PLANE1_FAULT; - else if (DISPLAY_VER(dev_priv) == 12) + else if (DISPLAY_VER(display) == 12) return GEN12_PIPEDMC_FAULT | GEN9_PIPE_CURSOR_FAULT | GEN11_PIPE_PLANE7_FAULT | @@ -871,7 +1072,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) GEN9_PIPE_PLANE3_FAULT | GEN9_PIPE_PLANE2_FAULT | GEN9_PIPE_PLANE1_FAULT; - else if (DISPLAY_VER(dev_priv) == 11) + else if (DISPLAY_VER(display) == 11) return GEN9_PIPE_CURSOR_FAULT | GEN11_PIPE_PLANE7_FAULT | GEN11_PIPE_PLANE6_FAULT | @@ -880,7 +1081,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) GEN9_PIPE_PLANE3_FAULT | GEN9_PIPE_PLANE2_FAULT | GEN9_PIPE_PLANE1_FAULT; - else if (DISPLAY_VER(dev_priv) >= 9) + else if (DISPLAY_VER(display) >= 9) return GEN9_PIPE_CURSOR_FAULT | GEN9_PIPE_PLANE4_FAULT | GEN9_PIPE_PLANE3_FAULT | @@ -892,6 +1093,108 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) GEN8_PIPE_PRIMARY_FAULT; } +static bool handle_plane_ats_fault(struct intel_crtc *crtc, enum plane_id plane_id) +{ + struct intel_display *display = to_intel_display(crtc); + + drm_err_ratelimited(display->drm, + "[CRTC:%d:%s] PLANE ATS fault\n", + crtc->base.base.id, crtc->base.name); + + return true; +} + +static bool handle_pipedmc_ats_fault(struct intel_crtc *crtc, enum plane_id plane_id) +{ + struct intel_display *display = to_intel_display(crtc); + + drm_err_ratelimited(display->drm, + "[CRTC:%d:%s] PIPEDMC ATS fault\n", + crtc->base.base.id, crtc->base.name); + + return true; +} + +static bool handle_pipedmc_fault(struct intel_crtc *crtc, enum plane_id plane_id) +{ + struct intel_display *display = to_intel_display(crtc); + + drm_err_ratelimited(display->drm, + "[CRTC:%d:%s] PIPEDMC fault\n", + crtc->base.base.id, crtc->base.name); + + return true; +} + +static const struct pipe_fault_handler mtl_pipe_fault_handlers[] = { + { .fault = MTL_PLANE_ATS_FAULT, .handle = handle_plane_ats_fault, }, + { .fault = MTL_PIPEDMC_ATS_FAULT, .handle = handle_pipedmc_ats_fault, }, + { .fault = GEN12_PIPEDMC_FAULT, .handle = handle_pipedmc_fault, }, + { .fault = GEN11_PIPE_PLANE5_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_5, }, + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + +static const struct pipe_fault_handler tgl_pipe_fault_handlers[] = { + { .fault = GEN12_PIPEDMC_FAULT, .handle = handle_pipedmc_fault, }, + { .fault = GEN11_PIPE_PLANE7_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_7, }, + { .fault = GEN11_PIPE_PLANE6_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_6, }, + { .fault = GEN11_PIPE_PLANE5_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_5, }, + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + +static const struct pipe_fault_handler icl_pipe_fault_handlers[] = { + { .fault = GEN11_PIPE_PLANE7_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_7, }, + { .fault = GEN11_PIPE_PLANE6_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_6, }, + { .fault = GEN11_PIPE_PLANE5_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_5, }, + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + +static const struct pipe_fault_handler skl_pipe_fault_handlers[] = { + { .fault = GEN9_PIPE_PLANE4_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_4, }, + { .fault = GEN9_PIPE_PLANE3_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_3, }, + { .fault = GEN9_PIPE_PLANE2_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_2, }, + { .fault = GEN9_PIPE_PLANE1_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_1, }, + { .fault = GEN9_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + +static const struct pipe_fault_handler bdw_pipe_fault_handlers[] = { + { .fault = GEN8_PIPE_SPRITE_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = GEN8_PIPE_PRIMARY_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = GEN8_PIPE_CURSOR_FAULT, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + +static const struct pipe_fault_handler * +gen8_pipe_fault_handlers(struct intel_display *display) +{ + if (DISPLAY_VER(display) >= 14) + return mtl_pipe_fault_handlers; + else if (DISPLAY_VER(display) >= 12) + return tgl_pipe_fault_handlers; + else if (DISPLAY_VER(display) >= 11) + return icl_pipe_fault_handlers; + else if (DISPLAY_VER(display) >= 9) + return skl_pipe_fault_handlers; + else + return bdw_pipe_fault_handlers; +} + static void intel_pmdemand_irq_handler(struct drm_i915_private *dev_priv) { wake_up_all(&dev_priv->display.pmdemand.waitqueue); @@ -922,8 +1225,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) } if (iir & XELPDP_RM_TIMEOUT) { - u32 val = intel_uncore_read(&dev_priv->uncore, - RM_TIMEOUT_REG_CAPTURE); + u32 val = intel_de_read(display, RM_TIMEOUT_REG_CAPTURE); drm_warn(&dev_priv->drm, "Register Access Timeout = 0x%x\n", val); found = true; } @@ -946,7 +1248,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) else iir_reg = EDP_PSR_IIR; - psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0); + psr_iir = intel_de_rmw(display, iir_reg, 0, 0); if (psr_iir) found = true; @@ -966,6 +1268,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, u32 te_trigger) { + struct intel_display *display = &dev_priv->display; enum pipe pipe = INVALID_PIPE; enum transcoder dsi_trans; enum port port; @@ -975,8 +1278,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, * Incase of dual link, TE comes from DSI_1 * this is to check if dual link is enabled */ - val = intel_uncore_read(&dev_priv->uncore, - TRANS_DDI_FUNC_CTL2(dev_priv, TRANSCODER_DSI_0)); + val = intel_de_read(display, TRANS_DDI_FUNC_CTL2(dev_priv, TRANSCODER_DSI_0)); val &= PORT_SYNC_MODE_ENABLE; /* @@ -988,7 +1290,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; /* Check if DSI configured in command mode */ - val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans)); + val = intel_de_read(display, DSI_TRANS_FUNC_CONF(dsi_trans)); val = val & OP_MODE_MASK; if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { @@ -997,8 +1299,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, } /* Get PIPE for handling VBLANK event */ - val = intel_uncore_read(&dev_priv->uncore, - TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans)); + val = intel_de_read(display, TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans)); switch (val & TRANS_DDI_EDP_INPUT_MASK) { case TRANS_DDI_EDP_INPUT_A_ON: pipe = PIPE_A; @@ -1018,7 +1319,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, /* clear TE in dsi IIR */ port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; - intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); + intel_de_rmw(display, DSI_INTR_IDENT_REG(port), 0, 0); } static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) @@ -1031,10 +1332,11 @@ static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir) { + struct intel_display *display = &i915->display; u32 pica_ier = 0; *pica_iir = 0; - *pch_iir = intel_de_read(i915, SDEIIR); + *pch_iir = intel_de_read(display, SDEIIR); if (!*pch_iir) return; @@ -1046,15 +1348,15 @@ static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_i if (*pch_iir & SDE_PICAINTERRUPT) { drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTL); - pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0); - *pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR); - intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir); + pica_ier = intel_de_rmw(display, PICAINTERRUPT_IER, ~0, 0); + *pica_iir = intel_de_read(display, PICAINTERRUPT_IIR); + intel_de_write(display, PICAINTERRUPT_IIR, *pica_iir); } - intel_de_write(i915, SDEIIR, *pch_iir); + intel_de_write(display, SDEIIR, *pch_iir); if (pica_ier) - intel_de_write(i915, PICAINTERRUPT_IER, pica_ier); + intel_de_write(display, PICAINTERRUPT_IER, pica_ier); } void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) @@ -1066,9 +1368,9 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv)); if (master_ctl & GEN8_DE_MISC_IRQ) { - iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR); + iir = intel_de_read(display, GEN8_DE_MISC_IIR); if (iir) { - intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir); + intel_de_write(display, GEN8_DE_MISC_IIR, iir); gen8_de_misc_irq_handler(dev_priv, iir); } else { drm_err_ratelimited(&dev_priv->drm, @@ -1077,9 +1379,9 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) } if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { - iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR); + iir = intel_de_read(display, GEN11_DE_HPD_IIR); if (iir) { - intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir); + intel_de_write(display, GEN11_DE_HPD_IIR, iir); gen11_hpd_irq_handler(dev_priv, iir); } else { drm_err_ratelimited(&dev_priv->drm, @@ -1088,11 +1390,11 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) } if (master_ctl & GEN8_DE_PORT_IRQ) { - iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR); + iir = intel_de_read(display, GEN8_DE_PORT_IIR); if (iir) { bool found = false; - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir); + intel_de_write(display, GEN8_DE_PORT_IIR, iir); if (iir & gen8_de_port_aux_mask(dev_priv)) { intel_dp_aux_irq_handler(display); @@ -1145,14 +1447,14 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) continue; - iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); + iir = intel_de_read(display, GEN8_DE_PIPE_IIR(pipe)); if (!iir) { drm_err_ratelimited(&dev_priv->drm, "The master control interrupt lied (DE PIPE)!\n"); continue; } - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir); + intel_de_write(display, GEN8_DE_PIPE_IIR(pipe), iir); if (iir & GEN8_PIPE_VBLANK) intel_handle_vblank(dev_priv, pipe); @@ -1175,14 +1477,13 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) hsw_pipe_crc_irq_handler(dev_priv, pipe); if (iir & GEN8_PIPE_FIFO_UNDERRUN) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + intel_cpu_fifo_underrun_irq_handler(display, pipe); fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); if (fault_errors) - drm_err_ratelimited(&dev_priv->drm, - "Fault errors on pipe %c: 0x%08x\n", - pipe_name(pipe), - fault_errors); + intel_pipe_fault_irq_handler(display, + gen8_pipe_fault_handlers(display), + pipe, fault_errors); } if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && @@ -1218,14 +1519,15 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl) { + struct intel_display *display = &i915->display; u32 iir; if (!(master_ctl & GEN11_GU_MISC_IRQ)) return 0; - iir = intel_de_read(i915, GEN11_GU_MISC_IIR); + iir = intel_de_read(display, GEN11_GU_MISC_IIR); if (likely(iir)) - intel_de_write(i915, GEN11_GU_MISC_IIR, iir); + intel_de_write(display, GEN11_GU_MISC_IIR, iir); return iir; } @@ -1240,6 +1542,7 @@ void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir) void gen11_display_irq_handler(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; u32 disp_ctl; disable_rpm_wakeref_asserts(&i915->runtime_pm); @@ -1247,17 +1550,18 @@ void gen11_display_irq_handler(struct drm_i915_private *i915) * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ * for the display related bits. */ - disp_ctl = intel_de_read(i915, GEN11_DISPLAY_INT_CTL); + disp_ctl = intel_de_read(display, GEN11_DISPLAY_INT_CTL); - intel_de_write(i915, GEN11_DISPLAY_INT_CTL, 0); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); gen8_de_irq_handler(i915, disp_ctl); - intel_de_write(i915, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); enable_rpm_wakeref_asserts(&i915->runtime_pm); } static void i915gm_irq_cstate_wa_enable(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; lockdep_assert_held(&i915->drm.vblank_time_lock); /* @@ -1267,15 +1571,18 @@ static void i915gm_irq_cstate_wa_enable(struct drm_i915_private *i915) * only when vblank/CRC interrupts are actually enabled. */ if (i915->display.irq.vblank_enabled++ == 0) - intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); + intel_de_write(display, SCPD0, + _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); } static void i915gm_irq_cstate_wa_disable(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; lockdep_assert_held(&i915->drm.vblank_time_lock); if (--i915->display.irq.vblank_enabled == 0) - intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); + intel_de_write(display, SCPD0, + _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); } void i915gm_irq_cstate_wa(struct drm_i915_private *i915, bool enable) @@ -1395,7 +1702,7 @@ void ilk_disable_vblank(struct drm_crtc *crtc) static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, bool enable) { - struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + struct intel_display *display = to_intel_display(intel_crtc); enum port port; if (!(intel_crtc->mode_flags & @@ -1408,10 +1715,9 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, else port = PORT_A; - intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, - enable ? 0 : DSI_TE_EVENT); + intel_de_rmw(display, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, enable ? 0 : DSI_TE_EVENT); - intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); + intel_de_rmw(display, DSI_INTR_IDENT_REG(port), 0, 0); return true; } @@ -1420,7 +1726,6 @@ static void intel_display_vblank_dc_work(struct work_struct *work) { struct intel_display *display = container_of(work, typeof(*display), irq.vblank_dc_work); - struct drm_i915_private *i915 = to_i915(display->drm); int vblank_wa_num_pipes = READ_ONCE(display->irq.vblank_wa_num_pipes); /* @@ -1429,7 +1734,7 @@ static void intel_display_vblank_dc_work(struct work_struct *work) * PSR code. If DC3CO is taken into use we need take that into account * here as well. */ - intel_display_power_set_target_dc_state(i915, vblank_wa_num_pipes ? DC_STATE_DISABLE : + intel_display_power_set_target_dc_state(display, vblank_wa_num_pipes ? DC_STATE_DISABLE : DC_STATE_EN_UPTO_DC6); } @@ -1479,43 +1784,181 @@ void bdw_disable_vblank(struct drm_crtc *_crtc) schedule_work(&display->irq.vblank_dc_work); } -void vlv_display_irq_reset(struct drm_i915_private *dev_priv) +static u32 vlv_dpinvgtt_pipe_fault_mask(enum pipe pipe) +{ + switch (pipe) { + case PIPE_A: + return SPRITEB_INVALID_GTT_STATUS | + SPRITEA_INVALID_GTT_STATUS | + PLANEA_INVALID_GTT_STATUS | + CURSORA_INVALID_GTT_STATUS; + case PIPE_B: + return SPRITED_INVALID_GTT_STATUS | + SPRITEC_INVALID_GTT_STATUS | + PLANEB_INVALID_GTT_STATUS | + CURSORB_INVALID_GTT_STATUS; + case PIPE_C: + return SPRITEF_INVALID_GTT_STATUS | + SPRITEE_INVALID_GTT_STATUS | + PLANEC_INVALID_GTT_STATUS | + CURSORC_INVALID_GTT_STATUS; + default: + return 0; + } +} + +static const struct pipe_fault_handler vlv_pipe_fault_handlers[] = { + { .fault = SPRITEB_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE1, }, + { .fault = SPRITEA_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = PLANEA_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = CURSORA_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + { .fault = SPRITED_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE1, }, + { .fault = SPRITEC_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = PLANEB_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = CURSORB_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + { .fault = SPRITEF_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE1, }, + { .fault = SPRITEE_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_SPRITE0, }, + { .fault = PLANEC_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_PRIMARY, }, + { .fault = CURSORC_INVALID_GTT_STATUS, .handle = handle_plane_fault, .plane_id = PLANE_CURSOR, }, + {} +}; + +static void vlv_page_table_error_irq_ack(struct intel_display *display, u32 *dpinvgtt) +{ + u32 status, enable, tmp; + + tmp = intel_de_read(display, DPINVGTT); + + enable = tmp >> 16; + status = tmp & 0xffff; + + /* + * Despite what the docs claim, the status bits seem to get + * stuck permanently (similar the old PGTBL_ER register), so + * we have to disable and ignore them once set. They do get + * reset if the display power well goes down, so no need to + * track the enable mask explicitly. + */ + *dpinvgtt = status & enable; + enable &= ~status; + + /* customary ack+disable then re-enable to guarantee an edge */ + intel_de_write(display, DPINVGTT, status); + intel_de_write(display, DPINVGTT, enable << 16); +} + +static void vlv_page_table_error_irq_handler(struct intel_display *display, u32 dpinvgtt) +{ + enum pipe pipe; + + for_each_pipe(display, pipe) { + u32 fault_errors; + + fault_errors = dpinvgtt & vlv_dpinvgtt_pipe_fault_mask(pipe); + if (fault_errors) + intel_pipe_fault_irq_handler(display, vlv_pipe_fault_handlers, + pipe, fault_errors); + } +} + +void vlv_display_error_irq_ack(struct intel_display *display, + u32 *eir, u32 *dpinvgtt) { - struct intel_uncore *uncore = &dev_priv->uncore; + u32 emr; + + *eir = intel_de_read(display, VLV_EIR); + + if (*eir & VLV_ERROR_PAGE_TABLE) + vlv_page_table_error_irq_ack(display, dpinvgtt); + + intel_de_write(display, VLV_EIR, *eir); + + /* + * Toggle all EMR bits to make sure we get an edge + * in the ISR master error bit if we don't clear + * all the EIR bits. + */ + emr = intel_de_read(display, VLV_EMR); + intel_de_write(display, VLV_EMR, 0xffffffff); + intel_de_write(display, VLV_EMR, emr); +} + +void vlv_display_error_irq_handler(struct intel_display *display, + u32 eir, u32 dpinvgtt) +{ + drm_dbg(display->drm, "Master Error, EIR 0x%08x\n", eir); + + if (eir & VLV_ERROR_PAGE_TABLE) + vlv_page_table_error_irq_handler(display, dpinvgtt); +} + +static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv) +{ + struct intel_display *display = &dev_priv->display; if (IS_CHERRYVIEW(dev_priv)) - intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); + intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); else - intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); + intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); + + gen2_error_reset(to_intel_uncore(display->drm), + VLV_ERROR_REGS); i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); - intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT(dev_priv), 0, 0); + intel_de_rmw(display, PORT_HOTPLUG_STAT(dev_priv), 0, 0); i9xx_pipestat_irq_reset(dev_priv); - gen2_irq_reset(uncore, VLV_IRQ_REGS); + intel_display_irq_regs_reset(display, VLV_IRQ_REGS); dev_priv->irq_mask = ~0u; } +void vlv_display_irq_reset(struct drm_i915_private *dev_priv) +{ + if (dev_priv->display.irq.vlv_display_irqs_enabled) + _vlv_display_irq_reset(dev_priv); +} + void i9xx_display_irq_reset(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; + if (I915_HAS_HOTPLUG(i915)) { i915_hotplug_interrupt_update(i915, 0xffffffff, 0); - intel_uncore_rmw(&i915->uncore, - PORT_HOTPLUG_STAT(i915), 0, 0); + intel_de_rmw(display, PORT_HOTPLUG_STAT(i915), 0, 0); } i9xx_pipestat_irq_reset(i915); } -void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) +static u32 vlv_error_mask(void) { - struct intel_uncore *uncore = &dev_priv->uncore; + /* TODO enable other errors too? */ + return VLV_ERROR_PAGE_TABLE; +} +void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) +{ + struct intel_display *display = &dev_priv->display; u32 pipestat_mask; u32 enable_mask; enum pipe pipe; + if (!dev_priv->display.irq.vlv_display_irqs_enabled) + return; + + if (IS_CHERRYVIEW(dev_priv)) + intel_de_write(display, DPINVGTT, + DPINVGTT_STATUS_MASK_CHV | + DPINVGTT_EN_MASK_CHV); + else + intel_de_write(display, DPINVGTT, + DPINVGTT_STATUS_MASK_VLV | + DPINVGTT_EN_MASK_VLV); + + gen2_error_init(to_intel_uncore(display->drm), + VLV_ERROR_REGS, ~vlv_error_mask()); + pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); @@ -1526,7 +1969,8 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | I915_LPE_PIPE_A_INTERRUPT | - I915_LPE_PIPE_B_INTERRUPT; + I915_LPE_PIPE_B_INTERRUPT | + I915_MASTER_ERROR_INTERRUPT; if (IS_CHERRYVIEW(dev_priv)) enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | @@ -1536,32 +1980,32 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->irq_mask = ~enable_mask; - gen2_irq_init(uncore, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask); + intel_display_irq_regs_init(display, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask); } void gen8_display_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; enum pipe pipe; if (!HAS_DISPLAY(dev_priv)) return; - intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); - intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); + intel_de_write(display, EDP_PSR_IMR, 0xffffffff); + intel_de_write(display, EDP_PSR_IIR, 0xffffffff); for_each_pipe(dev_priv, pipe) - if (intel_display_power_is_enabled(dev_priv, + if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe)); + intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - gen2_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS); - gen2_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); } void gen11_display_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; enum pipe pipe; u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D); @@ -1569,7 +2013,7 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); if (DISPLAY_VER(dev_priv) >= 12) { enum transcoder trans; @@ -1578,42 +2022,42 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv) enum intel_display_power_domain domain; domain = POWER_DOMAIN_TRANSCODER(trans); - if (!intel_display_power_is_enabled(dev_priv, domain)) + if (!intel_display_power_is_enabled(display, domain)) continue; - intel_uncore_write(uncore, - TRANS_PSR_IMR(dev_priv, trans), - 0xffffffff); - intel_uncore_write(uncore, - TRANS_PSR_IIR(dev_priv, trans), - 0xffffffff); + intel_de_write(display, + TRANS_PSR_IMR(dev_priv, trans), + 0xffffffff); + intel_de_write(display, + TRANS_PSR_IIR(dev_priv, trans), + 0xffffffff); } } else { - intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); - intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); + intel_de_write(display, EDP_PSR_IMR, 0xffffffff); + intel_de_write(display, EDP_PSR_IIR, 0xffffffff); } for_each_pipe(dev_priv, pipe) - if (intel_display_power_is_enabled(dev_priv, + if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe)); + intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - gen2_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS); - gen2_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); if (DISPLAY_VER(dev_priv) >= 14) - gen2_irq_reset(uncore, PICAINTERRUPT_IRQ_REGS); + intel_display_irq_regs_reset(display, PICAINTERRUPT_IRQ_REGS); else - gen2_irq_reset(uncore, GEN11_DE_HPD_IRQ_REGS); + intel_display_irq_regs_reset(display, GEN11_DE_HPD_IRQ_REGS); if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - gen2_irq_reset(uncore, SDE_IRQ_REGS); + intel_display_irq_regs_reset(display, SDE_IRQ_REGS); } void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u8 pipe_mask) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | gen8_de_pipe_flip_done_mask(dev_priv); enum pipe pipe; @@ -1626,9 +2070,9 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, } for_each_pipe_masked(dev_priv, pipe, pipe_mask) - gen2_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe), - dev_priv->display.irq.de_irq_mask[pipe], - ~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier); + intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + dev_priv->display.irq.de_irq_mask[pipe], + ~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier); spin_unlock_irq(&dev_priv->irq_lock); } @@ -1636,7 +2080,7 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, u8 pipe_mask) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; enum pipe pipe; spin_lock_irq(&dev_priv->irq_lock); @@ -1647,7 +2091,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, } for_each_pipe_masked(dev_priv, pipe, pipe_mask) - gen2_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe)); + intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); spin_unlock_irq(&dev_priv->irq_lock); @@ -1668,7 +2112,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, */ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; u32 mask; if (HAS_PCH_NOP(dev_priv)) @@ -1681,20 +2125,20 @@ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) else mask = SDE_GMBUS_CPT; - gen2_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff); + intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) { lockdep_assert_held(&dev_priv->irq_lock); - if (dev_priv->display.irq.display_irqs_enabled) + if (dev_priv->display.irq.vlv_display_irqs_enabled) return; - dev_priv->display.irq.display_irqs_enabled = true; + dev_priv->display.irq.vlv_display_irqs_enabled = true; if (intel_irqs_enabled(dev_priv)) { - vlv_display_irq_reset(dev_priv); + _vlv_display_irq_reset(dev_priv); vlv_display_irq_postinstall(dev_priv); } } @@ -1703,18 +2147,18 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) { lockdep_assert_held(&dev_priv->irq_lock); - if (!dev_priv->display.irq.display_irqs_enabled) + if (!dev_priv->display.irq.vlv_display_irqs_enabled) return; - dev_priv->display.irq.display_irqs_enabled = false; + dev_priv->display.irq.vlv_display_irqs_enabled = false; if (intel_irqs_enabled(dev_priv)) - vlv_display_irq_reset(dev_priv); + _vlv_display_irq_reset(dev_priv); } void ilk_de_irq_postinstall(struct drm_i915_private *i915) { - struct intel_uncore *uncore = &i915->uncore; + struct intel_display *display = &i915->display; u32 display_mask, extra_mask; if (DISPLAY_VER(i915) >= 7) { @@ -1727,7 +2171,8 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915) DE_PLANE_FLIP_DONE_IVB(PLANE_A) | DE_DP_A_HOTPLUG_IVB); } else { - display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | + display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | + DE_PCH_EVENT | DE_GTT_FAULT | DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE | DE_POISON); extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | @@ -1738,7 +2183,7 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915) } if (IS_HASWELL(i915)) { - gen2_assert_iir_is_zero(uncore, EDP_PSR_IIR); + intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); display_mask |= DE_EDP_PSR_INT_HSW; } @@ -1749,8 +2194,8 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915) ibx_irq_postinstall(i915); - gen2_irq_init(uncore, DE_IRQ_REGS, i915->irq_mask, - display_mask | extra_mask); + intel_display_irq_regs_init(display, DE_IRQ_REGS, i915->irq_mask, + display_mask | extra_mask); } static void mtp_irq_postinstall(struct drm_i915_private *i915); @@ -1759,7 +2204,6 @@ static void icp_irq_postinstall(struct drm_i915_private *i915); void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) { struct intel_display *display = &dev_priv->display; - struct intel_uncore *uncore = &dev_priv->uncore; u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) | GEN8_PIPE_CDCLK_CRC_DONE; @@ -1822,97 +2266,90 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) enum intel_display_power_domain domain; domain = POWER_DOMAIN_TRANSCODER(trans); - if (!intel_display_power_is_enabled(dev_priv, domain)) + if (!intel_display_power_is_enabled(display, domain)) continue; - gen2_assert_iir_is_zero(uncore, - TRANS_PSR_IIR(dev_priv, trans)); + intel_display_irq_regs_assert_irr_is_zero(display, + TRANS_PSR_IIR(dev_priv, trans)); } } else { - gen2_assert_iir_is_zero(uncore, EDP_PSR_IIR); + intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); } for_each_pipe(dev_priv, pipe) { dev_priv->display.irq.de_irq_mask[pipe] = ~de_pipe_masked; - if (intel_display_power_is_enabled(dev_priv, + if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - gen2_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe), - dev_priv->display.irq.de_irq_mask[pipe], - de_pipe_enables); + intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + dev_priv->display.irq.de_irq_mask[pipe], + de_pipe_enables); } - gen2_irq_init(uncore, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables); - gen2_irq_init(uncore, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked); + intel_display_irq_regs_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, + de_port_enables); + intel_display_irq_regs_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, + de_misc_masked); if (IS_DISPLAY_VER(dev_priv, 11, 13)) { u32 de_hpd_masked = 0; u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; - gen2_irq_init(uncore, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, - de_hpd_enables); + intel_display_irq_regs_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, + de_hpd_enables); } } static void mtp_irq_postinstall(struct drm_i915_private *i915) { - struct intel_uncore *uncore = &i915->uncore; + struct intel_display *display = &i915->display; u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT; u32 de_hpd_mask = XELPDP_AUX_TC_MASK; u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK; - gen2_irq_init(uncore, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, - de_hpd_enables); + intel_display_irq_regs_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, + de_hpd_enables); - gen2_irq_init(uncore, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); + intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); } static void icp_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_display *display = &dev_priv->display; u32 mask = SDE_GMBUS_ICP; - gen2_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff); + intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; + if (!HAS_DISPLAY(dev_priv)) return; gen8_de_irq_postinstall(dev_priv); - intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, - GEN11_DISPLAY_IRQ_ENABLE); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); } void dg1_de_irq_postinstall(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; + if (!HAS_DISPLAY(i915)) return; gen8_de_irq_postinstall(i915); - intel_uncore_write(&i915->uncore, GEN11_DISPLAY_INT_CTL, - GEN11_DISPLAY_IRQ_ENABLE); + intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); } void intel_display_irq_init(struct drm_i915_private *i915) { i915->drm.vblank_disable_immediate = true; - /* - * Most platforms treat the display irq block as an always-on power - * domain. vlv/chv can disable it at runtime and need special care to - * avoid writing any of the display block registers outside of the power - * domain. We defer setting up the display irqs in this case to the - * runtime pm. - */ - i915->display.irq.display_irqs_enabled = true; - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - i915->display.irq.display_irqs_enabled = false; - intel_hotplug_irq_init(i915); INIT_WORK(&i915->display.irq.vblank_dc_work, |