1c0e09200SDave Airlie /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- 2c0e09200SDave Airlie */ 3c0e09200SDave Airlie /* 4c0e09200SDave Airlie * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5c0e09200SDave Airlie * All Rights Reserved. 6c0e09200SDave Airlie * 7c0e09200SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 8c0e09200SDave Airlie * copy of this software and associated documentation files (the 9c0e09200SDave Airlie * "Software"), to deal in the Software without restriction, including 10c0e09200SDave Airlie * without limitation the rights to use, copy, modify, merge, publish, 11c0e09200SDave Airlie * distribute, sub license, and/or sell copies of the Software, and to 12c0e09200SDave Airlie * permit persons to whom the Software is furnished to do so, subject to 13c0e09200SDave Airlie * the following conditions: 14c0e09200SDave Airlie * 15c0e09200SDave Airlie * The above copyright notice and this permission notice (including the 16c0e09200SDave Airlie * next paragraph) shall be included in all copies or substantial portions 17c0e09200SDave Airlie * of the Software. 18c0e09200SDave Airlie * 19c0e09200SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20c0e09200SDave Airlie * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21c0e09200SDave Airlie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22c0e09200SDave Airlie * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23c0e09200SDave Airlie * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24c0e09200SDave Airlie * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25c0e09200SDave Airlie * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26c0e09200SDave Airlie * 27c0e09200SDave Airlie */ 28c0e09200SDave Airlie 29a70491ccSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 30a70491ccSJoe Perches 3155367a27SJani Nikula #include <linux/slab.h> 3255367a27SJani Nikula #include <linux/sysrq.h> 3355367a27SJani Nikula 34fcd70cd3SDaniel Vetter #include <drm/drm_drv.h> 3555367a27SJani Nikula 363c0deb14SJani Nikula #include "display/icl_dsi_regs.h" 377785ae0bSVille Syrjälä #include "display/intel_de.h" 38fd2b94a5SJani Nikula #include "display/intel_display_trace.h" 391d455f8dSJani Nikula #include "display/intel_display_types.h" 40685282a3SJani Nikula #include "display/intel_dp_aux.h" 4104500bfdSJani Nikula #include "display/intel_fdi_regs.h" 42df0566a6SJani Nikula #include "display/intel_fifo_underrun.h" 43685282a3SJani Nikula #include "display/intel_gmbus.h" 44df0566a6SJani Nikula #include "display/intel_hotplug.h" 45*da38ba98SJani Nikula #include "display/intel_hotplug_irq.h" 46df0566a6SJani Nikula #include "display/intel_lpe_audio.h" 47df0566a6SJani Nikula #include "display/intel_psr.h" 487f6947fdSJani Nikula #include "display/intel_psr_regs.h" 49df0566a6SJani Nikula 50b3786b29SChris Wilson #include "gt/intel_breadcrumbs.h" 512239e6dfSDaniele Ceraolo Spurio #include "gt/intel_gt.h" 52cf1c97dcSAndi Shyti #include "gt/intel_gt_irq.h" 53d762043fSAndi Shyti #include "gt/intel_gt_pm_irq.h" 540d6419e9SMatt Roper #include "gt/intel_gt_regs.h" 553e7abf81SAndi Shyti #include "gt/intel_rps.h" 562239e6dfSDaniele Ceraolo Spurio 5724524e3fSJani Nikula #include "i915_driver.h" 58c0e09200SDave Airlie #include "i915_drv.h" 59440e2b3dSJani Nikula #include "i915_irq.h" 60476f62b8SJani Nikula #include "i915_reg.h" 61c0e09200SDave Airlie 62fca52a55SDaniel Vetter /** 63fca52a55SDaniel Vetter * DOC: interrupt handling 64fca52a55SDaniel Vetter * 65fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 66fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 67fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 68fca52a55SDaniel Vetter */ 69fca52a55SDaniel Vetter 709c6508b9SThomas Gleixner /* 719c6508b9SThomas Gleixner * Interrupt statistic for PMU. Increments the counter only if the 7278f48aa6SBo Liu * interrupt originated from the GPU so interrupts from a device which 739c6508b9SThomas Gleixner * shares the interrupt line are not accounted. 749c6508b9SThomas Gleixner */ 759c6508b9SThomas Gleixner static inline void pmu_irq_stats(struct drm_i915_private *i915, 769c6508b9SThomas Gleixner irqreturn_t res) 779c6508b9SThomas Gleixner { 789c6508b9SThomas Gleixner if (unlikely(res != IRQ_HANDLED)) 799c6508b9SThomas Gleixner return; 809c6508b9SThomas Gleixner 819c6508b9SThomas Gleixner /* 829c6508b9SThomas Gleixner * A clever compiler translates that into INC. A not so clever one 839c6508b9SThomas Gleixner * should at least prevent store tearing. 849c6508b9SThomas Gleixner */ 859c6508b9SThomas Gleixner WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1); 869c6508b9SThomas Gleixner } 879c6508b9SThomas Gleixner 88aca9310aSAnshuman Gupta static void 89aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) 90aca9310aSAnshuman Gupta { 917794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 92aca9310aSAnshuman Gupta 93aca9310aSAnshuman Gupta drm_crtc_handle_vblank(&crtc->base); 94aca9310aSAnshuman Gupta } 95aca9310aSAnshuman Gupta 96cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, 9768eb49b1SPaulo Zanoni i915_reg_t iir, i915_reg_t ier) 9868eb49b1SPaulo Zanoni { 9965f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, 0xffffffff); 10065f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 10168eb49b1SPaulo Zanoni 10265f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, 0); 10368eb49b1SPaulo Zanoni 1045c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 10565f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 10665f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 10765f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 10865f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 10968eb49b1SPaulo Zanoni } 1105c502442SPaulo Zanoni 111ad7632ffSJani Nikula static void gen2_irq_reset(struct intel_uncore *uncore) 11268eb49b1SPaulo Zanoni { 11365f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, 0xffff); 11465f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 115a9d356a6SPaulo Zanoni 11665f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, 0); 11768eb49b1SPaulo Zanoni 11868eb49b1SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 11965f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 12065f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 12165f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 12265f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 12368eb49b1SPaulo Zanoni } 12468eb49b1SPaulo Zanoni 125337ba017SPaulo Zanoni /* 126337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 127337ba017SPaulo Zanoni */ 12865f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) 129b51a2842SVille Syrjälä { 13065f42cdcSPaulo Zanoni u32 val = intel_uncore_read(uncore, reg); 131b51a2842SVille Syrjälä 132b51a2842SVille Syrjälä if (val == 0) 133b51a2842SVille Syrjälä return; 134b51a2842SVille Syrjälä 135a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 136a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 137f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 13865f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 13965f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 14065f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 14165f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 142b51a2842SVille Syrjälä } 143337ba017SPaulo Zanoni 14465f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore) 145e9e9848aSVille Syrjälä { 14665f42cdcSPaulo Zanoni u16 val = intel_uncore_read16(uncore, GEN2_IIR); 147e9e9848aSVille Syrjälä 148e9e9848aSVille Syrjälä if (val == 0) 149e9e9848aSVille Syrjälä return; 150e9e9848aSVille Syrjälä 151a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 152a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 1539d9523d8SPaulo Zanoni i915_mmio_reg_offset(GEN2_IIR), val); 15465f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 15565f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 15665f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 15765f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 158e9e9848aSVille Syrjälä } 159e9e9848aSVille Syrjälä 160cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore, 16168eb49b1SPaulo Zanoni i915_reg_t imr, u32 imr_val, 16268eb49b1SPaulo Zanoni i915_reg_t ier, u32 ier_val, 16368eb49b1SPaulo Zanoni i915_reg_t iir) 16468eb49b1SPaulo Zanoni { 16565f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(uncore, iir); 16635079899SPaulo Zanoni 16765f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, ier_val); 16865f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, imr_val); 16965f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 17068eb49b1SPaulo Zanoni } 17135079899SPaulo Zanoni 172ad7632ffSJani Nikula static void gen2_irq_init(struct intel_uncore *uncore, 1732918c3caSPaulo Zanoni u32 imr_val, u32 ier_val) 17468eb49b1SPaulo Zanoni { 17565f42cdcSPaulo Zanoni gen2_assert_iir_is_zero(uncore); 17668eb49b1SPaulo Zanoni 17765f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, ier_val); 17865f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, imr_val); 17965f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 18068eb49b1SPaulo Zanoni } 18168eb49b1SPaulo Zanoni 182d9dc34f1SVille Syrjälä /** 183d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 184d9dc34f1SVille Syrjälä * @dev_priv: driver private 185d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 186d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 187d9dc34f1SVille Syrjälä */ 188*da38ba98SJani Nikula void ilk_update_display_irq(struct drm_i915_private *dev_priv, 1899e6dcf33SJani Nikula u32 interrupt_mask, u32 enabled_irq_mask) 190036a4a7dSZhenyu Wang { 191a9c287c9SJani Nikula u32 new_val; 192d9dc34f1SVille Syrjälä 19367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 19448a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 195d9dc34f1SVille Syrjälä 196d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 197d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 198d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 199d9dc34f1SVille Syrjälä 200e44adb5dSChris Wilson if (new_val != dev_priv->irq_mask && 201e44adb5dSChris Wilson !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { 202d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 2032939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask); 2042939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, DEIMR); 205036a4a7dSZhenyu Wang } 206036a4a7dSZhenyu Wang } 207036a4a7dSZhenyu Wang 2089e6dcf33SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits) 2099e6dcf33SJani Nikula { 2109e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, bits); 2119e6dcf33SJani Nikula } 2129e6dcf33SJani Nikula 2139e6dcf33SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits) 2149e6dcf33SJani Nikula { 2159e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, 0); 2169e6dcf33SJani Nikula } 2179e6dcf33SJani Nikula 2180961021aSBen Widawsky /** 2193a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 2203a3b3c7dSVille Syrjälä * @dev_priv: driver private 2213a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 2223a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 2233a3b3c7dSVille Syrjälä */ 224*da38ba98SJani Nikula void bdw_update_port_irq(struct drm_i915_private *dev_priv, 225*da38ba98SJani Nikula u32 interrupt_mask, u32 enabled_irq_mask) 2263a3b3c7dSVille Syrjälä { 227a9c287c9SJani Nikula u32 new_val; 228a9c287c9SJani Nikula u32 old_val; 2293a3b3c7dSVille Syrjälä 23067520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 2313a3b3c7dSVille Syrjälä 23248a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 2333a3b3c7dSVille Syrjälä 23448a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 2353a3b3c7dSVille Syrjälä return; 2363a3b3c7dSVille Syrjälä 2372939eb06SJani Nikula old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 2383a3b3c7dSVille Syrjälä 2393a3b3c7dSVille Syrjälä new_val = old_val; 2403a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 2413a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 2423a3b3c7dSVille Syrjälä 2433a3b3c7dSVille Syrjälä if (new_val != old_val) { 2442939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val); 2452939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 2463a3b3c7dSVille Syrjälä } 2473a3b3c7dSVille Syrjälä } 2483a3b3c7dSVille Syrjälä 2493a3b3c7dSVille Syrjälä /** 250013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 251013d3752SVille Syrjälä * @dev_priv: driver private 252013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 253013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 254013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 255013d3752SVille Syrjälä */ 2569e6dcf33SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 2579e6dcf33SJani Nikula enum pipe pipe, u32 interrupt_mask, 258a9c287c9SJani Nikula u32 enabled_irq_mask) 259013d3752SVille Syrjälä { 260a9c287c9SJani Nikula u32 new_val; 261013d3752SVille Syrjälä 26267520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 263013d3752SVille Syrjälä 26448a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 265013d3752SVille Syrjälä 26648a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 267013d3752SVille Syrjälä return; 268013d3752SVille Syrjälä 269013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 270013d3752SVille Syrjälä new_val &= ~interrupt_mask; 271013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 272013d3752SVille Syrjälä 273013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 274013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 2752939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 2762939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); 277013d3752SVille Syrjälä } 278013d3752SVille Syrjälä } 279013d3752SVille Syrjälä 2809e6dcf33SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915, 2819e6dcf33SJani Nikula enum pipe pipe, u32 bits) 2829e6dcf33SJani Nikula { 2839e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, bits); 2849e6dcf33SJani Nikula } 2859e6dcf33SJani Nikula 2869e6dcf33SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915, 2879e6dcf33SJani Nikula enum pipe pipe, u32 bits) 2889e6dcf33SJani Nikula { 2899e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, 0); 2909e6dcf33SJani Nikula } 2919e6dcf33SJani Nikula 292013d3752SVille Syrjälä /** 293fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 294fee884edSDaniel Vetter * @dev_priv: driver private 295fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 296fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 297fee884edSDaniel Vetter */ 298*da38ba98SJani Nikula void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 299a9c287c9SJani Nikula u32 interrupt_mask, 300a9c287c9SJani Nikula u32 enabled_irq_mask) 301fee884edSDaniel Vetter { 3022939eb06SJani Nikula u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR); 303fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 304fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 305fee884edSDaniel Vetter 30648a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 30715a17aaeSDaniel Vetter 30867520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 309fee884edSDaniel Vetter 31048a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 311c67a470bSPaulo Zanoni return; 312c67a470bSPaulo Zanoni 3132939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr); 3142939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, SDEIMR); 315fee884edSDaniel Vetter } 3168664281bSPaulo Zanoni 3179e6dcf33SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits) 3189e6dcf33SJani Nikula { 3199e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, bits); 3209e6dcf33SJani Nikula } 3219e6dcf33SJani Nikula 3229e6dcf33SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits) 3239e6dcf33SJani Nikula { 3249e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, 0); 3259e6dcf33SJani Nikula } 3269e6dcf33SJani Nikula 3276b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 3286b12ca56SVille Syrjälä enum pipe pipe) 3297c463586SKeith Packard { 3306b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 33110c59c51SImre Deak u32 enable_mask = status_mask << 16; 33210c59c51SImre Deak 3336b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 3346b12ca56SVille Syrjälä 335373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 5) 3366b12ca56SVille Syrjälä goto out; 3376b12ca56SVille Syrjälä 33810c59c51SImre Deak /* 339724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 340724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 34110c59c51SImre Deak */ 34248a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 34348a1b8d4SPankaj Bharadiya status_mask & PIPE_A_PSR_STATUS_VLV)) 34410c59c51SImre Deak return 0; 345724a6905SVille Syrjälä /* 346724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 347724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 348724a6905SVille Syrjälä */ 34948a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 35048a1b8d4SPankaj Bharadiya status_mask & PIPE_B_PSR_STATUS_VLV)) 351724a6905SVille Syrjälä return 0; 35210c59c51SImre Deak 35310c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 35410c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 35510c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 35610c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 35710c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 35810c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 35910c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 36010c59c51SImre Deak 3616b12ca56SVille Syrjälä out: 36248a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 36348a1b8d4SPankaj Bharadiya enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 3646b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 3656b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 3666b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 3676b12ca56SVille Syrjälä 36810c59c51SImre Deak return enable_mask; 36910c59c51SImre Deak } 37010c59c51SImre Deak 3716b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 3726b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 373755e9019SImre Deak { 3746b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 375755e9019SImre Deak u32 enable_mask; 376755e9019SImre Deak 37748a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 3786b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 3796b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 3806b12ca56SVille Syrjälä 3816b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 38248a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 3836b12ca56SVille Syrjälä 3846b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 3856b12ca56SVille Syrjälä return; 3866b12ca56SVille Syrjälä 3876b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 3886b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 3896b12ca56SVille Syrjälä 3902939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 3912939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 392755e9019SImre Deak } 393755e9019SImre Deak 3946b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 3956b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 396755e9019SImre Deak { 3976b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 398755e9019SImre Deak u32 enable_mask; 399755e9019SImre Deak 40048a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 4016b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 4026b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 4036b12ca56SVille Syrjälä 4046b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 40548a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 4066b12ca56SVille Syrjälä 4076b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 4086b12ca56SVille Syrjälä return; 4096b12ca56SVille Syrjälä 4106b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 4116b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 4126b12ca56SVille Syrjälä 4132939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 4142939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 415755e9019SImre Deak } 416755e9019SImre Deak 417f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 418f3e30485SVille Syrjälä { 4197249dfcbSJani Nikula if (!dev_priv->display.opregion.asle) 420f3e30485SVille Syrjälä return false; 421f3e30485SVille Syrjälä 422f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 423f3e30485SVille Syrjälä } 424f3e30485SVille Syrjälä 425c0e09200SDave Airlie /** 426f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 42714bb2c11STvrtko Ursulin * @dev_priv: i915 device private 42801c66889SZhao Yakui */ 42991d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 43001c66889SZhao Yakui { 431f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 432f49e38ddSJani Nikula return; 433f49e38ddSJani Nikula 43413321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 43501c66889SZhao Yakui 436755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 437373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 4) 4383b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 439755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 4401ec14ad3SChris Wilson 44113321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 44201c66889SZhao Yakui } 44301c66889SZhao Yakui 444e3689190SBen Widawsky /** 44574bb98baSLucas De Marchi * ivb_parity_work - Workqueue called when a parity error interrupt 446e3689190SBen Widawsky * occurred. 447e3689190SBen Widawsky * @work: workqueue struct 448e3689190SBen Widawsky * 449e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 450e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 451e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 452e3689190SBen Widawsky */ 45374bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work) 454e3689190SBen Widawsky { 4552d1013ddSJani Nikula struct drm_i915_private *dev_priv = 456cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 4572cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 458e3689190SBen Widawsky u32 error_status, row, bank, subbank; 45935a85ac6SBen Widawsky char *parity_event[6]; 460a9c287c9SJani Nikula u32 misccpctl; 461a9c287c9SJani Nikula u8 slice = 0; 462e3689190SBen Widawsky 463e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 464e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 465e3689190SBen Widawsky * any time we access those registers. 466e3689190SBen Widawsky */ 46791c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 468e3689190SBen Widawsky 46935a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 47048a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice)) 47135a85ac6SBen Widawsky goto out; 47235a85ac6SBen Widawsky 473f7435467SAndrzej Hajda misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL, 474f7435467SAndrzej Hajda GEN7_DOP_CLOCK_GATE_ENABLE, 0); 4752939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL); 476e3689190SBen Widawsky 47735a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 478f0f59a00SVille Syrjälä i915_reg_t reg; 47935a85ac6SBen Widawsky 48035a85ac6SBen Widawsky slice--; 48148a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 48248a1b8d4SPankaj Bharadiya slice >= NUM_L3_SLICES(dev_priv))) 48335a85ac6SBen Widawsky break; 48435a85ac6SBen Widawsky 48535a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 48635a85ac6SBen Widawsky 4876fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 48835a85ac6SBen Widawsky 4892939eb06SJani Nikula error_status = intel_uncore_read(&dev_priv->uncore, reg); 490e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 491e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 492e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 493e3689190SBen Widawsky 4942939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 4952939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 496e3689190SBen Widawsky 497cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 498e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 499e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 500e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 50135a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 50235a85ac6SBen Widawsky parity_event[5] = NULL; 503e3689190SBen Widawsky 50491c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 505e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 506e3689190SBen Widawsky 507a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, 508a10234fdSTvrtko Ursulin "Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 50935a85ac6SBen Widawsky slice, row, bank, subbank); 510e3689190SBen Widawsky 51135a85ac6SBen Widawsky kfree(parity_event[4]); 512e3689190SBen Widawsky kfree(parity_event[3]); 513e3689190SBen Widawsky kfree(parity_event[2]); 514e3689190SBen Widawsky kfree(parity_event[1]); 515e3689190SBen Widawsky } 516e3689190SBen Widawsky 5172939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl); 51835a85ac6SBen Widawsky 51935a85ac6SBen Widawsky out: 52048a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice); 52103d2c54dSMatt Roper spin_lock_irq(gt->irq_lock); 522cf1c97dcSAndi Shyti gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv)); 52303d2c54dSMatt Roper spin_unlock_irq(gt->irq_lock); 52435a85ac6SBen Widawsky 52591c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 52635a85ac6SBen Widawsky } 52735a85ac6SBen Widawsky 5288bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 52991d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 53091d14251STvrtko Ursulin enum pipe pipe, 531a9c287c9SJani Nikula u32 crc0, u32 crc1, 532a9c287c9SJani Nikula u32 crc2, u32 crc3, 533a9c287c9SJani Nikula u32 crc4) 5348bf1e9f1SShuang He { 5357794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 53600535527SJani Nikula struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc; 5375cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 5385cee6c45SVille Syrjälä 5395cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 540b2c88f5bSDamien Lespiau 541d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 5428c6b709dSTomeu Vizoso /* 5438c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 5448c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 5458c6b709dSTomeu Vizoso * out the buggy result. 5468c6b709dSTomeu Vizoso * 547163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 5488c6b709dSTomeu Vizoso * don't trust that one either. 5498c6b709dSTomeu Vizoso */ 550033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 551373abf1aSMatt Roper (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 5528c6b709dSTomeu Vizoso pipe_crc->skipped++; 5538c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 5548c6b709dSTomeu Vizoso return; 5558c6b709dSTomeu Vizoso } 5568c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 5576cc42152SMaarten Lankhorst 558246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 559ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 560246ee524STomeu Vizoso crcs); 5618c6b709dSTomeu Vizoso } 562277de95eSDaniel Vetter #else 563277de95eSDaniel Vetter static inline void 56491d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 56591d14251STvrtko Ursulin enum pipe pipe, 566a9c287c9SJani Nikula u32 crc0, u32 crc1, 567a9c287c9SJani Nikula u32 crc2, u32 crc3, 568a9c287c9SJani Nikula u32 crc4) {} 569277de95eSDaniel Vetter #endif 570eba94eb9SDaniel Vetter 5711288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915, 5721288f9b0SKarthik B S enum pipe pipe) 5731288f9b0SKarthik B S { 5747794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe); 5751288f9b0SKarthik B S struct drm_crtc_state *crtc_state = crtc->base.state; 5761288f9b0SKarthik B S struct drm_pending_vblank_event *e = crtc_state->event; 5771288f9b0SKarthik B S struct drm_device *dev = &i915->drm; 5781288f9b0SKarthik B S unsigned long irqflags; 5791288f9b0SKarthik B S 5801288f9b0SKarthik B S spin_lock_irqsave(&dev->event_lock, irqflags); 5811288f9b0SKarthik B S 5821288f9b0SKarthik B S crtc_state->event = NULL; 5831288f9b0SKarthik B S 5841288f9b0SKarthik B S drm_crtc_send_vblank_event(&crtc->base, e); 5851288f9b0SKarthik B S 5861288f9b0SKarthik B S spin_unlock_irqrestore(&dev->event_lock, irqflags); 5871288f9b0SKarthik B S } 588277de95eSDaniel Vetter 58991d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 59091d14251STvrtko Ursulin enum pipe pipe) 5915a69b89fSDaniel Vetter { 59291d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 5932939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 5945a69b89fSDaniel Vetter 0, 0, 0, 0); 5955a69b89fSDaniel Vetter } 5965a69b89fSDaniel Vetter 59791d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 59891d14251STvrtko Ursulin enum pipe pipe) 599eba94eb9SDaniel Vetter { 60091d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 6012939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 6022939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)), 6032939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)), 6042939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)), 6052939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe))); 606eba94eb9SDaniel Vetter } 6075b3a856bSDaniel Vetter 60891d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 60991d14251STvrtko Ursulin enum pipe pipe) 6105b3a856bSDaniel Vetter { 611a9c287c9SJani Nikula u32 res1, res2; 6120b5c5ed0SDaniel Vetter 613373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 3) 6142939eb06SJani Nikula res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe)); 6150b5c5ed0SDaniel Vetter else 6160b5c5ed0SDaniel Vetter res1 = 0; 6170b5c5ed0SDaniel Vetter 618373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) 6192939eb06SJani Nikula res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe)); 6200b5c5ed0SDaniel Vetter else 6210b5c5ed0SDaniel Vetter res2 = 0; 6225b3a856bSDaniel Vetter 62391d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 6242939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)), 6252939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)), 6262939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)), 6270b5c5ed0SDaniel Vetter res1, res2); 6285b3a856bSDaniel Vetter } 6298bf1e9f1SShuang He 63044d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 63144d9241eSVille Syrjälä { 63244d9241eSVille Syrjälä enum pipe pipe; 63344d9241eSVille Syrjälä 63444d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 6352939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe), 63644d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 63744d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 63844d9241eSVille Syrjälä 63944d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 64044d9241eSVille Syrjälä } 64144d9241eSVille Syrjälä } 64244d9241eSVille Syrjälä 643eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 64491d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 6457e231dbeSJesse Barnes { 646d048a268SVille Syrjälä enum pipe pipe; 6477e231dbeSJesse Barnes 64858ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 6491ca993d2SVille Syrjälä 6501ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 6511ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 6521ca993d2SVille Syrjälä return; 6531ca993d2SVille Syrjälä } 6541ca993d2SVille Syrjälä 655055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 656f0f59a00SVille Syrjälä i915_reg_t reg; 6576b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 65891d181ddSImre Deak 659bbb5eebfSDaniel Vetter /* 660bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 661bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 662bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 663bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 664bbb5eebfSDaniel Vetter * handle. 665bbb5eebfSDaniel Vetter */ 6660f239f4cSDaniel Vetter 6670f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 6686b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 669bbb5eebfSDaniel Vetter 670bbb5eebfSDaniel Vetter switch (pipe) { 671d048a268SVille Syrjälä default: 672bbb5eebfSDaniel Vetter case PIPE_A: 673bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 674bbb5eebfSDaniel Vetter break; 675bbb5eebfSDaniel Vetter case PIPE_B: 676bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 677bbb5eebfSDaniel Vetter break; 6783278f67fSVille Syrjälä case PIPE_C: 6793278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 6803278f67fSVille Syrjälä break; 681bbb5eebfSDaniel Vetter } 682bbb5eebfSDaniel Vetter if (iir & iir_bit) 6836b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 684bbb5eebfSDaniel Vetter 6856b12ca56SVille Syrjälä if (!status_mask) 68691d181ddSImre Deak continue; 68791d181ddSImre Deak 68891d181ddSImre Deak reg = PIPESTAT(pipe); 6892939eb06SJani Nikula pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; 6906b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 6917e231dbeSJesse Barnes 6927e231dbeSJesse Barnes /* 6937e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 694132c27c9SVille Syrjälä * 695132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 696132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 697132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 698132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 699132c27c9SVille Syrjälä * an interrupt is still pending. 7007e231dbeSJesse Barnes */ 701132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 7022939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]); 7032939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask); 704132c27c9SVille Syrjälä } 7057e231dbeSJesse Barnes } 70658ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 7072ecb8ca4SVille Syrjälä } 7082ecb8ca4SVille Syrjälä 709eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 710eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 711eb64343cSVille Syrjälä { 712eb64343cSVille Syrjälä enum pipe pipe; 713eb64343cSVille Syrjälä 714eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 715eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 716aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 717eb64343cSVille Syrjälä 718eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 719eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 720eb64343cSVille Syrjälä 721eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 722eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 723eb64343cSVille Syrjälä } 724eb64343cSVille Syrjälä } 725eb64343cSVille Syrjälä 726eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 727eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 728eb64343cSVille Syrjälä { 729eb64343cSVille Syrjälä bool blc_event = false; 730eb64343cSVille Syrjälä enum pipe pipe; 731eb64343cSVille Syrjälä 732eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 733eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 734aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 735eb64343cSVille Syrjälä 736eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 737eb64343cSVille Syrjälä blc_event = true; 738eb64343cSVille Syrjälä 739eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 740eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 741eb64343cSVille Syrjälä 742eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 743eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 744eb64343cSVille Syrjälä } 745eb64343cSVille Syrjälä 746eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 747eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 748eb64343cSVille Syrjälä } 749eb64343cSVille Syrjälä 750eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 751eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 752eb64343cSVille Syrjälä { 753eb64343cSVille Syrjälä bool blc_event = false; 754eb64343cSVille Syrjälä enum pipe pipe; 755eb64343cSVille Syrjälä 756eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 757eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 758aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 759eb64343cSVille Syrjälä 760eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 761eb64343cSVille Syrjälä blc_event = true; 762eb64343cSVille Syrjälä 763eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 764eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 765eb64343cSVille Syrjälä 766eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 767eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 768eb64343cSVille Syrjälä } 769eb64343cSVille Syrjälä 770eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 771eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 772eb64343cSVille Syrjälä 773eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 774685282a3SJani Nikula intel_gmbus_irq_handler(dev_priv); 775eb64343cSVille Syrjälä } 776eb64343cSVille Syrjälä 77791d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 7782ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 7792ecb8ca4SVille Syrjälä { 7802ecb8ca4SVille Syrjälä enum pipe pipe; 7817e231dbeSJesse Barnes 782055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 783fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 784aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 7854356d586SDaniel Vetter 7866ede6b06SVille Syrjälä if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) 7876ede6b06SVille Syrjälä flip_done_handler(dev_priv, pipe); 7886ede6b06SVille Syrjälä 7894356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 79091d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 7912d9d2b0bSVille Syrjälä 7921f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 7931f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 79431acc7f5SJesse Barnes } 79531acc7f5SJesse Barnes 796c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 797685282a3SJani Nikula intel_gmbus_irq_handler(dev_priv); 798c1874ed7SImre Deak } 799c1874ed7SImre Deak 800c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 801c1874ed7SImre Deak { 802b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 803c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 804c1874ed7SImre Deak 8052dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 8062dd2a883SImre Deak return IRQ_NONE; 8072dd2a883SImre Deak 8081f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 8099102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 8101f814dacSImre Deak 8111e1cace9SVille Syrjälä do { 8126e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 8132ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 8141ae3c34cSVille Syrjälä u32 hotplug_status = 0; 815a5e485a9SVille Syrjälä u32 ier = 0; 8163ff60f89SOscar Mateo 8172939eb06SJani Nikula gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR); 8182939eb06SJani Nikula pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR); 8192939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 820c1874ed7SImre Deak 821c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 8221e1cace9SVille Syrjälä break; 823c1874ed7SImre Deak 824c1874ed7SImre Deak ret = IRQ_HANDLED; 825c1874ed7SImre Deak 826a5e485a9SVille Syrjälä /* 827a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 828a5e485a9SVille Syrjälä * 829a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 830a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 831a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 832a5e485a9SVille Syrjälä * 833a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 834a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 835a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 836a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 837a5e485a9SVille Syrjälä * bits this time around. 838a5e485a9SVille Syrjälä */ 8392939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 8408cee664dSAndrzej Hajda ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); 8414a0a0202SVille Syrjälä 8424a0a0202SVille Syrjälä if (gt_iir) 8432939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir); 8444a0a0202SVille Syrjälä if (pm_iir) 8452939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir); 8464a0a0202SVille Syrjälä 8477ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 8481ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 8497ce4d1f2SVille Syrjälä 8503ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 8513ff60f89SOscar Mateo * signalled in iir */ 852eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 8537ce4d1f2SVille Syrjälä 854eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 855eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 856eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 857eef57324SJerome Anand 8587ce4d1f2SVille Syrjälä /* 8597ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 8607ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 8617ce4d1f2SVille Syrjälä */ 8627ce4d1f2SVille Syrjälä if (iir) 8632939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 8644a0a0202SVille Syrjälä 8652939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 8662939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 8671ae3c34cSVille Syrjälä 86852894874SVille Syrjälä if (gt_iir) 8692cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(dev_priv), gt_iir); 87052894874SVille Syrjälä if (pm_iir) 8712cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir); 87252894874SVille Syrjälä 8731ae3c34cSVille Syrjälä if (hotplug_status) 87491d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 8752ecb8ca4SVille Syrjälä 87691d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 8771e1cace9SVille Syrjälä } while (0); 8787e231dbeSJesse Barnes 8799c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 8809c6508b9SThomas Gleixner 8819102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 8821f814dacSImre Deak 8837e231dbeSJesse Barnes return ret; 8847e231dbeSJesse Barnes } 8857e231dbeSJesse Barnes 88643f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 88743f328d7SVille Syrjälä { 888b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 88943f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 89043f328d7SVille Syrjälä 8912dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 8922dd2a883SImre Deak return IRQ_NONE; 8932dd2a883SImre Deak 8941f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 8959102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 8961f814dacSImre Deak 897579de73bSChris Wilson do { 8986e814800SVille Syrjälä u32 master_ctl, iir; 8992ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 9001ae3c34cSVille Syrjälä u32 hotplug_status = 0; 901a5e485a9SVille Syrjälä u32 ier = 0; 902a5e485a9SVille Syrjälä 9032939eb06SJani Nikula master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 9042939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 9053278f67fSVille Syrjälä 9063278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 9078e5fd599SVille Syrjälä break; 90843f328d7SVille Syrjälä 90927b6c122SOscar Mateo ret = IRQ_HANDLED; 91027b6c122SOscar Mateo 911a5e485a9SVille Syrjälä /* 912a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 913a5e485a9SVille Syrjälä * 914a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 915a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 916a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 917a5e485a9SVille Syrjälä * 918a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 919a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 920a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 921a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 922a5e485a9SVille Syrjälä * bits this time around. 923a5e485a9SVille Syrjälä */ 9242939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); 9258cee664dSAndrzej Hajda ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); 92643f328d7SVille Syrjälä 9272cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 92827b6c122SOscar Mateo 92927b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 9301ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 93143f328d7SVille Syrjälä 93227b6c122SOscar Mateo /* Call regardless, as some status bits might not be 93327b6c122SOscar Mateo * signalled in iir */ 934eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 93543f328d7SVille Syrjälä 936eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 937eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 938eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 939eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 940eef57324SJerome Anand 9417ce4d1f2SVille Syrjälä /* 9427ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 9437ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 9447ce4d1f2SVille Syrjälä */ 9457ce4d1f2SVille Syrjälä if (iir) 9462939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 9477ce4d1f2SVille Syrjälä 9482939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 9492939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 9501ae3c34cSVille Syrjälä 9511ae3c34cSVille Syrjälä if (hotplug_status) 95291d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 9532ecb8ca4SVille Syrjälä 95491d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 955579de73bSChris Wilson } while (0); 9563278f67fSVille Syrjälä 9579c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 9589c6508b9SThomas Gleixner 9599102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 9601f814dacSImre Deak 96143f328d7SVille Syrjälä return ret; 96243f328d7SVille Syrjälä } 96343f328d7SVille Syrjälä 96491d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 96540e56410SVille Syrjälä { 966d048a268SVille Syrjälä enum pipe pipe; 96740e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 96840e56410SVille Syrjälä 9690398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 97040e56410SVille Syrjälä 971cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 972cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 973776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 97400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n", 975cfc33bf7SVille Syrjälä port_name(port)); 976cfc33bf7SVille Syrjälä } 977776ad806SJesse Barnes 978ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 979685282a3SJani Nikula intel_dp_aux_irq_handler(dev_priv); 980ce99c256SDaniel Vetter 981776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 982685282a3SJani Nikula intel_gmbus_irq_handler(dev_priv); 983776ad806SJesse Barnes 984776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 98500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n"); 986776ad806SJesse Barnes 987776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 98800376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n"); 989776ad806SJesse Barnes 990776ad806SJesse Barnes if (pch_iir & SDE_POISON) 99100376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 992776ad806SJesse Barnes 993b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK) { 994055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 99500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 9969db4a9c7SJesse Barnes pipe_name(pipe), 9972939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 998b8b65ccdSAnshuman Gupta } 999776ad806SJesse Barnes 1000776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 100100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n"); 1002776ad806SJesse Barnes 1003776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 100400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 100500376ccfSWambui Karuga "PCH transcoder CRC error interrupt\n"); 1006776ad806SJesse Barnes 1007776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 1008a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 10098664281bSPaulo Zanoni 10108664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 1011a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 10128664281bSPaulo Zanoni } 10138664281bSPaulo Zanoni 101491d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 10158664281bSPaulo Zanoni { 10162939eb06SJani Nikula u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT); 10175a69b89fSDaniel Vetter enum pipe pipe; 10188664281bSPaulo Zanoni 1019de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 102000376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1021de032bf4SPaulo Zanoni 1022055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 10231f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 10241f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 10258664281bSPaulo Zanoni 10265a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 102791d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 102891d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 10295a69b89fSDaniel Vetter else 103091d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 10315a69b89fSDaniel Vetter } 10325a69b89fSDaniel Vetter } 10338bf1e9f1SShuang He 10342939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int); 10358664281bSPaulo Zanoni } 10368664281bSPaulo Zanoni 103791d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 10388664281bSPaulo Zanoni { 10392939eb06SJani Nikula u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT); 104045c1cd87SMika Kahola enum pipe pipe; 10418664281bSPaulo Zanoni 1042de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 104300376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1044de032bf4SPaulo Zanoni 104545c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 104645c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 104745c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 10488664281bSPaulo Zanoni 10492939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int); 1050776ad806SJesse Barnes } 1051776ad806SJesse Barnes 105291d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 105323e81d69SAdam Jackson { 1054d048a268SVille Syrjälä enum pipe pipe; 10556dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 1056aaf5ec2eSSonika Jindal 10570398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 105891d131d2SDaniel Vetter 1059cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 1060cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 106123e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 106200376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n", 1063cfc33bf7SVille Syrjälä port_name(port)); 1064cfc33bf7SVille Syrjälä } 106523e81d69SAdam Jackson 106623e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 1067685282a3SJani Nikula intel_dp_aux_irq_handler(dev_priv); 106823e81d69SAdam Jackson 106923e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 1070685282a3SJani Nikula intel_gmbus_irq_handler(dev_priv); 107123e81d69SAdam Jackson 107223e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 107300376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n"); 107423e81d69SAdam Jackson 107523e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 107600376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n"); 107723e81d69SAdam Jackson 1078b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK_CPT) { 1079055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 108000376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 108123e81d69SAdam Jackson pipe_name(pipe), 10822939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1083b8b65ccdSAnshuman Gupta } 10848664281bSPaulo Zanoni 10858664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 108691d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 108723e81d69SAdam Jackson } 108823e81d69SAdam Jackson 108991d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 109091d14251STvrtko Ursulin u32 de_iir) 109140e56410SVille Syrjälä { 109240e56410SVille Syrjälä enum pipe pipe; 109340e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 109440e56410SVille Syrjälä 109540e56410SVille Syrjälä if (hotplug_trigger) 10960398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 109740e56410SVille Syrjälä 1098c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 1099685282a3SJani Nikula intel_dp_aux_irq_handler(dev_priv); 1100c008bc6eSPaulo Zanoni 1101c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 110291d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 1103c008bc6eSPaulo Zanoni 1104c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 110500376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1106c008bc6eSPaulo Zanoni 1107055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1108fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 1109aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1110c008bc6eSPaulo Zanoni 11114bb18054SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE(pipe)) 11124bb18054SVille Syrjälä flip_done_handler(dev_priv, pipe); 11134bb18054SVille Syrjälä 111440da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 11151f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1116c008bc6eSPaulo Zanoni 111740da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 111891d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1119c008bc6eSPaulo Zanoni } 1120c008bc6eSPaulo Zanoni 1121c008bc6eSPaulo Zanoni /* check event from PCH */ 1122c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 11232939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 1124c008bc6eSPaulo Zanoni 112591d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 112691d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 1127c008bc6eSPaulo Zanoni else 112891d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 1129c008bc6eSPaulo Zanoni 1130c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 11312939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 1132c008bc6eSPaulo Zanoni } 1133c008bc6eSPaulo Zanoni 113493e7e61eSLucas De Marchi if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT) 11352cbc876dSMichał Winiarski gen5_rps_irq_handler(&to_gt(dev_priv)->rps); 1136c008bc6eSPaulo Zanoni } 1137c008bc6eSPaulo Zanoni 113891d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 113991d14251STvrtko Ursulin u32 de_iir) 11409719fb98SPaulo Zanoni { 114107d27e20SDamien Lespiau enum pipe pipe; 114223bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 114323bb4cb5SVille Syrjälä 114440e56410SVille Syrjälä if (hotplug_trigger) 11450398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 11469719fb98SPaulo Zanoni 11479719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 114891d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 11499719fb98SPaulo Zanoni 11509719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 1151685282a3SJani Nikula intel_dp_aux_irq_handler(dev_priv); 11529719fb98SPaulo Zanoni 11539719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 115491d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 11559719fb98SPaulo Zanoni 1156055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 115733ef04faSVille Syrjälä if (de_iir & DE_PIPE_VBLANK_IVB(pipe)) 1158aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 11592a636e24SVille Syrjälä 11602a636e24SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) 11612a636e24SVille Syrjälä flip_done_handler(dev_priv, pipe); 11629719fb98SPaulo Zanoni } 11639719fb98SPaulo Zanoni 11649719fb98SPaulo Zanoni /* check event from PCH */ 116591d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 11662939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 11679719fb98SPaulo Zanoni 116891d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 11699719fb98SPaulo Zanoni 11709719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 11712939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 11729719fb98SPaulo Zanoni } 11739719fb98SPaulo Zanoni } 11749719fb98SPaulo Zanoni 117572c90f62SOscar Mateo /* 117672c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 117772c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 117872c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 117972c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 118072c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 118172c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 118272c90f62SOscar Mateo */ 11839eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg) 1184b1f14ad0SJesse Barnes { 1185c48a798aSChris Wilson struct drm_i915_private *i915 = arg; 1186c48a798aSChris Wilson void __iomem * const regs = i915->uncore.regs; 1187f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 11880e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 1189b1f14ad0SJesse Barnes 1190c48a798aSChris Wilson if (unlikely(!intel_irqs_enabled(i915))) 11912dd2a883SImre Deak return IRQ_NONE; 11922dd2a883SImre Deak 11931f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1194c48a798aSChris Wilson disable_rpm_wakeref_asserts(&i915->runtime_pm); 11951f814dacSImre Deak 1196b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 1197c48a798aSChris Wilson de_ier = raw_reg_read(regs, DEIER); 1198c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 11990e43406bSChris Wilson 120044498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 120144498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 120244498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 120344498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 120444498aeaSPaulo Zanoni * due to its back queue). */ 1205c48a798aSChris Wilson if (!HAS_PCH_NOP(i915)) { 1206c48a798aSChris Wilson sde_ier = raw_reg_read(regs, SDEIER); 1207c48a798aSChris Wilson raw_reg_write(regs, SDEIER, 0); 1208ab5c608bSBen Widawsky } 120944498aeaSPaulo Zanoni 121072c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 121172c90f62SOscar Mateo 1212c48a798aSChris Wilson gt_iir = raw_reg_read(regs, GTIIR); 12130e43406bSChris Wilson if (gt_iir) { 1214c48a798aSChris Wilson raw_reg_write(regs, GTIIR, gt_iir); 1215651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) 12162cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(i915), gt_iir); 1217d8fc8a47SPaulo Zanoni else 12182cbc876dSMichał Winiarski gen5_gt_irq_handler(to_gt(i915), gt_iir); 1219c48a798aSChris Wilson ret = IRQ_HANDLED; 12200e43406bSChris Wilson } 1221b1f14ad0SJesse Barnes 1222c48a798aSChris Wilson de_iir = raw_reg_read(regs, DEIIR); 12230e43406bSChris Wilson if (de_iir) { 1224c48a798aSChris Wilson raw_reg_write(regs, DEIIR, de_iir); 1225373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 7) 1226c48a798aSChris Wilson ivb_display_irq_handler(i915, de_iir); 1227f1af8fc1SPaulo Zanoni else 1228c48a798aSChris Wilson ilk_display_irq_handler(i915, de_iir); 12290e43406bSChris Wilson ret = IRQ_HANDLED; 1230c48a798aSChris Wilson } 1231c48a798aSChris Wilson 1232651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) { 1233c48a798aSChris Wilson u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR); 1234c48a798aSChris Wilson if (pm_iir) { 1235c48a798aSChris Wilson raw_reg_write(regs, GEN6_PMIIR, pm_iir); 12362cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(i915)->rps, pm_iir); 1237c48a798aSChris Wilson ret = IRQ_HANDLED; 12380e43406bSChris Wilson } 1239f1af8fc1SPaulo Zanoni } 1240b1f14ad0SJesse Barnes 1241c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier); 1242c48a798aSChris Wilson if (sde_ier) 1243c48a798aSChris Wilson raw_reg_write(regs, SDEIER, sde_ier); 1244b1f14ad0SJesse Barnes 12459c6508b9SThomas Gleixner pmu_irq_stats(i915, ret); 12469c6508b9SThomas Gleixner 12471f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1248c48a798aSChris Wilson enable_rpm_wakeref_asserts(&i915->runtime_pm); 12491f814dacSImre Deak 1250b1f14ad0SJesse Barnes return ret; 1251b1f14ad0SJesse Barnes } 1252b1f14ad0SJesse Barnes 12539d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 12549d17210fSLucas De Marchi { 125555523360SLucas De Marchi u32 mask; 12569d17210fSLucas De Marchi 1257c0f3faafSGustavo Sousa if (DISPLAY_VER(dev_priv) >= 14) 1258c0f3faafSGustavo Sousa return TGL_DE_PORT_AUX_DDIA | 1259c0f3faafSGustavo Sousa TGL_DE_PORT_AUX_DDIB; 1260c0f3faafSGustavo Sousa else if (DISPLAY_VER(dev_priv) >= 13) 126120fe778fSMatt Roper return TGL_DE_PORT_AUX_DDIA | 126220fe778fSMatt Roper TGL_DE_PORT_AUX_DDIB | 126320fe778fSMatt Roper TGL_DE_PORT_AUX_DDIC | 126420fe778fSMatt Roper XELPD_DE_PORT_AUX_DDID | 126520fe778fSMatt Roper XELPD_DE_PORT_AUX_DDIE | 126620fe778fSMatt Roper TGL_DE_PORT_AUX_USBC1 | 126720fe778fSMatt Roper TGL_DE_PORT_AUX_USBC2 | 126820fe778fSMatt Roper TGL_DE_PORT_AUX_USBC3 | 126920fe778fSMatt Roper TGL_DE_PORT_AUX_USBC4; 127020fe778fSMatt Roper else if (DISPLAY_VER(dev_priv) >= 12) 127155523360SLucas De Marchi return TGL_DE_PORT_AUX_DDIA | 127255523360SLucas De Marchi TGL_DE_PORT_AUX_DDIB | 1273e5df52dcSMatt Roper TGL_DE_PORT_AUX_DDIC | 1274e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC1 | 1275e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC2 | 1276e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC3 | 1277e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC4 | 1278e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC5 | 1279e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC6; 1280e5df52dcSMatt Roper 128155523360SLucas De Marchi 128255523360SLucas De Marchi mask = GEN8_AUX_CHANNEL_A; 1283373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 9) 12849d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 12859d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 12869d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 12879d17210fSLucas De Marchi 1288938a8a9aSLucas De Marchi if (DISPLAY_VER(dev_priv) == 11) { 1289938a8a9aSLucas De Marchi mask |= ICL_AUX_CHANNEL_F; 129055523360SLucas De Marchi mask |= ICL_AUX_CHANNEL_E; 1291938a8a9aSLucas De Marchi } 12929d17210fSLucas De Marchi 12939d17210fSLucas De Marchi return mask; 12949d17210fSLucas De Marchi } 12959d17210fSLucas De Marchi 12965270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) 12975270130dSVille Syrjälä { 12981649a4ccSMatt Roper if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv)) 129999e2d8bcSMatt Roper return RKL_DE_PIPE_IRQ_FAULT_ERRORS; 1300373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 11) 1301d506a65dSMatt Roper return GEN11_DE_PIPE_IRQ_FAULT_ERRORS; 1302373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 9) 13035270130dSVille Syrjälä return GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 13045270130dSVille Syrjälä else 13055270130dSVille Syrjälä return GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 13065270130dSVille Syrjälä } 13075270130dSVille Syrjälä 130846c63d24SJosé Roberto de Souza static void 130946c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 1310abd58f01SBen Widawsky { 1311e04f7eceSVille Syrjälä bool found = false; 1312e04f7eceSVille Syrjälä 1313e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 131491d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 1315e04f7eceSVille Syrjälä found = true; 1316e04f7eceSVille Syrjälä } 1317e04f7eceSVille Syrjälä 1318e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 1319b64d6c51SGwan-gyeong Mun struct intel_encoder *encoder; 13208241cfbeSJosé Roberto de Souza u32 psr_iir; 13218241cfbeSJosé Roberto de Souza i915_reg_t iir_reg; 13228241cfbeSJosé Roberto de Souza 1323a22af61dSJosé Roberto de Souza for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) { 1324b64d6c51SGwan-gyeong Mun struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1325b64d6c51SGwan-gyeong Mun 1326373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 1327b64d6c51SGwan-gyeong Mun iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder); 13288241cfbeSJosé Roberto de Souza else 13298241cfbeSJosé Roberto de Souza iir_reg = EDP_PSR_IIR; 13308241cfbeSJosé Roberto de Souza 13318cee664dSAndrzej Hajda psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0); 13328241cfbeSJosé Roberto de Souza 13338241cfbeSJosé Roberto de Souza if (psr_iir) 13348241cfbeSJosé Roberto de Souza found = true; 133554fd3149SDhinakaran Pandiyan 1336b64d6c51SGwan-gyeong Mun intel_psr_irq_handler(intel_dp, psr_iir); 1337b64d6c51SGwan-gyeong Mun 1338b64d6c51SGwan-gyeong Mun /* prior GEN12 only have one EDP PSR */ 1339373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 12) 1340b64d6c51SGwan-gyeong Mun break; 1341b64d6c51SGwan-gyeong Mun } 1342e04f7eceSVille Syrjälä } 1343e04f7eceSVille Syrjälä 1344e04f7eceSVille Syrjälä if (!found) 134500376ccfSWambui Karuga drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n"); 1346abd58f01SBen Widawsky } 134746c63d24SJosé Roberto de Souza 134800acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, 134900acb329SVandita Kulkarni u32 te_trigger) 135000acb329SVandita Kulkarni { 135100acb329SVandita Kulkarni enum pipe pipe = INVALID_PIPE; 135200acb329SVandita Kulkarni enum transcoder dsi_trans; 135300acb329SVandita Kulkarni enum port port; 135400acb329SVandita Kulkarni u32 val, tmp; 135500acb329SVandita Kulkarni 135600acb329SVandita Kulkarni /* 135700acb329SVandita Kulkarni * Incase of dual link, TE comes from DSI_1 135800acb329SVandita Kulkarni * this is to check if dual link is enabled 135900acb329SVandita Kulkarni */ 13602939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0)); 136100acb329SVandita Kulkarni val &= PORT_SYNC_MODE_ENABLE; 136200acb329SVandita Kulkarni 136300acb329SVandita Kulkarni /* 136400acb329SVandita Kulkarni * if dual link is enabled, then read DSI_0 136500acb329SVandita Kulkarni * transcoder registers 136600acb329SVandita Kulkarni */ 136700acb329SVandita Kulkarni port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ? 136800acb329SVandita Kulkarni PORT_A : PORT_B; 136900acb329SVandita Kulkarni dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; 137000acb329SVandita Kulkarni 137100acb329SVandita Kulkarni /* Check if DSI configured in command mode */ 13722939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans)); 137300acb329SVandita Kulkarni val = val & OP_MODE_MASK; 137400acb329SVandita Kulkarni 137500acb329SVandita Kulkarni if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { 137600acb329SVandita Kulkarni drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n"); 137700acb329SVandita Kulkarni return; 137800acb329SVandita Kulkarni } 137900acb329SVandita Kulkarni 138000acb329SVandita Kulkarni /* Get PIPE for handling VBLANK event */ 13812939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans)); 138200acb329SVandita Kulkarni switch (val & TRANS_DDI_EDP_INPUT_MASK) { 138300acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_A_ON: 138400acb329SVandita Kulkarni pipe = PIPE_A; 138500acb329SVandita Kulkarni break; 138600acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_B_ONOFF: 138700acb329SVandita Kulkarni pipe = PIPE_B; 138800acb329SVandita Kulkarni break; 138900acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_C_ONOFF: 139000acb329SVandita Kulkarni pipe = PIPE_C; 139100acb329SVandita Kulkarni break; 139200acb329SVandita Kulkarni default: 139300acb329SVandita Kulkarni drm_err(&dev_priv->drm, "Invalid PIPE\n"); 139400acb329SVandita Kulkarni return; 139500acb329SVandita Kulkarni } 139600acb329SVandita Kulkarni 139700acb329SVandita Kulkarni intel_handle_vblank(dev_priv, pipe); 139800acb329SVandita Kulkarni 139900acb329SVandita Kulkarni /* clear TE in dsi IIR */ 140000acb329SVandita Kulkarni port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; 14018cee664dSAndrzej Hajda tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); 140200acb329SVandita Kulkarni } 140300acb329SVandita Kulkarni 1404cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) 1405cda195f1SVille Syrjälä { 1406373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 9) 1407cda195f1SVille Syrjälä return GEN9_PIPE_PLANE1_FLIP_DONE; 1408cda195f1SVille Syrjälä else 1409cda195f1SVille Syrjälä return GEN8_PIPE_PRIMARY_FLIP_DONE; 1410cda195f1SVille Syrjälä } 1411cda195f1SVille Syrjälä 14128bcc0840SMatt Roper u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv) 14138bcc0840SMatt Roper { 14148bcc0840SMatt Roper u32 mask = GEN8_PIPE_FIFO_UNDERRUN; 14158bcc0840SMatt Roper 14168bcc0840SMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 14178bcc0840SMatt Roper mask |= XELPD_PIPE_SOFT_UNDERRUN | 14188bcc0840SMatt Roper XELPD_PIPE_HARD_UNDERRUN; 14198bcc0840SMatt Roper 14208bcc0840SMatt Roper return mask; 14218bcc0840SMatt Roper } 14228bcc0840SMatt Roper 1423babde06dSMika Kahola static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir) 1424babde06dSMika Kahola { 1425babde06dSMika Kahola u32 pica_ier = 0; 1426babde06dSMika Kahola 1427babde06dSMika Kahola *pica_iir = 0; 1428babde06dSMika Kahola *pch_iir = intel_de_read(i915, SDEIIR); 1429babde06dSMika Kahola if (!*pch_iir) 1430babde06dSMika Kahola return; 1431babde06dSMika Kahola 1432babde06dSMika Kahola /** 1433babde06dSMika Kahola * PICA IER must be disabled/re-enabled around clearing PICA IIR and 1434babde06dSMika Kahola * SDEIIR, to avoid losing PICA IRQs and to ensure that such IRQs set 1435babde06dSMika Kahola * their flags both in the PICA and SDE IIR. 1436babde06dSMika Kahola */ 1437babde06dSMika Kahola if (*pch_iir & SDE_PICAINTERRUPT) { 1438babde06dSMika Kahola drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTP); 1439babde06dSMika Kahola 1440babde06dSMika Kahola pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0); 1441babde06dSMika Kahola *pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR); 1442babde06dSMika Kahola intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir); 1443babde06dSMika Kahola } 1444babde06dSMika Kahola 1445babde06dSMika Kahola intel_de_write(i915, SDEIIR, *pch_iir); 1446babde06dSMika Kahola 1447babde06dSMika Kahola if (pica_ier) 1448babde06dSMika Kahola intel_de_write(i915, PICAINTERRUPT_IER, pica_ier); 1449babde06dSMika Kahola } 1450babde06dSMika Kahola 145108d8f430SJani Nikula static void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 145246c63d24SJosé Roberto de Souza { 145346c63d24SJosé Roberto de Souza u32 iir; 145446c63d24SJosé Roberto de Souza enum pipe pipe; 145546c63d24SJosé Roberto de Souza 1456a844cfbeSJosé Roberto de Souza drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv)); 1457a844cfbeSJosé Roberto de Souza 145846c63d24SJosé Roberto de Souza if (master_ctl & GEN8_DE_MISC_IRQ) { 14592939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR); 146046c63d24SJosé Roberto de Souza if (iir) { 14612939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir); 146246c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(dev_priv, iir); 146346c63d24SJosé Roberto de Souza } else { 14649a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 146500376ccfSWambui Karuga "The master control interrupt lied (DE MISC)!\n"); 1466abd58f01SBen Widawsky } 146746c63d24SJosé Roberto de Souza } 1468abd58f01SBen Widawsky 1469373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 14702939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR); 1471121e758eSDhinakaran Pandiyan if (iir) { 14722939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir); 1473121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 1474121e758eSDhinakaran Pandiyan } else { 14759a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 147600376ccfSWambui Karuga "The master control interrupt lied, (DE HPD)!\n"); 1477121e758eSDhinakaran Pandiyan } 1478121e758eSDhinakaran Pandiyan } 1479121e758eSDhinakaran Pandiyan 14806d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 14812939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR); 1482e32192e1STvrtko Ursulin if (iir) { 1483d04a492dSShashank Sharma bool found = false; 1484cebd87a0SVille Syrjälä 14852939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir); 148688e04703SJesse Barnes 14879d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 1488685282a3SJani Nikula intel_dp_aux_irq_handler(dev_priv); 1489d04a492dSShashank Sharma found = true; 1490d04a492dSShashank Sharma } 1491d04a492dSShashank Sharma 149270bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { 14939a55a620SVille Syrjälä u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK; 14949a55a620SVille Syrjälä 14959a55a620SVille Syrjälä if (hotplug_trigger) { 14969a55a620SVille Syrjälä bxt_hpd_irq_handler(dev_priv, hotplug_trigger); 1497d04a492dSShashank Sharma found = true; 1498d04a492dSShashank Sharma } 1499e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 15009a55a620SVille Syrjälä u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK; 15019a55a620SVille Syrjälä 15029a55a620SVille Syrjälä if (hotplug_trigger) { 15039a55a620SVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 1504e32192e1STvrtko Ursulin found = true; 1505e32192e1STvrtko Ursulin } 1506e32192e1STvrtko Ursulin } 1507d04a492dSShashank Sharma 150870bfb307SMatt Roper if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) && 150970bfb307SMatt Roper (iir & BXT_DE_PORT_GMBUS)) { 1510685282a3SJani Nikula intel_gmbus_irq_handler(dev_priv); 15119e63743eSShashank Sharma found = true; 15129e63743eSShashank Sharma } 15139e63743eSShashank Sharma 1514373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 15159a55a620SVille Syrjälä u32 te_trigger = iir & (DSI0_TE | DSI1_TE); 15169a55a620SVille Syrjälä 15179a55a620SVille Syrjälä if (te_trigger) { 15189a55a620SVille Syrjälä gen11_dsi_te_interrupt_handler(dev_priv, te_trigger); 151900acb329SVandita Kulkarni found = true; 152000acb329SVandita Kulkarni } 152100acb329SVandita Kulkarni } 152200acb329SVandita Kulkarni 1523d04a492dSShashank Sharma if (!found) 15249a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 152500376ccfSWambui Karuga "Unexpected DE Port interrupt\n"); 15266d766f02SDaniel Vetter } 152738cc46d7SOscar Mateo else 15289a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 152900376ccfSWambui Karuga "The master control interrupt lied (DE PORT)!\n"); 15306d766f02SDaniel Vetter } 15316d766f02SDaniel Vetter 1532055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1533fd3a4024SDaniel Vetter u32 fault_errors; 1534abd58f01SBen Widawsky 1535c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 1536c42664ccSDaniel Vetter continue; 1537c42664ccSDaniel Vetter 15382939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); 1539e32192e1STvrtko Ursulin if (!iir) { 15409a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 154100376ccfSWambui Karuga "The master control interrupt lied (DE PIPE)!\n"); 1542e32192e1STvrtko Ursulin continue; 1543e32192e1STvrtko Ursulin } 1544770de83dSDamien Lespiau 15452939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir); 1546e32192e1STvrtko Ursulin 1547fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 1548aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1549abd58f01SBen Widawsky 1550cda195f1SVille Syrjälä if (iir & gen8_de_pipe_flip_done_mask(dev_priv)) 15511288f9b0SKarthik B S flip_done_handler(dev_priv, pipe); 15521288f9b0SKarthik B S 1553e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 155491d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 15550fbe7870SDaniel Vetter 15568bcc0840SMatt Roper if (iir & gen8_de_pipe_underrun_mask(dev_priv)) 1557e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 155838d83c96SDaniel Vetter 15595270130dSVille Syrjälä fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); 1560770de83dSDamien Lespiau if (fault_errors) 15619a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 156200376ccfSWambui Karuga "Fault errors on pipe %c: 0x%08x\n", 156330100f2bSDaniel Vetter pipe_name(pipe), 1564e32192e1STvrtko Ursulin fault_errors); 1565abd58f01SBen Widawsky } 1566abd58f01SBen Widawsky 156791d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 1568266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 1569babde06dSMika Kahola u32 pica_iir; 1570babde06dSMika Kahola 157192d03a80SDaniel Vetter /* 157292d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 157392d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 157492d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 157592d03a80SDaniel Vetter */ 1576babde06dSMika Kahola gen8_read_and_ack_pch_irqs(dev_priv, &iir, &pica_iir); 1577e32192e1STvrtko Ursulin if (iir) { 1578babde06dSMika Kahola if (pica_iir) 1579babde06dSMika Kahola xelpdp_pica_irq_handler(dev_priv, pica_iir); 1580babde06dSMika Kahola 158158676af6SLucas De Marchi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 158258676af6SLucas De Marchi icp_irq_handler(dev_priv, iir); 1583c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 158491d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 15856dbf30ceSVille Syrjälä else 158691d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 15872dfb0b81SJani Nikula } else { 15882dfb0b81SJani Nikula /* 15892dfb0b81SJani Nikula * Like on previous PCH there seems to be something 15902dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 15912dfb0b81SJani Nikula */ 159200376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 159300376ccfSWambui Karuga "The master control interrupt lied (SDE)!\n"); 15942dfb0b81SJani Nikula } 159592d03a80SDaniel Vetter } 1596f11a0f46STvrtko Ursulin } 1597f11a0f46STvrtko Ursulin 15984376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 15994376b9c9SMika Kuoppala { 16004376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 16014376b9c9SMika Kuoppala 16024376b9c9SMika Kuoppala /* 16034376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 16044376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 16054376b9c9SMika Kuoppala * New indications can and will light up during processing, 16064376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 16074376b9c9SMika Kuoppala */ 16084376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 16094376b9c9SMika Kuoppala } 16104376b9c9SMika Kuoppala 16114376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 16124376b9c9SMika Kuoppala { 16134376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 16144376b9c9SMika Kuoppala } 16154376b9c9SMika Kuoppala 1616f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 1617f11a0f46STvrtko Ursulin { 1618b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 161925286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 1620f11a0f46STvrtko Ursulin u32 master_ctl; 1621f11a0f46STvrtko Ursulin 1622f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 1623f11a0f46STvrtko Ursulin return IRQ_NONE; 1624f11a0f46STvrtko Ursulin 16254376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 16264376b9c9SMika Kuoppala if (!master_ctl) { 16274376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 1628f11a0f46STvrtko Ursulin return IRQ_NONE; 16294376b9c9SMika Kuoppala } 1630f11a0f46STvrtko Ursulin 16316cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 16322cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 1633f0fd96f5SChris Wilson 1634f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1635f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 16369102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 163755ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 16389102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 1639f0fd96f5SChris Wilson } 1640f11a0f46STvrtko Ursulin 16414376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 1642abd58f01SBen Widawsky 16439c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 16449c6508b9SThomas Gleixner 164555ef72f2SChris Wilson return IRQ_HANDLED; 1646abd58f01SBen Widawsky } 1647abd58f01SBen Widawsky 164851951ae7SMika Kuoppala static u32 1649ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl) 1650df0d28c1SDhinakaran Pandiyan { 1651ddcf980fSAnusha Srivatsa void __iomem * const regs = i915->uncore.regs; 16527a909383SChris Wilson u32 iir; 1653df0d28c1SDhinakaran Pandiyan 1654df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 16557a909383SChris Wilson return 0; 1656df0d28c1SDhinakaran Pandiyan 16577a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 16587a909383SChris Wilson if (likely(iir)) 16597a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 16607a909383SChris Wilson 16617a909383SChris Wilson return iir; 1662df0d28c1SDhinakaran Pandiyan } 1663df0d28c1SDhinakaran Pandiyan 1664df0d28c1SDhinakaran Pandiyan static void 1665ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir) 1666df0d28c1SDhinakaran Pandiyan { 1667df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 1668ddcf980fSAnusha Srivatsa intel_opregion_asle_intr(i915); 1669df0d28c1SDhinakaran Pandiyan } 1670df0d28c1SDhinakaran Pandiyan 167181067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 167281067b71SMika Kuoppala { 167381067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 167481067b71SMika Kuoppala 167581067b71SMika Kuoppala /* 167681067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 167781067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 167881067b71SMika Kuoppala * New indications can and will light up during processing, 167981067b71SMika Kuoppala * and will generate new interrupt after enabling master. 168081067b71SMika Kuoppala */ 168181067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 168281067b71SMika Kuoppala } 168381067b71SMika Kuoppala 168481067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 168581067b71SMika Kuoppala { 168681067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 168781067b71SMika Kuoppala } 168881067b71SMika Kuoppala 1689a3265d85SMatt Roper static void 1690a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915) 1691a3265d85SMatt Roper { 1692a3265d85SMatt Roper void __iomem * const regs = i915->uncore.regs; 1693a3265d85SMatt Roper const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 1694a3265d85SMatt Roper 1695a3265d85SMatt Roper disable_rpm_wakeref_asserts(&i915->runtime_pm); 1696a3265d85SMatt Roper /* 1697a3265d85SMatt Roper * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 1698a3265d85SMatt Roper * for the display related bits. 1699a3265d85SMatt Roper */ 1700a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); 1701a3265d85SMatt Roper gen8_de_irq_handler(i915, disp_ctl); 1702a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 1703a3265d85SMatt Roper GEN11_DISPLAY_IRQ_ENABLE); 1704a3265d85SMatt Roper 1705a3265d85SMatt Roper enable_rpm_wakeref_asserts(&i915->runtime_pm); 1706a3265d85SMatt Roper } 1707a3265d85SMatt Roper 170822e26af7SPaulo Zanoni static irqreturn_t gen11_irq_handler(int irq, void *arg) 170951951ae7SMika Kuoppala { 171022e26af7SPaulo Zanoni struct drm_i915_private *i915 = arg; 171125286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 17122cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 171351951ae7SMika Kuoppala u32 master_ctl; 1714df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 171551951ae7SMika Kuoppala 171651951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 171751951ae7SMika Kuoppala return IRQ_NONE; 171851951ae7SMika Kuoppala 171922e26af7SPaulo Zanoni master_ctl = gen11_master_intr_disable(regs); 172081067b71SMika Kuoppala if (!master_ctl) { 172122e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 172251951ae7SMika Kuoppala return IRQ_NONE; 172381067b71SMika Kuoppala } 172451951ae7SMika Kuoppala 17256cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 17269b77011eSTvrtko Ursulin gen11_gt_irq_handler(gt, master_ctl); 172751951ae7SMika Kuoppala 172851951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1729a3265d85SMatt Roper if (master_ctl & GEN11_DISPLAY_IRQ) 1730a3265d85SMatt Roper gen11_display_irq_handler(i915); 173151951ae7SMika Kuoppala 1732ddcf980fSAnusha Srivatsa gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 1733df0d28c1SDhinakaran Pandiyan 173422e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 173551951ae7SMika Kuoppala 1736ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(i915, gu_misc_iir); 1737df0d28c1SDhinakaran Pandiyan 17389c6508b9SThomas Gleixner pmu_irq_stats(i915, IRQ_HANDLED); 17399c6508b9SThomas Gleixner 174051951ae7SMika Kuoppala return IRQ_HANDLED; 174151951ae7SMika Kuoppala } 174251951ae7SMika Kuoppala 174322e26af7SPaulo Zanoni static inline u32 dg1_master_intr_disable(void __iomem * const regs) 174497b492f5SLucas De Marchi { 174597b492f5SLucas De Marchi u32 val; 174697b492f5SLucas De Marchi 174797b492f5SLucas De Marchi /* First disable interrupts */ 174822e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0); 174997b492f5SLucas De Marchi 175097b492f5SLucas De Marchi /* Get the indication levels and ack the master unit */ 175122e26af7SPaulo Zanoni val = raw_reg_read(regs, DG1_MSTR_TILE_INTR); 175297b492f5SLucas De Marchi if (unlikely(!val)) 175397b492f5SLucas De Marchi return 0; 175497b492f5SLucas De Marchi 175522e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, val); 175697b492f5SLucas De Marchi 175797b492f5SLucas De Marchi return val; 175897b492f5SLucas De Marchi } 175997b492f5SLucas De Marchi 176097b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs) 176197b492f5SLucas De Marchi { 176222e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ); 176397b492f5SLucas De Marchi } 176497b492f5SLucas De Marchi 176597b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg) 176697b492f5SLucas De Marchi { 176722e26af7SPaulo Zanoni struct drm_i915_private * const i915 = arg; 17682cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 1769fd4d7904SPaulo Zanoni void __iomem * const regs = gt->uncore->regs; 177022e26af7SPaulo Zanoni u32 master_tile_ctl, master_ctl; 177122e26af7SPaulo Zanoni u32 gu_misc_iir; 177222e26af7SPaulo Zanoni 177322e26af7SPaulo Zanoni if (!intel_irqs_enabled(i915)) 177422e26af7SPaulo Zanoni return IRQ_NONE; 177522e26af7SPaulo Zanoni 177622e26af7SPaulo Zanoni master_tile_ctl = dg1_master_intr_disable(regs); 177722e26af7SPaulo Zanoni if (!master_tile_ctl) { 177822e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 177922e26af7SPaulo Zanoni return IRQ_NONE; 178022e26af7SPaulo Zanoni } 178122e26af7SPaulo Zanoni 178222e26af7SPaulo Zanoni /* FIXME: we only support tile 0 for now. */ 178322e26af7SPaulo Zanoni if (master_tile_ctl & DG1_MSTR_TILE(0)) { 178422e26af7SPaulo Zanoni master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 178522e26af7SPaulo Zanoni raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl); 178622e26af7SPaulo Zanoni } else { 1787a10234fdSTvrtko Ursulin drm_err(&i915->drm, "Tile not supported: 0x%08x\n", 1788a10234fdSTvrtko Ursulin master_tile_ctl); 178922e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 179022e26af7SPaulo Zanoni return IRQ_NONE; 179122e26af7SPaulo Zanoni } 179222e26af7SPaulo Zanoni 179322e26af7SPaulo Zanoni gen11_gt_irq_handler(gt, master_ctl); 179422e26af7SPaulo Zanoni 179522e26af7SPaulo Zanoni if (master_ctl & GEN11_DISPLAY_IRQ) 179622e26af7SPaulo Zanoni gen11_display_irq_handler(i915); 179722e26af7SPaulo Zanoni 1798ddcf980fSAnusha Srivatsa gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 179922e26af7SPaulo Zanoni 180022e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 180122e26af7SPaulo Zanoni 1802ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(i915, gu_misc_iir); 180322e26af7SPaulo Zanoni 180422e26af7SPaulo Zanoni pmu_irq_stats(i915, IRQ_HANDLED); 180522e26af7SPaulo Zanoni 180622e26af7SPaulo Zanoni return IRQ_HANDLED; 180797b492f5SLucas De Marchi } 180897b492f5SLucas De Marchi 180942f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 181042f52ef8SKeith Packard * we use as a pipe index 181142f52ef8SKeith Packard */ 181208fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc) 18130a3e67a4SJesse Barnes { 181408fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 181508fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 1816e9d21d7fSKeith Packard unsigned long irqflags; 181771e0ffa5SJesse Barnes 18181ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 181986e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 182086e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 182186e83e35SChris Wilson 182286e83e35SChris Wilson return 0; 182386e83e35SChris Wilson } 182486e83e35SChris Wilson 18257d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc) 1826d938da6bSVille Syrjälä { 182708fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 1828d938da6bSVille Syrjälä 18297d423af9SVille Syrjälä /* 18307d423af9SVille Syrjälä * Vblank interrupts fail to wake the device up from C2+. 18317d423af9SVille Syrjälä * Disabling render clock gating during C-states avoids 18327d423af9SVille Syrjälä * the problem. There is a small power cost so we do this 18337d423af9SVille Syrjälä * only when vblank interrupts are actually enabled. 18347d423af9SVille Syrjälä */ 18357d423af9SVille Syrjälä if (dev_priv->vblank_enabled++ == 0) 18362939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 1837d938da6bSVille Syrjälä 183808fa8fd0SVille Syrjälä return i8xx_enable_vblank(crtc); 1839d938da6bSVille Syrjälä } 1840d938da6bSVille Syrjälä 184108fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc) 184286e83e35SChris Wilson { 184308fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 184408fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 184586e83e35SChris Wilson unsigned long irqflags; 184686e83e35SChris Wilson 184786e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 18487c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 1849755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 18501ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 18518692d00eSChris Wilson 18520a3e67a4SJesse Barnes return 0; 18530a3e67a4SJesse Barnes } 18540a3e67a4SJesse Barnes 185508fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc) 1856f796cf8fSJesse Barnes { 185708fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 185808fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 1859f796cf8fSJesse Barnes unsigned long irqflags; 1860373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 186186e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 1862f796cf8fSJesse Barnes 1863f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1864fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 1865b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1866b1f14ad0SJesse Barnes 18672e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 18682e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 18692e8bf223SDhinakaran Pandiyan */ 18702e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 187108fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 18722e8bf223SDhinakaran Pandiyan 1873b1f14ad0SJesse Barnes return 0; 1874b1f14ad0SJesse Barnes } 1875b1f14ad0SJesse Barnes 18769c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, 18779c9e97c4SVandita Kulkarni bool enable) 18789c9e97c4SVandita Kulkarni { 18799c9e97c4SVandita Kulkarni struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); 18809c9e97c4SVandita Kulkarni enum port port; 18819c9e97c4SVandita Kulkarni 18829c9e97c4SVandita Kulkarni if (!(intel_crtc->mode_flags & 18839c9e97c4SVandita Kulkarni (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0))) 18849c9e97c4SVandita Kulkarni return false; 18859c9e97c4SVandita Kulkarni 18869c9e97c4SVandita Kulkarni /* for dual link cases we consider TE from slave */ 18879c9e97c4SVandita Kulkarni if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1) 18889c9e97c4SVandita Kulkarni port = PORT_B; 18899c9e97c4SVandita Kulkarni else 18909c9e97c4SVandita Kulkarni port = PORT_A; 18919c9e97c4SVandita Kulkarni 18928cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, 18938cee664dSAndrzej Hajda enable ? 0 : DSI_TE_EVENT); 18949c9e97c4SVandita Kulkarni 18958cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); 18969c9e97c4SVandita Kulkarni 18979c9e97c4SVandita Kulkarni return true; 18989c9e97c4SVandita Kulkarni } 18999c9e97c4SVandita Kulkarni 1900f15f01a7SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *_crtc) 1901abd58f01SBen Widawsky { 1902f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 1903f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 1904f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 1905abd58f01SBen Widawsky unsigned long irqflags; 1906abd58f01SBen Widawsky 1907f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, true)) 19089c9e97c4SVandita Kulkarni return 0; 19099c9e97c4SVandita Kulkarni 1910abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1911013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 1912abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1913013d3752SVille Syrjälä 19142e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 19152e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 19162e8bf223SDhinakaran Pandiyan */ 19172e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 1918f15f01a7SVille Syrjälä drm_crtc_vblank_restore(&crtc->base); 19192e8bf223SDhinakaran Pandiyan 1920abd58f01SBen Widawsky return 0; 1921abd58f01SBen Widawsky } 1922abd58f01SBen Widawsky 192342f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 192442f52ef8SKeith Packard * we use as a pipe index 192542f52ef8SKeith Packard */ 192608fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc) 192786e83e35SChris Wilson { 192808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 192908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 193086e83e35SChris Wilson unsigned long irqflags; 193186e83e35SChris Wilson 193286e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 193386e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 193486e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 193586e83e35SChris Wilson } 193686e83e35SChris Wilson 19377d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc) 1938d938da6bSVille Syrjälä { 193908fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 1940d938da6bSVille Syrjälä 194108fa8fd0SVille Syrjälä i8xx_disable_vblank(crtc); 1942d938da6bSVille Syrjälä 19437d423af9SVille Syrjälä if (--dev_priv->vblank_enabled == 0) 19442939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 1945d938da6bSVille Syrjälä } 1946d938da6bSVille Syrjälä 194708fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc) 19480a3e67a4SJesse Barnes { 194908fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 195008fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 1951e9d21d7fSKeith Packard unsigned long irqflags; 19520a3e67a4SJesse Barnes 19531ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 19547c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 1955755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 19561ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 19570a3e67a4SJesse Barnes } 19580a3e67a4SJesse Barnes 195908fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc) 1960f796cf8fSJesse Barnes { 196108fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 196208fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 1963f796cf8fSJesse Barnes unsigned long irqflags; 1964373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 196586e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 1966f796cf8fSJesse Barnes 1967f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1968fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 1969b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1970b1f14ad0SJesse Barnes } 1971b1f14ad0SJesse Barnes 1972f15f01a7SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *_crtc) 1973abd58f01SBen Widawsky { 1974f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 1975f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 1976f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 1977abd58f01SBen Widawsky unsigned long irqflags; 1978abd58f01SBen Widawsky 1979f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, false)) 19809c9e97c4SVandita Kulkarni return; 19819c9e97c4SVandita Kulkarni 1982abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1983013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 1984abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1985abd58f01SBen Widawsky } 1986abd58f01SBen Widawsky 1987b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 198891738a95SPaulo Zanoni { 1989b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 1990b16b2a2fSPaulo Zanoni 19916e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 199291738a95SPaulo Zanoni return; 199391738a95SPaulo Zanoni 1994b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 1995105b122eSPaulo Zanoni 19966e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 19972939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff); 1998622364b6SPaulo Zanoni } 1999105b122eSPaulo Zanoni 200070591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 200170591a41SVille Syrjälä { 2002b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2003b16b2a2fSPaulo Zanoni 200471b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2005f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 200671b8b41dSVille Syrjälä else 20077d938bc0SVille Syrjälä intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); 200871b8b41dSVille Syrjälä 2009ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 20108cee664dSAndrzej Hajda intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); 201170591a41SVille Syrjälä 201244d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 201370591a41SVille Syrjälä 2014b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, VLV_); 20158bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 201670591a41SVille Syrjälä } 201770591a41SVille Syrjälä 20188bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 20198bb61306SVille Syrjälä { 2020b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2021b16b2a2fSPaulo Zanoni 20228bb61306SVille Syrjälä u32 pipestat_mask; 20239ab981f2SVille Syrjälä u32 enable_mask; 20248bb61306SVille Syrjälä enum pipe pipe; 20258bb61306SVille Syrjälä 2026842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 20278bb61306SVille Syrjälä 20288bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 20298bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 20308bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 20318bb61306SVille Syrjälä 20329ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 20338bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2034ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 2035ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 2036ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 2037ebf5f921SVille Syrjälä 20388bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2039ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 2040ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 20416b7eafc1SVille Syrjälä 204248a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u); 20436b7eafc1SVille Syrjälä 20449ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 20458bb61306SVille Syrjälä 2046b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask); 20478bb61306SVille Syrjälä } 20488bb61306SVille Syrjälä 20498bb61306SVille Syrjälä /* drm_dma.h hooks 20508bb61306SVille Syrjälä */ 20519eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv) 20528bb61306SVille Syrjälä { 2053b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 20548bb61306SVille Syrjälä 2055b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, DE); 2056e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 2057e44adb5dSChris Wilson 2058651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) == 7) 2059f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); 20608bb61306SVille Syrjälä 2061fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 2062f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2063f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2064fc340442SDaniel Vetter } 2065fc340442SDaniel Vetter 20662cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 20678bb61306SVille Syrjälä 2068b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 20698bb61306SVille Syrjälä } 20708bb61306SVille Syrjälä 2071b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv) 20727e231dbeSJesse Barnes { 20732939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 20742939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 207534c7b8a7SVille Syrjälä 20762cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 20777e231dbeSJesse Barnes 2078ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 20799918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 208070591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2081ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 20827e231dbeSJesse Barnes } 20837e231dbeSJesse Barnes 2084a844cfbeSJosé Roberto de Souza static void gen8_display_irq_reset(struct drm_i915_private *dev_priv) 2085abd58f01SBen Widawsky { 2086b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2087d048a268SVille Syrjälä enum pipe pipe; 2088abd58f01SBen Widawsky 2089a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2090a844cfbeSJosé Roberto de Souza return; 2091abd58f01SBen Widawsky 2092f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2093f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2094e04f7eceSVille Syrjälä 2095055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 2096f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 2097813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 2098b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 2099abd58f01SBen Widawsky 2100b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2101b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2102a844cfbeSJosé Roberto de Souza } 2103a844cfbeSJosé Roberto de Souza 2104a844cfbeSJosé Roberto de Souza static void gen8_irq_reset(struct drm_i915_private *dev_priv) 2105a844cfbeSJosé Roberto de Souza { 2106a844cfbeSJosé Roberto de Souza struct intel_uncore *uncore = &dev_priv->uncore; 2107a844cfbeSJosé Roberto de Souza 2108e58c2cacSAndrzej Hajda gen8_master_intr_disable(uncore->regs); 2109a844cfbeSJosé Roberto de Souza 21102cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 2111a844cfbeSJosé Roberto de Souza gen8_display_irq_reset(dev_priv); 2112b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 2113abd58f01SBen Widawsky 21146e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 2115b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 211659b7cb44STejas Upadhyay 2117abd58f01SBen Widawsky } 2118abd58f01SBen Widawsky 2119a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) 212051951ae7SMika Kuoppala { 2121b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2122d048a268SVille Syrjälä enum pipe pipe; 2123562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 2124562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 212551951ae7SMika Kuoppala 2126a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2127a844cfbeSJosé Roberto de Souza return; 2128a844cfbeSJosé Roberto de Souza 2129f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); 213051951ae7SMika Kuoppala 2131373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 21328241cfbeSJosé Roberto de Souza enum transcoder trans; 21338241cfbeSJosé Roberto de Souza 2134562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 21358241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 21368241cfbeSJosé Roberto de Souza 21378241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 21388241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 21398241cfbeSJosé Roberto de Souza continue; 21408241cfbeSJosé Roberto de Souza 21418241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff); 21428241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff); 21438241cfbeSJosé Roberto de Souza } 21448241cfbeSJosé Roberto de Souza } else { 2145f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2146f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 21478241cfbeSJosé Roberto de Souza } 214862819dfdSJosé Roberto de Souza 214951951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 215051951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 215151951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 2152b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 215351951ae7SMika Kuoppala 2154b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2155b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2156babde06dSMika Kahola 2157babde06dSMika Kahola if (DISPLAY_VER(dev_priv) >= 14) 2158babde06dSMika Kahola GEN3_IRQ_RESET(uncore, PICAINTERRUPT_); 2159babde06dSMika Kahola else 2160b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); 216131604222SAnusha Srivatsa 216229b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2163b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 216451951ae7SMika Kuoppala } 216551951ae7SMika Kuoppala 2166a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv) 2167a3265d85SMatt Roper { 21682cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2169fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 2170a3265d85SMatt Roper 2171a3265d85SMatt Roper gen11_master_intr_disable(dev_priv->uncore.regs); 2172a3265d85SMatt Roper 2173fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 2174a3265d85SMatt Roper gen11_display_irq_reset(dev_priv); 2175a3265d85SMatt Roper 2176a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 2177a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN8_PCU_); 2178a3265d85SMatt Roper } 2179a3265d85SMatt Roper 218022e26af7SPaulo Zanoni static void dg1_irq_reset(struct drm_i915_private *dev_priv) 218122e26af7SPaulo Zanoni { 21822cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2183fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 218422e26af7SPaulo Zanoni 218522e26af7SPaulo Zanoni dg1_master_intr_disable(dev_priv->uncore.regs); 218622e26af7SPaulo Zanoni 2187fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 218822e26af7SPaulo Zanoni gen11_display_irq_reset(dev_priv); 218922e26af7SPaulo Zanoni 219022e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 219122e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 219222e26af7SPaulo Zanoni } 219322e26af7SPaulo Zanoni 21944c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 2195001bd2cbSImre Deak u8 pipe_mask) 2196d49bdb0eSPaulo Zanoni { 2197b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 21988bcc0840SMatt Roper u32 extra_ier = GEN8_PIPE_VBLANK | 21998bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 2200cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 22016831f3e3SVille Syrjälä enum pipe pipe; 2202d49bdb0eSPaulo Zanoni 220313321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 22049dfe2e3aSImre Deak 22059dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 22069dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 22079dfe2e3aSImre Deak return; 22089dfe2e3aSImre Deak } 22099dfe2e3aSImre Deak 22106831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2211b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 22126831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 22136831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 22149dfe2e3aSImre Deak 221513321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 2216d49bdb0eSPaulo Zanoni } 2217d49bdb0eSPaulo Zanoni 2218aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 2219001bd2cbSImre Deak u8 pipe_mask) 2220aae8ba84SVille Syrjälä { 2221b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 22226831f3e3SVille Syrjälä enum pipe pipe; 22236831f3e3SVille Syrjälä 2224aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 22259dfe2e3aSImre Deak 22269dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 22279dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 22289dfe2e3aSImre Deak return; 22299dfe2e3aSImre Deak } 22309dfe2e3aSImre Deak 22316831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2232b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 22339dfe2e3aSImre Deak 2234aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 2235aae8ba84SVille Syrjälä 2236aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 2237315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 2238aae8ba84SVille Syrjälä } 2239aae8ba84SVille Syrjälä 2240b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv) 224143f328d7SVille Syrjälä { 2242b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 224343f328d7SVille Syrjälä 2244e58c2cacSAndrzej Hajda intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0); 22452939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 224643f328d7SVille Syrjälä 22472cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 224843f328d7SVille Syrjälä 2249b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 225043f328d7SVille Syrjälä 2251ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 22529918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 225370591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2254ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 225543f328d7SVille Syrjälä } 225643f328d7SVille Syrjälä 2257a0a6d8cbSVille Syrjälä /* 2258a0a6d8cbSVille Syrjälä * SDEIER is also touched by the interrupt handler to work around missed PCH 2259a0a6d8cbSVille Syrjälä * interrupts. Hence we can't update it after the interrupt handler is enabled - 2260a0a6d8cbSVille Syrjälä * instead we unconditionally enable all PCH interrupt sources here, but then 2261a0a6d8cbSVille Syrjälä * only unmask them as needed with SDEIMR. 2262a0a6d8cbSVille Syrjälä * 2263a0a6d8cbSVille Syrjälä * Note that we currently do this after installing the interrupt handler, 2264a0a6d8cbSVille Syrjälä * but before we enable the master interrupt. That should be sufficient 2265a0a6d8cbSVille Syrjälä * to avoid races with the irq handler, assuming we have MSI. Shared legacy 2266a0a6d8cbSVille Syrjälä * interrupts could still race. 2267a0a6d8cbSVille Syrjälä */ 2268b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) 2269d46da437SPaulo Zanoni { 2270a0a6d8cbSVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 227182a28bcfSDaniel Vetter u32 mask; 2272d46da437SPaulo Zanoni 22736e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 2274692a04cfSDaniel Vetter return; 2275692a04cfSDaniel Vetter 22766e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 22775c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 22784ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 22795c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 22804ebc6509SDhinakaran Pandiyan else 22814ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 22828664281bSPaulo Zanoni 2283a0a6d8cbSVille Syrjälä GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 2284d46da437SPaulo Zanoni } 2285d46da437SPaulo Zanoni 22869eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) 2287036a4a7dSZhenyu Wang { 2288b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 22898e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 22908e76f8dcSPaulo Zanoni 2291651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) >= 7) { 22928e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 2293842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 22948e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 229523bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 22962a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_C) | 22972a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_B) | 22982a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_A) | 229923bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 23008e76f8dcSPaulo Zanoni } else { 23018e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 2302842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 2303842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 2304c6073d4cSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | 2305e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 23064bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_A) | 23074bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_B) | 2308e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 23098e76f8dcSPaulo Zanoni } 2310036a4a7dSZhenyu Wang 2311fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 2312b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 2313fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 2314fc340442SDaniel Vetter } 2315fc340442SDaniel Vetter 2316c6073d4cSVille Syrjälä if (IS_IRONLAKE_M(dev_priv)) 2317c6073d4cSVille Syrjälä extra_mask |= DE_PCU_EVENT; 2318c6073d4cSVille Syrjälä 23191ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 2320036a4a7dSZhenyu Wang 2321a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 2322622364b6SPaulo Zanoni 23232cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 2324a9922912SVille Syrjälä 2325b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, 2326b16b2a2fSPaulo Zanoni display_mask | extra_mask); 2327036a4a7dSZhenyu Wang } 2328036a4a7dSZhenyu Wang 2329f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 2330f8b79e58SImre Deak { 233167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 2332f8b79e58SImre Deak 2333f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 2334f8b79e58SImre Deak return; 2335f8b79e58SImre Deak 2336f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 2337f8b79e58SImre Deak 2338d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 2339d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 2340ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 2341f8b79e58SImre Deak } 2342d6c69803SVille Syrjälä } 2343f8b79e58SImre Deak 2344f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 2345f8b79e58SImre Deak { 234667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 2347f8b79e58SImre Deak 2348f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 2349f8b79e58SImre Deak return; 2350f8b79e58SImre Deak 2351f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 2352f8b79e58SImre Deak 2353950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 2354ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 2355f8b79e58SImre Deak } 2356f8b79e58SImre Deak 23570e6c9a9eSVille Syrjälä 2358b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) 23590e6c9a9eSVille Syrjälä { 23602cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 23617e231dbeSJesse Barnes 2362ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 23639918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 2364ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 2365ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 2366ad22d106SVille Syrjälä 23672939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 23682939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 236920afbda2SDaniel Vetter } 237020afbda2SDaniel Vetter 2371abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 2372abd58f01SBen Widawsky { 2373b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2374b16b2a2fSPaulo Zanoni 2375869129eeSMatt Roper u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) | 2376869129eeSMatt Roper GEN8_PIPE_CDCLK_CRC_DONE; 2377a9c287c9SJani Nikula u32 de_pipe_enables; 2378054318c7SImre Deak u32 de_port_masked = gen8_de_port_aux_mask(dev_priv); 23793a3b3c7dSVille Syrjälä u32 de_port_enables; 2380df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 2381562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 2382562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 23833a3b3c7dSVille Syrjälä enum pipe pipe; 2384770de83dSDamien Lespiau 2385a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2386a844cfbeSJosé Roberto de Souza return; 2387a844cfbeSJosé Roberto de Souza 2388373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) <= 10) 2389df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 2390df0d28c1SDhinakaran Pandiyan 239170bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 23923a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 2393a324fcacSRodrigo Vivi 2394373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 23959c9e97c4SVandita Kulkarni enum port port; 23969c9e97c4SVandita Kulkarni 23979c9e97c4SVandita Kulkarni if (intel_bios_is_dsi_present(dev_priv, &port)) 23989c9e97c4SVandita Kulkarni de_port_masked |= DSI0_TE | DSI1_TE; 23999c9e97c4SVandita Kulkarni } 24009c9e97c4SVandita Kulkarni 2401cda195f1SVille Syrjälä de_pipe_enables = de_pipe_masked | 24028bcc0840SMatt Roper GEN8_PIPE_VBLANK | 24038bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 2404cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 24051288f9b0SKarthik B S 24063a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 240770bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 2408a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 2409a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 2410e5abaab3SVille Syrjälä de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK; 24113a3b3c7dSVille Syrjälä 2412373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 24138241cfbeSJosé Roberto de Souza enum transcoder trans; 24148241cfbeSJosé Roberto de Souza 2415562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 24168241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 24178241cfbeSJosé Roberto de Souza 24188241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 24198241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 24208241cfbeSJosé Roberto de Souza continue; 24218241cfbeSJosé Roberto de Souza 24228241cfbeSJosé Roberto de Souza gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans)); 24238241cfbeSJosé Roberto de Souza } 24248241cfbeSJosé Roberto de Souza } else { 2425b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 24268241cfbeSJosé Roberto de Souza } 2427e04f7eceSVille Syrjälä 24280a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 24290a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 2430abd58f01SBen Widawsky 2431f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 2432813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 2433b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 2434813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 243535079899SPaulo Zanoni de_pipe_enables); 24360a195c02SMika Kahola } 2437abd58f01SBen Widawsky 2438b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 2439b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 24402a57d9ccSImre Deak 2441babde06dSMika Kahola if (IS_DISPLAY_VER(dev_priv, 11, 13)) { 2442121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 2443b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 2444b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 2445121e758eSDhinakaran Pandiyan 2446b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, 2447b16b2a2fSPaulo Zanoni de_hpd_enables); 2448abd58f01SBen Widawsky } 2449121e758eSDhinakaran Pandiyan } 2450abd58f01SBen Widawsky 2451babde06dSMika Kahola static void mtp_irq_postinstall(struct drm_i915_private *i915) 2452babde06dSMika Kahola { 2453babde06dSMika Kahola struct intel_uncore *uncore = &i915->uncore; 2454babde06dSMika Kahola u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT; 2455babde06dSMika Kahola u32 de_hpd_mask = XELPDP_AUX_TC_MASK; 2456babde06dSMika Kahola u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK | 2457babde06dSMika Kahola XELPDP_TBT_HOTPLUG_MASK; 2458babde06dSMika Kahola 2459babde06dSMika Kahola GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask, 2460babde06dSMika Kahola de_hpd_enables); 2461babde06dSMika Kahola 2462babde06dSMika Kahola GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff); 2463babde06dSMika Kahola } 2464babde06dSMika Kahola 246559b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv) 246659b7cb44STejas Upadhyay { 246759b7cb44STejas Upadhyay struct intel_uncore *uncore = &dev_priv->uncore; 246859b7cb44STejas Upadhyay u32 mask = SDE_GMBUS_ICP; 246959b7cb44STejas Upadhyay 247059b7cb44STejas Upadhyay GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 247159b7cb44STejas Upadhyay } 247259b7cb44STejas Upadhyay 2473b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) 2474abd58f01SBen Widawsky { 247559b7cb44STejas Upadhyay if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 247659b7cb44STejas Upadhyay icp_irq_postinstall(dev_priv); 247759b7cb44STejas Upadhyay else if (HAS_PCH_SPLIT(dev_priv)) 2478a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 2479622364b6SPaulo Zanoni 24802cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 2481abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 2482abd58f01SBen Widawsky 248325286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 2484abd58f01SBen Widawsky } 2485abd58f01SBen Widawsky 2486a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) 2487a844cfbeSJosé Roberto de Souza { 2488a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2489a844cfbeSJosé Roberto de Souza return; 2490a844cfbeSJosé Roberto de Souza 2491a844cfbeSJosé Roberto de Souza gen8_de_irq_postinstall(dev_priv); 2492a844cfbeSJosé Roberto de Souza 2493a844cfbeSJosé Roberto de Souza intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 2494a844cfbeSJosé Roberto de Souza GEN11_DISPLAY_IRQ_ENABLE); 2495a844cfbeSJosé Roberto de Souza } 249631604222SAnusha Srivatsa 2497b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) 249851951ae7SMika Kuoppala { 24992cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2500fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 2501df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 250251951ae7SMika Kuoppala 250329b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2504b318b824SVille Syrjälä icp_irq_postinstall(dev_priv); 250531604222SAnusha Srivatsa 2506fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 2507a844cfbeSJosé Roberto de Souza gen11_de_irq_postinstall(dev_priv); 250851951ae7SMika Kuoppala 2509b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 2510df0d28c1SDhinakaran Pandiyan 25119b77011eSTvrtko Ursulin gen11_master_intr_enable(uncore->regs); 25122939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ); 251351951ae7SMika Kuoppala } 251422e26af7SPaulo Zanoni 251522e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) 251622e26af7SPaulo Zanoni { 25172cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2518fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 251922e26af7SPaulo Zanoni u32 gu_misc_masked = GEN11_GU_MISC_GSE; 252022e26af7SPaulo Zanoni 2521fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 252222e26af7SPaulo Zanoni 252322e26af7SPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 252422e26af7SPaulo Zanoni 252522e26af7SPaulo Zanoni if (HAS_DISPLAY(dev_priv)) { 2526babde06dSMika Kahola if (DISPLAY_VER(dev_priv) >= 14) 2527babde06dSMika Kahola mtp_irq_postinstall(dev_priv); 2528babde06dSMika Kahola else 252922e26af7SPaulo Zanoni icp_irq_postinstall(dev_priv); 2530babde06dSMika Kahola 253122e26af7SPaulo Zanoni gen8_de_irq_postinstall(dev_priv); 253222e26af7SPaulo Zanoni intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 253322e26af7SPaulo Zanoni GEN11_DISPLAY_IRQ_ENABLE); 253422e26af7SPaulo Zanoni } 253522e26af7SPaulo Zanoni 2536fd4d7904SPaulo Zanoni dg1_master_intr_enable(uncore->regs); 2537fd4d7904SPaulo Zanoni intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR); 253897b492f5SLucas De Marchi } 253951951ae7SMika Kuoppala 2540b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) 254143f328d7SVille Syrjälä { 25422cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 254343f328d7SVille Syrjälä 2544ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 25459918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 2546ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 2547ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 2548ad22d106SVille Syrjälä 25492939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 25502939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 255143f328d7SVille Syrjälä } 255243f328d7SVille Syrjälä 2553b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv) 2554c2798b19SChris Wilson { 2555b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2556c2798b19SChris Wilson 255744d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 255844d9241eSVille Syrjälä 2559ad7632ffSJani Nikula gen2_irq_reset(uncore); 2560e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 2561c2798b19SChris Wilson } 2562c2798b19SChris Wilson 25633687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915) 25643687ce75SVille Syrjälä { 2565e7e12f6eSVille Syrjälä /* 2566e7e12f6eSVille Syrjälä * On gen2/3 FBC generates (seemingly spurious) 2567e7e12f6eSVille Syrjälä * display INVALID_GTT/INVALID_GTT_PTE table errors. 2568e7e12f6eSVille Syrjälä * 2569e7e12f6eSVille Syrjälä * Also gen3 bspec has this to say: 2570e7e12f6eSVille Syrjälä * "DISPA_INVALID_GTT_PTE 2571e7e12f6eSVille Syrjälä " [DevNapa] : Reserved. This bit does not reflect the page 2572e7e12f6eSVille Syrjälä " table error for the display plane A." 2573e7e12f6eSVille Syrjälä * 2574e7e12f6eSVille Syrjälä * Unfortunately we can't mask off individual PGTBL_ER bits, 2575e7e12f6eSVille Syrjälä * so we just have to mask off all page table errors via EMR. 2576e7e12f6eSVille Syrjälä */ 2577e7e12f6eSVille Syrjälä if (HAS_FBC(i915)) 2578e7e12f6eSVille Syrjälä return ~I915_ERROR_MEMORY_REFRESH; 2579e7e12f6eSVille Syrjälä else 25803687ce75SVille Syrjälä return ~(I915_ERROR_PAGE_TABLE | 25813687ce75SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 25823687ce75SVille Syrjälä } 25833687ce75SVille Syrjälä 2584b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) 2585c2798b19SChris Wilson { 2586b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2587e9e9848aSVille Syrjälä u16 enable_mask; 2588c2798b19SChris Wilson 25893687ce75SVille Syrjälä intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv)); 2590c2798b19SChris Wilson 2591c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 2592c2798b19SChris Wilson dev_priv->irq_mask = 2593c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 259416659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 259516659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 2596c2798b19SChris Wilson 2597e9e9848aSVille Syrjälä enable_mask = 2598c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2599c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 260016659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 2601e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 2602e9e9848aSVille Syrjälä 2603ad7632ffSJani Nikula gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask); 2604c2798b19SChris Wilson 2605379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 2606379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 2607d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 2608755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 2609755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 2610d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 2611c2798b19SChris Wilson } 2612c2798b19SChris Wilson 26134f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915, 261478c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 261578c357ddSVille Syrjälä { 26164f5fd91fSTvrtko Ursulin struct intel_uncore *uncore = &i915->uncore; 261778c357ddSVille Syrjälä u16 emr; 261878c357ddSVille Syrjälä 26194f5fd91fSTvrtko Ursulin *eir = intel_uncore_read16(uncore, EIR); 26204f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EIR, *eir); 262178c357ddSVille Syrjälä 26224f5fd91fSTvrtko Ursulin *eir_stuck = intel_uncore_read16(uncore, EIR); 262378c357ddSVille Syrjälä if (*eir_stuck == 0) 262478c357ddSVille Syrjälä return; 262578c357ddSVille Syrjälä 262678c357ddSVille Syrjälä /* 262778c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 262878c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 262978c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 263078c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 263178c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 263278c357ddSVille Syrjälä * cleared except by handling the underlying error 263378c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 263478c357ddSVille Syrjälä * remains set. 263578c357ddSVille Syrjälä */ 26364f5fd91fSTvrtko Ursulin emr = intel_uncore_read16(uncore, EMR); 26374f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, 0xffff); 26384f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, emr | *eir_stuck); 263978c357ddSVille Syrjälä } 264078c357ddSVille Syrjälä 264178c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 264278c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 264378c357ddSVille Syrjälä { 2644a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir); 264578c357ddSVille Syrjälä 264678c357ddSVille Syrjälä if (eir_stuck) 264700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n", 264800376ccfSWambui Karuga eir_stuck); 2649d1e89592SVille Syrjälä 2650d1e89592SVille Syrjälä drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n", 2651d1e89592SVille Syrjälä intel_uncore_read(&dev_priv->uncore, PGTBL_ER)); 265278c357ddSVille Syrjälä } 265378c357ddSVille Syrjälä 265478c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 265578c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 265678c357ddSVille Syrjälä { 265778c357ddSVille Syrjälä u32 emr; 265878c357ddSVille Syrjälä 2659839259b8SVille Syrjälä *eir = intel_uncore_read(&dev_priv->uncore, EIR); 2660839259b8SVille Syrjälä intel_uncore_write(&dev_priv->uncore, EIR, *eir); 266178c357ddSVille Syrjälä 26622939eb06SJani Nikula *eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR); 266378c357ddSVille Syrjälä if (*eir_stuck == 0) 266478c357ddSVille Syrjälä return; 266578c357ddSVille Syrjälä 266678c357ddSVille Syrjälä /* 266778c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 266878c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 266978c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 267078c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 267178c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 267278c357ddSVille Syrjälä * cleared except by handling the underlying error 267378c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 267478c357ddSVille Syrjälä * remains set. 267578c357ddSVille Syrjälä */ 2676839259b8SVille Syrjälä emr = intel_uncore_read(&dev_priv->uncore, EMR); 2677839259b8SVille Syrjälä intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff); 26782939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck); 267978c357ddSVille Syrjälä } 268078c357ddSVille Syrjälä 268178c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 268278c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 268378c357ddSVille Syrjälä { 2684a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir); 268578c357ddSVille Syrjälä 268678c357ddSVille Syrjälä if (eir_stuck) 268700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n", 268800376ccfSWambui Karuga eir_stuck); 2689d1e89592SVille Syrjälä 2690d1e89592SVille Syrjälä drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n", 2691d1e89592SVille Syrjälä intel_uncore_read(&dev_priv->uncore, PGTBL_ER)); 269278c357ddSVille Syrjälä } 269378c357ddSVille Syrjälä 2694ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 2695c2798b19SChris Wilson { 2696b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 2697af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 2698c2798b19SChris Wilson 26992dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 27002dd2a883SImre Deak return IRQ_NONE; 27012dd2a883SImre Deak 27021f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 27039102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 27041f814dacSImre Deak 2705af722d28SVille Syrjälä do { 2706af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 270778c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 2708af722d28SVille Syrjälä u16 iir; 2709af722d28SVille Syrjälä 27104f5fd91fSTvrtko Ursulin iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR); 2711c2798b19SChris Wilson if (iir == 0) 2712af722d28SVille Syrjälä break; 2713c2798b19SChris Wilson 2714af722d28SVille Syrjälä ret = IRQ_HANDLED; 2715c2798b19SChris Wilson 2716eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 2717eb64343cSVille Syrjälä * signalled in iir */ 2718eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 2719c2798b19SChris Wilson 272078c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 272178c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 272278c357ddSVille Syrjälä 27234f5fd91fSTvrtko Ursulin intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); 2724c2798b19SChris Wilson 2725c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 27262cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 2727c2798b19SChris Wilson 272878c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 272978c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 2730af722d28SVille Syrjälä 2731eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 2732af722d28SVille Syrjälä } while (0); 2733c2798b19SChris Wilson 27349c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 27359c6508b9SThomas Gleixner 27369102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 27371f814dacSImre Deak 27381f814dacSImre Deak return ret; 2739c2798b19SChris Wilson } 2740c2798b19SChris Wilson 2741b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv) 2742a266c7d5SChris Wilson { 2743b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2744a266c7d5SChris Wilson 274556b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 27460706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 27478cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0); 2748a266c7d5SChris Wilson } 2749a266c7d5SChris Wilson 275044d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 275144d9241eSVille Syrjälä 2752b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 2753e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 2754a266c7d5SChris Wilson } 2755a266c7d5SChris Wilson 2756b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv) 2757a266c7d5SChris Wilson { 2758b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 275938bde180SChris Wilson u32 enable_mask; 2760a266c7d5SChris Wilson 27613687ce75SVille Syrjälä intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv)); 276238bde180SChris Wilson 276338bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 276438bde180SChris Wilson dev_priv->irq_mask = 276538bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 276638bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 276716659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 276816659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 276938bde180SChris Wilson 277038bde180SChris Wilson enable_mask = 277138bde180SChris Wilson I915_ASLE_INTERRUPT | 277238bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 277338bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 277416659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 277538bde180SChris Wilson I915_USER_INTERRUPT; 277638bde180SChris Wilson 277756b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 2778a266c7d5SChris Wilson /* Enable in IER... */ 2779a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 2780a266c7d5SChris Wilson /* and unmask in IMR */ 2781a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 2782a266c7d5SChris Wilson } 2783a266c7d5SChris Wilson 2784b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 2785a266c7d5SChris Wilson 2786379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 2787379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 2788d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 2789755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 2790755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 2791d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 2792379ef82dSDaniel Vetter 2793c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 279420afbda2SDaniel Vetter } 279520afbda2SDaniel Vetter 2796ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 2797a266c7d5SChris Wilson { 2798b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 2799af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 2800a266c7d5SChris Wilson 28012dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 28022dd2a883SImre Deak return IRQ_NONE; 28032dd2a883SImre Deak 28041f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 28059102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 28061f814dacSImre Deak 280738bde180SChris Wilson do { 2808eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 280978c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 2810af722d28SVille Syrjälä u32 hotplug_status = 0; 2811af722d28SVille Syrjälä u32 iir; 2812a266c7d5SChris Wilson 28132939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 2814af722d28SVille Syrjälä if (iir == 0) 2815af722d28SVille Syrjälä break; 2816af722d28SVille Syrjälä 2817af722d28SVille Syrjälä ret = IRQ_HANDLED; 2818af722d28SVille Syrjälä 2819af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 2820af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 2821af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 2822a266c7d5SChris Wilson 2823eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 2824eb64343cSVille Syrjälä * signalled in iir */ 2825eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 2826a266c7d5SChris Wilson 282778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 282878c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 282978c357ddSVille Syrjälä 28302939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 2831a266c7d5SChris Wilson 2832a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 28332cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 2834a266c7d5SChris Wilson 283578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 283678c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 2837a266c7d5SChris Wilson 2838af722d28SVille Syrjälä if (hotplug_status) 2839af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 2840af722d28SVille Syrjälä 2841af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 2842af722d28SVille Syrjälä } while (0); 2843a266c7d5SChris Wilson 28449c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 28459c6508b9SThomas Gleixner 28469102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 28471f814dacSImre Deak 2848a266c7d5SChris Wilson return ret; 2849a266c7d5SChris Wilson } 2850a266c7d5SChris Wilson 2851b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv) 2852a266c7d5SChris Wilson { 2853b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2854a266c7d5SChris Wilson 28550706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 28568cee664dSAndrzej Hajda intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); 2857a266c7d5SChris Wilson 285844d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 285944d9241eSVille Syrjälä 2860b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 2861e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 2862a266c7d5SChris Wilson } 2863a266c7d5SChris Wilson 28643687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915) 2865a266c7d5SChris Wilson { 2866045cebd2SVille Syrjälä /* 2867045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 2868045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 2869e7e12f6eSVille Syrjälä * 2870e7e12f6eSVille Syrjälä * i965 FBC no longer generates spurious GTT errors, 2871e7e12f6eSVille Syrjälä * so we can always enable the page table errors. 2872045cebd2SVille Syrjälä */ 28733687ce75SVille Syrjälä if (IS_G4X(i915)) 28743687ce75SVille Syrjälä return ~(GM45_ERROR_PAGE_TABLE | 2875045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 2876045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 2877045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 28783687ce75SVille Syrjälä else 28793687ce75SVille Syrjälä return ~(I915_ERROR_PAGE_TABLE | 2880045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 2881045cebd2SVille Syrjälä } 28823687ce75SVille Syrjälä 28833687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv) 28843687ce75SVille Syrjälä { 28853687ce75SVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 28863687ce75SVille Syrjälä u32 enable_mask; 28873687ce75SVille Syrjälä 28883687ce75SVille Syrjälä intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv)); 2889045cebd2SVille Syrjälä 2890a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 2891c30bb1fdSVille Syrjälä dev_priv->irq_mask = 2892c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 2893adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 2894bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2895bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 289678c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 2897bbba0a97SChris Wilson 2898c30bb1fdSVille Syrjälä enable_mask = 2899c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 2900c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 2901c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2902c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 290378c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 2904c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 2905bbba0a97SChris Wilson 290691d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 2907bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 2908a266c7d5SChris Wilson 2909b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 2910c30bb1fdSVille Syrjälä 2911b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 2912b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 2913d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 2914755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 2915755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 2916755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 2917d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 2918a266c7d5SChris Wilson 291991d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 292020afbda2SDaniel Vetter } 292120afbda2SDaniel Vetter 2922ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 2923a266c7d5SChris Wilson { 2924b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 2925af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 2926a266c7d5SChris Wilson 29272dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 29282dd2a883SImre Deak return IRQ_NONE; 29292dd2a883SImre Deak 29301f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 29319102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 29321f814dacSImre Deak 2933af722d28SVille Syrjälä do { 2934eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 293578c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 2936af722d28SVille Syrjälä u32 hotplug_status = 0; 2937af722d28SVille Syrjälä u32 iir; 29382c8ba29fSChris Wilson 29392939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 2940af722d28SVille Syrjälä if (iir == 0) 2941af722d28SVille Syrjälä break; 2942af722d28SVille Syrjälä 2943af722d28SVille Syrjälä ret = IRQ_HANDLED; 2944af722d28SVille Syrjälä 2945af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 2946af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 2947a266c7d5SChris Wilson 2948eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 2949eb64343cSVille Syrjälä * signalled in iir */ 2950eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 2951a266c7d5SChris Wilson 295278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 295378c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 295478c357ddSVille Syrjälä 29552939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 2956a266c7d5SChris Wilson 2957a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 29582cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], 29590669a6e1SChris Wilson iir); 2960af722d28SVille Syrjälä 2961a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 29622cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0], 29630669a6e1SChris Wilson iir >> 25); 2964a266c7d5SChris Wilson 296578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 296678c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 2967515ac2bbSDaniel Vetter 2968af722d28SVille Syrjälä if (hotplug_status) 2969af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 2970af722d28SVille Syrjälä 2971af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 2972af722d28SVille Syrjälä } while (0); 2973a266c7d5SChris Wilson 29749c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 29759c6508b9SThomas Gleixner 29769102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 29771f814dacSImre Deak 2978a266c7d5SChris Wilson return ret; 2979a266c7d5SChris Wilson } 2980a266c7d5SChris Wilson 2981fca52a55SDaniel Vetter /** 2982fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 2983fca52a55SDaniel Vetter * @dev_priv: i915 device instance 2984fca52a55SDaniel Vetter * 2985fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 2986fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 2987fca52a55SDaniel Vetter */ 2988b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 2989f71d4af4SJesse Barnes { 2990cefcff8fSJoonas Lahtinen int i; 29918b2e326dSChris Wilson 299274bb98baSLucas De Marchi INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); 2993cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 2994cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 29958b2e326dSChris Wilson 2996633023a4SDaniele Ceraolo Spurio /* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */ 2997651e7d48SLucas De Marchi if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11) 29982cbc876dSMichał Winiarski to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16; 299926705e20SSagar Arun Kamble 30009a450b68SLucas De Marchi if (!HAS_DISPLAY(dev_priv)) 30019a450b68SLucas De Marchi return; 30029a450b68SLucas De Marchi 30033703060dSAndrzej Hajda dev_priv->drm.vblank_disable_immediate = true; 300421da2700SVille Syrjälä 3005262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 3006262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 3007262fd485SChris Wilson * special care to avoid writing any of the display block registers 3008262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 3009262fd485SChris Wilson * in this case to the runtime pm. 3010262fd485SChris Wilson */ 3011262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 3012262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 3013262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 3014262fd485SChris Wilson 3015*da38ba98SJani Nikula intel_hotplug_irq_init(dev_priv); 30162ccf2e03SChris Wilson } 301720afbda2SDaniel Vetter 3018fca52a55SDaniel Vetter /** 3019cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 3020cefcff8fSJoonas Lahtinen * @i915: i915 device instance 3021cefcff8fSJoonas Lahtinen * 3022cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 3023cefcff8fSJoonas Lahtinen */ 3024cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 3025cefcff8fSJoonas Lahtinen { 3026cefcff8fSJoonas Lahtinen int i; 3027cefcff8fSJoonas Lahtinen 3028cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 3029cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 3030cefcff8fSJoonas Lahtinen } 3031cefcff8fSJoonas Lahtinen 3032b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) 3033b318b824SVille Syrjälä { 3034b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 3035b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 3036b318b824SVille Syrjälä return cherryview_irq_handler; 3037b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 3038b318b824SVille Syrjälä return valleyview_irq_handler; 3039651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 3040b318b824SVille Syrjälä return i965_irq_handler; 3041651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 3042b318b824SVille Syrjälä return i915_irq_handler; 3043b318b824SVille Syrjälä else 3044b318b824SVille Syrjälä return i8xx_irq_handler; 3045b318b824SVille Syrjälä } else { 304622e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 304797b492f5SLucas De Marchi return dg1_irq_handler; 304822e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 3049b318b824SVille Syrjälä return gen11_irq_handler; 3050651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 3051b318b824SVille Syrjälä return gen8_irq_handler; 3052b318b824SVille Syrjälä else 30539eae5e27SLucas De Marchi return ilk_irq_handler; 3054b318b824SVille Syrjälä } 3055b318b824SVille Syrjälä } 3056b318b824SVille Syrjälä 3057b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv) 3058b318b824SVille Syrjälä { 3059b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 3060b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 3061b318b824SVille Syrjälä cherryview_irq_reset(dev_priv); 3062b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 3063b318b824SVille Syrjälä valleyview_irq_reset(dev_priv); 3064651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 3065b318b824SVille Syrjälä i965_irq_reset(dev_priv); 3066651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 3067b318b824SVille Syrjälä i915_irq_reset(dev_priv); 3068b318b824SVille Syrjälä else 3069b318b824SVille Syrjälä i8xx_irq_reset(dev_priv); 3070b318b824SVille Syrjälä } else { 307122e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 307222e26af7SPaulo Zanoni dg1_irq_reset(dev_priv); 307322e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 3074b318b824SVille Syrjälä gen11_irq_reset(dev_priv); 3075651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 3076b318b824SVille Syrjälä gen8_irq_reset(dev_priv); 3077b318b824SVille Syrjälä else 30789eae5e27SLucas De Marchi ilk_irq_reset(dev_priv); 3079b318b824SVille Syrjälä } 3080b318b824SVille Syrjälä } 3081b318b824SVille Syrjälä 3082b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv) 3083b318b824SVille Syrjälä { 3084b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 3085b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 3086b318b824SVille Syrjälä cherryview_irq_postinstall(dev_priv); 3087b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 3088b318b824SVille Syrjälä valleyview_irq_postinstall(dev_priv); 3089651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 3090b318b824SVille Syrjälä i965_irq_postinstall(dev_priv); 3091651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 3092b318b824SVille Syrjälä i915_irq_postinstall(dev_priv); 3093b318b824SVille Syrjälä else 3094b318b824SVille Syrjälä i8xx_irq_postinstall(dev_priv); 3095b318b824SVille Syrjälä } else { 309622e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 309722e26af7SPaulo Zanoni dg1_irq_postinstall(dev_priv); 309822e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 3099b318b824SVille Syrjälä gen11_irq_postinstall(dev_priv); 3100651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 3101b318b824SVille Syrjälä gen8_irq_postinstall(dev_priv); 3102b318b824SVille Syrjälä else 31039eae5e27SLucas De Marchi ilk_irq_postinstall(dev_priv); 3104b318b824SVille Syrjälä } 3105b318b824SVille Syrjälä } 3106b318b824SVille Syrjälä 3107cefcff8fSJoonas Lahtinen /** 3108fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 3109fca52a55SDaniel Vetter * @dev_priv: i915 device instance 3110fca52a55SDaniel Vetter * 3111fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 3112fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 3113fca52a55SDaniel Vetter * 3114fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 3115fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 3116fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 3117fca52a55SDaniel Vetter */ 31182aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 31192aeb7d3aSDaniel Vetter { 31208ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 3121b318b824SVille Syrjälä int ret; 3122b318b824SVille Syrjälä 31232aeb7d3aSDaniel Vetter /* 31242aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 31252aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 31262aeb7d3aSDaniel Vetter * special cases in our ordering checks. 31272aeb7d3aSDaniel Vetter */ 3128ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 31292aeb7d3aSDaniel Vetter 3130ac1723c1SThomas Zimmermann dev_priv->irq_enabled = true; 3131b318b824SVille Syrjälä 3132b318b824SVille Syrjälä intel_irq_reset(dev_priv); 3133b318b824SVille Syrjälä 3134b318b824SVille Syrjälä ret = request_irq(irq, intel_irq_handler(dev_priv), 3135b318b824SVille Syrjälä IRQF_SHARED, DRIVER_NAME, dev_priv); 3136b318b824SVille Syrjälä if (ret < 0) { 3137ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 3138b318b824SVille Syrjälä return ret; 3139b318b824SVille Syrjälä } 3140b318b824SVille Syrjälä 3141b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 3142b318b824SVille Syrjälä 3143b318b824SVille Syrjälä return ret; 31442aeb7d3aSDaniel Vetter } 31452aeb7d3aSDaniel Vetter 3146fca52a55SDaniel Vetter /** 3147fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 3148fca52a55SDaniel Vetter * @dev_priv: i915 device instance 3149fca52a55SDaniel Vetter * 3150fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 3151fca52a55SDaniel Vetter * resources acquired in the init functions. 3152fca52a55SDaniel Vetter */ 31532aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 31542aeb7d3aSDaniel Vetter { 31558ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 3156b318b824SVille Syrjälä 3157b318b824SVille Syrjälä /* 3158789fa874SJanusz Krzysztofik * FIXME we can get called twice during driver probe 3159789fa874SJanusz Krzysztofik * error handling as well as during driver remove due to 316086a1758dSJani Nikula * intel_display_driver_remove() calling us out of sequence. 3161789fa874SJanusz Krzysztofik * Would be nice if it didn't do that... 3162b318b824SVille Syrjälä */ 3163ac1723c1SThomas Zimmermann if (!dev_priv->irq_enabled) 3164b318b824SVille Syrjälä return; 3165b318b824SVille Syrjälä 3166ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 3167b318b824SVille Syrjälä 3168b318b824SVille Syrjälä intel_irq_reset(dev_priv); 3169b318b824SVille Syrjälä 3170b318b824SVille Syrjälä free_irq(irq, dev_priv); 3171b318b824SVille Syrjälä 31722aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 3173ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 31742aeb7d3aSDaniel Vetter } 31752aeb7d3aSDaniel Vetter 3176fca52a55SDaniel Vetter /** 3177fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 3178fca52a55SDaniel Vetter * @dev_priv: i915 device instance 3179fca52a55SDaniel Vetter * 3180fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 3181fca52a55SDaniel Vetter * pm and the system suspend/resume code. 3182fca52a55SDaniel Vetter */ 3183b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 3184c67a470bSPaulo Zanoni { 3185b318b824SVille Syrjälä intel_irq_reset(dev_priv); 3186ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 3187315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 3188c67a470bSPaulo Zanoni } 3189c67a470bSPaulo Zanoni 3190fca52a55SDaniel Vetter /** 3191fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 3192fca52a55SDaniel Vetter * @dev_priv: i915 device instance 3193fca52a55SDaniel Vetter * 3194fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 3195fca52a55SDaniel Vetter * pm and the system suspend/resume code. 3196fca52a55SDaniel Vetter */ 3197b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 3198c67a470bSPaulo Zanoni { 3199ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 3200b318b824SVille Syrjälä intel_irq_reset(dev_priv); 3201b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 3202c67a470bSPaulo Zanoni } 3203d64575eeSJani Nikula 3204d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv) 3205d64575eeSJani Nikula { 3206d64575eeSJani Nikula return dev_priv->runtime_pm.irqs_enabled; 3207d64575eeSJani Nikula } 3208d64575eeSJani Nikula 3209d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915) 3210d64575eeSJani Nikula { 32118ff5446aSThomas Zimmermann synchronize_irq(to_pci_dev(i915->drm.dev)->irq); 3212d64575eeSJani Nikula } 3213320ad343SThomas Zimmermann 3214320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915) 3215320ad343SThomas Zimmermann { 3216320ad343SThomas Zimmermann synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq); 3217320ad343SThomas Zimmermann } 3218