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/cpuidle.h> 3355367a27SJani Nikula #include <linux/slab.h> 3455367a27SJani Nikula #include <linux/sysrq.h> 3555367a27SJani Nikula 36fcd70cd3SDaniel Vetter #include <drm/drm_drv.h> 3755367a27SJani Nikula #include <drm/drm_irq.h> 38760285e7SDavid Howells #include <drm/i915_drm.h> 3955367a27SJani Nikula 40c0e09200SDave Airlie #include "i915_drv.h" 411c5d22f7SChris Wilson #include "i915_trace.h" 4279e53945SJesse Barnes #include "intel_drv.h" 4355367a27SJani Nikula #include "intel_psr.h" 44c0e09200SDave Airlie 45fca52a55SDaniel Vetter /** 46fca52a55SDaniel Vetter * DOC: interrupt handling 47fca52a55SDaniel Vetter * 48fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 49fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 50fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 51fca52a55SDaniel Vetter */ 52fca52a55SDaniel Vetter 53e4ce95aaSVille Syrjälä static const u32 hpd_ilk[HPD_NUM_PINS] = { 54e4ce95aaSVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG, 55e4ce95aaSVille Syrjälä }; 56e4ce95aaSVille Syrjälä 5723bb4cb5SVille Syrjälä static const u32 hpd_ivb[HPD_NUM_PINS] = { 5823bb4cb5SVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, 5923bb4cb5SVille Syrjälä }; 6023bb4cb5SVille Syrjälä 613a3b3c7dSVille Syrjälä static const u32 hpd_bdw[HPD_NUM_PINS] = { 623a3b3c7dSVille Syrjälä [HPD_PORT_A] = GEN8_PORT_DP_A_HOTPLUG, 633a3b3c7dSVille Syrjälä }; 643a3b3c7dSVille Syrjälä 657c7e10dbSVille Syrjälä static const u32 hpd_ibx[HPD_NUM_PINS] = { 66e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG, 67e5868a31SEgbert Eich [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, 68e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG, 69e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG, 70e5868a31SEgbert Eich [HPD_PORT_D] = SDE_PORTD_HOTPLUG 71e5868a31SEgbert Eich }; 72e5868a31SEgbert Eich 737c7e10dbSVille Syrjälä static const u32 hpd_cpt[HPD_NUM_PINS] = { 74e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, 7573c352a2SDaniel Vetter [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, 76e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 77e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 78e5868a31SEgbert Eich [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT 79e5868a31SEgbert Eich }; 80e5868a31SEgbert Eich 8126951cafSXiong Zhang static const u32 hpd_spt[HPD_NUM_PINS] = { 8274c0b395SVille Syrjälä [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, 8326951cafSXiong Zhang [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 8426951cafSXiong Zhang [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 8526951cafSXiong Zhang [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 8626951cafSXiong Zhang [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT 8726951cafSXiong Zhang }; 8826951cafSXiong Zhang 897c7e10dbSVille Syrjälä static const u32 hpd_mask_i915[HPD_NUM_PINS] = { 90e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_EN, 91e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, 92e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, 93e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN, 94e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN, 95e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN 96e5868a31SEgbert Eich }; 97e5868a31SEgbert Eich 987c7e10dbSVille Syrjälä static const u32 hpd_status_g4x[HPD_NUM_PINS] = { 99e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 100e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, 101e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, 102e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 103e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 104e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS 105e5868a31SEgbert Eich }; 106e5868a31SEgbert Eich 1074bca26d0SVille Syrjälä static const u32 hpd_status_i915[HPD_NUM_PINS] = { 108e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 109e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, 110e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, 111e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 112e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 113e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS 114e5868a31SEgbert Eich }; 115e5868a31SEgbert Eich 116e0a20ad7SShashank Sharma /* BXT hpd list */ 117e0a20ad7SShashank Sharma static const u32 hpd_bxt[HPD_NUM_PINS] = { 1187f3561beSSonika Jindal [HPD_PORT_A] = BXT_DE_PORT_HP_DDIA, 119e0a20ad7SShashank Sharma [HPD_PORT_B] = BXT_DE_PORT_HP_DDIB, 120e0a20ad7SShashank Sharma [HPD_PORT_C] = BXT_DE_PORT_HP_DDIC 121e0a20ad7SShashank Sharma }; 122e0a20ad7SShashank Sharma 123b796b971SDhinakaran Pandiyan static const u32 hpd_gen11[HPD_NUM_PINS] = { 124b796b971SDhinakaran Pandiyan [HPD_PORT_C] = GEN11_TC1_HOTPLUG | GEN11_TBT1_HOTPLUG, 125b796b971SDhinakaran Pandiyan [HPD_PORT_D] = GEN11_TC2_HOTPLUG | GEN11_TBT2_HOTPLUG, 126b796b971SDhinakaran Pandiyan [HPD_PORT_E] = GEN11_TC3_HOTPLUG | GEN11_TBT3_HOTPLUG, 127b796b971SDhinakaran Pandiyan [HPD_PORT_F] = GEN11_TC4_HOTPLUG | GEN11_TBT4_HOTPLUG 128121e758eSDhinakaran Pandiyan }; 129121e758eSDhinakaran Pandiyan 13031604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = { 13131604222SAnusha Srivatsa [HPD_PORT_A] = SDE_DDIA_HOTPLUG_ICP, 13231604222SAnusha Srivatsa [HPD_PORT_B] = SDE_DDIB_HOTPLUG_ICP, 13331604222SAnusha Srivatsa [HPD_PORT_C] = SDE_TC1_HOTPLUG_ICP, 13431604222SAnusha Srivatsa [HPD_PORT_D] = SDE_TC2_HOTPLUG_ICP, 13531604222SAnusha Srivatsa [HPD_PORT_E] = SDE_TC3_HOTPLUG_ICP, 13631604222SAnusha Srivatsa [HPD_PORT_F] = SDE_TC4_HOTPLUG_ICP 13731604222SAnusha Srivatsa }; 13831604222SAnusha Srivatsa 1395c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 140f86f3fb0SPaulo Zanoni #define GEN8_IRQ_RESET_NDX(type, which) do { \ 1415c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \ 1425c502442SPaulo Zanoni POSTING_READ(GEN8_##type##_IMR(which)); \ 1435c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IER(which), 0); \ 1445c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ 1455c502442SPaulo Zanoni POSTING_READ(GEN8_##type##_IIR(which)); \ 1465c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ 1475c502442SPaulo Zanoni POSTING_READ(GEN8_##type##_IIR(which)); \ 1485c502442SPaulo Zanoni } while (0) 1495c502442SPaulo Zanoni 1503488d4ebSVille Syrjälä #define GEN3_IRQ_RESET(type) do { \ 151a9d356a6SPaulo Zanoni I915_WRITE(type##IMR, 0xffffffff); \ 1525c502442SPaulo Zanoni POSTING_READ(type##IMR); \ 153a9d356a6SPaulo Zanoni I915_WRITE(type##IER, 0); \ 1545c502442SPaulo Zanoni I915_WRITE(type##IIR, 0xffffffff); \ 1555c502442SPaulo Zanoni POSTING_READ(type##IIR); \ 1565c502442SPaulo Zanoni I915_WRITE(type##IIR, 0xffffffff); \ 1575c502442SPaulo Zanoni POSTING_READ(type##IIR); \ 158a9d356a6SPaulo Zanoni } while (0) 159a9d356a6SPaulo Zanoni 160e9e9848aSVille Syrjälä #define GEN2_IRQ_RESET(type) do { \ 161e9e9848aSVille Syrjälä I915_WRITE16(type##IMR, 0xffff); \ 162e9e9848aSVille Syrjälä POSTING_READ16(type##IMR); \ 163e9e9848aSVille Syrjälä I915_WRITE16(type##IER, 0); \ 164e9e9848aSVille Syrjälä I915_WRITE16(type##IIR, 0xffff); \ 165e9e9848aSVille Syrjälä POSTING_READ16(type##IIR); \ 166e9e9848aSVille Syrjälä I915_WRITE16(type##IIR, 0xffff); \ 167e9e9848aSVille Syrjälä POSTING_READ16(type##IIR); \ 168e9e9848aSVille Syrjälä } while (0) 169e9e9848aSVille Syrjälä 170337ba017SPaulo Zanoni /* 171337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 172337ba017SPaulo Zanoni */ 1733488d4ebSVille Syrjälä static void gen3_assert_iir_is_zero(struct drm_i915_private *dev_priv, 174f0f59a00SVille Syrjälä i915_reg_t reg) 175b51a2842SVille Syrjälä { 176b51a2842SVille Syrjälä u32 val = I915_READ(reg); 177b51a2842SVille Syrjälä 178b51a2842SVille Syrjälä if (val == 0) 179b51a2842SVille Syrjälä return; 180b51a2842SVille Syrjälä 181b51a2842SVille Syrjälä WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", 182f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 183b51a2842SVille Syrjälä I915_WRITE(reg, 0xffffffff); 184b51a2842SVille Syrjälä POSTING_READ(reg); 185b51a2842SVille Syrjälä I915_WRITE(reg, 0xffffffff); 186b51a2842SVille Syrjälä POSTING_READ(reg); 187b51a2842SVille Syrjälä } 188337ba017SPaulo Zanoni 189e9e9848aSVille Syrjälä static void gen2_assert_iir_is_zero(struct drm_i915_private *dev_priv, 190e9e9848aSVille Syrjälä i915_reg_t reg) 191e9e9848aSVille Syrjälä { 192e9e9848aSVille Syrjälä u16 val = I915_READ16(reg); 193e9e9848aSVille Syrjälä 194e9e9848aSVille Syrjälä if (val == 0) 195e9e9848aSVille Syrjälä return; 196e9e9848aSVille Syrjälä 197e9e9848aSVille Syrjälä WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", 198e9e9848aSVille Syrjälä i915_mmio_reg_offset(reg), val); 199e9e9848aSVille Syrjälä I915_WRITE16(reg, 0xffff); 200e9e9848aSVille Syrjälä POSTING_READ16(reg); 201e9e9848aSVille Syrjälä I915_WRITE16(reg, 0xffff); 202e9e9848aSVille Syrjälä POSTING_READ16(reg); 203e9e9848aSVille Syrjälä } 204e9e9848aSVille Syrjälä 20535079899SPaulo Zanoni #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \ 2063488d4ebSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ 20735079899SPaulo Zanoni I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \ 2087d1bd539SVille Syrjälä I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \ 2097d1bd539SVille Syrjälä POSTING_READ(GEN8_##type##_IMR(which)); \ 21035079899SPaulo Zanoni } while (0) 21135079899SPaulo Zanoni 2123488d4ebSVille Syrjälä #define GEN3_IRQ_INIT(type, imr_val, ier_val) do { \ 2133488d4ebSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, type##IIR); \ 21435079899SPaulo Zanoni I915_WRITE(type##IER, (ier_val)); \ 2157d1bd539SVille Syrjälä I915_WRITE(type##IMR, (imr_val)); \ 2167d1bd539SVille Syrjälä POSTING_READ(type##IMR); \ 21735079899SPaulo Zanoni } while (0) 21835079899SPaulo Zanoni 219e9e9848aSVille Syrjälä #define GEN2_IRQ_INIT(type, imr_val, ier_val) do { \ 220e9e9848aSVille Syrjälä gen2_assert_iir_is_zero(dev_priv, type##IIR); \ 221e9e9848aSVille Syrjälä I915_WRITE16(type##IER, (ier_val)); \ 222e9e9848aSVille Syrjälä I915_WRITE16(type##IMR, (imr_val)); \ 223e9e9848aSVille Syrjälä POSTING_READ16(type##IMR); \ 224e9e9848aSVille Syrjälä } while (0) 225e9e9848aSVille Syrjälä 226c9a9a268SImre Deak static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); 22726705e20SSagar Arun Kamble static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); 228c9a9a268SImre Deak 2290706f17cSEgbert Eich /* For display hotplug interrupt */ 2300706f17cSEgbert Eich static inline void 2310706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, 232a9c287c9SJani Nikula u32 mask, 233a9c287c9SJani Nikula u32 bits) 2340706f17cSEgbert Eich { 235a9c287c9SJani Nikula u32 val; 2360706f17cSEgbert Eich 23767520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 2380706f17cSEgbert Eich WARN_ON(bits & ~mask); 2390706f17cSEgbert Eich 2400706f17cSEgbert Eich val = I915_READ(PORT_HOTPLUG_EN); 2410706f17cSEgbert Eich val &= ~mask; 2420706f17cSEgbert Eich val |= bits; 2430706f17cSEgbert Eich I915_WRITE(PORT_HOTPLUG_EN, val); 2440706f17cSEgbert Eich } 2450706f17cSEgbert Eich 2460706f17cSEgbert Eich /** 2470706f17cSEgbert Eich * i915_hotplug_interrupt_update - update hotplug interrupt enable 2480706f17cSEgbert Eich * @dev_priv: driver private 2490706f17cSEgbert Eich * @mask: bits to update 2500706f17cSEgbert Eich * @bits: bits to enable 2510706f17cSEgbert Eich * NOTE: the HPD enable bits are modified both inside and outside 2520706f17cSEgbert Eich * of an interrupt context. To avoid that read-modify-write cycles 2530706f17cSEgbert Eich * interfer, these bits are protected by a spinlock. Since this 2540706f17cSEgbert Eich * function is usually not called from a context where the lock is 2550706f17cSEgbert Eich * held already, this function acquires the lock itself. A non-locking 2560706f17cSEgbert Eich * version is also available. 2570706f17cSEgbert Eich */ 2580706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, 259a9c287c9SJani Nikula u32 mask, 260a9c287c9SJani Nikula u32 bits) 2610706f17cSEgbert Eich { 2620706f17cSEgbert Eich spin_lock_irq(&dev_priv->irq_lock); 2630706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); 2640706f17cSEgbert Eich spin_unlock_irq(&dev_priv->irq_lock); 2650706f17cSEgbert Eich } 2660706f17cSEgbert Eich 26796606f3bSOscar Mateo static u32 26896606f3bSOscar Mateo gen11_gt_engine_identity(struct drm_i915_private * const i915, 26996606f3bSOscar Mateo const unsigned int bank, const unsigned int bit); 27096606f3bSOscar Mateo 27160a94324SChris Wilson static bool gen11_reset_one_iir(struct drm_i915_private * const i915, 27296606f3bSOscar Mateo const unsigned int bank, 27396606f3bSOscar Mateo const unsigned int bit) 27496606f3bSOscar Mateo { 27525286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 27696606f3bSOscar Mateo u32 dw; 27796606f3bSOscar Mateo 27896606f3bSOscar Mateo lockdep_assert_held(&i915->irq_lock); 27996606f3bSOscar Mateo 28096606f3bSOscar Mateo dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); 28196606f3bSOscar Mateo if (dw & BIT(bit)) { 28296606f3bSOscar Mateo /* 28396606f3bSOscar Mateo * According to the BSpec, DW_IIR bits cannot be cleared without 28496606f3bSOscar Mateo * first servicing the Selector & Shared IIR registers. 28596606f3bSOscar Mateo */ 28696606f3bSOscar Mateo gen11_gt_engine_identity(i915, bank, bit); 28796606f3bSOscar Mateo 28896606f3bSOscar Mateo /* 28996606f3bSOscar Mateo * We locked GT INT DW by reading it. If we want to (try 29096606f3bSOscar Mateo * to) recover from this succesfully, we need to clear 29196606f3bSOscar Mateo * our bit, otherwise we are locking the register for 29296606f3bSOscar Mateo * everybody. 29396606f3bSOscar Mateo */ 29496606f3bSOscar Mateo raw_reg_write(regs, GEN11_GT_INTR_DW(bank), BIT(bit)); 29596606f3bSOscar Mateo 29696606f3bSOscar Mateo return true; 29796606f3bSOscar Mateo } 29896606f3bSOscar Mateo 29996606f3bSOscar Mateo return false; 30096606f3bSOscar Mateo } 30196606f3bSOscar Mateo 302d9dc34f1SVille Syrjälä /** 303d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 304d9dc34f1SVille Syrjälä * @dev_priv: driver private 305d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 306d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 307d9dc34f1SVille Syrjälä */ 308fbdedaeaSVille Syrjälä void ilk_update_display_irq(struct drm_i915_private *dev_priv, 309a9c287c9SJani Nikula u32 interrupt_mask, 310a9c287c9SJani Nikula u32 enabled_irq_mask) 311036a4a7dSZhenyu Wang { 312a9c287c9SJani Nikula u32 new_val; 313d9dc34f1SVille Syrjälä 31467520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3154bc9d430SDaniel Vetter 316d9dc34f1SVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 317d9dc34f1SVille Syrjälä 3189df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 319c67a470bSPaulo Zanoni return; 320c67a470bSPaulo Zanoni 321d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 322d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 323d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 324d9dc34f1SVille Syrjälä 325d9dc34f1SVille Syrjälä if (new_val != dev_priv->irq_mask) { 326d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 3271ec14ad3SChris Wilson I915_WRITE(DEIMR, dev_priv->irq_mask); 3283143a2bfSChris Wilson POSTING_READ(DEIMR); 329036a4a7dSZhenyu Wang } 330036a4a7dSZhenyu Wang } 331036a4a7dSZhenyu Wang 33243eaea13SPaulo Zanoni /** 33343eaea13SPaulo Zanoni * ilk_update_gt_irq - update GTIMR 33443eaea13SPaulo Zanoni * @dev_priv: driver private 33543eaea13SPaulo Zanoni * @interrupt_mask: mask of interrupt bits to update 33643eaea13SPaulo Zanoni * @enabled_irq_mask: mask of interrupt bits to enable 33743eaea13SPaulo Zanoni */ 33843eaea13SPaulo Zanoni static void ilk_update_gt_irq(struct drm_i915_private *dev_priv, 339a9c287c9SJani Nikula u32 interrupt_mask, 340a9c287c9SJani Nikula u32 enabled_irq_mask) 34143eaea13SPaulo Zanoni { 34267520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 34343eaea13SPaulo Zanoni 34415a17aaeSDaniel Vetter WARN_ON(enabled_irq_mask & ~interrupt_mask); 34515a17aaeSDaniel Vetter 3469df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 347c67a470bSPaulo Zanoni return; 348c67a470bSPaulo Zanoni 34943eaea13SPaulo Zanoni dev_priv->gt_irq_mask &= ~interrupt_mask; 35043eaea13SPaulo Zanoni dev_priv->gt_irq_mask |= (~enabled_irq_mask & interrupt_mask); 35143eaea13SPaulo Zanoni I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 35243eaea13SPaulo Zanoni } 35343eaea13SPaulo Zanoni 354a9c287c9SJani Nikula void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, u32 mask) 35543eaea13SPaulo Zanoni { 35643eaea13SPaulo Zanoni ilk_update_gt_irq(dev_priv, mask, mask); 35731bb59ccSChris Wilson POSTING_READ_FW(GTIMR); 35843eaea13SPaulo Zanoni } 35943eaea13SPaulo Zanoni 360a9c287c9SJani Nikula void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, u32 mask) 36143eaea13SPaulo Zanoni { 36243eaea13SPaulo Zanoni ilk_update_gt_irq(dev_priv, mask, 0); 36343eaea13SPaulo Zanoni } 36443eaea13SPaulo Zanoni 365f0f59a00SVille Syrjälä static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) 366b900b949SImre Deak { 367d02b98b8SOscar Mateo WARN_ON_ONCE(INTEL_GEN(dev_priv) >= 11); 368d02b98b8SOscar Mateo 369bca2bf2aSPandiyan, Dhinakaran return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; 370b900b949SImre Deak } 371b900b949SImre Deak 372f0f59a00SVille Syrjälä static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv) 373a72fbc3aSImre Deak { 374d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 375d02b98b8SOscar Mateo return GEN11_GPM_WGBOXPERF_INTR_MASK; 376d02b98b8SOscar Mateo else if (INTEL_GEN(dev_priv) >= 8) 377d02b98b8SOscar Mateo return GEN8_GT_IMR(2); 378d02b98b8SOscar Mateo else 379d02b98b8SOscar Mateo return GEN6_PMIMR; 380a72fbc3aSImre Deak } 381a72fbc3aSImre Deak 382f0f59a00SVille Syrjälä static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv) 383b900b949SImre Deak { 384d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 385d02b98b8SOscar Mateo return GEN11_GPM_WGBOXPERF_INTR_ENABLE; 386d02b98b8SOscar Mateo else if (INTEL_GEN(dev_priv) >= 8) 387d02b98b8SOscar Mateo return GEN8_GT_IER(2); 388d02b98b8SOscar Mateo else 389d02b98b8SOscar Mateo return GEN6_PMIER; 390b900b949SImre Deak } 391b900b949SImre Deak 392edbfdb45SPaulo Zanoni /** 393edbfdb45SPaulo Zanoni * snb_update_pm_irq - update GEN6_PMIMR 394edbfdb45SPaulo Zanoni * @dev_priv: driver private 395edbfdb45SPaulo Zanoni * @interrupt_mask: mask of interrupt bits to update 396edbfdb45SPaulo Zanoni * @enabled_irq_mask: mask of interrupt bits to enable 397edbfdb45SPaulo Zanoni */ 398edbfdb45SPaulo Zanoni static void snb_update_pm_irq(struct drm_i915_private *dev_priv, 399a9c287c9SJani Nikula u32 interrupt_mask, 400a9c287c9SJani Nikula u32 enabled_irq_mask) 401edbfdb45SPaulo Zanoni { 402a9c287c9SJani Nikula u32 new_val; 403edbfdb45SPaulo Zanoni 40415a17aaeSDaniel Vetter WARN_ON(enabled_irq_mask & ~interrupt_mask); 40515a17aaeSDaniel Vetter 40667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 407edbfdb45SPaulo Zanoni 408f4e9af4fSAkash Goel new_val = dev_priv->pm_imr; 409f52ecbcfSPaulo Zanoni new_val &= ~interrupt_mask; 410f52ecbcfSPaulo Zanoni new_val |= (~enabled_irq_mask & interrupt_mask); 411f52ecbcfSPaulo Zanoni 412f4e9af4fSAkash Goel if (new_val != dev_priv->pm_imr) { 413f4e9af4fSAkash Goel dev_priv->pm_imr = new_val; 414f4e9af4fSAkash Goel I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_imr); 415a72fbc3aSImre Deak POSTING_READ(gen6_pm_imr(dev_priv)); 416edbfdb45SPaulo Zanoni } 417f52ecbcfSPaulo Zanoni } 418edbfdb45SPaulo Zanoni 419f4e9af4fSAkash Goel void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) 420edbfdb45SPaulo Zanoni { 4219939fba2SImre Deak if (WARN_ON(!intel_irqs_enabled(dev_priv))) 4229939fba2SImre Deak return; 4239939fba2SImre Deak 424edbfdb45SPaulo Zanoni snb_update_pm_irq(dev_priv, mask, mask); 425edbfdb45SPaulo Zanoni } 426edbfdb45SPaulo Zanoni 427f4e9af4fSAkash Goel static void __gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) 4289939fba2SImre Deak { 4299939fba2SImre Deak snb_update_pm_irq(dev_priv, mask, 0); 4309939fba2SImre Deak } 4319939fba2SImre Deak 432f4e9af4fSAkash Goel void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) 433edbfdb45SPaulo Zanoni { 4349939fba2SImre Deak if (WARN_ON(!intel_irqs_enabled(dev_priv))) 4359939fba2SImre Deak return; 4369939fba2SImre Deak 437f4e9af4fSAkash Goel __gen6_mask_pm_irq(dev_priv, mask); 438f4e9af4fSAkash Goel } 439f4e9af4fSAkash Goel 4403814fd77SOscar Mateo static void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask) 441f4e9af4fSAkash Goel { 442f4e9af4fSAkash Goel i915_reg_t reg = gen6_pm_iir(dev_priv); 443f4e9af4fSAkash Goel 44467520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 445f4e9af4fSAkash Goel 446f4e9af4fSAkash Goel I915_WRITE(reg, reset_mask); 447f4e9af4fSAkash Goel I915_WRITE(reg, reset_mask); 448f4e9af4fSAkash Goel POSTING_READ(reg); 449f4e9af4fSAkash Goel } 450f4e9af4fSAkash Goel 4513814fd77SOscar Mateo static void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask) 452f4e9af4fSAkash Goel { 45367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 454f4e9af4fSAkash Goel 455f4e9af4fSAkash Goel dev_priv->pm_ier |= enable_mask; 456f4e9af4fSAkash Goel I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); 457f4e9af4fSAkash Goel gen6_unmask_pm_irq(dev_priv, enable_mask); 458f4e9af4fSAkash Goel /* unmask_pm_irq provides an implicit barrier (POSTING_READ) */ 459f4e9af4fSAkash Goel } 460f4e9af4fSAkash Goel 4613814fd77SOscar Mateo static void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask) 462f4e9af4fSAkash Goel { 46367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 464f4e9af4fSAkash Goel 465f4e9af4fSAkash Goel dev_priv->pm_ier &= ~disable_mask; 466f4e9af4fSAkash Goel __gen6_mask_pm_irq(dev_priv, disable_mask); 467f4e9af4fSAkash Goel I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); 468f4e9af4fSAkash Goel /* though a barrier is missing here, but don't really need a one */ 469edbfdb45SPaulo Zanoni } 470edbfdb45SPaulo Zanoni 471d02b98b8SOscar Mateo void gen11_reset_rps_interrupts(struct drm_i915_private *dev_priv) 472d02b98b8SOscar Mateo { 473d02b98b8SOscar Mateo spin_lock_irq(&dev_priv->irq_lock); 474d02b98b8SOscar Mateo 47596606f3bSOscar Mateo while (gen11_reset_one_iir(dev_priv, 0, GEN11_GTPM)) 47696606f3bSOscar Mateo ; 477d02b98b8SOscar Mateo 478d02b98b8SOscar Mateo dev_priv->gt_pm.rps.pm_iir = 0; 479d02b98b8SOscar Mateo 480d02b98b8SOscar Mateo spin_unlock_irq(&dev_priv->irq_lock); 481d02b98b8SOscar Mateo } 482d02b98b8SOscar Mateo 483dc97997aSChris Wilson void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) 4843cc134e3SImre Deak { 4853cc134e3SImre Deak spin_lock_irq(&dev_priv->irq_lock); 4864668f695SChris Wilson gen6_reset_pm_iir(dev_priv, GEN6_PM_RPS_EVENTS); 487562d9baeSSagar Arun Kamble dev_priv->gt_pm.rps.pm_iir = 0; 4883cc134e3SImre Deak spin_unlock_irq(&dev_priv->irq_lock); 4893cc134e3SImre Deak } 4903cc134e3SImre Deak 49191d14251STvrtko Ursulin void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) 492b900b949SImre Deak { 493562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 494562d9baeSSagar Arun Kamble 495562d9baeSSagar Arun Kamble if (READ_ONCE(rps->interrupts_enabled)) 496f2a91d1aSChris Wilson return; 497f2a91d1aSChris Wilson 498b900b949SImre Deak spin_lock_irq(&dev_priv->irq_lock); 499562d9baeSSagar Arun Kamble WARN_ON_ONCE(rps->pm_iir); 50096606f3bSOscar Mateo 501d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 50296606f3bSOscar Mateo WARN_ON_ONCE(gen11_reset_one_iir(dev_priv, 0, GEN11_GTPM)); 503d02b98b8SOscar Mateo else 504c33d247dSChris Wilson WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); 50596606f3bSOscar Mateo 506562d9baeSSagar Arun Kamble rps->interrupts_enabled = true; 507b900b949SImre Deak gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); 50878e68d36SImre Deak 509b900b949SImre Deak spin_unlock_irq(&dev_priv->irq_lock); 510b900b949SImre Deak } 511b900b949SImre Deak 51291d14251STvrtko Ursulin void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) 513b900b949SImre Deak { 514562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 515562d9baeSSagar Arun Kamble 516562d9baeSSagar Arun Kamble if (!READ_ONCE(rps->interrupts_enabled)) 517f2a91d1aSChris Wilson return; 518f2a91d1aSChris Wilson 519d4d70aa5SImre Deak spin_lock_irq(&dev_priv->irq_lock); 520562d9baeSSagar Arun Kamble rps->interrupts_enabled = false; 5219939fba2SImre Deak 522b20e3cfeSDave Gordon I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0u)); 5239939fba2SImre Deak 5244668f695SChris Wilson gen6_disable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS); 52558072ccbSImre Deak 52658072ccbSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 52791c8a326SChris Wilson synchronize_irq(dev_priv->drm.irq); 528c33d247dSChris Wilson 529c33d247dSChris Wilson /* Now that we will not be generating any more work, flush any 5303814fd77SOscar Mateo * outstanding tasks. As we are called on the RPS idle path, 531c33d247dSChris Wilson * we will reset the GPU to minimum frequencies, so the current 532c33d247dSChris Wilson * state of the worker can be discarded. 533c33d247dSChris Wilson */ 534562d9baeSSagar Arun Kamble cancel_work_sync(&rps->work); 535d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 536d02b98b8SOscar Mateo gen11_reset_rps_interrupts(dev_priv); 537d02b98b8SOscar Mateo else 538c33d247dSChris Wilson gen6_reset_rps_interrupts(dev_priv); 539b900b949SImre Deak } 540b900b949SImre Deak 54126705e20SSagar Arun Kamble void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv) 54226705e20SSagar Arun Kamble { 5431be333d3SSagar Arun Kamble assert_rpm_wakelock_held(dev_priv); 5441be333d3SSagar Arun Kamble 54526705e20SSagar Arun Kamble spin_lock_irq(&dev_priv->irq_lock); 54626705e20SSagar Arun Kamble gen6_reset_pm_iir(dev_priv, dev_priv->pm_guc_events); 54726705e20SSagar Arun Kamble spin_unlock_irq(&dev_priv->irq_lock); 54826705e20SSagar Arun Kamble } 54926705e20SSagar Arun Kamble 55026705e20SSagar Arun Kamble void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv) 55126705e20SSagar Arun Kamble { 5521be333d3SSagar Arun Kamble assert_rpm_wakelock_held(dev_priv); 5531be333d3SSagar Arun Kamble 55426705e20SSagar Arun Kamble spin_lock_irq(&dev_priv->irq_lock); 55526705e20SSagar Arun Kamble if (!dev_priv->guc.interrupts_enabled) { 55626705e20SSagar Arun Kamble WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & 55726705e20SSagar Arun Kamble dev_priv->pm_guc_events); 55826705e20SSagar Arun Kamble dev_priv->guc.interrupts_enabled = true; 55926705e20SSagar Arun Kamble gen6_enable_pm_irq(dev_priv, dev_priv->pm_guc_events); 56026705e20SSagar Arun Kamble } 56126705e20SSagar Arun Kamble spin_unlock_irq(&dev_priv->irq_lock); 56226705e20SSagar Arun Kamble } 56326705e20SSagar Arun Kamble 56426705e20SSagar Arun Kamble void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv) 56526705e20SSagar Arun Kamble { 5661be333d3SSagar Arun Kamble assert_rpm_wakelock_held(dev_priv); 5671be333d3SSagar Arun Kamble 56826705e20SSagar Arun Kamble spin_lock_irq(&dev_priv->irq_lock); 56926705e20SSagar Arun Kamble dev_priv->guc.interrupts_enabled = false; 57026705e20SSagar Arun Kamble 57126705e20SSagar Arun Kamble gen6_disable_pm_irq(dev_priv, dev_priv->pm_guc_events); 57226705e20SSagar Arun Kamble 57326705e20SSagar Arun Kamble spin_unlock_irq(&dev_priv->irq_lock); 57426705e20SSagar Arun Kamble synchronize_irq(dev_priv->drm.irq); 57526705e20SSagar Arun Kamble 57626705e20SSagar Arun Kamble gen9_reset_guc_interrupts(dev_priv); 57726705e20SSagar Arun Kamble } 57826705e20SSagar Arun Kamble 5790961021aSBen Widawsky /** 5803a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 5813a3b3c7dSVille Syrjälä * @dev_priv: driver private 5823a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 5833a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 5843a3b3c7dSVille Syrjälä */ 5853a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv, 586a9c287c9SJani Nikula u32 interrupt_mask, 587a9c287c9SJani Nikula u32 enabled_irq_mask) 5883a3b3c7dSVille Syrjälä { 589a9c287c9SJani Nikula u32 new_val; 590a9c287c9SJani Nikula u32 old_val; 5913a3b3c7dSVille Syrjälä 59267520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 5933a3b3c7dSVille Syrjälä 5943a3b3c7dSVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 5953a3b3c7dSVille Syrjälä 5963a3b3c7dSVille Syrjälä if (WARN_ON(!intel_irqs_enabled(dev_priv))) 5973a3b3c7dSVille Syrjälä return; 5983a3b3c7dSVille Syrjälä 5993a3b3c7dSVille Syrjälä old_val = I915_READ(GEN8_DE_PORT_IMR); 6003a3b3c7dSVille Syrjälä 6013a3b3c7dSVille Syrjälä new_val = old_val; 6023a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 6033a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 6043a3b3c7dSVille Syrjälä 6053a3b3c7dSVille Syrjälä if (new_val != old_val) { 6063a3b3c7dSVille Syrjälä I915_WRITE(GEN8_DE_PORT_IMR, new_val); 6073a3b3c7dSVille Syrjälä POSTING_READ(GEN8_DE_PORT_IMR); 6083a3b3c7dSVille Syrjälä } 6093a3b3c7dSVille Syrjälä } 6103a3b3c7dSVille Syrjälä 6113a3b3c7dSVille Syrjälä /** 612013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 613013d3752SVille Syrjälä * @dev_priv: driver private 614013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 615013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 616013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 617013d3752SVille Syrjälä */ 618013d3752SVille Syrjälä void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 619013d3752SVille Syrjälä enum pipe pipe, 620a9c287c9SJani Nikula u32 interrupt_mask, 621a9c287c9SJani Nikula u32 enabled_irq_mask) 622013d3752SVille Syrjälä { 623a9c287c9SJani Nikula u32 new_val; 624013d3752SVille Syrjälä 62567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 626013d3752SVille Syrjälä 627013d3752SVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 628013d3752SVille Syrjälä 629013d3752SVille Syrjälä if (WARN_ON(!intel_irqs_enabled(dev_priv))) 630013d3752SVille Syrjälä return; 631013d3752SVille Syrjälä 632013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 633013d3752SVille Syrjälä new_val &= ~interrupt_mask; 634013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 635013d3752SVille Syrjälä 636013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 637013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 638013d3752SVille Syrjälä I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 639013d3752SVille Syrjälä POSTING_READ(GEN8_DE_PIPE_IMR(pipe)); 640013d3752SVille Syrjälä } 641013d3752SVille Syrjälä } 642013d3752SVille Syrjälä 643013d3752SVille Syrjälä /** 644fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 645fee884edSDaniel Vetter * @dev_priv: driver private 646fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 647fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 648fee884edSDaniel Vetter */ 64947339cd9SDaniel Vetter void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 650a9c287c9SJani Nikula u32 interrupt_mask, 651a9c287c9SJani Nikula u32 enabled_irq_mask) 652fee884edSDaniel Vetter { 653a9c287c9SJani Nikula u32 sdeimr = I915_READ(SDEIMR); 654fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 655fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 656fee884edSDaniel Vetter 65715a17aaeSDaniel Vetter WARN_ON(enabled_irq_mask & ~interrupt_mask); 65815a17aaeSDaniel Vetter 65967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 660fee884edSDaniel Vetter 6619df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 662c67a470bSPaulo Zanoni return; 663c67a470bSPaulo Zanoni 664fee884edSDaniel Vetter I915_WRITE(SDEIMR, sdeimr); 665fee884edSDaniel Vetter POSTING_READ(SDEIMR); 666fee884edSDaniel Vetter } 6678664281bSPaulo Zanoni 6686b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 6696b12ca56SVille Syrjälä enum pipe pipe) 6707c463586SKeith Packard { 6716b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 67210c59c51SImre Deak u32 enable_mask = status_mask << 16; 67310c59c51SImre Deak 6746b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 6756b12ca56SVille Syrjälä 6766b12ca56SVille Syrjälä if (INTEL_GEN(dev_priv) < 5) 6776b12ca56SVille Syrjälä goto out; 6786b12ca56SVille Syrjälä 67910c59c51SImre Deak /* 680724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 681724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 68210c59c51SImre Deak */ 68310c59c51SImre Deak if (WARN_ON_ONCE(status_mask & PIPE_A_PSR_STATUS_VLV)) 68410c59c51SImre Deak return 0; 685724a6905SVille Syrjälä /* 686724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 687724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 688724a6905SVille Syrjälä */ 689724a6905SVille Syrjälä if (WARN_ON_ONCE(status_mask & PIPE_B_PSR_STATUS_VLV)) 690724a6905SVille Syrjälä return 0; 69110c59c51SImre Deak 69210c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 69310c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 69410c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 69510c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 69610c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 69710c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 69810c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 69910c59c51SImre Deak 7006b12ca56SVille Syrjälä out: 7016b12ca56SVille Syrjälä WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 7026b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 7036b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 7046b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 7056b12ca56SVille Syrjälä 70610c59c51SImre Deak return enable_mask; 70710c59c51SImre Deak } 70810c59c51SImre Deak 7096b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 7106b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 711755e9019SImre Deak { 7126b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 713755e9019SImre Deak u32 enable_mask; 714755e9019SImre Deak 7156b12ca56SVille Syrjälä WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, 7166b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 7176b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 7186b12ca56SVille Syrjälä 7196b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 7206b12ca56SVille Syrjälä WARN_ON(!intel_irqs_enabled(dev_priv)); 7216b12ca56SVille Syrjälä 7226b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 7236b12ca56SVille Syrjälä return; 7246b12ca56SVille Syrjälä 7256b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 7266b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 7276b12ca56SVille Syrjälä 7286b12ca56SVille Syrjälä I915_WRITE(reg, enable_mask | status_mask); 7296b12ca56SVille Syrjälä POSTING_READ(reg); 730755e9019SImre Deak } 731755e9019SImre Deak 7326b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 7336b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 734755e9019SImre Deak { 7356b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 736755e9019SImre Deak u32 enable_mask; 737755e9019SImre Deak 7386b12ca56SVille Syrjälä WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, 7396b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 7406b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 7416b12ca56SVille Syrjälä 7426b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 7436b12ca56SVille Syrjälä WARN_ON(!intel_irqs_enabled(dev_priv)); 7446b12ca56SVille Syrjälä 7456b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 7466b12ca56SVille Syrjälä return; 7476b12ca56SVille Syrjälä 7486b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 7496b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 7506b12ca56SVille Syrjälä 7516b12ca56SVille Syrjälä I915_WRITE(reg, enable_mask | status_mask); 7526b12ca56SVille Syrjälä POSTING_READ(reg); 753755e9019SImre Deak } 754755e9019SImre Deak 755f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 756f3e30485SVille Syrjälä { 757f3e30485SVille Syrjälä if (!dev_priv->opregion.asle) 758f3e30485SVille Syrjälä return false; 759f3e30485SVille Syrjälä 760f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 761f3e30485SVille Syrjälä } 762f3e30485SVille Syrjälä 763c0e09200SDave Airlie /** 764f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 76514bb2c11STvrtko Ursulin * @dev_priv: i915 device private 76601c66889SZhao Yakui */ 76791d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 76801c66889SZhao Yakui { 769f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 770f49e38ddSJani Nikula return; 771f49e38ddSJani Nikula 77213321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 77301c66889SZhao Yakui 774755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 77591d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 4) 7763b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 777755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 7781ec14ad3SChris Wilson 77913321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 78001c66889SZhao Yakui } 78101c66889SZhao Yakui 782f75f3746SVille Syrjälä /* 783f75f3746SVille Syrjälä * This timing diagram depicts the video signal in and 784f75f3746SVille Syrjälä * around the vertical blanking period. 785f75f3746SVille Syrjälä * 786f75f3746SVille Syrjälä * Assumptions about the fictitious mode used in this example: 787f75f3746SVille Syrjälä * vblank_start >= 3 788f75f3746SVille Syrjälä * vsync_start = vblank_start + 1 789f75f3746SVille Syrjälä * vsync_end = vblank_start + 2 790f75f3746SVille Syrjälä * vtotal = vblank_start + 3 791f75f3746SVille Syrjälä * 792f75f3746SVille Syrjälä * start of vblank: 793f75f3746SVille Syrjälä * latch double buffered registers 794f75f3746SVille Syrjälä * increment frame counter (ctg+) 795f75f3746SVille Syrjälä * generate start of vblank interrupt (gen4+) 796f75f3746SVille Syrjälä * | 797f75f3746SVille Syrjälä * | frame start: 798f75f3746SVille Syrjälä * | generate frame start interrupt (aka. vblank interrupt) (gmch) 799f75f3746SVille Syrjälä * | may be shifted forward 1-3 extra lines via PIPECONF 800f75f3746SVille Syrjälä * | | 801f75f3746SVille Syrjälä * | | start of vsync: 802f75f3746SVille Syrjälä * | | generate vsync interrupt 803f75f3746SVille Syrjälä * | | | 804f75f3746SVille Syrjälä * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx 805f75f3746SVille Syrjälä * . \hs/ . \hs/ \hs/ \hs/ . \hs/ 806f75f3746SVille Syrjälä * ----va---> <-----------------vb--------------------> <--------va------------- 807f75f3746SVille Syrjälä * | | <----vs-----> | 808f75f3746SVille Syrjälä * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) 809f75f3746SVille Syrjälä * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) 810f75f3746SVille Syrjälä * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) 811f75f3746SVille Syrjälä * | | | 812f75f3746SVille Syrjälä * last visible pixel first visible pixel 813f75f3746SVille Syrjälä * | increment frame counter (gen3/4) 814f75f3746SVille Syrjälä * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) 815f75f3746SVille Syrjälä * 816f75f3746SVille Syrjälä * x = horizontal active 817f75f3746SVille Syrjälä * _ = horizontal blanking 818f75f3746SVille Syrjälä * hs = horizontal sync 819f75f3746SVille Syrjälä * va = vertical active 820f75f3746SVille Syrjälä * vb = vertical blanking 821f75f3746SVille Syrjälä * vs = vertical sync 822f75f3746SVille Syrjälä * vbs = vblank_start (number) 823f75f3746SVille Syrjälä * 824f75f3746SVille Syrjälä * Summary: 825f75f3746SVille Syrjälä * - most events happen at the start of horizontal sync 826f75f3746SVille Syrjälä * - frame start happens at the start of horizontal blank, 1-4 lines 827f75f3746SVille Syrjälä * (depending on PIPECONF settings) after the start of vblank 828f75f3746SVille Syrjälä * - gen3/4 pixel and frame counter are synchronized with the start 829f75f3746SVille Syrjälä * of horizontal active on the first line of vertical active 830f75f3746SVille Syrjälä */ 831f75f3746SVille Syrjälä 83242f52ef8SKeith Packard /* Called from drm generic code, passed a 'crtc', which 83342f52ef8SKeith Packard * we use as a pipe index 83442f52ef8SKeith Packard */ 83588e72717SThierry Reding static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe) 8360a3e67a4SJesse Barnes { 837fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 83832db0b65SVille Syrjälä struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 83932db0b65SVille Syrjälä const struct drm_display_mode *mode = &vblank->hwmode; 840f0f59a00SVille Syrjälä i915_reg_t high_frame, low_frame; 8410b2a8e09SVille Syrjälä u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; 842694e409dSVille Syrjälä unsigned long irqflags; 843391f75e2SVille Syrjälä 84432db0b65SVille Syrjälä /* 84532db0b65SVille Syrjälä * On i965gm TV output the frame counter only works up to 84632db0b65SVille Syrjälä * the point when we enable the TV encoder. After that the 84732db0b65SVille Syrjälä * frame counter ceases to work and reads zero. We need a 84832db0b65SVille Syrjälä * vblank wait before enabling the TV encoder and so we 84932db0b65SVille Syrjälä * have to enable vblank interrupts while the frame counter 85032db0b65SVille Syrjälä * is still in a working state. However the core vblank code 85132db0b65SVille Syrjälä * does not like us returning non-zero frame counter values 85232db0b65SVille Syrjälä * when we've told it that we don't have a working frame 85332db0b65SVille Syrjälä * counter. Thus we must stop non-zero values leaking out. 85432db0b65SVille Syrjälä */ 85532db0b65SVille Syrjälä if (!vblank->max_vblank_count) 85632db0b65SVille Syrjälä return 0; 85732db0b65SVille Syrjälä 8580b2a8e09SVille Syrjälä htotal = mode->crtc_htotal; 8590b2a8e09SVille Syrjälä hsync_start = mode->crtc_hsync_start; 8600b2a8e09SVille Syrjälä vbl_start = mode->crtc_vblank_start; 8610b2a8e09SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 8620b2a8e09SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 863391f75e2SVille Syrjälä 8640b2a8e09SVille Syrjälä /* Convert to pixel count */ 8650b2a8e09SVille Syrjälä vbl_start *= htotal; 8660b2a8e09SVille Syrjälä 8670b2a8e09SVille Syrjälä /* Start of vblank event occurs at start of hsync */ 8680b2a8e09SVille Syrjälä vbl_start -= htotal - hsync_start; 8690b2a8e09SVille Syrjälä 8709db4a9c7SJesse Barnes high_frame = PIPEFRAME(pipe); 8719db4a9c7SJesse Barnes low_frame = PIPEFRAMEPIXEL(pipe); 8725eddb70bSChris Wilson 873694e409dSVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 874694e409dSVille Syrjälä 8750a3e67a4SJesse Barnes /* 8760a3e67a4SJesse Barnes * High & low register fields aren't synchronized, so make sure 8770a3e67a4SJesse Barnes * we get a low value that's stable across two reads of the high 8780a3e67a4SJesse Barnes * register. 8790a3e67a4SJesse Barnes */ 8800a3e67a4SJesse Barnes do { 881694e409dSVille Syrjälä high1 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK; 882694e409dSVille Syrjälä low = I915_READ_FW(low_frame); 883694e409dSVille Syrjälä high2 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK; 8840a3e67a4SJesse Barnes } while (high1 != high2); 8850a3e67a4SJesse Barnes 886694e409dSVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 887694e409dSVille Syrjälä 8885eddb70bSChris Wilson high1 >>= PIPE_FRAME_HIGH_SHIFT; 889391f75e2SVille Syrjälä pixel = low & PIPE_PIXEL_MASK; 8905eddb70bSChris Wilson low >>= PIPE_FRAME_LOW_SHIFT; 891391f75e2SVille Syrjälä 892391f75e2SVille Syrjälä /* 893391f75e2SVille Syrjälä * The frame counter increments at beginning of active. 894391f75e2SVille Syrjälä * Cook up a vblank counter by also checking the pixel 895391f75e2SVille Syrjälä * counter against vblank start. 896391f75e2SVille Syrjälä */ 897edc08d0aSVille Syrjälä return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; 8980a3e67a4SJesse Barnes } 8990a3e67a4SJesse Barnes 900974e59baSDave Airlie static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe) 9019880b7a5SJesse Barnes { 902fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 9039880b7a5SJesse Barnes 904649636efSVille Syrjälä return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); 9059880b7a5SJesse Barnes } 9069880b7a5SJesse Barnes 907aec0246fSUma Shankar /* 908aec0246fSUma Shankar * On certain encoders on certain platforms, pipe 909aec0246fSUma Shankar * scanline register will not work to get the scanline, 910aec0246fSUma Shankar * since the timings are driven from the PORT or issues 911aec0246fSUma Shankar * with scanline register updates. 912aec0246fSUma Shankar * This function will use Framestamp and current 913aec0246fSUma Shankar * timestamp registers to calculate the scanline. 914aec0246fSUma Shankar */ 915aec0246fSUma Shankar static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) 916aec0246fSUma Shankar { 917aec0246fSUma Shankar struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 918aec0246fSUma Shankar struct drm_vblank_crtc *vblank = 919aec0246fSUma Shankar &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 920aec0246fSUma Shankar const struct drm_display_mode *mode = &vblank->hwmode; 921aec0246fSUma Shankar u32 vblank_start = mode->crtc_vblank_start; 922aec0246fSUma Shankar u32 vtotal = mode->crtc_vtotal; 923aec0246fSUma Shankar u32 htotal = mode->crtc_htotal; 924aec0246fSUma Shankar u32 clock = mode->crtc_clock; 925aec0246fSUma Shankar u32 scanline, scan_prev_time, scan_curr_time, scan_post_time; 926aec0246fSUma Shankar 927aec0246fSUma Shankar /* 928aec0246fSUma Shankar * To avoid the race condition where we might cross into the 929aec0246fSUma Shankar * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR 930aec0246fSUma Shankar * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR 931aec0246fSUma Shankar * during the same frame. 932aec0246fSUma Shankar */ 933aec0246fSUma Shankar do { 934aec0246fSUma Shankar /* 935aec0246fSUma Shankar * This field provides read back of the display 936aec0246fSUma Shankar * pipe frame time stamp. The time stamp value 937aec0246fSUma Shankar * is sampled at every start of vertical blank. 938aec0246fSUma Shankar */ 939aec0246fSUma Shankar scan_prev_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); 940aec0246fSUma Shankar 941aec0246fSUma Shankar /* 942aec0246fSUma Shankar * The TIMESTAMP_CTR register has the current 943aec0246fSUma Shankar * time stamp value. 944aec0246fSUma Shankar */ 945aec0246fSUma Shankar scan_curr_time = I915_READ_FW(IVB_TIMESTAMP_CTR); 946aec0246fSUma Shankar 947aec0246fSUma Shankar scan_post_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); 948aec0246fSUma Shankar } while (scan_post_time != scan_prev_time); 949aec0246fSUma Shankar 950aec0246fSUma Shankar scanline = div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, 951aec0246fSUma Shankar clock), 1000 * htotal); 952aec0246fSUma Shankar scanline = min(scanline, vtotal - 1); 953aec0246fSUma Shankar scanline = (scanline + vblank_start) % vtotal; 954aec0246fSUma Shankar 955aec0246fSUma Shankar return scanline; 956aec0246fSUma Shankar } 957aec0246fSUma Shankar 95875aa3f63SVille Syrjälä /* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */ 959a225f079SVille Syrjälä static int __intel_get_crtc_scanline(struct intel_crtc *crtc) 960a225f079SVille Syrjälä { 961a225f079SVille Syrjälä struct drm_device *dev = crtc->base.dev; 962fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 9635caa0feaSDaniel Vetter const struct drm_display_mode *mode; 9645caa0feaSDaniel Vetter struct drm_vblank_crtc *vblank; 965a225f079SVille Syrjälä enum pipe pipe = crtc->pipe; 96680715b2fSVille Syrjälä int position, vtotal; 967a225f079SVille Syrjälä 96872259536SVille Syrjälä if (!crtc->active) 96972259536SVille Syrjälä return -1; 97072259536SVille Syrjälä 9715caa0feaSDaniel Vetter vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 9725caa0feaSDaniel Vetter mode = &vblank->hwmode; 9735caa0feaSDaniel Vetter 974aec0246fSUma Shankar if (mode->private_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) 975aec0246fSUma Shankar return __intel_get_crtc_scanline_from_timestamp(crtc); 976aec0246fSUma Shankar 97780715b2fSVille Syrjälä vtotal = mode->crtc_vtotal; 978a225f079SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 979a225f079SVille Syrjälä vtotal /= 2; 980a225f079SVille Syrjälä 981cf819effSLucas De Marchi if (IS_GEN(dev_priv, 2)) 98275aa3f63SVille Syrjälä position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; 983a225f079SVille Syrjälä else 98475aa3f63SVille Syrjälä position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 985a225f079SVille Syrjälä 986a225f079SVille Syrjälä /* 98741b578fbSJesse Barnes * On HSW, the DSL reg (0x70000) appears to return 0 if we 98841b578fbSJesse Barnes * read it just before the start of vblank. So try it again 98941b578fbSJesse Barnes * so we don't accidentally end up spanning a vblank frame 99041b578fbSJesse Barnes * increment, causing the pipe_update_end() code to squak at us. 99141b578fbSJesse Barnes * 99241b578fbSJesse Barnes * The nature of this problem means we can't simply check the ISR 99341b578fbSJesse Barnes * bit and return the vblank start value; nor can we use the scanline 99441b578fbSJesse Barnes * debug register in the transcoder as it appears to have the same 99541b578fbSJesse Barnes * problem. We may need to extend this to include other platforms, 99641b578fbSJesse Barnes * but so far testing only shows the problem on HSW. 99741b578fbSJesse Barnes */ 99891d14251STvrtko Ursulin if (HAS_DDI(dev_priv) && !position) { 99941b578fbSJesse Barnes int i, temp; 100041b578fbSJesse Barnes 100141b578fbSJesse Barnes for (i = 0; i < 100; i++) { 100241b578fbSJesse Barnes udelay(1); 1003707bdd3fSVille Syrjälä temp = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 100441b578fbSJesse Barnes if (temp != position) { 100541b578fbSJesse Barnes position = temp; 100641b578fbSJesse Barnes break; 100741b578fbSJesse Barnes } 100841b578fbSJesse Barnes } 100941b578fbSJesse Barnes } 101041b578fbSJesse Barnes 101141b578fbSJesse Barnes /* 101280715b2fSVille Syrjälä * See update_scanline_offset() for the details on the 101380715b2fSVille Syrjälä * scanline_offset adjustment. 1014a225f079SVille Syrjälä */ 101580715b2fSVille Syrjälä return (position + crtc->scanline_offset) % vtotal; 1016a225f079SVille Syrjälä } 1017a225f079SVille Syrjälä 10181bf6ad62SDaniel Vetter static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, 10191bf6ad62SDaniel Vetter bool in_vblank_irq, int *vpos, int *hpos, 10203bb403bfSVille Syrjälä ktime_t *stime, ktime_t *etime, 10213bb403bfSVille Syrjälä const struct drm_display_mode *mode) 10220af7e4dfSMario Kleiner { 1023fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 102498187836SVille Syrjälä struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, 102598187836SVille Syrjälä pipe); 10263aa18df8SVille Syrjälä int position; 102778e8fc6bSVille Syrjälä int vbl_start, vbl_end, hsync_start, htotal, vtotal; 1028ad3543edSMario Kleiner unsigned long irqflags; 10298a920e24SVille Syrjälä bool use_scanline_counter = INTEL_GEN(dev_priv) >= 5 || 10308a920e24SVille Syrjälä IS_G4X(dev_priv) || IS_GEN(dev_priv, 2) || 10318a920e24SVille Syrjälä mode->private_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; 10320af7e4dfSMario Kleiner 1033fc467a22SMaarten Lankhorst if (WARN_ON(!mode->crtc_clock)) { 10340af7e4dfSMario Kleiner DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " 10359db4a9c7SJesse Barnes "pipe %c\n", pipe_name(pipe)); 10361bf6ad62SDaniel Vetter return false; 10370af7e4dfSMario Kleiner } 10380af7e4dfSMario Kleiner 1039c2baf4b7SVille Syrjälä htotal = mode->crtc_htotal; 104078e8fc6bSVille Syrjälä hsync_start = mode->crtc_hsync_start; 1041c2baf4b7SVille Syrjälä vtotal = mode->crtc_vtotal; 1042c2baf4b7SVille Syrjälä vbl_start = mode->crtc_vblank_start; 1043c2baf4b7SVille Syrjälä vbl_end = mode->crtc_vblank_end; 10440af7e4dfSMario Kleiner 1045d31faf65SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1046d31faf65SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 1047d31faf65SVille Syrjälä vbl_end /= 2; 1048d31faf65SVille Syrjälä vtotal /= 2; 1049d31faf65SVille Syrjälä } 1050d31faf65SVille Syrjälä 1051ad3543edSMario Kleiner /* 1052ad3543edSMario Kleiner * Lock uncore.lock, as we will do multiple timing critical raw 1053ad3543edSMario Kleiner * register reads, potentially with preemption disabled, so the 1054ad3543edSMario Kleiner * following code must not block on uncore.lock. 1055ad3543edSMario Kleiner */ 1056ad3543edSMario Kleiner spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 1057ad3543edSMario Kleiner 1058ad3543edSMario Kleiner /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ 1059ad3543edSMario Kleiner 1060ad3543edSMario Kleiner /* Get optional system timestamp before query. */ 1061ad3543edSMario Kleiner if (stime) 1062ad3543edSMario Kleiner *stime = ktime_get(); 1063ad3543edSMario Kleiner 10648a920e24SVille Syrjälä if (use_scanline_counter) { 10650af7e4dfSMario Kleiner /* No obvious pixelcount register. Only query vertical 10660af7e4dfSMario Kleiner * scanout position from Display scan line register. 10670af7e4dfSMario Kleiner */ 1068a225f079SVille Syrjälä position = __intel_get_crtc_scanline(intel_crtc); 10690af7e4dfSMario Kleiner } else { 10700af7e4dfSMario Kleiner /* Have access to pixelcount since start of frame. 10710af7e4dfSMario Kleiner * We can split this into vertical and horizontal 10720af7e4dfSMario Kleiner * scanout position. 10730af7e4dfSMario Kleiner */ 107475aa3f63SVille Syrjälä position = (I915_READ_FW(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; 10750af7e4dfSMario Kleiner 10763aa18df8SVille Syrjälä /* convert to pixel counts */ 10773aa18df8SVille Syrjälä vbl_start *= htotal; 10783aa18df8SVille Syrjälä vbl_end *= htotal; 10793aa18df8SVille Syrjälä vtotal *= htotal; 108078e8fc6bSVille Syrjälä 108178e8fc6bSVille Syrjälä /* 10827e78f1cbSVille Syrjälä * In interlaced modes, the pixel counter counts all pixels, 10837e78f1cbSVille Syrjälä * so one field will have htotal more pixels. In order to avoid 10847e78f1cbSVille Syrjälä * the reported position from jumping backwards when the pixel 10857e78f1cbSVille Syrjälä * counter is beyond the length of the shorter field, just 10867e78f1cbSVille Syrjälä * clamp the position the length of the shorter field. This 10877e78f1cbSVille Syrjälä * matches how the scanline counter based position works since 10887e78f1cbSVille Syrjälä * the scanline counter doesn't count the two half lines. 10897e78f1cbSVille Syrjälä */ 10907e78f1cbSVille Syrjälä if (position >= vtotal) 10917e78f1cbSVille Syrjälä position = vtotal - 1; 10927e78f1cbSVille Syrjälä 10937e78f1cbSVille Syrjälä /* 109478e8fc6bSVille Syrjälä * Start of vblank interrupt is triggered at start of hsync, 109578e8fc6bSVille Syrjälä * just prior to the first active line of vblank. However we 109678e8fc6bSVille Syrjälä * consider lines to start at the leading edge of horizontal 109778e8fc6bSVille Syrjälä * active. So, should we get here before we've crossed into 109878e8fc6bSVille Syrjälä * the horizontal active of the first line in vblank, we would 109978e8fc6bSVille Syrjälä * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, 110078e8fc6bSVille Syrjälä * always add htotal-hsync_start to the current pixel position. 110178e8fc6bSVille Syrjälä */ 110278e8fc6bSVille Syrjälä position = (position + htotal - hsync_start) % vtotal; 11033aa18df8SVille Syrjälä } 11043aa18df8SVille Syrjälä 1105ad3543edSMario Kleiner /* Get optional system timestamp after query. */ 1106ad3543edSMario Kleiner if (etime) 1107ad3543edSMario Kleiner *etime = ktime_get(); 1108ad3543edSMario Kleiner 1109ad3543edSMario Kleiner /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ 1110ad3543edSMario Kleiner 1111ad3543edSMario Kleiner spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 1112ad3543edSMario Kleiner 11133aa18df8SVille Syrjälä /* 11143aa18df8SVille Syrjälä * While in vblank, position will be negative 11153aa18df8SVille Syrjälä * counting up towards 0 at vbl_end. And outside 11163aa18df8SVille Syrjälä * vblank, position will be positive counting 11173aa18df8SVille Syrjälä * up since vbl_end. 11183aa18df8SVille Syrjälä */ 11193aa18df8SVille Syrjälä if (position >= vbl_start) 11203aa18df8SVille Syrjälä position -= vbl_end; 11213aa18df8SVille Syrjälä else 11223aa18df8SVille Syrjälä position += vtotal - vbl_end; 11233aa18df8SVille Syrjälä 11248a920e24SVille Syrjälä if (use_scanline_counter) { 11253aa18df8SVille Syrjälä *vpos = position; 11263aa18df8SVille Syrjälä *hpos = 0; 11273aa18df8SVille Syrjälä } else { 11280af7e4dfSMario Kleiner *vpos = position / htotal; 11290af7e4dfSMario Kleiner *hpos = position - (*vpos * htotal); 11300af7e4dfSMario Kleiner } 11310af7e4dfSMario Kleiner 11321bf6ad62SDaniel Vetter return true; 11330af7e4dfSMario Kleiner } 11340af7e4dfSMario Kleiner 1135a225f079SVille Syrjälä int intel_get_crtc_scanline(struct intel_crtc *crtc) 1136a225f079SVille Syrjälä { 1137fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 1138a225f079SVille Syrjälä unsigned long irqflags; 1139a225f079SVille Syrjälä int position; 1140a225f079SVille Syrjälä 1141a225f079SVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 1142a225f079SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 1143a225f079SVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 1144a225f079SVille Syrjälä 1145a225f079SVille Syrjälä return position; 1146a225f079SVille Syrjälä } 1147a225f079SVille Syrjälä 114891d14251STvrtko Ursulin static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv) 1149f97108d1SJesse Barnes { 1150b5b72e89SMatthew Garrett u32 busy_up, busy_down, max_avg, min_avg; 11519270388eSDaniel Vetter u8 new_delay; 11529270388eSDaniel Vetter 1153d0ecd7e2SDaniel Vetter spin_lock(&mchdev_lock); 1154f97108d1SJesse Barnes 115573edd18fSDaniel Vetter I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); 115673edd18fSDaniel Vetter 115720e4d407SDaniel Vetter new_delay = dev_priv->ips.cur_delay; 11589270388eSDaniel Vetter 11597648fa99SJesse Barnes I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG); 1160b5b72e89SMatthew Garrett busy_up = I915_READ(RCPREVBSYTUPAVG); 1161b5b72e89SMatthew Garrett busy_down = I915_READ(RCPREVBSYTDNAVG); 1162f97108d1SJesse Barnes max_avg = I915_READ(RCBMAXAVG); 1163f97108d1SJesse Barnes min_avg = I915_READ(RCBMINAVG); 1164f97108d1SJesse Barnes 1165f97108d1SJesse Barnes /* Handle RCS change request from hw */ 1166b5b72e89SMatthew Garrett if (busy_up > max_avg) { 116720e4d407SDaniel Vetter if (dev_priv->ips.cur_delay != dev_priv->ips.max_delay) 116820e4d407SDaniel Vetter new_delay = dev_priv->ips.cur_delay - 1; 116920e4d407SDaniel Vetter if (new_delay < dev_priv->ips.max_delay) 117020e4d407SDaniel Vetter new_delay = dev_priv->ips.max_delay; 1171b5b72e89SMatthew Garrett } else if (busy_down < min_avg) { 117220e4d407SDaniel Vetter if (dev_priv->ips.cur_delay != dev_priv->ips.min_delay) 117320e4d407SDaniel Vetter new_delay = dev_priv->ips.cur_delay + 1; 117420e4d407SDaniel Vetter if (new_delay > dev_priv->ips.min_delay) 117520e4d407SDaniel Vetter new_delay = dev_priv->ips.min_delay; 1176f97108d1SJesse Barnes } 1177f97108d1SJesse Barnes 117891d14251STvrtko Ursulin if (ironlake_set_drps(dev_priv, new_delay)) 117920e4d407SDaniel Vetter dev_priv->ips.cur_delay = new_delay; 1180f97108d1SJesse Barnes 1181d0ecd7e2SDaniel Vetter spin_unlock(&mchdev_lock); 11829270388eSDaniel Vetter 1183f97108d1SJesse Barnes return; 1184f97108d1SJesse Barnes } 1185f97108d1SJesse Barnes 118643cf3bf0SChris Wilson static void vlv_c0_read(struct drm_i915_private *dev_priv, 118743cf3bf0SChris Wilson struct intel_rps_ei *ei) 118831685c25SDeepak S { 1189679cb6c1SMika Kuoppala ei->ktime = ktime_get_raw(); 119043cf3bf0SChris Wilson ei->render_c0 = I915_READ(VLV_RENDER_C0_COUNT); 119143cf3bf0SChris Wilson ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT); 119231685c25SDeepak S } 119331685c25SDeepak S 119443cf3bf0SChris Wilson void gen6_rps_reset_ei(struct drm_i915_private *dev_priv) 119543cf3bf0SChris Wilson { 1196562d9baeSSagar Arun Kamble memset(&dev_priv->gt_pm.rps.ei, 0, sizeof(dev_priv->gt_pm.rps.ei)); 119743cf3bf0SChris Wilson } 119843cf3bf0SChris Wilson 119943cf3bf0SChris Wilson static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) 120043cf3bf0SChris Wilson { 1201562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 1202562d9baeSSagar Arun Kamble const struct intel_rps_ei *prev = &rps->ei; 120343cf3bf0SChris Wilson struct intel_rps_ei now; 120443cf3bf0SChris Wilson u32 events = 0; 120543cf3bf0SChris Wilson 1206e0e8c7cbSChris Wilson if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0) 120743cf3bf0SChris Wilson return 0; 120843cf3bf0SChris Wilson 120943cf3bf0SChris Wilson vlv_c0_read(dev_priv, &now); 121031685c25SDeepak S 1211679cb6c1SMika Kuoppala if (prev->ktime) { 1212e0e8c7cbSChris Wilson u64 time, c0; 1213569884e3SChris Wilson u32 render, media; 1214e0e8c7cbSChris Wilson 1215679cb6c1SMika Kuoppala time = ktime_us_delta(now.ktime, prev->ktime); 12168f68d591SChris Wilson 1217e0e8c7cbSChris Wilson time *= dev_priv->czclk_freq; 1218e0e8c7cbSChris Wilson 1219e0e8c7cbSChris Wilson /* Workload can be split between render + media, 1220e0e8c7cbSChris Wilson * e.g. SwapBuffers being blitted in X after being rendered in 1221e0e8c7cbSChris Wilson * mesa. To account for this we need to combine both engines 1222e0e8c7cbSChris Wilson * into our activity counter. 1223e0e8c7cbSChris Wilson */ 1224569884e3SChris Wilson render = now.render_c0 - prev->render_c0; 1225569884e3SChris Wilson media = now.media_c0 - prev->media_c0; 1226569884e3SChris Wilson c0 = max(render, media); 12276b7f6aa7SMika Kuoppala c0 *= 1000 * 100 << 8; /* to usecs and scale to threshold% */ 1228e0e8c7cbSChris Wilson 122960548c55SChris Wilson if (c0 > time * rps->power.up_threshold) 1230e0e8c7cbSChris Wilson events = GEN6_PM_RP_UP_THRESHOLD; 123160548c55SChris Wilson else if (c0 < time * rps->power.down_threshold) 1232e0e8c7cbSChris Wilson events = GEN6_PM_RP_DOWN_THRESHOLD; 123331685c25SDeepak S } 123431685c25SDeepak S 1235562d9baeSSagar Arun Kamble rps->ei = now; 123643cf3bf0SChris Wilson return events; 123731685c25SDeepak S } 123831685c25SDeepak S 12394912d041SBen Widawsky static void gen6_pm_rps_work(struct work_struct *work) 12403b8d8d91SJesse Barnes { 12412d1013ddSJani Nikula struct drm_i915_private *dev_priv = 1242562d9baeSSagar Arun Kamble container_of(work, struct drm_i915_private, gt_pm.rps.work); 1243562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 12447c0a16adSChris Wilson bool client_boost = false; 12458d3afd7dSChris Wilson int new_delay, adj, min, max; 12467c0a16adSChris Wilson u32 pm_iir = 0; 12473b8d8d91SJesse Barnes 124859cdb63dSDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 1249562d9baeSSagar Arun Kamble if (rps->interrupts_enabled) { 1250562d9baeSSagar Arun Kamble pm_iir = fetch_and_zero(&rps->pm_iir); 1251562d9baeSSagar Arun Kamble client_boost = atomic_read(&rps->num_waiters); 1252d4d70aa5SImre Deak } 125359cdb63dSDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 12544912d041SBen Widawsky 125560611c13SPaulo Zanoni /* Make sure we didn't queue anything we're not going to process. */ 1256a6706b45SDeepak S WARN_ON(pm_iir & ~dev_priv->pm_rps_events); 12578d3afd7dSChris Wilson if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost) 12587c0a16adSChris Wilson goto out; 12593b8d8d91SJesse Barnes 12609f817501SSagar Arun Kamble mutex_lock(&dev_priv->pcu_lock); 12617b9e0ae6SChris Wilson 126243cf3bf0SChris Wilson pm_iir |= vlv_wa_c0_ei(dev_priv, pm_iir); 126343cf3bf0SChris Wilson 1264562d9baeSSagar Arun Kamble adj = rps->last_adj; 1265562d9baeSSagar Arun Kamble new_delay = rps->cur_freq; 1266562d9baeSSagar Arun Kamble min = rps->min_freq_softlimit; 1267562d9baeSSagar Arun Kamble max = rps->max_freq_softlimit; 12687b92c1bdSChris Wilson if (client_boost) 1269562d9baeSSagar Arun Kamble max = rps->max_freq; 1270562d9baeSSagar Arun Kamble if (client_boost && new_delay < rps->boost_freq) { 1271562d9baeSSagar Arun Kamble new_delay = rps->boost_freq; 12728d3afd7dSChris Wilson adj = 0; 12738d3afd7dSChris Wilson } else if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { 1274dd75fdc8SChris Wilson if (adj > 0) 1275dd75fdc8SChris Wilson adj *= 2; 1276edcf284bSChris Wilson else /* CHV needs even encode values */ 1277edcf284bSChris Wilson adj = IS_CHERRYVIEW(dev_priv) ? 2 : 1; 12787e79a683SSagar Arun Kamble 1279562d9baeSSagar Arun Kamble if (new_delay >= rps->max_freq_softlimit) 12807e79a683SSagar Arun Kamble adj = 0; 12817b92c1bdSChris Wilson } else if (client_boost) { 1282f5a4c67dSChris Wilson adj = 0; 1283dd75fdc8SChris Wilson } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) { 1284562d9baeSSagar Arun Kamble if (rps->cur_freq > rps->efficient_freq) 1285562d9baeSSagar Arun Kamble new_delay = rps->efficient_freq; 1286562d9baeSSagar Arun Kamble else if (rps->cur_freq > rps->min_freq_softlimit) 1287562d9baeSSagar Arun Kamble new_delay = rps->min_freq_softlimit; 1288dd75fdc8SChris Wilson adj = 0; 1289dd75fdc8SChris Wilson } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { 1290dd75fdc8SChris Wilson if (adj < 0) 1291dd75fdc8SChris Wilson adj *= 2; 1292edcf284bSChris Wilson else /* CHV needs even encode values */ 1293edcf284bSChris Wilson adj = IS_CHERRYVIEW(dev_priv) ? -2 : -1; 12947e79a683SSagar Arun Kamble 1295562d9baeSSagar Arun Kamble if (new_delay <= rps->min_freq_softlimit) 12967e79a683SSagar Arun Kamble adj = 0; 1297dd75fdc8SChris Wilson } else { /* unknown event */ 1298edcf284bSChris Wilson adj = 0; 1299dd75fdc8SChris Wilson } 13003b8d8d91SJesse Barnes 1301562d9baeSSagar Arun Kamble rps->last_adj = adj; 1302edcf284bSChris Wilson 13032a8862d2SChris Wilson /* 13042a8862d2SChris Wilson * Limit deboosting and boosting to keep ourselves at the extremes 13052a8862d2SChris Wilson * when in the respective power modes (i.e. slowly decrease frequencies 13062a8862d2SChris Wilson * while in the HIGH_POWER zone and slowly increase frequencies while 13072a8862d2SChris Wilson * in the LOW_POWER zone). On idle, we will hit the timeout and drop 13082a8862d2SChris Wilson * to the next level quickly, and conversely if busy we expect to 13092a8862d2SChris Wilson * hit a waitboost and rapidly switch into max power. 13102a8862d2SChris Wilson */ 13112a8862d2SChris Wilson if ((adj < 0 && rps->power.mode == HIGH_POWER) || 13122a8862d2SChris Wilson (adj > 0 && rps->power.mode == LOW_POWER)) 13132a8862d2SChris Wilson rps->last_adj = 0; 13142a8862d2SChris Wilson 131579249636SBen Widawsky /* sysfs frequency interfaces may have snuck in while servicing the 131679249636SBen Widawsky * interrupt 131779249636SBen Widawsky */ 1318edcf284bSChris Wilson new_delay += adj; 13198d3afd7dSChris Wilson new_delay = clamp_t(int, new_delay, min, max); 132027544369SDeepak S 13219fcee2f7SChris Wilson if (intel_set_rps(dev_priv, new_delay)) { 13229fcee2f7SChris Wilson DRM_DEBUG_DRIVER("Failed to set new GPU frequency\n"); 1323562d9baeSSagar Arun Kamble rps->last_adj = 0; 13249fcee2f7SChris Wilson } 13253b8d8d91SJesse Barnes 13269f817501SSagar Arun Kamble mutex_unlock(&dev_priv->pcu_lock); 13277c0a16adSChris Wilson 13287c0a16adSChris Wilson out: 13297c0a16adSChris Wilson /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */ 13307c0a16adSChris Wilson spin_lock_irq(&dev_priv->irq_lock); 1331562d9baeSSagar Arun Kamble if (rps->interrupts_enabled) 13327c0a16adSChris Wilson gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events); 13337c0a16adSChris Wilson spin_unlock_irq(&dev_priv->irq_lock); 13343b8d8d91SJesse Barnes } 13353b8d8d91SJesse Barnes 1336e3689190SBen Widawsky 1337e3689190SBen Widawsky /** 1338e3689190SBen Widawsky * ivybridge_parity_work - Workqueue called when a parity error interrupt 1339e3689190SBen Widawsky * occurred. 1340e3689190SBen Widawsky * @work: workqueue struct 1341e3689190SBen Widawsky * 1342e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 1343e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 1344e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 1345e3689190SBen Widawsky */ 1346e3689190SBen Widawsky static void ivybridge_parity_work(struct work_struct *work) 1347e3689190SBen Widawsky { 13482d1013ddSJani Nikula struct drm_i915_private *dev_priv = 1349cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 1350e3689190SBen Widawsky u32 error_status, row, bank, subbank; 135135a85ac6SBen Widawsky char *parity_event[6]; 1352a9c287c9SJani Nikula u32 misccpctl; 1353a9c287c9SJani Nikula u8 slice = 0; 1354e3689190SBen Widawsky 1355e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 1356e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 1357e3689190SBen Widawsky * any time we access those registers. 1358e3689190SBen Widawsky */ 135991c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 1360e3689190SBen Widawsky 136135a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 136235a85ac6SBen Widawsky if (WARN_ON(!dev_priv->l3_parity.which_slice)) 136335a85ac6SBen Widawsky goto out; 136435a85ac6SBen Widawsky 1365e3689190SBen Widawsky misccpctl = I915_READ(GEN7_MISCCPCTL); 1366e3689190SBen Widawsky I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); 1367e3689190SBen Widawsky POSTING_READ(GEN7_MISCCPCTL); 1368e3689190SBen Widawsky 136935a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 1370f0f59a00SVille Syrjälä i915_reg_t reg; 137135a85ac6SBen Widawsky 137235a85ac6SBen Widawsky slice--; 13732d1fe073SJoonas Lahtinen if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv))) 137435a85ac6SBen Widawsky break; 137535a85ac6SBen Widawsky 137635a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 137735a85ac6SBen Widawsky 13786fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 137935a85ac6SBen Widawsky 138035a85ac6SBen Widawsky error_status = I915_READ(reg); 1381e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 1382e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 1383e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 1384e3689190SBen Widawsky 138535a85ac6SBen Widawsky I915_WRITE(reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 138635a85ac6SBen Widawsky POSTING_READ(reg); 1387e3689190SBen Widawsky 1388cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 1389e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 1390e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 1391e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 139235a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 139335a85ac6SBen Widawsky parity_event[5] = NULL; 1394e3689190SBen Widawsky 139591c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 1396e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 1397e3689190SBen Widawsky 139835a85ac6SBen Widawsky DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 139935a85ac6SBen Widawsky slice, row, bank, subbank); 1400e3689190SBen Widawsky 140135a85ac6SBen Widawsky kfree(parity_event[4]); 1402e3689190SBen Widawsky kfree(parity_event[3]); 1403e3689190SBen Widawsky kfree(parity_event[2]); 1404e3689190SBen Widawsky kfree(parity_event[1]); 1405e3689190SBen Widawsky } 1406e3689190SBen Widawsky 140735a85ac6SBen Widawsky I915_WRITE(GEN7_MISCCPCTL, misccpctl); 140835a85ac6SBen Widawsky 140935a85ac6SBen Widawsky out: 141035a85ac6SBen Widawsky WARN_ON(dev_priv->l3_parity.which_slice); 14114cb21832SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 14122d1fe073SJoonas Lahtinen gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv)); 14134cb21832SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 141435a85ac6SBen Widawsky 141591c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 141635a85ac6SBen Widawsky } 141735a85ac6SBen Widawsky 1418261e40b8SVille Syrjälä static void ivybridge_parity_error_irq_handler(struct drm_i915_private *dev_priv, 1419261e40b8SVille Syrjälä u32 iir) 1420e3689190SBen Widawsky { 1421261e40b8SVille Syrjälä if (!HAS_L3_DPF(dev_priv)) 1422e3689190SBen Widawsky return; 1423e3689190SBen Widawsky 1424d0ecd7e2SDaniel Vetter spin_lock(&dev_priv->irq_lock); 1425261e40b8SVille Syrjälä gen5_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv)); 1426d0ecd7e2SDaniel Vetter spin_unlock(&dev_priv->irq_lock); 1427e3689190SBen Widawsky 1428261e40b8SVille Syrjälä iir &= GT_PARITY_ERROR(dev_priv); 142935a85ac6SBen Widawsky if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1) 143035a85ac6SBen Widawsky dev_priv->l3_parity.which_slice |= 1 << 1; 143135a85ac6SBen Widawsky 143235a85ac6SBen Widawsky if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) 143335a85ac6SBen Widawsky dev_priv->l3_parity.which_slice |= 1 << 0; 143435a85ac6SBen Widawsky 1435a4da4fa4SDaniel Vetter queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work); 1436e3689190SBen Widawsky } 1437e3689190SBen Widawsky 1438261e40b8SVille Syrjälä static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv, 1439f1af8fc1SPaulo Zanoni u32 gt_iir) 1440f1af8fc1SPaulo Zanoni { 1441f8973c21SChris Wilson if (gt_iir & GT_RENDER_USER_INTERRUPT) 14428a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 1443f1af8fc1SPaulo Zanoni if (gt_iir & ILK_BSD_USER_INTERRUPT) 14448a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); 1445f1af8fc1SPaulo Zanoni } 1446f1af8fc1SPaulo Zanoni 1447261e40b8SVille Syrjälä static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, 1448e7b4c6b1SDaniel Vetter u32 gt_iir) 1449e7b4c6b1SDaniel Vetter { 1450f8973c21SChris Wilson if (gt_iir & GT_RENDER_USER_INTERRUPT) 14518a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 1452cc609d5dSBen Widawsky if (gt_iir & GT_BSD_USER_INTERRUPT) 14538a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); 1454cc609d5dSBen Widawsky if (gt_iir & GT_BLT_USER_INTERRUPT) 14558a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[BCS0]); 1456e7b4c6b1SDaniel Vetter 1457cc609d5dSBen Widawsky if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | 1458cc609d5dSBen Widawsky GT_BSD_CS_ERROR_INTERRUPT | 1459aaecdf61SDaniel Vetter GT_RENDER_CS_MASTER_ERROR_INTERRUPT)) 1460aaecdf61SDaniel Vetter DRM_DEBUG("Command parser error, gt_iir 0x%08x\n", gt_iir); 1461e3689190SBen Widawsky 1462261e40b8SVille Syrjälä if (gt_iir & GT_PARITY_ERROR(dev_priv)) 1463261e40b8SVille Syrjälä ivybridge_parity_error_irq_handler(dev_priv, gt_iir); 1464e7b4c6b1SDaniel Vetter } 1465e7b4c6b1SDaniel Vetter 14665d3d69d5SChris Wilson static void 146751f6b0f9SChris Wilson gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir) 1468fbcc1a0cSNick Hoath { 146931de7350SChris Wilson bool tasklet = false; 1470f747026cSChris Wilson 1471fd8526e5SChris Wilson if (iir & GT_CONTEXT_SWITCH_INTERRUPT) 14728ea397faSChris Wilson tasklet = true; 147331de7350SChris Wilson 147451f6b0f9SChris Wilson if (iir & GT_RENDER_USER_INTERRUPT) { 147552c0fdb2SChris Wilson intel_engine_breadcrumbs_irq(engine); 14764c6ce5c9SChris Wilson tasklet |= intel_engine_needs_breadcrumb_tasklet(engine); 147731de7350SChris Wilson } 147831de7350SChris Wilson 147931de7350SChris Wilson if (tasklet) 1480fd8526e5SChris Wilson tasklet_hi_schedule(&engine->execlists.tasklet); 1481fbcc1a0cSNick Hoath } 1482fbcc1a0cSNick Hoath 14832e4a5b25SChris Wilson static void gen8_gt_irq_ack(struct drm_i915_private *i915, 148455ef72f2SChris Wilson u32 master_ctl, u32 gt_iir[4]) 1485abd58f01SBen Widawsky { 148625286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 14872e4a5b25SChris Wilson 1488f0fd96f5SChris Wilson #define GEN8_GT_IRQS (GEN8_GT_RCS_IRQ | \ 1489f0fd96f5SChris Wilson GEN8_GT_BCS_IRQ | \ 14908a68d464SChris Wilson GEN8_GT_VCS0_IRQ | \ 1491f0fd96f5SChris Wilson GEN8_GT_VCS1_IRQ | \ 1492f0fd96f5SChris Wilson GEN8_GT_VECS_IRQ | \ 1493f0fd96f5SChris Wilson GEN8_GT_PM_IRQ | \ 1494f0fd96f5SChris Wilson GEN8_GT_GUC_IRQ) 1495f0fd96f5SChris Wilson 1496abd58f01SBen Widawsky if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { 14972e4a5b25SChris Wilson gt_iir[0] = raw_reg_read(regs, GEN8_GT_IIR(0)); 14982e4a5b25SChris Wilson if (likely(gt_iir[0])) 14992e4a5b25SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(0), gt_iir[0]); 1500abd58f01SBen Widawsky } 1501abd58f01SBen Widawsky 15028a68d464SChris Wilson if (master_ctl & (GEN8_GT_VCS0_IRQ | GEN8_GT_VCS1_IRQ)) { 15032e4a5b25SChris Wilson gt_iir[1] = raw_reg_read(regs, GEN8_GT_IIR(1)); 15042e4a5b25SChris Wilson if (likely(gt_iir[1])) 15052e4a5b25SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(1), gt_iir[1]); 150674cdb337SChris Wilson } 150774cdb337SChris Wilson 150826705e20SSagar Arun Kamble if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { 15092e4a5b25SChris Wilson gt_iir[2] = raw_reg_read(regs, GEN8_GT_IIR(2)); 1510f4de7794SChris Wilson if (likely(gt_iir[2])) 1511f4de7794SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(2), gt_iir[2]); 15120961021aSBen Widawsky } 15132e4a5b25SChris Wilson 15142e4a5b25SChris Wilson if (master_ctl & GEN8_GT_VECS_IRQ) { 15152e4a5b25SChris Wilson gt_iir[3] = raw_reg_read(regs, GEN8_GT_IIR(3)); 15162e4a5b25SChris Wilson if (likely(gt_iir[3])) 15172e4a5b25SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(3), gt_iir[3]); 151855ef72f2SChris Wilson } 1519abd58f01SBen Widawsky } 1520abd58f01SBen Widawsky 15212e4a5b25SChris Wilson static void gen8_gt_irq_handler(struct drm_i915_private *i915, 1522f0fd96f5SChris Wilson u32 master_ctl, u32 gt_iir[4]) 1523e30e251aSVille Syrjälä { 1524f0fd96f5SChris Wilson if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { 15258a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[RCS0], 152651f6b0f9SChris Wilson gt_iir[0] >> GEN8_RCS_IRQ_SHIFT); 15278a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[BCS0], 152851f6b0f9SChris Wilson gt_iir[0] >> GEN8_BCS_IRQ_SHIFT); 1529e30e251aSVille Syrjälä } 1530e30e251aSVille Syrjälä 15318a68d464SChris Wilson if (master_ctl & (GEN8_GT_VCS0_IRQ | GEN8_GT_VCS1_IRQ)) { 15328a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[VCS0], 15338a68d464SChris Wilson gt_iir[1] >> GEN8_VCS0_IRQ_SHIFT); 15348a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[VCS1], 153551f6b0f9SChris Wilson gt_iir[1] >> GEN8_VCS1_IRQ_SHIFT); 1536e30e251aSVille Syrjälä } 1537e30e251aSVille Syrjälä 1538f0fd96f5SChris Wilson if (master_ctl & GEN8_GT_VECS_IRQ) { 15398a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[VECS0], 154051f6b0f9SChris Wilson gt_iir[3] >> GEN8_VECS_IRQ_SHIFT); 1541f0fd96f5SChris Wilson } 1542e30e251aSVille Syrjälä 1543f0fd96f5SChris Wilson if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { 15442e4a5b25SChris Wilson gen6_rps_irq_handler(i915, gt_iir[2]); 15452e4a5b25SChris Wilson gen9_guc_irq_handler(i915, gt_iir[2]); 1546e30e251aSVille Syrjälä } 1547f0fd96f5SChris Wilson } 1548e30e251aSVille Syrjälä 1549af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1550121e758eSDhinakaran Pandiyan { 1551af92058fSVille Syrjälä switch (pin) { 1552af92058fSVille Syrjälä case HPD_PORT_C: 1553121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1); 1554af92058fSVille Syrjälä case HPD_PORT_D: 1555121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2); 1556af92058fSVille Syrjälä case HPD_PORT_E: 1557121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3); 1558af92058fSVille Syrjälä case HPD_PORT_F: 1559121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4); 1560121e758eSDhinakaran Pandiyan default: 1561121e758eSDhinakaran Pandiyan return false; 1562121e758eSDhinakaran Pandiyan } 1563121e758eSDhinakaran Pandiyan } 1564121e758eSDhinakaran Pandiyan 1565af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 156663c88d22SImre Deak { 1567af92058fSVille Syrjälä switch (pin) { 1568af92058fSVille Syrjälä case HPD_PORT_A: 1569195baa06SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1570af92058fSVille Syrjälä case HPD_PORT_B: 157163c88d22SImre Deak return val & PORTB_HOTPLUG_LONG_DETECT; 1572af92058fSVille Syrjälä case HPD_PORT_C: 157363c88d22SImre Deak return val & PORTC_HOTPLUG_LONG_DETECT; 157463c88d22SImre Deak default: 157563c88d22SImre Deak return false; 157663c88d22SImre Deak } 157763c88d22SImre Deak } 157863c88d22SImre Deak 1579af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 158031604222SAnusha Srivatsa { 1581af92058fSVille Syrjälä switch (pin) { 1582af92058fSVille Syrjälä case HPD_PORT_A: 158331604222SAnusha Srivatsa return val & ICP_DDIA_HPD_LONG_DETECT; 1584af92058fSVille Syrjälä case HPD_PORT_B: 158531604222SAnusha Srivatsa return val & ICP_DDIB_HPD_LONG_DETECT; 158631604222SAnusha Srivatsa default: 158731604222SAnusha Srivatsa return false; 158831604222SAnusha Srivatsa } 158931604222SAnusha Srivatsa } 159031604222SAnusha Srivatsa 1591af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 159231604222SAnusha Srivatsa { 1593af92058fSVille Syrjälä switch (pin) { 1594af92058fSVille Syrjälä case HPD_PORT_C: 159531604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC1); 1596af92058fSVille Syrjälä case HPD_PORT_D: 159731604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC2); 1598af92058fSVille Syrjälä case HPD_PORT_E: 159931604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC3); 1600af92058fSVille Syrjälä case HPD_PORT_F: 160131604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC4); 160231604222SAnusha Srivatsa default: 160331604222SAnusha Srivatsa return false; 160431604222SAnusha Srivatsa } 160531604222SAnusha Srivatsa } 160631604222SAnusha Srivatsa 1607af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) 16086dbf30ceSVille Syrjälä { 1609af92058fSVille Syrjälä switch (pin) { 1610af92058fSVille Syrjälä case HPD_PORT_E: 16116dbf30ceSVille Syrjälä return val & PORTE_HOTPLUG_LONG_DETECT; 16126dbf30ceSVille Syrjälä default: 16136dbf30ceSVille Syrjälä return false; 16146dbf30ceSVille Syrjälä } 16156dbf30ceSVille Syrjälä } 16166dbf30ceSVille Syrjälä 1617af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 161874c0b395SVille Syrjälä { 1619af92058fSVille Syrjälä switch (pin) { 1620af92058fSVille Syrjälä case HPD_PORT_A: 162174c0b395SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1622af92058fSVille Syrjälä case HPD_PORT_B: 162374c0b395SVille Syrjälä return val & PORTB_HOTPLUG_LONG_DETECT; 1624af92058fSVille Syrjälä case HPD_PORT_C: 162574c0b395SVille Syrjälä return val & PORTC_HOTPLUG_LONG_DETECT; 1626af92058fSVille Syrjälä case HPD_PORT_D: 162774c0b395SVille Syrjälä return val & PORTD_HOTPLUG_LONG_DETECT; 162874c0b395SVille Syrjälä default: 162974c0b395SVille Syrjälä return false; 163074c0b395SVille Syrjälä } 163174c0b395SVille Syrjälä } 163274c0b395SVille Syrjälä 1633af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1634e4ce95aaSVille Syrjälä { 1635af92058fSVille Syrjälä switch (pin) { 1636af92058fSVille Syrjälä case HPD_PORT_A: 1637e4ce95aaSVille Syrjälä return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; 1638e4ce95aaSVille Syrjälä default: 1639e4ce95aaSVille Syrjälä return false; 1640e4ce95aaSVille Syrjälä } 1641e4ce95aaSVille Syrjälä } 1642e4ce95aaSVille Syrjälä 1643af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 164413cf5504SDave Airlie { 1645af92058fSVille Syrjälä switch (pin) { 1646af92058fSVille Syrjälä case HPD_PORT_B: 1647676574dfSJani Nikula return val & PORTB_HOTPLUG_LONG_DETECT; 1648af92058fSVille Syrjälä case HPD_PORT_C: 1649676574dfSJani Nikula return val & PORTC_HOTPLUG_LONG_DETECT; 1650af92058fSVille Syrjälä case HPD_PORT_D: 1651676574dfSJani Nikula return val & PORTD_HOTPLUG_LONG_DETECT; 1652676574dfSJani Nikula default: 1653676574dfSJani Nikula return false; 165413cf5504SDave Airlie } 165513cf5504SDave Airlie } 165613cf5504SDave Airlie 1657af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 165813cf5504SDave Airlie { 1659af92058fSVille Syrjälä switch (pin) { 1660af92058fSVille Syrjälä case HPD_PORT_B: 1661676574dfSJani Nikula return val & PORTB_HOTPLUG_INT_LONG_PULSE; 1662af92058fSVille Syrjälä case HPD_PORT_C: 1663676574dfSJani Nikula return val & PORTC_HOTPLUG_INT_LONG_PULSE; 1664af92058fSVille Syrjälä case HPD_PORT_D: 1665676574dfSJani Nikula return val & PORTD_HOTPLUG_INT_LONG_PULSE; 1666676574dfSJani Nikula default: 1667676574dfSJani Nikula return false; 166813cf5504SDave Airlie } 166913cf5504SDave Airlie } 167013cf5504SDave Airlie 167142db67d6SVille Syrjälä /* 167242db67d6SVille Syrjälä * Get a bit mask of pins that have triggered, and which ones may be long. 167342db67d6SVille Syrjälä * This can be called multiple times with the same masks to accumulate 167442db67d6SVille Syrjälä * hotplug detection results from several registers. 167542db67d6SVille Syrjälä * 167642db67d6SVille Syrjälä * Note that the caller is expected to zero out the masks initially. 167742db67d6SVille Syrjälä */ 1678cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, 1679cf53902fSRodrigo Vivi u32 *pin_mask, u32 *long_mask, 16808c841e57SJani Nikula u32 hotplug_trigger, u32 dig_hotplug_reg, 1681fd63e2a9SImre Deak const u32 hpd[HPD_NUM_PINS], 1682af92058fSVille Syrjälä bool long_pulse_detect(enum hpd_pin pin, u32 val)) 1683676574dfSJani Nikula { 1684e9be2850SVille Syrjälä enum hpd_pin pin; 1685676574dfSJani Nikula 1686e9be2850SVille Syrjälä for_each_hpd_pin(pin) { 1687e9be2850SVille Syrjälä if ((hpd[pin] & hotplug_trigger) == 0) 16888c841e57SJani Nikula continue; 16898c841e57SJani Nikula 1690e9be2850SVille Syrjälä *pin_mask |= BIT(pin); 1691676574dfSJani Nikula 1692af92058fSVille Syrjälä if (long_pulse_detect(pin, dig_hotplug_reg)) 1693e9be2850SVille Syrjälä *long_mask |= BIT(pin); 1694676574dfSJani Nikula } 1695676574dfSJani Nikula 1696f88f0478SVille Syrjälä DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n", 1697f88f0478SVille Syrjälä hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); 1698676574dfSJani Nikula 1699676574dfSJani Nikula } 1700676574dfSJani Nikula 170191d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv) 1702515ac2bbSDaniel Vetter { 170328c70f16SDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1704515ac2bbSDaniel Vetter } 1705515ac2bbSDaniel Vetter 170691d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) 1707ce99c256SDaniel Vetter { 17089ee32feaSDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1709ce99c256SDaniel Vetter } 1710ce99c256SDaniel Vetter 17118bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 171291d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 171391d14251STvrtko Ursulin enum pipe pipe, 1714a9c287c9SJani Nikula u32 crc0, u32 crc1, 1715a9c287c9SJani Nikula u32 crc2, u32 crc3, 1716a9c287c9SJani Nikula u32 crc4) 17178bf1e9f1SShuang He { 17188bf1e9f1SShuang He struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; 17198c6b709dSTomeu Vizoso struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); 17205cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 17215cee6c45SVille Syrjälä 17225cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 1723b2c88f5bSDamien Lespiau 1724d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 17258c6b709dSTomeu Vizoso /* 17268c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 17278c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 17288c6b709dSTomeu Vizoso * out the buggy result. 17298c6b709dSTomeu Vizoso * 1730163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 17318c6b709dSTomeu Vizoso * don't trust that one either. 17328c6b709dSTomeu Vizoso */ 1733033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 1734163e8aecSRodrigo Vivi (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 17358c6b709dSTomeu Vizoso pipe_crc->skipped++; 17368c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 17378c6b709dSTomeu Vizoso return; 17388c6b709dSTomeu Vizoso } 17398c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 17406cc42152SMaarten Lankhorst 1741246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 1742ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 1743246ee524STomeu Vizoso crcs); 17448c6b709dSTomeu Vizoso } 1745277de95eSDaniel Vetter #else 1746277de95eSDaniel Vetter static inline void 174791d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 174891d14251STvrtko Ursulin enum pipe pipe, 1749a9c287c9SJani Nikula u32 crc0, u32 crc1, 1750a9c287c9SJani Nikula u32 crc2, u32 crc3, 1751a9c287c9SJani Nikula u32 crc4) {} 1752277de95eSDaniel Vetter #endif 1753eba94eb9SDaniel Vetter 1754277de95eSDaniel Vetter 175591d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 175691d14251STvrtko Ursulin enum pipe pipe) 17575a69b89fSDaniel Vetter { 175891d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 17595a69b89fSDaniel Vetter I915_READ(PIPE_CRC_RES_1_IVB(pipe)), 17605a69b89fSDaniel Vetter 0, 0, 0, 0); 17615a69b89fSDaniel Vetter } 17625a69b89fSDaniel Vetter 176391d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 176491d14251STvrtko Ursulin enum pipe pipe) 1765eba94eb9SDaniel Vetter { 176691d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 1767eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_1_IVB(pipe)), 1768eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_2_IVB(pipe)), 1769eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_3_IVB(pipe)), 1770eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_4_IVB(pipe)), 17718bc5e955SDaniel Vetter I915_READ(PIPE_CRC_RES_5_IVB(pipe))); 1772eba94eb9SDaniel Vetter } 17735b3a856bSDaniel Vetter 177491d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 177591d14251STvrtko Ursulin enum pipe pipe) 17765b3a856bSDaniel Vetter { 1777a9c287c9SJani Nikula u32 res1, res2; 17780b5c5ed0SDaniel Vetter 177991d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 3) 17800b5c5ed0SDaniel Vetter res1 = I915_READ(PIPE_CRC_RES_RES1_I915(pipe)); 17810b5c5ed0SDaniel Vetter else 17820b5c5ed0SDaniel Vetter res1 = 0; 17830b5c5ed0SDaniel Vetter 178491d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) 17850b5c5ed0SDaniel Vetter res2 = I915_READ(PIPE_CRC_RES_RES2_G4X(pipe)); 17860b5c5ed0SDaniel Vetter else 17870b5c5ed0SDaniel Vetter res2 = 0; 17885b3a856bSDaniel Vetter 178991d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 17900b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_RED(pipe)), 17910b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_GREEN(pipe)), 17920b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_BLUE(pipe)), 17930b5c5ed0SDaniel Vetter res1, res2); 17945b3a856bSDaniel Vetter } 17958bf1e9f1SShuang He 17961403c0d4SPaulo Zanoni /* The RPS events need forcewake, so we add them to a work queue and mask their 17971403c0d4SPaulo Zanoni * IMR bits until the work is done. Other interrupts can be processed without 17981403c0d4SPaulo Zanoni * the work queue. */ 1799*a087bafeSMika Kuoppala static void gen11_rps_irq_handler(struct drm_i915_private *i915, u32 pm_iir) 1800*a087bafeSMika Kuoppala { 1801*a087bafeSMika Kuoppala struct intel_rps *rps = &i915->gt_pm.rps; 1802*a087bafeSMika Kuoppala const u32 events = i915->pm_rps_events & pm_iir; 1803*a087bafeSMika Kuoppala 1804*a087bafeSMika Kuoppala lockdep_assert_held(&i915->irq_lock); 1805*a087bafeSMika Kuoppala 1806*a087bafeSMika Kuoppala if (unlikely(!events)) 1807*a087bafeSMika Kuoppala return; 1808*a087bafeSMika Kuoppala 1809*a087bafeSMika Kuoppala gen6_mask_pm_irq(i915, events); 1810*a087bafeSMika Kuoppala 1811*a087bafeSMika Kuoppala if (!rps->interrupts_enabled) 1812*a087bafeSMika Kuoppala return; 1813*a087bafeSMika Kuoppala 1814*a087bafeSMika Kuoppala rps->pm_iir |= events; 1815*a087bafeSMika Kuoppala schedule_work(&rps->work); 1816*a087bafeSMika Kuoppala } 1817*a087bafeSMika Kuoppala 18181403c0d4SPaulo Zanoni static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) 1819baf02a1fSBen Widawsky { 1820562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 1821562d9baeSSagar Arun Kamble 1822a6706b45SDeepak S if (pm_iir & dev_priv->pm_rps_events) { 182359cdb63dSDaniel Vetter spin_lock(&dev_priv->irq_lock); 1824f4e9af4fSAkash Goel gen6_mask_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); 1825562d9baeSSagar Arun Kamble if (rps->interrupts_enabled) { 1826562d9baeSSagar Arun Kamble rps->pm_iir |= pm_iir & dev_priv->pm_rps_events; 1827562d9baeSSagar Arun Kamble schedule_work(&rps->work); 182841a05a3aSDaniel Vetter } 1829d4d70aa5SImre Deak spin_unlock(&dev_priv->irq_lock); 1830d4d70aa5SImre Deak } 1831baf02a1fSBen Widawsky 1832bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 8) 1833c9a9a268SImre Deak return; 1834c9a9a268SImre Deak 183512638c57SBen Widawsky if (pm_iir & PM_VEBOX_USER_INTERRUPT) 18368a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VECS0]); 183712638c57SBen Widawsky 1838aaecdf61SDaniel Vetter if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) 1839aaecdf61SDaniel Vetter DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); 184012638c57SBen Widawsky } 1841baf02a1fSBen Widawsky 184226705e20SSagar Arun Kamble static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) 184326705e20SSagar Arun Kamble { 184493bf8096SMichal Wajdeczko if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) 184593bf8096SMichal Wajdeczko intel_guc_to_host_event_handler(&dev_priv->guc); 184626705e20SSagar Arun Kamble } 184726705e20SSagar Arun Kamble 184844d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 184944d9241eSVille Syrjälä { 185044d9241eSVille Syrjälä enum pipe pipe; 185144d9241eSVille Syrjälä 185244d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 185344d9241eSVille Syrjälä I915_WRITE(PIPESTAT(pipe), 185444d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 185544d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 185644d9241eSVille Syrjälä 185744d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 185844d9241eSVille Syrjälä } 185944d9241eSVille Syrjälä } 186044d9241eSVille Syrjälä 1861eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 186291d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 18637e231dbeSJesse Barnes { 18647e231dbeSJesse Barnes int pipe; 18657e231dbeSJesse Barnes 186658ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 18671ca993d2SVille Syrjälä 18681ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 18691ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 18701ca993d2SVille Syrjälä return; 18711ca993d2SVille Syrjälä } 18721ca993d2SVille Syrjälä 1873055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1874f0f59a00SVille Syrjälä i915_reg_t reg; 18756b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 187691d181ddSImre Deak 1877bbb5eebfSDaniel Vetter /* 1878bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 1879bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 1880bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 1881bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 1882bbb5eebfSDaniel Vetter * handle. 1883bbb5eebfSDaniel Vetter */ 18840f239f4cSDaniel Vetter 18850f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 18866b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 1887bbb5eebfSDaniel Vetter 1888bbb5eebfSDaniel Vetter switch (pipe) { 1889bbb5eebfSDaniel Vetter case PIPE_A: 1890bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 1891bbb5eebfSDaniel Vetter break; 1892bbb5eebfSDaniel Vetter case PIPE_B: 1893bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1894bbb5eebfSDaniel Vetter break; 18953278f67fSVille Syrjälä case PIPE_C: 18963278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 18973278f67fSVille Syrjälä break; 1898bbb5eebfSDaniel Vetter } 1899bbb5eebfSDaniel Vetter if (iir & iir_bit) 19006b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 1901bbb5eebfSDaniel Vetter 19026b12ca56SVille Syrjälä if (!status_mask) 190391d181ddSImre Deak continue; 190491d181ddSImre Deak 190591d181ddSImre Deak reg = PIPESTAT(pipe); 19066b12ca56SVille Syrjälä pipe_stats[pipe] = I915_READ(reg) & status_mask; 19076b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 19087e231dbeSJesse Barnes 19097e231dbeSJesse Barnes /* 19107e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 1911132c27c9SVille Syrjälä * 1912132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 1913132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 1914132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 1915132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 1916132c27c9SVille Syrjälä * an interrupt is still pending. 19177e231dbeSJesse Barnes */ 1918132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 1919132c27c9SVille Syrjälä I915_WRITE(reg, pipe_stats[pipe]); 1920132c27c9SVille Syrjälä I915_WRITE(reg, enable_mask); 1921132c27c9SVille Syrjälä } 19227e231dbeSJesse Barnes } 192358ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 19242ecb8ca4SVille Syrjälä } 19252ecb8ca4SVille Syrjälä 1926eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1927eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 1928eb64343cSVille Syrjälä { 1929eb64343cSVille Syrjälä enum pipe pipe; 1930eb64343cSVille Syrjälä 1931eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1932eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1933eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1934eb64343cSVille Syrjälä 1935eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1936eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1937eb64343cSVille Syrjälä 1938eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1939eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1940eb64343cSVille Syrjälä } 1941eb64343cSVille Syrjälä } 1942eb64343cSVille Syrjälä 1943eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1944eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1945eb64343cSVille Syrjälä { 1946eb64343cSVille Syrjälä bool blc_event = false; 1947eb64343cSVille Syrjälä enum pipe pipe; 1948eb64343cSVille Syrjälä 1949eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1950eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1951eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1952eb64343cSVille Syrjälä 1953eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1954eb64343cSVille Syrjälä blc_event = true; 1955eb64343cSVille Syrjälä 1956eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1957eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1958eb64343cSVille Syrjälä 1959eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1960eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1961eb64343cSVille Syrjälä } 1962eb64343cSVille Syrjälä 1963eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1964eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1965eb64343cSVille Syrjälä } 1966eb64343cSVille Syrjälä 1967eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1968eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1969eb64343cSVille Syrjälä { 1970eb64343cSVille Syrjälä bool blc_event = false; 1971eb64343cSVille Syrjälä enum pipe pipe; 1972eb64343cSVille Syrjälä 1973eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1974eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1975eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1976eb64343cSVille Syrjälä 1977eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1978eb64343cSVille Syrjälä blc_event = true; 1979eb64343cSVille Syrjälä 1980eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1981eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1982eb64343cSVille Syrjälä 1983eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1984eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1985eb64343cSVille Syrjälä } 1986eb64343cSVille Syrjälä 1987eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1988eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1989eb64343cSVille Syrjälä 1990eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 1991eb64343cSVille Syrjälä gmbus_irq_handler(dev_priv); 1992eb64343cSVille Syrjälä } 1993eb64343cSVille Syrjälä 199491d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 19952ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 19962ecb8ca4SVille Syrjälä { 19972ecb8ca4SVille Syrjälä enum pipe pipe; 19987e231dbeSJesse Barnes 1999055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2000fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 2001fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 20024356d586SDaniel Vetter 20034356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 200491d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 20052d9d2b0bSVille Syrjälä 20061f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 20071f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 200831acc7f5SJesse Barnes } 200931acc7f5SJesse Barnes 2010c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 201191d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 2012c1874ed7SImre Deak } 2013c1874ed7SImre Deak 20141ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 201516c6c56bSVille Syrjälä { 20160ba7c51aSVille Syrjälä u32 hotplug_status = 0, hotplug_status_mask; 20170ba7c51aSVille Syrjälä int i; 201816c6c56bSVille Syrjälä 20190ba7c51aSVille Syrjälä if (IS_G4X(dev_priv) || 20200ba7c51aSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 20210ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | 20220ba7c51aSVille Syrjälä DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; 20230ba7c51aSVille Syrjälä else 20240ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_I915; 20250ba7c51aSVille Syrjälä 20260ba7c51aSVille Syrjälä /* 20270ba7c51aSVille Syrjälä * We absolutely have to clear all the pending interrupt 20280ba7c51aSVille Syrjälä * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port 20290ba7c51aSVille Syrjälä * interrupt bit won't have an edge, and the i965/g4x 20300ba7c51aSVille Syrjälä * edge triggered IIR will not notice that an interrupt 20310ba7c51aSVille Syrjälä * is still pending. We can't use PORT_HOTPLUG_EN to 20320ba7c51aSVille Syrjälä * guarantee the edge as the act of toggling the enable 20330ba7c51aSVille Syrjälä * bits can itself generate a new hotplug interrupt :( 20340ba7c51aSVille Syrjälä */ 20350ba7c51aSVille Syrjälä for (i = 0; i < 10; i++) { 20360ba7c51aSVille Syrjälä u32 tmp = I915_READ(PORT_HOTPLUG_STAT) & hotplug_status_mask; 20370ba7c51aSVille Syrjälä 20380ba7c51aSVille Syrjälä if (tmp == 0) 20390ba7c51aSVille Syrjälä return hotplug_status; 20400ba7c51aSVille Syrjälä 20410ba7c51aSVille Syrjälä hotplug_status |= tmp; 20423ff60f89SOscar Mateo I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); 20430ba7c51aSVille Syrjälä } 20440ba7c51aSVille Syrjälä 20450ba7c51aSVille Syrjälä WARN_ONCE(1, 20460ba7c51aSVille Syrjälä "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", 20470ba7c51aSVille Syrjälä I915_READ(PORT_HOTPLUG_STAT)); 20481ae3c34cSVille Syrjälä 20491ae3c34cSVille Syrjälä return hotplug_status; 20501ae3c34cSVille Syrjälä } 20511ae3c34cSVille Syrjälä 205291d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, 20531ae3c34cSVille Syrjälä u32 hotplug_status) 20541ae3c34cSVille Syrjälä { 20551ae3c34cSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 20563ff60f89SOscar Mateo 205791d14251STvrtko Ursulin if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || 205891d14251STvrtko Ursulin IS_CHERRYVIEW(dev_priv)) { 205916c6c56bSVille Syrjälä u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; 206016c6c56bSVille Syrjälä 206158f2cf24SVille Syrjälä if (hotplug_trigger) { 2062cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2063cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 2064cf53902fSRodrigo Vivi hpd_status_g4x, 2065fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 206658f2cf24SVille Syrjälä 206791d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 206858f2cf24SVille Syrjälä } 2069369712e8SJani Nikula 2070369712e8SJani Nikula if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) 207191d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 207216c6c56bSVille Syrjälä } else { 207316c6c56bSVille Syrjälä u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; 207416c6c56bSVille Syrjälä 207558f2cf24SVille Syrjälä if (hotplug_trigger) { 2076cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2077cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 2078cf53902fSRodrigo Vivi hpd_status_i915, 2079fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 208091d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 208116c6c56bSVille Syrjälä } 20823ff60f89SOscar Mateo } 208358f2cf24SVille Syrjälä } 208416c6c56bSVille Syrjälä 2085c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 2086c1874ed7SImre Deak { 208745a83f84SDaniel Vetter struct drm_device *dev = arg; 2088fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 2089c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 2090c1874ed7SImre Deak 20912dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 20922dd2a883SImre Deak return IRQ_NONE; 20932dd2a883SImre Deak 20941f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 20951f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 20961f814dacSImre Deak 20971e1cace9SVille Syrjälä do { 20986e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 20992ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 21001ae3c34cSVille Syrjälä u32 hotplug_status = 0; 2101a5e485a9SVille Syrjälä u32 ier = 0; 21023ff60f89SOscar Mateo 2103c1874ed7SImre Deak gt_iir = I915_READ(GTIIR); 2104c1874ed7SImre Deak pm_iir = I915_READ(GEN6_PMIIR); 21053ff60f89SOscar Mateo iir = I915_READ(VLV_IIR); 2106c1874ed7SImre Deak 2107c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 21081e1cace9SVille Syrjälä break; 2109c1874ed7SImre Deak 2110c1874ed7SImre Deak ret = IRQ_HANDLED; 2111c1874ed7SImre Deak 2112a5e485a9SVille Syrjälä /* 2113a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 2114a5e485a9SVille Syrjälä * 2115a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 2116a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 2117a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 2118a5e485a9SVille Syrjälä * 2119a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 2120a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 2121a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 2122a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 2123a5e485a9SVille Syrjälä * bits this time around. 2124a5e485a9SVille Syrjälä */ 21254a0a0202SVille Syrjälä I915_WRITE(VLV_MASTER_IER, 0); 2126a5e485a9SVille Syrjälä ier = I915_READ(VLV_IER); 2127a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, 0); 21284a0a0202SVille Syrjälä 21294a0a0202SVille Syrjälä if (gt_iir) 21304a0a0202SVille Syrjälä I915_WRITE(GTIIR, gt_iir); 21314a0a0202SVille Syrjälä if (pm_iir) 21324a0a0202SVille Syrjälä I915_WRITE(GEN6_PMIIR, pm_iir); 21334a0a0202SVille Syrjälä 21347ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 21351ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 21367ce4d1f2SVille Syrjälä 21373ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 21383ff60f89SOscar Mateo * signalled in iir */ 2139eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 21407ce4d1f2SVille Syrjälä 2141eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 2142eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 2143eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 2144eef57324SJerome Anand 21457ce4d1f2SVille Syrjälä /* 21467ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 21477ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 21487ce4d1f2SVille Syrjälä */ 21497ce4d1f2SVille Syrjälä if (iir) 21507ce4d1f2SVille Syrjälä I915_WRITE(VLV_IIR, iir); 21514a0a0202SVille Syrjälä 2152a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, ier); 21534a0a0202SVille Syrjälä I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 21541ae3c34cSVille Syrjälä 215552894874SVille Syrjälä if (gt_iir) 2156261e40b8SVille Syrjälä snb_gt_irq_handler(dev_priv, gt_iir); 215752894874SVille Syrjälä if (pm_iir) 215852894874SVille Syrjälä gen6_rps_irq_handler(dev_priv, pm_iir); 215952894874SVille Syrjälä 21601ae3c34cSVille Syrjälä if (hotplug_status) 216191d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 21622ecb8ca4SVille Syrjälä 216391d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 21641e1cace9SVille Syrjälä } while (0); 21657e231dbeSJesse Barnes 21661f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 21671f814dacSImre Deak 21687e231dbeSJesse Barnes return ret; 21697e231dbeSJesse Barnes } 21707e231dbeSJesse Barnes 217143f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 217243f328d7SVille Syrjälä { 217345a83f84SDaniel Vetter struct drm_device *dev = arg; 2174fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 217543f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 217643f328d7SVille Syrjälä 21772dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 21782dd2a883SImre Deak return IRQ_NONE; 21792dd2a883SImre Deak 21801f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 21811f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 21821f814dacSImre Deak 2183579de73bSChris Wilson do { 21846e814800SVille Syrjälä u32 master_ctl, iir; 21852ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 21861ae3c34cSVille Syrjälä u32 hotplug_status = 0; 2187f0fd96f5SChris Wilson u32 gt_iir[4]; 2188a5e485a9SVille Syrjälä u32 ier = 0; 2189a5e485a9SVille Syrjälä 21908e5fd599SVille Syrjälä master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 21913278f67fSVille Syrjälä iir = I915_READ(VLV_IIR); 21923278f67fSVille Syrjälä 21933278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 21948e5fd599SVille Syrjälä break; 219543f328d7SVille Syrjälä 219627b6c122SOscar Mateo ret = IRQ_HANDLED; 219727b6c122SOscar Mateo 2198a5e485a9SVille Syrjälä /* 2199a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 2200a5e485a9SVille Syrjälä * 2201a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 2202a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 2203a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 2204a5e485a9SVille Syrjälä * 2205a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 2206a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 2207a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 2208a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 2209a5e485a9SVille Syrjälä * bits this time around. 2210a5e485a9SVille Syrjälä */ 221143f328d7SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, 0); 2212a5e485a9SVille Syrjälä ier = I915_READ(VLV_IER); 2213a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, 0); 221443f328d7SVille Syrjälä 2215e30e251aSVille Syrjälä gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); 221627b6c122SOscar Mateo 221727b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 22181ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 221943f328d7SVille Syrjälä 222027b6c122SOscar Mateo /* Call regardless, as some status bits might not be 222127b6c122SOscar Mateo * signalled in iir */ 2222eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 222343f328d7SVille Syrjälä 2224eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 2225eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 2226eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 2227eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 2228eef57324SJerome Anand 22297ce4d1f2SVille Syrjälä /* 22307ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 22317ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 22327ce4d1f2SVille Syrjälä */ 22337ce4d1f2SVille Syrjälä if (iir) 22347ce4d1f2SVille Syrjälä I915_WRITE(VLV_IIR, iir); 22357ce4d1f2SVille Syrjälä 2236a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, ier); 2237e5328c43SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 22381ae3c34cSVille Syrjälä 2239f0fd96f5SChris Wilson gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); 2240e30e251aSVille Syrjälä 22411ae3c34cSVille Syrjälä if (hotplug_status) 224291d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 22432ecb8ca4SVille Syrjälä 224491d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 2245579de73bSChris Wilson } while (0); 22463278f67fSVille Syrjälä 22471f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 22481f814dacSImre Deak 224943f328d7SVille Syrjälä return ret; 225043f328d7SVille Syrjälä } 225143f328d7SVille Syrjälä 225291d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, 225391d14251STvrtko Ursulin u32 hotplug_trigger, 225440e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2255776ad806SJesse Barnes { 225642db67d6SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2257776ad806SJesse Barnes 22586a39d7c9SJani Nikula /* 22596a39d7c9SJani Nikula * Somehow the PCH doesn't seem to really ack the interrupt to the CPU 22606a39d7c9SJani Nikula * unless we touch the hotplug register, even if hotplug_trigger is 22616a39d7c9SJani Nikula * zero. Not acking leads to "The master control interrupt lied (SDE)!" 22626a39d7c9SJani Nikula * errors. 22636a39d7c9SJani Nikula */ 226413cf5504SDave Airlie dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 22656a39d7c9SJani Nikula if (!hotplug_trigger) { 22666a39d7c9SJani Nikula u32 mask = PORTA_HOTPLUG_STATUS_MASK | 22676a39d7c9SJani Nikula PORTD_HOTPLUG_STATUS_MASK | 22686a39d7c9SJani Nikula PORTC_HOTPLUG_STATUS_MASK | 22696a39d7c9SJani Nikula PORTB_HOTPLUG_STATUS_MASK; 22706a39d7c9SJani Nikula dig_hotplug_reg &= ~mask; 22716a39d7c9SJani Nikula } 22726a39d7c9SJani Nikula 227313cf5504SDave Airlie I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 22746a39d7c9SJani Nikula if (!hotplug_trigger) 22756a39d7c9SJani Nikula return; 227613cf5504SDave Airlie 2277cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 227840e56410SVille Syrjälä dig_hotplug_reg, hpd, 2279fd63e2a9SImre Deak pch_port_hotplug_long_detect); 228040e56410SVille Syrjälä 228191d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2282aaf5ec2eSSonika Jindal } 228391d131d2SDaniel Vetter 228491d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 228540e56410SVille Syrjälä { 228640e56410SVille Syrjälä int pipe; 228740e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 228840e56410SVille Syrjälä 228991d14251STvrtko Ursulin ibx_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ibx); 229040e56410SVille Syrjälä 2291cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 2292cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 2293776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 2294cfc33bf7SVille Syrjälä DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", 2295cfc33bf7SVille Syrjälä port_name(port)); 2296cfc33bf7SVille Syrjälä } 2297776ad806SJesse Barnes 2298ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 229991d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2300ce99c256SDaniel Vetter 2301776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 230291d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 2303776ad806SJesse Barnes 2304776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 2305776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n"); 2306776ad806SJesse Barnes 2307776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 2308776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n"); 2309776ad806SJesse Barnes 2310776ad806SJesse Barnes if (pch_iir & SDE_POISON) 2311776ad806SJesse Barnes DRM_ERROR("PCH poison interrupt\n"); 2312776ad806SJesse Barnes 23139db4a9c7SJesse Barnes if (pch_iir & SDE_FDI_MASK) 2314055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 23159db4a9c7SJesse Barnes DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", 23169db4a9c7SJesse Barnes pipe_name(pipe), 23179db4a9c7SJesse Barnes I915_READ(FDI_RX_IIR(pipe))); 2318776ad806SJesse Barnes 2319776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 2320776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n"); 2321776ad806SJesse Barnes 2322776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 2323776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n"); 2324776ad806SJesse Barnes 2325776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 2326a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 23278664281bSPaulo Zanoni 23288664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 2329a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 23308664281bSPaulo Zanoni } 23318664281bSPaulo Zanoni 233291d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 23338664281bSPaulo Zanoni { 23348664281bSPaulo Zanoni u32 err_int = I915_READ(GEN7_ERR_INT); 23355a69b89fSDaniel Vetter enum pipe pipe; 23368664281bSPaulo Zanoni 2337de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 2338de032bf4SPaulo Zanoni DRM_ERROR("Poison interrupt\n"); 2339de032bf4SPaulo Zanoni 2340055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 23411f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 23421f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 23438664281bSPaulo Zanoni 23445a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 234591d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 234691d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 23475a69b89fSDaniel Vetter else 234891d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 23495a69b89fSDaniel Vetter } 23505a69b89fSDaniel Vetter } 23518bf1e9f1SShuang He 23528664281bSPaulo Zanoni I915_WRITE(GEN7_ERR_INT, err_int); 23538664281bSPaulo Zanoni } 23548664281bSPaulo Zanoni 235591d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 23568664281bSPaulo Zanoni { 23578664281bSPaulo Zanoni u32 serr_int = I915_READ(SERR_INT); 235845c1cd87SMika Kahola enum pipe pipe; 23598664281bSPaulo Zanoni 2360de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 2361de032bf4SPaulo Zanoni DRM_ERROR("PCH poison interrupt\n"); 2362de032bf4SPaulo Zanoni 236345c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 236445c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 236545c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 23668664281bSPaulo Zanoni 23678664281bSPaulo Zanoni I915_WRITE(SERR_INT, serr_int); 2368776ad806SJesse Barnes } 2369776ad806SJesse Barnes 237091d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 237123e81d69SAdam Jackson { 237223e81d69SAdam Jackson int pipe; 23736dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 2374aaf5ec2eSSonika Jindal 237591d14251STvrtko Ursulin ibx_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_cpt); 237691d131d2SDaniel Vetter 2377cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 2378cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 237923e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 2380cfc33bf7SVille Syrjälä DRM_DEBUG_DRIVER("PCH audio power change on port %c\n", 2381cfc33bf7SVille Syrjälä port_name(port)); 2382cfc33bf7SVille Syrjälä } 238323e81d69SAdam Jackson 238423e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 238591d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 238623e81d69SAdam Jackson 238723e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 238891d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 238923e81d69SAdam Jackson 239023e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 239123e81d69SAdam Jackson DRM_DEBUG_DRIVER("Audio CP request interrupt\n"); 239223e81d69SAdam Jackson 239323e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 239423e81d69SAdam Jackson DRM_DEBUG_DRIVER("Audio CP change interrupt\n"); 239523e81d69SAdam Jackson 239623e81d69SAdam Jackson if (pch_iir & SDE_FDI_MASK_CPT) 2397055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 239823e81d69SAdam Jackson DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", 239923e81d69SAdam Jackson pipe_name(pipe), 240023e81d69SAdam Jackson I915_READ(FDI_RX_IIR(pipe))); 24018664281bSPaulo Zanoni 24028664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 240391d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 240423e81d69SAdam Jackson } 240523e81d69SAdam Jackson 240631604222SAnusha Srivatsa static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 240731604222SAnusha Srivatsa { 240831604222SAnusha Srivatsa u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; 240931604222SAnusha Srivatsa u32 tc_hotplug_trigger = pch_iir & SDE_TC_MASK_ICP; 241031604222SAnusha Srivatsa u32 pin_mask = 0, long_mask = 0; 241131604222SAnusha Srivatsa 241231604222SAnusha Srivatsa if (ddi_hotplug_trigger) { 241331604222SAnusha Srivatsa u32 dig_hotplug_reg; 241431604222SAnusha Srivatsa 241531604222SAnusha Srivatsa dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_DDI); 241631604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_DDI, dig_hotplug_reg); 241731604222SAnusha Srivatsa 241831604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 241931604222SAnusha Srivatsa ddi_hotplug_trigger, 242031604222SAnusha Srivatsa dig_hotplug_reg, hpd_icp, 242131604222SAnusha Srivatsa icp_ddi_port_hotplug_long_detect); 242231604222SAnusha Srivatsa } 242331604222SAnusha Srivatsa 242431604222SAnusha Srivatsa if (tc_hotplug_trigger) { 242531604222SAnusha Srivatsa u32 dig_hotplug_reg; 242631604222SAnusha Srivatsa 242731604222SAnusha Srivatsa dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_TC); 242831604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_TC, dig_hotplug_reg); 242931604222SAnusha Srivatsa 243031604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 243131604222SAnusha Srivatsa tc_hotplug_trigger, 243231604222SAnusha Srivatsa dig_hotplug_reg, hpd_icp, 243331604222SAnusha Srivatsa icp_tc_port_hotplug_long_detect); 243431604222SAnusha Srivatsa } 243531604222SAnusha Srivatsa 243631604222SAnusha Srivatsa if (pin_mask) 243731604222SAnusha Srivatsa intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 243831604222SAnusha Srivatsa 243931604222SAnusha Srivatsa if (pch_iir & SDE_GMBUS_ICP) 244031604222SAnusha Srivatsa gmbus_irq_handler(dev_priv); 244131604222SAnusha Srivatsa } 244231604222SAnusha Srivatsa 244391d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 24446dbf30ceSVille Syrjälä { 24456dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & 24466dbf30ceSVille Syrjälä ~SDE_PORTE_HOTPLUG_SPT; 24476dbf30ceSVille Syrjälä u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; 24486dbf30ceSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 24496dbf30ceSVille Syrjälä 24506dbf30ceSVille Syrjälä if (hotplug_trigger) { 24516dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 24526dbf30ceSVille Syrjälä 24536dbf30ceSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 24546dbf30ceSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 24556dbf30ceSVille Syrjälä 2456cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2457cf53902fSRodrigo Vivi hotplug_trigger, dig_hotplug_reg, hpd_spt, 245874c0b395SVille Syrjälä spt_port_hotplug_long_detect); 24596dbf30ceSVille Syrjälä } 24606dbf30ceSVille Syrjälä 24616dbf30ceSVille Syrjälä if (hotplug2_trigger) { 24626dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 24636dbf30ceSVille Syrjälä 24646dbf30ceSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); 24656dbf30ceSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG2, dig_hotplug_reg); 24666dbf30ceSVille Syrjälä 2467cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2468cf53902fSRodrigo Vivi hotplug2_trigger, dig_hotplug_reg, hpd_spt, 24696dbf30ceSVille Syrjälä spt_port_hotplug2_long_detect); 24706dbf30ceSVille Syrjälä } 24716dbf30ceSVille Syrjälä 24726dbf30ceSVille Syrjälä if (pin_mask) 247391d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 24746dbf30ceSVille Syrjälä 24756dbf30ceSVille Syrjälä if (pch_iir & SDE_GMBUS_CPT) 247691d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 24776dbf30ceSVille Syrjälä } 24786dbf30ceSVille Syrjälä 247991d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, 248091d14251STvrtko Ursulin u32 hotplug_trigger, 248140e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2482c008bc6eSPaulo Zanoni { 2483e4ce95aaSVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2484e4ce95aaSVille Syrjälä 2485e4ce95aaSVille Syrjälä dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); 2486e4ce95aaSVille Syrjälä I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); 2487e4ce95aaSVille Syrjälä 2488cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 248940e56410SVille Syrjälä dig_hotplug_reg, hpd, 2490e4ce95aaSVille Syrjälä ilk_port_hotplug_long_detect); 249140e56410SVille Syrjälä 249291d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2493e4ce95aaSVille Syrjälä } 2494c008bc6eSPaulo Zanoni 249591d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 249691d14251STvrtko Ursulin u32 de_iir) 249740e56410SVille Syrjälä { 249840e56410SVille Syrjälä enum pipe pipe; 249940e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 250040e56410SVille Syrjälä 250140e56410SVille Syrjälä if (hotplug_trigger) 250291d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ilk); 250340e56410SVille Syrjälä 2504c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 250591d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2506c008bc6eSPaulo Zanoni 2507c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 250891d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2509c008bc6eSPaulo Zanoni 2510c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 2511c008bc6eSPaulo Zanoni DRM_ERROR("Poison interrupt\n"); 2512c008bc6eSPaulo Zanoni 2513055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2514fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 2515fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 2516c008bc6eSPaulo Zanoni 251740da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 25181f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 2519c008bc6eSPaulo Zanoni 252040da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 252191d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 2522c008bc6eSPaulo Zanoni } 2523c008bc6eSPaulo Zanoni 2524c008bc6eSPaulo Zanoni /* check event from PCH */ 2525c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 2526c008bc6eSPaulo Zanoni u32 pch_iir = I915_READ(SDEIIR); 2527c008bc6eSPaulo Zanoni 252891d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 252991d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 2530c008bc6eSPaulo Zanoni else 253191d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 2532c008bc6eSPaulo Zanoni 2533c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 2534c008bc6eSPaulo Zanoni I915_WRITE(SDEIIR, pch_iir); 2535c008bc6eSPaulo Zanoni } 2536c008bc6eSPaulo Zanoni 2537cf819effSLucas De Marchi if (IS_GEN(dev_priv, 5) && de_iir & DE_PCU_EVENT) 253891d14251STvrtko Ursulin ironlake_rps_change_irq_handler(dev_priv); 2539c008bc6eSPaulo Zanoni } 2540c008bc6eSPaulo Zanoni 254191d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 254291d14251STvrtko Ursulin u32 de_iir) 25439719fb98SPaulo Zanoni { 254407d27e20SDamien Lespiau enum pipe pipe; 254523bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 254623bb4cb5SVille Syrjälä 254740e56410SVille Syrjälä if (hotplug_trigger) 254891d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ivb); 25499719fb98SPaulo Zanoni 25509719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 255191d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 25529719fb98SPaulo Zanoni 255354fd3149SDhinakaran Pandiyan if (de_iir & DE_EDP_PSR_INT_HSW) { 255454fd3149SDhinakaran Pandiyan u32 psr_iir = I915_READ(EDP_PSR_IIR); 255554fd3149SDhinakaran Pandiyan 255654fd3149SDhinakaran Pandiyan intel_psr_irq_handler(dev_priv, psr_iir); 255754fd3149SDhinakaran Pandiyan I915_WRITE(EDP_PSR_IIR, psr_iir); 255854fd3149SDhinakaran Pandiyan } 2559fc340442SDaniel Vetter 25609719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 256191d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 25629719fb98SPaulo Zanoni 25639719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 256491d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 25659719fb98SPaulo Zanoni 2566055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2567fd3a4024SDaniel Vetter if (de_iir & (DE_PIPE_VBLANK_IVB(pipe))) 2568fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 25699719fb98SPaulo Zanoni } 25709719fb98SPaulo Zanoni 25719719fb98SPaulo Zanoni /* check event from PCH */ 257291d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 25739719fb98SPaulo Zanoni u32 pch_iir = I915_READ(SDEIIR); 25749719fb98SPaulo Zanoni 257591d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 25769719fb98SPaulo Zanoni 25779719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 25789719fb98SPaulo Zanoni I915_WRITE(SDEIIR, pch_iir); 25799719fb98SPaulo Zanoni } 25809719fb98SPaulo Zanoni } 25819719fb98SPaulo Zanoni 258272c90f62SOscar Mateo /* 258372c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 258472c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 258572c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 258672c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 258772c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 258872c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 258972c90f62SOscar Mateo */ 2590f1af8fc1SPaulo Zanoni static irqreturn_t ironlake_irq_handler(int irq, void *arg) 2591b1f14ad0SJesse Barnes { 259245a83f84SDaniel Vetter struct drm_device *dev = arg; 2593fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 2594f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 25950e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 2596b1f14ad0SJesse Barnes 25972dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 25982dd2a883SImre Deak return IRQ_NONE; 25992dd2a883SImre Deak 26001f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 26011f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 26021f814dacSImre Deak 2603b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 2604b1f14ad0SJesse Barnes de_ier = I915_READ(DEIER); 2605b1f14ad0SJesse Barnes I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 26060e43406bSChris Wilson 260744498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 260844498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 260944498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 261044498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 261144498aeaSPaulo Zanoni * due to its back queue). */ 261291d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv)) { 261344498aeaSPaulo Zanoni sde_ier = I915_READ(SDEIER); 261444498aeaSPaulo Zanoni I915_WRITE(SDEIER, 0); 2615ab5c608bSBen Widawsky } 261644498aeaSPaulo Zanoni 261772c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 261872c90f62SOscar Mateo 26190e43406bSChris Wilson gt_iir = I915_READ(GTIIR); 26200e43406bSChris Wilson if (gt_iir) { 262172c90f62SOscar Mateo I915_WRITE(GTIIR, gt_iir); 262272c90f62SOscar Mateo ret = IRQ_HANDLED; 262391d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) 2624261e40b8SVille Syrjälä snb_gt_irq_handler(dev_priv, gt_iir); 2625d8fc8a47SPaulo Zanoni else 2626261e40b8SVille Syrjälä ilk_gt_irq_handler(dev_priv, gt_iir); 26270e43406bSChris Wilson } 2628b1f14ad0SJesse Barnes 2629b1f14ad0SJesse Barnes de_iir = I915_READ(DEIIR); 26300e43406bSChris Wilson if (de_iir) { 263172c90f62SOscar Mateo I915_WRITE(DEIIR, de_iir); 263272c90f62SOscar Mateo ret = IRQ_HANDLED; 263391d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 7) 263491d14251STvrtko Ursulin ivb_display_irq_handler(dev_priv, de_iir); 2635f1af8fc1SPaulo Zanoni else 263691d14251STvrtko Ursulin ilk_display_irq_handler(dev_priv, de_iir); 26370e43406bSChris Wilson } 26380e43406bSChris Wilson 263991d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) { 2640f1af8fc1SPaulo Zanoni u32 pm_iir = I915_READ(GEN6_PMIIR); 26410e43406bSChris Wilson if (pm_iir) { 2642b1f14ad0SJesse Barnes I915_WRITE(GEN6_PMIIR, pm_iir); 26430e43406bSChris Wilson ret = IRQ_HANDLED; 264472c90f62SOscar Mateo gen6_rps_irq_handler(dev_priv, pm_iir); 26450e43406bSChris Wilson } 2646f1af8fc1SPaulo Zanoni } 2647b1f14ad0SJesse Barnes 2648b1f14ad0SJesse Barnes I915_WRITE(DEIER, de_ier); 264974093f3eSChris Wilson if (!HAS_PCH_NOP(dev_priv)) 265044498aeaSPaulo Zanoni I915_WRITE(SDEIER, sde_ier); 2651b1f14ad0SJesse Barnes 26521f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 26531f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 26541f814dacSImre Deak 2655b1f14ad0SJesse Barnes return ret; 2656b1f14ad0SJesse Barnes } 2657b1f14ad0SJesse Barnes 265891d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, 265991d14251STvrtko Ursulin u32 hotplug_trigger, 266040e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2661d04a492dSShashank Sharma { 2662cebd87a0SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2663d04a492dSShashank Sharma 2664a52bb15bSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 2665a52bb15bSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 2666d04a492dSShashank Sharma 2667cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 266840e56410SVille Syrjälä dig_hotplug_reg, hpd, 2669cebd87a0SVille Syrjälä bxt_port_hotplug_long_detect); 267040e56410SVille Syrjälä 267191d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2672d04a492dSShashank Sharma } 2673d04a492dSShashank Sharma 2674121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2675121e758eSDhinakaran Pandiyan { 2676121e758eSDhinakaran Pandiyan u32 pin_mask = 0, long_mask = 0; 2677b796b971SDhinakaran Pandiyan u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; 2678b796b971SDhinakaran Pandiyan u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; 2679121e758eSDhinakaran Pandiyan 2680121e758eSDhinakaran Pandiyan if (trigger_tc) { 2681b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2682b796b971SDhinakaran Pandiyan 2683121e758eSDhinakaran Pandiyan dig_hotplug_reg = I915_READ(GEN11_TC_HOTPLUG_CTL); 2684121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_TC_HOTPLUG_CTL, dig_hotplug_reg); 2685121e758eSDhinakaran Pandiyan 2686121e758eSDhinakaran Pandiyan intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tc, 2687b796b971SDhinakaran Pandiyan dig_hotplug_reg, hpd_gen11, 2688121e758eSDhinakaran Pandiyan gen11_port_hotplug_long_detect); 2689121e758eSDhinakaran Pandiyan } 2690b796b971SDhinakaran Pandiyan 2691b796b971SDhinakaran Pandiyan if (trigger_tbt) { 2692b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2693b796b971SDhinakaran Pandiyan 2694b796b971SDhinakaran Pandiyan dig_hotplug_reg = I915_READ(GEN11_TBT_HOTPLUG_CTL); 2695b796b971SDhinakaran Pandiyan I915_WRITE(GEN11_TBT_HOTPLUG_CTL, dig_hotplug_reg); 2696b796b971SDhinakaran Pandiyan 2697b796b971SDhinakaran Pandiyan intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tbt, 2698b796b971SDhinakaran Pandiyan dig_hotplug_reg, hpd_gen11, 2699b796b971SDhinakaran Pandiyan gen11_port_hotplug_long_detect); 2700b796b971SDhinakaran Pandiyan } 2701b796b971SDhinakaran Pandiyan 2702b796b971SDhinakaran Pandiyan if (pin_mask) 2703b796b971SDhinakaran Pandiyan intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2704b796b971SDhinakaran Pandiyan else 2705b796b971SDhinakaran Pandiyan DRM_ERROR("Unexpected DE HPD interrupt 0x%08x\n", iir); 2706121e758eSDhinakaran Pandiyan } 2707121e758eSDhinakaran Pandiyan 27089d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 27099d17210fSLucas De Marchi { 27109d17210fSLucas De Marchi u32 mask = GEN8_AUX_CHANNEL_A; 27119d17210fSLucas De Marchi 27129d17210fSLucas De Marchi if (INTEL_GEN(dev_priv) >= 9) 27139d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 27149d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 27159d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 27169d17210fSLucas De Marchi 27179d17210fSLucas De Marchi if (IS_CNL_WITH_PORT_F(dev_priv)) 27189d17210fSLucas De Marchi mask |= CNL_AUX_CHANNEL_F; 27199d17210fSLucas De Marchi 27209d17210fSLucas De Marchi if (INTEL_GEN(dev_priv) >= 11) 27219d17210fSLucas De Marchi mask |= ICL_AUX_CHANNEL_E | 27229d17210fSLucas De Marchi CNL_AUX_CHANNEL_F; 27239d17210fSLucas De Marchi 27249d17210fSLucas De Marchi return mask; 27259d17210fSLucas De Marchi } 27269d17210fSLucas De Marchi 2727f11a0f46STvrtko Ursulin static irqreturn_t 2728f11a0f46STvrtko Ursulin gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 2729abd58f01SBen Widawsky { 2730abd58f01SBen Widawsky irqreturn_t ret = IRQ_NONE; 2731f11a0f46STvrtko Ursulin u32 iir; 2732c42664ccSDaniel Vetter enum pipe pipe; 273388e04703SJesse Barnes 2734abd58f01SBen Widawsky if (master_ctl & GEN8_DE_MISC_IRQ) { 2735e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_MISC_IIR); 2736e32192e1STvrtko Ursulin if (iir) { 2737e04f7eceSVille Syrjälä bool found = false; 2738e04f7eceSVille Syrjälä 2739e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_MISC_IIR, iir); 2740abd58f01SBen Widawsky ret = IRQ_HANDLED; 2741e04f7eceSVille Syrjälä 2742e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 274391d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2744e04f7eceSVille Syrjälä found = true; 2745e04f7eceSVille Syrjälä } 2746e04f7eceSVille Syrjälä 2747e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 274854fd3149SDhinakaran Pandiyan u32 psr_iir = I915_READ(EDP_PSR_IIR); 274954fd3149SDhinakaran Pandiyan 275054fd3149SDhinakaran Pandiyan intel_psr_irq_handler(dev_priv, psr_iir); 275154fd3149SDhinakaran Pandiyan I915_WRITE(EDP_PSR_IIR, psr_iir); 2752e04f7eceSVille Syrjälä found = true; 2753e04f7eceSVille Syrjälä } 2754e04f7eceSVille Syrjälä 2755e04f7eceSVille Syrjälä if (!found) 275638cc46d7SOscar Mateo DRM_ERROR("Unexpected DE Misc interrupt\n"); 2757abd58f01SBen Widawsky } 275838cc46d7SOscar Mateo else 275938cc46d7SOscar Mateo DRM_ERROR("The master control interrupt lied (DE MISC)!\n"); 2760abd58f01SBen Widawsky } 2761abd58f01SBen Widawsky 2762121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 2763121e758eSDhinakaran Pandiyan iir = I915_READ(GEN11_DE_HPD_IIR); 2764121e758eSDhinakaran Pandiyan if (iir) { 2765121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_DE_HPD_IIR, iir); 2766121e758eSDhinakaran Pandiyan ret = IRQ_HANDLED; 2767121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 2768121e758eSDhinakaran Pandiyan } else { 2769121e758eSDhinakaran Pandiyan DRM_ERROR("The master control interrupt lied, (DE HPD)!\n"); 2770121e758eSDhinakaran Pandiyan } 2771121e758eSDhinakaran Pandiyan } 2772121e758eSDhinakaran Pandiyan 27736d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 2774e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_PORT_IIR); 2775e32192e1STvrtko Ursulin if (iir) { 2776e32192e1STvrtko Ursulin u32 tmp_mask; 2777d04a492dSShashank Sharma bool found = false; 2778cebd87a0SVille Syrjälä 2779e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_PORT_IIR, iir); 27806d766f02SDaniel Vetter ret = IRQ_HANDLED; 278188e04703SJesse Barnes 27829d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 278391d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2784d04a492dSShashank Sharma found = true; 2785d04a492dSShashank Sharma } 2786d04a492dSShashank Sharma 2787cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) { 2788e32192e1STvrtko Ursulin tmp_mask = iir & BXT_DE_PORT_HOTPLUG_MASK; 2789e32192e1STvrtko Ursulin if (tmp_mask) { 279091d14251STvrtko Ursulin bxt_hpd_irq_handler(dev_priv, tmp_mask, 279191d14251STvrtko Ursulin hpd_bxt); 2792d04a492dSShashank Sharma found = true; 2793d04a492dSShashank Sharma } 2794e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 2795e32192e1STvrtko Ursulin tmp_mask = iir & GEN8_PORT_DP_A_HOTPLUG; 2796e32192e1STvrtko Ursulin if (tmp_mask) { 279791d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, 279891d14251STvrtko Ursulin tmp_mask, hpd_bdw); 2799e32192e1STvrtko Ursulin found = true; 2800e32192e1STvrtko Ursulin } 2801e32192e1STvrtko Ursulin } 2802d04a492dSShashank Sharma 2803cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv) && (iir & BXT_DE_PORT_GMBUS)) { 280491d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 28059e63743eSShashank Sharma found = true; 28069e63743eSShashank Sharma } 28079e63743eSShashank Sharma 2808d04a492dSShashank Sharma if (!found) 280938cc46d7SOscar Mateo DRM_ERROR("Unexpected DE Port interrupt\n"); 28106d766f02SDaniel Vetter } 281138cc46d7SOscar Mateo else 281238cc46d7SOscar Mateo DRM_ERROR("The master control interrupt lied (DE PORT)!\n"); 28136d766f02SDaniel Vetter } 28146d766f02SDaniel Vetter 2815055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2816fd3a4024SDaniel Vetter u32 fault_errors; 2817abd58f01SBen Widawsky 2818c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 2819c42664ccSDaniel Vetter continue; 2820c42664ccSDaniel Vetter 2821e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); 2822e32192e1STvrtko Ursulin if (!iir) { 2823e32192e1STvrtko Ursulin DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); 2824e32192e1STvrtko Ursulin continue; 2825e32192e1STvrtko Ursulin } 2826770de83dSDamien Lespiau 2827e32192e1STvrtko Ursulin ret = IRQ_HANDLED; 2828e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir); 2829e32192e1STvrtko Ursulin 2830fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 2831fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 2832abd58f01SBen Widawsky 2833e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 283491d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 28350fbe7870SDaniel Vetter 2836e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_FIFO_UNDERRUN) 2837e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 283838d83c96SDaniel Vetter 2839e32192e1STvrtko Ursulin fault_errors = iir; 2840bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 9) 2841e32192e1STvrtko Ursulin fault_errors &= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 2842770de83dSDamien Lespiau else 2843e32192e1STvrtko Ursulin fault_errors &= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 2844770de83dSDamien Lespiau 2845770de83dSDamien Lespiau if (fault_errors) 28461353ec38STvrtko Ursulin DRM_ERROR("Fault errors on pipe %c: 0x%08x\n", 284730100f2bSDaniel Vetter pipe_name(pipe), 2848e32192e1STvrtko Ursulin fault_errors); 2849abd58f01SBen Widawsky } 2850abd58f01SBen Widawsky 285191d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 2852266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 285392d03a80SDaniel Vetter /* 285492d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 285592d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 285692d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 285792d03a80SDaniel Vetter */ 2858e32192e1STvrtko Ursulin iir = I915_READ(SDEIIR); 2859e32192e1STvrtko Ursulin if (iir) { 2860e32192e1STvrtko Ursulin I915_WRITE(SDEIIR, iir); 286192d03a80SDaniel Vetter ret = IRQ_HANDLED; 28626dbf30ceSVille Syrjälä 286329b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 286431604222SAnusha Srivatsa icp_irq_handler(dev_priv, iir); 2865c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 286691d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 28676dbf30ceSVille Syrjälä else 286891d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 28692dfb0b81SJani Nikula } else { 28702dfb0b81SJani Nikula /* 28712dfb0b81SJani Nikula * Like on previous PCH there seems to be something 28722dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 28732dfb0b81SJani Nikula */ 28742dfb0b81SJani Nikula DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n"); 28752dfb0b81SJani Nikula } 287692d03a80SDaniel Vetter } 287792d03a80SDaniel Vetter 2878f11a0f46STvrtko Ursulin return ret; 2879f11a0f46STvrtko Ursulin } 2880f11a0f46STvrtko Ursulin 28814376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 28824376b9c9SMika Kuoppala { 28834376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 28844376b9c9SMika Kuoppala 28854376b9c9SMika Kuoppala /* 28864376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 28874376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 28884376b9c9SMika Kuoppala * New indications can and will light up during processing, 28894376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 28904376b9c9SMika Kuoppala */ 28914376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 28924376b9c9SMika Kuoppala } 28934376b9c9SMika Kuoppala 28944376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 28954376b9c9SMika Kuoppala { 28964376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 28974376b9c9SMika Kuoppala } 28984376b9c9SMika Kuoppala 2899f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 2900f11a0f46STvrtko Ursulin { 2901f0fd96f5SChris Wilson struct drm_i915_private *dev_priv = to_i915(arg); 290225286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 2903f11a0f46STvrtko Ursulin u32 master_ctl; 2904f0fd96f5SChris Wilson u32 gt_iir[4]; 2905f11a0f46STvrtko Ursulin 2906f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 2907f11a0f46STvrtko Ursulin return IRQ_NONE; 2908f11a0f46STvrtko Ursulin 29094376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 29104376b9c9SMika Kuoppala if (!master_ctl) { 29114376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2912f11a0f46STvrtko Ursulin return IRQ_NONE; 29134376b9c9SMika Kuoppala } 2914f11a0f46STvrtko Ursulin 2915f11a0f46STvrtko Ursulin /* Find, clear, then process each source of interrupt */ 291655ef72f2SChris Wilson gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); 2917f0fd96f5SChris Wilson 2918f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2919f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 2920f0fd96f5SChris Wilson disable_rpm_wakeref_asserts(dev_priv); 292155ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 2922f0fd96f5SChris Wilson enable_rpm_wakeref_asserts(dev_priv); 2923f0fd96f5SChris Wilson } 2924f11a0f46STvrtko Ursulin 29254376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2926abd58f01SBen Widawsky 2927f0fd96f5SChris Wilson gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); 29281f814dacSImre Deak 292955ef72f2SChris Wilson return IRQ_HANDLED; 2930abd58f01SBen Widawsky } 2931abd58f01SBen Widawsky 293251951ae7SMika Kuoppala static u32 2933f744dbc2SMika Kuoppala gen11_gt_engine_identity(struct drm_i915_private * const i915, 293451951ae7SMika Kuoppala const unsigned int bank, const unsigned int bit) 293551951ae7SMika Kuoppala { 293625286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 293751951ae7SMika Kuoppala u32 timeout_ts; 293851951ae7SMika Kuoppala u32 ident; 293951951ae7SMika Kuoppala 294096606f3bSOscar Mateo lockdep_assert_held(&i915->irq_lock); 294196606f3bSOscar Mateo 294251951ae7SMika Kuoppala raw_reg_write(regs, GEN11_IIR_REG_SELECTOR(bank), BIT(bit)); 294351951ae7SMika Kuoppala 294451951ae7SMika Kuoppala /* 294551951ae7SMika Kuoppala * NB: Specs do not specify how long to spin wait, 294651951ae7SMika Kuoppala * so we do ~100us as an educated guess. 294751951ae7SMika Kuoppala */ 294851951ae7SMika Kuoppala timeout_ts = (local_clock() >> 10) + 100; 294951951ae7SMika Kuoppala do { 295051951ae7SMika Kuoppala ident = raw_reg_read(regs, GEN11_INTR_IDENTITY_REG(bank)); 295151951ae7SMika Kuoppala } while (!(ident & GEN11_INTR_DATA_VALID) && 295251951ae7SMika Kuoppala !time_after32(local_clock() >> 10, timeout_ts)); 295351951ae7SMika Kuoppala 295451951ae7SMika Kuoppala if (unlikely(!(ident & GEN11_INTR_DATA_VALID))) { 295551951ae7SMika Kuoppala DRM_ERROR("INTR_IDENTITY_REG%u:%u 0x%08x not valid!\n", 295651951ae7SMika Kuoppala bank, bit, ident); 295751951ae7SMika Kuoppala return 0; 295851951ae7SMika Kuoppala } 295951951ae7SMika Kuoppala 296051951ae7SMika Kuoppala raw_reg_write(regs, GEN11_INTR_IDENTITY_REG(bank), 296151951ae7SMika Kuoppala GEN11_INTR_DATA_VALID); 296251951ae7SMika Kuoppala 2963f744dbc2SMika Kuoppala return ident; 2964f744dbc2SMika Kuoppala } 2965f744dbc2SMika Kuoppala 2966f744dbc2SMika Kuoppala static void 2967f744dbc2SMika Kuoppala gen11_other_irq_handler(struct drm_i915_private * const i915, 2968f744dbc2SMika Kuoppala const u8 instance, const u16 iir) 2969f744dbc2SMika Kuoppala { 2970d02b98b8SOscar Mateo if (instance == OTHER_GTPM_INSTANCE) 2971*a087bafeSMika Kuoppala return gen11_rps_irq_handler(i915, iir); 2972d02b98b8SOscar Mateo 2973f744dbc2SMika Kuoppala WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n", 2974f744dbc2SMika Kuoppala instance, iir); 2975f744dbc2SMika Kuoppala } 2976f744dbc2SMika Kuoppala 2977f744dbc2SMika Kuoppala static void 2978f744dbc2SMika Kuoppala gen11_engine_irq_handler(struct drm_i915_private * const i915, 2979f744dbc2SMika Kuoppala const u8 class, const u8 instance, const u16 iir) 2980f744dbc2SMika Kuoppala { 2981f744dbc2SMika Kuoppala struct intel_engine_cs *engine; 2982f744dbc2SMika Kuoppala 2983f744dbc2SMika Kuoppala if (instance <= MAX_ENGINE_INSTANCE) 2984f744dbc2SMika Kuoppala engine = i915->engine_class[class][instance]; 2985f744dbc2SMika Kuoppala else 2986f744dbc2SMika Kuoppala engine = NULL; 2987f744dbc2SMika Kuoppala 2988f744dbc2SMika Kuoppala if (likely(engine)) 2989f744dbc2SMika Kuoppala return gen8_cs_irq_handler(engine, iir); 2990f744dbc2SMika Kuoppala 2991f744dbc2SMika Kuoppala WARN_ONCE(1, "unhandled engine interrupt class=0x%x, instance=0x%x\n", 2992f744dbc2SMika Kuoppala class, instance); 2993f744dbc2SMika Kuoppala } 2994f744dbc2SMika Kuoppala 2995f744dbc2SMika Kuoppala static void 2996f744dbc2SMika Kuoppala gen11_gt_identity_handler(struct drm_i915_private * const i915, 2997f744dbc2SMika Kuoppala const u32 identity) 2998f744dbc2SMika Kuoppala { 2999f744dbc2SMika Kuoppala const u8 class = GEN11_INTR_ENGINE_CLASS(identity); 3000f744dbc2SMika Kuoppala const u8 instance = GEN11_INTR_ENGINE_INSTANCE(identity); 3001f744dbc2SMika Kuoppala const u16 intr = GEN11_INTR_ENGINE_INTR(identity); 3002f744dbc2SMika Kuoppala 3003f744dbc2SMika Kuoppala if (unlikely(!intr)) 3004f744dbc2SMika Kuoppala return; 3005f744dbc2SMika Kuoppala 3006f744dbc2SMika Kuoppala if (class <= COPY_ENGINE_CLASS) 3007f744dbc2SMika Kuoppala return gen11_engine_irq_handler(i915, class, instance, intr); 3008f744dbc2SMika Kuoppala 3009f744dbc2SMika Kuoppala if (class == OTHER_CLASS) 3010f744dbc2SMika Kuoppala return gen11_other_irq_handler(i915, instance, intr); 3011f744dbc2SMika Kuoppala 3012f744dbc2SMika Kuoppala WARN_ONCE(1, "unknown interrupt class=0x%x, instance=0x%x, intr=0x%x\n", 3013f744dbc2SMika Kuoppala class, instance, intr); 301451951ae7SMika Kuoppala } 301551951ae7SMika Kuoppala 301651951ae7SMika Kuoppala static void 301796606f3bSOscar Mateo gen11_gt_bank_handler(struct drm_i915_private * const i915, 301896606f3bSOscar Mateo const unsigned int bank) 301951951ae7SMika Kuoppala { 302025286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 302151951ae7SMika Kuoppala unsigned long intr_dw; 302251951ae7SMika Kuoppala unsigned int bit; 302351951ae7SMika Kuoppala 302496606f3bSOscar Mateo lockdep_assert_held(&i915->irq_lock); 302551951ae7SMika Kuoppala 302651951ae7SMika Kuoppala intr_dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); 302751951ae7SMika Kuoppala 302851951ae7SMika Kuoppala if (unlikely(!intr_dw)) { 302951951ae7SMika Kuoppala DRM_ERROR("GT_INTR_DW%u blank!\n", bank); 303096606f3bSOscar Mateo return; 303151951ae7SMika Kuoppala } 303251951ae7SMika Kuoppala 303351951ae7SMika Kuoppala for_each_set_bit(bit, &intr_dw, 32) { 3034f744dbc2SMika Kuoppala const u32 ident = gen11_gt_engine_identity(i915, 3035f744dbc2SMika Kuoppala bank, bit); 303651951ae7SMika Kuoppala 3037f744dbc2SMika Kuoppala gen11_gt_identity_handler(i915, ident); 303851951ae7SMika Kuoppala } 303951951ae7SMika Kuoppala 304051951ae7SMika Kuoppala /* Clear must be after shared has been served for engine */ 304151951ae7SMika Kuoppala raw_reg_write(regs, GEN11_GT_INTR_DW(bank), intr_dw); 304251951ae7SMika Kuoppala } 304396606f3bSOscar Mateo 304496606f3bSOscar Mateo static void 304596606f3bSOscar Mateo gen11_gt_irq_handler(struct drm_i915_private * const i915, 304696606f3bSOscar Mateo const u32 master_ctl) 304796606f3bSOscar Mateo { 304896606f3bSOscar Mateo unsigned int bank; 304996606f3bSOscar Mateo 305096606f3bSOscar Mateo spin_lock(&i915->irq_lock); 305196606f3bSOscar Mateo 305296606f3bSOscar Mateo for (bank = 0; bank < 2; bank++) { 305396606f3bSOscar Mateo if (master_ctl & GEN11_GT_DW_IRQ(bank)) 305496606f3bSOscar Mateo gen11_gt_bank_handler(i915, bank); 305596606f3bSOscar Mateo } 305696606f3bSOscar Mateo 305796606f3bSOscar Mateo spin_unlock(&i915->irq_lock); 305851951ae7SMika Kuoppala } 305951951ae7SMika Kuoppala 30607a909383SChris Wilson static u32 30617a909383SChris Wilson gen11_gu_misc_irq_ack(struct drm_i915_private *dev_priv, const u32 master_ctl) 3062df0d28c1SDhinakaran Pandiyan { 306325286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 30647a909383SChris Wilson u32 iir; 3065df0d28c1SDhinakaran Pandiyan 3066df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 30677a909383SChris Wilson return 0; 3068df0d28c1SDhinakaran Pandiyan 30697a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 30707a909383SChris Wilson if (likely(iir)) 30717a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 30727a909383SChris Wilson 30737a909383SChris Wilson return iir; 3074df0d28c1SDhinakaran Pandiyan } 3075df0d28c1SDhinakaran Pandiyan 3076df0d28c1SDhinakaran Pandiyan static void 30777a909383SChris Wilson gen11_gu_misc_irq_handler(struct drm_i915_private *dev_priv, const u32 iir) 3078df0d28c1SDhinakaran Pandiyan { 3079df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 3080df0d28c1SDhinakaran Pandiyan intel_opregion_asle_intr(dev_priv); 3081df0d28c1SDhinakaran Pandiyan } 3082df0d28c1SDhinakaran Pandiyan 308381067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 308481067b71SMika Kuoppala { 308581067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 308681067b71SMika Kuoppala 308781067b71SMika Kuoppala /* 308881067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 308981067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 309081067b71SMika Kuoppala * New indications can and will light up during processing, 309181067b71SMika Kuoppala * and will generate new interrupt after enabling master. 309281067b71SMika Kuoppala */ 309381067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 309481067b71SMika Kuoppala } 309581067b71SMika Kuoppala 309681067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 309781067b71SMika Kuoppala { 309881067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 309981067b71SMika Kuoppala } 310081067b71SMika Kuoppala 310151951ae7SMika Kuoppala static irqreturn_t gen11_irq_handler(int irq, void *arg) 310251951ae7SMika Kuoppala { 310351951ae7SMika Kuoppala struct drm_i915_private * const i915 = to_i915(arg); 310425286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 310551951ae7SMika Kuoppala u32 master_ctl; 3106df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 310751951ae7SMika Kuoppala 310851951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 310951951ae7SMika Kuoppala return IRQ_NONE; 311051951ae7SMika Kuoppala 311181067b71SMika Kuoppala master_ctl = gen11_master_intr_disable(regs); 311281067b71SMika Kuoppala if (!master_ctl) { 311381067b71SMika Kuoppala gen11_master_intr_enable(regs); 311451951ae7SMika Kuoppala return IRQ_NONE; 311581067b71SMika Kuoppala } 311651951ae7SMika Kuoppala 311751951ae7SMika Kuoppala /* Find, clear, then process each source of interrupt. */ 311851951ae7SMika Kuoppala gen11_gt_irq_handler(i915, master_ctl); 311951951ae7SMika Kuoppala 312051951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 312151951ae7SMika Kuoppala if (master_ctl & GEN11_DISPLAY_IRQ) { 312251951ae7SMika Kuoppala const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 312351951ae7SMika Kuoppala 312451951ae7SMika Kuoppala disable_rpm_wakeref_asserts(i915); 312551951ae7SMika Kuoppala /* 312651951ae7SMika Kuoppala * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 312751951ae7SMika Kuoppala * for the display related bits. 312851951ae7SMika Kuoppala */ 312951951ae7SMika Kuoppala gen8_de_irq_handler(i915, disp_ctl); 313051951ae7SMika Kuoppala enable_rpm_wakeref_asserts(i915); 313151951ae7SMika Kuoppala } 313251951ae7SMika Kuoppala 31337a909383SChris Wilson gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 3134df0d28c1SDhinakaran Pandiyan 313581067b71SMika Kuoppala gen11_master_intr_enable(regs); 313651951ae7SMika Kuoppala 31377a909383SChris Wilson gen11_gu_misc_irq_handler(i915, gu_misc_iir); 3138df0d28c1SDhinakaran Pandiyan 313951951ae7SMika Kuoppala return IRQ_HANDLED; 314051951ae7SMika Kuoppala } 314151951ae7SMika Kuoppala 314242f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 314342f52ef8SKeith Packard * we use as a pipe index 314442f52ef8SKeith Packard */ 314586e83e35SChris Wilson static int i8xx_enable_vblank(struct drm_device *dev, unsigned int pipe) 31460a3e67a4SJesse Barnes { 3147fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3148e9d21d7fSKeith Packard unsigned long irqflags; 314971e0ffa5SJesse Barnes 31501ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 315186e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 315286e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 315386e83e35SChris Wilson 315486e83e35SChris Wilson return 0; 315586e83e35SChris Wilson } 315686e83e35SChris Wilson 3157d938da6bSVille Syrjälä static int i945gm_enable_vblank(struct drm_device *dev, unsigned int pipe) 3158d938da6bSVille Syrjälä { 3159d938da6bSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(dev); 3160d938da6bSVille Syrjälä 3161d938da6bSVille Syrjälä if (dev_priv->i945gm_vblank.enabled++ == 0) 3162d938da6bSVille Syrjälä schedule_work(&dev_priv->i945gm_vblank.work); 3163d938da6bSVille Syrjälä 3164d938da6bSVille Syrjälä return i8xx_enable_vblank(dev, pipe); 3165d938da6bSVille Syrjälä } 3166d938da6bSVille Syrjälä 316786e83e35SChris Wilson static int i965_enable_vblank(struct drm_device *dev, unsigned int pipe) 316886e83e35SChris Wilson { 316986e83e35SChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 317086e83e35SChris Wilson unsigned long irqflags; 317186e83e35SChris Wilson 317286e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 31737c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 3174755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 31751ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 31768692d00eSChris Wilson 31770a3e67a4SJesse Barnes return 0; 31780a3e67a4SJesse Barnes } 31790a3e67a4SJesse Barnes 318088e72717SThierry Reding static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) 3181f796cf8fSJesse Barnes { 3182fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3183f796cf8fSJesse Barnes unsigned long irqflags; 3184a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 318586e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 3186f796cf8fSJesse Barnes 3187f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3188fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 3189b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3190b1f14ad0SJesse Barnes 31912e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 31922e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 31932e8bf223SDhinakaran Pandiyan */ 31942e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 31952e8bf223SDhinakaran Pandiyan drm_vblank_restore(dev, pipe); 31962e8bf223SDhinakaran Pandiyan 3197b1f14ad0SJesse Barnes return 0; 3198b1f14ad0SJesse Barnes } 3199b1f14ad0SJesse Barnes 320088e72717SThierry Reding static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) 3201abd58f01SBen Widawsky { 3202fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3203abd58f01SBen Widawsky unsigned long irqflags; 3204abd58f01SBen Widawsky 3205abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3206013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 3207abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3208013d3752SVille Syrjälä 32092e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 32102e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 32112e8bf223SDhinakaran Pandiyan */ 32122e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 32132e8bf223SDhinakaran Pandiyan drm_vblank_restore(dev, pipe); 32142e8bf223SDhinakaran Pandiyan 3215abd58f01SBen Widawsky return 0; 3216abd58f01SBen Widawsky } 3217abd58f01SBen Widawsky 321842f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 321942f52ef8SKeith Packard * we use as a pipe index 322042f52ef8SKeith Packard */ 322186e83e35SChris Wilson static void i8xx_disable_vblank(struct drm_device *dev, unsigned int pipe) 322286e83e35SChris Wilson { 322386e83e35SChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 322486e83e35SChris Wilson unsigned long irqflags; 322586e83e35SChris Wilson 322686e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 322786e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 322886e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 322986e83e35SChris Wilson } 323086e83e35SChris Wilson 3231d938da6bSVille Syrjälä static void i945gm_disable_vblank(struct drm_device *dev, unsigned int pipe) 3232d938da6bSVille Syrjälä { 3233d938da6bSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(dev); 3234d938da6bSVille Syrjälä 3235d938da6bSVille Syrjälä i8xx_disable_vblank(dev, pipe); 3236d938da6bSVille Syrjälä 3237d938da6bSVille Syrjälä if (--dev_priv->i945gm_vblank.enabled == 0) 3238d938da6bSVille Syrjälä schedule_work(&dev_priv->i945gm_vblank.work); 3239d938da6bSVille Syrjälä } 3240d938da6bSVille Syrjälä 324186e83e35SChris Wilson static void i965_disable_vblank(struct drm_device *dev, unsigned int pipe) 32420a3e67a4SJesse Barnes { 3243fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3244e9d21d7fSKeith Packard unsigned long irqflags; 32450a3e67a4SJesse Barnes 32461ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 32477c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 3248755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 32491ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 32500a3e67a4SJesse Barnes } 32510a3e67a4SJesse Barnes 325288e72717SThierry Reding static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) 3253f796cf8fSJesse Barnes { 3254fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3255f796cf8fSJesse Barnes unsigned long irqflags; 3256a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 325786e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 3258f796cf8fSJesse Barnes 3259f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3260fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 3261b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3262b1f14ad0SJesse Barnes } 3263b1f14ad0SJesse Barnes 326488e72717SThierry Reding static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe) 3265abd58f01SBen Widawsky { 3266fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3267abd58f01SBen Widawsky unsigned long irqflags; 3268abd58f01SBen Widawsky 3269abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3270013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 3271abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3272abd58f01SBen Widawsky } 3273abd58f01SBen Widawsky 3274d938da6bSVille Syrjälä static void i945gm_vblank_work_func(struct work_struct *work) 3275d938da6bSVille Syrjälä { 3276d938da6bSVille Syrjälä struct drm_i915_private *dev_priv = 3277d938da6bSVille Syrjälä container_of(work, struct drm_i915_private, i945gm_vblank.work); 3278d938da6bSVille Syrjälä 3279d938da6bSVille Syrjälä /* 3280d938da6bSVille Syrjälä * Vblank interrupts fail to wake up the device from C3, 3281d938da6bSVille Syrjälä * hence we want to prevent C3 usage while vblank interrupts 3282d938da6bSVille Syrjälä * are enabled. 3283d938da6bSVille Syrjälä */ 3284d938da6bSVille Syrjälä pm_qos_update_request(&dev_priv->i945gm_vblank.pm_qos, 3285d938da6bSVille Syrjälä READ_ONCE(dev_priv->i945gm_vblank.enabled) ? 3286d938da6bSVille Syrjälä dev_priv->i945gm_vblank.c3_disable_latency : 3287d938da6bSVille Syrjälä PM_QOS_DEFAULT_VALUE); 3288d938da6bSVille Syrjälä } 3289d938da6bSVille Syrjälä 3290d938da6bSVille Syrjälä static int cstate_disable_latency(const char *name) 3291d938da6bSVille Syrjälä { 3292d938da6bSVille Syrjälä const struct cpuidle_driver *drv; 3293d938da6bSVille Syrjälä int i; 3294d938da6bSVille Syrjälä 3295d938da6bSVille Syrjälä drv = cpuidle_get_driver(); 3296d938da6bSVille Syrjälä if (!drv) 3297d938da6bSVille Syrjälä return 0; 3298d938da6bSVille Syrjälä 3299d938da6bSVille Syrjälä for (i = 0; i < drv->state_count; i++) { 3300d938da6bSVille Syrjälä const struct cpuidle_state *state = &drv->states[i]; 3301d938da6bSVille Syrjälä 3302d938da6bSVille Syrjälä if (!strcmp(state->name, name)) 3303d938da6bSVille Syrjälä return state->exit_latency ? 3304d938da6bSVille Syrjälä state->exit_latency - 1 : 0; 3305d938da6bSVille Syrjälä } 3306d938da6bSVille Syrjälä 3307d938da6bSVille Syrjälä return 0; 3308d938da6bSVille Syrjälä } 3309d938da6bSVille Syrjälä 3310d938da6bSVille Syrjälä static void i945gm_vblank_work_init(struct drm_i915_private *dev_priv) 3311d938da6bSVille Syrjälä { 3312d938da6bSVille Syrjälä INIT_WORK(&dev_priv->i945gm_vblank.work, 3313d938da6bSVille Syrjälä i945gm_vblank_work_func); 3314d938da6bSVille Syrjälä 3315d938da6bSVille Syrjälä dev_priv->i945gm_vblank.c3_disable_latency = 3316d938da6bSVille Syrjälä cstate_disable_latency("C3"); 3317d938da6bSVille Syrjälä pm_qos_add_request(&dev_priv->i945gm_vblank.pm_qos, 3318d938da6bSVille Syrjälä PM_QOS_CPU_DMA_LATENCY, 3319d938da6bSVille Syrjälä PM_QOS_DEFAULT_VALUE); 3320d938da6bSVille Syrjälä } 3321d938da6bSVille Syrjälä 3322d938da6bSVille Syrjälä static void i945gm_vblank_work_fini(struct drm_i915_private *dev_priv) 3323d938da6bSVille Syrjälä { 3324d938da6bSVille Syrjälä cancel_work_sync(&dev_priv->i945gm_vblank.work); 3325d938da6bSVille Syrjälä pm_qos_remove_request(&dev_priv->i945gm_vblank.pm_qos); 3326d938da6bSVille Syrjälä } 3327d938da6bSVille Syrjälä 3328b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 332991738a95SPaulo Zanoni { 33306e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 333191738a95SPaulo Zanoni return; 333291738a95SPaulo Zanoni 33333488d4ebSVille Syrjälä GEN3_IRQ_RESET(SDE); 3334105b122eSPaulo Zanoni 33356e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 3336105b122eSPaulo Zanoni I915_WRITE(SERR_INT, 0xffffffff); 3337622364b6SPaulo Zanoni } 3338105b122eSPaulo Zanoni 333991738a95SPaulo Zanoni /* 3340622364b6SPaulo Zanoni * SDEIER is also touched by the interrupt handler to work around missed PCH 3341622364b6SPaulo Zanoni * interrupts. Hence we can't update it after the interrupt handler is enabled - 3342622364b6SPaulo Zanoni * instead we unconditionally enable all PCH interrupt sources here, but then 3343622364b6SPaulo Zanoni * only unmask them as needed with SDEIMR. 3344622364b6SPaulo Zanoni * 3345622364b6SPaulo Zanoni * This function needs to be called before interrupts are enabled. 334691738a95SPaulo Zanoni */ 3347622364b6SPaulo Zanoni static void ibx_irq_pre_postinstall(struct drm_device *dev) 3348622364b6SPaulo Zanoni { 3349fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3350622364b6SPaulo Zanoni 33516e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3352622364b6SPaulo Zanoni return; 3353622364b6SPaulo Zanoni 3354622364b6SPaulo Zanoni WARN_ON(I915_READ(SDEIER) != 0); 335591738a95SPaulo Zanoni I915_WRITE(SDEIER, 0xffffffff); 335691738a95SPaulo Zanoni POSTING_READ(SDEIER); 335791738a95SPaulo Zanoni } 335891738a95SPaulo Zanoni 3359b243f530STvrtko Ursulin static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv) 3360d18ea1b5SDaniel Vetter { 33613488d4ebSVille Syrjälä GEN3_IRQ_RESET(GT); 3362b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) 33633488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN6_PM); 3364d18ea1b5SDaniel Vetter } 3365d18ea1b5SDaniel Vetter 336670591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 336770591a41SVille Syrjälä { 336871b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 336971b8b41dSVille Syrjälä I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 337071b8b41dSVille Syrjälä else 337171b8b41dSVille Syrjälä I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK); 337271b8b41dSVille Syrjälä 3373ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 337470591a41SVille Syrjälä I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 337570591a41SVille Syrjälä 337644d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 337770591a41SVille Syrjälä 33783488d4ebSVille Syrjälä GEN3_IRQ_RESET(VLV_); 33798bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 338070591a41SVille Syrjälä } 338170591a41SVille Syrjälä 33828bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 33838bb61306SVille Syrjälä { 33848bb61306SVille Syrjälä u32 pipestat_mask; 33859ab981f2SVille Syrjälä u32 enable_mask; 33868bb61306SVille Syrjälä enum pipe pipe; 33878bb61306SVille Syrjälä 3388842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 33898bb61306SVille Syrjälä 33908bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 33918bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 33928bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 33938bb61306SVille Syrjälä 33949ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 33958bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3396ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 3397ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 3398ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 3399ebf5f921SVille Syrjälä 34008bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 3401ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 3402ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 34036b7eafc1SVille Syrjälä 34048bd099a7SChris Wilson WARN_ON(dev_priv->irq_mask != ~0u); 34056b7eafc1SVille Syrjälä 34069ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 34078bb61306SVille Syrjälä 34083488d4ebSVille Syrjälä GEN3_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); 34098bb61306SVille Syrjälä } 34108bb61306SVille Syrjälä 34118bb61306SVille Syrjälä /* drm_dma.h hooks 34128bb61306SVille Syrjälä */ 34138bb61306SVille Syrjälä static void ironlake_irq_reset(struct drm_device *dev) 34148bb61306SVille Syrjälä { 3415fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 34168bb61306SVille Syrjälä 34173488d4ebSVille Syrjälä GEN3_IRQ_RESET(DE); 3418cf819effSLucas De Marchi if (IS_GEN(dev_priv, 7)) 34198bb61306SVille Syrjälä I915_WRITE(GEN7_ERR_INT, 0xffffffff); 34208bb61306SVille Syrjälä 3421fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3422fc340442SDaniel Vetter I915_WRITE(EDP_PSR_IMR, 0xffffffff); 3423fc340442SDaniel Vetter I915_WRITE(EDP_PSR_IIR, 0xffffffff); 3424fc340442SDaniel Vetter } 3425fc340442SDaniel Vetter 3426b243f530STvrtko Ursulin gen5_gt_irq_reset(dev_priv); 34278bb61306SVille Syrjälä 3428b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 34298bb61306SVille Syrjälä } 34308bb61306SVille Syrjälä 34316bcdb1c8SVille Syrjälä static void valleyview_irq_reset(struct drm_device *dev) 34327e231dbeSJesse Barnes { 3433fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 34347e231dbeSJesse Barnes 343534c7b8a7SVille Syrjälä I915_WRITE(VLV_MASTER_IER, 0); 343634c7b8a7SVille Syrjälä POSTING_READ(VLV_MASTER_IER); 343734c7b8a7SVille Syrjälä 3438b243f530STvrtko Ursulin gen5_gt_irq_reset(dev_priv); 34397e231dbeSJesse Barnes 3440ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 34419918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 344270591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3443ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 34447e231dbeSJesse Barnes } 34457e231dbeSJesse Barnes 3446d6e3cca3SDaniel Vetter static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv) 3447d6e3cca3SDaniel Vetter { 3448d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 0); 3449d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 1); 3450d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 2); 3451d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 3); 3452d6e3cca3SDaniel Vetter } 3453d6e3cca3SDaniel Vetter 3454823f6b38SPaulo Zanoni static void gen8_irq_reset(struct drm_device *dev) 3455abd58f01SBen Widawsky { 3456fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3457abd58f01SBen Widawsky int pipe; 3458abd58f01SBen Widawsky 345925286aacSDaniele Ceraolo Spurio gen8_master_intr_disable(dev_priv->uncore.regs); 3460abd58f01SBen Widawsky 3461d6e3cca3SDaniel Vetter gen8_gt_irq_reset(dev_priv); 3462abd58f01SBen Widawsky 3463e04f7eceSVille Syrjälä I915_WRITE(EDP_PSR_IMR, 0xffffffff); 3464e04f7eceSVille Syrjälä I915_WRITE(EDP_PSR_IIR, 0xffffffff); 3465e04f7eceSVille Syrjälä 3466055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 3467f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3468813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3469f86f3fb0SPaulo Zanoni GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); 3470abd58f01SBen Widawsky 34713488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_DE_PORT_); 34723488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_DE_MISC_); 34733488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_PCU_); 3474abd58f01SBen Widawsky 34756e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 3476b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 3477abd58f01SBen Widawsky } 3478abd58f01SBen Widawsky 347951951ae7SMika Kuoppala static void gen11_gt_irq_reset(struct drm_i915_private *dev_priv) 348051951ae7SMika Kuoppala { 348151951ae7SMika Kuoppala /* Disable RCS, BCS, VCS and VECS class engines. */ 348251951ae7SMika Kuoppala I915_WRITE(GEN11_RENDER_COPY_INTR_ENABLE, 0); 348351951ae7SMika Kuoppala I915_WRITE(GEN11_VCS_VECS_INTR_ENABLE, 0); 348451951ae7SMika Kuoppala 348551951ae7SMika Kuoppala /* Restore masks irqs on RCS, BCS, VCS and VECS engines. */ 348651951ae7SMika Kuoppala I915_WRITE(GEN11_RCS0_RSVD_INTR_MASK, ~0); 348751951ae7SMika Kuoppala I915_WRITE(GEN11_BCS_RSVD_INTR_MASK, ~0); 348851951ae7SMika Kuoppala I915_WRITE(GEN11_VCS0_VCS1_INTR_MASK, ~0); 348951951ae7SMika Kuoppala I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~0); 349051951ae7SMika Kuoppala I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~0); 3491d02b98b8SOscar Mateo 3492d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); 3493d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); 349451951ae7SMika Kuoppala } 349551951ae7SMika Kuoppala 349651951ae7SMika Kuoppala static void gen11_irq_reset(struct drm_device *dev) 349751951ae7SMika Kuoppala { 349851951ae7SMika Kuoppala struct drm_i915_private *dev_priv = dev->dev_private; 349951951ae7SMika Kuoppala int pipe; 350051951ae7SMika Kuoppala 350125286aacSDaniele Ceraolo Spurio gen11_master_intr_disable(dev_priv->uncore.regs); 350251951ae7SMika Kuoppala 350351951ae7SMika Kuoppala gen11_gt_irq_reset(dev_priv); 350451951ae7SMika Kuoppala 350551951ae7SMika Kuoppala I915_WRITE(GEN11_DISPLAY_INT_CTL, 0); 350651951ae7SMika Kuoppala 350762819dfdSJosé Roberto de Souza I915_WRITE(EDP_PSR_IMR, 0xffffffff); 350862819dfdSJosé Roberto de Souza I915_WRITE(EDP_PSR_IIR, 0xffffffff); 350962819dfdSJosé Roberto de Souza 351051951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 351151951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 351251951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 351351951ae7SMika Kuoppala GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); 351451951ae7SMika Kuoppala 351551951ae7SMika Kuoppala GEN3_IRQ_RESET(GEN8_DE_PORT_); 351651951ae7SMika Kuoppala GEN3_IRQ_RESET(GEN8_DE_MISC_); 3517121e758eSDhinakaran Pandiyan GEN3_IRQ_RESET(GEN11_DE_HPD_); 3518df0d28c1SDhinakaran Pandiyan GEN3_IRQ_RESET(GEN11_GU_MISC_); 351951951ae7SMika Kuoppala GEN3_IRQ_RESET(GEN8_PCU_); 352031604222SAnusha Srivatsa 352129b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 352231604222SAnusha Srivatsa GEN3_IRQ_RESET(SDE); 352351951ae7SMika Kuoppala } 352451951ae7SMika Kuoppala 35254c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 3526001bd2cbSImre Deak u8 pipe_mask) 3527d49bdb0eSPaulo Zanoni { 3528a9c287c9SJani Nikula u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; 35296831f3e3SVille Syrjälä enum pipe pipe; 3530d49bdb0eSPaulo Zanoni 353113321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 35329dfe2e3aSImre Deak 35339dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 35349dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 35359dfe2e3aSImre Deak return; 35369dfe2e3aSImre Deak } 35379dfe2e3aSImre Deak 35386831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 35396831f3e3SVille Syrjälä GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, 35406831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 35416831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 35429dfe2e3aSImre Deak 354313321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3544d49bdb0eSPaulo Zanoni } 3545d49bdb0eSPaulo Zanoni 3546aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 3547001bd2cbSImre Deak u8 pipe_mask) 3548aae8ba84SVille Syrjälä { 35496831f3e3SVille Syrjälä enum pipe pipe; 35506831f3e3SVille Syrjälä 3551aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 35529dfe2e3aSImre Deak 35539dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 35549dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 35559dfe2e3aSImre Deak return; 35569dfe2e3aSImre Deak } 35579dfe2e3aSImre Deak 35586831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 35596831f3e3SVille Syrjälä GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); 35609dfe2e3aSImre Deak 3561aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3562aae8ba84SVille Syrjälä 3563aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 356491c8a326SChris Wilson synchronize_irq(dev_priv->drm.irq); 3565aae8ba84SVille Syrjälä } 3566aae8ba84SVille Syrjälä 35676bcdb1c8SVille Syrjälä static void cherryview_irq_reset(struct drm_device *dev) 356843f328d7SVille Syrjälä { 3569fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 357043f328d7SVille Syrjälä 357143f328d7SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, 0); 357243f328d7SVille Syrjälä POSTING_READ(GEN8_MASTER_IRQ); 357343f328d7SVille Syrjälä 3574d6e3cca3SDaniel Vetter gen8_gt_irq_reset(dev_priv); 357543f328d7SVille Syrjälä 35763488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_PCU_); 357743f328d7SVille Syrjälä 3578ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 35799918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 358070591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3581ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 358243f328d7SVille Syrjälä } 358343f328d7SVille Syrjälä 358491d14251STvrtko Ursulin static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, 358587a02106SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 358687a02106SVille Syrjälä { 358787a02106SVille Syrjälä struct intel_encoder *encoder; 358887a02106SVille Syrjälä u32 enabled_irqs = 0; 358987a02106SVille Syrjälä 359091c8a326SChris Wilson for_each_intel_encoder(&dev_priv->drm, encoder) 359187a02106SVille Syrjälä if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) 359287a02106SVille Syrjälä enabled_irqs |= hpd[encoder->hpd_pin]; 359387a02106SVille Syrjälä 359487a02106SVille Syrjälä return enabled_irqs; 359587a02106SVille Syrjälä } 359687a02106SVille Syrjälä 35971a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) 35981a56b1a2SImre Deak { 35991a56b1a2SImre Deak u32 hotplug; 36001a56b1a2SImre Deak 36011a56b1a2SImre Deak /* 36021a56b1a2SImre Deak * Enable digital hotplug on the PCH, and configure the DP short pulse 36031a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec). 36041a56b1a2SImre Deak * The pulse duration bits are reserved on LPT+. 36051a56b1a2SImre Deak */ 36061a56b1a2SImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG); 36071a56b1a2SImre Deak hotplug &= ~(PORTB_PULSE_DURATION_MASK | 36081a56b1a2SImre Deak PORTC_PULSE_DURATION_MASK | 36091a56b1a2SImre Deak PORTD_PULSE_DURATION_MASK); 36101a56b1a2SImre Deak hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms; 36111a56b1a2SImre Deak hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms; 36121a56b1a2SImre Deak hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms; 36131a56b1a2SImre Deak /* 36141a56b1a2SImre Deak * When CPU and PCH are on the same package, port A 36151a56b1a2SImre Deak * HPD must be enabled in both north and south. 36161a56b1a2SImre Deak */ 36171a56b1a2SImre Deak if (HAS_PCH_LPT_LP(dev_priv)) 36181a56b1a2SImre Deak hotplug |= PORTA_HOTPLUG_ENABLE; 36191a56b1a2SImre Deak I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 36201a56b1a2SImre Deak } 36211a56b1a2SImre Deak 362291d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) 362382a28bcfSDaniel Vetter { 36241a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 362582a28bcfSDaniel Vetter 362691d14251STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) { 3627fee884edSDaniel Vetter hotplug_irqs = SDE_HOTPLUG_MASK; 362891d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ibx); 362982a28bcfSDaniel Vetter } else { 3630fee884edSDaniel Vetter hotplug_irqs = SDE_HOTPLUG_MASK_CPT; 363191d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_cpt); 363282a28bcfSDaniel Vetter } 363382a28bcfSDaniel Vetter 3634fee884edSDaniel Vetter ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 363582a28bcfSDaniel Vetter 36361a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 36376dbf30ceSVille Syrjälä } 363826951cafSXiong Zhang 363931604222SAnusha Srivatsa static void icp_hpd_detection_setup(struct drm_i915_private *dev_priv) 364031604222SAnusha Srivatsa { 364131604222SAnusha Srivatsa u32 hotplug; 364231604222SAnusha Srivatsa 364331604222SAnusha Srivatsa hotplug = I915_READ(SHOTPLUG_CTL_DDI); 364431604222SAnusha Srivatsa hotplug |= ICP_DDIA_HPD_ENABLE | 364531604222SAnusha Srivatsa ICP_DDIB_HPD_ENABLE; 364631604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_DDI, hotplug); 364731604222SAnusha Srivatsa 364831604222SAnusha Srivatsa hotplug = I915_READ(SHOTPLUG_CTL_TC); 364931604222SAnusha Srivatsa hotplug |= ICP_TC_HPD_ENABLE(PORT_TC1) | 365031604222SAnusha Srivatsa ICP_TC_HPD_ENABLE(PORT_TC2) | 365131604222SAnusha Srivatsa ICP_TC_HPD_ENABLE(PORT_TC3) | 365231604222SAnusha Srivatsa ICP_TC_HPD_ENABLE(PORT_TC4); 365331604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_TC, hotplug); 365431604222SAnusha Srivatsa } 365531604222SAnusha Srivatsa 365631604222SAnusha Srivatsa static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) 365731604222SAnusha Srivatsa { 365831604222SAnusha Srivatsa u32 hotplug_irqs, enabled_irqs; 365931604222SAnusha Srivatsa 366031604222SAnusha Srivatsa hotplug_irqs = SDE_DDI_MASK_ICP | SDE_TC_MASK_ICP; 366131604222SAnusha Srivatsa enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_icp); 366231604222SAnusha Srivatsa 366331604222SAnusha Srivatsa ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 366431604222SAnusha Srivatsa 366531604222SAnusha Srivatsa icp_hpd_detection_setup(dev_priv); 366631604222SAnusha Srivatsa } 366731604222SAnusha Srivatsa 3668121e758eSDhinakaran Pandiyan static void gen11_hpd_detection_setup(struct drm_i915_private *dev_priv) 3669121e758eSDhinakaran Pandiyan { 3670121e758eSDhinakaran Pandiyan u32 hotplug; 3671121e758eSDhinakaran Pandiyan 3672121e758eSDhinakaran Pandiyan hotplug = I915_READ(GEN11_TC_HOTPLUG_CTL); 3673121e758eSDhinakaran Pandiyan hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | 3674121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | 3675121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | 3676121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); 3677121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_TC_HOTPLUG_CTL, hotplug); 3678b796b971SDhinakaran Pandiyan 3679b796b971SDhinakaran Pandiyan hotplug = I915_READ(GEN11_TBT_HOTPLUG_CTL); 3680b796b971SDhinakaran Pandiyan hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | 3681b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | 3682b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | 3683b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); 3684b796b971SDhinakaran Pandiyan I915_WRITE(GEN11_TBT_HOTPLUG_CTL, hotplug); 3685121e758eSDhinakaran Pandiyan } 3686121e758eSDhinakaran Pandiyan 3687121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) 3688121e758eSDhinakaran Pandiyan { 3689121e758eSDhinakaran Pandiyan u32 hotplug_irqs, enabled_irqs; 3690121e758eSDhinakaran Pandiyan u32 val; 3691121e758eSDhinakaran Pandiyan 3692b796b971SDhinakaran Pandiyan enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_gen11); 3693b796b971SDhinakaran Pandiyan hotplug_irqs = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; 3694121e758eSDhinakaran Pandiyan 3695121e758eSDhinakaran Pandiyan val = I915_READ(GEN11_DE_HPD_IMR); 3696121e758eSDhinakaran Pandiyan val &= ~hotplug_irqs; 3697121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_DE_HPD_IMR, val); 3698121e758eSDhinakaran Pandiyan POSTING_READ(GEN11_DE_HPD_IMR); 3699121e758eSDhinakaran Pandiyan 3700121e758eSDhinakaran Pandiyan gen11_hpd_detection_setup(dev_priv); 370131604222SAnusha Srivatsa 370229b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 370331604222SAnusha Srivatsa icp_hpd_irq_setup(dev_priv); 3704121e758eSDhinakaran Pandiyan } 3705121e758eSDhinakaran Pandiyan 37062a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) 37072a57d9ccSImre Deak { 37083b92e263SRodrigo Vivi u32 val, hotplug; 37093b92e263SRodrigo Vivi 37103b92e263SRodrigo Vivi /* Display WA #1179 WaHardHangonHotPlug: cnp */ 37113b92e263SRodrigo Vivi if (HAS_PCH_CNP(dev_priv)) { 37123b92e263SRodrigo Vivi val = I915_READ(SOUTH_CHICKEN1); 37133b92e263SRodrigo Vivi val &= ~CHASSIS_CLK_REQ_DURATION_MASK; 37143b92e263SRodrigo Vivi val |= CHASSIS_CLK_REQ_DURATION(0xf); 37153b92e263SRodrigo Vivi I915_WRITE(SOUTH_CHICKEN1, val); 37163b92e263SRodrigo Vivi } 37172a57d9ccSImre Deak 37182a57d9ccSImre Deak /* Enable digital hotplug on the PCH */ 37192a57d9ccSImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG); 37202a57d9ccSImre Deak hotplug |= PORTA_HOTPLUG_ENABLE | 37212a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 37222a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE | 37232a57d9ccSImre Deak PORTD_HOTPLUG_ENABLE; 37242a57d9ccSImre Deak I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 37252a57d9ccSImre Deak 37262a57d9ccSImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG2); 37272a57d9ccSImre Deak hotplug |= PORTE_HOTPLUG_ENABLE; 37282a57d9ccSImre Deak I915_WRITE(PCH_PORT_HOTPLUG2, hotplug); 37292a57d9ccSImre Deak } 37302a57d9ccSImre Deak 373191d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) 37326dbf30ceSVille Syrjälä { 37332a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 37346dbf30ceSVille Syrjälä 37356dbf30ceSVille Syrjälä hotplug_irqs = SDE_HOTPLUG_MASK_SPT; 373691d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_spt); 37376dbf30ceSVille Syrjälä 37386dbf30ceSVille Syrjälä ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 37396dbf30ceSVille Syrjälä 37402a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 374126951cafSXiong Zhang } 37427fe0b973SKeith Packard 37431a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) 37441a56b1a2SImre Deak { 37451a56b1a2SImre Deak u32 hotplug; 37461a56b1a2SImre Deak 37471a56b1a2SImre Deak /* 37481a56b1a2SImre Deak * Enable digital hotplug on the CPU, and configure the DP short pulse 37491a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec) 37501a56b1a2SImre Deak * The pulse duration bits are reserved on HSW+. 37511a56b1a2SImre Deak */ 37521a56b1a2SImre Deak hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); 37531a56b1a2SImre Deak hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK; 37541a56b1a2SImre Deak hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | 37551a56b1a2SImre Deak DIGITAL_PORTA_PULSE_DURATION_2ms; 37561a56b1a2SImre Deak I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); 37571a56b1a2SImre Deak } 37581a56b1a2SImre Deak 375991d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) 3760e4ce95aaSVille Syrjälä { 37611a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 3762e4ce95aaSVille Syrjälä 376391d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 8) { 37643a3b3c7dSVille Syrjälä hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG; 376591d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bdw); 37663a3b3c7dSVille Syrjälä 37673a3b3c7dSVille Syrjälä bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 376891d14251STvrtko Ursulin } else if (INTEL_GEN(dev_priv) >= 7) { 376923bb4cb5SVille Syrjälä hotplug_irqs = DE_DP_A_HOTPLUG_IVB; 377091d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ivb); 37713a3b3c7dSVille Syrjälä 37723a3b3c7dSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 377323bb4cb5SVille Syrjälä } else { 3774e4ce95aaSVille Syrjälä hotplug_irqs = DE_DP_A_HOTPLUG; 377591d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ilk); 3776e4ce95aaSVille Syrjälä 3777e4ce95aaSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 37783a3b3c7dSVille Syrjälä } 3779e4ce95aaSVille Syrjälä 37801a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3781e4ce95aaSVille Syrjälä 378291d14251STvrtko Ursulin ibx_hpd_irq_setup(dev_priv); 3783e4ce95aaSVille Syrjälä } 3784e4ce95aaSVille Syrjälä 37852a57d9ccSImre Deak static void __bxt_hpd_detection_setup(struct drm_i915_private *dev_priv, 37862a57d9ccSImre Deak u32 enabled_irqs) 3787e0a20ad7SShashank Sharma { 37882a57d9ccSImre Deak u32 hotplug; 3789e0a20ad7SShashank Sharma 3790a52bb15bSVille Syrjälä hotplug = I915_READ(PCH_PORT_HOTPLUG); 37912a57d9ccSImre Deak hotplug |= PORTA_HOTPLUG_ENABLE | 37922a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 37932a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE; 3794d252bf68SShubhangi Shrivastava 3795d252bf68SShubhangi Shrivastava DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n", 3796d252bf68SShubhangi Shrivastava hotplug, enabled_irqs); 3797d252bf68SShubhangi Shrivastava hotplug &= ~BXT_DDI_HPD_INVERT_MASK; 3798d252bf68SShubhangi Shrivastava 3799d252bf68SShubhangi Shrivastava /* 3800d252bf68SShubhangi Shrivastava * For BXT invert bit has to be set based on AOB design 3801d252bf68SShubhangi Shrivastava * for HPD detection logic, update it based on VBT fields. 3802d252bf68SShubhangi Shrivastava */ 3803d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) && 3804d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_A)) 3805d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIA_HPD_INVERT; 3806d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && 3807d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_B)) 3808d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIB_HPD_INVERT; 3809d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && 3810d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_C)) 3811d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIC_HPD_INVERT; 3812d252bf68SShubhangi Shrivastava 3813a52bb15bSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 3814e0a20ad7SShashank Sharma } 3815e0a20ad7SShashank Sharma 38162a57d9ccSImre Deak static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) 38172a57d9ccSImre Deak { 38182a57d9ccSImre Deak __bxt_hpd_detection_setup(dev_priv, BXT_DE_PORT_HOTPLUG_MASK); 38192a57d9ccSImre Deak } 38202a57d9ccSImre Deak 38212a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) 38222a57d9ccSImre Deak { 38232a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 38242a57d9ccSImre Deak 38252a57d9ccSImre Deak enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bxt); 38262a57d9ccSImre Deak hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK; 38272a57d9ccSImre Deak 38282a57d9ccSImre Deak bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 38292a57d9ccSImre Deak 38302a57d9ccSImre Deak __bxt_hpd_detection_setup(dev_priv, enabled_irqs); 38312a57d9ccSImre Deak } 38322a57d9ccSImre Deak 3833d46da437SPaulo Zanoni static void ibx_irq_postinstall(struct drm_device *dev) 3834d46da437SPaulo Zanoni { 3835fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 383682a28bcfSDaniel Vetter u32 mask; 3837d46da437SPaulo Zanoni 38386e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3839692a04cfSDaniel Vetter return; 3840692a04cfSDaniel Vetter 38416e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 38425c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 38434ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 38445c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 38454ebc6509SDhinakaran Pandiyan else 38464ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 38478664281bSPaulo Zanoni 38483488d4ebSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, SDEIIR); 3849d46da437SPaulo Zanoni I915_WRITE(SDEIMR, ~mask); 38502a57d9ccSImre Deak 38512a57d9ccSImre Deak if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || 38522a57d9ccSImre Deak HAS_PCH_LPT(dev_priv)) 38531a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 38542a57d9ccSImre Deak else 38552a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 3856d46da437SPaulo Zanoni } 3857d46da437SPaulo Zanoni 38580a9a8c91SDaniel Vetter static void gen5_gt_irq_postinstall(struct drm_device *dev) 38590a9a8c91SDaniel Vetter { 3860fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 38610a9a8c91SDaniel Vetter u32 pm_irqs, gt_irqs; 38620a9a8c91SDaniel Vetter 38630a9a8c91SDaniel Vetter pm_irqs = gt_irqs = 0; 38640a9a8c91SDaniel Vetter 38650a9a8c91SDaniel Vetter dev_priv->gt_irq_mask = ~0; 38663c9192bcSTvrtko Ursulin if (HAS_L3_DPF(dev_priv)) { 38670a9a8c91SDaniel Vetter /* L3 parity interrupt is always unmasked. */ 3868772c2a51STvrtko Ursulin dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev_priv); 3869772c2a51STvrtko Ursulin gt_irqs |= GT_PARITY_ERROR(dev_priv); 38700a9a8c91SDaniel Vetter } 38710a9a8c91SDaniel Vetter 38720a9a8c91SDaniel Vetter gt_irqs |= GT_RENDER_USER_INTERRUPT; 3873cf819effSLucas De Marchi if (IS_GEN(dev_priv, 5)) { 3874f8973c21SChris Wilson gt_irqs |= ILK_BSD_USER_INTERRUPT; 38750a9a8c91SDaniel Vetter } else { 38760a9a8c91SDaniel Vetter gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; 38770a9a8c91SDaniel Vetter } 38780a9a8c91SDaniel Vetter 38793488d4ebSVille Syrjälä GEN3_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); 38800a9a8c91SDaniel Vetter 3881b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) { 388278e68d36SImre Deak /* 388378e68d36SImre Deak * RPS interrupts will get enabled/disabled on demand when RPS 388478e68d36SImre Deak * itself is enabled/disabled. 388578e68d36SImre Deak */ 38868a68d464SChris Wilson if (HAS_ENGINE(dev_priv, VECS0)) { 38870a9a8c91SDaniel Vetter pm_irqs |= PM_VEBOX_USER_INTERRUPT; 3888f4e9af4fSAkash Goel dev_priv->pm_ier |= PM_VEBOX_USER_INTERRUPT; 3889f4e9af4fSAkash Goel } 38900a9a8c91SDaniel Vetter 3891f4e9af4fSAkash Goel dev_priv->pm_imr = 0xffffffff; 38923488d4ebSVille Syrjälä GEN3_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); 38930a9a8c91SDaniel Vetter } 38940a9a8c91SDaniel Vetter } 38950a9a8c91SDaniel Vetter 3896f71d4af4SJesse Barnes static int ironlake_irq_postinstall(struct drm_device *dev) 3897036a4a7dSZhenyu Wang { 3898fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 38998e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 39008e76f8dcSPaulo Zanoni 3901b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 7) { 39028e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 3903842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 39048e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 390523bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 390623bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 39078e76f8dcSPaulo Zanoni } else { 39088e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 3909842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 3910842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 3911e4ce95aaSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | 3912e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 3913e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 39148e76f8dcSPaulo Zanoni } 3915036a4a7dSZhenyu Wang 3916fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3917fc340442SDaniel Vetter gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); 39181aeb1b5fSDhinakaran Pandiyan intel_psr_irq_control(dev_priv, dev_priv->psr.debug); 3919fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 3920fc340442SDaniel Vetter } 3921fc340442SDaniel Vetter 39221ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 3923036a4a7dSZhenyu Wang 3924622364b6SPaulo Zanoni ibx_irq_pre_postinstall(dev); 3925622364b6SPaulo Zanoni 39263488d4ebSVille Syrjälä GEN3_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); 3927036a4a7dSZhenyu Wang 39280a9a8c91SDaniel Vetter gen5_gt_irq_postinstall(dev); 3929036a4a7dSZhenyu Wang 39301a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 39311a56b1a2SImre Deak 3932d46da437SPaulo Zanoni ibx_irq_postinstall(dev); 39337fe0b973SKeith Packard 393450a0bc90STvrtko Ursulin if (IS_IRONLAKE_M(dev_priv)) { 39356005ce42SDaniel Vetter /* Enable PCU event interrupts 39366005ce42SDaniel Vetter * 39376005ce42SDaniel Vetter * spinlocking not required here for correctness since interrupt 39384bc9d430SDaniel Vetter * setup is guaranteed to run in single-threaded context. But we 39394bc9d430SDaniel Vetter * need it to make the assert_spin_locked happy. */ 3940d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3941fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, DE_PCU_EVENT); 3942d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3943f97108d1SJesse Barnes } 3944f97108d1SJesse Barnes 3945036a4a7dSZhenyu Wang return 0; 3946036a4a7dSZhenyu Wang } 3947036a4a7dSZhenyu Wang 3948f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 3949f8b79e58SImre Deak { 395067520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3951f8b79e58SImre Deak 3952f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 3953f8b79e58SImre Deak return; 3954f8b79e58SImre Deak 3955f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 3956f8b79e58SImre Deak 3957d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 3958d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 3959ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3960f8b79e58SImre Deak } 3961d6c69803SVille Syrjälä } 3962f8b79e58SImre Deak 3963f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 3964f8b79e58SImre Deak { 396567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3966f8b79e58SImre Deak 3967f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 3968f8b79e58SImre Deak return; 3969f8b79e58SImre Deak 3970f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 3971f8b79e58SImre Deak 3972950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 3973ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 3974f8b79e58SImre Deak } 3975f8b79e58SImre Deak 39760e6c9a9eSVille Syrjälä 39770e6c9a9eSVille Syrjälä static int valleyview_irq_postinstall(struct drm_device *dev) 39780e6c9a9eSVille Syrjälä { 3979fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 39800e6c9a9eSVille Syrjälä 39810a9a8c91SDaniel Vetter gen5_gt_irq_postinstall(dev); 39827e231dbeSJesse Barnes 3983ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 39849918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3985ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3986ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3987ad22d106SVille Syrjälä 39887e231dbeSJesse Barnes I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 398934c7b8a7SVille Syrjälä POSTING_READ(VLV_MASTER_IER); 399020afbda2SDaniel Vetter 399120afbda2SDaniel Vetter return 0; 399220afbda2SDaniel Vetter } 399320afbda2SDaniel Vetter 3994abd58f01SBen Widawsky static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) 3995abd58f01SBen Widawsky { 3996abd58f01SBen Widawsky /* These are interrupts we'll toggle with the ring mask register */ 3997a9c287c9SJani Nikula u32 gt_interrupts[] = { 39988a68d464SChris Wilson (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | 399973d477f6SOscar Mateo GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | 400073d477f6SOscar Mateo GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT | 40018a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT), 40028a68d464SChris Wilson 40038a68d464SChris Wilson (GT_RENDER_USER_INTERRUPT << GEN8_VCS0_IRQ_SHIFT | 40048a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS0_IRQ_SHIFT | 4005abd58f01SBen Widawsky GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT | 40068a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT), 40078a68d464SChris Wilson 4008abd58f01SBen Widawsky 0, 40098a68d464SChris Wilson 40108a68d464SChris Wilson (GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT | 40118a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT) 4012abd58f01SBen Widawsky }; 4013abd58f01SBen Widawsky 4014f4e9af4fSAkash Goel dev_priv->pm_ier = 0x0; 4015f4e9af4fSAkash Goel dev_priv->pm_imr = ~dev_priv->pm_ier; 40169a2d2d87SDeepak S GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); 40179a2d2d87SDeepak S GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); 401878e68d36SImre Deak /* 401978e68d36SImre Deak * RPS interrupts will get enabled/disabled on demand when RPS itself 402026705e20SSagar Arun Kamble * is enabled/disabled. Same wil be the case for GuC interrupts. 402178e68d36SImre Deak */ 4022f4e9af4fSAkash Goel GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_imr, dev_priv->pm_ier); 40239a2d2d87SDeepak S GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); 4024abd58f01SBen Widawsky } 4025abd58f01SBen Widawsky 4026abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 4027abd58f01SBen Widawsky { 4028a9c287c9SJani Nikula u32 de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE; 4029a9c287c9SJani Nikula u32 de_pipe_enables; 40303a3b3c7dSVille Syrjälä u32 de_port_masked = GEN8_AUX_CHANNEL_A; 40313a3b3c7dSVille Syrjälä u32 de_port_enables; 4032df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 40333a3b3c7dSVille Syrjälä enum pipe pipe; 4034770de83dSDamien Lespiau 4035df0d28c1SDhinakaran Pandiyan if (INTEL_GEN(dev_priv) <= 10) 4036df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 4037df0d28c1SDhinakaran Pandiyan 4038bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 9) { 4039842ebf7aSVille Syrjälä de_pipe_masked |= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 40403a3b3c7dSVille Syrjälä de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | 404188e04703SJesse Barnes GEN9_AUX_CHANNEL_D; 4042cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 40433a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 40443a3b3c7dSVille Syrjälä } else { 4045842ebf7aSVille Syrjälä de_pipe_masked |= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 40463a3b3c7dSVille Syrjälä } 4047770de83dSDamien Lespiau 4048bb187e93SJames Ausmus if (INTEL_GEN(dev_priv) >= 11) 4049bb187e93SJames Ausmus de_port_masked |= ICL_AUX_CHANNEL_E; 4050bb187e93SJames Ausmus 40519bb635d9SDhinakaran Pandiyan if (IS_CNL_WITH_PORT_F(dev_priv) || INTEL_GEN(dev_priv) >= 11) 4052a324fcacSRodrigo Vivi de_port_masked |= CNL_AUX_CHANNEL_F; 4053a324fcacSRodrigo Vivi 4054770de83dSDamien Lespiau de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | 4055770de83dSDamien Lespiau GEN8_PIPE_FIFO_UNDERRUN; 4056770de83dSDamien Lespiau 40573a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 4058cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 4059a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 4060a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 40613a3b3c7dSVille Syrjälä de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; 40623a3b3c7dSVille Syrjälä 4063e04f7eceSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); 406454fd3149SDhinakaran Pandiyan intel_psr_irq_control(dev_priv, dev_priv->psr.debug); 4065e04f7eceSVille Syrjälä 40660a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 40670a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 4068abd58f01SBen Widawsky 4069f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 4070813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 4071813bde43SPaulo Zanoni GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, 4072813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 407335079899SPaulo Zanoni de_pipe_enables); 40740a195c02SMika Kahola } 4075abd58f01SBen Widawsky 40763488d4ebSVille Syrjälä GEN3_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 40773488d4ebSVille Syrjälä GEN3_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 40782a57d9ccSImre Deak 4079121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11) { 4080121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 4081b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 4082b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 4083121e758eSDhinakaran Pandiyan 4084121e758eSDhinakaran Pandiyan GEN3_IRQ_INIT(GEN11_DE_HPD_, ~de_hpd_masked, de_hpd_enables); 4085121e758eSDhinakaran Pandiyan gen11_hpd_detection_setup(dev_priv); 4086121e758eSDhinakaran Pandiyan } else if (IS_GEN9_LP(dev_priv)) { 40872a57d9ccSImre Deak bxt_hpd_detection_setup(dev_priv); 4088121e758eSDhinakaran Pandiyan } else if (IS_BROADWELL(dev_priv)) { 40891a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 4090abd58f01SBen Widawsky } 4091121e758eSDhinakaran Pandiyan } 4092abd58f01SBen Widawsky 4093abd58f01SBen Widawsky static int gen8_irq_postinstall(struct drm_device *dev) 4094abd58f01SBen Widawsky { 4095fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4096abd58f01SBen Widawsky 40976e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 4098622364b6SPaulo Zanoni ibx_irq_pre_postinstall(dev); 4099622364b6SPaulo Zanoni 4100abd58f01SBen Widawsky gen8_gt_irq_postinstall(dev_priv); 4101abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 4102abd58f01SBen Widawsky 41036e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 4104abd58f01SBen Widawsky ibx_irq_postinstall(dev); 4105abd58f01SBen Widawsky 410625286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 4107abd58f01SBen Widawsky 4108abd58f01SBen Widawsky return 0; 4109abd58f01SBen Widawsky } 4110abd58f01SBen Widawsky 411151951ae7SMika Kuoppala static void gen11_gt_irq_postinstall(struct drm_i915_private *dev_priv) 411251951ae7SMika Kuoppala { 411351951ae7SMika Kuoppala const u32 irqs = GT_RENDER_USER_INTERRUPT | GT_CONTEXT_SWITCH_INTERRUPT; 411451951ae7SMika Kuoppala 411551951ae7SMika Kuoppala BUILD_BUG_ON(irqs & 0xffff0000); 411651951ae7SMika Kuoppala 411751951ae7SMika Kuoppala /* Enable RCS, BCS, VCS and VECS class interrupts. */ 411851951ae7SMika Kuoppala I915_WRITE(GEN11_RENDER_COPY_INTR_ENABLE, irqs << 16 | irqs); 411951951ae7SMika Kuoppala I915_WRITE(GEN11_VCS_VECS_INTR_ENABLE, irqs << 16 | irqs); 412051951ae7SMika Kuoppala 412151951ae7SMika Kuoppala /* Unmask irqs on RCS, BCS, VCS and VECS engines. */ 412251951ae7SMika Kuoppala I915_WRITE(GEN11_RCS0_RSVD_INTR_MASK, ~(irqs << 16)); 412351951ae7SMika Kuoppala I915_WRITE(GEN11_BCS_RSVD_INTR_MASK, ~(irqs << 16)); 412451951ae7SMika Kuoppala I915_WRITE(GEN11_VCS0_VCS1_INTR_MASK, ~(irqs | irqs << 16)); 412551951ae7SMika Kuoppala I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~(irqs | irqs << 16)); 412651951ae7SMika Kuoppala I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~(irqs | irqs << 16)); 412751951ae7SMika Kuoppala 4128d02b98b8SOscar Mateo /* 4129d02b98b8SOscar Mateo * RPS interrupts will get enabled/disabled on demand when RPS itself 4130d02b98b8SOscar Mateo * is enabled/disabled. 4131d02b98b8SOscar Mateo */ 4132d02b98b8SOscar Mateo dev_priv->pm_ier = 0x0; 4133d02b98b8SOscar Mateo dev_priv->pm_imr = ~dev_priv->pm_ier; 4134d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); 4135d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); 413651951ae7SMika Kuoppala } 413751951ae7SMika Kuoppala 413831604222SAnusha Srivatsa static void icp_irq_postinstall(struct drm_device *dev) 413931604222SAnusha Srivatsa { 414031604222SAnusha Srivatsa struct drm_i915_private *dev_priv = to_i915(dev); 414131604222SAnusha Srivatsa u32 mask = SDE_GMBUS_ICP; 414231604222SAnusha Srivatsa 414331604222SAnusha Srivatsa WARN_ON(I915_READ(SDEIER) != 0); 414431604222SAnusha Srivatsa I915_WRITE(SDEIER, 0xffffffff); 414531604222SAnusha Srivatsa POSTING_READ(SDEIER); 414631604222SAnusha Srivatsa 414731604222SAnusha Srivatsa gen3_assert_iir_is_zero(dev_priv, SDEIIR); 414831604222SAnusha Srivatsa I915_WRITE(SDEIMR, ~mask); 414931604222SAnusha Srivatsa 415031604222SAnusha Srivatsa icp_hpd_detection_setup(dev_priv); 415131604222SAnusha Srivatsa } 415231604222SAnusha Srivatsa 415351951ae7SMika Kuoppala static int gen11_irq_postinstall(struct drm_device *dev) 415451951ae7SMika Kuoppala { 415551951ae7SMika Kuoppala struct drm_i915_private *dev_priv = dev->dev_private; 4156df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 415751951ae7SMika Kuoppala 415829b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 415931604222SAnusha Srivatsa icp_irq_postinstall(dev); 416031604222SAnusha Srivatsa 416151951ae7SMika Kuoppala gen11_gt_irq_postinstall(dev_priv); 416251951ae7SMika Kuoppala gen8_de_irq_postinstall(dev_priv); 416351951ae7SMika Kuoppala 4164df0d28c1SDhinakaran Pandiyan GEN3_IRQ_INIT(GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 4165df0d28c1SDhinakaran Pandiyan 416651951ae7SMika Kuoppala I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); 416751951ae7SMika Kuoppala 416825286aacSDaniele Ceraolo Spurio gen11_master_intr_enable(dev_priv->uncore.regs); 4169c25f0c6aSDaniele Ceraolo Spurio POSTING_READ(GEN11_GFX_MSTR_IRQ); 417051951ae7SMika Kuoppala 417151951ae7SMika Kuoppala return 0; 417251951ae7SMika Kuoppala } 417351951ae7SMika Kuoppala 417443f328d7SVille Syrjälä static int cherryview_irq_postinstall(struct drm_device *dev) 417543f328d7SVille Syrjälä { 4176fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 417743f328d7SVille Syrjälä 417843f328d7SVille Syrjälä gen8_gt_irq_postinstall(dev_priv); 417943f328d7SVille Syrjälä 4180ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 41819918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 4182ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 4183ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 4184ad22d106SVille Syrjälä 4185e5328c43SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 418643f328d7SVille Syrjälä POSTING_READ(GEN8_MASTER_IRQ); 418743f328d7SVille Syrjälä 418843f328d7SVille Syrjälä return 0; 418943f328d7SVille Syrjälä } 419043f328d7SVille Syrjälä 41916bcdb1c8SVille Syrjälä static void i8xx_irq_reset(struct drm_device *dev) 4192c2798b19SChris Wilson { 4193fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4194c2798b19SChris Wilson 419544d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 419644d9241eSVille Syrjälä 4197e9e9848aSVille Syrjälä GEN2_IRQ_RESET(); 4198c2798b19SChris Wilson } 4199c2798b19SChris Wilson 4200c2798b19SChris Wilson static int i8xx_irq_postinstall(struct drm_device *dev) 4201c2798b19SChris Wilson { 4202fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4203e9e9848aSVille Syrjälä u16 enable_mask; 4204c2798b19SChris Wilson 4205045cebd2SVille Syrjälä I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | 4206045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 4207c2798b19SChris Wilson 4208c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 4209c2798b19SChris Wilson dev_priv->irq_mask = 4210c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 421116659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 421216659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 4213c2798b19SChris Wilson 4214e9e9848aSVille Syrjälä enable_mask = 4215c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4216c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 421716659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 4218e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 4219e9e9848aSVille Syrjälä 4220e9e9848aSVille Syrjälä GEN2_IRQ_INIT(, dev_priv->irq_mask, enable_mask); 4221c2798b19SChris Wilson 4222379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4223379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4224d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4225755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4226755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4227d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4228379ef82dSDaniel Vetter 4229c2798b19SChris Wilson return 0; 4230c2798b19SChris Wilson } 4231c2798b19SChris Wilson 423278c357ddSVille Syrjälä static void i8xx_error_irq_ack(struct drm_i915_private *dev_priv, 423378c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 423478c357ddSVille Syrjälä { 423578c357ddSVille Syrjälä u16 emr; 423678c357ddSVille Syrjälä 423778c357ddSVille Syrjälä *eir = I915_READ16(EIR); 423878c357ddSVille Syrjälä 423978c357ddSVille Syrjälä if (*eir) 424078c357ddSVille Syrjälä I915_WRITE16(EIR, *eir); 424178c357ddSVille Syrjälä 424278c357ddSVille Syrjälä *eir_stuck = I915_READ16(EIR); 424378c357ddSVille Syrjälä if (*eir_stuck == 0) 424478c357ddSVille Syrjälä return; 424578c357ddSVille Syrjälä 424678c357ddSVille Syrjälä /* 424778c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 424878c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 424978c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 425078c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 425178c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 425278c357ddSVille Syrjälä * cleared except by handling the underlying error 425378c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 425478c357ddSVille Syrjälä * remains set. 425578c357ddSVille Syrjälä */ 425678c357ddSVille Syrjälä emr = I915_READ16(EMR); 425778c357ddSVille Syrjälä I915_WRITE16(EMR, 0xffff); 425878c357ddSVille Syrjälä I915_WRITE16(EMR, emr | *eir_stuck); 425978c357ddSVille Syrjälä } 426078c357ddSVille Syrjälä 426178c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 426278c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 426378c357ddSVille Syrjälä { 426478c357ddSVille Syrjälä DRM_DEBUG("Master Error: EIR 0x%04x\n", eir); 426578c357ddSVille Syrjälä 426678c357ddSVille Syrjälä if (eir_stuck) 426778c357ddSVille Syrjälä DRM_DEBUG_DRIVER("EIR stuck: 0x%04x, masked\n", eir_stuck); 426878c357ddSVille Syrjälä } 426978c357ddSVille Syrjälä 427078c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 427178c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 427278c357ddSVille Syrjälä { 427378c357ddSVille Syrjälä u32 emr; 427478c357ddSVille Syrjälä 427578c357ddSVille Syrjälä *eir = I915_READ(EIR); 427678c357ddSVille Syrjälä 427778c357ddSVille Syrjälä I915_WRITE(EIR, *eir); 427878c357ddSVille Syrjälä 427978c357ddSVille Syrjälä *eir_stuck = I915_READ(EIR); 428078c357ddSVille Syrjälä if (*eir_stuck == 0) 428178c357ddSVille Syrjälä return; 428278c357ddSVille Syrjälä 428378c357ddSVille Syrjälä /* 428478c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 428578c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 428678c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 428778c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 428878c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 428978c357ddSVille Syrjälä * cleared except by handling the underlying error 429078c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 429178c357ddSVille Syrjälä * remains set. 429278c357ddSVille Syrjälä */ 429378c357ddSVille Syrjälä emr = I915_READ(EMR); 429478c357ddSVille Syrjälä I915_WRITE(EMR, 0xffffffff); 429578c357ddSVille Syrjälä I915_WRITE(EMR, emr | *eir_stuck); 429678c357ddSVille Syrjälä } 429778c357ddSVille Syrjälä 429878c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 429978c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 430078c357ddSVille Syrjälä { 430178c357ddSVille Syrjälä DRM_DEBUG("Master Error, EIR 0x%08x\n", eir); 430278c357ddSVille Syrjälä 430378c357ddSVille Syrjälä if (eir_stuck) 430478c357ddSVille Syrjälä DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masked\n", eir_stuck); 430578c357ddSVille Syrjälä } 430678c357ddSVille Syrjälä 4307ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 4308c2798b19SChris Wilson { 430945a83f84SDaniel Vetter struct drm_device *dev = arg; 4310fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4311af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4312c2798b19SChris Wilson 43132dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 43142dd2a883SImre Deak return IRQ_NONE; 43152dd2a883SImre Deak 43161f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 43171f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 43181f814dacSImre Deak 4319af722d28SVille Syrjälä do { 4320af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 432178c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 4322af722d28SVille Syrjälä u16 iir; 4323af722d28SVille Syrjälä 4324c2798b19SChris Wilson iir = I915_READ16(IIR); 4325c2798b19SChris Wilson if (iir == 0) 4326af722d28SVille Syrjälä break; 4327c2798b19SChris Wilson 4328af722d28SVille Syrjälä ret = IRQ_HANDLED; 4329c2798b19SChris Wilson 4330eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4331eb64343cSVille Syrjälä * signalled in iir */ 4332eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4333c2798b19SChris Wilson 433478c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 433578c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 433678c357ddSVille Syrjälä 4337fd3a4024SDaniel Vetter I915_WRITE16(IIR, iir); 4338c2798b19SChris Wilson 4339c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 43408a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 4341c2798b19SChris Wilson 434278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 434378c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 4344af722d28SVille Syrjälä 4345eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4346af722d28SVille Syrjälä } while (0); 4347c2798b19SChris Wilson 43481f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 43491f814dacSImre Deak 43501f814dacSImre Deak return ret; 4351c2798b19SChris Wilson } 4352c2798b19SChris Wilson 43536bcdb1c8SVille Syrjälä static void i915_irq_reset(struct drm_device *dev) 4354a266c7d5SChris Wilson { 4355fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4356a266c7d5SChris Wilson 435756b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 43580706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 4359a266c7d5SChris Wilson I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 4360a266c7d5SChris Wilson } 4361a266c7d5SChris Wilson 436244d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 436344d9241eSVille Syrjälä 4364ba7eb789SVille Syrjälä GEN3_IRQ_RESET(); 4365a266c7d5SChris Wilson } 4366a266c7d5SChris Wilson 4367a266c7d5SChris Wilson static int i915_irq_postinstall(struct drm_device *dev) 4368a266c7d5SChris Wilson { 4369fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 437038bde180SChris Wilson u32 enable_mask; 4371a266c7d5SChris Wilson 4372045cebd2SVille Syrjälä I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | 4373045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 437438bde180SChris Wilson 437538bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 437638bde180SChris Wilson dev_priv->irq_mask = 437738bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 437838bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 437916659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 438016659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 438138bde180SChris Wilson 438238bde180SChris Wilson enable_mask = 438338bde180SChris Wilson I915_ASLE_INTERRUPT | 438438bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 438538bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 438616659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 438738bde180SChris Wilson I915_USER_INTERRUPT; 438838bde180SChris Wilson 438956b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 4390a266c7d5SChris Wilson /* Enable in IER... */ 4391a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 4392a266c7d5SChris Wilson /* and unmask in IMR */ 4393a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 4394a266c7d5SChris Wilson } 4395a266c7d5SChris Wilson 4396ba7eb789SVille Syrjälä GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); 4397a266c7d5SChris Wilson 4398379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4399379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4400d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4401755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4402755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4403d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4404379ef82dSDaniel Vetter 4405c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 4406c30bb1fdSVille Syrjälä 440720afbda2SDaniel Vetter return 0; 440820afbda2SDaniel Vetter } 440920afbda2SDaniel Vetter 4410ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 4411a266c7d5SChris Wilson { 441245a83f84SDaniel Vetter struct drm_device *dev = arg; 4413fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4414af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4415a266c7d5SChris Wilson 44162dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 44172dd2a883SImre Deak return IRQ_NONE; 44182dd2a883SImre Deak 44191f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 44201f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 44211f814dacSImre Deak 442238bde180SChris Wilson do { 4423eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 442478c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4425af722d28SVille Syrjälä u32 hotplug_status = 0; 4426af722d28SVille Syrjälä u32 iir; 4427a266c7d5SChris Wilson 4428af722d28SVille Syrjälä iir = I915_READ(IIR); 4429af722d28SVille Syrjälä if (iir == 0) 4430af722d28SVille Syrjälä break; 4431af722d28SVille Syrjälä 4432af722d28SVille Syrjälä ret = IRQ_HANDLED; 4433af722d28SVille Syrjälä 4434af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 4435af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 4436af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4437a266c7d5SChris Wilson 4438eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4439eb64343cSVille Syrjälä * signalled in iir */ 4440eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4441a266c7d5SChris Wilson 444278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 444378c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 444478c357ddSVille Syrjälä 4445fd3a4024SDaniel Vetter I915_WRITE(IIR, iir); 4446a266c7d5SChris Wilson 4447a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 44488a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 4449a266c7d5SChris Wilson 445078c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 445178c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4452a266c7d5SChris Wilson 4453af722d28SVille Syrjälä if (hotplug_status) 4454af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4455af722d28SVille Syrjälä 4456af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4457af722d28SVille Syrjälä } while (0); 4458a266c7d5SChris Wilson 44591f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 44601f814dacSImre Deak 4461a266c7d5SChris Wilson return ret; 4462a266c7d5SChris Wilson } 4463a266c7d5SChris Wilson 44646bcdb1c8SVille Syrjälä static void i965_irq_reset(struct drm_device *dev) 4465a266c7d5SChris Wilson { 4466fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4467a266c7d5SChris Wilson 44680706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 4469a266c7d5SChris Wilson I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 4470a266c7d5SChris Wilson 447144d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 447244d9241eSVille Syrjälä 4473ba7eb789SVille Syrjälä GEN3_IRQ_RESET(); 4474a266c7d5SChris Wilson } 4475a266c7d5SChris Wilson 4476a266c7d5SChris Wilson static int i965_irq_postinstall(struct drm_device *dev) 4477a266c7d5SChris Wilson { 4478fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4479bbba0a97SChris Wilson u32 enable_mask; 4480a266c7d5SChris Wilson u32 error_mask; 4481a266c7d5SChris Wilson 4482045cebd2SVille Syrjälä /* 4483045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 4484045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 4485045cebd2SVille Syrjälä */ 4486045cebd2SVille Syrjälä if (IS_G4X(dev_priv)) { 4487045cebd2SVille Syrjälä error_mask = ~(GM45_ERROR_PAGE_TABLE | 4488045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 4489045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 4490045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4491045cebd2SVille Syrjälä } else { 4492045cebd2SVille Syrjälä error_mask = ~(I915_ERROR_PAGE_TABLE | 4493045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4494045cebd2SVille Syrjälä } 4495045cebd2SVille Syrjälä I915_WRITE(EMR, error_mask); 4496045cebd2SVille Syrjälä 4497a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 4498c30bb1fdSVille Syrjälä dev_priv->irq_mask = 4499c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 4500adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 4501bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4502bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 450378c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 4504bbba0a97SChris Wilson 4505c30bb1fdSVille Syrjälä enable_mask = 4506c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 4507c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 4508c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4509c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 451078c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 4511c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 4512bbba0a97SChris Wilson 451391d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4514bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 4515a266c7d5SChris Wilson 4516c30bb1fdSVille Syrjälä GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); 4517c30bb1fdSVille Syrjälä 4518b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4519b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4520d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4521755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 4522755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4523755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4524d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4525a266c7d5SChris Wilson 452691d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 452720afbda2SDaniel Vetter 452820afbda2SDaniel Vetter return 0; 452920afbda2SDaniel Vetter } 453020afbda2SDaniel Vetter 453191d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) 453220afbda2SDaniel Vetter { 453320afbda2SDaniel Vetter u32 hotplug_en; 453420afbda2SDaniel Vetter 453567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4536b5ea2d56SDaniel Vetter 4537adca4730SChris Wilson /* Note HDMI and DP share hotplug bits */ 4538e5868a31SEgbert Eich /* enable bits are the same for all generations */ 453991d14251STvrtko Ursulin hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915); 4540a266c7d5SChris Wilson /* Programming the CRT detection parameters tends 4541a266c7d5SChris Wilson to generate a spurious hotplug event about three 4542a266c7d5SChris Wilson seconds later. So just do it once. 4543a266c7d5SChris Wilson */ 454491d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4545a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; 4546a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; 4547a266c7d5SChris Wilson 4548a266c7d5SChris Wilson /* Ignore TV since it's buggy */ 45490706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, 4550f9e3dc78SJani Nikula HOTPLUG_INT_EN_MASK | 4551f9e3dc78SJani Nikula CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | 4552f9e3dc78SJani Nikula CRT_HOTPLUG_ACTIVATION_PERIOD_64, 45530706f17cSEgbert Eich hotplug_en); 4554a266c7d5SChris Wilson } 4555a266c7d5SChris Wilson 4556ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 4557a266c7d5SChris Wilson { 455845a83f84SDaniel Vetter struct drm_device *dev = arg; 4559fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4560af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4561a266c7d5SChris Wilson 45622dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 45632dd2a883SImre Deak return IRQ_NONE; 45642dd2a883SImre Deak 45651f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 45661f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 45671f814dacSImre Deak 4568af722d28SVille Syrjälä do { 4569eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 457078c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4571af722d28SVille Syrjälä u32 hotplug_status = 0; 4572af722d28SVille Syrjälä u32 iir; 45732c8ba29fSChris Wilson 4574af722d28SVille Syrjälä iir = I915_READ(IIR); 4575af722d28SVille Syrjälä if (iir == 0) 4576af722d28SVille Syrjälä break; 4577af722d28SVille Syrjälä 4578af722d28SVille Syrjälä ret = IRQ_HANDLED; 4579af722d28SVille Syrjälä 4580af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 4581af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4582a266c7d5SChris Wilson 4583eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4584eb64343cSVille Syrjälä * signalled in iir */ 4585eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4586a266c7d5SChris Wilson 458778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 458878c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 458978c357ddSVille Syrjälä 4590fd3a4024SDaniel Vetter I915_WRITE(IIR, iir); 4591a266c7d5SChris Wilson 4592a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 45938a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 4594af722d28SVille Syrjälä 4595a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 45968a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); 4597a266c7d5SChris Wilson 459878c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 459978c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4600515ac2bbSDaniel Vetter 4601af722d28SVille Syrjälä if (hotplug_status) 4602af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4603af722d28SVille Syrjälä 4604af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4605af722d28SVille Syrjälä } while (0); 4606a266c7d5SChris Wilson 46071f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 46081f814dacSImre Deak 4609a266c7d5SChris Wilson return ret; 4610a266c7d5SChris Wilson } 4611a266c7d5SChris Wilson 4612fca52a55SDaniel Vetter /** 4613fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 4614fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4615fca52a55SDaniel Vetter * 4616fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 4617fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 4618fca52a55SDaniel Vetter */ 4619b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 4620f71d4af4SJesse Barnes { 462191c8a326SChris Wilson struct drm_device *dev = &dev_priv->drm; 4622562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 4623cefcff8fSJoonas Lahtinen int i; 46248b2e326dSChris Wilson 4625d938da6bSVille Syrjälä if (IS_I945GM(dev_priv)) 4626d938da6bSVille Syrjälä i945gm_vblank_work_init(dev_priv); 4627d938da6bSVille Syrjälä 462877913b39SJani Nikula intel_hpd_init_work(dev_priv); 462977913b39SJani Nikula 4630562d9baeSSagar Arun Kamble INIT_WORK(&rps->work, gen6_pm_rps_work); 4631cefcff8fSJoonas Lahtinen 4632a4da4fa4SDaniel Vetter INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); 4633cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4634cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 46358b2e326dSChris Wilson 46364805fe82STvrtko Ursulin if (HAS_GUC_SCHED(dev_priv)) 463726705e20SSagar Arun Kamble dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT; 463826705e20SSagar Arun Kamble 4639a6706b45SDeepak S /* Let's track the enabled rps events */ 4640666a4537SWayne Boyer if (IS_VALLEYVIEW(dev_priv)) 46416c65a587SVille Syrjälä /* WaGsvRC0ResidencyMethod:vlv */ 4642e0e8c7cbSChris Wilson dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED; 464331685c25SDeepak S else 46444668f695SChris Wilson dev_priv->pm_rps_events = (GEN6_PM_RP_UP_THRESHOLD | 46454668f695SChris Wilson GEN6_PM_RP_DOWN_THRESHOLD | 46464668f695SChris Wilson GEN6_PM_RP_DOWN_TIMEOUT); 4647a6706b45SDeepak S 4648562d9baeSSagar Arun Kamble rps->pm_intrmsk_mbz = 0; 46491800ad25SSagar Arun Kamble 46501800ad25SSagar Arun Kamble /* 4651acf2dc22SMika Kuoppala * SNB,IVB,HSW can while VLV,CHV may hard hang on looping batchbuffer 46521800ad25SSagar Arun Kamble * if GEN6_PM_UP_EI_EXPIRED is masked. 46531800ad25SSagar Arun Kamble * 46541800ad25SSagar Arun Kamble * TODO: verify if this can be reproduced on VLV,CHV. 46551800ad25SSagar Arun Kamble */ 4656bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) <= 7) 4657562d9baeSSagar Arun Kamble rps->pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED; 46581800ad25SSagar Arun Kamble 4659bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 8) 4660562d9baeSSagar Arun Kamble rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; 46611800ad25SSagar Arun Kamble 466232db0b65SVille Syrjälä if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) 4663fd8f507cSVille Syrjälä dev->driver->get_vblank_counter = g4x_get_vblank_counter; 466432db0b65SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 3) 4665391f75e2SVille Syrjälä dev->driver->get_vblank_counter = i915_get_vblank_counter; 4666f71d4af4SJesse Barnes 466721da2700SVille Syrjälä dev->vblank_disable_immediate = true; 466821da2700SVille Syrjälä 4669262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 4670262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 4671262fd485SChris Wilson * special care to avoid writing any of the display block registers 4672262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 4673262fd485SChris Wilson * in this case to the runtime pm. 4674262fd485SChris Wilson */ 4675262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 4676262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 4677262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 4678262fd485SChris Wilson 4679317eaa95SLyude dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; 46809a64c650SLyude Paul /* If we have MST support, we want to avoid doing short HPD IRQ storm 46819a64c650SLyude Paul * detection, as short HPD storms will occur as a natural part of 46829a64c650SLyude Paul * sideband messaging with MST. 46839a64c650SLyude Paul * On older platforms however, IRQ storms can occur with both long and 46849a64c650SLyude Paul * short pulses, as seen on some G4x systems. 46859a64c650SLyude Paul */ 46869a64c650SLyude Paul dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); 4687317eaa95SLyude 46881bf6ad62SDaniel Vetter dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; 4689f71d4af4SJesse Barnes dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; 4690f71d4af4SJesse Barnes 4691b963291cSDaniel Vetter if (IS_CHERRYVIEW(dev_priv)) { 469243f328d7SVille Syrjälä dev->driver->irq_handler = cherryview_irq_handler; 46936bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = cherryview_irq_reset; 469443f328d7SVille Syrjälä dev->driver->irq_postinstall = cherryview_irq_postinstall; 46956bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = cherryview_irq_reset; 469686e83e35SChris Wilson dev->driver->enable_vblank = i965_enable_vblank; 469786e83e35SChris Wilson dev->driver->disable_vblank = i965_disable_vblank; 469843f328d7SVille Syrjälä dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 4699b963291cSDaniel Vetter } else if (IS_VALLEYVIEW(dev_priv)) { 47007e231dbeSJesse Barnes dev->driver->irq_handler = valleyview_irq_handler; 47016bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = valleyview_irq_reset; 47027e231dbeSJesse Barnes dev->driver->irq_postinstall = valleyview_irq_postinstall; 47036bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = valleyview_irq_reset; 470486e83e35SChris Wilson dev->driver->enable_vblank = i965_enable_vblank; 470586e83e35SChris Wilson dev->driver->disable_vblank = i965_disable_vblank; 4706fa00abe0SEgbert Eich dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 470751951ae7SMika Kuoppala } else if (INTEL_GEN(dev_priv) >= 11) { 470851951ae7SMika Kuoppala dev->driver->irq_handler = gen11_irq_handler; 470951951ae7SMika Kuoppala dev->driver->irq_preinstall = gen11_irq_reset; 471051951ae7SMika Kuoppala dev->driver->irq_postinstall = gen11_irq_postinstall; 471151951ae7SMika Kuoppala dev->driver->irq_uninstall = gen11_irq_reset; 471251951ae7SMika Kuoppala dev->driver->enable_vblank = gen8_enable_vblank; 471351951ae7SMika Kuoppala dev->driver->disable_vblank = gen8_disable_vblank; 4714121e758eSDhinakaran Pandiyan dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; 4715bca2bf2aSPandiyan, Dhinakaran } else if (INTEL_GEN(dev_priv) >= 8) { 4716abd58f01SBen Widawsky dev->driver->irq_handler = gen8_irq_handler; 4717723761b8SDaniel Vetter dev->driver->irq_preinstall = gen8_irq_reset; 4718abd58f01SBen Widawsky dev->driver->irq_postinstall = gen8_irq_postinstall; 47196bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = gen8_irq_reset; 4720abd58f01SBen Widawsky dev->driver->enable_vblank = gen8_enable_vblank; 4721abd58f01SBen Widawsky dev->driver->disable_vblank = gen8_disable_vblank; 4722cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 4723e0a20ad7SShashank Sharma dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; 4724c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 47256dbf30ceSVille Syrjälä dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; 47266dbf30ceSVille Syrjälä else 47273a3b3c7dSVille Syrjälä dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; 47286e266956STvrtko Ursulin } else if (HAS_PCH_SPLIT(dev_priv)) { 4729f71d4af4SJesse Barnes dev->driver->irq_handler = ironlake_irq_handler; 4730723761b8SDaniel Vetter dev->driver->irq_preinstall = ironlake_irq_reset; 4731f71d4af4SJesse Barnes dev->driver->irq_postinstall = ironlake_irq_postinstall; 47326bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = ironlake_irq_reset; 4733f71d4af4SJesse Barnes dev->driver->enable_vblank = ironlake_enable_vblank; 4734f71d4af4SJesse Barnes dev->driver->disable_vblank = ironlake_disable_vblank; 4735e4ce95aaSVille Syrjälä dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; 4736f71d4af4SJesse Barnes } else { 4737cf819effSLucas De Marchi if (IS_GEN(dev_priv, 2)) { 47386bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = i8xx_irq_reset; 4739c2798b19SChris Wilson dev->driver->irq_postinstall = i8xx_irq_postinstall; 4740c2798b19SChris Wilson dev->driver->irq_handler = i8xx_irq_handler; 47416bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = i8xx_irq_reset; 474286e83e35SChris Wilson dev->driver->enable_vblank = i8xx_enable_vblank; 474386e83e35SChris Wilson dev->driver->disable_vblank = i8xx_disable_vblank; 4744d938da6bSVille Syrjälä } else if (IS_I945GM(dev_priv)) { 4745d938da6bSVille Syrjälä dev->driver->irq_preinstall = i915_irq_reset; 4746d938da6bSVille Syrjälä dev->driver->irq_postinstall = i915_irq_postinstall; 4747d938da6bSVille Syrjälä dev->driver->irq_uninstall = i915_irq_reset; 4748d938da6bSVille Syrjälä dev->driver->irq_handler = i915_irq_handler; 4749d938da6bSVille Syrjälä dev->driver->enable_vblank = i945gm_enable_vblank; 4750d938da6bSVille Syrjälä dev->driver->disable_vblank = i945gm_disable_vblank; 4751cf819effSLucas De Marchi } else if (IS_GEN(dev_priv, 3)) { 47526bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = i915_irq_reset; 4753a266c7d5SChris Wilson dev->driver->irq_postinstall = i915_irq_postinstall; 47546bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = i915_irq_reset; 4755a266c7d5SChris Wilson dev->driver->irq_handler = i915_irq_handler; 475686e83e35SChris Wilson dev->driver->enable_vblank = i8xx_enable_vblank; 475786e83e35SChris Wilson dev->driver->disable_vblank = i8xx_disable_vblank; 4758c2798b19SChris Wilson } else { 47596bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = i965_irq_reset; 4760a266c7d5SChris Wilson dev->driver->irq_postinstall = i965_irq_postinstall; 47616bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = i965_irq_reset; 4762a266c7d5SChris Wilson dev->driver->irq_handler = i965_irq_handler; 476386e83e35SChris Wilson dev->driver->enable_vblank = i965_enable_vblank; 476486e83e35SChris Wilson dev->driver->disable_vblank = i965_disable_vblank; 4765c2798b19SChris Wilson } 4766778eb334SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv)) 4767778eb334SVille Syrjälä dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 4768f71d4af4SJesse Barnes } 4769f71d4af4SJesse Barnes } 477020afbda2SDaniel Vetter 4771fca52a55SDaniel Vetter /** 4772cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 4773cefcff8fSJoonas Lahtinen * @i915: i915 device instance 4774cefcff8fSJoonas Lahtinen * 4775cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 4776cefcff8fSJoonas Lahtinen */ 4777cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 4778cefcff8fSJoonas Lahtinen { 4779cefcff8fSJoonas Lahtinen int i; 4780cefcff8fSJoonas Lahtinen 4781d938da6bSVille Syrjälä if (IS_I945GM(i915)) 4782d938da6bSVille Syrjälä i945gm_vblank_work_fini(i915); 4783d938da6bSVille Syrjälä 4784cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4785cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 4786cefcff8fSJoonas Lahtinen } 4787cefcff8fSJoonas Lahtinen 4788cefcff8fSJoonas Lahtinen /** 4789fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 4790fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4791fca52a55SDaniel Vetter * 4792fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 4793fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 4794fca52a55SDaniel Vetter * 4795fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 4796fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 4797fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 4798fca52a55SDaniel Vetter */ 47992aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 48002aeb7d3aSDaniel Vetter { 48012aeb7d3aSDaniel Vetter /* 48022aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 48032aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 48042aeb7d3aSDaniel Vetter * special cases in our ordering checks. 48052aeb7d3aSDaniel Vetter */ 4806ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 48072aeb7d3aSDaniel Vetter 480891c8a326SChris Wilson return drm_irq_install(&dev_priv->drm, dev_priv->drm.pdev->irq); 48092aeb7d3aSDaniel Vetter } 48102aeb7d3aSDaniel Vetter 4811fca52a55SDaniel Vetter /** 4812fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 4813fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4814fca52a55SDaniel Vetter * 4815fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 4816fca52a55SDaniel Vetter * resources acquired in the init functions. 4817fca52a55SDaniel Vetter */ 48182aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 48192aeb7d3aSDaniel Vetter { 482091c8a326SChris Wilson drm_irq_uninstall(&dev_priv->drm); 48212aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 4822ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 48232aeb7d3aSDaniel Vetter } 48242aeb7d3aSDaniel Vetter 4825fca52a55SDaniel Vetter /** 4826fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 4827fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4828fca52a55SDaniel Vetter * 4829fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 4830fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4831fca52a55SDaniel Vetter */ 4832b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 4833c67a470bSPaulo Zanoni { 483491c8a326SChris Wilson dev_priv->drm.driver->irq_uninstall(&dev_priv->drm); 4835ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 483691c8a326SChris Wilson synchronize_irq(dev_priv->drm.irq); 4837c67a470bSPaulo Zanoni } 4838c67a470bSPaulo Zanoni 4839fca52a55SDaniel Vetter /** 4840fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 4841fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4842fca52a55SDaniel Vetter * 4843fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 4844fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4845fca52a55SDaniel Vetter */ 4846b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 4847c67a470bSPaulo Zanoni { 4848ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 484991c8a326SChris Wilson dev_priv->drm.driver->irq_preinstall(&dev_priv->drm); 485091c8a326SChris Wilson dev_priv->drm.driver->irq_postinstall(&dev_priv->drm); 4851c67a470bSPaulo Zanoni } 4852