1c0e09200SDave Airlie /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- 2c0e09200SDave Airlie */ 3c0e09200SDave Airlie /* 4c0e09200SDave Airlie * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5c0e09200SDave Airlie * All Rights Reserved. 6c0e09200SDave Airlie * 7c0e09200SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 8c0e09200SDave Airlie * copy of this software and associated documentation files (the 9c0e09200SDave Airlie * "Software"), to deal in the Software without restriction, including 10c0e09200SDave Airlie * without limitation the rights to use, copy, modify, merge, publish, 11c0e09200SDave Airlie * distribute, sub license, and/or sell copies of the Software, and to 12c0e09200SDave Airlie * permit persons to whom the Software is furnished to do so, subject to 13c0e09200SDave Airlie * the following conditions: 14c0e09200SDave Airlie * 15c0e09200SDave Airlie * The above copyright notice and this permission notice (including the 16c0e09200SDave Airlie * next paragraph) shall be included in all copies or substantial portions 17c0e09200SDave Airlie * of the Software. 18c0e09200SDave Airlie * 19c0e09200SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20c0e09200SDave Airlie * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21c0e09200SDave Airlie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22c0e09200SDave Airlie * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23c0e09200SDave Airlie * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24c0e09200SDave Airlie * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25c0e09200SDave Airlie * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26c0e09200SDave Airlie * 27c0e09200SDave Airlie */ 28c0e09200SDave Airlie 29a70491ccSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 30a70491ccSJoe Perches 31b2c88f5bSDamien Lespiau #include <linux/circ_buf.h> 3255367a27SJani Nikula #include <linux/slab.h> 3355367a27SJani Nikula #include <linux/sysrq.h> 3455367a27SJani Nikula 35fcd70cd3SDaniel Vetter #include <drm/drm_drv.h> 3655367a27SJani Nikula 377785ae0bSVille Syrjälä #include "display/intel_de.h" 38fd2b94a5SJani Nikula #include "display/intel_display_trace.h" 391d455f8dSJani Nikula #include "display/intel_display_types.h" 40df0566a6SJani Nikula #include "display/intel_fifo_underrun.h" 41df0566a6SJani Nikula #include "display/intel_hotplug.h" 42df0566a6SJani Nikula #include "display/intel_lpe_audio.h" 43df0566a6SJani Nikula #include "display/intel_psr.h" 44df0566a6SJani Nikula 45b3786b29SChris Wilson #include "gt/intel_breadcrumbs.h" 462239e6dfSDaniele Ceraolo Spurio #include "gt/intel_gt.h" 47cf1c97dcSAndi Shyti #include "gt/intel_gt_irq.h" 48d762043fSAndi Shyti #include "gt/intel_gt_pm_irq.h" 490d6419e9SMatt Roper #include "gt/intel_gt_regs.h" 503e7abf81SAndi Shyti #include "gt/intel_rps.h" 512239e6dfSDaniele Ceraolo Spurio 52*24524e3fSJani Nikula #include "i915_driver.h" 53c0e09200SDave Airlie #include "i915_drv.h" 54440e2b3dSJani Nikula #include "i915_irq.h" 55d13616dbSJani Nikula #include "intel_pm.h" 56c0e09200SDave Airlie 57fca52a55SDaniel Vetter /** 58fca52a55SDaniel Vetter * DOC: interrupt handling 59fca52a55SDaniel Vetter * 60fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 61fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 62fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 63fca52a55SDaniel Vetter */ 64fca52a55SDaniel Vetter 659c6508b9SThomas Gleixner /* 669c6508b9SThomas Gleixner * Interrupt statistic for PMU. Increments the counter only if the 679c6508b9SThomas Gleixner * interrupt originated from the the GPU so interrupts from a device which 689c6508b9SThomas Gleixner * shares the interrupt line are not accounted. 699c6508b9SThomas Gleixner */ 709c6508b9SThomas Gleixner static inline void pmu_irq_stats(struct drm_i915_private *i915, 719c6508b9SThomas Gleixner irqreturn_t res) 729c6508b9SThomas Gleixner { 739c6508b9SThomas Gleixner if (unlikely(res != IRQ_HANDLED)) 749c6508b9SThomas Gleixner return; 759c6508b9SThomas Gleixner 769c6508b9SThomas Gleixner /* 779c6508b9SThomas Gleixner * A clever compiler translates that into INC. A not so clever one 789c6508b9SThomas Gleixner * should at least prevent store tearing. 799c6508b9SThomas Gleixner */ 809c6508b9SThomas Gleixner WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1); 819c6508b9SThomas Gleixner } 829c6508b9SThomas Gleixner 8348ef15d3SJosé Roberto de Souza typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val); 842ea63927SVille Syrjälä typedef u32 (*hotplug_enables_func)(struct drm_i915_private *i915, 852ea63927SVille Syrjälä enum hpd_pin pin); 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), 182229f31e2SLucas De Marchi }; 183229f31e2SLucas De Marchi 1840398993bSVille Syrjälä static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) 1850398993bSVille Syrjälä { 1860398993bSVille Syrjälä struct i915_hotplug *hpd = &dev_priv->hotplug; 1870398993bSVille Syrjälä 1880398993bSVille Syrjälä if (HAS_GMCH(dev_priv)) { 1890398993bSVille Syrjälä if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || 1900398993bSVille Syrjälä IS_CHERRYVIEW(dev_priv)) 1910398993bSVille Syrjälä hpd->hpd = hpd_status_g4x; 1920398993bSVille Syrjälä else 1930398993bSVille Syrjälä hpd->hpd = hpd_status_i915; 1940398993bSVille Syrjälä return; 1950398993bSVille Syrjälä } 1960398993bSVille Syrjälä 197373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) 1980398993bSVille Syrjälä hpd->hpd = hpd_gen11; 19970bfb307SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 2000398993bSVille Syrjälä hpd->hpd = hpd_bxt; 201373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 8) 2020398993bSVille Syrjälä hpd->hpd = hpd_bdw; 203373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 7) 2040398993bSVille Syrjälä hpd->hpd = hpd_ivb; 2050398993bSVille Syrjälä else 2060398993bSVille Syrjälä hpd->hpd = hpd_ilk; 2070398993bSVille Syrjälä 208229f31e2SLucas De Marchi if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) && 209229f31e2SLucas De Marchi (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv))) 2100398993bSVille Syrjälä return; 2110398993bSVille Syrjälä 2123176fb66SMatt Roper if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) 213229f31e2SLucas De Marchi hpd->pch_hpd = hpd_sde_dg1; 214fa58c9e4SAnusha Srivatsa else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2150398993bSVille Syrjälä hpd->pch_hpd = hpd_icp; 2160398993bSVille Syrjälä else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv)) 2170398993bSVille Syrjälä hpd->pch_hpd = hpd_spt; 2180398993bSVille Syrjälä else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv)) 2190398993bSVille Syrjälä hpd->pch_hpd = hpd_cpt; 2200398993bSVille Syrjälä else if (HAS_PCH_IBX(dev_priv)) 2210398993bSVille Syrjälä hpd->pch_hpd = hpd_ibx; 2220398993bSVille Syrjälä else 2230398993bSVille Syrjälä MISSING_CASE(INTEL_PCH_TYPE(dev_priv)); 2240398993bSVille Syrjälä } 2250398993bSVille Syrjälä 226aca9310aSAnshuman Gupta static void 227aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) 228aca9310aSAnshuman Gupta { 2297794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 230aca9310aSAnshuman Gupta 231aca9310aSAnshuman Gupta drm_crtc_handle_vblank(&crtc->base); 232aca9310aSAnshuman Gupta } 233aca9310aSAnshuman Gupta 234cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, 23568eb49b1SPaulo Zanoni i915_reg_t iir, i915_reg_t ier) 23668eb49b1SPaulo Zanoni { 23765f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, 0xffffffff); 23865f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 23968eb49b1SPaulo Zanoni 24065f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, 0); 24168eb49b1SPaulo Zanoni 2425c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 24365f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24465f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 24565f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24665f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 24768eb49b1SPaulo Zanoni } 2485c502442SPaulo Zanoni 249cf1c97dcSAndi Shyti void gen2_irq_reset(struct intel_uncore *uncore) 25068eb49b1SPaulo Zanoni { 25165f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, 0xffff); 25265f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 253a9d356a6SPaulo Zanoni 25465f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, 0); 25568eb49b1SPaulo Zanoni 25668eb49b1SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 25765f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 25865f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 25965f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 26065f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 26168eb49b1SPaulo Zanoni } 26268eb49b1SPaulo Zanoni 263337ba017SPaulo Zanoni /* 264337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 265337ba017SPaulo Zanoni */ 26665f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) 267b51a2842SVille Syrjälä { 26865f42cdcSPaulo Zanoni u32 val = intel_uncore_read(uncore, reg); 269b51a2842SVille Syrjälä 270b51a2842SVille Syrjälä if (val == 0) 271b51a2842SVille Syrjälä return; 272b51a2842SVille Syrjälä 273a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 274a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 275f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 27665f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 27765f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 27865f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 27965f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 280b51a2842SVille Syrjälä } 281337ba017SPaulo Zanoni 28265f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore) 283e9e9848aSVille Syrjälä { 28465f42cdcSPaulo Zanoni u16 val = intel_uncore_read16(uncore, GEN2_IIR); 285e9e9848aSVille Syrjälä 286e9e9848aSVille Syrjälä if (val == 0) 287e9e9848aSVille Syrjälä return; 288e9e9848aSVille Syrjälä 289a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 290a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 2919d9523d8SPaulo Zanoni i915_mmio_reg_offset(GEN2_IIR), val); 29265f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29365f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 29465f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29565f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 296e9e9848aSVille Syrjälä } 297e9e9848aSVille Syrjälä 298cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore, 29968eb49b1SPaulo Zanoni i915_reg_t imr, u32 imr_val, 30068eb49b1SPaulo Zanoni i915_reg_t ier, u32 ier_val, 30168eb49b1SPaulo Zanoni i915_reg_t iir) 30268eb49b1SPaulo Zanoni { 30365f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(uncore, iir); 30435079899SPaulo Zanoni 30565f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, ier_val); 30665f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, imr_val); 30765f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 30868eb49b1SPaulo Zanoni } 30935079899SPaulo Zanoni 310cf1c97dcSAndi Shyti void gen2_irq_init(struct intel_uncore *uncore, 3112918c3caSPaulo Zanoni u32 imr_val, u32 ier_val) 31268eb49b1SPaulo Zanoni { 31365f42cdcSPaulo Zanoni gen2_assert_iir_is_zero(uncore); 31468eb49b1SPaulo Zanoni 31565f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, ier_val); 31665f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, imr_val); 31765f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 31868eb49b1SPaulo Zanoni } 31968eb49b1SPaulo Zanoni 3200706f17cSEgbert Eich /* For display hotplug interrupt */ 3210706f17cSEgbert Eich static inline void 3220706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, 323a9c287c9SJani Nikula u32 mask, 324a9c287c9SJani Nikula u32 bits) 3250706f17cSEgbert Eich { 326a9c287c9SJani Nikula u32 val; 3270706f17cSEgbert Eich 32867520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 32948a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, bits & ~mask); 3300706f17cSEgbert Eich 3312939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_EN); 3320706f17cSEgbert Eich val &= ~mask; 3330706f17cSEgbert Eich val |= bits; 3342939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_EN, val); 3350706f17cSEgbert Eich } 3360706f17cSEgbert Eich 3370706f17cSEgbert Eich /** 3380706f17cSEgbert Eich * i915_hotplug_interrupt_update - update hotplug interrupt enable 3390706f17cSEgbert Eich * @dev_priv: driver private 3400706f17cSEgbert Eich * @mask: bits to update 3410706f17cSEgbert Eich * @bits: bits to enable 3420706f17cSEgbert Eich * NOTE: the HPD enable bits are modified both inside and outside 3430706f17cSEgbert Eich * of an interrupt context. To avoid that read-modify-write cycles 3440706f17cSEgbert Eich * interfer, these bits are protected by a spinlock. Since this 3450706f17cSEgbert Eich * function is usually not called from a context where the lock is 3460706f17cSEgbert Eich * held already, this function acquires the lock itself. A non-locking 3470706f17cSEgbert Eich * version is also available. 3480706f17cSEgbert Eich */ 3490706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, 350a9c287c9SJani Nikula u32 mask, 351a9c287c9SJani Nikula u32 bits) 3520706f17cSEgbert Eich { 3530706f17cSEgbert Eich spin_lock_irq(&dev_priv->irq_lock); 3540706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); 3550706f17cSEgbert Eich spin_unlock_irq(&dev_priv->irq_lock); 3560706f17cSEgbert Eich } 3570706f17cSEgbert Eich 358d9dc34f1SVille Syrjälä /** 359d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 360d9dc34f1SVille Syrjälä * @dev_priv: driver private 361d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 362d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 363d9dc34f1SVille Syrjälä */ 3649e6dcf33SJani Nikula static void ilk_update_display_irq(struct drm_i915_private *dev_priv, 3659e6dcf33SJani Nikula u32 interrupt_mask, u32 enabled_irq_mask) 366036a4a7dSZhenyu Wang { 367a9c287c9SJani Nikula u32 new_val; 368d9dc34f1SVille Syrjälä 36967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 37048a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 371d9dc34f1SVille Syrjälä 372d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 373d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 374d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 375d9dc34f1SVille Syrjälä 376e44adb5dSChris Wilson if (new_val != dev_priv->irq_mask && 377e44adb5dSChris Wilson !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { 378d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 3792939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask); 3802939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, DEIMR); 381036a4a7dSZhenyu Wang } 382036a4a7dSZhenyu Wang } 383036a4a7dSZhenyu Wang 3849e6dcf33SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits) 3859e6dcf33SJani Nikula { 3869e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, bits); 3879e6dcf33SJani Nikula } 3889e6dcf33SJani Nikula 3899e6dcf33SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits) 3909e6dcf33SJani Nikula { 3919e6dcf33SJani Nikula ilk_update_display_irq(i915, bits, 0); 3929e6dcf33SJani Nikula } 3939e6dcf33SJani Nikula 3940961021aSBen Widawsky /** 3953a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 3963a3b3c7dSVille Syrjälä * @dev_priv: driver private 3973a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 3983a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 3993a3b3c7dSVille Syrjälä */ 4003a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv, 401a9c287c9SJani Nikula u32 interrupt_mask, 402a9c287c9SJani Nikula u32 enabled_irq_mask) 4033a3b3c7dSVille Syrjälä { 404a9c287c9SJani Nikula u32 new_val; 405a9c287c9SJani Nikula u32 old_val; 4063a3b3c7dSVille Syrjälä 40767520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4083a3b3c7dSVille Syrjälä 40948a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 4103a3b3c7dSVille Syrjälä 41148a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 4123a3b3c7dSVille Syrjälä return; 4133a3b3c7dSVille Syrjälä 4142939eb06SJani Nikula old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4153a3b3c7dSVille Syrjälä 4163a3b3c7dSVille Syrjälä new_val = old_val; 4173a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 4183a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 4193a3b3c7dSVille Syrjälä 4203a3b3c7dSVille Syrjälä if (new_val != old_val) { 4212939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val); 4222939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4233a3b3c7dSVille Syrjälä } 4243a3b3c7dSVille Syrjälä } 4253a3b3c7dSVille Syrjälä 4263a3b3c7dSVille Syrjälä /** 427013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 428013d3752SVille Syrjälä * @dev_priv: driver private 429013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 430013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 431013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 432013d3752SVille Syrjälä */ 4339e6dcf33SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 4349e6dcf33SJani Nikula enum pipe pipe, u32 interrupt_mask, 435a9c287c9SJani Nikula u32 enabled_irq_mask) 436013d3752SVille Syrjälä { 437a9c287c9SJani Nikula u32 new_val; 438013d3752SVille Syrjälä 43967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 440013d3752SVille Syrjälä 44148a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 442013d3752SVille Syrjälä 44348a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 444013d3752SVille Syrjälä return; 445013d3752SVille Syrjälä 446013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 447013d3752SVille Syrjälä new_val &= ~interrupt_mask; 448013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 449013d3752SVille Syrjälä 450013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 451013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 4522939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 4532939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); 454013d3752SVille Syrjälä } 455013d3752SVille Syrjälä } 456013d3752SVille Syrjälä 4579e6dcf33SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915, 4589e6dcf33SJani Nikula enum pipe pipe, u32 bits) 4599e6dcf33SJani Nikula { 4609e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, bits); 4619e6dcf33SJani Nikula } 4629e6dcf33SJani Nikula 4639e6dcf33SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915, 4649e6dcf33SJani Nikula enum pipe pipe, u32 bits) 4659e6dcf33SJani Nikula { 4669e6dcf33SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, 0); 4679e6dcf33SJani Nikula } 4689e6dcf33SJani Nikula 469013d3752SVille Syrjälä /** 470fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 471fee884edSDaniel Vetter * @dev_priv: driver private 472fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 473fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 474fee884edSDaniel Vetter */ 4759e6dcf33SJani Nikula static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 476a9c287c9SJani Nikula u32 interrupt_mask, 477a9c287c9SJani Nikula u32 enabled_irq_mask) 478fee884edSDaniel Vetter { 4792939eb06SJani Nikula u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR); 480fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 481fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 482fee884edSDaniel Vetter 48348a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 48415a17aaeSDaniel Vetter 48567520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 486fee884edSDaniel Vetter 48748a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 488c67a470bSPaulo Zanoni return; 489c67a470bSPaulo Zanoni 4902939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr); 4912939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, SDEIMR); 492fee884edSDaniel Vetter } 4938664281bSPaulo Zanoni 4949e6dcf33SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits) 4959e6dcf33SJani Nikula { 4969e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, bits); 4979e6dcf33SJani Nikula } 4989e6dcf33SJani Nikula 4999e6dcf33SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits) 5009e6dcf33SJani Nikula { 5019e6dcf33SJani Nikula ibx_display_interrupt_update(i915, bits, 0); 5029e6dcf33SJani Nikula } 5039e6dcf33SJani Nikula 5046b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 5056b12ca56SVille Syrjälä enum pipe pipe) 5067c463586SKeith Packard { 5076b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 50810c59c51SImre Deak u32 enable_mask = status_mask << 16; 50910c59c51SImre Deak 5106b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 5116b12ca56SVille Syrjälä 512373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 5) 5136b12ca56SVille Syrjälä goto out; 5146b12ca56SVille Syrjälä 51510c59c51SImre Deak /* 516724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 517724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 51810c59c51SImre Deak */ 51948a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 52048a1b8d4SPankaj Bharadiya status_mask & PIPE_A_PSR_STATUS_VLV)) 52110c59c51SImre Deak return 0; 522724a6905SVille Syrjälä /* 523724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 524724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 525724a6905SVille Syrjälä */ 52648a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 52748a1b8d4SPankaj Bharadiya status_mask & PIPE_B_PSR_STATUS_VLV)) 528724a6905SVille Syrjälä return 0; 52910c59c51SImre Deak 53010c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 53110c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 53210c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 53310c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 53410c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 53510c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 53610c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 53710c59c51SImre Deak 5386b12ca56SVille Syrjälä out: 53948a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 54048a1b8d4SPankaj Bharadiya enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 5416b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 5426b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 5436b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 5446b12ca56SVille Syrjälä 54510c59c51SImre Deak return enable_mask; 54610c59c51SImre Deak } 54710c59c51SImre Deak 5486b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 5496b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 550755e9019SImre Deak { 5516b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 552755e9019SImre Deak u32 enable_mask; 553755e9019SImre Deak 55448a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5556b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5566b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5576b12ca56SVille Syrjälä 5586b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 55948a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5606b12ca56SVille Syrjälä 5616b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 5626b12ca56SVille Syrjälä return; 5636b12ca56SVille Syrjälä 5646b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 5656b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5666b12ca56SVille Syrjälä 5672939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5682939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 569755e9019SImre Deak } 570755e9019SImre Deak 5716b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 5726b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 573755e9019SImre Deak { 5746b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 575755e9019SImre Deak u32 enable_mask; 576755e9019SImre Deak 57748a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5786b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5796b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5806b12ca56SVille Syrjälä 5816b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 58248a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5836b12ca56SVille Syrjälä 5846b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 5856b12ca56SVille Syrjälä return; 5866b12ca56SVille Syrjälä 5876b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 5886b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5896b12ca56SVille Syrjälä 5902939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5912939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 592755e9019SImre Deak } 593755e9019SImre Deak 594f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 595f3e30485SVille Syrjälä { 596f3e30485SVille Syrjälä if (!dev_priv->opregion.asle) 597f3e30485SVille Syrjälä return false; 598f3e30485SVille Syrjälä 599f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 600f3e30485SVille Syrjälä } 601f3e30485SVille Syrjälä 602c0e09200SDave Airlie /** 603f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 60414bb2c11STvrtko Ursulin * @dev_priv: i915 device private 60501c66889SZhao Yakui */ 60691d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 60701c66889SZhao Yakui { 608f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 609f49e38ddSJani Nikula return; 610f49e38ddSJani Nikula 61113321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 61201c66889SZhao Yakui 613755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 614373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 4) 6153b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 616755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 6171ec14ad3SChris Wilson 61813321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 61901c66889SZhao Yakui } 62001c66889SZhao Yakui 621f75f3746SVille Syrjälä /* 622f75f3746SVille Syrjälä * This timing diagram depicts the video signal in and 623f75f3746SVille Syrjälä * around the vertical blanking period. 624f75f3746SVille Syrjälä * 625f75f3746SVille Syrjälä * Assumptions about the fictitious mode used in this example: 626f75f3746SVille Syrjälä * vblank_start >= 3 627f75f3746SVille Syrjälä * vsync_start = vblank_start + 1 628f75f3746SVille Syrjälä * vsync_end = vblank_start + 2 629f75f3746SVille Syrjälä * vtotal = vblank_start + 3 630f75f3746SVille Syrjälä * 631f75f3746SVille Syrjälä * start of vblank: 632f75f3746SVille Syrjälä * latch double buffered registers 633f75f3746SVille Syrjälä * increment frame counter (ctg+) 634f75f3746SVille Syrjälä * generate start of vblank interrupt (gen4+) 635f75f3746SVille Syrjälä * | 636f75f3746SVille Syrjälä * | frame start: 637f75f3746SVille Syrjälä * | generate frame start interrupt (aka. vblank interrupt) (gmch) 638f75f3746SVille Syrjälä * | may be shifted forward 1-3 extra lines via PIPECONF 639f75f3746SVille Syrjälä * | | 640f75f3746SVille Syrjälä * | | start of vsync: 641f75f3746SVille Syrjälä * | | generate vsync interrupt 642f75f3746SVille Syrjälä * | | | 643f75f3746SVille Syrjälä * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx 644f75f3746SVille Syrjälä * . \hs/ . \hs/ \hs/ \hs/ . \hs/ 645f75f3746SVille Syrjälä * ----va---> <-----------------vb--------------------> <--------va------------- 646f75f3746SVille Syrjälä * | | <----vs-----> | 647f75f3746SVille Syrjälä * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) 648f75f3746SVille Syrjälä * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) 649f75f3746SVille Syrjälä * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) 650f75f3746SVille Syrjälä * | | | 651f75f3746SVille Syrjälä * last visible pixel first visible pixel 652f75f3746SVille Syrjälä * | increment frame counter (gen3/4) 653f75f3746SVille Syrjälä * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) 654f75f3746SVille Syrjälä * 655f75f3746SVille Syrjälä * x = horizontal active 656f75f3746SVille Syrjälä * _ = horizontal blanking 657f75f3746SVille Syrjälä * hs = horizontal sync 658f75f3746SVille Syrjälä * va = vertical active 659f75f3746SVille Syrjälä * vb = vertical blanking 660f75f3746SVille Syrjälä * vs = vertical sync 661f75f3746SVille Syrjälä * vbs = vblank_start (number) 662f75f3746SVille Syrjälä * 663f75f3746SVille Syrjälä * Summary: 664f75f3746SVille Syrjälä * - most events happen at the start of horizontal sync 665f75f3746SVille Syrjälä * - frame start happens at the start of horizontal blank, 1-4 lines 666f75f3746SVille Syrjälä * (depending on PIPECONF settings) after the start of vblank 667f75f3746SVille Syrjälä * - gen3/4 pixel and frame counter are synchronized with the start 668f75f3746SVille Syrjälä * of horizontal active on the first line of vertical active 669f75f3746SVille Syrjälä */ 670f75f3746SVille Syrjälä 67142f52ef8SKeith Packard /* Called from drm generic code, passed a 'crtc', which 67242f52ef8SKeith Packard * we use as a pipe index 67342f52ef8SKeith Packard */ 67408fa8fd0SVille Syrjälä u32 i915_get_vblank_counter(struct drm_crtc *crtc) 6750a3e67a4SJesse Barnes { 67608fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 67708fa8fd0SVille Syrjälä struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; 67832db0b65SVille Syrjälä const struct drm_display_mode *mode = &vblank->hwmode; 67908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 680f0f59a00SVille Syrjälä i915_reg_t high_frame, low_frame; 6810b2a8e09SVille Syrjälä u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; 682694e409dSVille Syrjälä unsigned long irqflags; 683391f75e2SVille Syrjälä 68432db0b65SVille Syrjälä /* 68532db0b65SVille Syrjälä * On i965gm TV output the frame counter only works up to 68632db0b65SVille Syrjälä * the point when we enable the TV encoder. After that the 68732db0b65SVille Syrjälä * frame counter ceases to work and reads zero. We need a 68832db0b65SVille Syrjälä * vblank wait before enabling the TV encoder and so we 68932db0b65SVille Syrjälä * have to enable vblank interrupts while the frame counter 69032db0b65SVille Syrjälä * is still in a working state. However the core vblank code 69132db0b65SVille Syrjälä * does not like us returning non-zero frame counter values 69232db0b65SVille Syrjälä * when we've told it that we don't have a working frame 69332db0b65SVille Syrjälä * counter. Thus we must stop non-zero values leaking out. 69432db0b65SVille Syrjälä */ 69532db0b65SVille Syrjälä if (!vblank->max_vblank_count) 69632db0b65SVille Syrjälä return 0; 69732db0b65SVille Syrjälä 6980b2a8e09SVille Syrjälä htotal = mode->crtc_htotal; 6990b2a8e09SVille Syrjälä hsync_start = mode->crtc_hsync_start; 7000b2a8e09SVille Syrjälä vbl_start = mode->crtc_vblank_start; 7010b2a8e09SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 7020b2a8e09SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 703391f75e2SVille Syrjälä 7040b2a8e09SVille Syrjälä /* Convert to pixel count */ 7050b2a8e09SVille Syrjälä vbl_start *= htotal; 7060b2a8e09SVille Syrjälä 7070b2a8e09SVille Syrjälä /* Start of vblank event occurs at start of hsync */ 7080b2a8e09SVille Syrjälä vbl_start -= htotal - hsync_start; 7090b2a8e09SVille Syrjälä 7109db4a9c7SJesse Barnes high_frame = PIPEFRAME(pipe); 7119db4a9c7SJesse Barnes low_frame = PIPEFRAMEPIXEL(pipe); 7125eddb70bSChris Wilson 713694e409dSVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 714694e409dSVille Syrjälä 7150a3e67a4SJesse Barnes /* 7160a3e67a4SJesse Barnes * High & low register fields aren't synchronized, so make sure 7170a3e67a4SJesse Barnes * we get a low value that's stable across two reads of the high 7180a3e67a4SJesse Barnes * register. 7190a3e67a4SJesse Barnes */ 7200a3e67a4SJesse Barnes do { 7218cbda6b2SJani Nikula high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; 7228cbda6b2SJani Nikula low = intel_de_read_fw(dev_priv, low_frame); 7238cbda6b2SJani Nikula high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; 7240a3e67a4SJesse Barnes } while (high1 != high2); 7250a3e67a4SJesse Barnes 726694e409dSVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 727694e409dSVille Syrjälä 7285eddb70bSChris Wilson high1 >>= PIPE_FRAME_HIGH_SHIFT; 729391f75e2SVille Syrjälä pixel = low & PIPE_PIXEL_MASK; 7305eddb70bSChris Wilson low >>= PIPE_FRAME_LOW_SHIFT; 731391f75e2SVille Syrjälä 732391f75e2SVille Syrjälä /* 733391f75e2SVille Syrjälä * The frame counter increments at beginning of active. 734391f75e2SVille Syrjälä * Cook up a vblank counter by also checking the pixel 735391f75e2SVille Syrjälä * counter against vblank start. 736391f75e2SVille Syrjälä */ 737edc08d0aSVille Syrjälä return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; 7380a3e67a4SJesse Barnes } 7390a3e67a4SJesse Barnes 74008fa8fd0SVille Syrjälä u32 g4x_get_vblank_counter(struct drm_crtc *crtc) 7419880b7a5SJesse Barnes { 74208fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 74333267703SVandita Kulkarni struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; 74408fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 7459880b7a5SJesse Barnes 74633267703SVandita Kulkarni if (!vblank->max_vblank_count) 74733267703SVandita Kulkarni return 0; 74833267703SVandita Kulkarni 7492939eb06SJani Nikula return intel_uncore_read(&dev_priv->uncore, PIPE_FRMCOUNT_G4X(pipe)); 7509880b7a5SJesse Barnes } 7519880b7a5SJesse Barnes 75206d6fda5SVille Syrjälä static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) 753aec0246fSUma Shankar { 754aec0246fSUma Shankar struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 755aec0246fSUma Shankar struct drm_vblank_crtc *vblank = 756aec0246fSUma Shankar &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 757aec0246fSUma Shankar const struct drm_display_mode *mode = &vblank->hwmode; 758aec0246fSUma Shankar u32 htotal = mode->crtc_htotal; 759aec0246fSUma Shankar u32 clock = mode->crtc_clock; 76006d6fda5SVille Syrjälä u32 scan_prev_time, scan_curr_time, scan_post_time; 761aec0246fSUma Shankar 762aec0246fSUma Shankar /* 763aec0246fSUma Shankar * To avoid the race condition where we might cross into the 764aec0246fSUma Shankar * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR 765aec0246fSUma Shankar * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR 766aec0246fSUma Shankar * during the same frame. 767aec0246fSUma Shankar */ 768aec0246fSUma Shankar do { 769aec0246fSUma Shankar /* 770aec0246fSUma Shankar * This field provides read back of the display 771aec0246fSUma Shankar * pipe frame time stamp. The time stamp value 772aec0246fSUma Shankar * is sampled at every start of vertical blank. 773aec0246fSUma Shankar */ 7748cbda6b2SJani Nikula scan_prev_time = intel_de_read_fw(dev_priv, 7758cbda6b2SJani Nikula PIPE_FRMTMSTMP(crtc->pipe)); 776aec0246fSUma Shankar 777aec0246fSUma Shankar /* 778aec0246fSUma Shankar * The TIMESTAMP_CTR register has the current 779aec0246fSUma Shankar * time stamp value. 780aec0246fSUma Shankar */ 7818cbda6b2SJani Nikula scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); 782aec0246fSUma Shankar 7838cbda6b2SJani Nikula scan_post_time = intel_de_read_fw(dev_priv, 7848cbda6b2SJani Nikula PIPE_FRMTMSTMP(crtc->pipe)); 785aec0246fSUma Shankar } while (scan_post_time != scan_prev_time); 786aec0246fSUma Shankar 78706d6fda5SVille Syrjälä return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, 788aec0246fSUma Shankar clock), 1000 * htotal); 78906d6fda5SVille Syrjälä } 79006d6fda5SVille Syrjälä 79106d6fda5SVille Syrjälä /* 79206d6fda5SVille Syrjälä * On certain encoders on certain platforms, pipe 79306d6fda5SVille Syrjälä * scanline register will not work to get the scanline, 79406d6fda5SVille Syrjälä * since the timings are driven from the PORT or issues 79506d6fda5SVille Syrjälä * with scanline register updates. 79606d6fda5SVille Syrjälä * This function will use Framestamp and current 79706d6fda5SVille Syrjälä * timestamp registers to calculate the scanline. 79806d6fda5SVille Syrjälä */ 79906d6fda5SVille Syrjälä static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) 80006d6fda5SVille Syrjälä { 80106d6fda5SVille Syrjälä struct drm_vblank_crtc *vblank = 80206d6fda5SVille Syrjälä &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 80306d6fda5SVille Syrjälä const struct drm_display_mode *mode = &vblank->hwmode; 80406d6fda5SVille Syrjälä u32 vblank_start = mode->crtc_vblank_start; 80506d6fda5SVille Syrjälä u32 vtotal = mode->crtc_vtotal; 80606d6fda5SVille Syrjälä u32 scanline; 80706d6fda5SVille Syrjälä 80806d6fda5SVille Syrjälä scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); 809aec0246fSUma Shankar scanline = min(scanline, vtotal - 1); 810aec0246fSUma Shankar scanline = (scanline + vblank_start) % vtotal; 811aec0246fSUma Shankar 812aec0246fSUma Shankar return scanline; 813aec0246fSUma Shankar } 814aec0246fSUma Shankar 8158cbda6b2SJani Nikula /* 8168cbda6b2SJani Nikula * intel_de_read_fw(), only for fast reads of display block, no need for 8178cbda6b2SJani Nikula * forcewake etc. 8188cbda6b2SJani Nikula */ 819a225f079SVille Syrjälä static int __intel_get_crtc_scanline(struct intel_crtc *crtc) 820a225f079SVille Syrjälä { 821a225f079SVille Syrjälä struct drm_device *dev = crtc->base.dev; 822fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 8235caa0feaSDaniel Vetter const struct drm_display_mode *mode; 8245caa0feaSDaniel Vetter struct drm_vblank_crtc *vblank; 825a225f079SVille Syrjälä enum pipe pipe = crtc->pipe; 82680715b2fSVille Syrjälä int position, vtotal; 827a225f079SVille Syrjälä 82872259536SVille Syrjälä if (!crtc->active) 8292c6afc36SVille Syrjälä return 0; 83072259536SVille Syrjälä 8315caa0feaSDaniel Vetter vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 8325caa0feaSDaniel Vetter mode = &vblank->hwmode; 8335caa0feaSDaniel Vetter 834af157b76SVille Syrjälä if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) 835aec0246fSUma Shankar return __intel_get_crtc_scanline_from_timestamp(crtc); 836aec0246fSUma Shankar 83780715b2fSVille Syrjälä vtotal = mode->crtc_vtotal; 838a225f079SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 839a225f079SVille Syrjälä vtotal /= 2; 840a225f079SVille Syrjälä 84196e4c3c0SVille Syrjälä position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; 842a225f079SVille Syrjälä 843a225f079SVille Syrjälä /* 84441b578fbSJesse Barnes * On HSW, the DSL reg (0x70000) appears to return 0 if we 84541b578fbSJesse Barnes * read it just before the start of vblank. So try it again 84641b578fbSJesse Barnes * so we don't accidentally end up spanning a vblank frame 84741b578fbSJesse Barnes * increment, causing the pipe_update_end() code to squak at us. 84841b578fbSJesse Barnes * 84941b578fbSJesse Barnes * The nature of this problem means we can't simply check the ISR 85041b578fbSJesse Barnes * bit and return the vblank start value; nor can we use the scanline 85141b578fbSJesse Barnes * debug register in the transcoder as it appears to have the same 85241b578fbSJesse Barnes * problem. We may need to extend this to include other platforms, 85341b578fbSJesse Barnes * but so far testing only shows the problem on HSW. 85441b578fbSJesse Barnes */ 85591d14251STvrtko Ursulin if (HAS_DDI(dev_priv) && !position) { 85641b578fbSJesse Barnes int i, temp; 85741b578fbSJesse Barnes 85841b578fbSJesse Barnes for (i = 0; i < 100; i++) { 85941b578fbSJesse Barnes udelay(1); 86096e4c3c0SVille Syrjälä temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; 86141b578fbSJesse Barnes if (temp != position) { 86241b578fbSJesse Barnes position = temp; 86341b578fbSJesse Barnes break; 86441b578fbSJesse Barnes } 86541b578fbSJesse Barnes } 86641b578fbSJesse Barnes } 86741b578fbSJesse Barnes 86841b578fbSJesse Barnes /* 86980715b2fSVille Syrjälä * See update_scanline_offset() for the details on the 87080715b2fSVille Syrjälä * scanline_offset adjustment. 871a225f079SVille Syrjälä */ 87280715b2fSVille Syrjälä return (position + crtc->scanline_offset) % vtotal; 873a225f079SVille Syrjälä } 874a225f079SVille Syrjälä 8754bbffbf3SThomas Zimmermann static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, 8764bbffbf3SThomas Zimmermann bool in_vblank_irq, 8774bbffbf3SThomas Zimmermann int *vpos, int *hpos, 8783bb403bfSVille Syrjälä ktime_t *stime, ktime_t *etime, 8793bb403bfSVille Syrjälä const struct drm_display_mode *mode) 8800af7e4dfSMario Kleiner { 8814bbffbf3SThomas Zimmermann struct drm_device *dev = _crtc->dev; 882fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 8834bbffbf3SThomas Zimmermann struct intel_crtc *crtc = to_intel_crtc(_crtc); 884e8edae54SVille Syrjälä enum pipe pipe = crtc->pipe; 8853aa18df8SVille Syrjälä int position; 88678e8fc6bSVille Syrjälä int vbl_start, vbl_end, hsync_start, htotal, vtotal; 887ad3543edSMario Kleiner unsigned long irqflags; 888373abf1aSMatt Roper bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || 88993e7e61eSLucas De Marchi IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || 890af157b76SVille Syrjälä crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; 8910af7e4dfSMario Kleiner 89248a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { 89300376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 89400376ccfSWambui Karuga "trying to get scanoutpos for disabled " 8959db4a9c7SJesse Barnes "pipe %c\n", pipe_name(pipe)); 8961bf6ad62SDaniel Vetter return false; 8970af7e4dfSMario Kleiner } 8980af7e4dfSMario Kleiner 899c2baf4b7SVille Syrjälä htotal = mode->crtc_htotal; 90078e8fc6bSVille Syrjälä hsync_start = mode->crtc_hsync_start; 901c2baf4b7SVille Syrjälä vtotal = mode->crtc_vtotal; 902c2baf4b7SVille Syrjälä vbl_start = mode->crtc_vblank_start; 903c2baf4b7SVille Syrjälä vbl_end = mode->crtc_vblank_end; 9040af7e4dfSMario Kleiner 905d31faf65SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 906d31faf65SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 907d31faf65SVille Syrjälä vbl_end /= 2; 908d31faf65SVille Syrjälä vtotal /= 2; 909d31faf65SVille Syrjälä } 910d31faf65SVille Syrjälä 911ad3543edSMario Kleiner /* 912ad3543edSMario Kleiner * Lock uncore.lock, as we will do multiple timing critical raw 913ad3543edSMario Kleiner * register reads, potentially with preemption disabled, so the 914ad3543edSMario Kleiner * following code must not block on uncore.lock. 915ad3543edSMario Kleiner */ 916ad3543edSMario Kleiner spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 917ad3543edSMario Kleiner 918ad3543edSMario Kleiner /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ 919ad3543edSMario Kleiner 920ad3543edSMario Kleiner /* Get optional system timestamp before query. */ 921ad3543edSMario Kleiner if (stime) 922ad3543edSMario Kleiner *stime = ktime_get(); 923ad3543edSMario Kleiner 9247a2ec4a0SVille Syrjälä if (crtc->mode_flags & I915_MODE_FLAG_VRR) { 9257a2ec4a0SVille Syrjälä int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); 9267a2ec4a0SVille Syrjälä 9277a2ec4a0SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 9287a2ec4a0SVille Syrjälä 9297a2ec4a0SVille Syrjälä /* 9307a2ec4a0SVille Syrjälä * Already exiting vblank? If so, shift our position 9317a2ec4a0SVille Syrjälä * so it looks like we're already apporaching the full 9327a2ec4a0SVille Syrjälä * vblank end. This should make the generated timestamp 9337a2ec4a0SVille Syrjälä * more or less match when the active portion will start. 9347a2ec4a0SVille Syrjälä */ 9357a2ec4a0SVille Syrjälä if (position >= vbl_start && scanlines < position) 9367a2ec4a0SVille Syrjälä position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); 9377a2ec4a0SVille Syrjälä } else if (use_scanline_counter) { 9380af7e4dfSMario Kleiner /* No obvious pixelcount register. Only query vertical 9390af7e4dfSMario Kleiner * scanout position from Display scan line register. 9400af7e4dfSMario Kleiner */ 941e8edae54SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 9420af7e4dfSMario Kleiner } else { 9430af7e4dfSMario Kleiner /* Have access to pixelcount since start of frame. 9440af7e4dfSMario Kleiner * We can split this into vertical and horizontal 9450af7e4dfSMario Kleiner * scanout position. 9460af7e4dfSMario Kleiner */ 9478cbda6b2SJani Nikula position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; 9480af7e4dfSMario Kleiner 9493aa18df8SVille Syrjälä /* convert to pixel counts */ 9503aa18df8SVille Syrjälä vbl_start *= htotal; 9513aa18df8SVille Syrjälä vbl_end *= htotal; 9523aa18df8SVille Syrjälä vtotal *= htotal; 95378e8fc6bSVille Syrjälä 95478e8fc6bSVille Syrjälä /* 9557e78f1cbSVille Syrjälä * In interlaced modes, the pixel counter counts all pixels, 9567e78f1cbSVille Syrjälä * so one field will have htotal more pixels. In order to avoid 9577e78f1cbSVille Syrjälä * the reported position from jumping backwards when the pixel 9587e78f1cbSVille Syrjälä * counter is beyond the length of the shorter field, just 9597e78f1cbSVille Syrjälä * clamp the position the length of the shorter field. This 9607e78f1cbSVille Syrjälä * matches how the scanline counter based position works since 9617e78f1cbSVille Syrjälä * the scanline counter doesn't count the two half lines. 9627e78f1cbSVille Syrjälä */ 9637e78f1cbSVille Syrjälä if (position >= vtotal) 9647e78f1cbSVille Syrjälä position = vtotal - 1; 9657e78f1cbSVille Syrjälä 9667e78f1cbSVille Syrjälä /* 96778e8fc6bSVille Syrjälä * Start of vblank interrupt is triggered at start of hsync, 96878e8fc6bSVille Syrjälä * just prior to the first active line of vblank. However we 96978e8fc6bSVille Syrjälä * consider lines to start at the leading edge of horizontal 97078e8fc6bSVille Syrjälä * active. So, should we get here before we've crossed into 97178e8fc6bSVille Syrjälä * the horizontal active of the first line in vblank, we would 97278e8fc6bSVille Syrjälä * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, 97378e8fc6bSVille Syrjälä * always add htotal-hsync_start to the current pixel position. 97478e8fc6bSVille Syrjälä */ 97578e8fc6bSVille Syrjälä position = (position + htotal - hsync_start) % vtotal; 9763aa18df8SVille Syrjälä } 9773aa18df8SVille Syrjälä 978ad3543edSMario Kleiner /* Get optional system timestamp after query. */ 979ad3543edSMario Kleiner if (etime) 980ad3543edSMario Kleiner *etime = ktime_get(); 981ad3543edSMario Kleiner 982ad3543edSMario Kleiner /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ 983ad3543edSMario Kleiner 984ad3543edSMario Kleiner spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 985ad3543edSMario Kleiner 9863aa18df8SVille Syrjälä /* 9873aa18df8SVille Syrjälä * While in vblank, position will be negative 9883aa18df8SVille Syrjälä * counting up towards 0 at vbl_end. And outside 9893aa18df8SVille Syrjälä * vblank, position will be positive counting 9903aa18df8SVille Syrjälä * up since vbl_end. 9913aa18df8SVille Syrjälä */ 9923aa18df8SVille Syrjälä if (position >= vbl_start) 9933aa18df8SVille Syrjälä position -= vbl_end; 9943aa18df8SVille Syrjälä else 9953aa18df8SVille Syrjälä position += vtotal - vbl_end; 9963aa18df8SVille Syrjälä 9978a920e24SVille Syrjälä if (use_scanline_counter) { 9983aa18df8SVille Syrjälä *vpos = position; 9993aa18df8SVille Syrjälä *hpos = 0; 10003aa18df8SVille Syrjälä } else { 10010af7e4dfSMario Kleiner *vpos = position / htotal; 10020af7e4dfSMario Kleiner *hpos = position - (*vpos * htotal); 10030af7e4dfSMario Kleiner } 10040af7e4dfSMario Kleiner 10051bf6ad62SDaniel Vetter return true; 10060af7e4dfSMario Kleiner } 10070af7e4dfSMario Kleiner 10084bbffbf3SThomas Zimmermann bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, 10094bbffbf3SThomas Zimmermann ktime_t *vblank_time, bool in_vblank_irq) 10104bbffbf3SThomas Zimmermann { 10114bbffbf3SThomas Zimmermann return drm_crtc_vblank_helper_get_vblank_timestamp_internal( 10124bbffbf3SThomas Zimmermann crtc, max_error, vblank_time, in_vblank_irq, 101348e67807SThomas Zimmermann i915_get_crtc_scanoutpos); 10144bbffbf3SThomas Zimmermann } 10154bbffbf3SThomas Zimmermann 1016a225f079SVille Syrjälä int intel_get_crtc_scanline(struct intel_crtc *crtc) 1017a225f079SVille Syrjälä { 1018fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 1019a225f079SVille Syrjälä unsigned long irqflags; 1020a225f079SVille Syrjälä int position; 1021a225f079SVille Syrjälä 1022a225f079SVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 1023a225f079SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 1024a225f079SVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 1025a225f079SVille Syrjälä 1026a225f079SVille Syrjälä return position; 1027a225f079SVille Syrjälä } 1028a225f079SVille Syrjälä 1029e3689190SBen Widawsky /** 103074bb98baSLucas De Marchi * ivb_parity_work - Workqueue called when a parity error interrupt 1031e3689190SBen Widawsky * occurred. 1032e3689190SBen Widawsky * @work: workqueue struct 1033e3689190SBen Widawsky * 1034e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 1035e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 1036e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 1037e3689190SBen Widawsky */ 103874bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work) 1039e3689190SBen Widawsky { 10402d1013ddSJani Nikula struct drm_i915_private *dev_priv = 1041cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 10422cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 1043e3689190SBen Widawsky u32 error_status, row, bank, subbank; 104435a85ac6SBen Widawsky char *parity_event[6]; 1045a9c287c9SJani Nikula u32 misccpctl; 1046a9c287c9SJani Nikula u8 slice = 0; 1047e3689190SBen Widawsky 1048e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 1049e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 1050e3689190SBen Widawsky * any time we access those registers. 1051e3689190SBen Widawsky */ 105291c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 1053e3689190SBen Widawsky 105435a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 105548a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice)) 105635a85ac6SBen Widawsky goto out; 105735a85ac6SBen Widawsky 10582939eb06SJani Nikula misccpctl = intel_uncore_read(&dev_priv->uncore, GEN7_MISCCPCTL); 10592939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); 10602939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL); 1061e3689190SBen Widawsky 106235a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 1063f0f59a00SVille Syrjälä i915_reg_t reg; 106435a85ac6SBen Widawsky 106535a85ac6SBen Widawsky slice--; 106648a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 106748a1b8d4SPankaj Bharadiya slice >= NUM_L3_SLICES(dev_priv))) 106835a85ac6SBen Widawsky break; 106935a85ac6SBen Widawsky 107035a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 107135a85ac6SBen Widawsky 10726fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 107335a85ac6SBen Widawsky 10742939eb06SJani Nikula error_status = intel_uncore_read(&dev_priv->uncore, reg); 1075e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 1076e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 1077e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 1078e3689190SBen Widawsky 10792939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 10802939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 1081e3689190SBen Widawsky 1082cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 1083e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 1084e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 1085e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 108635a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 108735a85ac6SBen Widawsky parity_event[5] = NULL; 1088e3689190SBen Widawsky 108991c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 1090e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 1091e3689190SBen Widawsky 109235a85ac6SBen Widawsky DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 109335a85ac6SBen Widawsky slice, row, bank, subbank); 1094e3689190SBen Widawsky 109535a85ac6SBen Widawsky kfree(parity_event[4]); 1096e3689190SBen Widawsky kfree(parity_event[3]); 1097e3689190SBen Widawsky kfree(parity_event[2]); 1098e3689190SBen Widawsky kfree(parity_event[1]); 1099e3689190SBen Widawsky } 1100e3689190SBen Widawsky 11012939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl); 110235a85ac6SBen Widawsky 110335a85ac6SBen Widawsky out: 110448a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice); 1105cf1c97dcSAndi Shyti spin_lock_irq(>->irq_lock); 1106cf1c97dcSAndi Shyti gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv)); 1107cf1c97dcSAndi Shyti spin_unlock_irq(>->irq_lock); 110835a85ac6SBen Widawsky 110991c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 111035a85ac6SBen Widawsky } 111135a85ac6SBen Widawsky 1112af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1113121e758eSDhinakaran Pandiyan { 1114af92058fSVille Syrjälä switch (pin) { 1115da51e4baSVille Syrjälä case HPD_PORT_TC1: 1116da51e4baSVille Syrjälä case HPD_PORT_TC2: 1117da51e4baSVille Syrjälä case HPD_PORT_TC3: 1118da51e4baSVille Syrjälä case HPD_PORT_TC4: 1119da51e4baSVille Syrjälä case HPD_PORT_TC5: 1120da51e4baSVille Syrjälä case HPD_PORT_TC6: 11214294fa5fSVille Syrjälä return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin); 112248ef15d3SJosé Roberto de Souza default: 112348ef15d3SJosé Roberto de Souza return false; 112448ef15d3SJosé Roberto de Souza } 112548ef15d3SJosé Roberto de Souza } 112648ef15d3SJosé Roberto de Souza 1127af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 112863c88d22SImre Deak { 1129af92058fSVille Syrjälä switch (pin) { 1130af92058fSVille Syrjälä case HPD_PORT_A: 1131195baa06SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1132af92058fSVille Syrjälä case HPD_PORT_B: 113363c88d22SImre Deak return val & PORTB_HOTPLUG_LONG_DETECT; 1134af92058fSVille Syrjälä case HPD_PORT_C: 113563c88d22SImre Deak return val & PORTC_HOTPLUG_LONG_DETECT; 113663c88d22SImre Deak default: 113763c88d22SImre Deak return false; 113863c88d22SImre Deak } 113963c88d22SImre Deak } 114063c88d22SImre Deak 1141af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 114231604222SAnusha Srivatsa { 1143af92058fSVille Syrjälä switch (pin) { 1144af92058fSVille Syrjälä case HPD_PORT_A: 1145af92058fSVille Syrjälä case HPD_PORT_B: 11468ef7e340SMatt Roper case HPD_PORT_C: 1147229f31e2SLucas De Marchi case HPD_PORT_D: 11484294fa5fSVille Syrjälä return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin); 114931604222SAnusha Srivatsa default: 115031604222SAnusha Srivatsa return false; 115131604222SAnusha Srivatsa } 115231604222SAnusha Srivatsa } 115331604222SAnusha Srivatsa 1154af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 115531604222SAnusha Srivatsa { 1156af92058fSVille Syrjälä switch (pin) { 1157da51e4baSVille Syrjälä case HPD_PORT_TC1: 1158da51e4baSVille Syrjälä case HPD_PORT_TC2: 1159da51e4baSVille Syrjälä case HPD_PORT_TC3: 1160da51e4baSVille Syrjälä case HPD_PORT_TC4: 1161da51e4baSVille Syrjälä case HPD_PORT_TC5: 1162da51e4baSVille Syrjälä case HPD_PORT_TC6: 11634294fa5fSVille Syrjälä return val & ICP_TC_HPD_LONG_DETECT(pin); 116452dfdba0SLucas De Marchi default: 116552dfdba0SLucas De Marchi return false; 116652dfdba0SLucas De Marchi } 116752dfdba0SLucas De Marchi } 116852dfdba0SLucas De Marchi 1169af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) 11706dbf30ceSVille Syrjälä { 1171af92058fSVille Syrjälä switch (pin) { 1172af92058fSVille Syrjälä case HPD_PORT_E: 11736dbf30ceSVille Syrjälä return val & PORTE_HOTPLUG_LONG_DETECT; 11746dbf30ceSVille Syrjälä default: 11756dbf30ceSVille Syrjälä return false; 11766dbf30ceSVille Syrjälä } 11776dbf30ceSVille Syrjälä } 11786dbf30ceSVille Syrjälä 1179af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 118074c0b395SVille Syrjälä { 1181af92058fSVille Syrjälä switch (pin) { 1182af92058fSVille Syrjälä case HPD_PORT_A: 118374c0b395SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1184af92058fSVille Syrjälä case HPD_PORT_B: 118574c0b395SVille Syrjälä return val & PORTB_HOTPLUG_LONG_DETECT; 1186af92058fSVille Syrjälä case HPD_PORT_C: 118774c0b395SVille Syrjälä return val & PORTC_HOTPLUG_LONG_DETECT; 1188af92058fSVille Syrjälä case HPD_PORT_D: 118974c0b395SVille Syrjälä return val & PORTD_HOTPLUG_LONG_DETECT; 119074c0b395SVille Syrjälä default: 119174c0b395SVille Syrjälä return false; 119274c0b395SVille Syrjälä } 119374c0b395SVille Syrjälä } 119474c0b395SVille Syrjälä 1195af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1196e4ce95aaSVille Syrjälä { 1197af92058fSVille Syrjälä switch (pin) { 1198af92058fSVille Syrjälä case HPD_PORT_A: 1199e4ce95aaSVille Syrjälä return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; 1200e4ce95aaSVille Syrjälä default: 1201e4ce95aaSVille Syrjälä return false; 1202e4ce95aaSVille Syrjälä } 1203e4ce95aaSVille Syrjälä } 1204e4ce95aaSVille Syrjälä 1205af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 120613cf5504SDave Airlie { 1207af92058fSVille Syrjälä switch (pin) { 1208af92058fSVille Syrjälä case HPD_PORT_B: 1209676574dfSJani Nikula return val & PORTB_HOTPLUG_LONG_DETECT; 1210af92058fSVille Syrjälä case HPD_PORT_C: 1211676574dfSJani Nikula return val & PORTC_HOTPLUG_LONG_DETECT; 1212af92058fSVille Syrjälä case HPD_PORT_D: 1213676574dfSJani Nikula return val & PORTD_HOTPLUG_LONG_DETECT; 1214676574dfSJani Nikula default: 1215676574dfSJani Nikula return false; 121613cf5504SDave Airlie } 121713cf5504SDave Airlie } 121813cf5504SDave Airlie 1219af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 122013cf5504SDave Airlie { 1221af92058fSVille Syrjälä switch (pin) { 1222af92058fSVille Syrjälä case HPD_PORT_B: 1223676574dfSJani Nikula return val & PORTB_HOTPLUG_INT_LONG_PULSE; 1224af92058fSVille Syrjälä case HPD_PORT_C: 1225676574dfSJani Nikula return val & PORTC_HOTPLUG_INT_LONG_PULSE; 1226af92058fSVille Syrjälä case HPD_PORT_D: 1227676574dfSJani Nikula return val & PORTD_HOTPLUG_INT_LONG_PULSE; 1228676574dfSJani Nikula default: 1229676574dfSJani Nikula return false; 123013cf5504SDave Airlie } 123113cf5504SDave Airlie } 123213cf5504SDave Airlie 123342db67d6SVille Syrjälä /* 123442db67d6SVille Syrjälä * Get a bit mask of pins that have triggered, and which ones may be long. 123542db67d6SVille Syrjälä * This can be called multiple times with the same masks to accumulate 123642db67d6SVille Syrjälä * hotplug detection results from several registers. 123742db67d6SVille Syrjälä * 123842db67d6SVille Syrjälä * Note that the caller is expected to zero out the masks initially. 123942db67d6SVille Syrjälä */ 1240cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, 1241cf53902fSRodrigo Vivi u32 *pin_mask, u32 *long_mask, 12428c841e57SJani Nikula u32 hotplug_trigger, u32 dig_hotplug_reg, 1243fd63e2a9SImre Deak const u32 hpd[HPD_NUM_PINS], 1244af92058fSVille Syrjälä bool long_pulse_detect(enum hpd_pin pin, u32 val)) 1245676574dfSJani Nikula { 1246e9be2850SVille Syrjälä enum hpd_pin pin; 1247676574dfSJani Nikula 124852dfdba0SLucas De Marchi BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS); 124952dfdba0SLucas De Marchi 1250e9be2850SVille Syrjälä for_each_hpd_pin(pin) { 1251e9be2850SVille Syrjälä if ((hpd[pin] & hotplug_trigger) == 0) 12528c841e57SJani Nikula continue; 12538c841e57SJani Nikula 1254e9be2850SVille Syrjälä *pin_mask |= BIT(pin); 1255676574dfSJani Nikula 1256af92058fSVille Syrjälä if (long_pulse_detect(pin, dig_hotplug_reg)) 1257e9be2850SVille Syrjälä *long_mask |= BIT(pin); 1258676574dfSJani Nikula } 1259676574dfSJani Nikula 126000376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 126100376ccfSWambui Karuga "hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n", 1262f88f0478SVille Syrjälä hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); 1263676574dfSJani Nikula 1264676574dfSJani Nikula } 1265676574dfSJani Nikula 1266a0e066b8SVille Syrjälä static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, 1267a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 1268a0e066b8SVille Syrjälä { 1269a0e066b8SVille Syrjälä struct intel_encoder *encoder; 1270a0e066b8SVille Syrjälä u32 enabled_irqs = 0; 1271a0e066b8SVille Syrjälä 1272a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 1273a0e066b8SVille Syrjälä if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) 1274a0e066b8SVille Syrjälä enabled_irqs |= hpd[encoder->hpd_pin]; 1275a0e066b8SVille Syrjälä 1276a0e066b8SVille Syrjälä return enabled_irqs; 1277a0e066b8SVille Syrjälä } 1278a0e066b8SVille Syrjälä 1279a0e066b8SVille Syrjälä static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, 1280a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 1281a0e066b8SVille Syrjälä { 1282a0e066b8SVille Syrjälä struct intel_encoder *encoder; 1283a0e066b8SVille Syrjälä u32 hotplug_irqs = 0; 1284a0e066b8SVille Syrjälä 1285a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 1286a0e066b8SVille Syrjälä hotplug_irqs |= hpd[encoder->hpd_pin]; 1287a0e066b8SVille Syrjälä 1288a0e066b8SVille Syrjälä return hotplug_irqs; 1289a0e066b8SVille Syrjälä } 1290a0e066b8SVille Syrjälä 12912ea63927SVille Syrjälä static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915, 12922ea63927SVille Syrjälä hotplug_enables_func hotplug_enables) 12932ea63927SVille Syrjälä { 12942ea63927SVille Syrjälä struct intel_encoder *encoder; 12952ea63927SVille Syrjälä u32 hotplug = 0; 12962ea63927SVille Syrjälä 12972ea63927SVille Syrjälä for_each_intel_encoder(&i915->drm, encoder) 12982ea63927SVille Syrjälä hotplug |= hotplug_enables(i915, encoder->hpd_pin); 12992ea63927SVille Syrjälä 13002ea63927SVille Syrjälä return hotplug; 13012ea63927SVille Syrjälä } 13022ea63927SVille Syrjälä 130391d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv) 1304515ac2bbSDaniel Vetter { 130528c70f16SDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1306515ac2bbSDaniel Vetter } 1307515ac2bbSDaniel Vetter 130891d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) 1309ce99c256SDaniel Vetter { 13109ee32feaSDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1311ce99c256SDaniel Vetter } 1312ce99c256SDaniel Vetter 13138bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 131491d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 131591d14251STvrtko Ursulin enum pipe pipe, 1316a9c287c9SJani Nikula u32 crc0, u32 crc1, 1317a9c287c9SJani Nikula u32 crc2, u32 crc3, 1318a9c287c9SJani Nikula u32 crc4) 13198bf1e9f1SShuang He { 13207794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe); 132100535527SJani Nikula struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc; 13225cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 13235cee6c45SVille Syrjälä 13245cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 1325b2c88f5bSDamien Lespiau 1326d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 13278c6b709dSTomeu Vizoso /* 13288c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 13298c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 13308c6b709dSTomeu Vizoso * out the buggy result. 13318c6b709dSTomeu Vizoso * 1332163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 13338c6b709dSTomeu Vizoso * don't trust that one either. 13348c6b709dSTomeu Vizoso */ 1335033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 1336373abf1aSMatt Roper (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 13378c6b709dSTomeu Vizoso pipe_crc->skipped++; 13388c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 13398c6b709dSTomeu Vizoso return; 13408c6b709dSTomeu Vizoso } 13418c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 13426cc42152SMaarten Lankhorst 1343246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 1344ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 1345246ee524STomeu Vizoso crcs); 13468c6b709dSTomeu Vizoso } 1347277de95eSDaniel Vetter #else 1348277de95eSDaniel Vetter static inline void 134991d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 135091d14251STvrtko Ursulin enum pipe pipe, 1351a9c287c9SJani Nikula u32 crc0, u32 crc1, 1352a9c287c9SJani Nikula u32 crc2, u32 crc3, 1353a9c287c9SJani Nikula u32 crc4) {} 1354277de95eSDaniel Vetter #endif 1355eba94eb9SDaniel Vetter 13561288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915, 13571288f9b0SKarthik B S enum pipe pipe) 13581288f9b0SKarthik B S { 13597794b6deSJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe); 13601288f9b0SKarthik B S struct drm_crtc_state *crtc_state = crtc->base.state; 13611288f9b0SKarthik B S struct drm_pending_vblank_event *e = crtc_state->event; 13621288f9b0SKarthik B S struct drm_device *dev = &i915->drm; 13631288f9b0SKarthik B S unsigned long irqflags; 13641288f9b0SKarthik B S 13651288f9b0SKarthik B S spin_lock_irqsave(&dev->event_lock, irqflags); 13661288f9b0SKarthik B S 13671288f9b0SKarthik B S crtc_state->event = NULL; 13681288f9b0SKarthik B S 13691288f9b0SKarthik B S drm_crtc_send_vblank_event(&crtc->base, e); 13701288f9b0SKarthik B S 13711288f9b0SKarthik B S spin_unlock_irqrestore(&dev->event_lock, irqflags); 13721288f9b0SKarthik B S } 1373277de95eSDaniel Vetter 137491d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 137591d14251STvrtko Ursulin enum pipe pipe) 13765a69b89fSDaniel Vetter { 137791d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 13782939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 13795a69b89fSDaniel Vetter 0, 0, 0, 0); 13805a69b89fSDaniel Vetter } 13815a69b89fSDaniel Vetter 138291d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 138391d14251STvrtko Ursulin enum pipe pipe) 1384eba94eb9SDaniel Vetter { 138591d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 13862939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 13872939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)), 13882939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)), 13892939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)), 13902939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe))); 1391eba94eb9SDaniel Vetter } 13925b3a856bSDaniel Vetter 139391d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 139491d14251STvrtko Ursulin enum pipe pipe) 13955b3a856bSDaniel Vetter { 1396a9c287c9SJani Nikula u32 res1, res2; 13970b5c5ed0SDaniel Vetter 1398373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 3) 13992939eb06SJani Nikula res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe)); 14000b5c5ed0SDaniel Vetter else 14010b5c5ed0SDaniel Vetter res1 = 0; 14020b5c5ed0SDaniel Vetter 1403373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv)) 14042939eb06SJani Nikula res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe)); 14050b5c5ed0SDaniel Vetter else 14060b5c5ed0SDaniel Vetter res2 = 0; 14075b3a856bSDaniel Vetter 140891d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 14092939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)), 14102939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)), 14112939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)), 14120b5c5ed0SDaniel Vetter res1, res2); 14135b3a856bSDaniel Vetter } 14148bf1e9f1SShuang He 141544d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 141644d9241eSVille Syrjälä { 141744d9241eSVille Syrjälä enum pipe pipe; 141844d9241eSVille Syrjälä 141944d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 14202939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe), 142144d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 142244d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 142344d9241eSVille Syrjälä 142444d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 142544d9241eSVille Syrjälä } 142644d9241eSVille Syrjälä } 142744d9241eSVille Syrjälä 1428eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 142991d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 14307e231dbeSJesse Barnes { 1431d048a268SVille Syrjälä enum pipe pipe; 14327e231dbeSJesse Barnes 143358ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 14341ca993d2SVille Syrjälä 14351ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 14361ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 14371ca993d2SVille Syrjälä return; 14381ca993d2SVille Syrjälä } 14391ca993d2SVille Syrjälä 1440055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1441f0f59a00SVille Syrjälä i915_reg_t reg; 14426b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 144391d181ddSImre Deak 1444bbb5eebfSDaniel Vetter /* 1445bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 1446bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 1447bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 1448bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 1449bbb5eebfSDaniel Vetter * handle. 1450bbb5eebfSDaniel Vetter */ 14510f239f4cSDaniel Vetter 14520f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 14536b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 1454bbb5eebfSDaniel Vetter 1455bbb5eebfSDaniel Vetter switch (pipe) { 1456d048a268SVille Syrjälä default: 1457bbb5eebfSDaniel Vetter case PIPE_A: 1458bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 1459bbb5eebfSDaniel Vetter break; 1460bbb5eebfSDaniel Vetter case PIPE_B: 1461bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1462bbb5eebfSDaniel Vetter break; 14633278f67fSVille Syrjälä case PIPE_C: 14643278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 14653278f67fSVille Syrjälä break; 1466bbb5eebfSDaniel Vetter } 1467bbb5eebfSDaniel Vetter if (iir & iir_bit) 14686b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 1469bbb5eebfSDaniel Vetter 14706b12ca56SVille Syrjälä if (!status_mask) 147191d181ddSImre Deak continue; 147291d181ddSImre Deak 147391d181ddSImre Deak reg = PIPESTAT(pipe); 14742939eb06SJani Nikula pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; 14756b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 14767e231dbeSJesse Barnes 14777e231dbeSJesse Barnes /* 14787e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 1479132c27c9SVille Syrjälä * 1480132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 1481132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 1482132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 1483132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 1484132c27c9SVille Syrjälä * an interrupt is still pending. 14857e231dbeSJesse Barnes */ 1486132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 14872939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]); 14882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask); 1489132c27c9SVille Syrjälä } 14907e231dbeSJesse Barnes } 149158ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 14922ecb8ca4SVille Syrjälä } 14932ecb8ca4SVille Syrjälä 1494eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1495eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 1496eb64343cSVille Syrjälä { 1497eb64343cSVille Syrjälä enum pipe pipe; 1498eb64343cSVille Syrjälä 1499eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1500eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1501aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1502eb64343cSVille Syrjälä 1503eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1504eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1505eb64343cSVille Syrjälä 1506eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1507eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1508eb64343cSVille Syrjälä } 1509eb64343cSVille Syrjälä } 1510eb64343cSVille Syrjälä 1511eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1512eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1513eb64343cSVille Syrjälä { 1514eb64343cSVille Syrjälä bool blc_event = false; 1515eb64343cSVille Syrjälä enum pipe pipe; 1516eb64343cSVille Syrjälä 1517eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1518eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1519aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1520eb64343cSVille Syrjälä 1521eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1522eb64343cSVille Syrjälä blc_event = true; 1523eb64343cSVille Syrjälä 1524eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1525eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1526eb64343cSVille Syrjälä 1527eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1528eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1529eb64343cSVille Syrjälä } 1530eb64343cSVille Syrjälä 1531eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1532eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1533eb64343cSVille Syrjälä } 1534eb64343cSVille Syrjälä 1535eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1536eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1537eb64343cSVille Syrjälä { 1538eb64343cSVille Syrjälä bool blc_event = false; 1539eb64343cSVille Syrjälä enum pipe pipe; 1540eb64343cSVille Syrjälä 1541eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1542eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1543aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1544eb64343cSVille Syrjälä 1545eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1546eb64343cSVille Syrjälä blc_event = true; 1547eb64343cSVille Syrjälä 1548eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1549eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1550eb64343cSVille Syrjälä 1551eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1552eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1553eb64343cSVille Syrjälä } 1554eb64343cSVille Syrjälä 1555eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1556eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1557eb64343cSVille Syrjälä 1558eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 1559eb64343cSVille Syrjälä gmbus_irq_handler(dev_priv); 1560eb64343cSVille Syrjälä } 1561eb64343cSVille Syrjälä 156291d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 15632ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 15642ecb8ca4SVille Syrjälä { 15652ecb8ca4SVille Syrjälä enum pipe pipe; 15667e231dbeSJesse Barnes 1567055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1568fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1569aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 15704356d586SDaniel Vetter 15716ede6b06SVille Syrjälä if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) 15726ede6b06SVille Syrjälä flip_done_handler(dev_priv, pipe); 15736ede6b06SVille Syrjälä 15744356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 157591d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 15762d9d2b0bSVille Syrjälä 15771f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 15781f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 157931acc7f5SJesse Barnes } 158031acc7f5SJesse Barnes 1581c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 158291d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1583c1874ed7SImre Deak } 1584c1874ed7SImre Deak 15851ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 158616c6c56bSVille Syrjälä { 15870ba7c51aSVille Syrjälä u32 hotplug_status = 0, hotplug_status_mask; 15880ba7c51aSVille Syrjälä int i; 158916c6c56bSVille Syrjälä 15900ba7c51aSVille Syrjälä if (IS_G4X(dev_priv) || 15910ba7c51aSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 15920ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | 15930ba7c51aSVille Syrjälä DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; 15940ba7c51aSVille Syrjälä else 15950ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_I915; 15960ba7c51aSVille Syrjälä 15970ba7c51aSVille Syrjälä /* 15980ba7c51aSVille Syrjälä * We absolutely have to clear all the pending interrupt 15990ba7c51aSVille Syrjälä * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port 16000ba7c51aSVille Syrjälä * interrupt bit won't have an edge, and the i965/g4x 16010ba7c51aSVille Syrjälä * edge triggered IIR will not notice that an interrupt 16020ba7c51aSVille Syrjälä * is still pending. We can't use PORT_HOTPLUG_EN to 16030ba7c51aSVille Syrjälä * guarantee the edge as the act of toggling the enable 16040ba7c51aSVille Syrjälä * bits can itself generate a new hotplug interrupt :( 16050ba7c51aSVille Syrjälä */ 16060ba7c51aSVille Syrjälä for (i = 0; i < 10; i++) { 16072939eb06SJani Nikula u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask; 16080ba7c51aSVille Syrjälä 16090ba7c51aSVille Syrjälä if (tmp == 0) 16100ba7c51aSVille Syrjälä return hotplug_status; 16110ba7c51aSVille Syrjälä 16120ba7c51aSVille Syrjälä hotplug_status |= tmp; 16132939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status); 16140ba7c51aSVille Syrjälä } 16150ba7c51aSVille Syrjälä 161648a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 1, 16170ba7c51aSVille Syrjälä "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", 16182939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 16191ae3c34cSVille Syrjälä 16201ae3c34cSVille Syrjälä return hotplug_status; 16211ae3c34cSVille Syrjälä } 16221ae3c34cSVille Syrjälä 162391d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, 16241ae3c34cSVille Syrjälä u32 hotplug_status) 16251ae3c34cSVille Syrjälä { 16261ae3c34cSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 16270398993bSVille Syrjälä u32 hotplug_trigger; 16283ff60f89SOscar Mateo 16290398993bSVille Syrjälä if (IS_G4X(dev_priv) || 16300398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 16310398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; 16320398993bSVille Syrjälä else 16330398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; 163416c6c56bSVille Syrjälä 163558f2cf24SVille Syrjälä if (hotplug_trigger) { 1636cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1637cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 16380398993bSVille Syrjälä dev_priv->hotplug.hpd, 1639fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 164058f2cf24SVille Syrjälä 164191d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 164258f2cf24SVille Syrjälä } 1643369712e8SJani Nikula 16440398993bSVille Syrjälä if ((IS_G4X(dev_priv) || 16450398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && 16460398993bSVille Syrjälä hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) 164791d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 164858f2cf24SVille Syrjälä } 164916c6c56bSVille Syrjälä 1650c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 1651c1874ed7SImre Deak { 1652b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 1653c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 1654c1874ed7SImre Deak 16552dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 16562dd2a883SImre Deak return IRQ_NONE; 16572dd2a883SImre Deak 16581f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 16599102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 16601f814dacSImre Deak 16611e1cace9SVille Syrjälä do { 16626e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 16632ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 16641ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1665a5e485a9SVille Syrjälä u32 ier = 0; 16663ff60f89SOscar Mateo 16672939eb06SJani Nikula gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR); 16682939eb06SJani Nikula pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR); 16692939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 1670c1874ed7SImre Deak 1671c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 16721e1cace9SVille Syrjälä break; 1673c1874ed7SImre Deak 1674c1874ed7SImre Deak ret = IRQ_HANDLED; 1675c1874ed7SImre Deak 1676a5e485a9SVille Syrjälä /* 1677a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1678a5e485a9SVille Syrjälä * 1679a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1680a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 1681a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 1682a5e485a9SVille Syrjälä * 1683a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1684a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 1685a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1686a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 1687a5e485a9SVille Syrjälä * bits this time around. 1688a5e485a9SVille Syrjälä */ 16892939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 16902939eb06SJani Nikula ier = intel_uncore_read(&dev_priv->uncore, VLV_IER); 16912939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, 0); 16924a0a0202SVille Syrjälä 16934a0a0202SVille Syrjälä if (gt_iir) 16942939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir); 16954a0a0202SVille Syrjälä if (pm_iir) 16962939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir); 16974a0a0202SVille Syrjälä 16987ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 16991ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 17007ce4d1f2SVille Syrjälä 17013ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 17023ff60f89SOscar Mateo * signalled in iir */ 1703eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 17047ce4d1f2SVille Syrjälä 1705eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1706eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 1707eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1708eef57324SJerome Anand 17097ce4d1f2SVille Syrjälä /* 17107ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 17117ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 17127ce4d1f2SVille Syrjälä */ 17137ce4d1f2SVille Syrjälä if (iir) 17142939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 17154a0a0202SVille Syrjälä 17162939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 17172939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 17181ae3c34cSVille Syrjälä 171952894874SVille Syrjälä if (gt_iir) 17202cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(dev_priv), gt_iir); 172152894874SVille Syrjälä if (pm_iir) 17222cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir); 172352894874SVille Syrjälä 17241ae3c34cSVille Syrjälä if (hotplug_status) 172591d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 17262ecb8ca4SVille Syrjälä 172791d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 17281e1cace9SVille Syrjälä } while (0); 17297e231dbeSJesse Barnes 17309c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 17319c6508b9SThomas Gleixner 17329102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 17331f814dacSImre Deak 17347e231dbeSJesse Barnes return ret; 17357e231dbeSJesse Barnes } 17367e231dbeSJesse Barnes 173743f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 173843f328d7SVille Syrjälä { 1739b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 174043f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 174143f328d7SVille Syrjälä 17422dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 17432dd2a883SImre Deak return IRQ_NONE; 17442dd2a883SImre Deak 17451f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 17469102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 17471f814dacSImre Deak 1748579de73bSChris Wilson do { 17496e814800SVille Syrjälä u32 master_ctl, iir; 17502ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 17511ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1752a5e485a9SVille Syrjälä u32 ier = 0; 1753a5e485a9SVille Syrjälä 17542939eb06SJani Nikula master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 17552939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 17563278f67fSVille Syrjälä 17573278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 17588e5fd599SVille Syrjälä break; 175943f328d7SVille Syrjälä 176027b6c122SOscar Mateo ret = IRQ_HANDLED; 176127b6c122SOscar Mateo 1762a5e485a9SVille Syrjälä /* 1763a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1764a5e485a9SVille Syrjälä * 1765a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1766a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 1767a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 1768a5e485a9SVille Syrjälä * 1769a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1770a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 1771a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1772a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 1773a5e485a9SVille Syrjälä * bits this time around. 1774a5e485a9SVille Syrjälä */ 17752939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); 17762939eb06SJani Nikula ier = intel_uncore_read(&dev_priv->uncore, VLV_IER); 17772939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, 0); 177843f328d7SVille Syrjälä 17792cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 178027b6c122SOscar Mateo 178127b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 17821ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 178343f328d7SVille Syrjälä 178427b6c122SOscar Mateo /* Call regardless, as some status bits might not be 178527b6c122SOscar Mateo * signalled in iir */ 1786eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 178743f328d7SVille Syrjälä 1788eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1789eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 1790eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 1791eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1792eef57324SJerome Anand 17937ce4d1f2SVille Syrjälä /* 17947ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 17957ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 17967ce4d1f2SVille Syrjälä */ 17977ce4d1f2SVille Syrjälä if (iir) 17982939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 17997ce4d1f2SVille Syrjälä 18002939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 18012939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 18021ae3c34cSVille Syrjälä 18031ae3c34cSVille Syrjälä if (hotplug_status) 180491d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 18052ecb8ca4SVille Syrjälä 180691d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 1807579de73bSChris Wilson } while (0); 18083278f67fSVille Syrjälä 18099c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 18109c6508b9SThomas Gleixner 18119102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 18121f814dacSImre Deak 181343f328d7SVille Syrjälä return ret; 181443f328d7SVille Syrjälä } 181543f328d7SVille Syrjälä 181691d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, 18170398993bSVille Syrjälä u32 hotplug_trigger) 1818776ad806SJesse Barnes { 181942db67d6SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1820776ad806SJesse Barnes 18216a39d7c9SJani Nikula /* 18226a39d7c9SJani Nikula * Somehow the PCH doesn't seem to really ack the interrupt to the CPU 18236a39d7c9SJani Nikula * unless we touch the hotplug register, even if hotplug_trigger is 18246a39d7c9SJani Nikula * zero. Not acking leads to "The master control interrupt lied (SDE)!" 18256a39d7c9SJani Nikula * errors. 18266a39d7c9SJani Nikula */ 18272939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 18286a39d7c9SJani Nikula if (!hotplug_trigger) { 18296a39d7c9SJani Nikula u32 mask = PORTA_HOTPLUG_STATUS_MASK | 18306a39d7c9SJani Nikula PORTD_HOTPLUG_STATUS_MASK | 18316a39d7c9SJani Nikula PORTC_HOTPLUG_STATUS_MASK | 18326a39d7c9SJani Nikula PORTB_HOTPLUG_STATUS_MASK; 18336a39d7c9SJani Nikula dig_hotplug_reg &= ~mask; 18346a39d7c9SJani Nikula } 18356a39d7c9SJani Nikula 18362939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 18376a39d7c9SJani Nikula if (!hotplug_trigger) 18386a39d7c9SJani Nikula return; 183913cf5504SDave Airlie 18400398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18410398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 18420398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 1843fd63e2a9SImre Deak pch_port_hotplug_long_detect); 184440e56410SVille Syrjälä 184591d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1846aaf5ec2eSSonika Jindal } 184791d131d2SDaniel Vetter 184891d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 184940e56410SVille Syrjälä { 1850d048a268SVille Syrjälä enum pipe pipe; 185140e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 185240e56410SVille Syrjälä 18530398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 185440e56410SVille Syrjälä 1855cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 1856cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 1857776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 185800376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n", 1859cfc33bf7SVille Syrjälä port_name(port)); 1860cfc33bf7SVille Syrjälä } 1861776ad806SJesse Barnes 1862ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 186391d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 1864ce99c256SDaniel Vetter 1865776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 186691d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1867776ad806SJesse Barnes 1868776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 186900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n"); 1870776ad806SJesse Barnes 1871776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 187200376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n"); 1873776ad806SJesse Barnes 1874776ad806SJesse Barnes if (pch_iir & SDE_POISON) 187500376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1876776ad806SJesse Barnes 1877b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK) { 1878055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 187900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 18809db4a9c7SJesse Barnes pipe_name(pipe), 18812939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1882b8b65ccdSAnshuman Gupta } 1883776ad806SJesse Barnes 1884776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 188500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n"); 1886776ad806SJesse Barnes 1887776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 188800376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 188900376ccfSWambui Karuga "PCH transcoder CRC error interrupt\n"); 1890776ad806SJesse Barnes 1891776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 1892a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 18938664281bSPaulo Zanoni 18948664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 1895a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 18968664281bSPaulo Zanoni } 18978664281bSPaulo Zanoni 189891d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 18998664281bSPaulo Zanoni { 19002939eb06SJani Nikula u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT); 19015a69b89fSDaniel Vetter enum pipe pipe; 19028664281bSPaulo Zanoni 1903de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 190400376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1905de032bf4SPaulo Zanoni 1906055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 19071f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 19081f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 19098664281bSPaulo Zanoni 19105a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 191191d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 191291d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 19135a69b89fSDaniel Vetter else 191491d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 19155a69b89fSDaniel Vetter } 19165a69b89fSDaniel Vetter } 19178bf1e9f1SShuang He 19182939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int); 19198664281bSPaulo Zanoni } 19208664281bSPaulo Zanoni 192191d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 19228664281bSPaulo Zanoni { 19232939eb06SJani Nikula u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT); 192445c1cd87SMika Kahola enum pipe pipe; 19258664281bSPaulo Zanoni 1926de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 192700376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1928de032bf4SPaulo Zanoni 192945c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 193045c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 193145c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 19328664281bSPaulo Zanoni 19332939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int); 1934776ad806SJesse Barnes } 1935776ad806SJesse Barnes 193691d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 193723e81d69SAdam Jackson { 1938d048a268SVille Syrjälä enum pipe pipe; 19396dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 1940aaf5ec2eSSonika Jindal 19410398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 194291d131d2SDaniel Vetter 1943cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 1944cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 194523e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 194600376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n", 1947cfc33bf7SVille Syrjälä port_name(port)); 1948cfc33bf7SVille Syrjälä } 194923e81d69SAdam Jackson 195023e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 195191d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 195223e81d69SAdam Jackson 195323e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 195491d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 195523e81d69SAdam Jackson 195623e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 195700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n"); 195823e81d69SAdam Jackson 195923e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 196000376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n"); 196123e81d69SAdam Jackson 1962b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK_CPT) { 1963055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 196400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 196523e81d69SAdam Jackson pipe_name(pipe), 19662939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1967b8b65ccdSAnshuman Gupta } 19688664281bSPaulo Zanoni 19698664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 197091d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 197123e81d69SAdam Jackson } 197223e81d69SAdam Jackson 197358676af6SLucas De Marchi static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 197431604222SAnusha Srivatsa { 1975e76ab2cfSVille Syrjälä u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP; 1976e76ab2cfSVille Syrjälä u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP; 197731604222SAnusha Srivatsa u32 pin_mask = 0, long_mask = 0; 197831604222SAnusha Srivatsa 197931604222SAnusha Srivatsa if (ddi_hotplug_trigger) { 198031604222SAnusha Srivatsa u32 dig_hotplug_reg; 198131604222SAnusha Srivatsa 19822939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI); 19832939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, dig_hotplug_reg); 198431604222SAnusha Srivatsa 198531604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 19860398993bSVille Syrjälä ddi_hotplug_trigger, dig_hotplug_reg, 19870398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 198831604222SAnusha Srivatsa icp_ddi_port_hotplug_long_detect); 198931604222SAnusha Srivatsa } 199031604222SAnusha Srivatsa 199131604222SAnusha Srivatsa if (tc_hotplug_trigger) { 199231604222SAnusha Srivatsa u32 dig_hotplug_reg; 199331604222SAnusha Srivatsa 19942939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC); 19952939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, dig_hotplug_reg); 199631604222SAnusha Srivatsa 199731604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 19980398993bSVille Syrjälä tc_hotplug_trigger, dig_hotplug_reg, 19990398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 2000da51e4baSVille Syrjälä icp_tc_port_hotplug_long_detect); 200152dfdba0SLucas De Marchi } 200252dfdba0SLucas De Marchi 200352dfdba0SLucas De Marchi if (pin_mask) 200452dfdba0SLucas De Marchi intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 200552dfdba0SLucas De Marchi 200652dfdba0SLucas De Marchi if (pch_iir & SDE_GMBUS_ICP) 200752dfdba0SLucas De Marchi gmbus_irq_handler(dev_priv); 200852dfdba0SLucas De Marchi } 200952dfdba0SLucas De Marchi 201091d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 20116dbf30ceSVille Syrjälä { 20126dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & 20136dbf30ceSVille Syrjälä ~SDE_PORTE_HOTPLUG_SPT; 20146dbf30ceSVille Syrjälä u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; 20156dbf30ceSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 20166dbf30ceSVille Syrjälä 20176dbf30ceSVille Syrjälä if (hotplug_trigger) { 20186dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 20196dbf30ceSVille Syrjälä 20202939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 20212939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 20226dbf30ceSVille Syrjälä 2023cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 20240398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 20250398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 202674c0b395SVille Syrjälä spt_port_hotplug_long_detect); 20276dbf30ceSVille Syrjälä } 20286dbf30ceSVille Syrjälä 20296dbf30ceSVille Syrjälä if (hotplug2_trigger) { 20306dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 20316dbf30ceSVille Syrjälä 20322939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2); 20332939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, dig_hotplug_reg); 20346dbf30ceSVille Syrjälä 2035cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 20360398993bSVille Syrjälä hotplug2_trigger, dig_hotplug_reg, 20370398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 20386dbf30ceSVille Syrjälä spt_port_hotplug2_long_detect); 20396dbf30ceSVille Syrjälä } 20406dbf30ceSVille Syrjälä 20416dbf30ceSVille Syrjälä if (pin_mask) 204291d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 20436dbf30ceSVille Syrjälä 20446dbf30ceSVille Syrjälä if (pch_iir & SDE_GMBUS_CPT) 204591d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 20466dbf30ceSVille Syrjälä } 20476dbf30ceSVille Syrjälä 204891d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, 20490398993bSVille Syrjälä u32 hotplug_trigger) 2050c008bc6eSPaulo Zanoni { 2051e4ce95aaSVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2052e4ce95aaSVille Syrjälä 20532939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL); 20542939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); 2055e4ce95aaSVille Syrjälä 20560398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 20570398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 20580398993bSVille Syrjälä dev_priv->hotplug.hpd, 2059e4ce95aaSVille Syrjälä ilk_port_hotplug_long_detect); 206040e56410SVille Syrjälä 206191d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2062e4ce95aaSVille Syrjälä } 2063c008bc6eSPaulo Zanoni 206491d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 206591d14251STvrtko Ursulin u32 de_iir) 206640e56410SVille Syrjälä { 206740e56410SVille Syrjälä enum pipe pipe; 206840e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 206940e56410SVille Syrjälä 207040e56410SVille Syrjälä if (hotplug_trigger) 20710398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 207240e56410SVille Syrjälä 2073c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 207491d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2075c008bc6eSPaulo Zanoni 2076c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 207791d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2078c008bc6eSPaulo Zanoni 2079c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 208000376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 2081c008bc6eSPaulo Zanoni 2082055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2083fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 2084aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 2085c008bc6eSPaulo Zanoni 20864bb18054SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE(pipe)) 20874bb18054SVille Syrjälä flip_done_handler(dev_priv, pipe); 20884bb18054SVille Syrjälä 208940da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 20901f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 2091c008bc6eSPaulo Zanoni 209240da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 209391d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 2094c008bc6eSPaulo Zanoni } 2095c008bc6eSPaulo Zanoni 2096c008bc6eSPaulo Zanoni /* check event from PCH */ 2097c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 20982939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 2099c008bc6eSPaulo Zanoni 210091d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 210191d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 2102c008bc6eSPaulo Zanoni else 210391d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 2104c008bc6eSPaulo Zanoni 2105c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 21062939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 2107c008bc6eSPaulo Zanoni } 2108c008bc6eSPaulo Zanoni 210993e7e61eSLucas De Marchi if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT) 21102cbc876dSMichał Winiarski gen5_rps_irq_handler(&to_gt(dev_priv)->rps); 2111c008bc6eSPaulo Zanoni } 2112c008bc6eSPaulo Zanoni 211391d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 211491d14251STvrtko Ursulin u32 de_iir) 21159719fb98SPaulo Zanoni { 211607d27e20SDamien Lespiau enum pipe pipe; 211723bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 211823bb4cb5SVille Syrjälä 211940e56410SVille Syrjälä if (hotplug_trigger) 21200398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 21219719fb98SPaulo Zanoni 21229719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 212391d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 21249719fb98SPaulo Zanoni 21259719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 212691d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 21279719fb98SPaulo Zanoni 21289719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 212991d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 21309719fb98SPaulo Zanoni 2131055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 213233ef04faSVille Syrjälä if (de_iir & DE_PIPE_VBLANK_IVB(pipe)) 2133aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 21342a636e24SVille Syrjälä 21352a636e24SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) 21362a636e24SVille Syrjälä flip_done_handler(dev_priv, pipe); 21379719fb98SPaulo Zanoni } 21389719fb98SPaulo Zanoni 21399719fb98SPaulo Zanoni /* check event from PCH */ 214091d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 21412939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 21429719fb98SPaulo Zanoni 214391d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 21449719fb98SPaulo Zanoni 21459719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 21462939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 21479719fb98SPaulo Zanoni } 21489719fb98SPaulo Zanoni } 21499719fb98SPaulo Zanoni 215072c90f62SOscar Mateo /* 215172c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 215272c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 215372c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 215472c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 215572c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 215672c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 215772c90f62SOscar Mateo */ 21589eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg) 2159b1f14ad0SJesse Barnes { 2160c48a798aSChris Wilson struct drm_i915_private *i915 = arg; 2161c48a798aSChris Wilson void __iomem * const regs = i915->uncore.regs; 2162f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 21630e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 2164b1f14ad0SJesse Barnes 2165c48a798aSChris Wilson if (unlikely(!intel_irqs_enabled(i915))) 21662dd2a883SImre Deak return IRQ_NONE; 21672dd2a883SImre Deak 21681f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2169c48a798aSChris Wilson disable_rpm_wakeref_asserts(&i915->runtime_pm); 21701f814dacSImre Deak 2171b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 2172c48a798aSChris Wilson de_ier = raw_reg_read(regs, DEIER); 2173c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 21740e43406bSChris Wilson 217544498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 217644498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 217744498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 217844498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 217944498aeaSPaulo Zanoni * due to its back queue). */ 2180c48a798aSChris Wilson if (!HAS_PCH_NOP(i915)) { 2181c48a798aSChris Wilson sde_ier = raw_reg_read(regs, SDEIER); 2182c48a798aSChris Wilson raw_reg_write(regs, SDEIER, 0); 2183ab5c608bSBen Widawsky } 218444498aeaSPaulo Zanoni 218572c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 218672c90f62SOscar Mateo 2187c48a798aSChris Wilson gt_iir = raw_reg_read(regs, GTIIR); 21880e43406bSChris Wilson if (gt_iir) { 2189c48a798aSChris Wilson raw_reg_write(regs, GTIIR, gt_iir); 2190651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) 21912cbc876dSMichał Winiarski gen6_gt_irq_handler(to_gt(i915), gt_iir); 2192d8fc8a47SPaulo Zanoni else 21932cbc876dSMichał Winiarski gen5_gt_irq_handler(to_gt(i915), gt_iir); 2194c48a798aSChris Wilson ret = IRQ_HANDLED; 21950e43406bSChris Wilson } 2196b1f14ad0SJesse Barnes 2197c48a798aSChris Wilson de_iir = raw_reg_read(regs, DEIIR); 21980e43406bSChris Wilson if (de_iir) { 2199c48a798aSChris Wilson raw_reg_write(regs, DEIIR, de_iir); 2200373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 7) 2201c48a798aSChris Wilson ivb_display_irq_handler(i915, de_iir); 2202f1af8fc1SPaulo Zanoni else 2203c48a798aSChris Wilson ilk_display_irq_handler(i915, de_iir); 22040e43406bSChris Wilson ret = IRQ_HANDLED; 2205c48a798aSChris Wilson } 2206c48a798aSChris Wilson 2207651e7d48SLucas De Marchi if (GRAPHICS_VER(i915) >= 6) { 2208c48a798aSChris Wilson u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR); 2209c48a798aSChris Wilson if (pm_iir) { 2210c48a798aSChris Wilson raw_reg_write(regs, GEN6_PMIIR, pm_iir); 22112cbc876dSMichał Winiarski gen6_rps_irq_handler(&to_gt(i915)->rps, pm_iir); 2212c48a798aSChris Wilson ret = IRQ_HANDLED; 22130e43406bSChris Wilson } 2214f1af8fc1SPaulo Zanoni } 2215b1f14ad0SJesse Barnes 2216c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier); 2217c48a798aSChris Wilson if (sde_ier) 2218c48a798aSChris Wilson raw_reg_write(regs, SDEIER, sde_ier); 2219b1f14ad0SJesse Barnes 22209c6508b9SThomas Gleixner pmu_irq_stats(i915, ret); 22219c6508b9SThomas Gleixner 22221f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2223c48a798aSChris Wilson enable_rpm_wakeref_asserts(&i915->runtime_pm); 22241f814dacSImre Deak 2225b1f14ad0SJesse Barnes return ret; 2226b1f14ad0SJesse Barnes } 2227b1f14ad0SJesse Barnes 222891d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, 22290398993bSVille Syrjälä u32 hotplug_trigger) 2230d04a492dSShashank Sharma { 2231cebd87a0SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2232d04a492dSShashank Sharma 22332939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 22342939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 2235d04a492dSShashank Sharma 22360398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 22370398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 22380398993bSVille Syrjälä dev_priv->hotplug.hpd, 2239cebd87a0SVille Syrjälä bxt_port_hotplug_long_detect); 224040e56410SVille Syrjälä 224191d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2242d04a492dSShashank Sharma } 2243d04a492dSShashank Sharma 2244121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2245121e758eSDhinakaran Pandiyan { 2246121e758eSDhinakaran Pandiyan u32 pin_mask = 0, long_mask = 0; 2247b796b971SDhinakaran Pandiyan u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; 2248b796b971SDhinakaran Pandiyan u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; 2249121e758eSDhinakaran Pandiyan 2250121e758eSDhinakaran Pandiyan if (trigger_tc) { 2251b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2252b796b971SDhinakaran Pandiyan 22532939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL); 22542939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, dig_hotplug_reg); 2255121e758eSDhinakaran Pandiyan 22560398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 22570398993bSVille Syrjälä trigger_tc, dig_hotplug_reg, 22580398993bSVille Syrjälä dev_priv->hotplug.hpd, 2259da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 2260121e758eSDhinakaran Pandiyan } 2261b796b971SDhinakaran Pandiyan 2262b796b971SDhinakaran Pandiyan if (trigger_tbt) { 2263b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2264b796b971SDhinakaran Pandiyan 22652939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL); 22662939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, dig_hotplug_reg); 2267b796b971SDhinakaran Pandiyan 22680398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 22690398993bSVille Syrjälä trigger_tbt, dig_hotplug_reg, 22700398993bSVille Syrjälä dev_priv->hotplug.hpd, 2271da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 2272b796b971SDhinakaran Pandiyan } 2273b796b971SDhinakaran Pandiyan 2274b796b971SDhinakaran Pandiyan if (pin_mask) 2275b796b971SDhinakaran Pandiyan intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2276b796b971SDhinakaran Pandiyan else 227700376ccfSWambui Karuga drm_err(&dev_priv->drm, 227800376ccfSWambui Karuga "Unexpected DE HPD interrupt 0x%08x\n", iir); 2279121e758eSDhinakaran Pandiyan } 2280121e758eSDhinakaran Pandiyan 22819d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 22829d17210fSLucas De Marchi { 228355523360SLucas De Marchi u32 mask; 22849d17210fSLucas De Marchi 228520fe778fSMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 228620fe778fSMatt Roper return TGL_DE_PORT_AUX_DDIA | 228720fe778fSMatt Roper TGL_DE_PORT_AUX_DDIB | 228820fe778fSMatt Roper TGL_DE_PORT_AUX_DDIC | 228920fe778fSMatt Roper XELPD_DE_PORT_AUX_DDID | 229020fe778fSMatt Roper XELPD_DE_PORT_AUX_DDIE | 229120fe778fSMatt Roper TGL_DE_PORT_AUX_USBC1 | 229220fe778fSMatt Roper TGL_DE_PORT_AUX_USBC2 | 229320fe778fSMatt Roper TGL_DE_PORT_AUX_USBC3 | 229420fe778fSMatt Roper TGL_DE_PORT_AUX_USBC4; 229520fe778fSMatt Roper else if (DISPLAY_VER(dev_priv) >= 12) 229655523360SLucas De Marchi return TGL_DE_PORT_AUX_DDIA | 229755523360SLucas De Marchi TGL_DE_PORT_AUX_DDIB | 2298e5df52dcSMatt Roper TGL_DE_PORT_AUX_DDIC | 2299e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC1 | 2300e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC2 | 2301e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC3 | 2302e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC4 | 2303e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC5 | 2304e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC6; 2305e5df52dcSMatt Roper 230655523360SLucas De Marchi 230755523360SLucas De Marchi mask = GEN8_AUX_CHANNEL_A; 2308373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 9) 23099d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 23109d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 23119d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 23129d17210fSLucas De Marchi 2313938a8a9aSLucas De Marchi if (DISPLAY_VER(dev_priv) == 11) { 2314938a8a9aSLucas De Marchi mask |= ICL_AUX_CHANNEL_F; 231555523360SLucas De Marchi mask |= ICL_AUX_CHANNEL_E; 2316938a8a9aSLucas De Marchi } 23179d17210fSLucas De Marchi 23189d17210fSLucas De Marchi return mask; 23199d17210fSLucas De Marchi } 23209d17210fSLucas De Marchi 23215270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) 23225270130dSVille Syrjälä { 23231649a4ccSMatt Roper if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv)) 232499e2d8bcSMatt Roper return RKL_DE_PIPE_IRQ_FAULT_ERRORS; 2325373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 11) 2326d506a65dSMatt Roper return GEN11_DE_PIPE_IRQ_FAULT_ERRORS; 2327373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 9) 23285270130dSVille Syrjälä return GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 23295270130dSVille Syrjälä else 23305270130dSVille Syrjälä return GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 23315270130dSVille Syrjälä } 23325270130dSVille Syrjälä 233346c63d24SJosé Roberto de Souza static void 233446c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2335abd58f01SBen Widawsky { 2336e04f7eceSVille Syrjälä bool found = false; 2337e04f7eceSVille Syrjälä 2338e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 233991d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2340e04f7eceSVille Syrjälä found = true; 2341e04f7eceSVille Syrjälä } 2342e04f7eceSVille Syrjälä 2343e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 2344b64d6c51SGwan-gyeong Mun struct intel_encoder *encoder; 23458241cfbeSJosé Roberto de Souza u32 psr_iir; 23468241cfbeSJosé Roberto de Souza i915_reg_t iir_reg; 23478241cfbeSJosé Roberto de Souza 2348a22af61dSJosé Roberto de Souza for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) { 2349b64d6c51SGwan-gyeong Mun struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 2350b64d6c51SGwan-gyeong Mun 2351373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 2352b64d6c51SGwan-gyeong Mun iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder); 23538241cfbeSJosé Roberto de Souza else 23548241cfbeSJosé Roberto de Souza iir_reg = EDP_PSR_IIR; 23558241cfbeSJosé Roberto de Souza 23562939eb06SJani Nikula psr_iir = intel_uncore_read(&dev_priv->uncore, iir_reg); 23572939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, iir_reg, psr_iir); 23588241cfbeSJosé Roberto de Souza 23598241cfbeSJosé Roberto de Souza if (psr_iir) 23608241cfbeSJosé Roberto de Souza found = true; 236154fd3149SDhinakaran Pandiyan 2362b64d6c51SGwan-gyeong Mun intel_psr_irq_handler(intel_dp, psr_iir); 2363b64d6c51SGwan-gyeong Mun 2364b64d6c51SGwan-gyeong Mun /* prior GEN12 only have one EDP PSR */ 2365373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) < 12) 2366b64d6c51SGwan-gyeong Mun break; 2367b64d6c51SGwan-gyeong Mun } 2368e04f7eceSVille Syrjälä } 2369e04f7eceSVille Syrjälä 2370e04f7eceSVille Syrjälä if (!found) 237100376ccfSWambui Karuga drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n"); 2372abd58f01SBen Widawsky } 237346c63d24SJosé Roberto de Souza 237400acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, 237500acb329SVandita Kulkarni u32 te_trigger) 237600acb329SVandita Kulkarni { 237700acb329SVandita Kulkarni enum pipe pipe = INVALID_PIPE; 237800acb329SVandita Kulkarni enum transcoder dsi_trans; 237900acb329SVandita Kulkarni enum port port; 238000acb329SVandita Kulkarni u32 val, tmp; 238100acb329SVandita Kulkarni 238200acb329SVandita Kulkarni /* 238300acb329SVandita Kulkarni * Incase of dual link, TE comes from DSI_1 238400acb329SVandita Kulkarni * this is to check if dual link is enabled 238500acb329SVandita Kulkarni */ 23862939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0)); 238700acb329SVandita Kulkarni val &= PORT_SYNC_MODE_ENABLE; 238800acb329SVandita Kulkarni 238900acb329SVandita Kulkarni /* 239000acb329SVandita Kulkarni * if dual link is enabled, then read DSI_0 239100acb329SVandita Kulkarni * transcoder registers 239200acb329SVandita Kulkarni */ 239300acb329SVandita Kulkarni port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ? 239400acb329SVandita Kulkarni PORT_A : PORT_B; 239500acb329SVandita Kulkarni dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; 239600acb329SVandita Kulkarni 239700acb329SVandita Kulkarni /* Check if DSI configured in command mode */ 23982939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans)); 239900acb329SVandita Kulkarni val = val & OP_MODE_MASK; 240000acb329SVandita Kulkarni 240100acb329SVandita Kulkarni if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { 240200acb329SVandita Kulkarni drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n"); 240300acb329SVandita Kulkarni return; 240400acb329SVandita Kulkarni } 240500acb329SVandita Kulkarni 240600acb329SVandita Kulkarni /* Get PIPE for handling VBLANK event */ 24072939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans)); 240800acb329SVandita Kulkarni switch (val & TRANS_DDI_EDP_INPUT_MASK) { 240900acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_A_ON: 241000acb329SVandita Kulkarni pipe = PIPE_A; 241100acb329SVandita Kulkarni break; 241200acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_B_ONOFF: 241300acb329SVandita Kulkarni pipe = PIPE_B; 241400acb329SVandita Kulkarni break; 241500acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_C_ONOFF: 241600acb329SVandita Kulkarni pipe = PIPE_C; 241700acb329SVandita Kulkarni break; 241800acb329SVandita Kulkarni default: 241900acb329SVandita Kulkarni drm_err(&dev_priv->drm, "Invalid PIPE\n"); 242000acb329SVandita Kulkarni return; 242100acb329SVandita Kulkarni } 242200acb329SVandita Kulkarni 242300acb329SVandita Kulkarni intel_handle_vblank(dev_priv, pipe); 242400acb329SVandita Kulkarni 242500acb329SVandita Kulkarni /* clear TE in dsi IIR */ 242600acb329SVandita Kulkarni port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; 24272939eb06SJani Nikula tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port)); 24282939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp); 242900acb329SVandita Kulkarni } 243000acb329SVandita Kulkarni 2431cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) 2432cda195f1SVille Syrjälä { 2433373abf1aSMatt Roper if (DISPLAY_VER(i915) >= 9) 2434cda195f1SVille Syrjälä return GEN9_PIPE_PLANE1_FLIP_DONE; 2435cda195f1SVille Syrjälä else 2436cda195f1SVille Syrjälä return GEN8_PIPE_PRIMARY_FLIP_DONE; 2437cda195f1SVille Syrjälä } 2438cda195f1SVille Syrjälä 24398bcc0840SMatt Roper u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv) 24408bcc0840SMatt Roper { 24418bcc0840SMatt Roper u32 mask = GEN8_PIPE_FIFO_UNDERRUN; 24428bcc0840SMatt Roper 24438bcc0840SMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 24448bcc0840SMatt Roper mask |= XELPD_PIPE_SOFT_UNDERRUN | 24458bcc0840SMatt Roper XELPD_PIPE_HARD_UNDERRUN; 24468bcc0840SMatt Roper 24478bcc0840SMatt Roper return mask; 24488bcc0840SMatt Roper } 24498bcc0840SMatt Roper 245046c63d24SJosé Roberto de Souza static irqreturn_t 245146c63d24SJosé Roberto de Souza gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 245246c63d24SJosé Roberto de Souza { 245346c63d24SJosé Roberto de Souza irqreturn_t ret = IRQ_NONE; 245446c63d24SJosé Roberto de Souza u32 iir; 245546c63d24SJosé Roberto de Souza enum pipe pipe; 245646c63d24SJosé Roberto de Souza 2457a844cfbeSJosé Roberto de Souza drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv)); 2458a844cfbeSJosé Roberto de Souza 245946c63d24SJosé Roberto de Souza if (master_ctl & GEN8_DE_MISC_IRQ) { 24602939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR); 246146c63d24SJosé Roberto de Souza if (iir) { 24622939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir); 246346c63d24SJosé Roberto de Souza ret = IRQ_HANDLED; 246446c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(dev_priv, iir); 246546c63d24SJosé Roberto de Souza } else { 246600376ccfSWambui Karuga drm_err(&dev_priv->drm, 246700376ccfSWambui Karuga "The master control interrupt lied (DE MISC)!\n"); 2468abd58f01SBen Widawsky } 246946c63d24SJosé Roberto de Souza } 2470abd58f01SBen Widawsky 2471373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 24722939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR); 2473121e758eSDhinakaran Pandiyan if (iir) { 24742939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir); 2475121e758eSDhinakaran Pandiyan ret = IRQ_HANDLED; 2476121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 2477121e758eSDhinakaran Pandiyan } else { 247800376ccfSWambui Karuga drm_err(&dev_priv->drm, 247900376ccfSWambui Karuga "The master control interrupt lied, (DE HPD)!\n"); 2480121e758eSDhinakaran Pandiyan } 2481121e758eSDhinakaran Pandiyan } 2482121e758eSDhinakaran Pandiyan 24836d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 24842939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR); 2485e32192e1STvrtko Ursulin if (iir) { 2486d04a492dSShashank Sharma bool found = false; 2487cebd87a0SVille Syrjälä 24882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir); 24896d766f02SDaniel Vetter ret = IRQ_HANDLED; 249088e04703SJesse Barnes 24919d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 249291d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2493d04a492dSShashank Sharma found = true; 2494d04a492dSShashank Sharma } 2495d04a492dSShashank Sharma 249670bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { 24979a55a620SVille Syrjälä u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK; 24989a55a620SVille Syrjälä 24999a55a620SVille Syrjälä if (hotplug_trigger) { 25009a55a620SVille Syrjälä bxt_hpd_irq_handler(dev_priv, hotplug_trigger); 2501d04a492dSShashank Sharma found = true; 2502d04a492dSShashank Sharma } 2503e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 25049a55a620SVille Syrjälä u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK; 25059a55a620SVille Syrjälä 25069a55a620SVille Syrjälä if (hotplug_trigger) { 25079a55a620SVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 2508e32192e1STvrtko Ursulin found = true; 2509e32192e1STvrtko Ursulin } 2510e32192e1STvrtko Ursulin } 2511d04a492dSShashank Sharma 251270bfb307SMatt Roper if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) && 251370bfb307SMatt Roper (iir & BXT_DE_PORT_GMBUS)) { 251491d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 25159e63743eSShashank Sharma found = true; 25169e63743eSShashank Sharma } 25179e63743eSShashank Sharma 2518373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 25199a55a620SVille Syrjälä u32 te_trigger = iir & (DSI0_TE | DSI1_TE); 25209a55a620SVille Syrjälä 25219a55a620SVille Syrjälä if (te_trigger) { 25229a55a620SVille Syrjälä gen11_dsi_te_interrupt_handler(dev_priv, te_trigger); 252300acb329SVandita Kulkarni found = true; 252400acb329SVandita Kulkarni } 252500acb329SVandita Kulkarni } 252600acb329SVandita Kulkarni 2527d04a492dSShashank Sharma if (!found) 252800376ccfSWambui Karuga drm_err(&dev_priv->drm, 252900376ccfSWambui Karuga "Unexpected DE Port interrupt\n"); 25306d766f02SDaniel Vetter } 253138cc46d7SOscar Mateo else 253200376ccfSWambui Karuga drm_err(&dev_priv->drm, 253300376ccfSWambui Karuga "The master control interrupt lied (DE PORT)!\n"); 25346d766f02SDaniel Vetter } 25356d766f02SDaniel Vetter 2536055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2537fd3a4024SDaniel Vetter u32 fault_errors; 2538abd58f01SBen Widawsky 2539c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 2540c42664ccSDaniel Vetter continue; 2541c42664ccSDaniel Vetter 25422939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); 2543e32192e1STvrtko Ursulin if (!iir) { 254400376ccfSWambui Karuga drm_err(&dev_priv->drm, 254500376ccfSWambui Karuga "The master control interrupt lied (DE PIPE)!\n"); 2546e32192e1STvrtko Ursulin continue; 2547e32192e1STvrtko Ursulin } 2548770de83dSDamien Lespiau 2549e32192e1STvrtko Ursulin ret = IRQ_HANDLED; 25502939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir); 2551e32192e1STvrtko Ursulin 2552fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 2553aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 2554abd58f01SBen Widawsky 2555cda195f1SVille Syrjälä if (iir & gen8_de_pipe_flip_done_mask(dev_priv)) 25561288f9b0SKarthik B S flip_done_handler(dev_priv, pipe); 25571288f9b0SKarthik B S 2558e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 255991d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 25600fbe7870SDaniel Vetter 25618bcc0840SMatt Roper if (iir & gen8_de_pipe_underrun_mask(dev_priv)) 2562e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 256338d83c96SDaniel Vetter 25645270130dSVille Syrjälä fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); 2565770de83dSDamien Lespiau if (fault_errors) 256600376ccfSWambui Karuga drm_err(&dev_priv->drm, 256700376ccfSWambui Karuga "Fault errors on pipe %c: 0x%08x\n", 256830100f2bSDaniel Vetter pipe_name(pipe), 2569e32192e1STvrtko Ursulin fault_errors); 2570abd58f01SBen Widawsky } 2571abd58f01SBen Widawsky 257291d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 2573266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 257492d03a80SDaniel Vetter /* 257592d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 257692d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 257792d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 257892d03a80SDaniel Vetter */ 25792939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 2580e32192e1STvrtko Ursulin if (iir) { 25812939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, iir); 258292d03a80SDaniel Vetter ret = IRQ_HANDLED; 25836dbf30ceSVille Syrjälä 258458676af6SLucas De Marchi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 258558676af6SLucas De Marchi icp_irq_handler(dev_priv, iir); 2586c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 258791d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 25886dbf30ceSVille Syrjälä else 258991d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 25902dfb0b81SJani Nikula } else { 25912dfb0b81SJani Nikula /* 25922dfb0b81SJani Nikula * Like on previous PCH there seems to be something 25932dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 25942dfb0b81SJani Nikula */ 259500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 259600376ccfSWambui Karuga "The master control interrupt lied (SDE)!\n"); 25972dfb0b81SJani Nikula } 259892d03a80SDaniel Vetter } 259992d03a80SDaniel Vetter 2600f11a0f46STvrtko Ursulin return ret; 2601f11a0f46STvrtko Ursulin } 2602f11a0f46STvrtko Ursulin 26034376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 26044376b9c9SMika Kuoppala { 26054376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 26064376b9c9SMika Kuoppala 26074376b9c9SMika Kuoppala /* 26084376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 26094376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 26104376b9c9SMika Kuoppala * New indications can and will light up during processing, 26114376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 26124376b9c9SMika Kuoppala */ 26134376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 26144376b9c9SMika Kuoppala } 26154376b9c9SMika Kuoppala 26164376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 26174376b9c9SMika Kuoppala { 26184376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 26194376b9c9SMika Kuoppala } 26204376b9c9SMika Kuoppala 2621f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 2622f11a0f46STvrtko Ursulin { 2623b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 262425286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 2625f11a0f46STvrtko Ursulin u32 master_ctl; 2626f11a0f46STvrtko Ursulin 2627f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 2628f11a0f46STvrtko Ursulin return IRQ_NONE; 2629f11a0f46STvrtko Ursulin 26304376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 26314376b9c9SMika Kuoppala if (!master_ctl) { 26324376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2633f11a0f46STvrtko Ursulin return IRQ_NONE; 26344376b9c9SMika Kuoppala } 2635f11a0f46STvrtko Ursulin 26366cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 26372cbc876dSMichał Winiarski gen8_gt_irq_handler(to_gt(dev_priv), master_ctl); 2638f0fd96f5SChris Wilson 2639f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2640f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 26419102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 264255ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 26439102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 2644f0fd96f5SChris Wilson } 2645f11a0f46STvrtko Ursulin 26464376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2647abd58f01SBen Widawsky 26489c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 26499c6508b9SThomas Gleixner 265055ef72f2SChris Wilson return IRQ_HANDLED; 2651abd58f01SBen Widawsky } 2652abd58f01SBen Widawsky 265351951ae7SMika Kuoppala static u32 26549b77011eSTvrtko Ursulin gen11_gu_misc_irq_ack(struct intel_gt *gt, const u32 master_ctl) 2655df0d28c1SDhinakaran Pandiyan { 26569b77011eSTvrtko Ursulin void __iomem * const regs = gt->uncore->regs; 26577a909383SChris Wilson u32 iir; 2658df0d28c1SDhinakaran Pandiyan 2659df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 26607a909383SChris Wilson return 0; 2661df0d28c1SDhinakaran Pandiyan 26627a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 26637a909383SChris Wilson if (likely(iir)) 26647a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 26657a909383SChris Wilson 26667a909383SChris Wilson return iir; 2667df0d28c1SDhinakaran Pandiyan } 2668df0d28c1SDhinakaran Pandiyan 2669df0d28c1SDhinakaran Pandiyan static void 26709b77011eSTvrtko Ursulin gen11_gu_misc_irq_handler(struct intel_gt *gt, const u32 iir) 2671df0d28c1SDhinakaran Pandiyan { 2672df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 26739b77011eSTvrtko Ursulin intel_opregion_asle_intr(gt->i915); 2674df0d28c1SDhinakaran Pandiyan } 2675df0d28c1SDhinakaran Pandiyan 267681067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 267781067b71SMika Kuoppala { 267881067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 267981067b71SMika Kuoppala 268081067b71SMika Kuoppala /* 268181067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 268281067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 268381067b71SMika Kuoppala * New indications can and will light up during processing, 268481067b71SMika Kuoppala * and will generate new interrupt after enabling master. 268581067b71SMika Kuoppala */ 268681067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 268781067b71SMika Kuoppala } 268881067b71SMika Kuoppala 268981067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 269081067b71SMika Kuoppala { 269181067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 269281067b71SMika Kuoppala } 269381067b71SMika Kuoppala 2694a3265d85SMatt Roper static void 2695a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915) 2696a3265d85SMatt Roper { 2697a3265d85SMatt Roper void __iomem * const regs = i915->uncore.regs; 2698a3265d85SMatt Roper const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 2699a3265d85SMatt Roper 2700a3265d85SMatt Roper disable_rpm_wakeref_asserts(&i915->runtime_pm); 2701a3265d85SMatt Roper /* 2702a3265d85SMatt Roper * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 2703a3265d85SMatt Roper * for the display related bits. 2704a3265d85SMatt Roper */ 2705a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); 2706a3265d85SMatt Roper gen8_de_irq_handler(i915, disp_ctl); 2707a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 2708a3265d85SMatt Roper GEN11_DISPLAY_IRQ_ENABLE); 2709a3265d85SMatt Roper 2710a3265d85SMatt Roper enable_rpm_wakeref_asserts(&i915->runtime_pm); 2711a3265d85SMatt Roper } 2712a3265d85SMatt Roper 271322e26af7SPaulo Zanoni static irqreturn_t gen11_irq_handler(int irq, void *arg) 271451951ae7SMika Kuoppala { 271522e26af7SPaulo Zanoni struct drm_i915_private *i915 = arg; 271625286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 27172cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 271851951ae7SMika Kuoppala u32 master_ctl; 2719df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 272051951ae7SMika Kuoppala 272151951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 272251951ae7SMika Kuoppala return IRQ_NONE; 272351951ae7SMika Kuoppala 272422e26af7SPaulo Zanoni master_ctl = gen11_master_intr_disable(regs); 272581067b71SMika Kuoppala if (!master_ctl) { 272622e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 272751951ae7SMika Kuoppala return IRQ_NONE; 272881067b71SMika Kuoppala } 272951951ae7SMika Kuoppala 27306cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 27319b77011eSTvrtko Ursulin gen11_gt_irq_handler(gt, master_ctl); 273251951ae7SMika Kuoppala 273351951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2734a3265d85SMatt Roper if (master_ctl & GEN11_DISPLAY_IRQ) 2735a3265d85SMatt Roper gen11_display_irq_handler(i915); 273651951ae7SMika Kuoppala 27379b77011eSTvrtko Ursulin gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl); 2738df0d28c1SDhinakaran Pandiyan 273922e26af7SPaulo Zanoni gen11_master_intr_enable(regs); 274051951ae7SMika Kuoppala 27419b77011eSTvrtko Ursulin gen11_gu_misc_irq_handler(gt, gu_misc_iir); 2742df0d28c1SDhinakaran Pandiyan 27439c6508b9SThomas Gleixner pmu_irq_stats(i915, IRQ_HANDLED); 27449c6508b9SThomas Gleixner 274551951ae7SMika Kuoppala return IRQ_HANDLED; 274651951ae7SMika Kuoppala } 274751951ae7SMika Kuoppala 274822e26af7SPaulo Zanoni static inline u32 dg1_master_intr_disable(void __iomem * const regs) 274997b492f5SLucas De Marchi { 275097b492f5SLucas De Marchi u32 val; 275197b492f5SLucas De Marchi 275297b492f5SLucas De Marchi /* First disable interrupts */ 275322e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0); 275497b492f5SLucas De Marchi 275597b492f5SLucas De Marchi /* Get the indication levels and ack the master unit */ 275622e26af7SPaulo Zanoni val = raw_reg_read(regs, DG1_MSTR_TILE_INTR); 275797b492f5SLucas De Marchi if (unlikely(!val)) 275897b492f5SLucas De Marchi return 0; 275997b492f5SLucas De Marchi 276022e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, val); 276197b492f5SLucas De Marchi 276297b492f5SLucas De Marchi return val; 276397b492f5SLucas De Marchi } 276497b492f5SLucas De Marchi 276597b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs) 276697b492f5SLucas De Marchi { 276722e26af7SPaulo Zanoni raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ); 276897b492f5SLucas De Marchi } 276997b492f5SLucas De Marchi 277097b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg) 277197b492f5SLucas De Marchi { 277222e26af7SPaulo Zanoni struct drm_i915_private * const i915 = arg; 27732cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 2774fd4d7904SPaulo Zanoni void __iomem * const regs = gt->uncore->regs; 277522e26af7SPaulo Zanoni u32 master_tile_ctl, master_ctl; 277622e26af7SPaulo Zanoni u32 gu_misc_iir; 277722e26af7SPaulo Zanoni 277822e26af7SPaulo Zanoni if (!intel_irqs_enabled(i915)) 277922e26af7SPaulo Zanoni return IRQ_NONE; 278022e26af7SPaulo Zanoni 278122e26af7SPaulo Zanoni master_tile_ctl = dg1_master_intr_disable(regs); 278222e26af7SPaulo Zanoni if (!master_tile_ctl) { 278322e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 278422e26af7SPaulo Zanoni return IRQ_NONE; 278522e26af7SPaulo Zanoni } 278622e26af7SPaulo Zanoni 278722e26af7SPaulo Zanoni /* FIXME: we only support tile 0 for now. */ 278822e26af7SPaulo Zanoni if (master_tile_ctl & DG1_MSTR_TILE(0)) { 278922e26af7SPaulo Zanoni master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 279022e26af7SPaulo Zanoni raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl); 279122e26af7SPaulo Zanoni } else { 279222e26af7SPaulo Zanoni DRM_ERROR("Tile not supported: 0x%08x\n", master_tile_ctl); 279322e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 279422e26af7SPaulo Zanoni return IRQ_NONE; 279522e26af7SPaulo Zanoni } 279622e26af7SPaulo Zanoni 279722e26af7SPaulo Zanoni gen11_gt_irq_handler(gt, master_ctl); 279822e26af7SPaulo Zanoni 279922e26af7SPaulo Zanoni if (master_ctl & GEN11_DISPLAY_IRQ) 280022e26af7SPaulo Zanoni gen11_display_irq_handler(i915); 280122e26af7SPaulo Zanoni 280222e26af7SPaulo Zanoni gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl); 280322e26af7SPaulo Zanoni 280422e26af7SPaulo Zanoni dg1_master_intr_enable(regs); 280522e26af7SPaulo Zanoni 280622e26af7SPaulo Zanoni gen11_gu_misc_irq_handler(gt, gu_misc_iir); 280722e26af7SPaulo Zanoni 280822e26af7SPaulo Zanoni pmu_irq_stats(i915, IRQ_HANDLED); 280922e26af7SPaulo Zanoni 281022e26af7SPaulo Zanoni return IRQ_HANDLED; 281197b492f5SLucas De Marchi } 281297b492f5SLucas De Marchi 281342f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 281442f52ef8SKeith Packard * we use as a pipe index 281542f52ef8SKeith Packard */ 281608fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc) 28170a3e67a4SJesse Barnes { 281808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 281908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2820e9d21d7fSKeith Packard unsigned long irqflags; 282171e0ffa5SJesse Barnes 28221ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 282386e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 282486e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 282586e83e35SChris Wilson 282686e83e35SChris Wilson return 0; 282786e83e35SChris Wilson } 282886e83e35SChris Wilson 28297d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc) 2830d938da6bSVille Syrjälä { 283108fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2832d938da6bSVille Syrjälä 28337d423af9SVille Syrjälä /* 28347d423af9SVille Syrjälä * Vblank interrupts fail to wake the device up from C2+. 28357d423af9SVille Syrjälä * Disabling render clock gating during C-states avoids 28367d423af9SVille Syrjälä * the problem. There is a small power cost so we do this 28377d423af9SVille Syrjälä * only when vblank interrupts are actually enabled. 28387d423af9SVille Syrjälä */ 28397d423af9SVille Syrjälä if (dev_priv->vblank_enabled++ == 0) 28402939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2841d938da6bSVille Syrjälä 284208fa8fd0SVille Syrjälä return i8xx_enable_vblank(crtc); 2843d938da6bSVille Syrjälä } 2844d938da6bSVille Syrjälä 284508fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc) 284686e83e35SChris Wilson { 284708fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 284808fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 284986e83e35SChris Wilson unsigned long irqflags; 285086e83e35SChris Wilson 285186e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 28527c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 2853755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 28541ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 28558692d00eSChris Wilson 28560a3e67a4SJesse Barnes return 0; 28570a3e67a4SJesse Barnes } 28580a3e67a4SJesse Barnes 285908fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc) 2860f796cf8fSJesse Barnes { 286108fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 286208fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2863f796cf8fSJesse Barnes unsigned long irqflags; 2864373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 286586e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2866f796cf8fSJesse Barnes 2867f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2868fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 2869b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2870b1f14ad0SJesse Barnes 28712e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 28722e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 28732e8bf223SDhinakaran Pandiyan */ 28742e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 287508fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 28762e8bf223SDhinakaran Pandiyan 2877b1f14ad0SJesse Barnes return 0; 2878b1f14ad0SJesse Barnes } 2879b1f14ad0SJesse Barnes 28809c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, 28819c9e97c4SVandita Kulkarni bool enable) 28829c9e97c4SVandita Kulkarni { 28839c9e97c4SVandita Kulkarni struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); 28849c9e97c4SVandita Kulkarni enum port port; 28859c9e97c4SVandita Kulkarni u32 tmp; 28869c9e97c4SVandita Kulkarni 28879c9e97c4SVandita Kulkarni if (!(intel_crtc->mode_flags & 28889c9e97c4SVandita Kulkarni (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0))) 28899c9e97c4SVandita Kulkarni return false; 28909c9e97c4SVandita Kulkarni 28919c9e97c4SVandita Kulkarni /* for dual link cases we consider TE from slave */ 28929c9e97c4SVandita Kulkarni if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1) 28939c9e97c4SVandita Kulkarni port = PORT_B; 28949c9e97c4SVandita Kulkarni else 28959c9e97c4SVandita Kulkarni port = PORT_A; 28969c9e97c4SVandita Kulkarni 28972939eb06SJani Nikula tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_MASK_REG(port)); 28989c9e97c4SVandita Kulkarni if (enable) 28999c9e97c4SVandita Kulkarni tmp &= ~DSI_TE_EVENT; 29009c9e97c4SVandita Kulkarni else 29019c9e97c4SVandita Kulkarni tmp |= DSI_TE_EVENT; 29029c9e97c4SVandita Kulkarni 29032939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DSI_INTR_MASK_REG(port), tmp); 29049c9e97c4SVandita Kulkarni 29052939eb06SJani Nikula tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port)); 29062939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp); 29079c9e97c4SVandita Kulkarni 29089c9e97c4SVandita Kulkarni return true; 29099c9e97c4SVandita Kulkarni } 29109c9e97c4SVandita Kulkarni 2911f15f01a7SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *_crtc) 2912abd58f01SBen Widawsky { 2913f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 2914f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2915f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 2916abd58f01SBen Widawsky unsigned long irqflags; 2917abd58f01SBen Widawsky 2918f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, true)) 29199c9e97c4SVandita Kulkarni return 0; 29209c9e97c4SVandita Kulkarni 2921abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2922013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2923abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2924013d3752SVille Syrjälä 29252e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 29262e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 29272e8bf223SDhinakaran Pandiyan */ 29282e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 2929f15f01a7SVille Syrjälä drm_crtc_vblank_restore(&crtc->base); 29302e8bf223SDhinakaran Pandiyan 2931abd58f01SBen Widawsky return 0; 2932abd58f01SBen Widawsky } 2933abd58f01SBen Widawsky 293442f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 293542f52ef8SKeith Packard * we use as a pipe index 293642f52ef8SKeith Packard */ 293708fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc) 293886e83e35SChris Wilson { 293908fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 294008fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 294186e83e35SChris Wilson unsigned long irqflags; 294286e83e35SChris Wilson 294386e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 294486e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 294586e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 294686e83e35SChris Wilson } 294786e83e35SChris Wilson 29487d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc) 2949d938da6bSVille Syrjälä { 295008fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2951d938da6bSVille Syrjälä 295208fa8fd0SVille Syrjälä i8xx_disable_vblank(crtc); 2953d938da6bSVille Syrjälä 29547d423af9SVille Syrjälä if (--dev_priv->vblank_enabled == 0) 29552939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2956d938da6bSVille Syrjälä } 2957d938da6bSVille Syrjälä 295808fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc) 29590a3e67a4SJesse Barnes { 296008fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 296108fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2962e9d21d7fSKeith Packard unsigned long irqflags; 29630a3e67a4SJesse Barnes 29641ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 29657c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 2966755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 29671ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 29680a3e67a4SJesse Barnes } 29690a3e67a4SJesse Barnes 297008fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc) 2971f796cf8fSJesse Barnes { 297208fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 297308fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2974f796cf8fSJesse Barnes unsigned long irqflags; 2975373abf1aSMatt Roper u32 bit = DISPLAY_VER(dev_priv) >= 7 ? 297686e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2977f796cf8fSJesse Barnes 2978f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2979fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 2980b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2981b1f14ad0SJesse Barnes } 2982b1f14ad0SJesse Barnes 2983f15f01a7SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *_crtc) 2984abd58f01SBen Widawsky { 2985f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(_crtc); 2986f15f01a7SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2987f15f01a7SVille Syrjälä enum pipe pipe = crtc->pipe; 2988abd58f01SBen Widawsky unsigned long irqflags; 2989abd58f01SBen Widawsky 2990f15f01a7SVille Syrjälä if (gen11_dsi_configure_te(crtc, false)) 29919c9e97c4SVandita Kulkarni return; 29929c9e97c4SVandita Kulkarni 2993abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2994013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2995abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2996abd58f01SBen Widawsky } 2997abd58f01SBen Widawsky 2998b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 299991738a95SPaulo Zanoni { 3000b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3001b16b2a2fSPaulo Zanoni 30026e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 300391738a95SPaulo Zanoni return; 300491738a95SPaulo Zanoni 3005b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 3006105b122eSPaulo Zanoni 30076e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 30082939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff); 3009622364b6SPaulo Zanoni } 3010105b122eSPaulo Zanoni 301170591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 301270591a41SVille Syrjälä { 3013b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3014b16b2a2fSPaulo Zanoni 301571b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 3016f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 301771b8b41dSVille Syrjälä else 30187d938bc0SVille Syrjälä intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); 301971b8b41dSVille Syrjälä 3020ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 30212939eb06SJani Nikula intel_uncore_write(uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 302270591a41SVille Syrjälä 302344d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 302470591a41SVille Syrjälä 3025b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, VLV_); 30268bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 302770591a41SVille Syrjälä } 302870591a41SVille Syrjälä 30298bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 30308bb61306SVille Syrjälä { 3031b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3032b16b2a2fSPaulo Zanoni 30338bb61306SVille Syrjälä u32 pipestat_mask; 30349ab981f2SVille Syrjälä u32 enable_mask; 30358bb61306SVille Syrjälä enum pipe pipe; 30368bb61306SVille Syrjälä 3037842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 30388bb61306SVille Syrjälä 30398bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 30408bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 30418bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 30428bb61306SVille Syrjälä 30439ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 30448bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3045ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 3046ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 3047ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 3048ebf5f921SVille Syrjälä 30498bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 3050ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 3051ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 30526b7eafc1SVille Syrjälä 305348a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u); 30546b7eafc1SVille Syrjälä 30559ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 30568bb61306SVille Syrjälä 3057b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask); 30588bb61306SVille Syrjälä } 30598bb61306SVille Syrjälä 30608bb61306SVille Syrjälä /* drm_dma.h hooks 30618bb61306SVille Syrjälä */ 30629eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv) 30638bb61306SVille Syrjälä { 3064b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 30658bb61306SVille Syrjälä 3066b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, DE); 3067e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3068e44adb5dSChris Wilson 3069651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) == 7) 3070f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); 30718bb61306SVille Syrjälä 3072fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3073f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 3074f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 3075fc340442SDaniel Vetter } 3076fc340442SDaniel Vetter 30772cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 30788bb61306SVille Syrjälä 3079b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 30808bb61306SVille Syrjälä } 30818bb61306SVille Syrjälä 3082b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv) 30837e231dbeSJesse Barnes { 30842939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 30852939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 308634c7b8a7SVille Syrjälä 30872cbc876dSMichał Winiarski gen5_gt_irq_reset(to_gt(dev_priv)); 30887e231dbeSJesse Barnes 3089ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 30909918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 309170591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3092ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 30937e231dbeSJesse Barnes } 30947e231dbeSJesse Barnes 3095a844cfbeSJosé Roberto de Souza static void gen8_display_irq_reset(struct drm_i915_private *dev_priv) 3096abd58f01SBen Widawsky { 3097b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3098d048a268SVille Syrjälä enum pipe pipe; 3099abd58f01SBen Widawsky 3100a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3101a844cfbeSJosé Roberto de Souza return; 3102abd58f01SBen Widawsky 3103f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 3104f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 3105e04f7eceSVille Syrjälä 3106055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 3107f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3108813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3109b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 3110abd58f01SBen Widawsky 3111b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 3112b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 3113a844cfbeSJosé Roberto de Souza } 3114a844cfbeSJosé Roberto de Souza 3115a844cfbeSJosé Roberto de Souza static void gen8_irq_reset(struct drm_i915_private *dev_priv) 3116a844cfbeSJosé Roberto de Souza { 3117a844cfbeSJosé Roberto de Souza struct intel_uncore *uncore = &dev_priv->uncore; 3118a844cfbeSJosé Roberto de Souza 3119a844cfbeSJosé Roberto de Souza gen8_master_intr_disable(dev_priv->uncore.regs); 3120a844cfbeSJosé Roberto de Souza 31212cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 3122a844cfbeSJosé Roberto de Souza gen8_display_irq_reset(dev_priv); 3123b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 3124abd58f01SBen Widawsky 31256e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 3126b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 312759b7cb44STejas Upadhyay 3128abd58f01SBen Widawsky } 3129abd58f01SBen Widawsky 3130a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) 313151951ae7SMika Kuoppala { 3132b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3133d048a268SVille Syrjälä enum pipe pipe; 3134562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 3135562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 313651951ae7SMika Kuoppala 3137a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3138a844cfbeSJosé Roberto de Souza return; 3139a844cfbeSJosé Roberto de Souza 3140f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); 314151951ae7SMika Kuoppala 3142373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 31438241cfbeSJosé Roberto de Souza enum transcoder trans; 31448241cfbeSJosé Roberto de Souza 3145562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 31468241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 31478241cfbeSJosé Roberto de Souza 31488241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 31498241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 31508241cfbeSJosé Roberto de Souza continue; 31518241cfbeSJosé Roberto de Souza 31528241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff); 31538241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff); 31548241cfbeSJosé Roberto de Souza } 31558241cfbeSJosé Roberto de Souza } else { 3156f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 3157f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 31588241cfbeSJosé Roberto de Souza } 315962819dfdSJosé Roberto de Souza 316051951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 316151951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 316251951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 3163b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 316451951ae7SMika Kuoppala 3165b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 3166b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 3167b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); 316831604222SAnusha Srivatsa 316929b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 3170b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 317151951ae7SMika Kuoppala } 317251951ae7SMika Kuoppala 3173a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv) 3174a3265d85SMatt Roper { 31752cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3176fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 3177a3265d85SMatt Roper 3178a3265d85SMatt Roper gen11_master_intr_disable(dev_priv->uncore.regs); 3179a3265d85SMatt Roper 3180fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 3181a3265d85SMatt Roper gen11_display_irq_reset(dev_priv); 3182a3265d85SMatt Roper 3183a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 3184a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN8_PCU_); 3185a3265d85SMatt Roper } 3186a3265d85SMatt Roper 318722e26af7SPaulo Zanoni static void dg1_irq_reset(struct drm_i915_private *dev_priv) 318822e26af7SPaulo Zanoni { 31892cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3190fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 319122e26af7SPaulo Zanoni 319222e26af7SPaulo Zanoni dg1_master_intr_disable(dev_priv->uncore.regs); 319322e26af7SPaulo Zanoni 3194fd4d7904SPaulo Zanoni gen11_gt_irq_reset(gt); 319522e26af7SPaulo Zanoni gen11_display_irq_reset(dev_priv); 319622e26af7SPaulo Zanoni 319722e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 319822e26af7SPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 319922e26af7SPaulo Zanoni } 320022e26af7SPaulo Zanoni 32014c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 3202001bd2cbSImre Deak u8 pipe_mask) 3203d49bdb0eSPaulo Zanoni { 3204b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 32058bcc0840SMatt Roper u32 extra_ier = GEN8_PIPE_VBLANK | 32068bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 3207cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 32086831f3e3SVille Syrjälä enum pipe pipe; 3209d49bdb0eSPaulo Zanoni 321013321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 32119dfe2e3aSImre Deak 32129dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 32139dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 32149dfe2e3aSImre Deak return; 32159dfe2e3aSImre Deak } 32169dfe2e3aSImre Deak 32176831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 3218b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 32196831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 32206831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 32219dfe2e3aSImre Deak 322213321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3223d49bdb0eSPaulo Zanoni } 3224d49bdb0eSPaulo Zanoni 3225aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 3226001bd2cbSImre Deak u8 pipe_mask) 3227aae8ba84SVille Syrjälä { 3228b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 32296831f3e3SVille Syrjälä enum pipe pipe; 32306831f3e3SVille Syrjälä 3231aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 32329dfe2e3aSImre Deak 32339dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 32349dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 32359dfe2e3aSImre Deak return; 32369dfe2e3aSImre Deak } 32379dfe2e3aSImre Deak 32386831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 3239b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 32409dfe2e3aSImre Deak 3241aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3242aae8ba84SVille Syrjälä 3243aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 3244315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 3245aae8ba84SVille Syrjälä } 3246aae8ba84SVille Syrjälä 3247b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv) 324843f328d7SVille Syrjälä { 3249b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 325043f328d7SVille Syrjälä 32512939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); 32522939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 325343f328d7SVille Syrjälä 32542cbc876dSMichał Winiarski gen8_gt_irq_reset(to_gt(dev_priv)); 325543f328d7SVille Syrjälä 3256b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 325743f328d7SVille Syrjälä 3258ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 32599918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 326070591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3261ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 326243f328d7SVille Syrjälä } 326343f328d7SVille Syrjälä 32642ea63927SVille Syrjälä static u32 ibx_hotplug_enables(struct drm_i915_private *i915, 32652ea63927SVille Syrjälä enum hpd_pin pin) 32662ea63927SVille Syrjälä { 32672ea63927SVille Syrjälä switch (pin) { 32682ea63927SVille Syrjälä case HPD_PORT_A: 32692ea63927SVille Syrjälä /* 32702ea63927SVille Syrjälä * When CPU and PCH are on the same package, port A 32712ea63927SVille Syrjälä * HPD must be enabled in both north and south. 32722ea63927SVille Syrjälä */ 32732ea63927SVille Syrjälä return HAS_PCH_LPT_LP(i915) ? 32742ea63927SVille Syrjälä PORTA_HOTPLUG_ENABLE : 0; 32752ea63927SVille Syrjälä case HPD_PORT_B: 32762ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE | 32772ea63927SVille Syrjälä PORTB_PULSE_DURATION_2ms; 32782ea63927SVille Syrjälä case HPD_PORT_C: 32792ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE | 32802ea63927SVille Syrjälä PORTC_PULSE_DURATION_2ms; 32812ea63927SVille Syrjälä case HPD_PORT_D: 32822ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE | 32832ea63927SVille Syrjälä PORTD_PULSE_DURATION_2ms; 32842ea63927SVille Syrjälä default: 32852ea63927SVille Syrjälä return 0; 32862ea63927SVille Syrjälä } 32872ea63927SVille Syrjälä } 32882ea63927SVille Syrjälä 32891a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) 32901a56b1a2SImre Deak { 32911a56b1a2SImre Deak u32 hotplug; 32921a56b1a2SImre Deak 32931a56b1a2SImre Deak /* 32941a56b1a2SImre Deak * Enable digital hotplug on the PCH, and configure the DP short pulse 32951a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec). 32961a56b1a2SImre Deak * The pulse duration bits are reserved on LPT+. 32971a56b1a2SImre Deak */ 32982939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 32992ea63927SVille Syrjälä hotplug &= ~(PORTA_HOTPLUG_ENABLE | 33002ea63927SVille Syrjälä PORTB_HOTPLUG_ENABLE | 33012ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 33022ea63927SVille Syrjälä PORTD_HOTPLUG_ENABLE | 33032ea63927SVille Syrjälä PORTB_PULSE_DURATION_MASK | 33041a56b1a2SImre Deak PORTC_PULSE_DURATION_MASK | 33051a56b1a2SImre Deak PORTD_PULSE_DURATION_MASK); 33062ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables); 33072939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); 33081a56b1a2SImre Deak } 33091a56b1a2SImre Deak 331091d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) 331182a28bcfSDaniel Vetter { 33121a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 331382a28bcfSDaniel Vetter 33140398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 33156d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 331682a28bcfSDaniel Vetter 3317fee884edSDaniel Vetter ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 331882a28bcfSDaniel Vetter 33191a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 33206dbf30ceSVille Syrjälä } 332126951cafSXiong Zhang 33222ea63927SVille Syrjälä static u32 icp_ddi_hotplug_enables(struct drm_i915_private *i915, 33232ea63927SVille Syrjälä enum hpd_pin pin) 33242ea63927SVille Syrjälä { 33252ea63927SVille Syrjälä switch (pin) { 33262ea63927SVille Syrjälä case HPD_PORT_A: 33272ea63927SVille Syrjälä case HPD_PORT_B: 33282ea63927SVille Syrjälä case HPD_PORT_C: 33292ea63927SVille Syrjälä case HPD_PORT_D: 33302ea63927SVille Syrjälä return SHOTPLUG_CTL_DDI_HPD_ENABLE(pin); 33312ea63927SVille Syrjälä default: 33322ea63927SVille Syrjälä return 0; 33332ea63927SVille Syrjälä } 33342ea63927SVille Syrjälä } 33352ea63927SVille Syrjälä 33362ea63927SVille Syrjälä static u32 icp_tc_hotplug_enables(struct drm_i915_private *i915, 33372ea63927SVille Syrjälä enum hpd_pin pin) 33382ea63927SVille Syrjälä { 33392ea63927SVille Syrjälä switch (pin) { 33402ea63927SVille Syrjälä case HPD_PORT_TC1: 33412ea63927SVille Syrjälä case HPD_PORT_TC2: 33422ea63927SVille Syrjälä case HPD_PORT_TC3: 33432ea63927SVille Syrjälä case HPD_PORT_TC4: 33442ea63927SVille Syrjälä case HPD_PORT_TC5: 33452ea63927SVille Syrjälä case HPD_PORT_TC6: 33462ea63927SVille Syrjälä return ICP_TC_HPD_ENABLE(pin); 33472ea63927SVille Syrjälä default: 33482ea63927SVille Syrjälä return 0; 33492ea63927SVille Syrjälä } 33502ea63927SVille Syrjälä } 33512ea63927SVille Syrjälä 33522ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv) 335331604222SAnusha Srivatsa { 335431604222SAnusha Srivatsa u32 hotplug; 335531604222SAnusha Srivatsa 33562939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI); 33572ea63927SVille Syrjälä hotplug &= ~(SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) | 33582ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | 33592ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | 33602ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D)); 33612ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables); 33622939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, hotplug); 336331604222SAnusha Srivatsa } 3364815f4ef2SVille Syrjälä 33652ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 3366815f4ef2SVille Syrjälä { 3367815f4ef2SVille Syrjälä u32 hotplug; 3368815f4ef2SVille Syrjälä 33692939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC); 33702ea63927SVille Syrjälä hotplug &= ~(ICP_TC_HPD_ENABLE(HPD_PORT_TC1) | 33712ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | 33722ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | 33732ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | 33742ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | 33752ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC6)); 33762ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables); 33772939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, hotplug); 33788ef7e340SMatt Roper } 337931604222SAnusha Srivatsa 33802ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) 338131604222SAnusha Srivatsa { 338231604222SAnusha Srivatsa u32 hotplug_irqs, enabled_irqs; 338331604222SAnusha Srivatsa 33840398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 33856d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 338631604222SAnusha Srivatsa 3387f619e516SAnusha Srivatsa if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) 33882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 3389f49108d0SMatt Roper 339031604222SAnusha Srivatsa ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 339131604222SAnusha Srivatsa 33922ea63927SVille Syrjälä icp_ddi_hpd_detection_setup(dev_priv); 33932ea63927SVille Syrjälä icp_tc_hpd_detection_setup(dev_priv); 339452dfdba0SLucas De Marchi } 339552dfdba0SLucas De Marchi 33962ea63927SVille Syrjälä static u32 gen11_hotplug_enables(struct drm_i915_private *i915, 33972ea63927SVille Syrjälä enum hpd_pin pin) 33988ef7e340SMatt Roper { 33992ea63927SVille Syrjälä switch (pin) { 34002ea63927SVille Syrjälä case HPD_PORT_TC1: 34012ea63927SVille Syrjälä case HPD_PORT_TC2: 34022ea63927SVille Syrjälä case HPD_PORT_TC3: 34032ea63927SVille Syrjälä case HPD_PORT_TC4: 34042ea63927SVille Syrjälä case HPD_PORT_TC5: 34052ea63927SVille Syrjälä case HPD_PORT_TC6: 34062ea63927SVille Syrjälä return GEN11_HOTPLUG_CTL_ENABLE(pin); 34072ea63927SVille Syrjälä default: 34082ea63927SVille Syrjälä return 0; 340931604222SAnusha Srivatsa } 3410943682e3SMatt Roper } 3411943682e3SMatt Roper 3412229f31e2SLucas De Marchi static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) 3413229f31e2SLucas De Marchi { 3414b18c1eb9SClinton A Taylor u32 val; 3415b18c1eb9SClinton A Taylor 34162939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1); 3417b18c1eb9SClinton A Taylor val |= (INVERT_DDIA_HPD | 3418b18c1eb9SClinton A Taylor INVERT_DDIB_HPD | 3419b18c1eb9SClinton A Taylor INVERT_DDIC_HPD | 3420b18c1eb9SClinton A Taylor INVERT_DDID_HPD); 34212939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val); 3422b18c1eb9SClinton A Taylor 34232ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 3424229f31e2SLucas De Marchi } 3425229f31e2SLucas De Marchi 342652c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 3427121e758eSDhinakaran Pandiyan { 3428121e758eSDhinakaran Pandiyan u32 hotplug; 3429121e758eSDhinakaran Pandiyan 34302939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL); 34312ea63927SVille Syrjälä hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 34325b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 34335b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 34345b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 34355b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 34362ea63927SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); 34372ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); 34382939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, hotplug); 343952c7f5f1SVille Syrjälä } 344052c7f5f1SVille Syrjälä 344152c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv) 344252c7f5f1SVille Syrjälä { 344352c7f5f1SVille Syrjälä u32 hotplug; 3444b796b971SDhinakaran Pandiyan 34452939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL); 34462ea63927SVille Syrjälä hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 34475b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 34485b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 34495b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 34505b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 34512ea63927SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); 34522ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); 34532939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, hotplug); 3454121e758eSDhinakaran Pandiyan } 3455121e758eSDhinakaran Pandiyan 3456121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) 3457121e758eSDhinakaran Pandiyan { 3458121e758eSDhinakaran Pandiyan u32 hotplug_irqs, enabled_irqs; 3459121e758eSDhinakaran Pandiyan u32 val; 3460121e758eSDhinakaran Pandiyan 34610398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); 34626d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); 3463121e758eSDhinakaran Pandiyan 34642939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); 3465121e758eSDhinakaran Pandiyan val &= ~hotplug_irqs; 3466587a87b9SImre Deak val |= ~enabled_irqs & hotplug_irqs; 34672939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IMR, val); 34682939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); 3469121e758eSDhinakaran Pandiyan 347052c7f5f1SVille Syrjälä gen11_tc_hpd_detection_setup(dev_priv); 347152c7f5f1SVille Syrjälä gen11_tbt_hpd_detection_setup(dev_priv); 347231604222SAnusha Srivatsa 34732ea63927SVille Syrjälä if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 34742ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 34752ea63927SVille Syrjälä } 34762ea63927SVille Syrjälä 34772ea63927SVille Syrjälä static u32 spt_hotplug_enables(struct drm_i915_private *i915, 34782ea63927SVille Syrjälä enum hpd_pin pin) 34792ea63927SVille Syrjälä { 34802ea63927SVille Syrjälä switch (pin) { 34812ea63927SVille Syrjälä case HPD_PORT_A: 34822ea63927SVille Syrjälä return PORTA_HOTPLUG_ENABLE; 34832ea63927SVille Syrjälä case HPD_PORT_B: 34842ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE; 34852ea63927SVille Syrjälä case HPD_PORT_C: 34862ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE; 34872ea63927SVille Syrjälä case HPD_PORT_D: 34882ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE; 34892ea63927SVille Syrjälä default: 34902ea63927SVille Syrjälä return 0; 34912ea63927SVille Syrjälä } 34922ea63927SVille Syrjälä } 34932ea63927SVille Syrjälä 34942ea63927SVille Syrjälä static u32 spt_hotplug2_enables(struct drm_i915_private *i915, 34952ea63927SVille Syrjälä enum hpd_pin pin) 34962ea63927SVille Syrjälä { 34972ea63927SVille Syrjälä switch (pin) { 34982ea63927SVille Syrjälä case HPD_PORT_E: 34992ea63927SVille Syrjälä return PORTE_HOTPLUG_ENABLE; 35002ea63927SVille Syrjälä default: 35012ea63927SVille Syrjälä return 0; 35022ea63927SVille Syrjälä } 3503121e758eSDhinakaran Pandiyan } 3504121e758eSDhinakaran Pandiyan 35052a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) 35062a57d9ccSImre Deak { 35073b92e263SRodrigo Vivi u32 val, hotplug; 35083b92e263SRodrigo Vivi 35093b92e263SRodrigo Vivi /* Display WA #1179 WaHardHangonHotPlug: cnp */ 35103b92e263SRodrigo Vivi if (HAS_PCH_CNP(dev_priv)) { 35112939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1); 35123b92e263SRodrigo Vivi val &= ~CHASSIS_CLK_REQ_DURATION_MASK; 35133b92e263SRodrigo Vivi val |= CHASSIS_CLK_REQ_DURATION(0xf); 35142939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val); 35153b92e263SRodrigo Vivi } 35162a57d9ccSImre Deak 35172a57d9ccSImre Deak /* Enable digital hotplug on the PCH */ 35182939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 35192ea63927SVille Syrjälä hotplug &= ~(PORTA_HOTPLUG_ENABLE | 35202a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 35212a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE | 35222ea63927SVille Syrjälä PORTD_HOTPLUG_ENABLE); 35232ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables); 35242939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); 35252a57d9ccSImre Deak 35262939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2); 35272ea63927SVille Syrjälä hotplug &= ~PORTE_HOTPLUG_ENABLE; 35282ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables); 35292939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, hotplug); 35302a57d9ccSImre Deak } 35312a57d9ccSImre Deak 353291d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) 35336dbf30ceSVille Syrjälä { 35342a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 35356dbf30ceSVille Syrjälä 3536f49108d0SMatt Roper if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) 35372939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 3538f49108d0SMatt Roper 35390398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 35406d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 35416dbf30ceSVille Syrjälä 35426dbf30ceSVille Syrjälä ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 35436dbf30ceSVille Syrjälä 35442a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 354526951cafSXiong Zhang } 35467fe0b973SKeith Packard 35472ea63927SVille Syrjälä static u32 ilk_hotplug_enables(struct drm_i915_private *i915, 35482ea63927SVille Syrjälä enum hpd_pin pin) 35492ea63927SVille Syrjälä { 35502ea63927SVille Syrjälä switch (pin) { 35512ea63927SVille Syrjälä case HPD_PORT_A: 35522ea63927SVille Syrjälä return DIGITAL_PORTA_HOTPLUG_ENABLE | 35532ea63927SVille Syrjälä DIGITAL_PORTA_PULSE_DURATION_2ms; 35542ea63927SVille Syrjälä default: 35552ea63927SVille Syrjälä return 0; 35562ea63927SVille Syrjälä } 35572ea63927SVille Syrjälä } 35582ea63927SVille Syrjälä 35591a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) 35601a56b1a2SImre Deak { 35611a56b1a2SImre Deak u32 hotplug; 35621a56b1a2SImre Deak 35631a56b1a2SImre Deak /* 35641a56b1a2SImre Deak * Enable digital hotplug on the CPU, and configure the DP short pulse 35651a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec) 35661a56b1a2SImre Deak * The pulse duration bits are reserved on HSW+. 35671a56b1a2SImre Deak */ 35682939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL); 35692ea63927SVille Syrjälä hotplug &= ~(DIGITAL_PORTA_HOTPLUG_ENABLE | 35702ea63927SVille Syrjälä DIGITAL_PORTA_PULSE_DURATION_MASK); 35712ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables); 35722939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); 35731a56b1a2SImre Deak } 35741a56b1a2SImre Deak 357591d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) 3576e4ce95aaSVille Syrjälä { 35771a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 3578e4ce95aaSVille Syrjälä 35790398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); 35806d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); 35813a3b3c7dSVille Syrjälä 3582373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 8) 35833a3b3c7dSVille Syrjälä bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 35846d3144ebSVille Syrjälä else 35853a3b3c7dSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 3586e4ce95aaSVille Syrjälä 35871a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3588e4ce95aaSVille Syrjälä 358991d14251STvrtko Ursulin ibx_hpd_irq_setup(dev_priv); 3590e4ce95aaSVille Syrjälä } 3591e4ce95aaSVille Syrjälä 35922ea63927SVille Syrjälä static u32 bxt_hotplug_enables(struct drm_i915_private *i915, 35932ea63927SVille Syrjälä enum hpd_pin pin) 35942ea63927SVille Syrjälä { 35952ea63927SVille Syrjälä u32 hotplug; 35962ea63927SVille Syrjälä 35972ea63927SVille Syrjälä switch (pin) { 35982ea63927SVille Syrjälä case HPD_PORT_A: 35992ea63927SVille Syrjälä hotplug = PORTA_HOTPLUG_ENABLE; 36002ea63927SVille Syrjälä if (intel_bios_is_port_hpd_inverted(i915, PORT_A)) 36012ea63927SVille Syrjälä hotplug |= BXT_DDIA_HPD_INVERT; 36022ea63927SVille Syrjälä return hotplug; 36032ea63927SVille Syrjälä case HPD_PORT_B: 36042ea63927SVille Syrjälä hotplug = PORTB_HOTPLUG_ENABLE; 36052ea63927SVille Syrjälä if (intel_bios_is_port_hpd_inverted(i915, PORT_B)) 36062ea63927SVille Syrjälä hotplug |= BXT_DDIB_HPD_INVERT; 36072ea63927SVille Syrjälä return hotplug; 36082ea63927SVille Syrjälä case HPD_PORT_C: 36092ea63927SVille Syrjälä hotplug = PORTC_HOTPLUG_ENABLE; 36102ea63927SVille Syrjälä if (intel_bios_is_port_hpd_inverted(i915, PORT_C)) 36112ea63927SVille Syrjälä hotplug |= BXT_DDIC_HPD_INVERT; 36122ea63927SVille Syrjälä return hotplug; 36132ea63927SVille Syrjälä default: 36142ea63927SVille Syrjälä return 0; 36152ea63927SVille Syrjälä } 36162ea63927SVille Syrjälä } 36172ea63927SVille Syrjälä 36182ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) 3619e0a20ad7SShashank Sharma { 36202a57d9ccSImre Deak u32 hotplug; 3621e0a20ad7SShashank Sharma 36222939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 36232ea63927SVille Syrjälä hotplug &= ~(PORTA_HOTPLUG_ENABLE | 36242a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 36252ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 36262ea63927SVille Syrjälä BXT_DDIA_HPD_INVERT | 36272ea63927SVille Syrjälä BXT_DDIB_HPD_INVERT | 36282ea63927SVille Syrjälä BXT_DDIC_HPD_INVERT); 36292ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables); 36302939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); 3631e0a20ad7SShashank Sharma } 3632e0a20ad7SShashank Sharma 36332a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) 36342a57d9ccSImre Deak { 36352a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 36362a57d9ccSImre Deak 36370398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); 36386d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); 36392a57d9ccSImre Deak 36402a57d9ccSImre Deak bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 36412a57d9ccSImre Deak 36422ea63927SVille Syrjälä bxt_hpd_detection_setup(dev_priv); 36432a57d9ccSImre Deak } 36442a57d9ccSImre Deak 3645a0a6d8cbSVille Syrjälä /* 3646a0a6d8cbSVille Syrjälä * SDEIER is also touched by the interrupt handler to work around missed PCH 3647a0a6d8cbSVille Syrjälä * interrupts. Hence we can't update it after the interrupt handler is enabled - 3648a0a6d8cbSVille Syrjälä * instead we unconditionally enable all PCH interrupt sources here, but then 3649a0a6d8cbSVille Syrjälä * only unmask them as needed with SDEIMR. 3650a0a6d8cbSVille Syrjälä * 3651a0a6d8cbSVille Syrjälä * Note that we currently do this after installing the interrupt handler, 3652a0a6d8cbSVille Syrjälä * but before we enable the master interrupt. That should be sufficient 3653a0a6d8cbSVille Syrjälä * to avoid races with the irq handler, assuming we have MSI. Shared legacy 3654a0a6d8cbSVille Syrjälä * interrupts could still race. 3655a0a6d8cbSVille Syrjälä */ 3656b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) 3657d46da437SPaulo Zanoni { 3658a0a6d8cbSVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 365982a28bcfSDaniel Vetter u32 mask; 3660d46da437SPaulo Zanoni 36616e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3662692a04cfSDaniel Vetter return; 3663692a04cfSDaniel Vetter 36646e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 36655c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 36664ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 36675c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 36684ebc6509SDhinakaran Pandiyan else 36694ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 36708664281bSPaulo Zanoni 3671a0a6d8cbSVille Syrjälä GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 3672d46da437SPaulo Zanoni } 3673d46da437SPaulo Zanoni 36749eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) 3675036a4a7dSZhenyu Wang { 3676b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 36778e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 36788e76f8dcSPaulo Zanoni 3679651e7d48SLucas De Marchi if (GRAPHICS_VER(dev_priv) >= 7) { 36808e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 3681842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 36828e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 368323bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 36842a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_C) | 36852a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_B) | 36862a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_A) | 368723bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 36888e76f8dcSPaulo Zanoni } else { 36898e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 3690842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 3691842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 3692c6073d4cSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | 3693e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 36944bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_A) | 36954bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_B) | 3696e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 36978e76f8dcSPaulo Zanoni } 3698036a4a7dSZhenyu Wang 3699fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3700b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 3701fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 3702fc340442SDaniel Vetter } 3703fc340442SDaniel Vetter 3704c6073d4cSVille Syrjälä if (IS_IRONLAKE_M(dev_priv)) 3705c6073d4cSVille Syrjälä extra_mask |= DE_PCU_EVENT; 3706c6073d4cSVille Syrjälä 37071ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 3708036a4a7dSZhenyu Wang 3709a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3710622364b6SPaulo Zanoni 37112cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 3712a9922912SVille Syrjälä 3713b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, 3714b16b2a2fSPaulo Zanoni display_mask | extra_mask); 3715036a4a7dSZhenyu Wang } 3716036a4a7dSZhenyu Wang 3717f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 3718f8b79e58SImre Deak { 371967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3720f8b79e58SImre Deak 3721f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 3722f8b79e58SImre Deak return; 3723f8b79e58SImre Deak 3724f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 3725f8b79e58SImre Deak 3726d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 3727d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 3728ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3729f8b79e58SImre Deak } 3730d6c69803SVille Syrjälä } 3731f8b79e58SImre Deak 3732f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 3733f8b79e58SImre Deak { 373467520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3735f8b79e58SImre Deak 3736f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 3737f8b79e58SImre Deak return; 3738f8b79e58SImre Deak 3739f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 3740f8b79e58SImre Deak 3741950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 3742ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 3743f8b79e58SImre Deak } 3744f8b79e58SImre Deak 37450e6c9a9eSVille Syrjälä 3746b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) 37470e6c9a9eSVille Syrjälä { 37482cbc876dSMichał Winiarski gen5_gt_irq_postinstall(to_gt(dev_priv)); 37497e231dbeSJesse Barnes 3750ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 37519918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3752ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3753ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3754ad22d106SVille Syrjälä 37552939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 37562939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 375720afbda2SDaniel Vetter } 375820afbda2SDaniel Vetter 3759abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 3760abd58f01SBen Widawsky { 3761b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3762b16b2a2fSPaulo Zanoni 3763869129eeSMatt Roper u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) | 3764869129eeSMatt Roper GEN8_PIPE_CDCLK_CRC_DONE; 3765a9c287c9SJani Nikula u32 de_pipe_enables; 3766054318c7SImre Deak u32 de_port_masked = gen8_de_port_aux_mask(dev_priv); 37673a3b3c7dSVille Syrjälä u32 de_port_enables; 3768df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 3769562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 3770562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 37713a3b3c7dSVille Syrjälä enum pipe pipe; 3772770de83dSDamien Lespiau 3773a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3774a844cfbeSJosé Roberto de Souza return; 3775a844cfbeSJosé Roberto de Souza 3776373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) <= 10) 3777df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 3778df0d28c1SDhinakaran Pandiyan 377970bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 37803a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 3781a324fcacSRodrigo Vivi 3782373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 37839c9e97c4SVandita Kulkarni enum port port; 37849c9e97c4SVandita Kulkarni 37859c9e97c4SVandita Kulkarni if (intel_bios_is_dsi_present(dev_priv, &port)) 37869c9e97c4SVandita Kulkarni de_port_masked |= DSI0_TE | DSI1_TE; 37879c9e97c4SVandita Kulkarni } 37889c9e97c4SVandita Kulkarni 3789cda195f1SVille Syrjälä de_pipe_enables = de_pipe_masked | 37908bcc0840SMatt Roper GEN8_PIPE_VBLANK | 37918bcc0840SMatt Roper gen8_de_pipe_underrun_mask(dev_priv) | 3792cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 37931288f9b0SKarthik B S 37943a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 379570bfb307SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 3796a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 3797a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 3798e5abaab3SVille Syrjälä de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK; 37993a3b3c7dSVille Syrjälä 3800373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 38018241cfbeSJosé Roberto de Souza enum transcoder trans; 38028241cfbeSJosé Roberto de Souza 3803562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 38048241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 38058241cfbeSJosé Roberto de Souza 38068241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 38078241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 38088241cfbeSJosé Roberto de Souza continue; 38098241cfbeSJosé Roberto de Souza 38108241cfbeSJosé Roberto de Souza gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans)); 38118241cfbeSJosé Roberto de Souza } 38128241cfbeSJosé Roberto de Souza } else { 3813b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 38148241cfbeSJosé Roberto de Souza } 3815e04f7eceSVille Syrjälä 38160a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 38170a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 3818abd58f01SBen Widawsky 3819f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3820813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3821b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 3822813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 382335079899SPaulo Zanoni de_pipe_enables); 38240a195c02SMika Kahola } 3825abd58f01SBen Widawsky 3826b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 3827b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 38282a57d9ccSImre Deak 3829373abf1aSMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 3830121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 3831b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 3832b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 3833121e758eSDhinakaran Pandiyan 3834b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, 3835b16b2a2fSPaulo Zanoni de_hpd_enables); 3836abd58f01SBen Widawsky } 3837121e758eSDhinakaran Pandiyan } 3838abd58f01SBen Widawsky 383959b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv) 384059b7cb44STejas Upadhyay { 384159b7cb44STejas Upadhyay struct intel_uncore *uncore = &dev_priv->uncore; 384259b7cb44STejas Upadhyay u32 mask = SDE_GMBUS_ICP; 384359b7cb44STejas Upadhyay 384459b7cb44STejas Upadhyay GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 384559b7cb44STejas Upadhyay } 384659b7cb44STejas Upadhyay 3847b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) 3848abd58f01SBen Widawsky { 384959b7cb44STejas Upadhyay if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 385059b7cb44STejas Upadhyay icp_irq_postinstall(dev_priv); 385159b7cb44STejas Upadhyay else if (HAS_PCH_SPLIT(dev_priv)) 3852a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3853622364b6SPaulo Zanoni 38542cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 3855abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 3856abd58f01SBen Widawsky 385725286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 3858abd58f01SBen Widawsky } 3859abd58f01SBen Widawsky 3860a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) 3861a844cfbeSJosé Roberto de Souza { 3862a844cfbeSJosé Roberto de Souza if (!HAS_DISPLAY(dev_priv)) 3863a844cfbeSJosé Roberto de Souza return; 3864a844cfbeSJosé Roberto de Souza 3865a844cfbeSJosé Roberto de Souza gen8_de_irq_postinstall(dev_priv); 3866a844cfbeSJosé Roberto de Souza 3867a844cfbeSJosé Roberto de Souza intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 3868a844cfbeSJosé Roberto de Souza GEN11_DISPLAY_IRQ_ENABLE); 3869a844cfbeSJosé Roberto de Souza } 387031604222SAnusha Srivatsa 3871b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) 387251951ae7SMika Kuoppala { 38732cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3874fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 3875df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 387651951ae7SMika Kuoppala 387729b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 3878b318b824SVille Syrjälä icp_irq_postinstall(dev_priv); 387931604222SAnusha Srivatsa 3880fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 3881a844cfbeSJosé Roberto de Souza gen11_de_irq_postinstall(dev_priv); 388251951ae7SMika Kuoppala 3883b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 3884df0d28c1SDhinakaran Pandiyan 38859b77011eSTvrtko Ursulin gen11_master_intr_enable(uncore->regs); 38862939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ); 388751951ae7SMika Kuoppala } 388822e26af7SPaulo Zanoni 388922e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) 389022e26af7SPaulo Zanoni { 38912cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 3892fd4d7904SPaulo Zanoni struct intel_uncore *uncore = gt->uncore; 389322e26af7SPaulo Zanoni u32 gu_misc_masked = GEN11_GU_MISC_GSE; 389422e26af7SPaulo Zanoni 3895fd4d7904SPaulo Zanoni gen11_gt_irq_postinstall(gt); 389622e26af7SPaulo Zanoni 389722e26af7SPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 389822e26af7SPaulo Zanoni 389922e26af7SPaulo Zanoni if (HAS_DISPLAY(dev_priv)) { 390022e26af7SPaulo Zanoni icp_irq_postinstall(dev_priv); 390122e26af7SPaulo Zanoni gen8_de_irq_postinstall(dev_priv); 390222e26af7SPaulo Zanoni intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, 390322e26af7SPaulo Zanoni GEN11_DISPLAY_IRQ_ENABLE); 390422e26af7SPaulo Zanoni } 390522e26af7SPaulo Zanoni 3906fd4d7904SPaulo Zanoni dg1_master_intr_enable(uncore->regs); 3907fd4d7904SPaulo Zanoni intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR); 390897b492f5SLucas De Marchi } 390951951ae7SMika Kuoppala 3910b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) 391143f328d7SVille Syrjälä { 39122cbc876dSMichał Winiarski gen8_gt_irq_postinstall(to_gt(dev_priv)); 391343f328d7SVille Syrjälä 3914ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 39159918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3916ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3917ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3918ad22d106SVille Syrjälä 39192939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 39202939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 392143f328d7SVille Syrjälä } 392243f328d7SVille Syrjälä 3923b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv) 3924c2798b19SChris Wilson { 3925b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3926c2798b19SChris Wilson 392744d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 392844d9241eSVille Syrjälä 3929b16b2a2fSPaulo Zanoni GEN2_IRQ_RESET(uncore); 3930e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3931c2798b19SChris Wilson } 3932c2798b19SChris Wilson 3933b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) 3934c2798b19SChris Wilson { 3935b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3936e9e9848aSVille Syrjälä u16 enable_mask; 3937c2798b19SChris Wilson 39384f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, 39394f5fd91fSTvrtko Ursulin EMR, 39404f5fd91fSTvrtko Ursulin ~(I915_ERROR_PAGE_TABLE | 3941045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 3942c2798b19SChris Wilson 3943c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 3944c2798b19SChris Wilson dev_priv->irq_mask = 3945c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 394616659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 394716659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3948c2798b19SChris Wilson 3949e9e9848aSVille Syrjälä enable_mask = 3950c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3951c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 395216659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3953e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 3954e9e9848aSVille Syrjälä 3955b16b2a2fSPaulo Zanoni GEN2_IRQ_INIT(uncore, dev_priv->irq_mask, enable_mask); 3956c2798b19SChris Wilson 3957379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3958379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3959d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3960755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3961755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3962d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3963c2798b19SChris Wilson } 3964c2798b19SChris Wilson 39654f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915, 396678c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 396778c357ddSVille Syrjälä { 39684f5fd91fSTvrtko Ursulin struct intel_uncore *uncore = &i915->uncore; 396978c357ddSVille Syrjälä u16 emr; 397078c357ddSVille Syrjälä 39714f5fd91fSTvrtko Ursulin *eir = intel_uncore_read16(uncore, EIR); 397278c357ddSVille Syrjälä 397378c357ddSVille Syrjälä if (*eir) 39744f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EIR, *eir); 397578c357ddSVille Syrjälä 39764f5fd91fSTvrtko Ursulin *eir_stuck = intel_uncore_read16(uncore, EIR); 397778c357ddSVille Syrjälä if (*eir_stuck == 0) 397878c357ddSVille Syrjälä return; 397978c357ddSVille Syrjälä 398078c357ddSVille Syrjälä /* 398178c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 398278c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 398378c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 398478c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 398578c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 398678c357ddSVille Syrjälä * cleared except by handling the underlying error 398778c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 398878c357ddSVille Syrjälä * remains set. 398978c357ddSVille Syrjälä */ 39904f5fd91fSTvrtko Ursulin emr = intel_uncore_read16(uncore, EMR); 39914f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, 0xffff); 39924f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, emr | *eir_stuck); 399378c357ddSVille Syrjälä } 399478c357ddSVille Syrjälä 399578c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 399678c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 399778c357ddSVille Syrjälä { 399878c357ddSVille Syrjälä DRM_DEBUG("Master Error: EIR 0x%04x\n", eir); 399978c357ddSVille Syrjälä 400078c357ddSVille Syrjälä if (eir_stuck) 400100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n", 400200376ccfSWambui Karuga eir_stuck); 400378c357ddSVille Syrjälä } 400478c357ddSVille Syrjälä 400578c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 400678c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 400778c357ddSVille Syrjälä { 400878c357ddSVille Syrjälä u32 emr; 400978c357ddSVille Syrjälä 40102939eb06SJani Nikula *eir = intel_uncore_read(&dev_priv->uncore, EIR); 401178c357ddSVille Syrjälä 40122939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EIR, *eir); 401378c357ddSVille Syrjälä 40142939eb06SJani Nikula *eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR); 401578c357ddSVille Syrjälä if (*eir_stuck == 0) 401678c357ddSVille Syrjälä return; 401778c357ddSVille Syrjälä 401878c357ddSVille Syrjälä /* 401978c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 402078c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 402178c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 402278c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 402378c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 402478c357ddSVille Syrjälä * cleared except by handling the underlying error 402578c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 402678c357ddSVille Syrjälä * remains set. 402778c357ddSVille Syrjälä */ 40282939eb06SJani Nikula emr = intel_uncore_read(&dev_priv->uncore, EMR); 40292939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff); 40302939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck); 403178c357ddSVille Syrjälä } 403278c357ddSVille Syrjälä 403378c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 403478c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 403578c357ddSVille Syrjälä { 403678c357ddSVille Syrjälä DRM_DEBUG("Master Error, EIR 0x%08x\n", eir); 403778c357ddSVille Syrjälä 403878c357ddSVille Syrjälä if (eir_stuck) 403900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n", 404000376ccfSWambui Karuga eir_stuck); 404178c357ddSVille Syrjälä } 404278c357ddSVille Syrjälä 4043ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 4044c2798b19SChris Wilson { 4045b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 4046af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4047c2798b19SChris Wilson 40482dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 40492dd2a883SImre Deak return IRQ_NONE; 40502dd2a883SImre Deak 40511f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 40529102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 40531f814dacSImre Deak 4054af722d28SVille Syrjälä do { 4055af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 405678c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 4057af722d28SVille Syrjälä u16 iir; 4058af722d28SVille Syrjälä 40594f5fd91fSTvrtko Ursulin iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR); 4060c2798b19SChris Wilson if (iir == 0) 4061af722d28SVille Syrjälä break; 4062c2798b19SChris Wilson 4063af722d28SVille Syrjälä ret = IRQ_HANDLED; 4064c2798b19SChris Wilson 4065eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4066eb64343cSVille Syrjälä * signalled in iir */ 4067eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4068c2798b19SChris Wilson 406978c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 407078c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 407178c357ddSVille Syrjälä 40724f5fd91fSTvrtko Ursulin intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); 4073c2798b19SChris Wilson 4074c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 40752cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 4076c2798b19SChris Wilson 407778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 407878c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 4079af722d28SVille Syrjälä 4080eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4081af722d28SVille Syrjälä } while (0); 4082c2798b19SChris Wilson 40839c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 40849c6508b9SThomas Gleixner 40859102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 40861f814dacSImre Deak 40871f814dacSImre Deak return ret; 4088c2798b19SChris Wilson } 4089c2798b19SChris Wilson 4090b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv) 4091a266c7d5SChris Wilson { 4092b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 4093a266c7d5SChris Wilson 409456b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 40950706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 40962939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 4097a266c7d5SChris Wilson } 4098a266c7d5SChris Wilson 409944d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 410044d9241eSVille Syrjälä 4101b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 4102e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 4103a266c7d5SChris Wilson } 4104a266c7d5SChris Wilson 4105b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv) 4106a266c7d5SChris Wilson { 4107b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 410838bde180SChris Wilson u32 enable_mask; 4109a266c7d5SChris Wilson 41102939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, ~(I915_ERROR_PAGE_TABLE | 4111045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 411238bde180SChris Wilson 411338bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 411438bde180SChris Wilson dev_priv->irq_mask = 411538bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 411638bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 411716659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 411816659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 411938bde180SChris Wilson 412038bde180SChris Wilson enable_mask = 412138bde180SChris Wilson I915_ASLE_INTERRUPT | 412238bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 412338bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 412416659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 412538bde180SChris Wilson I915_USER_INTERRUPT; 412638bde180SChris Wilson 412756b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 4128a266c7d5SChris Wilson /* Enable in IER... */ 4129a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 4130a266c7d5SChris Wilson /* and unmask in IMR */ 4131a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 4132a266c7d5SChris Wilson } 4133a266c7d5SChris Wilson 4134b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 4135a266c7d5SChris Wilson 4136379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4137379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4138d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4139755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4140755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4141d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4142379ef82dSDaniel Vetter 4143c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 414420afbda2SDaniel Vetter } 414520afbda2SDaniel Vetter 4146ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 4147a266c7d5SChris Wilson { 4148b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 4149af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4150a266c7d5SChris Wilson 41512dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 41522dd2a883SImre Deak return IRQ_NONE; 41532dd2a883SImre Deak 41541f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 41559102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 41561f814dacSImre Deak 415738bde180SChris Wilson do { 4158eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 415978c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4160af722d28SVille Syrjälä u32 hotplug_status = 0; 4161af722d28SVille Syrjälä u32 iir; 4162a266c7d5SChris Wilson 41632939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 4164af722d28SVille Syrjälä if (iir == 0) 4165af722d28SVille Syrjälä break; 4166af722d28SVille Syrjälä 4167af722d28SVille Syrjälä ret = IRQ_HANDLED; 4168af722d28SVille Syrjälä 4169af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 4170af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 4171af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4172a266c7d5SChris Wilson 4173eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4174eb64343cSVille Syrjälä * signalled in iir */ 4175eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4176a266c7d5SChris Wilson 417778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 417878c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 417978c357ddSVille Syrjälä 41802939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 4181a266c7d5SChris Wilson 4182a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 41832cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir); 4184a266c7d5SChris Wilson 418578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 418678c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4187a266c7d5SChris Wilson 4188af722d28SVille Syrjälä if (hotplug_status) 4189af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4190af722d28SVille Syrjälä 4191af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4192af722d28SVille Syrjälä } while (0); 4193a266c7d5SChris Wilson 41949c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 41959c6508b9SThomas Gleixner 41969102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 41971f814dacSImre Deak 4198a266c7d5SChris Wilson return ret; 4199a266c7d5SChris Wilson } 4200a266c7d5SChris Wilson 4201b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv) 4202a266c7d5SChris Wilson { 4203b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 4204a266c7d5SChris Wilson 42050706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 42062939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 4207a266c7d5SChris Wilson 420844d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 420944d9241eSVille Syrjälä 4210b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 4211e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 4212a266c7d5SChris Wilson } 4213a266c7d5SChris Wilson 4214b318b824SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv) 4215a266c7d5SChris Wilson { 4216b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 4217bbba0a97SChris Wilson u32 enable_mask; 4218a266c7d5SChris Wilson u32 error_mask; 4219a266c7d5SChris Wilson 4220045cebd2SVille Syrjälä /* 4221045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 4222045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 4223045cebd2SVille Syrjälä */ 4224045cebd2SVille Syrjälä if (IS_G4X(dev_priv)) { 4225045cebd2SVille Syrjälä error_mask = ~(GM45_ERROR_PAGE_TABLE | 4226045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 4227045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 4228045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4229045cebd2SVille Syrjälä } else { 4230045cebd2SVille Syrjälä error_mask = ~(I915_ERROR_PAGE_TABLE | 4231045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4232045cebd2SVille Syrjälä } 42332939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, error_mask); 4234045cebd2SVille Syrjälä 4235a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 4236c30bb1fdSVille Syrjälä dev_priv->irq_mask = 4237c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 4238adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 4239bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4240bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 424178c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 4242bbba0a97SChris Wilson 4243c30bb1fdSVille Syrjälä enable_mask = 4244c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 4245c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 4246c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4247c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 424878c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 4249c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 4250bbba0a97SChris Wilson 425191d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4252bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 4253a266c7d5SChris Wilson 4254b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 4255c30bb1fdSVille Syrjälä 4256b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4257b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4258d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4259755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 4260755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4261755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4262d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4263a266c7d5SChris Wilson 426491d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 426520afbda2SDaniel Vetter } 426620afbda2SDaniel Vetter 426791d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) 426820afbda2SDaniel Vetter { 426920afbda2SDaniel Vetter u32 hotplug_en; 427020afbda2SDaniel Vetter 427167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4272b5ea2d56SDaniel Vetter 4273adca4730SChris Wilson /* Note HDMI and DP share hotplug bits */ 4274e5868a31SEgbert Eich /* enable bits are the same for all generations */ 427591d14251STvrtko Ursulin hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915); 4276a266c7d5SChris Wilson /* Programming the CRT detection parameters tends 4277a266c7d5SChris Wilson to generate a spurious hotplug event about three 4278a266c7d5SChris Wilson seconds later. So just do it once. 4279a266c7d5SChris Wilson */ 428091d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4281a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; 4282a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; 4283a266c7d5SChris Wilson 4284a266c7d5SChris Wilson /* Ignore TV since it's buggy */ 42850706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, 4286f9e3dc78SJani Nikula HOTPLUG_INT_EN_MASK | 4287f9e3dc78SJani Nikula CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | 4288f9e3dc78SJani Nikula CRT_HOTPLUG_ACTIVATION_PERIOD_64, 42890706f17cSEgbert Eich hotplug_en); 4290a266c7d5SChris Wilson } 4291a266c7d5SChris Wilson 4292ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 4293a266c7d5SChris Wilson { 4294b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 4295af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4296a266c7d5SChris Wilson 42972dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 42982dd2a883SImre Deak return IRQ_NONE; 42992dd2a883SImre Deak 43001f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 43019102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 43021f814dacSImre Deak 4303af722d28SVille Syrjälä do { 4304eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 430578c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4306af722d28SVille Syrjälä u32 hotplug_status = 0; 4307af722d28SVille Syrjälä u32 iir; 43082c8ba29fSChris Wilson 43092939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 4310af722d28SVille Syrjälä if (iir == 0) 4311af722d28SVille Syrjälä break; 4312af722d28SVille Syrjälä 4313af722d28SVille Syrjälä ret = IRQ_HANDLED; 4314af722d28SVille Syrjälä 4315af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 4316af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4317a266c7d5SChris Wilson 4318eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4319eb64343cSVille Syrjälä * signalled in iir */ 4320eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4321a266c7d5SChris Wilson 432278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 432378c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 432478c357ddSVille Syrjälä 43252939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 4326a266c7d5SChris Wilson 4327a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 43282cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], 43290669a6e1SChris Wilson iir); 4330af722d28SVille Syrjälä 4331a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 43322cbc876dSMichał Winiarski intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0], 43330669a6e1SChris Wilson iir >> 25); 4334a266c7d5SChris Wilson 433578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 433678c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4337515ac2bbSDaniel Vetter 4338af722d28SVille Syrjälä if (hotplug_status) 4339af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4340af722d28SVille Syrjälä 4341af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4342af722d28SVille Syrjälä } while (0); 4343a266c7d5SChris Wilson 43449c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 43459c6508b9SThomas Gleixner 43469102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 43471f814dacSImre Deak 4348a266c7d5SChris Wilson return ret; 4349a266c7d5SChris Wilson } 4350a266c7d5SChris Wilson 43517e97596cSJani Nikula struct intel_hotplug_funcs { 43527e97596cSJani Nikula void (*hpd_irq_setup)(struct drm_i915_private *i915); 43537e97596cSJani Nikula }; 43547e97596cSJani Nikula 4355cd030c7cSDave Airlie #define HPD_FUNCS(platform) \ 4356cd030c7cSDave Airlie static const struct intel_hotplug_funcs platform##_hpd_funcs = { \ 4357cd030c7cSDave Airlie .hpd_irq_setup = platform##_hpd_irq_setup, \ 4358cd030c7cSDave Airlie } 4359cd030c7cSDave Airlie 4360cd030c7cSDave Airlie HPD_FUNCS(i915); 4361cd030c7cSDave Airlie HPD_FUNCS(dg1); 4362cd030c7cSDave Airlie HPD_FUNCS(gen11); 4363cd030c7cSDave Airlie HPD_FUNCS(bxt); 4364cd030c7cSDave Airlie HPD_FUNCS(icp); 4365cd030c7cSDave Airlie HPD_FUNCS(spt); 4366cd030c7cSDave Airlie HPD_FUNCS(ilk); 4367cd030c7cSDave Airlie #undef HPD_FUNCS 4368cd030c7cSDave Airlie 43697e97596cSJani Nikula void intel_hpd_irq_setup(struct drm_i915_private *i915) 43707e97596cSJani Nikula { 43717e97596cSJani Nikula if (i915->display_irqs_enabled && i915->hotplug_funcs) 43727e97596cSJani Nikula i915->hotplug_funcs->hpd_irq_setup(i915); 43737e97596cSJani Nikula } 43747e97596cSJani Nikula 4375fca52a55SDaniel Vetter /** 4376fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 4377fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4378fca52a55SDaniel Vetter * 4379fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 4380fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 4381fca52a55SDaniel Vetter */ 4382b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 4383f71d4af4SJesse Barnes { 438491c8a326SChris Wilson struct drm_device *dev = &dev_priv->drm; 4385cefcff8fSJoonas Lahtinen int i; 43868b2e326dSChris Wilson 438774bb98baSLucas De Marchi INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); 4388cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4389cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 43908b2e326dSChris Wilson 4391633023a4SDaniele Ceraolo Spurio /* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */ 4392651e7d48SLucas De Marchi if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11) 43932cbc876dSMichał Winiarski to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16; 439426705e20SSagar Arun Kamble 43959a450b68SLucas De Marchi if (!HAS_DISPLAY(dev_priv)) 43969a450b68SLucas De Marchi return; 43979a450b68SLucas De Marchi 439896bd87b7SLucas De Marchi intel_hpd_init_pins(dev_priv); 439996bd87b7SLucas De Marchi 440096bd87b7SLucas De Marchi intel_hpd_init_work(dev_priv); 440196bd87b7SLucas De Marchi 440221da2700SVille Syrjälä dev->vblank_disable_immediate = true; 440321da2700SVille Syrjälä 4404262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 4405262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 4406262fd485SChris Wilson * special care to avoid writing any of the display block registers 4407262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 4408262fd485SChris Wilson * in this case to the runtime pm. 4409262fd485SChris Wilson */ 4410262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 4411262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 4412262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 4413262fd485SChris Wilson 4414317eaa95SLyude dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; 44159a64c650SLyude Paul /* If we have MST support, we want to avoid doing short HPD IRQ storm 44169a64c650SLyude Paul * detection, as short HPD storms will occur as a natural part of 44179a64c650SLyude Paul * sideband messaging with MST. 44189a64c650SLyude Paul * On older platforms however, IRQ storms can occur with both long and 44199a64c650SLyude Paul * short pulses, as seen on some G4x systems. 44209a64c650SLyude Paul */ 44219a64c650SLyude Paul dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); 4422317eaa95SLyude 44232ccf2e03SChris Wilson if (HAS_GMCH(dev_priv)) { 44242ccf2e03SChris Wilson if (I915_HAS_HOTPLUG(dev_priv)) 4425cd030c7cSDave Airlie dev_priv->hotplug_funcs = &i915_hpd_funcs; 44262ccf2e03SChris Wilson } else { 4427229f31e2SLucas De Marchi if (HAS_PCH_DG1(dev_priv)) 4428cd030c7cSDave Airlie dev_priv->hotplug_funcs = &dg1_hpd_funcs; 4429373abf1aSMatt Roper else if (DISPLAY_VER(dev_priv) >= 11) 4430cd030c7cSDave Airlie dev_priv->hotplug_funcs = &gen11_hpd_funcs; 443170bfb307SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 4432cd030c7cSDave Airlie dev_priv->hotplug_funcs = &bxt_hpd_funcs; 4433cec3295bSLyude Paul else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 4434cd030c7cSDave Airlie dev_priv->hotplug_funcs = &icp_hpd_funcs; 4435c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 4436cd030c7cSDave Airlie dev_priv->hotplug_funcs = &spt_hpd_funcs; 44376dbf30ceSVille Syrjälä else 4438cd030c7cSDave Airlie dev_priv->hotplug_funcs = &ilk_hpd_funcs; 4439f71d4af4SJesse Barnes } 44402ccf2e03SChris Wilson } 444120afbda2SDaniel Vetter 4442fca52a55SDaniel Vetter /** 4443cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 4444cefcff8fSJoonas Lahtinen * @i915: i915 device instance 4445cefcff8fSJoonas Lahtinen * 4446cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 4447cefcff8fSJoonas Lahtinen */ 4448cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 4449cefcff8fSJoonas Lahtinen { 4450cefcff8fSJoonas Lahtinen int i; 4451cefcff8fSJoonas Lahtinen 4452cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4453cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 4454cefcff8fSJoonas Lahtinen } 4455cefcff8fSJoonas Lahtinen 4456b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) 4457b318b824SVille Syrjälä { 4458b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4459b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4460b318b824SVille Syrjälä return cherryview_irq_handler; 4461b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4462b318b824SVille Syrjälä return valleyview_irq_handler; 4463651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4464b318b824SVille Syrjälä return i965_irq_handler; 4465651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4466b318b824SVille Syrjälä return i915_irq_handler; 4467b318b824SVille Syrjälä else 4468b318b824SVille Syrjälä return i8xx_irq_handler; 4469b318b824SVille Syrjälä } else { 447022e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 447197b492f5SLucas De Marchi return dg1_irq_handler; 447222e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4473b318b824SVille Syrjälä return gen11_irq_handler; 4474651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4475b318b824SVille Syrjälä return gen8_irq_handler; 4476b318b824SVille Syrjälä else 44779eae5e27SLucas De Marchi return ilk_irq_handler; 4478b318b824SVille Syrjälä } 4479b318b824SVille Syrjälä } 4480b318b824SVille Syrjälä 4481b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv) 4482b318b824SVille Syrjälä { 4483b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4484b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4485b318b824SVille Syrjälä cherryview_irq_reset(dev_priv); 4486b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4487b318b824SVille Syrjälä valleyview_irq_reset(dev_priv); 4488651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4489b318b824SVille Syrjälä i965_irq_reset(dev_priv); 4490651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4491b318b824SVille Syrjälä i915_irq_reset(dev_priv); 4492b318b824SVille Syrjälä else 4493b318b824SVille Syrjälä i8xx_irq_reset(dev_priv); 4494b318b824SVille Syrjälä } else { 449522e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 449622e26af7SPaulo Zanoni dg1_irq_reset(dev_priv); 449722e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4498b318b824SVille Syrjälä gen11_irq_reset(dev_priv); 4499651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4500b318b824SVille Syrjälä gen8_irq_reset(dev_priv); 4501b318b824SVille Syrjälä else 45029eae5e27SLucas De Marchi ilk_irq_reset(dev_priv); 4503b318b824SVille Syrjälä } 4504b318b824SVille Syrjälä } 4505b318b824SVille Syrjälä 4506b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv) 4507b318b824SVille Syrjälä { 4508b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4509b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4510b318b824SVille Syrjälä cherryview_irq_postinstall(dev_priv); 4511b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4512b318b824SVille Syrjälä valleyview_irq_postinstall(dev_priv); 4513651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 4) 4514b318b824SVille Syrjälä i965_irq_postinstall(dev_priv); 4515651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) == 3) 4516b318b824SVille Syrjälä i915_irq_postinstall(dev_priv); 4517b318b824SVille Syrjälä else 4518b318b824SVille Syrjälä i8xx_irq_postinstall(dev_priv); 4519b318b824SVille Syrjälä } else { 452022e26af7SPaulo Zanoni if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) 452122e26af7SPaulo Zanoni dg1_irq_postinstall(dev_priv); 452222e26af7SPaulo Zanoni else if (GRAPHICS_VER(dev_priv) >= 11) 4523b318b824SVille Syrjälä gen11_irq_postinstall(dev_priv); 4524651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 8) 4525b318b824SVille Syrjälä gen8_irq_postinstall(dev_priv); 4526b318b824SVille Syrjälä else 45279eae5e27SLucas De Marchi ilk_irq_postinstall(dev_priv); 4528b318b824SVille Syrjälä } 4529b318b824SVille Syrjälä } 4530b318b824SVille Syrjälä 4531cefcff8fSJoonas Lahtinen /** 4532fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 4533fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4534fca52a55SDaniel Vetter * 4535fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 4536fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 4537fca52a55SDaniel Vetter * 4538fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 4539fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 4540fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 4541fca52a55SDaniel Vetter */ 45422aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 45432aeb7d3aSDaniel Vetter { 45448ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4545b318b824SVille Syrjälä int ret; 4546b318b824SVille Syrjälä 45472aeb7d3aSDaniel Vetter /* 45482aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 45492aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 45502aeb7d3aSDaniel Vetter * special cases in our ordering checks. 45512aeb7d3aSDaniel Vetter */ 4552ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 45532aeb7d3aSDaniel Vetter 4554ac1723c1SThomas Zimmermann dev_priv->irq_enabled = true; 4555b318b824SVille Syrjälä 4556b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4557b318b824SVille Syrjälä 4558b318b824SVille Syrjälä ret = request_irq(irq, intel_irq_handler(dev_priv), 4559b318b824SVille Syrjälä IRQF_SHARED, DRIVER_NAME, dev_priv); 4560b318b824SVille Syrjälä if (ret < 0) { 4561ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 4562b318b824SVille Syrjälä return ret; 4563b318b824SVille Syrjälä } 4564b318b824SVille Syrjälä 4565b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4566b318b824SVille Syrjälä 4567b318b824SVille Syrjälä return ret; 45682aeb7d3aSDaniel Vetter } 45692aeb7d3aSDaniel Vetter 4570fca52a55SDaniel Vetter /** 4571fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 4572fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4573fca52a55SDaniel Vetter * 4574fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 4575fca52a55SDaniel Vetter * resources acquired in the init functions. 4576fca52a55SDaniel Vetter */ 45772aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 45782aeb7d3aSDaniel Vetter { 45798ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4580b318b824SVille Syrjälä 4581b318b824SVille Syrjälä /* 4582789fa874SJanusz Krzysztofik * FIXME we can get called twice during driver probe 4583789fa874SJanusz Krzysztofik * error handling as well as during driver remove due to 4584789fa874SJanusz Krzysztofik * intel_modeset_driver_remove() calling us out of sequence. 4585789fa874SJanusz Krzysztofik * Would be nice if it didn't do that... 4586b318b824SVille Syrjälä */ 4587ac1723c1SThomas Zimmermann if (!dev_priv->irq_enabled) 4588b318b824SVille Syrjälä return; 4589b318b824SVille Syrjälä 4590ac1723c1SThomas Zimmermann dev_priv->irq_enabled = false; 4591b318b824SVille Syrjälä 4592b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4593b318b824SVille Syrjälä 4594b318b824SVille Syrjälä free_irq(irq, dev_priv); 4595b318b824SVille Syrjälä 45962aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 4597ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 45982aeb7d3aSDaniel Vetter } 45992aeb7d3aSDaniel Vetter 4600fca52a55SDaniel Vetter /** 4601fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 4602fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4603fca52a55SDaniel Vetter * 4604fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 4605fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4606fca52a55SDaniel Vetter */ 4607b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 4608c67a470bSPaulo Zanoni { 4609b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4610ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 4611315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 4612c67a470bSPaulo Zanoni } 4613c67a470bSPaulo Zanoni 4614fca52a55SDaniel Vetter /** 4615fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 4616fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4617fca52a55SDaniel Vetter * 4618fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 4619fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4620fca52a55SDaniel Vetter */ 4621b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 4622c67a470bSPaulo Zanoni { 4623ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 4624b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4625b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4626c67a470bSPaulo Zanoni } 4627d64575eeSJani Nikula 4628d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv) 4629d64575eeSJani Nikula { 4630d64575eeSJani Nikula return dev_priv->runtime_pm.irqs_enabled; 4631d64575eeSJani Nikula } 4632d64575eeSJani Nikula 4633d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915) 4634d64575eeSJani Nikula { 46358ff5446aSThomas Zimmermann synchronize_irq(to_pci_dev(i915->drm.dev)->irq); 4636d64575eeSJani Nikula } 4637320ad343SThomas Zimmermann 4638320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915) 4639320ad343SThomas Zimmermann { 4640320ad343SThomas Zimmermann synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq); 4641320ad343SThomas Zimmermann } 4642