1c0e09200SDave Airlie /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- 2c0e09200SDave Airlie */ 3c0e09200SDave Airlie /* 4c0e09200SDave Airlie * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5c0e09200SDave Airlie * All Rights Reserved. 6c0e09200SDave Airlie * 7c0e09200SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 8c0e09200SDave Airlie * copy of this software and associated documentation files (the 9c0e09200SDave Airlie * "Software"), to deal in the Software without restriction, including 10c0e09200SDave Airlie * without limitation the rights to use, copy, modify, merge, publish, 11c0e09200SDave Airlie * distribute, sub license, and/or sell copies of the Software, and to 12c0e09200SDave Airlie * permit persons to whom the Software is furnished to do so, subject to 13c0e09200SDave Airlie * the following conditions: 14c0e09200SDave Airlie * 15c0e09200SDave Airlie * The above copyright notice and this permission notice (including the 16c0e09200SDave Airlie * next paragraph) shall be included in all copies or substantial portions 17c0e09200SDave Airlie * of the Software. 18c0e09200SDave Airlie * 19c0e09200SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20c0e09200SDave Airlie * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21c0e09200SDave Airlie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22c0e09200SDave Airlie * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23c0e09200SDave Airlie * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24c0e09200SDave Airlie * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25c0e09200SDave Airlie * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26c0e09200SDave Airlie * 27c0e09200SDave Airlie */ 28c0e09200SDave Airlie 29a70491ccSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 30a70491ccSJoe Perches 3155367a27SJani Nikula #include <linux/slab.h> 3255367a27SJani Nikula #include <linux/sysrq.h> 3355367a27SJani Nikula 34fcd70cd3SDaniel Vetter #include <drm/drm_drv.h> 3555367a27SJani Nikula 363c0deb14SJani Nikula #include "display/icl_dsi_regs.h" 377785ae0bSVille Syrjälä #include "display/intel_de.h" 38fd2b94a5SJani Nikula #include "display/intel_display_trace.h" 391d455f8dSJani Nikula #include "display/intel_display_types.h" 40df0566a6SJani Nikula #include "display/intel_fifo_underrun.h" 41df0566a6SJani Nikula #include "display/intel_hotplug.h" 42df0566a6SJani Nikula #include "display/intel_lpe_audio.h" 43df0566a6SJani Nikula #include "display/intel_psr.h" 44df0566a6SJani Nikula 45b3786b29SChris Wilson #include "gt/intel_breadcrumbs.h" 462239e6dfSDaniele Ceraolo Spurio #include "gt/intel_gt.h" 47cf1c97dcSAndi Shyti #include "gt/intel_gt_irq.h" 48d762043fSAndi Shyti #include "gt/intel_gt_pm_irq.h" 490d6419e9SMatt Roper #include "gt/intel_gt_regs.h" 503e7abf81SAndi Shyti #include "gt/intel_rps.h" 512239e6dfSDaniele Ceraolo Spurio 5224524e3fSJani Nikula #include "i915_driver.h" 53c0e09200SDave Airlie #include "i915_drv.h" 54440e2b3dSJani Nikula #include "i915_irq.h" 55c0e09200SDave Airlie 56fca52a55SDaniel Vetter /** 57fca52a55SDaniel Vetter * DOC: interrupt handling 58fca52a55SDaniel Vetter * 59fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 60fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 61fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 62fca52a55SDaniel Vetter */ 63fca52a55SDaniel Vetter 649c6508b9SThomas Gleixner /* 659c6508b9SThomas Gleixner * Interrupt statistic for PMU. Increments the counter only if the 6678f48aa6SBo Liu * interrupt originated from the GPU so interrupts from a device which 679c6508b9SThomas Gleixner * shares the interrupt line are not accounted. 689c6508b9SThomas Gleixner */ 699c6508b9SThomas Gleixner static inline void pmu_irq_stats(struct drm_i915_private *i915, 709c6508b9SThomas Gleixner irqreturn_t res) 719c6508b9SThomas Gleixner { 729c6508b9SThomas Gleixner if (unlikely(res != IRQ_HANDLED)) 739c6508b9SThomas Gleixner return; 749c6508b9SThomas Gleixner 759c6508b9SThomas Gleixner /* 769c6508b9SThomas Gleixner * A clever compiler translates that into INC. A not so clever one 779c6508b9SThomas Gleixner * should at least prevent store tearing. 789c6508b9SThomas Gleixner */ 799c6508b9SThomas Gleixner WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1); 809c6508b9SThomas Gleixner } 819c6508b9SThomas Gleixner 8248ef15d3SJosé Roberto de Souza typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val); 83dfefe7bcSVille Syrjälä typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder); 8448ef15d3SJosé Roberto de Souza 85e4ce95aaSVille Syrjälä static const u32 hpd_ilk[HPD_NUM_PINS] = { 86e4ce95aaSVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG, 87e4ce95aaSVille Syrjälä }; 88e4ce95aaSVille Syrjälä 8923bb4cb5SVille Syrjälä static const u32 hpd_ivb[HPD_NUM_PINS] = { 9023bb4cb5SVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, 9123bb4cb5SVille Syrjälä }; 9223bb4cb5SVille Syrjälä 933a3b3c7dSVille Syrjälä static const u32 hpd_bdw[HPD_NUM_PINS] = { 94e5abaab3SVille Syrjälä [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), 953a3b3c7dSVille Syrjälä }; 963a3b3c7dSVille Syrjälä 977c7e10dbSVille Syrjälä static const u32 hpd_ibx[HPD_NUM_PINS] = { 98e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG, 99e5868a31SEgbert Eich [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, 100e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG, 101e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG, 1027203d49cSVille Syrjälä [HPD_PORT_D] = SDE_PORTD_HOTPLUG, 103e5868a31SEgbert Eich }; 104e5868a31SEgbert Eich 1057c7e10dbSVille Syrjälä static const u32 hpd_cpt[HPD_NUM_PINS] = { 106e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, 10773c352a2SDaniel Vetter [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, 108e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 109e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 1107203d49cSVille Syrjälä [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 111e5868a31SEgbert Eich }; 112e5868a31SEgbert Eich 11326951cafSXiong Zhang static const u32 hpd_spt[HPD_NUM_PINS] = { 11474c0b395SVille Syrjälä [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, 11526951cafSXiong Zhang [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 11626951cafSXiong Zhang [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 11726951cafSXiong Zhang [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 1187203d49cSVille Syrjälä [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT, 11926951cafSXiong Zhang }; 12026951cafSXiong Zhang 1217c7e10dbSVille Syrjälä static const u32 hpd_mask_i915[HPD_NUM_PINS] = { 122e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_EN, 123e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, 124e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, 125e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN, 126e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN, 1277203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN, 128e5868a31SEgbert Eich }; 129e5868a31SEgbert Eich 1307c7e10dbSVille Syrjälä static const u32 hpd_status_g4x[HPD_NUM_PINS] = { 131e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 132e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, 133e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, 134e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 135e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 1367203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, 137e5868a31SEgbert Eich }; 138e5868a31SEgbert Eich 1394bca26d0SVille Syrjälä static const u32 hpd_status_i915[HPD_NUM_PINS] = { 140e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 141e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, 142e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, 143e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 144e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 1457203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, 146e5868a31SEgbert Eich }; 147e5868a31SEgbert Eich 148e0a20ad7SShashank Sharma static const u32 hpd_bxt[HPD_NUM_PINS] = { 149e5abaab3SVille Syrjälä [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), 150e5abaab3SVille Syrjälä [HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B), 151e5abaab3SVille Syrjälä [HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C), 152e0a20ad7SShashank Sharma }; 153e0a20ad7SShashank Sharma 154b796b971SDhinakaran Pandiyan static const u32 hpd_gen11[HPD_NUM_PINS] = { 1555b76e860SVille Syrjälä [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1), 1565b76e860SVille Syrjälä [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2), 1575b76e860SVille Syrjälä [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3), 1585b76e860SVille Syrjälä [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4), 1595b76e860SVille Syrjälä [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5), 1605b76e860SVille Syrjälä [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6), 16148ef15d3SJosé Roberto de Souza }; 16248ef15d3SJosé Roberto de Souza 16331604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = { 1645f371a81SVille Syrjälä [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), 1655f371a81SVille Syrjälä [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), 1665f371a81SVille Syrjälä [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), 16797011359SVille Syrjälä [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1), 16897011359SVille Syrjälä [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2), 16997011359SVille Syrjälä [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3), 17097011359SVille Syrjälä [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4), 17197011359SVille Syrjälä [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5), 17297011359SVille Syrjälä [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6), 17352dfdba0SLucas De Marchi }; 17452dfdba0SLucas De Marchi 175229f31e2SLucas De Marchi static const u32 hpd_sde_dg1[HPD_NUM_PINS] = { 1765f371a81SVille Syrjälä [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), 1775f371a81SVille Syrjälä [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), 1785f371a81SVille Syrjälä [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), 1795f371a81SVille Syrjälä [HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D), 1802f8a6699SMatt Roper [HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1), 181229f31e2SLucas De Marchi }; 182229f31e2SLucas De Marchi 1830398993bSVille Syrjälä static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) 1840398993bSVille Syrjälä { 1855a4dd6f0SJani Nikula struct intel_hotplug *hpd = &dev_priv->display.hotplug; 1860398993bSVille Syrjälä 1870398993bSVille Syrjälä if (HAS_GMCH(dev_priv)) { 1880398993bSVille Syrjälä if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || 1890398993bSVille Syrjälä IS_CHERRYVIEW(dev_priv)) 1900398993bSVille Syrjälä hpd->hpd = hpd_status_g4x; 1910398993bSVille Syrjälä else 1920398993bSVille Syrjälä hpd->hpd = hpd_status_i915; 1930398993bSVille Syrjälä return; 1940398993bSVille Syrjälä } 1950398993bSVille Syrjälä 196373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) 1970398993bSVille Syrjälä hpd->hpd = hpd_gen11; 19870bfb307SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 1990398993bSVille Syrjälä hpd->hpd = hpd_bxt; 200*dded35acSVille Syrjälä else if (DISPLAY_VER(dev_priv) == 9) 201*dded35acSVille Syrjälä hpd->hpd = NULL; /* no north HPD on SKL */ 202373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 8) 2030398993bSVille Syrjälä hpd->hpd = hpd_bdw; 204373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 7) 2050398993bSVille Syrjälä hpd->hpd = hpd_ivb; 2060398993bSVille Syrjälä else 2070398993bSVille Syrjälä hpd->hpd = hpd_ilk; 2080398993bSVille Syrjälä 209229f31e2SLucas De Marchi if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) && 210229f31e2SLucas De Marchi (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv))) 2110398993bSVille Syrjälä return; 2120398993bSVille Syrjälä 2133176fb66SMatt Roper if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) 214229f31e2SLucas De Marchi hpd->pch_hpd = hpd_sde_dg1; 215fa58c9e4SAnusha Srivatsa else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2160398993bSVille Syrjälä hpd->pch_hpd = hpd_icp; 2170398993bSVille Syrjälä else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv)) 2180398993bSVille Syrjälä hpd->pch_hpd = hpd_spt; 2190398993bSVille Syrjälä else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv)) 2200398993bSVille Syrjälä hpd->pch_hpd = hpd_cpt; 2210398993bSVille Syrjälä else if (HAS_PCH_IBX(dev_priv)) 2220398993bSVille Syrjälä hpd->pch_hpd = hpd_ibx; 2230398993bSVille Syrjälä else 2240398993bSVille Syrjälä MISSING_CASE(INTEL_PCH_TYPE(dev_priv)); 2250398993bSVille Syrjälä } 2260398993bSVille Syrjälä 227aca9310aSAnshuman Gupta static void 228aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) 229aca9310aSAnshuman Gupta { 2307794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 231aca9310aSAnshuman Gupta 232aca9310aSAnshuman Gupta drm_crtc_handle_vblank(&crtc->base); 233aca9310aSAnshuman Gupta } 234aca9310aSAnshuman Gupta 235cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, 23668eb49b1SPaulo Zanoni i915_reg_t iir, i915_reg_t ier) 23768eb49b1SPaulo Zanoni { 23865f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, 0xffffffff); 23965f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 24068eb49b1SPaulo Zanoni 24165f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, 0); 24268eb49b1SPaulo Zanoni 2435c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 24465f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24565f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 24665f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24765f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 24868eb49b1SPaulo Zanoni } 2495c502442SPaulo Zanoni 250ad7632ffSJani Nikula static void gen2_irq_reset(struct intel_uncore *uncore) 25168eb49b1SPaulo Zanoni { 25265f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, 0xffff); 25365f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 254a9d356a6SPaulo Zanoni 25565f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, 0); 25668eb49b1SPaulo Zanoni 25768eb49b1SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 25865f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 25965f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 26065f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 26165f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 26268eb49b1SPaulo Zanoni } 26368eb49b1SPaulo Zanoni 264337ba017SPaulo Zanoni /* 265337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 266337ba017SPaulo Zanoni */ 26765f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) 268b51a2842SVille Syrjälä { 26965f42cdcSPaulo Zanoni u32 val = intel_uncore_read(uncore, reg); 270b51a2842SVille Syrjälä 271b51a2842SVille Syrjälä if (val == 0) 272b51a2842SVille Syrjälä return; 273b51a2842SVille Syrjälä 274a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 275a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 276f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 27765f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 27865f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 27965f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 28065f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 281b51a2842SVille Syrjälä } 282337ba017SPaulo Zanoni 28365f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore) 284e9e9848aSVille Syrjälä { 28565f42cdcSPaulo Zanoni u16 val = intel_uncore_read16(uncore, GEN2_IIR); 286e9e9848aSVille Syrjälä 287e9e9848aSVille Syrjälä if (val == 0) 288e9e9848aSVille Syrjälä return; 289e9e9848aSVille Syrjälä 290a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 291a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 2929d9523d8SPaulo Zanoni i915_mmio_reg_offset(GEN2_IIR), val); 29365f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29465f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 29565f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29665f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 297e9e9848aSVille Syrjälä } 298e9e9848aSVille Syrjälä 299cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore, 30068eb49b1SPaulo Zanoni i915_reg_t imr, u32 imr_val, 30168eb49b1SPaulo Zanoni i915_reg_t ier, u32 ier_val, 30268eb49b1SPaulo Zanoni i915_reg_t iir) 30368eb49b1SPaulo Zanoni { 30465f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(uncore, iir); 30535079899SPaulo Zanoni 30665f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, ier_val); 30765f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, imr_val); 30865f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 30968eb49b1SPaulo Zanoni } 31035079899SPaulo Zanoni 311ad7632ffSJani Nikula static void gen2_irq_init(struct intel_uncore *uncore, 3122918c3caSPaulo Zanoni u32 imr_val, u32 ier_val) 31368eb49b1SPaulo Zanoni { 31465f42cdcSPaulo Zanoni gen2_assert_iir_is_zero(uncore); 31568eb49b1SPaulo Zanoni 31665f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, ier_val); 31765f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, imr_val); 31865f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 31968eb49b1SPaulo Zanoni } 32068eb49b1SPaulo Zanoni 3210706f17cSEgbert Eich /* For display hotplug interrupt */ 3220706f17cSEgbert Eich static inline void 3230706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, 324a9c287c9SJani Nikula u32 mask, 325a9c287c9SJani Nikula u32 bits) 3260706f17cSEgbert Eich { 32767520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 32848a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, bits & ~mask); 3290706f17cSEgbert Eich 3308cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits); 3310706f17cSEgbert Eich } 3320706f17cSEgbert Eich 3330706f17cSEgbert Eich /** 3340706f17cSEgbert Eich * i915_hotplug_interrupt_update - update hotplug interrupt enable 3350706f17cSEgbert Eich * @dev_priv: driver private 3360706f17cSEgbert Eich * @mask: bits to update 3370706f17cSEgbert Eich * @bits: bits to enable 3380706f17cSEgbert Eich * NOTE: the HPD enable bits are modified both inside and outside 3390706f17cSEgbert Eich * of an interrupt context. To avoid that read-modify-write cycles 3400706f17cSEgbert Eich * interfer, these bits are protected by a spinlock. Since this 3410706f17cSEgbert Eich * function is usually not called from a context where the lock is 3420706f17cSEgbert Eich * held already, this function acquires the lock itself. A non-locking 3430706f17cSEgbert Eich * version is also available. 3440706f17cSEgbert Eich */ 3450706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, 346a9c287c9SJani Nikula u32 mask, 347a9c287c9SJani Nikula u32 bits) 3480706f17cSEgbert Eich { 3490706f17cSEgbert Eich spin_lock_irq(&dev_priv->irq_lock); 3500706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); 3510706f17cSEgbert Eich spin_unlock_irq(&dev_priv->irq_lock); 3520706f17cSEgbert Eich } 3530706f17cSEgbert Eich 354d9dc34f1SVille Syrjälä /** 355d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 356d9dc34f1SVille Syrjälä * @dev_priv: driver private 357d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 358d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 359d9dc34f1SVille Syrjälä */ 3609e6dcf33SJani Nikula static void ilk_update_display_irq(struct drm_i915_private *dev_priv, 3619e6dcf33SJani Nikula u32 interrupt_mask, u32 enabled_irq_mask) 362036a4a7dSZhenyu Wang { 363a9c287c9SJani Nikula u32 new_val; 364d9dc34f1SVille Syrjälä 36567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 36648a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 367d9dc34f1SVille Syrjälä 368d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 369d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 370d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 371d9dc34f1SVille Syrjälä 372e44adb5dSChris Wilson if (new_val != dev_priv->irq_mask && 373e44adb5dSChris Wilson !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { 374d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 3752939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask); 3762939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, DEIMR); 377036a4a7dSZhenyu Wang } 378036a4a7dSZhenyu Wang } 379036a4a7dSZhenyu Wang 3809e6dcf33SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits) 3819e6dcf33SJani Nikula { 3829e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, bits); 3839e6dcf33SJani Nikula } 3849e6dcf33SJani Nikula 3859e6dcf33SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits) 3869e6dcf33SJani Nikula { 3879e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, 0); 3889e6dcf33SJani Nikula } 3899e6dcf33SJani Nikula 3900961021aSBen Widawsky /** 3913a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 3923a3b3c7dSVille Syrjälä * @dev_priv: driver private 3933a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 3943a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 3953a3b3c7dSVille Syrjälä */ 3963a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv, 397a9c287c9SJani Nikula u32 interrupt_mask, 398a9c287c9SJani Nikula u32 enabled_irq_mask) 3993a3b3c7dSVille Syrjälä { 400a9c287c9SJani Nikula u32 new_val; 401a9c287c9SJani Nikula u32 old_val; 4023a3b3c7dSVille Syrjälä 40367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4043a3b3c7dSVille Syrjälä 40548a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 4063a3b3c7dSVille Syrjälä 40748a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 4083a3b3c7dSVille Syrjälä return; 4093a3b3c7dSVille Syrjälä 4102939eb06SJani Nikula old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4113a3b3c7dSVille Syrjälä 4123a3b3c7dSVille Syrjälä new_val = old_val; 4133a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 4143a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 4153a3b3c7dSVille Syrjälä 4163a3b3c7dSVille Syrjälä if (new_val != old_val) { 4172939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val); 4182939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4193a3b3c7dSVille Syrjälä } 4203a3b3c7dSVille Syrjälä } 4213a3b3c7dSVille Syrjälä 4223a3b3c7dSVille Syrjälä /** 423013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 424013d3752SVille Syrjälä * @dev_priv: driver private 425013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 426013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 427013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 428013d3752SVille Syrjälä */ 4299e6dcf33SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 4309e6dcf33SJani Nikula enum pipe pipe, u32 interrupt_mask, 431a9c287c9SJani Nikula u32 enabled_irq_mask) 432013d3752SVille Syrjälä { 433a9c287c9SJani Nikula u32 new_val; 434013d3752SVille Syrjälä 43567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 436013d3752SVille Syrjälä 43748a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 438013d3752SVille Syrjälä 43948a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 440013d3752SVille Syrjälä return; 441013d3752SVille Syrjälä 442013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 443013d3752SVille Syrjälä new_val &= ~interrupt_mask; 444013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 445013d3752SVille Syrjälä 446013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 447013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 4482939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 4492939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); 450013d3752SVille Syrjälä } 451013d3752SVille Syrjälä } 452013d3752SVille Syrjälä 4539e6dcf33SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915, 4549e6dcf33SJani Nikula enum pipe pipe, u32 bits) 4559e6dcf33SJani Nikula { 4569e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, bits); 4579e6dcf33SJani Nikula } 4589e6dcf33SJani Nikula 4599e6dcf33SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915, 4609e6dcf33SJani Nikula enum pipe pipe, u32 bits) 4619e6dcf33SJani Nikula { 4629e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, 0); 4639e6dcf33SJani Nikula } 4649e6dcf33SJani Nikula 465013d3752SVille Syrjälä /** 466fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 467fee884edSDaniel Vetter * @dev_priv: driver private 468fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 469fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 470fee884edSDaniel Vetter */ 4719e6dcf33SJani Nikula static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 472a9c287c9SJani Nikula u32 interrupt_mask, 473a9c287c9SJani Nikula u32 enabled_irq_mask) 474fee884edSDaniel Vetter { 4752939eb06SJani Nikula u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR); 476fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 477fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 478fee884edSDaniel Vetter 47948a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 48015a17aaeSDaniel Vetter 48167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 482fee884edSDaniel Vetter 48348a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 484c67a470bSPaulo Zanoni return; 485c67a470bSPaulo Zanoni 4862939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr); 4872939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, SDEIMR); 488fee884edSDaniel Vetter } 4898664281bSPaulo Zanoni 4909e6dcf33SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits) 4919e6dcf33SJani Nikula { 4929e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, bits); 4939e6dcf33SJani Nikula } 4949e6dcf33SJani Nikula 4959e6dcf33SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits) 4969e6dcf33SJani Nikula { 4979e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, 0); 4989e6dcf33SJani Nikula } 4999e6dcf33SJani Nikula 5006b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 5016b12ca56SVille Syrjälä enum pipe pipe) 5027c463586SKeith Packard { 5036b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 50410c59c51SImre Deak u32 enable_mask = status_mask << 16; 50510c59c51SImre Deak 5066b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 5076b12ca56SVille Syrjälä 508373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 5) 5096b12ca56SVille Syrjälä goto out; 5106b12ca56SVille Syrjälä 51110c59c51SImre Deak /* 512724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 513724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 51410c59c51SImre Deak */ 51548a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 51648a1b8d4SPankaj Bharadiya status_mask & PIPE_A_PSR_STATUS_VLV)) 51710c59c51SImre Deak return 0; 518724a6905SVille Syrjälä /* 519724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 520724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 521724a6905SVille Syrjälä */ 52248a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 52348a1b8d4SPankaj Bharadiya status_mask & PIPE_B_PSR_STATUS_VLV)) 524724a6905SVille Syrjälä return 0; 52510c59c51SImre Deak 52610c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 52710c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 52810c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 52910c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 53010c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 53110c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 53210c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 53310c59c51SImre Deak 5346b12ca56SVille Syrjälä out: 53548a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 53648a1b8d4SPankaj Bharadiya enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 5376b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 5386b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 5396b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 5406b12ca56SVille Syrjälä 54110c59c51SImre Deak return enable_mask; 54210c59c51SImre Deak } 54310c59c51SImre Deak 5446b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 5456b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 546755e9019SImre Deak { 5476b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 548755e9019SImre Deak u32 enable_mask; 549755e9019SImre Deak 55048a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5516b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5526b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5536b12ca56SVille Syrjälä 5546b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 55548a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5566b12ca56SVille Syrjälä 5576b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 5586b12ca56SVille Syrjälä return; 5596b12ca56SVille Syrjälä 5606b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 5616b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5626b12ca56SVille Syrjälä 5632939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5642939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 565755e9019SImre Deak } 566755e9019SImre Deak 5676b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 5686b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 569755e9019SImre Deak { 5706b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 571755e9019SImre Deak u32 enable_mask; 572755e9019SImre Deak 57348a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5746b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5756b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5766b12ca56SVille Syrjälä 5776b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 57848a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5796b12ca56SVille Syrjälä 5806b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 5816b12ca56SVille Syrjälä return; 5826b12ca56SVille Syrjälä 5836b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 5846b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5856b12ca56SVille Syrjälä 5862939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5872939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 588755e9019SImre Deak } 589755e9019SImre Deak 590f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 591f3e30485SVille Syrjälä { 5927249dfcbSJani Nikula if (!dev_priv->display.opregion.asle) 593f3e30485SVille Syrjälä return false; 594f3e30485SVille Syrjälä 595f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 596f3e30485SVille Syrjälä } 597f3e30485SVille Syrjälä 598c0e09200SDave Airlie /** 599f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 60014bb2c11STvrtko Ursulin * @dev_priv: i915 device private 60101c66889SZhao Yakui */ 60291d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 60301c66889SZhao Yakui { 604f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 605f49e38ddSJani Nikula return; 606f49e38ddSJani Nikula 60713321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 60801c66889SZhao Yakui 609755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 610373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 4) 6113b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 612755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 6131ec14ad3SChris Wilson 61413321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 61501c66889SZhao Yakui } 61601c66889SZhao Yakui 617e3689190SBen Widawsky /** 61874bb98baSLucas De Marchi * ivb_parity_work - Workqueue called when a parity error interrupt 619e3689190SBen Widawsky * occurred. 620e3689190SBen Widawsky * @work: workqueue struct 621e3689190SBen Widawsky * 622e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 623e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 624e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 625e3689190SBen Widawsky */ 62674bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work) 627e3689190SBen Widawsky { 6282d1013ddSJani Nikula struct drm_i915_private *dev_priv = 629cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 6302cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 631e3689190SBen Widawsky u32 error_status, row, bank, subbank; 63235a85ac6SBen Widawsky char *parity_event[6]; 633a9c287c9SJani Nikula u32 misccpctl; 634a9c287c9SJani Nikula u8 slice = 0; 635e3689190SBen Widawsky 636e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 637e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 638e3689190SBen Widawsky * any time we access those registers. 639e3689190SBen Widawsky */ 64091c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 641e3689190SBen Widawsky 64235a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 64348a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice)) 64435a85ac6SBen Widawsky goto out; 64535a85ac6SBen Widawsky 646f7435467SAndrzej Hajda misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL, 647f7435467SAndrzej Hajda GEN7_DOP_CLOCK_GATE_ENABLE, 0); 6482939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL); 649e3689190SBen Widawsky 65035a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 651f0f59a00SVille Syrjälä i915_reg_t reg; 65235a85ac6SBen Widawsky 65335a85ac6SBen Widawsky slice--; 65448a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 65548a1b8d4SPankaj Bharadiya slice >= NUM_L3_SLICES(dev_priv))) 65635a85ac6SBen Widawsky break; 65735a85ac6SBen Widawsky 65835a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 65935a85ac6SBen Widawsky 6606fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 66135a85ac6SBen Widawsky 6622939eb06SJani Nikula error_status = intel_uncore_read(&dev_priv->uncore, reg); 663e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 664e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 665e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 666e3689190SBen Widawsky 6672939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 6682939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 669e3689190SBen Widawsky 670cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 671e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 672e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 673e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 67435a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 67535a85ac6SBen Widawsky parity_event[5] = NULL; 676e3689190SBen Widawsky 67791c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 678e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 679e3689190SBen Widawsky 680a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, 681a10234fdSTvrtko Ursulin "Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 68235a85ac6SBen Widawsky slice, row, bank, subbank); 683e3689190SBen Widawsky 68435a85ac6SBen Widawsky kfree(parity_event[4]); 685e3689190SBen Widawsky kfree(parity_event[3]); 686e3689190SBen Widawsky kfree(parity_event[2]); 687e3689190SBen Widawsky kfree(parity_event[1]); 688e3689190SBen Widawsky } 689e3689190SBen Widawsky 6902939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl); 69135a85ac6SBen Widawsky 69235a85ac6SBen Widawsky out: 69348a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice); 69403d2c54dSMatt Roper spin_lock_irq(gt->irq_lock); 695cf1c97dcSAndi Shyti gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv)); 69603d2c54dSMatt Roper spin_unlock_irq(gt->irq_lock); 69735a85ac6SBen Widawsky 69891c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 69935a85ac6SBen Widawsky } 70035a85ac6SBen Widawsky 701af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 702121e758eSDhinakaran Pandiyan { 703af92058fSVille Syrjälä switch (pin) { 704da51e4baSVille Syrjälä case HPD_PORT_TC1: 705da51e4baSVille Syrjälä case HPD_PORT_TC2: 706da51e4baSVille Syrjälä case HPD_PORT_TC3: 707da51e4baSVille Syrjälä case HPD_PORT_TC4: 708da51e4baSVille Syrjälä case HPD_PORT_TC5: 709da51e4baSVille Syrjälä case HPD_PORT_TC6: 7104294fa5fSVille Syrjälä return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin); 71148ef15d3SJosé Roberto de Souza default: 71248ef15d3SJosé Roberto de Souza return false; 71348ef15d3SJosé Roberto de Souza } 71448ef15d3SJosé Roberto de Souza } 71548ef15d3SJosé Roberto de Souza 716af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 71763c88d22SImre Deak { 718af92058fSVille Syrjälä switch (pin) { 719af92058fSVille Syrjälä case HPD_PORT_A: 720195baa06SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 721af92058fSVille Syrjälä case HPD_PORT_B: 72263c88d22SImre Deak return val & PORTB_HOTPLUG_LONG_DETECT; 723af92058fSVille Syrjälä case HPD_PORT_C: 72463c88d22SImre Deak return val & PORTC_HOTPLUG_LONG_DETECT; 72563c88d22SImre Deak default: 72663c88d22SImre Deak return false; 72763c88d22SImre Deak } 72863c88d22SImre Deak } 72963c88d22SImre Deak 730af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 73131604222SAnusha Srivatsa { 732af92058fSVille Syrjälä switch (pin) { 733af92058fSVille Syrjälä case HPD_PORT_A: 734af92058fSVille Syrjälä case HPD_PORT_B: 7358ef7e340SMatt Roper case HPD_PORT_C: 736229f31e2SLucas De Marchi case HPD_PORT_D: 7374294fa5fSVille Syrjälä return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin); 73831604222SAnusha Srivatsa default: 73931604222SAnusha Srivatsa return false; 74031604222SAnusha Srivatsa } 74131604222SAnusha Srivatsa } 74231604222SAnusha Srivatsa 743af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 74431604222SAnusha Srivatsa { 745af92058fSVille Syrjälä switch (pin) { 746da51e4baSVille Syrjälä case HPD_PORT_TC1: 747da51e4baSVille Syrjälä case HPD_PORT_TC2: 748da51e4baSVille Syrjälä case HPD_PORT_TC3: 749da51e4baSVille Syrjälä case HPD_PORT_TC4: 750da51e4baSVille Syrjälä case HPD_PORT_TC5: 751da51e4baSVille Syrjälä case HPD_PORT_TC6: 7524294fa5fSVille Syrjälä return val & ICP_TC_HPD_LONG_DETECT(pin); 75352dfdba0SLucas De Marchi default: 75452dfdba0SLucas De Marchi return false; 75552dfdba0SLucas De Marchi } 75652dfdba0SLucas De Marchi } 75752dfdba0SLucas De Marchi 758af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) 7596dbf30ceSVille Syrjälä { 760af92058fSVille Syrjälä switch (pin) { 761af92058fSVille Syrjälä case HPD_PORT_E: 7626dbf30ceSVille Syrjälä return val & PORTE_HOTPLUG_LONG_DETECT; 7636dbf30ceSVille Syrjälä default: 7646dbf30ceSVille Syrjälä return false; 7656dbf30ceSVille Syrjälä } 7666dbf30ceSVille Syrjälä } 7676dbf30ceSVille Syrjälä 768af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 76974c0b395SVille Syrjälä { 770af92058fSVille Syrjälä switch (pin) { 771af92058fSVille Syrjälä case HPD_PORT_A: 77274c0b395SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 773af92058fSVille Syrjälä case HPD_PORT_B: 77474c0b395SVille Syrjälä return val & PORTB_HOTPLUG_LONG_DETECT; 775af92058fSVille Syrjälä case HPD_PORT_C: 77674c0b395SVille Syrjälä return val & PORTC_HOTPLUG_LONG_DETECT; 777af92058fSVille Syrjälä case HPD_PORT_D: 77874c0b395SVille Syrjälä return val & PORTD_HOTPLUG_LONG_DETECT; 77974c0b395SVille Syrjälä default: 78074c0b395SVille Syrjälä return false; 78174c0b395SVille Syrjälä } 78274c0b395SVille Syrjälä } 78374c0b395SVille Syrjälä 784af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 785e4ce95aaSVille Syrjälä { 786af92058fSVille Syrjälä switch (pin) { 787af92058fSVille Syrjälä case HPD_PORT_A: 788e4ce95aaSVille Syrjälä return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; 789e4ce95aaSVille Syrjälä default: 790e4ce95aaSVille Syrjälä return false; 791e4ce95aaSVille Syrjälä } 792e4ce95aaSVille Syrjälä } 793e4ce95aaSVille Syrjälä 794af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 79513cf5504SDave Airlie { 796af92058fSVille Syrjälä switch (pin) { 797af92058fSVille Syrjälä case HPD_PORT_B: 798676574dfSJani Nikula return val & PORTB_HOTPLUG_LONG_DETECT; 799af92058fSVille Syrjälä case HPD_PORT_C: 800676574dfSJani Nikula return val & PORTC_HOTPLUG_LONG_DETECT; 801af92058fSVille Syrjälä case HPD_PORT_D: 802676574dfSJani Nikula return val & PORTD_HOTPLUG_LONG_DETECT; 803676574dfSJani Nikula default: 804676574dfSJani Nikula return false; 80513cf5504SDave Airlie } 80613cf5504SDave Airlie } 80713cf5504SDave Airlie 808af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 80913cf5504SDave Airlie { 810af92058fSVille Syrjälä switch (pin) { 811af92058fSVille Syrjälä case HPD_PORT_B: 812676574dfSJani Nikula return val & PORTB_HOTPLUG_INT_LONG_PULSE; 813af92058fSVille Syrjälä case HPD_PORT_C: 814676574dfSJani Nikula return val & PORTC_HOTPLUG_INT_LONG_PULSE; 815af92058fSVille Syrjälä case HPD_PORT_D: 816676574dfSJani Nikula return val & PORTD_HOTPLUG_INT_LONG_PULSE; 817676574dfSJani Nikula default: 818676574dfSJani Nikula return false; 81913cf5504SDave Airlie } 82013cf5504SDave Airlie } 82113cf5504SDave Airlie 82242db67d6SVille Syrjälä /* 82342db67d6SVille Syrjälä * Get a bit mask of pins that have triggered, and which ones may be long. 82442db67d6SVille Syrjälä * This can be called multiple times with the same masks to accumulate 82542db67d6SVille Syrjälä * hotplug detection results from several registers. 82642db67d6SVille Syrjälä * 82742db67d6SVille Syrjälä * Note that the caller is expected to zero out the masks initially. 82842db67d6SVille Syrjälä */ 829cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, 830cf53902fSRodrigo Vivi u32 *pin_mask, u32 *long_mask, 8318c841e57SJani Nikula u32 hotplug_trigger, u32 dig_hotplug_reg, 832fd63e2a9SImre Deak const u32 hpd[HPD_NUM_PINS], 833af92058fSVille Syrjälä bool long_pulse_detect(enum hpd_pin pin, u32 val)) 834676574dfSJani Nikula { 835e9be2850SVille Syrjälä enum hpd_pin pin; 836676574dfSJani Nikula 83752dfdba0SLucas De Marchi BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS); 83852dfdba0SLucas De Marchi 839e9be2850SVille Syrjälä for_each_hpd_pin(pin) { 840e9be2850SVille Syrjälä if ((hpd[pin] & hotplug_trigger) == 0) 8418c841e57SJani Nikula continue; 8428c841e57SJani Nikula 843e9be2850SVille Syrjälä *pin_mask |= BIT(pin); 844676574dfSJani Nikula 845af92058fSVille Syrjälä if (long_pulse_detect(pin, dig_hotplug_reg)) 846e9be2850SVille Syrjälä *long_mask |= BIT(pin); 847676574dfSJani Nikula } 848676574dfSJani Nikula 84900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 85000376ccfSWambui Karuga "hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n", 851f88f0478SVille Syrjälä hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); 852676574dfSJani Nikula 853676574dfSJani Nikula } 854676574dfSJani Nikula 855a0e066b8SVille Syrjälä static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, 856a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 857a0e066b8SVille Syrjälä { 858a0e066b8SVille Syrjälä struct intel_encoder *encoder; 859a0e066b8SVille Syrjälä u32 enabled_irqs = 0; 860a0e066b8SVille Syrjälä 861a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 8625a4dd6f0SJani Nikula if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) 863a0e066b8SVille Syrjälä enabled_irqs |= hpd[encoder->hpd_pin]; 864a0e066b8SVille Syrjälä 865a0e066b8SVille Syrjälä return enabled_irqs; 866a0e066b8SVille Syrjälä } 867a0e066b8SVille Syrjälä 868a0e066b8SVille Syrjälä static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, 869a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 870a0e066b8SVille Syrjälä { 871a0e066b8SVille Syrjälä struct intel_encoder *encoder; 872a0e066b8SVille Syrjälä u32 hotplug_irqs = 0; 873a0e066b8SVille Syrjälä 874a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 875a0e066b8SVille Syrjälä hotplug_irqs |= hpd[encoder->hpd_pin]; 876a0e066b8SVille Syrjälä 877a0e066b8SVille Syrjälä return hotplug_irqs; 878a0e066b8SVille Syrjälä } 879a0e066b8SVille Syrjälä 8802ea63927SVille Syrjälä static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915, 8812ea63927SVille Syrjälä hotplug_enables_func hotplug_enables) 8822ea63927SVille Syrjälä { 8832ea63927SVille Syrjälä struct intel_encoder *encoder; 8842ea63927SVille Syrjälä u32 hotplug = 0; 8852ea63927SVille Syrjälä 8862ea63927SVille Syrjälä for_each_intel_encoder(&i915->drm, encoder) 887dfefe7bcSVille Syrjälä hotplug |= hotplug_enables(encoder); 8882ea63927SVille Syrjälä 8892ea63927SVille Syrjälä return hotplug; 8902ea63927SVille Syrjälä } 8912ea63927SVille Syrjälä 89291d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv) 893515ac2bbSDaniel Vetter { 894203eb5a9SJani Nikula wake_up_all(&dev_priv->display.gmbus.wait_queue); 895515ac2bbSDaniel Vetter } 896515ac2bbSDaniel Vetter 89791d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) 898ce99c256SDaniel Vetter { 899203eb5a9SJani Nikula wake_up_all(&dev_priv->display.gmbus.wait_queue); 900ce99c256SDaniel Vetter } 901ce99c256SDaniel Vetter 9028bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 90391d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 90491d14251STvrtko Ursulin enum pipe pipe, 905a9c287c9SJani Nikula u32 crc0, u32 crc1, 906a9c287c9SJani Nikula u32 crc2, u32 crc3, 907a9c287c9SJani Nikula u32 crc4) 9088bf1e9f1SShuang He { 9097794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 91000535527SJani Nikula struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc; 9115cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 9125cee6c45SVille Syrjälä 9135cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 914b2c88f5bSDamien Lespiau 915d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 9168c6b709dSTomeu Vizoso /* 9178c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 9188c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 9198c6b709dSTomeu Vizoso * out the buggy result. 9208c6b709dSTomeu Vizoso * 921163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 9228c6b709dSTomeu Vizoso * don't trust that one either. 9238c6b709dSTomeu Vizoso */ 924033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 925373abf1aSMatt Roper (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 9268c6b709dSTomeu Vizoso pipe_crc->skipped++; 9278c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 9288c6b709dSTomeu Vizoso return; 9298c6b709dSTomeu Vizoso } 9308c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 9316cc42152SMaarten Lankhorst 932246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 933ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 934246ee524STomeu Vizoso crcs); 9358c6b709dSTomeu Vizoso } 936277de95eSDaniel Vetter #else 937277de95eSDaniel Vetter static inline void 93891d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 93991d14251STvrtko Ursulin enum pipe pipe, 940a9c287c9SJani Nikula u32 crc0, u32 crc1, 941a9c287c9SJani Nikula u32 crc2, u32 crc3, 942a9c287c9SJani Nikula u32 crc4) {} 943277de95eSDaniel Vetter #endif 944eba94eb9SDaniel Vetter 9451288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915, 9461288f9b0SKarthik B S enum pipe pipe) 9471288f9b0SKarthik B S { 9487794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe); 9491288f9b0SKarthik B S struct drm_crtc_state *crtc_state = crtc->base.state; 9501288f9b0SKarthik B S struct drm_pending_vblank_event *e = crtc_state->event; 9511288f9b0SKarthik B S struct drm_device *dev = &i915->drm; 9521288f9b0SKarthik B S unsigned long irqflags; 9531288f9b0SKarthik B S 9541288f9b0SKarthik B S spin_lock_irqsave(&dev->event_lock, irqflags); 9551288f9b0SKarthik B S 9561288f9b0SKarthik B S crtc_state->event = NULL; 9571288f9b0SKarthik B S 9581288f9b0SKarthik B S drm_crtc_send_vblank_event(&crtc->base, e); 9591288f9b0SKarthik B S 9601288f9b0SKarthik B S spin_unlock_irqrestore(&dev->event_lock, irqflags); 9611288f9b0SKarthik B S } 962277de95eSDaniel Vetter 96391d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 96491d14251STvrtko Ursulin enum pipe pipe) 9655a69b89fSDaniel Vetter { 96691d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 9672939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 9685a69b89fSDaniel Vetter 0, 0, 0, 0); 9695a69b89fSDaniel Vetter } 9705a69b89fSDaniel Vetter 97191d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 97291d14251STvrtko Ursulin enum pipe pipe) 973eba94eb9SDaniel Vetter { 97491d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 9752939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 9762939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)), 9772939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)), 9782939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)), 9792939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe))); 980eba94eb9SDaniel Vetter } 9815b3a856bSDaniel Vetter 98291d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 98391d14251STvrtko Ursulin enum pipe pipe) 9845b3a856bSDaniel Vetter { 985a9c287c9SJani Nikula u32 res1, res2; 9860b5c5ed0SDaniel Vetter 987373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 3) 9882939eb06SJani Nikula res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe)); 9890b5c5ed0SDaniel Vetter else 9900b5c5ed0SDaniel Vetter res1 = 0; 9910b5c5ed0SDaniel Vetter 992373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) 9932939eb06SJani Nikula res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe)); 9940b5c5ed0SDaniel Vetter else 9950b5c5ed0SDaniel Vetter res2 = 0; 9965b3a856bSDaniel Vetter 99791d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 9982939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)), 9992939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)), 10002939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)), 10010b5c5ed0SDaniel Vetter res1, res2); 10025b3a856bSDaniel Vetter } 10038bf1e9f1SShuang He 100444d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 100544d9241eSVille Syrjälä { 100644d9241eSVille Syrjälä enum pipe pipe; 100744d9241eSVille Syrjälä 100844d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 10092939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe), 101044d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 101144d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 101244d9241eSVille Syrjälä 101344d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 101444d9241eSVille Syrjälä } 101544d9241eSVille Syrjälä } 101644d9241eSVille Syrjälä 1017eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 101891d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 10197e231dbeSJesse Barnes { 1020d048a268SVille Syrjälä enum pipe pipe; 10217e231dbeSJesse Barnes 102258ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 10231ca993d2SVille Syrjälä 10241ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 10251ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 10261ca993d2SVille Syrjälä return; 10271ca993d2SVille Syrjälä } 10281ca993d2SVille Syrjälä 1029055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1030f0f59a00SVille Syrjälä i915_reg_t reg; 10316b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 103291d181ddSImre Deak 1033bbb5eebfSDaniel Vetter /* 1034bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 1035bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 1036bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 1037bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 1038bbb5eebfSDaniel Vetter * handle. 1039bbb5eebfSDaniel Vetter */ 10400f239f4cSDaniel Vetter 10410f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 10426b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 1043bbb5eebfSDaniel Vetter 1044bbb5eebfSDaniel Vetter switch (pipe) { 1045d048a268SVille Syrjälä default: 1046bbb5eebfSDaniel Vetter case PIPE_A: 1047bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 1048bbb5eebfSDaniel Vetter break; 1049bbb5eebfSDaniel Vetter case PIPE_B: 1050bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1051bbb5eebfSDaniel Vetter break; 10523278f67fSVille Syrjälä case PIPE_C: 10533278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 10543278f67fSVille Syrjälä break; 1055bbb5eebfSDaniel Vetter } 1056bbb5eebfSDaniel Vetter if (iir & iir_bit) 10576b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 1058bbb5eebfSDaniel Vetter 10596b12ca56SVille Syrjälä if (!status_mask) 106091d181ddSImre Deak continue; 106191d181ddSImre Deak 106291d181ddSImre Deak reg = PIPESTAT(pipe); 10632939eb06SJani Nikula pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; 10646b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 10657e231dbeSJesse Barnes 10667e231dbeSJesse Barnes /* 10677e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 1068132c27c9SVille Syrjälä * 1069132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 1070132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 1071132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 1072132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 1073132c27c9SVille Syrjälä * an interrupt is still pending. 10747e231dbeSJesse Barnes */ 1075132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 10762939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]); 10772939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask); 1078132c27c9SVille Syrjälä } 10797e231dbeSJesse Barnes } 108058ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 10812ecb8ca4SVille Syrjälä } 10822ecb8ca4SVille Syrjälä 1083eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1084eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 1085eb64343cSVille Syrjälä { 1086eb64343cSVille Syrjälä enum pipe pipe; 1087eb64343cSVille Syrjälä 1088eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1089eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1090aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1091eb64343cSVille Syrjälä 1092eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1093eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1094eb64343cSVille Syrjälä 1095eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1096eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1097eb64343cSVille Syrjälä } 1098eb64343cSVille Syrjälä } 1099eb64343cSVille Syrjälä 1100eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1101eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1102eb64343cSVille Syrjälä { 1103eb64343cSVille Syrjälä bool blc_event = false; 1104eb64343cSVille Syrjälä enum pipe pipe; 1105eb64343cSVille Syrjälä 1106eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1107eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1108aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1109eb64343cSVille Syrjälä 1110eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1111eb64343cSVille Syrjälä blc_event = true; 1112eb64343cSVille Syrjälä 1113eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1114eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1115eb64343cSVille Syrjälä 1116eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1117eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1118eb64343cSVille Syrjälä } 1119eb64343cSVille Syrjälä 1120eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1121eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1122eb64343cSVille Syrjälä } 1123eb64343cSVille Syrjälä 1124eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1125eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1126eb64343cSVille Syrjälä { 1127eb64343cSVille Syrjälä bool blc_event = false; 1128eb64343cSVille Syrjälä enum pipe pipe; 1129eb64343cSVille Syrjälä 1130eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1131eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1132aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1133eb64343cSVille Syrjälä 1134eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1135eb64343cSVille Syrjälä blc_event = true; 1136eb64343cSVille Syrjälä 1137eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1138eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1139eb64343cSVille Syrjälä 1140eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1141eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1142eb64343cSVille Syrjälä } 1143eb64343cSVille Syrjälä 1144eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1145eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1146eb64343cSVille Syrjälä 1147eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 1148eb64343cSVille Syrjälä gmbus_irq_handler(dev_priv); 1149eb64343cSVille Syrjälä } 1150eb64343cSVille Syrjälä 115191d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 11522ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 11532ecb8ca4SVille Syrjälä { 11542ecb8ca4SVille Syrjälä enum pipe pipe; 11557e231dbeSJesse Barnes 1156055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1157fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1158aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 11594356d586SDaniel Vetter 11606ede6b06SVille Syrjälä if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) 11616ede6b06SVille Syrjälä flip_done_handler(dev_priv, pipe); 11626ede6b06SVille Syrjälä 11634356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 116491d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 11652d9d2b0bSVille Syrjälä 11661f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 11671f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 116831acc7f5SJesse Barnes } 116931acc7f5SJesse Barnes 1170c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 117191d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1172c1874ed7SImre Deak } 1173c1874ed7SImre Deak 11741ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 117516c6c56bSVille Syrjälä { 11760ba7c51aSVille Syrjälä u32 hotplug_status = 0, hotplug_status_mask; 11770ba7c51aSVille Syrjälä int i; 117816c6c56bSVille Syrjälä 11790ba7c51aSVille Syrjälä if (IS_G4X(dev_priv) || 11800ba7c51aSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 11810ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | 11820ba7c51aSVille Syrjälä DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; 11830ba7c51aSVille Syrjälä else 11840ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_I915; 11850ba7c51aSVille Syrjälä 11860ba7c51aSVille Syrjälä /* 11870ba7c51aSVille Syrjälä * We absolutely have to clear all the pending interrupt 11880ba7c51aSVille Syrjälä * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port 11890ba7c51aSVille Syrjälä * interrupt bit won't have an edge, and the i965/g4x 11900ba7c51aSVille Syrjälä * edge triggered IIR will not notice that an interrupt 11910ba7c51aSVille Syrjälä * is still pending. We can't use PORT_HOTPLUG_EN to 11920ba7c51aSVille Syrjälä * guarantee the edge as the act of toggling the enable 11930ba7c51aSVille Syrjälä * bits can itself generate a new hotplug interrupt :( 11940ba7c51aSVille Syrjälä */ 11950ba7c51aSVille Syrjälä for (i = 0; i < 10; i++) { 11962939eb06SJani Nikula u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask; 11970ba7c51aSVille Syrjälä 11980ba7c51aSVille Syrjälä if (tmp == 0) 11990ba7c51aSVille Syrjälä return hotplug_status; 12000ba7c51aSVille Syrjälä 12010ba7c51aSVille Syrjälä hotplug_status |= tmp; 12022939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status); 12030ba7c51aSVille Syrjälä } 12040ba7c51aSVille Syrjälä 120548a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 1, 12060ba7c51aSVille Syrjälä "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", 12072939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 12081ae3c34cSVille Syrjälä 12091ae3c34cSVille Syrjälä return hotplug_status; 12101ae3c34cSVille Syrjälä } 12111ae3c34cSVille Syrjälä 121291d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, 12131ae3c34cSVille Syrjälä u32 hotplug_status) 12141ae3c34cSVille Syrjälä { 12151ae3c34cSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 12160398993bSVille Syrjälä u32 hotplug_trigger; 12173ff60f89SOscar Mateo 12180398993bSVille Syrjälä if (IS_G4X(dev_priv) || 12190398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 12200398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; 12210398993bSVille Syrjälä else 12220398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; 122316c6c56bSVille Syrjälä 122458f2cf24SVille Syrjälä if (hotplug_trigger) { 1225cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1226cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 12275a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1228fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 122958f2cf24SVille Syrjälä 123091d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 123158f2cf24SVille Syrjälä } 1232369712e8SJani Nikula 12330398993bSVille Syrjälä if ((IS_G4X(dev_priv) || 12340398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && 12350398993bSVille Syrjälä hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) 123691d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 123758f2cf24SVille Syrjälä } 123816c6c56bSVille Syrjälä 1239c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 1240c1874ed7SImre Deak { 1241b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 1242c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 1243c1874ed7SImre Deak 12442dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 12452dd2a883SImre Deak return IRQ_NONE; 12462dd2a883SImre Deak 12471f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 12489102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 12491f814dacSImre Deak 12501e1cace9SVille Syrjälä do { 12516e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 12522ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 12531ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1254a5e485a9SVille Syrjälä u32 ier = 0; 12553ff60f89SOscar Mateo 12562939eb06SJani Nikula gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR); 12572939eb06SJani Nikula pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR); 12582939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 1259c1874ed7SImre Deak 1260c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 12611e1cace9SVille Syrjälä break; 1262c1874ed7SImre Deak 1263c1874ed7SImre Deak ret = IRQ_HANDLED; 1264c1874ed7SImre Deak 1265a5e485a9SVille Syrjälä /* 1266a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1267a5e485a9SVille Syrjälä * 1268a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1269a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 1270a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 1271a5e485a9SVille Syrjälä * 1272a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1273a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 1274a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1275a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 1276a5e485a9SVille Syrjälä * bits this time around. 1277a5e485a9SVille Syrjälä */ 12782939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 12798cee664dSAndrzej Hajda ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); 12804a0a0202SVille Syrjälä 12814a0a0202SVille Syrjälä if (gt_iir) 12822939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir); 12834a0a0202SVille Syrjälä if (pm_iir) 12842939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir); 12854a0a0202SVille Syrjälä 12867ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 12871ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 12887ce4d1f2SVille Syrjälä 12893ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 12903ff60f89SOscar Mateo * signalled in iir */ 1291eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 12927ce4d1f2SVille Syrjälä 1293eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1294eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 1295eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1296eef57324SJerome Anand 12977ce4d1f2SVille Syrjälä /* 12987ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 12997ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 13007ce4d1f2SVille Syrjälä */ 13017ce4d1f2SVille Syrjälä if (iir) 13022939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 13034a0a0202SVille Syrjälä 13042939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 13052939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 13061ae3c34cSVille Syrjälä 130752894874SVille Syrjälä if (gt_iir) 13082cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(dev_priv), gt_iir); 130952894874SVille Syrjälä if (pm_iir) 13102cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir); 131152894874SVille Syrjälä 13121ae3c34cSVille Syrjälä if (hotplug_status) 131391d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 13142ecb8ca4SVille Syrjälä 131591d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 13161e1cace9SVille Syrjälä } while (0); 13177e231dbeSJesse Barnes 13189c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 13199c6508b9SThomas Gleixner 13209102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 13211f814dacSImre Deak 13227e231dbeSJesse Barnes return ret; 13237e231dbeSJesse Barnes } 13247e231dbeSJesse Barnes 132543f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 132643f328d7SVille Syrjälä { 1327b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 132843f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 132943f328d7SVille Syrjälä 13302dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 13312dd2a883SImre Deak return IRQ_NONE; 13322dd2a883SImre Deak 13331f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 13349102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 13351f814dacSImre Deak 1336579de73bSChris Wilson do { 13376e814800SVille Syrjälä u32 master_ctl, iir; 13382ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 13391ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1340a5e485a9SVille Syrjälä u32 ier = 0; 1341a5e485a9SVille Syrjälä 13422939eb06SJani Nikula master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 13432939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 13443278f67fSVille Syrjälä 13453278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 13468e5fd599SVille Syrjälä break; 134743f328d7SVille Syrjälä 134827b6c122SOscar Mateo ret = IRQ_HANDLED; 134927b6c122SOscar Mateo 1350a5e485a9SVille Syrjälä /* 1351a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1352a5e485a9SVille Syrjälä * 1353a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1354a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 1355a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 1356a5e485a9SVille Syrjälä * 1357a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1358a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 1359a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1360a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 1361a5e485a9SVille Syrjälä * bits this time around. 1362a5e485a9SVille Syrjälä */ 13632939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); 13648cee664dSAndrzej Hajda ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); 136543f328d7SVille Syrjälä 13662cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 136727b6c122SOscar Mateo 136827b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 13691ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 137043f328d7SVille Syrjälä 137127b6c122SOscar Mateo /* Call regardless, as some status bits might not be 137227b6c122SOscar Mateo * signalled in iir */ 1373eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 137443f328d7SVille Syrjälä 1375eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1376eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 1377eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 1378eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1379eef57324SJerome Anand 13807ce4d1f2SVille Syrjälä /* 13817ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 13827ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 13837ce4d1f2SVille Syrjälä */ 13847ce4d1f2SVille Syrjälä if (iir) 13852939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 13867ce4d1f2SVille Syrjälä 13872939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 13882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 13891ae3c34cSVille Syrjälä 13901ae3c34cSVille Syrjälä if (hotplug_status) 139191d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 13922ecb8ca4SVille Syrjälä 139391d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 1394579de73bSChris Wilson } while (0); 13953278f67fSVille Syrjälä 13969c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 13979c6508b9SThomas Gleixner 13989102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 13991f814dacSImre Deak 140043f328d7SVille Syrjälä return ret; 140143f328d7SVille Syrjälä } 140243f328d7SVille Syrjälä 140391d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, 14040398993bSVille Syrjälä u32 hotplug_trigger) 1405776ad806SJesse Barnes { 140642db67d6SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1407776ad806SJesse Barnes 14086a39d7c9SJani Nikula /* 14096a39d7c9SJani Nikula * Somehow the PCH doesn't seem to really ack the interrupt to the CPU 14106a39d7c9SJani Nikula * unless we touch the hotplug register, even if hotplug_trigger is 14116a39d7c9SJani Nikula * zero. Not acking leads to "The master control interrupt lied (SDE)!" 14126a39d7c9SJani Nikula * errors. 14136a39d7c9SJani Nikula */ 14142939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 14156a39d7c9SJani Nikula if (!hotplug_trigger) { 14166a39d7c9SJani Nikula u32 mask = PORTA_HOTPLUG_STATUS_MASK | 14176a39d7c9SJani Nikula PORTD_HOTPLUG_STATUS_MASK | 14186a39d7c9SJani Nikula PORTC_HOTPLUG_STATUS_MASK | 14196a39d7c9SJani Nikula PORTB_HOTPLUG_STATUS_MASK; 14206a39d7c9SJani Nikula dig_hotplug_reg &= ~mask; 14216a39d7c9SJani Nikula } 14226a39d7c9SJani Nikula 14232939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 14246a39d7c9SJani Nikula if (!hotplug_trigger) 14256a39d7c9SJani Nikula return; 142613cf5504SDave Airlie 14270398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 14280398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 14295a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 1430fd63e2a9SImre Deak pch_port_hotplug_long_detect); 143140e56410SVille Syrjälä 143291d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1433aaf5ec2eSSonika Jindal } 143491d131d2SDaniel Vetter 143591d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 143640e56410SVille Syrjälä { 1437d048a268SVille Syrjälä enum pipe pipe; 143840e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 143940e56410SVille Syrjälä 14400398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 144140e56410SVille Syrjälä 1442cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 1443cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 1444776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 144500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n", 1446cfc33bf7SVille Syrjälä port_name(port)); 1447cfc33bf7SVille Syrjälä } 1448776ad806SJesse Barnes 1449ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 145091d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 1451ce99c256SDaniel Vetter 1452776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 145391d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1454776ad806SJesse Barnes 1455776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 145600376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n"); 1457776ad806SJesse Barnes 1458776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 145900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n"); 1460776ad806SJesse Barnes 1461776ad806SJesse Barnes if (pch_iir & SDE_POISON) 146200376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1463776ad806SJesse Barnes 1464b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK) { 1465055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 146600376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 14679db4a9c7SJesse Barnes pipe_name(pipe), 14682939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1469b8b65ccdSAnshuman Gupta } 1470776ad806SJesse Barnes 1471776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 147200376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n"); 1473776ad806SJesse Barnes 1474776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 147500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 147600376ccfSWambui Karuga "PCH transcoder CRC error interrupt\n"); 1477776ad806SJesse Barnes 1478776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 1479a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 14808664281bSPaulo Zanoni 14818664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 1482a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 14838664281bSPaulo Zanoni } 14848664281bSPaulo Zanoni 148591d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 14868664281bSPaulo Zanoni { 14872939eb06SJani Nikula u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT); 14885a69b89fSDaniel Vetter enum pipe pipe; 14898664281bSPaulo Zanoni 1490de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 149100376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1492de032bf4SPaulo Zanoni 1493055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 14941f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 14951f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 14968664281bSPaulo Zanoni 14975a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 149891d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 149991d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 15005a69b89fSDaniel Vetter else 150191d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 15025a69b89fSDaniel Vetter } 15035a69b89fSDaniel Vetter } 15048bf1e9f1SShuang He 15052939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int); 15068664281bSPaulo Zanoni } 15078664281bSPaulo Zanoni 150891d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 15098664281bSPaulo Zanoni { 15102939eb06SJani Nikula u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT); 151145c1cd87SMika Kahola enum pipe pipe; 15128664281bSPaulo Zanoni 1513de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 151400376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1515de032bf4SPaulo Zanoni 151645c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 151745c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 151845c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 15198664281bSPaulo Zanoni 15202939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int); 1521776ad806SJesse Barnes } 1522776ad806SJesse Barnes 152391d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 152423e81d69SAdam Jackson { 1525d048a268SVille Syrjälä enum pipe pipe; 15266dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 1527aaf5ec2eSSonika Jindal 15280398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 152991d131d2SDaniel Vetter 1530cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 1531cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 153223e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 153300376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n", 1534cfc33bf7SVille Syrjälä port_name(port)); 1535cfc33bf7SVille Syrjälä } 153623e81d69SAdam Jackson 153723e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 153891d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 153923e81d69SAdam Jackson 154023e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 154191d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 154223e81d69SAdam Jackson 154323e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 154400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n"); 154523e81d69SAdam Jackson 154623e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 154700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n"); 154823e81d69SAdam Jackson 1549b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK_CPT) { 1550055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 155100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 155223e81d69SAdam Jackson pipe_name(pipe), 15532939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1554b8b65ccdSAnshuman Gupta } 15558664281bSPaulo Zanoni 15568664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 155791d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 155823e81d69SAdam Jackson } 155923e81d69SAdam Jackson 156058676af6SLucas De Marchi static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 156131604222SAnusha Srivatsa { 1562e76ab2cfSVille Syrjälä u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP; 1563e76ab2cfSVille Syrjälä u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP; 156431604222SAnusha Srivatsa u32 pin_mask = 0, long_mask = 0; 156531604222SAnusha Srivatsa 156631604222SAnusha Srivatsa if (ddi_hotplug_trigger) { 156731604222SAnusha Srivatsa u32 dig_hotplug_reg; 156831604222SAnusha Srivatsa 1569f087cfe6SJani Nikula /* Locking due to DSI native GPIO sequences */ 1570f087cfe6SJani Nikula spin_lock(&dev_priv->irq_lock); 15718cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0); 1572f087cfe6SJani Nikula spin_unlock(&dev_priv->irq_lock); 157331604222SAnusha Srivatsa 157431604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 15750398993bSVille Syrjälä ddi_hotplug_trigger, dig_hotplug_reg, 15765a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 157731604222SAnusha Srivatsa icp_ddi_port_hotplug_long_detect); 157831604222SAnusha Srivatsa } 157931604222SAnusha Srivatsa 158031604222SAnusha Srivatsa if (tc_hotplug_trigger) { 158131604222SAnusha Srivatsa u32 dig_hotplug_reg; 158231604222SAnusha Srivatsa 15838cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0); 158431604222SAnusha Srivatsa 158531604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 15860398993bSVille Syrjälä tc_hotplug_trigger, dig_hotplug_reg, 15875a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 1588da51e4baSVille Syrjälä icp_tc_port_hotplug_long_detect); 158952dfdba0SLucas De Marchi } 159052dfdba0SLucas De Marchi 159152dfdba0SLucas De Marchi if (pin_mask) 159252dfdba0SLucas De Marchi intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 159352dfdba0SLucas De Marchi 159452dfdba0SLucas De Marchi if (pch_iir & SDE_GMBUS_ICP) 159552dfdba0SLucas De Marchi gmbus_irq_handler(dev_priv); 159652dfdba0SLucas De Marchi } 159752dfdba0SLucas De Marchi 159891d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 15996dbf30ceSVille Syrjälä { 16006dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & 16016dbf30ceSVille Syrjälä ~SDE_PORTE_HOTPLUG_SPT; 16026dbf30ceSVille Syrjälä u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; 16036dbf30ceSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 16046dbf30ceSVille Syrjälä 16056dbf30ceSVille Syrjälä if (hotplug_trigger) { 16066dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 16076dbf30ceSVille Syrjälä 16088cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0); 16096dbf30ceSVille Syrjälä 1610cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 16110398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 16125a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 161374c0b395SVille Syrjälä spt_port_hotplug_long_detect); 16146dbf30ceSVille Syrjälä } 16156dbf30ceSVille Syrjälä 16166dbf30ceSVille Syrjälä if (hotplug2_trigger) { 16176dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 16186dbf30ceSVille Syrjälä 16198cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0); 16206dbf30ceSVille Syrjälä 1621cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 16220398993bSVille Syrjälä hotplug2_trigger, dig_hotplug_reg, 16235a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 16246dbf30ceSVille Syrjälä spt_port_hotplug2_long_detect); 16256dbf30ceSVille Syrjälä } 16266dbf30ceSVille Syrjälä 16276dbf30ceSVille Syrjälä if (pin_mask) 162891d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 16296dbf30ceSVille Syrjälä 16306dbf30ceSVille Syrjälä if (pch_iir & SDE_GMBUS_CPT) 163191d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 16326dbf30ceSVille Syrjälä } 16336dbf30ceSVille Syrjälä 163491d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, 16350398993bSVille Syrjälä u32 hotplug_trigger) 1636c008bc6eSPaulo Zanoni { 1637e4ce95aaSVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1638e4ce95aaSVille Syrjälä 16398cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0); 1640e4ce95aaSVille Syrjälä 16410398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 16420398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 16435a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1644e4ce95aaSVille Syrjälä ilk_port_hotplug_long_detect); 164540e56410SVille Syrjälä 164691d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1647e4ce95aaSVille Syrjälä } 1648c008bc6eSPaulo Zanoni 164991d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 165091d14251STvrtko Ursulin u32 de_iir) 165140e56410SVille Syrjälä { 165240e56410SVille Syrjälä enum pipe pipe; 165340e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 165440e56410SVille Syrjälä 165540e56410SVille Syrjälä if (hotplug_trigger) 16560398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 165740e56410SVille Syrjälä 1658c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 165991d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 1660c008bc6eSPaulo Zanoni 1661c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 166291d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 1663c008bc6eSPaulo Zanoni 1664c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 166500376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1666c008bc6eSPaulo Zanoni 1667055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1668fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 1669aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1670c008bc6eSPaulo Zanoni 16714bb18054SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE(pipe)) 16724bb18054SVille Syrjälä flip_done_handler(dev_priv, pipe); 16734bb18054SVille Syrjälä 167440da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 16751f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1676c008bc6eSPaulo Zanoni 167740da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 167891d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1679c008bc6eSPaulo Zanoni } 1680c008bc6eSPaulo Zanoni 1681c008bc6eSPaulo Zanoni /* check event from PCH */ 1682c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 16832939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 1684c008bc6eSPaulo Zanoni 168591d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 168691d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 1687c008bc6eSPaulo Zanoni else 168891d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 1689c008bc6eSPaulo Zanoni 1690c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 16912939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 1692c008bc6eSPaulo Zanoni } 1693c008bc6eSPaulo Zanoni 169493e7e61eSLucas De Marchi if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT) 16952cbc876dSMichał Winiarski gen5_rps_irq_handler(&to_gt(dev_priv)->rps); 1696c008bc6eSPaulo Zanoni } 1697c008bc6eSPaulo Zanoni 169891d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 169991d14251STvrtko Ursulin u32 de_iir) 17009719fb98SPaulo Zanoni { 170107d27e20SDamien Lespiau enum pipe pipe; 170223bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 170323bb4cb5SVille Syrjälä 170440e56410SVille Syrjälä if (hotplug_trigger) 17050398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 17069719fb98SPaulo Zanoni 17079719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 170891d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 17099719fb98SPaulo Zanoni 17109719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 171191d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 17129719fb98SPaulo Zanoni 17139719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 171491d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 17159719fb98SPaulo Zanoni 1716055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 171733ef04faSVille Syrjälä if (de_iir & DE_PIPE_VBLANK_IVB(pipe)) 1718aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 17192a636e24SVille Syrjälä 17202a636e24SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) 17212a636e24SVille Syrjälä flip_done_handler(dev_priv, pipe); 17229719fb98SPaulo Zanoni } 17239719fb98SPaulo Zanoni 17249719fb98SPaulo Zanoni /* check event from PCH */ 172591d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 17262939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 17279719fb98SPaulo Zanoni 172891d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 17299719fb98SPaulo Zanoni 17309719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 17312939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 17329719fb98SPaulo Zanoni } 17339719fb98SPaulo Zanoni } 17349719fb98SPaulo Zanoni 173572c90f62SOscar Mateo /* 173672c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 173772c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 173872c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 173972c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 174072c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 174172c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 174272c90f62SOscar Mateo */ 17439eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg) 1744b1f14ad0SJesse Barnes { 1745c48a798aSChris Wilson struct drm_i915_private *i915 = arg; 1746c48a798aSChris Wilson void __iomem * const regs = i915->uncore.regs; 1747f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 17480e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 1749b1f14ad0SJesse Barnes 1750c48a798aSChris Wilson if (unlikely(!intel_irqs_enabled(i915))) 17512dd2a883SImre Deak return IRQ_NONE; 17522dd2a883SImre Deak 17531f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1754c48a798aSChris Wilson disable_rpm_wakeref_asserts(&i915->runtime_pm); 17551f814dacSImre Deak 1756b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 1757c48a798aSChris Wilson de_ier = raw_reg_read(regs, DEIER); 1758c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 17590e43406bSChris Wilson 176044498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 176144498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 176244498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 176344498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 176444498aeaSPaulo Zanoni * due to its back queue). */ 1765c48a798aSChris Wilson if (!HAS_PCH_NOP(i915)) { 1766c48a798aSChris Wilson sde_ier = raw_reg_read(regs, SDEIER); 1767c48a798aSChris Wilson raw_reg_write(regs, SDEIER, 0); 1768ab5c608bSBen Widawsky } 176944498aeaSPaulo Zanoni 177072c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 177172c90f62SOscar Mateo 1772c48a798aSChris Wilson gt_iir = raw_reg_read(regs, GTIIR); 17730e43406bSChris Wilson if (gt_iir) { 1774c48a798aSChris Wilson raw_reg_write(regs, GTIIR, gt_iir); 1775651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) 17762cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(i915), gt_iir); 1777d8fc8a47SPaulo Zanoni else 17782cbc876dSMichał Winiarski gen5_gt_irq_handler(to_gt(i915), gt_iir); 1779c48a798aSChris Wilson ret = IRQ_HANDLED; 17800e43406bSChris Wilson } 1781b1f14ad0SJesse Barnes 1782c48a798aSChris Wilson de_iir = raw_reg_read(regs, DEIIR); 17830e43406bSChris Wilson if (de_iir) { 1784c48a798aSChris Wilson raw_reg_write(regs, DEIIR, de_iir); 1785373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 7) 1786c48a798aSChris Wilson ivb_display_irq_handler(i915, de_iir); 1787f1af8fc1SPaulo Zanoni else 1788c48a798aSChris Wilson ilk_display_irq_handler(i915, de_iir); 17890e43406bSChris Wilson ret = IRQ_HANDLED; 1790c48a798aSChris Wilson } 1791c48a798aSChris Wilson 1792651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) { 1793c48a798aSChris Wilson u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR); 1794c48a798aSChris Wilson if (pm_iir) { 1795c48a798aSChris Wilson raw_reg_write(regs, GEN6_PMIIR, pm_iir); 17962cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(i915)->rps, pm_iir); 1797c48a798aSChris Wilson ret = IRQ_HANDLED; 17980e43406bSChris Wilson } 1799f1af8fc1SPaulo Zanoni } 1800b1f14ad0SJesse Barnes 1801c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier); 1802c48a798aSChris Wilson if (sde_ier) 1803c48a798aSChris Wilson raw_reg_write(regs, SDEIER, sde_ier); 1804b1f14ad0SJesse Barnes 18059c6508b9SThomas Gleixner pmu_irq_stats(i915, ret); 18069c6508b9SThomas Gleixner 18071f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1808c48a798aSChris Wilson enable_rpm_wakeref_asserts(&i915->runtime_pm); 18091f814dacSImre Deak 1810b1f14ad0SJesse Barnes return ret; 1811b1f14ad0SJesse Barnes } 1812b1f14ad0SJesse Barnes 181391d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, 18140398993bSVille Syrjälä u32 hotplug_trigger) 1815d04a492dSShashank Sharma { 1816cebd87a0SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1817d04a492dSShashank Sharma 18188cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0); 1819d04a492dSShashank Sharma 18200398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18210398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 18225a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1823cebd87a0SVille Syrjälä bxt_port_hotplug_long_detect); 182440e56410SVille Syrjälä 182591d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1826d04a492dSShashank Sharma } 1827d04a492dSShashank Sharma 1828121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 1829121e758eSDhinakaran Pandiyan { 1830121e758eSDhinakaran Pandiyan u32 pin_mask = 0, long_mask = 0; 1831b796b971SDhinakaran Pandiyan u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; 1832b796b971SDhinakaran Pandiyan u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; 1833121e758eSDhinakaran Pandiyan 1834121e758eSDhinakaran Pandiyan if (trigger_tc) { 1835b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 1836b796b971SDhinakaran Pandiyan 18378cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0); 1838121e758eSDhinakaran Pandiyan 18390398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18400398993bSVille Syrjälä trigger_tc, dig_hotplug_reg, 18415a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1842da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 1843121e758eSDhinakaran Pandiyan } 1844b796b971SDhinakaran Pandiyan 1845b796b971SDhinakaran Pandiyan if (trigger_tbt) { 1846b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 1847b796b971SDhinakaran Pandiyan 18488cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0); 1849b796b971SDhinakaran Pandiyan 18500398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18510398993bSVille Syrjälä trigger_tbt, dig_hotplug_reg, 18525a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1853da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 1854b796b971SDhinakaran Pandiyan } 1855b796b971SDhinakaran Pandiyan 1856b796b971SDhinakaran Pandiyan if (pin_mask) 1857b796b971SDhinakaran Pandiyan intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1858b796b971SDhinakaran Pandiyan else 185900376ccfSWambui Karuga drm_err(&dev_priv->drm, 186000376ccfSWambui Karuga "Unexpected DE HPD interrupt 0x%08x\n", iir); 1861121e758eSDhinakaran Pandiyan } 1862121e758eSDhinakaran Pandiyan 18639d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 18649d17210fSLucas De Marchi { 186555523360SLucas De Marchi u32 mask; 18669d17210fSLucas De Marchi 186720fe778fSMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 186820fe778fSMatt Roper return TGL_DE_PORT_AUX_DDIA | 186920fe778fSMatt Roper TGL_DE_PORT_AUX_DDIB | 187020fe778fSMatt Roper TGL_DE_PORT_AUX_DDIC | 187120fe778fSMatt Roper XELPD_DE_PORT_AUX_DDID | 187220fe778fSMatt Roper XELPD_DE_PORT_AUX_DDIE | 187320fe778fSMatt Roper TGL_DE_PORT_AUX_USBC1 | 187420fe778fSMatt Roper TGL_DE_PORT_AUX_USBC2 | 187520fe778fSMatt Roper TGL_DE_PORT_AUX_USBC3 | 187620fe778fSMatt Roper TGL_DE_PORT_AUX_USBC4; 187720fe778fSMatt Roper else if (DISPLAY_VER(dev_priv) >= 12) 187855523360SLucas De Marchi return TGL_DE_PORT_AUX_DDIA | 187955523360SLucas De Marchi TGL_DE_PORT_AUX_DDIB | 1880e5df52dcSMatt Roper TGL_DE_PORT_AUX_DDIC | 1881e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC1 | 1882e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC2 | 1883e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC3 | 1884e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC4 | 1885e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC5 | 1886e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC6; 1887e5df52dcSMatt Roper 188855523360SLucas De Marchi 188955523360SLucas De Marchi mask = GEN8_AUX_CHANNEL_A; 1890373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 9) 18919d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 18929d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 18939d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 18949d17210fSLucas De Marchi 1895938a8a9aSLucas De Marchi if (DISPLAY_VER(dev_priv) == 11) { 1896938a8a9aSLucas De Marchi mask |= ICL_AUX_CHANNEL_F; 189755523360SLucas De Marchi mask |= ICL_AUX_CHANNEL_E; 1898938a8a9aSLucas De Marchi } 18999d17210fSLucas De Marchi 19009d17210fSLucas De Marchi return mask; 19019d17210fSLucas De Marchi } 19029d17210fSLucas De Marchi 19035270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) 19045270130dSVille Syrjälä { 19051649a4ccSMatt Roper if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv)) 190699e2d8bcSMatt Roper return RKL_DE_PIPE_IRQ_FAULT_ERRORS; 1907373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 11) 1908d506a65dSMatt Roper return GEN11_DE_PIPE_IRQ_FAULT_ERRORS; 1909373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 9) 19105270130dSVille Syrjälä return GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 19115270130dSVille Syrjälä else 19125270130dSVille Syrjälä return GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 19135270130dSVille Syrjälä } 19145270130dSVille Syrjälä 191546c63d24SJosé Roberto de Souza static void 191646c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 1917abd58f01SBen Widawsky { 1918e04f7eceSVille Syrjälä bool found = false; 1919e04f7eceSVille Syrjälä 1920e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 192191d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 1922e04f7eceSVille Syrjälä found = true; 1923e04f7eceSVille Syrjälä } 1924e04f7eceSVille Syrjälä 1925e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 1926b64d6c51SGwan-gyeong Mun struct intel_encoder *encoder; 19278241cfbeSJosé Roberto de Souza u32 psr_iir; 19288241cfbeSJosé Roberto de Souza i915_reg_t iir_reg; 19298241cfbeSJosé Roberto de Souza 1930a22af61dSJosé Roberto de Souza for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) { 1931b64d6c51SGwan-gyeong Mun struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1932b64d6c51SGwan-gyeong Mun 1933373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 1934b64d6c51SGwan-gyeong Mun iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder); 19358241cfbeSJosé Roberto de Souza else 19368241cfbeSJosé Roberto de Souza iir_reg = EDP_PSR_IIR; 19378241cfbeSJosé Roberto de Souza 19388cee664dSAndrzej Hajda psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0); 19398241cfbeSJosé Roberto de Souza 19408241cfbeSJosé Roberto de Souza if (psr_iir) 19418241cfbeSJosé Roberto de Souza found = true; 194254fd3149SDhinakaran Pandiyan 1943b64d6c51SGwan-gyeong Mun intel_psr_irq_handler(intel_dp, psr_iir); 1944b64d6c51SGwan-gyeong Mun 1945b64d6c51SGwan-gyeong Mun /* prior GEN12 only have one EDP PSR */ 1946373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 12) 1947b64d6c51SGwan-gyeong Mun break; 1948b64d6c51SGwan-gyeong Mun } 1949e04f7eceSVille Syrjälä } 1950e04f7eceSVille Syrjälä 1951e04f7eceSVille Syrjälä if (!found) 195200376ccfSWambui Karuga drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n"); 1953abd58f01SBen Widawsky } 195446c63d24SJosé Roberto de Souza 195500acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, 195600acb329SVandita Kulkarni u32 te_trigger) 195700acb329SVandita Kulkarni { 195800acb329SVandita Kulkarni enum pipe pipe = INVALID_PIPE; 195900acb329SVandita Kulkarni enum transcoder dsi_trans; 196000acb329SVandita Kulkarni enum port port; 196100acb329SVandita Kulkarni u32 val, tmp; 196200acb329SVandita Kulkarni 196300acb329SVandita Kulkarni /* 196400acb329SVandita Kulkarni * Incase of dual link, TE comes from DSI_1 196500acb329SVandita Kulkarni * this is to check if dual link is enabled 196600acb329SVandita Kulkarni */ 19672939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0)); 196800acb329SVandita Kulkarni val &= PORT_SYNC_MODE_ENABLE; 196900acb329SVandita Kulkarni 197000acb329SVandita Kulkarni /* 197100acb329SVandita Kulkarni * if dual link is enabled, then read DSI_0 197200acb329SVandita Kulkarni * transcoder registers 197300acb329SVandita Kulkarni */ 197400acb329SVandita Kulkarni port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ? 197500acb329SVandita Kulkarni PORT_A : PORT_B; 197600acb329SVandita Kulkarni dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; 197700acb329SVandita Kulkarni 197800acb329SVandita Kulkarni /* Check if DSI configured in command mode */ 19792939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans)); 198000acb329SVandita Kulkarni val = val & OP_MODE_MASK; 198100acb329SVandita Kulkarni 198200acb329SVandita Kulkarni if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { 198300acb329SVandita Kulkarni drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n"); 198400acb329SVandita Kulkarni return; 198500acb329SVandita Kulkarni } 198600acb329SVandita Kulkarni 198700acb329SVandita Kulkarni /* Get PIPE for handling VBLANK event */ 19882939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans)); 198900acb329SVandita Kulkarni switch (val & TRANS_DDI_EDP_INPUT_MASK) { 199000acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_A_ON: 199100acb329SVandita Kulkarni pipe = PIPE_A; 199200acb329SVandita Kulkarni break; 199300acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_B_ONOFF: 199400acb329SVandita Kulkarni pipe = PIPE_B; 199500acb329SVandita Kulkarni break; 199600acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_C_ONOFF: 199700acb329SVandita Kulkarni pipe = PIPE_C; 199800acb329SVandita Kulkarni break; 199900acb329SVandita Kulkarni default: 200000acb329SVandita Kulkarni drm_err(&dev_priv->drm, "Invalid PIPE\n"); 200100acb329SVandita Kulkarni return; 200200acb329SVandita Kulkarni } 200300acb329SVandita Kulkarni 200400acb329SVandita Kulkarni intel_handle_vblank(dev_priv, pipe); 200500acb329SVandita Kulkarni 200600acb329SVandita Kulkarni /* clear TE in dsi IIR */ 200700acb329SVandita Kulkarni port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; 20088cee664dSAndrzej Hajda tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); 200900acb329SVandita Kulkarni } 201000acb329SVandita Kulkarni 2011cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) 2012cda195f1SVille Syrjälä { 2013373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 9) 2014cda195f1SVille Syrjälä return GEN9_PIPE_PLANE1_FLIP_DONE; 2015cda195f1SVille Syrjälä else 2016cda195f1SVille Syrjälä return GEN8_PIPE_PRIMARY_FLIP_DONE; 2017cda195f1SVille Syrjälä } 2018cda195f1SVille Syrjälä 20198bcc0840SMatt Roper u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv) 20208bcc0840SMatt Roper { 20218bcc0840SMatt Roper u32 mask = GEN8_PIPE_FIFO_UNDERRUN; 20228bcc0840SMatt Roper 20238bcc0840SMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 20248bcc0840SMatt Roper mask |= XELPD_PIPE_SOFT_UNDERRUN | 20258bcc0840SMatt Roper XELPD_PIPE_HARD_UNDERRUN; 20268bcc0840SMatt Roper 20278bcc0840SMatt Roper return mask; 20288bcc0840SMatt Roper } 20298bcc0840SMatt Roper 203046c63d24SJosé Roberto de Souza static irqreturn_t 203146c63d24SJosé Roberto de Souza gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 203246c63d24SJosé Roberto de Souza { 203346c63d24SJosé Roberto de Souza irqreturn_t ret = IRQ_NONE; 203446c63d24SJosé Roberto de Souza u32 iir; 203546c63d24SJosé Roberto de Souza enum pipe pipe; 203646c63d24SJosé Roberto de Souza 2037a844cfbeSJosé Roberto de Souza drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv)); 2038a844cfbeSJosé Roberto de Souza 203946c63d24SJosé Roberto de Souza if (master_ctl & GEN8_DE_MISC_IRQ) { 20402939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR); 204146c63d24SJosé Roberto de Souza if (iir) { 20422939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir); 204346c63d24SJosé Roberto de Souza ret = IRQ_HANDLED; 204446c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(dev_priv, iir); 204546c63d24SJosé Roberto de Souza } else { 20469a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 204700376ccfSWambui Karuga "The master control interrupt lied (DE MISC)!\n"); 2048abd58f01SBen Widawsky } 204946c63d24SJosé Roberto de Souza } 2050abd58f01SBen Widawsky 2051373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 20522939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR); 2053121e758eSDhinakaran Pandiyan if (iir) { 20542939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir); 2055121e758eSDhinakaran Pandiyan ret = IRQ_HANDLED; 2056121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 2057121e758eSDhinakaran Pandiyan } else { 20589a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 205900376ccfSWambui Karuga "The master control interrupt lied, (DE HPD)!\n"); 2060121e758eSDhinakaran Pandiyan } 2061121e758eSDhinakaran Pandiyan } 2062121e758eSDhinakaran Pandiyan 20636d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 20642939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR); 2065e32192e1STvrtko Ursulin if (iir) { 2066d04a492dSShashank Sharma bool found = false; 2067cebd87a0SVille Syrjälä 20682939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir); 20696d766f02SDaniel Vetter ret = IRQ_HANDLED; 207088e04703SJesse Barnes 20719d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 207291d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2073d04a492dSShashank Sharma found = true; 2074d04a492dSShashank Sharma } 2075d04a492dSShashank Sharma 207670bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { 20779a55a620SVille Syrjälä u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK; 20789a55a620SVille Syrjälä 20799a55a620SVille Syrjälä if (hotplug_trigger) { 20809a55a620SVille Syrjälä bxt_hpd_irq_handler(dev_priv, hotplug_trigger); 2081d04a492dSShashank Sharma found = true; 2082d04a492dSShashank Sharma } 2083e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 20849a55a620SVille Syrjälä u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK; 20859a55a620SVille Syrjälä 20869a55a620SVille Syrjälä if (hotplug_trigger) { 20879a55a620SVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 2088e32192e1STvrtko Ursulin found = true; 2089e32192e1STvrtko Ursulin } 2090e32192e1STvrtko Ursulin } 2091d04a492dSShashank Sharma 209270bfb307SMatt Roper if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) && 209370bfb307SMatt Roper (iir & BXT_DE_PORT_GMBUS)) { 209491d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 20959e63743eSShashank Sharma found = true; 20969e63743eSShashank Sharma } 20979e63743eSShashank Sharma 2098373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 20999a55a620SVille Syrjälä u32 te_trigger = iir & (DSI0_TE | DSI1_TE); 21009a55a620SVille Syrjälä 21019a55a620SVille Syrjälä if (te_trigger) { 21029a55a620SVille Syrjälä gen11_dsi_te_interrupt_handler(dev_priv, te_trigger); 210300acb329SVandita Kulkarni found = true; 210400acb329SVandita Kulkarni } 210500acb329SVandita Kulkarni } 210600acb329SVandita Kulkarni 2107d04a492dSShashank Sharma if (!found) 21089a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 210900376ccfSWambui Karuga "Unexpected DE Port interrupt\n"); 21106d766f02SDaniel Vetter } 211138cc46d7SOscar Mateo else 21129a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 211300376ccfSWambui Karuga "The master control interrupt lied (DE PORT)!\n"); 21146d766f02SDaniel Vetter } 21156d766f02SDaniel Vetter 2116055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2117fd3a4024SDaniel Vetter u32 fault_errors; 2118abd58f01SBen Widawsky 2119c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 2120c42664ccSDaniel Vetter continue; 2121c42664ccSDaniel Vetter 21222939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); 2123e32192e1STvrtko Ursulin if (!iir) { 21249a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 212500376ccfSWambui Karuga "The master control interrupt lied (DE PIPE)!\n"); 2126e32192e1STvrtko Ursulin continue; 2127e32192e1STvrtko Ursulin } 2128770de83dSDamien Lespiau 2129e32192e1STvrtko Ursulin ret = IRQ_HANDLED; 21302939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir); 2131e32192e1STvrtko Ursulin 2132fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 2133aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 2134abd58f01SBen Widawsky 2135cda195f1SVille Syrjälä if (iir & gen8_de_pipe_flip_done_mask(dev_priv)) 21361288f9b0SKarthik B S flip_done_handler(dev_priv, pipe); 21371288f9b0SKarthik B S 2138e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 213991d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 21400fbe7870SDaniel Vetter 21418bcc0840SMatt Roper if (iir & gen8_de_pipe_underrun_mask(dev_priv)) 2142e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 214338d83c96SDaniel Vetter 21445270130dSVille Syrjälä fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); 2145770de83dSDamien Lespiau if (fault_errors) 21469a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 214700376ccfSWambui Karuga "Fault errors on pipe %c: 0x%08x\n", 214830100f2bSDaniel Vetter pipe_name(pipe), 2149e32192e1STvrtko Ursulin fault_errors); 2150abd58f01SBen Widawsky } 2151abd58f01SBen Widawsky 215291d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 2153266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 215492d03a80SDaniel Vetter /* 215592d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 215692d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 215792d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 215892d03a80SDaniel Vetter */ 21592939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 2160e32192e1STvrtko Ursulin if (iir) { 21612939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, iir); 216292d03a80SDaniel Vetter ret = IRQ_HANDLED; 21636dbf30ceSVille Syrjälä 216458676af6SLucas De Marchi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 216558676af6SLucas De Marchi icp_irq_handler(dev_priv, iir); 2166c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 216791d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 21686dbf30ceSVille Syrjälä else 216991d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 21702dfb0b81SJani Nikula } else { 21712dfb0b81SJani Nikula /* 21722dfb0b81SJani Nikula * Like on previous PCH there seems to be something 21732dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 21742dfb0b81SJani Nikula */ 217500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 217600376ccfSWambui Karuga "The master control interrupt lied (SDE)!\n"); 21772dfb0b81SJani Nikula } 217892d03a80SDaniel Vetter } 217992d03a80SDaniel Vetter 2180f11a0f46STvrtko Ursulin return ret; 2181f11a0f46STvrtko Ursulin } 2182f11a0f46STvrtko Ursulin 21834376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 21844376b9c9SMika Kuoppala { 21854376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 21864376b9c9SMika Kuoppala 21874376b9c9SMika Kuoppala /* 21884376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 21894376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 21904376b9c9SMika Kuoppala * New indications can and will light up during processing, 21914376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 21924376b9c9SMika Kuoppala */ 21934376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 21944376b9c9SMika Kuoppala } 21954376b9c9SMika Kuoppala 21964376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 21974376b9c9SMika Kuoppala { 21984376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 21994376b9c9SMika Kuoppala } 22004376b9c9SMika Kuoppala 2201f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 2202f11a0f46STvrtko Ursulin { 2203b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 220425286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 2205f11a0f46STvrtko Ursulin u32 master_ctl; 2206f11a0f46STvrtko Ursulin 2207f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 2208f11a0f46STvrtko Ursulin return IRQ_NONE; 2209f11a0f46STvrtko Ursulin 22104376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 22114376b9c9SMika Kuoppala if (!master_ctl) { 22124376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2213f11a0f46STvrtko Ursulin return IRQ_NONE; 22144376b9c9SMika Kuoppala } 2215f11a0f46STvrtko Ursulin 22166cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 22172cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 2218f0fd96f5SChris Wilson 2219f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2220f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 22219102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 222255ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 22239102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 2224f0fd96f5SChris Wilson } 2225f11a0f46STvrtko Ursulin 22264376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2227abd58f01SBen Widawsky 22289c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 22299c6508b9SThomas Gleixner 223055ef72f2SChris Wilson return IRQ_HANDLED; 2231abd58f01SBen Widawsky } 2232abd58f01SBen Widawsky 223351951ae7SMika Kuoppala static u32 2234ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl) 2235df0d28c1SDhinakaran Pandiyan { 2236ddcf980fSAnusha Srivatsa void __iomem * const regs = i915->uncore.regs; 22377a909383SChris Wilson u32 iir; 2238df0d28c1SDhinakaran Pandiyan 2239df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 22407a909383SChris Wilson return 0; 2241df0d28c1SDhinakaran Pandiyan 22427a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 22437a909383SChris Wilson if (likely(iir)) 22447a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 22457a909383SChris Wilson 22467a909383SChris Wilson return iir; 2247df0d28c1SDhinakaran Pandiyan } 2248df0d28c1SDhinakaran Pandiyan 2249df0d28c1SDhinakaran Pandiyan static void 2250ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir) 2251df0d28c1SDhinakaran Pandiyan { 2252df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 2253ddcf980fSAnusha Srivatsa intel_opregion_asle_intr(i915); 2254df0d28c1SDhinakaran Pandiyan } 2255df0d28c1SDhinakaran Pandiyan 225681067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 225781067b71SMika Kuoppala { 225881067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 225981067b71SMika Kuoppala 226081067b71SMika Kuoppala /* 226181067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 226281067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 226381067b71SMika Kuoppala * New indications can and will light up during processing, 226481067b71SMika Kuoppala * and will generate new interrupt after enabling master. 226581067b71SMika Kuoppala */ 226681067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 226781067b71SMika Kuoppala } 226881067b71SMika Kuoppala 226981067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 227081067b71SMika Kuoppala { 227181067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 227281067b71SMika Kuoppala } 227381067b71SMika Kuoppala 2274a3265d85SMatt Roper static void 2275a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915) 2276a3265d85SMatt Roper { 2277a3265d85SMatt Roper void __iomem * const regs = i915->uncore.regs; 2278a3265d85SMatt Roper const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 2279a3265d85SMatt Roper 2280a3265d85SMatt Roper disable_rpm_wakeref_asserts(&i915->runtime_pm); 2281a3265d85SMatt Roper /* 2282a3265d85SMatt Roper * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 2283a3265d85SMatt Roper * for the display related bits. 2284a3265d85SMatt Roper */ 2285a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); 2286a3265d85SMatt Roper gen8_de_irq_handler(i915, disp_ctl); 2287a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 2288a3265d85SMatt Roper GEN11_DISPLAY_IRQ_ENABLE); 2289a3265d85SMatt Roper 2290a3265d85SMatt Roper enable_rpm_wakeref_asserts(&i915->runtime_pm); 2291a3265d85SMatt Roper } 2292a3265d85SMatt Roper 229322e26af7SPaulo Zanoni static irqreturn_t gen11_irq_handler(int irq, void *arg) 229451951ae7SMika Kuoppala { 229522e26af7SPaulo Zanoni struct drm_i915_private *i915 = arg; 229625286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 22972cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 229851951ae7SMika Kuoppala u32 master_ctl; 2299df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 230051951ae7SMika Kuoppala 230151951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 230251951ae7SMika Kuoppala return IRQ_NONE; 230351951ae7SMika Kuoppala 230422e26af7SPaulo Zanoni master_ctl = gen11_master_intr_disable(regs); 230581067b71SMika Kuoppala if (!master_ctl) { 230622e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 230751951ae7SMika Kuoppala return IRQ_NONE; 230881067b71SMika Kuoppala } 230951951ae7SMika Kuoppala 23106cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 23119b77011eSTvrtko Ursulin gen11_gt_irq_handler(gt, master_ctl); 231251951ae7SMika Kuoppala 231351951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2314a3265d85SMatt Roper if (master_ctl & GEN11_DISPLAY_IRQ) 2315a3265d85SMatt Roper gen11_display_irq_handler(i915); 231651951ae7SMika Kuoppala 2317ddcf980fSAnusha Srivatsa gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 2318df0d28c1SDhinakaran Pandiyan 231922e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 232051951ae7SMika Kuoppala 2321ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(i915, gu_misc_iir); 2322df0d28c1SDhinakaran Pandiyan 23239c6508b9SThomas Gleixner pmu_irq_stats(i915, IRQ_HANDLED); 23249c6508b9SThomas Gleixner 232551951ae7SMika Kuoppala return IRQ_HANDLED; 232651951ae7SMika Kuoppala } 232751951ae7SMika Kuoppala 232822e26af7SPaulo Zanoni static inline u32 dg1_master_intr_disable(void __iomem * const regs) 232997b492f5SLucas De Marchi { 233097b492f5SLucas De Marchi u32 val; 233197b492f5SLucas De Marchi 233297b492f5SLucas De Marchi /* First disable interrupts */ 233322e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0); 233497b492f5SLucas De Marchi 233597b492f5SLucas De Marchi /* Get the indication levels and ack the master unit */ 233622e26af7SPaulo Zanoni val = raw_reg_read(regs, DG1_MSTR_TILE_INTR); 233797b492f5SLucas De Marchi if (unlikely(!val)) 233897b492f5SLucas De Marchi return 0; 233997b492f5SLucas De Marchi 234022e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, val); 234197b492f5SLucas De Marchi 234297b492f5SLucas De Marchi return val; 234397b492f5SLucas De Marchi } 234497b492f5SLucas De Marchi 234597b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs) 234697b492f5SLucas De Marchi { 234722e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ); 234897b492f5SLucas De Marchi } 234997b492f5SLucas De Marchi 235097b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg) 235197b492f5SLucas De Marchi { 235222e26af7SPaulo Zanoni struct drm_i915_private * const i915 = arg; 23532cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 2354fd4d7904SPaulo Zanoni void __iomem * const regs = gt->uncore->regs; 235522e26af7SPaulo Zanoni u32 master_tile_ctl, master_ctl; 235622e26af7SPaulo Zanoni u32 gu_misc_iir; 235722e26af7SPaulo Zanoni 235822e26af7SPaulo Zanoni if (!intel_irqs_enabled(i915)) 235922e26af7SPaulo Zanoni return IRQ_NONE; 236022e26af7SPaulo Zanoni 236122e26af7SPaulo Zanoni master_tile_ctl = dg1_master_intr_disable(regs); 236222e26af7SPaulo Zanoni if (!master_tile_ctl) { 236322e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 236422e26af7SPaulo Zanoni return IRQ_NONE; 236522e26af7SPaulo Zanoni } 236622e26af7SPaulo Zanoni 236722e26af7SPaulo Zanoni /* FIXME: we only support tile 0 for now. */ 236822e26af7SPaulo Zanoni if (master_tile_ctl & DG1_MSTR_TILE(0)) { 236922e26af7SPaulo Zanoni master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 237022e26af7SPaulo Zanoni raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl); 237122e26af7SPaulo Zanoni } else { 2372a10234fdSTvrtko Ursulin drm_err(&i915->drm, "Tile not supported: 0x%08x\n", 2373a10234fdSTvrtko Ursulin master_tile_ctl); 237422e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 237522e26af7SPaulo Zanoni return IRQ_NONE; 237622e26af7SPaulo Zanoni } 237722e26af7SPaulo Zanoni 237822e26af7SPaulo Zanoni gen11_gt_irq_handler(gt, master_ctl); 237922e26af7SPaulo Zanoni 238022e26af7SPaulo Zanoni if (master_ctl & GEN11_DISPLAY_IRQ) 238122e26af7SPaulo Zanoni gen11_display_irq_handler(i915); 238222e26af7SPaulo Zanoni 2383ddcf980fSAnusha Srivatsa gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 238422e26af7SPaulo Zanoni 238522e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 238622e26af7SPaulo Zanoni 2387ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(i915, gu_misc_iir); 238822e26af7SPaulo Zanoni 238922e26af7SPaulo Zanoni pmu_irq_stats(i915, IRQ_HANDLED); 239022e26af7SPaulo Zanoni 239122e26af7SPaulo Zanoni return IRQ_HANDLED; 239297b492f5SLucas De Marchi } 239397b492f5SLucas De Marchi 239442f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 239542f52ef8SKeith Packard * we use as a pipe index 239642f52ef8SKeith Packard */ 239708fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc) 23980a3e67a4SJesse Barnes { 239908fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 240008fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2401e9d21d7fSKeith Packard unsigned long irqflags; 240271e0ffa5SJesse Barnes 24031ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 240486e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 240586e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 240686e83e35SChris Wilson 240786e83e35SChris Wilson return 0; 240886e83e35SChris Wilson } 240986e83e35SChris Wilson 24107d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc) 2411d938da6bSVille Syrjälä { 241208fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2413d938da6bSVille Syrjälä 24147d423af9SVille Syrjälä /* 24157d423af9SVille Syrjälä * Vblank interrupts fail to wake the device up from C2+. 24167d423af9SVille Syrjälä * Disabling render clock gating during C-states avoids 24177d423af9SVille Syrjälä * the problem. There is a small power cost so we do this 24187d423af9SVille Syrjälä * only when vblank interrupts are actually enabled. 24197d423af9SVille Syrjälä */ 24207d423af9SVille Syrjälä if (dev_priv->vblank_enabled++ == 0) 24212939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2422d938da6bSVille Syrjälä 242308fa8fd0SVille Syrjälä return i8xx_enable_vblank(crtc); 2424d938da6bSVille Syrjälä } 2425d938da6bSVille Syrjälä 242608fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc) 242786e83e35SChris Wilson { 242808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 242908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 243086e83e35SChris Wilson unsigned long irqflags; 243186e83e35SChris Wilson 243286e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 24337c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 2434755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 24351ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 24368692d00eSChris Wilson 24370a3e67a4SJesse Barnes return 0; 24380a3e67a4SJesse Barnes } 24390a3e67a4SJesse Barnes 244008fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc) 2441f796cf8fSJesse Barnes { 244208fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 244308fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2444f796cf8fSJesse Barnes unsigned long irqflags; 2445373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 244686e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2447f796cf8fSJesse Barnes 2448f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2449fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 2450b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2451b1f14ad0SJesse Barnes 24522e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 24532e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 24542e8bf223SDhinakaran Pandiyan */ 24552e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 245608fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 24572e8bf223SDhinakaran Pandiyan 2458b1f14ad0SJesse Barnes return 0; 2459b1f14ad0SJesse Barnes } 2460b1f14ad0SJesse Barnes 24619c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, 24629c9e97c4SVandita Kulkarni bool enable) 24639c9e97c4SVandita Kulkarni { 24649c9e97c4SVandita Kulkarni struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); 24659c9e97c4SVandita Kulkarni enum port port; 24669c9e97c4SVandita Kulkarni 24679c9e97c4SVandita Kulkarni if (!(intel_crtc->mode_flags & 24689c9e97c4SVandita Kulkarni (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0))) 24699c9e97c4SVandita Kulkarni return false; 24709c9e97c4SVandita Kulkarni 24719c9e97c4SVandita Kulkarni /* for dual link cases we consider TE from slave */ 24729c9e97c4SVandita Kulkarni if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1) 24739c9e97c4SVandita Kulkarni port = PORT_B; 24749c9e97c4SVandita Kulkarni else 24759c9e97c4SVandita Kulkarni port = PORT_A; 24769c9e97c4SVandita Kulkarni 24778cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, 24788cee664dSAndrzej Hajda enable ? 0 : DSI_TE_EVENT); 24799c9e97c4SVandita Kulkarni 24808cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); 24819c9e97c4SVandita Kulkarni 24829c9e97c4SVandita Kulkarni return true; 24839c9e97c4SVandita Kulkarni } 24849c9e97c4SVandita Kulkarni 2485f15f01a7SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *_crtc) 2486abd58f01SBen Widawsky { 2487f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 2488f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2489f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 2490abd58f01SBen Widawsky unsigned long irqflags; 2491abd58f01SBen Widawsky 2492f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, true)) 24939c9e97c4SVandita Kulkarni return 0; 24949c9e97c4SVandita Kulkarni 2495abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2496013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2497abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2498013d3752SVille Syrjälä 24992e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 25002e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 25012e8bf223SDhinakaran Pandiyan */ 25022e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 2503f15f01a7SVille Syrjälä drm_crtc_vblank_restore(&crtc->base); 25042e8bf223SDhinakaran Pandiyan 2505abd58f01SBen Widawsky return 0; 2506abd58f01SBen Widawsky } 2507abd58f01SBen Widawsky 250842f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 250942f52ef8SKeith Packard * we use as a pipe index 251042f52ef8SKeith Packard */ 251108fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc) 251286e83e35SChris Wilson { 251308fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 251408fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 251586e83e35SChris Wilson unsigned long irqflags; 251686e83e35SChris Wilson 251786e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 251886e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 251986e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 252086e83e35SChris Wilson } 252186e83e35SChris Wilson 25227d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc) 2523d938da6bSVille Syrjälä { 252408fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2525d938da6bSVille Syrjälä 252608fa8fd0SVille Syrjälä i8xx_disable_vblank(crtc); 2527d938da6bSVille Syrjälä 25287d423af9SVille Syrjälä if (--dev_priv->vblank_enabled == 0) 25292939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2530d938da6bSVille Syrjälä } 2531d938da6bSVille Syrjälä 253208fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc) 25330a3e67a4SJesse Barnes { 253408fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 253508fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2536e9d21d7fSKeith Packard unsigned long irqflags; 25370a3e67a4SJesse Barnes 25381ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 25397c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 2540755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 25411ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 25420a3e67a4SJesse Barnes } 25430a3e67a4SJesse Barnes 254408fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc) 2545f796cf8fSJesse Barnes { 254608fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 254708fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2548f796cf8fSJesse Barnes unsigned long irqflags; 2549373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 255086e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2551f796cf8fSJesse Barnes 2552f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2553fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 2554b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2555b1f14ad0SJesse Barnes } 2556b1f14ad0SJesse Barnes 2557f15f01a7SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *_crtc) 2558abd58f01SBen Widawsky { 2559f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 2560f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2561f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 2562abd58f01SBen Widawsky unsigned long irqflags; 2563abd58f01SBen Widawsky 2564f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, false)) 25659c9e97c4SVandita Kulkarni return; 25669c9e97c4SVandita Kulkarni 2567abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2568013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2569abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2570abd58f01SBen Widawsky } 2571abd58f01SBen Widawsky 2572b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 257391738a95SPaulo Zanoni { 2574b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2575b16b2a2fSPaulo Zanoni 25766e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 257791738a95SPaulo Zanoni return; 257891738a95SPaulo Zanoni 2579b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 2580105b122eSPaulo Zanoni 25816e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 25822939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff); 2583622364b6SPaulo Zanoni } 2584105b122eSPaulo Zanoni 258570591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 258670591a41SVille Syrjälä { 2587b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2588b16b2a2fSPaulo Zanoni 258971b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2590f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 259171b8b41dSVille Syrjälä else 25927d938bc0SVille Syrjälä intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); 259371b8b41dSVille Syrjälä 2594ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 25958cee664dSAndrzej Hajda intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); 259670591a41SVille Syrjälä 259744d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 259870591a41SVille Syrjälä 2599b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, VLV_); 26008bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 260170591a41SVille Syrjälä } 260270591a41SVille Syrjälä 26038bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 26048bb61306SVille Syrjälä { 2605b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2606b16b2a2fSPaulo Zanoni 26078bb61306SVille Syrjälä u32 pipestat_mask; 26089ab981f2SVille Syrjälä u32 enable_mask; 26098bb61306SVille Syrjälä enum pipe pipe; 26108bb61306SVille Syrjälä 2611842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 26128bb61306SVille Syrjälä 26138bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 26148bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 26158bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 26168bb61306SVille Syrjälä 26179ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 26188bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2619ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 2620ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 2621ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 2622ebf5f921SVille Syrjälä 26238bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2624ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 2625ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 26266b7eafc1SVille Syrjälä 262748a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u); 26286b7eafc1SVille Syrjälä 26299ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 26308bb61306SVille Syrjälä 2631b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask); 26328bb61306SVille Syrjälä } 26338bb61306SVille Syrjälä 26348bb61306SVille Syrjälä /* drm_dma.h hooks 26358bb61306SVille Syrjälä */ 26369eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv) 26378bb61306SVille Syrjälä { 2638b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 26398bb61306SVille Syrjälä 2640b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, DE); 2641e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 2642e44adb5dSChris Wilson 2643651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) == 7) 2644f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); 26458bb61306SVille Syrjälä 2646fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 2647f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2648f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2649fc340442SDaniel Vetter } 2650fc340442SDaniel Vetter 26512cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 26528bb61306SVille Syrjälä 2653b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 26548bb61306SVille Syrjälä } 26558bb61306SVille Syrjälä 2656b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv) 26577e231dbeSJesse Barnes { 26582939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 26592939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 266034c7b8a7SVille Syrjälä 26612cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 26627e231dbeSJesse Barnes 2663ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 26649918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 266570591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2666ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 26677e231dbeSJesse Barnes } 26687e231dbeSJesse Barnes 2669a844cfbeSJosé Roberto de Souza static void gen8_display_irq_reset(struct drm_i915_private *dev_priv) 2670abd58f01SBen Widawsky { 2671b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2672d048a268SVille Syrjälä enum pipe pipe; 2673abd58f01SBen Widawsky 2674a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2675a844cfbeSJosé Roberto de Souza return; 2676abd58f01SBen Widawsky 2677f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2678f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2679e04f7eceSVille Syrjälä 2680055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 2681f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 2682813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 2683b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 2684abd58f01SBen Widawsky 2685b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2686b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2687a844cfbeSJosé Roberto de Souza } 2688a844cfbeSJosé Roberto de Souza 2689a844cfbeSJosé Roberto de Souza static void gen8_irq_reset(struct drm_i915_private *dev_priv) 2690a844cfbeSJosé Roberto de Souza { 2691a844cfbeSJosé Roberto de Souza struct intel_uncore *uncore = &dev_priv->uncore; 2692a844cfbeSJosé Roberto de Souza 2693e58c2cacSAndrzej Hajda gen8_master_intr_disable(uncore->regs); 2694a844cfbeSJosé Roberto de Souza 26952cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 2696a844cfbeSJosé Roberto de Souza gen8_display_irq_reset(dev_priv); 2697b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 2698abd58f01SBen Widawsky 26996e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 2700b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 270159b7cb44STejas Upadhyay 2702abd58f01SBen Widawsky } 2703abd58f01SBen Widawsky 2704a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) 270551951ae7SMika Kuoppala { 2706b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2707d048a268SVille Syrjälä enum pipe pipe; 2708562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 2709562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 271051951ae7SMika Kuoppala 2711a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2712a844cfbeSJosé Roberto de Souza return; 2713a844cfbeSJosé Roberto de Souza 2714f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); 271551951ae7SMika Kuoppala 2716373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 27178241cfbeSJosé Roberto de Souza enum transcoder trans; 27188241cfbeSJosé Roberto de Souza 2719562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 27208241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 27218241cfbeSJosé Roberto de Souza 27228241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 27238241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 27248241cfbeSJosé Roberto de Souza continue; 27258241cfbeSJosé Roberto de Souza 27268241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff); 27278241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff); 27288241cfbeSJosé Roberto de Souza } 27298241cfbeSJosé Roberto de Souza } else { 2730f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2731f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 27328241cfbeSJosé Roberto de Souza } 273362819dfdSJosé Roberto de Souza 273451951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 273551951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 273651951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 2737b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 273851951ae7SMika Kuoppala 2739b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2740b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2741b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); 274231604222SAnusha Srivatsa 274329b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2744b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 274551951ae7SMika Kuoppala } 274651951ae7SMika Kuoppala 2747a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv) 2748a3265d85SMatt Roper { 27492cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2750fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 2751a3265d85SMatt Roper 2752a3265d85SMatt Roper gen11_master_intr_disable(dev_priv->uncore.regs); 2753a3265d85SMatt Roper 2754fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 2755a3265d85SMatt Roper gen11_display_irq_reset(dev_priv); 2756a3265d85SMatt Roper 2757a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 2758a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN8_PCU_); 2759a3265d85SMatt Roper } 2760a3265d85SMatt Roper 276122e26af7SPaulo Zanoni static void dg1_irq_reset(struct drm_i915_private *dev_priv) 276222e26af7SPaulo Zanoni { 27632cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2764fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 276522e26af7SPaulo Zanoni 276622e26af7SPaulo Zanoni dg1_master_intr_disable(dev_priv->uncore.regs); 276722e26af7SPaulo Zanoni 2768fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 276922e26af7SPaulo Zanoni gen11_display_irq_reset(dev_priv); 277022e26af7SPaulo Zanoni 277122e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 277222e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 277322e26af7SPaulo Zanoni } 277422e26af7SPaulo Zanoni 27754c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 2776001bd2cbSImre Deak u8 pipe_mask) 2777d49bdb0eSPaulo Zanoni { 2778b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 27798bcc0840SMatt Roper u32 extra_ier = GEN8_PIPE_VBLANK | 27808bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 2781cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 27826831f3e3SVille Syrjälä enum pipe pipe; 2783d49bdb0eSPaulo Zanoni 278413321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 27859dfe2e3aSImre Deak 27869dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 27879dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 27889dfe2e3aSImre Deak return; 27899dfe2e3aSImre Deak } 27909dfe2e3aSImre Deak 27916831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2792b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 27936831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 27946831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 27959dfe2e3aSImre Deak 279613321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 2797d49bdb0eSPaulo Zanoni } 2798d49bdb0eSPaulo Zanoni 2799aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 2800001bd2cbSImre Deak u8 pipe_mask) 2801aae8ba84SVille Syrjälä { 2802b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 28036831f3e3SVille Syrjälä enum pipe pipe; 28046831f3e3SVille Syrjälä 2805aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 28069dfe2e3aSImre Deak 28079dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 28089dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 28099dfe2e3aSImre Deak return; 28109dfe2e3aSImre Deak } 28119dfe2e3aSImre Deak 28126831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2813b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 28149dfe2e3aSImre Deak 2815aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 2816aae8ba84SVille Syrjälä 2817aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 2818315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 2819aae8ba84SVille Syrjälä } 2820aae8ba84SVille Syrjälä 2821b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv) 282243f328d7SVille Syrjälä { 2823b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 282443f328d7SVille Syrjälä 2825e58c2cacSAndrzej Hajda intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0); 28262939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 282743f328d7SVille Syrjälä 28282cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 282943f328d7SVille Syrjälä 2830b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 283143f328d7SVille Syrjälä 2832ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 28339918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 283470591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2835ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 283643f328d7SVille Syrjälä } 283743f328d7SVille Syrjälä 2838dfefe7bcSVille Syrjälä static u32 ibx_hotplug_enables(struct intel_encoder *encoder) 28392ea63927SVille Syrjälä { 2840dfefe7bcSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 2841dfefe7bcSVille Syrjälä 2842dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 28432ea63927SVille Syrjälä case HPD_PORT_A: 28442ea63927SVille Syrjälä /* 28452ea63927SVille Syrjälä * When CPU and PCH are on the same package, port A 28462ea63927SVille Syrjälä * HPD must be enabled in both north and south. 28472ea63927SVille Syrjälä */ 28482ea63927SVille Syrjälä return HAS_PCH_LPT_LP(i915) ? 28492ea63927SVille Syrjälä PORTA_HOTPLUG_ENABLE : 0; 28502ea63927SVille Syrjälä case HPD_PORT_B: 28512ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE | 28522ea63927SVille Syrjälä PORTB_PULSE_DURATION_2ms; 28532ea63927SVille Syrjälä case HPD_PORT_C: 28542ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE | 28552ea63927SVille Syrjälä PORTC_PULSE_DURATION_2ms; 28562ea63927SVille Syrjälä case HPD_PORT_D: 28572ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE | 28582ea63927SVille Syrjälä PORTD_PULSE_DURATION_2ms; 28592ea63927SVille Syrjälä default: 28602ea63927SVille Syrjälä return 0; 28612ea63927SVille Syrjälä } 28622ea63927SVille Syrjälä } 28632ea63927SVille Syrjälä 28641a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) 28651a56b1a2SImre Deak { 28661a56b1a2SImre Deak /* 28671a56b1a2SImre Deak * Enable digital hotplug on the PCH, and configure the DP short pulse 28681a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec). 28691a56b1a2SImre Deak * The pulse duration bits are reserved on LPT+. 28701a56b1a2SImre Deak */ 28718cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 28728cee664dSAndrzej Hajda PORTA_HOTPLUG_ENABLE | 28732ea63927SVille Syrjälä PORTB_HOTPLUG_ENABLE | 28742ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 28752ea63927SVille Syrjälä PORTD_HOTPLUG_ENABLE | 28762ea63927SVille Syrjälä PORTB_PULSE_DURATION_MASK | 28771a56b1a2SImre Deak PORTC_PULSE_DURATION_MASK | 28788cee664dSAndrzej Hajda PORTD_PULSE_DURATION_MASK, 28798cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables)); 28801a56b1a2SImre Deak } 28811a56b1a2SImre Deak 288291d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) 288382a28bcfSDaniel Vetter { 28841a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 288582a28bcfSDaniel Vetter 28865a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 28875a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 288882a28bcfSDaniel Vetter 2889fee884edSDaniel Vetter ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 289082a28bcfSDaniel Vetter 28911a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 28926dbf30ceSVille Syrjälä } 289326951cafSXiong Zhang 2894dfefe7bcSVille Syrjälä static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder) 28952ea63927SVille Syrjälä { 2896dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 28972ea63927SVille Syrjälä case HPD_PORT_A: 28982ea63927SVille Syrjälä case HPD_PORT_B: 28992ea63927SVille Syrjälä case HPD_PORT_C: 29002ea63927SVille Syrjälä case HPD_PORT_D: 2901dfefe7bcSVille Syrjälä return SHOTPLUG_CTL_DDI_HPD_ENABLE(encoder->hpd_pin); 29022ea63927SVille Syrjälä default: 29032ea63927SVille Syrjälä return 0; 29042ea63927SVille Syrjälä } 29052ea63927SVille Syrjälä } 29062ea63927SVille Syrjälä 2907dfefe7bcSVille Syrjälä static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder) 29082ea63927SVille Syrjälä { 2909dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 29102ea63927SVille Syrjälä case HPD_PORT_TC1: 29112ea63927SVille Syrjälä case HPD_PORT_TC2: 29122ea63927SVille Syrjälä case HPD_PORT_TC3: 29132ea63927SVille Syrjälä case HPD_PORT_TC4: 29142ea63927SVille Syrjälä case HPD_PORT_TC5: 29152ea63927SVille Syrjälä case HPD_PORT_TC6: 2916dfefe7bcSVille Syrjälä return ICP_TC_HPD_ENABLE(encoder->hpd_pin); 29172ea63927SVille Syrjälä default: 29182ea63927SVille Syrjälä return 0; 29192ea63927SVille Syrjälä } 29202ea63927SVille Syrjälä } 29212ea63927SVille Syrjälä 29222ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv) 292331604222SAnusha Srivatsa { 29248cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 29258cee664dSAndrzej Hajda SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) | 29262ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | 29272ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | 29288cee664dSAndrzej Hajda SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D), 29298cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables)); 293031604222SAnusha Srivatsa } 2931815f4ef2SVille Syrjälä 29322ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 2933815f4ef2SVille Syrjälä { 29348cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 29358cee664dSAndrzej Hajda ICP_TC_HPD_ENABLE(HPD_PORT_TC1) | 29362ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | 29372ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | 29382ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | 29392ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | 29408cee664dSAndrzej Hajda ICP_TC_HPD_ENABLE(HPD_PORT_TC6), 29418cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables)); 29428ef7e340SMatt Roper } 294331604222SAnusha Srivatsa 29442ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) 294531604222SAnusha Srivatsa { 294631604222SAnusha Srivatsa u32 hotplug_irqs, enabled_irqs; 294731604222SAnusha Srivatsa 29485a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 29495a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 295031604222SAnusha Srivatsa 2951f619e516SAnusha Srivatsa if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) 29522939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 2953f49108d0SMatt Roper 295431604222SAnusha Srivatsa ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 295531604222SAnusha Srivatsa 29562ea63927SVille Syrjälä icp_ddi_hpd_detection_setup(dev_priv); 29572ea63927SVille Syrjälä icp_tc_hpd_detection_setup(dev_priv); 295852dfdba0SLucas De Marchi } 295952dfdba0SLucas De Marchi 2960dfefe7bcSVille Syrjälä static u32 gen11_hotplug_enables(struct intel_encoder *encoder) 29618ef7e340SMatt Roper { 2962dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 29632ea63927SVille Syrjälä case HPD_PORT_TC1: 29642ea63927SVille Syrjälä case HPD_PORT_TC2: 29652ea63927SVille Syrjälä case HPD_PORT_TC3: 29662ea63927SVille Syrjälä case HPD_PORT_TC4: 29672ea63927SVille Syrjälä case HPD_PORT_TC5: 29682ea63927SVille Syrjälä case HPD_PORT_TC6: 2969dfefe7bcSVille Syrjälä return GEN11_HOTPLUG_CTL_ENABLE(encoder->hpd_pin); 29702ea63927SVille Syrjälä default: 29712ea63927SVille Syrjälä return 0; 297231604222SAnusha Srivatsa } 2973943682e3SMatt Roper } 2974943682e3SMatt Roper 297571690148SGustavo Sousa static void dg1_hpd_invert(struct drm_i915_private *i915) 2976229f31e2SLucas De Marchi { 297771690148SGustavo Sousa u32 val = (INVERT_DDIA_HPD | 2978b18c1eb9SClinton A Taylor INVERT_DDIB_HPD | 2979b18c1eb9SClinton A Taylor INVERT_DDIC_HPD | 2980b18c1eb9SClinton A Taylor INVERT_DDID_HPD); 298171690148SGustavo Sousa intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val); 298271690148SGustavo Sousa } 2983b18c1eb9SClinton A Taylor 298471690148SGustavo Sousa static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) 298571690148SGustavo Sousa { 298671690148SGustavo Sousa dg1_hpd_invert(dev_priv); 29872ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 2988229f31e2SLucas De Marchi } 2989229f31e2SLucas De Marchi 299052c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 2991121e758eSDhinakaran Pandiyan { 29928cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 29938cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 29945b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 29955b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 29965b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 29975b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 29988cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6), 29998cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables)); 300052c7f5f1SVille Syrjälä } 300152c7f5f1SVille Syrjälä 300252c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv) 300352c7f5f1SVille Syrjälä { 30048cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 30058cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 30065b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 30075b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 30085b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 30095b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 30108cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6), 30118cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables)); 3012121e758eSDhinakaran Pandiyan } 3013121e758eSDhinakaran Pandiyan 3014121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) 3015121e758eSDhinakaran Pandiyan { 3016121e758eSDhinakaran Pandiyan u32 hotplug_irqs, enabled_irqs; 3017121e758eSDhinakaran Pandiyan 30185a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); 30195a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); 3020121e758eSDhinakaran Pandiyan 30218cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs, 30228cee664dSAndrzej Hajda ~enabled_irqs & hotplug_irqs); 30232939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); 3024121e758eSDhinakaran Pandiyan 302552c7f5f1SVille Syrjälä gen11_tc_hpd_detection_setup(dev_priv); 302652c7f5f1SVille Syrjälä gen11_tbt_hpd_detection_setup(dev_priv); 302731604222SAnusha Srivatsa 30282ea63927SVille Syrjälä if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 30292ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 30302ea63927SVille Syrjälä } 30312ea63927SVille Syrjälä 3032dfefe7bcSVille Syrjälä static u32 spt_hotplug_enables(struct intel_encoder *encoder) 30332ea63927SVille Syrjälä { 3034dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 30352ea63927SVille Syrjälä case HPD_PORT_A: 30362ea63927SVille Syrjälä return PORTA_HOTPLUG_ENABLE; 30372ea63927SVille Syrjälä case HPD_PORT_B: 30382ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE; 30392ea63927SVille Syrjälä case HPD_PORT_C: 30402ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE; 30412ea63927SVille Syrjälä case HPD_PORT_D: 30422ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE; 30432ea63927SVille Syrjälä default: 30442ea63927SVille Syrjälä return 0; 30452ea63927SVille Syrjälä } 30462ea63927SVille Syrjälä } 30472ea63927SVille Syrjälä 3048dfefe7bcSVille Syrjälä static u32 spt_hotplug2_enables(struct intel_encoder *encoder) 30492ea63927SVille Syrjälä { 3050dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 30512ea63927SVille Syrjälä case HPD_PORT_E: 30522ea63927SVille Syrjälä return PORTE_HOTPLUG_ENABLE; 30532ea63927SVille Syrjälä default: 30542ea63927SVille Syrjälä return 0; 30552ea63927SVille Syrjälä } 3056121e758eSDhinakaran Pandiyan } 3057121e758eSDhinakaran Pandiyan 30582a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) 30592a57d9ccSImre Deak { 30603b92e263SRodrigo Vivi /* Display WA #1179 WaHardHangonHotPlug: cnp */ 30613b92e263SRodrigo Vivi if (HAS_PCH_CNP(dev_priv)) { 30628cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK, 30638cee664dSAndrzej Hajda CHASSIS_CLK_REQ_DURATION(0xf)); 30643b92e263SRodrigo Vivi } 30652a57d9ccSImre Deak 30662a57d9ccSImre Deak /* Enable digital hotplug on the PCH */ 30678cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 30688cee664dSAndrzej Hajda PORTA_HOTPLUG_ENABLE | 30692a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 30702a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE | 30718cee664dSAndrzej Hajda PORTD_HOTPLUG_ENABLE, 30728cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables)); 30732a57d9ccSImre Deak 30748cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, PORTE_HOTPLUG_ENABLE, 30758cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables)); 30762a57d9ccSImre Deak } 30772a57d9ccSImre Deak 307891d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) 30796dbf30ceSVille Syrjälä { 30802a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 30816dbf30ceSVille Syrjälä 3082f49108d0SMatt Roper if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) 30832939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 3084f49108d0SMatt Roper 30855a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 30865a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 30876dbf30ceSVille Syrjälä 30886dbf30ceSVille Syrjälä ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 30896dbf30ceSVille Syrjälä 30902a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 309126951cafSXiong Zhang } 30927fe0b973SKeith Packard 3093dfefe7bcSVille Syrjälä static u32 ilk_hotplug_enables(struct intel_encoder *encoder) 30942ea63927SVille Syrjälä { 3095dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 30962ea63927SVille Syrjälä case HPD_PORT_A: 30972ea63927SVille Syrjälä return DIGITAL_PORTA_HOTPLUG_ENABLE | 30982ea63927SVille Syrjälä DIGITAL_PORTA_PULSE_DURATION_2ms; 30992ea63927SVille Syrjälä default: 31002ea63927SVille Syrjälä return 0; 31012ea63927SVille Syrjälä } 31022ea63927SVille Syrjälä } 31032ea63927SVille Syrjälä 31041a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) 31051a56b1a2SImre Deak { 31061a56b1a2SImre Deak /* 31071a56b1a2SImre Deak * Enable digital hotplug on the CPU, and configure the DP short pulse 31081a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec) 31091a56b1a2SImre Deak * The pulse duration bits are reserved on HSW+. 31101a56b1a2SImre Deak */ 31118cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 31128cee664dSAndrzej Hajda DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_MASK, 31138cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables)); 31141a56b1a2SImre Deak } 31151a56b1a2SImre Deak 311691d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) 3117e4ce95aaSVille Syrjälä { 31181a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 3119e4ce95aaSVille Syrjälä 31205a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31215a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31223a3b3c7dSVille Syrjälä 3123373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 8) 31243a3b3c7dSVille Syrjälä bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 31256d3144ebSVille Syrjälä else 31263a3b3c7dSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 3127e4ce95aaSVille Syrjälä 31281a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3129e4ce95aaSVille Syrjälä 313091d14251STvrtko Ursulin ibx_hpd_irq_setup(dev_priv); 3131e4ce95aaSVille Syrjälä } 3132e4ce95aaSVille Syrjälä 3133dfefe7bcSVille Syrjälä static u32 bxt_hotplug_enables(struct intel_encoder *encoder) 31342ea63927SVille Syrjälä { 31352ea63927SVille Syrjälä u32 hotplug; 31362ea63927SVille Syrjälä 3137dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 31382ea63927SVille Syrjälä case HPD_PORT_A: 31392ea63927SVille Syrjälä hotplug = PORTA_HOTPLUG_ENABLE; 31409151c85cSVille Syrjälä if (intel_bios_encoder_hpd_invert(encoder->devdata)) 31412ea63927SVille Syrjälä hotplug |= BXT_DDIA_HPD_INVERT; 31422ea63927SVille Syrjälä return hotplug; 31432ea63927SVille Syrjälä case HPD_PORT_B: 31442ea63927SVille Syrjälä hotplug = PORTB_HOTPLUG_ENABLE; 31459151c85cSVille Syrjälä if (intel_bios_encoder_hpd_invert(encoder->devdata)) 31462ea63927SVille Syrjälä hotplug |= BXT_DDIB_HPD_INVERT; 31472ea63927SVille Syrjälä return hotplug; 31482ea63927SVille Syrjälä case HPD_PORT_C: 31492ea63927SVille Syrjälä hotplug = PORTC_HOTPLUG_ENABLE; 31509151c85cSVille Syrjälä if (intel_bios_encoder_hpd_invert(encoder->devdata)) 31512ea63927SVille Syrjälä hotplug |= BXT_DDIC_HPD_INVERT; 31522ea63927SVille Syrjälä return hotplug; 31532ea63927SVille Syrjälä default: 31542ea63927SVille Syrjälä return 0; 31552ea63927SVille Syrjälä } 31562ea63927SVille Syrjälä } 31572ea63927SVille Syrjälä 31582ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) 3159e0a20ad7SShashank Sharma { 31608cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 31618cee664dSAndrzej Hajda PORTA_HOTPLUG_ENABLE | 31622a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 31632ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 31648cee664dSAndrzej Hajda BXT_DDI_HPD_INVERT_MASK, 31658cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables)); 3166e0a20ad7SShashank Sharma } 3167e0a20ad7SShashank Sharma 31682a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) 31692a57d9ccSImre Deak { 31702a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 31712a57d9ccSImre Deak 31725a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31735a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31742a57d9ccSImre Deak 31752a57d9ccSImre Deak bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 31762a57d9ccSImre Deak 31772ea63927SVille Syrjälä bxt_hpd_detection_setup(dev_priv); 31782a57d9ccSImre Deak } 31792a57d9ccSImre Deak 3180a0a6d8cbSVille Syrjälä /* 3181a0a6d8cbSVille Syrjälä * SDEIER is also touched by the interrupt handler to work around missed PCH 3182a0a6d8cbSVille Syrjälä * interrupts. Hence we can't update it after the interrupt handler is enabled - 3183a0a6d8cbSVille Syrjälä * instead we unconditionally enable all PCH interrupt sources here, but then 3184a0a6d8cbSVille Syrjälä * only unmask them as needed with SDEIMR. 3185a0a6d8cbSVille Syrjälä * 3186a0a6d8cbSVille Syrjälä * Note that we currently do this after installing the interrupt handler, 3187a0a6d8cbSVille Syrjälä * but before we enable the master interrupt. That should be sufficient 3188a0a6d8cbSVille Syrjälä * to avoid races with the irq handler, assuming we have MSI. Shared legacy 3189a0a6d8cbSVille Syrjälä * interrupts could still race. 3190a0a6d8cbSVille Syrjälä */ 3191b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) 3192d46da437SPaulo Zanoni { 3193a0a6d8cbSVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 319482a28bcfSDaniel Vetter u32 mask; 3195d46da437SPaulo Zanoni 31966e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3197692a04cfSDaniel Vetter return; 3198692a04cfSDaniel Vetter 31996e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 32005c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 32014ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 32025c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 32034ebc6509SDhinakaran Pandiyan else 32044ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 32058664281bSPaulo Zanoni 3206a0a6d8cbSVille Syrjälä GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 3207d46da437SPaulo Zanoni } 3208d46da437SPaulo Zanoni 32099eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) 3210036a4a7dSZhenyu Wang { 3211b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 32128e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 32138e76f8dcSPaulo Zanoni 3214651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) >= 7) { 32158e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 3216842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 32178e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 321823bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 32192a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_C) | 32202a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_B) | 32212a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_A) | 322223bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 32238e76f8dcSPaulo Zanoni } else { 32248e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 3225842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 3226842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 3227c6073d4cSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | 3228e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 32294bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_A) | 32304bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_B) | 3231e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 32328e76f8dcSPaulo Zanoni } 3233036a4a7dSZhenyu Wang 3234fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3235b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 3236fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 3237fc340442SDaniel Vetter } 3238fc340442SDaniel Vetter 3239c6073d4cSVille Syrjälä if (IS_IRONLAKE_M(dev_priv)) 3240c6073d4cSVille Syrjälä extra_mask |= DE_PCU_EVENT; 3241c6073d4cSVille Syrjälä 32421ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 3243036a4a7dSZhenyu Wang 3244a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3245622364b6SPaulo Zanoni 32462cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 3247a9922912SVille Syrjälä 3248b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, 3249b16b2a2fSPaulo Zanoni display_mask | extra_mask); 3250036a4a7dSZhenyu Wang } 3251036a4a7dSZhenyu Wang 3252f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 3253f8b79e58SImre Deak { 325467520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3255f8b79e58SImre Deak 3256f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 3257f8b79e58SImre Deak return; 3258f8b79e58SImre Deak 3259f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 3260f8b79e58SImre Deak 3261d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 3262d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 3263ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3264f8b79e58SImre Deak } 3265d6c69803SVille Syrjälä } 3266f8b79e58SImre Deak 3267f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 3268f8b79e58SImre Deak { 326967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3270f8b79e58SImre Deak 3271f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 3272f8b79e58SImre Deak return; 3273f8b79e58SImre Deak 3274f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 3275f8b79e58SImre Deak 3276950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 3277ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 3278f8b79e58SImre Deak } 3279f8b79e58SImre Deak 32800e6c9a9eSVille Syrjälä 3281b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) 32820e6c9a9eSVille Syrjälä { 32832cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 32847e231dbeSJesse Barnes 3285ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 32869918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3287ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3288ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3289ad22d106SVille Syrjälä 32902939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 32912939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 329220afbda2SDaniel Vetter } 329320afbda2SDaniel Vetter 3294abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 3295abd58f01SBen Widawsky { 3296b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3297b16b2a2fSPaulo Zanoni 3298869129eeSMatt Roper u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) | 3299869129eeSMatt Roper GEN8_PIPE_CDCLK_CRC_DONE; 3300a9c287c9SJani Nikula u32 de_pipe_enables; 3301054318c7SImre Deak u32 de_port_masked = gen8_de_port_aux_mask(dev_priv); 33023a3b3c7dSVille Syrjälä u32 de_port_enables; 3303df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 3304562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 3305562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 33063a3b3c7dSVille Syrjälä enum pipe pipe; 3307770de83dSDamien Lespiau 3308a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3309a844cfbeSJosé Roberto de Souza return; 3310a844cfbeSJosé Roberto de Souza 3311373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) <= 10) 3312df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 3313df0d28c1SDhinakaran Pandiyan 331470bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 33153a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 3316a324fcacSRodrigo Vivi 3317373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 33189c9e97c4SVandita Kulkarni enum port port; 33199c9e97c4SVandita Kulkarni 33209c9e97c4SVandita Kulkarni if (intel_bios_is_dsi_present(dev_priv, &port)) 33219c9e97c4SVandita Kulkarni de_port_masked |= DSI0_TE | DSI1_TE; 33229c9e97c4SVandita Kulkarni } 33239c9e97c4SVandita Kulkarni 3324cda195f1SVille Syrjälä de_pipe_enables = de_pipe_masked | 33258bcc0840SMatt Roper GEN8_PIPE_VBLANK | 33268bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 3327cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 33281288f9b0SKarthik B S 33293a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 333070bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 3331a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 3332a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 3333e5abaab3SVille Syrjälä de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK; 33343a3b3c7dSVille Syrjälä 3335373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 33368241cfbeSJosé Roberto de Souza enum transcoder trans; 33378241cfbeSJosé Roberto de Souza 3338562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 33398241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 33408241cfbeSJosé Roberto de Souza 33418241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 33428241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 33438241cfbeSJosé Roberto de Souza continue; 33448241cfbeSJosé Roberto de Souza 33458241cfbeSJosé Roberto de Souza gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans)); 33468241cfbeSJosé Roberto de Souza } 33478241cfbeSJosé Roberto de Souza } else { 3348b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 33498241cfbeSJosé Roberto de Souza } 3350e04f7eceSVille Syrjälä 33510a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 33520a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 3353abd58f01SBen Widawsky 3354f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3355813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3356b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 3357813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 335835079899SPaulo Zanoni de_pipe_enables); 33590a195c02SMika Kahola } 3360abd58f01SBen Widawsky 3361b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 3362b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 33632a57d9ccSImre Deak 3364373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 3365121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 3366b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 3367b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 3368121e758eSDhinakaran Pandiyan 3369b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, 3370b16b2a2fSPaulo Zanoni de_hpd_enables); 3371abd58f01SBen Widawsky } 3372121e758eSDhinakaran Pandiyan } 3373abd58f01SBen Widawsky 337459b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv) 337559b7cb44STejas Upadhyay { 337659b7cb44STejas Upadhyay struct intel_uncore *uncore = &dev_priv->uncore; 337759b7cb44STejas Upadhyay u32 mask = SDE_GMBUS_ICP; 337859b7cb44STejas Upadhyay 337959b7cb44STejas Upadhyay GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 338059b7cb44STejas Upadhyay } 338159b7cb44STejas Upadhyay 3382b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) 3383abd58f01SBen Widawsky { 338459b7cb44STejas Upadhyay if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 338559b7cb44STejas Upadhyay icp_irq_postinstall(dev_priv); 338659b7cb44STejas Upadhyay else if (HAS_PCH_SPLIT(dev_priv)) 3387a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3388622364b6SPaulo Zanoni 33892cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 3390abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 3391abd58f01SBen Widawsky 339225286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 3393abd58f01SBen Widawsky } 3394abd58f01SBen Widawsky 3395a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) 3396a844cfbeSJosé Roberto de Souza { 3397a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3398a844cfbeSJosé Roberto de Souza return; 3399a844cfbeSJosé Roberto de Souza 3400a844cfbeSJosé Roberto de Souza gen8_de_irq_postinstall(dev_priv); 3401a844cfbeSJosé Roberto de Souza 3402a844cfbeSJosé Roberto de Souza intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 3403a844cfbeSJosé Roberto de Souza GEN11_DISPLAY_IRQ_ENABLE); 3404a844cfbeSJosé Roberto de Souza } 340531604222SAnusha Srivatsa 3406b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) 340751951ae7SMika Kuoppala { 34082cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3409fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 3410df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 341151951ae7SMika Kuoppala 341229b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 3413b318b824SVille Syrjälä icp_irq_postinstall(dev_priv); 341431604222SAnusha Srivatsa 3415fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 3416a844cfbeSJosé Roberto de Souza gen11_de_irq_postinstall(dev_priv); 341751951ae7SMika Kuoppala 3418b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 3419df0d28c1SDhinakaran Pandiyan 34209b77011eSTvrtko Ursulin gen11_master_intr_enable(uncore->regs); 34212939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ); 342251951ae7SMika Kuoppala } 342322e26af7SPaulo Zanoni 342422e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) 342522e26af7SPaulo Zanoni { 34262cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3427fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 342822e26af7SPaulo Zanoni u32 gu_misc_masked = GEN11_GU_MISC_GSE; 342922e26af7SPaulo Zanoni 3430fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 343122e26af7SPaulo Zanoni 343222e26af7SPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 343322e26af7SPaulo Zanoni 343422e26af7SPaulo Zanoni if (HAS_DISPLAY(dev_priv)) { 343522e26af7SPaulo Zanoni icp_irq_postinstall(dev_priv); 343622e26af7SPaulo Zanoni gen8_de_irq_postinstall(dev_priv); 343722e26af7SPaulo Zanoni intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 343822e26af7SPaulo Zanoni GEN11_DISPLAY_IRQ_ENABLE); 343922e26af7SPaulo Zanoni } 344022e26af7SPaulo Zanoni 3441fd4d7904SPaulo Zanoni dg1_master_intr_enable(uncore->regs); 3442fd4d7904SPaulo Zanoni intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR); 344397b492f5SLucas De Marchi } 344451951ae7SMika Kuoppala 3445b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) 344643f328d7SVille Syrjälä { 34472cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 344843f328d7SVille Syrjälä 3449ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 34509918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3451ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3452ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3453ad22d106SVille Syrjälä 34542939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 34552939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 345643f328d7SVille Syrjälä } 345743f328d7SVille Syrjälä 3458b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv) 3459c2798b19SChris Wilson { 3460b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3461c2798b19SChris Wilson 346244d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 346344d9241eSVille Syrjälä 3464ad7632ffSJani Nikula gen2_irq_reset(uncore); 3465e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3466c2798b19SChris Wilson } 3467c2798b19SChris Wilson 34683687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915) 34693687ce75SVille Syrjälä { 3470e7e12f6eSVille Syrjälä /* 3471e7e12f6eSVille Syrjälä * On gen2/3 FBC generates (seemingly spurious) 3472e7e12f6eSVille Syrjälä * display INVALID_GTT/INVALID_GTT_PTE table errors. 3473e7e12f6eSVille Syrjälä * 3474e7e12f6eSVille Syrjälä * Also gen3 bspec has this to say: 3475e7e12f6eSVille Syrjälä * "DISPA_INVALID_GTT_PTE 3476e7e12f6eSVille Syrjälä " [DevNapa] : Reserved. This bit does not reflect the page 3477e7e12f6eSVille Syrjälä " table error for the display plane A." 3478e7e12f6eSVille Syrjälä * 3479e7e12f6eSVille Syrjälä * Unfortunately we can't mask off individual PGTBL_ER bits, 3480e7e12f6eSVille Syrjälä * so we just have to mask off all page table errors via EMR. 3481e7e12f6eSVille Syrjälä */ 3482e7e12f6eSVille Syrjälä if (HAS_FBC(i915)) 3483e7e12f6eSVille Syrjälä return ~I915_ERROR_MEMORY_REFRESH; 3484e7e12f6eSVille Syrjälä else 34853687ce75SVille Syrjälä return ~(I915_ERROR_PAGE_TABLE | 34863687ce75SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 34873687ce75SVille Syrjälä } 34883687ce75SVille Syrjälä 3489b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) 3490c2798b19SChris Wilson { 3491b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3492e9e9848aSVille Syrjälä u16 enable_mask; 3493c2798b19SChris Wilson 34943687ce75SVille Syrjälä intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv)); 3495c2798b19SChris Wilson 3496c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 3497c2798b19SChris Wilson dev_priv->irq_mask = 3498c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 349916659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 350016659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3501c2798b19SChris Wilson 3502e9e9848aSVille Syrjälä enable_mask = 3503c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3504c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 350516659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3506e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 3507e9e9848aSVille Syrjälä 3508ad7632ffSJani Nikula gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask); 3509c2798b19SChris Wilson 3510379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3511379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3512d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3513755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3514755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3515d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3516c2798b19SChris Wilson } 3517c2798b19SChris Wilson 35184f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915, 351978c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 352078c357ddSVille Syrjälä { 35214f5fd91fSTvrtko Ursulin struct intel_uncore *uncore = &i915->uncore; 352278c357ddSVille Syrjälä u16 emr; 352378c357ddSVille Syrjälä 35244f5fd91fSTvrtko Ursulin *eir = intel_uncore_read16(uncore, EIR); 35254f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EIR, *eir); 352678c357ddSVille Syrjälä 35274f5fd91fSTvrtko Ursulin *eir_stuck = intel_uncore_read16(uncore, EIR); 352878c357ddSVille Syrjälä if (*eir_stuck == 0) 352978c357ddSVille Syrjälä return; 353078c357ddSVille Syrjälä 353178c357ddSVille Syrjälä /* 353278c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 353378c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 353478c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 353578c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 353678c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 353778c357ddSVille Syrjälä * cleared except by handling the underlying error 353878c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 353978c357ddSVille Syrjälä * remains set. 354078c357ddSVille Syrjälä */ 35414f5fd91fSTvrtko Ursulin emr = intel_uncore_read16(uncore, EMR); 35424f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, 0xffff); 35434f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, emr | *eir_stuck); 354478c357ddSVille Syrjälä } 354578c357ddSVille Syrjälä 354678c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 354778c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 354878c357ddSVille Syrjälä { 3549a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir); 355078c357ddSVille Syrjälä 355178c357ddSVille Syrjälä if (eir_stuck) 355200376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n", 355300376ccfSWambui Karuga eir_stuck); 3554d1e89592SVille Syrjälä 3555d1e89592SVille Syrjälä drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n", 3556d1e89592SVille Syrjälä intel_uncore_read(&dev_priv->uncore, PGTBL_ER)); 355778c357ddSVille Syrjälä } 355878c357ddSVille Syrjälä 355978c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 356078c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 356178c357ddSVille Syrjälä { 356278c357ddSVille Syrjälä u32 emr; 356378c357ddSVille Syrjälä 3564839259b8SVille Syrjälä *eir = intel_uncore_read(&dev_priv->uncore, EIR); 3565839259b8SVille Syrjälä intel_uncore_write(&dev_priv->uncore, EIR, *eir); 356678c357ddSVille Syrjälä 35672939eb06SJani Nikula *eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR); 356878c357ddSVille Syrjälä if (*eir_stuck == 0) 356978c357ddSVille Syrjälä return; 357078c357ddSVille Syrjälä 357178c357ddSVille Syrjälä /* 357278c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 357378c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 357478c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 357578c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 357678c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 357778c357ddSVille Syrjälä * cleared except by handling the underlying error 357878c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 357978c357ddSVille Syrjälä * remains set. 358078c357ddSVille Syrjälä */ 3581839259b8SVille Syrjälä emr = intel_uncore_read(&dev_priv->uncore, EMR); 3582839259b8SVille Syrjälä intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff); 35832939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck); 358478c357ddSVille Syrjälä } 358578c357ddSVille Syrjälä 358678c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 358778c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 358878c357ddSVille Syrjälä { 3589a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir); 359078c357ddSVille Syrjälä 359178c357ddSVille Syrjälä if (eir_stuck) 359200376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n", 359300376ccfSWambui Karuga eir_stuck); 3594d1e89592SVille Syrjälä 3595d1e89592SVille Syrjälä drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n", 3596d1e89592SVille Syrjälä intel_uncore_read(&dev_priv->uncore, PGTBL_ER)); 359778c357ddSVille Syrjälä } 359878c357ddSVille Syrjälä 3599ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 3600c2798b19SChris Wilson { 3601b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3602af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3603c2798b19SChris Wilson 36042dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 36052dd2a883SImre Deak return IRQ_NONE; 36062dd2a883SImre Deak 36071f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 36089102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 36091f814dacSImre Deak 3610af722d28SVille Syrjälä do { 3611af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 361278c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 3613af722d28SVille Syrjälä u16 iir; 3614af722d28SVille Syrjälä 36154f5fd91fSTvrtko Ursulin iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR); 3616c2798b19SChris Wilson if (iir == 0) 3617af722d28SVille Syrjälä break; 3618c2798b19SChris Wilson 3619af722d28SVille Syrjälä ret = IRQ_HANDLED; 3620c2798b19SChris Wilson 3621eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3622eb64343cSVille Syrjälä * signalled in iir */ 3623eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3624c2798b19SChris Wilson 362578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 362678c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 362778c357ddSVille Syrjälä 36284f5fd91fSTvrtko Ursulin intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); 3629c2798b19SChris Wilson 3630c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 36312cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 3632c2798b19SChris Wilson 363378c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 363478c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 3635af722d28SVille Syrjälä 3636eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3637af722d28SVille Syrjälä } while (0); 3638c2798b19SChris Wilson 36399c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 36409c6508b9SThomas Gleixner 36419102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 36421f814dacSImre Deak 36431f814dacSImre Deak return ret; 3644c2798b19SChris Wilson } 3645c2798b19SChris Wilson 3646b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv) 3647a266c7d5SChris Wilson { 3648b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3649a266c7d5SChris Wilson 365056b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 36510706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 36528cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0); 3653a266c7d5SChris Wilson } 3654a266c7d5SChris Wilson 365544d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 365644d9241eSVille Syrjälä 3657b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 3658e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3659a266c7d5SChris Wilson } 3660a266c7d5SChris Wilson 3661b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv) 3662a266c7d5SChris Wilson { 3663b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 366438bde180SChris Wilson u32 enable_mask; 3665a266c7d5SChris Wilson 36663687ce75SVille Syrjälä intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv)); 366738bde180SChris Wilson 366838bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 366938bde180SChris Wilson dev_priv->irq_mask = 367038bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 367138bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 367216659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 367316659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 367438bde180SChris Wilson 367538bde180SChris Wilson enable_mask = 367638bde180SChris Wilson I915_ASLE_INTERRUPT | 367738bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 367838bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 367916659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 368038bde180SChris Wilson I915_USER_INTERRUPT; 368138bde180SChris Wilson 368256b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 3683a266c7d5SChris Wilson /* Enable in IER... */ 3684a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 3685a266c7d5SChris Wilson /* and unmask in IMR */ 3686a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 3687a266c7d5SChris Wilson } 3688a266c7d5SChris Wilson 3689b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 3690a266c7d5SChris Wilson 3691379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3692379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3693d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3694755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3695755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3696d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3697379ef82dSDaniel Vetter 3698c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 369920afbda2SDaniel Vetter } 370020afbda2SDaniel Vetter 3701ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 3702a266c7d5SChris Wilson { 3703b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3704af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3705a266c7d5SChris Wilson 37062dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 37072dd2a883SImre Deak return IRQ_NONE; 37082dd2a883SImre Deak 37091f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 37109102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 37111f814dacSImre Deak 371238bde180SChris Wilson do { 3713eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 371478c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 3715af722d28SVille Syrjälä u32 hotplug_status = 0; 3716af722d28SVille Syrjälä u32 iir; 3717a266c7d5SChris Wilson 37182939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 3719af722d28SVille Syrjälä if (iir == 0) 3720af722d28SVille Syrjälä break; 3721af722d28SVille Syrjälä 3722af722d28SVille Syrjälä ret = IRQ_HANDLED; 3723af722d28SVille Syrjälä 3724af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 3725af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 3726af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 3727a266c7d5SChris Wilson 3728eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3729eb64343cSVille Syrjälä * signalled in iir */ 3730eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3731a266c7d5SChris Wilson 373278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 373378c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 373478c357ddSVille Syrjälä 37352939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 3736a266c7d5SChris Wilson 3737a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 37382cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 3739a266c7d5SChris Wilson 374078c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 374178c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 3742a266c7d5SChris Wilson 3743af722d28SVille Syrjälä if (hotplug_status) 3744af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 3745af722d28SVille Syrjälä 3746af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3747af722d28SVille Syrjälä } while (0); 3748a266c7d5SChris Wilson 37499c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 37509c6508b9SThomas Gleixner 37519102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 37521f814dacSImre Deak 3753a266c7d5SChris Wilson return ret; 3754a266c7d5SChris Wilson } 3755a266c7d5SChris Wilson 3756b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv) 3757a266c7d5SChris Wilson { 3758b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3759a266c7d5SChris Wilson 37600706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 37618cee664dSAndrzej Hajda intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); 3762a266c7d5SChris Wilson 376344d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 376444d9241eSVille Syrjälä 3765b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 3766e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3767a266c7d5SChris Wilson } 3768a266c7d5SChris Wilson 37693687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915) 3770a266c7d5SChris Wilson { 3771045cebd2SVille Syrjälä /* 3772045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 3773045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 3774e7e12f6eSVille Syrjälä * 3775e7e12f6eSVille Syrjälä * i965 FBC no longer generates spurious GTT errors, 3776e7e12f6eSVille Syrjälä * so we can always enable the page table errors. 3777045cebd2SVille Syrjälä */ 37783687ce75SVille Syrjälä if (IS_G4X(i915)) 37793687ce75SVille Syrjälä return ~(GM45_ERROR_PAGE_TABLE | 3780045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 3781045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 3782045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 37833687ce75SVille Syrjälä else 37843687ce75SVille Syrjälä return ~(I915_ERROR_PAGE_TABLE | 3785045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 3786045cebd2SVille Syrjälä } 37873687ce75SVille Syrjälä 37883687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv) 37893687ce75SVille Syrjälä { 37903687ce75SVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 37913687ce75SVille Syrjälä u32 enable_mask; 37923687ce75SVille Syrjälä 37933687ce75SVille Syrjälä intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv)); 3794045cebd2SVille Syrjälä 3795a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 3796c30bb1fdSVille Syrjälä dev_priv->irq_mask = 3797c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 3798adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 3799bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3800bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 380178c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3802bbba0a97SChris Wilson 3803c30bb1fdSVille Syrjälä enable_mask = 3804c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 3805c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 3806c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3807c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 380878c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3809c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 3810bbba0a97SChris Wilson 381191d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 3812bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 3813a266c7d5SChris Wilson 3814b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 3815c30bb1fdSVille Syrjälä 3816b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3817b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3818d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3819755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 3820755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3821755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3822d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3823a266c7d5SChris Wilson 382491d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 382520afbda2SDaniel Vetter } 382620afbda2SDaniel Vetter 382791d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) 382820afbda2SDaniel Vetter { 382920afbda2SDaniel Vetter u32 hotplug_en; 383020afbda2SDaniel Vetter 383167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3832b5ea2d56SDaniel Vetter 3833adca4730SChris Wilson /* Note HDMI and DP share hotplug bits */ 3834e5868a31SEgbert Eich /* enable bits are the same for all generations */ 383591d14251STvrtko Ursulin hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915); 3836a266c7d5SChris Wilson /* Programming the CRT detection parameters tends 3837a266c7d5SChris Wilson to generate a spurious hotplug event about three 3838a266c7d5SChris Wilson seconds later. So just do it once. 3839a266c7d5SChris Wilson */ 384091d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 3841a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; 3842a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; 3843a266c7d5SChris Wilson 3844a266c7d5SChris Wilson /* Ignore TV since it's buggy */ 38450706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, 3846f9e3dc78SJani Nikula HOTPLUG_INT_EN_MASK | 3847f9e3dc78SJani Nikula CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | 3848f9e3dc78SJani Nikula CRT_HOTPLUG_ACTIVATION_PERIOD_64, 38490706f17cSEgbert Eich hotplug_en); 3850a266c7d5SChris Wilson } 3851a266c7d5SChris Wilson 3852ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 3853a266c7d5SChris Wilson { 3854b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3855af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3856a266c7d5SChris Wilson 38572dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 38582dd2a883SImre Deak return IRQ_NONE; 38592dd2a883SImre Deak 38601f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 38619102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 38621f814dacSImre Deak 3863af722d28SVille Syrjälä do { 3864eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 386578c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 3866af722d28SVille Syrjälä u32 hotplug_status = 0; 3867af722d28SVille Syrjälä u32 iir; 38682c8ba29fSChris Wilson 38692939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 3870af722d28SVille Syrjälä if (iir == 0) 3871af722d28SVille Syrjälä break; 3872af722d28SVille Syrjälä 3873af722d28SVille Syrjälä ret = IRQ_HANDLED; 3874af722d28SVille Syrjälä 3875af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 3876af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 3877a266c7d5SChris Wilson 3878eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3879eb64343cSVille Syrjälä * signalled in iir */ 3880eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3881a266c7d5SChris Wilson 388278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 388378c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 388478c357ddSVille Syrjälä 38852939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 3886a266c7d5SChris Wilson 3887a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 38882cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], 38890669a6e1SChris Wilson iir); 3890af722d28SVille Syrjälä 3891a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 38922cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0], 38930669a6e1SChris Wilson iir >> 25); 3894a266c7d5SChris Wilson 389578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 389678c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 3897515ac2bbSDaniel Vetter 3898af722d28SVille Syrjälä if (hotplug_status) 3899af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 3900af722d28SVille Syrjälä 3901af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3902af722d28SVille Syrjälä } while (0); 3903a266c7d5SChris Wilson 39049c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 39059c6508b9SThomas Gleixner 39069102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 39071f814dacSImre Deak 3908a266c7d5SChris Wilson return ret; 3909a266c7d5SChris Wilson } 3910a266c7d5SChris Wilson 39117e97596cSJani Nikula struct intel_hotplug_funcs { 39127e97596cSJani Nikula void (*hpd_irq_setup)(struct drm_i915_private *i915); 39137e97596cSJani Nikula }; 39147e97596cSJani Nikula 3915cd030c7cSDave Airlie #define HPD_FUNCS(platform) \ 3916cd030c7cSDave Airlie static const struct intel_hotplug_funcs platform##_hpd_funcs = { \ 3917cd030c7cSDave Airlie .hpd_irq_setup = platform##_hpd_irq_setup, \ 3918cd030c7cSDave Airlie } 3919cd030c7cSDave Airlie 3920cd030c7cSDave Airlie HPD_FUNCS(i915); 3921cd030c7cSDave Airlie HPD_FUNCS(dg1); 3922cd030c7cSDave Airlie HPD_FUNCS(gen11); 3923cd030c7cSDave Airlie HPD_FUNCS(bxt); 3924cd030c7cSDave Airlie HPD_FUNCS(icp); 3925cd030c7cSDave Airlie HPD_FUNCS(spt); 3926cd030c7cSDave Airlie HPD_FUNCS(ilk); 3927cd030c7cSDave Airlie #undef HPD_FUNCS 3928cd030c7cSDave Airlie 39297e97596cSJani Nikula void intel_hpd_irq_setup(struct drm_i915_private *i915) 39307e97596cSJani Nikula { 39315a04eb5bSJani Nikula if (i915->display_irqs_enabled && i915->display.funcs.hotplug) 39325a04eb5bSJani Nikula i915->display.funcs.hotplug->hpd_irq_setup(i915); 39337e97596cSJani Nikula } 39347e97596cSJani Nikula 3935fca52a55SDaniel Vetter /** 3936fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 3937fca52a55SDaniel Vetter * @dev_priv: i915 device instance 3938fca52a55SDaniel Vetter * 3939fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 3940fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 3941fca52a55SDaniel Vetter */ 3942b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 3943f71d4af4SJesse Barnes { 3944cefcff8fSJoonas Lahtinen int i; 39458b2e326dSChris Wilson 394674bb98baSLucas De Marchi INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); 3947cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 3948cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 39498b2e326dSChris Wilson 3950633023a4SDaniele Ceraolo Spurio /* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */ 3951651e7d48SLucas De Marchi if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11) 39522cbc876dSMichał Winiarski to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16; 395326705e20SSagar Arun Kamble 39549a450b68SLucas De Marchi if (!HAS_DISPLAY(dev_priv)) 39559a450b68SLucas De Marchi return; 39569a450b68SLucas De Marchi 395796bd87b7SLucas De Marchi intel_hpd_init_pins(dev_priv); 395896bd87b7SLucas De Marchi 3959dd890d42SJani Nikula intel_hpd_init_early(dev_priv); 396096bd87b7SLucas De Marchi 39613703060dSAndrzej Hajda dev_priv->drm.vblank_disable_immediate = true; 396221da2700SVille Syrjälä 3963262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 3964262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 3965262fd485SChris Wilson * special care to avoid writing any of the display block registers 3966262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 3967262fd485SChris Wilson * in this case to the runtime pm. 3968262fd485SChris Wilson */ 3969262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 3970262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 3971262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 3972262fd485SChris Wilson 39732ccf2e03SChris Wilson if (HAS_GMCH(dev_priv)) { 39742ccf2e03SChris Wilson if (I915_HAS_HOTPLUG(dev_priv)) 39755a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &i915_hpd_funcs; 39762ccf2e03SChris Wilson } else { 39772f8a6699SMatt Roper if (HAS_PCH_DG2(dev_priv)) 39785a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &icp_hpd_funcs; 39792f8a6699SMatt Roper else if (HAS_PCH_DG1(dev_priv)) 39805a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &dg1_hpd_funcs; 3981373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 11) 39825a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &gen11_hpd_funcs; 398370bfb307SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 39845a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &bxt_hpd_funcs; 3985cec3295bSLyude Paul else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 39865a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &icp_hpd_funcs; 3987c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 39885a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &spt_hpd_funcs; 39896dbf30ceSVille Syrjälä else 39905a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &ilk_hpd_funcs; 3991f71d4af4SJesse Barnes } 39922ccf2e03SChris Wilson } 399320afbda2SDaniel Vetter 3994fca52a55SDaniel Vetter /** 3995cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 3996cefcff8fSJoonas Lahtinen * @i915: i915 device instance 3997cefcff8fSJoonas Lahtinen * 3998cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 3999cefcff8fSJoonas Lahtinen */ 4000cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 4001cefcff8fSJoonas Lahtinen { 4002cefcff8fSJoonas Lahtinen int i; 4003cefcff8fSJoonas Lahtinen 4004cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4005cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 4006cefcff8fSJoonas Lahtinen } 4007cefcff8fSJoonas Lahtinen 4008b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) 4009b318b824SVille Syrjälä { 4010b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4011b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4012b318b824SVille Syrjälä return cherryview_irq_handler; 4013b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4014b318b824SVille Syrjälä return valleyview_irq_handler; 4015651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4016b318b824SVille Syrjälä return i965_irq_handler; 4017651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4018b318b824SVille Syrjälä return i915_irq_handler; 4019b318b824SVille Syrjälä else 4020b318b824SVille Syrjälä return i8xx_irq_handler; 4021b318b824SVille Syrjälä } else { 402222e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 402397b492f5SLucas De Marchi return dg1_irq_handler; 402422e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4025b318b824SVille Syrjälä return gen11_irq_handler; 4026651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4027b318b824SVille Syrjälä return gen8_irq_handler; 4028b318b824SVille Syrjälä else 40299eae5e27SLucas De Marchi return ilk_irq_handler; 4030b318b824SVille Syrjälä } 4031b318b824SVille Syrjälä } 4032b318b824SVille Syrjälä 4033b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv) 4034b318b824SVille Syrjälä { 4035b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4036b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4037b318b824SVille Syrjälä cherryview_irq_reset(dev_priv); 4038b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4039b318b824SVille Syrjälä valleyview_irq_reset(dev_priv); 4040651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4041b318b824SVille Syrjälä i965_irq_reset(dev_priv); 4042651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4043b318b824SVille Syrjälä i915_irq_reset(dev_priv); 4044b318b824SVille Syrjälä else 4045b318b824SVille Syrjälä i8xx_irq_reset(dev_priv); 4046b318b824SVille Syrjälä } else { 404722e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 404822e26af7SPaulo Zanoni dg1_irq_reset(dev_priv); 404922e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4050b318b824SVille Syrjälä gen11_irq_reset(dev_priv); 4051651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4052b318b824SVille Syrjälä gen8_irq_reset(dev_priv); 4053b318b824SVille Syrjälä else 40549eae5e27SLucas De Marchi ilk_irq_reset(dev_priv); 4055b318b824SVille Syrjälä } 4056b318b824SVille Syrjälä } 4057b318b824SVille Syrjälä 4058b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv) 4059b318b824SVille Syrjälä { 4060b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4061b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4062b318b824SVille Syrjälä cherryview_irq_postinstall(dev_priv); 4063b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4064b318b824SVille Syrjälä valleyview_irq_postinstall(dev_priv); 4065651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4066b318b824SVille Syrjälä i965_irq_postinstall(dev_priv); 4067651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4068b318b824SVille Syrjälä i915_irq_postinstall(dev_priv); 4069b318b824SVille Syrjälä else 4070b318b824SVille Syrjälä i8xx_irq_postinstall(dev_priv); 4071b318b824SVille Syrjälä } else { 407222e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 407322e26af7SPaulo Zanoni dg1_irq_postinstall(dev_priv); 407422e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4075b318b824SVille Syrjälä gen11_irq_postinstall(dev_priv); 4076651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4077b318b824SVille Syrjälä gen8_irq_postinstall(dev_priv); 4078b318b824SVille Syrjälä else 40799eae5e27SLucas De Marchi ilk_irq_postinstall(dev_priv); 4080b318b824SVille Syrjälä } 4081b318b824SVille Syrjälä } 4082b318b824SVille Syrjälä 4083cefcff8fSJoonas Lahtinen /** 4084fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 4085fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4086fca52a55SDaniel Vetter * 4087fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 4088fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 4089fca52a55SDaniel Vetter * 4090fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 4091fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 4092fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 4093fca52a55SDaniel Vetter */ 40942aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 40952aeb7d3aSDaniel Vetter { 40968ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4097b318b824SVille Syrjälä int ret; 4098b318b824SVille Syrjälä 40992aeb7d3aSDaniel Vetter /* 41002aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 41012aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 41022aeb7d3aSDaniel Vetter * special cases in our ordering checks. 41032aeb7d3aSDaniel Vetter */ 4104ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 41052aeb7d3aSDaniel Vetter 4106ac1723c1SThomas Zimmermann dev_priv->irq_enabled = true; 4107b318b824SVille Syrjälä 4108b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4109b318b824SVille Syrjälä 4110b318b824SVille Syrjälä ret = request_irq(irq, intel_irq_handler(dev_priv), 4111b318b824SVille Syrjälä IRQF_SHARED, DRIVER_NAME, dev_priv); 4112b318b824SVille Syrjälä if (ret < 0) { 4113ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 4114b318b824SVille Syrjälä return ret; 4115b318b824SVille Syrjälä } 4116b318b824SVille Syrjälä 4117b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4118b318b824SVille Syrjälä 4119b318b824SVille Syrjälä return ret; 41202aeb7d3aSDaniel Vetter } 41212aeb7d3aSDaniel Vetter 4122fca52a55SDaniel Vetter /** 4123fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 4124fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4125fca52a55SDaniel Vetter * 4126fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 4127fca52a55SDaniel Vetter * resources acquired in the init functions. 4128fca52a55SDaniel Vetter */ 41292aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 41302aeb7d3aSDaniel Vetter { 41318ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4132b318b824SVille Syrjälä 4133b318b824SVille Syrjälä /* 4134789fa874SJanusz Krzysztofik * FIXME we can get called twice during driver probe 4135789fa874SJanusz Krzysztofik * error handling as well as during driver remove due to 4136789fa874SJanusz Krzysztofik * intel_modeset_driver_remove() calling us out of sequence. 4137789fa874SJanusz Krzysztofik * Would be nice if it didn't do that... 4138b318b824SVille Syrjälä */ 4139ac1723c1SThomas Zimmermann if (!dev_priv->irq_enabled) 4140b318b824SVille Syrjälä return; 4141b318b824SVille Syrjälä 4142ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 4143b318b824SVille Syrjälä 4144b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4145b318b824SVille Syrjälä 4146b318b824SVille Syrjälä free_irq(irq, dev_priv); 4147b318b824SVille Syrjälä 41482aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 4149ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 41502aeb7d3aSDaniel Vetter } 41512aeb7d3aSDaniel Vetter 4152fca52a55SDaniel Vetter /** 4153fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 4154fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4155fca52a55SDaniel Vetter * 4156fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 4157fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4158fca52a55SDaniel Vetter */ 4159b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 4160c67a470bSPaulo Zanoni { 4161b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4162ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 4163315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 4164c67a470bSPaulo Zanoni } 4165c67a470bSPaulo Zanoni 4166fca52a55SDaniel Vetter /** 4167fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 4168fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4169fca52a55SDaniel Vetter * 4170fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 4171fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4172fca52a55SDaniel Vetter */ 4173b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 4174c67a470bSPaulo Zanoni { 4175ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 4176b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4177b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4178c67a470bSPaulo Zanoni } 4179d64575eeSJani Nikula 4180d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv) 4181d64575eeSJani Nikula { 4182d64575eeSJani Nikula return dev_priv->runtime_pm.irqs_enabled; 4183d64575eeSJani Nikula } 4184d64575eeSJani Nikula 4185d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915) 4186d64575eeSJani Nikula { 41878ff5446aSThomas Zimmermann synchronize_irq(to_pci_dev(i915->drm.dev)->irq); 4188d64575eeSJani Nikula } 4189320ad343SThomas Zimmermann 4190320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915) 4191320ad343SThomas Zimmermann { 4192320ad343SThomas Zimmermann synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq); 4193320ad343SThomas Zimmermann } 4194