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" 4004500bfdSJani Nikula #include "display/intel_fdi_regs.h" 41df0566a6SJani Nikula #include "display/intel_fifo_underrun.h" 42df0566a6SJani Nikula #include "display/intel_hotplug.h" 43df0566a6SJani Nikula #include "display/intel_lpe_audio.h" 44df0566a6SJani Nikula #include "display/intel_psr.h" 45*7f6947fdSJani Nikula #include "display/intel_psr_regs.h" 46df0566a6SJani Nikula 47b3786b29SChris Wilson #include "gt/intel_breadcrumbs.h" 482239e6dfSDaniele Ceraolo Spurio #include "gt/intel_gt.h" 49cf1c97dcSAndi Shyti #include "gt/intel_gt_irq.h" 50d762043fSAndi Shyti #include "gt/intel_gt_pm_irq.h" 510d6419e9SMatt Roper #include "gt/intel_gt_regs.h" 523e7abf81SAndi Shyti #include "gt/intel_rps.h" 532239e6dfSDaniele Ceraolo Spurio 5424524e3fSJani Nikula #include "i915_driver.h" 55c0e09200SDave Airlie #include "i915_drv.h" 56440e2b3dSJani Nikula #include "i915_irq.h" 57c0e09200SDave Airlie 58fca52a55SDaniel Vetter /** 59fca52a55SDaniel Vetter * DOC: interrupt handling 60fca52a55SDaniel Vetter * 61fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 62fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 63fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 64fca52a55SDaniel Vetter */ 65fca52a55SDaniel Vetter 669c6508b9SThomas Gleixner /* 679c6508b9SThomas Gleixner * Interrupt statistic for PMU. Increments the counter only if the 6878f48aa6SBo Liu * interrupt originated from the GPU so interrupts from a device which 699c6508b9SThomas Gleixner * shares the interrupt line are not accounted. 709c6508b9SThomas Gleixner */ 719c6508b9SThomas Gleixner static inline void pmu_irq_stats(struct drm_i915_private *i915, 729c6508b9SThomas Gleixner irqreturn_t res) 739c6508b9SThomas Gleixner { 749c6508b9SThomas Gleixner if (unlikely(res != IRQ_HANDLED)) 759c6508b9SThomas Gleixner return; 769c6508b9SThomas Gleixner 779c6508b9SThomas Gleixner /* 789c6508b9SThomas Gleixner * A clever compiler translates that into INC. A not so clever one 799c6508b9SThomas Gleixner * should at least prevent store tearing. 809c6508b9SThomas Gleixner */ 819c6508b9SThomas Gleixner WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1); 829c6508b9SThomas Gleixner } 839c6508b9SThomas Gleixner 8448ef15d3SJosé Roberto de Souza typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val); 85dfefe7bcSVille Syrjälä typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder); 8648ef15d3SJosé Roberto de Souza 87e4ce95aaSVille Syrjälä static const u32 hpd_ilk[HPD_NUM_PINS] = { 88e4ce95aaSVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG, 89e4ce95aaSVille Syrjälä }; 90e4ce95aaSVille Syrjälä 9123bb4cb5SVille Syrjälä static const u32 hpd_ivb[HPD_NUM_PINS] = { 9223bb4cb5SVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, 9323bb4cb5SVille Syrjälä }; 9423bb4cb5SVille Syrjälä 953a3b3c7dSVille Syrjälä static const u32 hpd_bdw[HPD_NUM_PINS] = { 96e5abaab3SVille Syrjälä [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), 973a3b3c7dSVille Syrjälä }; 983a3b3c7dSVille Syrjälä 997c7e10dbSVille Syrjälä static const u32 hpd_ibx[HPD_NUM_PINS] = { 100e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG, 101e5868a31SEgbert Eich [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, 102e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG, 103e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG, 1047203d49cSVille Syrjälä [HPD_PORT_D] = SDE_PORTD_HOTPLUG, 105e5868a31SEgbert Eich }; 106e5868a31SEgbert Eich 1077c7e10dbSVille Syrjälä static const u32 hpd_cpt[HPD_NUM_PINS] = { 108e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, 10973c352a2SDaniel Vetter [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, 110e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 111e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 1127203d49cSVille Syrjälä [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 113e5868a31SEgbert Eich }; 114e5868a31SEgbert Eich 11526951cafSXiong Zhang static const u32 hpd_spt[HPD_NUM_PINS] = { 11674c0b395SVille Syrjälä [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, 11726951cafSXiong Zhang [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 11826951cafSXiong Zhang [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 11926951cafSXiong Zhang [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 1207203d49cSVille Syrjälä [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT, 12126951cafSXiong Zhang }; 12226951cafSXiong Zhang 1237c7e10dbSVille Syrjälä static const u32 hpd_mask_i915[HPD_NUM_PINS] = { 124e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_EN, 125e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, 126e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, 127e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN, 128e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN, 1297203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN, 130e5868a31SEgbert Eich }; 131e5868a31SEgbert Eich 1327c7e10dbSVille Syrjälä static const u32 hpd_status_g4x[HPD_NUM_PINS] = { 133e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 134e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, 135e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, 136e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 137e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 1387203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, 139e5868a31SEgbert Eich }; 140e5868a31SEgbert Eich 1414bca26d0SVille Syrjälä static const u32 hpd_status_i915[HPD_NUM_PINS] = { 142e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 143e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, 144e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, 145e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 146e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 1477203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, 148e5868a31SEgbert Eich }; 149e5868a31SEgbert Eich 150e0a20ad7SShashank Sharma static const u32 hpd_bxt[HPD_NUM_PINS] = { 151e5abaab3SVille Syrjälä [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), 152e5abaab3SVille Syrjälä [HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B), 153e5abaab3SVille Syrjälä [HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C), 154e0a20ad7SShashank Sharma }; 155e0a20ad7SShashank Sharma 156b796b971SDhinakaran Pandiyan static const u32 hpd_gen11[HPD_NUM_PINS] = { 1575b76e860SVille Syrjälä [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1), 1585b76e860SVille Syrjälä [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2), 1595b76e860SVille Syrjälä [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3), 1605b76e860SVille Syrjälä [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4), 1615b76e860SVille Syrjälä [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5), 1625b76e860SVille Syrjälä [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6), 16348ef15d3SJosé Roberto de Souza }; 16448ef15d3SJosé Roberto de Souza 16531604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = { 1665f371a81SVille Syrjälä [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), 1675f371a81SVille Syrjälä [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), 1685f371a81SVille Syrjälä [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), 16997011359SVille Syrjälä [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1), 17097011359SVille Syrjälä [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2), 17197011359SVille Syrjälä [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3), 17297011359SVille Syrjälä [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4), 17397011359SVille Syrjälä [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5), 17497011359SVille Syrjälä [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6), 17552dfdba0SLucas De Marchi }; 17652dfdba0SLucas De Marchi 177229f31e2SLucas De Marchi static const u32 hpd_sde_dg1[HPD_NUM_PINS] = { 1785f371a81SVille Syrjälä [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), 1795f371a81SVille Syrjälä [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), 1805f371a81SVille Syrjälä [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), 1815f371a81SVille Syrjälä [HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D), 1822f8a6699SMatt Roper [HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1), 183229f31e2SLucas De Marchi }; 184229f31e2SLucas De Marchi 1850398993bSVille Syrjälä static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) 1860398993bSVille Syrjälä { 1875a4dd6f0SJani Nikula struct intel_hotplug *hpd = &dev_priv->display.hotplug; 1880398993bSVille Syrjälä 1890398993bSVille Syrjälä if (HAS_GMCH(dev_priv)) { 1900398993bSVille Syrjälä if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || 1910398993bSVille Syrjälä IS_CHERRYVIEW(dev_priv)) 1920398993bSVille Syrjälä hpd->hpd = hpd_status_g4x; 1930398993bSVille Syrjälä else 1940398993bSVille Syrjälä hpd->hpd = hpd_status_i915; 1950398993bSVille Syrjälä return; 1960398993bSVille Syrjälä } 1970398993bSVille Syrjälä 198373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) 1990398993bSVille Syrjälä hpd->hpd = hpd_gen11; 20070bfb307SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 2010398993bSVille Syrjälä hpd->hpd = hpd_bxt; 202dded35acSVille Syrjälä else if (DISPLAY_VER(dev_priv) == 9) 203dded35acSVille Syrjälä hpd->hpd = NULL; /* no north HPD on SKL */ 204373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 8) 2050398993bSVille Syrjälä hpd->hpd = hpd_bdw; 206373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 7) 2070398993bSVille Syrjälä hpd->hpd = hpd_ivb; 2080398993bSVille Syrjälä else 2090398993bSVille Syrjälä hpd->hpd = hpd_ilk; 2100398993bSVille Syrjälä 211229f31e2SLucas De Marchi if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) && 212229f31e2SLucas De Marchi (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv))) 2130398993bSVille Syrjälä return; 2140398993bSVille Syrjälä 2153176fb66SMatt Roper if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) 216229f31e2SLucas De Marchi hpd->pch_hpd = hpd_sde_dg1; 217fa58c9e4SAnusha Srivatsa else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2180398993bSVille Syrjälä hpd->pch_hpd = hpd_icp; 2190398993bSVille Syrjälä else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv)) 2200398993bSVille Syrjälä hpd->pch_hpd = hpd_spt; 2210398993bSVille Syrjälä else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv)) 2220398993bSVille Syrjälä hpd->pch_hpd = hpd_cpt; 2230398993bSVille Syrjälä else if (HAS_PCH_IBX(dev_priv)) 2240398993bSVille Syrjälä hpd->pch_hpd = hpd_ibx; 2250398993bSVille Syrjälä else 2260398993bSVille Syrjälä MISSING_CASE(INTEL_PCH_TYPE(dev_priv)); 2270398993bSVille Syrjälä } 2280398993bSVille Syrjälä 229aca9310aSAnshuman Gupta static void 230aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) 231aca9310aSAnshuman Gupta { 2327794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 233aca9310aSAnshuman Gupta 234aca9310aSAnshuman Gupta drm_crtc_handle_vblank(&crtc->base); 235aca9310aSAnshuman Gupta } 236aca9310aSAnshuman Gupta 237cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, 23868eb49b1SPaulo Zanoni i915_reg_t iir, i915_reg_t ier) 23968eb49b1SPaulo Zanoni { 24065f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, 0xffffffff); 24165f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 24268eb49b1SPaulo Zanoni 24365f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, 0); 24468eb49b1SPaulo Zanoni 2455c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 24665f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24765f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 24865f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24965f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 25068eb49b1SPaulo Zanoni } 2515c502442SPaulo Zanoni 252ad7632ffSJani Nikula static void gen2_irq_reset(struct intel_uncore *uncore) 25368eb49b1SPaulo Zanoni { 25465f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, 0xffff); 25565f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 256a9d356a6SPaulo Zanoni 25765f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, 0); 25868eb49b1SPaulo Zanoni 25968eb49b1SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 26065f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 26165f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 26265f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 26365f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 26468eb49b1SPaulo Zanoni } 26568eb49b1SPaulo Zanoni 266337ba017SPaulo Zanoni /* 267337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 268337ba017SPaulo Zanoni */ 26965f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) 270b51a2842SVille Syrjälä { 27165f42cdcSPaulo Zanoni u32 val = intel_uncore_read(uncore, reg); 272b51a2842SVille Syrjälä 273b51a2842SVille Syrjälä if (val == 0) 274b51a2842SVille Syrjälä return; 275b51a2842SVille Syrjälä 276a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 277a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 278f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 27965f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 28065f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 28165f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 28265f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 283b51a2842SVille Syrjälä } 284337ba017SPaulo Zanoni 28565f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore) 286e9e9848aSVille Syrjälä { 28765f42cdcSPaulo Zanoni u16 val = intel_uncore_read16(uncore, GEN2_IIR); 288e9e9848aSVille Syrjälä 289e9e9848aSVille Syrjälä if (val == 0) 290e9e9848aSVille Syrjälä return; 291e9e9848aSVille Syrjälä 292a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 293a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 2949d9523d8SPaulo Zanoni i915_mmio_reg_offset(GEN2_IIR), val); 29565f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29665f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 29765f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29865f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 299e9e9848aSVille Syrjälä } 300e9e9848aSVille Syrjälä 301cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore, 30268eb49b1SPaulo Zanoni i915_reg_t imr, u32 imr_val, 30368eb49b1SPaulo Zanoni i915_reg_t ier, u32 ier_val, 30468eb49b1SPaulo Zanoni i915_reg_t iir) 30568eb49b1SPaulo Zanoni { 30665f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(uncore, iir); 30735079899SPaulo Zanoni 30865f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, ier_val); 30965f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, imr_val); 31065f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 31168eb49b1SPaulo Zanoni } 31235079899SPaulo Zanoni 313ad7632ffSJani Nikula static void gen2_irq_init(struct intel_uncore *uncore, 3142918c3caSPaulo Zanoni u32 imr_val, u32 ier_val) 31568eb49b1SPaulo Zanoni { 31665f42cdcSPaulo Zanoni gen2_assert_iir_is_zero(uncore); 31768eb49b1SPaulo Zanoni 31865f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, ier_val); 31965f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, imr_val); 32065f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 32168eb49b1SPaulo Zanoni } 32268eb49b1SPaulo Zanoni 3230706f17cSEgbert Eich /* For display hotplug interrupt */ 3240706f17cSEgbert Eich static inline void 3250706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, 326a9c287c9SJani Nikula u32 mask, 327a9c287c9SJani Nikula u32 bits) 3280706f17cSEgbert Eich { 32967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 33048a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, bits & ~mask); 3310706f17cSEgbert Eich 3328cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits); 3330706f17cSEgbert Eich } 3340706f17cSEgbert Eich 3350706f17cSEgbert Eich /** 3360706f17cSEgbert Eich * i915_hotplug_interrupt_update - update hotplug interrupt enable 3370706f17cSEgbert Eich * @dev_priv: driver private 3380706f17cSEgbert Eich * @mask: bits to update 3390706f17cSEgbert Eich * @bits: bits to enable 3400706f17cSEgbert Eich * NOTE: the HPD enable bits are modified both inside and outside 3410706f17cSEgbert Eich * of an interrupt context. To avoid that read-modify-write cycles 3420706f17cSEgbert Eich * interfer, these bits are protected by a spinlock. Since this 3430706f17cSEgbert Eich * function is usually not called from a context where the lock is 3440706f17cSEgbert Eich * held already, this function acquires the lock itself. A non-locking 3450706f17cSEgbert Eich * version is also available. 3460706f17cSEgbert Eich */ 3470706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, 348a9c287c9SJani Nikula u32 mask, 349a9c287c9SJani Nikula u32 bits) 3500706f17cSEgbert Eich { 3510706f17cSEgbert Eich spin_lock_irq(&dev_priv->irq_lock); 3520706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); 3530706f17cSEgbert Eich spin_unlock_irq(&dev_priv->irq_lock); 3540706f17cSEgbert Eich } 3550706f17cSEgbert Eich 356d9dc34f1SVille Syrjälä /** 357d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 358d9dc34f1SVille Syrjälä * @dev_priv: driver private 359d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 360d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 361d9dc34f1SVille Syrjälä */ 3629e6dcf33SJani Nikula static void ilk_update_display_irq(struct drm_i915_private *dev_priv, 3639e6dcf33SJani Nikula u32 interrupt_mask, u32 enabled_irq_mask) 364036a4a7dSZhenyu Wang { 365a9c287c9SJani Nikula u32 new_val; 366d9dc34f1SVille Syrjälä 36767520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 36848a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 369d9dc34f1SVille Syrjälä 370d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 371d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 372d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 373d9dc34f1SVille Syrjälä 374e44adb5dSChris Wilson if (new_val != dev_priv->irq_mask && 375e44adb5dSChris Wilson !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { 376d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 3772939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask); 3782939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, DEIMR); 379036a4a7dSZhenyu Wang } 380036a4a7dSZhenyu Wang } 381036a4a7dSZhenyu Wang 3829e6dcf33SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits) 3839e6dcf33SJani Nikula { 3849e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, bits); 3859e6dcf33SJani Nikula } 3869e6dcf33SJani Nikula 3879e6dcf33SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits) 3889e6dcf33SJani Nikula { 3899e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, 0); 3909e6dcf33SJani Nikula } 3919e6dcf33SJani Nikula 3920961021aSBen Widawsky /** 3933a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 3943a3b3c7dSVille Syrjälä * @dev_priv: driver private 3953a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 3963a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 3973a3b3c7dSVille Syrjälä */ 3983a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv, 399a9c287c9SJani Nikula u32 interrupt_mask, 400a9c287c9SJani Nikula u32 enabled_irq_mask) 4013a3b3c7dSVille Syrjälä { 402a9c287c9SJani Nikula u32 new_val; 403a9c287c9SJani Nikula u32 old_val; 4043a3b3c7dSVille Syrjälä 40567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4063a3b3c7dSVille Syrjälä 40748a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 4083a3b3c7dSVille Syrjälä 40948a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 4103a3b3c7dSVille Syrjälä return; 4113a3b3c7dSVille Syrjälä 4122939eb06SJani Nikula old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4133a3b3c7dSVille Syrjälä 4143a3b3c7dSVille Syrjälä new_val = old_val; 4153a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 4163a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 4173a3b3c7dSVille Syrjälä 4183a3b3c7dSVille Syrjälä if (new_val != old_val) { 4192939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val); 4202939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4213a3b3c7dSVille Syrjälä } 4223a3b3c7dSVille Syrjälä } 4233a3b3c7dSVille Syrjälä 4243a3b3c7dSVille Syrjälä /** 425013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 426013d3752SVille Syrjälä * @dev_priv: driver private 427013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 428013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 429013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 430013d3752SVille Syrjälä */ 4319e6dcf33SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 4329e6dcf33SJani Nikula enum pipe pipe, u32 interrupt_mask, 433a9c287c9SJani Nikula u32 enabled_irq_mask) 434013d3752SVille Syrjälä { 435a9c287c9SJani Nikula u32 new_val; 436013d3752SVille Syrjälä 43767520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 438013d3752SVille Syrjälä 43948a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 440013d3752SVille Syrjälä 44148a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 442013d3752SVille Syrjälä return; 443013d3752SVille Syrjälä 444013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 445013d3752SVille Syrjälä new_val &= ~interrupt_mask; 446013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 447013d3752SVille Syrjälä 448013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 449013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 4502939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 4512939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); 452013d3752SVille Syrjälä } 453013d3752SVille Syrjälä } 454013d3752SVille Syrjälä 4559e6dcf33SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915, 4569e6dcf33SJani Nikula enum pipe pipe, u32 bits) 4579e6dcf33SJani Nikula { 4589e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, bits); 4599e6dcf33SJani Nikula } 4609e6dcf33SJani Nikula 4619e6dcf33SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915, 4629e6dcf33SJani Nikula enum pipe pipe, u32 bits) 4639e6dcf33SJani Nikula { 4649e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, 0); 4659e6dcf33SJani Nikula } 4669e6dcf33SJani Nikula 467013d3752SVille Syrjälä /** 468fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 469fee884edSDaniel Vetter * @dev_priv: driver private 470fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 471fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 472fee884edSDaniel Vetter */ 4739e6dcf33SJani Nikula static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 474a9c287c9SJani Nikula u32 interrupt_mask, 475a9c287c9SJani Nikula u32 enabled_irq_mask) 476fee884edSDaniel Vetter { 4772939eb06SJani Nikula u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR); 478fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 479fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 480fee884edSDaniel Vetter 48148a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 48215a17aaeSDaniel Vetter 48367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 484fee884edSDaniel Vetter 48548a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 486c67a470bSPaulo Zanoni return; 487c67a470bSPaulo Zanoni 4882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr); 4892939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, SDEIMR); 490fee884edSDaniel Vetter } 4918664281bSPaulo Zanoni 4929e6dcf33SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits) 4939e6dcf33SJani Nikula { 4949e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, bits); 4959e6dcf33SJani Nikula } 4969e6dcf33SJani Nikula 4979e6dcf33SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits) 4989e6dcf33SJani Nikula { 4999e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, 0); 5009e6dcf33SJani Nikula } 5019e6dcf33SJani Nikula 5026b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 5036b12ca56SVille Syrjälä enum pipe pipe) 5047c463586SKeith Packard { 5056b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 50610c59c51SImre Deak u32 enable_mask = status_mask << 16; 50710c59c51SImre Deak 5086b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 5096b12ca56SVille Syrjälä 510373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 5) 5116b12ca56SVille Syrjälä goto out; 5126b12ca56SVille Syrjälä 51310c59c51SImre Deak /* 514724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 515724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 51610c59c51SImre Deak */ 51748a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 51848a1b8d4SPankaj Bharadiya status_mask & PIPE_A_PSR_STATUS_VLV)) 51910c59c51SImre Deak return 0; 520724a6905SVille Syrjälä /* 521724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 522724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 523724a6905SVille Syrjälä */ 52448a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 52548a1b8d4SPankaj Bharadiya status_mask & PIPE_B_PSR_STATUS_VLV)) 526724a6905SVille Syrjälä return 0; 52710c59c51SImre Deak 52810c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 52910c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 53010c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 53110c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 53210c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 53310c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 53410c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 53510c59c51SImre Deak 5366b12ca56SVille Syrjälä out: 53748a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 53848a1b8d4SPankaj Bharadiya enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 5396b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 5406b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 5416b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 5426b12ca56SVille Syrjälä 54310c59c51SImre Deak return enable_mask; 54410c59c51SImre Deak } 54510c59c51SImre Deak 5466b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 5476b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 548755e9019SImre Deak { 5496b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 550755e9019SImre Deak u32 enable_mask; 551755e9019SImre Deak 55248a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5536b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5546b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5556b12ca56SVille Syrjälä 5566b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 55748a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5586b12ca56SVille Syrjälä 5596b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 5606b12ca56SVille Syrjälä return; 5616b12ca56SVille Syrjälä 5626b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 5636b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5646b12ca56SVille Syrjälä 5652939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5662939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 567755e9019SImre Deak } 568755e9019SImre Deak 5696b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 5706b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 571755e9019SImre Deak { 5726b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 573755e9019SImre Deak u32 enable_mask; 574755e9019SImre Deak 57548a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5766b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5776b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5786b12ca56SVille Syrjälä 5796b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 58048a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5816b12ca56SVille Syrjälä 5826b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 5836b12ca56SVille Syrjälä return; 5846b12ca56SVille Syrjälä 5856b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 5866b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5876b12ca56SVille Syrjälä 5882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5892939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 590755e9019SImre Deak } 591755e9019SImre Deak 592f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 593f3e30485SVille Syrjälä { 5947249dfcbSJani Nikula if (!dev_priv->display.opregion.asle) 595f3e30485SVille Syrjälä return false; 596f3e30485SVille Syrjälä 597f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 598f3e30485SVille Syrjälä } 599f3e30485SVille Syrjälä 600c0e09200SDave Airlie /** 601f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 60214bb2c11STvrtko Ursulin * @dev_priv: i915 device private 60301c66889SZhao Yakui */ 60491d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 60501c66889SZhao Yakui { 606f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 607f49e38ddSJani Nikula return; 608f49e38ddSJani Nikula 60913321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 61001c66889SZhao Yakui 611755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 612373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 4) 6133b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 614755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 6151ec14ad3SChris Wilson 61613321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 61701c66889SZhao Yakui } 61801c66889SZhao Yakui 619e3689190SBen Widawsky /** 62074bb98baSLucas De Marchi * ivb_parity_work - Workqueue called when a parity error interrupt 621e3689190SBen Widawsky * occurred. 622e3689190SBen Widawsky * @work: workqueue struct 623e3689190SBen Widawsky * 624e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 625e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 626e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 627e3689190SBen Widawsky */ 62874bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work) 629e3689190SBen Widawsky { 6302d1013ddSJani Nikula struct drm_i915_private *dev_priv = 631cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 6322cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 633e3689190SBen Widawsky u32 error_status, row, bank, subbank; 63435a85ac6SBen Widawsky char *parity_event[6]; 635a9c287c9SJani Nikula u32 misccpctl; 636a9c287c9SJani Nikula u8 slice = 0; 637e3689190SBen Widawsky 638e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 639e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 640e3689190SBen Widawsky * any time we access those registers. 641e3689190SBen Widawsky */ 64291c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 643e3689190SBen Widawsky 64435a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 64548a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice)) 64635a85ac6SBen Widawsky goto out; 64735a85ac6SBen Widawsky 648f7435467SAndrzej Hajda misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL, 649f7435467SAndrzej Hajda GEN7_DOP_CLOCK_GATE_ENABLE, 0); 6502939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL); 651e3689190SBen Widawsky 65235a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 653f0f59a00SVille Syrjälä i915_reg_t reg; 65435a85ac6SBen Widawsky 65535a85ac6SBen Widawsky slice--; 65648a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 65748a1b8d4SPankaj Bharadiya slice >= NUM_L3_SLICES(dev_priv))) 65835a85ac6SBen Widawsky break; 65935a85ac6SBen Widawsky 66035a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 66135a85ac6SBen Widawsky 6626fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 66335a85ac6SBen Widawsky 6642939eb06SJani Nikula error_status = intel_uncore_read(&dev_priv->uncore, reg); 665e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 666e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 667e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 668e3689190SBen Widawsky 6692939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 6702939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 671e3689190SBen Widawsky 672cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 673e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 674e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 675e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 67635a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 67735a85ac6SBen Widawsky parity_event[5] = NULL; 678e3689190SBen Widawsky 67991c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 680e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 681e3689190SBen Widawsky 682a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, 683a10234fdSTvrtko Ursulin "Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 68435a85ac6SBen Widawsky slice, row, bank, subbank); 685e3689190SBen Widawsky 68635a85ac6SBen Widawsky kfree(parity_event[4]); 687e3689190SBen Widawsky kfree(parity_event[3]); 688e3689190SBen Widawsky kfree(parity_event[2]); 689e3689190SBen Widawsky kfree(parity_event[1]); 690e3689190SBen Widawsky } 691e3689190SBen Widawsky 6922939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl); 69335a85ac6SBen Widawsky 69435a85ac6SBen Widawsky out: 69548a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice); 69603d2c54dSMatt Roper spin_lock_irq(gt->irq_lock); 697cf1c97dcSAndi Shyti gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv)); 69803d2c54dSMatt Roper spin_unlock_irq(gt->irq_lock); 69935a85ac6SBen Widawsky 70091c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 70135a85ac6SBen Widawsky } 70235a85ac6SBen Widawsky 703af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 704121e758eSDhinakaran Pandiyan { 705af92058fSVille Syrjälä switch (pin) { 706da51e4baSVille Syrjälä case HPD_PORT_TC1: 707da51e4baSVille Syrjälä case HPD_PORT_TC2: 708da51e4baSVille Syrjälä case HPD_PORT_TC3: 709da51e4baSVille Syrjälä case HPD_PORT_TC4: 710da51e4baSVille Syrjälä case HPD_PORT_TC5: 711da51e4baSVille Syrjälä case HPD_PORT_TC6: 7124294fa5fSVille Syrjälä return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin); 71348ef15d3SJosé Roberto de Souza default: 71448ef15d3SJosé Roberto de Souza return false; 71548ef15d3SJosé Roberto de Souza } 71648ef15d3SJosé Roberto de Souza } 71748ef15d3SJosé Roberto de Souza 718af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 71963c88d22SImre Deak { 720af92058fSVille Syrjälä switch (pin) { 721af92058fSVille Syrjälä case HPD_PORT_A: 722195baa06SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 723af92058fSVille Syrjälä case HPD_PORT_B: 72463c88d22SImre Deak return val & PORTB_HOTPLUG_LONG_DETECT; 725af92058fSVille Syrjälä case HPD_PORT_C: 72663c88d22SImre Deak return val & PORTC_HOTPLUG_LONG_DETECT; 72763c88d22SImre Deak default: 72863c88d22SImre Deak return false; 72963c88d22SImre Deak } 73063c88d22SImre Deak } 73163c88d22SImre Deak 732af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 73331604222SAnusha Srivatsa { 734af92058fSVille Syrjälä switch (pin) { 735af92058fSVille Syrjälä case HPD_PORT_A: 736af92058fSVille Syrjälä case HPD_PORT_B: 7378ef7e340SMatt Roper case HPD_PORT_C: 738229f31e2SLucas De Marchi case HPD_PORT_D: 7394294fa5fSVille Syrjälä return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin); 74031604222SAnusha Srivatsa default: 74131604222SAnusha Srivatsa return false; 74231604222SAnusha Srivatsa } 74331604222SAnusha Srivatsa } 74431604222SAnusha Srivatsa 745af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 74631604222SAnusha Srivatsa { 747af92058fSVille Syrjälä switch (pin) { 748da51e4baSVille Syrjälä case HPD_PORT_TC1: 749da51e4baSVille Syrjälä case HPD_PORT_TC2: 750da51e4baSVille Syrjälä case HPD_PORT_TC3: 751da51e4baSVille Syrjälä case HPD_PORT_TC4: 752da51e4baSVille Syrjälä case HPD_PORT_TC5: 753da51e4baSVille Syrjälä case HPD_PORT_TC6: 7544294fa5fSVille Syrjälä return val & ICP_TC_HPD_LONG_DETECT(pin); 75552dfdba0SLucas De Marchi default: 75652dfdba0SLucas De Marchi return false; 75752dfdba0SLucas De Marchi } 75852dfdba0SLucas De Marchi } 75952dfdba0SLucas De Marchi 760af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) 7616dbf30ceSVille Syrjälä { 762af92058fSVille Syrjälä switch (pin) { 763af92058fSVille Syrjälä case HPD_PORT_E: 7646dbf30ceSVille Syrjälä return val & PORTE_HOTPLUG_LONG_DETECT; 7656dbf30ceSVille Syrjälä default: 7666dbf30ceSVille Syrjälä return false; 7676dbf30ceSVille Syrjälä } 7686dbf30ceSVille Syrjälä } 7696dbf30ceSVille Syrjälä 770af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 77174c0b395SVille Syrjälä { 772af92058fSVille Syrjälä switch (pin) { 773af92058fSVille Syrjälä case HPD_PORT_A: 77474c0b395SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 775af92058fSVille Syrjälä case HPD_PORT_B: 77674c0b395SVille Syrjälä return val & PORTB_HOTPLUG_LONG_DETECT; 777af92058fSVille Syrjälä case HPD_PORT_C: 77874c0b395SVille Syrjälä return val & PORTC_HOTPLUG_LONG_DETECT; 779af92058fSVille Syrjälä case HPD_PORT_D: 78074c0b395SVille Syrjälä return val & PORTD_HOTPLUG_LONG_DETECT; 78174c0b395SVille Syrjälä default: 78274c0b395SVille Syrjälä return false; 78374c0b395SVille Syrjälä } 78474c0b395SVille Syrjälä } 78574c0b395SVille Syrjälä 786af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 787e4ce95aaSVille Syrjälä { 788af92058fSVille Syrjälä switch (pin) { 789af92058fSVille Syrjälä case HPD_PORT_A: 790e4ce95aaSVille Syrjälä return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; 791e4ce95aaSVille Syrjälä default: 792e4ce95aaSVille Syrjälä return false; 793e4ce95aaSVille Syrjälä } 794e4ce95aaSVille Syrjälä } 795e4ce95aaSVille Syrjälä 796af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 79713cf5504SDave Airlie { 798af92058fSVille Syrjälä switch (pin) { 799af92058fSVille Syrjälä case HPD_PORT_B: 800676574dfSJani Nikula return val & PORTB_HOTPLUG_LONG_DETECT; 801af92058fSVille Syrjälä case HPD_PORT_C: 802676574dfSJani Nikula return val & PORTC_HOTPLUG_LONG_DETECT; 803af92058fSVille Syrjälä case HPD_PORT_D: 804676574dfSJani Nikula return val & PORTD_HOTPLUG_LONG_DETECT; 805676574dfSJani Nikula default: 806676574dfSJani Nikula return false; 80713cf5504SDave Airlie } 80813cf5504SDave Airlie } 80913cf5504SDave Airlie 810af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 81113cf5504SDave Airlie { 812af92058fSVille Syrjälä switch (pin) { 813af92058fSVille Syrjälä case HPD_PORT_B: 814676574dfSJani Nikula return val & PORTB_HOTPLUG_INT_LONG_PULSE; 815af92058fSVille Syrjälä case HPD_PORT_C: 816676574dfSJani Nikula return val & PORTC_HOTPLUG_INT_LONG_PULSE; 817af92058fSVille Syrjälä case HPD_PORT_D: 818676574dfSJani Nikula return val & PORTD_HOTPLUG_INT_LONG_PULSE; 819676574dfSJani Nikula default: 820676574dfSJani Nikula return false; 82113cf5504SDave Airlie } 82213cf5504SDave Airlie } 82313cf5504SDave Airlie 82442db67d6SVille Syrjälä /* 82542db67d6SVille Syrjälä * Get a bit mask of pins that have triggered, and which ones may be long. 82642db67d6SVille Syrjälä * This can be called multiple times with the same masks to accumulate 82742db67d6SVille Syrjälä * hotplug detection results from several registers. 82842db67d6SVille Syrjälä * 82942db67d6SVille Syrjälä * Note that the caller is expected to zero out the masks initially. 83042db67d6SVille Syrjälä */ 831cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, 832cf53902fSRodrigo Vivi u32 *pin_mask, u32 *long_mask, 8338c841e57SJani Nikula u32 hotplug_trigger, u32 dig_hotplug_reg, 834fd63e2a9SImre Deak const u32 hpd[HPD_NUM_PINS], 835af92058fSVille Syrjälä bool long_pulse_detect(enum hpd_pin pin, u32 val)) 836676574dfSJani Nikula { 837e9be2850SVille Syrjälä enum hpd_pin pin; 838676574dfSJani Nikula 83952dfdba0SLucas De Marchi BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS); 84052dfdba0SLucas De Marchi 841e9be2850SVille Syrjälä for_each_hpd_pin(pin) { 842e9be2850SVille Syrjälä if ((hpd[pin] & hotplug_trigger) == 0) 8438c841e57SJani Nikula continue; 8448c841e57SJani Nikula 845e9be2850SVille Syrjälä *pin_mask |= BIT(pin); 846676574dfSJani Nikula 847af92058fSVille Syrjälä if (long_pulse_detect(pin, dig_hotplug_reg)) 848e9be2850SVille Syrjälä *long_mask |= BIT(pin); 849676574dfSJani Nikula } 850676574dfSJani Nikula 85100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 85200376ccfSWambui Karuga "hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n", 853f88f0478SVille Syrjälä hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); 854676574dfSJani Nikula 855676574dfSJani Nikula } 856676574dfSJani Nikula 857a0e066b8SVille Syrjälä static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, 858a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 859a0e066b8SVille Syrjälä { 860a0e066b8SVille Syrjälä struct intel_encoder *encoder; 861a0e066b8SVille Syrjälä u32 enabled_irqs = 0; 862a0e066b8SVille Syrjälä 863a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 8645a4dd6f0SJani Nikula if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) 865a0e066b8SVille Syrjälä enabled_irqs |= hpd[encoder->hpd_pin]; 866a0e066b8SVille Syrjälä 867a0e066b8SVille Syrjälä return enabled_irqs; 868a0e066b8SVille Syrjälä } 869a0e066b8SVille Syrjälä 870a0e066b8SVille Syrjälä static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, 871a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 872a0e066b8SVille Syrjälä { 873a0e066b8SVille Syrjälä struct intel_encoder *encoder; 874a0e066b8SVille Syrjälä u32 hotplug_irqs = 0; 875a0e066b8SVille Syrjälä 876a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 877a0e066b8SVille Syrjälä hotplug_irqs |= hpd[encoder->hpd_pin]; 878a0e066b8SVille Syrjälä 879a0e066b8SVille Syrjälä return hotplug_irqs; 880a0e066b8SVille Syrjälä } 881a0e066b8SVille Syrjälä 8822ea63927SVille Syrjälä static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915, 8832ea63927SVille Syrjälä hotplug_enables_func hotplug_enables) 8842ea63927SVille Syrjälä { 8852ea63927SVille Syrjälä struct intel_encoder *encoder; 8862ea63927SVille Syrjälä u32 hotplug = 0; 8872ea63927SVille Syrjälä 8882ea63927SVille Syrjälä for_each_intel_encoder(&i915->drm, encoder) 889dfefe7bcSVille Syrjälä hotplug |= hotplug_enables(encoder); 8902ea63927SVille Syrjälä 8912ea63927SVille Syrjälä return hotplug; 8922ea63927SVille Syrjälä } 8932ea63927SVille Syrjälä 89491d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv) 895515ac2bbSDaniel Vetter { 896203eb5a9SJani Nikula wake_up_all(&dev_priv->display.gmbus.wait_queue); 897515ac2bbSDaniel Vetter } 898515ac2bbSDaniel Vetter 89991d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) 900ce99c256SDaniel Vetter { 901203eb5a9SJani Nikula wake_up_all(&dev_priv->display.gmbus.wait_queue); 902ce99c256SDaniel Vetter } 903ce99c256SDaniel Vetter 9048bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 90591d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 90691d14251STvrtko Ursulin enum pipe pipe, 907a9c287c9SJani Nikula u32 crc0, u32 crc1, 908a9c287c9SJani Nikula u32 crc2, u32 crc3, 909a9c287c9SJani Nikula u32 crc4) 9108bf1e9f1SShuang He { 9117794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 91200535527SJani Nikula struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc; 9135cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 9145cee6c45SVille Syrjälä 9155cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 916b2c88f5bSDamien Lespiau 917d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 9188c6b709dSTomeu Vizoso /* 9198c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 9208c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 9218c6b709dSTomeu Vizoso * out the buggy result. 9228c6b709dSTomeu Vizoso * 923163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 9248c6b709dSTomeu Vizoso * don't trust that one either. 9258c6b709dSTomeu Vizoso */ 926033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 927373abf1aSMatt Roper (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 9288c6b709dSTomeu Vizoso pipe_crc->skipped++; 9298c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 9308c6b709dSTomeu Vizoso return; 9318c6b709dSTomeu Vizoso } 9328c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 9336cc42152SMaarten Lankhorst 934246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 935ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 936246ee524STomeu Vizoso crcs); 9378c6b709dSTomeu Vizoso } 938277de95eSDaniel Vetter #else 939277de95eSDaniel Vetter static inline void 94091d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 94191d14251STvrtko Ursulin enum pipe pipe, 942a9c287c9SJani Nikula u32 crc0, u32 crc1, 943a9c287c9SJani Nikula u32 crc2, u32 crc3, 944a9c287c9SJani Nikula u32 crc4) {} 945277de95eSDaniel Vetter #endif 946eba94eb9SDaniel Vetter 9471288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915, 9481288f9b0SKarthik B S enum pipe pipe) 9491288f9b0SKarthik B S { 9507794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe); 9511288f9b0SKarthik B S struct drm_crtc_state *crtc_state = crtc->base.state; 9521288f9b0SKarthik B S struct drm_pending_vblank_event *e = crtc_state->event; 9531288f9b0SKarthik B S struct drm_device *dev = &i915->drm; 9541288f9b0SKarthik B S unsigned long irqflags; 9551288f9b0SKarthik B S 9561288f9b0SKarthik B S spin_lock_irqsave(&dev->event_lock, irqflags); 9571288f9b0SKarthik B S 9581288f9b0SKarthik B S crtc_state->event = NULL; 9591288f9b0SKarthik B S 9601288f9b0SKarthik B S drm_crtc_send_vblank_event(&crtc->base, e); 9611288f9b0SKarthik B S 9621288f9b0SKarthik B S spin_unlock_irqrestore(&dev->event_lock, irqflags); 9631288f9b0SKarthik B S } 964277de95eSDaniel Vetter 96591d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 96691d14251STvrtko Ursulin enum pipe pipe) 9675a69b89fSDaniel Vetter { 96891d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 9692939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 9705a69b89fSDaniel Vetter 0, 0, 0, 0); 9715a69b89fSDaniel Vetter } 9725a69b89fSDaniel Vetter 97391d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 97491d14251STvrtko Ursulin enum pipe pipe) 975eba94eb9SDaniel Vetter { 97691d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 9772939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 9782939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)), 9792939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)), 9802939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)), 9812939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe))); 982eba94eb9SDaniel Vetter } 9835b3a856bSDaniel Vetter 98491d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 98591d14251STvrtko Ursulin enum pipe pipe) 9865b3a856bSDaniel Vetter { 987a9c287c9SJani Nikula u32 res1, res2; 9880b5c5ed0SDaniel Vetter 989373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 3) 9902939eb06SJani Nikula res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe)); 9910b5c5ed0SDaniel Vetter else 9920b5c5ed0SDaniel Vetter res1 = 0; 9930b5c5ed0SDaniel Vetter 994373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) 9952939eb06SJani Nikula res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe)); 9960b5c5ed0SDaniel Vetter else 9970b5c5ed0SDaniel Vetter res2 = 0; 9985b3a856bSDaniel Vetter 99991d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 10002939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)), 10012939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)), 10022939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)), 10030b5c5ed0SDaniel Vetter res1, res2); 10045b3a856bSDaniel Vetter } 10058bf1e9f1SShuang He 100644d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 100744d9241eSVille Syrjälä { 100844d9241eSVille Syrjälä enum pipe pipe; 100944d9241eSVille Syrjälä 101044d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 10112939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe), 101244d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 101344d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 101444d9241eSVille Syrjälä 101544d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 101644d9241eSVille Syrjälä } 101744d9241eSVille Syrjälä } 101844d9241eSVille Syrjälä 1019eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 102091d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 10217e231dbeSJesse Barnes { 1022d048a268SVille Syrjälä enum pipe pipe; 10237e231dbeSJesse Barnes 102458ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 10251ca993d2SVille Syrjälä 10261ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 10271ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 10281ca993d2SVille Syrjälä return; 10291ca993d2SVille Syrjälä } 10301ca993d2SVille Syrjälä 1031055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1032f0f59a00SVille Syrjälä i915_reg_t reg; 10336b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 103491d181ddSImre Deak 1035bbb5eebfSDaniel Vetter /* 1036bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 1037bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 1038bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 1039bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 1040bbb5eebfSDaniel Vetter * handle. 1041bbb5eebfSDaniel Vetter */ 10420f239f4cSDaniel Vetter 10430f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 10446b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 1045bbb5eebfSDaniel Vetter 1046bbb5eebfSDaniel Vetter switch (pipe) { 1047d048a268SVille Syrjälä default: 1048bbb5eebfSDaniel Vetter case PIPE_A: 1049bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 1050bbb5eebfSDaniel Vetter break; 1051bbb5eebfSDaniel Vetter case PIPE_B: 1052bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1053bbb5eebfSDaniel Vetter break; 10543278f67fSVille Syrjälä case PIPE_C: 10553278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 10563278f67fSVille Syrjälä break; 1057bbb5eebfSDaniel Vetter } 1058bbb5eebfSDaniel Vetter if (iir & iir_bit) 10596b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 1060bbb5eebfSDaniel Vetter 10616b12ca56SVille Syrjälä if (!status_mask) 106291d181ddSImre Deak continue; 106391d181ddSImre Deak 106491d181ddSImre Deak reg = PIPESTAT(pipe); 10652939eb06SJani Nikula pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; 10666b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 10677e231dbeSJesse Barnes 10687e231dbeSJesse Barnes /* 10697e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 1070132c27c9SVille Syrjälä * 1071132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 1072132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 1073132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 1074132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 1075132c27c9SVille Syrjälä * an interrupt is still pending. 10767e231dbeSJesse Barnes */ 1077132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 10782939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]); 10792939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask); 1080132c27c9SVille Syrjälä } 10817e231dbeSJesse Barnes } 108258ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 10832ecb8ca4SVille Syrjälä } 10842ecb8ca4SVille Syrjälä 1085eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1086eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 1087eb64343cSVille Syrjälä { 1088eb64343cSVille Syrjälä enum pipe pipe; 1089eb64343cSVille Syrjälä 1090eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1091eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1092aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1093eb64343cSVille Syrjälä 1094eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1095eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1096eb64343cSVille Syrjälä 1097eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1098eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1099eb64343cSVille Syrjälä } 1100eb64343cSVille Syrjälä } 1101eb64343cSVille Syrjälä 1102eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1103eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1104eb64343cSVille Syrjälä { 1105eb64343cSVille Syrjälä bool blc_event = false; 1106eb64343cSVille Syrjälä enum pipe pipe; 1107eb64343cSVille Syrjälä 1108eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1109eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1110aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1111eb64343cSVille Syrjälä 1112eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1113eb64343cSVille Syrjälä blc_event = true; 1114eb64343cSVille Syrjälä 1115eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1116eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1117eb64343cSVille Syrjälä 1118eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1119eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1120eb64343cSVille Syrjälä } 1121eb64343cSVille Syrjälä 1122eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1123eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1124eb64343cSVille Syrjälä } 1125eb64343cSVille Syrjälä 1126eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1127eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1128eb64343cSVille Syrjälä { 1129eb64343cSVille Syrjälä bool blc_event = false; 1130eb64343cSVille Syrjälä enum pipe pipe; 1131eb64343cSVille Syrjälä 1132eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1133eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1134aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1135eb64343cSVille Syrjälä 1136eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1137eb64343cSVille Syrjälä blc_event = true; 1138eb64343cSVille Syrjälä 1139eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1140eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1141eb64343cSVille Syrjälä 1142eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1143eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1144eb64343cSVille Syrjälä } 1145eb64343cSVille Syrjälä 1146eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1147eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1148eb64343cSVille Syrjälä 1149eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 1150eb64343cSVille Syrjälä gmbus_irq_handler(dev_priv); 1151eb64343cSVille Syrjälä } 1152eb64343cSVille Syrjälä 115391d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 11542ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 11552ecb8ca4SVille Syrjälä { 11562ecb8ca4SVille Syrjälä enum pipe pipe; 11577e231dbeSJesse Barnes 1158055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1159fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1160aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 11614356d586SDaniel Vetter 11626ede6b06SVille Syrjälä if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) 11636ede6b06SVille Syrjälä flip_done_handler(dev_priv, pipe); 11646ede6b06SVille Syrjälä 11654356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 116691d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 11672d9d2b0bSVille Syrjälä 11681f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 11691f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 117031acc7f5SJesse Barnes } 117131acc7f5SJesse Barnes 1172c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 117391d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1174c1874ed7SImre Deak } 1175c1874ed7SImre Deak 11761ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 117716c6c56bSVille Syrjälä { 11780ba7c51aSVille Syrjälä u32 hotplug_status = 0, hotplug_status_mask; 11790ba7c51aSVille Syrjälä int i; 118016c6c56bSVille Syrjälä 11810ba7c51aSVille Syrjälä if (IS_G4X(dev_priv) || 11820ba7c51aSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 11830ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | 11840ba7c51aSVille Syrjälä DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; 11850ba7c51aSVille Syrjälä else 11860ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_I915; 11870ba7c51aSVille Syrjälä 11880ba7c51aSVille Syrjälä /* 11890ba7c51aSVille Syrjälä * We absolutely have to clear all the pending interrupt 11900ba7c51aSVille Syrjälä * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port 11910ba7c51aSVille Syrjälä * interrupt bit won't have an edge, and the i965/g4x 11920ba7c51aSVille Syrjälä * edge triggered IIR will not notice that an interrupt 11930ba7c51aSVille Syrjälä * is still pending. We can't use PORT_HOTPLUG_EN to 11940ba7c51aSVille Syrjälä * guarantee the edge as the act of toggling the enable 11950ba7c51aSVille Syrjälä * bits can itself generate a new hotplug interrupt :( 11960ba7c51aSVille Syrjälä */ 11970ba7c51aSVille Syrjälä for (i = 0; i < 10; i++) { 11982939eb06SJani Nikula u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask; 11990ba7c51aSVille Syrjälä 12000ba7c51aSVille Syrjälä if (tmp == 0) 12010ba7c51aSVille Syrjälä return hotplug_status; 12020ba7c51aSVille Syrjälä 12030ba7c51aSVille Syrjälä hotplug_status |= tmp; 12042939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status); 12050ba7c51aSVille Syrjälä } 12060ba7c51aSVille Syrjälä 120748a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 1, 12080ba7c51aSVille Syrjälä "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", 12092939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 12101ae3c34cSVille Syrjälä 12111ae3c34cSVille Syrjälä return hotplug_status; 12121ae3c34cSVille Syrjälä } 12131ae3c34cSVille Syrjälä 121491d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, 12151ae3c34cSVille Syrjälä u32 hotplug_status) 12161ae3c34cSVille Syrjälä { 12171ae3c34cSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 12180398993bSVille Syrjälä u32 hotplug_trigger; 12193ff60f89SOscar Mateo 12200398993bSVille Syrjälä if (IS_G4X(dev_priv) || 12210398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 12220398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; 12230398993bSVille Syrjälä else 12240398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; 122516c6c56bSVille Syrjälä 122658f2cf24SVille Syrjälä if (hotplug_trigger) { 1227cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1228cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 12295a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1230fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 123158f2cf24SVille Syrjälä 123291d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 123358f2cf24SVille Syrjälä } 1234369712e8SJani Nikula 12350398993bSVille Syrjälä if ((IS_G4X(dev_priv) || 12360398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && 12370398993bSVille Syrjälä hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) 123891d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 123958f2cf24SVille Syrjälä } 124016c6c56bSVille Syrjälä 1241c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 1242c1874ed7SImre Deak { 1243b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 1244c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 1245c1874ed7SImre Deak 12462dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 12472dd2a883SImre Deak return IRQ_NONE; 12482dd2a883SImre Deak 12491f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 12509102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 12511f814dacSImre Deak 12521e1cace9SVille Syrjälä do { 12536e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 12542ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 12551ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1256a5e485a9SVille Syrjälä u32 ier = 0; 12573ff60f89SOscar Mateo 12582939eb06SJani Nikula gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR); 12592939eb06SJani Nikula pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR); 12602939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 1261c1874ed7SImre Deak 1262c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 12631e1cace9SVille Syrjälä break; 1264c1874ed7SImre Deak 1265c1874ed7SImre Deak ret = IRQ_HANDLED; 1266c1874ed7SImre Deak 1267a5e485a9SVille Syrjälä /* 1268a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1269a5e485a9SVille Syrjälä * 1270a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1271a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 1272a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 1273a5e485a9SVille Syrjälä * 1274a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1275a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 1276a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1277a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 1278a5e485a9SVille Syrjälä * bits this time around. 1279a5e485a9SVille Syrjälä */ 12802939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 12818cee664dSAndrzej Hajda ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); 12824a0a0202SVille Syrjälä 12834a0a0202SVille Syrjälä if (gt_iir) 12842939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir); 12854a0a0202SVille Syrjälä if (pm_iir) 12862939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir); 12874a0a0202SVille Syrjälä 12887ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 12891ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 12907ce4d1f2SVille Syrjälä 12913ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 12923ff60f89SOscar Mateo * signalled in iir */ 1293eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 12947ce4d1f2SVille Syrjälä 1295eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1296eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 1297eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1298eef57324SJerome Anand 12997ce4d1f2SVille Syrjälä /* 13007ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 13017ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 13027ce4d1f2SVille Syrjälä */ 13037ce4d1f2SVille Syrjälä if (iir) 13042939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 13054a0a0202SVille Syrjälä 13062939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 13072939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 13081ae3c34cSVille Syrjälä 130952894874SVille Syrjälä if (gt_iir) 13102cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(dev_priv), gt_iir); 131152894874SVille Syrjälä if (pm_iir) 13122cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir); 131352894874SVille Syrjälä 13141ae3c34cSVille Syrjälä if (hotplug_status) 131591d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 13162ecb8ca4SVille Syrjälä 131791d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 13181e1cace9SVille Syrjälä } while (0); 13197e231dbeSJesse Barnes 13209c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 13219c6508b9SThomas Gleixner 13229102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 13231f814dacSImre Deak 13247e231dbeSJesse Barnes return ret; 13257e231dbeSJesse Barnes } 13267e231dbeSJesse Barnes 132743f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 132843f328d7SVille Syrjälä { 1329b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 133043f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 133143f328d7SVille Syrjälä 13322dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 13332dd2a883SImre Deak return IRQ_NONE; 13342dd2a883SImre Deak 13351f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 13369102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 13371f814dacSImre Deak 1338579de73bSChris Wilson do { 13396e814800SVille Syrjälä u32 master_ctl, iir; 13402ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 13411ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1342a5e485a9SVille Syrjälä u32 ier = 0; 1343a5e485a9SVille Syrjälä 13442939eb06SJani Nikula master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 13452939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 13463278f67fSVille Syrjälä 13473278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 13488e5fd599SVille Syrjälä break; 134943f328d7SVille Syrjälä 135027b6c122SOscar Mateo ret = IRQ_HANDLED; 135127b6c122SOscar Mateo 1352a5e485a9SVille Syrjälä /* 1353a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1354a5e485a9SVille Syrjälä * 1355a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1356a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 1357a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 1358a5e485a9SVille Syrjälä * 1359a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1360a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 1361a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1362a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 1363a5e485a9SVille Syrjälä * bits this time around. 1364a5e485a9SVille Syrjälä */ 13652939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); 13668cee664dSAndrzej Hajda ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0); 136743f328d7SVille Syrjälä 13682cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 136927b6c122SOscar Mateo 137027b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 13711ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 137243f328d7SVille Syrjälä 137327b6c122SOscar Mateo /* Call regardless, as some status bits might not be 137427b6c122SOscar Mateo * signalled in iir */ 1375eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 137643f328d7SVille Syrjälä 1377eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1378eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 1379eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 1380eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1381eef57324SJerome Anand 13827ce4d1f2SVille Syrjälä /* 13837ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 13847ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 13857ce4d1f2SVille Syrjälä */ 13867ce4d1f2SVille Syrjälä if (iir) 13872939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 13887ce4d1f2SVille Syrjälä 13892939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 13902939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 13911ae3c34cSVille Syrjälä 13921ae3c34cSVille Syrjälä if (hotplug_status) 139391d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 13942ecb8ca4SVille Syrjälä 139591d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 1396579de73bSChris Wilson } while (0); 13973278f67fSVille Syrjälä 13989c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 13999c6508b9SThomas Gleixner 14009102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 14011f814dacSImre Deak 140243f328d7SVille Syrjälä return ret; 140343f328d7SVille Syrjälä } 140443f328d7SVille Syrjälä 140591d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, 14060398993bSVille Syrjälä u32 hotplug_trigger) 1407776ad806SJesse Barnes { 140842db67d6SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1409776ad806SJesse Barnes 14106a39d7c9SJani Nikula /* 14116a39d7c9SJani Nikula * Somehow the PCH doesn't seem to really ack the interrupt to the CPU 14126a39d7c9SJani Nikula * unless we touch the hotplug register, even if hotplug_trigger is 14136a39d7c9SJani Nikula * zero. Not acking leads to "The master control interrupt lied (SDE)!" 14146a39d7c9SJani Nikula * errors. 14156a39d7c9SJani Nikula */ 14162939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 14176a39d7c9SJani Nikula if (!hotplug_trigger) { 14186a39d7c9SJani Nikula u32 mask = PORTA_HOTPLUG_STATUS_MASK | 14196a39d7c9SJani Nikula PORTD_HOTPLUG_STATUS_MASK | 14206a39d7c9SJani Nikula PORTC_HOTPLUG_STATUS_MASK | 14216a39d7c9SJani Nikula PORTB_HOTPLUG_STATUS_MASK; 14226a39d7c9SJani Nikula dig_hotplug_reg &= ~mask; 14236a39d7c9SJani Nikula } 14246a39d7c9SJani Nikula 14252939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 14266a39d7c9SJani Nikula if (!hotplug_trigger) 14276a39d7c9SJani Nikula return; 142813cf5504SDave Airlie 14290398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 14300398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 14315a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 1432fd63e2a9SImre Deak pch_port_hotplug_long_detect); 143340e56410SVille Syrjälä 143491d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1435aaf5ec2eSSonika Jindal } 143691d131d2SDaniel Vetter 143791d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 143840e56410SVille Syrjälä { 1439d048a268SVille Syrjälä enum pipe pipe; 144040e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 144140e56410SVille Syrjälä 14420398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 144340e56410SVille Syrjälä 1444cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 1445cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 1446776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 144700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n", 1448cfc33bf7SVille Syrjälä port_name(port)); 1449cfc33bf7SVille Syrjälä } 1450776ad806SJesse Barnes 1451ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 145291d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 1453ce99c256SDaniel Vetter 1454776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 145591d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1456776ad806SJesse Barnes 1457776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 145800376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n"); 1459776ad806SJesse Barnes 1460776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 146100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n"); 1462776ad806SJesse Barnes 1463776ad806SJesse Barnes if (pch_iir & SDE_POISON) 146400376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1465776ad806SJesse Barnes 1466b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK) { 1467055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 146800376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 14699db4a9c7SJesse Barnes pipe_name(pipe), 14702939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1471b8b65ccdSAnshuman Gupta } 1472776ad806SJesse Barnes 1473776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 147400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n"); 1475776ad806SJesse Barnes 1476776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 147700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 147800376ccfSWambui Karuga "PCH transcoder CRC error interrupt\n"); 1479776ad806SJesse Barnes 1480776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 1481a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 14828664281bSPaulo Zanoni 14838664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 1484a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 14858664281bSPaulo Zanoni } 14868664281bSPaulo Zanoni 148791d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 14888664281bSPaulo Zanoni { 14892939eb06SJani Nikula u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT); 14905a69b89fSDaniel Vetter enum pipe pipe; 14918664281bSPaulo Zanoni 1492de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 149300376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1494de032bf4SPaulo Zanoni 1495055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 14961f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 14971f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 14988664281bSPaulo Zanoni 14995a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 150091d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 150191d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 15025a69b89fSDaniel Vetter else 150391d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 15045a69b89fSDaniel Vetter } 15055a69b89fSDaniel Vetter } 15068bf1e9f1SShuang He 15072939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int); 15088664281bSPaulo Zanoni } 15098664281bSPaulo Zanoni 151091d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 15118664281bSPaulo Zanoni { 15122939eb06SJani Nikula u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT); 151345c1cd87SMika Kahola enum pipe pipe; 15148664281bSPaulo Zanoni 1515de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 151600376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1517de032bf4SPaulo Zanoni 151845c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 151945c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 152045c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 15218664281bSPaulo Zanoni 15222939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int); 1523776ad806SJesse Barnes } 1524776ad806SJesse Barnes 152591d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 152623e81d69SAdam Jackson { 1527d048a268SVille Syrjälä enum pipe pipe; 15286dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 1529aaf5ec2eSSonika Jindal 15300398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 153191d131d2SDaniel Vetter 1532cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 1533cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 153423e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 153500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n", 1536cfc33bf7SVille Syrjälä port_name(port)); 1537cfc33bf7SVille Syrjälä } 153823e81d69SAdam Jackson 153923e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 154091d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 154123e81d69SAdam Jackson 154223e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 154391d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 154423e81d69SAdam Jackson 154523e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 154600376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n"); 154723e81d69SAdam Jackson 154823e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 154900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n"); 155023e81d69SAdam Jackson 1551b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK_CPT) { 1552055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 155300376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 155423e81d69SAdam Jackson pipe_name(pipe), 15552939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1556b8b65ccdSAnshuman Gupta } 15578664281bSPaulo Zanoni 15588664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 155991d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 156023e81d69SAdam Jackson } 156123e81d69SAdam Jackson 156258676af6SLucas De Marchi static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 156331604222SAnusha Srivatsa { 1564e76ab2cfSVille Syrjälä u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP; 1565e76ab2cfSVille Syrjälä u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP; 156631604222SAnusha Srivatsa u32 pin_mask = 0, long_mask = 0; 156731604222SAnusha Srivatsa 156831604222SAnusha Srivatsa if (ddi_hotplug_trigger) { 156931604222SAnusha Srivatsa u32 dig_hotplug_reg; 157031604222SAnusha Srivatsa 1571f087cfe6SJani Nikula /* Locking due to DSI native GPIO sequences */ 1572f087cfe6SJani Nikula spin_lock(&dev_priv->irq_lock); 15738cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0); 1574f087cfe6SJani Nikula spin_unlock(&dev_priv->irq_lock); 157531604222SAnusha Srivatsa 157631604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 15770398993bSVille Syrjälä ddi_hotplug_trigger, dig_hotplug_reg, 15785a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 157931604222SAnusha Srivatsa icp_ddi_port_hotplug_long_detect); 158031604222SAnusha Srivatsa } 158131604222SAnusha Srivatsa 158231604222SAnusha Srivatsa if (tc_hotplug_trigger) { 158331604222SAnusha Srivatsa u32 dig_hotplug_reg; 158431604222SAnusha Srivatsa 15858cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0); 158631604222SAnusha Srivatsa 158731604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 15880398993bSVille Syrjälä tc_hotplug_trigger, dig_hotplug_reg, 15895a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 1590da51e4baSVille Syrjälä icp_tc_port_hotplug_long_detect); 159152dfdba0SLucas De Marchi } 159252dfdba0SLucas De Marchi 159352dfdba0SLucas De Marchi if (pin_mask) 159452dfdba0SLucas De Marchi intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 159552dfdba0SLucas De Marchi 159652dfdba0SLucas De Marchi if (pch_iir & SDE_GMBUS_ICP) 159752dfdba0SLucas De Marchi gmbus_irq_handler(dev_priv); 159852dfdba0SLucas De Marchi } 159952dfdba0SLucas De Marchi 160091d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 16016dbf30ceSVille Syrjälä { 16026dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & 16036dbf30ceSVille Syrjälä ~SDE_PORTE_HOTPLUG_SPT; 16046dbf30ceSVille Syrjälä u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; 16056dbf30ceSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 16066dbf30ceSVille Syrjälä 16076dbf30ceSVille Syrjälä if (hotplug_trigger) { 16086dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 16096dbf30ceSVille Syrjälä 16108cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0); 16116dbf30ceSVille Syrjälä 1612cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 16130398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 16145a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 161574c0b395SVille Syrjälä spt_port_hotplug_long_detect); 16166dbf30ceSVille Syrjälä } 16176dbf30ceSVille Syrjälä 16186dbf30ceSVille Syrjälä if (hotplug2_trigger) { 16196dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 16206dbf30ceSVille Syrjälä 16218cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0); 16226dbf30ceSVille Syrjälä 1623cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 16240398993bSVille Syrjälä hotplug2_trigger, dig_hotplug_reg, 16255a4dd6f0SJani Nikula dev_priv->display.hotplug.pch_hpd, 16266dbf30ceSVille Syrjälä spt_port_hotplug2_long_detect); 16276dbf30ceSVille Syrjälä } 16286dbf30ceSVille Syrjälä 16296dbf30ceSVille Syrjälä if (pin_mask) 163091d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 16316dbf30ceSVille Syrjälä 16326dbf30ceSVille Syrjälä if (pch_iir & SDE_GMBUS_CPT) 163391d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 16346dbf30ceSVille Syrjälä } 16356dbf30ceSVille Syrjälä 163691d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, 16370398993bSVille Syrjälä u32 hotplug_trigger) 1638c008bc6eSPaulo Zanoni { 1639e4ce95aaSVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1640e4ce95aaSVille Syrjälä 16418cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0); 1642e4ce95aaSVille Syrjälä 16430398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 16440398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 16455a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1646e4ce95aaSVille Syrjälä ilk_port_hotplug_long_detect); 164740e56410SVille Syrjälä 164891d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1649e4ce95aaSVille Syrjälä } 1650c008bc6eSPaulo Zanoni 165191d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 165291d14251STvrtko Ursulin u32 de_iir) 165340e56410SVille Syrjälä { 165440e56410SVille Syrjälä enum pipe pipe; 165540e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 165640e56410SVille Syrjälä 165740e56410SVille Syrjälä if (hotplug_trigger) 16580398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 165940e56410SVille Syrjälä 1660c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 166191d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 1662c008bc6eSPaulo Zanoni 1663c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 166491d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 1665c008bc6eSPaulo Zanoni 1666c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 166700376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1668c008bc6eSPaulo Zanoni 1669055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1670fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 1671aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1672c008bc6eSPaulo Zanoni 16734bb18054SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE(pipe)) 16744bb18054SVille Syrjälä flip_done_handler(dev_priv, pipe); 16754bb18054SVille Syrjälä 167640da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 16771f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1678c008bc6eSPaulo Zanoni 167940da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 168091d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1681c008bc6eSPaulo Zanoni } 1682c008bc6eSPaulo Zanoni 1683c008bc6eSPaulo Zanoni /* check event from PCH */ 1684c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 16852939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 1686c008bc6eSPaulo Zanoni 168791d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 168891d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 1689c008bc6eSPaulo Zanoni else 169091d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 1691c008bc6eSPaulo Zanoni 1692c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 16932939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 1694c008bc6eSPaulo Zanoni } 1695c008bc6eSPaulo Zanoni 169693e7e61eSLucas De Marchi if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT) 16972cbc876dSMichał Winiarski gen5_rps_irq_handler(&to_gt(dev_priv)->rps); 1698c008bc6eSPaulo Zanoni } 1699c008bc6eSPaulo Zanoni 170091d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 170191d14251STvrtko Ursulin u32 de_iir) 17029719fb98SPaulo Zanoni { 170307d27e20SDamien Lespiau enum pipe pipe; 170423bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 170523bb4cb5SVille Syrjälä 170640e56410SVille Syrjälä if (hotplug_trigger) 17070398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 17089719fb98SPaulo Zanoni 17099719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 171091d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 17119719fb98SPaulo Zanoni 17129719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 171391d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 17149719fb98SPaulo Zanoni 17159719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 171691d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 17179719fb98SPaulo Zanoni 1718055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 171933ef04faSVille Syrjälä if (de_iir & DE_PIPE_VBLANK_IVB(pipe)) 1720aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 17212a636e24SVille Syrjälä 17222a636e24SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) 17232a636e24SVille Syrjälä flip_done_handler(dev_priv, pipe); 17249719fb98SPaulo Zanoni } 17259719fb98SPaulo Zanoni 17269719fb98SPaulo Zanoni /* check event from PCH */ 172791d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 17282939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 17299719fb98SPaulo Zanoni 173091d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 17319719fb98SPaulo Zanoni 17329719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 17332939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 17349719fb98SPaulo Zanoni } 17359719fb98SPaulo Zanoni } 17369719fb98SPaulo Zanoni 173772c90f62SOscar Mateo /* 173872c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 173972c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 174072c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 174172c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 174272c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 174372c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 174472c90f62SOscar Mateo */ 17459eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg) 1746b1f14ad0SJesse Barnes { 1747c48a798aSChris Wilson struct drm_i915_private *i915 = arg; 1748c48a798aSChris Wilson void __iomem * const regs = i915->uncore.regs; 1749f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 17500e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 1751b1f14ad0SJesse Barnes 1752c48a798aSChris Wilson if (unlikely(!intel_irqs_enabled(i915))) 17532dd2a883SImre Deak return IRQ_NONE; 17542dd2a883SImre Deak 17551f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1756c48a798aSChris Wilson disable_rpm_wakeref_asserts(&i915->runtime_pm); 17571f814dacSImre Deak 1758b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 1759c48a798aSChris Wilson de_ier = raw_reg_read(regs, DEIER); 1760c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 17610e43406bSChris Wilson 176244498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 176344498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 176444498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 176544498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 176644498aeaSPaulo Zanoni * due to its back queue). */ 1767c48a798aSChris Wilson if (!HAS_PCH_NOP(i915)) { 1768c48a798aSChris Wilson sde_ier = raw_reg_read(regs, SDEIER); 1769c48a798aSChris Wilson raw_reg_write(regs, SDEIER, 0); 1770ab5c608bSBen Widawsky } 177144498aeaSPaulo Zanoni 177272c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 177372c90f62SOscar Mateo 1774c48a798aSChris Wilson gt_iir = raw_reg_read(regs, GTIIR); 17750e43406bSChris Wilson if (gt_iir) { 1776c48a798aSChris Wilson raw_reg_write(regs, GTIIR, gt_iir); 1777651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) 17782cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(i915), gt_iir); 1779d8fc8a47SPaulo Zanoni else 17802cbc876dSMichał Winiarski gen5_gt_irq_handler(to_gt(i915), gt_iir); 1781c48a798aSChris Wilson ret = IRQ_HANDLED; 17820e43406bSChris Wilson } 1783b1f14ad0SJesse Barnes 1784c48a798aSChris Wilson de_iir = raw_reg_read(regs, DEIIR); 17850e43406bSChris Wilson if (de_iir) { 1786c48a798aSChris Wilson raw_reg_write(regs, DEIIR, de_iir); 1787373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 7) 1788c48a798aSChris Wilson ivb_display_irq_handler(i915, de_iir); 1789f1af8fc1SPaulo Zanoni else 1790c48a798aSChris Wilson ilk_display_irq_handler(i915, de_iir); 17910e43406bSChris Wilson ret = IRQ_HANDLED; 1792c48a798aSChris Wilson } 1793c48a798aSChris Wilson 1794651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) { 1795c48a798aSChris Wilson u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR); 1796c48a798aSChris Wilson if (pm_iir) { 1797c48a798aSChris Wilson raw_reg_write(regs, GEN6_PMIIR, pm_iir); 17982cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(i915)->rps, pm_iir); 1799c48a798aSChris Wilson ret = IRQ_HANDLED; 18000e43406bSChris Wilson } 1801f1af8fc1SPaulo Zanoni } 1802b1f14ad0SJesse Barnes 1803c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier); 1804c48a798aSChris Wilson if (sde_ier) 1805c48a798aSChris Wilson raw_reg_write(regs, SDEIER, sde_ier); 1806b1f14ad0SJesse Barnes 18079c6508b9SThomas Gleixner pmu_irq_stats(i915, ret); 18089c6508b9SThomas Gleixner 18091f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 1810c48a798aSChris Wilson enable_rpm_wakeref_asserts(&i915->runtime_pm); 18111f814dacSImre Deak 1812b1f14ad0SJesse Barnes return ret; 1813b1f14ad0SJesse Barnes } 1814b1f14ad0SJesse Barnes 181591d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, 18160398993bSVille Syrjälä u32 hotplug_trigger) 1817d04a492dSShashank Sharma { 1818cebd87a0SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1819d04a492dSShashank Sharma 18208cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0); 1821d04a492dSShashank Sharma 18220398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18230398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 18245a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1825cebd87a0SVille Syrjälä bxt_port_hotplug_long_detect); 182640e56410SVille Syrjälä 182791d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1828d04a492dSShashank Sharma } 1829d04a492dSShashank Sharma 1830121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 1831121e758eSDhinakaran Pandiyan { 1832121e758eSDhinakaran Pandiyan u32 pin_mask = 0, long_mask = 0; 1833b796b971SDhinakaran Pandiyan u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; 1834b796b971SDhinakaran Pandiyan u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; 1835121e758eSDhinakaran Pandiyan 1836121e758eSDhinakaran Pandiyan if (trigger_tc) { 1837b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 1838b796b971SDhinakaran Pandiyan 18398cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0); 1840121e758eSDhinakaran Pandiyan 18410398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18420398993bSVille Syrjälä trigger_tc, dig_hotplug_reg, 18435a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1844da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 1845121e758eSDhinakaran Pandiyan } 1846b796b971SDhinakaran Pandiyan 1847b796b971SDhinakaran Pandiyan if (trigger_tbt) { 1848b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 1849b796b971SDhinakaran Pandiyan 18508cee664dSAndrzej Hajda dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0); 1851b796b971SDhinakaran Pandiyan 18520398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18530398993bSVille Syrjälä trigger_tbt, dig_hotplug_reg, 18545a4dd6f0SJani Nikula dev_priv->display.hotplug.hpd, 1855da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 1856b796b971SDhinakaran Pandiyan } 1857b796b971SDhinakaran Pandiyan 1858b796b971SDhinakaran Pandiyan if (pin_mask) 1859b796b971SDhinakaran Pandiyan intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1860b796b971SDhinakaran Pandiyan else 186100376ccfSWambui Karuga drm_err(&dev_priv->drm, 186200376ccfSWambui Karuga "Unexpected DE HPD interrupt 0x%08x\n", iir); 1863121e758eSDhinakaran Pandiyan } 1864121e758eSDhinakaran Pandiyan 18659d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 18669d17210fSLucas De Marchi { 186755523360SLucas De Marchi u32 mask; 18689d17210fSLucas De Marchi 186920fe778fSMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 187020fe778fSMatt Roper return TGL_DE_PORT_AUX_DDIA | 187120fe778fSMatt Roper TGL_DE_PORT_AUX_DDIB | 187220fe778fSMatt Roper TGL_DE_PORT_AUX_DDIC | 187320fe778fSMatt Roper XELPD_DE_PORT_AUX_DDID | 187420fe778fSMatt Roper XELPD_DE_PORT_AUX_DDIE | 187520fe778fSMatt Roper TGL_DE_PORT_AUX_USBC1 | 187620fe778fSMatt Roper TGL_DE_PORT_AUX_USBC2 | 187720fe778fSMatt Roper TGL_DE_PORT_AUX_USBC3 | 187820fe778fSMatt Roper TGL_DE_PORT_AUX_USBC4; 187920fe778fSMatt Roper else if (DISPLAY_VER(dev_priv) >= 12) 188055523360SLucas De Marchi return TGL_DE_PORT_AUX_DDIA | 188155523360SLucas De Marchi TGL_DE_PORT_AUX_DDIB | 1882e5df52dcSMatt Roper TGL_DE_PORT_AUX_DDIC | 1883e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC1 | 1884e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC2 | 1885e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC3 | 1886e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC4 | 1887e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC5 | 1888e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC6; 1889e5df52dcSMatt Roper 189055523360SLucas De Marchi 189155523360SLucas De Marchi mask = GEN8_AUX_CHANNEL_A; 1892373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 9) 18939d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 18949d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 18959d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 18969d17210fSLucas De Marchi 1897938a8a9aSLucas De Marchi if (DISPLAY_VER(dev_priv) == 11) { 1898938a8a9aSLucas De Marchi mask |= ICL_AUX_CHANNEL_F; 189955523360SLucas De Marchi mask |= ICL_AUX_CHANNEL_E; 1900938a8a9aSLucas De Marchi } 19019d17210fSLucas De Marchi 19029d17210fSLucas De Marchi return mask; 19039d17210fSLucas De Marchi } 19049d17210fSLucas De Marchi 19055270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) 19065270130dSVille Syrjälä { 19071649a4ccSMatt Roper if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv)) 190899e2d8bcSMatt Roper return RKL_DE_PIPE_IRQ_FAULT_ERRORS; 1909373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 11) 1910d506a65dSMatt Roper return GEN11_DE_PIPE_IRQ_FAULT_ERRORS; 1911373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 9) 19125270130dSVille Syrjälä return GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 19135270130dSVille Syrjälä else 19145270130dSVille Syrjälä return GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 19155270130dSVille Syrjälä } 19165270130dSVille Syrjälä 191746c63d24SJosé Roberto de Souza static void 191846c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 1919abd58f01SBen Widawsky { 1920e04f7eceSVille Syrjälä bool found = false; 1921e04f7eceSVille Syrjälä 1922e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 192391d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 1924e04f7eceSVille Syrjälä found = true; 1925e04f7eceSVille Syrjälä } 1926e04f7eceSVille Syrjälä 1927e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 1928b64d6c51SGwan-gyeong Mun struct intel_encoder *encoder; 19298241cfbeSJosé Roberto de Souza u32 psr_iir; 19308241cfbeSJosé Roberto de Souza i915_reg_t iir_reg; 19318241cfbeSJosé Roberto de Souza 1932a22af61dSJosé Roberto de Souza for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) { 1933b64d6c51SGwan-gyeong Mun struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1934b64d6c51SGwan-gyeong Mun 1935373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 1936b64d6c51SGwan-gyeong Mun iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder); 19378241cfbeSJosé Roberto de Souza else 19388241cfbeSJosé Roberto de Souza iir_reg = EDP_PSR_IIR; 19398241cfbeSJosé Roberto de Souza 19408cee664dSAndrzej Hajda psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0); 19418241cfbeSJosé Roberto de Souza 19428241cfbeSJosé Roberto de Souza if (psr_iir) 19438241cfbeSJosé Roberto de Souza found = true; 194454fd3149SDhinakaran Pandiyan 1945b64d6c51SGwan-gyeong Mun intel_psr_irq_handler(intel_dp, psr_iir); 1946b64d6c51SGwan-gyeong Mun 1947b64d6c51SGwan-gyeong Mun /* prior GEN12 only have one EDP PSR */ 1948373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 12) 1949b64d6c51SGwan-gyeong Mun break; 1950b64d6c51SGwan-gyeong Mun } 1951e04f7eceSVille Syrjälä } 1952e04f7eceSVille Syrjälä 1953e04f7eceSVille Syrjälä if (!found) 195400376ccfSWambui Karuga drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n"); 1955abd58f01SBen Widawsky } 195646c63d24SJosé Roberto de Souza 195700acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, 195800acb329SVandita Kulkarni u32 te_trigger) 195900acb329SVandita Kulkarni { 196000acb329SVandita Kulkarni enum pipe pipe = INVALID_PIPE; 196100acb329SVandita Kulkarni enum transcoder dsi_trans; 196200acb329SVandita Kulkarni enum port port; 196300acb329SVandita Kulkarni u32 val, tmp; 196400acb329SVandita Kulkarni 196500acb329SVandita Kulkarni /* 196600acb329SVandita Kulkarni * Incase of dual link, TE comes from DSI_1 196700acb329SVandita Kulkarni * this is to check if dual link is enabled 196800acb329SVandita Kulkarni */ 19692939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0)); 197000acb329SVandita Kulkarni val &= PORT_SYNC_MODE_ENABLE; 197100acb329SVandita Kulkarni 197200acb329SVandita Kulkarni /* 197300acb329SVandita Kulkarni * if dual link is enabled, then read DSI_0 197400acb329SVandita Kulkarni * transcoder registers 197500acb329SVandita Kulkarni */ 197600acb329SVandita Kulkarni port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ? 197700acb329SVandita Kulkarni PORT_A : PORT_B; 197800acb329SVandita Kulkarni dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; 197900acb329SVandita Kulkarni 198000acb329SVandita Kulkarni /* Check if DSI configured in command mode */ 19812939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans)); 198200acb329SVandita Kulkarni val = val & OP_MODE_MASK; 198300acb329SVandita Kulkarni 198400acb329SVandita Kulkarni if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { 198500acb329SVandita Kulkarni drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n"); 198600acb329SVandita Kulkarni return; 198700acb329SVandita Kulkarni } 198800acb329SVandita Kulkarni 198900acb329SVandita Kulkarni /* Get PIPE for handling VBLANK event */ 19902939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans)); 199100acb329SVandita Kulkarni switch (val & TRANS_DDI_EDP_INPUT_MASK) { 199200acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_A_ON: 199300acb329SVandita Kulkarni pipe = PIPE_A; 199400acb329SVandita Kulkarni break; 199500acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_B_ONOFF: 199600acb329SVandita Kulkarni pipe = PIPE_B; 199700acb329SVandita Kulkarni break; 199800acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_C_ONOFF: 199900acb329SVandita Kulkarni pipe = PIPE_C; 200000acb329SVandita Kulkarni break; 200100acb329SVandita Kulkarni default: 200200acb329SVandita Kulkarni drm_err(&dev_priv->drm, "Invalid PIPE\n"); 200300acb329SVandita Kulkarni return; 200400acb329SVandita Kulkarni } 200500acb329SVandita Kulkarni 200600acb329SVandita Kulkarni intel_handle_vblank(dev_priv, pipe); 200700acb329SVandita Kulkarni 200800acb329SVandita Kulkarni /* clear TE in dsi IIR */ 200900acb329SVandita Kulkarni port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; 20108cee664dSAndrzej Hajda tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); 201100acb329SVandita Kulkarni } 201200acb329SVandita Kulkarni 2013cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) 2014cda195f1SVille Syrjälä { 2015373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 9) 2016cda195f1SVille Syrjälä return GEN9_PIPE_PLANE1_FLIP_DONE; 2017cda195f1SVille Syrjälä else 2018cda195f1SVille Syrjälä return GEN8_PIPE_PRIMARY_FLIP_DONE; 2019cda195f1SVille Syrjälä } 2020cda195f1SVille Syrjälä 20218bcc0840SMatt Roper u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv) 20228bcc0840SMatt Roper { 20238bcc0840SMatt Roper u32 mask = GEN8_PIPE_FIFO_UNDERRUN; 20248bcc0840SMatt Roper 20258bcc0840SMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 20268bcc0840SMatt Roper mask |= XELPD_PIPE_SOFT_UNDERRUN | 20278bcc0840SMatt Roper XELPD_PIPE_HARD_UNDERRUN; 20288bcc0840SMatt Roper 20298bcc0840SMatt Roper return mask; 20308bcc0840SMatt Roper } 20318bcc0840SMatt Roper 203246c63d24SJosé Roberto de Souza static irqreturn_t 203346c63d24SJosé Roberto de Souza gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 203446c63d24SJosé Roberto de Souza { 203546c63d24SJosé Roberto de Souza irqreturn_t ret = IRQ_NONE; 203646c63d24SJosé Roberto de Souza u32 iir; 203746c63d24SJosé Roberto de Souza enum pipe pipe; 203846c63d24SJosé Roberto de Souza 2039a844cfbeSJosé Roberto de Souza drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv)); 2040a844cfbeSJosé Roberto de Souza 204146c63d24SJosé Roberto de Souza if (master_ctl & GEN8_DE_MISC_IRQ) { 20422939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR); 204346c63d24SJosé Roberto de Souza if (iir) { 20442939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir); 204546c63d24SJosé Roberto de Souza ret = IRQ_HANDLED; 204646c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(dev_priv, iir); 204746c63d24SJosé Roberto de Souza } else { 20489a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 204900376ccfSWambui Karuga "The master control interrupt lied (DE MISC)!\n"); 2050abd58f01SBen Widawsky } 205146c63d24SJosé Roberto de Souza } 2052abd58f01SBen Widawsky 2053373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 20542939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR); 2055121e758eSDhinakaran Pandiyan if (iir) { 20562939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir); 2057121e758eSDhinakaran Pandiyan ret = IRQ_HANDLED; 2058121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 2059121e758eSDhinakaran Pandiyan } else { 20609a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 206100376ccfSWambui Karuga "The master control interrupt lied, (DE HPD)!\n"); 2062121e758eSDhinakaran Pandiyan } 2063121e758eSDhinakaran Pandiyan } 2064121e758eSDhinakaran Pandiyan 20656d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 20662939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR); 2067e32192e1STvrtko Ursulin if (iir) { 2068d04a492dSShashank Sharma bool found = false; 2069cebd87a0SVille Syrjälä 20702939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir); 20716d766f02SDaniel Vetter ret = IRQ_HANDLED; 207288e04703SJesse Barnes 20739d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 207491d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2075d04a492dSShashank Sharma found = true; 2076d04a492dSShashank Sharma } 2077d04a492dSShashank Sharma 207870bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { 20799a55a620SVille Syrjälä u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK; 20809a55a620SVille Syrjälä 20819a55a620SVille Syrjälä if (hotplug_trigger) { 20829a55a620SVille Syrjälä bxt_hpd_irq_handler(dev_priv, hotplug_trigger); 2083d04a492dSShashank Sharma found = true; 2084d04a492dSShashank Sharma } 2085e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 20869a55a620SVille Syrjälä u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK; 20879a55a620SVille Syrjälä 20889a55a620SVille Syrjälä if (hotplug_trigger) { 20899a55a620SVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 2090e32192e1STvrtko Ursulin found = true; 2091e32192e1STvrtko Ursulin } 2092e32192e1STvrtko Ursulin } 2093d04a492dSShashank Sharma 209470bfb307SMatt Roper if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) && 209570bfb307SMatt Roper (iir & BXT_DE_PORT_GMBUS)) { 209691d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 20979e63743eSShashank Sharma found = true; 20989e63743eSShashank Sharma } 20999e63743eSShashank Sharma 2100373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 21019a55a620SVille Syrjälä u32 te_trigger = iir & (DSI0_TE | DSI1_TE); 21029a55a620SVille Syrjälä 21039a55a620SVille Syrjälä if (te_trigger) { 21049a55a620SVille Syrjälä gen11_dsi_te_interrupt_handler(dev_priv, te_trigger); 210500acb329SVandita Kulkarni found = true; 210600acb329SVandita Kulkarni } 210700acb329SVandita Kulkarni } 210800acb329SVandita Kulkarni 2109d04a492dSShashank Sharma if (!found) 21109a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 211100376ccfSWambui Karuga "Unexpected DE Port interrupt\n"); 21126d766f02SDaniel Vetter } 211338cc46d7SOscar Mateo else 21149a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 211500376ccfSWambui Karuga "The master control interrupt lied (DE PORT)!\n"); 21166d766f02SDaniel Vetter } 21176d766f02SDaniel Vetter 2118055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2119fd3a4024SDaniel Vetter u32 fault_errors; 2120abd58f01SBen Widawsky 2121c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 2122c42664ccSDaniel Vetter continue; 2123c42664ccSDaniel Vetter 21242939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); 2125e32192e1STvrtko Ursulin if (!iir) { 21269a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 212700376ccfSWambui Karuga "The master control interrupt lied (DE PIPE)!\n"); 2128e32192e1STvrtko Ursulin continue; 2129e32192e1STvrtko Ursulin } 2130770de83dSDamien Lespiau 2131e32192e1STvrtko Ursulin ret = IRQ_HANDLED; 21322939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir); 2133e32192e1STvrtko Ursulin 2134fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 2135aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 2136abd58f01SBen Widawsky 2137cda195f1SVille Syrjälä if (iir & gen8_de_pipe_flip_done_mask(dev_priv)) 21381288f9b0SKarthik B S flip_done_handler(dev_priv, pipe); 21391288f9b0SKarthik B S 2140e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 214191d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 21420fbe7870SDaniel Vetter 21438bcc0840SMatt Roper if (iir & gen8_de_pipe_underrun_mask(dev_priv)) 2144e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 214538d83c96SDaniel Vetter 21465270130dSVille Syrjälä fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); 2147770de83dSDamien Lespiau if (fault_errors) 21489a4cea62SLucas De Marchi drm_err_ratelimited(&dev_priv->drm, 214900376ccfSWambui Karuga "Fault errors on pipe %c: 0x%08x\n", 215030100f2bSDaniel Vetter pipe_name(pipe), 2151e32192e1STvrtko Ursulin fault_errors); 2152abd58f01SBen Widawsky } 2153abd58f01SBen Widawsky 215491d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 2155266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 215692d03a80SDaniel Vetter /* 215792d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 215892d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 215992d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 216092d03a80SDaniel Vetter */ 21612939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 2162e32192e1STvrtko Ursulin if (iir) { 21632939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, iir); 216492d03a80SDaniel Vetter ret = IRQ_HANDLED; 21656dbf30ceSVille Syrjälä 216658676af6SLucas De Marchi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 216758676af6SLucas De Marchi icp_irq_handler(dev_priv, iir); 2168c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 216991d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 21706dbf30ceSVille Syrjälä else 217191d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 21722dfb0b81SJani Nikula } else { 21732dfb0b81SJani Nikula /* 21742dfb0b81SJani Nikula * Like on previous PCH there seems to be something 21752dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 21762dfb0b81SJani Nikula */ 217700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 217800376ccfSWambui Karuga "The master control interrupt lied (SDE)!\n"); 21792dfb0b81SJani Nikula } 218092d03a80SDaniel Vetter } 218192d03a80SDaniel Vetter 2182f11a0f46STvrtko Ursulin return ret; 2183f11a0f46STvrtko Ursulin } 2184f11a0f46STvrtko Ursulin 21854376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 21864376b9c9SMika Kuoppala { 21874376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 21884376b9c9SMika Kuoppala 21894376b9c9SMika Kuoppala /* 21904376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 21914376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 21924376b9c9SMika Kuoppala * New indications can and will light up during processing, 21934376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 21944376b9c9SMika Kuoppala */ 21954376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 21964376b9c9SMika Kuoppala } 21974376b9c9SMika Kuoppala 21984376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 21994376b9c9SMika Kuoppala { 22004376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 22014376b9c9SMika Kuoppala } 22024376b9c9SMika Kuoppala 2203f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 2204f11a0f46STvrtko Ursulin { 2205b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 220625286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 2207f11a0f46STvrtko Ursulin u32 master_ctl; 2208f11a0f46STvrtko Ursulin 2209f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 2210f11a0f46STvrtko Ursulin return IRQ_NONE; 2211f11a0f46STvrtko Ursulin 22124376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 22134376b9c9SMika Kuoppala if (!master_ctl) { 22144376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2215f11a0f46STvrtko Ursulin return IRQ_NONE; 22164376b9c9SMika Kuoppala } 2217f11a0f46STvrtko Ursulin 22186cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 22192cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 2220f0fd96f5SChris Wilson 2221f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2222f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 22239102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 222455ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 22259102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 2226f0fd96f5SChris Wilson } 2227f11a0f46STvrtko Ursulin 22284376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2229abd58f01SBen Widawsky 22309c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 22319c6508b9SThomas Gleixner 223255ef72f2SChris Wilson return IRQ_HANDLED; 2233abd58f01SBen Widawsky } 2234abd58f01SBen Widawsky 223551951ae7SMika Kuoppala static u32 2236ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl) 2237df0d28c1SDhinakaran Pandiyan { 2238ddcf980fSAnusha Srivatsa void __iomem * const regs = i915->uncore.regs; 22397a909383SChris Wilson u32 iir; 2240df0d28c1SDhinakaran Pandiyan 2241df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 22427a909383SChris Wilson return 0; 2243df0d28c1SDhinakaran Pandiyan 22447a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 22457a909383SChris Wilson if (likely(iir)) 22467a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 22477a909383SChris Wilson 22487a909383SChris Wilson return iir; 2249df0d28c1SDhinakaran Pandiyan } 2250df0d28c1SDhinakaran Pandiyan 2251df0d28c1SDhinakaran Pandiyan static void 2252ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir) 2253df0d28c1SDhinakaran Pandiyan { 2254df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 2255ddcf980fSAnusha Srivatsa intel_opregion_asle_intr(i915); 2256df0d28c1SDhinakaran Pandiyan } 2257df0d28c1SDhinakaran Pandiyan 225881067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 225981067b71SMika Kuoppala { 226081067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 226181067b71SMika Kuoppala 226281067b71SMika Kuoppala /* 226381067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 226481067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 226581067b71SMika Kuoppala * New indications can and will light up during processing, 226681067b71SMika Kuoppala * and will generate new interrupt after enabling master. 226781067b71SMika Kuoppala */ 226881067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 226981067b71SMika Kuoppala } 227081067b71SMika Kuoppala 227181067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 227281067b71SMika Kuoppala { 227381067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 227481067b71SMika Kuoppala } 227581067b71SMika Kuoppala 2276a3265d85SMatt Roper static void 2277a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915) 2278a3265d85SMatt Roper { 2279a3265d85SMatt Roper void __iomem * const regs = i915->uncore.regs; 2280a3265d85SMatt Roper const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 2281a3265d85SMatt Roper 2282a3265d85SMatt Roper disable_rpm_wakeref_asserts(&i915->runtime_pm); 2283a3265d85SMatt Roper /* 2284a3265d85SMatt Roper * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 2285a3265d85SMatt Roper * for the display related bits. 2286a3265d85SMatt Roper */ 2287a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); 2288a3265d85SMatt Roper gen8_de_irq_handler(i915, disp_ctl); 2289a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 2290a3265d85SMatt Roper GEN11_DISPLAY_IRQ_ENABLE); 2291a3265d85SMatt Roper 2292a3265d85SMatt Roper enable_rpm_wakeref_asserts(&i915->runtime_pm); 2293a3265d85SMatt Roper } 2294a3265d85SMatt Roper 229522e26af7SPaulo Zanoni static irqreturn_t gen11_irq_handler(int irq, void *arg) 229651951ae7SMika Kuoppala { 229722e26af7SPaulo Zanoni struct drm_i915_private *i915 = arg; 229825286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 22992cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 230051951ae7SMika Kuoppala u32 master_ctl; 2301df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 230251951ae7SMika Kuoppala 230351951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 230451951ae7SMika Kuoppala return IRQ_NONE; 230551951ae7SMika Kuoppala 230622e26af7SPaulo Zanoni master_ctl = gen11_master_intr_disable(regs); 230781067b71SMika Kuoppala if (!master_ctl) { 230822e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 230951951ae7SMika Kuoppala return IRQ_NONE; 231081067b71SMika Kuoppala } 231151951ae7SMika Kuoppala 23126cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 23139b77011eSTvrtko Ursulin gen11_gt_irq_handler(gt, master_ctl); 231451951ae7SMika Kuoppala 231551951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2316a3265d85SMatt Roper if (master_ctl & GEN11_DISPLAY_IRQ) 2317a3265d85SMatt Roper gen11_display_irq_handler(i915); 231851951ae7SMika Kuoppala 2319ddcf980fSAnusha Srivatsa gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 2320df0d28c1SDhinakaran Pandiyan 232122e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 232251951ae7SMika Kuoppala 2323ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(i915, gu_misc_iir); 2324df0d28c1SDhinakaran Pandiyan 23259c6508b9SThomas Gleixner pmu_irq_stats(i915, IRQ_HANDLED); 23269c6508b9SThomas Gleixner 232751951ae7SMika Kuoppala return IRQ_HANDLED; 232851951ae7SMika Kuoppala } 232951951ae7SMika Kuoppala 233022e26af7SPaulo Zanoni static inline u32 dg1_master_intr_disable(void __iomem * const regs) 233197b492f5SLucas De Marchi { 233297b492f5SLucas De Marchi u32 val; 233397b492f5SLucas De Marchi 233497b492f5SLucas De Marchi /* First disable interrupts */ 233522e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0); 233697b492f5SLucas De Marchi 233797b492f5SLucas De Marchi /* Get the indication levels and ack the master unit */ 233822e26af7SPaulo Zanoni val = raw_reg_read(regs, DG1_MSTR_TILE_INTR); 233997b492f5SLucas De Marchi if (unlikely(!val)) 234097b492f5SLucas De Marchi return 0; 234197b492f5SLucas De Marchi 234222e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, val); 234397b492f5SLucas De Marchi 234497b492f5SLucas De Marchi return val; 234597b492f5SLucas De Marchi } 234697b492f5SLucas De Marchi 234797b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs) 234897b492f5SLucas De Marchi { 234922e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ); 235097b492f5SLucas De Marchi } 235197b492f5SLucas De Marchi 235297b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg) 235397b492f5SLucas De Marchi { 235422e26af7SPaulo Zanoni struct drm_i915_private * const i915 = arg; 23552cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 2356fd4d7904SPaulo Zanoni void __iomem * const regs = gt->uncore->regs; 235722e26af7SPaulo Zanoni u32 master_tile_ctl, master_ctl; 235822e26af7SPaulo Zanoni u32 gu_misc_iir; 235922e26af7SPaulo Zanoni 236022e26af7SPaulo Zanoni if (!intel_irqs_enabled(i915)) 236122e26af7SPaulo Zanoni return IRQ_NONE; 236222e26af7SPaulo Zanoni 236322e26af7SPaulo Zanoni master_tile_ctl = dg1_master_intr_disable(regs); 236422e26af7SPaulo Zanoni if (!master_tile_ctl) { 236522e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 236622e26af7SPaulo Zanoni return IRQ_NONE; 236722e26af7SPaulo Zanoni } 236822e26af7SPaulo Zanoni 236922e26af7SPaulo Zanoni /* FIXME: we only support tile 0 for now. */ 237022e26af7SPaulo Zanoni if (master_tile_ctl & DG1_MSTR_TILE(0)) { 237122e26af7SPaulo Zanoni master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 237222e26af7SPaulo Zanoni raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl); 237322e26af7SPaulo Zanoni } else { 2374a10234fdSTvrtko Ursulin drm_err(&i915->drm, "Tile not supported: 0x%08x\n", 2375a10234fdSTvrtko Ursulin master_tile_ctl); 237622e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 237722e26af7SPaulo Zanoni return IRQ_NONE; 237822e26af7SPaulo Zanoni } 237922e26af7SPaulo Zanoni 238022e26af7SPaulo Zanoni gen11_gt_irq_handler(gt, master_ctl); 238122e26af7SPaulo Zanoni 238222e26af7SPaulo Zanoni if (master_ctl & GEN11_DISPLAY_IRQ) 238322e26af7SPaulo Zanoni gen11_display_irq_handler(i915); 238422e26af7SPaulo Zanoni 2385ddcf980fSAnusha Srivatsa gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); 238622e26af7SPaulo Zanoni 238722e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 238822e26af7SPaulo Zanoni 2389ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(i915, gu_misc_iir); 239022e26af7SPaulo Zanoni 239122e26af7SPaulo Zanoni pmu_irq_stats(i915, IRQ_HANDLED); 239222e26af7SPaulo Zanoni 239322e26af7SPaulo Zanoni return IRQ_HANDLED; 239497b492f5SLucas De Marchi } 239597b492f5SLucas De Marchi 239642f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 239742f52ef8SKeith Packard * we use as a pipe index 239842f52ef8SKeith Packard */ 239908fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc) 24000a3e67a4SJesse Barnes { 240108fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 240208fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2403e9d21d7fSKeith Packard unsigned long irqflags; 240471e0ffa5SJesse Barnes 24051ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 240686e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 240786e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 240886e83e35SChris Wilson 240986e83e35SChris Wilson return 0; 241086e83e35SChris Wilson } 241186e83e35SChris Wilson 24127d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc) 2413d938da6bSVille Syrjälä { 241408fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2415d938da6bSVille Syrjälä 24167d423af9SVille Syrjälä /* 24177d423af9SVille Syrjälä * Vblank interrupts fail to wake the device up from C2+. 24187d423af9SVille Syrjälä * Disabling render clock gating during C-states avoids 24197d423af9SVille Syrjälä * the problem. There is a small power cost so we do this 24207d423af9SVille Syrjälä * only when vblank interrupts are actually enabled. 24217d423af9SVille Syrjälä */ 24227d423af9SVille Syrjälä if (dev_priv->vblank_enabled++ == 0) 24232939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2424d938da6bSVille Syrjälä 242508fa8fd0SVille Syrjälä return i8xx_enable_vblank(crtc); 2426d938da6bSVille Syrjälä } 2427d938da6bSVille Syrjälä 242808fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc) 242986e83e35SChris Wilson { 243008fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 243108fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 243286e83e35SChris Wilson unsigned long irqflags; 243386e83e35SChris Wilson 243486e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 24357c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 2436755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 24371ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 24388692d00eSChris Wilson 24390a3e67a4SJesse Barnes return 0; 24400a3e67a4SJesse Barnes } 24410a3e67a4SJesse Barnes 244208fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc) 2443f796cf8fSJesse Barnes { 244408fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 244508fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2446f796cf8fSJesse Barnes unsigned long irqflags; 2447373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 244886e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2449f796cf8fSJesse Barnes 2450f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2451fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 2452b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2453b1f14ad0SJesse Barnes 24542e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 24552e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 24562e8bf223SDhinakaran Pandiyan */ 24572e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 245808fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 24592e8bf223SDhinakaran Pandiyan 2460b1f14ad0SJesse Barnes return 0; 2461b1f14ad0SJesse Barnes } 2462b1f14ad0SJesse Barnes 24639c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, 24649c9e97c4SVandita Kulkarni bool enable) 24659c9e97c4SVandita Kulkarni { 24669c9e97c4SVandita Kulkarni struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); 24679c9e97c4SVandita Kulkarni enum port port; 24689c9e97c4SVandita Kulkarni 24699c9e97c4SVandita Kulkarni if (!(intel_crtc->mode_flags & 24709c9e97c4SVandita Kulkarni (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0))) 24719c9e97c4SVandita Kulkarni return false; 24729c9e97c4SVandita Kulkarni 24739c9e97c4SVandita Kulkarni /* for dual link cases we consider TE from slave */ 24749c9e97c4SVandita Kulkarni if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1) 24759c9e97c4SVandita Kulkarni port = PORT_B; 24769c9e97c4SVandita Kulkarni else 24779c9e97c4SVandita Kulkarni port = PORT_A; 24789c9e97c4SVandita Kulkarni 24798cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT, 24808cee664dSAndrzej Hajda enable ? 0 : DSI_TE_EVENT); 24819c9e97c4SVandita Kulkarni 24828cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0); 24839c9e97c4SVandita Kulkarni 24849c9e97c4SVandita Kulkarni return true; 24859c9e97c4SVandita Kulkarni } 24869c9e97c4SVandita Kulkarni 2487f15f01a7SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *_crtc) 2488abd58f01SBen Widawsky { 2489f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 2490f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2491f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 2492abd58f01SBen Widawsky unsigned long irqflags; 2493abd58f01SBen Widawsky 2494f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, true)) 24959c9e97c4SVandita Kulkarni return 0; 24969c9e97c4SVandita Kulkarni 2497abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2498013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2499abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2500013d3752SVille Syrjälä 25012e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 25022e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 25032e8bf223SDhinakaran Pandiyan */ 25042e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 2505f15f01a7SVille Syrjälä drm_crtc_vblank_restore(&crtc->base); 25062e8bf223SDhinakaran Pandiyan 2507abd58f01SBen Widawsky return 0; 2508abd58f01SBen Widawsky } 2509abd58f01SBen Widawsky 251042f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 251142f52ef8SKeith Packard * we use as a pipe index 251242f52ef8SKeith Packard */ 251308fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc) 251486e83e35SChris Wilson { 251508fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 251608fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 251786e83e35SChris Wilson unsigned long irqflags; 251886e83e35SChris Wilson 251986e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 252086e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 252186e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 252286e83e35SChris Wilson } 252386e83e35SChris Wilson 25247d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc) 2525d938da6bSVille Syrjälä { 252608fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2527d938da6bSVille Syrjälä 252808fa8fd0SVille Syrjälä i8xx_disable_vblank(crtc); 2529d938da6bSVille Syrjälä 25307d423af9SVille Syrjälä if (--dev_priv->vblank_enabled == 0) 25312939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2532d938da6bSVille Syrjälä } 2533d938da6bSVille Syrjälä 253408fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc) 25350a3e67a4SJesse Barnes { 253608fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 253708fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2538e9d21d7fSKeith Packard unsigned long irqflags; 25390a3e67a4SJesse Barnes 25401ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 25417c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 2542755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 25431ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 25440a3e67a4SJesse Barnes } 25450a3e67a4SJesse Barnes 254608fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc) 2547f796cf8fSJesse Barnes { 254808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 254908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2550f796cf8fSJesse Barnes unsigned long irqflags; 2551373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 255286e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2553f796cf8fSJesse Barnes 2554f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2555fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 2556b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2557b1f14ad0SJesse Barnes } 2558b1f14ad0SJesse Barnes 2559f15f01a7SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *_crtc) 2560abd58f01SBen Widawsky { 2561f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 2562f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2563f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 2564abd58f01SBen Widawsky unsigned long irqflags; 2565abd58f01SBen Widawsky 2566f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, false)) 25679c9e97c4SVandita Kulkarni return; 25689c9e97c4SVandita Kulkarni 2569abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2570013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2571abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2572abd58f01SBen Widawsky } 2573abd58f01SBen Widawsky 2574b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 257591738a95SPaulo Zanoni { 2576b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2577b16b2a2fSPaulo Zanoni 25786e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 257991738a95SPaulo Zanoni return; 258091738a95SPaulo Zanoni 2581b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 2582105b122eSPaulo Zanoni 25836e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 25842939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff); 2585622364b6SPaulo Zanoni } 2586105b122eSPaulo Zanoni 258770591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 258870591a41SVille Syrjälä { 2589b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2590b16b2a2fSPaulo Zanoni 259171b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2592f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 259371b8b41dSVille Syrjälä else 25947d938bc0SVille Syrjälä intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); 259571b8b41dSVille Syrjälä 2596ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 25978cee664dSAndrzej Hajda intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); 259870591a41SVille Syrjälä 259944d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 260070591a41SVille Syrjälä 2601b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, VLV_); 26028bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 260370591a41SVille Syrjälä } 260470591a41SVille Syrjälä 26058bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 26068bb61306SVille Syrjälä { 2607b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2608b16b2a2fSPaulo Zanoni 26098bb61306SVille Syrjälä u32 pipestat_mask; 26109ab981f2SVille Syrjälä u32 enable_mask; 26118bb61306SVille Syrjälä enum pipe pipe; 26128bb61306SVille Syrjälä 2613842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 26148bb61306SVille Syrjälä 26158bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 26168bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 26178bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 26188bb61306SVille Syrjälä 26199ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 26208bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2621ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 2622ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 2623ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 2624ebf5f921SVille Syrjälä 26258bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2626ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 2627ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 26286b7eafc1SVille Syrjälä 262948a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u); 26306b7eafc1SVille Syrjälä 26319ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 26328bb61306SVille Syrjälä 2633b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask); 26348bb61306SVille Syrjälä } 26358bb61306SVille Syrjälä 26368bb61306SVille Syrjälä /* drm_dma.h hooks 26378bb61306SVille Syrjälä */ 26389eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv) 26398bb61306SVille Syrjälä { 2640b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 26418bb61306SVille Syrjälä 2642b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, DE); 2643e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 2644e44adb5dSChris Wilson 2645651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) == 7) 2646f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); 26478bb61306SVille Syrjälä 2648fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 2649f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2650f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2651fc340442SDaniel Vetter } 2652fc340442SDaniel Vetter 26532cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 26548bb61306SVille Syrjälä 2655b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 26568bb61306SVille Syrjälä } 26578bb61306SVille Syrjälä 2658b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv) 26597e231dbeSJesse Barnes { 26602939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 26612939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 266234c7b8a7SVille Syrjälä 26632cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 26647e231dbeSJesse Barnes 2665ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 26669918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 266770591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2668ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 26697e231dbeSJesse Barnes } 26707e231dbeSJesse Barnes 2671a844cfbeSJosé Roberto de Souza static void gen8_display_irq_reset(struct drm_i915_private *dev_priv) 2672abd58f01SBen Widawsky { 2673b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2674d048a268SVille Syrjälä enum pipe pipe; 2675abd58f01SBen Widawsky 2676a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2677a844cfbeSJosé Roberto de Souza return; 2678abd58f01SBen Widawsky 2679f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2680f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 2681e04f7eceSVille Syrjälä 2682055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 2683f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 2684813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 2685b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 2686abd58f01SBen Widawsky 2687b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2688b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2689a844cfbeSJosé Roberto de Souza } 2690a844cfbeSJosé Roberto de Souza 2691a844cfbeSJosé Roberto de Souza static void gen8_irq_reset(struct drm_i915_private *dev_priv) 2692a844cfbeSJosé Roberto de Souza { 2693a844cfbeSJosé Roberto de Souza struct intel_uncore *uncore = &dev_priv->uncore; 2694a844cfbeSJosé Roberto de Souza 2695e58c2cacSAndrzej Hajda gen8_master_intr_disable(uncore->regs); 2696a844cfbeSJosé Roberto de Souza 26972cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 2698a844cfbeSJosé Roberto de Souza gen8_display_irq_reset(dev_priv); 2699b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 2700abd58f01SBen Widawsky 27016e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 2702b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 270359b7cb44STejas Upadhyay 2704abd58f01SBen Widawsky } 2705abd58f01SBen Widawsky 2706a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) 270751951ae7SMika Kuoppala { 2708b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2709d048a268SVille Syrjälä enum pipe pipe; 2710562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 2711562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 271251951ae7SMika Kuoppala 2713a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 2714a844cfbeSJosé Roberto de Souza return; 2715a844cfbeSJosé Roberto de Souza 2716f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); 271751951ae7SMika Kuoppala 2718373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 27198241cfbeSJosé Roberto de Souza enum transcoder trans; 27208241cfbeSJosé Roberto de Souza 2721562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 27228241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 27238241cfbeSJosé Roberto de Souza 27248241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 27258241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 27268241cfbeSJosé Roberto de Souza continue; 27278241cfbeSJosé Roberto de Souza 27288241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff); 27298241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff); 27308241cfbeSJosé Roberto de Souza } 27318241cfbeSJosé Roberto de Souza } else { 2732f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 2733f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 27348241cfbeSJosé Roberto de Souza } 273562819dfdSJosé Roberto de Souza 273651951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 273751951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 273851951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 2739b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 274051951ae7SMika Kuoppala 2741b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 2742b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 2743b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); 274431604222SAnusha Srivatsa 274529b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2746b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 274751951ae7SMika Kuoppala } 274851951ae7SMika Kuoppala 2749a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv) 2750a3265d85SMatt Roper { 27512cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2752fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 2753a3265d85SMatt Roper 2754a3265d85SMatt Roper gen11_master_intr_disable(dev_priv->uncore.regs); 2755a3265d85SMatt Roper 2756fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 2757a3265d85SMatt Roper gen11_display_irq_reset(dev_priv); 2758a3265d85SMatt Roper 2759a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 2760a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN8_PCU_); 2761a3265d85SMatt Roper } 2762a3265d85SMatt Roper 276322e26af7SPaulo Zanoni static void dg1_irq_reset(struct drm_i915_private *dev_priv) 276422e26af7SPaulo Zanoni { 27652cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 2766fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 276722e26af7SPaulo Zanoni 276822e26af7SPaulo Zanoni dg1_master_intr_disable(dev_priv->uncore.regs); 276922e26af7SPaulo Zanoni 2770fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 277122e26af7SPaulo Zanoni gen11_display_irq_reset(dev_priv); 277222e26af7SPaulo Zanoni 277322e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 277422e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 277522e26af7SPaulo Zanoni } 277622e26af7SPaulo Zanoni 27774c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 2778001bd2cbSImre Deak u8 pipe_mask) 2779d49bdb0eSPaulo Zanoni { 2780b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 27818bcc0840SMatt Roper u32 extra_ier = GEN8_PIPE_VBLANK | 27828bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 2783cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 27846831f3e3SVille Syrjälä enum pipe pipe; 2785d49bdb0eSPaulo Zanoni 278613321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 27879dfe2e3aSImre Deak 27889dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 27899dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 27909dfe2e3aSImre Deak return; 27919dfe2e3aSImre Deak } 27929dfe2e3aSImre Deak 27936831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2794b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 27956831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 27966831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 27979dfe2e3aSImre Deak 279813321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 2799d49bdb0eSPaulo Zanoni } 2800d49bdb0eSPaulo Zanoni 2801aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 2802001bd2cbSImre Deak u8 pipe_mask) 2803aae8ba84SVille Syrjälä { 2804b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 28056831f3e3SVille Syrjälä enum pipe pipe; 28066831f3e3SVille Syrjälä 2807aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 28089dfe2e3aSImre Deak 28099dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 28109dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 28119dfe2e3aSImre Deak return; 28129dfe2e3aSImre Deak } 28139dfe2e3aSImre Deak 28146831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 2815b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 28169dfe2e3aSImre Deak 2817aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 2818aae8ba84SVille Syrjälä 2819aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 2820315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 2821aae8ba84SVille Syrjälä } 2822aae8ba84SVille Syrjälä 2823b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv) 282443f328d7SVille Syrjälä { 2825b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 282643f328d7SVille Syrjälä 2827e58c2cacSAndrzej Hajda intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0); 28282939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 282943f328d7SVille Syrjälä 28302cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 283143f328d7SVille Syrjälä 2832b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 283343f328d7SVille Syrjälä 2834ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 28359918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 283670591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 2837ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 283843f328d7SVille Syrjälä } 283943f328d7SVille Syrjälä 2840dfefe7bcSVille Syrjälä static u32 ibx_hotplug_enables(struct intel_encoder *encoder) 28412ea63927SVille Syrjälä { 2842dfefe7bcSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 2843dfefe7bcSVille Syrjälä 2844dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 28452ea63927SVille Syrjälä case HPD_PORT_A: 28462ea63927SVille Syrjälä /* 28472ea63927SVille Syrjälä * When CPU and PCH are on the same package, port A 28482ea63927SVille Syrjälä * HPD must be enabled in both north and south. 28492ea63927SVille Syrjälä */ 28502ea63927SVille Syrjälä return HAS_PCH_LPT_LP(i915) ? 28512ea63927SVille Syrjälä PORTA_HOTPLUG_ENABLE : 0; 28522ea63927SVille Syrjälä case HPD_PORT_B: 28532ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE | 28542ea63927SVille Syrjälä PORTB_PULSE_DURATION_2ms; 28552ea63927SVille Syrjälä case HPD_PORT_C: 28562ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE | 28572ea63927SVille Syrjälä PORTC_PULSE_DURATION_2ms; 28582ea63927SVille Syrjälä case HPD_PORT_D: 28592ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE | 28602ea63927SVille Syrjälä PORTD_PULSE_DURATION_2ms; 28612ea63927SVille Syrjälä default: 28622ea63927SVille Syrjälä return 0; 28632ea63927SVille Syrjälä } 28642ea63927SVille Syrjälä } 28652ea63927SVille Syrjälä 28661a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) 28671a56b1a2SImre Deak { 28681a56b1a2SImre Deak /* 28691a56b1a2SImre Deak * Enable digital hotplug on the PCH, and configure the DP short pulse 28701a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec). 28711a56b1a2SImre Deak * The pulse duration bits are reserved on LPT+. 28721a56b1a2SImre Deak */ 28738cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 28748cee664dSAndrzej Hajda PORTA_HOTPLUG_ENABLE | 28752ea63927SVille Syrjälä PORTB_HOTPLUG_ENABLE | 28762ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 28772ea63927SVille Syrjälä PORTD_HOTPLUG_ENABLE | 28782ea63927SVille Syrjälä PORTB_PULSE_DURATION_MASK | 28791a56b1a2SImre Deak PORTC_PULSE_DURATION_MASK | 28808cee664dSAndrzej Hajda PORTD_PULSE_DURATION_MASK, 28818cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables)); 28821a56b1a2SImre Deak } 28831a56b1a2SImre Deak 288491d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) 288582a28bcfSDaniel Vetter { 28861a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 288782a28bcfSDaniel Vetter 28885a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 28895a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 289082a28bcfSDaniel Vetter 2891fee884edSDaniel Vetter ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 289282a28bcfSDaniel Vetter 28931a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 28946dbf30ceSVille Syrjälä } 289526951cafSXiong Zhang 2896dfefe7bcSVille Syrjälä static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder) 28972ea63927SVille Syrjälä { 2898dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 28992ea63927SVille Syrjälä case HPD_PORT_A: 29002ea63927SVille Syrjälä case HPD_PORT_B: 29012ea63927SVille Syrjälä case HPD_PORT_C: 29022ea63927SVille Syrjälä case HPD_PORT_D: 2903dfefe7bcSVille Syrjälä return SHOTPLUG_CTL_DDI_HPD_ENABLE(encoder->hpd_pin); 29042ea63927SVille Syrjälä default: 29052ea63927SVille Syrjälä return 0; 29062ea63927SVille Syrjälä } 29072ea63927SVille Syrjälä } 29082ea63927SVille Syrjälä 2909dfefe7bcSVille Syrjälä static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder) 29102ea63927SVille Syrjälä { 2911dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 29122ea63927SVille Syrjälä case HPD_PORT_TC1: 29132ea63927SVille Syrjälä case HPD_PORT_TC2: 29142ea63927SVille Syrjälä case HPD_PORT_TC3: 29152ea63927SVille Syrjälä case HPD_PORT_TC4: 29162ea63927SVille Syrjälä case HPD_PORT_TC5: 29172ea63927SVille Syrjälä case HPD_PORT_TC6: 2918dfefe7bcSVille Syrjälä return ICP_TC_HPD_ENABLE(encoder->hpd_pin); 29192ea63927SVille Syrjälä default: 29202ea63927SVille Syrjälä return 0; 29212ea63927SVille Syrjälä } 29222ea63927SVille Syrjälä } 29232ea63927SVille Syrjälä 29242ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv) 292531604222SAnusha Srivatsa { 29268cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 29278cee664dSAndrzej Hajda SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) | 29282ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | 29292ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | 29308cee664dSAndrzej Hajda SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D), 29318cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables)); 293231604222SAnusha Srivatsa } 2933815f4ef2SVille Syrjälä 29342ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 2935815f4ef2SVille Syrjälä { 29368cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 29378cee664dSAndrzej Hajda ICP_TC_HPD_ENABLE(HPD_PORT_TC1) | 29382ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | 29392ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | 29402ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | 29412ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | 29428cee664dSAndrzej Hajda ICP_TC_HPD_ENABLE(HPD_PORT_TC6), 29438cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables)); 29448ef7e340SMatt Roper } 294531604222SAnusha Srivatsa 29462ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) 294731604222SAnusha Srivatsa { 294831604222SAnusha Srivatsa u32 hotplug_irqs, enabled_irqs; 294931604222SAnusha Srivatsa 29505a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 29515a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 295231604222SAnusha Srivatsa 2953f619e516SAnusha Srivatsa if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) 29542939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 2955f49108d0SMatt Roper 295631604222SAnusha Srivatsa ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 295731604222SAnusha Srivatsa 29582ea63927SVille Syrjälä icp_ddi_hpd_detection_setup(dev_priv); 29592ea63927SVille Syrjälä icp_tc_hpd_detection_setup(dev_priv); 296052dfdba0SLucas De Marchi } 296152dfdba0SLucas De Marchi 2962dfefe7bcSVille Syrjälä static u32 gen11_hotplug_enables(struct intel_encoder *encoder) 29638ef7e340SMatt Roper { 2964dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 29652ea63927SVille Syrjälä case HPD_PORT_TC1: 29662ea63927SVille Syrjälä case HPD_PORT_TC2: 29672ea63927SVille Syrjälä case HPD_PORT_TC3: 29682ea63927SVille Syrjälä case HPD_PORT_TC4: 29692ea63927SVille Syrjälä case HPD_PORT_TC5: 29702ea63927SVille Syrjälä case HPD_PORT_TC6: 2971dfefe7bcSVille Syrjälä return GEN11_HOTPLUG_CTL_ENABLE(encoder->hpd_pin); 29722ea63927SVille Syrjälä default: 29732ea63927SVille Syrjälä return 0; 297431604222SAnusha Srivatsa } 2975943682e3SMatt Roper } 2976943682e3SMatt Roper 297771690148SGustavo Sousa static void dg1_hpd_invert(struct drm_i915_private *i915) 2978229f31e2SLucas De Marchi { 297971690148SGustavo Sousa u32 val = (INVERT_DDIA_HPD | 2980b18c1eb9SClinton A Taylor INVERT_DDIB_HPD | 2981b18c1eb9SClinton A Taylor INVERT_DDIC_HPD | 2982b18c1eb9SClinton A Taylor INVERT_DDID_HPD); 298371690148SGustavo Sousa intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val); 298471690148SGustavo Sousa } 2985b18c1eb9SClinton A Taylor 298671690148SGustavo Sousa static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) 298771690148SGustavo Sousa { 298871690148SGustavo Sousa dg1_hpd_invert(dev_priv); 29892ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 2990229f31e2SLucas De Marchi } 2991229f31e2SLucas De Marchi 299252c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 2993121e758eSDhinakaran Pandiyan { 29948cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 29958cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 29965b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 29975b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 29985b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 29995b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 30008cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6), 30018cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables)); 300252c7f5f1SVille Syrjälä } 300352c7f5f1SVille Syrjälä 300452c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv) 300552c7f5f1SVille Syrjälä { 30068cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 30078cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 30085b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 30095b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 30105b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 30115b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 30128cee664dSAndrzej Hajda GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6), 30138cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables)); 3014121e758eSDhinakaran Pandiyan } 3015121e758eSDhinakaran Pandiyan 3016121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) 3017121e758eSDhinakaran Pandiyan { 3018121e758eSDhinakaran Pandiyan u32 hotplug_irqs, enabled_irqs; 3019121e758eSDhinakaran Pandiyan 30205a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); 30215a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); 3022121e758eSDhinakaran Pandiyan 30238cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs, 30248cee664dSAndrzej Hajda ~enabled_irqs & hotplug_irqs); 30252939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); 3026121e758eSDhinakaran Pandiyan 302752c7f5f1SVille Syrjälä gen11_tc_hpd_detection_setup(dev_priv); 302852c7f5f1SVille Syrjälä gen11_tbt_hpd_detection_setup(dev_priv); 302931604222SAnusha Srivatsa 30302ea63927SVille Syrjälä if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 30312ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 30322ea63927SVille Syrjälä } 30332ea63927SVille Syrjälä 3034dfefe7bcSVille Syrjälä static u32 spt_hotplug_enables(struct intel_encoder *encoder) 30352ea63927SVille Syrjälä { 3036dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 30372ea63927SVille Syrjälä case HPD_PORT_A: 30382ea63927SVille Syrjälä return PORTA_HOTPLUG_ENABLE; 30392ea63927SVille Syrjälä case HPD_PORT_B: 30402ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE; 30412ea63927SVille Syrjälä case HPD_PORT_C: 30422ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE; 30432ea63927SVille Syrjälä case HPD_PORT_D: 30442ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE; 30452ea63927SVille Syrjälä default: 30462ea63927SVille Syrjälä return 0; 30472ea63927SVille Syrjälä } 30482ea63927SVille Syrjälä } 30492ea63927SVille Syrjälä 3050dfefe7bcSVille Syrjälä static u32 spt_hotplug2_enables(struct intel_encoder *encoder) 30512ea63927SVille Syrjälä { 3052dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 30532ea63927SVille Syrjälä case HPD_PORT_E: 30542ea63927SVille Syrjälä return PORTE_HOTPLUG_ENABLE; 30552ea63927SVille Syrjälä default: 30562ea63927SVille Syrjälä return 0; 30572ea63927SVille Syrjälä } 3058121e758eSDhinakaran Pandiyan } 3059121e758eSDhinakaran Pandiyan 30602a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) 30612a57d9ccSImre Deak { 30623b92e263SRodrigo Vivi /* Display WA #1179 WaHardHangonHotPlug: cnp */ 30633b92e263SRodrigo Vivi if (HAS_PCH_CNP(dev_priv)) { 30648cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK, 30658cee664dSAndrzej Hajda CHASSIS_CLK_REQ_DURATION(0xf)); 30663b92e263SRodrigo Vivi } 30672a57d9ccSImre Deak 30682a57d9ccSImre Deak /* Enable digital hotplug on the PCH */ 30698cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 30708cee664dSAndrzej Hajda PORTA_HOTPLUG_ENABLE | 30712a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 30722a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE | 30738cee664dSAndrzej Hajda PORTD_HOTPLUG_ENABLE, 30748cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables)); 30752a57d9ccSImre Deak 30768cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, PORTE_HOTPLUG_ENABLE, 30778cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables)); 30782a57d9ccSImre Deak } 30792a57d9ccSImre Deak 308091d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) 30816dbf30ceSVille Syrjälä { 30822a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 30836dbf30ceSVille Syrjälä 3084f49108d0SMatt Roper if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) 30852939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 3086f49108d0SMatt Roper 30875a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 30885a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd); 30896dbf30ceSVille Syrjälä 30906dbf30ceSVille Syrjälä ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 30916dbf30ceSVille Syrjälä 30922a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 309326951cafSXiong Zhang } 30947fe0b973SKeith Packard 3095dfefe7bcSVille Syrjälä static u32 ilk_hotplug_enables(struct intel_encoder *encoder) 30962ea63927SVille Syrjälä { 3097dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 30982ea63927SVille Syrjälä case HPD_PORT_A: 30992ea63927SVille Syrjälä return DIGITAL_PORTA_HOTPLUG_ENABLE | 31002ea63927SVille Syrjälä DIGITAL_PORTA_PULSE_DURATION_2ms; 31012ea63927SVille Syrjälä default: 31022ea63927SVille Syrjälä return 0; 31032ea63927SVille Syrjälä } 31042ea63927SVille Syrjälä } 31052ea63927SVille Syrjälä 31061a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) 31071a56b1a2SImre Deak { 31081a56b1a2SImre Deak /* 31091a56b1a2SImre Deak * Enable digital hotplug on the CPU, and configure the DP short pulse 31101a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec) 31111a56b1a2SImre Deak * The pulse duration bits are reserved on HSW+. 31121a56b1a2SImre Deak */ 31138cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 31148cee664dSAndrzej Hajda DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_MASK, 31158cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables)); 31161a56b1a2SImre Deak } 31171a56b1a2SImre Deak 311891d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) 3119e4ce95aaSVille Syrjälä { 31201a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 3121e4ce95aaSVille Syrjälä 31225a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31235a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31243a3b3c7dSVille Syrjälä 3125373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 8) 31263a3b3c7dSVille Syrjälä bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 31276d3144ebSVille Syrjälä else 31283a3b3c7dSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 3129e4ce95aaSVille Syrjälä 31301a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3131e4ce95aaSVille Syrjälä 313291d14251STvrtko Ursulin ibx_hpd_irq_setup(dev_priv); 3133e4ce95aaSVille Syrjälä } 3134e4ce95aaSVille Syrjälä 3135dfefe7bcSVille Syrjälä static u32 bxt_hotplug_enables(struct intel_encoder *encoder) 31362ea63927SVille Syrjälä { 31372ea63927SVille Syrjälä u32 hotplug; 31382ea63927SVille Syrjälä 3139dfefe7bcSVille Syrjälä switch (encoder->hpd_pin) { 31402ea63927SVille Syrjälä case HPD_PORT_A: 31412ea63927SVille Syrjälä hotplug = PORTA_HOTPLUG_ENABLE; 31429151c85cSVille Syrjälä if (intel_bios_encoder_hpd_invert(encoder->devdata)) 31432ea63927SVille Syrjälä hotplug |= BXT_DDIA_HPD_INVERT; 31442ea63927SVille Syrjälä return hotplug; 31452ea63927SVille Syrjälä case HPD_PORT_B: 31462ea63927SVille Syrjälä hotplug = PORTB_HOTPLUG_ENABLE; 31479151c85cSVille Syrjälä if (intel_bios_encoder_hpd_invert(encoder->devdata)) 31482ea63927SVille Syrjälä hotplug |= BXT_DDIB_HPD_INVERT; 31492ea63927SVille Syrjälä return hotplug; 31502ea63927SVille Syrjälä case HPD_PORT_C: 31512ea63927SVille Syrjälä hotplug = PORTC_HOTPLUG_ENABLE; 31529151c85cSVille Syrjälä if (intel_bios_encoder_hpd_invert(encoder->devdata)) 31532ea63927SVille Syrjälä hotplug |= BXT_DDIC_HPD_INVERT; 31542ea63927SVille Syrjälä return hotplug; 31552ea63927SVille Syrjälä default: 31562ea63927SVille Syrjälä return 0; 31572ea63927SVille Syrjälä } 31582ea63927SVille Syrjälä } 31592ea63927SVille Syrjälä 31602ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) 3161e0a20ad7SShashank Sharma { 31628cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 31638cee664dSAndrzej Hajda PORTA_HOTPLUG_ENABLE | 31642a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 31652ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 31668cee664dSAndrzej Hajda BXT_DDI_HPD_INVERT_MASK, 31678cee664dSAndrzej Hajda intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables)); 3168e0a20ad7SShashank Sharma } 3169e0a20ad7SShashank Sharma 31702a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) 31712a57d9ccSImre Deak { 31722a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 31732a57d9ccSImre Deak 31745a4dd6f0SJani Nikula enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31755a4dd6f0SJani Nikula hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd); 31762a57d9ccSImre Deak 31772a57d9ccSImre Deak bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 31782a57d9ccSImre Deak 31792ea63927SVille Syrjälä bxt_hpd_detection_setup(dev_priv); 31802a57d9ccSImre Deak } 31812a57d9ccSImre Deak 3182a0a6d8cbSVille Syrjälä /* 3183a0a6d8cbSVille Syrjälä * SDEIER is also touched by the interrupt handler to work around missed PCH 3184a0a6d8cbSVille Syrjälä * interrupts. Hence we can't update it after the interrupt handler is enabled - 3185a0a6d8cbSVille Syrjälä * instead we unconditionally enable all PCH interrupt sources here, but then 3186a0a6d8cbSVille Syrjälä * only unmask them as needed with SDEIMR. 3187a0a6d8cbSVille Syrjälä * 3188a0a6d8cbSVille Syrjälä * Note that we currently do this after installing the interrupt handler, 3189a0a6d8cbSVille Syrjälä * but before we enable the master interrupt. That should be sufficient 3190a0a6d8cbSVille Syrjälä * to avoid races with the irq handler, assuming we have MSI. Shared legacy 3191a0a6d8cbSVille Syrjälä * interrupts could still race. 3192a0a6d8cbSVille Syrjälä */ 3193b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) 3194d46da437SPaulo Zanoni { 3195a0a6d8cbSVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 319682a28bcfSDaniel Vetter u32 mask; 3197d46da437SPaulo Zanoni 31986e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3199692a04cfSDaniel Vetter return; 3200692a04cfSDaniel Vetter 32016e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 32025c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 32034ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 32045c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 32054ebc6509SDhinakaran Pandiyan else 32064ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 32078664281bSPaulo Zanoni 3208a0a6d8cbSVille Syrjälä GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 3209d46da437SPaulo Zanoni } 3210d46da437SPaulo Zanoni 32119eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) 3212036a4a7dSZhenyu Wang { 3213b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 32148e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 32158e76f8dcSPaulo Zanoni 3216651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) >= 7) { 32178e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 3218842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 32198e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 322023bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 32212a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_C) | 32222a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_B) | 32232a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_A) | 322423bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 32258e76f8dcSPaulo Zanoni } else { 32268e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 3227842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 3228842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 3229c6073d4cSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | 3230e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 32314bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_A) | 32324bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_B) | 3233e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 32348e76f8dcSPaulo Zanoni } 3235036a4a7dSZhenyu Wang 3236fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3237b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 3238fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 3239fc340442SDaniel Vetter } 3240fc340442SDaniel Vetter 3241c6073d4cSVille Syrjälä if (IS_IRONLAKE_M(dev_priv)) 3242c6073d4cSVille Syrjälä extra_mask |= DE_PCU_EVENT; 3243c6073d4cSVille Syrjälä 32441ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 3245036a4a7dSZhenyu Wang 3246a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3247622364b6SPaulo Zanoni 32482cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 3249a9922912SVille Syrjälä 3250b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, 3251b16b2a2fSPaulo Zanoni display_mask | extra_mask); 3252036a4a7dSZhenyu Wang } 3253036a4a7dSZhenyu Wang 3254f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 3255f8b79e58SImre Deak { 325667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3257f8b79e58SImre Deak 3258f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 3259f8b79e58SImre Deak return; 3260f8b79e58SImre Deak 3261f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 3262f8b79e58SImre Deak 3263d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 3264d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 3265ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3266f8b79e58SImre Deak } 3267d6c69803SVille Syrjälä } 3268f8b79e58SImre Deak 3269f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 3270f8b79e58SImre Deak { 327167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3272f8b79e58SImre Deak 3273f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 3274f8b79e58SImre Deak return; 3275f8b79e58SImre Deak 3276f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 3277f8b79e58SImre Deak 3278950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 3279ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 3280f8b79e58SImre Deak } 3281f8b79e58SImre Deak 32820e6c9a9eSVille Syrjälä 3283b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) 32840e6c9a9eSVille Syrjälä { 32852cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 32867e231dbeSJesse Barnes 3287ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 32889918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3289ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3290ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3291ad22d106SVille Syrjälä 32922939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 32932939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 329420afbda2SDaniel Vetter } 329520afbda2SDaniel Vetter 3296abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 3297abd58f01SBen Widawsky { 3298b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3299b16b2a2fSPaulo Zanoni 3300869129eeSMatt Roper u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) | 3301869129eeSMatt Roper GEN8_PIPE_CDCLK_CRC_DONE; 3302a9c287c9SJani Nikula u32 de_pipe_enables; 3303054318c7SImre Deak u32 de_port_masked = gen8_de_port_aux_mask(dev_priv); 33043a3b3c7dSVille Syrjälä u32 de_port_enables; 3305df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 3306562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 3307562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 33083a3b3c7dSVille Syrjälä enum pipe pipe; 3309770de83dSDamien Lespiau 3310a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3311a844cfbeSJosé Roberto de Souza return; 3312a844cfbeSJosé Roberto de Souza 3313373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) <= 10) 3314df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 3315df0d28c1SDhinakaran Pandiyan 331670bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 33173a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 3318a324fcacSRodrigo Vivi 3319373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 33209c9e97c4SVandita Kulkarni enum port port; 33219c9e97c4SVandita Kulkarni 33229c9e97c4SVandita Kulkarni if (intel_bios_is_dsi_present(dev_priv, &port)) 33239c9e97c4SVandita Kulkarni de_port_masked |= DSI0_TE | DSI1_TE; 33249c9e97c4SVandita Kulkarni } 33259c9e97c4SVandita Kulkarni 3326cda195f1SVille Syrjälä de_pipe_enables = de_pipe_masked | 33278bcc0840SMatt Roper GEN8_PIPE_VBLANK | 33288bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 3329cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 33301288f9b0SKarthik B S 33313a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 333270bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 3333a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 3334a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 3335e5abaab3SVille Syrjälä de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK; 33363a3b3c7dSVille Syrjälä 3337373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 33388241cfbeSJosé Roberto de Souza enum transcoder trans; 33398241cfbeSJosé Roberto de Souza 3340562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 33418241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 33428241cfbeSJosé Roberto de Souza 33438241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 33448241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 33458241cfbeSJosé Roberto de Souza continue; 33468241cfbeSJosé Roberto de Souza 33478241cfbeSJosé Roberto de Souza gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans)); 33488241cfbeSJosé Roberto de Souza } 33498241cfbeSJosé Roberto de Souza } else { 3350b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 33518241cfbeSJosé Roberto de Souza } 3352e04f7eceSVille Syrjälä 33530a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 33540a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 3355abd58f01SBen Widawsky 3356f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3357813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3358b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 3359813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 336035079899SPaulo Zanoni de_pipe_enables); 33610a195c02SMika Kahola } 3362abd58f01SBen Widawsky 3363b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 3364b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 33652a57d9ccSImre Deak 3366373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 3367121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 3368b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 3369b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 3370121e758eSDhinakaran Pandiyan 3371b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, 3372b16b2a2fSPaulo Zanoni de_hpd_enables); 3373abd58f01SBen Widawsky } 3374121e758eSDhinakaran Pandiyan } 3375abd58f01SBen Widawsky 337659b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv) 337759b7cb44STejas Upadhyay { 337859b7cb44STejas Upadhyay struct intel_uncore *uncore = &dev_priv->uncore; 337959b7cb44STejas Upadhyay u32 mask = SDE_GMBUS_ICP; 338059b7cb44STejas Upadhyay 338159b7cb44STejas Upadhyay GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 338259b7cb44STejas Upadhyay } 338359b7cb44STejas Upadhyay 3384b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) 3385abd58f01SBen Widawsky { 338659b7cb44STejas Upadhyay if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 338759b7cb44STejas Upadhyay icp_irq_postinstall(dev_priv); 338859b7cb44STejas Upadhyay else if (HAS_PCH_SPLIT(dev_priv)) 3389a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3390622364b6SPaulo Zanoni 33912cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 3392abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 3393abd58f01SBen Widawsky 339425286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 3395abd58f01SBen Widawsky } 3396abd58f01SBen Widawsky 3397a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) 3398a844cfbeSJosé Roberto de Souza { 3399a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3400a844cfbeSJosé Roberto de Souza return; 3401a844cfbeSJosé Roberto de Souza 3402a844cfbeSJosé Roberto de Souza gen8_de_irq_postinstall(dev_priv); 3403a844cfbeSJosé Roberto de Souza 3404a844cfbeSJosé Roberto de Souza intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 3405a844cfbeSJosé Roberto de Souza GEN11_DISPLAY_IRQ_ENABLE); 3406a844cfbeSJosé Roberto de Souza } 340731604222SAnusha Srivatsa 3408b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) 340951951ae7SMika Kuoppala { 34102cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3411fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 3412df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 341351951ae7SMika Kuoppala 341429b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 3415b318b824SVille Syrjälä icp_irq_postinstall(dev_priv); 341631604222SAnusha Srivatsa 3417fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 3418a844cfbeSJosé Roberto de Souza gen11_de_irq_postinstall(dev_priv); 341951951ae7SMika Kuoppala 3420b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 3421df0d28c1SDhinakaran Pandiyan 34229b77011eSTvrtko Ursulin gen11_master_intr_enable(uncore->regs); 34232939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ); 342451951ae7SMika Kuoppala } 342522e26af7SPaulo Zanoni 342622e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) 342722e26af7SPaulo Zanoni { 34282cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3429fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 343022e26af7SPaulo Zanoni u32 gu_misc_masked = GEN11_GU_MISC_GSE; 343122e26af7SPaulo Zanoni 3432fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 343322e26af7SPaulo Zanoni 343422e26af7SPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 343522e26af7SPaulo Zanoni 343622e26af7SPaulo Zanoni if (HAS_DISPLAY(dev_priv)) { 343722e26af7SPaulo Zanoni icp_irq_postinstall(dev_priv); 343822e26af7SPaulo Zanoni gen8_de_irq_postinstall(dev_priv); 343922e26af7SPaulo Zanoni intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 344022e26af7SPaulo Zanoni GEN11_DISPLAY_IRQ_ENABLE); 344122e26af7SPaulo Zanoni } 344222e26af7SPaulo Zanoni 3443fd4d7904SPaulo Zanoni dg1_master_intr_enable(uncore->regs); 3444fd4d7904SPaulo Zanoni intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR); 344597b492f5SLucas De Marchi } 344651951ae7SMika Kuoppala 3447b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) 344843f328d7SVille Syrjälä { 34492cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 345043f328d7SVille Syrjälä 3451ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 34529918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3453ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3454ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3455ad22d106SVille Syrjälä 34562939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 34572939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 345843f328d7SVille Syrjälä } 345943f328d7SVille Syrjälä 3460b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv) 3461c2798b19SChris Wilson { 3462b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3463c2798b19SChris Wilson 346444d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 346544d9241eSVille Syrjälä 3466ad7632ffSJani Nikula gen2_irq_reset(uncore); 3467e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3468c2798b19SChris Wilson } 3469c2798b19SChris Wilson 34703687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915) 34713687ce75SVille Syrjälä { 3472e7e12f6eSVille Syrjälä /* 3473e7e12f6eSVille Syrjälä * On gen2/3 FBC generates (seemingly spurious) 3474e7e12f6eSVille Syrjälä * display INVALID_GTT/INVALID_GTT_PTE table errors. 3475e7e12f6eSVille Syrjälä * 3476e7e12f6eSVille Syrjälä * Also gen3 bspec has this to say: 3477e7e12f6eSVille Syrjälä * "DISPA_INVALID_GTT_PTE 3478e7e12f6eSVille Syrjälä " [DevNapa] : Reserved. This bit does not reflect the page 3479e7e12f6eSVille Syrjälä " table error for the display plane A." 3480e7e12f6eSVille Syrjälä * 3481e7e12f6eSVille Syrjälä * Unfortunately we can't mask off individual PGTBL_ER bits, 3482e7e12f6eSVille Syrjälä * so we just have to mask off all page table errors via EMR. 3483e7e12f6eSVille Syrjälä */ 3484e7e12f6eSVille Syrjälä if (HAS_FBC(i915)) 3485e7e12f6eSVille Syrjälä return ~I915_ERROR_MEMORY_REFRESH; 3486e7e12f6eSVille Syrjälä else 34873687ce75SVille Syrjälä return ~(I915_ERROR_PAGE_TABLE | 34883687ce75SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 34893687ce75SVille Syrjälä } 34903687ce75SVille Syrjälä 3491b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) 3492c2798b19SChris Wilson { 3493b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3494e9e9848aSVille Syrjälä u16 enable_mask; 3495c2798b19SChris Wilson 34963687ce75SVille Syrjälä intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv)); 3497c2798b19SChris Wilson 3498c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 3499c2798b19SChris Wilson dev_priv->irq_mask = 3500c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 350116659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 350216659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3503c2798b19SChris Wilson 3504e9e9848aSVille Syrjälä enable_mask = 3505c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3506c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 350716659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3508e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 3509e9e9848aSVille Syrjälä 3510ad7632ffSJani Nikula gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask); 3511c2798b19SChris Wilson 3512379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3513379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3514d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3515755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3516755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3517d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3518c2798b19SChris Wilson } 3519c2798b19SChris Wilson 35204f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915, 352178c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 352278c357ddSVille Syrjälä { 35234f5fd91fSTvrtko Ursulin struct intel_uncore *uncore = &i915->uncore; 352478c357ddSVille Syrjälä u16 emr; 352578c357ddSVille Syrjälä 35264f5fd91fSTvrtko Ursulin *eir = intel_uncore_read16(uncore, EIR); 35274f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EIR, *eir); 352878c357ddSVille Syrjälä 35294f5fd91fSTvrtko Ursulin *eir_stuck = intel_uncore_read16(uncore, EIR); 353078c357ddSVille Syrjälä if (*eir_stuck == 0) 353178c357ddSVille Syrjälä return; 353278c357ddSVille Syrjälä 353378c357ddSVille Syrjälä /* 353478c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 353578c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 353678c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 353778c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 353878c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 353978c357ddSVille Syrjälä * cleared except by handling the underlying error 354078c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 354178c357ddSVille Syrjälä * remains set. 354278c357ddSVille Syrjälä */ 35434f5fd91fSTvrtko Ursulin emr = intel_uncore_read16(uncore, EMR); 35444f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, 0xffff); 35454f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, emr | *eir_stuck); 354678c357ddSVille Syrjälä } 354778c357ddSVille Syrjälä 354878c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 354978c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 355078c357ddSVille Syrjälä { 3551a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir); 355278c357ddSVille Syrjälä 355378c357ddSVille Syrjälä if (eir_stuck) 355400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n", 355500376ccfSWambui Karuga eir_stuck); 3556d1e89592SVille Syrjälä 3557d1e89592SVille Syrjälä drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n", 3558d1e89592SVille Syrjälä intel_uncore_read(&dev_priv->uncore, PGTBL_ER)); 355978c357ddSVille Syrjälä } 356078c357ddSVille Syrjälä 356178c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 356278c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 356378c357ddSVille Syrjälä { 356478c357ddSVille Syrjälä u32 emr; 356578c357ddSVille Syrjälä 3566839259b8SVille Syrjälä *eir = intel_uncore_read(&dev_priv->uncore, EIR); 3567839259b8SVille Syrjälä intel_uncore_write(&dev_priv->uncore, EIR, *eir); 356878c357ddSVille Syrjälä 35692939eb06SJani Nikula *eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR); 357078c357ddSVille Syrjälä if (*eir_stuck == 0) 357178c357ddSVille Syrjälä return; 357278c357ddSVille Syrjälä 357378c357ddSVille Syrjälä /* 357478c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 357578c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 357678c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 357778c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 357878c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 357978c357ddSVille Syrjälä * cleared except by handling the underlying error 358078c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 358178c357ddSVille Syrjälä * remains set. 358278c357ddSVille Syrjälä */ 3583839259b8SVille Syrjälä emr = intel_uncore_read(&dev_priv->uncore, EMR); 3584839259b8SVille Syrjälä intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff); 35852939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck); 358678c357ddSVille Syrjälä } 358778c357ddSVille Syrjälä 358878c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 358978c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 359078c357ddSVille Syrjälä { 3591a10234fdSTvrtko Ursulin drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir); 359278c357ddSVille Syrjälä 359378c357ddSVille Syrjälä if (eir_stuck) 359400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n", 359500376ccfSWambui Karuga eir_stuck); 3596d1e89592SVille Syrjälä 3597d1e89592SVille Syrjälä drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n", 3598d1e89592SVille Syrjälä intel_uncore_read(&dev_priv->uncore, PGTBL_ER)); 359978c357ddSVille Syrjälä } 360078c357ddSVille Syrjälä 3601ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 3602c2798b19SChris Wilson { 3603b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3604af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3605c2798b19SChris Wilson 36062dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 36072dd2a883SImre Deak return IRQ_NONE; 36082dd2a883SImre Deak 36091f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 36109102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 36111f814dacSImre Deak 3612af722d28SVille Syrjälä do { 3613af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 361478c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 3615af722d28SVille Syrjälä u16 iir; 3616af722d28SVille Syrjälä 36174f5fd91fSTvrtko Ursulin iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR); 3618c2798b19SChris Wilson if (iir == 0) 3619af722d28SVille Syrjälä break; 3620c2798b19SChris Wilson 3621af722d28SVille Syrjälä ret = IRQ_HANDLED; 3622c2798b19SChris Wilson 3623eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3624eb64343cSVille Syrjälä * signalled in iir */ 3625eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3626c2798b19SChris Wilson 362778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 362878c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 362978c357ddSVille Syrjälä 36304f5fd91fSTvrtko Ursulin intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); 3631c2798b19SChris Wilson 3632c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 36332cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 3634c2798b19SChris Wilson 363578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 363678c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 3637af722d28SVille Syrjälä 3638eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3639af722d28SVille Syrjälä } while (0); 3640c2798b19SChris Wilson 36419c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 36429c6508b9SThomas Gleixner 36439102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 36441f814dacSImre Deak 36451f814dacSImre Deak return ret; 3646c2798b19SChris Wilson } 3647c2798b19SChris Wilson 3648b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv) 3649a266c7d5SChris Wilson { 3650b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3651a266c7d5SChris Wilson 365256b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 36530706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 36548cee664dSAndrzej Hajda intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0); 3655a266c7d5SChris Wilson } 3656a266c7d5SChris Wilson 365744d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 365844d9241eSVille Syrjälä 3659b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 3660e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3661a266c7d5SChris Wilson } 3662a266c7d5SChris Wilson 3663b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv) 3664a266c7d5SChris Wilson { 3665b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 366638bde180SChris Wilson u32 enable_mask; 3667a266c7d5SChris Wilson 36683687ce75SVille Syrjälä intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv)); 366938bde180SChris Wilson 367038bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 367138bde180SChris Wilson dev_priv->irq_mask = 367238bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 367338bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 367416659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 367516659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 367638bde180SChris Wilson 367738bde180SChris Wilson enable_mask = 367838bde180SChris Wilson I915_ASLE_INTERRUPT | 367938bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 368038bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 368116659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 368238bde180SChris Wilson I915_USER_INTERRUPT; 368338bde180SChris Wilson 368456b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 3685a266c7d5SChris Wilson /* Enable in IER... */ 3686a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 3687a266c7d5SChris Wilson /* and unmask in IMR */ 3688a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 3689a266c7d5SChris Wilson } 3690a266c7d5SChris Wilson 3691b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 3692a266c7d5SChris Wilson 3693379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3694379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3695d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3696755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3697755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3698d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3699379ef82dSDaniel Vetter 3700c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 370120afbda2SDaniel Vetter } 370220afbda2SDaniel Vetter 3703ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 3704a266c7d5SChris Wilson { 3705b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3706af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3707a266c7d5SChris Wilson 37082dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 37092dd2a883SImre Deak return IRQ_NONE; 37102dd2a883SImre Deak 37111f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 37129102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 37131f814dacSImre Deak 371438bde180SChris Wilson do { 3715eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 371678c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 3717af722d28SVille Syrjälä u32 hotplug_status = 0; 3718af722d28SVille Syrjälä u32 iir; 3719a266c7d5SChris Wilson 37202939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 3721af722d28SVille Syrjälä if (iir == 0) 3722af722d28SVille Syrjälä break; 3723af722d28SVille Syrjälä 3724af722d28SVille Syrjälä ret = IRQ_HANDLED; 3725af722d28SVille Syrjälä 3726af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 3727af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 3728af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 3729a266c7d5SChris Wilson 3730eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3731eb64343cSVille Syrjälä * signalled in iir */ 3732eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3733a266c7d5SChris Wilson 373478c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 373578c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 373678c357ddSVille Syrjälä 37372939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 3738a266c7d5SChris Wilson 3739a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 37402cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 3741a266c7d5SChris Wilson 374278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 374378c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 3744a266c7d5SChris Wilson 3745af722d28SVille Syrjälä if (hotplug_status) 3746af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 3747af722d28SVille Syrjälä 3748af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3749af722d28SVille Syrjälä } while (0); 3750a266c7d5SChris Wilson 37519c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 37529c6508b9SThomas Gleixner 37539102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 37541f814dacSImre Deak 3755a266c7d5SChris Wilson return ret; 3756a266c7d5SChris Wilson } 3757a266c7d5SChris Wilson 3758b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv) 3759a266c7d5SChris Wilson { 3760b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3761a266c7d5SChris Wilson 37620706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 37638cee664dSAndrzej Hajda intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0); 3764a266c7d5SChris Wilson 376544d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 376644d9241eSVille Syrjälä 3767b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 3768e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3769a266c7d5SChris Wilson } 3770a266c7d5SChris Wilson 37713687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915) 3772a266c7d5SChris Wilson { 3773045cebd2SVille Syrjälä /* 3774045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 3775045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 3776e7e12f6eSVille Syrjälä * 3777e7e12f6eSVille Syrjälä * i965 FBC no longer generates spurious GTT errors, 3778e7e12f6eSVille Syrjälä * so we can always enable the page table errors. 3779045cebd2SVille Syrjälä */ 37803687ce75SVille Syrjälä if (IS_G4X(i915)) 37813687ce75SVille Syrjälä return ~(GM45_ERROR_PAGE_TABLE | 3782045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 3783045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 3784045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 37853687ce75SVille Syrjälä else 37863687ce75SVille Syrjälä return ~(I915_ERROR_PAGE_TABLE | 3787045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 3788045cebd2SVille Syrjälä } 37893687ce75SVille Syrjälä 37903687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv) 37913687ce75SVille Syrjälä { 37923687ce75SVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 37933687ce75SVille Syrjälä u32 enable_mask; 37943687ce75SVille Syrjälä 37953687ce75SVille Syrjälä intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv)); 3796045cebd2SVille Syrjälä 3797a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 3798c30bb1fdSVille Syrjälä dev_priv->irq_mask = 3799c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 3800adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 3801bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3802bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 380378c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3804bbba0a97SChris Wilson 3805c30bb1fdSVille Syrjälä enable_mask = 3806c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 3807c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 3808c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3809c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 381078c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3811c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 3812bbba0a97SChris Wilson 381391d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 3814bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 3815a266c7d5SChris Wilson 3816b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 3817c30bb1fdSVille Syrjälä 3818b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3819b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3820d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3821755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 3822755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3823755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3824d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3825a266c7d5SChris Wilson 382691d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 382720afbda2SDaniel Vetter } 382820afbda2SDaniel Vetter 382991d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) 383020afbda2SDaniel Vetter { 383120afbda2SDaniel Vetter u32 hotplug_en; 383220afbda2SDaniel Vetter 383367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3834b5ea2d56SDaniel Vetter 3835adca4730SChris Wilson /* Note HDMI and DP share hotplug bits */ 3836e5868a31SEgbert Eich /* enable bits are the same for all generations */ 383791d14251STvrtko Ursulin hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915); 3838a266c7d5SChris Wilson /* Programming the CRT detection parameters tends 3839a266c7d5SChris Wilson to generate a spurious hotplug event about three 3840a266c7d5SChris Wilson seconds later. So just do it once. 3841a266c7d5SChris Wilson */ 384291d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 3843a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; 3844a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; 3845a266c7d5SChris Wilson 3846a266c7d5SChris Wilson /* Ignore TV since it's buggy */ 38470706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, 3848f9e3dc78SJani Nikula HOTPLUG_INT_EN_MASK | 3849f9e3dc78SJani Nikula CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | 3850f9e3dc78SJani Nikula CRT_HOTPLUG_ACTIVATION_PERIOD_64, 38510706f17cSEgbert Eich hotplug_en); 3852a266c7d5SChris Wilson } 3853a266c7d5SChris Wilson 3854ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 3855a266c7d5SChris Wilson { 3856b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3857af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3858a266c7d5SChris Wilson 38592dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 38602dd2a883SImre Deak return IRQ_NONE; 38612dd2a883SImre Deak 38621f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 38639102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 38641f814dacSImre Deak 3865af722d28SVille Syrjälä do { 3866eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 386778c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 3868af722d28SVille Syrjälä u32 hotplug_status = 0; 3869af722d28SVille Syrjälä u32 iir; 38702c8ba29fSChris Wilson 38712939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 3872af722d28SVille Syrjälä if (iir == 0) 3873af722d28SVille Syrjälä break; 3874af722d28SVille Syrjälä 3875af722d28SVille Syrjälä ret = IRQ_HANDLED; 3876af722d28SVille Syrjälä 3877af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 3878af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 3879a266c7d5SChris Wilson 3880eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3881eb64343cSVille Syrjälä * signalled in iir */ 3882eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3883a266c7d5SChris Wilson 388478c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 388578c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 388678c357ddSVille Syrjälä 38872939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 3888a266c7d5SChris Wilson 3889a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 38902cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], 38910669a6e1SChris Wilson iir); 3892af722d28SVille Syrjälä 3893a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 38942cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0], 38950669a6e1SChris Wilson iir >> 25); 3896a266c7d5SChris Wilson 389778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 389878c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 3899515ac2bbSDaniel Vetter 3900af722d28SVille Syrjälä if (hotplug_status) 3901af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 3902af722d28SVille Syrjälä 3903af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3904af722d28SVille Syrjälä } while (0); 3905a266c7d5SChris Wilson 39069c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 39079c6508b9SThomas Gleixner 39089102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 39091f814dacSImre Deak 3910a266c7d5SChris Wilson return ret; 3911a266c7d5SChris Wilson } 3912a266c7d5SChris Wilson 39137e97596cSJani Nikula struct intel_hotplug_funcs { 39147e97596cSJani Nikula void (*hpd_irq_setup)(struct drm_i915_private *i915); 39157e97596cSJani Nikula }; 39167e97596cSJani Nikula 3917cd030c7cSDave Airlie #define HPD_FUNCS(platform) \ 3918cd030c7cSDave Airlie static const struct intel_hotplug_funcs platform##_hpd_funcs = { \ 3919cd030c7cSDave Airlie .hpd_irq_setup = platform##_hpd_irq_setup, \ 3920cd030c7cSDave Airlie } 3921cd030c7cSDave Airlie 3922cd030c7cSDave Airlie HPD_FUNCS(i915); 3923cd030c7cSDave Airlie HPD_FUNCS(dg1); 3924cd030c7cSDave Airlie HPD_FUNCS(gen11); 3925cd030c7cSDave Airlie HPD_FUNCS(bxt); 3926cd030c7cSDave Airlie HPD_FUNCS(icp); 3927cd030c7cSDave Airlie HPD_FUNCS(spt); 3928cd030c7cSDave Airlie HPD_FUNCS(ilk); 3929cd030c7cSDave Airlie #undef HPD_FUNCS 3930cd030c7cSDave Airlie 39317e97596cSJani Nikula void intel_hpd_irq_setup(struct drm_i915_private *i915) 39327e97596cSJani Nikula { 39335a04eb5bSJani Nikula if (i915->display_irqs_enabled && i915->display.funcs.hotplug) 39345a04eb5bSJani Nikula i915->display.funcs.hotplug->hpd_irq_setup(i915); 39357e97596cSJani Nikula } 39367e97596cSJani Nikula 3937fca52a55SDaniel Vetter /** 3938fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 3939fca52a55SDaniel Vetter * @dev_priv: i915 device instance 3940fca52a55SDaniel Vetter * 3941fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 3942fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 3943fca52a55SDaniel Vetter */ 3944b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 3945f71d4af4SJesse Barnes { 3946cefcff8fSJoonas Lahtinen int i; 39478b2e326dSChris Wilson 394874bb98baSLucas De Marchi INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); 3949cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 3950cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 39518b2e326dSChris Wilson 3952633023a4SDaniele Ceraolo Spurio /* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */ 3953651e7d48SLucas De Marchi if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11) 39542cbc876dSMichał Winiarski to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16; 395526705e20SSagar Arun Kamble 39569a450b68SLucas De Marchi if (!HAS_DISPLAY(dev_priv)) 39579a450b68SLucas De Marchi return; 39589a450b68SLucas De Marchi 395996bd87b7SLucas De Marchi intel_hpd_init_pins(dev_priv); 396096bd87b7SLucas De Marchi 3961dd890d42SJani Nikula intel_hpd_init_early(dev_priv); 396296bd87b7SLucas De Marchi 39633703060dSAndrzej Hajda dev_priv->drm.vblank_disable_immediate = true; 396421da2700SVille Syrjälä 3965262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 3966262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 3967262fd485SChris Wilson * special care to avoid writing any of the display block registers 3968262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 3969262fd485SChris Wilson * in this case to the runtime pm. 3970262fd485SChris Wilson */ 3971262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 3972262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 3973262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 3974262fd485SChris Wilson 39752ccf2e03SChris Wilson if (HAS_GMCH(dev_priv)) { 39762ccf2e03SChris Wilson if (I915_HAS_HOTPLUG(dev_priv)) 39775a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &i915_hpd_funcs; 39782ccf2e03SChris Wilson } else { 39792f8a6699SMatt Roper if (HAS_PCH_DG2(dev_priv)) 39805a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &icp_hpd_funcs; 39812f8a6699SMatt Roper else if (HAS_PCH_DG1(dev_priv)) 39825a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &dg1_hpd_funcs; 3983373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 11) 39845a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &gen11_hpd_funcs; 398570bfb307SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 39865a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &bxt_hpd_funcs; 3987cec3295bSLyude Paul else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 39885a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &icp_hpd_funcs; 3989c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 39905a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &spt_hpd_funcs; 39916dbf30ceSVille Syrjälä else 39925a04eb5bSJani Nikula dev_priv->display.funcs.hotplug = &ilk_hpd_funcs; 3993f71d4af4SJesse Barnes } 39942ccf2e03SChris Wilson } 399520afbda2SDaniel Vetter 3996fca52a55SDaniel Vetter /** 3997cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 3998cefcff8fSJoonas Lahtinen * @i915: i915 device instance 3999cefcff8fSJoonas Lahtinen * 4000cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 4001cefcff8fSJoonas Lahtinen */ 4002cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 4003cefcff8fSJoonas Lahtinen { 4004cefcff8fSJoonas Lahtinen int i; 4005cefcff8fSJoonas Lahtinen 4006cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4007cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 4008cefcff8fSJoonas Lahtinen } 4009cefcff8fSJoonas Lahtinen 4010b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) 4011b318b824SVille Syrjälä { 4012b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4013b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4014b318b824SVille Syrjälä return cherryview_irq_handler; 4015b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4016b318b824SVille Syrjälä return valleyview_irq_handler; 4017651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4018b318b824SVille Syrjälä return i965_irq_handler; 4019651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4020b318b824SVille Syrjälä return i915_irq_handler; 4021b318b824SVille Syrjälä else 4022b318b824SVille Syrjälä return i8xx_irq_handler; 4023b318b824SVille Syrjälä } else { 402422e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 402597b492f5SLucas De Marchi return dg1_irq_handler; 402622e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4027b318b824SVille Syrjälä return gen11_irq_handler; 4028651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4029b318b824SVille Syrjälä return gen8_irq_handler; 4030b318b824SVille Syrjälä else 40319eae5e27SLucas De Marchi return ilk_irq_handler; 4032b318b824SVille Syrjälä } 4033b318b824SVille Syrjälä } 4034b318b824SVille Syrjälä 4035b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv) 4036b318b824SVille Syrjälä { 4037b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4038b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4039b318b824SVille Syrjälä cherryview_irq_reset(dev_priv); 4040b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4041b318b824SVille Syrjälä valleyview_irq_reset(dev_priv); 4042651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4043b318b824SVille Syrjälä i965_irq_reset(dev_priv); 4044651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4045b318b824SVille Syrjälä i915_irq_reset(dev_priv); 4046b318b824SVille Syrjälä else 4047b318b824SVille Syrjälä i8xx_irq_reset(dev_priv); 4048b318b824SVille Syrjälä } else { 404922e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 405022e26af7SPaulo Zanoni dg1_irq_reset(dev_priv); 405122e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4052b318b824SVille Syrjälä gen11_irq_reset(dev_priv); 4053651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4054b318b824SVille Syrjälä gen8_irq_reset(dev_priv); 4055b318b824SVille Syrjälä else 40569eae5e27SLucas De Marchi ilk_irq_reset(dev_priv); 4057b318b824SVille Syrjälä } 4058b318b824SVille Syrjälä } 4059b318b824SVille Syrjälä 4060b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv) 4061b318b824SVille Syrjälä { 4062b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4063b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4064b318b824SVille Syrjälä cherryview_irq_postinstall(dev_priv); 4065b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4066b318b824SVille Syrjälä valleyview_irq_postinstall(dev_priv); 4067651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4068b318b824SVille Syrjälä i965_irq_postinstall(dev_priv); 4069651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4070b318b824SVille Syrjälä i915_irq_postinstall(dev_priv); 4071b318b824SVille Syrjälä else 4072b318b824SVille Syrjälä i8xx_irq_postinstall(dev_priv); 4073b318b824SVille Syrjälä } else { 407422e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 407522e26af7SPaulo Zanoni dg1_irq_postinstall(dev_priv); 407622e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4077b318b824SVille Syrjälä gen11_irq_postinstall(dev_priv); 4078651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4079b318b824SVille Syrjälä gen8_irq_postinstall(dev_priv); 4080b318b824SVille Syrjälä else 40819eae5e27SLucas De Marchi ilk_irq_postinstall(dev_priv); 4082b318b824SVille Syrjälä } 4083b318b824SVille Syrjälä } 4084b318b824SVille Syrjälä 4085cefcff8fSJoonas Lahtinen /** 4086fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 4087fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4088fca52a55SDaniel Vetter * 4089fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 4090fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 4091fca52a55SDaniel Vetter * 4092fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 4093fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 4094fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 4095fca52a55SDaniel Vetter */ 40962aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 40972aeb7d3aSDaniel Vetter { 40988ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4099b318b824SVille Syrjälä int ret; 4100b318b824SVille Syrjälä 41012aeb7d3aSDaniel Vetter /* 41022aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 41032aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 41042aeb7d3aSDaniel Vetter * special cases in our ordering checks. 41052aeb7d3aSDaniel Vetter */ 4106ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 41072aeb7d3aSDaniel Vetter 4108ac1723c1SThomas Zimmermann dev_priv->irq_enabled = true; 4109b318b824SVille Syrjälä 4110b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4111b318b824SVille Syrjälä 4112b318b824SVille Syrjälä ret = request_irq(irq, intel_irq_handler(dev_priv), 4113b318b824SVille Syrjälä IRQF_SHARED, DRIVER_NAME, dev_priv); 4114b318b824SVille Syrjälä if (ret < 0) { 4115ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 4116b318b824SVille Syrjälä return ret; 4117b318b824SVille Syrjälä } 4118b318b824SVille Syrjälä 4119b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4120b318b824SVille Syrjälä 4121b318b824SVille Syrjälä return ret; 41222aeb7d3aSDaniel Vetter } 41232aeb7d3aSDaniel Vetter 4124fca52a55SDaniel Vetter /** 4125fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 4126fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4127fca52a55SDaniel Vetter * 4128fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 4129fca52a55SDaniel Vetter * resources acquired in the init functions. 4130fca52a55SDaniel Vetter */ 41312aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 41322aeb7d3aSDaniel Vetter { 41338ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4134b318b824SVille Syrjälä 4135b318b824SVille Syrjälä /* 4136789fa874SJanusz Krzysztofik * FIXME we can get called twice during driver probe 4137789fa874SJanusz Krzysztofik * error handling as well as during driver remove due to 4138789fa874SJanusz Krzysztofik * intel_modeset_driver_remove() calling us out of sequence. 4139789fa874SJanusz Krzysztofik * Would be nice if it didn't do that... 4140b318b824SVille Syrjälä */ 4141ac1723c1SThomas Zimmermann if (!dev_priv->irq_enabled) 4142b318b824SVille Syrjälä return; 4143b318b824SVille Syrjälä 4144ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 4145b318b824SVille Syrjälä 4146b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4147b318b824SVille Syrjälä 4148b318b824SVille Syrjälä free_irq(irq, dev_priv); 4149b318b824SVille Syrjälä 41502aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 4151ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 41522aeb7d3aSDaniel Vetter } 41532aeb7d3aSDaniel Vetter 4154fca52a55SDaniel Vetter /** 4155fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 4156fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4157fca52a55SDaniel Vetter * 4158fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 4159fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4160fca52a55SDaniel Vetter */ 4161b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 4162c67a470bSPaulo Zanoni { 4163b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4164ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 4165315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 4166c67a470bSPaulo Zanoni } 4167c67a470bSPaulo Zanoni 4168fca52a55SDaniel Vetter /** 4169fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 4170fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4171fca52a55SDaniel Vetter * 4172fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 4173fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4174fca52a55SDaniel Vetter */ 4175b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 4176c67a470bSPaulo Zanoni { 4177ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 4178b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4179b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4180c67a470bSPaulo Zanoni } 4181d64575eeSJani Nikula 4182d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv) 4183d64575eeSJani Nikula { 4184d64575eeSJani Nikula return dev_priv->runtime_pm.irqs_enabled; 4185d64575eeSJani Nikula } 4186d64575eeSJani Nikula 4187d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915) 4188d64575eeSJani Nikula { 41898ff5446aSThomas Zimmermann synchronize_irq(to_pci_dev(i915->drm.dev)->irq); 4190d64575eeSJani Nikula } 4191320ad343SThomas Zimmermann 4192320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915) 4193320ad343SThomas Zimmermann { 4194320ad343SThomas Zimmermann synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq); 4195320ad343SThomas Zimmermann } 4196