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 3163eeaf38SJesse Barnes #include <linux/sysrq.h> 325a0e3ad6STejun Heo #include <linux/slab.h> 33*d938da6bSVille Syrjälä #include <linux/cpuidle.h> 34b2c88f5bSDamien Lespiau #include <linux/circ_buf.h> 35fcd70cd3SDaniel Vetter #include <drm/drm_irq.h> 36fcd70cd3SDaniel Vetter #include <drm/drm_drv.h> 37760285e7SDavid Howells #include <drm/i915_drm.h> 38c0e09200SDave Airlie #include "i915_drv.h" 391c5d22f7SChris Wilson #include "i915_trace.h" 4079e53945SJesse Barnes #include "intel_drv.h" 41c0e09200SDave Airlie 42fca52a55SDaniel Vetter /** 43fca52a55SDaniel Vetter * DOC: interrupt handling 44fca52a55SDaniel Vetter * 45fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 46fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 47fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 48fca52a55SDaniel Vetter */ 49fca52a55SDaniel Vetter 50e4ce95aaSVille Syrjälä static const u32 hpd_ilk[HPD_NUM_PINS] = { 51e4ce95aaSVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG, 52e4ce95aaSVille Syrjälä }; 53e4ce95aaSVille Syrjälä 5423bb4cb5SVille Syrjälä static const u32 hpd_ivb[HPD_NUM_PINS] = { 5523bb4cb5SVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, 5623bb4cb5SVille Syrjälä }; 5723bb4cb5SVille Syrjälä 583a3b3c7dSVille Syrjälä static const u32 hpd_bdw[HPD_NUM_PINS] = { 593a3b3c7dSVille Syrjälä [HPD_PORT_A] = GEN8_PORT_DP_A_HOTPLUG, 603a3b3c7dSVille Syrjälä }; 613a3b3c7dSVille Syrjälä 627c7e10dbSVille Syrjälä static const u32 hpd_ibx[HPD_NUM_PINS] = { 63e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG, 64e5868a31SEgbert Eich [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, 65e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG, 66e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG, 67e5868a31SEgbert Eich [HPD_PORT_D] = SDE_PORTD_HOTPLUG 68e5868a31SEgbert Eich }; 69e5868a31SEgbert Eich 707c7e10dbSVille Syrjälä static const u32 hpd_cpt[HPD_NUM_PINS] = { 71e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, 7273c352a2SDaniel Vetter [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, 73e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 74e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 75e5868a31SEgbert Eich [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT 76e5868a31SEgbert Eich }; 77e5868a31SEgbert Eich 7826951cafSXiong Zhang static const u32 hpd_spt[HPD_NUM_PINS] = { 7974c0b395SVille Syrjälä [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, 8026951cafSXiong Zhang [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 8126951cafSXiong Zhang [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 8226951cafSXiong Zhang [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 8326951cafSXiong Zhang [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT 8426951cafSXiong Zhang }; 8526951cafSXiong Zhang 867c7e10dbSVille Syrjälä static const u32 hpd_mask_i915[HPD_NUM_PINS] = { 87e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_EN, 88e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, 89e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, 90e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN, 91e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN, 92e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN 93e5868a31SEgbert Eich }; 94e5868a31SEgbert Eich 957c7e10dbSVille Syrjälä static const u32 hpd_status_g4x[HPD_NUM_PINS] = { 96e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 97e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, 98e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, 99e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 100e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 101e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS 102e5868a31SEgbert Eich }; 103e5868a31SEgbert Eich 1044bca26d0SVille Syrjälä static const u32 hpd_status_i915[HPD_NUM_PINS] = { 105e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 106e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, 107e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, 108e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 109e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 110e5868a31SEgbert Eich [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS 111e5868a31SEgbert Eich }; 112e5868a31SEgbert Eich 113e0a20ad7SShashank Sharma /* BXT hpd list */ 114e0a20ad7SShashank Sharma static const u32 hpd_bxt[HPD_NUM_PINS] = { 1157f3561beSSonika Jindal [HPD_PORT_A] = BXT_DE_PORT_HP_DDIA, 116e0a20ad7SShashank Sharma [HPD_PORT_B] = BXT_DE_PORT_HP_DDIB, 117e0a20ad7SShashank Sharma [HPD_PORT_C] = BXT_DE_PORT_HP_DDIC 118e0a20ad7SShashank Sharma }; 119e0a20ad7SShashank Sharma 120b796b971SDhinakaran Pandiyan static const u32 hpd_gen11[HPD_NUM_PINS] = { 121b796b971SDhinakaran Pandiyan [HPD_PORT_C] = GEN11_TC1_HOTPLUG | GEN11_TBT1_HOTPLUG, 122b796b971SDhinakaran Pandiyan [HPD_PORT_D] = GEN11_TC2_HOTPLUG | GEN11_TBT2_HOTPLUG, 123b796b971SDhinakaran Pandiyan [HPD_PORT_E] = GEN11_TC3_HOTPLUG | GEN11_TBT3_HOTPLUG, 124b796b971SDhinakaran Pandiyan [HPD_PORT_F] = GEN11_TC4_HOTPLUG | GEN11_TBT4_HOTPLUG 125121e758eSDhinakaran Pandiyan }; 126121e758eSDhinakaran Pandiyan 12731604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = { 12831604222SAnusha Srivatsa [HPD_PORT_A] = SDE_DDIA_HOTPLUG_ICP, 12931604222SAnusha Srivatsa [HPD_PORT_B] = SDE_DDIB_HOTPLUG_ICP, 13031604222SAnusha Srivatsa [HPD_PORT_C] = SDE_TC1_HOTPLUG_ICP, 13131604222SAnusha Srivatsa [HPD_PORT_D] = SDE_TC2_HOTPLUG_ICP, 13231604222SAnusha Srivatsa [HPD_PORT_E] = SDE_TC3_HOTPLUG_ICP, 13331604222SAnusha Srivatsa [HPD_PORT_F] = SDE_TC4_HOTPLUG_ICP 13431604222SAnusha Srivatsa }; 13531604222SAnusha Srivatsa 1365c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 137f86f3fb0SPaulo Zanoni #define GEN8_IRQ_RESET_NDX(type, which) do { \ 1385c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \ 1395c502442SPaulo Zanoni POSTING_READ(GEN8_##type##_IMR(which)); \ 1405c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IER(which), 0); \ 1415c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ 1425c502442SPaulo Zanoni POSTING_READ(GEN8_##type##_IIR(which)); \ 1435c502442SPaulo Zanoni I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ 1445c502442SPaulo Zanoni POSTING_READ(GEN8_##type##_IIR(which)); \ 1455c502442SPaulo Zanoni } while (0) 1465c502442SPaulo Zanoni 1473488d4ebSVille Syrjälä #define GEN3_IRQ_RESET(type) do { \ 148a9d356a6SPaulo Zanoni I915_WRITE(type##IMR, 0xffffffff); \ 1495c502442SPaulo Zanoni POSTING_READ(type##IMR); \ 150a9d356a6SPaulo Zanoni I915_WRITE(type##IER, 0); \ 1515c502442SPaulo Zanoni I915_WRITE(type##IIR, 0xffffffff); \ 1525c502442SPaulo Zanoni POSTING_READ(type##IIR); \ 1535c502442SPaulo Zanoni I915_WRITE(type##IIR, 0xffffffff); \ 1545c502442SPaulo Zanoni POSTING_READ(type##IIR); \ 155a9d356a6SPaulo Zanoni } while (0) 156a9d356a6SPaulo Zanoni 157e9e9848aSVille Syrjälä #define GEN2_IRQ_RESET(type) do { \ 158e9e9848aSVille Syrjälä I915_WRITE16(type##IMR, 0xffff); \ 159e9e9848aSVille Syrjälä POSTING_READ16(type##IMR); \ 160e9e9848aSVille Syrjälä I915_WRITE16(type##IER, 0); \ 161e9e9848aSVille Syrjälä I915_WRITE16(type##IIR, 0xffff); \ 162e9e9848aSVille Syrjälä POSTING_READ16(type##IIR); \ 163e9e9848aSVille Syrjälä I915_WRITE16(type##IIR, 0xffff); \ 164e9e9848aSVille Syrjälä POSTING_READ16(type##IIR); \ 165e9e9848aSVille Syrjälä } while (0) 166e9e9848aSVille Syrjälä 167337ba017SPaulo Zanoni /* 168337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 169337ba017SPaulo Zanoni */ 1703488d4ebSVille Syrjälä static void gen3_assert_iir_is_zero(struct drm_i915_private *dev_priv, 171f0f59a00SVille Syrjälä i915_reg_t reg) 172b51a2842SVille Syrjälä { 173b51a2842SVille Syrjälä u32 val = I915_READ(reg); 174b51a2842SVille Syrjälä 175b51a2842SVille Syrjälä if (val == 0) 176b51a2842SVille Syrjälä return; 177b51a2842SVille Syrjälä 178b51a2842SVille Syrjälä WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", 179f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 180b51a2842SVille Syrjälä I915_WRITE(reg, 0xffffffff); 181b51a2842SVille Syrjälä POSTING_READ(reg); 182b51a2842SVille Syrjälä I915_WRITE(reg, 0xffffffff); 183b51a2842SVille Syrjälä POSTING_READ(reg); 184b51a2842SVille Syrjälä } 185337ba017SPaulo Zanoni 186e9e9848aSVille Syrjälä static void gen2_assert_iir_is_zero(struct drm_i915_private *dev_priv, 187e9e9848aSVille Syrjälä i915_reg_t reg) 188e9e9848aSVille Syrjälä { 189e9e9848aSVille Syrjälä u16 val = I915_READ16(reg); 190e9e9848aSVille Syrjälä 191e9e9848aSVille Syrjälä if (val == 0) 192e9e9848aSVille Syrjälä return; 193e9e9848aSVille Syrjälä 194e9e9848aSVille Syrjälä WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", 195e9e9848aSVille Syrjälä i915_mmio_reg_offset(reg), val); 196e9e9848aSVille Syrjälä I915_WRITE16(reg, 0xffff); 197e9e9848aSVille Syrjälä POSTING_READ16(reg); 198e9e9848aSVille Syrjälä I915_WRITE16(reg, 0xffff); 199e9e9848aSVille Syrjälä POSTING_READ16(reg); 200e9e9848aSVille Syrjälä } 201e9e9848aSVille Syrjälä 20235079899SPaulo Zanoni #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \ 2033488d4ebSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ 20435079899SPaulo Zanoni I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \ 2057d1bd539SVille Syrjälä I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \ 2067d1bd539SVille Syrjälä POSTING_READ(GEN8_##type##_IMR(which)); \ 20735079899SPaulo Zanoni } while (0) 20835079899SPaulo Zanoni 2093488d4ebSVille Syrjälä #define GEN3_IRQ_INIT(type, imr_val, ier_val) do { \ 2103488d4ebSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, type##IIR); \ 21135079899SPaulo Zanoni I915_WRITE(type##IER, (ier_val)); \ 2127d1bd539SVille Syrjälä I915_WRITE(type##IMR, (imr_val)); \ 2137d1bd539SVille Syrjälä POSTING_READ(type##IMR); \ 21435079899SPaulo Zanoni } while (0) 21535079899SPaulo Zanoni 216e9e9848aSVille Syrjälä #define GEN2_IRQ_INIT(type, imr_val, ier_val) do { \ 217e9e9848aSVille Syrjälä gen2_assert_iir_is_zero(dev_priv, type##IIR); \ 218e9e9848aSVille Syrjälä I915_WRITE16(type##IER, (ier_val)); \ 219e9e9848aSVille Syrjälä I915_WRITE16(type##IMR, (imr_val)); \ 220e9e9848aSVille Syrjälä POSTING_READ16(type##IMR); \ 221e9e9848aSVille Syrjälä } while (0) 222e9e9848aSVille Syrjälä 223c9a9a268SImre Deak static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); 22426705e20SSagar Arun Kamble static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); 225c9a9a268SImre Deak 2260706f17cSEgbert Eich /* For display hotplug interrupt */ 2270706f17cSEgbert Eich static inline void 2280706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, 229a9c287c9SJani Nikula u32 mask, 230a9c287c9SJani Nikula u32 bits) 2310706f17cSEgbert Eich { 232a9c287c9SJani Nikula u32 val; 2330706f17cSEgbert Eich 23467520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 2350706f17cSEgbert Eich WARN_ON(bits & ~mask); 2360706f17cSEgbert Eich 2370706f17cSEgbert Eich val = I915_READ(PORT_HOTPLUG_EN); 2380706f17cSEgbert Eich val &= ~mask; 2390706f17cSEgbert Eich val |= bits; 2400706f17cSEgbert Eich I915_WRITE(PORT_HOTPLUG_EN, val); 2410706f17cSEgbert Eich } 2420706f17cSEgbert Eich 2430706f17cSEgbert Eich /** 2440706f17cSEgbert Eich * i915_hotplug_interrupt_update - update hotplug interrupt enable 2450706f17cSEgbert Eich * @dev_priv: driver private 2460706f17cSEgbert Eich * @mask: bits to update 2470706f17cSEgbert Eich * @bits: bits to enable 2480706f17cSEgbert Eich * NOTE: the HPD enable bits are modified both inside and outside 2490706f17cSEgbert Eich * of an interrupt context. To avoid that read-modify-write cycles 2500706f17cSEgbert Eich * interfer, these bits are protected by a spinlock. Since this 2510706f17cSEgbert Eich * function is usually not called from a context where the lock is 2520706f17cSEgbert Eich * held already, this function acquires the lock itself. A non-locking 2530706f17cSEgbert Eich * version is also available. 2540706f17cSEgbert Eich */ 2550706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, 256a9c287c9SJani Nikula u32 mask, 257a9c287c9SJani Nikula u32 bits) 2580706f17cSEgbert Eich { 2590706f17cSEgbert Eich spin_lock_irq(&dev_priv->irq_lock); 2600706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); 2610706f17cSEgbert Eich spin_unlock_irq(&dev_priv->irq_lock); 2620706f17cSEgbert Eich } 2630706f17cSEgbert Eich 26496606f3bSOscar Mateo static u32 26596606f3bSOscar Mateo gen11_gt_engine_identity(struct drm_i915_private * const i915, 26696606f3bSOscar Mateo const unsigned int bank, const unsigned int bit); 26796606f3bSOscar Mateo 26860a94324SChris Wilson static bool gen11_reset_one_iir(struct drm_i915_private * const i915, 26996606f3bSOscar Mateo const unsigned int bank, 27096606f3bSOscar Mateo const unsigned int bit) 27196606f3bSOscar Mateo { 27225286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 27396606f3bSOscar Mateo u32 dw; 27496606f3bSOscar Mateo 27596606f3bSOscar Mateo lockdep_assert_held(&i915->irq_lock); 27696606f3bSOscar Mateo 27796606f3bSOscar Mateo dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); 27896606f3bSOscar Mateo if (dw & BIT(bit)) { 27996606f3bSOscar Mateo /* 28096606f3bSOscar Mateo * According to the BSpec, DW_IIR bits cannot be cleared without 28196606f3bSOscar Mateo * first servicing the Selector & Shared IIR registers. 28296606f3bSOscar Mateo */ 28396606f3bSOscar Mateo gen11_gt_engine_identity(i915, bank, bit); 28496606f3bSOscar Mateo 28596606f3bSOscar Mateo /* 28696606f3bSOscar Mateo * We locked GT INT DW by reading it. If we want to (try 28796606f3bSOscar Mateo * to) recover from this succesfully, we need to clear 28896606f3bSOscar Mateo * our bit, otherwise we are locking the register for 28996606f3bSOscar Mateo * everybody. 29096606f3bSOscar Mateo */ 29196606f3bSOscar Mateo raw_reg_write(regs, GEN11_GT_INTR_DW(bank), BIT(bit)); 29296606f3bSOscar Mateo 29396606f3bSOscar Mateo return true; 29496606f3bSOscar Mateo } 29596606f3bSOscar Mateo 29696606f3bSOscar Mateo return false; 29796606f3bSOscar Mateo } 29896606f3bSOscar Mateo 299d9dc34f1SVille Syrjälä /** 300d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 301d9dc34f1SVille Syrjälä * @dev_priv: driver private 302d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 303d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 304d9dc34f1SVille Syrjälä */ 305fbdedaeaSVille Syrjälä void ilk_update_display_irq(struct drm_i915_private *dev_priv, 306a9c287c9SJani Nikula u32 interrupt_mask, 307a9c287c9SJani Nikula u32 enabled_irq_mask) 308036a4a7dSZhenyu Wang { 309a9c287c9SJani Nikula u32 new_val; 310d9dc34f1SVille Syrjälä 31167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3124bc9d430SDaniel Vetter 313d9dc34f1SVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 314d9dc34f1SVille Syrjälä 3159df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 316c67a470bSPaulo Zanoni return; 317c67a470bSPaulo Zanoni 318d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 319d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 320d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 321d9dc34f1SVille Syrjälä 322d9dc34f1SVille Syrjälä if (new_val != dev_priv->irq_mask) { 323d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 3241ec14ad3SChris Wilson I915_WRITE(DEIMR, dev_priv->irq_mask); 3253143a2bfSChris Wilson POSTING_READ(DEIMR); 326036a4a7dSZhenyu Wang } 327036a4a7dSZhenyu Wang } 328036a4a7dSZhenyu Wang 32943eaea13SPaulo Zanoni /** 33043eaea13SPaulo Zanoni * ilk_update_gt_irq - update GTIMR 33143eaea13SPaulo Zanoni * @dev_priv: driver private 33243eaea13SPaulo Zanoni * @interrupt_mask: mask of interrupt bits to update 33343eaea13SPaulo Zanoni * @enabled_irq_mask: mask of interrupt bits to enable 33443eaea13SPaulo Zanoni */ 33543eaea13SPaulo Zanoni static void ilk_update_gt_irq(struct drm_i915_private *dev_priv, 336a9c287c9SJani Nikula u32 interrupt_mask, 337a9c287c9SJani Nikula u32 enabled_irq_mask) 33843eaea13SPaulo Zanoni { 33967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 34043eaea13SPaulo Zanoni 34115a17aaeSDaniel Vetter WARN_ON(enabled_irq_mask & ~interrupt_mask); 34215a17aaeSDaniel Vetter 3439df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 344c67a470bSPaulo Zanoni return; 345c67a470bSPaulo Zanoni 34643eaea13SPaulo Zanoni dev_priv->gt_irq_mask &= ~interrupt_mask; 34743eaea13SPaulo Zanoni dev_priv->gt_irq_mask |= (~enabled_irq_mask & interrupt_mask); 34843eaea13SPaulo Zanoni I915_WRITE(GTIMR, dev_priv->gt_irq_mask); 34943eaea13SPaulo Zanoni } 35043eaea13SPaulo Zanoni 351a9c287c9SJani Nikula void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, u32 mask) 35243eaea13SPaulo Zanoni { 35343eaea13SPaulo Zanoni ilk_update_gt_irq(dev_priv, mask, mask); 35431bb59ccSChris Wilson POSTING_READ_FW(GTIMR); 35543eaea13SPaulo Zanoni } 35643eaea13SPaulo Zanoni 357a9c287c9SJani Nikula void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, u32 mask) 35843eaea13SPaulo Zanoni { 35943eaea13SPaulo Zanoni ilk_update_gt_irq(dev_priv, mask, 0); 36043eaea13SPaulo Zanoni } 36143eaea13SPaulo Zanoni 362f0f59a00SVille Syrjälä static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) 363b900b949SImre Deak { 364d02b98b8SOscar Mateo WARN_ON_ONCE(INTEL_GEN(dev_priv) >= 11); 365d02b98b8SOscar Mateo 366bca2bf2aSPandiyan, Dhinakaran return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; 367b900b949SImre Deak } 368b900b949SImre Deak 369f0f59a00SVille Syrjälä static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv) 370a72fbc3aSImre Deak { 371d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 372d02b98b8SOscar Mateo return GEN11_GPM_WGBOXPERF_INTR_MASK; 373d02b98b8SOscar Mateo else if (INTEL_GEN(dev_priv) >= 8) 374d02b98b8SOscar Mateo return GEN8_GT_IMR(2); 375d02b98b8SOscar Mateo else 376d02b98b8SOscar Mateo return GEN6_PMIMR; 377a72fbc3aSImre Deak } 378a72fbc3aSImre Deak 379f0f59a00SVille Syrjälä static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv) 380b900b949SImre Deak { 381d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 382d02b98b8SOscar Mateo return GEN11_GPM_WGBOXPERF_INTR_ENABLE; 383d02b98b8SOscar Mateo else if (INTEL_GEN(dev_priv) >= 8) 384d02b98b8SOscar Mateo return GEN8_GT_IER(2); 385d02b98b8SOscar Mateo else 386d02b98b8SOscar Mateo return GEN6_PMIER; 387b900b949SImre Deak } 388b900b949SImre Deak 389edbfdb45SPaulo Zanoni /** 390edbfdb45SPaulo Zanoni * snb_update_pm_irq - update GEN6_PMIMR 391edbfdb45SPaulo Zanoni * @dev_priv: driver private 392edbfdb45SPaulo Zanoni * @interrupt_mask: mask of interrupt bits to update 393edbfdb45SPaulo Zanoni * @enabled_irq_mask: mask of interrupt bits to enable 394edbfdb45SPaulo Zanoni */ 395edbfdb45SPaulo Zanoni static void snb_update_pm_irq(struct drm_i915_private *dev_priv, 396a9c287c9SJani Nikula u32 interrupt_mask, 397a9c287c9SJani Nikula u32 enabled_irq_mask) 398edbfdb45SPaulo Zanoni { 399a9c287c9SJani Nikula u32 new_val; 400edbfdb45SPaulo Zanoni 40115a17aaeSDaniel Vetter WARN_ON(enabled_irq_mask & ~interrupt_mask); 40215a17aaeSDaniel Vetter 40367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 404edbfdb45SPaulo Zanoni 405f4e9af4fSAkash Goel new_val = dev_priv->pm_imr; 406f52ecbcfSPaulo Zanoni new_val &= ~interrupt_mask; 407f52ecbcfSPaulo Zanoni new_val |= (~enabled_irq_mask & interrupt_mask); 408f52ecbcfSPaulo Zanoni 409f4e9af4fSAkash Goel if (new_val != dev_priv->pm_imr) { 410f4e9af4fSAkash Goel dev_priv->pm_imr = new_val; 411f4e9af4fSAkash Goel I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_imr); 412a72fbc3aSImre Deak POSTING_READ(gen6_pm_imr(dev_priv)); 413edbfdb45SPaulo Zanoni } 414f52ecbcfSPaulo Zanoni } 415edbfdb45SPaulo Zanoni 416f4e9af4fSAkash Goel void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) 417edbfdb45SPaulo Zanoni { 4189939fba2SImre Deak if (WARN_ON(!intel_irqs_enabled(dev_priv))) 4199939fba2SImre Deak return; 4209939fba2SImre Deak 421edbfdb45SPaulo Zanoni snb_update_pm_irq(dev_priv, mask, mask); 422edbfdb45SPaulo Zanoni } 423edbfdb45SPaulo Zanoni 424f4e9af4fSAkash Goel static void __gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) 4259939fba2SImre Deak { 4269939fba2SImre Deak snb_update_pm_irq(dev_priv, mask, 0); 4279939fba2SImre Deak } 4289939fba2SImre Deak 429f4e9af4fSAkash Goel void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) 430edbfdb45SPaulo Zanoni { 4319939fba2SImre Deak if (WARN_ON(!intel_irqs_enabled(dev_priv))) 4329939fba2SImre Deak return; 4339939fba2SImre Deak 434f4e9af4fSAkash Goel __gen6_mask_pm_irq(dev_priv, mask); 435f4e9af4fSAkash Goel } 436f4e9af4fSAkash Goel 4373814fd77SOscar Mateo static void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask) 438f4e9af4fSAkash Goel { 439f4e9af4fSAkash Goel i915_reg_t reg = gen6_pm_iir(dev_priv); 440f4e9af4fSAkash Goel 44167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 442f4e9af4fSAkash Goel 443f4e9af4fSAkash Goel I915_WRITE(reg, reset_mask); 444f4e9af4fSAkash Goel I915_WRITE(reg, reset_mask); 445f4e9af4fSAkash Goel POSTING_READ(reg); 446f4e9af4fSAkash Goel } 447f4e9af4fSAkash Goel 4483814fd77SOscar Mateo static void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask) 449f4e9af4fSAkash Goel { 45067520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 451f4e9af4fSAkash Goel 452f4e9af4fSAkash Goel dev_priv->pm_ier |= enable_mask; 453f4e9af4fSAkash Goel I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); 454f4e9af4fSAkash Goel gen6_unmask_pm_irq(dev_priv, enable_mask); 455f4e9af4fSAkash Goel /* unmask_pm_irq provides an implicit barrier (POSTING_READ) */ 456f4e9af4fSAkash Goel } 457f4e9af4fSAkash Goel 4583814fd77SOscar Mateo static void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask) 459f4e9af4fSAkash Goel { 46067520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 461f4e9af4fSAkash Goel 462f4e9af4fSAkash Goel dev_priv->pm_ier &= ~disable_mask; 463f4e9af4fSAkash Goel __gen6_mask_pm_irq(dev_priv, disable_mask); 464f4e9af4fSAkash Goel I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); 465f4e9af4fSAkash Goel /* though a barrier is missing here, but don't really need a one */ 466edbfdb45SPaulo Zanoni } 467edbfdb45SPaulo Zanoni 468d02b98b8SOscar Mateo void gen11_reset_rps_interrupts(struct drm_i915_private *dev_priv) 469d02b98b8SOscar Mateo { 470d02b98b8SOscar Mateo spin_lock_irq(&dev_priv->irq_lock); 471d02b98b8SOscar Mateo 47296606f3bSOscar Mateo while (gen11_reset_one_iir(dev_priv, 0, GEN11_GTPM)) 47396606f3bSOscar Mateo ; 474d02b98b8SOscar Mateo 475d02b98b8SOscar Mateo dev_priv->gt_pm.rps.pm_iir = 0; 476d02b98b8SOscar Mateo 477d02b98b8SOscar Mateo spin_unlock_irq(&dev_priv->irq_lock); 478d02b98b8SOscar Mateo } 479d02b98b8SOscar Mateo 480dc97997aSChris Wilson void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) 4813cc134e3SImre Deak { 4823cc134e3SImre Deak spin_lock_irq(&dev_priv->irq_lock); 4834668f695SChris Wilson gen6_reset_pm_iir(dev_priv, GEN6_PM_RPS_EVENTS); 484562d9baeSSagar Arun Kamble dev_priv->gt_pm.rps.pm_iir = 0; 4853cc134e3SImre Deak spin_unlock_irq(&dev_priv->irq_lock); 4863cc134e3SImre Deak } 4873cc134e3SImre Deak 48891d14251STvrtko Ursulin void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) 489b900b949SImre Deak { 490562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 491562d9baeSSagar Arun Kamble 492562d9baeSSagar Arun Kamble if (READ_ONCE(rps->interrupts_enabled)) 493f2a91d1aSChris Wilson return; 494f2a91d1aSChris Wilson 495b900b949SImre Deak spin_lock_irq(&dev_priv->irq_lock); 496562d9baeSSagar Arun Kamble WARN_ON_ONCE(rps->pm_iir); 49796606f3bSOscar Mateo 498d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 49996606f3bSOscar Mateo WARN_ON_ONCE(gen11_reset_one_iir(dev_priv, 0, GEN11_GTPM)); 500d02b98b8SOscar Mateo else 501c33d247dSChris Wilson WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); 50296606f3bSOscar Mateo 503562d9baeSSagar Arun Kamble rps->interrupts_enabled = true; 504b900b949SImre Deak gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); 50578e68d36SImre Deak 506b900b949SImre Deak spin_unlock_irq(&dev_priv->irq_lock); 507b900b949SImre Deak } 508b900b949SImre Deak 50991d14251STvrtko Ursulin void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) 510b900b949SImre Deak { 511562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 512562d9baeSSagar Arun Kamble 513562d9baeSSagar Arun Kamble if (!READ_ONCE(rps->interrupts_enabled)) 514f2a91d1aSChris Wilson return; 515f2a91d1aSChris Wilson 516d4d70aa5SImre Deak spin_lock_irq(&dev_priv->irq_lock); 517562d9baeSSagar Arun Kamble rps->interrupts_enabled = false; 5189939fba2SImre Deak 519b20e3cfeSDave Gordon I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0u)); 5209939fba2SImre Deak 5214668f695SChris Wilson gen6_disable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS); 52258072ccbSImre Deak 52358072ccbSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 52491c8a326SChris Wilson synchronize_irq(dev_priv->drm.irq); 525c33d247dSChris Wilson 526c33d247dSChris Wilson /* Now that we will not be generating any more work, flush any 5273814fd77SOscar Mateo * outstanding tasks. As we are called on the RPS idle path, 528c33d247dSChris Wilson * we will reset the GPU to minimum frequencies, so the current 529c33d247dSChris Wilson * state of the worker can be discarded. 530c33d247dSChris Wilson */ 531562d9baeSSagar Arun Kamble cancel_work_sync(&rps->work); 532d02b98b8SOscar Mateo if (INTEL_GEN(dev_priv) >= 11) 533d02b98b8SOscar Mateo gen11_reset_rps_interrupts(dev_priv); 534d02b98b8SOscar Mateo else 535c33d247dSChris Wilson gen6_reset_rps_interrupts(dev_priv); 536b900b949SImre Deak } 537b900b949SImre Deak 53826705e20SSagar Arun Kamble void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv) 53926705e20SSagar Arun Kamble { 5401be333d3SSagar Arun Kamble assert_rpm_wakelock_held(dev_priv); 5411be333d3SSagar Arun Kamble 54226705e20SSagar Arun Kamble spin_lock_irq(&dev_priv->irq_lock); 54326705e20SSagar Arun Kamble gen6_reset_pm_iir(dev_priv, dev_priv->pm_guc_events); 54426705e20SSagar Arun Kamble spin_unlock_irq(&dev_priv->irq_lock); 54526705e20SSagar Arun Kamble } 54626705e20SSagar Arun Kamble 54726705e20SSagar Arun Kamble void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv) 54826705e20SSagar Arun Kamble { 5491be333d3SSagar Arun Kamble assert_rpm_wakelock_held(dev_priv); 5501be333d3SSagar Arun Kamble 55126705e20SSagar Arun Kamble spin_lock_irq(&dev_priv->irq_lock); 55226705e20SSagar Arun Kamble if (!dev_priv->guc.interrupts_enabled) { 55326705e20SSagar Arun Kamble WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & 55426705e20SSagar Arun Kamble dev_priv->pm_guc_events); 55526705e20SSagar Arun Kamble dev_priv->guc.interrupts_enabled = true; 55626705e20SSagar Arun Kamble gen6_enable_pm_irq(dev_priv, dev_priv->pm_guc_events); 55726705e20SSagar Arun Kamble } 55826705e20SSagar Arun Kamble spin_unlock_irq(&dev_priv->irq_lock); 55926705e20SSagar Arun Kamble } 56026705e20SSagar Arun Kamble 56126705e20SSagar Arun Kamble void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv) 56226705e20SSagar Arun Kamble { 5631be333d3SSagar Arun Kamble assert_rpm_wakelock_held(dev_priv); 5641be333d3SSagar Arun Kamble 56526705e20SSagar Arun Kamble spin_lock_irq(&dev_priv->irq_lock); 56626705e20SSagar Arun Kamble dev_priv->guc.interrupts_enabled = false; 56726705e20SSagar Arun Kamble 56826705e20SSagar Arun Kamble gen6_disable_pm_irq(dev_priv, dev_priv->pm_guc_events); 56926705e20SSagar Arun Kamble 57026705e20SSagar Arun Kamble spin_unlock_irq(&dev_priv->irq_lock); 57126705e20SSagar Arun Kamble synchronize_irq(dev_priv->drm.irq); 57226705e20SSagar Arun Kamble 57326705e20SSagar Arun Kamble gen9_reset_guc_interrupts(dev_priv); 57426705e20SSagar Arun Kamble } 57526705e20SSagar Arun Kamble 5760961021aSBen Widawsky /** 5773a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 5783a3b3c7dSVille Syrjälä * @dev_priv: driver private 5793a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 5803a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 5813a3b3c7dSVille Syrjälä */ 5823a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv, 583a9c287c9SJani Nikula u32 interrupt_mask, 584a9c287c9SJani Nikula u32 enabled_irq_mask) 5853a3b3c7dSVille Syrjälä { 586a9c287c9SJani Nikula u32 new_val; 587a9c287c9SJani Nikula u32 old_val; 5883a3b3c7dSVille Syrjälä 58967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 5903a3b3c7dSVille Syrjälä 5913a3b3c7dSVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 5923a3b3c7dSVille Syrjälä 5933a3b3c7dSVille Syrjälä if (WARN_ON(!intel_irqs_enabled(dev_priv))) 5943a3b3c7dSVille Syrjälä return; 5953a3b3c7dSVille Syrjälä 5963a3b3c7dSVille Syrjälä old_val = I915_READ(GEN8_DE_PORT_IMR); 5973a3b3c7dSVille Syrjälä 5983a3b3c7dSVille Syrjälä new_val = old_val; 5993a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 6003a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 6013a3b3c7dSVille Syrjälä 6023a3b3c7dSVille Syrjälä if (new_val != old_val) { 6033a3b3c7dSVille Syrjälä I915_WRITE(GEN8_DE_PORT_IMR, new_val); 6043a3b3c7dSVille Syrjälä POSTING_READ(GEN8_DE_PORT_IMR); 6053a3b3c7dSVille Syrjälä } 6063a3b3c7dSVille Syrjälä } 6073a3b3c7dSVille Syrjälä 6083a3b3c7dSVille Syrjälä /** 609013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 610013d3752SVille Syrjälä * @dev_priv: driver private 611013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 612013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 613013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 614013d3752SVille Syrjälä */ 615013d3752SVille Syrjälä void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 616013d3752SVille Syrjälä enum pipe pipe, 617a9c287c9SJani Nikula u32 interrupt_mask, 618a9c287c9SJani Nikula u32 enabled_irq_mask) 619013d3752SVille Syrjälä { 620a9c287c9SJani Nikula u32 new_val; 621013d3752SVille Syrjälä 62267520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 623013d3752SVille Syrjälä 624013d3752SVille Syrjälä WARN_ON(enabled_irq_mask & ~interrupt_mask); 625013d3752SVille Syrjälä 626013d3752SVille Syrjälä if (WARN_ON(!intel_irqs_enabled(dev_priv))) 627013d3752SVille Syrjälä return; 628013d3752SVille Syrjälä 629013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 630013d3752SVille Syrjälä new_val &= ~interrupt_mask; 631013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 632013d3752SVille Syrjälä 633013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 634013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 635013d3752SVille Syrjälä I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 636013d3752SVille Syrjälä POSTING_READ(GEN8_DE_PIPE_IMR(pipe)); 637013d3752SVille Syrjälä } 638013d3752SVille Syrjälä } 639013d3752SVille Syrjälä 640013d3752SVille Syrjälä /** 641fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 642fee884edSDaniel Vetter * @dev_priv: driver private 643fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 644fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 645fee884edSDaniel Vetter */ 64647339cd9SDaniel Vetter void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 647a9c287c9SJani Nikula u32 interrupt_mask, 648a9c287c9SJani Nikula u32 enabled_irq_mask) 649fee884edSDaniel Vetter { 650a9c287c9SJani Nikula u32 sdeimr = I915_READ(SDEIMR); 651fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 652fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 653fee884edSDaniel Vetter 65415a17aaeSDaniel Vetter WARN_ON(enabled_irq_mask & ~interrupt_mask); 65515a17aaeSDaniel Vetter 65667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 657fee884edSDaniel Vetter 6589df7575fSJesse Barnes if (WARN_ON(!intel_irqs_enabled(dev_priv))) 659c67a470bSPaulo Zanoni return; 660c67a470bSPaulo Zanoni 661fee884edSDaniel Vetter I915_WRITE(SDEIMR, sdeimr); 662fee884edSDaniel Vetter POSTING_READ(SDEIMR); 663fee884edSDaniel Vetter } 6648664281bSPaulo Zanoni 6656b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 6666b12ca56SVille Syrjälä enum pipe pipe) 6677c463586SKeith Packard { 6686b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 66910c59c51SImre Deak u32 enable_mask = status_mask << 16; 67010c59c51SImre Deak 6716b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 6726b12ca56SVille Syrjälä 6736b12ca56SVille Syrjälä if (INTEL_GEN(dev_priv) < 5) 6746b12ca56SVille Syrjälä goto out; 6756b12ca56SVille Syrjälä 67610c59c51SImre Deak /* 677724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 678724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 67910c59c51SImre Deak */ 68010c59c51SImre Deak if (WARN_ON_ONCE(status_mask & PIPE_A_PSR_STATUS_VLV)) 68110c59c51SImre Deak return 0; 682724a6905SVille Syrjälä /* 683724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 684724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 685724a6905SVille Syrjälä */ 686724a6905SVille Syrjälä if (WARN_ON_ONCE(status_mask & PIPE_B_PSR_STATUS_VLV)) 687724a6905SVille Syrjälä return 0; 68810c59c51SImre Deak 68910c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 69010c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 69110c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 69210c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 69310c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 69410c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 69510c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 69610c59c51SImre Deak 6976b12ca56SVille Syrjälä out: 6986b12ca56SVille Syrjälä WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 6996b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 7006b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 7016b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 7026b12ca56SVille Syrjälä 70310c59c51SImre Deak return enable_mask; 70410c59c51SImre Deak } 70510c59c51SImre Deak 7066b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 7076b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 708755e9019SImre Deak { 7096b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 710755e9019SImre Deak u32 enable_mask; 711755e9019SImre Deak 7126b12ca56SVille Syrjälä WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, 7136b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 7146b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 7156b12ca56SVille Syrjälä 7166b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 7176b12ca56SVille Syrjälä WARN_ON(!intel_irqs_enabled(dev_priv)); 7186b12ca56SVille Syrjälä 7196b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 7206b12ca56SVille Syrjälä return; 7216b12ca56SVille Syrjälä 7226b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 7236b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 7246b12ca56SVille Syrjälä 7256b12ca56SVille Syrjälä I915_WRITE(reg, enable_mask | status_mask); 7266b12ca56SVille Syrjälä POSTING_READ(reg); 727755e9019SImre Deak } 728755e9019SImre Deak 7296b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 7306b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 731755e9019SImre Deak { 7326b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 733755e9019SImre Deak u32 enable_mask; 734755e9019SImre Deak 7356b12ca56SVille Syrjälä WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, 7366b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 7376b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 7386b12ca56SVille Syrjälä 7396b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 7406b12ca56SVille Syrjälä WARN_ON(!intel_irqs_enabled(dev_priv)); 7416b12ca56SVille Syrjälä 7426b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 7436b12ca56SVille Syrjälä return; 7446b12ca56SVille Syrjälä 7456b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 7466b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 7476b12ca56SVille Syrjälä 7486b12ca56SVille Syrjälä I915_WRITE(reg, enable_mask | status_mask); 7496b12ca56SVille Syrjälä POSTING_READ(reg); 750755e9019SImre Deak } 751755e9019SImre Deak 752f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 753f3e30485SVille Syrjälä { 754f3e30485SVille Syrjälä if (!dev_priv->opregion.asle) 755f3e30485SVille Syrjälä return false; 756f3e30485SVille Syrjälä 757f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 758f3e30485SVille Syrjälä } 759f3e30485SVille Syrjälä 760c0e09200SDave Airlie /** 761f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 76214bb2c11STvrtko Ursulin * @dev_priv: i915 device private 76301c66889SZhao Yakui */ 76491d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 76501c66889SZhao Yakui { 766f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 767f49e38ddSJani Nikula return; 768f49e38ddSJani Nikula 76913321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 77001c66889SZhao Yakui 771755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 77291d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 4) 7733b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 774755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 7751ec14ad3SChris Wilson 77613321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 77701c66889SZhao Yakui } 77801c66889SZhao Yakui 779f75f3746SVille Syrjälä /* 780f75f3746SVille Syrjälä * This timing diagram depicts the video signal in and 781f75f3746SVille Syrjälä * around the vertical blanking period. 782f75f3746SVille Syrjälä * 783f75f3746SVille Syrjälä * Assumptions about the fictitious mode used in this example: 784f75f3746SVille Syrjälä * vblank_start >= 3 785f75f3746SVille Syrjälä * vsync_start = vblank_start + 1 786f75f3746SVille Syrjälä * vsync_end = vblank_start + 2 787f75f3746SVille Syrjälä * vtotal = vblank_start + 3 788f75f3746SVille Syrjälä * 789f75f3746SVille Syrjälä * start of vblank: 790f75f3746SVille Syrjälä * latch double buffered registers 791f75f3746SVille Syrjälä * increment frame counter (ctg+) 792f75f3746SVille Syrjälä * generate start of vblank interrupt (gen4+) 793f75f3746SVille Syrjälä * | 794f75f3746SVille Syrjälä * | frame start: 795f75f3746SVille Syrjälä * | generate frame start interrupt (aka. vblank interrupt) (gmch) 796f75f3746SVille Syrjälä * | may be shifted forward 1-3 extra lines via PIPECONF 797f75f3746SVille Syrjälä * | | 798f75f3746SVille Syrjälä * | | start of vsync: 799f75f3746SVille Syrjälä * | | generate vsync interrupt 800f75f3746SVille Syrjälä * | | | 801f75f3746SVille Syrjälä * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx 802f75f3746SVille Syrjälä * . \hs/ . \hs/ \hs/ \hs/ . \hs/ 803f75f3746SVille Syrjälä * ----va---> <-----------------vb--------------------> <--------va------------- 804f75f3746SVille Syrjälä * | | <----vs-----> | 805f75f3746SVille Syrjälä * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) 806f75f3746SVille Syrjälä * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) 807f75f3746SVille Syrjälä * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) 808f75f3746SVille Syrjälä * | | | 809f75f3746SVille Syrjälä * last visible pixel first visible pixel 810f75f3746SVille Syrjälä * | increment frame counter (gen3/4) 811f75f3746SVille Syrjälä * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) 812f75f3746SVille Syrjälä * 813f75f3746SVille Syrjälä * x = horizontal active 814f75f3746SVille Syrjälä * _ = horizontal blanking 815f75f3746SVille Syrjälä * hs = horizontal sync 816f75f3746SVille Syrjälä * va = vertical active 817f75f3746SVille Syrjälä * vb = vertical blanking 818f75f3746SVille Syrjälä * vs = vertical sync 819f75f3746SVille Syrjälä * vbs = vblank_start (number) 820f75f3746SVille Syrjälä * 821f75f3746SVille Syrjälä * Summary: 822f75f3746SVille Syrjälä * - most events happen at the start of horizontal sync 823f75f3746SVille Syrjälä * - frame start happens at the start of horizontal blank, 1-4 lines 824f75f3746SVille Syrjälä * (depending on PIPECONF settings) after the start of vblank 825f75f3746SVille Syrjälä * - gen3/4 pixel and frame counter are synchronized with the start 826f75f3746SVille Syrjälä * of horizontal active on the first line of vertical active 827f75f3746SVille Syrjälä */ 828f75f3746SVille Syrjälä 82942f52ef8SKeith Packard /* Called from drm generic code, passed a 'crtc', which 83042f52ef8SKeith Packard * we use as a pipe index 83142f52ef8SKeith Packard */ 83288e72717SThierry Reding static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe) 8330a3e67a4SJesse Barnes { 834fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 83532db0b65SVille Syrjälä struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 83632db0b65SVille Syrjälä const struct drm_display_mode *mode = &vblank->hwmode; 837f0f59a00SVille Syrjälä i915_reg_t high_frame, low_frame; 8380b2a8e09SVille Syrjälä u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; 839694e409dSVille Syrjälä unsigned long irqflags; 840391f75e2SVille Syrjälä 84132db0b65SVille Syrjälä /* 84232db0b65SVille Syrjälä * On i965gm TV output the frame counter only works up to 84332db0b65SVille Syrjälä * the point when we enable the TV encoder. After that the 84432db0b65SVille Syrjälä * frame counter ceases to work and reads zero. We need a 84532db0b65SVille Syrjälä * vblank wait before enabling the TV encoder and so we 84632db0b65SVille Syrjälä * have to enable vblank interrupts while the frame counter 84732db0b65SVille Syrjälä * is still in a working state. However the core vblank code 84832db0b65SVille Syrjälä * does not like us returning non-zero frame counter values 84932db0b65SVille Syrjälä * when we've told it that we don't have a working frame 85032db0b65SVille Syrjälä * counter. Thus we must stop non-zero values leaking out. 85132db0b65SVille Syrjälä */ 85232db0b65SVille Syrjälä if (!vblank->max_vblank_count) 85332db0b65SVille Syrjälä return 0; 85432db0b65SVille Syrjälä 8550b2a8e09SVille Syrjälä htotal = mode->crtc_htotal; 8560b2a8e09SVille Syrjälä hsync_start = mode->crtc_hsync_start; 8570b2a8e09SVille Syrjälä vbl_start = mode->crtc_vblank_start; 8580b2a8e09SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 8590b2a8e09SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 860391f75e2SVille Syrjälä 8610b2a8e09SVille Syrjälä /* Convert to pixel count */ 8620b2a8e09SVille Syrjälä vbl_start *= htotal; 8630b2a8e09SVille Syrjälä 8640b2a8e09SVille Syrjälä /* Start of vblank event occurs at start of hsync */ 8650b2a8e09SVille Syrjälä vbl_start -= htotal - hsync_start; 8660b2a8e09SVille Syrjälä 8679db4a9c7SJesse Barnes high_frame = PIPEFRAME(pipe); 8689db4a9c7SJesse Barnes low_frame = PIPEFRAMEPIXEL(pipe); 8695eddb70bSChris Wilson 870694e409dSVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 871694e409dSVille Syrjälä 8720a3e67a4SJesse Barnes /* 8730a3e67a4SJesse Barnes * High & low register fields aren't synchronized, so make sure 8740a3e67a4SJesse Barnes * we get a low value that's stable across two reads of the high 8750a3e67a4SJesse Barnes * register. 8760a3e67a4SJesse Barnes */ 8770a3e67a4SJesse Barnes do { 878694e409dSVille Syrjälä high1 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK; 879694e409dSVille Syrjälä low = I915_READ_FW(low_frame); 880694e409dSVille Syrjälä high2 = I915_READ_FW(high_frame) & PIPE_FRAME_HIGH_MASK; 8810a3e67a4SJesse Barnes } while (high1 != high2); 8820a3e67a4SJesse Barnes 883694e409dSVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 884694e409dSVille Syrjälä 8855eddb70bSChris Wilson high1 >>= PIPE_FRAME_HIGH_SHIFT; 886391f75e2SVille Syrjälä pixel = low & PIPE_PIXEL_MASK; 8875eddb70bSChris Wilson low >>= PIPE_FRAME_LOW_SHIFT; 888391f75e2SVille Syrjälä 889391f75e2SVille Syrjälä /* 890391f75e2SVille Syrjälä * The frame counter increments at beginning of active. 891391f75e2SVille Syrjälä * Cook up a vblank counter by also checking the pixel 892391f75e2SVille Syrjälä * counter against vblank start. 893391f75e2SVille Syrjälä */ 894edc08d0aSVille Syrjälä return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; 8950a3e67a4SJesse Barnes } 8960a3e67a4SJesse Barnes 897974e59baSDave Airlie static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe) 8989880b7a5SJesse Barnes { 899fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 9009880b7a5SJesse Barnes 901649636efSVille Syrjälä return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); 9029880b7a5SJesse Barnes } 9039880b7a5SJesse Barnes 904aec0246fSUma Shankar /* 905aec0246fSUma Shankar * On certain encoders on certain platforms, pipe 906aec0246fSUma Shankar * scanline register will not work to get the scanline, 907aec0246fSUma Shankar * since the timings are driven from the PORT or issues 908aec0246fSUma Shankar * with scanline register updates. 909aec0246fSUma Shankar * This function will use Framestamp and current 910aec0246fSUma Shankar * timestamp registers to calculate the scanline. 911aec0246fSUma Shankar */ 912aec0246fSUma Shankar static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) 913aec0246fSUma Shankar { 914aec0246fSUma Shankar struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 915aec0246fSUma Shankar struct drm_vblank_crtc *vblank = 916aec0246fSUma Shankar &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 917aec0246fSUma Shankar const struct drm_display_mode *mode = &vblank->hwmode; 918aec0246fSUma Shankar u32 vblank_start = mode->crtc_vblank_start; 919aec0246fSUma Shankar u32 vtotal = mode->crtc_vtotal; 920aec0246fSUma Shankar u32 htotal = mode->crtc_htotal; 921aec0246fSUma Shankar u32 clock = mode->crtc_clock; 922aec0246fSUma Shankar u32 scanline, scan_prev_time, scan_curr_time, scan_post_time; 923aec0246fSUma Shankar 924aec0246fSUma Shankar /* 925aec0246fSUma Shankar * To avoid the race condition where we might cross into the 926aec0246fSUma Shankar * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR 927aec0246fSUma Shankar * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR 928aec0246fSUma Shankar * during the same frame. 929aec0246fSUma Shankar */ 930aec0246fSUma Shankar do { 931aec0246fSUma Shankar /* 932aec0246fSUma Shankar * This field provides read back of the display 933aec0246fSUma Shankar * pipe frame time stamp. The time stamp value 934aec0246fSUma Shankar * is sampled at every start of vertical blank. 935aec0246fSUma Shankar */ 936aec0246fSUma Shankar scan_prev_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); 937aec0246fSUma Shankar 938aec0246fSUma Shankar /* 939aec0246fSUma Shankar * The TIMESTAMP_CTR register has the current 940aec0246fSUma Shankar * time stamp value. 941aec0246fSUma Shankar */ 942aec0246fSUma Shankar scan_curr_time = I915_READ_FW(IVB_TIMESTAMP_CTR); 943aec0246fSUma Shankar 944aec0246fSUma Shankar scan_post_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); 945aec0246fSUma Shankar } while (scan_post_time != scan_prev_time); 946aec0246fSUma Shankar 947aec0246fSUma Shankar scanline = div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, 948aec0246fSUma Shankar clock), 1000 * htotal); 949aec0246fSUma Shankar scanline = min(scanline, vtotal - 1); 950aec0246fSUma Shankar scanline = (scanline + vblank_start) % vtotal; 951aec0246fSUma Shankar 952aec0246fSUma Shankar return scanline; 953aec0246fSUma Shankar } 954aec0246fSUma Shankar 95575aa3f63SVille Syrjälä /* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */ 956a225f079SVille Syrjälä static int __intel_get_crtc_scanline(struct intel_crtc *crtc) 957a225f079SVille Syrjälä { 958a225f079SVille Syrjälä struct drm_device *dev = crtc->base.dev; 959fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 9605caa0feaSDaniel Vetter const struct drm_display_mode *mode; 9615caa0feaSDaniel Vetter struct drm_vblank_crtc *vblank; 962a225f079SVille Syrjälä enum pipe pipe = crtc->pipe; 96380715b2fSVille Syrjälä int position, vtotal; 964a225f079SVille Syrjälä 96572259536SVille Syrjälä if (!crtc->active) 96672259536SVille Syrjälä return -1; 96772259536SVille Syrjälä 9685caa0feaSDaniel Vetter vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 9695caa0feaSDaniel Vetter mode = &vblank->hwmode; 9705caa0feaSDaniel Vetter 971aec0246fSUma Shankar if (mode->private_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) 972aec0246fSUma Shankar return __intel_get_crtc_scanline_from_timestamp(crtc); 973aec0246fSUma Shankar 97480715b2fSVille Syrjälä vtotal = mode->crtc_vtotal; 975a225f079SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 976a225f079SVille Syrjälä vtotal /= 2; 977a225f079SVille Syrjälä 978cf819effSLucas De Marchi if (IS_GEN(dev_priv, 2)) 97975aa3f63SVille Syrjälä position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; 980a225f079SVille Syrjälä else 98175aa3f63SVille Syrjälä position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 982a225f079SVille Syrjälä 983a225f079SVille Syrjälä /* 98441b578fbSJesse Barnes * On HSW, the DSL reg (0x70000) appears to return 0 if we 98541b578fbSJesse Barnes * read it just before the start of vblank. So try it again 98641b578fbSJesse Barnes * so we don't accidentally end up spanning a vblank frame 98741b578fbSJesse Barnes * increment, causing the pipe_update_end() code to squak at us. 98841b578fbSJesse Barnes * 98941b578fbSJesse Barnes * The nature of this problem means we can't simply check the ISR 99041b578fbSJesse Barnes * bit and return the vblank start value; nor can we use the scanline 99141b578fbSJesse Barnes * debug register in the transcoder as it appears to have the same 99241b578fbSJesse Barnes * problem. We may need to extend this to include other platforms, 99341b578fbSJesse Barnes * but so far testing only shows the problem on HSW. 99441b578fbSJesse Barnes */ 99591d14251STvrtko Ursulin if (HAS_DDI(dev_priv) && !position) { 99641b578fbSJesse Barnes int i, temp; 99741b578fbSJesse Barnes 99841b578fbSJesse Barnes for (i = 0; i < 100; i++) { 99941b578fbSJesse Barnes udelay(1); 1000707bdd3fSVille Syrjälä temp = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 100141b578fbSJesse Barnes if (temp != position) { 100241b578fbSJesse Barnes position = temp; 100341b578fbSJesse Barnes break; 100441b578fbSJesse Barnes } 100541b578fbSJesse Barnes } 100641b578fbSJesse Barnes } 100741b578fbSJesse Barnes 100841b578fbSJesse Barnes /* 100980715b2fSVille Syrjälä * See update_scanline_offset() for the details on the 101080715b2fSVille Syrjälä * scanline_offset adjustment. 1011a225f079SVille Syrjälä */ 101280715b2fSVille Syrjälä return (position + crtc->scanline_offset) % vtotal; 1013a225f079SVille Syrjälä } 1014a225f079SVille Syrjälä 10151bf6ad62SDaniel Vetter static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, 10161bf6ad62SDaniel Vetter bool in_vblank_irq, int *vpos, int *hpos, 10173bb403bfSVille Syrjälä ktime_t *stime, ktime_t *etime, 10183bb403bfSVille Syrjälä const struct drm_display_mode *mode) 10190af7e4dfSMario Kleiner { 1020fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 102198187836SVille Syrjälä struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, 102298187836SVille Syrjälä pipe); 10233aa18df8SVille Syrjälä int position; 102478e8fc6bSVille Syrjälä int vbl_start, vbl_end, hsync_start, htotal, vtotal; 1025ad3543edSMario Kleiner unsigned long irqflags; 10268a920e24SVille Syrjälä bool use_scanline_counter = INTEL_GEN(dev_priv) >= 5 || 10278a920e24SVille Syrjälä IS_G4X(dev_priv) || IS_GEN(dev_priv, 2) || 10288a920e24SVille Syrjälä mode->private_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; 10290af7e4dfSMario Kleiner 1030fc467a22SMaarten Lankhorst if (WARN_ON(!mode->crtc_clock)) { 10310af7e4dfSMario Kleiner DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " 10329db4a9c7SJesse Barnes "pipe %c\n", pipe_name(pipe)); 10331bf6ad62SDaniel Vetter return false; 10340af7e4dfSMario Kleiner } 10350af7e4dfSMario Kleiner 1036c2baf4b7SVille Syrjälä htotal = mode->crtc_htotal; 103778e8fc6bSVille Syrjälä hsync_start = mode->crtc_hsync_start; 1038c2baf4b7SVille Syrjälä vtotal = mode->crtc_vtotal; 1039c2baf4b7SVille Syrjälä vbl_start = mode->crtc_vblank_start; 1040c2baf4b7SVille Syrjälä vbl_end = mode->crtc_vblank_end; 10410af7e4dfSMario Kleiner 1042d31faf65SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1043d31faf65SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 1044d31faf65SVille Syrjälä vbl_end /= 2; 1045d31faf65SVille Syrjälä vtotal /= 2; 1046d31faf65SVille Syrjälä } 1047d31faf65SVille Syrjälä 1048ad3543edSMario Kleiner /* 1049ad3543edSMario Kleiner * Lock uncore.lock, as we will do multiple timing critical raw 1050ad3543edSMario Kleiner * register reads, potentially with preemption disabled, so the 1051ad3543edSMario Kleiner * following code must not block on uncore.lock. 1052ad3543edSMario Kleiner */ 1053ad3543edSMario Kleiner spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 1054ad3543edSMario Kleiner 1055ad3543edSMario Kleiner /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ 1056ad3543edSMario Kleiner 1057ad3543edSMario Kleiner /* Get optional system timestamp before query. */ 1058ad3543edSMario Kleiner if (stime) 1059ad3543edSMario Kleiner *stime = ktime_get(); 1060ad3543edSMario Kleiner 10618a920e24SVille Syrjälä if (use_scanline_counter) { 10620af7e4dfSMario Kleiner /* No obvious pixelcount register. Only query vertical 10630af7e4dfSMario Kleiner * scanout position from Display scan line register. 10640af7e4dfSMario Kleiner */ 1065a225f079SVille Syrjälä position = __intel_get_crtc_scanline(intel_crtc); 10660af7e4dfSMario Kleiner } else { 10670af7e4dfSMario Kleiner /* Have access to pixelcount since start of frame. 10680af7e4dfSMario Kleiner * We can split this into vertical and horizontal 10690af7e4dfSMario Kleiner * scanout position. 10700af7e4dfSMario Kleiner */ 107175aa3f63SVille Syrjälä position = (I915_READ_FW(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; 10720af7e4dfSMario Kleiner 10733aa18df8SVille Syrjälä /* convert to pixel counts */ 10743aa18df8SVille Syrjälä vbl_start *= htotal; 10753aa18df8SVille Syrjälä vbl_end *= htotal; 10763aa18df8SVille Syrjälä vtotal *= htotal; 107778e8fc6bSVille Syrjälä 107878e8fc6bSVille Syrjälä /* 10797e78f1cbSVille Syrjälä * In interlaced modes, the pixel counter counts all pixels, 10807e78f1cbSVille Syrjälä * so one field will have htotal more pixels. In order to avoid 10817e78f1cbSVille Syrjälä * the reported position from jumping backwards when the pixel 10827e78f1cbSVille Syrjälä * counter is beyond the length of the shorter field, just 10837e78f1cbSVille Syrjälä * clamp the position the length of the shorter field. This 10847e78f1cbSVille Syrjälä * matches how the scanline counter based position works since 10857e78f1cbSVille Syrjälä * the scanline counter doesn't count the two half lines. 10867e78f1cbSVille Syrjälä */ 10877e78f1cbSVille Syrjälä if (position >= vtotal) 10887e78f1cbSVille Syrjälä position = vtotal - 1; 10897e78f1cbSVille Syrjälä 10907e78f1cbSVille Syrjälä /* 109178e8fc6bSVille Syrjälä * Start of vblank interrupt is triggered at start of hsync, 109278e8fc6bSVille Syrjälä * just prior to the first active line of vblank. However we 109378e8fc6bSVille Syrjälä * consider lines to start at the leading edge of horizontal 109478e8fc6bSVille Syrjälä * active. So, should we get here before we've crossed into 109578e8fc6bSVille Syrjälä * the horizontal active of the first line in vblank, we would 109678e8fc6bSVille Syrjälä * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, 109778e8fc6bSVille Syrjälä * always add htotal-hsync_start to the current pixel position. 109878e8fc6bSVille Syrjälä */ 109978e8fc6bSVille Syrjälä position = (position + htotal - hsync_start) % vtotal; 11003aa18df8SVille Syrjälä } 11013aa18df8SVille Syrjälä 1102ad3543edSMario Kleiner /* Get optional system timestamp after query. */ 1103ad3543edSMario Kleiner if (etime) 1104ad3543edSMario Kleiner *etime = ktime_get(); 1105ad3543edSMario Kleiner 1106ad3543edSMario Kleiner /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ 1107ad3543edSMario Kleiner 1108ad3543edSMario Kleiner spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 1109ad3543edSMario Kleiner 11103aa18df8SVille Syrjälä /* 11113aa18df8SVille Syrjälä * While in vblank, position will be negative 11123aa18df8SVille Syrjälä * counting up towards 0 at vbl_end. And outside 11133aa18df8SVille Syrjälä * vblank, position will be positive counting 11143aa18df8SVille Syrjälä * up since vbl_end. 11153aa18df8SVille Syrjälä */ 11163aa18df8SVille Syrjälä if (position >= vbl_start) 11173aa18df8SVille Syrjälä position -= vbl_end; 11183aa18df8SVille Syrjälä else 11193aa18df8SVille Syrjälä position += vtotal - vbl_end; 11203aa18df8SVille Syrjälä 11218a920e24SVille Syrjälä if (use_scanline_counter) { 11223aa18df8SVille Syrjälä *vpos = position; 11233aa18df8SVille Syrjälä *hpos = 0; 11243aa18df8SVille Syrjälä } else { 11250af7e4dfSMario Kleiner *vpos = position / htotal; 11260af7e4dfSMario Kleiner *hpos = position - (*vpos * htotal); 11270af7e4dfSMario Kleiner } 11280af7e4dfSMario Kleiner 11291bf6ad62SDaniel Vetter return true; 11300af7e4dfSMario Kleiner } 11310af7e4dfSMario Kleiner 1132a225f079SVille Syrjälä int intel_get_crtc_scanline(struct intel_crtc *crtc) 1133a225f079SVille Syrjälä { 1134fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 1135a225f079SVille Syrjälä unsigned long irqflags; 1136a225f079SVille Syrjälä int position; 1137a225f079SVille Syrjälä 1138a225f079SVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 1139a225f079SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 1140a225f079SVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 1141a225f079SVille Syrjälä 1142a225f079SVille Syrjälä return position; 1143a225f079SVille Syrjälä } 1144a225f079SVille Syrjälä 114591d14251STvrtko Ursulin static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv) 1146f97108d1SJesse Barnes { 1147b5b72e89SMatthew Garrett u32 busy_up, busy_down, max_avg, min_avg; 11489270388eSDaniel Vetter u8 new_delay; 11499270388eSDaniel Vetter 1150d0ecd7e2SDaniel Vetter spin_lock(&mchdev_lock); 1151f97108d1SJesse Barnes 115273edd18fSDaniel Vetter I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); 115373edd18fSDaniel Vetter 115420e4d407SDaniel Vetter new_delay = dev_priv->ips.cur_delay; 11559270388eSDaniel Vetter 11567648fa99SJesse Barnes I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG); 1157b5b72e89SMatthew Garrett busy_up = I915_READ(RCPREVBSYTUPAVG); 1158b5b72e89SMatthew Garrett busy_down = I915_READ(RCPREVBSYTDNAVG); 1159f97108d1SJesse Barnes max_avg = I915_READ(RCBMAXAVG); 1160f97108d1SJesse Barnes min_avg = I915_READ(RCBMINAVG); 1161f97108d1SJesse Barnes 1162f97108d1SJesse Barnes /* Handle RCS change request from hw */ 1163b5b72e89SMatthew Garrett if (busy_up > max_avg) { 116420e4d407SDaniel Vetter if (dev_priv->ips.cur_delay != dev_priv->ips.max_delay) 116520e4d407SDaniel Vetter new_delay = dev_priv->ips.cur_delay - 1; 116620e4d407SDaniel Vetter if (new_delay < dev_priv->ips.max_delay) 116720e4d407SDaniel Vetter new_delay = dev_priv->ips.max_delay; 1168b5b72e89SMatthew Garrett } else if (busy_down < min_avg) { 116920e4d407SDaniel Vetter if (dev_priv->ips.cur_delay != dev_priv->ips.min_delay) 117020e4d407SDaniel Vetter new_delay = dev_priv->ips.cur_delay + 1; 117120e4d407SDaniel Vetter if (new_delay > dev_priv->ips.min_delay) 117220e4d407SDaniel Vetter new_delay = dev_priv->ips.min_delay; 1173f97108d1SJesse Barnes } 1174f97108d1SJesse Barnes 117591d14251STvrtko Ursulin if (ironlake_set_drps(dev_priv, new_delay)) 117620e4d407SDaniel Vetter dev_priv->ips.cur_delay = new_delay; 1177f97108d1SJesse Barnes 1178d0ecd7e2SDaniel Vetter spin_unlock(&mchdev_lock); 11799270388eSDaniel Vetter 1180f97108d1SJesse Barnes return; 1181f97108d1SJesse Barnes } 1182f97108d1SJesse Barnes 118343cf3bf0SChris Wilson static void vlv_c0_read(struct drm_i915_private *dev_priv, 118443cf3bf0SChris Wilson struct intel_rps_ei *ei) 118531685c25SDeepak S { 1186679cb6c1SMika Kuoppala ei->ktime = ktime_get_raw(); 118743cf3bf0SChris Wilson ei->render_c0 = I915_READ(VLV_RENDER_C0_COUNT); 118843cf3bf0SChris Wilson ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT); 118931685c25SDeepak S } 119031685c25SDeepak S 119143cf3bf0SChris Wilson void gen6_rps_reset_ei(struct drm_i915_private *dev_priv) 119243cf3bf0SChris Wilson { 1193562d9baeSSagar Arun Kamble memset(&dev_priv->gt_pm.rps.ei, 0, sizeof(dev_priv->gt_pm.rps.ei)); 119443cf3bf0SChris Wilson } 119543cf3bf0SChris Wilson 119643cf3bf0SChris Wilson static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) 119743cf3bf0SChris Wilson { 1198562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 1199562d9baeSSagar Arun Kamble const struct intel_rps_ei *prev = &rps->ei; 120043cf3bf0SChris Wilson struct intel_rps_ei now; 120143cf3bf0SChris Wilson u32 events = 0; 120243cf3bf0SChris Wilson 1203e0e8c7cbSChris Wilson if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0) 120443cf3bf0SChris Wilson return 0; 120543cf3bf0SChris Wilson 120643cf3bf0SChris Wilson vlv_c0_read(dev_priv, &now); 120731685c25SDeepak S 1208679cb6c1SMika Kuoppala if (prev->ktime) { 1209e0e8c7cbSChris Wilson u64 time, c0; 1210569884e3SChris Wilson u32 render, media; 1211e0e8c7cbSChris Wilson 1212679cb6c1SMika Kuoppala time = ktime_us_delta(now.ktime, prev->ktime); 12138f68d591SChris Wilson 1214e0e8c7cbSChris Wilson time *= dev_priv->czclk_freq; 1215e0e8c7cbSChris Wilson 1216e0e8c7cbSChris Wilson /* Workload can be split between render + media, 1217e0e8c7cbSChris Wilson * e.g. SwapBuffers being blitted in X after being rendered in 1218e0e8c7cbSChris Wilson * mesa. To account for this we need to combine both engines 1219e0e8c7cbSChris Wilson * into our activity counter. 1220e0e8c7cbSChris Wilson */ 1221569884e3SChris Wilson render = now.render_c0 - prev->render_c0; 1222569884e3SChris Wilson media = now.media_c0 - prev->media_c0; 1223569884e3SChris Wilson c0 = max(render, media); 12246b7f6aa7SMika Kuoppala c0 *= 1000 * 100 << 8; /* to usecs and scale to threshold% */ 1225e0e8c7cbSChris Wilson 122660548c55SChris Wilson if (c0 > time * rps->power.up_threshold) 1227e0e8c7cbSChris Wilson events = GEN6_PM_RP_UP_THRESHOLD; 122860548c55SChris Wilson else if (c0 < time * rps->power.down_threshold) 1229e0e8c7cbSChris Wilson events = GEN6_PM_RP_DOWN_THRESHOLD; 123031685c25SDeepak S } 123131685c25SDeepak S 1232562d9baeSSagar Arun Kamble rps->ei = now; 123343cf3bf0SChris Wilson return events; 123431685c25SDeepak S } 123531685c25SDeepak S 12364912d041SBen Widawsky static void gen6_pm_rps_work(struct work_struct *work) 12373b8d8d91SJesse Barnes { 12382d1013ddSJani Nikula struct drm_i915_private *dev_priv = 1239562d9baeSSagar Arun Kamble container_of(work, struct drm_i915_private, gt_pm.rps.work); 1240562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 12417c0a16adSChris Wilson bool client_boost = false; 12428d3afd7dSChris Wilson int new_delay, adj, min, max; 12437c0a16adSChris Wilson u32 pm_iir = 0; 12443b8d8d91SJesse Barnes 124559cdb63dSDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 1246562d9baeSSagar Arun Kamble if (rps->interrupts_enabled) { 1247562d9baeSSagar Arun Kamble pm_iir = fetch_and_zero(&rps->pm_iir); 1248562d9baeSSagar Arun Kamble client_boost = atomic_read(&rps->num_waiters); 1249d4d70aa5SImre Deak } 125059cdb63dSDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 12514912d041SBen Widawsky 125260611c13SPaulo Zanoni /* Make sure we didn't queue anything we're not going to process. */ 1253a6706b45SDeepak S WARN_ON(pm_iir & ~dev_priv->pm_rps_events); 12548d3afd7dSChris Wilson if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost) 12557c0a16adSChris Wilson goto out; 12563b8d8d91SJesse Barnes 12579f817501SSagar Arun Kamble mutex_lock(&dev_priv->pcu_lock); 12587b9e0ae6SChris Wilson 125943cf3bf0SChris Wilson pm_iir |= vlv_wa_c0_ei(dev_priv, pm_iir); 126043cf3bf0SChris Wilson 1261562d9baeSSagar Arun Kamble adj = rps->last_adj; 1262562d9baeSSagar Arun Kamble new_delay = rps->cur_freq; 1263562d9baeSSagar Arun Kamble min = rps->min_freq_softlimit; 1264562d9baeSSagar Arun Kamble max = rps->max_freq_softlimit; 12657b92c1bdSChris Wilson if (client_boost) 1266562d9baeSSagar Arun Kamble max = rps->max_freq; 1267562d9baeSSagar Arun Kamble if (client_boost && new_delay < rps->boost_freq) { 1268562d9baeSSagar Arun Kamble new_delay = rps->boost_freq; 12698d3afd7dSChris Wilson adj = 0; 12708d3afd7dSChris Wilson } else if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { 1271dd75fdc8SChris Wilson if (adj > 0) 1272dd75fdc8SChris Wilson adj *= 2; 1273edcf284bSChris Wilson else /* CHV needs even encode values */ 1274edcf284bSChris Wilson adj = IS_CHERRYVIEW(dev_priv) ? 2 : 1; 12757e79a683SSagar Arun Kamble 1276562d9baeSSagar Arun Kamble if (new_delay >= rps->max_freq_softlimit) 12777e79a683SSagar Arun Kamble adj = 0; 12787b92c1bdSChris Wilson } else if (client_boost) { 1279f5a4c67dSChris Wilson adj = 0; 1280dd75fdc8SChris Wilson } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) { 1281562d9baeSSagar Arun Kamble if (rps->cur_freq > rps->efficient_freq) 1282562d9baeSSagar Arun Kamble new_delay = rps->efficient_freq; 1283562d9baeSSagar Arun Kamble else if (rps->cur_freq > rps->min_freq_softlimit) 1284562d9baeSSagar Arun Kamble new_delay = rps->min_freq_softlimit; 1285dd75fdc8SChris Wilson adj = 0; 1286dd75fdc8SChris Wilson } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { 1287dd75fdc8SChris Wilson if (adj < 0) 1288dd75fdc8SChris Wilson adj *= 2; 1289edcf284bSChris Wilson else /* CHV needs even encode values */ 1290edcf284bSChris Wilson adj = IS_CHERRYVIEW(dev_priv) ? -2 : -1; 12917e79a683SSagar Arun Kamble 1292562d9baeSSagar Arun Kamble if (new_delay <= rps->min_freq_softlimit) 12937e79a683SSagar Arun Kamble adj = 0; 1294dd75fdc8SChris Wilson } else { /* unknown event */ 1295edcf284bSChris Wilson adj = 0; 1296dd75fdc8SChris Wilson } 12973b8d8d91SJesse Barnes 1298562d9baeSSagar Arun Kamble rps->last_adj = adj; 1299edcf284bSChris Wilson 13002a8862d2SChris Wilson /* 13012a8862d2SChris Wilson * Limit deboosting and boosting to keep ourselves at the extremes 13022a8862d2SChris Wilson * when in the respective power modes (i.e. slowly decrease frequencies 13032a8862d2SChris Wilson * while in the HIGH_POWER zone and slowly increase frequencies while 13042a8862d2SChris Wilson * in the LOW_POWER zone). On idle, we will hit the timeout and drop 13052a8862d2SChris Wilson * to the next level quickly, and conversely if busy we expect to 13062a8862d2SChris Wilson * hit a waitboost and rapidly switch into max power. 13072a8862d2SChris Wilson */ 13082a8862d2SChris Wilson if ((adj < 0 && rps->power.mode == HIGH_POWER) || 13092a8862d2SChris Wilson (adj > 0 && rps->power.mode == LOW_POWER)) 13102a8862d2SChris Wilson rps->last_adj = 0; 13112a8862d2SChris Wilson 131279249636SBen Widawsky /* sysfs frequency interfaces may have snuck in while servicing the 131379249636SBen Widawsky * interrupt 131479249636SBen Widawsky */ 1315edcf284bSChris Wilson new_delay += adj; 13168d3afd7dSChris Wilson new_delay = clamp_t(int, new_delay, min, max); 131727544369SDeepak S 13189fcee2f7SChris Wilson if (intel_set_rps(dev_priv, new_delay)) { 13199fcee2f7SChris Wilson DRM_DEBUG_DRIVER("Failed to set new GPU frequency\n"); 1320562d9baeSSagar Arun Kamble rps->last_adj = 0; 13219fcee2f7SChris Wilson } 13223b8d8d91SJesse Barnes 13239f817501SSagar Arun Kamble mutex_unlock(&dev_priv->pcu_lock); 13247c0a16adSChris Wilson 13257c0a16adSChris Wilson out: 13267c0a16adSChris Wilson /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */ 13277c0a16adSChris Wilson spin_lock_irq(&dev_priv->irq_lock); 1328562d9baeSSagar Arun Kamble if (rps->interrupts_enabled) 13297c0a16adSChris Wilson gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events); 13307c0a16adSChris Wilson spin_unlock_irq(&dev_priv->irq_lock); 13313b8d8d91SJesse Barnes } 13323b8d8d91SJesse Barnes 1333e3689190SBen Widawsky 1334e3689190SBen Widawsky /** 1335e3689190SBen Widawsky * ivybridge_parity_work - Workqueue called when a parity error interrupt 1336e3689190SBen Widawsky * occurred. 1337e3689190SBen Widawsky * @work: workqueue struct 1338e3689190SBen Widawsky * 1339e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 1340e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 1341e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 1342e3689190SBen Widawsky */ 1343e3689190SBen Widawsky static void ivybridge_parity_work(struct work_struct *work) 1344e3689190SBen Widawsky { 13452d1013ddSJani Nikula struct drm_i915_private *dev_priv = 1346cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 1347e3689190SBen Widawsky u32 error_status, row, bank, subbank; 134835a85ac6SBen Widawsky char *parity_event[6]; 1349a9c287c9SJani Nikula u32 misccpctl; 1350a9c287c9SJani Nikula u8 slice = 0; 1351e3689190SBen Widawsky 1352e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 1353e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 1354e3689190SBen Widawsky * any time we access those registers. 1355e3689190SBen Widawsky */ 135691c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 1357e3689190SBen Widawsky 135835a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 135935a85ac6SBen Widawsky if (WARN_ON(!dev_priv->l3_parity.which_slice)) 136035a85ac6SBen Widawsky goto out; 136135a85ac6SBen Widawsky 1362e3689190SBen Widawsky misccpctl = I915_READ(GEN7_MISCCPCTL); 1363e3689190SBen Widawsky I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); 1364e3689190SBen Widawsky POSTING_READ(GEN7_MISCCPCTL); 1365e3689190SBen Widawsky 136635a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 1367f0f59a00SVille Syrjälä i915_reg_t reg; 136835a85ac6SBen Widawsky 136935a85ac6SBen Widawsky slice--; 13702d1fe073SJoonas Lahtinen if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv))) 137135a85ac6SBen Widawsky break; 137235a85ac6SBen Widawsky 137335a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 137435a85ac6SBen Widawsky 13756fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 137635a85ac6SBen Widawsky 137735a85ac6SBen Widawsky error_status = I915_READ(reg); 1378e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 1379e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 1380e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 1381e3689190SBen Widawsky 138235a85ac6SBen Widawsky I915_WRITE(reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 138335a85ac6SBen Widawsky POSTING_READ(reg); 1384e3689190SBen Widawsky 1385cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 1386e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 1387e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 1388e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 138935a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 139035a85ac6SBen Widawsky parity_event[5] = NULL; 1391e3689190SBen Widawsky 139291c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 1393e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 1394e3689190SBen Widawsky 139535a85ac6SBen Widawsky DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 139635a85ac6SBen Widawsky slice, row, bank, subbank); 1397e3689190SBen Widawsky 139835a85ac6SBen Widawsky kfree(parity_event[4]); 1399e3689190SBen Widawsky kfree(parity_event[3]); 1400e3689190SBen Widawsky kfree(parity_event[2]); 1401e3689190SBen Widawsky kfree(parity_event[1]); 1402e3689190SBen Widawsky } 1403e3689190SBen Widawsky 140435a85ac6SBen Widawsky I915_WRITE(GEN7_MISCCPCTL, misccpctl); 140535a85ac6SBen Widawsky 140635a85ac6SBen Widawsky out: 140735a85ac6SBen Widawsky WARN_ON(dev_priv->l3_parity.which_slice); 14084cb21832SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 14092d1fe073SJoonas Lahtinen gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv)); 14104cb21832SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 141135a85ac6SBen Widawsky 141291c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 141335a85ac6SBen Widawsky } 141435a85ac6SBen Widawsky 1415261e40b8SVille Syrjälä static void ivybridge_parity_error_irq_handler(struct drm_i915_private *dev_priv, 1416261e40b8SVille Syrjälä u32 iir) 1417e3689190SBen Widawsky { 1418261e40b8SVille Syrjälä if (!HAS_L3_DPF(dev_priv)) 1419e3689190SBen Widawsky return; 1420e3689190SBen Widawsky 1421d0ecd7e2SDaniel Vetter spin_lock(&dev_priv->irq_lock); 1422261e40b8SVille Syrjälä gen5_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv)); 1423d0ecd7e2SDaniel Vetter spin_unlock(&dev_priv->irq_lock); 1424e3689190SBen Widawsky 1425261e40b8SVille Syrjälä iir &= GT_PARITY_ERROR(dev_priv); 142635a85ac6SBen Widawsky if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1) 142735a85ac6SBen Widawsky dev_priv->l3_parity.which_slice |= 1 << 1; 142835a85ac6SBen Widawsky 142935a85ac6SBen Widawsky if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) 143035a85ac6SBen Widawsky dev_priv->l3_parity.which_slice |= 1 << 0; 143135a85ac6SBen Widawsky 1432a4da4fa4SDaniel Vetter queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work); 1433e3689190SBen Widawsky } 1434e3689190SBen Widawsky 1435261e40b8SVille Syrjälä static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv, 1436f1af8fc1SPaulo Zanoni u32 gt_iir) 1437f1af8fc1SPaulo Zanoni { 1438f8973c21SChris Wilson if (gt_iir & GT_RENDER_USER_INTERRUPT) 14398a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 1440f1af8fc1SPaulo Zanoni if (gt_iir & ILK_BSD_USER_INTERRUPT) 14418a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); 1442f1af8fc1SPaulo Zanoni } 1443f1af8fc1SPaulo Zanoni 1444261e40b8SVille Syrjälä static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, 1445e7b4c6b1SDaniel Vetter u32 gt_iir) 1446e7b4c6b1SDaniel Vetter { 1447f8973c21SChris Wilson if (gt_iir & GT_RENDER_USER_INTERRUPT) 14488a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 1449cc609d5dSBen Widawsky if (gt_iir & GT_BSD_USER_INTERRUPT) 14508a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); 1451cc609d5dSBen Widawsky if (gt_iir & GT_BLT_USER_INTERRUPT) 14528a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[BCS0]); 1453e7b4c6b1SDaniel Vetter 1454cc609d5dSBen Widawsky if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | 1455cc609d5dSBen Widawsky GT_BSD_CS_ERROR_INTERRUPT | 1456aaecdf61SDaniel Vetter GT_RENDER_CS_MASTER_ERROR_INTERRUPT)) 1457aaecdf61SDaniel Vetter DRM_DEBUG("Command parser error, gt_iir 0x%08x\n", gt_iir); 1458e3689190SBen Widawsky 1459261e40b8SVille Syrjälä if (gt_iir & GT_PARITY_ERROR(dev_priv)) 1460261e40b8SVille Syrjälä ivybridge_parity_error_irq_handler(dev_priv, gt_iir); 1461e7b4c6b1SDaniel Vetter } 1462e7b4c6b1SDaniel Vetter 14635d3d69d5SChris Wilson static void 146451f6b0f9SChris Wilson gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir) 1465fbcc1a0cSNick Hoath { 146631de7350SChris Wilson bool tasklet = false; 1467f747026cSChris Wilson 1468fd8526e5SChris Wilson if (iir & GT_CONTEXT_SWITCH_INTERRUPT) 14698ea397faSChris Wilson tasklet = true; 147031de7350SChris Wilson 147151f6b0f9SChris Wilson if (iir & GT_RENDER_USER_INTERRUPT) { 147252c0fdb2SChris Wilson intel_engine_breadcrumbs_irq(engine); 147393ffbe8eSMichal Wajdeczko tasklet |= USES_GUC_SUBMISSION(engine->i915); 147431de7350SChris Wilson } 147531de7350SChris Wilson 147631de7350SChris Wilson if (tasklet) 1477fd8526e5SChris Wilson tasklet_hi_schedule(&engine->execlists.tasklet); 1478fbcc1a0cSNick Hoath } 1479fbcc1a0cSNick Hoath 14802e4a5b25SChris Wilson static void gen8_gt_irq_ack(struct drm_i915_private *i915, 148155ef72f2SChris Wilson u32 master_ctl, u32 gt_iir[4]) 1482abd58f01SBen Widawsky { 148325286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 14842e4a5b25SChris Wilson 1485f0fd96f5SChris Wilson #define GEN8_GT_IRQS (GEN8_GT_RCS_IRQ | \ 1486f0fd96f5SChris Wilson GEN8_GT_BCS_IRQ | \ 14878a68d464SChris Wilson GEN8_GT_VCS0_IRQ | \ 1488f0fd96f5SChris Wilson GEN8_GT_VCS1_IRQ | \ 1489f0fd96f5SChris Wilson GEN8_GT_VECS_IRQ | \ 1490f0fd96f5SChris Wilson GEN8_GT_PM_IRQ | \ 1491f0fd96f5SChris Wilson GEN8_GT_GUC_IRQ) 1492f0fd96f5SChris Wilson 1493abd58f01SBen Widawsky if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { 14942e4a5b25SChris Wilson gt_iir[0] = raw_reg_read(regs, GEN8_GT_IIR(0)); 14952e4a5b25SChris Wilson if (likely(gt_iir[0])) 14962e4a5b25SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(0), gt_iir[0]); 1497abd58f01SBen Widawsky } 1498abd58f01SBen Widawsky 14998a68d464SChris Wilson if (master_ctl & (GEN8_GT_VCS0_IRQ | GEN8_GT_VCS1_IRQ)) { 15002e4a5b25SChris Wilson gt_iir[1] = raw_reg_read(regs, GEN8_GT_IIR(1)); 15012e4a5b25SChris Wilson if (likely(gt_iir[1])) 15022e4a5b25SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(1), gt_iir[1]); 150374cdb337SChris Wilson } 150474cdb337SChris Wilson 150526705e20SSagar Arun Kamble if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { 15062e4a5b25SChris Wilson gt_iir[2] = raw_reg_read(regs, GEN8_GT_IIR(2)); 1507f4de7794SChris Wilson if (likely(gt_iir[2])) 1508f4de7794SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(2), gt_iir[2]); 15090961021aSBen Widawsky } 15102e4a5b25SChris Wilson 15112e4a5b25SChris Wilson if (master_ctl & GEN8_GT_VECS_IRQ) { 15122e4a5b25SChris Wilson gt_iir[3] = raw_reg_read(regs, GEN8_GT_IIR(3)); 15132e4a5b25SChris Wilson if (likely(gt_iir[3])) 15142e4a5b25SChris Wilson raw_reg_write(regs, GEN8_GT_IIR(3), gt_iir[3]); 151555ef72f2SChris Wilson } 1516abd58f01SBen Widawsky } 1517abd58f01SBen Widawsky 15182e4a5b25SChris Wilson static void gen8_gt_irq_handler(struct drm_i915_private *i915, 1519f0fd96f5SChris Wilson u32 master_ctl, u32 gt_iir[4]) 1520e30e251aSVille Syrjälä { 1521f0fd96f5SChris Wilson if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { 15228a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[RCS0], 152351f6b0f9SChris Wilson gt_iir[0] >> GEN8_RCS_IRQ_SHIFT); 15248a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[BCS0], 152551f6b0f9SChris Wilson gt_iir[0] >> GEN8_BCS_IRQ_SHIFT); 1526e30e251aSVille Syrjälä } 1527e30e251aSVille Syrjälä 15288a68d464SChris Wilson if (master_ctl & (GEN8_GT_VCS0_IRQ | GEN8_GT_VCS1_IRQ)) { 15298a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[VCS0], 15308a68d464SChris Wilson gt_iir[1] >> GEN8_VCS0_IRQ_SHIFT); 15318a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[VCS1], 153251f6b0f9SChris Wilson gt_iir[1] >> GEN8_VCS1_IRQ_SHIFT); 1533e30e251aSVille Syrjälä } 1534e30e251aSVille Syrjälä 1535f0fd96f5SChris Wilson if (master_ctl & GEN8_GT_VECS_IRQ) { 15368a68d464SChris Wilson gen8_cs_irq_handler(i915->engine[VECS0], 153751f6b0f9SChris Wilson gt_iir[3] >> GEN8_VECS_IRQ_SHIFT); 1538f0fd96f5SChris Wilson } 1539e30e251aSVille Syrjälä 1540f0fd96f5SChris Wilson if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { 15412e4a5b25SChris Wilson gen6_rps_irq_handler(i915, gt_iir[2]); 15422e4a5b25SChris Wilson gen9_guc_irq_handler(i915, gt_iir[2]); 1543e30e251aSVille Syrjälä } 1544f0fd96f5SChris Wilson } 1545e30e251aSVille Syrjälä 1546af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1547121e758eSDhinakaran Pandiyan { 1548af92058fSVille Syrjälä switch (pin) { 1549af92058fSVille Syrjälä case HPD_PORT_C: 1550121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1); 1551af92058fSVille Syrjälä case HPD_PORT_D: 1552121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2); 1553af92058fSVille Syrjälä case HPD_PORT_E: 1554121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3); 1555af92058fSVille Syrjälä case HPD_PORT_F: 1556121e758eSDhinakaran Pandiyan return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4); 1557121e758eSDhinakaran Pandiyan default: 1558121e758eSDhinakaran Pandiyan return false; 1559121e758eSDhinakaran Pandiyan } 1560121e758eSDhinakaran Pandiyan } 1561121e758eSDhinakaran Pandiyan 1562af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 156363c88d22SImre Deak { 1564af92058fSVille Syrjälä switch (pin) { 1565af92058fSVille Syrjälä case HPD_PORT_A: 1566195baa06SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1567af92058fSVille Syrjälä case HPD_PORT_B: 156863c88d22SImre Deak return val & PORTB_HOTPLUG_LONG_DETECT; 1569af92058fSVille Syrjälä case HPD_PORT_C: 157063c88d22SImre Deak return val & PORTC_HOTPLUG_LONG_DETECT; 157163c88d22SImre Deak default: 157263c88d22SImre Deak return false; 157363c88d22SImre Deak } 157463c88d22SImre Deak } 157563c88d22SImre Deak 1576af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 157731604222SAnusha Srivatsa { 1578af92058fSVille Syrjälä switch (pin) { 1579af92058fSVille Syrjälä case HPD_PORT_A: 158031604222SAnusha Srivatsa return val & ICP_DDIA_HPD_LONG_DETECT; 1581af92058fSVille Syrjälä case HPD_PORT_B: 158231604222SAnusha Srivatsa return val & ICP_DDIB_HPD_LONG_DETECT; 158331604222SAnusha Srivatsa default: 158431604222SAnusha Srivatsa return false; 158531604222SAnusha Srivatsa } 158631604222SAnusha Srivatsa } 158731604222SAnusha Srivatsa 1588af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 158931604222SAnusha Srivatsa { 1590af92058fSVille Syrjälä switch (pin) { 1591af92058fSVille Syrjälä case HPD_PORT_C: 159231604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC1); 1593af92058fSVille Syrjälä case HPD_PORT_D: 159431604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC2); 1595af92058fSVille Syrjälä case HPD_PORT_E: 159631604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC3); 1597af92058fSVille Syrjälä case HPD_PORT_F: 159831604222SAnusha Srivatsa return val & ICP_TC_HPD_LONG_DETECT(PORT_TC4); 159931604222SAnusha Srivatsa default: 160031604222SAnusha Srivatsa return false; 160131604222SAnusha Srivatsa } 160231604222SAnusha Srivatsa } 160331604222SAnusha Srivatsa 1604af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) 16056dbf30ceSVille Syrjälä { 1606af92058fSVille Syrjälä switch (pin) { 1607af92058fSVille Syrjälä case HPD_PORT_E: 16086dbf30ceSVille Syrjälä return val & PORTE_HOTPLUG_LONG_DETECT; 16096dbf30ceSVille Syrjälä default: 16106dbf30ceSVille Syrjälä return false; 16116dbf30ceSVille Syrjälä } 16126dbf30ceSVille Syrjälä } 16136dbf30ceSVille Syrjälä 1614af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 161574c0b395SVille Syrjälä { 1616af92058fSVille Syrjälä switch (pin) { 1617af92058fSVille Syrjälä case HPD_PORT_A: 161874c0b395SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1619af92058fSVille Syrjälä case HPD_PORT_B: 162074c0b395SVille Syrjälä return val & PORTB_HOTPLUG_LONG_DETECT; 1621af92058fSVille Syrjälä case HPD_PORT_C: 162274c0b395SVille Syrjälä return val & PORTC_HOTPLUG_LONG_DETECT; 1623af92058fSVille Syrjälä case HPD_PORT_D: 162474c0b395SVille Syrjälä return val & PORTD_HOTPLUG_LONG_DETECT; 162574c0b395SVille Syrjälä default: 162674c0b395SVille Syrjälä return false; 162774c0b395SVille Syrjälä } 162874c0b395SVille Syrjälä } 162974c0b395SVille Syrjälä 1630af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1631e4ce95aaSVille Syrjälä { 1632af92058fSVille Syrjälä switch (pin) { 1633af92058fSVille Syrjälä case HPD_PORT_A: 1634e4ce95aaSVille Syrjälä return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; 1635e4ce95aaSVille Syrjälä default: 1636e4ce95aaSVille Syrjälä return false; 1637e4ce95aaSVille Syrjälä } 1638e4ce95aaSVille Syrjälä } 1639e4ce95aaSVille Syrjälä 1640af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 164113cf5504SDave Airlie { 1642af92058fSVille Syrjälä switch (pin) { 1643af92058fSVille Syrjälä case HPD_PORT_B: 1644676574dfSJani Nikula return val & PORTB_HOTPLUG_LONG_DETECT; 1645af92058fSVille Syrjälä case HPD_PORT_C: 1646676574dfSJani Nikula return val & PORTC_HOTPLUG_LONG_DETECT; 1647af92058fSVille Syrjälä case HPD_PORT_D: 1648676574dfSJani Nikula return val & PORTD_HOTPLUG_LONG_DETECT; 1649676574dfSJani Nikula default: 1650676574dfSJani Nikula return false; 165113cf5504SDave Airlie } 165213cf5504SDave Airlie } 165313cf5504SDave Airlie 1654af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 165513cf5504SDave Airlie { 1656af92058fSVille Syrjälä switch (pin) { 1657af92058fSVille Syrjälä case HPD_PORT_B: 1658676574dfSJani Nikula return val & PORTB_HOTPLUG_INT_LONG_PULSE; 1659af92058fSVille Syrjälä case HPD_PORT_C: 1660676574dfSJani Nikula return val & PORTC_HOTPLUG_INT_LONG_PULSE; 1661af92058fSVille Syrjälä case HPD_PORT_D: 1662676574dfSJani Nikula return val & PORTD_HOTPLUG_INT_LONG_PULSE; 1663676574dfSJani Nikula default: 1664676574dfSJani Nikula return false; 166513cf5504SDave Airlie } 166613cf5504SDave Airlie } 166713cf5504SDave Airlie 166842db67d6SVille Syrjälä /* 166942db67d6SVille Syrjälä * Get a bit mask of pins that have triggered, and which ones may be long. 167042db67d6SVille Syrjälä * This can be called multiple times with the same masks to accumulate 167142db67d6SVille Syrjälä * hotplug detection results from several registers. 167242db67d6SVille Syrjälä * 167342db67d6SVille Syrjälä * Note that the caller is expected to zero out the masks initially. 167442db67d6SVille Syrjälä */ 1675cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, 1676cf53902fSRodrigo Vivi u32 *pin_mask, u32 *long_mask, 16778c841e57SJani Nikula u32 hotplug_trigger, u32 dig_hotplug_reg, 1678fd63e2a9SImre Deak const u32 hpd[HPD_NUM_PINS], 1679af92058fSVille Syrjälä bool long_pulse_detect(enum hpd_pin pin, u32 val)) 1680676574dfSJani Nikula { 1681e9be2850SVille Syrjälä enum hpd_pin pin; 1682676574dfSJani Nikula 1683e9be2850SVille Syrjälä for_each_hpd_pin(pin) { 1684e9be2850SVille Syrjälä if ((hpd[pin] & hotplug_trigger) == 0) 16858c841e57SJani Nikula continue; 16868c841e57SJani Nikula 1687e9be2850SVille Syrjälä *pin_mask |= BIT(pin); 1688676574dfSJani Nikula 1689af92058fSVille Syrjälä if (long_pulse_detect(pin, dig_hotplug_reg)) 1690e9be2850SVille Syrjälä *long_mask |= BIT(pin); 1691676574dfSJani Nikula } 1692676574dfSJani Nikula 1693f88f0478SVille Syrjälä DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n", 1694f88f0478SVille Syrjälä hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); 1695676574dfSJani Nikula 1696676574dfSJani Nikula } 1697676574dfSJani Nikula 169891d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv) 1699515ac2bbSDaniel Vetter { 170028c70f16SDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1701515ac2bbSDaniel Vetter } 1702515ac2bbSDaniel Vetter 170391d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) 1704ce99c256SDaniel Vetter { 17059ee32feaSDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1706ce99c256SDaniel Vetter } 1707ce99c256SDaniel Vetter 17088bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 170991d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 171091d14251STvrtko Ursulin enum pipe pipe, 1711a9c287c9SJani Nikula u32 crc0, u32 crc1, 1712a9c287c9SJani Nikula u32 crc2, u32 crc3, 1713a9c287c9SJani Nikula u32 crc4) 17148bf1e9f1SShuang He { 17158bf1e9f1SShuang He struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; 17168c6b709dSTomeu Vizoso struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); 17175cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 17185cee6c45SVille Syrjälä 17195cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 1720b2c88f5bSDamien Lespiau 1721d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 17228c6b709dSTomeu Vizoso /* 17238c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 17248c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 17258c6b709dSTomeu Vizoso * out the buggy result. 17268c6b709dSTomeu Vizoso * 1727163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 17288c6b709dSTomeu Vizoso * don't trust that one either. 17298c6b709dSTomeu Vizoso */ 1730033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 1731163e8aecSRodrigo Vivi (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 17328c6b709dSTomeu Vizoso pipe_crc->skipped++; 17338c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 17348c6b709dSTomeu Vizoso return; 17358c6b709dSTomeu Vizoso } 17368c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 17376cc42152SMaarten Lankhorst 1738246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 1739ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 1740246ee524STomeu Vizoso crcs); 17418c6b709dSTomeu Vizoso } 1742277de95eSDaniel Vetter #else 1743277de95eSDaniel Vetter static inline void 174491d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 174591d14251STvrtko Ursulin enum pipe pipe, 1746a9c287c9SJani Nikula u32 crc0, u32 crc1, 1747a9c287c9SJani Nikula u32 crc2, u32 crc3, 1748a9c287c9SJani Nikula u32 crc4) {} 1749277de95eSDaniel Vetter #endif 1750eba94eb9SDaniel Vetter 1751277de95eSDaniel Vetter 175291d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 175391d14251STvrtko Ursulin enum pipe pipe) 17545a69b89fSDaniel Vetter { 175591d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 17565a69b89fSDaniel Vetter I915_READ(PIPE_CRC_RES_1_IVB(pipe)), 17575a69b89fSDaniel Vetter 0, 0, 0, 0); 17585a69b89fSDaniel Vetter } 17595a69b89fSDaniel Vetter 176091d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 176191d14251STvrtko Ursulin enum pipe pipe) 1762eba94eb9SDaniel Vetter { 176391d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 1764eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_1_IVB(pipe)), 1765eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_2_IVB(pipe)), 1766eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_3_IVB(pipe)), 1767eba94eb9SDaniel Vetter I915_READ(PIPE_CRC_RES_4_IVB(pipe)), 17688bc5e955SDaniel Vetter I915_READ(PIPE_CRC_RES_5_IVB(pipe))); 1769eba94eb9SDaniel Vetter } 17705b3a856bSDaniel Vetter 177191d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 177291d14251STvrtko Ursulin enum pipe pipe) 17735b3a856bSDaniel Vetter { 1774a9c287c9SJani Nikula u32 res1, res2; 17750b5c5ed0SDaniel Vetter 177691d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 3) 17770b5c5ed0SDaniel Vetter res1 = I915_READ(PIPE_CRC_RES_RES1_I915(pipe)); 17780b5c5ed0SDaniel Vetter else 17790b5c5ed0SDaniel Vetter res1 = 0; 17800b5c5ed0SDaniel Vetter 178191d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) 17820b5c5ed0SDaniel Vetter res2 = I915_READ(PIPE_CRC_RES_RES2_G4X(pipe)); 17830b5c5ed0SDaniel Vetter else 17840b5c5ed0SDaniel Vetter res2 = 0; 17855b3a856bSDaniel Vetter 178691d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 17870b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_RED(pipe)), 17880b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_GREEN(pipe)), 17890b5c5ed0SDaniel Vetter I915_READ(PIPE_CRC_RES_BLUE(pipe)), 17900b5c5ed0SDaniel Vetter res1, res2); 17915b3a856bSDaniel Vetter } 17928bf1e9f1SShuang He 17931403c0d4SPaulo Zanoni /* The RPS events need forcewake, so we add them to a work queue and mask their 17941403c0d4SPaulo Zanoni * IMR bits until the work is done. Other interrupts can be processed without 17951403c0d4SPaulo Zanoni * the work queue. */ 17961403c0d4SPaulo Zanoni static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) 1797baf02a1fSBen Widawsky { 1798562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 1799562d9baeSSagar Arun Kamble 1800a6706b45SDeepak S if (pm_iir & dev_priv->pm_rps_events) { 180159cdb63dSDaniel Vetter spin_lock(&dev_priv->irq_lock); 1802f4e9af4fSAkash Goel gen6_mask_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); 1803562d9baeSSagar Arun Kamble if (rps->interrupts_enabled) { 1804562d9baeSSagar Arun Kamble rps->pm_iir |= pm_iir & dev_priv->pm_rps_events; 1805562d9baeSSagar Arun Kamble schedule_work(&rps->work); 180641a05a3aSDaniel Vetter } 1807d4d70aa5SImre Deak spin_unlock(&dev_priv->irq_lock); 1808d4d70aa5SImre Deak } 1809baf02a1fSBen Widawsky 1810bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 8) 1811c9a9a268SImre Deak return; 1812c9a9a268SImre Deak 181312638c57SBen Widawsky if (pm_iir & PM_VEBOX_USER_INTERRUPT) 18148a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VECS0]); 181512638c57SBen Widawsky 1816aaecdf61SDaniel Vetter if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) 1817aaecdf61SDaniel Vetter DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); 181812638c57SBen Widawsky } 1819baf02a1fSBen Widawsky 182026705e20SSagar Arun Kamble static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) 182126705e20SSagar Arun Kamble { 182293bf8096SMichal Wajdeczko if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) 182393bf8096SMichal Wajdeczko intel_guc_to_host_event_handler(&dev_priv->guc); 182426705e20SSagar Arun Kamble } 182526705e20SSagar Arun Kamble 182644d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 182744d9241eSVille Syrjälä { 182844d9241eSVille Syrjälä enum pipe pipe; 182944d9241eSVille Syrjälä 183044d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 183144d9241eSVille Syrjälä I915_WRITE(PIPESTAT(pipe), 183244d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 183344d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 183444d9241eSVille Syrjälä 183544d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 183644d9241eSVille Syrjälä } 183744d9241eSVille Syrjälä } 183844d9241eSVille Syrjälä 1839eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 184091d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 18417e231dbeSJesse Barnes { 18427e231dbeSJesse Barnes int pipe; 18437e231dbeSJesse Barnes 184458ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 18451ca993d2SVille Syrjälä 18461ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 18471ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 18481ca993d2SVille Syrjälä return; 18491ca993d2SVille Syrjälä } 18501ca993d2SVille Syrjälä 1851055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1852f0f59a00SVille Syrjälä i915_reg_t reg; 18536b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 185491d181ddSImre Deak 1855bbb5eebfSDaniel Vetter /* 1856bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 1857bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 1858bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 1859bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 1860bbb5eebfSDaniel Vetter * handle. 1861bbb5eebfSDaniel Vetter */ 18620f239f4cSDaniel Vetter 18630f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 18646b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 1865bbb5eebfSDaniel Vetter 1866bbb5eebfSDaniel Vetter switch (pipe) { 1867bbb5eebfSDaniel Vetter case PIPE_A: 1868bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 1869bbb5eebfSDaniel Vetter break; 1870bbb5eebfSDaniel Vetter case PIPE_B: 1871bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1872bbb5eebfSDaniel Vetter break; 18733278f67fSVille Syrjälä case PIPE_C: 18743278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 18753278f67fSVille Syrjälä break; 1876bbb5eebfSDaniel Vetter } 1877bbb5eebfSDaniel Vetter if (iir & iir_bit) 18786b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 1879bbb5eebfSDaniel Vetter 18806b12ca56SVille Syrjälä if (!status_mask) 188191d181ddSImre Deak continue; 188291d181ddSImre Deak 188391d181ddSImre Deak reg = PIPESTAT(pipe); 18846b12ca56SVille Syrjälä pipe_stats[pipe] = I915_READ(reg) & status_mask; 18856b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 18867e231dbeSJesse Barnes 18877e231dbeSJesse Barnes /* 18887e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 1889132c27c9SVille Syrjälä * 1890132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 1891132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 1892132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 1893132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 1894132c27c9SVille Syrjälä * an interrupt is still pending. 18957e231dbeSJesse Barnes */ 1896132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 1897132c27c9SVille Syrjälä I915_WRITE(reg, pipe_stats[pipe]); 1898132c27c9SVille Syrjälä I915_WRITE(reg, enable_mask); 1899132c27c9SVille Syrjälä } 19007e231dbeSJesse Barnes } 190158ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 19022ecb8ca4SVille Syrjälä } 19032ecb8ca4SVille Syrjälä 1904eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1905eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 1906eb64343cSVille Syrjälä { 1907eb64343cSVille Syrjälä enum pipe pipe; 1908eb64343cSVille Syrjälä 1909eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1910eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1911eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1912eb64343cSVille Syrjälä 1913eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1914eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1915eb64343cSVille Syrjälä 1916eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1917eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1918eb64343cSVille Syrjälä } 1919eb64343cSVille Syrjälä } 1920eb64343cSVille Syrjälä 1921eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1922eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1923eb64343cSVille Syrjälä { 1924eb64343cSVille Syrjälä bool blc_event = false; 1925eb64343cSVille Syrjälä enum pipe pipe; 1926eb64343cSVille Syrjälä 1927eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1928eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1929eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1930eb64343cSVille Syrjälä 1931eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1932eb64343cSVille Syrjälä blc_event = true; 1933eb64343cSVille Syrjälä 1934eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1935eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1936eb64343cSVille Syrjälä 1937eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1938eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1939eb64343cSVille Syrjälä } 1940eb64343cSVille Syrjälä 1941eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1942eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1943eb64343cSVille Syrjälä } 1944eb64343cSVille Syrjälä 1945eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1946eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1947eb64343cSVille Syrjälä { 1948eb64343cSVille Syrjälä bool blc_event = false; 1949eb64343cSVille Syrjälä enum pipe pipe; 1950eb64343cSVille Syrjälä 1951eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1952eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1953eb64343cSVille Syrjälä drm_handle_vblank(&dev_priv->drm, pipe); 1954eb64343cSVille Syrjälä 1955eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1956eb64343cSVille Syrjälä blc_event = true; 1957eb64343cSVille Syrjälä 1958eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1959eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1960eb64343cSVille Syrjälä 1961eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1962eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1963eb64343cSVille Syrjälä } 1964eb64343cSVille Syrjälä 1965eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1966eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1967eb64343cSVille Syrjälä 1968eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 1969eb64343cSVille Syrjälä gmbus_irq_handler(dev_priv); 1970eb64343cSVille Syrjälä } 1971eb64343cSVille Syrjälä 197291d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 19732ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 19742ecb8ca4SVille Syrjälä { 19752ecb8ca4SVille Syrjälä enum pipe pipe; 19767e231dbeSJesse Barnes 1977055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1978fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1979fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 19804356d586SDaniel Vetter 19814356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 198291d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 19832d9d2b0bSVille Syrjälä 19841f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 19851f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 198631acc7f5SJesse Barnes } 198731acc7f5SJesse Barnes 1988c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 198991d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1990c1874ed7SImre Deak } 1991c1874ed7SImre Deak 19921ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 199316c6c56bSVille Syrjälä { 19940ba7c51aSVille Syrjälä u32 hotplug_status = 0, hotplug_status_mask; 19950ba7c51aSVille Syrjälä int i; 199616c6c56bSVille Syrjälä 19970ba7c51aSVille Syrjälä if (IS_G4X(dev_priv) || 19980ba7c51aSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 19990ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | 20000ba7c51aSVille Syrjälä DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; 20010ba7c51aSVille Syrjälä else 20020ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_I915; 20030ba7c51aSVille Syrjälä 20040ba7c51aSVille Syrjälä /* 20050ba7c51aSVille Syrjälä * We absolutely have to clear all the pending interrupt 20060ba7c51aSVille Syrjälä * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port 20070ba7c51aSVille Syrjälä * interrupt bit won't have an edge, and the i965/g4x 20080ba7c51aSVille Syrjälä * edge triggered IIR will not notice that an interrupt 20090ba7c51aSVille Syrjälä * is still pending. We can't use PORT_HOTPLUG_EN to 20100ba7c51aSVille Syrjälä * guarantee the edge as the act of toggling the enable 20110ba7c51aSVille Syrjälä * bits can itself generate a new hotplug interrupt :( 20120ba7c51aSVille Syrjälä */ 20130ba7c51aSVille Syrjälä for (i = 0; i < 10; i++) { 20140ba7c51aSVille Syrjälä u32 tmp = I915_READ(PORT_HOTPLUG_STAT) & hotplug_status_mask; 20150ba7c51aSVille Syrjälä 20160ba7c51aSVille Syrjälä if (tmp == 0) 20170ba7c51aSVille Syrjälä return hotplug_status; 20180ba7c51aSVille Syrjälä 20190ba7c51aSVille Syrjälä hotplug_status |= tmp; 20203ff60f89SOscar Mateo I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); 20210ba7c51aSVille Syrjälä } 20220ba7c51aSVille Syrjälä 20230ba7c51aSVille Syrjälä WARN_ONCE(1, 20240ba7c51aSVille Syrjälä "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", 20250ba7c51aSVille Syrjälä I915_READ(PORT_HOTPLUG_STAT)); 20261ae3c34cSVille Syrjälä 20271ae3c34cSVille Syrjälä return hotplug_status; 20281ae3c34cSVille Syrjälä } 20291ae3c34cSVille Syrjälä 203091d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, 20311ae3c34cSVille Syrjälä u32 hotplug_status) 20321ae3c34cSVille Syrjälä { 20331ae3c34cSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 20343ff60f89SOscar Mateo 203591d14251STvrtko Ursulin if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || 203691d14251STvrtko Ursulin IS_CHERRYVIEW(dev_priv)) { 203716c6c56bSVille Syrjälä u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; 203816c6c56bSVille Syrjälä 203958f2cf24SVille Syrjälä if (hotplug_trigger) { 2040cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2041cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 2042cf53902fSRodrigo Vivi hpd_status_g4x, 2043fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 204458f2cf24SVille Syrjälä 204591d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 204658f2cf24SVille Syrjälä } 2047369712e8SJani Nikula 2048369712e8SJani Nikula if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) 204991d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 205016c6c56bSVille Syrjälä } else { 205116c6c56bSVille Syrjälä u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; 205216c6c56bSVille Syrjälä 205358f2cf24SVille Syrjälä if (hotplug_trigger) { 2054cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2055cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 2056cf53902fSRodrigo Vivi hpd_status_i915, 2057fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 205891d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 205916c6c56bSVille Syrjälä } 20603ff60f89SOscar Mateo } 206158f2cf24SVille Syrjälä } 206216c6c56bSVille Syrjälä 2063c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 2064c1874ed7SImre Deak { 206545a83f84SDaniel Vetter struct drm_device *dev = arg; 2066fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 2067c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 2068c1874ed7SImre Deak 20692dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 20702dd2a883SImre Deak return IRQ_NONE; 20712dd2a883SImre Deak 20721f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 20731f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 20741f814dacSImre Deak 20751e1cace9SVille Syrjälä do { 20766e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 20772ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 20781ae3c34cSVille Syrjälä u32 hotplug_status = 0; 2079a5e485a9SVille Syrjälä u32 ier = 0; 20803ff60f89SOscar Mateo 2081c1874ed7SImre Deak gt_iir = I915_READ(GTIIR); 2082c1874ed7SImre Deak pm_iir = I915_READ(GEN6_PMIIR); 20833ff60f89SOscar Mateo iir = I915_READ(VLV_IIR); 2084c1874ed7SImre Deak 2085c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 20861e1cace9SVille Syrjälä break; 2087c1874ed7SImre Deak 2088c1874ed7SImre Deak ret = IRQ_HANDLED; 2089c1874ed7SImre Deak 2090a5e485a9SVille Syrjälä /* 2091a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 2092a5e485a9SVille Syrjälä * 2093a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 2094a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 2095a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 2096a5e485a9SVille Syrjälä * 2097a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 2098a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 2099a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 2100a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 2101a5e485a9SVille Syrjälä * bits this time around. 2102a5e485a9SVille Syrjälä */ 21034a0a0202SVille Syrjälä I915_WRITE(VLV_MASTER_IER, 0); 2104a5e485a9SVille Syrjälä ier = I915_READ(VLV_IER); 2105a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, 0); 21064a0a0202SVille Syrjälä 21074a0a0202SVille Syrjälä if (gt_iir) 21084a0a0202SVille Syrjälä I915_WRITE(GTIIR, gt_iir); 21094a0a0202SVille Syrjälä if (pm_iir) 21104a0a0202SVille Syrjälä I915_WRITE(GEN6_PMIIR, pm_iir); 21114a0a0202SVille Syrjälä 21127ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 21131ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 21147ce4d1f2SVille Syrjälä 21153ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 21163ff60f89SOscar Mateo * signalled in iir */ 2117eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 21187ce4d1f2SVille Syrjälä 2119eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 2120eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 2121eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 2122eef57324SJerome Anand 21237ce4d1f2SVille Syrjälä /* 21247ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 21257ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 21267ce4d1f2SVille Syrjälä */ 21277ce4d1f2SVille Syrjälä if (iir) 21287ce4d1f2SVille Syrjälä I915_WRITE(VLV_IIR, iir); 21294a0a0202SVille Syrjälä 2130a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, ier); 21314a0a0202SVille Syrjälä I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 21321ae3c34cSVille Syrjälä 213352894874SVille Syrjälä if (gt_iir) 2134261e40b8SVille Syrjälä snb_gt_irq_handler(dev_priv, gt_iir); 213552894874SVille Syrjälä if (pm_iir) 213652894874SVille Syrjälä gen6_rps_irq_handler(dev_priv, pm_iir); 213752894874SVille Syrjälä 21381ae3c34cSVille Syrjälä if (hotplug_status) 213991d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 21402ecb8ca4SVille Syrjälä 214191d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 21421e1cace9SVille Syrjälä } while (0); 21437e231dbeSJesse Barnes 21441f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 21451f814dacSImre Deak 21467e231dbeSJesse Barnes return ret; 21477e231dbeSJesse Barnes } 21487e231dbeSJesse Barnes 214943f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 215043f328d7SVille Syrjälä { 215145a83f84SDaniel Vetter struct drm_device *dev = arg; 2152fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 215343f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 215443f328d7SVille Syrjälä 21552dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 21562dd2a883SImre Deak return IRQ_NONE; 21572dd2a883SImre Deak 21581f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 21591f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 21601f814dacSImre Deak 2161579de73bSChris Wilson do { 21626e814800SVille Syrjälä u32 master_ctl, iir; 21632ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 21641ae3c34cSVille Syrjälä u32 hotplug_status = 0; 2165f0fd96f5SChris Wilson u32 gt_iir[4]; 2166a5e485a9SVille Syrjälä u32 ier = 0; 2167a5e485a9SVille Syrjälä 21688e5fd599SVille Syrjälä master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 21693278f67fSVille Syrjälä iir = I915_READ(VLV_IIR); 21703278f67fSVille Syrjälä 21713278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 21728e5fd599SVille Syrjälä break; 217343f328d7SVille Syrjälä 217427b6c122SOscar Mateo ret = IRQ_HANDLED; 217527b6c122SOscar Mateo 2176a5e485a9SVille Syrjälä /* 2177a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 2178a5e485a9SVille Syrjälä * 2179a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 2180a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 2181a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 2182a5e485a9SVille Syrjälä * 2183a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 2184a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 2185a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 2186a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 2187a5e485a9SVille Syrjälä * bits this time around. 2188a5e485a9SVille Syrjälä */ 218943f328d7SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, 0); 2190a5e485a9SVille Syrjälä ier = I915_READ(VLV_IER); 2191a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, 0); 219243f328d7SVille Syrjälä 2193e30e251aSVille Syrjälä gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); 219427b6c122SOscar Mateo 219527b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 21961ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 219743f328d7SVille Syrjälä 219827b6c122SOscar Mateo /* Call regardless, as some status bits might not be 219927b6c122SOscar Mateo * signalled in iir */ 2200eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 220143f328d7SVille Syrjälä 2202eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 2203eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 2204eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 2205eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 2206eef57324SJerome Anand 22077ce4d1f2SVille Syrjälä /* 22087ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 22097ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 22107ce4d1f2SVille Syrjälä */ 22117ce4d1f2SVille Syrjälä if (iir) 22127ce4d1f2SVille Syrjälä I915_WRITE(VLV_IIR, iir); 22137ce4d1f2SVille Syrjälä 2214a5e485a9SVille Syrjälä I915_WRITE(VLV_IER, ier); 2215e5328c43SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 22161ae3c34cSVille Syrjälä 2217f0fd96f5SChris Wilson gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); 2218e30e251aSVille Syrjälä 22191ae3c34cSVille Syrjälä if (hotplug_status) 222091d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 22212ecb8ca4SVille Syrjälä 222291d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 2223579de73bSChris Wilson } while (0); 22243278f67fSVille Syrjälä 22251f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 22261f814dacSImre Deak 222743f328d7SVille Syrjälä return ret; 222843f328d7SVille Syrjälä } 222943f328d7SVille Syrjälä 223091d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, 223191d14251STvrtko Ursulin u32 hotplug_trigger, 223240e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2233776ad806SJesse Barnes { 223442db67d6SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2235776ad806SJesse Barnes 22366a39d7c9SJani Nikula /* 22376a39d7c9SJani Nikula * Somehow the PCH doesn't seem to really ack the interrupt to the CPU 22386a39d7c9SJani Nikula * unless we touch the hotplug register, even if hotplug_trigger is 22396a39d7c9SJani Nikula * zero. Not acking leads to "The master control interrupt lied (SDE)!" 22406a39d7c9SJani Nikula * errors. 22416a39d7c9SJani Nikula */ 224213cf5504SDave Airlie dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 22436a39d7c9SJani Nikula if (!hotplug_trigger) { 22446a39d7c9SJani Nikula u32 mask = PORTA_HOTPLUG_STATUS_MASK | 22456a39d7c9SJani Nikula PORTD_HOTPLUG_STATUS_MASK | 22466a39d7c9SJani Nikula PORTC_HOTPLUG_STATUS_MASK | 22476a39d7c9SJani Nikula PORTB_HOTPLUG_STATUS_MASK; 22486a39d7c9SJani Nikula dig_hotplug_reg &= ~mask; 22496a39d7c9SJani Nikula } 22506a39d7c9SJani Nikula 225113cf5504SDave Airlie I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 22526a39d7c9SJani Nikula if (!hotplug_trigger) 22536a39d7c9SJani Nikula return; 225413cf5504SDave Airlie 2255cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 225640e56410SVille Syrjälä dig_hotplug_reg, hpd, 2257fd63e2a9SImre Deak pch_port_hotplug_long_detect); 225840e56410SVille Syrjälä 225991d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2260aaf5ec2eSSonika Jindal } 226191d131d2SDaniel Vetter 226291d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 226340e56410SVille Syrjälä { 226440e56410SVille Syrjälä int pipe; 226540e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 226640e56410SVille Syrjälä 226791d14251STvrtko Ursulin ibx_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ibx); 226840e56410SVille Syrjälä 2269cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 2270cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 2271776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 2272cfc33bf7SVille Syrjälä DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", 2273cfc33bf7SVille Syrjälä port_name(port)); 2274cfc33bf7SVille Syrjälä } 2275776ad806SJesse Barnes 2276ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 227791d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2278ce99c256SDaniel Vetter 2279776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 228091d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 2281776ad806SJesse Barnes 2282776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 2283776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n"); 2284776ad806SJesse Barnes 2285776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 2286776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n"); 2287776ad806SJesse Barnes 2288776ad806SJesse Barnes if (pch_iir & SDE_POISON) 2289776ad806SJesse Barnes DRM_ERROR("PCH poison interrupt\n"); 2290776ad806SJesse Barnes 22919db4a9c7SJesse Barnes if (pch_iir & SDE_FDI_MASK) 2292055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 22939db4a9c7SJesse Barnes DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", 22949db4a9c7SJesse Barnes pipe_name(pipe), 22959db4a9c7SJesse Barnes I915_READ(FDI_RX_IIR(pipe))); 2296776ad806SJesse Barnes 2297776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 2298776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n"); 2299776ad806SJesse Barnes 2300776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 2301776ad806SJesse Barnes DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n"); 2302776ad806SJesse Barnes 2303776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 2304a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 23058664281bSPaulo Zanoni 23068664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 2307a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 23088664281bSPaulo Zanoni } 23098664281bSPaulo Zanoni 231091d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 23118664281bSPaulo Zanoni { 23128664281bSPaulo Zanoni u32 err_int = I915_READ(GEN7_ERR_INT); 23135a69b89fSDaniel Vetter enum pipe pipe; 23148664281bSPaulo Zanoni 2315de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 2316de032bf4SPaulo Zanoni DRM_ERROR("Poison interrupt\n"); 2317de032bf4SPaulo Zanoni 2318055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 23191f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 23201f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 23218664281bSPaulo Zanoni 23225a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 232391d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 232491d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 23255a69b89fSDaniel Vetter else 232691d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 23275a69b89fSDaniel Vetter } 23285a69b89fSDaniel Vetter } 23298bf1e9f1SShuang He 23308664281bSPaulo Zanoni I915_WRITE(GEN7_ERR_INT, err_int); 23318664281bSPaulo Zanoni } 23328664281bSPaulo Zanoni 233391d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 23348664281bSPaulo Zanoni { 23358664281bSPaulo Zanoni u32 serr_int = I915_READ(SERR_INT); 233645c1cd87SMika Kahola enum pipe pipe; 23378664281bSPaulo Zanoni 2338de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 2339de032bf4SPaulo Zanoni DRM_ERROR("PCH poison interrupt\n"); 2340de032bf4SPaulo Zanoni 234145c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 234245c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 234345c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 23448664281bSPaulo Zanoni 23458664281bSPaulo Zanoni I915_WRITE(SERR_INT, serr_int); 2346776ad806SJesse Barnes } 2347776ad806SJesse Barnes 234891d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 234923e81d69SAdam Jackson { 235023e81d69SAdam Jackson int pipe; 23516dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 2352aaf5ec2eSSonika Jindal 235391d14251STvrtko Ursulin ibx_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_cpt); 235491d131d2SDaniel Vetter 2355cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 2356cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 235723e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 2358cfc33bf7SVille Syrjälä DRM_DEBUG_DRIVER("PCH audio power change on port %c\n", 2359cfc33bf7SVille Syrjälä port_name(port)); 2360cfc33bf7SVille Syrjälä } 236123e81d69SAdam Jackson 236223e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 236391d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 236423e81d69SAdam Jackson 236523e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 236691d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 236723e81d69SAdam Jackson 236823e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 236923e81d69SAdam Jackson DRM_DEBUG_DRIVER("Audio CP request interrupt\n"); 237023e81d69SAdam Jackson 237123e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 237223e81d69SAdam Jackson DRM_DEBUG_DRIVER("Audio CP change interrupt\n"); 237323e81d69SAdam Jackson 237423e81d69SAdam Jackson if (pch_iir & SDE_FDI_MASK_CPT) 2375055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 237623e81d69SAdam Jackson DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", 237723e81d69SAdam Jackson pipe_name(pipe), 237823e81d69SAdam Jackson I915_READ(FDI_RX_IIR(pipe))); 23798664281bSPaulo Zanoni 23808664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 238191d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 238223e81d69SAdam Jackson } 238323e81d69SAdam Jackson 238431604222SAnusha Srivatsa static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 238531604222SAnusha Srivatsa { 238631604222SAnusha Srivatsa u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; 238731604222SAnusha Srivatsa u32 tc_hotplug_trigger = pch_iir & SDE_TC_MASK_ICP; 238831604222SAnusha Srivatsa u32 pin_mask = 0, long_mask = 0; 238931604222SAnusha Srivatsa 239031604222SAnusha Srivatsa if (ddi_hotplug_trigger) { 239131604222SAnusha Srivatsa u32 dig_hotplug_reg; 239231604222SAnusha Srivatsa 239331604222SAnusha Srivatsa dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_DDI); 239431604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_DDI, dig_hotplug_reg); 239531604222SAnusha Srivatsa 239631604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 239731604222SAnusha Srivatsa ddi_hotplug_trigger, 239831604222SAnusha Srivatsa dig_hotplug_reg, hpd_icp, 239931604222SAnusha Srivatsa icp_ddi_port_hotplug_long_detect); 240031604222SAnusha Srivatsa } 240131604222SAnusha Srivatsa 240231604222SAnusha Srivatsa if (tc_hotplug_trigger) { 240331604222SAnusha Srivatsa u32 dig_hotplug_reg; 240431604222SAnusha Srivatsa 240531604222SAnusha Srivatsa dig_hotplug_reg = I915_READ(SHOTPLUG_CTL_TC); 240631604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_TC, dig_hotplug_reg); 240731604222SAnusha Srivatsa 240831604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 240931604222SAnusha Srivatsa tc_hotplug_trigger, 241031604222SAnusha Srivatsa dig_hotplug_reg, hpd_icp, 241131604222SAnusha Srivatsa icp_tc_port_hotplug_long_detect); 241231604222SAnusha Srivatsa } 241331604222SAnusha Srivatsa 241431604222SAnusha Srivatsa if (pin_mask) 241531604222SAnusha Srivatsa intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 241631604222SAnusha Srivatsa 241731604222SAnusha Srivatsa if (pch_iir & SDE_GMBUS_ICP) 241831604222SAnusha Srivatsa gmbus_irq_handler(dev_priv); 241931604222SAnusha Srivatsa } 242031604222SAnusha Srivatsa 242191d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 24226dbf30ceSVille Syrjälä { 24236dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & 24246dbf30ceSVille Syrjälä ~SDE_PORTE_HOTPLUG_SPT; 24256dbf30ceSVille Syrjälä u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; 24266dbf30ceSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 24276dbf30ceSVille Syrjälä 24286dbf30ceSVille Syrjälä if (hotplug_trigger) { 24296dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 24306dbf30ceSVille Syrjälä 24316dbf30ceSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 24326dbf30ceSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 24336dbf30ceSVille Syrjälä 2434cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2435cf53902fSRodrigo Vivi hotplug_trigger, dig_hotplug_reg, hpd_spt, 243674c0b395SVille Syrjälä spt_port_hotplug_long_detect); 24376dbf30ceSVille Syrjälä } 24386dbf30ceSVille Syrjälä 24396dbf30ceSVille Syrjälä if (hotplug2_trigger) { 24406dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 24416dbf30ceSVille Syrjälä 24426dbf30ceSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG2); 24436dbf30ceSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG2, dig_hotplug_reg); 24446dbf30ceSVille Syrjälä 2445cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 2446cf53902fSRodrigo Vivi hotplug2_trigger, dig_hotplug_reg, hpd_spt, 24476dbf30ceSVille Syrjälä spt_port_hotplug2_long_detect); 24486dbf30ceSVille Syrjälä } 24496dbf30ceSVille Syrjälä 24506dbf30ceSVille Syrjälä if (pin_mask) 245191d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 24526dbf30ceSVille Syrjälä 24536dbf30ceSVille Syrjälä if (pch_iir & SDE_GMBUS_CPT) 245491d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 24556dbf30ceSVille Syrjälä } 24566dbf30ceSVille Syrjälä 245791d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, 245891d14251STvrtko Ursulin u32 hotplug_trigger, 245940e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2460c008bc6eSPaulo Zanoni { 2461e4ce95aaSVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2462e4ce95aaSVille Syrjälä 2463e4ce95aaSVille Syrjälä dig_hotplug_reg = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); 2464e4ce95aaSVille Syrjälä I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); 2465e4ce95aaSVille Syrjälä 2466cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 246740e56410SVille Syrjälä dig_hotplug_reg, hpd, 2468e4ce95aaSVille Syrjälä ilk_port_hotplug_long_detect); 246940e56410SVille Syrjälä 247091d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2471e4ce95aaSVille Syrjälä } 2472c008bc6eSPaulo Zanoni 247391d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 247491d14251STvrtko Ursulin u32 de_iir) 247540e56410SVille Syrjälä { 247640e56410SVille Syrjälä enum pipe pipe; 247740e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 247840e56410SVille Syrjälä 247940e56410SVille Syrjälä if (hotplug_trigger) 248091d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ilk); 248140e56410SVille Syrjälä 2482c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 248391d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2484c008bc6eSPaulo Zanoni 2485c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 248691d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2487c008bc6eSPaulo Zanoni 2488c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 2489c008bc6eSPaulo Zanoni DRM_ERROR("Poison interrupt\n"); 2490c008bc6eSPaulo Zanoni 2491055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2492fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 2493fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 2494c008bc6eSPaulo Zanoni 249540da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 24961f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 2497c008bc6eSPaulo Zanoni 249840da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 249991d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 2500c008bc6eSPaulo Zanoni } 2501c008bc6eSPaulo Zanoni 2502c008bc6eSPaulo Zanoni /* check event from PCH */ 2503c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 2504c008bc6eSPaulo Zanoni u32 pch_iir = I915_READ(SDEIIR); 2505c008bc6eSPaulo Zanoni 250691d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 250791d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 2508c008bc6eSPaulo Zanoni else 250991d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 2510c008bc6eSPaulo Zanoni 2511c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 2512c008bc6eSPaulo Zanoni I915_WRITE(SDEIIR, pch_iir); 2513c008bc6eSPaulo Zanoni } 2514c008bc6eSPaulo Zanoni 2515cf819effSLucas De Marchi if (IS_GEN(dev_priv, 5) && de_iir & DE_PCU_EVENT) 251691d14251STvrtko Ursulin ironlake_rps_change_irq_handler(dev_priv); 2517c008bc6eSPaulo Zanoni } 2518c008bc6eSPaulo Zanoni 251991d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 252091d14251STvrtko Ursulin u32 de_iir) 25219719fb98SPaulo Zanoni { 252207d27e20SDamien Lespiau enum pipe pipe; 252323bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 252423bb4cb5SVille Syrjälä 252540e56410SVille Syrjälä if (hotplug_trigger) 252691d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, hotplug_trigger, hpd_ivb); 25279719fb98SPaulo Zanoni 25289719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 252991d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 25309719fb98SPaulo Zanoni 253154fd3149SDhinakaran Pandiyan if (de_iir & DE_EDP_PSR_INT_HSW) { 253254fd3149SDhinakaran Pandiyan u32 psr_iir = I915_READ(EDP_PSR_IIR); 253354fd3149SDhinakaran Pandiyan 253454fd3149SDhinakaran Pandiyan intel_psr_irq_handler(dev_priv, psr_iir); 253554fd3149SDhinakaran Pandiyan I915_WRITE(EDP_PSR_IIR, psr_iir); 253654fd3149SDhinakaran Pandiyan } 2537fc340442SDaniel Vetter 25389719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 253991d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 25409719fb98SPaulo Zanoni 25419719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 254291d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 25439719fb98SPaulo Zanoni 2544055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2545fd3a4024SDaniel Vetter if (de_iir & (DE_PIPE_VBLANK_IVB(pipe))) 2546fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 25479719fb98SPaulo Zanoni } 25489719fb98SPaulo Zanoni 25499719fb98SPaulo Zanoni /* check event from PCH */ 255091d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 25519719fb98SPaulo Zanoni u32 pch_iir = I915_READ(SDEIIR); 25529719fb98SPaulo Zanoni 255391d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 25549719fb98SPaulo Zanoni 25559719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 25569719fb98SPaulo Zanoni I915_WRITE(SDEIIR, pch_iir); 25579719fb98SPaulo Zanoni } 25589719fb98SPaulo Zanoni } 25599719fb98SPaulo Zanoni 256072c90f62SOscar Mateo /* 256172c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 256272c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 256372c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 256472c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 256572c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 256672c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 256772c90f62SOscar Mateo */ 2568f1af8fc1SPaulo Zanoni static irqreturn_t ironlake_irq_handler(int irq, void *arg) 2569b1f14ad0SJesse Barnes { 257045a83f84SDaniel Vetter struct drm_device *dev = arg; 2571fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 2572f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 25730e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 2574b1f14ad0SJesse Barnes 25752dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 25762dd2a883SImre Deak return IRQ_NONE; 25772dd2a883SImre Deak 25781f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 25791f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 25801f814dacSImre Deak 2581b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 2582b1f14ad0SJesse Barnes de_ier = I915_READ(DEIER); 2583b1f14ad0SJesse Barnes I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 25840e43406bSChris Wilson 258544498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 258644498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 258744498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 258844498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 258944498aeaSPaulo Zanoni * due to its back queue). */ 259091d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv)) { 259144498aeaSPaulo Zanoni sde_ier = I915_READ(SDEIER); 259244498aeaSPaulo Zanoni I915_WRITE(SDEIER, 0); 2593ab5c608bSBen Widawsky } 259444498aeaSPaulo Zanoni 259572c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 259672c90f62SOscar Mateo 25970e43406bSChris Wilson gt_iir = I915_READ(GTIIR); 25980e43406bSChris Wilson if (gt_iir) { 259972c90f62SOscar Mateo I915_WRITE(GTIIR, gt_iir); 260072c90f62SOscar Mateo ret = IRQ_HANDLED; 260191d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) 2602261e40b8SVille Syrjälä snb_gt_irq_handler(dev_priv, gt_iir); 2603d8fc8a47SPaulo Zanoni else 2604261e40b8SVille Syrjälä ilk_gt_irq_handler(dev_priv, gt_iir); 26050e43406bSChris Wilson } 2606b1f14ad0SJesse Barnes 2607b1f14ad0SJesse Barnes de_iir = I915_READ(DEIIR); 26080e43406bSChris Wilson if (de_iir) { 260972c90f62SOscar Mateo I915_WRITE(DEIIR, de_iir); 261072c90f62SOscar Mateo ret = IRQ_HANDLED; 261191d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 7) 261291d14251STvrtko Ursulin ivb_display_irq_handler(dev_priv, de_iir); 2613f1af8fc1SPaulo Zanoni else 261491d14251STvrtko Ursulin ilk_display_irq_handler(dev_priv, de_iir); 26150e43406bSChris Wilson } 26160e43406bSChris Wilson 261791d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) { 2618f1af8fc1SPaulo Zanoni u32 pm_iir = I915_READ(GEN6_PMIIR); 26190e43406bSChris Wilson if (pm_iir) { 2620b1f14ad0SJesse Barnes I915_WRITE(GEN6_PMIIR, pm_iir); 26210e43406bSChris Wilson ret = IRQ_HANDLED; 262272c90f62SOscar Mateo gen6_rps_irq_handler(dev_priv, pm_iir); 26230e43406bSChris Wilson } 2624f1af8fc1SPaulo Zanoni } 2625b1f14ad0SJesse Barnes 2626b1f14ad0SJesse Barnes I915_WRITE(DEIER, de_ier); 262774093f3eSChris Wilson if (!HAS_PCH_NOP(dev_priv)) 262844498aeaSPaulo Zanoni I915_WRITE(SDEIER, sde_ier); 2629b1f14ad0SJesse Barnes 26301f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 26311f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 26321f814dacSImre Deak 2633b1f14ad0SJesse Barnes return ret; 2634b1f14ad0SJesse Barnes } 2635b1f14ad0SJesse Barnes 263691d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, 263791d14251STvrtko Ursulin u32 hotplug_trigger, 263840e56410SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 2639d04a492dSShashank Sharma { 2640cebd87a0SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2641d04a492dSShashank Sharma 2642a52bb15bSVille Syrjälä dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); 2643a52bb15bSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); 2644d04a492dSShashank Sharma 2645cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, hotplug_trigger, 264640e56410SVille Syrjälä dig_hotplug_reg, hpd, 2647cebd87a0SVille Syrjälä bxt_port_hotplug_long_detect); 264840e56410SVille Syrjälä 264991d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2650d04a492dSShashank Sharma } 2651d04a492dSShashank Sharma 2652121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2653121e758eSDhinakaran Pandiyan { 2654121e758eSDhinakaran Pandiyan u32 pin_mask = 0, long_mask = 0; 2655b796b971SDhinakaran Pandiyan u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; 2656b796b971SDhinakaran Pandiyan u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; 2657121e758eSDhinakaran Pandiyan 2658121e758eSDhinakaran Pandiyan if (trigger_tc) { 2659b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2660b796b971SDhinakaran Pandiyan 2661121e758eSDhinakaran Pandiyan dig_hotplug_reg = I915_READ(GEN11_TC_HOTPLUG_CTL); 2662121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_TC_HOTPLUG_CTL, dig_hotplug_reg); 2663121e758eSDhinakaran Pandiyan 2664121e758eSDhinakaran Pandiyan intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tc, 2665b796b971SDhinakaran Pandiyan dig_hotplug_reg, hpd_gen11, 2666121e758eSDhinakaran Pandiyan gen11_port_hotplug_long_detect); 2667121e758eSDhinakaran Pandiyan } 2668b796b971SDhinakaran Pandiyan 2669b796b971SDhinakaran Pandiyan if (trigger_tbt) { 2670b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2671b796b971SDhinakaran Pandiyan 2672b796b971SDhinakaran Pandiyan dig_hotplug_reg = I915_READ(GEN11_TBT_HOTPLUG_CTL); 2673b796b971SDhinakaran Pandiyan I915_WRITE(GEN11_TBT_HOTPLUG_CTL, dig_hotplug_reg); 2674b796b971SDhinakaran Pandiyan 2675b796b971SDhinakaran Pandiyan intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tbt, 2676b796b971SDhinakaran Pandiyan dig_hotplug_reg, hpd_gen11, 2677b796b971SDhinakaran Pandiyan gen11_port_hotplug_long_detect); 2678b796b971SDhinakaran Pandiyan } 2679b796b971SDhinakaran Pandiyan 2680b796b971SDhinakaran Pandiyan if (pin_mask) 2681b796b971SDhinakaran Pandiyan intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2682b796b971SDhinakaran Pandiyan else 2683b796b971SDhinakaran Pandiyan DRM_ERROR("Unexpected DE HPD interrupt 0x%08x\n", iir); 2684121e758eSDhinakaran Pandiyan } 2685121e758eSDhinakaran Pandiyan 26869d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 26879d17210fSLucas De Marchi { 26889d17210fSLucas De Marchi u32 mask = GEN8_AUX_CHANNEL_A; 26899d17210fSLucas De Marchi 26909d17210fSLucas De Marchi if (INTEL_GEN(dev_priv) >= 9) 26919d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 26929d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 26939d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 26949d17210fSLucas De Marchi 26959d17210fSLucas De Marchi if (IS_CNL_WITH_PORT_F(dev_priv)) 26969d17210fSLucas De Marchi mask |= CNL_AUX_CHANNEL_F; 26979d17210fSLucas De Marchi 26989d17210fSLucas De Marchi if (INTEL_GEN(dev_priv) >= 11) 26999d17210fSLucas De Marchi mask |= ICL_AUX_CHANNEL_E | 27009d17210fSLucas De Marchi CNL_AUX_CHANNEL_F; 27019d17210fSLucas De Marchi 27029d17210fSLucas De Marchi return mask; 27039d17210fSLucas De Marchi } 27049d17210fSLucas De Marchi 2705f11a0f46STvrtko Ursulin static irqreturn_t 2706f11a0f46STvrtko Ursulin gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 2707abd58f01SBen Widawsky { 2708abd58f01SBen Widawsky irqreturn_t ret = IRQ_NONE; 2709f11a0f46STvrtko Ursulin u32 iir; 2710c42664ccSDaniel Vetter enum pipe pipe; 271188e04703SJesse Barnes 2712abd58f01SBen Widawsky if (master_ctl & GEN8_DE_MISC_IRQ) { 2713e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_MISC_IIR); 2714e32192e1STvrtko Ursulin if (iir) { 2715e04f7eceSVille Syrjälä bool found = false; 2716e04f7eceSVille Syrjälä 2717e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_MISC_IIR, iir); 2718abd58f01SBen Widawsky ret = IRQ_HANDLED; 2719e04f7eceSVille Syrjälä 2720e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 272191d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2722e04f7eceSVille Syrjälä found = true; 2723e04f7eceSVille Syrjälä } 2724e04f7eceSVille Syrjälä 2725e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 272654fd3149SDhinakaran Pandiyan u32 psr_iir = I915_READ(EDP_PSR_IIR); 272754fd3149SDhinakaran Pandiyan 272854fd3149SDhinakaran Pandiyan intel_psr_irq_handler(dev_priv, psr_iir); 272954fd3149SDhinakaran Pandiyan I915_WRITE(EDP_PSR_IIR, psr_iir); 2730e04f7eceSVille Syrjälä found = true; 2731e04f7eceSVille Syrjälä } 2732e04f7eceSVille Syrjälä 2733e04f7eceSVille Syrjälä if (!found) 273438cc46d7SOscar Mateo DRM_ERROR("Unexpected DE Misc interrupt\n"); 2735abd58f01SBen Widawsky } 273638cc46d7SOscar Mateo else 273738cc46d7SOscar Mateo DRM_ERROR("The master control interrupt lied (DE MISC)!\n"); 2738abd58f01SBen Widawsky } 2739abd58f01SBen Widawsky 2740121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 2741121e758eSDhinakaran Pandiyan iir = I915_READ(GEN11_DE_HPD_IIR); 2742121e758eSDhinakaran Pandiyan if (iir) { 2743121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_DE_HPD_IIR, iir); 2744121e758eSDhinakaran Pandiyan ret = IRQ_HANDLED; 2745121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 2746121e758eSDhinakaran Pandiyan } else { 2747121e758eSDhinakaran Pandiyan DRM_ERROR("The master control interrupt lied, (DE HPD)!\n"); 2748121e758eSDhinakaran Pandiyan } 2749121e758eSDhinakaran Pandiyan } 2750121e758eSDhinakaran Pandiyan 27516d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 2752e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_PORT_IIR); 2753e32192e1STvrtko Ursulin if (iir) { 2754e32192e1STvrtko Ursulin u32 tmp_mask; 2755d04a492dSShashank Sharma bool found = false; 2756cebd87a0SVille Syrjälä 2757e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_PORT_IIR, iir); 27586d766f02SDaniel Vetter ret = IRQ_HANDLED; 275988e04703SJesse Barnes 27609d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 276191d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2762d04a492dSShashank Sharma found = true; 2763d04a492dSShashank Sharma } 2764d04a492dSShashank Sharma 2765cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) { 2766e32192e1STvrtko Ursulin tmp_mask = iir & BXT_DE_PORT_HOTPLUG_MASK; 2767e32192e1STvrtko Ursulin if (tmp_mask) { 276891d14251STvrtko Ursulin bxt_hpd_irq_handler(dev_priv, tmp_mask, 276991d14251STvrtko Ursulin hpd_bxt); 2770d04a492dSShashank Sharma found = true; 2771d04a492dSShashank Sharma } 2772e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 2773e32192e1STvrtko Ursulin tmp_mask = iir & GEN8_PORT_DP_A_HOTPLUG; 2774e32192e1STvrtko Ursulin if (tmp_mask) { 277591d14251STvrtko Ursulin ilk_hpd_irq_handler(dev_priv, 277691d14251STvrtko Ursulin tmp_mask, hpd_bdw); 2777e32192e1STvrtko Ursulin found = true; 2778e32192e1STvrtko Ursulin } 2779e32192e1STvrtko Ursulin } 2780d04a492dSShashank Sharma 2781cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv) && (iir & BXT_DE_PORT_GMBUS)) { 278291d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 27839e63743eSShashank Sharma found = true; 27849e63743eSShashank Sharma } 27859e63743eSShashank Sharma 2786d04a492dSShashank Sharma if (!found) 278738cc46d7SOscar Mateo DRM_ERROR("Unexpected DE Port interrupt\n"); 27886d766f02SDaniel Vetter } 278938cc46d7SOscar Mateo else 279038cc46d7SOscar Mateo DRM_ERROR("The master control interrupt lied (DE PORT)!\n"); 27916d766f02SDaniel Vetter } 27926d766f02SDaniel Vetter 2793055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2794fd3a4024SDaniel Vetter u32 fault_errors; 2795abd58f01SBen Widawsky 2796c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 2797c42664ccSDaniel Vetter continue; 2798c42664ccSDaniel Vetter 2799e32192e1STvrtko Ursulin iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); 2800e32192e1STvrtko Ursulin if (!iir) { 2801e32192e1STvrtko Ursulin DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); 2802e32192e1STvrtko Ursulin continue; 2803e32192e1STvrtko Ursulin } 2804770de83dSDamien Lespiau 2805e32192e1STvrtko Ursulin ret = IRQ_HANDLED; 2806e32192e1STvrtko Ursulin I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir); 2807e32192e1STvrtko Ursulin 2808fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 2809fd3a4024SDaniel Vetter drm_handle_vblank(&dev_priv->drm, pipe); 2810abd58f01SBen Widawsky 2811e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 281291d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 28130fbe7870SDaniel Vetter 2814e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_FIFO_UNDERRUN) 2815e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 281638d83c96SDaniel Vetter 2817e32192e1STvrtko Ursulin fault_errors = iir; 2818bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 9) 2819e32192e1STvrtko Ursulin fault_errors &= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 2820770de83dSDamien Lespiau else 2821e32192e1STvrtko Ursulin fault_errors &= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 2822770de83dSDamien Lespiau 2823770de83dSDamien Lespiau if (fault_errors) 28241353ec38STvrtko Ursulin DRM_ERROR("Fault errors on pipe %c: 0x%08x\n", 282530100f2bSDaniel Vetter pipe_name(pipe), 2826e32192e1STvrtko Ursulin fault_errors); 2827abd58f01SBen Widawsky } 2828abd58f01SBen Widawsky 282991d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 2830266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 283192d03a80SDaniel Vetter /* 283292d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 283392d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 283492d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 283592d03a80SDaniel Vetter */ 2836e32192e1STvrtko Ursulin iir = I915_READ(SDEIIR); 2837e32192e1STvrtko Ursulin if (iir) { 2838e32192e1STvrtko Ursulin I915_WRITE(SDEIIR, iir); 283992d03a80SDaniel Vetter ret = IRQ_HANDLED; 28406dbf30ceSVille Syrjälä 284129b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 284231604222SAnusha Srivatsa icp_irq_handler(dev_priv, iir); 2843c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 284491d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 28456dbf30ceSVille Syrjälä else 284691d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 28472dfb0b81SJani Nikula } else { 28482dfb0b81SJani Nikula /* 28492dfb0b81SJani Nikula * Like on previous PCH there seems to be something 28502dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 28512dfb0b81SJani Nikula */ 28522dfb0b81SJani Nikula DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n"); 28532dfb0b81SJani Nikula } 285492d03a80SDaniel Vetter } 285592d03a80SDaniel Vetter 2856f11a0f46STvrtko Ursulin return ret; 2857f11a0f46STvrtko Ursulin } 2858f11a0f46STvrtko Ursulin 28594376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 28604376b9c9SMika Kuoppala { 28614376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 28624376b9c9SMika Kuoppala 28634376b9c9SMika Kuoppala /* 28644376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 28654376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 28664376b9c9SMika Kuoppala * New indications can and will light up during processing, 28674376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 28684376b9c9SMika Kuoppala */ 28694376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 28704376b9c9SMika Kuoppala } 28714376b9c9SMika Kuoppala 28724376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 28734376b9c9SMika Kuoppala { 28744376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 28754376b9c9SMika Kuoppala } 28764376b9c9SMika Kuoppala 2877f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 2878f11a0f46STvrtko Ursulin { 2879f0fd96f5SChris Wilson struct drm_i915_private *dev_priv = to_i915(arg); 288025286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 2881f11a0f46STvrtko Ursulin u32 master_ctl; 2882f0fd96f5SChris Wilson u32 gt_iir[4]; 2883f11a0f46STvrtko Ursulin 2884f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 2885f11a0f46STvrtko Ursulin return IRQ_NONE; 2886f11a0f46STvrtko Ursulin 28874376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 28884376b9c9SMika Kuoppala if (!master_ctl) { 28894376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2890f11a0f46STvrtko Ursulin return IRQ_NONE; 28914376b9c9SMika Kuoppala } 2892f11a0f46STvrtko Ursulin 2893f11a0f46STvrtko Ursulin /* Find, clear, then process each source of interrupt */ 289455ef72f2SChris Wilson gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); 2895f0fd96f5SChris Wilson 2896f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2897f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 2898f0fd96f5SChris Wilson disable_rpm_wakeref_asserts(dev_priv); 289955ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 2900f0fd96f5SChris Wilson enable_rpm_wakeref_asserts(dev_priv); 2901f0fd96f5SChris Wilson } 2902f11a0f46STvrtko Ursulin 29034376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2904abd58f01SBen Widawsky 2905f0fd96f5SChris Wilson gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); 29061f814dacSImre Deak 290755ef72f2SChris Wilson return IRQ_HANDLED; 2908abd58f01SBen Widawsky } 2909abd58f01SBen Widawsky 291051951ae7SMika Kuoppala static u32 2911f744dbc2SMika Kuoppala gen11_gt_engine_identity(struct drm_i915_private * const i915, 291251951ae7SMika Kuoppala const unsigned int bank, const unsigned int bit) 291351951ae7SMika Kuoppala { 291425286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 291551951ae7SMika Kuoppala u32 timeout_ts; 291651951ae7SMika Kuoppala u32 ident; 291751951ae7SMika Kuoppala 291896606f3bSOscar Mateo lockdep_assert_held(&i915->irq_lock); 291996606f3bSOscar Mateo 292051951ae7SMika Kuoppala raw_reg_write(regs, GEN11_IIR_REG_SELECTOR(bank), BIT(bit)); 292151951ae7SMika Kuoppala 292251951ae7SMika Kuoppala /* 292351951ae7SMika Kuoppala * NB: Specs do not specify how long to spin wait, 292451951ae7SMika Kuoppala * so we do ~100us as an educated guess. 292551951ae7SMika Kuoppala */ 292651951ae7SMika Kuoppala timeout_ts = (local_clock() >> 10) + 100; 292751951ae7SMika Kuoppala do { 292851951ae7SMika Kuoppala ident = raw_reg_read(regs, GEN11_INTR_IDENTITY_REG(bank)); 292951951ae7SMika Kuoppala } while (!(ident & GEN11_INTR_DATA_VALID) && 293051951ae7SMika Kuoppala !time_after32(local_clock() >> 10, timeout_ts)); 293151951ae7SMika Kuoppala 293251951ae7SMika Kuoppala if (unlikely(!(ident & GEN11_INTR_DATA_VALID))) { 293351951ae7SMika Kuoppala DRM_ERROR("INTR_IDENTITY_REG%u:%u 0x%08x not valid!\n", 293451951ae7SMika Kuoppala bank, bit, ident); 293551951ae7SMika Kuoppala return 0; 293651951ae7SMika Kuoppala } 293751951ae7SMika Kuoppala 293851951ae7SMika Kuoppala raw_reg_write(regs, GEN11_INTR_IDENTITY_REG(bank), 293951951ae7SMika Kuoppala GEN11_INTR_DATA_VALID); 294051951ae7SMika Kuoppala 2941f744dbc2SMika Kuoppala return ident; 2942f744dbc2SMika Kuoppala } 2943f744dbc2SMika Kuoppala 2944f744dbc2SMika Kuoppala static void 2945f744dbc2SMika Kuoppala gen11_other_irq_handler(struct drm_i915_private * const i915, 2946f744dbc2SMika Kuoppala const u8 instance, const u16 iir) 2947f744dbc2SMika Kuoppala { 2948d02b98b8SOscar Mateo if (instance == OTHER_GTPM_INSTANCE) 2949d02b98b8SOscar Mateo return gen6_rps_irq_handler(i915, iir); 2950d02b98b8SOscar Mateo 2951f744dbc2SMika Kuoppala WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n", 2952f744dbc2SMika Kuoppala instance, iir); 2953f744dbc2SMika Kuoppala } 2954f744dbc2SMika Kuoppala 2955f744dbc2SMika Kuoppala static void 2956f744dbc2SMika Kuoppala gen11_engine_irq_handler(struct drm_i915_private * const i915, 2957f744dbc2SMika Kuoppala const u8 class, const u8 instance, const u16 iir) 2958f744dbc2SMika Kuoppala { 2959f744dbc2SMika Kuoppala struct intel_engine_cs *engine; 2960f744dbc2SMika Kuoppala 2961f744dbc2SMika Kuoppala if (instance <= MAX_ENGINE_INSTANCE) 2962f744dbc2SMika Kuoppala engine = i915->engine_class[class][instance]; 2963f744dbc2SMika Kuoppala else 2964f744dbc2SMika Kuoppala engine = NULL; 2965f744dbc2SMika Kuoppala 2966f744dbc2SMika Kuoppala if (likely(engine)) 2967f744dbc2SMika Kuoppala return gen8_cs_irq_handler(engine, iir); 2968f744dbc2SMika Kuoppala 2969f744dbc2SMika Kuoppala WARN_ONCE(1, "unhandled engine interrupt class=0x%x, instance=0x%x\n", 2970f744dbc2SMika Kuoppala class, instance); 2971f744dbc2SMika Kuoppala } 2972f744dbc2SMika Kuoppala 2973f744dbc2SMika Kuoppala static void 2974f744dbc2SMika Kuoppala gen11_gt_identity_handler(struct drm_i915_private * const i915, 2975f744dbc2SMika Kuoppala const u32 identity) 2976f744dbc2SMika Kuoppala { 2977f744dbc2SMika Kuoppala const u8 class = GEN11_INTR_ENGINE_CLASS(identity); 2978f744dbc2SMika Kuoppala const u8 instance = GEN11_INTR_ENGINE_INSTANCE(identity); 2979f744dbc2SMika Kuoppala const u16 intr = GEN11_INTR_ENGINE_INTR(identity); 2980f744dbc2SMika Kuoppala 2981f744dbc2SMika Kuoppala if (unlikely(!intr)) 2982f744dbc2SMika Kuoppala return; 2983f744dbc2SMika Kuoppala 2984f744dbc2SMika Kuoppala if (class <= COPY_ENGINE_CLASS) 2985f744dbc2SMika Kuoppala return gen11_engine_irq_handler(i915, class, instance, intr); 2986f744dbc2SMika Kuoppala 2987f744dbc2SMika Kuoppala if (class == OTHER_CLASS) 2988f744dbc2SMika Kuoppala return gen11_other_irq_handler(i915, instance, intr); 2989f744dbc2SMika Kuoppala 2990f744dbc2SMika Kuoppala WARN_ONCE(1, "unknown interrupt class=0x%x, instance=0x%x, intr=0x%x\n", 2991f744dbc2SMika Kuoppala class, instance, intr); 299251951ae7SMika Kuoppala } 299351951ae7SMika Kuoppala 299451951ae7SMika Kuoppala static void 299596606f3bSOscar Mateo gen11_gt_bank_handler(struct drm_i915_private * const i915, 299696606f3bSOscar Mateo const unsigned int bank) 299751951ae7SMika Kuoppala { 299825286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 299951951ae7SMika Kuoppala unsigned long intr_dw; 300051951ae7SMika Kuoppala unsigned int bit; 300151951ae7SMika Kuoppala 300296606f3bSOscar Mateo lockdep_assert_held(&i915->irq_lock); 300351951ae7SMika Kuoppala 300451951ae7SMika Kuoppala intr_dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); 300551951ae7SMika Kuoppala 300651951ae7SMika Kuoppala if (unlikely(!intr_dw)) { 300751951ae7SMika Kuoppala DRM_ERROR("GT_INTR_DW%u blank!\n", bank); 300896606f3bSOscar Mateo return; 300951951ae7SMika Kuoppala } 301051951ae7SMika Kuoppala 301151951ae7SMika Kuoppala for_each_set_bit(bit, &intr_dw, 32) { 3012f744dbc2SMika Kuoppala const u32 ident = gen11_gt_engine_identity(i915, 3013f744dbc2SMika Kuoppala bank, bit); 301451951ae7SMika Kuoppala 3015f744dbc2SMika Kuoppala gen11_gt_identity_handler(i915, ident); 301651951ae7SMika Kuoppala } 301751951ae7SMika Kuoppala 301851951ae7SMika Kuoppala /* Clear must be after shared has been served for engine */ 301951951ae7SMika Kuoppala raw_reg_write(regs, GEN11_GT_INTR_DW(bank), intr_dw); 302051951ae7SMika Kuoppala } 302196606f3bSOscar Mateo 302296606f3bSOscar Mateo static void 302396606f3bSOscar Mateo gen11_gt_irq_handler(struct drm_i915_private * const i915, 302496606f3bSOscar Mateo const u32 master_ctl) 302596606f3bSOscar Mateo { 302696606f3bSOscar Mateo unsigned int bank; 302796606f3bSOscar Mateo 302896606f3bSOscar Mateo spin_lock(&i915->irq_lock); 302996606f3bSOscar Mateo 303096606f3bSOscar Mateo for (bank = 0; bank < 2; bank++) { 303196606f3bSOscar Mateo if (master_ctl & GEN11_GT_DW_IRQ(bank)) 303296606f3bSOscar Mateo gen11_gt_bank_handler(i915, bank); 303396606f3bSOscar Mateo } 303496606f3bSOscar Mateo 303596606f3bSOscar Mateo spin_unlock(&i915->irq_lock); 303651951ae7SMika Kuoppala } 303751951ae7SMika Kuoppala 30387a909383SChris Wilson static u32 30397a909383SChris Wilson gen11_gu_misc_irq_ack(struct drm_i915_private *dev_priv, const u32 master_ctl) 3040df0d28c1SDhinakaran Pandiyan { 304125286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 30427a909383SChris Wilson u32 iir; 3043df0d28c1SDhinakaran Pandiyan 3044df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 30457a909383SChris Wilson return 0; 3046df0d28c1SDhinakaran Pandiyan 30477a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 30487a909383SChris Wilson if (likely(iir)) 30497a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 30507a909383SChris Wilson 30517a909383SChris Wilson return iir; 3052df0d28c1SDhinakaran Pandiyan } 3053df0d28c1SDhinakaran Pandiyan 3054df0d28c1SDhinakaran Pandiyan static void 30557a909383SChris Wilson gen11_gu_misc_irq_handler(struct drm_i915_private *dev_priv, const u32 iir) 3056df0d28c1SDhinakaran Pandiyan { 3057df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 3058df0d28c1SDhinakaran Pandiyan intel_opregion_asle_intr(dev_priv); 3059df0d28c1SDhinakaran Pandiyan } 3060df0d28c1SDhinakaran Pandiyan 306181067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 306281067b71SMika Kuoppala { 306381067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 306481067b71SMika Kuoppala 306581067b71SMika Kuoppala /* 306681067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 306781067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 306881067b71SMika Kuoppala * New indications can and will light up during processing, 306981067b71SMika Kuoppala * and will generate new interrupt after enabling master. 307081067b71SMika Kuoppala */ 307181067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 307281067b71SMika Kuoppala } 307381067b71SMika Kuoppala 307481067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 307581067b71SMika Kuoppala { 307681067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 307781067b71SMika Kuoppala } 307881067b71SMika Kuoppala 307951951ae7SMika Kuoppala static irqreturn_t gen11_irq_handler(int irq, void *arg) 308051951ae7SMika Kuoppala { 308151951ae7SMika Kuoppala struct drm_i915_private * const i915 = to_i915(arg); 308225286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 308351951ae7SMika Kuoppala u32 master_ctl; 3084df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 308551951ae7SMika Kuoppala 308651951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 308751951ae7SMika Kuoppala return IRQ_NONE; 308851951ae7SMika Kuoppala 308981067b71SMika Kuoppala master_ctl = gen11_master_intr_disable(regs); 309081067b71SMika Kuoppala if (!master_ctl) { 309181067b71SMika Kuoppala gen11_master_intr_enable(regs); 309251951ae7SMika Kuoppala return IRQ_NONE; 309381067b71SMika Kuoppala } 309451951ae7SMika Kuoppala 309551951ae7SMika Kuoppala /* Find, clear, then process each source of interrupt. */ 309651951ae7SMika Kuoppala gen11_gt_irq_handler(i915, master_ctl); 309751951ae7SMika Kuoppala 309851951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 309951951ae7SMika Kuoppala if (master_ctl & GEN11_DISPLAY_IRQ) { 310051951ae7SMika Kuoppala const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 310151951ae7SMika Kuoppala 310251951ae7SMika Kuoppala disable_rpm_wakeref_asserts(i915); 310351951ae7SMika Kuoppala /* 310451951ae7SMika Kuoppala * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 310551951ae7SMika Kuoppala * for the display related bits. 310651951ae7SMika Kuoppala */ 310751951ae7SMika Kuoppala gen8_de_irq_handler(i915, disp_ctl); 310851951ae7SMika Kuoppala enable_rpm_wakeref_asserts(i915); 310951951ae7SMika Kuoppala } 311051951ae7SMika Kuoppala 31117a909383SChris Wilson gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 3112df0d28c1SDhinakaran Pandiyan 311381067b71SMika Kuoppala gen11_master_intr_enable(regs); 311451951ae7SMika Kuoppala 31157a909383SChris Wilson gen11_gu_misc_irq_handler(i915, gu_misc_iir); 3116df0d28c1SDhinakaran Pandiyan 311751951ae7SMika Kuoppala return IRQ_HANDLED; 311851951ae7SMika Kuoppala } 311951951ae7SMika Kuoppala 312042f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 312142f52ef8SKeith Packard * we use as a pipe index 312242f52ef8SKeith Packard */ 312386e83e35SChris Wilson static int i8xx_enable_vblank(struct drm_device *dev, unsigned int pipe) 31240a3e67a4SJesse Barnes { 3125fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3126e9d21d7fSKeith Packard unsigned long irqflags; 312771e0ffa5SJesse Barnes 31281ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 312986e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 313086e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 313186e83e35SChris Wilson 313286e83e35SChris Wilson return 0; 313386e83e35SChris Wilson } 313486e83e35SChris Wilson 3135*d938da6bSVille Syrjälä static int i945gm_enable_vblank(struct drm_device *dev, unsigned int pipe) 3136*d938da6bSVille Syrjälä { 3137*d938da6bSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(dev); 3138*d938da6bSVille Syrjälä 3139*d938da6bSVille Syrjälä if (dev_priv->i945gm_vblank.enabled++ == 0) 3140*d938da6bSVille Syrjälä schedule_work(&dev_priv->i945gm_vblank.work); 3141*d938da6bSVille Syrjälä 3142*d938da6bSVille Syrjälä return i8xx_enable_vblank(dev, pipe); 3143*d938da6bSVille Syrjälä } 3144*d938da6bSVille Syrjälä 314586e83e35SChris Wilson static int i965_enable_vblank(struct drm_device *dev, unsigned int pipe) 314686e83e35SChris Wilson { 314786e83e35SChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 314886e83e35SChris Wilson unsigned long irqflags; 314986e83e35SChris Wilson 315086e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 31517c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 3152755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 31531ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 31548692d00eSChris Wilson 31550a3e67a4SJesse Barnes return 0; 31560a3e67a4SJesse Barnes } 31570a3e67a4SJesse Barnes 315888e72717SThierry Reding static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) 3159f796cf8fSJesse Barnes { 3160fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3161f796cf8fSJesse Barnes unsigned long irqflags; 3162a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 316386e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 3164f796cf8fSJesse Barnes 3165f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3166fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 3167b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3168b1f14ad0SJesse Barnes 31692e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 31702e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 31712e8bf223SDhinakaran Pandiyan */ 31722e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 31732e8bf223SDhinakaran Pandiyan drm_vblank_restore(dev, pipe); 31742e8bf223SDhinakaran Pandiyan 3175b1f14ad0SJesse Barnes return 0; 3176b1f14ad0SJesse Barnes } 3177b1f14ad0SJesse Barnes 317888e72717SThierry Reding static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) 3179abd58f01SBen Widawsky { 3180fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3181abd58f01SBen Widawsky unsigned long irqflags; 3182abd58f01SBen Widawsky 3183abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3184013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 3185abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3186013d3752SVille Syrjälä 31872e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 31882e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 31892e8bf223SDhinakaran Pandiyan */ 31902e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 31912e8bf223SDhinakaran Pandiyan drm_vblank_restore(dev, pipe); 31922e8bf223SDhinakaran Pandiyan 3193abd58f01SBen Widawsky return 0; 3194abd58f01SBen Widawsky } 3195abd58f01SBen Widawsky 319642f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 319742f52ef8SKeith Packard * we use as a pipe index 319842f52ef8SKeith Packard */ 319986e83e35SChris Wilson static void i8xx_disable_vblank(struct drm_device *dev, unsigned int pipe) 320086e83e35SChris Wilson { 320186e83e35SChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 320286e83e35SChris Wilson unsigned long irqflags; 320386e83e35SChris Wilson 320486e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 320586e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 320686e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 320786e83e35SChris Wilson } 320886e83e35SChris Wilson 3209*d938da6bSVille Syrjälä static void i945gm_disable_vblank(struct drm_device *dev, unsigned int pipe) 3210*d938da6bSVille Syrjälä { 3211*d938da6bSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(dev); 3212*d938da6bSVille Syrjälä 3213*d938da6bSVille Syrjälä i8xx_disable_vblank(dev, pipe); 3214*d938da6bSVille Syrjälä 3215*d938da6bSVille Syrjälä if (--dev_priv->i945gm_vblank.enabled == 0) 3216*d938da6bSVille Syrjälä schedule_work(&dev_priv->i945gm_vblank.work); 3217*d938da6bSVille Syrjälä } 3218*d938da6bSVille Syrjälä 321986e83e35SChris Wilson static void i965_disable_vblank(struct drm_device *dev, unsigned int pipe) 32200a3e67a4SJesse Barnes { 3221fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3222e9d21d7fSKeith Packard unsigned long irqflags; 32230a3e67a4SJesse Barnes 32241ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 32257c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 3226755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 32271ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 32280a3e67a4SJesse Barnes } 32290a3e67a4SJesse Barnes 323088e72717SThierry Reding static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) 3231f796cf8fSJesse Barnes { 3232fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3233f796cf8fSJesse Barnes unsigned long irqflags; 3234a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 323586e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 3236f796cf8fSJesse Barnes 3237f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3238fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 3239b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3240b1f14ad0SJesse Barnes } 3241b1f14ad0SJesse Barnes 324288e72717SThierry Reding static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe) 3243abd58f01SBen Widawsky { 3244fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3245abd58f01SBen Widawsky unsigned long irqflags; 3246abd58f01SBen Widawsky 3247abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3248013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 3249abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3250abd58f01SBen Widawsky } 3251abd58f01SBen Widawsky 3252*d938da6bSVille Syrjälä static void i945gm_vblank_work_func(struct work_struct *work) 3253*d938da6bSVille Syrjälä { 3254*d938da6bSVille Syrjälä struct drm_i915_private *dev_priv = 3255*d938da6bSVille Syrjälä container_of(work, struct drm_i915_private, i945gm_vblank.work); 3256*d938da6bSVille Syrjälä 3257*d938da6bSVille Syrjälä /* 3258*d938da6bSVille Syrjälä * Vblank interrupts fail to wake up the device from C3, 3259*d938da6bSVille Syrjälä * hence we want to prevent C3 usage while vblank interrupts 3260*d938da6bSVille Syrjälä * are enabled. 3261*d938da6bSVille Syrjälä */ 3262*d938da6bSVille Syrjälä pm_qos_update_request(&dev_priv->i945gm_vblank.pm_qos, 3263*d938da6bSVille Syrjälä READ_ONCE(dev_priv->i945gm_vblank.enabled) ? 3264*d938da6bSVille Syrjälä dev_priv->i945gm_vblank.c3_disable_latency : 3265*d938da6bSVille Syrjälä PM_QOS_DEFAULT_VALUE); 3266*d938da6bSVille Syrjälä } 3267*d938da6bSVille Syrjälä 3268*d938da6bSVille Syrjälä static int cstate_disable_latency(const char *name) 3269*d938da6bSVille Syrjälä { 3270*d938da6bSVille Syrjälä const struct cpuidle_driver *drv; 3271*d938da6bSVille Syrjälä int i; 3272*d938da6bSVille Syrjälä 3273*d938da6bSVille Syrjälä drv = cpuidle_get_driver(); 3274*d938da6bSVille Syrjälä if (!drv) 3275*d938da6bSVille Syrjälä return 0; 3276*d938da6bSVille Syrjälä 3277*d938da6bSVille Syrjälä for (i = 0; i < drv->state_count; i++) { 3278*d938da6bSVille Syrjälä const struct cpuidle_state *state = &drv->states[i]; 3279*d938da6bSVille Syrjälä 3280*d938da6bSVille Syrjälä if (!strcmp(state->name, name)) 3281*d938da6bSVille Syrjälä return state->exit_latency ? 3282*d938da6bSVille Syrjälä state->exit_latency - 1 : 0; 3283*d938da6bSVille Syrjälä } 3284*d938da6bSVille Syrjälä 3285*d938da6bSVille Syrjälä return 0; 3286*d938da6bSVille Syrjälä } 3287*d938da6bSVille Syrjälä 3288*d938da6bSVille Syrjälä static void i945gm_vblank_work_init(struct drm_i915_private *dev_priv) 3289*d938da6bSVille Syrjälä { 3290*d938da6bSVille Syrjälä INIT_WORK(&dev_priv->i945gm_vblank.work, 3291*d938da6bSVille Syrjälä i945gm_vblank_work_func); 3292*d938da6bSVille Syrjälä 3293*d938da6bSVille Syrjälä dev_priv->i945gm_vblank.c3_disable_latency = 3294*d938da6bSVille Syrjälä cstate_disable_latency("C3"); 3295*d938da6bSVille Syrjälä pm_qos_add_request(&dev_priv->i945gm_vblank.pm_qos, 3296*d938da6bSVille Syrjälä PM_QOS_CPU_DMA_LATENCY, 3297*d938da6bSVille Syrjälä PM_QOS_DEFAULT_VALUE); 3298*d938da6bSVille Syrjälä } 3299*d938da6bSVille Syrjälä 3300*d938da6bSVille Syrjälä static void i945gm_vblank_work_fini(struct drm_i915_private *dev_priv) 3301*d938da6bSVille Syrjälä { 3302*d938da6bSVille Syrjälä cancel_work_sync(&dev_priv->i945gm_vblank.work); 3303*d938da6bSVille Syrjälä pm_qos_remove_request(&dev_priv->i945gm_vblank.pm_qos); 3304*d938da6bSVille Syrjälä } 3305*d938da6bSVille Syrjälä 3306b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 330791738a95SPaulo Zanoni { 33086e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 330991738a95SPaulo Zanoni return; 331091738a95SPaulo Zanoni 33113488d4ebSVille Syrjälä GEN3_IRQ_RESET(SDE); 3312105b122eSPaulo Zanoni 33136e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 3314105b122eSPaulo Zanoni I915_WRITE(SERR_INT, 0xffffffff); 3315622364b6SPaulo Zanoni } 3316105b122eSPaulo Zanoni 331791738a95SPaulo Zanoni /* 3318622364b6SPaulo Zanoni * SDEIER is also touched by the interrupt handler to work around missed PCH 3319622364b6SPaulo Zanoni * interrupts. Hence we can't update it after the interrupt handler is enabled - 3320622364b6SPaulo Zanoni * instead we unconditionally enable all PCH interrupt sources here, but then 3321622364b6SPaulo Zanoni * only unmask them as needed with SDEIMR. 3322622364b6SPaulo Zanoni * 3323622364b6SPaulo Zanoni * This function needs to be called before interrupts are enabled. 332491738a95SPaulo Zanoni */ 3325622364b6SPaulo Zanoni static void ibx_irq_pre_postinstall(struct drm_device *dev) 3326622364b6SPaulo Zanoni { 3327fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3328622364b6SPaulo Zanoni 33296e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3330622364b6SPaulo Zanoni return; 3331622364b6SPaulo Zanoni 3332622364b6SPaulo Zanoni WARN_ON(I915_READ(SDEIER) != 0); 333391738a95SPaulo Zanoni I915_WRITE(SDEIER, 0xffffffff); 333491738a95SPaulo Zanoni POSTING_READ(SDEIER); 333591738a95SPaulo Zanoni } 333691738a95SPaulo Zanoni 3337b243f530STvrtko Ursulin static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv) 3338d18ea1b5SDaniel Vetter { 33393488d4ebSVille Syrjälä GEN3_IRQ_RESET(GT); 3340b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) 33413488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN6_PM); 3342d18ea1b5SDaniel Vetter } 3343d18ea1b5SDaniel Vetter 334470591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 334570591a41SVille Syrjälä { 334671b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 334771b8b41dSVille Syrjälä I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 334871b8b41dSVille Syrjälä else 334971b8b41dSVille Syrjälä I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK); 335071b8b41dSVille Syrjälä 3351ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 335270591a41SVille Syrjälä I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 335370591a41SVille Syrjälä 335444d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 335570591a41SVille Syrjälä 33563488d4ebSVille Syrjälä GEN3_IRQ_RESET(VLV_); 33578bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 335870591a41SVille Syrjälä } 335970591a41SVille Syrjälä 33608bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 33618bb61306SVille Syrjälä { 33628bb61306SVille Syrjälä u32 pipestat_mask; 33639ab981f2SVille Syrjälä u32 enable_mask; 33648bb61306SVille Syrjälä enum pipe pipe; 33658bb61306SVille Syrjälä 3366842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 33678bb61306SVille Syrjälä 33688bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 33698bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 33708bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 33718bb61306SVille Syrjälä 33729ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 33738bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3374ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 3375ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 3376ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 3377ebf5f921SVille Syrjälä 33788bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 3379ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 3380ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 33816b7eafc1SVille Syrjälä 33828bd099a7SChris Wilson WARN_ON(dev_priv->irq_mask != ~0u); 33836b7eafc1SVille Syrjälä 33849ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 33858bb61306SVille Syrjälä 33863488d4ebSVille Syrjälä GEN3_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); 33878bb61306SVille Syrjälä } 33888bb61306SVille Syrjälä 33898bb61306SVille Syrjälä /* drm_dma.h hooks 33908bb61306SVille Syrjälä */ 33918bb61306SVille Syrjälä static void ironlake_irq_reset(struct drm_device *dev) 33928bb61306SVille Syrjälä { 3393fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 33948bb61306SVille Syrjälä 33953488d4ebSVille Syrjälä GEN3_IRQ_RESET(DE); 3396cf819effSLucas De Marchi if (IS_GEN(dev_priv, 7)) 33978bb61306SVille Syrjälä I915_WRITE(GEN7_ERR_INT, 0xffffffff); 33988bb61306SVille Syrjälä 3399fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3400fc340442SDaniel Vetter I915_WRITE(EDP_PSR_IMR, 0xffffffff); 3401fc340442SDaniel Vetter I915_WRITE(EDP_PSR_IIR, 0xffffffff); 3402fc340442SDaniel Vetter } 3403fc340442SDaniel Vetter 3404b243f530STvrtko Ursulin gen5_gt_irq_reset(dev_priv); 34058bb61306SVille Syrjälä 3406b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 34078bb61306SVille Syrjälä } 34088bb61306SVille Syrjälä 34096bcdb1c8SVille Syrjälä static void valleyview_irq_reset(struct drm_device *dev) 34107e231dbeSJesse Barnes { 3411fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 34127e231dbeSJesse Barnes 341334c7b8a7SVille Syrjälä I915_WRITE(VLV_MASTER_IER, 0); 341434c7b8a7SVille Syrjälä POSTING_READ(VLV_MASTER_IER); 341534c7b8a7SVille Syrjälä 3416b243f530STvrtko Ursulin gen5_gt_irq_reset(dev_priv); 34177e231dbeSJesse Barnes 3418ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 34199918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 342070591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3421ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 34227e231dbeSJesse Barnes } 34237e231dbeSJesse Barnes 3424d6e3cca3SDaniel Vetter static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv) 3425d6e3cca3SDaniel Vetter { 3426d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 0); 3427d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 1); 3428d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 2); 3429d6e3cca3SDaniel Vetter GEN8_IRQ_RESET_NDX(GT, 3); 3430d6e3cca3SDaniel Vetter } 3431d6e3cca3SDaniel Vetter 3432823f6b38SPaulo Zanoni static void gen8_irq_reset(struct drm_device *dev) 3433abd58f01SBen Widawsky { 3434fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 3435abd58f01SBen Widawsky int pipe; 3436abd58f01SBen Widawsky 343725286aacSDaniele Ceraolo Spurio gen8_master_intr_disable(dev_priv->uncore.regs); 3438abd58f01SBen Widawsky 3439d6e3cca3SDaniel Vetter gen8_gt_irq_reset(dev_priv); 3440abd58f01SBen Widawsky 3441e04f7eceSVille Syrjälä I915_WRITE(EDP_PSR_IMR, 0xffffffff); 3442e04f7eceSVille Syrjälä I915_WRITE(EDP_PSR_IIR, 0xffffffff); 3443e04f7eceSVille Syrjälä 3444055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 3445f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3446813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3447f86f3fb0SPaulo Zanoni GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); 3448abd58f01SBen Widawsky 34493488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_DE_PORT_); 34503488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_DE_MISC_); 34513488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_PCU_); 3452abd58f01SBen Widawsky 34536e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 3454b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 3455abd58f01SBen Widawsky } 3456abd58f01SBen Widawsky 345751951ae7SMika Kuoppala static void gen11_gt_irq_reset(struct drm_i915_private *dev_priv) 345851951ae7SMika Kuoppala { 345951951ae7SMika Kuoppala /* Disable RCS, BCS, VCS and VECS class engines. */ 346051951ae7SMika Kuoppala I915_WRITE(GEN11_RENDER_COPY_INTR_ENABLE, 0); 346151951ae7SMika Kuoppala I915_WRITE(GEN11_VCS_VECS_INTR_ENABLE, 0); 346251951ae7SMika Kuoppala 346351951ae7SMika Kuoppala /* Restore masks irqs on RCS, BCS, VCS and VECS engines. */ 346451951ae7SMika Kuoppala I915_WRITE(GEN11_RCS0_RSVD_INTR_MASK, ~0); 346551951ae7SMika Kuoppala I915_WRITE(GEN11_BCS_RSVD_INTR_MASK, ~0); 346651951ae7SMika Kuoppala I915_WRITE(GEN11_VCS0_VCS1_INTR_MASK, ~0); 346751951ae7SMika Kuoppala I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~0); 346851951ae7SMika Kuoppala I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~0); 3469d02b98b8SOscar Mateo 3470d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); 3471d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); 347251951ae7SMika Kuoppala } 347351951ae7SMika Kuoppala 347451951ae7SMika Kuoppala static void gen11_irq_reset(struct drm_device *dev) 347551951ae7SMika Kuoppala { 347651951ae7SMika Kuoppala struct drm_i915_private *dev_priv = dev->dev_private; 347751951ae7SMika Kuoppala int pipe; 347851951ae7SMika Kuoppala 347925286aacSDaniele Ceraolo Spurio gen11_master_intr_disable(dev_priv->uncore.regs); 348051951ae7SMika Kuoppala 348151951ae7SMika Kuoppala gen11_gt_irq_reset(dev_priv); 348251951ae7SMika Kuoppala 348351951ae7SMika Kuoppala I915_WRITE(GEN11_DISPLAY_INT_CTL, 0); 348451951ae7SMika Kuoppala 348562819dfdSJosé Roberto de Souza I915_WRITE(EDP_PSR_IMR, 0xffffffff); 348662819dfdSJosé Roberto de Souza I915_WRITE(EDP_PSR_IIR, 0xffffffff); 348762819dfdSJosé Roberto de Souza 348851951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 348951951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 349051951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 349151951ae7SMika Kuoppala GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); 349251951ae7SMika Kuoppala 349351951ae7SMika Kuoppala GEN3_IRQ_RESET(GEN8_DE_PORT_); 349451951ae7SMika Kuoppala GEN3_IRQ_RESET(GEN8_DE_MISC_); 3495121e758eSDhinakaran Pandiyan GEN3_IRQ_RESET(GEN11_DE_HPD_); 3496df0d28c1SDhinakaran Pandiyan GEN3_IRQ_RESET(GEN11_GU_MISC_); 349751951ae7SMika Kuoppala GEN3_IRQ_RESET(GEN8_PCU_); 349831604222SAnusha Srivatsa 349929b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 350031604222SAnusha Srivatsa GEN3_IRQ_RESET(SDE); 350151951ae7SMika Kuoppala } 350251951ae7SMika Kuoppala 35034c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 3504001bd2cbSImre Deak u8 pipe_mask) 3505d49bdb0eSPaulo Zanoni { 3506a9c287c9SJani Nikula u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN; 35076831f3e3SVille Syrjälä enum pipe pipe; 3508d49bdb0eSPaulo Zanoni 350913321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 35109dfe2e3aSImre Deak 35119dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 35129dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 35139dfe2e3aSImre Deak return; 35149dfe2e3aSImre Deak } 35159dfe2e3aSImre Deak 35166831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 35176831f3e3SVille Syrjälä GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, 35186831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 35196831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 35209dfe2e3aSImre Deak 352113321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3522d49bdb0eSPaulo Zanoni } 3523d49bdb0eSPaulo Zanoni 3524aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 3525001bd2cbSImre Deak u8 pipe_mask) 3526aae8ba84SVille Syrjälä { 35276831f3e3SVille Syrjälä enum pipe pipe; 35286831f3e3SVille Syrjälä 3529aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 35309dfe2e3aSImre Deak 35319dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 35329dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 35339dfe2e3aSImre Deak return; 35349dfe2e3aSImre Deak } 35359dfe2e3aSImre Deak 35366831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 35376831f3e3SVille Syrjälä GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); 35389dfe2e3aSImre Deak 3539aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3540aae8ba84SVille Syrjälä 3541aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 354291c8a326SChris Wilson synchronize_irq(dev_priv->drm.irq); 3543aae8ba84SVille Syrjälä } 3544aae8ba84SVille Syrjälä 35456bcdb1c8SVille Syrjälä static void cherryview_irq_reset(struct drm_device *dev) 354643f328d7SVille Syrjälä { 3547fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 354843f328d7SVille Syrjälä 354943f328d7SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, 0); 355043f328d7SVille Syrjälä POSTING_READ(GEN8_MASTER_IRQ); 355143f328d7SVille Syrjälä 3552d6e3cca3SDaniel Vetter gen8_gt_irq_reset(dev_priv); 355343f328d7SVille Syrjälä 35543488d4ebSVille Syrjälä GEN3_IRQ_RESET(GEN8_PCU_); 355543f328d7SVille Syrjälä 3556ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 35579918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 355870591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3559ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 356043f328d7SVille Syrjälä } 356143f328d7SVille Syrjälä 356291d14251STvrtko Ursulin static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, 356387a02106SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 356487a02106SVille Syrjälä { 356587a02106SVille Syrjälä struct intel_encoder *encoder; 356687a02106SVille Syrjälä u32 enabled_irqs = 0; 356787a02106SVille Syrjälä 356891c8a326SChris Wilson for_each_intel_encoder(&dev_priv->drm, encoder) 356987a02106SVille Syrjälä if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) 357087a02106SVille Syrjälä enabled_irqs |= hpd[encoder->hpd_pin]; 357187a02106SVille Syrjälä 357287a02106SVille Syrjälä return enabled_irqs; 357387a02106SVille Syrjälä } 357487a02106SVille Syrjälä 35751a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) 35761a56b1a2SImre Deak { 35771a56b1a2SImre Deak u32 hotplug; 35781a56b1a2SImre Deak 35791a56b1a2SImre Deak /* 35801a56b1a2SImre Deak * Enable digital hotplug on the PCH, and configure the DP short pulse 35811a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec). 35821a56b1a2SImre Deak * The pulse duration bits are reserved on LPT+. 35831a56b1a2SImre Deak */ 35841a56b1a2SImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG); 35851a56b1a2SImre Deak hotplug &= ~(PORTB_PULSE_DURATION_MASK | 35861a56b1a2SImre Deak PORTC_PULSE_DURATION_MASK | 35871a56b1a2SImre Deak PORTD_PULSE_DURATION_MASK); 35881a56b1a2SImre Deak hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms; 35891a56b1a2SImre Deak hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms; 35901a56b1a2SImre Deak hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms; 35911a56b1a2SImre Deak /* 35921a56b1a2SImre Deak * When CPU and PCH are on the same package, port A 35931a56b1a2SImre Deak * HPD must be enabled in both north and south. 35941a56b1a2SImre Deak */ 35951a56b1a2SImre Deak if (HAS_PCH_LPT_LP(dev_priv)) 35961a56b1a2SImre Deak hotplug |= PORTA_HOTPLUG_ENABLE; 35971a56b1a2SImre Deak I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 35981a56b1a2SImre Deak } 35991a56b1a2SImre Deak 360091d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) 360182a28bcfSDaniel Vetter { 36021a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 360382a28bcfSDaniel Vetter 360491d14251STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) { 3605fee884edSDaniel Vetter hotplug_irqs = SDE_HOTPLUG_MASK; 360691d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ibx); 360782a28bcfSDaniel Vetter } else { 3608fee884edSDaniel Vetter hotplug_irqs = SDE_HOTPLUG_MASK_CPT; 360991d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_cpt); 361082a28bcfSDaniel Vetter } 361182a28bcfSDaniel Vetter 3612fee884edSDaniel Vetter ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 361382a28bcfSDaniel Vetter 36141a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 36156dbf30ceSVille Syrjälä } 361626951cafSXiong Zhang 361731604222SAnusha Srivatsa static void icp_hpd_detection_setup(struct drm_i915_private *dev_priv) 361831604222SAnusha Srivatsa { 361931604222SAnusha Srivatsa u32 hotplug; 362031604222SAnusha Srivatsa 362131604222SAnusha Srivatsa hotplug = I915_READ(SHOTPLUG_CTL_DDI); 362231604222SAnusha Srivatsa hotplug |= ICP_DDIA_HPD_ENABLE | 362331604222SAnusha Srivatsa ICP_DDIB_HPD_ENABLE; 362431604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_DDI, hotplug); 362531604222SAnusha Srivatsa 362631604222SAnusha Srivatsa hotplug = I915_READ(SHOTPLUG_CTL_TC); 362731604222SAnusha Srivatsa hotplug |= ICP_TC_HPD_ENABLE(PORT_TC1) | 362831604222SAnusha Srivatsa ICP_TC_HPD_ENABLE(PORT_TC2) | 362931604222SAnusha Srivatsa ICP_TC_HPD_ENABLE(PORT_TC3) | 363031604222SAnusha Srivatsa ICP_TC_HPD_ENABLE(PORT_TC4); 363131604222SAnusha Srivatsa I915_WRITE(SHOTPLUG_CTL_TC, hotplug); 363231604222SAnusha Srivatsa } 363331604222SAnusha Srivatsa 363431604222SAnusha Srivatsa static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) 363531604222SAnusha Srivatsa { 363631604222SAnusha Srivatsa u32 hotplug_irqs, enabled_irqs; 363731604222SAnusha Srivatsa 363831604222SAnusha Srivatsa hotplug_irqs = SDE_DDI_MASK_ICP | SDE_TC_MASK_ICP; 363931604222SAnusha Srivatsa enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_icp); 364031604222SAnusha Srivatsa 364131604222SAnusha Srivatsa ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 364231604222SAnusha Srivatsa 364331604222SAnusha Srivatsa icp_hpd_detection_setup(dev_priv); 364431604222SAnusha Srivatsa } 364531604222SAnusha Srivatsa 3646121e758eSDhinakaran Pandiyan static void gen11_hpd_detection_setup(struct drm_i915_private *dev_priv) 3647121e758eSDhinakaran Pandiyan { 3648121e758eSDhinakaran Pandiyan u32 hotplug; 3649121e758eSDhinakaran Pandiyan 3650121e758eSDhinakaran Pandiyan hotplug = I915_READ(GEN11_TC_HOTPLUG_CTL); 3651121e758eSDhinakaran Pandiyan hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | 3652121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | 3653121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | 3654121e758eSDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); 3655121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_TC_HOTPLUG_CTL, hotplug); 3656b796b971SDhinakaran Pandiyan 3657b796b971SDhinakaran Pandiyan hotplug = I915_READ(GEN11_TBT_HOTPLUG_CTL); 3658b796b971SDhinakaran Pandiyan hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | 3659b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | 3660b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | 3661b796b971SDhinakaran Pandiyan GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); 3662b796b971SDhinakaran Pandiyan I915_WRITE(GEN11_TBT_HOTPLUG_CTL, hotplug); 3663121e758eSDhinakaran Pandiyan } 3664121e758eSDhinakaran Pandiyan 3665121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) 3666121e758eSDhinakaran Pandiyan { 3667121e758eSDhinakaran Pandiyan u32 hotplug_irqs, enabled_irqs; 3668121e758eSDhinakaran Pandiyan u32 val; 3669121e758eSDhinakaran Pandiyan 3670b796b971SDhinakaran Pandiyan enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_gen11); 3671b796b971SDhinakaran Pandiyan hotplug_irqs = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; 3672121e758eSDhinakaran Pandiyan 3673121e758eSDhinakaran Pandiyan val = I915_READ(GEN11_DE_HPD_IMR); 3674121e758eSDhinakaran Pandiyan val &= ~hotplug_irqs; 3675121e758eSDhinakaran Pandiyan I915_WRITE(GEN11_DE_HPD_IMR, val); 3676121e758eSDhinakaran Pandiyan POSTING_READ(GEN11_DE_HPD_IMR); 3677121e758eSDhinakaran Pandiyan 3678121e758eSDhinakaran Pandiyan gen11_hpd_detection_setup(dev_priv); 367931604222SAnusha Srivatsa 368029b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 368131604222SAnusha Srivatsa icp_hpd_irq_setup(dev_priv); 3682121e758eSDhinakaran Pandiyan } 3683121e758eSDhinakaran Pandiyan 36842a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) 36852a57d9ccSImre Deak { 36863b92e263SRodrigo Vivi u32 val, hotplug; 36873b92e263SRodrigo Vivi 36883b92e263SRodrigo Vivi /* Display WA #1179 WaHardHangonHotPlug: cnp */ 36893b92e263SRodrigo Vivi if (HAS_PCH_CNP(dev_priv)) { 36903b92e263SRodrigo Vivi val = I915_READ(SOUTH_CHICKEN1); 36913b92e263SRodrigo Vivi val &= ~CHASSIS_CLK_REQ_DURATION_MASK; 36923b92e263SRodrigo Vivi val |= CHASSIS_CLK_REQ_DURATION(0xf); 36933b92e263SRodrigo Vivi I915_WRITE(SOUTH_CHICKEN1, val); 36943b92e263SRodrigo Vivi } 36952a57d9ccSImre Deak 36962a57d9ccSImre Deak /* Enable digital hotplug on the PCH */ 36972a57d9ccSImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG); 36982a57d9ccSImre Deak hotplug |= PORTA_HOTPLUG_ENABLE | 36992a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 37002a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE | 37012a57d9ccSImre Deak PORTD_HOTPLUG_ENABLE; 37022a57d9ccSImre Deak I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 37032a57d9ccSImre Deak 37042a57d9ccSImre Deak hotplug = I915_READ(PCH_PORT_HOTPLUG2); 37052a57d9ccSImre Deak hotplug |= PORTE_HOTPLUG_ENABLE; 37062a57d9ccSImre Deak I915_WRITE(PCH_PORT_HOTPLUG2, hotplug); 37072a57d9ccSImre Deak } 37082a57d9ccSImre Deak 370991d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) 37106dbf30ceSVille Syrjälä { 37112a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 37126dbf30ceSVille Syrjälä 37136dbf30ceSVille Syrjälä hotplug_irqs = SDE_HOTPLUG_MASK_SPT; 371491d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_spt); 37156dbf30ceSVille Syrjälä 37166dbf30ceSVille Syrjälä ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 37176dbf30ceSVille Syrjälä 37182a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 371926951cafSXiong Zhang } 37207fe0b973SKeith Packard 37211a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) 37221a56b1a2SImre Deak { 37231a56b1a2SImre Deak u32 hotplug; 37241a56b1a2SImre Deak 37251a56b1a2SImre Deak /* 37261a56b1a2SImre Deak * Enable digital hotplug on the CPU, and configure the DP short pulse 37271a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec) 37281a56b1a2SImre Deak * The pulse duration bits are reserved on HSW+. 37291a56b1a2SImre Deak */ 37301a56b1a2SImre Deak hotplug = I915_READ(DIGITAL_PORT_HOTPLUG_CNTRL); 37311a56b1a2SImre Deak hotplug &= ~DIGITAL_PORTA_PULSE_DURATION_MASK; 37321a56b1a2SImre Deak hotplug |= DIGITAL_PORTA_HOTPLUG_ENABLE | 37331a56b1a2SImre Deak DIGITAL_PORTA_PULSE_DURATION_2ms; 37341a56b1a2SImre Deak I915_WRITE(DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); 37351a56b1a2SImre Deak } 37361a56b1a2SImre Deak 373791d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) 3738e4ce95aaSVille Syrjälä { 37391a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 3740e4ce95aaSVille Syrjälä 374191d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 8) { 37423a3b3c7dSVille Syrjälä hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG; 374391d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bdw); 37443a3b3c7dSVille Syrjälä 37453a3b3c7dSVille Syrjälä bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 374691d14251STvrtko Ursulin } else if (INTEL_GEN(dev_priv) >= 7) { 374723bb4cb5SVille Syrjälä hotplug_irqs = DE_DP_A_HOTPLUG_IVB; 374891d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ivb); 37493a3b3c7dSVille Syrjälä 37503a3b3c7dSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 375123bb4cb5SVille Syrjälä } else { 3752e4ce95aaSVille Syrjälä hotplug_irqs = DE_DP_A_HOTPLUG; 375391d14251STvrtko Ursulin enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_ilk); 3754e4ce95aaSVille Syrjälä 3755e4ce95aaSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 37563a3b3c7dSVille Syrjälä } 3757e4ce95aaSVille Syrjälä 37581a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3759e4ce95aaSVille Syrjälä 376091d14251STvrtko Ursulin ibx_hpd_irq_setup(dev_priv); 3761e4ce95aaSVille Syrjälä } 3762e4ce95aaSVille Syrjälä 37632a57d9ccSImre Deak static void __bxt_hpd_detection_setup(struct drm_i915_private *dev_priv, 37642a57d9ccSImre Deak u32 enabled_irqs) 3765e0a20ad7SShashank Sharma { 37662a57d9ccSImre Deak u32 hotplug; 3767e0a20ad7SShashank Sharma 3768a52bb15bSVille Syrjälä hotplug = I915_READ(PCH_PORT_HOTPLUG); 37692a57d9ccSImre Deak hotplug |= PORTA_HOTPLUG_ENABLE | 37702a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 37712a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE; 3772d252bf68SShubhangi Shrivastava 3773d252bf68SShubhangi Shrivastava DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n", 3774d252bf68SShubhangi Shrivastava hotplug, enabled_irqs); 3775d252bf68SShubhangi Shrivastava hotplug &= ~BXT_DDI_HPD_INVERT_MASK; 3776d252bf68SShubhangi Shrivastava 3777d252bf68SShubhangi Shrivastava /* 3778d252bf68SShubhangi Shrivastava * For BXT invert bit has to be set based on AOB design 3779d252bf68SShubhangi Shrivastava * for HPD detection logic, update it based on VBT fields. 3780d252bf68SShubhangi Shrivastava */ 3781d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) && 3782d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_A)) 3783d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIA_HPD_INVERT; 3784d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && 3785d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_B)) 3786d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIB_HPD_INVERT; 3787d252bf68SShubhangi Shrivastava if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && 3788d252bf68SShubhangi Shrivastava intel_bios_is_port_hpd_inverted(dev_priv, PORT_C)) 3789d252bf68SShubhangi Shrivastava hotplug |= BXT_DDIC_HPD_INVERT; 3790d252bf68SShubhangi Shrivastava 3791a52bb15bSVille Syrjälä I915_WRITE(PCH_PORT_HOTPLUG, hotplug); 3792e0a20ad7SShashank Sharma } 3793e0a20ad7SShashank Sharma 37942a57d9ccSImre Deak static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) 37952a57d9ccSImre Deak { 37962a57d9ccSImre Deak __bxt_hpd_detection_setup(dev_priv, BXT_DE_PORT_HOTPLUG_MASK); 37972a57d9ccSImre Deak } 37982a57d9ccSImre Deak 37992a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) 38002a57d9ccSImre Deak { 38012a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 38022a57d9ccSImre Deak 38032a57d9ccSImre Deak enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_bxt); 38042a57d9ccSImre Deak hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK; 38052a57d9ccSImre Deak 38062a57d9ccSImre Deak bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 38072a57d9ccSImre Deak 38082a57d9ccSImre Deak __bxt_hpd_detection_setup(dev_priv, enabled_irqs); 38092a57d9ccSImre Deak } 38102a57d9ccSImre Deak 3811d46da437SPaulo Zanoni static void ibx_irq_postinstall(struct drm_device *dev) 3812d46da437SPaulo Zanoni { 3813fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 381482a28bcfSDaniel Vetter u32 mask; 3815d46da437SPaulo Zanoni 38166e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3817692a04cfSDaniel Vetter return; 3818692a04cfSDaniel Vetter 38196e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 38205c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 38214ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 38225c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 38234ebc6509SDhinakaran Pandiyan else 38244ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 38258664281bSPaulo Zanoni 38263488d4ebSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, SDEIIR); 3827d46da437SPaulo Zanoni I915_WRITE(SDEIMR, ~mask); 38282a57d9ccSImre Deak 38292a57d9ccSImre Deak if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || 38302a57d9ccSImre Deak HAS_PCH_LPT(dev_priv)) 38311a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 38322a57d9ccSImre Deak else 38332a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 3834d46da437SPaulo Zanoni } 3835d46da437SPaulo Zanoni 38360a9a8c91SDaniel Vetter static void gen5_gt_irq_postinstall(struct drm_device *dev) 38370a9a8c91SDaniel Vetter { 3838fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 38390a9a8c91SDaniel Vetter u32 pm_irqs, gt_irqs; 38400a9a8c91SDaniel Vetter 38410a9a8c91SDaniel Vetter pm_irqs = gt_irqs = 0; 38420a9a8c91SDaniel Vetter 38430a9a8c91SDaniel Vetter dev_priv->gt_irq_mask = ~0; 38443c9192bcSTvrtko Ursulin if (HAS_L3_DPF(dev_priv)) { 38450a9a8c91SDaniel Vetter /* L3 parity interrupt is always unmasked. */ 3846772c2a51STvrtko Ursulin dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev_priv); 3847772c2a51STvrtko Ursulin gt_irqs |= GT_PARITY_ERROR(dev_priv); 38480a9a8c91SDaniel Vetter } 38490a9a8c91SDaniel Vetter 38500a9a8c91SDaniel Vetter gt_irqs |= GT_RENDER_USER_INTERRUPT; 3851cf819effSLucas De Marchi if (IS_GEN(dev_priv, 5)) { 3852f8973c21SChris Wilson gt_irqs |= ILK_BSD_USER_INTERRUPT; 38530a9a8c91SDaniel Vetter } else { 38540a9a8c91SDaniel Vetter gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; 38550a9a8c91SDaniel Vetter } 38560a9a8c91SDaniel Vetter 38573488d4ebSVille Syrjälä GEN3_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); 38580a9a8c91SDaniel Vetter 3859b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 6) { 386078e68d36SImre Deak /* 386178e68d36SImre Deak * RPS interrupts will get enabled/disabled on demand when RPS 386278e68d36SImre Deak * itself is enabled/disabled. 386378e68d36SImre Deak */ 38648a68d464SChris Wilson if (HAS_ENGINE(dev_priv, VECS0)) { 38650a9a8c91SDaniel Vetter pm_irqs |= PM_VEBOX_USER_INTERRUPT; 3866f4e9af4fSAkash Goel dev_priv->pm_ier |= PM_VEBOX_USER_INTERRUPT; 3867f4e9af4fSAkash Goel } 38680a9a8c91SDaniel Vetter 3869f4e9af4fSAkash Goel dev_priv->pm_imr = 0xffffffff; 38703488d4ebSVille Syrjälä GEN3_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); 38710a9a8c91SDaniel Vetter } 38720a9a8c91SDaniel Vetter } 38730a9a8c91SDaniel Vetter 3874f71d4af4SJesse Barnes static int ironlake_irq_postinstall(struct drm_device *dev) 3875036a4a7dSZhenyu Wang { 3876fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 38778e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 38788e76f8dcSPaulo Zanoni 3879b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 7) { 38808e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 3881842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 38828e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 388323bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 388423bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 38858e76f8dcSPaulo Zanoni } else { 38868e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 3887842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 3888842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 3889e4ce95aaSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | 3890e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 3891e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 38928e76f8dcSPaulo Zanoni } 3893036a4a7dSZhenyu Wang 3894fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3895fc340442SDaniel Vetter gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); 38961aeb1b5fSDhinakaran Pandiyan intel_psr_irq_control(dev_priv, dev_priv->psr.debug); 3897fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 3898fc340442SDaniel Vetter } 3899fc340442SDaniel Vetter 39001ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 3901036a4a7dSZhenyu Wang 3902622364b6SPaulo Zanoni ibx_irq_pre_postinstall(dev); 3903622364b6SPaulo Zanoni 39043488d4ebSVille Syrjälä GEN3_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); 3905036a4a7dSZhenyu Wang 39060a9a8c91SDaniel Vetter gen5_gt_irq_postinstall(dev); 3907036a4a7dSZhenyu Wang 39081a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 39091a56b1a2SImre Deak 3910d46da437SPaulo Zanoni ibx_irq_postinstall(dev); 39117fe0b973SKeith Packard 391250a0bc90STvrtko Ursulin if (IS_IRONLAKE_M(dev_priv)) { 39136005ce42SDaniel Vetter /* Enable PCU event interrupts 39146005ce42SDaniel Vetter * 39156005ce42SDaniel Vetter * spinlocking not required here for correctness since interrupt 39164bc9d430SDaniel Vetter * setup is guaranteed to run in single-threaded context. But we 39174bc9d430SDaniel Vetter * need it to make the assert_spin_locked happy. */ 3918d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3919fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, DE_PCU_EVENT); 3920d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3921f97108d1SJesse Barnes } 3922f97108d1SJesse Barnes 3923036a4a7dSZhenyu Wang return 0; 3924036a4a7dSZhenyu Wang } 3925036a4a7dSZhenyu Wang 3926f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 3927f8b79e58SImre Deak { 392867520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3929f8b79e58SImre Deak 3930f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 3931f8b79e58SImre Deak return; 3932f8b79e58SImre Deak 3933f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 3934f8b79e58SImre Deak 3935d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 3936d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 3937ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3938f8b79e58SImre Deak } 3939d6c69803SVille Syrjälä } 3940f8b79e58SImre Deak 3941f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 3942f8b79e58SImre Deak { 394367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3944f8b79e58SImre Deak 3945f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 3946f8b79e58SImre Deak return; 3947f8b79e58SImre Deak 3948f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 3949f8b79e58SImre Deak 3950950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 3951ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 3952f8b79e58SImre Deak } 3953f8b79e58SImre Deak 39540e6c9a9eSVille Syrjälä 39550e6c9a9eSVille Syrjälä static int valleyview_irq_postinstall(struct drm_device *dev) 39560e6c9a9eSVille Syrjälä { 3957fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 39580e6c9a9eSVille Syrjälä 39590a9a8c91SDaniel Vetter gen5_gt_irq_postinstall(dev); 39607e231dbeSJesse Barnes 3961ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 39629918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3963ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3964ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3965ad22d106SVille Syrjälä 39667e231dbeSJesse Barnes I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 396734c7b8a7SVille Syrjälä POSTING_READ(VLV_MASTER_IER); 396820afbda2SDaniel Vetter 396920afbda2SDaniel Vetter return 0; 397020afbda2SDaniel Vetter } 397120afbda2SDaniel Vetter 3972abd58f01SBen Widawsky static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) 3973abd58f01SBen Widawsky { 3974abd58f01SBen Widawsky /* These are interrupts we'll toggle with the ring mask register */ 3975a9c287c9SJani Nikula u32 gt_interrupts[] = { 39768a68d464SChris Wilson (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | 397773d477f6SOscar Mateo GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | 397873d477f6SOscar Mateo GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT | 39798a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT), 39808a68d464SChris Wilson 39818a68d464SChris Wilson (GT_RENDER_USER_INTERRUPT << GEN8_VCS0_IRQ_SHIFT | 39828a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS0_IRQ_SHIFT | 3983abd58f01SBen Widawsky GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT | 39848a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT), 39858a68d464SChris Wilson 3986abd58f01SBen Widawsky 0, 39878a68d464SChris Wilson 39888a68d464SChris Wilson (GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT | 39898a68d464SChris Wilson GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT) 3990abd58f01SBen Widawsky }; 3991abd58f01SBen Widawsky 3992f4e9af4fSAkash Goel dev_priv->pm_ier = 0x0; 3993f4e9af4fSAkash Goel dev_priv->pm_imr = ~dev_priv->pm_ier; 39949a2d2d87SDeepak S GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); 39959a2d2d87SDeepak S GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); 399678e68d36SImre Deak /* 399778e68d36SImre Deak * RPS interrupts will get enabled/disabled on demand when RPS itself 399826705e20SSagar Arun Kamble * is enabled/disabled. Same wil be the case for GuC interrupts. 399978e68d36SImre Deak */ 4000f4e9af4fSAkash Goel GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_imr, dev_priv->pm_ier); 40019a2d2d87SDeepak S GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); 4002abd58f01SBen Widawsky } 4003abd58f01SBen Widawsky 4004abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 4005abd58f01SBen Widawsky { 4006a9c287c9SJani Nikula u32 de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE; 4007a9c287c9SJani Nikula u32 de_pipe_enables; 40083a3b3c7dSVille Syrjälä u32 de_port_masked = GEN8_AUX_CHANNEL_A; 40093a3b3c7dSVille Syrjälä u32 de_port_enables; 4010df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 40113a3b3c7dSVille Syrjälä enum pipe pipe; 4012770de83dSDamien Lespiau 4013df0d28c1SDhinakaran Pandiyan if (INTEL_GEN(dev_priv) <= 10) 4014df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 4015df0d28c1SDhinakaran Pandiyan 4016bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 9) { 4017842ebf7aSVille Syrjälä de_pipe_masked |= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 40183a3b3c7dSVille Syrjälä de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | 401988e04703SJesse Barnes GEN9_AUX_CHANNEL_D; 4020cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 40213a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 40223a3b3c7dSVille Syrjälä } else { 4023842ebf7aSVille Syrjälä de_pipe_masked |= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 40243a3b3c7dSVille Syrjälä } 4025770de83dSDamien Lespiau 4026bb187e93SJames Ausmus if (INTEL_GEN(dev_priv) >= 11) 4027bb187e93SJames Ausmus de_port_masked |= ICL_AUX_CHANNEL_E; 4028bb187e93SJames Ausmus 40299bb635d9SDhinakaran Pandiyan if (IS_CNL_WITH_PORT_F(dev_priv) || INTEL_GEN(dev_priv) >= 11) 4030a324fcacSRodrigo Vivi de_port_masked |= CNL_AUX_CHANNEL_F; 4031a324fcacSRodrigo Vivi 4032770de83dSDamien Lespiau de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | 4033770de83dSDamien Lespiau GEN8_PIPE_FIFO_UNDERRUN; 4034770de83dSDamien Lespiau 40353a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 4036cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 4037a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 4038a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 40393a3b3c7dSVille Syrjälä de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; 40403a3b3c7dSVille Syrjälä 4041e04f7eceSVille Syrjälä gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); 404254fd3149SDhinakaran Pandiyan intel_psr_irq_control(dev_priv, dev_priv->psr.debug); 4043e04f7eceSVille Syrjälä 40440a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 40450a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 4046abd58f01SBen Widawsky 4047f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 4048813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 4049813bde43SPaulo Zanoni GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, 4050813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 405135079899SPaulo Zanoni de_pipe_enables); 40520a195c02SMika Kahola } 4053abd58f01SBen Widawsky 40543488d4ebSVille Syrjälä GEN3_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 40553488d4ebSVille Syrjälä GEN3_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 40562a57d9ccSImre Deak 4057121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11) { 4058121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 4059b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 4060b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 4061121e758eSDhinakaran Pandiyan 4062121e758eSDhinakaran Pandiyan GEN3_IRQ_INIT(GEN11_DE_HPD_, ~de_hpd_masked, de_hpd_enables); 4063121e758eSDhinakaran Pandiyan gen11_hpd_detection_setup(dev_priv); 4064121e758eSDhinakaran Pandiyan } else if (IS_GEN9_LP(dev_priv)) { 40652a57d9ccSImre Deak bxt_hpd_detection_setup(dev_priv); 4066121e758eSDhinakaran Pandiyan } else if (IS_BROADWELL(dev_priv)) { 40671a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 4068abd58f01SBen Widawsky } 4069121e758eSDhinakaran Pandiyan } 4070abd58f01SBen Widawsky 4071abd58f01SBen Widawsky static int gen8_irq_postinstall(struct drm_device *dev) 4072abd58f01SBen Widawsky { 4073fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4074abd58f01SBen Widawsky 40756e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 4076622364b6SPaulo Zanoni ibx_irq_pre_postinstall(dev); 4077622364b6SPaulo Zanoni 4078abd58f01SBen Widawsky gen8_gt_irq_postinstall(dev_priv); 4079abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 4080abd58f01SBen Widawsky 40816e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 4082abd58f01SBen Widawsky ibx_irq_postinstall(dev); 4083abd58f01SBen Widawsky 408425286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 4085abd58f01SBen Widawsky 4086abd58f01SBen Widawsky return 0; 4087abd58f01SBen Widawsky } 4088abd58f01SBen Widawsky 408951951ae7SMika Kuoppala static void gen11_gt_irq_postinstall(struct drm_i915_private *dev_priv) 409051951ae7SMika Kuoppala { 409151951ae7SMika Kuoppala const u32 irqs = GT_RENDER_USER_INTERRUPT | GT_CONTEXT_SWITCH_INTERRUPT; 409251951ae7SMika Kuoppala 409351951ae7SMika Kuoppala BUILD_BUG_ON(irqs & 0xffff0000); 409451951ae7SMika Kuoppala 409551951ae7SMika Kuoppala /* Enable RCS, BCS, VCS and VECS class interrupts. */ 409651951ae7SMika Kuoppala I915_WRITE(GEN11_RENDER_COPY_INTR_ENABLE, irqs << 16 | irqs); 409751951ae7SMika Kuoppala I915_WRITE(GEN11_VCS_VECS_INTR_ENABLE, irqs << 16 | irqs); 409851951ae7SMika Kuoppala 409951951ae7SMika Kuoppala /* Unmask irqs on RCS, BCS, VCS and VECS engines. */ 410051951ae7SMika Kuoppala I915_WRITE(GEN11_RCS0_RSVD_INTR_MASK, ~(irqs << 16)); 410151951ae7SMika Kuoppala I915_WRITE(GEN11_BCS_RSVD_INTR_MASK, ~(irqs << 16)); 410251951ae7SMika Kuoppala I915_WRITE(GEN11_VCS0_VCS1_INTR_MASK, ~(irqs | irqs << 16)); 410351951ae7SMika Kuoppala I915_WRITE(GEN11_VCS2_VCS3_INTR_MASK, ~(irqs | irqs << 16)); 410451951ae7SMika Kuoppala I915_WRITE(GEN11_VECS0_VECS1_INTR_MASK, ~(irqs | irqs << 16)); 410551951ae7SMika Kuoppala 4106d02b98b8SOscar Mateo /* 4107d02b98b8SOscar Mateo * RPS interrupts will get enabled/disabled on demand when RPS itself 4108d02b98b8SOscar Mateo * is enabled/disabled. 4109d02b98b8SOscar Mateo */ 4110d02b98b8SOscar Mateo dev_priv->pm_ier = 0x0; 4111d02b98b8SOscar Mateo dev_priv->pm_imr = ~dev_priv->pm_ier; 4112d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0); 4113d02b98b8SOscar Mateo I915_WRITE(GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); 411451951ae7SMika Kuoppala } 411551951ae7SMika Kuoppala 411631604222SAnusha Srivatsa static void icp_irq_postinstall(struct drm_device *dev) 411731604222SAnusha Srivatsa { 411831604222SAnusha Srivatsa struct drm_i915_private *dev_priv = to_i915(dev); 411931604222SAnusha Srivatsa u32 mask = SDE_GMBUS_ICP; 412031604222SAnusha Srivatsa 412131604222SAnusha Srivatsa WARN_ON(I915_READ(SDEIER) != 0); 412231604222SAnusha Srivatsa I915_WRITE(SDEIER, 0xffffffff); 412331604222SAnusha Srivatsa POSTING_READ(SDEIER); 412431604222SAnusha Srivatsa 412531604222SAnusha Srivatsa gen3_assert_iir_is_zero(dev_priv, SDEIIR); 412631604222SAnusha Srivatsa I915_WRITE(SDEIMR, ~mask); 412731604222SAnusha Srivatsa 412831604222SAnusha Srivatsa icp_hpd_detection_setup(dev_priv); 412931604222SAnusha Srivatsa } 413031604222SAnusha Srivatsa 413151951ae7SMika Kuoppala static int gen11_irq_postinstall(struct drm_device *dev) 413251951ae7SMika Kuoppala { 413351951ae7SMika Kuoppala struct drm_i915_private *dev_priv = dev->dev_private; 4134df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 413551951ae7SMika Kuoppala 413629b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 413731604222SAnusha Srivatsa icp_irq_postinstall(dev); 413831604222SAnusha Srivatsa 413951951ae7SMika Kuoppala gen11_gt_irq_postinstall(dev_priv); 414051951ae7SMika Kuoppala gen8_de_irq_postinstall(dev_priv); 414151951ae7SMika Kuoppala 4142df0d28c1SDhinakaran Pandiyan GEN3_IRQ_INIT(GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 4143df0d28c1SDhinakaran Pandiyan 414451951ae7SMika Kuoppala I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); 414551951ae7SMika Kuoppala 414625286aacSDaniele Ceraolo Spurio gen11_master_intr_enable(dev_priv->uncore.regs); 4147c25f0c6aSDaniele Ceraolo Spurio POSTING_READ(GEN11_GFX_MSTR_IRQ); 414851951ae7SMika Kuoppala 414951951ae7SMika Kuoppala return 0; 415051951ae7SMika Kuoppala } 415151951ae7SMika Kuoppala 415243f328d7SVille Syrjälä static int cherryview_irq_postinstall(struct drm_device *dev) 415343f328d7SVille Syrjälä { 4154fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 415543f328d7SVille Syrjälä 415643f328d7SVille Syrjälä gen8_gt_irq_postinstall(dev_priv); 415743f328d7SVille Syrjälä 4158ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 41599918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 4160ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 4161ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 4162ad22d106SVille Syrjälä 4163e5328c43SVille Syrjälä I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 416443f328d7SVille Syrjälä POSTING_READ(GEN8_MASTER_IRQ); 416543f328d7SVille Syrjälä 416643f328d7SVille Syrjälä return 0; 416743f328d7SVille Syrjälä } 416843f328d7SVille Syrjälä 41696bcdb1c8SVille Syrjälä static void i8xx_irq_reset(struct drm_device *dev) 4170c2798b19SChris Wilson { 4171fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4172c2798b19SChris Wilson 417344d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 417444d9241eSVille Syrjälä 4175e9e9848aSVille Syrjälä GEN2_IRQ_RESET(); 4176c2798b19SChris Wilson } 4177c2798b19SChris Wilson 4178c2798b19SChris Wilson static int i8xx_irq_postinstall(struct drm_device *dev) 4179c2798b19SChris Wilson { 4180fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4181e9e9848aSVille Syrjälä u16 enable_mask; 4182c2798b19SChris Wilson 4183045cebd2SVille Syrjälä I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | 4184045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 4185c2798b19SChris Wilson 4186c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 4187c2798b19SChris Wilson dev_priv->irq_mask = 4188c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 418916659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 419016659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 4191c2798b19SChris Wilson 4192e9e9848aSVille Syrjälä enable_mask = 4193c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4194c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 419516659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 4196e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 4197e9e9848aSVille Syrjälä 4198e9e9848aSVille Syrjälä GEN2_IRQ_INIT(, dev_priv->irq_mask, enable_mask); 4199c2798b19SChris Wilson 4200379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4201379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4202d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4203755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4204755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4205d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4206379ef82dSDaniel Vetter 4207c2798b19SChris Wilson return 0; 4208c2798b19SChris Wilson } 4209c2798b19SChris Wilson 421078c357ddSVille Syrjälä static void i8xx_error_irq_ack(struct drm_i915_private *dev_priv, 421178c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 421278c357ddSVille Syrjälä { 421378c357ddSVille Syrjälä u16 emr; 421478c357ddSVille Syrjälä 421578c357ddSVille Syrjälä *eir = I915_READ16(EIR); 421678c357ddSVille Syrjälä 421778c357ddSVille Syrjälä if (*eir) 421878c357ddSVille Syrjälä I915_WRITE16(EIR, *eir); 421978c357ddSVille Syrjälä 422078c357ddSVille Syrjälä *eir_stuck = I915_READ16(EIR); 422178c357ddSVille Syrjälä if (*eir_stuck == 0) 422278c357ddSVille Syrjälä return; 422378c357ddSVille Syrjälä 422478c357ddSVille Syrjälä /* 422578c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 422678c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 422778c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 422878c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 422978c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 423078c357ddSVille Syrjälä * cleared except by handling the underlying error 423178c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 423278c357ddSVille Syrjälä * remains set. 423378c357ddSVille Syrjälä */ 423478c357ddSVille Syrjälä emr = I915_READ16(EMR); 423578c357ddSVille Syrjälä I915_WRITE16(EMR, 0xffff); 423678c357ddSVille Syrjälä I915_WRITE16(EMR, emr | *eir_stuck); 423778c357ddSVille Syrjälä } 423878c357ddSVille Syrjälä 423978c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 424078c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 424178c357ddSVille Syrjälä { 424278c357ddSVille Syrjälä DRM_DEBUG("Master Error: EIR 0x%04x\n", eir); 424378c357ddSVille Syrjälä 424478c357ddSVille Syrjälä if (eir_stuck) 424578c357ddSVille Syrjälä DRM_DEBUG_DRIVER("EIR stuck: 0x%04x, masked\n", eir_stuck); 424678c357ddSVille Syrjälä } 424778c357ddSVille Syrjälä 424878c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 424978c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 425078c357ddSVille Syrjälä { 425178c357ddSVille Syrjälä u32 emr; 425278c357ddSVille Syrjälä 425378c357ddSVille Syrjälä *eir = I915_READ(EIR); 425478c357ddSVille Syrjälä 425578c357ddSVille Syrjälä I915_WRITE(EIR, *eir); 425678c357ddSVille Syrjälä 425778c357ddSVille Syrjälä *eir_stuck = I915_READ(EIR); 425878c357ddSVille Syrjälä if (*eir_stuck == 0) 425978c357ddSVille Syrjälä return; 426078c357ddSVille Syrjälä 426178c357ddSVille Syrjälä /* 426278c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 426378c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 426478c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 426578c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 426678c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 426778c357ddSVille Syrjälä * cleared except by handling the underlying error 426878c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 426978c357ddSVille Syrjälä * remains set. 427078c357ddSVille Syrjälä */ 427178c357ddSVille Syrjälä emr = I915_READ(EMR); 427278c357ddSVille Syrjälä I915_WRITE(EMR, 0xffffffff); 427378c357ddSVille Syrjälä I915_WRITE(EMR, emr | *eir_stuck); 427478c357ddSVille Syrjälä } 427578c357ddSVille Syrjälä 427678c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 427778c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 427878c357ddSVille Syrjälä { 427978c357ddSVille Syrjälä DRM_DEBUG("Master Error, EIR 0x%08x\n", eir); 428078c357ddSVille Syrjälä 428178c357ddSVille Syrjälä if (eir_stuck) 428278c357ddSVille Syrjälä DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masked\n", eir_stuck); 428378c357ddSVille Syrjälä } 428478c357ddSVille Syrjälä 4285ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 4286c2798b19SChris Wilson { 428745a83f84SDaniel Vetter struct drm_device *dev = arg; 4288fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4289af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4290c2798b19SChris Wilson 42912dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 42922dd2a883SImre Deak return IRQ_NONE; 42932dd2a883SImre Deak 42941f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 42951f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 42961f814dacSImre Deak 4297af722d28SVille Syrjälä do { 4298af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 429978c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 4300af722d28SVille Syrjälä u16 iir; 4301af722d28SVille Syrjälä 4302c2798b19SChris Wilson iir = I915_READ16(IIR); 4303c2798b19SChris Wilson if (iir == 0) 4304af722d28SVille Syrjälä break; 4305c2798b19SChris Wilson 4306af722d28SVille Syrjälä ret = IRQ_HANDLED; 4307c2798b19SChris Wilson 4308eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4309eb64343cSVille Syrjälä * signalled in iir */ 4310eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4311c2798b19SChris Wilson 431278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 431378c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 431478c357ddSVille Syrjälä 4315fd3a4024SDaniel Vetter I915_WRITE16(IIR, iir); 4316c2798b19SChris Wilson 4317c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 43188a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 4319c2798b19SChris Wilson 432078c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 432178c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 4322af722d28SVille Syrjälä 4323eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4324af722d28SVille Syrjälä } while (0); 4325c2798b19SChris Wilson 43261f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 43271f814dacSImre Deak 43281f814dacSImre Deak return ret; 4329c2798b19SChris Wilson } 4330c2798b19SChris Wilson 43316bcdb1c8SVille Syrjälä static void i915_irq_reset(struct drm_device *dev) 4332a266c7d5SChris Wilson { 4333fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4334a266c7d5SChris Wilson 433556b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 43360706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 4337a266c7d5SChris Wilson I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 4338a266c7d5SChris Wilson } 4339a266c7d5SChris Wilson 434044d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 434144d9241eSVille Syrjälä 4342ba7eb789SVille Syrjälä GEN3_IRQ_RESET(); 4343a266c7d5SChris Wilson } 4344a266c7d5SChris Wilson 4345a266c7d5SChris Wilson static int i915_irq_postinstall(struct drm_device *dev) 4346a266c7d5SChris Wilson { 4347fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 434838bde180SChris Wilson u32 enable_mask; 4349a266c7d5SChris Wilson 4350045cebd2SVille Syrjälä I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | 4351045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 435238bde180SChris Wilson 435338bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 435438bde180SChris Wilson dev_priv->irq_mask = 435538bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 435638bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 435716659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 435816659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 435938bde180SChris Wilson 436038bde180SChris Wilson enable_mask = 436138bde180SChris Wilson I915_ASLE_INTERRUPT | 436238bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 436338bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 436416659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 436538bde180SChris Wilson I915_USER_INTERRUPT; 436638bde180SChris Wilson 436756b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 4368a266c7d5SChris Wilson /* Enable in IER... */ 4369a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 4370a266c7d5SChris Wilson /* and unmask in IMR */ 4371a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 4372a266c7d5SChris Wilson } 4373a266c7d5SChris Wilson 4374ba7eb789SVille Syrjälä GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); 4375a266c7d5SChris Wilson 4376379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4377379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4378d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4379755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4380755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4381d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4382379ef82dSDaniel Vetter 4383c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 4384c30bb1fdSVille Syrjälä 438520afbda2SDaniel Vetter return 0; 438620afbda2SDaniel Vetter } 438720afbda2SDaniel Vetter 4388ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 4389a266c7d5SChris Wilson { 439045a83f84SDaniel Vetter struct drm_device *dev = arg; 4391fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4392af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4393a266c7d5SChris Wilson 43942dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 43952dd2a883SImre Deak return IRQ_NONE; 43962dd2a883SImre Deak 43971f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 43981f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 43991f814dacSImre Deak 440038bde180SChris Wilson do { 4401eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 440278c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4403af722d28SVille Syrjälä u32 hotplug_status = 0; 4404af722d28SVille Syrjälä u32 iir; 4405a266c7d5SChris Wilson 4406af722d28SVille Syrjälä iir = I915_READ(IIR); 4407af722d28SVille Syrjälä if (iir == 0) 4408af722d28SVille Syrjälä break; 4409af722d28SVille Syrjälä 4410af722d28SVille Syrjälä ret = IRQ_HANDLED; 4411af722d28SVille Syrjälä 4412af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 4413af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 4414af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4415a266c7d5SChris Wilson 4416eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4417eb64343cSVille Syrjälä * signalled in iir */ 4418eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4419a266c7d5SChris Wilson 442078c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 442178c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 442278c357ddSVille Syrjälä 4423fd3a4024SDaniel Vetter I915_WRITE(IIR, iir); 4424a266c7d5SChris Wilson 4425a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 44268a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 4427a266c7d5SChris Wilson 442878c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 442978c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4430a266c7d5SChris Wilson 4431af722d28SVille Syrjälä if (hotplug_status) 4432af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4433af722d28SVille Syrjälä 4434af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4435af722d28SVille Syrjälä } while (0); 4436a266c7d5SChris Wilson 44371f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 44381f814dacSImre Deak 4439a266c7d5SChris Wilson return ret; 4440a266c7d5SChris Wilson } 4441a266c7d5SChris Wilson 44426bcdb1c8SVille Syrjälä static void i965_irq_reset(struct drm_device *dev) 4443a266c7d5SChris Wilson { 4444fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4445a266c7d5SChris Wilson 44460706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 4447a266c7d5SChris Wilson I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 4448a266c7d5SChris Wilson 444944d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 445044d9241eSVille Syrjälä 4451ba7eb789SVille Syrjälä GEN3_IRQ_RESET(); 4452a266c7d5SChris Wilson } 4453a266c7d5SChris Wilson 4454a266c7d5SChris Wilson static int i965_irq_postinstall(struct drm_device *dev) 4455a266c7d5SChris Wilson { 4456fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4457bbba0a97SChris Wilson u32 enable_mask; 4458a266c7d5SChris Wilson u32 error_mask; 4459a266c7d5SChris Wilson 4460045cebd2SVille Syrjälä /* 4461045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 4462045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 4463045cebd2SVille Syrjälä */ 4464045cebd2SVille Syrjälä if (IS_G4X(dev_priv)) { 4465045cebd2SVille Syrjälä error_mask = ~(GM45_ERROR_PAGE_TABLE | 4466045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 4467045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 4468045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4469045cebd2SVille Syrjälä } else { 4470045cebd2SVille Syrjälä error_mask = ~(I915_ERROR_PAGE_TABLE | 4471045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4472045cebd2SVille Syrjälä } 4473045cebd2SVille Syrjälä I915_WRITE(EMR, error_mask); 4474045cebd2SVille Syrjälä 4475a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 4476c30bb1fdSVille Syrjälä dev_priv->irq_mask = 4477c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 4478adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 4479bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4480bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 448178c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 4482bbba0a97SChris Wilson 4483c30bb1fdSVille Syrjälä enable_mask = 4484c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 4485c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 4486c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4487c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 448878c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 4489c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 4490bbba0a97SChris Wilson 449191d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4492bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 4493a266c7d5SChris Wilson 4494c30bb1fdSVille Syrjälä GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); 4495c30bb1fdSVille Syrjälä 4496b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4497b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4498d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4499755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 4500755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4501755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4502d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4503a266c7d5SChris Wilson 450491d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 450520afbda2SDaniel Vetter 450620afbda2SDaniel Vetter return 0; 450720afbda2SDaniel Vetter } 450820afbda2SDaniel Vetter 450991d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) 451020afbda2SDaniel Vetter { 451120afbda2SDaniel Vetter u32 hotplug_en; 451220afbda2SDaniel Vetter 451367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4514b5ea2d56SDaniel Vetter 4515adca4730SChris Wilson /* Note HDMI and DP share hotplug bits */ 4516e5868a31SEgbert Eich /* enable bits are the same for all generations */ 451791d14251STvrtko Ursulin hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915); 4518a266c7d5SChris Wilson /* Programming the CRT detection parameters tends 4519a266c7d5SChris Wilson to generate a spurious hotplug event about three 4520a266c7d5SChris Wilson seconds later. So just do it once. 4521a266c7d5SChris Wilson */ 452291d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4523a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; 4524a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; 4525a266c7d5SChris Wilson 4526a266c7d5SChris Wilson /* Ignore TV since it's buggy */ 45270706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, 4528f9e3dc78SJani Nikula HOTPLUG_INT_EN_MASK | 4529f9e3dc78SJani Nikula CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | 4530f9e3dc78SJani Nikula CRT_HOTPLUG_ACTIVATION_PERIOD_64, 45310706f17cSEgbert Eich hotplug_en); 4532a266c7d5SChris Wilson } 4533a266c7d5SChris Wilson 4534ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 4535a266c7d5SChris Wilson { 453645a83f84SDaniel Vetter struct drm_device *dev = arg; 4537fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 4538af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4539a266c7d5SChris Wilson 45402dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 45412dd2a883SImre Deak return IRQ_NONE; 45422dd2a883SImre Deak 45431f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 45441f814dacSImre Deak disable_rpm_wakeref_asserts(dev_priv); 45451f814dacSImre Deak 4546af722d28SVille Syrjälä do { 4547eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 454878c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4549af722d28SVille Syrjälä u32 hotplug_status = 0; 4550af722d28SVille Syrjälä u32 iir; 45512c8ba29fSChris Wilson 4552af722d28SVille Syrjälä iir = I915_READ(IIR); 4553af722d28SVille Syrjälä if (iir == 0) 4554af722d28SVille Syrjälä break; 4555af722d28SVille Syrjälä 4556af722d28SVille Syrjälä ret = IRQ_HANDLED; 4557af722d28SVille Syrjälä 4558af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 4559af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4560a266c7d5SChris Wilson 4561eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4562eb64343cSVille Syrjälä * signalled in iir */ 4563eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4564a266c7d5SChris Wilson 456578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 456678c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 456778c357ddSVille Syrjälä 4568fd3a4024SDaniel Vetter I915_WRITE(IIR, iir); 4569a266c7d5SChris Wilson 4570a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 45718a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); 4572af722d28SVille Syrjälä 4573a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 45748a68d464SChris Wilson intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); 4575a266c7d5SChris Wilson 457678c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 457778c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4578515ac2bbSDaniel Vetter 4579af722d28SVille Syrjälä if (hotplug_status) 4580af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4581af722d28SVille Syrjälä 4582af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4583af722d28SVille Syrjälä } while (0); 4584a266c7d5SChris Wilson 45851f814dacSImre Deak enable_rpm_wakeref_asserts(dev_priv); 45861f814dacSImre Deak 4587a266c7d5SChris Wilson return ret; 4588a266c7d5SChris Wilson } 4589a266c7d5SChris Wilson 4590fca52a55SDaniel Vetter /** 4591fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 4592fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4593fca52a55SDaniel Vetter * 4594fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 4595fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 4596fca52a55SDaniel Vetter */ 4597b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 4598f71d4af4SJesse Barnes { 459991c8a326SChris Wilson struct drm_device *dev = &dev_priv->drm; 4600562d9baeSSagar Arun Kamble struct intel_rps *rps = &dev_priv->gt_pm.rps; 4601cefcff8fSJoonas Lahtinen int i; 46028b2e326dSChris Wilson 4603*d938da6bSVille Syrjälä if (IS_I945GM(dev_priv)) 4604*d938da6bSVille Syrjälä i945gm_vblank_work_init(dev_priv); 4605*d938da6bSVille Syrjälä 460677913b39SJani Nikula intel_hpd_init_work(dev_priv); 460777913b39SJani Nikula 4608562d9baeSSagar Arun Kamble INIT_WORK(&rps->work, gen6_pm_rps_work); 4609cefcff8fSJoonas Lahtinen 4610a4da4fa4SDaniel Vetter INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); 4611cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4612cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 46138b2e326dSChris Wilson 46144805fe82STvrtko Ursulin if (HAS_GUC_SCHED(dev_priv)) 461526705e20SSagar Arun Kamble dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT; 461626705e20SSagar Arun Kamble 4617a6706b45SDeepak S /* Let's track the enabled rps events */ 4618666a4537SWayne Boyer if (IS_VALLEYVIEW(dev_priv)) 46196c65a587SVille Syrjälä /* WaGsvRC0ResidencyMethod:vlv */ 4620e0e8c7cbSChris Wilson dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED; 462131685c25SDeepak S else 46224668f695SChris Wilson dev_priv->pm_rps_events = (GEN6_PM_RP_UP_THRESHOLD | 46234668f695SChris Wilson GEN6_PM_RP_DOWN_THRESHOLD | 46244668f695SChris Wilson GEN6_PM_RP_DOWN_TIMEOUT); 4625a6706b45SDeepak S 4626562d9baeSSagar Arun Kamble rps->pm_intrmsk_mbz = 0; 46271800ad25SSagar Arun Kamble 46281800ad25SSagar Arun Kamble /* 4629acf2dc22SMika Kuoppala * SNB,IVB,HSW can while VLV,CHV may hard hang on looping batchbuffer 46301800ad25SSagar Arun Kamble * if GEN6_PM_UP_EI_EXPIRED is masked. 46311800ad25SSagar Arun Kamble * 46321800ad25SSagar Arun Kamble * TODO: verify if this can be reproduced on VLV,CHV. 46331800ad25SSagar Arun Kamble */ 4634bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) <= 7) 4635562d9baeSSagar Arun Kamble rps->pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED; 46361800ad25SSagar Arun Kamble 4637bca2bf2aSPandiyan, Dhinakaran if (INTEL_GEN(dev_priv) >= 8) 4638562d9baeSSagar Arun Kamble rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; 46391800ad25SSagar Arun Kamble 464032db0b65SVille Syrjälä if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) 4641fd8f507cSVille Syrjälä dev->driver->get_vblank_counter = g4x_get_vblank_counter; 464232db0b65SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 3) 4643391f75e2SVille Syrjälä dev->driver->get_vblank_counter = i915_get_vblank_counter; 4644f71d4af4SJesse Barnes 464521da2700SVille Syrjälä /* 464621da2700SVille Syrjälä * Opt out of the vblank disable timer on everything except gen2. 464721da2700SVille Syrjälä * Gen2 doesn't have a hardware frame counter and so depends on 464821da2700SVille Syrjälä * vblank interrupts to produce sane vblank seuquence numbers. 464921da2700SVille Syrjälä */ 4650cf819effSLucas De Marchi if (!IS_GEN(dev_priv, 2)) 465121da2700SVille Syrjälä dev->vblank_disable_immediate = true; 465221da2700SVille Syrjälä 4653262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 4654262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 4655262fd485SChris Wilson * special care to avoid writing any of the display block registers 4656262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 4657262fd485SChris Wilson * in this case to the runtime pm. 4658262fd485SChris Wilson */ 4659262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 4660262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 4661262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 4662262fd485SChris Wilson 4663317eaa95SLyude dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; 46649a64c650SLyude Paul /* If we have MST support, we want to avoid doing short HPD IRQ storm 46659a64c650SLyude Paul * detection, as short HPD storms will occur as a natural part of 46669a64c650SLyude Paul * sideband messaging with MST. 46679a64c650SLyude Paul * On older platforms however, IRQ storms can occur with both long and 46689a64c650SLyude Paul * short pulses, as seen on some G4x systems. 46699a64c650SLyude Paul */ 46709a64c650SLyude Paul dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); 4671317eaa95SLyude 46721bf6ad62SDaniel Vetter dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; 4673f71d4af4SJesse Barnes dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; 4674f71d4af4SJesse Barnes 4675b963291cSDaniel Vetter if (IS_CHERRYVIEW(dev_priv)) { 467643f328d7SVille Syrjälä dev->driver->irq_handler = cherryview_irq_handler; 46776bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = cherryview_irq_reset; 467843f328d7SVille Syrjälä dev->driver->irq_postinstall = cherryview_irq_postinstall; 46796bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = cherryview_irq_reset; 468086e83e35SChris Wilson dev->driver->enable_vblank = i965_enable_vblank; 468186e83e35SChris Wilson dev->driver->disable_vblank = i965_disable_vblank; 468243f328d7SVille Syrjälä dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 4683b963291cSDaniel Vetter } else if (IS_VALLEYVIEW(dev_priv)) { 46847e231dbeSJesse Barnes dev->driver->irq_handler = valleyview_irq_handler; 46856bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = valleyview_irq_reset; 46867e231dbeSJesse Barnes dev->driver->irq_postinstall = valleyview_irq_postinstall; 46876bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = valleyview_irq_reset; 468886e83e35SChris Wilson dev->driver->enable_vblank = i965_enable_vblank; 468986e83e35SChris Wilson dev->driver->disable_vblank = i965_disable_vblank; 4690fa00abe0SEgbert Eich dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 469151951ae7SMika Kuoppala } else if (INTEL_GEN(dev_priv) >= 11) { 469251951ae7SMika Kuoppala dev->driver->irq_handler = gen11_irq_handler; 469351951ae7SMika Kuoppala dev->driver->irq_preinstall = gen11_irq_reset; 469451951ae7SMika Kuoppala dev->driver->irq_postinstall = gen11_irq_postinstall; 469551951ae7SMika Kuoppala dev->driver->irq_uninstall = gen11_irq_reset; 469651951ae7SMika Kuoppala dev->driver->enable_vblank = gen8_enable_vblank; 469751951ae7SMika Kuoppala dev->driver->disable_vblank = gen8_disable_vblank; 4698121e758eSDhinakaran Pandiyan dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; 4699bca2bf2aSPandiyan, Dhinakaran } else if (INTEL_GEN(dev_priv) >= 8) { 4700abd58f01SBen Widawsky dev->driver->irq_handler = gen8_irq_handler; 4701723761b8SDaniel Vetter dev->driver->irq_preinstall = gen8_irq_reset; 4702abd58f01SBen Widawsky dev->driver->irq_postinstall = gen8_irq_postinstall; 47036bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = gen8_irq_reset; 4704abd58f01SBen Widawsky dev->driver->enable_vblank = gen8_enable_vblank; 4705abd58f01SBen Widawsky dev->driver->disable_vblank = gen8_disable_vblank; 4706cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 4707e0a20ad7SShashank Sharma dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; 4708c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 47096dbf30ceSVille Syrjälä dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; 47106dbf30ceSVille Syrjälä else 47113a3b3c7dSVille Syrjälä dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; 47126e266956STvrtko Ursulin } else if (HAS_PCH_SPLIT(dev_priv)) { 4713f71d4af4SJesse Barnes dev->driver->irq_handler = ironlake_irq_handler; 4714723761b8SDaniel Vetter dev->driver->irq_preinstall = ironlake_irq_reset; 4715f71d4af4SJesse Barnes dev->driver->irq_postinstall = ironlake_irq_postinstall; 47166bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = ironlake_irq_reset; 4717f71d4af4SJesse Barnes dev->driver->enable_vblank = ironlake_enable_vblank; 4718f71d4af4SJesse Barnes dev->driver->disable_vblank = ironlake_disable_vblank; 4719e4ce95aaSVille Syrjälä dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; 4720f71d4af4SJesse Barnes } else { 4721cf819effSLucas De Marchi if (IS_GEN(dev_priv, 2)) { 47226bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = i8xx_irq_reset; 4723c2798b19SChris Wilson dev->driver->irq_postinstall = i8xx_irq_postinstall; 4724c2798b19SChris Wilson dev->driver->irq_handler = i8xx_irq_handler; 47256bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = i8xx_irq_reset; 472686e83e35SChris Wilson dev->driver->enable_vblank = i8xx_enable_vblank; 472786e83e35SChris Wilson dev->driver->disable_vblank = i8xx_disable_vblank; 4728*d938da6bSVille Syrjälä } else if (IS_I945GM(dev_priv)) { 4729*d938da6bSVille Syrjälä dev->driver->irq_preinstall = i915_irq_reset; 4730*d938da6bSVille Syrjälä dev->driver->irq_postinstall = i915_irq_postinstall; 4731*d938da6bSVille Syrjälä dev->driver->irq_uninstall = i915_irq_reset; 4732*d938da6bSVille Syrjälä dev->driver->irq_handler = i915_irq_handler; 4733*d938da6bSVille Syrjälä dev->driver->enable_vblank = i945gm_enable_vblank; 4734*d938da6bSVille Syrjälä dev->driver->disable_vblank = i945gm_disable_vblank; 4735cf819effSLucas De Marchi } else if (IS_GEN(dev_priv, 3)) { 47366bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = i915_irq_reset; 4737a266c7d5SChris Wilson dev->driver->irq_postinstall = i915_irq_postinstall; 47386bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = i915_irq_reset; 4739a266c7d5SChris Wilson dev->driver->irq_handler = i915_irq_handler; 474086e83e35SChris Wilson dev->driver->enable_vblank = i8xx_enable_vblank; 474186e83e35SChris Wilson dev->driver->disable_vblank = i8xx_disable_vblank; 4742c2798b19SChris Wilson } else { 47436bcdb1c8SVille Syrjälä dev->driver->irq_preinstall = i965_irq_reset; 4744a266c7d5SChris Wilson dev->driver->irq_postinstall = i965_irq_postinstall; 47456bcdb1c8SVille Syrjälä dev->driver->irq_uninstall = i965_irq_reset; 4746a266c7d5SChris Wilson dev->driver->irq_handler = i965_irq_handler; 474786e83e35SChris Wilson dev->driver->enable_vblank = i965_enable_vblank; 474886e83e35SChris Wilson dev->driver->disable_vblank = i965_disable_vblank; 4749c2798b19SChris Wilson } 4750778eb334SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv)) 4751778eb334SVille Syrjälä dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 4752f71d4af4SJesse Barnes } 4753f71d4af4SJesse Barnes } 475420afbda2SDaniel Vetter 4755fca52a55SDaniel Vetter /** 4756cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 4757cefcff8fSJoonas Lahtinen * @i915: i915 device instance 4758cefcff8fSJoonas Lahtinen * 4759cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 4760cefcff8fSJoonas Lahtinen */ 4761cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 4762cefcff8fSJoonas Lahtinen { 4763cefcff8fSJoonas Lahtinen int i; 4764cefcff8fSJoonas Lahtinen 4765*d938da6bSVille Syrjälä if (IS_I945GM(i915)) 4766*d938da6bSVille Syrjälä i945gm_vblank_work_fini(i915); 4767*d938da6bSVille Syrjälä 4768cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4769cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 4770cefcff8fSJoonas Lahtinen } 4771cefcff8fSJoonas Lahtinen 4772cefcff8fSJoonas Lahtinen /** 4773fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 4774fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4775fca52a55SDaniel Vetter * 4776fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 4777fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 4778fca52a55SDaniel Vetter * 4779fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 4780fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 4781fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 4782fca52a55SDaniel Vetter */ 47832aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 47842aeb7d3aSDaniel Vetter { 47852aeb7d3aSDaniel Vetter /* 47862aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 47872aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 47882aeb7d3aSDaniel Vetter * special cases in our ordering checks. 47892aeb7d3aSDaniel Vetter */ 4790ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 47912aeb7d3aSDaniel Vetter 479291c8a326SChris Wilson return drm_irq_install(&dev_priv->drm, dev_priv->drm.pdev->irq); 47932aeb7d3aSDaniel Vetter } 47942aeb7d3aSDaniel Vetter 4795fca52a55SDaniel Vetter /** 4796fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 4797fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4798fca52a55SDaniel Vetter * 4799fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 4800fca52a55SDaniel Vetter * resources acquired in the init functions. 4801fca52a55SDaniel Vetter */ 48022aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 48032aeb7d3aSDaniel Vetter { 480491c8a326SChris Wilson drm_irq_uninstall(&dev_priv->drm); 48052aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 4806ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 48072aeb7d3aSDaniel Vetter } 48082aeb7d3aSDaniel Vetter 4809fca52a55SDaniel Vetter /** 4810fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 4811fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4812fca52a55SDaniel Vetter * 4813fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 4814fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4815fca52a55SDaniel Vetter */ 4816b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 4817c67a470bSPaulo Zanoni { 481891c8a326SChris Wilson dev_priv->drm.driver->irq_uninstall(&dev_priv->drm); 4819ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 482091c8a326SChris Wilson synchronize_irq(dev_priv->drm.irq); 4821c67a470bSPaulo Zanoni } 4822c67a470bSPaulo Zanoni 4823fca52a55SDaniel Vetter /** 4824fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 4825fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4826fca52a55SDaniel Vetter * 4827fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 4828fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4829fca52a55SDaniel Vetter */ 4830b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 4831c67a470bSPaulo Zanoni { 4832ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 483391c8a326SChris Wilson dev_priv->drm.driver->irq_preinstall(&dev_priv->drm); 483491c8a326SChris Wilson dev_priv->drm.driver->irq_postinstall(&dev_priv->drm); 4835c67a470bSPaulo Zanoni } 4836