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 31b2c88f5bSDamien Lespiau #include <linux/circ_buf.h> 3255367a27SJani Nikula #include <linux/slab.h> 3355367a27SJani Nikula #include <linux/sysrq.h> 3455367a27SJani Nikula 35fcd70cd3SDaniel Vetter #include <drm/drm_drv.h> 3655367a27SJani Nikula #include <drm/drm_irq.h> 37760285e7SDavid Howells #include <drm/i915_drm.h> 3855367a27SJani Nikula 391d455f8dSJani Nikula #include "display/intel_display_types.h" 40df0566a6SJani Nikula #include "display/intel_fifo_underrun.h" 41df0566a6SJani Nikula #include "display/intel_hotplug.h" 42df0566a6SJani Nikula #include "display/intel_lpe_audio.h" 43df0566a6SJani Nikula #include "display/intel_psr.h" 44df0566a6SJani Nikula 452239e6dfSDaniele Ceraolo Spurio #include "gt/intel_gt.h" 46cf1c97dcSAndi Shyti #include "gt/intel_gt_irq.h" 47d762043fSAndi Shyti #include "gt/intel_gt_pm_irq.h" 48*3e7abf81SAndi Shyti #include "gt/intel_rps.h" 492239e6dfSDaniele Ceraolo Spurio 50c0e09200SDave Airlie #include "i915_drv.h" 51440e2b3dSJani Nikula #include "i915_irq.h" 521c5d22f7SChris Wilson #include "i915_trace.h" 53d13616dbSJani Nikula #include "intel_pm.h" 54c0e09200SDave Airlie 55fca52a55SDaniel Vetter /** 56fca52a55SDaniel Vetter * DOC: interrupt handling 57fca52a55SDaniel Vetter * 58fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 59fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 60fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 61fca52a55SDaniel Vetter */ 62fca52a55SDaniel Vetter 6348ef15d3SJosé Roberto de Souza typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val); 6448ef15d3SJosé Roberto de Souza 65e4ce95aaSVille Syrjälä static const u32 hpd_ilk[HPD_NUM_PINS] = { 66e4ce95aaSVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG, 67e4ce95aaSVille Syrjälä }; 68e4ce95aaSVille Syrjälä 6923bb4cb5SVille Syrjälä static const u32 hpd_ivb[HPD_NUM_PINS] = { 7023bb4cb5SVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, 7123bb4cb5SVille Syrjälä }; 7223bb4cb5SVille Syrjälä 733a3b3c7dSVille Syrjälä static const u32 hpd_bdw[HPD_NUM_PINS] = { 743a3b3c7dSVille Syrjälä [HPD_PORT_A] = GEN8_PORT_DP_A_HOTPLUG, 753a3b3c7dSVille Syrjälä }; 763a3b3c7dSVille Syrjälä 777c7e10dbSVille Syrjälä static const u32 hpd_ibx[HPD_NUM_PINS] = { 78e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG, 79e5868a31SEgbert Eich [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, 80e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG, 81e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG, 82e5868a31SEgbert Eich [HPD_PORT_D] = SDE_PORTD_HOTPLUG 83e5868a31SEgbert Eich }; 84e5868a31SEgbert Eich 857c7e10dbSVille Syrjälä static const u32 hpd_cpt[HPD_NUM_PINS] = { 86e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, 8773c352a2SDaniel Vetter [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, 88e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 89e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 90e5868a31SEgbert Eich [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT 91e5868a31SEgbert Eich }; 92e5868a31SEgbert Eich 9326951cafSXiong Zhang static const u32 hpd_spt[HPD_NUM_PINS] = { 9474c0b395SVille Syrjälä [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, 9526951cafSXiong Zhang [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 9626951cafSXiong Zhang [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 9726951cafSXiong Zhang [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 9826951cafSXiong Zhang [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT 9926951cafSXiong Zhang }; 10026951cafSXiong Zhang 1017c7e10dbSVille Syrjälä static const u32 hpd_mask_i915[HPD_NUM_PINS] = { 102e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_EN, 103e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, 104e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, 105e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN, 106e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN, 107e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN 108e5868a31SEgbert Eich }; 109e5868a31SEgbert Eich 1107c7e10dbSVille Syrjälä static const u32 hpd_status_g4x[HPD_NUM_PINS] = { 111e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 112e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, 113e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, 114e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 115e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 116e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS 117e5868a31SEgbert Eich }; 118e5868a31SEgbert Eich 1194bca26d0SVille Syrjälä static const u32 hpd_status_i915[HPD_NUM_PINS] = { 120e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 121e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, 122e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, 123e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 124e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 125e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS 126e5868a31SEgbert Eich }; 127e5868a31SEgbert Eich 128e0a20ad7SShashank Sharma /* BXT hpd list */ 129e0a20ad7SShashank Sharma static const u32 hpd_bxt[HPD_NUM_PINS] = { 1307f3561beSSonika Jindal [HPD_PORT_A] = BXT_DE_PORT_HP_DDIA, 131e0a20ad7SShashank Sharma [HPD_PORT_B] = BXT_DE_PORT_HP_DDIB, 132e0a20ad7SShashank Sharma [HPD_PORT_C] = BXT_DE_PORT_HP_DDIC 133e0a20ad7SShashank Sharma }; 134e0a20ad7SShashank Sharma 135b796b971SDhinakaran Pandiyan static const u32 hpd_gen11[HPD_NUM_PINS] = { 136b796b971SDhinakaran Pandiyan [HPD_PORT_C] = GEN11_TC1_HOTPLUG | GEN11_TBT1_HOTPLUG, 137b796b971SDhinakaran Pandiyan [HPD_PORT_D] = GEN11_TC2_HOTPLUG | GEN11_TBT2_HOTPLUG, 138b796b971SDhinakaran Pandiyan [HPD_PORT_E] = GEN11_TC3_HOTPLUG | GEN11_TBT3_HOTPLUG, 139b796b971SDhinakaran Pandiyan [HPD_PORT_F] = GEN11_TC4_HOTPLUG | GEN11_TBT4_HOTPLUG 140121e758eSDhinakaran Pandiyan }; 141121e758eSDhinakaran Pandiyan 14248ef15d3SJosé Roberto de Souza static const u32 hpd_gen12[HPD_NUM_PINS] = { 14348ef15d3SJosé Roberto de Souza [HPD_PORT_D] = GEN11_TC1_HOTPLUG | GEN11_TBT1_HOTPLUG, 14448ef15d3SJosé Roberto de Souza [HPD_PORT_E] = GEN11_TC2_HOTPLUG | GEN11_TBT2_HOTPLUG, 14548ef15d3SJosé Roberto de Souza [HPD_PORT_F] = GEN11_TC3_HOTPLUG | GEN11_TBT3_HOTPLUG, 14648ef15d3SJosé Roberto de Souza [HPD_PORT_G] = GEN11_TC4_HOTPLUG | GEN11_TBT4_HOTPLUG, 14748ef15d3SJosé Roberto de Souza [HPD_PORT_H] = GEN12_TC5_HOTPLUG | GEN12_TBT5_HOTPLUG, 14848ef15d3SJosé Roberto de Souza [HPD_PORT_I] = GEN12_TC6_HOTPLUG | GEN12_TBT6_HOTPLUG 14948ef15d3SJosé Roberto de Souza }; 15048ef15d3SJosé Roberto de Souza 15131604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = { 152b32821c0SLucas De Marchi [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(PORT_A), 153b32821c0SLucas De Marchi [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(PORT_B), 154b32821c0SLucas De Marchi [HPD_PORT_C] = SDE_TC_HOTPLUG_ICP(PORT_TC1), 155b32821c0SLucas De Marchi [HPD_PORT_D] = SDE_TC_HOTPLUG_ICP(PORT_TC2), 156b32821c0SLucas De Marchi [HPD_PORT_E] = SDE_TC_HOTPLUG_ICP(PORT_TC3), 157b32821c0SLucas De Marchi [HPD_PORT_F] = SDE_TC_HOTPLUG_ICP(PORT_TC4), 15831604222SAnusha Srivatsa }; 15931604222SAnusha Srivatsa 16052dfdba0SLucas De Marchi static const u32 hpd_tgp[HPD_NUM_PINS] = { 161b32821c0SLucas De Marchi [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(PORT_A), 162b32821c0SLucas De Marchi [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(PORT_B), 163b32821c0SLucas De Marchi [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(PORT_C), 164b32821c0SLucas De Marchi [HPD_PORT_D] = SDE_TC_HOTPLUG_ICP(PORT_TC1), 165b32821c0SLucas De Marchi [HPD_PORT_E] = SDE_TC_HOTPLUG_ICP(PORT_TC2), 166b32821c0SLucas De Marchi [HPD_PORT_F] = SDE_TC_HOTPLUG_ICP(PORT_TC3), 167b32821c0SLucas De Marchi [HPD_PORT_G] = SDE_TC_HOTPLUG_ICP(PORT_TC4), 168b32821c0SLucas De Marchi [HPD_PORT_H] = SDE_TC_HOTPLUG_ICP(PORT_TC5), 169b32821c0SLucas De Marchi [HPD_PORT_I] = SDE_TC_HOTPLUG_ICP(PORT_TC6), 17052dfdba0SLucas De Marchi }; 17152dfdba0SLucas De Marchi 172cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, 17368eb49b1SPaulo Zanoni i915_reg_t iir, i915_reg_t ier) 17468eb49b1SPaulo Zanoni { 17565f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, 0xffffffff); 17665f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 17768eb49b1SPaulo Zanoni 17865f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, 0); 17968eb49b1SPaulo Zanoni 1805c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 18165f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 18265f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 18365f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 18465f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 18568eb49b1SPaulo Zanoni } 1865c502442SPaulo Zanoni 187cf1c97dcSAndi Shyti void gen2_irq_reset(struct intel_uncore *uncore) 18868eb49b1SPaulo Zanoni { 18965f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, 0xffff); 19065f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 191a9d356a6SPaulo Zanoni 19265f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, 0); 19368eb49b1SPaulo Zanoni 19468eb49b1SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 19565f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 19665f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 19765f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 19865f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 19968eb49b1SPaulo Zanoni } 20068eb49b1SPaulo Zanoni 201337ba017SPaulo Zanoni /* 202337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 203337ba017SPaulo Zanoni */ 20465f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) 205b51a2842SVille Syrjälä { 20665f42cdcSPaulo Zanoni u32 val = intel_uncore_read(uncore, reg); 207b51a2842SVille Syrjälä 208b51a2842SVille Syrjälä if (val == 0) 209b51a2842SVille Syrjälä return; 210b51a2842SVille Syrjälä 211b51a2842SVille Syrjälä WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", 212f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 21365f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 21465f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 21565f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 21665f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 217b51a2842SVille Syrjälä } 218337ba017SPaulo Zanoni 21965f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore) 220e9e9848aSVille Syrjälä { 22165f42cdcSPaulo Zanoni u16 val = intel_uncore_read16(uncore, GEN2_IIR); 222e9e9848aSVille Syrjälä 223e9e9848aSVille Syrjälä if (val == 0) 224e9e9848aSVille Syrjälä return; 225e9e9848aSVille Syrjälä 226e9e9848aSVille Syrjälä WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", 2279d9523d8SPaulo Zanoni i915_mmio_reg_offset(GEN2_IIR), val); 22865f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 22965f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 23065f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 23165f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 232e9e9848aSVille Syrjälä } 233e9e9848aSVille Syrjälä 234cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore, 23568eb49b1SPaulo Zanoni i915_reg_t imr, u32 imr_val, 23668eb49b1SPaulo Zanoni i915_reg_t ier, u32 ier_val, 23768eb49b1SPaulo Zanoni i915_reg_t iir) 23868eb49b1SPaulo Zanoni { 23965f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(uncore, iir); 24035079899SPaulo Zanoni 24165f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, ier_val); 24265f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, imr_val); 24365f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 24468eb49b1SPaulo Zanoni } 24535079899SPaulo Zanoni 246cf1c97dcSAndi Shyti void gen2_irq_init(struct intel_uncore *uncore, 2472918c3caSPaulo Zanoni u32 imr_val, u32 ier_val) 24868eb49b1SPaulo Zanoni { 24965f42cdcSPaulo Zanoni gen2_assert_iir_is_zero(uncore); 25068eb49b1SPaulo Zanoni 25165f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, ier_val); 25265f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, imr_val); 25365f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 25468eb49b1SPaulo Zanoni } 25568eb49b1SPaulo Zanoni 2560706f17cSEgbert Eich /* For display hotplug interrupt */ 2570706f17cSEgbert Eich static inline void 2580706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, 259a9c287c9SJani Nikula u32 mask, 260a9c287c9SJani Nikula u32 bits) 2610706f17cSEgbert Eich { 262a9c287c9SJani Nikula u32 val; 2630706f17cSEgbert Eich 26467520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 2650706f17cSEgbert Eich WARN_ON(bits & ~mask); 2660706f17cSEgbert Eich 2670706f17cSEgbert Eich val = I915_READ(PORT_HOTPLUG_EN); 2680706f17cSEgbert Eich val &= ~mask; 2690706f17cSEgbert Eich val |= bits; 2700706f17cSEgbert Eich I915_WRITE(PORT_HOTPLUG_EN, val); 2710706f17cSEgbert Eich } 2720706f17cSEgbert Eich 2730706f17cSEgbert Eich /** 2740706f17cSEgbert Eich * i915_hotplug_interrupt_update - update hotplug interrupt enable 2750706f17cSEgbert Eich * @dev_priv: driver private 2760706f17cSEgbert Eich * @mask: bits to update 2770706f17cSEgbert Eich * @bits: bits to enable 2780706f17cSEgbert Eich * NOTE: the HPD enable bits are modified both inside and outside 2790706f17cSEgbert Eich * of an interrupt context. To avoid that read-modify-write cycles 2800706f17cSEgbert Eich * interfer, these bits are protected by a spinlock. Since this 2810706f17cSEgbert Eich * function is usually not called from a context where the lock is 2820706f17cSEgbert Eich * held already, this function acquires the lock itself. A non-locking 2830706f17cSEgbert Eich * version is also available. 2840706f17cSEgbert Eich */ 2850706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, 286a9c287c9SJani Nikula u32 mask, 287a9c287c9SJani Nikula u32 bits) 2880706f17cSEgbert Eich { 2890706f17cSEgbert Eich spin_lock_irq(&dev_priv->irq_lock); 2900706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); 2910706f17cSEgbert Eich spin_unlock_irq(&dev_priv->irq_lock); 2920706f17cSEgbert Eich } 2930706f17cSEgbert Eich 294d9dc34f1SVille Syrjälä /** 295d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 296d9dc34f1SVille Syrjälä * @dev_priv: driver private 297d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 298d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 299d9dc34f1SVille Syrjälä */ 300fbdedaeaSVille Syrjälä void ilk_update_display_irq(struct drm_i915_private *dev_priv, 301a9c287c9SJani Nikula u32 interrupt_mask, 302a9c287c9SJani Nikula u32 enabled_irq_mask) 303036a4a7dSZhenyu Wang { 304a9c287c9SJani Nikula u32 new_val; 305d9dc34f1SVille Syrjälä 30667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3074bc9d430SDaniel Vetter 308d9dc34f1SVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 309d9dc34f1SVille Syrjälä 3109df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 311c67a470bSPaulo Zanoni return; 312c67a470bSPaulo Zanoni 313d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 314d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 315d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 316d9dc34f1SVille Syrjälä 317d9dc34f1SVille Syrjälä if (new_val != dev_priv->irq_mask) { 318d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 3191ec14ad3SChris Wilson I915_WRITE(DEIMR, dev_priv->irq_mask); 3203143a2bfSChris Wilson POSTING_READ(DEIMR); 321036a4a7dSZhenyu Wang } 322036a4a7dSZhenyu Wang } 323036a4a7dSZhenyu Wang 324f0f59a00SVille Syrjälä static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) 325b900b949SImre Deak { 326d02b98b8SOscar Mateo WARN_ON_ONCE(INTEL_GEN(dev_priv) >= 11); 327d02b98b8SOscar Mateo 328bca2bf2aSPandiyan, Dhinakaran return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; 329b900b949SImre Deak } 330b900b949SImre Deak 3319cbd51c2SDaniele Ceraolo Spurio void gen9_reset_guc_interrupts(struct intel_guc *guc) 33226705e20SSagar Arun Kamble { 3332239e6dfSDaniele Ceraolo Spurio struct intel_gt *gt = guc_to_gt(guc); 3349cbd51c2SDaniele Ceraolo Spurio 335cd6a8513SChris Wilson assert_rpm_wakelock_held(gt->uncore->rpm); 3361be333d3SSagar Arun Kamble 337d762043fSAndi Shyti spin_lock_irq(>->irq_lock); 338d762043fSAndi Shyti gen6_gt_pm_reset_iir(gt, gt->pm_guc_events); 339d762043fSAndi Shyti spin_unlock_irq(>->irq_lock); 34026705e20SSagar Arun Kamble } 34126705e20SSagar Arun Kamble 3429cbd51c2SDaniele Ceraolo Spurio void gen9_enable_guc_interrupts(struct intel_guc *guc) 34326705e20SSagar Arun Kamble { 3442239e6dfSDaniele Ceraolo Spurio struct intel_gt *gt = guc_to_gt(guc); 3459cbd51c2SDaniele Ceraolo Spurio 346cd6a8513SChris Wilson assert_rpm_wakelock_held(gt->uncore->rpm); 3471be333d3SSagar Arun Kamble 348d762043fSAndi Shyti spin_lock_irq(>->irq_lock); 3499cbd51c2SDaniele Ceraolo Spurio if (!guc->interrupts.enabled) { 350d762043fSAndi Shyti WARN_ON_ONCE(intel_uncore_read(gt->uncore, 351d762043fSAndi Shyti gen6_pm_iir(gt->i915)) & 3522239e6dfSDaniele Ceraolo Spurio gt->pm_guc_events); 3539cbd51c2SDaniele Ceraolo Spurio guc->interrupts.enabled = true; 354d762043fSAndi Shyti gen6_gt_pm_enable_irq(gt, gt->pm_guc_events); 35526705e20SSagar Arun Kamble } 356d762043fSAndi Shyti spin_unlock_irq(>->irq_lock); 35726705e20SSagar Arun Kamble } 35826705e20SSagar Arun Kamble 3599cbd51c2SDaniele Ceraolo Spurio void gen9_disable_guc_interrupts(struct intel_guc *guc) 36026705e20SSagar Arun Kamble { 3612239e6dfSDaniele Ceraolo Spurio struct intel_gt *gt = guc_to_gt(guc); 3629cbd51c2SDaniele Ceraolo Spurio 363cd6a8513SChris Wilson assert_rpm_wakelock_held(gt->uncore->rpm); 3641be333d3SSagar Arun Kamble 365d762043fSAndi Shyti spin_lock_irq(>->irq_lock); 3669cbd51c2SDaniele Ceraolo Spurio guc->interrupts.enabled = false; 36726705e20SSagar Arun Kamble 368d762043fSAndi Shyti gen6_gt_pm_disable_irq(gt, gt->pm_guc_events); 36926705e20SSagar Arun Kamble 370d762043fSAndi Shyti spin_unlock_irq(>->irq_lock); 371d762043fSAndi Shyti intel_synchronize_irq(gt->i915); 37226705e20SSagar Arun Kamble 3739cbd51c2SDaniele Ceraolo Spurio gen9_reset_guc_interrupts(guc); 37426705e20SSagar Arun Kamble } 37526705e20SSagar Arun Kamble 3769cbd51c2SDaniele Ceraolo Spurio void gen11_reset_guc_interrupts(struct intel_guc *guc) 37754c52a84SOscar Mateo { 3782239e6dfSDaniele Ceraolo Spurio struct intel_gt *gt = guc_to_gt(guc); 3799cbd51c2SDaniele Ceraolo Spurio 380d762043fSAndi Shyti spin_lock_irq(>->irq_lock); 381cf1c97dcSAndi Shyti gen11_gt_reset_one_iir(gt, 0, GEN11_GUC); 382d762043fSAndi Shyti spin_unlock_irq(>->irq_lock); 38354c52a84SOscar Mateo } 38454c52a84SOscar Mateo 3859cbd51c2SDaniele Ceraolo Spurio void gen11_enable_guc_interrupts(struct intel_guc *guc) 38654c52a84SOscar Mateo { 3872239e6dfSDaniele Ceraolo Spurio struct intel_gt *gt = guc_to_gt(guc); 3889cbd51c2SDaniele Ceraolo Spurio 389d762043fSAndi Shyti spin_lock_irq(>->irq_lock); 3909cbd51c2SDaniele Ceraolo Spurio if (!guc->interrupts.enabled) { 391633023a4SDaniele Ceraolo Spurio u32 events = REG_FIELD_PREP(ENGINE1_MASK, GUC_INTR_GUC2HOST); 39254c52a84SOscar Mateo 393cf1c97dcSAndi Shyti WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_GUC)); 3942239e6dfSDaniele Ceraolo Spurio intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_ENABLE, events); 3952239e6dfSDaniele Ceraolo Spurio intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_MASK, ~events); 3969cbd51c2SDaniele Ceraolo Spurio guc->interrupts.enabled = true; 39754c52a84SOscar Mateo } 398d762043fSAndi Shyti spin_unlock_irq(>->irq_lock); 39954c52a84SOscar Mateo } 40054c52a84SOscar Mateo 4019cbd51c2SDaniele Ceraolo Spurio void gen11_disable_guc_interrupts(struct intel_guc *guc) 40254c52a84SOscar Mateo { 4032239e6dfSDaniele Ceraolo Spurio struct intel_gt *gt = guc_to_gt(guc); 4049cbd51c2SDaniele Ceraolo Spurio 405d762043fSAndi Shyti spin_lock_irq(>->irq_lock); 4069cbd51c2SDaniele Ceraolo Spurio guc->interrupts.enabled = false; 40754c52a84SOscar Mateo 4082239e6dfSDaniele Ceraolo Spurio intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_MASK, ~0); 4092239e6dfSDaniele Ceraolo Spurio intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_ENABLE, 0); 41054c52a84SOscar Mateo 411d762043fSAndi Shyti spin_unlock_irq(>->irq_lock); 412d762043fSAndi Shyti intel_synchronize_irq(gt->i915); 41354c52a84SOscar Mateo 4149cbd51c2SDaniele Ceraolo Spurio gen11_reset_guc_interrupts(guc); 41554c52a84SOscar Mateo } 41654c52a84SOscar Mateo 4170961021aSBen Widawsky /** 4183a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 4193a3b3c7dSVille Syrjälä * @dev_priv: driver private 4203a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 4213a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 4223a3b3c7dSVille Syrjälä */ 4233a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv, 424a9c287c9SJani Nikula u32 interrupt_mask, 425a9c287c9SJani Nikula u32 enabled_irq_mask) 4263a3b3c7dSVille Syrjälä { 427a9c287c9SJani Nikula u32 new_val; 428a9c287c9SJani Nikula u32 old_val; 4293a3b3c7dSVille Syrjälä 43067520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4313a3b3c7dSVille Syrjälä 4323a3b3c7dSVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 4333a3b3c7dSVille Syrjälä 4343a3b3c7dSVille Syrjälä if (WARN_ON(!intel_irqs_enabled(dev_priv))) 4353a3b3c7dSVille Syrjälä return; 4363a3b3c7dSVille Syrjälä 4373a3b3c7dSVille Syrjälä old_val = I915_READ(GEN8_DE_PORT_IMR); 4383a3b3c7dSVille Syrjälä 4393a3b3c7dSVille Syrjälä new_val = old_val; 4403a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 4413a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 4423a3b3c7dSVille Syrjälä 4433a3b3c7dSVille Syrjälä if (new_val != old_val) { 4443a3b3c7dSVille Syrjälä I915_WRITE(GEN8_DE_PORT_IMR, new_val); 4453a3b3c7dSVille Syrjälä POSTING_READ(GEN8_DE_PORT_IMR); 4463a3b3c7dSVille Syrjälä } 4473a3b3c7dSVille Syrjälä } 4483a3b3c7dSVille Syrjälä 4493a3b3c7dSVille Syrjälä /** 450013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 451013d3752SVille Syrjälä * @dev_priv: driver private 452013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 453013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 454013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 455013d3752SVille Syrjälä */ 456013d3752SVille Syrjälä void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 457013d3752SVille Syrjälä enum pipe pipe, 458a9c287c9SJani Nikula u32 interrupt_mask, 459a9c287c9SJani Nikula u32 enabled_irq_mask) 460013d3752SVille Syrjälä { 461a9c287c9SJani Nikula u32 new_val; 462013d3752SVille Syrjälä 46367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 464013d3752SVille Syrjälä 465013d3752SVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 466013d3752SVille Syrjälä 467013d3752SVille Syrjälä if (WARN_ON(!intel_irqs_enabled(dev_priv))) 468013d3752SVille Syrjälä return; 469013d3752SVille Syrjälä 470013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 471013d3752SVille Syrjälä new_val &= ~interrupt_mask; 472013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 473013d3752SVille Syrjälä 474013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 475013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 476013d3752SVille Syrjälä I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 477013d3752SVille Syrjälä POSTING_READ(GEN8_DE_PIPE_IMR(pipe)); 478013d3752SVille Syrjälä } 479013d3752SVille Syrjälä } 480013d3752SVille Syrjälä 481013d3752SVille Syrjälä /** 482fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 483fee884edSDaniel Vetter * @dev_priv: driver private 484fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 485fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 486fee884edSDaniel Vetter */ 48747339cd9SDaniel Vetter void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 488a9c287c9SJani Nikula u32 interrupt_mask, 489a9c287c9SJani Nikula u32 enabled_irq_mask) 490fee884edSDaniel Vetter { 491a9c287c9SJani Nikula u32 sdeimr = I915_READ(SDEIMR); 492fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 493fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 494fee884edSDaniel Vetter 49515a17aaeSDaniel Vetter WARN_ON(enabled_irq_mask & ~interrupt_mask); 49615a17aaeSDaniel Vetter 49767520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 498fee884edSDaniel Vetter 4999df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 500c67a470bSPaulo Zanoni return; 501c67a470bSPaulo Zanoni 502fee884edSDaniel Vetter I915_WRITE(SDEIMR, sdeimr); 503fee884edSDaniel Vetter POSTING_READ(SDEIMR); 504fee884edSDaniel Vetter } 5058664281bSPaulo Zanoni 5066b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 5076b12ca56SVille Syrjälä enum pipe pipe) 5087c463586SKeith Packard { 5096b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 51010c59c51SImre Deak u32 enable_mask = status_mask << 16; 51110c59c51SImre Deak 5126b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 5136b12ca56SVille Syrjälä 5146b12ca56SVille Syrjälä if (INTEL_GEN(dev_priv) < 5) 5156b12ca56SVille Syrjälä goto out; 5166b12ca56SVille Syrjälä 51710c59c51SImre Deak /* 518724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 519724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 52010c59c51SImre Deak */ 52110c59c51SImre Deak if (WARN_ON_ONCE(status_mask & PIPE_A_PSR_STATUS_VLV)) 52210c59c51SImre Deak return 0; 523724a6905SVille Syrjälä /* 524724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 525724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 526724a6905SVille Syrjälä */ 527724a6905SVille Syrjälä if (WARN_ON_ONCE(status_mask & PIPE_B_PSR_STATUS_VLV)) 528724a6905SVille Syrjälä return 0; 52910c59c51SImre Deak 53010c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 53110c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 53210c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 53310c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 53410c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 53510c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 53610c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 53710c59c51SImre Deak 5386b12ca56SVille Syrjälä out: 5396b12ca56SVille Syrjälä WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 5406b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 5416b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 5426b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 5436b12ca56SVille Syrjälä 54410c59c51SImre Deak return enable_mask; 54510c59c51SImre Deak } 54610c59c51SImre Deak 5476b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 5486b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 549755e9019SImre Deak { 5506b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 551755e9019SImre Deak u32 enable_mask; 552755e9019SImre Deak 5536b12ca56SVille Syrjälä WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, 5546b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5556b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5566b12ca56SVille Syrjälä 5576b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 5586b12ca56SVille Syrjälä WARN_ON(!intel_irqs_enabled(dev_priv)); 5596b12ca56SVille Syrjälä 5606b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 5616b12ca56SVille Syrjälä return; 5626b12ca56SVille Syrjälä 5636b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 5646b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5656b12ca56SVille Syrjälä 5666b12ca56SVille Syrjälä I915_WRITE(reg, enable_mask | status_mask); 5676b12ca56SVille Syrjälä POSTING_READ(reg); 568755e9019SImre Deak } 569755e9019SImre Deak 5706b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 5716b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 572755e9019SImre Deak { 5736b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 574755e9019SImre Deak u32 enable_mask; 575755e9019SImre Deak 5766b12ca56SVille Syrjälä WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, 5776b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5786b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5796b12ca56SVille Syrjälä 5806b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 5816b12ca56SVille Syrjälä WARN_ON(!intel_irqs_enabled(dev_priv)); 5826b12ca56SVille Syrjälä 5836b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 5846b12ca56SVille Syrjälä return; 5856b12ca56SVille Syrjälä 5866b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 5876b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5886b12ca56SVille Syrjälä 5896b12ca56SVille Syrjälä I915_WRITE(reg, enable_mask | status_mask); 5906b12ca56SVille Syrjälä POSTING_READ(reg); 591755e9019SImre Deak } 592755e9019SImre Deak 593f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 594f3e30485SVille Syrjälä { 595f3e30485SVille Syrjälä if (!dev_priv->opregion.asle) 596f3e30485SVille Syrjälä return false; 597f3e30485SVille Syrjälä 598f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 599f3e30485SVille Syrjälä } 600f3e30485SVille Syrjälä 601c0e09200SDave Airlie /** 602f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 60314bb2c11STvrtko Ursulin * @dev_priv: i915 device private 60401c66889SZhao Yakui */ 60591d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 60601c66889SZhao Yakui { 607f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 608f49e38ddSJani Nikula return; 609f49e38ddSJani Nikula 61013321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 61101c66889SZhao Yakui 612755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 61391d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 4) 6143b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 615755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 6161ec14ad3SChris Wilson 61713321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 61801c66889SZhao Yakui } 61901c66889SZhao Yakui 620f75f3746SVille Syrjälä /* 621f75f3746SVille Syrjälä * This timing diagram depicts the video signal in and 622f75f3746SVille Syrjälä * around the vertical blanking period. 623f75f3746SVille Syrjälä * 624f75f3746SVille Syrjälä * Assumptions about the fictitious mode used in this example: 625f75f3746SVille Syrjälä * vblank_start >= 3 626f75f3746SVille Syrjälä * vsync_start = vblank_start + 1 627f75f3746SVille Syrjälä * vsync_end = vblank_start + 2 628f75f3746SVille Syrjälä * vtotal = vblank_start + 3 629f75f3746SVille Syrjälä * 630f75f3746SVille Syrjälä * start of vblank: 631f75f3746SVille Syrjälä * latch double buffered registers 632f75f3746SVille Syrjälä * increment frame counter (ctg+) 633f75f3746SVille Syrjälä * generate start of vblank interrupt (gen4+) 634f75f3746SVille Syrjälä * | 635f75f3746SVille Syrjälä * | frame start: 636f75f3746SVille Syrjälä * | generate frame start interrupt (aka. vblank interrupt) (gmch) 637f75f3746SVille Syrjälä * | may be shifted forward 1-3 extra lines via PIPECONF 638f75f3746SVille Syrjälä * | | 639f75f3746SVille Syrjälä * | | start of vsync: 640f75f3746SVille Syrjälä * | | generate vsync interrupt 641f75f3746SVille Syrjälä * | | | 642f75f3746SVille Syrjälä * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx 643f75f3746SVille Syrjälä * . \hs/ . \hs/ \hs/ \hs/ . \hs/ 644f75f3746SVille Syrjälä * ----va---> <-----------------vb--------------------> <--------va------------- 645f75f3746SVille Syrjälä * | | <----vs-----> | 646f75f3746SVille Syrjälä * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) 647f75f3746SVille Syrjälä * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) 648f75f3746SVille Syrjälä * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) 649f75f3746SVille Syrjälä * | | | 650f75f3746SVille Syrjälä * last visible pixel first visible pixel 651f75f3746SVille Syrjälä * | increment frame counter (gen3/4) 652f75f3746SVille Syrjälä * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) 653f75f3746SVille Syrjälä * 654f75f3746SVille Syrjälä * x = horizontal active 655f75f3746SVille Syrjälä * _ = horizontal blanking 656f75f3746SVille Syrjälä * hs = horizontal sync 657f75f3746SVille Syrjälä * va = vertical active 658f75f3746SVille Syrjälä * vb = vertical blanking 659f75f3746SVille Syrjälä * vs = vertical sync 660f75f3746SVille Syrjälä * vbs = vblank_start (number) 661f75f3746SVille Syrjälä * 662f75f3746SVille Syrjälä * Summary: 663f75f3746SVille Syrjälä * - most events happen at the start of horizontal sync 664f75f3746SVille Syrjälä * - frame start happens at the start of horizontal blank, 1-4 lines 665f75f3746SVille Syrjälä * (depending on PIPECONF settings) after the start of vblank 666f75f3746SVille Syrjälä * - gen3/4 pixel and frame counter are synchronized with the start 667f75f3746SVille Syrjälä * of horizontal active on the first line of vertical active 668f75f3746SVille Syrjälä */ 669f75f3746SVille Syrjälä 67042f52ef8SKeith Packard /* Called from drm generic code, passed a 'crtc', which 67142f52ef8SKeith Packard * we use as a pipe index 67242f52ef8SKeith Packard */ 67308fa8fd0SVille Syrjälä u32 i915_get_vblank_counter(struct drm_crtc *crtc) 6740a3e67a4SJesse Barnes { 67508fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 67608fa8fd0SVille Syrjälä struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; 67732db0b65SVille Syrjälä const struct drm_display_mode *mode = &vblank->hwmode; 67808fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 679f0f59a00SVille Syrjälä i915_reg_t high_frame, low_frame; 6800b2a8e09SVille Syrjälä u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; 681694e409dSVille Syrjälä unsigned long irqflags; 682391f75e2SVille Syrjälä 68332db0b65SVille Syrjälä /* 68432db0b65SVille Syrjälä * On i965gm TV output the frame counter only works up to 68532db0b65SVille Syrjälä * the point when we enable the TV encoder. After that the 68632db0b65SVille Syrjälä * frame counter ceases to work and reads zero. We need a 68732db0b65SVille Syrjälä * vblank wait before enabling the TV encoder and so we 68832db0b65SVille Syrjälä * have to enable vblank interrupts while the frame counter 68932db0b65SVille Syrjälä * is still in a working state. However the core vblank code 69032db0b65SVille Syrjälä * does not like us returning non-zero frame counter values 69132db0b65SVille Syrjälä * when we've told it that we don't have a working frame 69232db0b65SVille Syrjälä * counter. Thus we must stop non-zero values leaking out. 69332db0b65SVille Syrjälä */ 69432db0b65SVille Syrjälä if (!vblank->max_vblank_count) 69532db0b65SVille Syrjälä return 0; 69632db0b65SVille Syrjälä 6970b2a8e09SVille Syrjälä htotal = mode->crtc_htotal; 6980b2a8e09SVille Syrjälä hsync_start = mode->crtc_hsync_start; 6990b2a8e09SVille Syrjälä vbl_start = mode->crtc_vblank_start; 7000b2a8e09SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 7010b2a8e09SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 702391f75e2SVille Syrjälä 7030b2a8e09SVille Syrjälä /* Convert to pixel count */ 7040b2a8e09SVille Syrjälä vbl_start *= htotal; 7050b2a8e09SVille Syrjälä 7060b2a8e09SVille Syrjälä /* Start of vblank event occurs at start of hsync */ 7070b2a8e09SVille Syrjälä vbl_start -= htotal - hsync_start; 7080b2a8e09SVille Syrjälä 7099db4a9c7SJesse Barnes high_frame = PIPEFRAME(pipe); 7109db4a9c7SJesse Barnes low_frame = PIPEFRAMEPIXEL(pipe); 7115eddb70bSChris Wilson 712694e409dSVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 713694e409dSVille Syrjälä 7140a3e67a4SJesse Barnes /* 7150a3e67a4SJesse Barnes * High & low register fields aren't synchronized, so make sure 7160a3e67a4SJesse Barnes * we get a low value that's stable across two reads of the high 7170a3e67a4SJesse Barnes * register. 7180a3e67a4SJesse Barnes */ 7190a3e67a4SJesse Barnes do { 720694e409dSVille Syrjälä high1 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK; 721694e409dSVille Syrjälä low = I915_READ_FW(low_frame); 722694e409dSVille Syrjälä high2 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK; 7230a3e67a4SJesse Barnes } while (high1 != high2); 7240a3e67a4SJesse Barnes 725694e409dSVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 726694e409dSVille Syrjälä 7275eddb70bSChris Wilson high1 >>= PIPE_FRAME_HIGH_SHIFT; 728391f75e2SVille Syrjälä pixel = low & PIPE_PIXEL_MASK; 7295eddb70bSChris Wilson low >>= PIPE_FRAME_LOW_SHIFT; 730391f75e2SVille Syrjälä 731391f75e2SVille Syrjälä /* 732391f75e2SVille Syrjälä * The frame counter increments at beginning of active. 733391f75e2SVille Syrjälä * Cook up a vblank counter by also checking the pixel 734391f75e2SVille Syrjälä * counter against vblank start. 735391f75e2SVille Syrjälä */ 736edc08d0aSVille Syrjälä return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; 7370a3e67a4SJesse Barnes } 7380a3e67a4SJesse Barnes 73908fa8fd0SVille Syrjälä u32 g4x_get_vblank_counter(struct drm_crtc *crtc) 7409880b7a5SJesse Barnes { 74108fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 74208fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 7439880b7a5SJesse Barnes 744649636efSVille Syrjälä return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); 7459880b7a5SJesse Barnes } 7469880b7a5SJesse Barnes 747aec0246fSUma Shankar /* 748aec0246fSUma Shankar * On certain encoders on certain platforms, pipe 749aec0246fSUma Shankar * scanline register will not work to get the scanline, 750aec0246fSUma Shankar * since the timings are driven from the PORT or issues 751aec0246fSUma Shankar * with scanline register updates. 752aec0246fSUma Shankar * This function will use Framestamp and current 753aec0246fSUma Shankar * timestamp registers to calculate the scanline. 754aec0246fSUma Shankar */ 755aec0246fSUma Shankar static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) 756aec0246fSUma Shankar { 757aec0246fSUma Shankar struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 758aec0246fSUma Shankar struct drm_vblank_crtc *vblank = 759aec0246fSUma Shankar &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 760aec0246fSUma Shankar const struct drm_display_mode *mode = &vblank->hwmode; 761aec0246fSUma Shankar u32 vblank_start = mode->crtc_vblank_start; 762aec0246fSUma Shankar u32 vtotal = mode->crtc_vtotal; 763aec0246fSUma Shankar u32 htotal = mode->crtc_htotal; 764aec0246fSUma Shankar u32 clock = mode->crtc_clock; 765aec0246fSUma Shankar u32 scanline, scan_prev_time, scan_curr_time, scan_post_time; 766aec0246fSUma Shankar 767aec0246fSUma Shankar /* 768aec0246fSUma Shankar * To avoid the race condition where we might cross into the 769aec0246fSUma Shankar * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR 770aec0246fSUma Shankar * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR 771aec0246fSUma Shankar * during the same frame. 772aec0246fSUma Shankar */ 773aec0246fSUma Shankar do { 774aec0246fSUma Shankar /* 775aec0246fSUma Shankar * This field provides read back of the display 776aec0246fSUma Shankar * pipe frame time stamp. The time stamp value 777aec0246fSUma Shankar * is sampled at every start of vertical blank. 778aec0246fSUma Shankar */ 779aec0246fSUma Shankar scan_prev_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); 780aec0246fSUma Shankar 781aec0246fSUma Shankar /* 782aec0246fSUma Shankar * The TIMESTAMP_CTR register has the current 783aec0246fSUma Shankar * time stamp value. 784aec0246fSUma Shankar */ 785aec0246fSUma Shankar scan_curr_time = I915_READ_FW(IVB_TIMESTAMP_CTR); 786aec0246fSUma Shankar 787aec0246fSUma Shankar scan_post_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); 788aec0246fSUma Shankar } while (scan_post_time != scan_prev_time); 789aec0246fSUma Shankar 790aec0246fSUma Shankar scanline = div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, 791aec0246fSUma Shankar clock), 1000 * htotal); 792aec0246fSUma Shankar scanline = min(scanline, vtotal - 1); 793aec0246fSUma Shankar scanline = (scanline + vblank_start) % vtotal; 794aec0246fSUma Shankar 795aec0246fSUma Shankar return scanline; 796aec0246fSUma Shankar } 797aec0246fSUma Shankar 79875aa3f63SVille Syrjälä /* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */ 799a225f079SVille Syrjälä static int __intel_get_crtc_scanline(struct intel_crtc *crtc) 800a225f079SVille Syrjälä { 801a225f079SVille Syrjälä struct drm_device *dev = crtc->base.dev; 802fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 8035caa0feaSDaniel Vetter const struct drm_display_mode *mode; 8045caa0feaSDaniel Vetter struct drm_vblank_crtc *vblank; 805a225f079SVille Syrjälä enum pipe pipe = crtc->pipe; 80680715b2fSVille Syrjälä int position, vtotal; 807a225f079SVille Syrjälä 80872259536SVille Syrjälä if (!crtc->active) 80972259536SVille Syrjälä return -1; 81072259536SVille Syrjälä 8115caa0feaSDaniel Vetter vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 8125caa0feaSDaniel Vetter mode = &vblank->hwmode; 8135caa0feaSDaniel Vetter 814aec0246fSUma Shankar if (mode->private_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) 815aec0246fSUma Shankar return __intel_get_crtc_scanline_from_timestamp(crtc); 816aec0246fSUma Shankar 81780715b2fSVille Syrjälä vtotal = mode->crtc_vtotal; 818a225f079SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 819a225f079SVille Syrjälä vtotal /= 2; 820a225f079SVille Syrjälä 821cf819effSLucas De Marchi if (IS_GEN(dev_priv, 2)) 82275aa3f63SVille Syrjälä position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; 823a225f079SVille Syrjälä else 82475aa3f63SVille Syrjälä position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 825a225f079SVille Syrjälä 826a225f079SVille Syrjälä /* 82741b578fbSJesse Barnes * On HSW, the DSL reg (0x70000) appears to return 0 if we 82841b578fbSJesse Barnes * read it just before the start of vblank. So try it again 82941b578fbSJesse Barnes * so we don't accidentally end up spanning a vblank frame 83041b578fbSJesse Barnes * increment, causing the pipe_update_end() code to squak at us. 83141b578fbSJesse Barnes * 83241b578fbSJesse Barnes * The nature of this problem means we can't simply check the ISR 83341b578fbSJesse Barnes * bit and return the vblank start value; nor can we use the scanline 83441b578fbSJesse Barnes * debug register in the transcoder as it appears to have the same 83541b578fbSJesse Barnes * problem. We may need to extend this to include other platforms, 83641b578fbSJesse Barnes * but so far testing only shows the problem on HSW. 83741b578fbSJesse Barnes */ 83891d14251STvrtko Ursulin if (HAS_DDI(dev_priv) && !position) { 83941b578fbSJesse Barnes int i, temp; 84041b578fbSJesse Barnes 84141b578fbSJesse Barnes for (i = 0; i < 100; i++) { 84241b578fbSJesse Barnes udelay(1); 843707bdd3fSVille Syrjälä temp = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 84441b578fbSJesse Barnes if (temp != position) { 84541b578fbSJesse Barnes position = temp; 84641b578fbSJesse Barnes break; 84741b578fbSJesse Barnes } 84841b578fbSJesse Barnes } 84941b578fbSJesse Barnes } 85041b578fbSJesse Barnes 85141b578fbSJesse Barnes /* 85280715b2fSVille Syrjälä * See update_scanline_offset() for the details on the 85380715b2fSVille Syrjälä * scanline_offset adjustment. 854a225f079SVille Syrjälä */ 85580715b2fSVille Syrjälä return (position + crtc->scanline_offset) % vtotal; 856a225f079SVille Syrjälä } 857a225f079SVille Syrjälä 858e8edae54SVille Syrjälä bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int index, 8591bf6ad62SDaniel Vetter bool in_vblank_irq, int *vpos, int *hpos, 8603bb403bfSVille Syrjälä ktime_t *stime, ktime_t *etime, 8613bb403bfSVille Syrjälä const struct drm_display_mode *mode) 8620af7e4dfSMario Kleiner { 863fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 864e8edae54SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(drm_crtc_from_index(dev, index)); 865e8edae54SVille Syrjälä enum pipe pipe = crtc->pipe; 8663aa18df8SVille Syrjälä int position; 86778e8fc6bSVille Syrjälä int vbl_start, vbl_end, hsync_start, htotal, vtotal; 868ad3543edSMario Kleiner unsigned long irqflags; 8698a920e24SVille Syrjälä bool use_scanline_counter = INTEL_GEN(dev_priv) >= 5 || 8708a920e24SVille Syrjälä IS_G4X(dev_priv) || IS_GEN(dev_priv, 2) || 8718a920e24SVille Syrjälä mode->private_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; 8720af7e4dfSMario Kleiner 873fc467a22SMaarten Lankhorst if (WARN_ON(!mode->crtc_clock)) { 8740af7e4dfSMario Kleiner DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " 8759db4a9c7SJesse Barnes "pipe %c\n", pipe_name(pipe)); 8761bf6ad62SDaniel Vetter return false; 8770af7e4dfSMario Kleiner } 8780af7e4dfSMario Kleiner 879c2baf4b7SVille Syrjälä htotal = mode->crtc_htotal; 88078e8fc6bSVille Syrjälä hsync_start = mode->crtc_hsync_start; 881c2baf4b7SVille Syrjälä vtotal = mode->crtc_vtotal; 882c2baf4b7SVille Syrjälä vbl_start = mode->crtc_vblank_start; 883c2baf4b7SVille Syrjälä vbl_end = mode->crtc_vblank_end; 8840af7e4dfSMario Kleiner 885d31faf65SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 886d31faf65SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 887d31faf65SVille Syrjälä vbl_end /= 2; 888d31faf65SVille Syrjälä vtotal /= 2; 889d31faf65SVille Syrjälä } 890d31faf65SVille Syrjälä 891ad3543edSMario Kleiner /* 892ad3543edSMario Kleiner * Lock uncore.lock, as we will do multiple timing critical raw 893ad3543edSMario Kleiner * register reads, potentially with preemption disabled, so the 894ad3543edSMario Kleiner * following code must not block on uncore.lock. 895ad3543edSMario Kleiner */ 896ad3543edSMario Kleiner spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 897ad3543edSMario Kleiner 898ad3543edSMario Kleiner /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ 899ad3543edSMario Kleiner 900ad3543edSMario Kleiner /* Get optional system timestamp before query. */ 901ad3543edSMario Kleiner if (stime) 902ad3543edSMario Kleiner *stime = ktime_get(); 903ad3543edSMario Kleiner 9048a920e24SVille Syrjälä if (use_scanline_counter) { 9050af7e4dfSMario Kleiner /* No obvious pixelcount register. Only query vertical 9060af7e4dfSMario Kleiner * scanout position from Display scan line register. 9070af7e4dfSMario Kleiner */ 908e8edae54SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 9090af7e4dfSMario Kleiner } else { 9100af7e4dfSMario Kleiner /* Have access to pixelcount since start of frame. 9110af7e4dfSMario Kleiner * We can split this into vertical and horizontal 9120af7e4dfSMario Kleiner * scanout position. 9130af7e4dfSMario Kleiner */ 91475aa3f63SVille Syrjälä position = (I915_READ_FW(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; 9150af7e4dfSMario Kleiner 9163aa18df8SVille Syrjälä /* convert to pixel counts */ 9173aa18df8SVille Syrjälä vbl_start *= htotal; 9183aa18df8SVille Syrjälä vbl_end *= htotal; 9193aa18df8SVille Syrjälä vtotal *= htotal; 92078e8fc6bSVille Syrjälä 92178e8fc6bSVille Syrjälä /* 9227e78f1cbSVille Syrjälä * In interlaced modes, the pixel counter counts all pixels, 9237e78f1cbSVille Syrjälä * so one field will have htotal more pixels. In order to avoid 9247e78f1cbSVille Syrjälä * the reported position from jumping backwards when the pixel 9257e78f1cbSVille Syrjälä * counter is beyond the length of the shorter field, just 9267e78f1cbSVille Syrjälä * clamp the position the length of the shorter field. This 9277e78f1cbSVille Syrjälä * matches how the scanline counter based position works since 9287e78f1cbSVille Syrjälä * the scanline counter doesn't count the two half lines. 9297e78f1cbSVille Syrjälä */ 9307e78f1cbSVille Syrjälä if (position >= vtotal) 9317e78f1cbSVille Syrjälä position = vtotal - 1; 9327e78f1cbSVille Syrjälä 9337e78f1cbSVille Syrjälä /* 93478e8fc6bSVille Syrjälä * Start of vblank interrupt is triggered at start of hsync, 93578e8fc6bSVille Syrjälä * just prior to the first active line of vblank. However we 93678e8fc6bSVille Syrjälä * consider lines to start at the leading edge of horizontal 93778e8fc6bSVille Syrjälä * active. So, should we get here before we've crossed into 93878e8fc6bSVille Syrjälä * the horizontal active of the first line in vblank, we would 93978e8fc6bSVille Syrjälä * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, 94078e8fc6bSVille Syrjälä * always add htotal-hsync_start to the current pixel position. 94178e8fc6bSVille Syrjälä */ 94278e8fc6bSVille Syrjälä position = (position + htotal - hsync_start) % vtotal; 9433aa18df8SVille Syrjälä } 9443aa18df8SVille Syrjälä 945ad3543edSMario Kleiner /* Get optional system timestamp after query. */ 946ad3543edSMario Kleiner if (etime) 947ad3543edSMario Kleiner *etime = ktime_get(); 948ad3543edSMario Kleiner 949ad3543edSMario Kleiner /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ 950ad3543edSMario Kleiner 951ad3543edSMario Kleiner spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 952ad3543edSMario Kleiner 9533aa18df8SVille Syrjälä /* 9543aa18df8SVille Syrjälä * While in vblank, position will be negative 9553aa18df8SVille Syrjälä * counting up towards 0 at vbl_end. And outside 9563aa18df8SVille Syrjälä * vblank, position will be positive counting 9573aa18df8SVille Syrjälä * up since vbl_end. 9583aa18df8SVille Syrjälä */ 9593aa18df8SVille Syrjälä if (position >= vbl_start) 9603aa18df8SVille Syrjälä position -= vbl_end; 9613aa18df8SVille Syrjälä else 9623aa18df8SVille Syrjälä position += vtotal - vbl_end; 9633aa18df8SVille Syrjälä 9648a920e24SVille Syrjälä if (use_scanline_counter) { 9653aa18df8SVille Syrjälä *vpos = position; 9663aa18df8SVille Syrjälä *hpos = 0; 9673aa18df8SVille Syrjälä } else { 9680af7e4dfSMario Kleiner *vpos = position / htotal; 9690af7e4dfSMario Kleiner *hpos = position - (*vpos * htotal); 9700af7e4dfSMario Kleiner } 9710af7e4dfSMario Kleiner 9721bf6ad62SDaniel Vetter return true; 9730af7e4dfSMario Kleiner } 9740af7e4dfSMario Kleiner 975a225f079SVille Syrjälä int intel_get_crtc_scanline(struct intel_crtc *crtc) 976a225f079SVille Syrjälä { 977fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 978a225f079SVille Syrjälä unsigned long irqflags; 979a225f079SVille Syrjälä int position; 980a225f079SVille Syrjälä 981a225f079SVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 982a225f079SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 983a225f079SVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 984a225f079SVille Syrjälä 985a225f079SVille Syrjälä return position; 986a225f079SVille Syrjälä } 987a225f079SVille Syrjälä 988e3689190SBen Widawsky /** 989e3689190SBen Widawsky * ivybridge_parity_work - Workqueue called when a parity error interrupt 990e3689190SBen Widawsky * occurred. 991e3689190SBen Widawsky * @work: workqueue struct 992e3689190SBen Widawsky * 993e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 994e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 995e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 996e3689190SBen Widawsky */ 997e3689190SBen Widawsky static void ivybridge_parity_work(struct work_struct *work) 998e3689190SBen Widawsky { 9992d1013ddSJani Nikula struct drm_i915_private *dev_priv = 1000cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 1001cf1c97dcSAndi Shyti struct intel_gt *gt = &dev_priv->gt; 1002e3689190SBen Widawsky u32 error_status, row, bank, subbank; 100335a85ac6SBen Widawsky char *parity_event[6]; 1004a9c287c9SJani Nikula u32 misccpctl; 1005a9c287c9SJani Nikula u8 slice = 0; 1006e3689190SBen Widawsky 1007e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 1008e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 1009e3689190SBen Widawsky * any time we access those registers. 1010e3689190SBen Widawsky */ 101191c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 1012e3689190SBen Widawsky 101335a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 101435a85ac6SBen Widawsky if (WARN_ON(!dev_priv->l3_parity.which_slice)) 101535a85ac6SBen Widawsky goto out; 101635a85ac6SBen Widawsky 1017e3689190SBen Widawsky misccpctl = I915_READ(GEN7_MISCCPCTL); 1018e3689190SBen Widawsky I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); 1019e3689190SBen Widawsky POSTING_READ(GEN7_MISCCPCTL); 1020e3689190SBen Widawsky 102135a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 1022f0f59a00SVille Syrjälä i915_reg_t reg; 102335a85ac6SBen Widawsky 102435a85ac6SBen Widawsky slice--; 10252d1fe073SJoonas Lahtinen if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv))) 102635a85ac6SBen Widawsky break; 102735a85ac6SBen Widawsky 102835a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 102935a85ac6SBen Widawsky 10306fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 103135a85ac6SBen Widawsky 103235a85ac6SBen Widawsky error_status = I915_READ(reg); 1033e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 1034e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 1035e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 1036e3689190SBen Widawsky 103735a85ac6SBen Widawsky I915_WRITE(reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 103835a85ac6SBen Widawsky POSTING_READ(reg); 1039e3689190SBen Widawsky 1040cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 1041e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 1042e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 1043e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 104435a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 104535a85ac6SBen Widawsky parity_event[5] = NULL; 1046e3689190SBen Widawsky 104791c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 1048e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 1049e3689190SBen Widawsky 105035a85ac6SBen Widawsky DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 105135a85ac6SBen Widawsky slice, row, bank, subbank); 1052e3689190SBen Widawsky 105335a85ac6SBen Widawsky kfree(parity_event[4]); 1054e3689190SBen Widawsky kfree(parity_event[3]); 1055e3689190SBen Widawsky kfree(parity_event[2]); 1056e3689190SBen Widawsky kfree(parity_event[1]); 1057e3689190SBen Widawsky } 1058e3689190SBen Widawsky 105935a85ac6SBen Widawsky I915_WRITE(GEN7_MISCCPCTL, misccpctl); 106035a85ac6SBen Widawsky 106135a85ac6SBen Widawsky out: 106235a85ac6SBen Widawsky WARN_ON(dev_priv->l3_parity.which_slice); 1063cf1c97dcSAndi Shyti spin_lock_irq(>->irq_lock); 1064cf1c97dcSAndi Shyti gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv)); 1065cf1c97dcSAndi Shyti spin_unlock_irq(>->irq_lock); 106635a85ac6SBen Widawsky 106791c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 106835a85ac6SBen Widawsky } 106935a85ac6SBen Widawsky 1070af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1071121e758eSDhinakaran Pandiyan { 1072af92058fSVille Syrjälä switch (pin) { 1073af92058fSVille Syrjälä case HPD_PORT_C: 1074121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1); 1075af92058fSVille Syrjälä case HPD_PORT_D: 1076121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2); 1077af92058fSVille Syrjälä case HPD_PORT_E: 1078121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3); 1079af92058fSVille Syrjälä case HPD_PORT_F: 1080121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4); 1081121e758eSDhinakaran Pandiyan default: 1082121e758eSDhinakaran Pandiyan return false; 1083121e758eSDhinakaran Pandiyan } 1084121e758eSDhinakaran Pandiyan } 1085121e758eSDhinakaran Pandiyan 108648ef15d3SJosé Roberto de Souza static bool gen12_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 108748ef15d3SJosé Roberto de Souza { 108848ef15d3SJosé Roberto de Souza switch (pin) { 108948ef15d3SJosé Roberto de Souza case HPD_PORT_D: 109048ef15d3SJosé Roberto de Souza return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1); 109148ef15d3SJosé Roberto de Souza case HPD_PORT_E: 109248ef15d3SJosé Roberto de Souza return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2); 109348ef15d3SJosé Roberto de Souza case HPD_PORT_F: 109448ef15d3SJosé Roberto de Souza return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3); 109548ef15d3SJosé Roberto de Souza case HPD_PORT_G: 109648ef15d3SJosé Roberto de Souza return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4); 109748ef15d3SJosé Roberto de Souza case HPD_PORT_H: 109848ef15d3SJosé Roberto de Souza return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC5); 109948ef15d3SJosé Roberto de Souza case HPD_PORT_I: 110048ef15d3SJosé Roberto de Souza return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC6); 110148ef15d3SJosé Roberto de Souza default: 110248ef15d3SJosé Roberto de Souza return false; 110348ef15d3SJosé Roberto de Souza } 110448ef15d3SJosé Roberto de Souza } 110548ef15d3SJosé Roberto de Souza 1106af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 110763c88d22SImre Deak { 1108af92058fSVille Syrjälä switch (pin) { 1109af92058fSVille Syrjälä case HPD_PORT_A: 1110195baa06SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1111af92058fSVille Syrjälä case HPD_PORT_B: 111263c88d22SImre Deak return val & PORTB_HOTPLUG_LONG_DETECT; 1113af92058fSVille Syrjälä case HPD_PORT_C: 111463c88d22SImre Deak return val & PORTC_HOTPLUG_LONG_DETECT; 111563c88d22SImre Deak default: 111663c88d22SImre Deak return false; 111763c88d22SImre Deak } 111863c88d22SImre Deak } 111963c88d22SImre Deak 1120af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 112131604222SAnusha Srivatsa { 1122af92058fSVille Syrjälä switch (pin) { 1123af92058fSVille Syrjälä case HPD_PORT_A: 1124ed3126faSLucas De Marchi return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(PORT_A); 1125af92058fSVille Syrjälä case HPD_PORT_B: 1126ed3126faSLucas De Marchi return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(PORT_B); 11278ef7e340SMatt Roper case HPD_PORT_C: 1128ed3126faSLucas De Marchi return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(PORT_C); 112931604222SAnusha Srivatsa default: 113031604222SAnusha Srivatsa return false; 113131604222SAnusha Srivatsa } 113231604222SAnusha Srivatsa } 113331604222SAnusha Srivatsa 1134af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 113531604222SAnusha Srivatsa { 1136af92058fSVille Syrjälä switch (pin) { 1137af92058fSVille Syrjälä case HPD_PORT_C: 113831604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC1); 1139af92058fSVille Syrjälä case HPD_PORT_D: 114031604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC2); 1141af92058fSVille Syrjälä case HPD_PORT_E: 114231604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC3); 1143af92058fSVille Syrjälä case HPD_PORT_F: 114431604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC4); 114531604222SAnusha Srivatsa default: 114631604222SAnusha Srivatsa return false; 114731604222SAnusha Srivatsa } 114831604222SAnusha Srivatsa } 114931604222SAnusha Srivatsa 115052dfdba0SLucas De Marchi static bool tgp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 115152dfdba0SLucas De Marchi { 115252dfdba0SLucas De Marchi switch (pin) { 115352dfdba0SLucas De Marchi case HPD_PORT_D: 115452dfdba0SLucas De Marchi return val & ICP_TC_HPD_LONG_DETECT(PORT_TC1); 115552dfdba0SLucas De Marchi case HPD_PORT_E: 115652dfdba0SLucas De Marchi return val & ICP_TC_HPD_LONG_DETECT(PORT_TC2); 115752dfdba0SLucas De Marchi case HPD_PORT_F: 115852dfdba0SLucas De Marchi return val & ICP_TC_HPD_LONG_DETECT(PORT_TC3); 115952dfdba0SLucas De Marchi case HPD_PORT_G: 116052dfdba0SLucas De Marchi return val & ICP_TC_HPD_LONG_DETECT(PORT_TC4); 116152dfdba0SLucas De Marchi case HPD_PORT_H: 116252dfdba0SLucas De Marchi return val & ICP_TC_HPD_LONG_DETECT(PORT_TC5); 116352dfdba0SLucas De Marchi case HPD_PORT_I: 116452dfdba0SLucas De Marchi return val & ICP_TC_HPD_LONG_DETECT(PORT_TC6); 116552dfdba0SLucas De Marchi default: 116652dfdba0SLucas De Marchi return false; 116752dfdba0SLucas De Marchi } 116852dfdba0SLucas De Marchi } 116952dfdba0SLucas De Marchi 1170af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) 11716dbf30ceSVille Syrjälä { 1172af92058fSVille Syrjälä switch (pin) { 1173af92058fSVille Syrjälä case HPD_PORT_E: 11746dbf30ceSVille Syrjälä return val & PORTE_HOTPLUG_LONG_DETECT; 11756dbf30ceSVille Syrjälä default: 11766dbf30ceSVille Syrjälä return false; 11776dbf30ceSVille Syrjälä } 11786dbf30ceSVille Syrjälä } 11796dbf30ceSVille Syrjälä 1180af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 118174c0b395SVille Syrjälä { 1182af92058fSVille Syrjälä switch (pin) { 1183af92058fSVille Syrjälä case HPD_PORT_A: 118474c0b395SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1185af92058fSVille Syrjälä case HPD_PORT_B: 118674c0b395SVille Syrjälä return val & PORTB_HOTPLUG_LONG_DETECT; 1187af92058fSVille Syrjälä case HPD_PORT_C: 118874c0b395SVille Syrjälä return val & PORTC_HOTPLUG_LONG_DETECT; 1189af92058fSVille Syrjälä case HPD_PORT_D: 119074c0b395SVille Syrjälä return val & PORTD_HOTPLUG_LONG_DETECT; 119174c0b395SVille Syrjälä default: 119274c0b395SVille Syrjälä return false; 119374c0b395SVille Syrjälä } 119474c0b395SVille Syrjälä } 119574c0b395SVille Syrjälä 1196af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1197e4ce95aaSVille Syrjälä { 1198af92058fSVille Syrjälä switch (pin) { 1199af92058fSVille Syrjälä case HPD_PORT_A: 1200e4ce95aaSVille Syrjälä return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; 1201e4ce95aaSVille Syrjälä default: 1202e4ce95aaSVille Syrjälä return false; 1203e4ce95aaSVille Syrjälä } 1204e4ce95aaSVille Syrjälä } 1205e4ce95aaSVille Syrjälä 1206af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 120713cf5504SDave Airlie { 1208af92058fSVille Syrjälä switch (pin) { 1209af92058fSVille Syrjälä case HPD_PORT_B: 1210676574dfSJani Nikula return val & PORTB_HOTPLUG_LONG_DETECT; 1211af92058fSVille Syrjälä case HPD_PORT_C: 1212676574dfSJani Nikula return val & PORTC_HOTPLUG_LONG_DETECT; 1213af92058fSVille Syrjälä case HPD_PORT_D: 1214676574dfSJani Nikula return val & PORTD_HOTPLUG_LONG_DETECT; 1215676574dfSJani Nikula default: 1216676574dfSJani Nikula return false; 121713cf5504SDave Airlie } 121813cf5504SDave Airlie } 121913cf5504SDave Airlie 1220af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 122113cf5504SDave Airlie { 1222af92058fSVille Syrjälä switch (pin) { 1223af92058fSVille Syrjälä case HPD_PORT_B: 1224676574dfSJani Nikula return val & PORTB_HOTPLUG_INT_LONG_PULSE; 1225af92058fSVille Syrjälä case HPD_PORT_C: 1226676574dfSJani Nikula return val & PORTC_HOTPLUG_INT_LONG_PULSE; 1227af92058fSVille Syrjälä case HPD_PORT_D: 1228676574dfSJani Nikula return val & PORTD_HOTPLUG_INT_LONG_PULSE; 1229676574dfSJani Nikula default: 1230676574dfSJani Nikula return false; 123113cf5504SDave Airlie } 123213cf5504SDave Airlie } 123313cf5504SDave Airlie 123442db67d6SVille Syrjälä /* 123542db67d6SVille Syrjälä * Get a bit mask of pins that have triggered, and which ones may be long. 123642db67d6SVille Syrjälä * This can be called multiple times with the same masks to accumulate 123742db67d6SVille Syrjälä * hotplug detection results from several registers. 123842db67d6SVille Syrjälä * 123942db67d6SVille Syrjälä * Note that the caller is expected to zero out the masks initially. 124042db67d6SVille Syrjälä */ 1241cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, 1242cf53902fSRodrigo Vivi u32 *pin_mask, u32 *long_mask, 12438c841e57SJani Nikula u32 hotplug_trigger, u32 dig_hotplug_reg, 1244fd63e2a9SImre Deak const u32 hpd[HPD_NUM_PINS], 1245af92058fSVille Syrjälä bool long_pulse_detect(enum hpd_pin pin, u32 val)) 1246676574dfSJani Nikula { 1247e9be2850SVille Syrjälä enum hpd_pin pin; 1248676574dfSJani Nikula 124952dfdba0SLucas De Marchi BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS); 125052dfdba0SLucas De Marchi 1251e9be2850SVille Syrjälä for_each_hpd_pin(pin) { 1252e9be2850SVille Syrjälä if ((hpd[pin] & hotplug_trigger) == 0) 12538c841e57SJani Nikula continue; 12548c841e57SJani Nikula 1255e9be2850SVille Syrjälä *pin_mask |= BIT(pin); 1256676574dfSJani Nikula 1257af92058fSVille Syrjälä if (long_pulse_detect(pin, dig_hotplug_reg)) 1258e9be2850SVille Syrjälä *long_mask |= BIT(pin); 1259676574dfSJani Nikula } 1260676574dfSJani Nikula 1261f88f0478SVille Syrjälä DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n", 1262f88f0478SVille Syrjälä hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); 1263676574dfSJani Nikula 1264676574dfSJani Nikula } 1265676574dfSJani Nikula 126691d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv) 1267515ac2bbSDaniel Vetter { 126828c70f16SDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1269515ac2bbSDaniel Vetter } 1270515ac2bbSDaniel Vetter 127191d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) 1272ce99c256SDaniel Vetter { 12739ee32feaSDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1274ce99c256SDaniel Vetter } 1275ce99c256SDaniel Vetter 12768bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 127791d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 127891d14251STvrtko Ursulin enum pipe pipe, 1279a9c287c9SJani Nikula u32 crc0, u32 crc1, 1280a9c287c9SJani Nikula u32 crc2, u32 crc3, 1281a9c287c9SJani Nikula u32 crc4) 12828bf1e9f1SShuang He { 12838bf1e9f1SShuang He struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; 12848c6b709dSTomeu Vizoso struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); 12855cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 12865cee6c45SVille Syrjälä 12875cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 1288b2c88f5bSDamien Lespiau 1289d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 12908c6b709dSTomeu Vizoso /* 12918c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 12928c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 12938c6b709dSTomeu Vizoso * out the buggy result. 12948c6b709dSTomeu Vizoso * 1295163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 12968c6b709dSTomeu Vizoso * don't trust that one either. 12978c6b709dSTomeu Vizoso */ 1298033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 1299163e8aecSRodrigo Vivi (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 13008c6b709dSTomeu Vizoso pipe_crc->skipped++; 13018c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 13028c6b709dSTomeu Vizoso return; 13038c6b709dSTomeu Vizoso } 13048c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 13056cc42152SMaarten Lankhorst 1306246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 1307ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 1308246ee524STomeu Vizoso crcs); 13098c6b709dSTomeu Vizoso } 1310277de95eSDaniel Vetter #else 1311277de95eSDaniel Vetter static inline void 131291d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 131391d14251STvrtko Ursulin enum pipe pipe, 1314a9c287c9SJani Nikula u32 crc0, u32 crc1, 1315a9c287c9SJani Nikula u32 crc2, u32 crc3, 1316a9c287c9SJani Nikula u32 crc4) {} 1317277de95eSDaniel Vetter #endif 1318eba94eb9SDaniel Vetter 1319277de95eSDaniel Vetter 132091d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 132191d14251STvrtko Ursulin enum pipe pipe) 13225a69b89fSDaniel Vetter { 132391d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 13245a69b89fSDaniel Vetter I915_READ(PIPE_CRC_RES_1_IVB(pipe)), 13255a69b89fSDaniel Vetter 0, 0, 0, 0); 13265a69b89fSDaniel Vetter } 13275a69b89fSDaniel Vetter 132891d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 132991d14251STvrtko Ursulin enum pipe pipe) 1330eba94eb9SDaniel Vetter { 133191d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 1332eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_1_IVB(pipe)), 1333eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_2_IVB(pipe)), 1334eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_3_IVB(pipe)), 1335eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_4_IVB(pipe)), 13368bc5e955SDaniel Vetter I915_READ(PIPE_CRC_RES_5_IVB(pipe))); 1337eba94eb9SDaniel Vetter } 13385b3a856bSDaniel Vetter 133991d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 134091d14251STvrtko Ursulin enum pipe pipe) 13415b3a856bSDaniel Vetter { 1342a9c287c9SJani Nikula u32 res1, res2; 13430b5c5ed0SDaniel Vetter 134491d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 3) 13450b5c5ed0SDaniel Vetter res1 = I915_READ(PIPE_CRC_RES_RES1_I915(pipe)); 13460b5c5ed0SDaniel Vetter else 13470b5c5ed0SDaniel Vetter res1 = 0; 13480b5c5ed0SDaniel Vetter 134991d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) 13500b5c5ed0SDaniel Vetter res2 = I915_READ(PIPE_CRC_RES_RES2_G4X(pipe)); 13510b5c5ed0SDaniel Vetter else 13520b5c5ed0SDaniel Vetter res2 = 0; 13535b3a856bSDaniel Vetter 135491d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 13550b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_RED(pipe)), 13560b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_GREEN(pipe)), 13570b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_BLUE(pipe)), 13580b5c5ed0SDaniel Vetter res1, res2); 13595b3a856bSDaniel Vetter } 13608bf1e9f1SShuang He 136144d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 136244d9241eSVille Syrjälä { 136344d9241eSVille Syrjälä enum pipe pipe; 136444d9241eSVille Syrjälä 136544d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 136644d9241eSVille Syrjälä I915_WRITE(PIPESTAT(pipe), 136744d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 136844d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 136944d9241eSVille Syrjälä 137044d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 137144d9241eSVille Syrjälä } 137244d9241eSVille Syrjälä } 137344d9241eSVille Syrjälä 1374eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 137591d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 13767e231dbeSJesse Barnes { 1377d048a268SVille Syrjälä enum pipe pipe; 13787e231dbeSJesse Barnes 137958ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 13801ca993d2SVille Syrjälä 13811ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 13821ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 13831ca993d2SVille Syrjälä return; 13841ca993d2SVille Syrjälä } 13851ca993d2SVille Syrjälä 1386055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1387f0f59a00SVille Syrjälä i915_reg_t reg; 13886b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 138991d181ddSImre Deak 1390bbb5eebfSDaniel Vetter /* 1391bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 1392bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 1393bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 1394bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 1395bbb5eebfSDaniel Vetter * handle. 1396bbb5eebfSDaniel Vetter */ 13970f239f4cSDaniel Vetter 13980f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 13996b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 1400bbb5eebfSDaniel Vetter 1401bbb5eebfSDaniel Vetter switch (pipe) { 1402d048a268SVille Syrjälä default: 1403bbb5eebfSDaniel Vetter case PIPE_A: 1404bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 1405bbb5eebfSDaniel Vetter break; 1406bbb5eebfSDaniel Vetter case PIPE_B: 1407bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1408bbb5eebfSDaniel Vetter break; 14093278f67fSVille Syrjälä case PIPE_C: 14103278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 14113278f67fSVille Syrjälä break; 1412bbb5eebfSDaniel Vetter } 1413bbb5eebfSDaniel Vetter if (iir & iir_bit) 14146b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 1415bbb5eebfSDaniel Vetter 14166b12ca56SVille Syrjälä if (!status_mask) 141791d181ddSImre Deak continue; 141891d181ddSImre Deak 141991d181ddSImre Deak reg = PIPESTAT(pipe); 14206b12ca56SVille Syrjälä pipe_stats[pipe] = I915_READ(reg) & status_mask; 14216b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 14227e231dbeSJesse Barnes 14237e231dbeSJesse Barnes /* 14247e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 1425132c27c9SVille Syrjälä * 1426132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 1427132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 1428132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 1429132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 1430132c27c9SVille Syrjälä * an interrupt is still pending. 14317e231dbeSJesse Barnes */ 1432132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 1433132c27c9SVille Syrjälä I915_WRITE(reg, pipe_stats[pipe]); 1434132c27c9SVille Syrjälä I915_WRITE(reg, enable_mask); 1435132c27c9SVille Syrjälä } 14367e231dbeSJesse Barnes } 143758ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 14382ecb8ca4SVille Syrjälä } 14392ecb8ca4SVille Syrjälä 1440eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1441eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 1442eb64343cSVille Syrjälä { 1443eb64343cSVille Syrjälä enum pipe pipe; 1444eb64343cSVille Syrjälä 1445eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1446eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1447eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1448eb64343cSVille Syrjälä 1449eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1450eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1451eb64343cSVille Syrjälä 1452eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1453eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1454eb64343cSVille Syrjälä } 1455eb64343cSVille Syrjälä } 1456eb64343cSVille Syrjälä 1457eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1458eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1459eb64343cSVille Syrjälä { 1460eb64343cSVille Syrjälä bool blc_event = false; 1461eb64343cSVille Syrjälä enum pipe pipe; 1462eb64343cSVille Syrjälä 1463eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1464eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1465eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1466eb64343cSVille Syrjälä 1467eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1468eb64343cSVille Syrjälä blc_event = true; 1469eb64343cSVille Syrjälä 1470eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1471eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1472eb64343cSVille Syrjälä 1473eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1474eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1475eb64343cSVille Syrjälä } 1476eb64343cSVille Syrjälä 1477eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1478eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1479eb64343cSVille Syrjälä } 1480eb64343cSVille Syrjälä 1481eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1482eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1483eb64343cSVille Syrjälä { 1484eb64343cSVille Syrjälä bool blc_event = false; 1485eb64343cSVille Syrjälä enum pipe pipe; 1486eb64343cSVille Syrjälä 1487eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1488eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1489eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1490eb64343cSVille Syrjälä 1491eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1492eb64343cSVille Syrjälä blc_event = true; 1493eb64343cSVille Syrjälä 1494eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1495eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1496eb64343cSVille Syrjälä 1497eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1498eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1499eb64343cSVille Syrjälä } 1500eb64343cSVille Syrjälä 1501eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1502eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1503eb64343cSVille Syrjälä 1504eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 1505eb64343cSVille Syrjälä gmbus_irq_handler(dev_priv); 1506eb64343cSVille Syrjälä } 1507eb64343cSVille Syrjälä 150891d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 15092ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 15102ecb8ca4SVille Syrjälä { 15112ecb8ca4SVille Syrjälä enum pipe pipe; 15127e231dbeSJesse Barnes 1513055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1514fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1515fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 15164356d586SDaniel Vetter 15174356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 151891d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 15192d9d2b0bSVille Syrjälä 15201f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 15211f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 152231acc7f5SJesse Barnes } 152331acc7f5SJesse Barnes 1524c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 152591d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1526c1874ed7SImre Deak } 1527c1874ed7SImre Deak 15281ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 152916c6c56bSVille Syrjälä { 15300ba7c51aSVille Syrjälä u32 hotplug_status = 0, hotplug_status_mask; 15310ba7c51aSVille Syrjälä int i; 153216c6c56bSVille Syrjälä 15330ba7c51aSVille Syrjälä if (IS_G4X(dev_priv) || 15340ba7c51aSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 15350ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | 15360ba7c51aSVille Syrjälä DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; 15370ba7c51aSVille Syrjälä else 15380ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_I915; 15390ba7c51aSVille Syrjälä 15400ba7c51aSVille Syrjälä /* 15410ba7c51aSVille Syrjälä * We absolutely have to clear all the pending interrupt 15420ba7c51aSVille Syrjälä * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port 15430ba7c51aSVille Syrjälä * interrupt bit won't have an edge, and the i965/g4x 15440ba7c51aSVille Syrjälä * edge triggered IIR will not notice that an interrupt 15450ba7c51aSVille Syrjälä * is still pending. We can't use PORT_HOTPLUG_EN to 15460ba7c51aSVille Syrjälä * guarantee the edge as the act of toggling the enable 15470ba7c51aSVille Syrjälä * bits can itself generate a new hotplug interrupt :( 15480ba7c51aSVille Syrjälä */ 15490ba7c51aSVille Syrjälä for (i = 0; i < 10; i++) { 15500ba7c51aSVille Syrjälä u32 tmp = I915_READ(PORT_HOTPLUG_STAT) & hotplug_status_mask; 15510ba7c51aSVille Syrjälä 15520ba7c51aSVille Syrjälä if (tmp == 0) 15530ba7c51aSVille Syrjälä return hotplug_status; 15540ba7c51aSVille Syrjälä 15550ba7c51aSVille Syrjälä hotplug_status |= tmp; 15563ff60f89SOscar Mateo I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); 15570ba7c51aSVille Syrjälä } 15580ba7c51aSVille Syrjälä 15590ba7c51aSVille Syrjälä WARN_ONCE(1, 15600ba7c51aSVille Syrjälä "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", 15610ba7c51aSVille Syrjälä I915_READ(PORT_HOTPLUG_STAT)); 15621ae3c34cSVille Syrjälä 15631ae3c34cSVille Syrjälä return hotplug_status; 15641ae3c34cSVille Syrjälä } 15651ae3c34cSVille Syrjälä 156691d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, 15671ae3c34cSVille Syrjälä u32 hotplug_status) 15681ae3c34cSVille Syrjälä { 15691ae3c34cSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 15703ff60f89SOscar Mateo 157191d14251STvrtko Ursulin if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || 157291d14251STvrtko Ursulin IS_CHERRYVIEW(dev_priv)) { 157316c6c56bSVille Syrjälä u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; 157416c6c56bSVille Syrjälä 157558f2cf24SVille Syrjälä if (hotplug_trigger) { 1576cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1577cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 1578cf53902fSRodrigo Vivi hpd_status_g4x, 1579fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 158058f2cf24SVille Syrjälä 158191d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 158258f2cf24SVille Syrjälä } 1583369712e8SJani Nikula 1584369712e8SJani Nikula if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) 158591d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 158616c6c56bSVille Syrjälä } else { 158716c6c56bSVille Syrjälä u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; 158816c6c56bSVille Syrjälä 158958f2cf24SVille Syrjälä if (hotplug_trigger) { 1590cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1591cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 1592cf53902fSRodrigo Vivi hpd_status_i915, 1593fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 159491d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 159516c6c56bSVille Syrjälä } 15963ff60f89SOscar Mateo } 159758f2cf24SVille Syrjälä } 159816c6c56bSVille Syrjälä 1599c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 1600c1874ed7SImre Deak { 1601b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 1602c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 1603c1874ed7SImre Deak 16042dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 16052dd2a883SImre Deak return IRQ_NONE; 16062dd2a883SImre Deak 16071f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 16089102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 16091f814dacSImre Deak 16101e1cace9SVille Syrjälä do { 16116e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 16122ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 16131ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1614a5e485a9SVille Syrjälä u32 ier = 0; 16153ff60f89SOscar Mateo 1616c1874ed7SImre Deak gt_iir = I915_READ(GTIIR); 1617c1874ed7SImre Deak pm_iir = I915_READ(GEN6_PMIIR); 16183ff60f89SOscar Mateo iir = I915_READ(VLV_IIR); 1619c1874ed7SImre Deak 1620c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 16211e1cace9SVille Syrjälä break; 1622c1874ed7SImre Deak 1623c1874ed7SImre Deak ret = IRQ_HANDLED; 1624c1874ed7SImre Deak 1625a5e485a9SVille Syrjälä /* 1626a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1627a5e485a9SVille Syrjälä * 1628a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1629a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 1630a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 1631a5e485a9SVille Syrjälä * 1632a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1633a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 1634a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1635a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 1636a5e485a9SVille Syrjälä * bits this time around. 1637a5e485a9SVille Syrjälä */ 16384a0a0202SVille Syrjälä I915_WRITE(VLV_MASTER_IER, 0); 1639a5e485a9SVille Syrjälä ier = I915_READ(VLV_IER); 1640a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, 0); 16414a0a0202SVille Syrjälä 16424a0a0202SVille Syrjälä if (gt_iir) 16434a0a0202SVille Syrjälä I915_WRITE(GTIIR, gt_iir); 16444a0a0202SVille Syrjälä if (pm_iir) 16454a0a0202SVille Syrjälä I915_WRITE(GEN6_PMIIR, pm_iir); 16464a0a0202SVille Syrjälä 16477ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 16481ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 16497ce4d1f2SVille Syrjälä 16503ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 16513ff60f89SOscar Mateo * signalled in iir */ 1652eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 16537ce4d1f2SVille Syrjälä 1654eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1655eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 1656eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1657eef57324SJerome Anand 16587ce4d1f2SVille Syrjälä /* 16597ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 16607ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 16617ce4d1f2SVille Syrjälä */ 16627ce4d1f2SVille Syrjälä if (iir) 16637ce4d1f2SVille Syrjälä I915_WRITE(VLV_IIR, iir); 16644a0a0202SVille Syrjälä 1665a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, ier); 16664a0a0202SVille Syrjälä I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 16671ae3c34cSVille Syrjälä 166852894874SVille Syrjälä if (gt_iir) 1669cf1c97dcSAndi Shyti gen6_gt_irq_handler(&dev_priv->gt, gt_iir); 167052894874SVille Syrjälä if (pm_iir) 1671*3e7abf81SAndi Shyti gen6_rps_irq_handler(&dev_priv->gt.rps, pm_iir); 167252894874SVille Syrjälä 16731ae3c34cSVille Syrjälä if (hotplug_status) 167491d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 16752ecb8ca4SVille Syrjälä 167691d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 16771e1cace9SVille Syrjälä } while (0); 16787e231dbeSJesse Barnes 16799102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 16801f814dacSImre Deak 16817e231dbeSJesse Barnes return ret; 16827e231dbeSJesse Barnes } 16837e231dbeSJesse Barnes 168443f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 168543f328d7SVille Syrjälä { 1686b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 168743f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 168843f328d7SVille Syrjälä 16892dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 16902dd2a883SImre Deak return IRQ_NONE; 16912dd2a883SImre Deak 16921f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 16939102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 16941f814dacSImre Deak 1695579de73bSChris Wilson do { 16966e814800SVille Syrjälä u32 master_ctl, iir; 16972ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 16981ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1699f0fd96f5SChris Wilson u32 gt_iir[4]; 1700a5e485a9SVille Syrjälä u32 ier = 0; 1701a5e485a9SVille Syrjälä 17028e5fd599SVille Syrjälä master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 17033278f67fSVille Syrjälä iir = I915_READ(VLV_IIR); 17043278f67fSVille Syrjälä 17053278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 17068e5fd599SVille Syrjälä break; 170743f328d7SVille Syrjälä 170827b6c122SOscar Mateo ret = IRQ_HANDLED; 170927b6c122SOscar Mateo 1710a5e485a9SVille Syrjälä /* 1711a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1712a5e485a9SVille Syrjälä * 1713a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1714a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 1715a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 1716a5e485a9SVille Syrjälä * 1717a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1718a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 1719a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1720a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 1721a5e485a9SVille Syrjälä * bits this time around. 1722a5e485a9SVille Syrjälä */ 172343f328d7SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, 0); 1724a5e485a9SVille Syrjälä ier = I915_READ(VLV_IER); 1725a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, 0); 172643f328d7SVille Syrjälä 1727cf1c97dcSAndi Shyti gen8_gt_irq_ack(&dev_priv->gt, master_ctl, gt_iir); 172827b6c122SOscar Mateo 172927b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 17301ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 173143f328d7SVille Syrjälä 173227b6c122SOscar Mateo /* Call regardless, as some status bits might not be 173327b6c122SOscar Mateo * signalled in iir */ 1734eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 173543f328d7SVille Syrjälä 1736eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1737eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 1738eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 1739eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1740eef57324SJerome Anand 17417ce4d1f2SVille Syrjälä /* 17427ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 17437ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 17447ce4d1f2SVille Syrjälä */ 17457ce4d1f2SVille Syrjälä if (iir) 17467ce4d1f2SVille Syrjälä I915_WRITE(VLV_IIR, iir); 17477ce4d1f2SVille Syrjälä 1748a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, ier); 1749e5328c43SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 17501ae3c34cSVille Syrjälä 1751cf1c97dcSAndi Shyti gen8_gt_irq_handler(&dev_priv->gt, master_ctl, gt_iir); 1752e30e251aSVille Syrjälä 17531ae3c34cSVille Syrjälä if (hotplug_status) 175491d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 17552ecb8ca4SVille Syrjälä 175691d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 1757579de73bSChris Wilson } while (0); 17583278f67fSVille Syrjälä 17599102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 17601f814dacSImre Deak 176143f328d7SVille Syrjälä return ret; 176243f328d7SVille Syrjälä } 176343f328d7SVille Syrjälä 176491d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, 176591d14251STvrtko Ursulin u32 hotplug_trigger, 176640e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 1767776ad806SJesse Barnes { 176842db67d6SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1769776ad806SJesse Barnes 17706a39d7c9SJani Nikula /* 17716a39d7c9SJani Nikula * Somehow the PCH doesn't seem to really ack the interrupt to the CPU 17726a39d7c9SJani Nikula * unless we touch the hotplug register, even if hotplug_trigger is 17736a39d7c9SJani Nikula * zero. Not acking leads to "The master control interrupt lied (SDE)!" 17746a39d7c9SJani Nikula * errors. 17756a39d7c9SJani Nikula */ 177613cf5504SDave Airlie dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 17776a39d7c9SJani Nikula if (!hotplug_trigger) { 17786a39d7c9SJani Nikula u32 mask = PORTA_HOTPLUG_STATUS_MASK | 17796a39d7c9SJani Nikula PORTD_HOTPLUG_STATUS_MASK | 17806a39d7c9SJani Nikula PORTC_HOTPLUG_STATUS_MASK | 17816a39d7c9SJani Nikula PORTB_HOTPLUG_STATUS_MASK; 17826a39d7c9SJani Nikula dig_hotplug_reg &= ~mask; 17836a39d7c9SJani Nikula } 17846a39d7c9SJani Nikula 178513cf5504SDave Airlie I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 17866a39d7c9SJani Nikula if (!hotplug_trigger) 17876a39d7c9SJani Nikula return; 178813cf5504SDave Airlie 1789cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 179040e56410SVille Syrjälä dig_hotplug_reg, hpd, 1791fd63e2a9SImre Deak pch_port_hotplug_long_detect); 179240e56410SVille Syrjälä 179391d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1794aaf5ec2eSSonika Jindal } 179591d131d2SDaniel Vetter 179691d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 179740e56410SVille Syrjälä { 1798d048a268SVille Syrjälä enum pipe pipe; 179940e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 180040e56410SVille Syrjälä 180191d14251STvrtko Ursulin ibx_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ibx); 180240e56410SVille Syrjälä 1803cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 1804cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 1805776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 1806cfc33bf7SVille Syrjälä DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", 1807cfc33bf7SVille Syrjälä port_name(port)); 1808cfc33bf7SVille Syrjälä } 1809776ad806SJesse Barnes 1810ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 181191d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 1812ce99c256SDaniel Vetter 1813776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 181491d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1815776ad806SJesse Barnes 1816776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 1817776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n"); 1818776ad806SJesse Barnes 1819776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 1820776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n"); 1821776ad806SJesse Barnes 1822776ad806SJesse Barnes if (pch_iir & SDE_POISON) 1823776ad806SJesse Barnes DRM_ERROR("PCH poison interrupt\n"); 1824776ad806SJesse Barnes 18259db4a9c7SJesse Barnes if (pch_iir & SDE_FDI_MASK) 1826055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 18279db4a9c7SJesse Barnes DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", 18289db4a9c7SJesse Barnes pipe_name(pipe), 18299db4a9c7SJesse Barnes I915_READ(FDI_RX_IIR(pipe))); 1830776ad806SJesse Barnes 1831776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 1832776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n"); 1833776ad806SJesse Barnes 1834776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 1835776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n"); 1836776ad806SJesse Barnes 1837776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 1838a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 18398664281bSPaulo Zanoni 18408664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 1841a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 18428664281bSPaulo Zanoni } 18438664281bSPaulo Zanoni 184491d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 18458664281bSPaulo Zanoni { 18468664281bSPaulo Zanoni u32 err_int = I915_READ(GEN7_ERR_INT); 18475a69b89fSDaniel Vetter enum pipe pipe; 18488664281bSPaulo Zanoni 1849de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 1850de032bf4SPaulo Zanoni DRM_ERROR("Poison interrupt\n"); 1851de032bf4SPaulo Zanoni 1852055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 18531f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 18541f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 18558664281bSPaulo Zanoni 18565a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 185791d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 185891d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 18595a69b89fSDaniel Vetter else 186091d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 18615a69b89fSDaniel Vetter } 18625a69b89fSDaniel Vetter } 18638bf1e9f1SShuang He 18648664281bSPaulo Zanoni I915_WRITE(GEN7_ERR_INT, err_int); 18658664281bSPaulo Zanoni } 18668664281bSPaulo Zanoni 186791d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 18688664281bSPaulo Zanoni { 18698664281bSPaulo Zanoni u32 serr_int = I915_READ(SERR_INT); 187045c1cd87SMika Kahola enum pipe pipe; 18718664281bSPaulo Zanoni 1872de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 1873de032bf4SPaulo Zanoni DRM_ERROR("PCH poison interrupt\n"); 1874de032bf4SPaulo Zanoni 187545c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 187645c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 187745c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 18788664281bSPaulo Zanoni 18798664281bSPaulo Zanoni I915_WRITE(SERR_INT, serr_int); 1880776ad806SJesse Barnes } 1881776ad806SJesse Barnes 188291d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 188323e81d69SAdam Jackson { 1884d048a268SVille Syrjälä enum pipe pipe; 18856dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 1886aaf5ec2eSSonika Jindal 188791d14251STvrtko Ursulin ibx_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_cpt); 188891d131d2SDaniel Vetter 1889cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 1890cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 189123e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 1892cfc33bf7SVille Syrjälä DRM_DEBUG_DRIVER("PCH audio power change on port %c\n", 1893cfc33bf7SVille Syrjälä port_name(port)); 1894cfc33bf7SVille Syrjälä } 189523e81d69SAdam Jackson 189623e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 189791d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 189823e81d69SAdam Jackson 189923e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 190091d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 190123e81d69SAdam Jackson 190223e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 190323e81d69SAdam Jackson DRM_DEBUG_DRIVER("Audio CP request interrupt\n"); 190423e81d69SAdam Jackson 190523e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 190623e81d69SAdam Jackson DRM_DEBUG_DRIVER("Audio CP change interrupt\n"); 190723e81d69SAdam Jackson 190823e81d69SAdam Jackson if (pch_iir & SDE_FDI_MASK_CPT) 1909055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 191023e81d69SAdam Jackson DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", 191123e81d69SAdam Jackson pipe_name(pipe), 191223e81d69SAdam Jackson I915_READ(FDI_RX_IIR(pipe))); 19138664281bSPaulo Zanoni 19148664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 191591d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 191623e81d69SAdam Jackson } 191723e81d69SAdam Jackson 191858676af6SLucas De Marchi static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 191931604222SAnusha Srivatsa { 192058676af6SLucas De Marchi u32 ddi_hotplug_trigger, tc_hotplug_trigger; 192131604222SAnusha Srivatsa u32 pin_mask = 0, long_mask = 0; 192258676af6SLucas De Marchi bool (*tc_port_hotplug_long_detect)(enum hpd_pin pin, u32 val); 192358676af6SLucas De Marchi const u32 *pins; 192431604222SAnusha Srivatsa 192558676af6SLucas De Marchi if (HAS_PCH_TGP(dev_priv)) { 192658676af6SLucas De Marchi ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_TGP; 192758676af6SLucas De Marchi tc_hotplug_trigger = pch_iir & SDE_TC_MASK_TGP; 192858676af6SLucas De Marchi tc_port_hotplug_long_detect = tgp_tc_port_hotplug_long_detect; 192958676af6SLucas De Marchi pins = hpd_tgp; 1930943682e3SMatt Roper } else if (HAS_PCH_JSP(dev_priv)) { 1931943682e3SMatt Roper ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_TGP; 1932943682e3SMatt Roper tc_hotplug_trigger = 0; 1933943682e3SMatt Roper pins = hpd_tgp; 193458676af6SLucas De Marchi } else if (HAS_PCH_MCC(dev_priv)) { 193553448aedSVivek Kasireddy ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; 193653448aedSVivek Kasireddy tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_ICP(PORT_TC1); 1937fcb9bba4SMatt Roper tc_port_hotplug_long_detect = icp_tc_port_hotplug_long_detect; 1938d09ad3e7SMatt Roper pins = hpd_icp; 19398ef7e340SMatt Roper } else { 1940943682e3SMatt Roper WARN(!HAS_PCH_ICP(dev_priv), 1941943682e3SMatt Roper "Unrecognized PCH type 0x%x\n", INTEL_PCH_TYPE(dev_priv)); 1942943682e3SMatt Roper 19438ef7e340SMatt Roper ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; 19448ef7e340SMatt Roper tc_hotplug_trigger = pch_iir & SDE_TC_MASK_ICP; 194558676af6SLucas De Marchi tc_port_hotplug_long_detect = icp_tc_port_hotplug_long_detect; 194658676af6SLucas De Marchi pins = hpd_icp; 19478ef7e340SMatt Roper } 19488ef7e340SMatt Roper 194931604222SAnusha Srivatsa if (ddi_hotplug_trigger) { 195031604222SAnusha Srivatsa u32 dig_hotplug_reg; 195131604222SAnusha Srivatsa 195231604222SAnusha Srivatsa dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_DDI); 195331604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_DDI, dig_hotplug_reg); 195431604222SAnusha Srivatsa 195531604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 195631604222SAnusha Srivatsa ddi_hotplug_trigger, 1957c6f7acb8SMatt Roper dig_hotplug_reg, pins, 195831604222SAnusha Srivatsa icp_ddi_port_hotplug_long_detect); 195931604222SAnusha Srivatsa } 196031604222SAnusha Srivatsa 196131604222SAnusha Srivatsa if (tc_hotplug_trigger) { 196231604222SAnusha Srivatsa u32 dig_hotplug_reg; 196331604222SAnusha Srivatsa 196431604222SAnusha Srivatsa dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_TC); 196531604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_TC, dig_hotplug_reg); 196631604222SAnusha Srivatsa 196731604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 196831604222SAnusha Srivatsa tc_hotplug_trigger, 1969c6f7acb8SMatt Roper dig_hotplug_reg, pins, 197058676af6SLucas De Marchi tc_port_hotplug_long_detect); 197152dfdba0SLucas De Marchi } 197252dfdba0SLucas De Marchi 197352dfdba0SLucas De Marchi if (pin_mask) 197452dfdba0SLucas De Marchi intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 197552dfdba0SLucas De Marchi 197652dfdba0SLucas De Marchi if (pch_iir & SDE_GMBUS_ICP) 197752dfdba0SLucas De Marchi gmbus_irq_handler(dev_priv); 197852dfdba0SLucas De Marchi } 197952dfdba0SLucas De Marchi 198091d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 19816dbf30ceSVille Syrjälä { 19826dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & 19836dbf30ceSVille Syrjälä ~SDE_PORTE_HOTPLUG_SPT; 19846dbf30ceSVille Syrjälä u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; 19856dbf30ceSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 19866dbf30ceSVille Syrjälä 19876dbf30ceSVille Syrjälä if (hotplug_trigger) { 19886dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 19896dbf30ceSVille Syrjälä 19906dbf30ceSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 19916dbf30ceSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 19926dbf30ceSVille Syrjälä 1993cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1994cf53902fSRodrigo Vivi hotplug_trigger, dig_hotplug_reg, hpd_spt, 199574c0b395SVille Syrjälä spt_port_hotplug_long_detect); 19966dbf30ceSVille Syrjälä } 19976dbf30ceSVille Syrjälä 19986dbf30ceSVille Syrjälä if (hotplug2_trigger) { 19996dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 20006dbf30ceSVille Syrjälä 20016dbf30ceSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); 20026dbf30ceSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG2, dig_hotplug_reg); 20036dbf30ceSVille Syrjälä 2004cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2005cf53902fSRodrigo Vivi hotplug2_trigger, dig_hotplug_reg, hpd_spt, 20066dbf30ceSVille Syrjälä spt_port_hotplug2_long_detect); 20076dbf30ceSVille Syrjälä } 20086dbf30ceSVille Syrjälä 20096dbf30ceSVille Syrjälä if (pin_mask) 201091d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 20116dbf30ceSVille Syrjälä 20126dbf30ceSVille Syrjälä if (pch_iir & SDE_GMBUS_CPT) 201391d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 20146dbf30ceSVille Syrjälä } 20156dbf30ceSVille Syrjälä 201691d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, 201791d14251STvrtko Ursulin u32 hotplug_trigger, 201840e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2019c008bc6eSPaulo Zanoni { 2020e4ce95aaSVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2021e4ce95aaSVille Syrjälä 2022e4ce95aaSVille Syrjälä dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); 2023e4ce95aaSVille Syrjälä I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); 2024e4ce95aaSVille Syrjälä 2025cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 202640e56410SVille Syrjälä dig_hotplug_reg, hpd, 2027e4ce95aaSVille Syrjälä ilk_port_hotplug_long_detect); 202840e56410SVille Syrjälä 202991d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2030e4ce95aaSVille Syrjälä } 2031c008bc6eSPaulo Zanoni 203291d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 203391d14251STvrtko Ursulin u32 de_iir) 203440e56410SVille Syrjälä { 203540e56410SVille Syrjälä enum pipe pipe; 203640e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 203740e56410SVille Syrjälä 203840e56410SVille Syrjälä if (hotplug_trigger) 203991d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ilk); 204040e56410SVille Syrjälä 2041c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 204291d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2043c008bc6eSPaulo Zanoni 2044c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 204591d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2046c008bc6eSPaulo Zanoni 2047c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 2048c008bc6eSPaulo Zanoni DRM_ERROR("Poison interrupt\n"); 2049c008bc6eSPaulo Zanoni 2050055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2051fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 2052fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 2053c008bc6eSPaulo Zanoni 205440da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 20551f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 2056c008bc6eSPaulo Zanoni 205740da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 205891d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 2059c008bc6eSPaulo Zanoni } 2060c008bc6eSPaulo Zanoni 2061c008bc6eSPaulo Zanoni /* check event from PCH */ 2062c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 2063c008bc6eSPaulo Zanoni u32 pch_iir = I915_READ(SDEIIR); 2064c008bc6eSPaulo Zanoni 206591d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 206691d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 2067c008bc6eSPaulo Zanoni else 206891d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 2069c008bc6eSPaulo Zanoni 2070c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 2071c008bc6eSPaulo Zanoni I915_WRITE(SDEIIR, pch_iir); 2072c008bc6eSPaulo Zanoni } 2073c008bc6eSPaulo Zanoni 2074cf819effSLucas De Marchi if (IS_GEN(dev_priv, 5) && de_iir & DE_PCU_EVENT) 2075*3e7abf81SAndi Shyti gen5_rps_irq_handler(&dev_priv->gt.rps); 2076c008bc6eSPaulo Zanoni } 2077c008bc6eSPaulo Zanoni 207891d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 207991d14251STvrtko Ursulin u32 de_iir) 20809719fb98SPaulo Zanoni { 208107d27e20SDamien Lespiau enum pipe pipe; 208223bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 208323bb4cb5SVille Syrjälä 208440e56410SVille Syrjälä if (hotplug_trigger) 208591d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ivb); 20869719fb98SPaulo Zanoni 20879719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 208891d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 20899719fb98SPaulo Zanoni 209054fd3149SDhinakaran Pandiyan if (de_iir & DE_EDP_PSR_INT_HSW) { 209154fd3149SDhinakaran Pandiyan u32 psr_iir = I915_READ(EDP_PSR_IIR); 209254fd3149SDhinakaran Pandiyan 209354fd3149SDhinakaran Pandiyan intel_psr_irq_handler(dev_priv, psr_iir); 209454fd3149SDhinakaran Pandiyan I915_WRITE(EDP_PSR_IIR, psr_iir); 209554fd3149SDhinakaran Pandiyan } 2096fc340442SDaniel Vetter 20979719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 209891d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 20999719fb98SPaulo Zanoni 21009719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 210191d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 21029719fb98SPaulo Zanoni 2103055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2104fd3a4024SDaniel Vetter if (de_iir & (DE_PIPE_VBLANK_IVB(pipe))) 2105fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 21069719fb98SPaulo Zanoni } 21079719fb98SPaulo Zanoni 21089719fb98SPaulo Zanoni /* check event from PCH */ 210991d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 21109719fb98SPaulo Zanoni u32 pch_iir = I915_READ(SDEIIR); 21119719fb98SPaulo Zanoni 211291d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 21139719fb98SPaulo Zanoni 21149719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 21159719fb98SPaulo Zanoni I915_WRITE(SDEIIR, pch_iir); 21169719fb98SPaulo Zanoni } 21179719fb98SPaulo Zanoni } 21189719fb98SPaulo Zanoni 211972c90f62SOscar Mateo /* 212072c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 212172c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 212272c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 212372c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 212472c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 212572c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 212672c90f62SOscar Mateo */ 2127f1af8fc1SPaulo Zanoni static irqreturn_t ironlake_irq_handler(int irq, void *arg) 2128b1f14ad0SJesse Barnes { 2129b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 2130f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 21310e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 2132b1f14ad0SJesse Barnes 21332dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 21342dd2a883SImre Deak return IRQ_NONE; 21352dd2a883SImre Deak 21361f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 21379102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 21381f814dacSImre Deak 2139b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 2140b1f14ad0SJesse Barnes de_ier = I915_READ(DEIER); 2141b1f14ad0SJesse Barnes I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 21420e43406bSChris Wilson 214344498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 214444498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 214544498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 214644498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 214744498aeaSPaulo Zanoni * due to its back queue). */ 214891d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv)) { 214944498aeaSPaulo Zanoni sde_ier = I915_READ(SDEIER); 215044498aeaSPaulo Zanoni I915_WRITE(SDEIER, 0); 2151ab5c608bSBen Widawsky } 215244498aeaSPaulo Zanoni 215372c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 215472c90f62SOscar Mateo 21550e43406bSChris Wilson gt_iir = I915_READ(GTIIR); 21560e43406bSChris Wilson if (gt_iir) { 215772c90f62SOscar Mateo I915_WRITE(GTIIR, gt_iir); 215872c90f62SOscar Mateo ret = IRQ_HANDLED; 215991d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) 2160cf1c97dcSAndi Shyti gen6_gt_irq_handler(&dev_priv->gt, gt_iir); 2161d8fc8a47SPaulo Zanoni else 2162cf1c97dcSAndi Shyti gen5_gt_irq_handler(&dev_priv->gt, gt_iir); 21630e43406bSChris Wilson } 2164b1f14ad0SJesse Barnes 2165b1f14ad0SJesse Barnes de_iir = I915_READ(DEIIR); 21660e43406bSChris Wilson if (de_iir) { 216772c90f62SOscar Mateo I915_WRITE(DEIIR, de_iir); 216872c90f62SOscar Mateo ret = IRQ_HANDLED; 216991d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 7) 217091d14251STvrtko Ursulin ivb_display_irq_handler(dev_priv, de_iir); 2171f1af8fc1SPaulo Zanoni else 217291d14251STvrtko Ursulin ilk_display_irq_handler(dev_priv, de_iir); 21730e43406bSChris Wilson } 21740e43406bSChris Wilson 217591d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) { 2176f1af8fc1SPaulo Zanoni u32 pm_iir = I915_READ(GEN6_PMIIR); 21770e43406bSChris Wilson if (pm_iir) { 2178b1f14ad0SJesse Barnes I915_WRITE(GEN6_PMIIR, pm_iir); 21790e43406bSChris Wilson ret = IRQ_HANDLED; 2180*3e7abf81SAndi Shyti gen6_rps_irq_handler(&dev_priv->gt.rps, pm_iir); 21810e43406bSChris Wilson } 2182f1af8fc1SPaulo Zanoni } 2183b1f14ad0SJesse Barnes 2184b1f14ad0SJesse Barnes I915_WRITE(DEIER, de_ier); 218574093f3eSChris Wilson if (!HAS_PCH_NOP(dev_priv)) 218644498aeaSPaulo Zanoni I915_WRITE(SDEIER, sde_ier); 2187b1f14ad0SJesse Barnes 21881f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 21899102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 21901f814dacSImre Deak 2191b1f14ad0SJesse Barnes return ret; 2192b1f14ad0SJesse Barnes } 2193b1f14ad0SJesse Barnes 219491d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, 219591d14251STvrtko Ursulin u32 hotplug_trigger, 219640e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2197d04a492dSShashank Sharma { 2198cebd87a0SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2199d04a492dSShashank Sharma 2200a52bb15bSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 2201a52bb15bSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 2202d04a492dSShashank Sharma 2203cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 220440e56410SVille Syrjälä dig_hotplug_reg, hpd, 2205cebd87a0SVille Syrjälä bxt_port_hotplug_long_detect); 220640e56410SVille Syrjälä 220791d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2208d04a492dSShashank Sharma } 2209d04a492dSShashank Sharma 2210121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2211121e758eSDhinakaran Pandiyan { 2212121e758eSDhinakaran Pandiyan u32 pin_mask = 0, long_mask = 0; 2213b796b971SDhinakaran Pandiyan u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; 2214b796b971SDhinakaran Pandiyan u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; 221548ef15d3SJosé Roberto de Souza long_pulse_detect_func long_pulse_detect; 221648ef15d3SJosé Roberto de Souza const u32 *hpd; 221748ef15d3SJosé Roberto de Souza 221848ef15d3SJosé Roberto de Souza if (INTEL_GEN(dev_priv) >= 12) { 221948ef15d3SJosé Roberto de Souza long_pulse_detect = gen12_port_hotplug_long_detect; 222048ef15d3SJosé Roberto de Souza hpd = hpd_gen12; 222148ef15d3SJosé Roberto de Souza } else { 222248ef15d3SJosé Roberto de Souza long_pulse_detect = gen11_port_hotplug_long_detect; 222348ef15d3SJosé Roberto de Souza hpd = hpd_gen11; 222448ef15d3SJosé Roberto de Souza } 2225121e758eSDhinakaran Pandiyan 2226121e758eSDhinakaran Pandiyan if (trigger_tc) { 2227b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2228b796b971SDhinakaran Pandiyan 2229121e758eSDhinakaran Pandiyan dig_hotplug_reg = I915_READ(GEN11_TC_HOTPLUG_CTL); 2230121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_TC_HOTPLUG_CTL, dig_hotplug_reg); 2231121e758eSDhinakaran Pandiyan 2232121e758eSDhinakaran Pandiyan intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tc, 223348ef15d3SJosé Roberto de Souza dig_hotplug_reg, hpd, long_pulse_detect); 2234121e758eSDhinakaran Pandiyan } 2235b796b971SDhinakaran Pandiyan 2236b796b971SDhinakaran Pandiyan if (trigger_tbt) { 2237b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2238b796b971SDhinakaran Pandiyan 2239b796b971SDhinakaran Pandiyan dig_hotplug_reg = I915_READ(GEN11_TBT_HOTPLUG_CTL); 2240b796b971SDhinakaran Pandiyan I915_WRITE(GEN11_TBT_HOTPLUG_CTL, dig_hotplug_reg); 2241b796b971SDhinakaran Pandiyan 2242b796b971SDhinakaran Pandiyan intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tbt, 224348ef15d3SJosé Roberto de Souza dig_hotplug_reg, hpd, long_pulse_detect); 2244b796b971SDhinakaran Pandiyan } 2245b796b971SDhinakaran Pandiyan 2246b796b971SDhinakaran Pandiyan if (pin_mask) 2247b796b971SDhinakaran Pandiyan intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2248b796b971SDhinakaran Pandiyan else 2249b796b971SDhinakaran Pandiyan DRM_ERROR("Unexpected DE HPD interrupt 0x%08x\n", iir); 2250121e758eSDhinakaran Pandiyan } 2251121e758eSDhinakaran Pandiyan 22529d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 22539d17210fSLucas De Marchi { 225455523360SLucas De Marchi u32 mask; 22559d17210fSLucas De Marchi 225655523360SLucas De Marchi if (INTEL_GEN(dev_priv) >= 12) 225755523360SLucas De Marchi /* TODO: Add AUX entries for USBC */ 225855523360SLucas De Marchi return TGL_DE_PORT_AUX_DDIA | 225955523360SLucas De Marchi TGL_DE_PORT_AUX_DDIB | 226055523360SLucas De Marchi TGL_DE_PORT_AUX_DDIC; 226155523360SLucas De Marchi 226255523360SLucas De Marchi mask = GEN8_AUX_CHANNEL_A; 22639d17210fSLucas De Marchi if (INTEL_GEN(dev_priv) >= 9) 22649d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 22659d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 22669d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 22679d17210fSLucas De Marchi 226855523360SLucas De Marchi if (IS_CNL_WITH_PORT_F(dev_priv) || IS_GEN(dev_priv, 11)) 22699d17210fSLucas De Marchi mask |= CNL_AUX_CHANNEL_F; 22709d17210fSLucas De Marchi 227155523360SLucas De Marchi if (IS_GEN(dev_priv, 11)) 227255523360SLucas De Marchi mask |= ICL_AUX_CHANNEL_E; 22739d17210fSLucas De Marchi 22749d17210fSLucas De Marchi return mask; 22759d17210fSLucas De Marchi } 22769d17210fSLucas De Marchi 22775270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) 22785270130dSVille Syrjälä { 2279d506a65dSMatt Roper if (INTEL_GEN(dev_priv) >= 11) 2280d506a65dSMatt Roper return GEN11_DE_PIPE_IRQ_FAULT_ERRORS; 2281d506a65dSMatt Roper else if (INTEL_GEN(dev_priv) >= 9) 22825270130dSVille Syrjälä return GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 22835270130dSVille Syrjälä else 22845270130dSVille Syrjälä return GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 22855270130dSVille Syrjälä } 22865270130dSVille Syrjälä 228746c63d24SJosé Roberto de Souza static void 228846c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2289abd58f01SBen Widawsky { 2290e04f7eceSVille Syrjälä bool found = false; 2291e04f7eceSVille Syrjälä 2292e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 229391d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2294e04f7eceSVille Syrjälä found = true; 2295e04f7eceSVille Syrjälä } 2296e04f7eceSVille Syrjälä 2297e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 22988241cfbeSJosé Roberto de Souza u32 psr_iir; 22998241cfbeSJosé Roberto de Souza i915_reg_t iir_reg; 23008241cfbeSJosé Roberto de Souza 23018241cfbeSJosé Roberto de Souza if (INTEL_GEN(dev_priv) >= 12) 23028241cfbeSJosé Roberto de Souza iir_reg = TRANS_PSR_IIR(dev_priv->psr.transcoder); 23038241cfbeSJosé Roberto de Souza else 23048241cfbeSJosé Roberto de Souza iir_reg = EDP_PSR_IIR; 23058241cfbeSJosé Roberto de Souza 23068241cfbeSJosé Roberto de Souza psr_iir = I915_READ(iir_reg); 23078241cfbeSJosé Roberto de Souza I915_WRITE(iir_reg, psr_iir); 23088241cfbeSJosé Roberto de Souza 23098241cfbeSJosé Roberto de Souza if (psr_iir) 23108241cfbeSJosé Roberto de Souza found = true; 231154fd3149SDhinakaran Pandiyan 231254fd3149SDhinakaran Pandiyan intel_psr_irq_handler(dev_priv, psr_iir); 2313e04f7eceSVille Syrjälä } 2314e04f7eceSVille Syrjälä 2315e04f7eceSVille Syrjälä if (!found) 231638cc46d7SOscar Mateo DRM_ERROR("Unexpected DE Misc interrupt\n"); 2317abd58f01SBen Widawsky } 231846c63d24SJosé Roberto de Souza 231946c63d24SJosé Roberto de Souza static irqreturn_t 232046c63d24SJosé Roberto de Souza gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 232146c63d24SJosé Roberto de Souza { 232246c63d24SJosé Roberto de Souza irqreturn_t ret = IRQ_NONE; 232346c63d24SJosé Roberto de Souza u32 iir; 232446c63d24SJosé Roberto de Souza enum pipe pipe; 232546c63d24SJosé Roberto de Souza 232646c63d24SJosé Roberto de Souza if (master_ctl & GEN8_DE_MISC_IRQ) { 232746c63d24SJosé Roberto de Souza iir = I915_READ(GEN8_DE_MISC_IIR); 232846c63d24SJosé Roberto de Souza if (iir) { 232946c63d24SJosé Roberto de Souza I915_WRITE(GEN8_DE_MISC_IIR, iir); 233046c63d24SJosé Roberto de Souza ret = IRQ_HANDLED; 233146c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(dev_priv, iir); 233246c63d24SJosé Roberto de Souza } else { 233338cc46d7SOscar Mateo DRM_ERROR("The master control interrupt lied (DE MISC)!\n"); 2334abd58f01SBen Widawsky } 233546c63d24SJosé Roberto de Souza } 2336abd58f01SBen Widawsky 2337121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 2338121e758eSDhinakaran Pandiyan iir = I915_READ(GEN11_DE_HPD_IIR); 2339121e758eSDhinakaran Pandiyan if (iir) { 2340121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_DE_HPD_IIR, iir); 2341121e758eSDhinakaran Pandiyan ret = IRQ_HANDLED; 2342121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 2343121e758eSDhinakaran Pandiyan } else { 2344121e758eSDhinakaran Pandiyan DRM_ERROR("The master control interrupt lied, (DE HPD)!\n"); 2345121e758eSDhinakaran Pandiyan } 2346121e758eSDhinakaran Pandiyan } 2347121e758eSDhinakaran Pandiyan 23486d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 2349e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_PORT_IIR); 2350e32192e1STvrtko Ursulin if (iir) { 2351e32192e1STvrtko Ursulin u32 tmp_mask; 2352d04a492dSShashank Sharma bool found = false; 2353cebd87a0SVille Syrjälä 2354e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_PORT_IIR, iir); 23556d766f02SDaniel Vetter ret = IRQ_HANDLED; 235688e04703SJesse Barnes 23579d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 235891d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2359d04a492dSShashank Sharma found = true; 2360d04a492dSShashank Sharma } 2361d04a492dSShashank Sharma 2362cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) { 2363e32192e1STvrtko Ursulin tmp_mask = iir & BXT_DE_PORT_HOTPLUG_MASK; 2364e32192e1STvrtko Ursulin if (tmp_mask) { 236591d14251STvrtko Ursulin bxt_hpd_irq_handler(dev_priv, tmp_mask, 236691d14251STvrtko Ursulin hpd_bxt); 2367d04a492dSShashank Sharma found = true; 2368d04a492dSShashank Sharma } 2369e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 2370e32192e1STvrtko Ursulin tmp_mask = iir & GEN8_PORT_DP_A_HOTPLUG; 2371e32192e1STvrtko Ursulin if (tmp_mask) { 237291d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, 237391d14251STvrtko Ursulin tmp_mask, hpd_bdw); 2374e32192e1STvrtko Ursulin found = true; 2375e32192e1STvrtko Ursulin } 2376e32192e1STvrtko Ursulin } 2377d04a492dSShashank Sharma 2378cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv) && (iir & BXT_DE_PORT_GMBUS)) { 237991d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 23809e63743eSShashank Sharma found = true; 23819e63743eSShashank Sharma } 23829e63743eSShashank Sharma 2383d04a492dSShashank Sharma if (!found) 238438cc46d7SOscar Mateo DRM_ERROR("Unexpected DE Port interrupt\n"); 23856d766f02SDaniel Vetter } 238638cc46d7SOscar Mateo else 238738cc46d7SOscar Mateo DRM_ERROR("The master control interrupt lied (DE PORT)!\n"); 23886d766f02SDaniel Vetter } 23896d766f02SDaniel Vetter 2390055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2391fd3a4024SDaniel Vetter u32 fault_errors; 2392abd58f01SBen Widawsky 2393c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 2394c42664ccSDaniel Vetter continue; 2395c42664ccSDaniel Vetter 2396e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); 2397e32192e1STvrtko Ursulin if (!iir) { 2398e32192e1STvrtko Ursulin DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); 2399e32192e1STvrtko Ursulin continue; 2400e32192e1STvrtko Ursulin } 2401770de83dSDamien Lespiau 2402e32192e1STvrtko Ursulin ret = IRQ_HANDLED; 2403e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir); 2404e32192e1STvrtko Ursulin 2405fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 2406fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 2407abd58f01SBen Widawsky 2408e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 240991d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 24100fbe7870SDaniel Vetter 2411e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_FIFO_UNDERRUN) 2412e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 241338d83c96SDaniel Vetter 24145270130dSVille Syrjälä fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); 2415770de83dSDamien Lespiau if (fault_errors) 24161353ec38STvrtko Ursulin DRM_ERROR("Fault errors on pipe %c: 0x%08x\n", 241730100f2bSDaniel Vetter pipe_name(pipe), 2418e32192e1STvrtko Ursulin fault_errors); 2419abd58f01SBen Widawsky } 2420abd58f01SBen Widawsky 242191d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 2422266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 242392d03a80SDaniel Vetter /* 242492d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 242592d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 242692d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 242792d03a80SDaniel Vetter */ 2428e32192e1STvrtko Ursulin iir = I915_READ(SDEIIR); 2429e32192e1STvrtko Ursulin if (iir) { 2430e32192e1STvrtko Ursulin I915_WRITE(SDEIIR, iir); 243192d03a80SDaniel Vetter ret = IRQ_HANDLED; 24326dbf30ceSVille Syrjälä 243358676af6SLucas De Marchi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 243458676af6SLucas De Marchi icp_irq_handler(dev_priv, iir); 2435c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 243691d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 24376dbf30ceSVille Syrjälä else 243891d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 24392dfb0b81SJani Nikula } else { 24402dfb0b81SJani Nikula /* 24412dfb0b81SJani Nikula * Like on previous PCH there seems to be something 24422dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 24432dfb0b81SJani Nikula */ 24442dfb0b81SJani Nikula DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n"); 24452dfb0b81SJani Nikula } 244692d03a80SDaniel Vetter } 244792d03a80SDaniel Vetter 2448f11a0f46STvrtko Ursulin return ret; 2449f11a0f46STvrtko Ursulin } 2450f11a0f46STvrtko Ursulin 24514376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 24524376b9c9SMika Kuoppala { 24534376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 24544376b9c9SMika Kuoppala 24554376b9c9SMika Kuoppala /* 24564376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 24574376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 24584376b9c9SMika Kuoppala * New indications can and will light up during processing, 24594376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 24604376b9c9SMika Kuoppala */ 24614376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 24624376b9c9SMika Kuoppala } 24634376b9c9SMika Kuoppala 24644376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 24654376b9c9SMika Kuoppala { 24664376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 24674376b9c9SMika Kuoppala } 24684376b9c9SMika Kuoppala 2469f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 2470f11a0f46STvrtko Ursulin { 2471b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 247225286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 2473f11a0f46STvrtko Ursulin u32 master_ctl; 2474f0fd96f5SChris Wilson u32 gt_iir[4]; 2475f11a0f46STvrtko Ursulin 2476f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 2477f11a0f46STvrtko Ursulin return IRQ_NONE; 2478f11a0f46STvrtko Ursulin 24794376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 24804376b9c9SMika Kuoppala if (!master_ctl) { 24814376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2482f11a0f46STvrtko Ursulin return IRQ_NONE; 24834376b9c9SMika Kuoppala } 2484f11a0f46STvrtko Ursulin 2485f11a0f46STvrtko Ursulin /* Find, clear, then process each source of interrupt */ 2486cf1c97dcSAndi Shyti gen8_gt_irq_ack(&dev_priv->gt, master_ctl, gt_iir); 2487f0fd96f5SChris Wilson 2488f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2489f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 24909102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 249155ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 24929102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 2493f0fd96f5SChris Wilson } 2494f11a0f46STvrtko Ursulin 24954376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2496abd58f01SBen Widawsky 2497cf1c97dcSAndi Shyti gen8_gt_irq_handler(&dev_priv->gt, master_ctl, gt_iir); 24981f814dacSImre Deak 249955ef72f2SChris Wilson return IRQ_HANDLED; 2500abd58f01SBen Widawsky } 2501abd58f01SBen Widawsky 250251951ae7SMika Kuoppala static u32 25039b77011eSTvrtko Ursulin gen11_gu_misc_irq_ack(struct intel_gt *gt, const u32 master_ctl) 2504df0d28c1SDhinakaran Pandiyan { 25059b77011eSTvrtko Ursulin void __iomem * const regs = gt->uncore->regs; 25067a909383SChris Wilson u32 iir; 2507df0d28c1SDhinakaran Pandiyan 2508df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 25097a909383SChris Wilson return 0; 2510df0d28c1SDhinakaran Pandiyan 25117a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 25127a909383SChris Wilson if (likely(iir)) 25137a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 25147a909383SChris Wilson 25157a909383SChris Wilson return iir; 2516df0d28c1SDhinakaran Pandiyan } 2517df0d28c1SDhinakaran Pandiyan 2518df0d28c1SDhinakaran Pandiyan static void 25199b77011eSTvrtko Ursulin gen11_gu_misc_irq_handler(struct intel_gt *gt, const u32 iir) 2520df0d28c1SDhinakaran Pandiyan { 2521df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 25229b77011eSTvrtko Ursulin intel_opregion_asle_intr(gt->i915); 2523df0d28c1SDhinakaran Pandiyan } 2524df0d28c1SDhinakaran Pandiyan 252581067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 252681067b71SMika Kuoppala { 252781067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 252881067b71SMika Kuoppala 252981067b71SMika Kuoppala /* 253081067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 253181067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 253281067b71SMika Kuoppala * New indications can and will light up during processing, 253381067b71SMika Kuoppala * and will generate new interrupt after enabling master. 253481067b71SMika Kuoppala */ 253581067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 253681067b71SMika Kuoppala } 253781067b71SMika Kuoppala 253881067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 253981067b71SMika Kuoppala { 254081067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 254181067b71SMika Kuoppala } 254281067b71SMika Kuoppala 25437be8782aSLucas De Marchi static __always_inline irqreturn_t 25447be8782aSLucas De Marchi __gen11_irq_handler(struct drm_i915_private * const i915, 25457be8782aSLucas De Marchi u32 (*intr_disable)(void __iomem * const regs), 25467be8782aSLucas De Marchi void (*intr_enable)(void __iomem * const regs)) 254751951ae7SMika Kuoppala { 254825286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 25499b77011eSTvrtko Ursulin struct intel_gt *gt = &i915->gt; 255051951ae7SMika Kuoppala u32 master_ctl; 2551df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 255251951ae7SMika Kuoppala 255351951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 255451951ae7SMika Kuoppala return IRQ_NONE; 255551951ae7SMika Kuoppala 25567be8782aSLucas De Marchi master_ctl = intr_disable(regs); 255781067b71SMika Kuoppala if (!master_ctl) { 25587be8782aSLucas De Marchi intr_enable(regs); 255951951ae7SMika Kuoppala return IRQ_NONE; 256081067b71SMika Kuoppala } 256151951ae7SMika Kuoppala 256251951ae7SMika Kuoppala /* Find, clear, then process each source of interrupt. */ 25639b77011eSTvrtko Ursulin gen11_gt_irq_handler(gt, master_ctl); 256451951ae7SMika Kuoppala 256551951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 256651951ae7SMika Kuoppala if (master_ctl & GEN11_DISPLAY_IRQ) { 256751951ae7SMika Kuoppala const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 256851951ae7SMika Kuoppala 25699102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&i915->runtime_pm); 257051951ae7SMika Kuoppala /* 257151951ae7SMika Kuoppala * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 257251951ae7SMika Kuoppala * for the display related bits. 257351951ae7SMika Kuoppala */ 257451951ae7SMika Kuoppala gen8_de_irq_handler(i915, disp_ctl); 25759102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&i915->runtime_pm); 257651951ae7SMika Kuoppala } 257751951ae7SMika Kuoppala 25789b77011eSTvrtko Ursulin gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl); 2579df0d28c1SDhinakaran Pandiyan 25807be8782aSLucas De Marchi intr_enable(regs); 258151951ae7SMika Kuoppala 25829b77011eSTvrtko Ursulin gen11_gu_misc_irq_handler(gt, gu_misc_iir); 2583df0d28c1SDhinakaran Pandiyan 258451951ae7SMika Kuoppala return IRQ_HANDLED; 258551951ae7SMika Kuoppala } 258651951ae7SMika Kuoppala 25877be8782aSLucas De Marchi static irqreturn_t gen11_irq_handler(int irq, void *arg) 25887be8782aSLucas De Marchi { 25897be8782aSLucas De Marchi return __gen11_irq_handler(arg, 25907be8782aSLucas De Marchi gen11_master_intr_disable, 25917be8782aSLucas De Marchi gen11_master_intr_enable); 25927be8782aSLucas De Marchi } 25937be8782aSLucas De Marchi 259442f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 259542f52ef8SKeith Packard * we use as a pipe index 259642f52ef8SKeith Packard */ 259708fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc) 25980a3e67a4SJesse Barnes { 259908fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 260008fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2601e9d21d7fSKeith Packard unsigned long irqflags; 260271e0ffa5SJesse Barnes 26031ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 260486e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 260586e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 260686e83e35SChris Wilson 260786e83e35SChris Wilson return 0; 260886e83e35SChris Wilson } 260986e83e35SChris Wilson 26107d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc) 2611d938da6bSVille Syrjälä { 261208fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2613d938da6bSVille Syrjälä 26147d423af9SVille Syrjälä /* 26157d423af9SVille Syrjälä * Vblank interrupts fail to wake the device up from C2+. 26167d423af9SVille Syrjälä * Disabling render clock gating during C-states avoids 26177d423af9SVille Syrjälä * the problem. There is a small power cost so we do this 26187d423af9SVille Syrjälä * only when vblank interrupts are actually enabled. 26197d423af9SVille Syrjälä */ 26207d423af9SVille Syrjälä if (dev_priv->vblank_enabled++ == 0) 26217d423af9SVille Syrjälä I915_WRITE(SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2622d938da6bSVille Syrjälä 262308fa8fd0SVille Syrjälä return i8xx_enable_vblank(crtc); 2624d938da6bSVille Syrjälä } 2625d938da6bSVille Syrjälä 262608fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc) 262786e83e35SChris Wilson { 262808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 262908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 263086e83e35SChris Wilson unsigned long irqflags; 263186e83e35SChris Wilson 263286e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 26337c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 2634755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 26351ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 26368692d00eSChris Wilson 26370a3e67a4SJesse Barnes return 0; 26380a3e67a4SJesse Barnes } 26390a3e67a4SJesse Barnes 264008fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc) 2641f796cf8fSJesse Barnes { 264208fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 264308fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2644f796cf8fSJesse Barnes unsigned long irqflags; 2645a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 264686e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2647f796cf8fSJesse Barnes 2648f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2649fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 2650b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2651b1f14ad0SJesse Barnes 26522e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 26532e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 26542e8bf223SDhinakaran Pandiyan */ 26552e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 265608fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 26572e8bf223SDhinakaran Pandiyan 2658b1f14ad0SJesse Barnes return 0; 2659b1f14ad0SJesse Barnes } 2660b1f14ad0SJesse Barnes 266108fa8fd0SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *crtc) 2662abd58f01SBen Widawsky { 266308fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 266408fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2665abd58f01SBen Widawsky unsigned long irqflags; 2666abd58f01SBen Widawsky 2667abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2668013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2669abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2670013d3752SVille Syrjälä 26712e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 26722e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 26732e8bf223SDhinakaran Pandiyan */ 26742e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 267508fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 26762e8bf223SDhinakaran Pandiyan 2677abd58f01SBen Widawsky return 0; 2678abd58f01SBen Widawsky } 2679abd58f01SBen Widawsky 268042f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 268142f52ef8SKeith Packard * we use as a pipe index 268242f52ef8SKeith Packard */ 268308fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc) 268486e83e35SChris Wilson { 268508fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 268608fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 268786e83e35SChris Wilson unsigned long irqflags; 268886e83e35SChris Wilson 268986e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 269086e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 269186e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 269286e83e35SChris Wilson } 269386e83e35SChris Wilson 26947d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc) 2695d938da6bSVille Syrjälä { 269608fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2697d938da6bSVille Syrjälä 269808fa8fd0SVille Syrjälä i8xx_disable_vblank(crtc); 2699d938da6bSVille Syrjälä 27007d423af9SVille Syrjälä if (--dev_priv->vblank_enabled == 0) 27017d423af9SVille Syrjälä I915_WRITE(SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2702d938da6bSVille Syrjälä } 2703d938da6bSVille Syrjälä 270408fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc) 27050a3e67a4SJesse Barnes { 270608fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 270708fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2708e9d21d7fSKeith Packard unsigned long irqflags; 27090a3e67a4SJesse Barnes 27101ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 27117c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 2712755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 27131ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 27140a3e67a4SJesse Barnes } 27150a3e67a4SJesse Barnes 271608fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc) 2717f796cf8fSJesse Barnes { 271808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 271908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2720f796cf8fSJesse Barnes unsigned long irqflags; 2721a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 272286e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2723f796cf8fSJesse Barnes 2724f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2725fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 2726b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2727b1f14ad0SJesse Barnes } 2728b1f14ad0SJesse Barnes 272908fa8fd0SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *crtc) 2730abd58f01SBen Widawsky { 273108fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 273208fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2733abd58f01SBen Widawsky unsigned long irqflags; 2734abd58f01SBen Widawsky 2735abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2736013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2737abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2738abd58f01SBen Widawsky } 2739abd58f01SBen Widawsky 2740b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 274191738a95SPaulo Zanoni { 2742b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2743b16b2a2fSPaulo Zanoni 27446e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 274591738a95SPaulo Zanoni return; 274691738a95SPaulo Zanoni 2747b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 2748105b122eSPaulo Zanoni 27496e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 2750105b122eSPaulo Zanoni I915_WRITE(SERR_INT, 0xffffffff); 2751622364b6SPaulo Zanoni } 2752105b122eSPaulo Zanoni 275391738a95SPaulo Zanoni /* 2754622364b6SPaulo Zanoni * SDEIER is also touched by the interrupt handler to work around missed PCH 2755622364b6SPaulo Zanoni * interrupts. Hence we can't update it after the interrupt handler is enabled - 2756622364b6SPaulo Zanoni * instead we unconditionally enable all PCH interrupt sources here, but then 2757622364b6SPaulo Zanoni * only unmask them as needed with SDEIMR. 2758622364b6SPaulo Zanoni * 2759622364b6SPaulo Zanoni * This function needs to be called before interrupts are enabled. 276091738a95SPaulo Zanoni */ 2761b318b824SVille Syrjälä static void ibx_irq_pre_postinstall(struct drm_i915_private *dev_priv) 2762622364b6SPaulo Zanoni { 27636e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 2764622364b6SPaulo Zanoni return; 2765622364b6SPaulo Zanoni 2766622364b6SPaulo Zanoni WARN_ON(I915_READ(SDEIER) != 0); 276791738a95SPaulo Zanoni I915_WRITE(SDEIER, 0xffffffff); 276891738a95SPaulo Zanoni POSTING_READ(SDEIER); 276991738a95SPaulo Zanoni } 277091738a95SPaulo Zanoni 277170591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 277270591a41SVille Syrjälä { 2773b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2774b16b2a2fSPaulo Zanoni 277571b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2776f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 277771b8b41dSVille Syrjälä else 2778f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK); 277971b8b41dSVille Syrjälä 2780ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 2781f0818984STvrtko Ursulin intel_uncore_write(uncore, PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 278270591a41SVille Syrjälä 278344d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 278470591a41SVille Syrjälä 2785b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, VLV_); 27868bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 278770591a41SVille Syrjälä } 278870591a41SVille Syrjälä 27898bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 27908bb61306SVille Syrjälä { 2791b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2792b16b2a2fSPaulo Zanoni 27938bb61306SVille Syrjälä u32 pipestat_mask; 27949ab981f2SVille Syrjälä u32 enable_mask; 27958bb61306SVille Syrjälä enum pipe pipe; 27968bb61306SVille Syrjälä 2797842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 27988bb61306SVille Syrjälä 27998bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 28008bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 28018bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 28028bb61306SVille Syrjälä 28039ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 28048bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2805ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 2806ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 2807ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 2808ebf5f921SVille Syrjälä 28098bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2810ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 2811ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 28126b7eafc1SVille Syrjälä 28138bd099a7SChris Wilson WARN_ON(dev_priv->irq_mask != ~0u); 28146b7eafc1SVille Syrjälä 28159ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 28168bb61306SVille Syrjälä 2817b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask); 28188bb61306SVille Syrjälä } 28198bb61306SVille Syrjälä 28208bb61306SVille Syrjälä /* drm_dma.h hooks 28218bb61306SVille Syrjälä */ 2822b318b824SVille Syrjälä static void ironlake_irq_reset(struct drm_i915_private *dev_priv) 28238bb61306SVille Syrjälä { 2824b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 28258bb61306SVille Syrjälä 2826b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, DE); 2827cf819effSLucas De Marchi if (IS_GEN(dev_priv, 7)) 2828f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); 28298bb61306SVille Syrjälä 2830fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 2831f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2832f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2833fc340442SDaniel Vetter } 2834fc340442SDaniel Vetter 2835cf1c97dcSAndi Shyti gen5_gt_irq_reset(&dev_priv->gt); 28368bb61306SVille Syrjälä 2837b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 28388bb61306SVille Syrjälä } 28398bb61306SVille Syrjälä 2840b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv) 28417e231dbeSJesse Barnes { 284234c7b8a7SVille Syrjälä I915_WRITE(VLV_MASTER_IER, 0); 284334c7b8a7SVille Syrjälä POSTING_READ(VLV_MASTER_IER); 284434c7b8a7SVille Syrjälä 2845cf1c97dcSAndi Shyti gen5_gt_irq_reset(&dev_priv->gt); 28467e231dbeSJesse Barnes 2847ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 28489918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 284970591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2850ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 28517e231dbeSJesse Barnes } 28527e231dbeSJesse Barnes 2853b318b824SVille Syrjälä static void gen8_irq_reset(struct drm_i915_private *dev_priv) 2854abd58f01SBen Widawsky { 2855b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2856d048a268SVille Syrjälä enum pipe pipe; 2857abd58f01SBen Widawsky 285825286aacSDaniele Ceraolo Spurio gen8_master_intr_disable(dev_priv->uncore.regs); 2859abd58f01SBen Widawsky 2860cf1c97dcSAndi Shyti gen8_gt_irq_reset(&dev_priv->gt); 2861abd58f01SBen Widawsky 2862f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2863f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2864e04f7eceSVille Syrjälä 2865055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 2866f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 2867813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 2868b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 2869abd58f01SBen Widawsky 2870b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2871b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2872b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 2873abd58f01SBen Widawsky 28746e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 2875b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 2876abd58f01SBen Widawsky } 2877abd58f01SBen Widawsky 2878b318b824SVille Syrjälä static void gen11_irq_reset(struct drm_i915_private *dev_priv) 287951951ae7SMika Kuoppala { 2880b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2881d048a268SVille Syrjälä enum pipe pipe; 288251951ae7SMika Kuoppala 288325286aacSDaniele Ceraolo Spurio gen11_master_intr_disable(dev_priv->uncore.regs); 288451951ae7SMika Kuoppala 28859b77011eSTvrtko Ursulin gen11_gt_irq_reset(&dev_priv->gt); 288651951ae7SMika Kuoppala 2887f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); 288851951ae7SMika Kuoppala 28898241cfbeSJosé Roberto de Souza if (INTEL_GEN(dev_priv) >= 12) { 28908241cfbeSJosé Roberto de Souza enum transcoder trans; 28918241cfbeSJosé Roberto de Souza 28928241cfbeSJosé Roberto de Souza for (trans = TRANSCODER_A; trans <= TRANSCODER_D; trans++) { 28938241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 28948241cfbeSJosé Roberto de Souza 28958241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 28968241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 28978241cfbeSJosé Roberto de Souza continue; 28988241cfbeSJosé Roberto de Souza 28998241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff); 29008241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff); 29018241cfbeSJosé Roberto de Souza } 29028241cfbeSJosé Roberto de Souza } else { 2903f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2904f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 29058241cfbeSJosé Roberto de Souza } 290662819dfdSJosé Roberto de Souza 290751951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 290851951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 290951951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 2910b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 291151951ae7SMika Kuoppala 2912b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2913b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2914b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); 2915b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 2916b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 291731604222SAnusha Srivatsa 291829b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2919b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 292051951ae7SMika Kuoppala } 292151951ae7SMika Kuoppala 29224c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 2923001bd2cbSImre Deak u8 pipe_mask) 2924d49bdb0eSPaulo Zanoni { 2925b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2926b16b2a2fSPaulo Zanoni 2927a9c287c9SJani Nikula u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; 29286831f3e3SVille Syrjälä enum pipe pipe; 2929d49bdb0eSPaulo Zanoni 293013321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 29319dfe2e3aSImre Deak 29329dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 29339dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 29349dfe2e3aSImre Deak return; 29359dfe2e3aSImre Deak } 29369dfe2e3aSImre Deak 29376831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2938b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 29396831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 29406831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 29419dfe2e3aSImre Deak 294213321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 2943d49bdb0eSPaulo Zanoni } 2944d49bdb0eSPaulo Zanoni 2945aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 2946001bd2cbSImre Deak u8 pipe_mask) 2947aae8ba84SVille Syrjälä { 2948b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 29496831f3e3SVille Syrjälä enum pipe pipe; 29506831f3e3SVille Syrjälä 2951aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 29529dfe2e3aSImre Deak 29539dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 29549dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 29559dfe2e3aSImre Deak return; 29569dfe2e3aSImre Deak } 29579dfe2e3aSImre Deak 29586831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2959b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 29609dfe2e3aSImre Deak 2961aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 2962aae8ba84SVille Syrjälä 2963aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 2964315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 2965aae8ba84SVille Syrjälä } 2966aae8ba84SVille Syrjälä 2967b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv) 296843f328d7SVille Syrjälä { 2969b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 297043f328d7SVille Syrjälä 297143f328d7SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, 0); 297243f328d7SVille Syrjälä POSTING_READ(GEN8_MASTER_IRQ); 297343f328d7SVille Syrjälä 2974cf1c97dcSAndi Shyti gen8_gt_irq_reset(&dev_priv->gt); 297543f328d7SVille Syrjälä 2976b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 297743f328d7SVille Syrjälä 2978ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 29799918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 298070591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2981ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 298243f328d7SVille Syrjälä } 298343f328d7SVille Syrjälä 298491d14251STvrtko Ursulin static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, 298587a02106SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 298687a02106SVille Syrjälä { 298787a02106SVille Syrjälä struct intel_encoder *encoder; 298887a02106SVille Syrjälä u32 enabled_irqs = 0; 298987a02106SVille Syrjälä 299091c8a326SChris Wilson for_each_intel_encoder(&dev_priv->drm, encoder) 299187a02106SVille Syrjälä if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) 299287a02106SVille Syrjälä enabled_irqs |= hpd[encoder->hpd_pin]; 299387a02106SVille Syrjälä 299487a02106SVille Syrjälä return enabled_irqs; 299587a02106SVille Syrjälä } 299687a02106SVille Syrjälä 29971a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) 29981a56b1a2SImre Deak { 29991a56b1a2SImre Deak u32 hotplug; 30001a56b1a2SImre Deak 30011a56b1a2SImre Deak /* 30021a56b1a2SImre Deak * Enable digital hotplug on the PCH, and configure the DP short pulse 30031a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec). 30041a56b1a2SImre Deak * The pulse duration bits are reserved on LPT+. 30051a56b1a2SImre Deak */ 30061a56b1a2SImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG); 30071a56b1a2SImre Deak hotplug &= ~(PORTB_PULSE_DURATION_MASK | 30081a56b1a2SImre Deak PORTC_PULSE_DURATION_MASK | 30091a56b1a2SImre Deak PORTD_PULSE_DURATION_MASK); 30101a56b1a2SImre Deak hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms; 30111a56b1a2SImre Deak hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms; 30121a56b1a2SImre Deak hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms; 30131a56b1a2SImre Deak /* 30141a56b1a2SImre Deak * When CPU and PCH are on the same package, port A 30151a56b1a2SImre Deak * HPD must be enabled in both north and south. 30161a56b1a2SImre Deak */ 30171a56b1a2SImre Deak if (HAS_PCH_LPT_LP(dev_priv)) 30181a56b1a2SImre Deak hotplug |= PORTA_HOTPLUG_ENABLE; 30191a56b1a2SImre Deak I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 30201a56b1a2SImre Deak } 30211a56b1a2SImre Deak 302291d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) 302382a28bcfSDaniel Vetter { 30241a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 302582a28bcfSDaniel Vetter 302691d14251STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) { 3027fee884edSDaniel Vetter hotplug_irqs = SDE_HOTPLUG_MASK; 302891d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ibx); 302982a28bcfSDaniel Vetter } else { 3030fee884edSDaniel Vetter hotplug_irqs = SDE_HOTPLUG_MASK_CPT; 303191d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_cpt); 303282a28bcfSDaniel Vetter } 303382a28bcfSDaniel Vetter 3034fee884edSDaniel Vetter ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 303582a28bcfSDaniel Vetter 30361a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 30376dbf30ceSVille Syrjälä } 303826951cafSXiong Zhang 303952dfdba0SLucas De Marchi static void icp_hpd_detection_setup(struct drm_i915_private *dev_priv, 304052dfdba0SLucas De Marchi u32 ddi_hotplug_enable_mask, 304152dfdba0SLucas De Marchi u32 tc_hotplug_enable_mask) 304231604222SAnusha Srivatsa { 304331604222SAnusha Srivatsa u32 hotplug; 304431604222SAnusha Srivatsa 304531604222SAnusha Srivatsa hotplug = I915_READ(SHOTPLUG_CTL_DDI); 304652dfdba0SLucas De Marchi hotplug |= ddi_hotplug_enable_mask; 304731604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_DDI, hotplug); 304831604222SAnusha Srivatsa 30498ef7e340SMatt Roper if (tc_hotplug_enable_mask) { 305031604222SAnusha Srivatsa hotplug = I915_READ(SHOTPLUG_CTL_TC); 305152dfdba0SLucas De Marchi hotplug |= tc_hotplug_enable_mask; 305231604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_TC, hotplug); 305331604222SAnusha Srivatsa } 30548ef7e340SMatt Roper } 305531604222SAnusha Srivatsa 305640e98130SLucas De Marchi static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, 305740e98130SLucas De Marchi u32 sde_ddi_mask, u32 sde_tc_mask, 305840e98130SLucas De Marchi u32 ddi_enable_mask, u32 tc_enable_mask, 305940e98130SLucas De Marchi const u32 *pins) 306031604222SAnusha Srivatsa { 306131604222SAnusha Srivatsa u32 hotplug_irqs, enabled_irqs; 306231604222SAnusha Srivatsa 306340e98130SLucas De Marchi hotplug_irqs = sde_ddi_mask | sde_tc_mask; 306440e98130SLucas De Marchi enabled_irqs = intel_hpd_enabled_irqs(dev_priv, pins); 306531604222SAnusha Srivatsa 306631604222SAnusha Srivatsa ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 306731604222SAnusha Srivatsa 306840e98130SLucas De Marchi icp_hpd_detection_setup(dev_priv, ddi_enable_mask, tc_enable_mask); 306952dfdba0SLucas De Marchi } 307052dfdba0SLucas De Marchi 307140e98130SLucas De Marchi /* 307240e98130SLucas De Marchi * EHL doesn't need most of gen11_hpd_irq_setup, it's handling only the 307340e98130SLucas De Marchi * equivalent of SDE. 307440e98130SLucas De Marchi */ 30758ef7e340SMatt Roper static void mcc_hpd_irq_setup(struct drm_i915_private *dev_priv) 30768ef7e340SMatt Roper { 307740e98130SLucas De Marchi icp_hpd_irq_setup(dev_priv, 307853448aedSVivek Kasireddy SDE_DDI_MASK_ICP, SDE_TC_HOTPLUG_ICP(PORT_TC1), 307953448aedSVivek Kasireddy ICP_DDI_HPD_ENABLE_MASK, ICP_TC_HPD_ENABLE(PORT_TC1), 3080d09ad3e7SMatt Roper hpd_icp); 308131604222SAnusha Srivatsa } 308231604222SAnusha Srivatsa 3083943682e3SMatt Roper /* 3084943682e3SMatt Roper * JSP behaves exactly the same as MCC above except that port C is mapped to 3085943682e3SMatt Roper * the DDI-C pins instead of the TC1 pins. This means we should follow TGP's 3086943682e3SMatt Roper * masks & tables rather than ICP's masks & tables. 3087943682e3SMatt Roper */ 3088943682e3SMatt Roper static void jsp_hpd_irq_setup(struct drm_i915_private *dev_priv) 3089943682e3SMatt Roper { 3090943682e3SMatt Roper icp_hpd_irq_setup(dev_priv, 3091943682e3SMatt Roper SDE_DDI_MASK_TGP, 0, 3092943682e3SMatt Roper TGP_DDI_HPD_ENABLE_MASK, 0, 3093943682e3SMatt Roper hpd_tgp); 3094943682e3SMatt Roper } 3095943682e3SMatt Roper 3096121e758eSDhinakaran Pandiyan static void gen11_hpd_detection_setup(struct drm_i915_private *dev_priv) 3097121e758eSDhinakaran Pandiyan { 3098121e758eSDhinakaran Pandiyan u32 hotplug; 3099121e758eSDhinakaran Pandiyan 3100121e758eSDhinakaran Pandiyan hotplug = I915_READ(GEN11_TC_HOTPLUG_CTL); 3101121e758eSDhinakaran Pandiyan hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | 3102121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | 3103121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | 3104121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); 3105121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_TC_HOTPLUG_CTL, hotplug); 3106b796b971SDhinakaran Pandiyan 3107b796b971SDhinakaran Pandiyan hotplug = I915_READ(GEN11_TBT_HOTPLUG_CTL); 3108b796b971SDhinakaran Pandiyan hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | 3109b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | 3110b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | 3111b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); 3112b796b971SDhinakaran Pandiyan I915_WRITE(GEN11_TBT_HOTPLUG_CTL, hotplug); 3113121e758eSDhinakaran Pandiyan } 3114121e758eSDhinakaran Pandiyan 3115121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) 3116121e758eSDhinakaran Pandiyan { 3117121e758eSDhinakaran Pandiyan u32 hotplug_irqs, enabled_irqs; 311848ef15d3SJosé Roberto de Souza const u32 *hpd; 3119121e758eSDhinakaran Pandiyan u32 val; 3120121e758eSDhinakaran Pandiyan 312148ef15d3SJosé Roberto de Souza hpd = INTEL_GEN(dev_priv) >= 12 ? hpd_gen12 : hpd_gen11; 312248ef15d3SJosé Roberto de Souza enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd); 3123b796b971SDhinakaran Pandiyan hotplug_irqs = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; 3124121e758eSDhinakaran Pandiyan 3125121e758eSDhinakaran Pandiyan val = I915_READ(GEN11_DE_HPD_IMR); 3126121e758eSDhinakaran Pandiyan val &= ~hotplug_irqs; 3127121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_DE_HPD_IMR, val); 3128121e758eSDhinakaran Pandiyan POSTING_READ(GEN11_DE_HPD_IMR); 3129121e758eSDhinakaran Pandiyan 3130121e758eSDhinakaran Pandiyan gen11_hpd_detection_setup(dev_priv); 313131604222SAnusha Srivatsa 313252dfdba0SLucas De Marchi if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP) 313340e98130SLucas De Marchi icp_hpd_irq_setup(dev_priv, SDE_DDI_MASK_TGP, SDE_TC_MASK_TGP, 313440e98130SLucas De Marchi TGP_DDI_HPD_ENABLE_MASK, 313540e98130SLucas De Marchi TGP_TC_HPD_ENABLE_MASK, hpd_tgp); 313652dfdba0SLucas De Marchi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 313740e98130SLucas De Marchi icp_hpd_irq_setup(dev_priv, SDE_DDI_MASK_ICP, SDE_TC_MASK_ICP, 313840e98130SLucas De Marchi ICP_DDI_HPD_ENABLE_MASK, 313940e98130SLucas De Marchi ICP_TC_HPD_ENABLE_MASK, hpd_icp); 3140121e758eSDhinakaran Pandiyan } 3141121e758eSDhinakaran Pandiyan 31422a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) 31432a57d9ccSImre Deak { 31443b92e263SRodrigo Vivi u32 val, hotplug; 31453b92e263SRodrigo Vivi 31463b92e263SRodrigo Vivi /* Display WA #1179 WaHardHangonHotPlug: cnp */ 31473b92e263SRodrigo Vivi if (HAS_PCH_CNP(dev_priv)) { 31483b92e263SRodrigo Vivi val = I915_READ(SOUTH_CHICKEN1); 31493b92e263SRodrigo Vivi val &= ~CHASSIS_CLK_REQ_DURATION_MASK; 31503b92e263SRodrigo Vivi val |= CHASSIS_CLK_REQ_DURATION(0xf); 31513b92e263SRodrigo Vivi I915_WRITE(SOUTH_CHICKEN1, val); 31523b92e263SRodrigo Vivi } 31532a57d9ccSImre Deak 31542a57d9ccSImre Deak /* Enable digital hotplug on the PCH */ 31552a57d9ccSImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG); 31562a57d9ccSImre Deak hotplug |= PORTA_HOTPLUG_ENABLE | 31572a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 31582a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE | 31592a57d9ccSImre Deak PORTD_HOTPLUG_ENABLE; 31602a57d9ccSImre Deak I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 31612a57d9ccSImre Deak 31622a57d9ccSImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG2); 31632a57d9ccSImre Deak hotplug |= PORTE_HOTPLUG_ENABLE; 31642a57d9ccSImre Deak I915_WRITE(PCH_PORT_HOTPLUG2, hotplug); 31652a57d9ccSImre Deak } 31662a57d9ccSImre Deak 316791d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) 31686dbf30ceSVille Syrjälä { 31692a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 31706dbf30ceSVille Syrjälä 31716dbf30ceSVille Syrjälä hotplug_irqs = SDE_HOTPLUG_MASK_SPT; 317291d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_spt); 31736dbf30ceSVille Syrjälä 31746dbf30ceSVille Syrjälä ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 31756dbf30ceSVille Syrjälä 31762a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 317726951cafSXiong Zhang } 31787fe0b973SKeith Packard 31791a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) 31801a56b1a2SImre Deak { 31811a56b1a2SImre Deak u32 hotplug; 31821a56b1a2SImre Deak 31831a56b1a2SImre Deak /* 31841a56b1a2SImre Deak * Enable digital hotplug on the CPU, and configure the DP short pulse 31851a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec) 31861a56b1a2SImre Deak * The pulse duration bits are reserved on HSW+. 31871a56b1a2SImre Deak */ 31881a56b1a2SImre Deak hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); 31891a56b1a2SImre Deak hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK; 31901a56b1a2SImre Deak hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | 31911a56b1a2SImre Deak DIGITAL_PORTA_PULSE_DURATION_2ms; 31921a56b1a2SImre Deak I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); 31931a56b1a2SImre Deak } 31941a56b1a2SImre Deak 319591d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) 3196e4ce95aaSVille Syrjälä { 31971a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 3198e4ce95aaSVille Syrjälä 319991d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 8) { 32003a3b3c7dSVille Syrjälä hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG; 320191d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bdw); 32023a3b3c7dSVille Syrjälä 32033a3b3c7dSVille Syrjälä bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 320491d14251STvrtko Ursulin } else if (INTEL_GEN(dev_priv) >= 7) { 320523bb4cb5SVille Syrjälä hotplug_irqs = DE_DP_A_HOTPLUG_IVB; 320691d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ivb); 32073a3b3c7dSVille Syrjälä 32083a3b3c7dSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 320923bb4cb5SVille Syrjälä } else { 3210e4ce95aaSVille Syrjälä hotplug_irqs = DE_DP_A_HOTPLUG; 321191d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ilk); 3212e4ce95aaSVille Syrjälä 3213e4ce95aaSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 32143a3b3c7dSVille Syrjälä } 3215e4ce95aaSVille Syrjälä 32161a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3217e4ce95aaSVille Syrjälä 321891d14251STvrtko Ursulin ibx_hpd_irq_setup(dev_priv); 3219e4ce95aaSVille Syrjälä } 3220e4ce95aaSVille Syrjälä 32212a57d9ccSImre Deak static void __bxt_hpd_detection_setup(struct drm_i915_private *dev_priv, 32222a57d9ccSImre Deak u32 enabled_irqs) 3223e0a20ad7SShashank Sharma { 32242a57d9ccSImre Deak u32 hotplug; 3225e0a20ad7SShashank Sharma 3226a52bb15bSVille Syrjälä hotplug = I915_READ(PCH_PORT_HOTPLUG); 32272a57d9ccSImre Deak hotplug |= PORTA_HOTPLUG_ENABLE | 32282a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 32292a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE; 3230d252bf68SShubhangi Shrivastava 3231d252bf68SShubhangi Shrivastava DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n", 3232d252bf68SShubhangi Shrivastava hotplug, enabled_irqs); 3233d252bf68SShubhangi Shrivastava hotplug &= ~BXT_DDI_HPD_INVERT_MASK; 3234d252bf68SShubhangi Shrivastava 3235d252bf68SShubhangi Shrivastava /* 3236d252bf68SShubhangi Shrivastava * For BXT invert bit has to be set based on AOB design 3237d252bf68SShubhangi Shrivastava * for HPD detection logic, update it based on VBT fields. 3238d252bf68SShubhangi Shrivastava */ 3239d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) && 3240d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_A)) 3241d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIA_HPD_INVERT; 3242d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && 3243d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_B)) 3244d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIB_HPD_INVERT; 3245d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && 3246d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_C)) 3247d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIC_HPD_INVERT; 3248d252bf68SShubhangi Shrivastava 3249a52bb15bSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 3250e0a20ad7SShashank Sharma } 3251e0a20ad7SShashank Sharma 32522a57d9ccSImre Deak static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) 32532a57d9ccSImre Deak { 32542a57d9ccSImre Deak __bxt_hpd_detection_setup(dev_priv, BXT_DE_PORT_HOTPLUG_MASK); 32552a57d9ccSImre Deak } 32562a57d9ccSImre Deak 32572a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) 32582a57d9ccSImre Deak { 32592a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 32602a57d9ccSImre Deak 32612a57d9ccSImre Deak enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bxt); 32622a57d9ccSImre Deak hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK; 32632a57d9ccSImre Deak 32642a57d9ccSImre Deak bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 32652a57d9ccSImre Deak 32662a57d9ccSImre Deak __bxt_hpd_detection_setup(dev_priv, enabled_irqs); 32672a57d9ccSImre Deak } 32682a57d9ccSImre Deak 3269b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) 3270d46da437SPaulo Zanoni { 327182a28bcfSDaniel Vetter u32 mask; 3272d46da437SPaulo Zanoni 32736e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3274692a04cfSDaniel Vetter return; 3275692a04cfSDaniel Vetter 32766e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 32775c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 32784ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 32795c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 32804ebc6509SDhinakaran Pandiyan else 32814ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 32828664281bSPaulo Zanoni 328365f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(&dev_priv->uncore, SDEIIR); 3284d46da437SPaulo Zanoni I915_WRITE(SDEIMR, ~mask); 32852a57d9ccSImre Deak 32862a57d9ccSImre Deak if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || 32872a57d9ccSImre Deak HAS_PCH_LPT(dev_priv)) 32881a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 32892a57d9ccSImre Deak else 32902a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 3291d46da437SPaulo Zanoni } 3292d46da437SPaulo Zanoni 3293b318b824SVille Syrjälä static void ironlake_irq_postinstall(struct drm_i915_private *dev_priv) 3294036a4a7dSZhenyu Wang { 3295b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 32968e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 32978e76f8dcSPaulo Zanoni 3298b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 7) { 32998e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 3300842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 33018e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 330223bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 330323bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 33048e76f8dcSPaulo Zanoni } else { 33058e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 3306842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 3307842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 3308e4ce95aaSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | 3309e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 3310e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 33118e76f8dcSPaulo Zanoni } 3312036a4a7dSZhenyu Wang 3313fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3314b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 3315fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 3316fc340442SDaniel Vetter } 3317fc340442SDaniel Vetter 33181ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 3319036a4a7dSZhenyu Wang 3320b318b824SVille Syrjälä ibx_irq_pre_postinstall(dev_priv); 3321622364b6SPaulo Zanoni 3322b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, 3323b16b2a2fSPaulo Zanoni display_mask | extra_mask); 3324036a4a7dSZhenyu Wang 3325cf1c97dcSAndi Shyti gen5_gt_irq_postinstall(&dev_priv->gt); 3326036a4a7dSZhenyu Wang 33271a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 33281a56b1a2SImre Deak 3329b318b824SVille Syrjälä ibx_irq_postinstall(dev_priv); 33307fe0b973SKeith Packard 333150a0bc90STvrtko Ursulin if (IS_IRONLAKE_M(dev_priv)) { 33326005ce42SDaniel Vetter /* Enable PCU event interrupts 33336005ce42SDaniel Vetter * 33346005ce42SDaniel Vetter * spinlocking not required here for correctness since interrupt 33354bc9d430SDaniel Vetter * setup is guaranteed to run in single-threaded context. But we 33364bc9d430SDaniel Vetter * need it to make the assert_spin_locked happy. */ 3337d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3338fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, DE_PCU_EVENT); 3339d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3340f97108d1SJesse Barnes } 3341036a4a7dSZhenyu Wang } 3342036a4a7dSZhenyu Wang 3343f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 3344f8b79e58SImre Deak { 334567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3346f8b79e58SImre Deak 3347f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 3348f8b79e58SImre Deak return; 3349f8b79e58SImre Deak 3350f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 3351f8b79e58SImre Deak 3352d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 3353d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 3354ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3355f8b79e58SImre Deak } 3356d6c69803SVille Syrjälä } 3357f8b79e58SImre Deak 3358f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 3359f8b79e58SImre Deak { 336067520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3361f8b79e58SImre Deak 3362f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 3363f8b79e58SImre Deak return; 3364f8b79e58SImre Deak 3365f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 3366f8b79e58SImre Deak 3367950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 3368ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 3369f8b79e58SImre Deak } 3370f8b79e58SImre Deak 33710e6c9a9eSVille Syrjälä 3372b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) 33730e6c9a9eSVille Syrjälä { 3374cf1c97dcSAndi Shyti gen5_gt_irq_postinstall(&dev_priv->gt); 33757e231dbeSJesse Barnes 3376ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 33779918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3378ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3379ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3380ad22d106SVille Syrjälä 33817e231dbeSJesse Barnes I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 338234c7b8a7SVille Syrjälä POSTING_READ(VLV_MASTER_IER); 338320afbda2SDaniel Vetter } 338420afbda2SDaniel Vetter 3385abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 3386abd58f01SBen Widawsky { 3387b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3388b16b2a2fSPaulo Zanoni 3389a9c287c9SJani Nikula u32 de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE; 3390a9c287c9SJani Nikula u32 de_pipe_enables; 33913a3b3c7dSVille Syrjälä u32 de_port_masked = GEN8_AUX_CHANNEL_A; 33923a3b3c7dSVille Syrjälä u32 de_port_enables; 3393df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 33943a3b3c7dSVille Syrjälä enum pipe pipe; 3395770de83dSDamien Lespiau 3396df0d28c1SDhinakaran Pandiyan if (INTEL_GEN(dev_priv) <= 10) 3397df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 3398df0d28c1SDhinakaran Pandiyan 3399bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 9) { 3400842ebf7aSVille Syrjälä de_pipe_masked |= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 34013a3b3c7dSVille Syrjälä de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | 340288e04703SJesse Barnes GEN9_AUX_CHANNEL_D; 3403cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 34043a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 34053a3b3c7dSVille Syrjälä } else { 3406842ebf7aSVille Syrjälä de_pipe_masked |= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 34073a3b3c7dSVille Syrjälä } 3408770de83dSDamien Lespiau 3409bb187e93SJames Ausmus if (INTEL_GEN(dev_priv) >= 11) 3410bb187e93SJames Ausmus de_port_masked |= ICL_AUX_CHANNEL_E; 3411bb187e93SJames Ausmus 34129bb635d9SDhinakaran Pandiyan if (IS_CNL_WITH_PORT_F(dev_priv) || INTEL_GEN(dev_priv) >= 11) 3413a324fcacSRodrigo Vivi de_port_masked |= CNL_AUX_CHANNEL_F; 3414a324fcacSRodrigo Vivi 3415770de83dSDamien Lespiau de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | 3416770de83dSDamien Lespiau GEN8_PIPE_FIFO_UNDERRUN; 3417770de83dSDamien Lespiau 34183a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 3419cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 3420a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 3421a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 34223a3b3c7dSVille Syrjälä de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; 34233a3b3c7dSVille Syrjälä 34248241cfbeSJosé Roberto de Souza if (INTEL_GEN(dev_priv) >= 12) { 34258241cfbeSJosé Roberto de Souza enum transcoder trans; 34268241cfbeSJosé Roberto de Souza 34278241cfbeSJosé Roberto de Souza for (trans = TRANSCODER_A; trans <= TRANSCODER_D; trans++) { 34288241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 34298241cfbeSJosé Roberto de Souza 34308241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 34318241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 34328241cfbeSJosé Roberto de Souza continue; 34338241cfbeSJosé Roberto de Souza 34348241cfbeSJosé Roberto de Souza gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans)); 34358241cfbeSJosé Roberto de Souza } 34368241cfbeSJosé Roberto de Souza } else { 3437b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 34388241cfbeSJosé Roberto de Souza } 3439e04f7eceSVille Syrjälä 34400a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 34410a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 3442abd58f01SBen Widawsky 3443f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3444813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3445b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 3446813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 344735079899SPaulo Zanoni de_pipe_enables); 34480a195c02SMika Kahola } 3449abd58f01SBen Widawsky 3450b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 3451b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 34522a57d9ccSImre Deak 3453121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11) { 3454121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 3455b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 3456b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 3457121e758eSDhinakaran Pandiyan 3458b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, 3459b16b2a2fSPaulo Zanoni de_hpd_enables); 3460121e758eSDhinakaran Pandiyan gen11_hpd_detection_setup(dev_priv); 3461121e758eSDhinakaran Pandiyan } else if (IS_GEN9_LP(dev_priv)) { 34622a57d9ccSImre Deak bxt_hpd_detection_setup(dev_priv); 3463121e758eSDhinakaran Pandiyan } else if (IS_BROADWELL(dev_priv)) { 34641a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3465abd58f01SBen Widawsky } 3466121e758eSDhinakaran Pandiyan } 3467abd58f01SBen Widawsky 3468b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) 3469abd58f01SBen Widawsky { 34706e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 3471b318b824SVille Syrjälä ibx_irq_pre_postinstall(dev_priv); 3472622364b6SPaulo Zanoni 3473cf1c97dcSAndi Shyti gen8_gt_irq_postinstall(&dev_priv->gt); 3474abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 3475abd58f01SBen Widawsky 34766e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 3477b318b824SVille Syrjälä ibx_irq_postinstall(dev_priv); 3478abd58f01SBen Widawsky 347925286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 3480abd58f01SBen Widawsky } 3481abd58f01SBen Widawsky 3482b318b824SVille Syrjälä static void icp_irq_postinstall(struct drm_i915_private *dev_priv) 348331604222SAnusha Srivatsa { 348431604222SAnusha Srivatsa u32 mask = SDE_GMBUS_ICP; 348531604222SAnusha Srivatsa 348631604222SAnusha Srivatsa WARN_ON(I915_READ(SDEIER) != 0); 348731604222SAnusha Srivatsa I915_WRITE(SDEIER, 0xffffffff); 348831604222SAnusha Srivatsa POSTING_READ(SDEIER); 348931604222SAnusha Srivatsa 349065f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(&dev_priv->uncore, SDEIIR); 349131604222SAnusha Srivatsa I915_WRITE(SDEIMR, ~mask); 349231604222SAnusha Srivatsa 349352dfdba0SLucas De Marchi if (HAS_PCH_TGP(dev_priv)) 349452dfdba0SLucas De Marchi icp_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK, 349552dfdba0SLucas De Marchi TGP_TC_HPD_ENABLE_MASK); 3496e83c4673SVivek Kasireddy else if (HAS_PCH_JSP(dev_priv)) 34978ef7e340SMatt Roper icp_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK, 0); 3498e83c4673SVivek Kasireddy else if (HAS_PCH_MCC(dev_priv)) 3499e83c4673SVivek Kasireddy icp_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK, 3500e83c4673SVivek Kasireddy ICP_TC_HPD_ENABLE(PORT_TC1)); 350152dfdba0SLucas De Marchi else 350252dfdba0SLucas De Marchi icp_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK, 350352dfdba0SLucas De Marchi ICP_TC_HPD_ENABLE_MASK); 350431604222SAnusha Srivatsa } 350531604222SAnusha Srivatsa 3506b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) 350751951ae7SMika Kuoppala { 3508b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3509df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 351051951ae7SMika Kuoppala 351129b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 3512b318b824SVille Syrjälä icp_irq_postinstall(dev_priv); 351331604222SAnusha Srivatsa 35149b77011eSTvrtko Ursulin gen11_gt_irq_postinstall(&dev_priv->gt); 351551951ae7SMika Kuoppala gen8_de_irq_postinstall(dev_priv); 351651951ae7SMika Kuoppala 3517b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 3518df0d28c1SDhinakaran Pandiyan 351951951ae7SMika Kuoppala I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); 352051951ae7SMika Kuoppala 35219b77011eSTvrtko Ursulin gen11_master_intr_enable(uncore->regs); 3522c25f0c6aSDaniele Ceraolo Spurio POSTING_READ(GEN11_GFX_MSTR_IRQ); 352351951ae7SMika Kuoppala } 352451951ae7SMika Kuoppala 3525b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) 352643f328d7SVille Syrjälä { 3527cf1c97dcSAndi Shyti gen8_gt_irq_postinstall(&dev_priv->gt); 352843f328d7SVille Syrjälä 3529ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 35309918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3531ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3532ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3533ad22d106SVille Syrjälä 3534e5328c43SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 353543f328d7SVille Syrjälä POSTING_READ(GEN8_MASTER_IRQ); 353643f328d7SVille Syrjälä } 353743f328d7SVille Syrjälä 3538b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv) 3539c2798b19SChris Wilson { 3540b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3541c2798b19SChris Wilson 354244d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 354344d9241eSVille Syrjälä 3544b16b2a2fSPaulo Zanoni GEN2_IRQ_RESET(uncore); 3545c2798b19SChris Wilson } 3546c2798b19SChris Wilson 3547b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) 3548c2798b19SChris Wilson { 3549b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3550e9e9848aSVille Syrjälä u16 enable_mask; 3551c2798b19SChris Wilson 35524f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, 35534f5fd91fSTvrtko Ursulin EMR, 35544f5fd91fSTvrtko Ursulin ~(I915_ERROR_PAGE_TABLE | 3555045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 3556c2798b19SChris Wilson 3557c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 3558c2798b19SChris Wilson dev_priv->irq_mask = 3559c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 356016659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 356116659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3562c2798b19SChris Wilson 3563e9e9848aSVille Syrjälä enable_mask = 3564c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3565c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 356616659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3567e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 3568e9e9848aSVille Syrjälä 3569b16b2a2fSPaulo Zanoni GEN2_IRQ_INIT(uncore, dev_priv->irq_mask, enable_mask); 3570c2798b19SChris Wilson 3571379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3572379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3573d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3574755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3575755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3576d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3577c2798b19SChris Wilson } 3578c2798b19SChris Wilson 35794f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915, 358078c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 358178c357ddSVille Syrjälä { 35824f5fd91fSTvrtko Ursulin struct intel_uncore *uncore = &i915->uncore; 358378c357ddSVille Syrjälä u16 emr; 358478c357ddSVille Syrjälä 35854f5fd91fSTvrtko Ursulin *eir = intel_uncore_read16(uncore, EIR); 358678c357ddSVille Syrjälä 358778c357ddSVille Syrjälä if (*eir) 35884f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EIR, *eir); 358978c357ddSVille Syrjälä 35904f5fd91fSTvrtko Ursulin *eir_stuck = intel_uncore_read16(uncore, EIR); 359178c357ddSVille Syrjälä if (*eir_stuck == 0) 359278c357ddSVille Syrjälä return; 359378c357ddSVille Syrjälä 359478c357ddSVille Syrjälä /* 359578c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 359678c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 359778c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 359878c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 359978c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 360078c357ddSVille Syrjälä * cleared except by handling the underlying error 360178c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 360278c357ddSVille Syrjälä * remains set. 360378c357ddSVille Syrjälä */ 36044f5fd91fSTvrtko Ursulin emr = intel_uncore_read16(uncore, EMR); 36054f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, 0xffff); 36064f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, emr | *eir_stuck); 360778c357ddSVille Syrjälä } 360878c357ddSVille Syrjälä 360978c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 361078c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 361178c357ddSVille Syrjälä { 361278c357ddSVille Syrjälä DRM_DEBUG("Master Error: EIR 0x%04x\n", eir); 361378c357ddSVille Syrjälä 361478c357ddSVille Syrjälä if (eir_stuck) 361578c357ddSVille Syrjälä DRM_DEBUG_DRIVER("EIR stuck: 0x%04x, masked\n", eir_stuck); 361678c357ddSVille Syrjälä } 361778c357ddSVille Syrjälä 361878c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 361978c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 362078c357ddSVille Syrjälä { 362178c357ddSVille Syrjälä u32 emr; 362278c357ddSVille Syrjälä 362378c357ddSVille Syrjälä *eir = I915_READ(EIR); 362478c357ddSVille Syrjälä 362578c357ddSVille Syrjälä I915_WRITE(EIR, *eir); 362678c357ddSVille Syrjälä 362778c357ddSVille Syrjälä *eir_stuck = I915_READ(EIR); 362878c357ddSVille Syrjälä if (*eir_stuck == 0) 362978c357ddSVille Syrjälä return; 363078c357ddSVille Syrjälä 363178c357ddSVille Syrjälä /* 363278c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 363378c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 363478c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 363578c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 363678c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 363778c357ddSVille Syrjälä * cleared except by handling the underlying error 363878c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 363978c357ddSVille Syrjälä * remains set. 364078c357ddSVille Syrjälä */ 364178c357ddSVille Syrjälä emr = I915_READ(EMR); 364278c357ddSVille Syrjälä I915_WRITE(EMR, 0xffffffff); 364378c357ddSVille Syrjälä I915_WRITE(EMR, emr | *eir_stuck); 364478c357ddSVille Syrjälä } 364578c357ddSVille Syrjälä 364678c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 364778c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 364878c357ddSVille Syrjälä { 364978c357ddSVille Syrjälä DRM_DEBUG("Master Error, EIR 0x%08x\n", eir); 365078c357ddSVille Syrjälä 365178c357ddSVille Syrjälä if (eir_stuck) 365278c357ddSVille Syrjälä DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masked\n", eir_stuck); 365378c357ddSVille Syrjälä } 365478c357ddSVille Syrjälä 3655ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 3656c2798b19SChris Wilson { 3657b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3658af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3659c2798b19SChris Wilson 36602dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 36612dd2a883SImre Deak return IRQ_NONE; 36622dd2a883SImre Deak 36631f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 36649102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 36651f814dacSImre Deak 3666af722d28SVille Syrjälä do { 3667af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 366878c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 3669af722d28SVille Syrjälä u16 iir; 3670af722d28SVille Syrjälä 36714f5fd91fSTvrtko Ursulin iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR); 3672c2798b19SChris Wilson if (iir == 0) 3673af722d28SVille Syrjälä break; 3674c2798b19SChris Wilson 3675af722d28SVille Syrjälä ret = IRQ_HANDLED; 3676c2798b19SChris Wilson 3677eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3678eb64343cSVille Syrjälä * signalled in iir */ 3679eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3680c2798b19SChris Wilson 368178c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 368278c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 368378c357ddSVille Syrjälä 36844f5fd91fSTvrtko Ursulin intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); 3685c2798b19SChris Wilson 3686c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 36878a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 3688c2798b19SChris Wilson 368978c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 369078c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 3691af722d28SVille Syrjälä 3692eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3693af722d28SVille Syrjälä } while (0); 3694c2798b19SChris Wilson 36959102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 36961f814dacSImre Deak 36971f814dacSImre Deak return ret; 3698c2798b19SChris Wilson } 3699c2798b19SChris Wilson 3700b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv) 3701a266c7d5SChris Wilson { 3702b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3703a266c7d5SChris Wilson 370456b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 37050706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 3706a266c7d5SChris Wilson I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 3707a266c7d5SChris Wilson } 3708a266c7d5SChris Wilson 370944d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 371044d9241eSVille Syrjälä 3711b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 3712a266c7d5SChris Wilson } 3713a266c7d5SChris Wilson 3714b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv) 3715a266c7d5SChris Wilson { 3716b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 371738bde180SChris Wilson u32 enable_mask; 3718a266c7d5SChris Wilson 3719045cebd2SVille Syrjälä I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | 3720045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 372138bde180SChris Wilson 372238bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 372338bde180SChris Wilson dev_priv->irq_mask = 372438bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 372538bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 372616659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 372716659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 372838bde180SChris Wilson 372938bde180SChris Wilson enable_mask = 373038bde180SChris Wilson I915_ASLE_INTERRUPT | 373138bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 373238bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 373316659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 373438bde180SChris Wilson I915_USER_INTERRUPT; 373538bde180SChris Wilson 373656b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 3737a266c7d5SChris Wilson /* Enable in IER... */ 3738a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 3739a266c7d5SChris Wilson /* and unmask in IMR */ 3740a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 3741a266c7d5SChris Wilson } 3742a266c7d5SChris Wilson 3743b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 3744a266c7d5SChris Wilson 3745379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3746379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3747d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3748755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3749755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3750d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3751379ef82dSDaniel Vetter 3752c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 375320afbda2SDaniel Vetter } 375420afbda2SDaniel Vetter 3755ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 3756a266c7d5SChris Wilson { 3757b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3758af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3759a266c7d5SChris Wilson 37602dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 37612dd2a883SImre Deak return IRQ_NONE; 37622dd2a883SImre Deak 37631f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 37649102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 37651f814dacSImre Deak 376638bde180SChris Wilson do { 3767eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 376878c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 3769af722d28SVille Syrjälä u32 hotplug_status = 0; 3770af722d28SVille Syrjälä u32 iir; 3771a266c7d5SChris Wilson 37729d9523d8SPaulo Zanoni iir = I915_READ(GEN2_IIR); 3773af722d28SVille Syrjälä if (iir == 0) 3774af722d28SVille Syrjälä break; 3775af722d28SVille Syrjälä 3776af722d28SVille Syrjälä ret = IRQ_HANDLED; 3777af722d28SVille Syrjälä 3778af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 3779af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 3780af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 3781a266c7d5SChris Wilson 3782eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3783eb64343cSVille Syrjälä * signalled in iir */ 3784eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3785a266c7d5SChris Wilson 378678c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 378778c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 378878c357ddSVille Syrjälä 37899d9523d8SPaulo Zanoni I915_WRITE(GEN2_IIR, iir); 3790a266c7d5SChris Wilson 3791a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 37928a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 3793a266c7d5SChris Wilson 379478c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 379578c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 3796a266c7d5SChris Wilson 3797af722d28SVille Syrjälä if (hotplug_status) 3798af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 3799af722d28SVille Syrjälä 3800af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3801af722d28SVille Syrjälä } while (0); 3802a266c7d5SChris Wilson 38039102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 38041f814dacSImre Deak 3805a266c7d5SChris Wilson return ret; 3806a266c7d5SChris Wilson } 3807a266c7d5SChris Wilson 3808b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv) 3809a266c7d5SChris Wilson { 3810b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3811a266c7d5SChris Wilson 38120706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 3813a266c7d5SChris Wilson I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 3814a266c7d5SChris Wilson 381544d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 381644d9241eSVille Syrjälä 3817b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 3818a266c7d5SChris Wilson } 3819a266c7d5SChris Wilson 3820b318b824SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv) 3821a266c7d5SChris Wilson { 3822b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3823bbba0a97SChris Wilson u32 enable_mask; 3824a266c7d5SChris Wilson u32 error_mask; 3825a266c7d5SChris Wilson 3826045cebd2SVille Syrjälä /* 3827045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 3828045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 3829045cebd2SVille Syrjälä */ 3830045cebd2SVille Syrjälä if (IS_G4X(dev_priv)) { 3831045cebd2SVille Syrjälä error_mask = ~(GM45_ERROR_PAGE_TABLE | 3832045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 3833045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 3834045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 3835045cebd2SVille Syrjälä } else { 3836045cebd2SVille Syrjälä error_mask = ~(I915_ERROR_PAGE_TABLE | 3837045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 3838045cebd2SVille Syrjälä } 3839045cebd2SVille Syrjälä I915_WRITE(EMR, error_mask); 3840045cebd2SVille Syrjälä 3841a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 3842c30bb1fdSVille Syrjälä dev_priv->irq_mask = 3843c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 3844adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 3845bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3846bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 384778c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3848bbba0a97SChris Wilson 3849c30bb1fdSVille Syrjälä enable_mask = 3850c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 3851c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 3852c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3853c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 385478c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3855c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 3856bbba0a97SChris Wilson 385791d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 3858bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 3859a266c7d5SChris Wilson 3860b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 3861c30bb1fdSVille Syrjälä 3862b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3863b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3864d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3865755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 3866755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3867755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3868d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3869a266c7d5SChris Wilson 387091d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 387120afbda2SDaniel Vetter } 387220afbda2SDaniel Vetter 387391d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) 387420afbda2SDaniel Vetter { 387520afbda2SDaniel Vetter u32 hotplug_en; 387620afbda2SDaniel Vetter 387767520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3878b5ea2d56SDaniel Vetter 3879adca4730SChris Wilson /* Note HDMI and DP share hotplug bits */ 3880e5868a31SEgbert Eich /* enable bits are the same for all generations */ 388191d14251STvrtko Ursulin hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915); 3882a266c7d5SChris Wilson /* Programming the CRT detection parameters tends 3883a266c7d5SChris Wilson to generate a spurious hotplug event about three 3884a266c7d5SChris Wilson seconds later. So just do it once. 3885a266c7d5SChris Wilson */ 388691d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 3887a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; 3888a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; 3889a266c7d5SChris Wilson 3890a266c7d5SChris Wilson /* Ignore TV since it's buggy */ 38910706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, 3892f9e3dc78SJani Nikula HOTPLUG_INT_EN_MASK | 3893f9e3dc78SJani Nikula CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | 3894f9e3dc78SJani Nikula CRT_HOTPLUG_ACTIVATION_PERIOD_64, 38950706f17cSEgbert Eich hotplug_en); 3896a266c7d5SChris Wilson } 3897a266c7d5SChris Wilson 3898ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 3899a266c7d5SChris Wilson { 3900b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3901af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3902a266c7d5SChris Wilson 39032dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 39042dd2a883SImre Deak return IRQ_NONE; 39052dd2a883SImre Deak 39061f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 39079102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 39081f814dacSImre Deak 3909af722d28SVille Syrjälä do { 3910eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 391178c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 3912af722d28SVille Syrjälä u32 hotplug_status = 0; 3913af722d28SVille Syrjälä u32 iir; 39142c8ba29fSChris Wilson 39159d9523d8SPaulo Zanoni iir = I915_READ(GEN2_IIR); 3916af722d28SVille Syrjälä if (iir == 0) 3917af722d28SVille Syrjälä break; 3918af722d28SVille Syrjälä 3919af722d28SVille Syrjälä ret = IRQ_HANDLED; 3920af722d28SVille Syrjälä 3921af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 3922af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 3923a266c7d5SChris Wilson 3924eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3925eb64343cSVille Syrjälä * signalled in iir */ 3926eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3927a266c7d5SChris Wilson 392878c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 392978c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 393078c357ddSVille Syrjälä 39319d9523d8SPaulo Zanoni I915_WRITE(GEN2_IIR, iir); 3932a266c7d5SChris Wilson 3933a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 39348a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 3935af722d28SVille Syrjälä 3936a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 39378a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); 3938a266c7d5SChris Wilson 393978c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 394078c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 3941515ac2bbSDaniel Vetter 3942af722d28SVille Syrjälä if (hotplug_status) 3943af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 3944af722d28SVille Syrjälä 3945af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3946af722d28SVille Syrjälä } while (0); 3947a266c7d5SChris Wilson 39489102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 39491f814dacSImre Deak 3950a266c7d5SChris Wilson return ret; 3951a266c7d5SChris Wilson } 3952a266c7d5SChris Wilson 3953fca52a55SDaniel Vetter /** 3954fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 3955fca52a55SDaniel Vetter * @dev_priv: i915 device instance 3956fca52a55SDaniel Vetter * 3957fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 3958fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 3959fca52a55SDaniel Vetter */ 3960b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 3961f71d4af4SJesse Barnes { 396291c8a326SChris Wilson struct drm_device *dev = &dev_priv->drm; 3963cefcff8fSJoonas Lahtinen int i; 39648b2e326dSChris Wilson 396577913b39SJani Nikula intel_hpd_init_work(dev_priv); 396677913b39SJani Nikula 3967a4da4fa4SDaniel Vetter INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); 3968cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 3969cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 39708b2e326dSChris Wilson 3971633023a4SDaniele Ceraolo Spurio /* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */ 3972702668e6SDaniele Ceraolo Spurio if (HAS_GT_UC(dev_priv) && INTEL_GEN(dev_priv) < 11) 39732239e6dfSDaniele Ceraolo Spurio dev_priv->gt.pm_guc_events = GUC_INTR_GUC2HOST << 16; 397426705e20SSagar Arun Kamble 397521da2700SVille Syrjälä dev->vblank_disable_immediate = true; 397621da2700SVille Syrjälä 3977262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 3978262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 3979262fd485SChris Wilson * special care to avoid writing any of the display block registers 3980262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 3981262fd485SChris Wilson * in this case to the runtime pm. 3982262fd485SChris Wilson */ 3983262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 3984262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 3985262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 3986262fd485SChris Wilson 3987317eaa95SLyude dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; 39889a64c650SLyude Paul /* If we have MST support, we want to avoid doing short HPD IRQ storm 39899a64c650SLyude Paul * detection, as short HPD storms will occur as a natural part of 39909a64c650SLyude Paul * sideband messaging with MST. 39919a64c650SLyude Paul * On older platforms however, IRQ storms can occur with both long and 39929a64c650SLyude Paul * short pulses, as seen on some G4x systems. 39939a64c650SLyude Paul */ 39949a64c650SLyude Paul dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); 3995317eaa95SLyude 3996b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 3997b318b824SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv)) 399843f328d7SVille Syrjälä dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 3999b318b824SVille Syrjälä } else { 4000943682e3SMatt Roper if (HAS_PCH_JSP(dev_priv)) 4001943682e3SMatt Roper dev_priv->display.hpd_irq_setup = jsp_hpd_irq_setup; 4002943682e3SMatt Roper else if (HAS_PCH_MCC(dev_priv)) 40038ef7e340SMatt Roper dev_priv->display.hpd_irq_setup = mcc_hpd_irq_setup; 40048ef7e340SMatt Roper else if (INTEL_GEN(dev_priv) >= 11) 4005121e758eSDhinakaran Pandiyan dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; 4006b318b824SVille Syrjälä else if (IS_GEN9_LP(dev_priv)) 4007e0a20ad7SShashank Sharma dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; 4008c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 40096dbf30ceSVille Syrjälä dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; 40106dbf30ceSVille Syrjälä else 40113a3b3c7dSVille Syrjälä dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; 4012f71d4af4SJesse Barnes } 4013f71d4af4SJesse Barnes } 401420afbda2SDaniel Vetter 4015fca52a55SDaniel Vetter /** 4016cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 4017cefcff8fSJoonas Lahtinen * @i915: i915 device instance 4018cefcff8fSJoonas Lahtinen * 4019cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 4020cefcff8fSJoonas Lahtinen */ 4021cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 4022cefcff8fSJoonas Lahtinen { 4023cefcff8fSJoonas Lahtinen int i; 4024cefcff8fSJoonas Lahtinen 4025cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4026cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 4027cefcff8fSJoonas Lahtinen } 4028cefcff8fSJoonas Lahtinen 4029b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) 4030b318b824SVille Syrjälä { 4031b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4032b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4033b318b824SVille Syrjälä return cherryview_irq_handler; 4034b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4035b318b824SVille Syrjälä return valleyview_irq_handler; 4036b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 4)) 4037b318b824SVille Syrjälä return i965_irq_handler; 4038b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 3)) 4039b318b824SVille Syrjälä return i915_irq_handler; 4040b318b824SVille Syrjälä else 4041b318b824SVille Syrjälä return i8xx_irq_handler; 4042b318b824SVille Syrjälä } else { 4043b318b824SVille Syrjälä if (INTEL_GEN(dev_priv) >= 11) 4044b318b824SVille Syrjälä return gen11_irq_handler; 4045b318b824SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 8) 4046b318b824SVille Syrjälä return gen8_irq_handler; 4047b318b824SVille Syrjälä else 4048b318b824SVille Syrjälä return ironlake_irq_handler; 4049b318b824SVille Syrjälä } 4050b318b824SVille Syrjälä } 4051b318b824SVille Syrjälä 4052b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv) 4053b318b824SVille Syrjälä { 4054b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4055b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4056b318b824SVille Syrjälä cherryview_irq_reset(dev_priv); 4057b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4058b318b824SVille Syrjälä valleyview_irq_reset(dev_priv); 4059b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 4)) 4060b318b824SVille Syrjälä i965_irq_reset(dev_priv); 4061b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 3)) 4062b318b824SVille Syrjälä i915_irq_reset(dev_priv); 4063b318b824SVille Syrjälä else 4064b318b824SVille Syrjälä i8xx_irq_reset(dev_priv); 4065b318b824SVille Syrjälä } else { 4066b318b824SVille Syrjälä if (INTEL_GEN(dev_priv) >= 11) 4067b318b824SVille Syrjälä gen11_irq_reset(dev_priv); 4068b318b824SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 8) 4069b318b824SVille Syrjälä gen8_irq_reset(dev_priv); 4070b318b824SVille Syrjälä else 4071b318b824SVille Syrjälä ironlake_irq_reset(dev_priv); 4072b318b824SVille Syrjälä } 4073b318b824SVille Syrjälä } 4074b318b824SVille Syrjälä 4075b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv) 4076b318b824SVille Syrjälä { 4077b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4078b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4079b318b824SVille Syrjälä cherryview_irq_postinstall(dev_priv); 4080b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4081b318b824SVille Syrjälä valleyview_irq_postinstall(dev_priv); 4082b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 4)) 4083b318b824SVille Syrjälä i965_irq_postinstall(dev_priv); 4084b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 3)) 4085b318b824SVille Syrjälä i915_irq_postinstall(dev_priv); 4086b318b824SVille Syrjälä else 4087b318b824SVille Syrjälä i8xx_irq_postinstall(dev_priv); 4088b318b824SVille Syrjälä } else { 4089b318b824SVille Syrjälä if (INTEL_GEN(dev_priv) >= 11) 4090b318b824SVille Syrjälä gen11_irq_postinstall(dev_priv); 4091b318b824SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 8) 4092b318b824SVille Syrjälä gen8_irq_postinstall(dev_priv); 4093b318b824SVille Syrjälä else 4094b318b824SVille Syrjälä ironlake_irq_postinstall(dev_priv); 4095b318b824SVille Syrjälä } 4096b318b824SVille Syrjälä } 4097b318b824SVille Syrjälä 4098cefcff8fSJoonas Lahtinen /** 4099fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 4100fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4101fca52a55SDaniel Vetter * 4102fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 4103fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 4104fca52a55SDaniel Vetter * 4105fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 4106fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 4107fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 4108fca52a55SDaniel Vetter */ 41092aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 41102aeb7d3aSDaniel Vetter { 4111b318b824SVille Syrjälä int irq = dev_priv->drm.pdev->irq; 4112b318b824SVille Syrjälä int ret; 4113b318b824SVille Syrjälä 41142aeb7d3aSDaniel Vetter /* 41152aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 41162aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 41172aeb7d3aSDaniel Vetter * special cases in our ordering checks. 41182aeb7d3aSDaniel Vetter */ 4119ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 41202aeb7d3aSDaniel Vetter 4121b318b824SVille Syrjälä dev_priv->drm.irq_enabled = true; 4122b318b824SVille Syrjälä 4123b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4124b318b824SVille Syrjälä 4125b318b824SVille Syrjälä ret = request_irq(irq, intel_irq_handler(dev_priv), 4126b318b824SVille Syrjälä IRQF_SHARED, DRIVER_NAME, dev_priv); 4127b318b824SVille Syrjälä if (ret < 0) { 4128b318b824SVille Syrjälä dev_priv->drm.irq_enabled = false; 4129b318b824SVille Syrjälä return ret; 4130b318b824SVille Syrjälä } 4131b318b824SVille Syrjälä 4132b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4133b318b824SVille Syrjälä 4134b318b824SVille Syrjälä return ret; 41352aeb7d3aSDaniel Vetter } 41362aeb7d3aSDaniel Vetter 4137fca52a55SDaniel Vetter /** 4138fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 4139fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4140fca52a55SDaniel Vetter * 4141fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 4142fca52a55SDaniel Vetter * resources acquired in the init functions. 4143fca52a55SDaniel Vetter */ 41442aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 41452aeb7d3aSDaniel Vetter { 4146b318b824SVille Syrjälä int irq = dev_priv->drm.pdev->irq; 4147b318b824SVille Syrjälä 4148b318b824SVille Syrjälä /* 4149789fa874SJanusz Krzysztofik * FIXME we can get called twice during driver probe 4150789fa874SJanusz Krzysztofik * error handling as well as during driver remove due to 4151789fa874SJanusz Krzysztofik * intel_modeset_driver_remove() calling us out of sequence. 4152789fa874SJanusz Krzysztofik * Would be nice if it didn't do that... 4153b318b824SVille Syrjälä */ 4154b318b824SVille Syrjälä if (!dev_priv->drm.irq_enabled) 4155b318b824SVille Syrjälä return; 4156b318b824SVille Syrjälä 4157b318b824SVille Syrjälä dev_priv->drm.irq_enabled = false; 4158b318b824SVille Syrjälä 4159b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4160b318b824SVille Syrjälä 4161b318b824SVille Syrjälä free_irq(irq, dev_priv); 4162b318b824SVille Syrjälä 41632aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 4164ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 41652aeb7d3aSDaniel Vetter } 41662aeb7d3aSDaniel Vetter 4167fca52a55SDaniel Vetter /** 4168fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 4169fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4170fca52a55SDaniel Vetter * 4171fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 4172fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4173fca52a55SDaniel Vetter */ 4174b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 4175c67a470bSPaulo Zanoni { 4176b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4177ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 4178315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 4179c67a470bSPaulo Zanoni } 4180c67a470bSPaulo Zanoni 4181fca52a55SDaniel Vetter /** 4182fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 4183fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4184fca52a55SDaniel Vetter * 4185fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 4186fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4187fca52a55SDaniel Vetter */ 4188b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 4189c67a470bSPaulo Zanoni { 4190ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 4191b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4192b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4193c67a470bSPaulo Zanoni } 4194d64575eeSJani Nikula 4195d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv) 4196d64575eeSJani Nikula { 4197d64575eeSJani Nikula /* 4198d64575eeSJani Nikula * We only use drm_irq_uninstall() at unload and VT switch, so 4199d64575eeSJani Nikula * this is the only thing we need to check. 4200d64575eeSJani Nikula */ 4201d64575eeSJani Nikula return dev_priv->runtime_pm.irqs_enabled; 4202d64575eeSJani Nikula } 4203d64575eeSJani Nikula 4204d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915) 4205d64575eeSJani Nikula { 4206d64575eeSJani Nikula synchronize_irq(i915->drm.pdev->irq); 4207d64575eeSJani Nikula } 4208