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 #include <drm/drm_irq.h> 3755367a27SJani Nikula 381d455f8dSJani Nikula #include "display/intel_display_types.h" 39df0566a6SJani Nikula #include "display/intel_fifo_underrun.h" 40df0566a6SJani Nikula #include "display/intel_hotplug.h" 41df0566a6SJani Nikula #include "display/intel_lpe_audio.h" 42df0566a6SJani Nikula #include "display/intel_psr.h" 43df0566a6SJani Nikula 44b3786b29SChris Wilson #include "gt/intel_breadcrumbs.h" 452239e6dfSDaniele Ceraolo Spurio #include "gt/intel_gt.h" 46cf1c97dcSAndi Shyti #include "gt/intel_gt_irq.h" 47d762043fSAndi Shyti #include "gt/intel_gt_pm_irq.h" 483e7abf81SAndi Shyti #include "gt/intel_rps.h" 492239e6dfSDaniele Ceraolo Spurio 50c0e09200SDave Airlie #include "i915_drv.h" 51440e2b3dSJani Nikula #include "i915_irq.h" 521c5d22f7SChris Wilson #include "i915_trace.h" 53d13616dbSJani Nikula #include "intel_pm.h" 54c0e09200SDave Airlie 55fca52a55SDaniel Vetter /** 56fca52a55SDaniel Vetter * DOC: interrupt handling 57fca52a55SDaniel Vetter * 58fca52a55SDaniel Vetter * These functions provide the basic support for enabling and disabling the 59fca52a55SDaniel Vetter * interrupt handling support. There's a lot more functionality in i915_irq.c 60fca52a55SDaniel Vetter * and related files, but that will be described in separate chapters. 61fca52a55SDaniel Vetter */ 62fca52a55SDaniel Vetter 639c6508b9SThomas Gleixner /* 649c6508b9SThomas Gleixner * Interrupt statistic for PMU. Increments the counter only if the 659c6508b9SThomas Gleixner * interrupt originated from the the GPU so interrupts from a device which 669c6508b9SThomas Gleixner * shares the interrupt line are not accounted. 679c6508b9SThomas Gleixner */ 689c6508b9SThomas Gleixner static inline void pmu_irq_stats(struct drm_i915_private *i915, 699c6508b9SThomas Gleixner irqreturn_t res) 709c6508b9SThomas Gleixner { 719c6508b9SThomas Gleixner if (unlikely(res != IRQ_HANDLED)) 729c6508b9SThomas Gleixner return; 739c6508b9SThomas Gleixner 749c6508b9SThomas Gleixner /* 759c6508b9SThomas Gleixner * A clever compiler translates that into INC. A not so clever one 769c6508b9SThomas Gleixner * should at least prevent store tearing. 779c6508b9SThomas Gleixner */ 789c6508b9SThomas Gleixner WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1); 799c6508b9SThomas Gleixner } 809c6508b9SThomas Gleixner 8148ef15d3SJosé Roberto de Souza typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val); 822ea63927SVille Syrjälä typedef u32 (*hotplug_enables_func)(struct drm_i915_private *i915, 832ea63927SVille Syrjälä enum hpd_pin pin); 8448ef15d3SJosé Roberto de Souza 85e4ce95aaSVille Syrjälä static const u32 hpd_ilk[HPD_NUM_PINS] = { 86e4ce95aaSVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG, 87e4ce95aaSVille Syrjälä }; 88e4ce95aaSVille Syrjälä 8923bb4cb5SVille Syrjälä static const u32 hpd_ivb[HPD_NUM_PINS] = { 9023bb4cb5SVille Syrjälä [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, 9123bb4cb5SVille Syrjälä }; 9223bb4cb5SVille Syrjälä 933a3b3c7dSVille Syrjälä static const u32 hpd_bdw[HPD_NUM_PINS] = { 94e5abaab3SVille Syrjälä [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), 953a3b3c7dSVille Syrjälä }; 963a3b3c7dSVille Syrjälä 977c7e10dbSVille Syrjälä static const u32 hpd_ibx[HPD_NUM_PINS] = { 98e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG, 99e5868a31SEgbert Eich [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, 100e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG, 101e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG, 1027203d49cSVille Syrjälä [HPD_PORT_D] = SDE_PORTD_HOTPLUG, 103e5868a31SEgbert Eich }; 104e5868a31SEgbert Eich 1057c7e10dbSVille Syrjälä static const u32 hpd_cpt[HPD_NUM_PINS] = { 106e5868a31SEgbert Eich [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, 10773c352a2SDaniel Vetter [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, 108e5868a31SEgbert Eich [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 109e5868a31SEgbert Eich [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 1107203d49cSVille Syrjälä [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 111e5868a31SEgbert Eich }; 112e5868a31SEgbert Eich 11326951cafSXiong Zhang static const u32 hpd_spt[HPD_NUM_PINS] = { 11474c0b395SVille Syrjälä [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, 11526951cafSXiong Zhang [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, 11626951cafSXiong Zhang [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, 11726951cafSXiong Zhang [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, 1187203d49cSVille Syrjälä [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT, 11926951cafSXiong Zhang }; 12026951cafSXiong Zhang 1217c7e10dbSVille Syrjälä static const u32 hpd_mask_i915[HPD_NUM_PINS] = { 122e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_EN, 123e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, 124e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, 125e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN, 126e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN, 1277203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN, 128e5868a31SEgbert Eich }; 129e5868a31SEgbert Eich 1307c7e10dbSVille Syrjälä static const u32 hpd_status_g4x[HPD_NUM_PINS] = { 131e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 132e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, 133e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, 134e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 135e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 1367203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, 137e5868a31SEgbert Eich }; 138e5868a31SEgbert Eich 1394bca26d0SVille Syrjälä static const u32 hpd_status_i915[HPD_NUM_PINS] = { 140e5868a31SEgbert Eich [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, 141e5868a31SEgbert Eich [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, 142e5868a31SEgbert Eich [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, 143e5868a31SEgbert Eich [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, 144e5868a31SEgbert Eich [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, 1457203d49cSVille Syrjälä [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, 146e5868a31SEgbert Eich }; 147e5868a31SEgbert Eich 148e0a20ad7SShashank Sharma static const u32 hpd_bxt[HPD_NUM_PINS] = { 149e5abaab3SVille Syrjälä [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), 150e5abaab3SVille Syrjälä [HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B), 151e5abaab3SVille Syrjälä [HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C), 152e0a20ad7SShashank Sharma }; 153e0a20ad7SShashank Sharma 154b796b971SDhinakaran Pandiyan static const u32 hpd_gen11[HPD_NUM_PINS] = { 1555b76e860SVille Syrjälä [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1), 1565b76e860SVille Syrjälä [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2), 1575b76e860SVille Syrjälä [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3), 1585b76e860SVille Syrjälä [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4), 1595b76e860SVille Syrjälä [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5), 1605b76e860SVille Syrjälä [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6), 16148ef15d3SJosé Roberto de Souza }; 16248ef15d3SJosé Roberto de Souza 16331604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = { 1645f371a81SVille Syrjälä [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), 1655f371a81SVille Syrjälä [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), 1665f371a81SVille Syrjälä [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), 16797011359SVille Syrjälä [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1), 16897011359SVille Syrjälä [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2), 16997011359SVille Syrjälä [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3), 17097011359SVille Syrjälä [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4), 17197011359SVille Syrjälä [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5), 17297011359SVille Syrjälä [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6), 17352dfdba0SLucas De Marchi }; 17452dfdba0SLucas De Marchi 175229f31e2SLucas De Marchi static const u32 hpd_sde_dg1[HPD_NUM_PINS] = { 1765f371a81SVille Syrjälä [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), 1775f371a81SVille Syrjälä [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), 1785f371a81SVille Syrjälä [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), 1795f371a81SVille Syrjälä [HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D), 180229f31e2SLucas De Marchi }; 181229f31e2SLucas De Marchi 1820398993bSVille Syrjälä static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) 1830398993bSVille Syrjälä { 1840398993bSVille Syrjälä struct i915_hotplug *hpd = &dev_priv->hotplug; 1850398993bSVille Syrjälä 1860398993bSVille Syrjälä if (HAS_GMCH(dev_priv)) { 1870398993bSVille Syrjälä if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || 1880398993bSVille Syrjälä IS_CHERRYVIEW(dev_priv)) 1890398993bSVille Syrjälä hpd->hpd = hpd_status_g4x; 1900398993bSVille Syrjälä else 1910398993bSVille Syrjälä hpd->hpd = hpd_status_i915; 1920398993bSVille Syrjälä return; 1930398993bSVille Syrjälä } 1940398993bSVille Syrjälä 195da51e4baSVille Syrjälä if (INTEL_GEN(dev_priv) >= 11) 1960398993bSVille Syrjälä hpd->hpd = hpd_gen11; 1970398993bSVille Syrjälä else if (IS_GEN9_LP(dev_priv)) 1980398993bSVille Syrjälä hpd->hpd = hpd_bxt; 1990398993bSVille Syrjälä else if (INTEL_GEN(dev_priv) >= 8) 2000398993bSVille Syrjälä hpd->hpd = hpd_bdw; 2010398993bSVille Syrjälä else if (INTEL_GEN(dev_priv) >= 7) 2020398993bSVille Syrjälä hpd->hpd = hpd_ivb; 2030398993bSVille Syrjälä else 2040398993bSVille Syrjälä hpd->hpd = hpd_ilk; 2050398993bSVille Syrjälä 206229f31e2SLucas De Marchi if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) && 207229f31e2SLucas De Marchi (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv))) 2080398993bSVille Syrjälä return; 2090398993bSVille Syrjälä 210229f31e2SLucas De Marchi if (HAS_PCH_DG1(dev_priv)) 211229f31e2SLucas De Marchi hpd->pch_hpd = hpd_sde_dg1; 212fa58c9e4SAnusha Srivatsa else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 2130398993bSVille Syrjälä hpd->pch_hpd = hpd_icp; 2140398993bSVille Syrjälä else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv)) 2150398993bSVille Syrjälä hpd->pch_hpd = hpd_spt; 2160398993bSVille Syrjälä else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv)) 2170398993bSVille Syrjälä hpd->pch_hpd = hpd_cpt; 2180398993bSVille Syrjälä else if (HAS_PCH_IBX(dev_priv)) 2190398993bSVille Syrjälä hpd->pch_hpd = hpd_ibx; 2200398993bSVille Syrjälä else 2210398993bSVille Syrjälä MISSING_CASE(INTEL_PCH_TYPE(dev_priv)); 2220398993bSVille Syrjälä } 2230398993bSVille Syrjälä 224aca9310aSAnshuman Gupta static void 225aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) 226aca9310aSAnshuman Gupta { 227aca9310aSAnshuman Gupta struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); 228aca9310aSAnshuman Gupta 229aca9310aSAnshuman Gupta drm_crtc_handle_vblank(&crtc->base); 230aca9310aSAnshuman Gupta } 231aca9310aSAnshuman Gupta 232cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr, 23368eb49b1SPaulo Zanoni i915_reg_t iir, i915_reg_t ier) 23468eb49b1SPaulo Zanoni { 23565f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, 0xffffffff); 23665f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 23768eb49b1SPaulo Zanoni 23865f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, 0); 23968eb49b1SPaulo Zanoni 2405c502442SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 24165f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24265f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 24365f42cdcSPaulo Zanoni intel_uncore_write(uncore, iir, 0xffffffff); 24465f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, iir); 24568eb49b1SPaulo Zanoni } 2465c502442SPaulo Zanoni 247cf1c97dcSAndi Shyti void gen2_irq_reset(struct intel_uncore *uncore) 24868eb49b1SPaulo Zanoni { 24965f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, 0xffff); 25065f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 251a9d356a6SPaulo Zanoni 25265f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, 0); 25368eb49b1SPaulo Zanoni 25468eb49b1SPaulo Zanoni /* IIR can theoretically queue up two events. Be paranoid. */ 25565f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 25665f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 25765f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 25865f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 25968eb49b1SPaulo Zanoni } 26068eb49b1SPaulo Zanoni 261337ba017SPaulo Zanoni /* 262337ba017SPaulo Zanoni * We should clear IMR at preinstall/uninstall, and just check at postinstall. 263337ba017SPaulo Zanoni */ 26465f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) 265b51a2842SVille Syrjälä { 26665f42cdcSPaulo Zanoni u32 val = intel_uncore_read(uncore, reg); 267b51a2842SVille Syrjälä 268b51a2842SVille Syrjälä if (val == 0) 269b51a2842SVille Syrjälä return; 270b51a2842SVille Syrjälä 271a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 272a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 273f0f59a00SVille Syrjälä i915_mmio_reg_offset(reg), val); 27465f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 27565f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 27665f42cdcSPaulo Zanoni intel_uncore_write(uncore, reg, 0xffffffff); 27765f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, reg); 278b51a2842SVille Syrjälä } 279337ba017SPaulo Zanoni 28065f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore) 281e9e9848aSVille Syrjälä { 28265f42cdcSPaulo Zanoni u16 val = intel_uncore_read16(uncore, GEN2_IIR); 283e9e9848aSVille Syrjälä 284e9e9848aSVille Syrjälä if (val == 0) 285e9e9848aSVille Syrjälä return; 286e9e9848aSVille Syrjälä 287a9f236d1SPankaj Bharadiya drm_WARN(&uncore->i915->drm, 1, 288a9f236d1SPankaj Bharadiya "Interrupt register 0x%x is not zero: 0x%08x\n", 2899d9523d8SPaulo Zanoni i915_mmio_reg_offset(GEN2_IIR), val); 29065f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29165f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 29265f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IIR, 0xffff); 29365f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IIR); 294e9e9848aSVille Syrjälä } 295e9e9848aSVille Syrjälä 296cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore, 29768eb49b1SPaulo Zanoni i915_reg_t imr, u32 imr_val, 29868eb49b1SPaulo Zanoni i915_reg_t ier, u32 ier_val, 29968eb49b1SPaulo Zanoni i915_reg_t iir) 30068eb49b1SPaulo Zanoni { 30165f42cdcSPaulo Zanoni gen3_assert_iir_is_zero(uncore, iir); 30235079899SPaulo Zanoni 30365f42cdcSPaulo Zanoni intel_uncore_write(uncore, ier, ier_val); 30465f42cdcSPaulo Zanoni intel_uncore_write(uncore, imr, imr_val); 30565f42cdcSPaulo Zanoni intel_uncore_posting_read(uncore, imr); 30668eb49b1SPaulo Zanoni } 30735079899SPaulo Zanoni 308cf1c97dcSAndi Shyti void gen2_irq_init(struct intel_uncore *uncore, 3092918c3caSPaulo Zanoni u32 imr_val, u32 ier_val) 31068eb49b1SPaulo Zanoni { 31165f42cdcSPaulo Zanoni gen2_assert_iir_is_zero(uncore); 31268eb49b1SPaulo Zanoni 31365f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IER, ier_val); 31465f42cdcSPaulo Zanoni intel_uncore_write16(uncore, GEN2_IMR, imr_val); 31565f42cdcSPaulo Zanoni intel_uncore_posting_read16(uncore, GEN2_IMR); 31668eb49b1SPaulo Zanoni } 31768eb49b1SPaulo Zanoni 3180706f17cSEgbert Eich /* For display hotplug interrupt */ 3190706f17cSEgbert Eich static inline void 3200706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, 321a9c287c9SJani Nikula u32 mask, 322a9c287c9SJani Nikula u32 bits) 3230706f17cSEgbert Eich { 324a9c287c9SJani Nikula u32 val; 3250706f17cSEgbert Eich 32667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 32748a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, bits & ~mask); 3280706f17cSEgbert Eich 3292939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_EN); 3300706f17cSEgbert Eich val &= ~mask; 3310706f17cSEgbert Eich val |= bits; 3322939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_EN, val); 3330706f17cSEgbert Eich } 3340706f17cSEgbert Eich 3350706f17cSEgbert Eich /** 3360706f17cSEgbert Eich * i915_hotplug_interrupt_update - update hotplug interrupt enable 3370706f17cSEgbert Eich * @dev_priv: driver private 3380706f17cSEgbert Eich * @mask: bits to update 3390706f17cSEgbert Eich * @bits: bits to enable 3400706f17cSEgbert Eich * NOTE: the HPD enable bits are modified both inside and outside 3410706f17cSEgbert Eich * of an interrupt context. To avoid that read-modify-write cycles 3420706f17cSEgbert Eich * interfer, these bits are protected by a spinlock. Since this 3430706f17cSEgbert Eich * function is usually not called from a context where the lock is 3440706f17cSEgbert Eich * held already, this function acquires the lock itself. A non-locking 3450706f17cSEgbert Eich * version is also available. 3460706f17cSEgbert Eich */ 3470706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, 348a9c287c9SJani Nikula u32 mask, 349a9c287c9SJani Nikula u32 bits) 3500706f17cSEgbert Eich { 3510706f17cSEgbert Eich spin_lock_irq(&dev_priv->irq_lock); 3520706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); 3530706f17cSEgbert Eich spin_unlock_irq(&dev_priv->irq_lock); 3540706f17cSEgbert Eich } 3550706f17cSEgbert Eich 356d9dc34f1SVille Syrjälä /** 357d9dc34f1SVille Syrjälä * ilk_update_display_irq - update DEIMR 358d9dc34f1SVille Syrjälä * @dev_priv: driver private 359d9dc34f1SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 360d9dc34f1SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 361d9dc34f1SVille Syrjälä */ 362fbdedaeaSVille Syrjälä void ilk_update_display_irq(struct drm_i915_private *dev_priv, 363a9c287c9SJani Nikula u32 interrupt_mask, 364a9c287c9SJani Nikula u32 enabled_irq_mask) 365036a4a7dSZhenyu Wang { 366a9c287c9SJani Nikula u32 new_val; 367d9dc34f1SVille Syrjälä 36867520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 36948a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 370d9dc34f1SVille Syrjälä 371d9dc34f1SVille Syrjälä new_val = dev_priv->irq_mask; 372d9dc34f1SVille Syrjälä new_val &= ~interrupt_mask; 373d9dc34f1SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 374d9dc34f1SVille Syrjälä 375e44adb5dSChris Wilson if (new_val != dev_priv->irq_mask && 376e44adb5dSChris Wilson !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) { 377d9dc34f1SVille Syrjälä dev_priv->irq_mask = new_val; 3782939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask); 3792939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, DEIMR); 380036a4a7dSZhenyu Wang } 381036a4a7dSZhenyu Wang } 382036a4a7dSZhenyu Wang 3830961021aSBen Widawsky /** 3843a3b3c7dSVille Syrjälä * bdw_update_port_irq - update DE port interrupt 3853a3b3c7dSVille Syrjälä * @dev_priv: driver private 3863a3b3c7dSVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 3873a3b3c7dSVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 3883a3b3c7dSVille Syrjälä */ 3893a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv, 390a9c287c9SJani Nikula u32 interrupt_mask, 391a9c287c9SJani Nikula u32 enabled_irq_mask) 3923a3b3c7dSVille Syrjälä { 393a9c287c9SJani Nikula u32 new_val; 394a9c287c9SJani Nikula u32 old_val; 3953a3b3c7dSVille Syrjälä 39667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3973a3b3c7dSVille Syrjälä 39848a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 3993a3b3c7dSVille Syrjälä 40048a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 4013a3b3c7dSVille Syrjälä return; 4023a3b3c7dSVille Syrjälä 4032939eb06SJani Nikula old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4043a3b3c7dSVille Syrjälä 4053a3b3c7dSVille Syrjälä new_val = old_val; 4063a3b3c7dSVille Syrjälä new_val &= ~interrupt_mask; 4073a3b3c7dSVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 4083a3b3c7dSVille Syrjälä 4093a3b3c7dSVille Syrjälä if (new_val != old_val) { 4102939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val); 4112939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR); 4123a3b3c7dSVille Syrjälä } 4133a3b3c7dSVille Syrjälä } 4143a3b3c7dSVille Syrjälä 4153a3b3c7dSVille Syrjälä /** 416013d3752SVille Syrjälä * bdw_update_pipe_irq - update DE pipe interrupt 417013d3752SVille Syrjälä * @dev_priv: driver private 418013d3752SVille Syrjälä * @pipe: pipe whose interrupt to update 419013d3752SVille Syrjälä * @interrupt_mask: mask of interrupt bits to update 420013d3752SVille Syrjälä * @enabled_irq_mask: mask of interrupt bits to enable 421013d3752SVille Syrjälä */ 422013d3752SVille Syrjälä void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, 423013d3752SVille Syrjälä enum pipe pipe, 424a9c287c9SJani Nikula u32 interrupt_mask, 425a9c287c9SJani Nikula u32 enabled_irq_mask) 426013d3752SVille Syrjälä { 427a9c287c9SJani Nikula u32 new_val; 428013d3752SVille Syrjälä 42967520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 430013d3752SVille Syrjälä 43148a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 432013d3752SVille Syrjälä 43348a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 434013d3752SVille Syrjälä return; 435013d3752SVille Syrjälä 436013d3752SVille Syrjälä new_val = dev_priv->de_irq_mask[pipe]; 437013d3752SVille Syrjälä new_val &= ~interrupt_mask; 438013d3752SVille Syrjälä new_val |= (~enabled_irq_mask & interrupt_mask); 439013d3752SVille Syrjälä 440013d3752SVille Syrjälä if (new_val != dev_priv->de_irq_mask[pipe]) { 441013d3752SVille Syrjälä dev_priv->de_irq_mask[pipe] = new_val; 4422939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); 4432939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); 444013d3752SVille Syrjälä } 445013d3752SVille Syrjälä } 446013d3752SVille Syrjälä 447013d3752SVille Syrjälä /** 448fee884edSDaniel Vetter * ibx_display_interrupt_update - update SDEIMR 449fee884edSDaniel Vetter * @dev_priv: driver private 450fee884edSDaniel Vetter * @interrupt_mask: mask of interrupt bits to update 451fee884edSDaniel Vetter * @enabled_irq_mask: mask of interrupt bits to enable 452fee884edSDaniel Vetter */ 45347339cd9SDaniel Vetter void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, 454a9c287c9SJani Nikula u32 interrupt_mask, 455a9c287c9SJani Nikula u32 enabled_irq_mask) 456fee884edSDaniel Vetter { 4572939eb06SJani Nikula u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR); 458fee884edSDaniel Vetter sdeimr &= ~interrupt_mask; 459fee884edSDaniel Vetter sdeimr |= (~enabled_irq_mask & interrupt_mask); 460fee884edSDaniel Vetter 46148a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask); 46215a17aaeSDaniel Vetter 46367520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 464fee884edSDaniel Vetter 46548a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) 466c67a470bSPaulo Zanoni return; 467c67a470bSPaulo Zanoni 4682939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr); 4692939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, SDEIMR); 470fee884edSDaniel Vetter } 4718664281bSPaulo Zanoni 4726b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, 4736b12ca56SVille Syrjälä enum pipe pipe) 4747c463586SKeith Packard { 4756b12ca56SVille Syrjälä u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; 47610c59c51SImre Deak u32 enable_mask = status_mask << 16; 47710c59c51SImre Deak 4786b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 4796b12ca56SVille Syrjälä 4806b12ca56SVille Syrjälä if (INTEL_GEN(dev_priv) < 5) 4816b12ca56SVille Syrjälä goto out; 4826b12ca56SVille Syrjälä 48310c59c51SImre Deak /* 484724a6905SVille Syrjälä * On pipe A we don't support the PSR interrupt yet, 485724a6905SVille Syrjälä * on pipe B and C the same bit MBZ. 48610c59c51SImre Deak */ 48748a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 48848a1b8d4SPankaj Bharadiya status_mask & PIPE_A_PSR_STATUS_VLV)) 48910c59c51SImre Deak return 0; 490724a6905SVille Syrjälä /* 491724a6905SVille Syrjälä * On pipe B and C we don't support the PSR interrupt yet, on pipe 492724a6905SVille Syrjälä * A the same bit is for perf counters which we don't use either. 493724a6905SVille Syrjälä */ 49448a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 49548a1b8d4SPankaj Bharadiya status_mask & PIPE_B_PSR_STATUS_VLV)) 496724a6905SVille Syrjälä return 0; 49710c59c51SImre Deak 49810c59c51SImre Deak enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS | 49910c59c51SImre Deak SPRITE0_FLIP_DONE_INT_EN_VLV | 50010c59c51SImre Deak SPRITE1_FLIP_DONE_INT_EN_VLV); 50110c59c51SImre Deak if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV) 50210c59c51SImre Deak enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV; 50310c59c51SImre Deak if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) 50410c59c51SImre Deak enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; 50510c59c51SImre Deak 5066b12ca56SVille Syrjälä out: 50748a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 50848a1b8d4SPankaj Bharadiya enable_mask & ~PIPESTAT_INT_ENABLE_MASK || 5096b12ca56SVille Syrjälä status_mask & ~PIPESTAT_INT_STATUS_MASK, 5106b12ca56SVille Syrjälä "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", 5116b12ca56SVille Syrjälä pipe_name(pipe), enable_mask, status_mask); 5126b12ca56SVille Syrjälä 51310c59c51SImre Deak return enable_mask; 51410c59c51SImre Deak } 51510c59c51SImre Deak 5166b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv, 5176b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 518755e9019SImre Deak { 5196b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 520755e9019SImre Deak u32 enable_mask; 521755e9019SImre Deak 52248a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5236b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5246b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5256b12ca56SVille Syrjälä 5266b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 52748a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5286b12ca56SVille Syrjälä 5296b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) 5306b12ca56SVille Syrjälä return; 5316b12ca56SVille Syrjälä 5326b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] |= status_mask; 5336b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5346b12ca56SVille Syrjälä 5352939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5362939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 537755e9019SImre Deak } 538755e9019SImre Deak 5396b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv, 5406b12ca56SVille Syrjälä enum pipe pipe, u32 status_mask) 541755e9019SImre Deak { 5426b12ca56SVille Syrjälä i915_reg_t reg = PIPESTAT(pipe); 543755e9019SImre Deak u32 enable_mask; 544755e9019SImre Deak 54548a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK, 5466b12ca56SVille Syrjälä "pipe %c: status_mask=0x%x\n", 5476b12ca56SVille Syrjälä pipe_name(pipe), status_mask); 5486b12ca56SVille Syrjälä 5496b12ca56SVille Syrjälä lockdep_assert_held(&dev_priv->irq_lock); 55048a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); 5516b12ca56SVille Syrjälä 5526b12ca56SVille Syrjälä if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) 5536b12ca56SVille Syrjälä return; 5546b12ca56SVille Syrjälä 5556b12ca56SVille Syrjälä dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; 5566b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 5576b12ca56SVille Syrjälä 5582939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); 5592939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 560755e9019SImre Deak } 561755e9019SImre Deak 562f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv) 563f3e30485SVille Syrjälä { 564f3e30485SVille Syrjälä if (!dev_priv->opregion.asle) 565f3e30485SVille Syrjälä return false; 566f3e30485SVille Syrjälä 567f3e30485SVille Syrjälä return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv); 568f3e30485SVille Syrjälä } 569f3e30485SVille Syrjälä 570c0e09200SDave Airlie /** 571f49e38ddSJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion 57214bb2c11STvrtko Ursulin * @dev_priv: i915 device private 57301c66889SZhao Yakui */ 57491d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) 57501c66889SZhao Yakui { 576f3e30485SVille Syrjälä if (!i915_has_asle(dev_priv)) 577f49e38ddSJani Nikula return; 578f49e38ddSJani Nikula 57913321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 58001c66889SZhao Yakui 581755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS); 58291d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 4) 5833b6c42e8SDaniel Vetter i915_enable_pipestat(dev_priv, PIPE_A, 584755e9019SImre Deak PIPE_LEGACY_BLC_EVENT_STATUS); 5851ec14ad3SChris Wilson 58613321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 58701c66889SZhao Yakui } 58801c66889SZhao Yakui 589f75f3746SVille Syrjälä /* 590f75f3746SVille Syrjälä * This timing diagram depicts the video signal in and 591f75f3746SVille Syrjälä * around the vertical blanking period. 592f75f3746SVille Syrjälä * 593f75f3746SVille Syrjälä * Assumptions about the fictitious mode used in this example: 594f75f3746SVille Syrjälä * vblank_start >= 3 595f75f3746SVille Syrjälä * vsync_start = vblank_start + 1 596f75f3746SVille Syrjälä * vsync_end = vblank_start + 2 597f75f3746SVille Syrjälä * vtotal = vblank_start + 3 598f75f3746SVille Syrjälä * 599f75f3746SVille Syrjälä * start of vblank: 600f75f3746SVille Syrjälä * latch double buffered registers 601f75f3746SVille Syrjälä * increment frame counter (ctg+) 602f75f3746SVille Syrjälä * generate start of vblank interrupt (gen4+) 603f75f3746SVille Syrjälä * | 604f75f3746SVille Syrjälä * | frame start: 605f75f3746SVille Syrjälä * | generate frame start interrupt (aka. vblank interrupt) (gmch) 606f75f3746SVille Syrjälä * | may be shifted forward 1-3 extra lines via PIPECONF 607f75f3746SVille Syrjälä * | | 608f75f3746SVille Syrjälä * | | start of vsync: 609f75f3746SVille Syrjälä * | | generate vsync interrupt 610f75f3746SVille Syrjälä * | | | 611f75f3746SVille Syrjälä * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx 612f75f3746SVille Syrjälä * . \hs/ . \hs/ \hs/ \hs/ . \hs/ 613f75f3746SVille Syrjälä * ----va---> <-----------------vb--------------------> <--------va------------- 614f75f3746SVille Syrjälä * | | <----vs-----> | 615f75f3746SVille Syrjälä * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) 616f75f3746SVille Syrjälä * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) 617f75f3746SVille Syrjälä * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) 618f75f3746SVille Syrjälä * | | | 619f75f3746SVille Syrjälä * last visible pixel first visible pixel 620f75f3746SVille Syrjälä * | increment frame counter (gen3/4) 621f75f3746SVille Syrjälä * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) 622f75f3746SVille Syrjälä * 623f75f3746SVille Syrjälä * x = horizontal active 624f75f3746SVille Syrjälä * _ = horizontal blanking 625f75f3746SVille Syrjälä * hs = horizontal sync 626f75f3746SVille Syrjälä * va = vertical active 627f75f3746SVille Syrjälä * vb = vertical blanking 628f75f3746SVille Syrjälä * vs = vertical sync 629f75f3746SVille Syrjälä * vbs = vblank_start (number) 630f75f3746SVille Syrjälä * 631f75f3746SVille Syrjälä * Summary: 632f75f3746SVille Syrjälä * - most events happen at the start of horizontal sync 633f75f3746SVille Syrjälä * - frame start happens at the start of horizontal blank, 1-4 lines 634f75f3746SVille Syrjälä * (depending on PIPECONF settings) after the start of vblank 635f75f3746SVille Syrjälä * - gen3/4 pixel and frame counter are synchronized with the start 636f75f3746SVille Syrjälä * of horizontal active on the first line of vertical active 637f75f3746SVille Syrjälä */ 638f75f3746SVille Syrjälä 63942f52ef8SKeith Packard /* Called from drm generic code, passed a 'crtc', which 64042f52ef8SKeith Packard * we use as a pipe index 64142f52ef8SKeith Packard */ 64208fa8fd0SVille Syrjälä u32 i915_get_vblank_counter(struct drm_crtc *crtc) 6430a3e67a4SJesse Barnes { 64408fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 64508fa8fd0SVille Syrjälä struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; 64632db0b65SVille Syrjälä const struct drm_display_mode *mode = &vblank->hwmode; 64708fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 648f0f59a00SVille Syrjälä i915_reg_t high_frame, low_frame; 6490b2a8e09SVille Syrjälä u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; 650694e409dSVille Syrjälä unsigned long irqflags; 651391f75e2SVille Syrjälä 65232db0b65SVille Syrjälä /* 65332db0b65SVille Syrjälä * On i965gm TV output the frame counter only works up to 65432db0b65SVille Syrjälä * the point when we enable the TV encoder. After that the 65532db0b65SVille Syrjälä * frame counter ceases to work and reads zero. We need a 65632db0b65SVille Syrjälä * vblank wait before enabling the TV encoder and so we 65732db0b65SVille Syrjälä * have to enable vblank interrupts while the frame counter 65832db0b65SVille Syrjälä * is still in a working state. However the core vblank code 65932db0b65SVille Syrjälä * does not like us returning non-zero frame counter values 66032db0b65SVille Syrjälä * when we've told it that we don't have a working frame 66132db0b65SVille Syrjälä * counter. Thus we must stop non-zero values leaking out. 66232db0b65SVille Syrjälä */ 66332db0b65SVille Syrjälä if (!vblank->max_vblank_count) 66432db0b65SVille Syrjälä return 0; 66532db0b65SVille Syrjälä 6660b2a8e09SVille Syrjälä htotal = mode->crtc_htotal; 6670b2a8e09SVille Syrjälä hsync_start = mode->crtc_hsync_start; 6680b2a8e09SVille Syrjälä vbl_start = mode->crtc_vblank_start; 6690b2a8e09SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 6700b2a8e09SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 671391f75e2SVille Syrjälä 6720b2a8e09SVille Syrjälä /* Convert to pixel count */ 6730b2a8e09SVille Syrjälä vbl_start *= htotal; 6740b2a8e09SVille Syrjälä 6750b2a8e09SVille Syrjälä /* Start of vblank event occurs at start of hsync */ 6760b2a8e09SVille Syrjälä vbl_start -= htotal - hsync_start; 6770b2a8e09SVille Syrjälä 6789db4a9c7SJesse Barnes high_frame = PIPEFRAME(pipe); 6799db4a9c7SJesse Barnes low_frame = PIPEFRAMEPIXEL(pipe); 6805eddb70bSChris Wilson 681694e409dSVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 682694e409dSVille Syrjälä 6830a3e67a4SJesse Barnes /* 6840a3e67a4SJesse Barnes * High & low register fields aren't synchronized, so make sure 6850a3e67a4SJesse Barnes * we get a low value that's stable across two reads of the high 6860a3e67a4SJesse Barnes * register. 6870a3e67a4SJesse Barnes */ 6880a3e67a4SJesse Barnes do { 6898cbda6b2SJani Nikula high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; 6908cbda6b2SJani Nikula low = intel_de_read_fw(dev_priv, low_frame); 6918cbda6b2SJani Nikula high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; 6920a3e67a4SJesse Barnes } while (high1 != high2); 6930a3e67a4SJesse Barnes 694694e409dSVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 695694e409dSVille Syrjälä 6965eddb70bSChris Wilson high1 >>= PIPE_FRAME_HIGH_SHIFT; 697391f75e2SVille Syrjälä pixel = low & PIPE_PIXEL_MASK; 6985eddb70bSChris Wilson low >>= PIPE_FRAME_LOW_SHIFT; 699391f75e2SVille Syrjälä 700391f75e2SVille Syrjälä /* 701391f75e2SVille Syrjälä * The frame counter increments at beginning of active. 702391f75e2SVille Syrjälä * Cook up a vblank counter by also checking the pixel 703391f75e2SVille Syrjälä * counter against vblank start. 704391f75e2SVille Syrjälä */ 705edc08d0aSVille Syrjälä return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; 7060a3e67a4SJesse Barnes } 7070a3e67a4SJesse Barnes 70808fa8fd0SVille Syrjälä u32 g4x_get_vblank_counter(struct drm_crtc *crtc) 7099880b7a5SJesse Barnes { 71008fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 71133267703SVandita Kulkarni struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; 71208fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 7139880b7a5SJesse Barnes 71433267703SVandita Kulkarni if (!vblank->max_vblank_count) 71533267703SVandita Kulkarni return 0; 71633267703SVandita Kulkarni 7172939eb06SJani Nikula return intel_uncore_read(&dev_priv->uncore, PIPE_FRMCOUNT_G4X(pipe)); 7189880b7a5SJesse Barnes } 7199880b7a5SJesse Barnes 72006d6fda5SVille Syrjälä static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) 721aec0246fSUma Shankar { 722aec0246fSUma Shankar struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 723aec0246fSUma Shankar struct drm_vblank_crtc *vblank = 724aec0246fSUma Shankar &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 725aec0246fSUma Shankar const struct drm_display_mode *mode = &vblank->hwmode; 726aec0246fSUma Shankar u32 htotal = mode->crtc_htotal; 727aec0246fSUma Shankar u32 clock = mode->crtc_clock; 72806d6fda5SVille Syrjälä u32 scan_prev_time, scan_curr_time, scan_post_time; 729aec0246fSUma Shankar 730aec0246fSUma Shankar /* 731aec0246fSUma Shankar * To avoid the race condition where we might cross into the 732aec0246fSUma Shankar * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR 733aec0246fSUma Shankar * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR 734aec0246fSUma Shankar * during the same frame. 735aec0246fSUma Shankar */ 736aec0246fSUma Shankar do { 737aec0246fSUma Shankar /* 738aec0246fSUma Shankar * This field provides read back of the display 739aec0246fSUma Shankar * pipe frame time stamp. The time stamp value 740aec0246fSUma Shankar * is sampled at every start of vertical blank. 741aec0246fSUma Shankar */ 7428cbda6b2SJani Nikula scan_prev_time = intel_de_read_fw(dev_priv, 7438cbda6b2SJani Nikula PIPE_FRMTMSTMP(crtc->pipe)); 744aec0246fSUma Shankar 745aec0246fSUma Shankar /* 746aec0246fSUma Shankar * The TIMESTAMP_CTR register has the current 747aec0246fSUma Shankar * time stamp value. 748aec0246fSUma Shankar */ 7498cbda6b2SJani Nikula scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); 750aec0246fSUma Shankar 7518cbda6b2SJani Nikula scan_post_time = intel_de_read_fw(dev_priv, 7528cbda6b2SJani Nikula PIPE_FRMTMSTMP(crtc->pipe)); 753aec0246fSUma Shankar } while (scan_post_time != scan_prev_time); 754aec0246fSUma Shankar 75506d6fda5SVille Syrjälä return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, 756aec0246fSUma Shankar clock), 1000 * htotal); 75706d6fda5SVille Syrjälä } 75806d6fda5SVille Syrjälä 75906d6fda5SVille Syrjälä /* 76006d6fda5SVille Syrjälä * On certain encoders on certain platforms, pipe 76106d6fda5SVille Syrjälä * scanline register will not work to get the scanline, 76206d6fda5SVille Syrjälä * since the timings are driven from the PORT or issues 76306d6fda5SVille Syrjälä * with scanline register updates. 76406d6fda5SVille Syrjälä * This function will use Framestamp and current 76506d6fda5SVille Syrjälä * timestamp registers to calculate the scanline. 76606d6fda5SVille Syrjälä */ 76706d6fda5SVille Syrjälä static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) 76806d6fda5SVille Syrjälä { 76906d6fda5SVille Syrjälä struct drm_vblank_crtc *vblank = 77006d6fda5SVille Syrjälä &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 77106d6fda5SVille Syrjälä const struct drm_display_mode *mode = &vblank->hwmode; 77206d6fda5SVille Syrjälä u32 vblank_start = mode->crtc_vblank_start; 77306d6fda5SVille Syrjälä u32 vtotal = mode->crtc_vtotal; 77406d6fda5SVille Syrjälä u32 scanline; 77506d6fda5SVille Syrjälä 77606d6fda5SVille Syrjälä scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); 777aec0246fSUma Shankar scanline = min(scanline, vtotal - 1); 778aec0246fSUma Shankar scanline = (scanline + vblank_start) % vtotal; 779aec0246fSUma Shankar 780aec0246fSUma Shankar return scanline; 781aec0246fSUma Shankar } 782aec0246fSUma Shankar 7838cbda6b2SJani Nikula /* 7848cbda6b2SJani Nikula * intel_de_read_fw(), only for fast reads of display block, no need for 7858cbda6b2SJani Nikula * forcewake etc. 7868cbda6b2SJani Nikula */ 787a225f079SVille Syrjälä static int __intel_get_crtc_scanline(struct intel_crtc *crtc) 788a225f079SVille Syrjälä { 789a225f079SVille Syrjälä struct drm_device *dev = crtc->base.dev; 790fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 7915caa0feaSDaniel Vetter const struct drm_display_mode *mode; 7925caa0feaSDaniel Vetter struct drm_vblank_crtc *vblank; 793a225f079SVille Syrjälä enum pipe pipe = crtc->pipe; 79480715b2fSVille Syrjälä int position, vtotal; 795a225f079SVille Syrjälä 79672259536SVille Syrjälä if (!crtc->active) 79772259536SVille Syrjälä return -1; 79872259536SVille Syrjälä 7995caa0feaSDaniel Vetter vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; 8005caa0feaSDaniel Vetter mode = &vblank->hwmode; 8015caa0feaSDaniel Vetter 802af157b76SVille Syrjälä if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) 803aec0246fSUma Shankar return __intel_get_crtc_scanline_from_timestamp(crtc); 804aec0246fSUma Shankar 80580715b2fSVille Syrjälä vtotal = mode->crtc_vtotal; 806a225f079SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) 807a225f079SVille Syrjälä vtotal /= 2; 808a225f079SVille Syrjälä 809cf819effSLucas De Marchi if (IS_GEN(dev_priv, 2)) 8108cbda6b2SJani Nikula position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; 811a225f079SVille Syrjälä else 8128cbda6b2SJani Nikula position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 813a225f079SVille Syrjälä 814a225f079SVille Syrjälä /* 81541b578fbSJesse Barnes * On HSW, the DSL reg (0x70000) appears to return 0 if we 81641b578fbSJesse Barnes * read it just before the start of vblank. So try it again 81741b578fbSJesse Barnes * so we don't accidentally end up spanning a vblank frame 81841b578fbSJesse Barnes * increment, causing the pipe_update_end() code to squak at us. 81941b578fbSJesse Barnes * 82041b578fbSJesse Barnes * The nature of this problem means we can't simply check the ISR 82141b578fbSJesse Barnes * bit and return the vblank start value; nor can we use the scanline 82241b578fbSJesse Barnes * debug register in the transcoder as it appears to have the same 82341b578fbSJesse Barnes * problem. We may need to extend this to include other platforms, 82441b578fbSJesse Barnes * but so far testing only shows the problem on HSW. 82541b578fbSJesse Barnes */ 82691d14251STvrtko Ursulin if (HAS_DDI(dev_priv) && !position) { 82741b578fbSJesse Barnes int i, temp; 82841b578fbSJesse Barnes 82941b578fbSJesse Barnes for (i = 0; i < 100; i++) { 83041b578fbSJesse Barnes udelay(1); 8318cbda6b2SJani Nikula temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 83241b578fbSJesse Barnes if (temp != position) { 83341b578fbSJesse Barnes position = temp; 83441b578fbSJesse Barnes break; 83541b578fbSJesse Barnes } 83641b578fbSJesse Barnes } 83741b578fbSJesse Barnes } 83841b578fbSJesse Barnes 83941b578fbSJesse Barnes /* 84080715b2fSVille Syrjälä * See update_scanline_offset() for the details on the 84180715b2fSVille Syrjälä * scanline_offset adjustment. 842a225f079SVille Syrjälä */ 84380715b2fSVille Syrjälä return (position + crtc->scanline_offset) % vtotal; 844a225f079SVille Syrjälä } 845a225f079SVille Syrjälä 8464bbffbf3SThomas Zimmermann static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, 8474bbffbf3SThomas Zimmermann bool in_vblank_irq, 8484bbffbf3SThomas Zimmermann int *vpos, int *hpos, 8493bb403bfSVille Syrjälä ktime_t *stime, ktime_t *etime, 8503bb403bfSVille Syrjälä const struct drm_display_mode *mode) 8510af7e4dfSMario Kleiner { 8524bbffbf3SThomas Zimmermann struct drm_device *dev = _crtc->dev; 853fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(dev); 8544bbffbf3SThomas Zimmermann struct intel_crtc *crtc = to_intel_crtc(_crtc); 855e8edae54SVille Syrjälä enum pipe pipe = crtc->pipe; 8563aa18df8SVille Syrjälä int position; 85778e8fc6bSVille Syrjälä int vbl_start, vbl_end, hsync_start, htotal, vtotal; 858ad3543edSMario Kleiner unsigned long irqflags; 8598a920e24SVille Syrjälä bool use_scanline_counter = INTEL_GEN(dev_priv) >= 5 || 8608a920e24SVille Syrjälä IS_G4X(dev_priv) || IS_GEN(dev_priv, 2) || 861af157b76SVille Syrjälä crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; 8620af7e4dfSMario Kleiner 86348a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { 86400376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 86500376ccfSWambui Karuga "trying to get scanoutpos for disabled " 8669db4a9c7SJesse Barnes "pipe %c\n", pipe_name(pipe)); 8671bf6ad62SDaniel Vetter return false; 8680af7e4dfSMario Kleiner } 8690af7e4dfSMario Kleiner 870c2baf4b7SVille Syrjälä htotal = mode->crtc_htotal; 87178e8fc6bSVille Syrjälä hsync_start = mode->crtc_hsync_start; 872c2baf4b7SVille Syrjälä vtotal = mode->crtc_vtotal; 873c2baf4b7SVille Syrjälä vbl_start = mode->crtc_vblank_start; 874c2baf4b7SVille Syrjälä vbl_end = mode->crtc_vblank_end; 8750af7e4dfSMario Kleiner 876d31faf65SVille Syrjälä if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 877d31faf65SVille Syrjälä vbl_start = DIV_ROUND_UP(vbl_start, 2); 878d31faf65SVille Syrjälä vbl_end /= 2; 879d31faf65SVille Syrjälä vtotal /= 2; 880d31faf65SVille Syrjälä } 881d31faf65SVille Syrjälä 882ad3543edSMario Kleiner /* 883ad3543edSMario Kleiner * Lock uncore.lock, as we will do multiple timing critical raw 884ad3543edSMario Kleiner * register reads, potentially with preemption disabled, so the 885ad3543edSMario Kleiner * following code must not block on uncore.lock. 886ad3543edSMario Kleiner */ 887ad3543edSMario Kleiner spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 888ad3543edSMario Kleiner 889ad3543edSMario Kleiner /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ 890ad3543edSMario Kleiner 891ad3543edSMario Kleiner /* Get optional system timestamp before query. */ 892ad3543edSMario Kleiner if (stime) 893ad3543edSMario Kleiner *stime = ktime_get(); 894ad3543edSMario Kleiner 8957a2ec4a0SVille Syrjälä if (crtc->mode_flags & I915_MODE_FLAG_VRR) { 8967a2ec4a0SVille Syrjälä int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); 8977a2ec4a0SVille Syrjälä 8987a2ec4a0SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 8997a2ec4a0SVille Syrjälä 9007a2ec4a0SVille Syrjälä /* 9017a2ec4a0SVille Syrjälä * Already exiting vblank? If so, shift our position 9027a2ec4a0SVille Syrjälä * so it looks like we're already apporaching the full 9037a2ec4a0SVille Syrjälä * vblank end. This should make the generated timestamp 9047a2ec4a0SVille Syrjälä * more or less match when the active portion will start. 9057a2ec4a0SVille Syrjälä */ 9067a2ec4a0SVille Syrjälä if (position >= vbl_start && scanlines < position) 9077a2ec4a0SVille Syrjälä position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); 9087a2ec4a0SVille Syrjälä } else if (use_scanline_counter) { 9090af7e4dfSMario Kleiner /* No obvious pixelcount register. Only query vertical 9100af7e4dfSMario Kleiner * scanout position from Display scan line register. 9110af7e4dfSMario Kleiner */ 912e8edae54SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 9130af7e4dfSMario Kleiner } else { 9140af7e4dfSMario Kleiner /* Have access to pixelcount since start of frame. 9150af7e4dfSMario Kleiner * We can split this into vertical and horizontal 9160af7e4dfSMario Kleiner * scanout position. 9170af7e4dfSMario Kleiner */ 9188cbda6b2SJani Nikula position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; 9190af7e4dfSMario Kleiner 9203aa18df8SVille Syrjälä /* convert to pixel counts */ 9213aa18df8SVille Syrjälä vbl_start *= htotal; 9223aa18df8SVille Syrjälä vbl_end *= htotal; 9233aa18df8SVille Syrjälä vtotal *= htotal; 92478e8fc6bSVille Syrjälä 92578e8fc6bSVille Syrjälä /* 9267e78f1cbSVille Syrjälä * In interlaced modes, the pixel counter counts all pixels, 9277e78f1cbSVille Syrjälä * so one field will have htotal more pixels. In order to avoid 9287e78f1cbSVille Syrjälä * the reported position from jumping backwards when the pixel 9297e78f1cbSVille Syrjälä * counter is beyond the length of the shorter field, just 9307e78f1cbSVille Syrjälä * clamp the position the length of the shorter field. This 9317e78f1cbSVille Syrjälä * matches how the scanline counter based position works since 9327e78f1cbSVille Syrjälä * the scanline counter doesn't count the two half lines. 9337e78f1cbSVille Syrjälä */ 9347e78f1cbSVille Syrjälä if (position >= vtotal) 9357e78f1cbSVille Syrjälä position = vtotal - 1; 9367e78f1cbSVille Syrjälä 9377e78f1cbSVille Syrjälä /* 93878e8fc6bSVille Syrjälä * Start of vblank interrupt is triggered at start of hsync, 93978e8fc6bSVille Syrjälä * just prior to the first active line of vblank. However we 94078e8fc6bSVille Syrjälä * consider lines to start at the leading edge of horizontal 94178e8fc6bSVille Syrjälä * active. So, should we get here before we've crossed into 94278e8fc6bSVille Syrjälä * the horizontal active of the first line in vblank, we would 94378e8fc6bSVille Syrjälä * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, 94478e8fc6bSVille Syrjälä * always add htotal-hsync_start to the current pixel position. 94578e8fc6bSVille Syrjälä */ 94678e8fc6bSVille Syrjälä position = (position + htotal - hsync_start) % vtotal; 9473aa18df8SVille Syrjälä } 9483aa18df8SVille Syrjälä 949ad3543edSMario Kleiner /* Get optional system timestamp after query. */ 950ad3543edSMario Kleiner if (etime) 951ad3543edSMario Kleiner *etime = ktime_get(); 952ad3543edSMario Kleiner 953ad3543edSMario Kleiner /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ 954ad3543edSMario Kleiner 955ad3543edSMario Kleiner spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 956ad3543edSMario Kleiner 9573aa18df8SVille Syrjälä /* 9583aa18df8SVille Syrjälä * While in vblank, position will be negative 9593aa18df8SVille Syrjälä * counting up towards 0 at vbl_end. And outside 9603aa18df8SVille Syrjälä * vblank, position will be positive counting 9613aa18df8SVille Syrjälä * up since vbl_end. 9623aa18df8SVille Syrjälä */ 9633aa18df8SVille Syrjälä if (position >= vbl_start) 9643aa18df8SVille Syrjälä position -= vbl_end; 9653aa18df8SVille Syrjälä else 9663aa18df8SVille Syrjälä position += vtotal - vbl_end; 9673aa18df8SVille Syrjälä 9688a920e24SVille Syrjälä if (use_scanline_counter) { 9693aa18df8SVille Syrjälä *vpos = position; 9703aa18df8SVille Syrjälä *hpos = 0; 9713aa18df8SVille Syrjälä } else { 9720af7e4dfSMario Kleiner *vpos = position / htotal; 9730af7e4dfSMario Kleiner *hpos = position - (*vpos * htotal); 9740af7e4dfSMario Kleiner } 9750af7e4dfSMario Kleiner 9761bf6ad62SDaniel Vetter return true; 9770af7e4dfSMario Kleiner } 9780af7e4dfSMario Kleiner 9794bbffbf3SThomas Zimmermann bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, 9804bbffbf3SThomas Zimmermann ktime_t *vblank_time, bool in_vblank_irq) 9814bbffbf3SThomas Zimmermann { 9824bbffbf3SThomas Zimmermann return drm_crtc_vblank_helper_get_vblank_timestamp_internal( 9834bbffbf3SThomas Zimmermann crtc, max_error, vblank_time, in_vblank_irq, 98448e67807SThomas Zimmermann i915_get_crtc_scanoutpos); 9854bbffbf3SThomas Zimmermann } 9864bbffbf3SThomas Zimmermann 987a225f079SVille Syrjälä int intel_get_crtc_scanline(struct intel_crtc *crtc) 988a225f079SVille Syrjälä { 989fac5e23eSChris Wilson struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 990a225f079SVille Syrjälä unsigned long irqflags; 991a225f079SVille Syrjälä int position; 992a225f079SVille Syrjälä 993a225f079SVille Syrjälä spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 994a225f079SVille Syrjälä position = __intel_get_crtc_scanline(crtc); 995a225f079SVille Syrjälä spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 996a225f079SVille Syrjälä 997a225f079SVille Syrjälä return position; 998a225f079SVille Syrjälä } 999a225f079SVille Syrjälä 1000e3689190SBen Widawsky /** 100174bb98baSLucas De Marchi * ivb_parity_work - Workqueue called when a parity error interrupt 1002e3689190SBen Widawsky * occurred. 1003e3689190SBen Widawsky * @work: workqueue struct 1004e3689190SBen Widawsky * 1005e3689190SBen Widawsky * Doesn't actually do anything except notify userspace. As a consequence of 1006e3689190SBen Widawsky * this event, userspace should try to remap the bad rows since statistically 1007e3689190SBen Widawsky * it is likely the same row is more likely to go bad again. 1008e3689190SBen Widawsky */ 100974bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work) 1010e3689190SBen Widawsky { 10112d1013ddSJani Nikula struct drm_i915_private *dev_priv = 1012cefcff8fSJoonas Lahtinen container_of(work, typeof(*dev_priv), l3_parity.error_work); 1013cf1c97dcSAndi Shyti struct intel_gt *gt = &dev_priv->gt; 1014e3689190SBen Widawsky u32 error_status, row, bank, subbank; 101535a85ac6SBen Widawsky char *parity_event[6]; 1016a9c287c9SJani Nikula u32 misccpctl; 1017a9c287c9SJani Nikula u8 slice = 0; 1018e3689190SBen Widawsky 1019e3689190SBen Widawsky /* We must turn off DOP level clock gating to access the L3 registers. 1020e3689190SBen Widawsky * In order to prevent a get/put style interface, acquire struct mutex 1021e3689190SBen Widawsky * any time we access those registers. 1022e3689190SBen Widawsky */ 102391c8a326SChris Wilson mutex_lock(&dev_priv->drm.struct_mutex); 1024e3689190SBen Widawsky 102535a85ac6SBen Widawsky /* If we've screwed up tracking, just let the interrupt fire again */ 102648a1b8d4SPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice)) 102735a85ac6SBen Widawsky goto out; 102835a85ac6SBen Widawsky 10292939eb06SJani Nikula misccpctl = intel_uncore_read(&dev_priv->uncore, GEN7_MISCCPCTL); 10302939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); 10312939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL); 1032e3689190SBen Widawsky 103335a85ac6SBen Widawsky while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { 1034f0f59a00SVille Syrjälä i915_reg_t reg; 103535a85ac6SBen Widawsky 103635a85ac6SBen Widawsky slice--; 103748a1b8d4SPankaj Bharadiya if (drm_WARN_ON_ONCE(&dev_priv->drm, 103848a1b8d4SPankaj Bharadiya slice >= NUM_L3_SLICES(dev_priv))) 103935a85ac6SBen Widawsky break; 104035a85ac6SBen Widawsky 104135a85ac6SBen Widawsky dev_priv->l3_parity.which_slice &= ~(1<<slice); 104235a85ac6SBen Widawsky 10436fa1c5f1SVille Syrjälä reg = GEN7_L3CDERRST1(slice); 104435a85ac6SBen Widawsky 10452939eb06SJani Nikula error_status = intel_uncore_read(&dev_priv->uncore, reg); 1046e3689190SBen Widawsky row = GEN7_PARITY_ERROR_ROW(error_status); 1047e3689190SBen Widawsky bank = GEN7_PARITY_ERROR_BANK(error_status); 1048e3689190SBen Widawsky subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); 1049e3689190SBen Widawsky 10502939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); 10512939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg); 1052e3689190SBen Widawsky 1053cce723edSBen Widawsky parity_event[0] = I915_L3_PARITY_UEVENT "=1"; 1054e3689190SBen Widawsky parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); 1055e3689190SBen Widawsky parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); 1056e3689190SBen Widawsky parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); 105735a85ac6SBen Widawsky parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); 105835a85ac6SBen Widawsky parity_event[5] = NULL; 1059e3689190SBen Widawsky 106091c8a326SChris Wilson kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj, 1061e3689190SBen Widawsky KOBJ_CHANGE, parity_event); 1062e3689190SBen Widawsky 106335a85ac6SBen Widawsky DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", 106435a85ac6SBen Widawsky slice, row, bank, subbank); 1065e3689190SBen Widawsky 106635a85ac6SBen Widawsky kfree(parity_event[4]); 1067e3689190SBen Widawsky kfree(parity_event[3]); 1068e3689190SBen Widawsky kfree(parity_event[2]); 1069e3689190SBen Widawsky kfree(parity_event[1]); 1070e3689190SBen Widawsky } 1071e3689190SBen Widawsky 10722939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl); 107335a85ac6SBen Widawsky 107435a85ac6SBen Widawsky out: 107548a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice); 1076cf1c97dcSAndi Shyti spin_lock_irq(>->irq_lock); 1077cf1c97dcSAndi Shyti gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv)); 1078cf1c97dcSAndi Shyti spin_unlock_irq(>->irq_lock); 107935a85ac6SBen Widawsky 108091c8a326SChris Wilson mutex_unlock(&dev_priv->drm.struct_mutex); 108135a85ac6SBen Widawsky } 108235a85ac6SBen Widawsky 1083af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1084121e758eSDhinakaran Pandiyan { 1085af92058fSVille Syrjälä switch (pin) { 1086da51e4baSVille Syrjälä case HPD_PORT_TC1: 1087da51e4baSVille Syrjälä case HPD_PORT_TC2: 1088da51e4baSVille Syrjälä case HPD_PORT_TC3: 1089da51e4baSVille Syrjälä case HPD_PORT_TC4: 1090da51e4baSVille Syrjälä case HPD_PORT_TC5: 1091da51e4baSVille Syrjälä case HPD_PORT_TC6: 10924294fa5fSVille Syrjälä return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin); 109348ef15d3SJosé Roberto de Souza default: 109448ef15d3SJosé Roberto de Souza return false; 109548ef15d3SJosé Roberto de Souza } 109648ef15d3SJosé Roberto de Souza } 109748ef15d3SJosé Roberto de Souza 1098af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 109963c88d22SImre Deak { 1100af92058fSVille Syrjälä switch (pin) { 1101af92058fSVille Syrjälä case HPD_PORT_A: 1102195baa06SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1103af92058fSVille Syrjälä case HPD_PORT_B: 110463c88d22SImre Deak return val & PORTB_HOTPLUG_LONG_DETECT; 1105af92058fSVille Syrjälä case HPD_PORT_C: 110663c88d22SImre Deak return val & PORTC_HOTPLUG_LONG_DETECT; 110763c88d22SImre Deak default: 110863c88d22SImre Deak return false; 110963c88d22SImre Deak } 111063c88d22SImre Deak } 111163c88d22SImre Deak 1112af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 111331604222SAnusha Srivatsa { 1114af92058fSVille Syrjälä switch (pin) { 1115af92058fSVille Syrjälä case HPD_PORT_A: 1116af92058fSVille Syrjälä case HPD_PORT_B: 11178ef7e340SMatt Roper case HPD_PORT_C: 1118229f31e2SLucas De Marchi case HPD_PORT_D: 11194294fa5fSVille Syrjälä return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin); 112031604222SAnusha Srivatsa default: 112131604222SAnusha Srivatsa return false; 112231604222SAnusha Srivatsa } 112331604222SAnusha Srivatsa } 112431604222SAnusha Srivatsa 1125af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 112631604222SAnusha Srivatsa { 1127af92058fSVille Syrjälä switch (pin) { 1128da51e4baSVille Syrjälä case HPD_PORT_TC1: 1129da51e4baSVille Syrjälä case HPD_PORT_TC2: 1130da51e4baSVille Syrjälä case HPD_PORT_TC3: 1131da51e4baSVille Syrjälä case HPD_PORT_TC4: 1132da51e4baSVille Syrjälä case HPD_PORT_TC5: 1133da51e4baSVille Syrjälä case HPD_PORT_TC6: 11344294fa5fSVille Syrjälä return val & ICP_TC_HPD_LONG_DETECT(pin); 113552dfdba0SLucas De Marchi default: 113652dfdba0SLucas De Marchi return false; 113752dfdba0SLucas De Marchi } 113852dfdba0SLucas De Marchi } 113952dfdba0SLucas De Marchi 1140af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) 11416dbf30ceSVille Syrjälä { 1142af92058fSVille Syrjälä switch (pin) { 1143af92058fSVille Syrjälä case HPD_PORT_E: 11446dbf30ceSVille Syrjälä return val & PORTE_HOTPLUG_LONG_DETECT; 11456dbf30ceSVille Syrjälä default: 11466dbf30ceSVille Syrjälä return false; 11476dbf30ceSVille Syrjälä } 11486dbf30ceSVille Syrjälä } 11496dbf30ceSVille Syrjälä 1150af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 115174c0b395SVille Syrjälä { 1152af92058fSVille Syrjälä switch (pin) { 1153af92058fSVille Syrjälä case HPD_PORT_A: 115474c0b395SVille Syrjälä return val & PORTA_HOTPLUG_LONG_DETECT; 1155af92058fSVille Syrjälä case HPD_PORT_B: 115674c0b395SVille Syrjälä return val & PORTB_HOTPLUG_LONG_DETECT; 1157af92058fSVille Syrjälä case HPD_PORT_C: 115874c0b395SVille Syrjälä return val & PORTC_HOTPLUG_LONG_DETECT; 1159af92058fSVille Syrjälä case HPD_PORT_D: 116074c0b395SVille Syrjälä return val & PORTD_HOTPLUG_LONG_DETECT; 116174c0b395SVille Syrjälä default: 116274c0b395SVille Syrjälä return false; 116374c0b395SVille Syrjälä } 116474c0b395SVille Syrjälä } 116574c0b395SVille Syrjälä 1166af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 1167e4ce95aaSVille Syrjälä { 1168af92058fSVille Syrjälä switch (pin) { 1169af92058fSVille Syrjälä case HPD_PORT_A: 1170e4ce95aaSVille Syrjälä return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; 1171e4ce95aaSVille Syrjälä default: 1172e4ce95aaSVille Syrjälä return false; 1173e4ce95aaSVille Syrjälä } 1174e4ce95aaSVille Syrjälä } 1175e4ce95aaSVille Syrjälä 1176af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 117713cf5504SDave Airlie { 1178af92058fSVille Syrjälä switch (pin) { 1179af92058fSVille Syrjälä case HPD_PORT_B: 1180676574dfSJani Nikula return val & PORTB_HOTPLUG_LONG_DETECT; 1181af92058fSVille Syrjälä case HPD_PORT_C: 1182676574dfSJani Nikula return val & PORTC_HOTPLUG_LONG_DETECT; 1183af92058fSVille Syrjälä case HPD_PORT_D: 1184676574dfSJani Nikula return val & PORTD_HOTPLUG_LONG_DETECT; 1185676574dfSJani Nikula default: 1186676574dfSJani Nikula return false; 118713cf5504SDave Airlie } 118813cf5504SDave Airlie } 118913cf5504SDave Airlie 1190af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) 119113cf5504SDave Airlie { 1192af92058fSVille Syrjälä switch (pin) { 1193af92058fSVille Syrjälä case HPD_PORT_B: 1194676574dfSJani Nikula return val & PORTB_HOTPLUG_INT_LONG_PULSE; 1195af92058fSVille Syrjälä case HPD_PORT_C: 1196676574dfSJani Nikula return val & PORTC_HOTPLUG_INT_LONG_PULSE; 1197af92058fSVille Syrjälä case HPD_PORT_D: 1198676574dfSJani Nikula return val & PORTD_HOTPLUG_INT_LONG_PULSE; 1199676574dfSJani Nikula default: 1200676574dfSJani Nikula return false; 120113cf5504SDave Airlie } 120213cf5504SDave Airlie } 120313cf5504SDave Airlie 120442db67d6SVille Syrjälä /* 120542db67d6SVille Syrjälä * Get a bit mask of pins that have triggered, and which ones may be long. 120642db67d6SVille Syrjälä * This can be called multiple times with the same masks to accumulate 120742db67d6SVille Syrjälä * hotplug detection results from several registers. 120842db67d6SVille Syrjälä * 120942db67d6SVille Syrjälä * Note that the caller is expected to zero out the masks initially. 121042db67d6SVille Syrjälä */ 1211cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, 1212cf53902fSRodrigo Vivi u32 *pin_mask, u32 *long_mask, 12138c841e57SJani Nikula u32 hotplug_trigger, u32 dig_hotplug_reg, 1214fd63e2a9SImre Deak const u32 hpd[HPD_NUM_PINS], 1215af92058fSVille Syrjälä bool long_pulse_detect(enum hpd_pin pin, u32 val)) 1216676574dfSJani Nikula { 1217e9be2850SVille Syrjälä enum hpd_pin pin; 1218676574dfSJani Nikula 121952dfdba0SLucas De Marchi BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS); 122052dfdba0SLucas De Marchi 1221e9be2850SVille Syrjälä for_each_hpd_pin(pin) { 1222e9be2850SVille Syrjälä if ((hpd[pin] & hotplug_trigger) == 0) 12238c841e57SJani Nikula continue; 12248c841e57SJani Nikula 1225e9be2850SVille Syrjälä *pin_mask |= BIT(pin); 1226676574dfSJani Nikula 1227af92058fSVille Syrjälä if (long_pulse_detect(pin, dig_hotplug_reg)) 1228e9be2850SVille Syrjälä *long_mask |= BIT(pin); 1229676574dfSJani Nikula } 1230676574dfSJani Nikula 123100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 123200376ccfSWambui Karuga "hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n", 1233f88f0478SVille Syrjälä hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); 1234676574dfSJani Nikula 1235676574dfSJani Nikula } 1236676574dfSJani Nikula 1237a0e066b8SVille Syrjälä static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, 1238a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 1239a0e066b8SVille Syrjälä { 1240a0e066b8SVille Syrjälä struct intel_encoder *encoder; 1241a0e066b8SVille Syrjälä u32 enabled_irqs = 0; 1242a0e066b8SVille Syrjälä 1243a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 1244a0e066b8SVille Syrjälä if (dev_priv->hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) 1245a0e066b8SVille Syrjälä enabled_irqs |= hpd[encoder->hpd_pin]; 1246a0e066b8SVille Syrjälä 1247a0e066b8SVille Syrjälä return enabled_irqs; 1248a0e066b8SVille Syrjälä } 1249a0e066b8SVille Syrjälä 1250a0e066b8SVille Syrjälä static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, 1251a0e066b8SVille Syrjälä const u32 hpd[HPD_NUM_PINS]) 1252a0e066b8SVille Syrjälä { 1253a0e066b8SVille Syrjälä struct intel_encoder *encoder; 1254a0e066b8SVille Syrjälä u32 hotplug_irqs = 0; 1255a0e066b8SVille Syrjälä 1256a0e066b8SVille Syrjälä for_each_intel_encoder(&dev_priv->drm, encoder) 1257a0e066b8SVille Syrjälä hotplug_irqs |= hpd[encoder->hpd_pin]; 1258a0e066b8SVille Syrjälä 1259a0e066b8SVille Syrjälä return hotplug_irqs; 1260a0e066b8SVille Syrjälä } 1261a0e066b8SVille Syrjälä 12622ea63927SVille Syrjälä static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915, 12632ea63927SVille Syrjälä hotplug_enables_func hotplug_enables) 12642ea63927SVille Syrjälä { 12652ea63927SVille Syrjälä struct intel_encoder *encoder; 12662ea63927SVille Syrjälä u32 hotplug = 0; 12672ea63927SVille Syrjälä 12682ea63927SVille Syrjälä for_each_intel_encoder(&i915->drm, encoder) 12692ea63927SVille Syrjälä hotplug |= hotplug_enables(i915, encoder->hpd_pin); 12702ea63927SVille Syrjälä 12712ea63927SVille Syrjälä return hotplug; 12722ea63927SVille Syrjälä } 12732ea63927SVille Syrjälä 127491d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv) 1275515ac2bbSDaniel Vetter { 127628c70f16SDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1277515ac2bbSDaniel Vetter } 1278515ac2bbSDaniel Vetter 127991d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv) 1280ce99c256SDaniel Vetter { 12819ee32feaSDaniel Vetter wake_up_all(&dev_priv->gmbus_wait_queue); 1282ce99c256SDaniel Vetter } 1283ce99c256SDaniel Vetter 12848bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS) 128591d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 128691d14251STvrtko Ursulin enum pipe pipe, 1287a9c287c9SJani Nikula u32 crc0, u32 crc1, 1288a9c287c9SJani Nikula u32 crc2, u32 crc3, 1289a9c287c9SJani Nikula u32 crc4) 12908bf1e9f1SShuang He { 12918c6b709dSTomeu Vizoso struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); 129200535527SJani Nikula struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc; 12935cee6c45SVille Syrjälä u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 }; 12945cee6c45SVille Syrjälä 12955cee6c45SVille Syrjälä trace_intel_pipe_crc(crtc, crcs); 1296b2c88f5bSDamien Lespiau 1297d538bbdfSDamien Lespiau spin_lock(&pipe_crc->lock); 12988c6b709dSTomeu Vizoso /* 12998c6b709dSTomeu Vizoso * For some not yet identified reason, the first CRC is 13008c6b709dSTomeu Vizoso * bonkers. So let's just wait for the next vblank and read 13018c6b709dSTomeu Vizoso * out the buggy result. 13028c6b709dSTomeu Vizoso * 1303163e8aecSRodrigo Vivi * On GEN8+ sometimes the second CRC is bonkers as well, so 13048c6b709dSTomeu Vizoso * don't trust that one either. 13058c6b709dSTomeu Vizoso */ 1306033b7a23SMaarten Lankhorst if (pipe_crc->skipped <= 0 || 1307163e8aecSRodrigo Vivi (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { 13088c6b709dSTomeu Vizoso pipe_crc->skipped++; 13098c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 13108c6b709dSTomeu Vizoso return; 13118c6b709dSTomeu Vizoso } 13128c6b709dSTomeu Vizoso spin_unlock(&pipe_crc->lock); 13136cc42152SMaarten Lankhorst 1314246ee524STomeu Vizoso drm_crtc_add_crc_entry(&crtc->base, true, 1315ca814b25SDaniel Vetter drm_crtc_accurate_vblank_count(&crtc->base), 1316246ee524STomeu Vizoso crcs); 13178c6b709dSTomeu Vizoso } 1318277de95eSDaniel Vetter #else 1319277de95eSDaniel Vetter static inline void 132091d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 132191d14251STvrtko Ursulin enum pipe pipe, 1322a9c287c9SJani Nikula u32 crc0, u32 crc1, 1323a9c287c9SJani Nikula u32 crc2, u32 crc3, 1324a9c287c9SJani Nikula u32 crc4) {} 1325277de95eSDaniel Vetter #endif 1326eba94eb9SDaniel Vetter 13271288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915, 13281288f9b0SKarthik B S enum pipe pipe) 13291288f9b0SKarthik B S { 13301288f9b0SKarthik B S struct intel_crtc *crtc = intel_get_crtc_for_pipe(i915, pipe); 13311288f9b0SKarthik B S struct drm_crtc_state *crtc_state = crtc->base.state; 13321288f9b0SKarthik B S struct drm_pending_vblank_event *e = crtc_state->event; 13331288f9b0SKarthik B S struct drm_device *dev = &i915->drm; 13341288f9b0SKarthik B S unsigned long irqflags; 13351288f9b0SKarthik B S 13361288f9b0SKarthik B S spin_lock_irqsave(&dev->event_lock, irqflags); 13371288f9b0SKarthik B S 13381288f9b0SKarthik B S crtc_state->event = NULL; 13391288f9b0SKarthik B S 13401288f9b0SKarthik B S drm_crtc_send_vblank_event(&crtc->base, e); 13411288f9b0SKarthik B S 13421288f9b0SKarthik B S spin_unlock_irqrestore(&dev->event_lock, irqflags); 13431288f9b0SKarthik B S } 1344277de95eSDaniel Vetter 134591d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 134691d14251STvrtko Ursulin enum pipe pipe) 13475a69b89fSDaniel Vetter { 134891d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 13492939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 13505a69b89fSDaniel Vetter 0, 0, 0, 0); 13515a69b89fSDaniel Vetter } 13525a69b89fSDaniel Vetter 135391d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 135491d14251STvrtko Ursulin enum pipe pipe) 1355eba94eb9SDaniel Vetter { 135691d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 13572939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)), 13582939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)), 13592939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)), 13602939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)), 13612939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe))); 1362eba94eb9SDaniel Vetter } 13635b3a856bSDaniel Vetter 136491d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, 136591d14251STvrtko Ursulin enum pipe pipe) 13665b3a856bSDaniel Vetter { 1367a9c287c9SJani Nikula u32 res1, res2; 13680b5c5ed0SDaniel Vetter 136991d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 3) 13702939eb06SJani Nikula res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe)); 13710b5c5ed0SDaniel Vetter else 13720b5c5ed0SDaniel Vetter res1 = 0; 13730b5c5ed0SDaniel Vetter 137491d14251STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) 13752939eb06SJani Nikula res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe)); 13760b5c5ed0SDaniel Vetter else 13770b5c5ed0SDaniel Vetter res2 = 0; 13785b3a856bSDaniel Vetter 137991d14251STvrtko Ursulin display_pipe_crc_irq_handler(dev_priv, pipe, 13802939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)), 13812939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)), 13822939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)), 13830b5c5ed0SDaniel Vetter res1, res2); 13845b3a856bSDaniel Vetter } 13858bf1e9f1SShuang He 138644d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) 138744d9241eSVille Syrjälä { 138844d9241eSVille Syrjälä enum pipe pipe; 138944d9241eSVille Syrjälä 139044d9241eSVille Syrjälä for_each_pipe(dev_priv, pipe) { 13912939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe), 139244d9241eSVille Syrjälä PIPESTAT_INT_STATUS_MASK | 139344d9241eSVille Syrjälä PIPE_FIFO_UNDERRUN_STATUS); 139444d9241eSVille Syrjälä 139544d9241eSVille Syrjälä dev_priv->pipestat_irq_mask[pipe] = 0; 139644d9241eSVille Syrjälä } 139744d9241eSVille Syrjälä } 139844d9241eSVille Syrjälä 1399eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, 140091d14251STvrtko Ursulin u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 14017e231dbeSJesse Barnes { 1402d048a268SVille Syrjälä enum pipe pipe; 14037e231dbeSJesse Barnes 140458ead0d7SImre Deak spin_lock(&dev_priv->irq_lock); 14051ca993d2SVille Syrjälä 14061ca993d2SVille Syrjälä if (!dev_priv->display_irqs_enabled) { 14071ca993d2SVille Syrjälä spin_unlock(&dev_priv->irq_lock); 14081ca993d2SVille Syrjälä return; 14091ca993d2SVille Syrjälä } 14101ca993d2SVille Syrjälä 1411055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1412f0f59a00SVille Syrjälä i915_reg_t reg; 14136b12ca56SVille Syrjälä u32 status_mask, enable_mask, iir_bit = 0; 141491d181ddSImre Deak 1415bbb5eebfSDaniel Vetter /* 1416bbb5eebfSDaniel Vetter * PIPESTAT bits get signalled even when the interrupt is 1417bbb5eebfSDaniel Vetter * disabled with the mask bits, and some of the status bits do 1418bbb5eebfSDaniel Vetter * not generate interrupts at all (like the underrun bit). Hence 1419bbb5eebfSDaniel Vetter * we need to be careful that we only handle what we want to 1420bbb5eebfSDaniel Vetter * handle. 1421bbb5eebfSDaniel Vetter */ 14220f239f4cSDaniel Vetter 14230f239f4cSDaniel Vetter /* fifo underruns are filterered in the underrun handler. */ 14246b12ca56SVille Syrjälä status_mask = PIPE_FIFO_UNDERRUN_STATUS; 1425bbb5eebfSDaniel Vetter 1426bbb5eebfSDaniel Vetter switch (pipe) { 1427d048a268SVille Syrjälä default: 1428bbb5eebfSDaniel Vetter case PIPE_A: 1429bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; 1430bbb5eebfSDaniel Vetter break; 1431bbb5eebfSDaniel Vetter case PIPE_B: 1432bbb5eebfSDaniel Vetter iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1433bbb5eebfSDaniel Vetter break; 14343278f67fSVille Syrjälä case PIPE_C: 14353278f67fSVille Syrjälä iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; 14363278f67fSVille Syrjälä break; 1437bbb5eebfSDaniel Vetter } 1438bbb5eebfSDaniel Vetter if (iir & iir_bit) 14396b12ca56SVille Syrjälä status_mask |= dev_priv->pipestat_irq_mask[pipe]; 1440bbb5eebfSDaniel Vetter 14416b12ca56SVille Syrjälä if (!status_mask) 144291d181ddSImre Deak continue; 144391d181ddSImre Deak 144491d181ddSImre Deak reg = PIPESTAT(pipe); 14452939eb06SJani Nikula pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask; 14466b12ca56SVille Syrjälä enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); 14477e231dbeSJesse Barnes 14487e231dbeSJesse Barnes /* 14497e231dbeSJesse Barnes * Clear the PIPE*STAT regs before the IIR 1450132c27c9SVille Syrjälä * 1451132c27c9SVille Syrjälä * Toggle the enable bits to make sure we get an 1452132c27c9SVille Syrjälä * edge in the ISR pipe event bit if we don't clear 1453132c27c9SVille Syrjälä * all the enabled status bits. Otherwise the edge 1454132c27c9SVille Syrjälä * triggered IIR on i965/g4x wouldn't notice that 1455132c27c9SVille Syrjälä * an interrupt is still pending. 14567e231dbeSJesse Barnes */ 1457132c27c9SVille Syrjälä if (pipe_stats[pipe]) { 14582939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]); 14592939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask); 1460132c27c9SVille Syrjälä } 14617e231dbeSJesse Barnes } 146258ead0d7SImre Deak spin_unlock(&dev_priv->irq_lock); 14632ecb8ca4SVille Syrjälä } 14642ecb8ca4SVille Syrjälä 1465eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1466eb64343cSVille Syrjälä u16 iir, u32 pipe_stats[I915_MAX_PIPES]) 1467eb64343cSVille Syrjälä { 1468eb64343cSVille Syrjälä enum pipe pipe; 1469eb64343cSVille Syrjälä 1470eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1471eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1472aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1473eb64343cSVille Syrjälä 1474eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1475eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1476eb64343cSVille Syrjälä 1477eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1478eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1479eb64343cSVille Syrjälä } 1480eb64343cSVille Syrjälä } 1481eb64343cSVille Syrjälä 1482eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1483eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1484eb64343cSVille Syrjälä { 1485eb64343cSVille Syrjälä bool blc_event = false; 1486eb64343cSVille Syrjälä enum pipe pipe; 1487eb64343cSVille Syrjälä 1488eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1489eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) 1490aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1491eb64343cSVille Syrjälä 1492eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1493eb64343cSVille Syrjälä blc_event = true; 1494eb64343cSVille Syrjälä 1495eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1496eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1497eb64343cSVille Syrjälä 1498eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1499eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1500eb64343cSVille Syrjälä } 1501eb64343cSVille Syrjälä 1502eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1503eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1504eb64343cSVille Syrjälä } 1505eb64343cSVille Syrjälä 1506eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, 1507eb64343cSVille Syrjälä u32 iir, u32 pipe_stats[I915_MAX_PIPES]) 1508eb64343cSVille Syrjälä { 1509eb64343cSVille Syrjälä bool blc_event = false; 1510eb64343cSVille Syrjälä enum pipe pipe; 1511eb64343cSVille Syrjälä 1512eb64343cSVille Syrjälä for_each_pipe(dev_priv, pipe) { 1513eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1514aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 1515eb64343cSVille Syrjälä 1516eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) 1517eb64343cSVille Syrjälä blc_event = true; 1518eb64343cSVille Syrjälä 1519eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 1520eb64343cSVille Syrjälä i9xx_pipe_crc_irq_handler(dev_priv, pipe); 1521eb64343cSVille Syrjälä 1522eb64343cSVille Syrjälä if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 1523eb64343cSVille Syrjälä intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 1524eb64343cSVille Syrjälä } 1525eb64343cSVille Syrjälä 1526eb64343cSVille Syrjälä if (blc_event || (iir & I915_ASLE_INTERRUPT)) 1527eb64343cSVille Syrjälä intel_opregion_asle_intr(dev_priv); 1528eb64343cSVille Syrjälä 1529eb64343cSVille Syrjälä if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 1530eb64343cSVille Syrjälä gmbus_irq_handler(dev_priv); 1531eb64343cSVille Syrjälä } 1532eb64343cSVille Syrjälä 153391d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, 15342ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES]) 15352ecb8ca4SVille Syrjälä { 15362ecb8ca4SVille Syrjälä enum pipe pipe; 15377e231dbeSJesse Barnes 1538055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 1539fd3a4024SDaniel Vetter if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) 1540aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 15414356d586SDaniel Vetter 15426ede6b06SVille Syrjälä if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV) 15436ede6b06SVille Syrjälä flip_done_handler(dev_priv, pipe); 15446ede6b06SVille Syrjälä 15454356d586SDaniel Vetter if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) 154691d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 15472d9d2b0bSVille Syrjälä 15481f7247c0SDaniel Vetter if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) 15491f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 155031acc7f5SJesse Barnes } 155131acc7f5SJesse Barnes 1552c1874ed7SImre Deak if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) 155391d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1554c1874ed7SImre Deak } 1555c1874ed7SImre Deak 15561ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 155716c6c56bSVille Syrjälä { 15580ba7c51aSVille Syrjälä u32 hotplug_status = 0, hotplug_status_mask; 15590ba7c51aSVille Syrjälä int i; 156016c6c56bSVille Syrjälä 15610ba7c51aSVille Syrjälä if (IS_G4X(dev_priv) || 15620ba7c51aSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 15630ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | 15640ba7c51aSVille Syrjälä DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; 15650ba7c51aSVille Syrjälä else 15660ba7c51aSVille Syrjälä hotplug_status_mask = HOTPLUG_INT_STATUS_I915; 15670ba7c51aSVille Syrjälä 15680ba7c51aSVille Syrjälä /* 15690ba7c51aSVille Syrjälä * We absolutely have to clear all the pending interrupt 15700ba7c51aSVille Syrjälä * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port 15710ba7c51aSVille Syrjälä * interrupt bit won't have an edge, and the i965/g4x 15720ba7c51aSVille Syrjälä * edge triggered IIR will not notice that an interrupt 15730ba7c51aSVille Syrjälä * is still pending. We can't use PORT_HOTPLUG_EN to 15740ba7c51aSVille Syrjälä * guarantee the edge as the act of toggling the enable 15750ba7c51aSVille Syrjälä * bits can itself generate a new hotplug interrupt :( 15760ba7c51aSVille Syrjälä */ 15770ba7c51aSVille Syrjälä for (i = 0; i < 10; i++) { 15782939eb06SJani Nikula u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask; 15790ba7c51aSVille Syrjälä 15800ba7c51aSVille Syrjälä if (tmp == 0) 15810ba7c51aSVille Syrjälä return hotplug_status; 15820ba7c51aSVille Syrjälä 15830ba7c51aSVille Syrjälä hotplug_status |= tmp; 15842939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status); 15850ba7c51aSVille Syrjälä } 15860ba7c51aSVille Syrjälä 158748a1b8d4SPankaj Bharadiya drm_WARN_ONCE(&dev_priv->drm, 1, 15880ba7c51aSVille Syrjälä "PORT_HOTPLUG_STAT did not clear (0x%08x)\n", 15892939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 15901ae3c34cSVille Syrjälä 15911ae3c34cSVille Syrjälä return hotplug_status; 15921ae3c34cSVille Syrjälä } 15931ae3c34cSVille Syrjälä 159491d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, 15951ae3c34cSVille Syrjälä u32 hotplug_status) 15961ae3c34cSVille Syrjälä { 15971ae3c34cSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 15980398993bSVille Syrjälä u32 hotplug_trigger; 15993ff60f89SOscar Mateo 16000398993bSVille Syrjälä if (IS_G4X(dev_priv) || 16010398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 16020398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; 16030398993bSVille Syrjälä else 16040398993bSVille Syrjälä hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; 160516c6c56bSVille Syrjälä 160658f2cf24SVille Syrjälä if (hotplug_trigger) { 1607cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1608cf53902fSRodrigo Vivi hotplug_trigger, hotplug_trigger, 16090398993bSVille Syrjälä dev_priv->hotplug.hpd, 1610fd63e2a9SImre Deak i9xx_port_hotplug_long_detect); 161158f2cf24SVille Syrjälä 161291d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 161358f2cf24SVille Syrjälä } 1614369712e8SJani Nikula 16150398993bSVille Syrjälä if ((IS_G4X(dev_priv) || 16160398993bSVille Syrjälä IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && 16170398993bSVille Syrjälä hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) 161891d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 161958f2cf24SVille Syrjälä } 162016c6c56bSVille Syrjälä 1621c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg) 1622c1874ed7SImre Deak { 1623b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 1624c1874ed7SImre Deak irqreturn_t ret = IRQ_NONE; 1625c1874ed7SImre Deak 16262dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 16272dd2a883SImre Deak return IRQ_NONE; 16282dd2a883SImre Deak 16291f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 16309102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 16311f814dacSImre Deak 16321e1cace9SVille Syrjälä do { 16336e814800SVille Syrjälä u32 iir, gt_iir, pm_iir; 16342ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 16351ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1636a5e485a9SVille Syrjälä u32 ier = 0; 16373ff60f89SOscar Mateo 16382939eb06SJani Nikula gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR); 16392939eb06SJani Nikula pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR); 16402939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 1641c1874ed7SImre Deak 1642c1874ed7SImre Deak if (gt_iir == 0 && pm_iir == 0 && iir == 0) 16431e1cace9SVille Syrjälä break; 1644c1874ed7SImre Deak 1645c1874ed7SImre Deak ret = IRQ_HANDLED; 1646c1874ed7SImre Deak 1647a5e485a9SVille Syrjälä /* 1648a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1649a5e485a9SVille Syrjälä * 1650a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1651a5e485a9SVille Syrjälä * (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) && 1652a5e485a9SVille Syrjälä * (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE))); 1653a5e485a9SVille Syrjälä * 1654a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1655a5e485a9SVille Syrjälä * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to 1656a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1657a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR 1658a5e485a9SVille Syrjälä * bits this time around. 1659a5e485a9SVille Syrjälä */ 16602939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 16612939eb06SJani Nikula ier = intel_uncore_read(&dev_priv->uncore, VLV_IER); 16622939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, 0); 16634a0a0202SVille Syrjälä 16644a0a0202SVille Syrjälä if (gt_iir) 16652939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir); 16664a0a0202SVille Syrjälä if (pm_iir) 16672939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir); 16684a0a0202SVille Syrjälä 16697ce4d1f2SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 16701ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 16717ce4d1f2SVille Syrjälä 16723ff60f89SOscar Mateo /* Call regardless, as some status bits might not be 16733ff60f89SOscar Mateo * signalled in iir */ 1674eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 16757ce4d1f2SVille Syrjälä 1676eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1677eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT)) 1678eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1679eef57324SJerome Anand 16807ce4d1f2SVille Syrjälä /* 16817ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 16827ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 16837ce4d1f2SVille Syrjälä */ 16847ce4d1f2SVille Syrjälä if (iir) 16852939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 16864a0a0202SVille Syrjälä 16872939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 16882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 16891ae3c34cSVille Syrjälä 169052894874SVille Syrjälä if (gt_iir) 1691cf1c97dcSAndi Shyti gen6_gt_irq_handler(&dev_priv->gt, gt_iir); 169252894874SVille Syrjälä if (pm_iir) 16933e7abf81SAndi Shyti gen6_rps_irq_handler(&dev_priv->gt.rps, pm_iir); 169452894874SVille Syrjälä 16951ae3c34cSVille Syrjälä if (hotplug_status) 169691d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 16972ecb8ca4SVille Syrjälä 169891d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 16991e1cace9SVille Syrjälä } while (0); 17007e231dbeSJesse Barnes 17019c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 17029c6508b9SThomas Gleixner 17039102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 17041f814dacSImre Deak 17057e231dbeSJesse Barnes return ret; 17067e231dbeSJesse Barnes } 17077e231dbeSJesse Barnes 170843f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg) 170943f328d7SVille Syrjälä { 1710b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 171143f328d7SVille Syrjälä irqreturn_t ret = IRQ_NONE; 171243f328d7SVille Syrjälä 17132dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 17142dd2a883SImre Deak return IRQ_NONE; 17152dd2a883SImre Deak 17161f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 17179102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 17181f814dacSImre Deak 1719579de73bSChris Wilson do { 17206e814800SVille Syrjälä u32 master_ctl, iir; 17212ecb8ca4SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 17221ae3c34cSVille Syrjälä u32 hotplug_status = 0; 1723a5e485a9SVille Syrjälä u32 ier = 0; 1724a5e485a9SVille Syrjälä 17252939eb06SJani Nikula master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; 17262939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR); 17273278f67fSVille Syrjälä 17283278f67fSVille Syrjälä if (master_ctl == 0 && iir == 0) 17298e5fd599SVille Syrjälä break; 173043f328d7SVille Syrjälä 173127b6c122SOscar Mateo ret = IRQ_HANDLED; 173227b6c122SOscar Mateo 1733a5e485a9SVille Syrjälä /* 1734a5e485a9SVille Syrjälä * Theory on interrupt generation, based on empirical evidence: 1735a5e485a9SVille Syrjälä * 1736a5e485a9SVille Syrjälä * x = ((VLV_IIR & VLV_IER) || 1737a5e485a9SVille Syrjälä * ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) && 1738a5e485a9SVille Syrjälä * (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL))); 1739a5e485a9SVille Syrjälä * 1740a5e485a9SVille Syrjälä * A CPU interrupt will only be raised when 'x' has a 0->1 edge. 1741a5e485a9SVille Syrjälä * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to 1742a5e485a9SVille Syrjälä * guarantee the CPU interrupt will be raised again even if we 1743a5e485a9SVille Syrjälä * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL 1744a5e485a9SVille Syrjälä * bits this time around. 1745a5e485a9SVille Syrjälä */ 17462939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); 17472939eb06SJani Nikula ier = intel_uncore_read(&dev_priv->uncore, VLV_IER); 17482939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, 0); 174943f328d7SVille Syrjälä 17506cc32f15SChris Wilson gen8_gt_irq_handler(&dev_priv->gt, master_ctl); 175127b6c122SOscar Mateo 175227b6c122SOscar Mateo if (iir & I915_DISPLAY_PORT_INTERRUPT) 17531ae3c34cSVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 175443f328d7SVille Syrjälä 175527b6c122SOscar Mateo /* Call regardless, as some status bits might not be 175627b6c122SOscar Mateo * signalled in iir */ 1757eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 175843f328d7SVille Syrjälä 1759eef57324SJerome Anand if (iir & (I915_LPE_PIPE_A_INTERRUPT | 1760eef57324SJerome Anand I915_LPE_PIPE_B_INTERRUPT | 1761eef57324SJerome Anand I915_LPE_PIPE_C_INTERRUPT)) 1762eef57324SJerome Anand intel_lpe_audio_irq_handler(dev_priv); 1763eef57324SJerome Anand 17647ce4d1f2SVille Syrjälä /* 17657ce4d1f2SVille Syrjälä * VLV_IIR is single buffered, and reflects the level 17667ce4d1f2SVille Syrjälä * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last. 17677ce4d1f2SVille Syrjälä */ 17687ce4d1f2SVille Syrjälä if (iir) 17692939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir); 17707ce4d1f2SVille Syrjälä 17712939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_IER, ier); 17722939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 17731ae3c34cSVille Syrjälä 17741ae3c34cSVille Syrjälä if (hotplug_status) 177591d14251STvrtko Ursulin i9xx_hpd_irq_handler(dev_priv, hotplug_status); 17762ecb8ca4SVille Syrjälä 177791d14251STvrtko Ursulin valleyview_pipestat_irq_handler(dev_priv, pipe_stats); 1778579de73bSChris Wilson } while (0); 17793278f67fSVille Syrjälä 17809c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 17819c6508b9SThomas Gleixner 17829102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 17831f814dacSImre Deak 178443f328d7SVille Syrjälä return ret; 178543f328d7SVille Syrjälä } 178643f328d7SVille Syrjälä 178791d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, 17880398993bSVille Syrjälä u32 hotplug_trigger) 1789776ad806SJesse Barnes { 179042db67d6SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 1791776ad806SJesse Barnes 17926a39d7c9SJani Nikula /* 17936a39d7c9SJani Nikula * Somehow the PCH doesn't seem to really ack the interrupt to the CPU 17946a39d7c9SJani Nikula * unless we touch the hotplug register, even if hotplug_trigger is 17956a39d7c9SJani Nikula * zero. Not acking leads to "The master control interrupt lied (SDE)!" 17966a39d7c9SJani Nikula * errors. 17976a39d7c9SJani Nikula */ 17982939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 17996a39d7c9SJani Nikula if (!hotplug_trigger) { 18006a39d7c9SJani Nikula u32 mask = PORTA_HOTPLUG_STATUS_MASK | 18016a39d7c9SJani Nikula PORTD_HOTPLUG_STATUS_MASK | 18026a39d7c9SJani Nikula PORTC_HOTPLUG_STATUS_MASK | 18036a39d7c9SJani Nikula PORTB_HOTPLUG_STATUS_MASK; 18046a39d7c9SJani Nikula dig_hotplug_reg &= ~mask; 18056a39d7c9SJani Nikula } 18066a39d7c9SJani Nikula 18072939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 18086a39d7c9SJani Nikula if (!hotplug_trigger) 18096a39d7c9SJani Nikula return; 181013cf5504SDave Airlie 18110398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 18120398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 18130398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 1814fd63e2a9SImre Deak pch_port_hotplug_long_detect); 181540e56410SVille Syrjälä 181691d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 1817aaf5ec2eSSonika Jindal } 181891d131d2SDaniel Vetter 181991d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 182040e56410SVille Syrjälä { 1821d048a268SVille Syrjälä enum pipe pipe; 182240e56410SVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 182340e56410SVille Syrjälä 18240398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 182540e56410SVille Syrjälä 1826cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK) { 1827cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> 1828776ad806SJesse Barnes SDE_AUDIO_POWER_SHIFT); 182900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n", 1830cfc33bf7SVille Syrjälä port_name(port)); 1831cfc33bf7SVille Syrjälä } 1832776ad806SJesse Barnes 1833ce99c256SDaniel Vetter if (pch_iir & SDE_AUX_MASK) 183491d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 1835ce99c256SDaniel Vetter 1836776ad806SJesse Barnes if (pch_iir & SDE_GMBUS) 183791d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 1838776ad806SJesse Barnes 1839776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_HDCP_MASK) 184000376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n"); 1841776ad806SJesse Barnes 1842776ad806SJesse Barnes if (pch_iir & SDE_AUDIO_TRANS_MASK) 184300376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n"); 1844776ad806SJesse Barnes 1845776ad806SJesse Barnes if (pch_iir & SDE_POISON) 184600376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1847776ad806SJesse Barnes 1848b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK) { 1849055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 185000376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 18519db4a9c7SJesse Barnes pipe_name(pipe), 18522939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1853b8b65ccdSAnshuman Gupta } 1854776ad806SJesse Barnes 1855776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) 185600376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n"); 1857776ad806SJesse Barnes 1858776ad806SJesse Barnes if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) 185900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 186000376ccfSWambui Karuga "PCH transcoder CRC error interrupt\n"); 1861776ad806SJesse Barnes 1862776ad806SJesse Barnes if (pch_iir & SDE_TRANSA_FIFO_UNDER) 1863a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); 18648664281bSPaulo Zanoni 18658664281bSPaulo Zanoni if (pch_iir & SDE_TRANSB_FIFO_UNDER) 1866a2196033SMatthias Kaehlcke intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); 18678664281bSPaulo Zanoni } 18688664281bSPaulo Zanoni 186991d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv) 18708664281bSPaulo Zanoni { 18712939eb06SJani Nikula u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT); 18725a69b89fSDaniel Vetter enum pipe pipe; 18738664281bSPaulo Zanoni 1874de032bf4SPaulo Zanoni if (err_int & ERR_INT_POISON) 187500376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 1876de032bf4SPaulo Zanoni 1877055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 18781f7247c0SDaniel Vetter if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) 18791f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 18808664281bSPaulo Zanoni 18815a69b89fSDaniel Vetter if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { 188291d14251STvrtko Ursulin if (IS_IVYBRIDGE(dev_priv)) 188391d14251STvrtko Ursulin ivb_pipe_crc_irq_handler(dev_priv, pipe); 18845a69b89fSDaniel Vetter else 188591d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 18865a69b89fSDaniel Vetter } 18875a69b89fSDaniel Vetter } 18888bf1e9f1SShuang He 18892939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int); 18908664281bSPaulo Zanoni } 18918664281bSPaulo Zanoni 189291d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) 18938664281bSPaulo Zanoni { 18942939eb06SJani Nikula u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT); 189545c1cd87SMika Kahola enum pipe pipe; 18968664281bSPaulo Zanoni 1897de032bf4SPaulo Zanoni if (serr_int & SERR_INT_POISON) 189800376ccfSWambui Karuga drm_err(&dev_priv->drm, "PCH poison interrupt\n"); 1899de032bf4SPaulo Zanoni 190045c1cd87SMika Kahola for_each_pipe(dev_priv, pipe) 190145c1cd87SMika Kahola if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) 190245c1cd87SMika Kahola intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); 19038664281bSPaulo Zanoni 19042939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int); 1905776ad806SJesse Barnes } 1906776ad806SJesse Barnes 190791d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 190823e81d69SAdam Jackson { 1909d048a268SVille Syrjälä enum pipe pipe; 19106dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 1911aaf5ec2eSSonika Jindal 19120398993bSVille Syrjälä ibx_hpd_irq_handler(dev_priv, hotplug_trigger); 191391d131d2SDaniel Vetter 1914cfc33bf7SVille Syrjälä if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { 1915cfc33bf7SVille Syrjälä int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> 191623e81d69SAdam Jackson SDE_AUDIO_POWER_SHIFT_CPT); 191700376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n", 1918cfc33bf7SVille Syrjälä port_name(port)); 1919cfc33bf7SVille Syrjälä } 192023e81d69SAdam Jackson 192123e81d69SAdam Jackson if (pch_iir & SDE_AUX_MASK_CPT) 192291d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 192323e81d69SAdam Jackson 192423e81d69SAdam Jackson if (pch_iir & SDE_GMBUS_CPT) 192591d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 192623e81d69SAdam Jackson 192723e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_REQ_CPT) 192800376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n"); 192923e81d69SAdam Jackson 193023e81d69SAdam Jackson if (pch_iir & SDE_AUDIO_CP_CHG_CPT) 193100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n"); 193223e81d69SAdam Jackson 1933b8b65ccdSAnshuman Gupta if (pch_iir & SDE_FDI_MASK_CPT) { 1934055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 193500376ccfSWambui Karuga drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n", 193623e81d69SAdam Jackson pipe_name(pipe), 19372939eb06SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe))); 1938b8b65ccdSAnshuman Gupta } 19398664281bSPaulo Zanoni 19408664281bSPaulo Zanoni if (pch_iir & SDE_ERROR_CPT) 194191d14251STvrtko Ursulin cpt_serr_int_handler(dev_priv); 194223e81d69SAdam Jackson } 194323e81d69SAdam Jackson 194458676af6SLucas De Marchi static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 194531604222SAnusha Srivatsa { 1946e76ab2cfSVille Syrjälä u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP; 1947e76ab2cfSVille Syrjälä u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP; 194831604222SAnusha Srivatsa u32 pin_mask = 0, long_mask = 0; 194931604222SAnusha Srivatsa 195031604222SAnusha Srivatsa if (ddi_hotplug_trigger) { 195131604222SAnusha Srivatsa u32 dig_hotplug_reg; 195231604222SAnusha Srivatsa 19532939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI); 19542939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, dig_hotplug_reg); 195531604222SAnusha Srivatsa 195631604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 19570398993bSVille Syrjälä ddi_hotplug_trigger, dig_hotplug_reg, 19580398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 195931604222SAnusha Srivatsa icp_ddi_port_hotplug_long_detect); 196031604222SAnusha Srivatsa } 196131604222SAnusha Srivatsa 196231604222SAnusha Srivatsa if (tc_hotplug_trigger) { 196331604222SAnusha Srivatsa u32 dig_hotplug_reg; 196431604222SAnusha Srivatsa 19652939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC); 19662939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, dig_hotplug_reg); 196731604222SAnusha Srivatsa 196831604222SAnusha Srivatsa intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 19690398993bSVille Syrjälä tc_hotplug_trigger, dig_hotplug_reg, 19700398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 1971da51e4baSVille Syrjälä icp_tc_port_hotplug_long_detect); 197252dfdba0SLucas De Marchi } 197352dfdba0SLucas De Marchi 197452dfdba0SLucas De Marchi if (pin_mask) 197552dfdba0SLucas De Marchi intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 197652dfdba0SLucas De Marchi 197752dfdba0SLucas De Marchi if (pch_iir & SDE_GMBUS_ICP) 197852dfdba0SLucas De Marchi gmbus_irq_handler(dev_priv); 197952dfdba0SLucas De Marchi } 198052dfdba0SLucas De Marchi 198191d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) 19826dbf30ceSVille Syrjälä { 19836dbf30ceSVille Syrjälä u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & 19846dbf30ceSVille Syrjälä ~SDE_PORTE_HOTPLUG_SPT; 19856dbf30ceSVille Syrjälä u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; 19866dbf30ceSVille Syrjälä u32 pin_mask = 0, long_mask = 0; 19876dbf30ceSVille Syrjälä 19886dbf30ceSVille Syrjälä if (hotplug_trigger) { 19896dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 19906dbf30ceSVille Syrjälä 19912939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 19922939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 19936dbf30ceSVille Syrjälä 1994cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 19950398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 19960398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 199774c0b395SVille Syrjälä spt_port_hotplug_long_detect); 19986dbf30ceSVille Syrjälä } 19996dbf30ceSVille Syrjälä 20006dbf30ceSVille Syrjälä if (hotplug2_trigger) { 20016dbf30ceSVille Syrjälä u32 dig_hotplug_reg; 20026dbf30ceSVille Syrjälä 20032939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2); 20042939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, dig_hotplug_reg); 20056dbf30ceSVille Syrjälä 2006cf53902fSRodrigo Vivi intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 20070398993bSVille Syrjälä hotplug2_trigger, dig_hotplug_reg, 20080398993bSVille Syrjälä dev_priv->hotplug.pch_hpd, 20096dbf30ceSVille Syrjälä spt_port_hotplug2_long_detect); 20106dbf30ceSVille Syrjälä } 20116dbf30ceSVille Syrjälä 20126dbf30ceSVille Syrjälä if (pin_mask) 201391d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 20146dbf30ceSVille Syrjälä 20156dbf30ceSVille Syrjälä if (pch_iir & SDE_GMBUS_CPT) 201691d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 20176dbf30ceSVille Syrjälä } 20186dbf30ceSVille Syrjälä 201991d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, 20200398993bSVille Syrjälä u32 hotplug_trigger) 2021c008bc6eSPaulo Zanoni { 2022e4ce95aaSVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2023e4ce95aaSVille Syrjälä 20242939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL); 20252939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg); 2026e4ce95aaSVille Syrjälä 20270398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 20280398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 20290398993bSVille Syrjälä dev_priv->hotplug.hpd, 2030e4ce95aaSVille Syrjälä ilk_port_hotplug_long_detect); 203140e56410SVille Syrjälä 203291d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2033e4ce95aaSVille Syrjälä } 2034c008bc6eSPaulo Zanoni 203591d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv, 203691d14251STvrtko Ursulin u32 de_iir) 203740e56410SVille Syrjälä { 203840e56410SVille Syrjälä enum pipe pipe; 203940e56410SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; 204040e56410SVille Syrjälä 204140e56410SVille Syrjälä if (hotplug_trigger) 20420398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 204340e56410SVille Syrjälä 2044c008bc6eSPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A) 204591d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2046c008bc6eSPaulo Zanoni 2047c008bc6eSPaulo Zanoni if (de_iir & DE_GSE) 204891d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2049c008bc6eSPaulo Zanoni 2050c008bc6eSPaulo Zanoni if (de_iir & DE_POISON) 205100376ccfSWambui Karuga drm_err(&dev_priv->drm, "Poison interrupt\n"); 2052c008bc6eSPaulo Zanoni 2053055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2054fd3a4024SDaniel Vetter if (de_iir & DE_PIPE_VBLANK(pipe)) 2055aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 2056c008bc6eSPaulo Zanoni 20574bb18054SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE(pipe)) 20584bb18054SVille Syrjälä flip_done_handler(dev_priv, pipe); 20594bb18054SVille Syrjälä 206040da17c2SDaniel Vetter if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) 20611f7247c0SDaniel Vetter intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 2062c008bc6eSPaulo Zanoni 206340da17c2SDaniel Vetter if (de_iir & DE_PIPE_CRC_DONE(pipe)) 206491d14251STvrtko Ursulin i9xx_pipe_crc_irq_handler(dev_priv, pipe); 2065c008bc6eSPaulo Zanoni } 2066c008bc6eSPaulo Zanoni 2067c008bc6eSPaulo Zanoni /* check event from PCH */ 2068c008bc6eSPaulo Zanoni if (de_iir & DE_PCH_EVENT) { 20692939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 2070c008bc6eSPaulo Zanoni 207191d14251STvrtko Ursulin if (HAS_PCH_CPT(dev_priv)) 207291d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 2073c008bc6eSPaulo Zanoni else 207491d14251STvrtko Ursulin ibx_irq_handler(dev_priv, pch_iir); 2075c008bc6eSPaulo Zanoni 2076c008bc6eSPaulo Zanoni /* should clear PCH hotplug event before clear CPU irq */ 20772939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 2078c008bc6eSPaulo Zanoni } 2079c008bc6eSPaulo Zanoni 2080cf819effSLucas De Marchi if (IS_GEN(dev_priv, 5) && de_iir & DE_PCU_EVENT) 20813e7abf81SAndi Shyti gen5_rps_irq_handler(&dev_priv->gt.rps); 2082c008bc6eSPaulo Zanoni } 2083c008bc6eSPaulo Zanoni 208491d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, 208591d14251STvrtko Ursulin u32 de_iir) 20869719fb98SPaulo Zanoni { 208707d27e20SDamien Lespiau enum pipe pipe; 208823bb4cb5SVille Syrjälä u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; 208923bb4cb5SVille Syrjälä 209040e56410SVille Syrjälä if (hotplug_trigger) 20910398993bSVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 20929719fb98SPaulo Zanoni 20939719fb98SPaulo Zanoni if (de_iir & DE_ERR_INT_IVB) 209491d14251STvrtko Ursulin ivb_err_int_handler(dev_priv); 20959719fb98SPaulo Zanoni 209654fd3149SDhinakaran Pandiyan if (de_iir & DE_EDP_PSR_INT_HSW) { 2097*b64d6c51SGwan-gyeong Mun struct intel_encoder *encoder; 209854fd3149SDhinakaran Pandiyan 2099*b64d6c51SGwan-gyeong Mun for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) { 2100*b64d6c51SGwan-gyeong Mun struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 2101*b64d6c51SGwan-gyeong Mun 2102*b64d6c51SGwan-gyeong Mun u32 psr_iir = intel_uncore_read(&dev_priv->uncore, 2103*b64d6c51SGwan-gyeong Mun EDP_PSR_IIR); 2104*b64d6c51SGwan-gyeong Mun 2105*b64d6c51SGwan-gyeong Mun intel_psr_irq_handler(intel_dp, psr_iir); 2106*b64d6c51SGwan-gyeong Mun intel_uncore_write(&dev_priv->uncore, 2107*b64d6c51SGwan-gyeong Mun EDP_PSR_IIR, psr_iir); 2108*b64d6c51SGwan-gyeong Mun break; 2109*b64d6c51SGwan-gyeong Mun } 211054fd3149SDhinakaran Pandiyan } 2111fc340442SDaniel Vetter 21129719fb98SPaulo Zanoni if (de_iir & DE_AUX_CHANNEL_A_IVB) 211391d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 21149719fb98SPaulo Zanoni 21159719fb98SPaulo Zanoni if (de_iir & DE_GSE_IVB) 211691d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 21179719fb98SPaulo Zanoni 2118055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 211933ef04faSVille Syrjälä if (de_iir & DE_PIPE_VBLANK_IVB(pipe)) 2120aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 21212a636e24SVille Syrjälä 21222a636e24SVille Syrjälä if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe)) 21232a636e24SVille Syrjälä flip_done_handler(dev_priv, pipe); 21249719fb98SPaulo Zanoni } 21259719fb98SPaulo Zanoni 21269719fb98SPaulo Zanoni /* check event from PCH */ 212791d14251STvrtko Ursulin if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) { 21282939eb06SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 21299719fb98SPaulo Zanoni 213091d14251STvrtko Ursulin cpt_irq_handler(dev_priv, pch_iir); 21319719fb98SPaulo Zanoni 21329719fb98SPaulo Zanoni /* clear PCH hotplug event before clear CPU irq */ 21332939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir); 21349719fb98SPaulo Zanoni } 21359719fb98SPaulo Zanoni } 21369719fb98SPaulo Zanoni 213772c90f62SOscar Mateo /* 213872c90f62SOscar Mateo * To handle irqs with the minimum potential races with fresh interrupts, we: 213972c90f62SOscar Mateo * 1 - Disable Master Interrupt Control. 214072c90f62SOscar Mateo * 2 - Find the source(s) of the interrupt. 214172c90f62SOscar Mateo * 3 - Clear the Interrupt Identity bits (IIR). 214272c90f62SOscar Mateo * 4 - Process the interrupt(s) that had bits set in the IIRs. 214372c90f62SOscar Mateo * 5 - Re-enable Master Interrupt Control. 214472c90f62SOscar Mateo */ 21459eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg) 2146b1f14ad0SJesse Barnes { 2147c48a798aSChris Wilson struct drm_i915_private *i915 = arg; 2148c48a798aSChris Wilson void __iomem * const regs = i915->uncore.regs; 2149f1af8fc1SPaulo Zanoni u32 de_iir, gt_iir, de_ier, sde_ier = 0; 21500e43406bSChris Wilson irqreturn_t ret = IRQ_NONE; 2151b1f14ad0SJesse Barnes 2152c48a798aSChris Wilson if (unlikely(!intel_irqs_enabled(i915))) 21532dd2a883SImre Deak return IRQ_NONE; 21542dd2a883SImre Deak 21551f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2156c48a798aSChris Wilson disable_rpm_wakeref_asserts(&i915->runtime_pm); 21571f814dacSImre Deak 2158b1f14ad0SJesse Barnes /* disable master interrupt before clearing iir */ 2159c48a798aSChris Wilson de_ier = raw_reg_read(regs, DEIER); 2160c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 21610e43406bSChris Wilson 216244498aeaSPaulo Zanoni /* Disable south interrupts. We'll only write to SDEIIR once, so further 216344498aeaSPaulo Zanoni * interrupts will will be stored on its back queue, and then we'll be 216444498aeaSPaulo Zanoni * able to process them after we restore SDEIER (as soon as we restore 216544498aeaSPaulo Zanoni * it, we'll get an interrupt if SDEIIR still has something to process 216644498aeaSPaulo Zanoni * due to its back queue). */ 2167c48a798aSChris Wilson if (!HAS_PCH_NOP(i915)) { 2168c48a798aSChris Wilson sde_ier = raw_reg_read(regs, SDEIER); 2169c48a798aSChris Wilson raw_reg_write(regs, SDEIER, 0); 2170ab5c608bSBen Widawsky } 217144498aeaSPaulo Zanoni 217272c90f62SOscar Mateo /* Find, clear, then process each source of interrupt */ 217372c90f62SOscar Mateo 2174c48a798aSChris Wilson gt_iir = raw_reg_read(regs, GTIIR); 21750e43406bSChris Wilson if (gt_iir) { 2176c48a798aSChris Wilson raw_reg_write(regs, GTIIR, gt_iir); 2177c48a798aSChris Wilson if (INTEL_GEN(i915) >= 6) 2178c48a798aSChris Wilson gen6_gt_irq_handler(&i915->gt, gt_iir); 2179d8fc8a47SPaulo Zanoni else 2180c48a798aSChris Wilson gen5_gt_irq_handler(&i915->gt, gt_iir); 2181c48a798aSChris Wilson ret = IRQ_HANDLED; 21820e43406bSChris Wilson } 2183b1f14ad0SJesse Barnes 2184c48a798aSChris Wilson de_iir = raw_reg_read(regs, DEIIR); 21850e43406bSChris Wilson if (de_iir) { 2186c48a798aSChris Wilson raw_reg_write(regs, DEIIR, de_iir); 2187c48a798aSChris Wilson if (INTEL_GEN(i915) >= 7) 2188c48a798aSChris Wilson ivb_display_irq_handler(i915, de_iir); 2189f1af8fc1SPaulo Zanoni else 2190c48a798aSChris Wilson ilk_display_irq_handler(i915, de_iir); 21910e43406bSChris Wilson ret = IRQ_HANDLED; 2192c48a798aSChris Wilson } 2193c48a798aSChris Wilson 2194c48a798aSChris Wilson if (INTEL_GEN(i915) >= 6) { 2195c48a798aSChris Wilson u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR); 2196c48a798aSChris Wilson if (pm_iir) { 2197c48a798aSChris Wilson raw_reg_write(regs, GEN6_PMIIR, pm_iir); 2198c48a798aSChris Wilson gen6_rps_irq_handler(&i915->gt.rps, pm_iir); 2199c48a798aSChris Wilson ret = IRQ_HANDLED; 22000e43406bSChris Wilson } 2201f1af8fc1SPaulo Zanoni } 2202b1f14ad0SJesse Barnes 2203c48a798aSChris Wilson raw_reg_write(regs, DEIER, de_ier); 2204c48a798aSChris Wilson if (sde_ier) 2205c48a798aSChris Wilson raw_reg_write(regs, SDEIER, sde_ier); 2206b1f14ad0SJesse Barnes 22079c6508b9SThomas Gleixner pmu_irq_stats(i915, ret); 22089c6508b9SThomas Gleixner 22091f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2210c48a798aSChris Wilson enable_rpm_wakeref_asserts(&i915->runtime_pm); 22111f814dacSImre Deak 2212b1f14ad0SJesse Barnes return ret; 2213b1f14ad0SJesse Barnes } 2214b1f14ad0SJesse Barnes 221591d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, 22160398993bSVille Syrjälä u32 hotplug_trigger) 2217d04a492dSShashank Sharma { 2218cebd87a0SVille Syrjälä u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; 2219d04a492dSShashank Sharma 22202939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 22212939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg); 2222d04a492dSShashank Sharma 22230398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 22240398993bSVille Syrjälä hotplug_trigger, dig_hotplug_reg, 22250398993bSVille Syrjälä dev_priv->hotplug.hpd, 2226cebd87a0SVille Syrjälä bxt_port_hotplug_long_detect); 222740e56410SVille Syrjälä 222891d14251STvrtko Ursulin intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2229d04a492dSShashank Sharma } 2230d04a492dSShashank Sharma 2231121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2232121e758eSDhinakaran Pandiyan { 2233121e758eSDhinakaran Pandiyan u32 pin_mask = 0, long_mask = 0; 2234b796b971SDhinakaran Pandiyan u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; 2235b796b971SDhinakaran Pandiyan u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; 2236121e758eSDhinakaran Pandiyan 2237121e758eSDhinakaran Pandiyan if (trigger_tc) { 2238b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2239b796b971SDhinakaran Pandiyan 22402939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL); 22412939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, dig_hotplug_reg); 2242121e758eSDhinakaran Pandiyan 22430398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 22440398993bSVille Syrjälä trigger_tc, dig_hotplug_reg, 22450398993bSVille Syrjälä dev_priv->hotplug.hpd, 2246da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 2247121e758eSDhinakaran Pandiyan } 2248b796b971SDhinakaran Pandiyan 2249b796b971SDhinakaran Pandiyan if (trigger_tbt) { 2250b796b971SDhinakaran Pandiyan u32 dig_hotplug_reg; 2251b796b971SDhinakaran Pandiyan 22522939eb06SJani Nikula dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL); 22532939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, dig_hotplug_reg); 2254b796b971SDhinakaran Pandiyan 22550398993bSVille Syrjälä intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 22560398993bSVille Syrjälä trigger_tbt, dig_hotplug_reg, 22570398993bSVille Syrjälä dev_priv->hotplug.hpd, 2258da51e4baSVille Syrjälä gen11_port_hotplug_long_detect); 2259b796b971SDhinakaran Pandiyan } 2260b796b971SDhinakaran Pandiyan 2261b796b971SDhinakaran Pandiyan if (pin_mask) 2262b796b971SDhinakaran Pandiyan intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); 2263b796b971SDhinakaran Pandiyan else 226400376ccfSWambui Karuga drm_err(&dev_priv->drm, 226500376ccfSWambui Karuga "Unexpected DE HPD interrupt 0x%08x\n", iir); 2266121e758eSDhinakaran Pandiyan } 2267121e758eSDhinakaran Pandiyan 22689d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv) 22699d17210fSLucas De Marchi { 227055523360SLucas De Marchi u32 mask; 22719d17210fSLucas De Marchi 227255523360SLucas De Marchi if (INTEL_GEN(dev_priv) >= 12) 227355523360SLucas De Marchi return TGL_DE_PORT_AUX_DDIA | 227455523360SLucas De Marchi TGL_DE_PORT_AUX_DDIB | 2275e5df52dcSMatt Roper TGL_DE_PORT_AUX_DDIC | 2276e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC1 | 2277e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC2 | 2278e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC3 | 2279e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC4 | 2280e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC5 | 2281e5df52dcSMatt Roper TGL_DE_PORT_AUX_USBC6; 2282e5df52dcSMatt Roper 228355523360SLucas De Marchi 228455523360SLucas De Marchi mask = GEN8_AUX_CHANNEL_A; 22859d17210fSLucas De Marchi if (INTEL_GEN(dev_priv) >= 9) 22869d17210fSLucas De Marchi mask |= GEN9_AUX_CHANNEL_B | 22879d17210fSLucas De Marchi GEN9_AUX_CHANNEL_C | 22889d17210fSLucas De Marchi GEN9_AUX_CHANNEL_D; 22899d17210fSLucas De Marchi 229055523360SLucas De Marchi if (IS_CNL_WITH_PORT_F(dev_priv) || IS_GEN(dev_priv, 11)) 22919d17210fSLucas De Marchi mask |= CNL_AUX_CHANNEL_F; 22929d17210fSLucas De Marchi 229355523360SLucas De Marchi if (IS_GEN(dev_priv, 11)) 229455523360SLucas De Marchi mask |= ICL_AUX_CHANNEL_E; 22959d17210fSLucas De Marchi 22969d17210fSLucas De Marchi return mask; 22979d17210fSLucas De Marchi } 22989d17210fSLucas De Marchi 22995270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv) 23005270130dSVille Syrjälä { 2301a75816e8SJosé Roberto de Souza if (HAS_D12_PLANE_MINIMIZATION(dev_priv)) 230299e2d8bcSMatt Roper return RKL_DE_PIPE_IRQ_FAULT_ERRORS; 230399e2d8bcSMatt Roper else if (INTEL_GEN(dev_priv) >= 11) 2304d506a65dSMatt Roper return GEN11_DE_PIPE_IRQ_FAULT_ERRORS; 2305d506a65dSMatt Roper else if (INTEL_GEN(dev_priv) >= 9) 23065270130dSVille Syrjälä return GEN9_DE_PIPE_IRQ_FAULT_ERRORS; 23075270130dSVille Syrjälä else 23085270130dSVille Syrjälä return GEN8_DE_PIPE_IRQ_FAULT_ERRORS; 23095270130dSVille Syrjälä } 23105270130dSVille Syrjälä 231146c63d24SJosé Roberto de Souza static void 231246c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) 2313abd58f01SBen Widawsky { 2314e04f7eceSVille Syrjälä bool found = false; 2315e04f7eceSVille Syrjälä 2316e04f7eceSVille Syrjälä if (iir & GEN8_DE_MISC_GSE) { 231791d14251STvrtko Ursulin intel_opregion_asle_intr(dev_priv); 2318e04f7eceSVille Syrjälä found = true; 2319e04f7eceSVille Syrjälä } 2320e04f7eceSVille Syrjälä 2321e04f7eceSVille Syrjälä if (iir & GEN8_DE_EDP_PSR) { 2322*b64d6c51SGwan-gyeong Mun struct intel_encoder *encoder; 23238241cfbeSJosé Roberto de Souza u32 psr_iir; 23248241cfbeSJosé Roberto de Souza i915_reg_t iir_reg; 23258241cfbeSJosé Roberto de Souza 2326*b64d6c51SGwan-gyeong Mun for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) { 2327*b64d6c51SGwan-gyeong Mun struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 2328*b64d6c51SGwan-gyeong Mun 23298241cfbeSJosé Roberto de Souza if (INTEL_GEN(dev_priv) >= 12) 2330*b64d6c51SGwan-gyeong Mun iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder); 23318241cfbeSJosé Roberto de Souza else 23328241cfbeSJosé Roberto de Souza iir_reg = EDP_PSR_IIR; 23338241cfbeSJosé Roberto de Souza 23342939eb06SJani Nikula psr_iir = intel_uncore_read(&dev_priv->uncore, iir_reg); 23352939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, iir_reg, psr_iir); 23368241cfbeSJosé Roberto de Souza 23378241cfbeSJosé Roberto de Souza if (psr_iir) 23388241cfbeSJosé Roberto de Souza found = true; 233954fd3149SDhinakaran Pandiyan 2340*b64d6c51SGwan-gyeong Mun intel_psr_irq_handler(intel_dp, psr_iir); 2341*b64d6c51SGwan-gyeong Mun 2342*b64d6c51SGwan-gyeong Mun /* prior GEN12 only have one EDP PSR */ 2343*b64d6c51SGwan-gyeong Mun if (INTEL_GEN(dev_priv) < 12) 2344*b64d6c51SGwan-gyeong Mun break; 2345*b64d6c51SGwan-gyeong Mun } 2346e04f7eceSVille Syrjälä } 2347e04f7eceSVille Syrjälä 2348e04f7eceSVille Syrjälä if (!found) 234900376ccfSWambui Karuga drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n"); 2350abd58f01SBen Widawsky } 235146c63d24SJosé Roberto de Souza 235200acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv, 235300acb329SVandita Kulkarni u32 te_trigger) 235400acb329SVandita Kulkarni { 235500acb329SVandita Kulkarni enum pipe pipe = INVALID_PIPE; 235600acb329SVandita Kulkarni enum transcoder dsi_trans; 235700acb329SVandita Kulkarni enum port port; 235800acb329SVandita Kulkarni u32 val, tmp; 235900acb329SVandita Kulkarni 236000acb329SVandita Kulkarni /* 236100acb329SVandita Kulkarni * Incase of dual link, TE comes from DSI_1 236200acb329SVandita Kulkarni * this is to check if dual link is enabled 236300acb329SVandita Kulkarni */ 23642939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0)); 236500acb329SVandita Kulkarni val &= PORT_SYNC_MODE_ENABLE; 236600acb329SVandita Kulkarni 236700acb329SVandita Kulkarni /* 236800acb329SVandita Kulkarni * if dual link is enabled, then read DSI_0 236900acb329SVandita Kulkarni * transcoder registers 237000acb329SVandita Kulkarni */ 237100acb329SVandita Kulkarni port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ? 237200acb329SVandita Kulkarni PORT_A : PORT_B; 237300acb329SVandita Kulkarni dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1; 237400acb329SVandita Kulkarni 237500acb329SVandita Kulkarni /* Check if DSI configured in command mode */ 23762939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans)); 237700acb329SVandita Kulkarni val = val & OP_MODE_MASK; 237800acb329SVandita Kulkarni 237900acb329SVandita Kulkarni if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) { 238000acb329SVandita Kulkarni drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n"); 238100acb329SVandita Kulkarni return; 238200acb329SVandita Kulkarni } 238300acb329SVandita Kulkarni 238400acb329SVandita Kulkarni /* Get PIPE for handling VBLANK event */ 23852939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans)); 238600acb329SVandita Kulkarni switch (val & TRANS_DDI_EDP_INPUT_MASK) { 238700acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_A_ON: 238800acb329SVandita Kulkarni pipe = PIPE_A; 238900acb329SVandita Kulkarni break; 239000acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_B_ONOFF: 239100acb329SVandita Kulkarni pipe = PIPE_B; 239200acb329SVandita Kulkarni break; 239300acb329SVandita Kulkarni case TRANS_DDI_EDP_INPUT_C_ONOFF: 239400acb329SVandita Kulkarni pipe = PIPE_C; 239500acb329SVandita Kulkarni break; 239600acb329SVandita Kulkarni default: 239700acb329SVandita Kulkarni drm_err(&dev_priv->drm, "Invalid PIPE\n"); 239800acb329SVandita Kulkarni return; 239900acb329SVandita Kulkarni } 240000acb329SVandita Kulkarni 240100acb329SVandita Kulkarni intel_handle_vblank(dev_priv, pipe); 240200acb329SVandita Kulkarni 240300acb329SVandita Kulkarni /* clear TE in dsi IIR */ 240400acb329SVandita Kulkarni port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A; 24052939eb06SJani Nikula tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port)); 24062939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp); 240700acb329SVandita Kulkarni } 240800acb329SVandita Kulkarni 2409cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915) 2410cda195f1SVille Syrjälä { 2411cda195f1SVille Syrjälä if (INTEL_GEN(i915) >= 9) 2412cda195f1SVille Syrjälä return GEN9_PIPE_PLANE1_FLIP_DONE; 2413cda195f1SVille Syrjälä else 2414cda195f1SVille Syrjälä return GEN8_PIPE_PRIMARY_FLIP_DONE; 2415cda195f1SVille Syrjälä } 2416cda195f1SVille Syrjälä 241746c63d24SJosé Roberto de Souza static irqreturn_t 241846c63d24SJosé Roberto de Souza gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) 241946c63d24SJosé Roberto de Souza { 242046c63d24SJosé Roberto de Souza irqreturn_t ret = IRQ_NONE; 242146c63d24SJosé Roberto de Souza u32 iir; 242246c63d24SJosé Roberto de Souza enum pipe pipe; 242346c63d24SJosé Roberto de Souza 242446c63d24SJosé Roberto de Souza if (master_ctl & GEN8_DE_MISC_IRQ) { 24252939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR); 242646c63d24SJosé Roberto de Souza if (iir) { 24272939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir); 242846c63d24SJosé Roberto de Souza ret = IRQ_HANDLED; 242946c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(dev_priv, iir); 243046c63d24SJosé Roberto de Souza } else { 243100376ccfSWambui Karuga drm_err(&dev_priv->drm, 243200376ccfSWambui Karuga "The master control interrupt lied (DE MISC)!\n"); 2433abd58f01SBen Widawsky } 243446c63d24SJosé Roberto de Souza } 2435abd58f01SBen Widawsky 2436121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) { 24372939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR); 2438121e758eSDhinakaran Pandiyan if (iir) { 24392939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir); 2440121e758eSDhinakaran Pandiyan ret = IRQ_HANDLED; 2441121e758eSDhinakaran Pandiyan gen11_hpd_irq_handler(dev_priv, iir); 2442121e758eSDhinakaran Pandiyan } else { 244300376ccfSWambui Karuga drm_err(&dev_priv->drm, 244400376ccfSWambui Karuga "The master control interrupt lied, (DE HPD)!\n"); 2445121e758eSDhinakaran Pandiyan } 2446121e758eSDhinakaran Pandiyan } 2447121e758eSDhinakaran Pandiyan 24486d766f02SDaniel Vetter if (master_ctl & GEN8_DE_PORT_IRQ) { 24492939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR); 2450e32192e1STvrtko Ursulin if (iir) { 2451d04a492dSShashank Sharma bool found = false; 2452cebd87a0SVille Syrjälä 24532939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir); 24546d766f02SDaniel Vetter ret = IRQ_HANDLED; 245588e04703SJesse Barnes 24569d17210fSLucas De Marchi if (iir & gen8_de_port_aux_mask(dev_priv)) { 245791d14251STvrtko Ursulin dp_aux_irq_handler(dev_priv); 2458d04a492dSShashank Sharma found = true; 2459d04a492dSShashank Sharma } 2460d04a492dSShashank Sharma 2461cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) { 24629a55a620SVille Syrjälä u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK; 24639a55a620SVille Syrjälä 24649a55a620SVille Syrjälä if (hotplug_trigger) { 24659a55a620SVille Syrjälä bxt_hpd_irq_handler(dev_priv, hotplug_trigger); 2466d04a492dSShashank Sharma found = true; 2467d04a492dSShashank Sharma } 2468e32192e1STvrtko Ursulin } else if (IS_BROADWELL(dev_priv)) { 24699a55a620SVille Syrjälä u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK; 24709a55a620SVille Syrjälä 24719a55a620SVille Syrjälä if (hotplug_trigger) { 24729a55a620SVille Syrjälä ilk_hpd_irq_handler(dev_priv, hotplug_trigger); 2473e32192e1STvrtko Ursulin found = true; 2474e32192e1STvrtko Ursulin } 2475e32192e1STvrtko Ursulin } 2476d04a492dSShashank Sharma 2477cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv) && (iir & BXT_DE_PORT_GMBUS)) { 247891d14251STvrtko Ursulin gmbus_irq_handler(dev_priv); 24799e63743eSShashank Sharma found = true; 24809e63743eSShashank Sharma } 24819e63743eSShashank Sharma 248200acb329SVandita Kulkarni if (INTEL_GEN(dev_priv) >= 11) { 24839a55a620SVille Syrjälä u32 te_trigger = iir & (DSI0_TE | DSI1_TE); 24849a55a620SVille Syrjälä 24859a55a620SVille Syrjälä if (te_trigger) { 24869a55a620SVille Syrjälä gen11_dsi_te_interrupt_handler(dev_priv, te_trigger); 248700acb329SVandita Kulkarni found = true; 248800acb329SVandita Kulkarni } 248900acb329SVandita Kulkarni } 249000acb329SVandita Kulkarni 2491d04a492dSShashank Sharma if (!found) 249200376ccfSWambui Karuga drm_err(&dev_priv->drm, 249300376ccfSWambui Karuga "Unexpected DE Port interrupt\n"); 24946d766f02SDaniel Vetter } 249538cc46d7SOscar Mateo else 249600376ccfSWambui Karuga drm_err(&dev_priv->drm, 249700376ccfSWambui Karuga "The master control interrupt lied (DE PORT)!\n"); 24986d766f02SDaniel Vetter } 24996d766f02SDaniel Vetter 2500055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) { 2501fd3a4024SDaniel Vetter u32 fault_errors; 2502abd58f01SBen Widawsky 2503c42664ccSDaniel Vetter if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) 2504c42664ccSDaniel Vetter continue; 2505c42664ccSDaniel Vetter 25062939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe)); 2507e32192e1STvrtko Ursulin if (!iir) { 250800376ccfSWambui Karuga drm_err(&dev_priv->drm, 250900376ccfSWambui Karuga "The master control interrupt lied (DE PIPE)!\n"); 2510e32192e1STvrtko Ursulin continue; 2511e32192e1STvrtko Ursulin } 2512770de83dSDamien Lespiau 2513e32192e1STvrtko Ursulin ret = IRQ_HANDLED; 25142939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir); 2515e32192e1STvrtko Ursulin 2516fd3a4024SDaniel Vetter if (iir & GEN8_PIPE_VBLANK) 2517aca9310aSAnshuman Gupta intel_handle_vblank(dev_priv, pipe); 2518abd58f01SBen Widawsky 2519cda195f1SVille Syrjälä if (iir & gen8_de_pipe_flip_done_mask(dev_priv)) 25201288f9b0SKarthik B S flip_done_handler(dev_priv, pipe); 25211288f9b0SKarthik B S 2522e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_CDCLK_CRC_DONE) 252391d14251STvrtko Ursulin hsw_pipe_crc_irq_handler(dev_priv, pipe); 25240fbe7870SDaniel Vetter 2525e32192e1STvrtko Ursulin if (iir & GEN8_PIPE_FIFO_UNDERRUN) 2526e32192e1STvrtko Ursulin intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); 252738d83c96SDaniel Vetter 25285270130dSVille Syrjälä fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv); 2529770de83dSDamien Lespiau if (fault_errors) 253000376ccfSWambui Karuga drm_err(&dev_priv->drm, 253100376ccfSWambui Karuga "Fault errors on pipe %c: 0x%08x\n", 253230100f2bSDaniel Vetter pipe_name(pipe), 2533e32192e1STvrtko Ursulin fault_errors); 2534abd58f01SBen Widawsky } 2535abd58f01SBen Widawsky 253691d14251STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) && 2537266ea3d9SShashank Sharma master_ctl & GEN8_DE_PCH_IRQ) { 253892d03a80SDaniel Vetter /* 253992d03a80SDaniel Vetter * FIXME(BDW): Assume for now that the new interrupt handling 254092d03a80SDaniel Vetter * scheme also closed the SDE interrupt handling race we've seen 254192d03a80SDaniel Vetter * on older pch-split platforms. But this needs testing. 254292d03a80SDaniel Vetter */ 25432939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, SDEIIR); 2544e32192e1STvrtko Ursulin if (iir) { 25452939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, iir); 254692d03a80SDaniel Vetter ret = IRQ_HANDLED; 25476dbf30ceSVille Syrjälä 254858676af6SLucas De Marchi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 254958676af6SLucas De Marchi icp_irq_handler(dev_priv, iir); 2550c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 255191d14251STvrtko Ursulin spt_irq_handler(dev_priv, iir); 25526dbf30ceSVille Syrjälä else 255391d14251STvrtko Ursulin cpt_irq_handler(dev_priv, iir); 25542dfb0b81SJani Nikula } else { 25552dfb0b81SJani Nikula /* 25562dfb0b81SJani Nikula * Like on previous PCH there seems to be something 25572dfb0b81SJani Nikula * fishy going on with forwarding PCH interrupts. 25582dfb0b81SJani Nikula */ 255900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, 256000376ccfSWambui Karuga "The master control interrupt lied (SDE)!\n"); 25612dfb0b81SJani Nikula } 256292d03a80SDaniel Vetter } 256392d03a80SDaniel Vetter 2564f11a0f46STvrtko Ursulin return ret; 2565f11a0f46STvrtko Ursulin } 2566f11a0f46STvrtko Ursulin 25674376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs) 25684376b9c9SMika Kuoppala { 25694376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, 0); 25704376b9c9SMika Kuoppala 25714376b9c9SMika Kuoppala /* 25724376b9c9SMika Kuoppala * Now with master disabled, get a sample of level indications 25734376b9c9SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 25744376b9c9SMika Kuoppala * New indications can and will light up during processing, 25754376b9c9SMika Kuoppala * and will generate new interrupt after enabling master. 25764376b9c9SMika Kuoppala */ 25774376b9c9SMika Kuoppala return raw_reg_read(regs, GEN8_MASTER_IRQ); 25784376b9c9SMika Kuoppala } 25794376b9c9SMika Kuoppala 25804376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs) 25814376b9c9SMika Kuoppala { 25824376b9c9SMika Kuoppala raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 25834376b9c9SMika Kuoppala } 25844376b9c9SMika Kuoppala 2585f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg) 2586f11a0f46STvrtko Ursulin { 2587b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 258825286aacSDaniele Ceraolo Spurio void __iomem * const regs = dev_priv->uncore.regs; 2589f11a0f46STvrtko Ursulin u32 master_ctl; 2590f11a0f46STvrtko Ursulin 2591f11a0f46STvrtko Ursulin if (!intel_irqs_enabled(dev_priv)) 2592f11a0f46STvrtko Ursulin return IRQ_NONE; 2593f11a0f46STvrtko Ursulin 25944376b9c9SMika Kuoppala master_ctl = gen8_master_intr_disable(regs); 25954376b9c9SMika Kuoppala if (!master_ctl) { 25964376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2597f11a0f46STvrtko Ursulin return IRQ_NONE; 25984376b9c9SMika Kuoppala } 2599f11a0f46STvrtko Ursulin 26006cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 26016cc32f15SChris Wilson gen8_gt_irq_handler(&dev_priv->gt, master_ctl); 2602f0fd96f5SChris Wilson 2603f0fd96f5SChris Wilson /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2604f0fd96f5SChris Wilson if (master_ctl & ~GEN8_GT_IRQS) { 26059102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 260655ef72f2SChris Wilson gen8_de_irq_handler(dev_priv, master_ctl); 26079102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 2608f0fd96f5SChris Wilson } 2609f11a0f46STvrtko Ursulin 26104376b9c9SMika Kuoppala gen8_master_intr_enable(regs); 2611abd58f01SBen Widawsky 26129c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 26139c6508b9SThomas Gleixner 261455ef72f2SChris Wilson return IRQ_HANDLED; 2615abd58f01SBen Widawsky } 2616abd58f01SBen Widawsky 261751951ae7SMika Kuoppala static u32 26189b77011eSTvrtko Ursulin gen11_gu_misc_irq_ack(struct intel_gt *gt, const u32 master_ctl) 2619df0d28c1SDhinakaran Pandiyan { 26209b77011eSTvrtko Ursulin void __iomem * const regs = gt->uncore->regs; 26217a909383SChris Wilson u32 iir; 2622df0d28c1SDhinakaran Pandiyan 2623df0d28c1SDhinakaran Pandiyan if (!(master_ctl & GEN11_GU_MISC_IRQ)) 26247a909383SChris Wilson return 0; 2625df0d28c1SDhinakaran Pandiyan 26267a909383SChris Wilson iir = raw_reg_read(regs, GEN11_GU_MISC_IIR); 26277a909383SChris Wilson if (likely(iir)) 26287a909383SChris Wilson raw_reg_write(regs, GEN11_GU_MISC_IIR, iir); 26297a909383SChris Wilson 26307a909383SChris Wilson return iir; 2631df0d28c1SDhinakaran Pandiyan } 2632df0d28c1SDhinakaran Pandiyan 2633df0d28c1SDhinakaran Pandiyan static void 26349b77011eSTvrtko Ursulin gen11_gu_misc_irq_handler(struct intel_gt *gt, const u32 iir) 2635df0d28c1SDhinakaran Pandiyan { 2636df0d28c1SDhinakaran Pandiyan if (iir & GEN11_GU_MISC_GSE) 26379b77011eSTvrtko Ursulin intel_opregion_asle_intr(gt->i915); 2638df0d28c1SDhinakaran Pandiyan } 2639df0d28c1SDhinakaran Pandiyan 264081067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs) 264181067b71SMika Kuoppala { 264281067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); 264381067b71SMika Kuoppala 264481067b71SMika Kuoppala /* 264581067b71SMika Kuoppala * Now with master disabled, get a sample of level indications 264681067b71SMika Kuoppala * for this interrupt. Indications will be cleared on related acks. 264781067b71SMika Kuoppala * New indications can and will light up during processing, 264881067b71SMika Kuoppala * and will generate new interrupt after enabling master. 264981067b71SMika Kuoppala */ 265081067b71SMika Kuoppala return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); 265181067b71SMika Kuoppala } 265281067b71SMika Kuoppala 265381067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs) 265481067b71SMika Kuoppala { 265581067b71SMika Kuoppala raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); 265681067b71SMika Kuoppala } 265781067b71SMika Kuoppala 2658a3265d85SMatt Roper static void 2659a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915) 2660a3265d85SMatt Roper { 2661a3265d85SMatt Roper void __iomem * const regs = i915->uncore.regs; 2662a3265d85SMatt Roper const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); 2663a3265d85SMatt Roper 2664a3265d85SMatt Roper disable_rpm_wakeref_asserts(&i915->runtime_pm); 2665a3265d85SMatt Roper /* 2666a3265d85SMatt Roper * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ 2667a3265d85SMatt Roper * for the display related bits. 2668a3265d85SMatt Roper */ 2669a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); 2670a3265d85SMatt Roper gen8_de_irq_handler(i915, disp_ctl); 2671a3265d85SMatt Roper raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 2672a3265d85SMatt Roper GEN11_DISPLAY_IRQ_ENABLE); 2673a3265d85SMatt Roper 2674a3265d85SMatt Roper enable_rpm_wakeref_asserts(&i915->runtime_pm); 2675a3265d85SMatt Roper } 2676a3265d85SMatt Roper 26777be8782aSLucas De Marchi static __always_inline irqreturn_t 26787be8782aSLucas De Marchi __gen11_irq_handler(struct drm_i915_private * const i915, 26797be8782aSLucas De Marchi u32 (*intr_disable)(void __iomem * const regs), 26807be8782aSLucas De Marchi void (*intr_enable)(void __iomem * const regs)) 268151951ae7SMika Kuoppala { 268225286aacSDaniele Ceraolo Spurio void __iomem * const regs = i915->uncore.regs; 26839b77011eSTvrtko Ursulin struct intel_gt *gt = &i915->gt; 268451951ae7SMika Kuoppala u32 master_ctl; 2685df0d28c1SDhinakaran Pandiyan u32 gu_misc_iir; 268651951ae7SMika Kuoppala 268751951ae7SMika Kuoppala if (!intel_irqs_enabled(i915)) 268851951ae7SMika Kuoppala return IRQ_NONE; 268951951ae7SMika Kuoppala 26907be8782aSLucas De Marchi master_ctl = intr_disable(regs); 269181067b71SMika Kuoppala if (!master_ctl) { 26927be8782aSLucas De Marchi intr_enable(regs); 269351951ae7SMika Kuoppala return IRQ_NONE; 269481067b71SMika Kuoppala } 269551951ae7SMika Kuoppala 26966cc32f15SChris Wilson /* Find, queue (onto bottom-halves), then clear each source */ 26979b77011eSTvrtko Ursulin gen11_gt_irq_handler(gt, master_ctl); 269851951ae7SMika Kuoppala 269951951ae7SMika Kuoppala /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 2700a3265d85SMatt Roper if (master_ctl & GEN11_DISPLAY_IRQ) 2701a3265d85SMatt Roper gen11_display_irq_handler(i915); 270251951ae7SMika Kuoppala 27039b77011eSTvrtko Ursulin gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl); 2704df0d28c1SDhinakaran Pandiyan 27057be8782aSLucas De Marchi intr_enable(regs); 270651951ae7SMika Kuoppala 27079b77011eSTvrtko Ursulin gen11_gu_misc_irq_handler(gt, gu_misc_iir); 2708df0d28c1SDhinakaran Pandiyan 27099c6508b9SThomas Gleixner pmu_irq_stats(i915, IRQ_HANDLED); 27109c6508b9SThomas Gleixner 271151951ae7SMika Kuoppala return IRQ_HANDLED; 271251951ae7SMika Kuoppala } 271351951ae7SMika Kuoppala 27147be8782aSLucas De Marchi static irqreturn_t gen11_irq_handler(int irq, void *arg) 27157be8782aSLucas De Marchi { 27167be8782aSLucas De Marchi return __gen11_irq_handler(arg, 27177be8782aSLucas De Marchi gen11_master_intr_disable, 27187be8782aSLucas De Marchi gen11_master_intr_enable); 27197be8782aSLucas De Marchi } 27207be8782aSLucas De Marchi 272197b492f5SLucas De Marchi static u32 dg1_master_intr_disable_and_ack(void __iomem * const regs) 272297b492f5SLucas De Marchi { 272397b492f5SLucas De Marchi u32 val; 272497b492f5SLucas De Marchi 272597b492f5SLucas De Marchi /* First disable interrupts */ 272697b492f5SLucas De Marchi raw_reg_write(regs, DG1_MSTR_UNIT_INTR, 0); 272797b492f5SLucas De Marchi 272897b492f5SLucas De Marchi /* Get the indication levels and ack the master unit */ 272997b492f5SLucas De Marchi val = raw_reg_read(regs, DG1_MSTR_UNIT_INTR); 273097b492f5SLucas De Marchi if (unlikely(!val)) 273197b492f5SLucas De Marchi return 0; 273297b492f5SLucas De Marchi 273397b492f5SLucas De Marchi raw_reg_write(regs, DG1_MSTR_UNIT_INTR, val); 273497b492f5SLucas De Marchi 273597b492f5SLucas De Marchi /* 273697b492f5SLucas De Marchi * Now with master disabled, get a sample of level indications 273797b492f5SLucas De Marchi * for this interrupt and ack them right away - we keep GEN11_MASTER_IRQ 273897b492f5SLucas De Marchi * out as this bit doesn't exist anymore for DG1 273997b492f5SLucas De Marchi */ 274097b492f5SLucas De Marchi val = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ) & ~GEN11_MASTER_IRQ; 274197b492f5SLucas De Marchi if (unlikely(!val)) 274297b492f5SLucas De Marchi return 0; 274397b492f5SLucas De Marchi 274497b492f5SLucas De Marchi raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, val); 274597b492f5SLucas De Marchi 274697b492f5SLucas De Marchi return val; 274797b492f5SLucas De Marchi } 274897b492f5SLucas De Marchi 274997b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs) 275097b492f5SLucas De Marchi { 275197b492f5SLucas De Marchi raw_reg_write(regs, DG1_MSTR_UNIT_INTR, DG1_MSTR_IRQ); 275297b492f5SLucas De Marchi } 275397b492f5SLucas De Marchi 275497b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg) 275597b492f5SLucas De Marchi { 275697b492f5SLucas De Marchi return __gen11_irq_handler(arg, 275797b492f5SLucas De Marchi dg1_master_intr_disable_and_ack, 275897b492f5SLucas De Marchi dg1_master_intr_enable); 275997b492f5SLucas De Marchi } 276097b492f5SLucas De Marchi 276142f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 276242f52ef8SKeith Packard * we use as a pipe index 276342f52ef8SKeith Packard */ 276408fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc) 27650a3e67a4SJesse Barnes { 276608fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 276708fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2768e9d21d7fSKeith Packard unsigned long irqflags; 276971e0ffa5SJesse Barnes 27701ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 277186e83e35SChris Wilson i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 277286e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 277386e83e35SChris Wilson 277486e83e35SChris Wilson return 0; 277586e83e35SChris Wilson } 277686e83e35SChris Wilson 27777d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc) 2778d938da6bSVille Syrjälä { 277908fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2780d938da6bSVille Syrjälä 27817d423af9SVille Syrjälä /* 27827d423af9SVille Syrjälä * Vblank interrupts fail to wake the device up from C2+. 27837d423af9SVille Syrjälä * Disabling render clock gating during C-states avoids 27847d423af9SVille Syrjälä * the problem. There is a small power cost so we do this 27857d423af9SVille Syrjälä * only when vblank interrupts are actually enabled. 27867d423af9SVille Syrjälä */ 27877d423af9SVille Syrjälä if (dev_priv->vblank_enabled++ == 0) 27882939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2789d938da6bSVille Syrjälä 279008fa8fd0SVille Syrjälä return i8xx_enable_vblank(crtc); 2791d938da6bSVille Syrjälä } 2792d938da6bSVille Syrjälä 279308fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc) 279486e83e35SChris Wilson { 279508fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 279608fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 279786e83e35SChris Wilson unsigned long irqflags; 279886e83e35SChris Wilson 279986e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 28007c463586SKeith Packard i915_enable_pipestat(dev_priv, pipe, 2801755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 28021ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 28038692d00eSChris Wilson 28040a3e67a4SJesse Barnes return 0; 28050a3e67a4SJesse Barnes } 28060a3e67a4SJesse Barnes 280708fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc) 2808f796cf8fSJesse Barnes { 280908fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 281008fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2811f796cf8fSJesse Barnes unsigned long irqflags; 2812a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 281386e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2814f796cf8fSJesse Barnes 2815f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2816fbdedaeaSVille Syrjälä ilk_enable_display_irq(dev_priv, bit); 2817b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2818b1f14ad0SJesse Barnes 28192e8bf223SDhinakaran Pandiyan /* Even though there is no DMC, frame counter can get stuck when 28202e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated. 28212e8bf223SDhinakaran Pandiyan */ 28222e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 282308fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 28242e8bf223SDhinakaran Pandiyan 2825b1f14ad0SJesse Barnes return 0; 2826b1f14ad0SJesse Barnes } 2827b1f14ad0SJesse Barnes 28289c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc, 28299c9e97c4SVandita Kulkarni bool enable) 28309c9e97c4SVandita Kulkarni { 28319c9e97c4SVandita Kulkarni struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); 28329c9e97c4SVandita Kulkarni enum port port; 28339c9e97c4SVandita Kulkarni u32 tmp; 28349c9e97c4SVandita Kulkarni 28359c9e97c4SVandita Kulkarni if (!(intel_crtc->mode_flags & 28369c9e97c4SVandita Kulkarni (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0))) 28379c9e97c4SVandita Kulkarni return false; 28389c9e97c4SVandita Kulkarni 28399c9e97c4SVandita Kulkarni /* for dual link cases we consider TE from slave */ 28409c9e97c4SVandita Kulkarni if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1) 28419c9e97c4SVandita Kulkarni port = PORT_B; 28429c9e97c4SVandita Kulkarni else 28439c9e97c4SVandita Kulkarni port = PORT_A; 28449c9e97c4SVandita Kulkarni 28452939eb06SJani Nikula tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_MASK_REG(port)); 28469c9e97c4SVandita Kulkarni if (enable) 28479c9e97c4SVandita Kulkarni tmp &= ~DSI_TE_EVENT; 28489c9e97c4SVandita Kulkarni else 28499c9e97c4SVandita Kulkarni tmp |= DSI_TE_EVENT; 28509c9e97c4SVandita Kulkarni 28512939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DSI_INTR_MASK_REG(port), tmp); 28529c9e97c4SVandita Kulkarni 28532939eb06SJani Nikula tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port)); 28542939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp); 28559c9e97c4SVandita Kulkarni 28569c9e97c4SVandita Kulkarni return true; 28579c9e97c4SVandita Kulkarni } 28589c9e97c4SVandita Kulkarni 285908fa8fd0SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *crtc) 2860abd58f01SBen Widawsky { 286108fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 28629c9e97c4SVandita Kulkarni struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 28639c9e97c4SVandita Kulkarni enum pipe pipe = intel_crtc->pipe; 2864abd58f01SBen Widawsky unsigned long irqflags; 2865abd58f01SBen Widawsky 28669c9e97c4SVandita Kulkarni if (gen11_dsi_configure_te(intel_crtc, true)) 28679c9e97c4SVandita Kulkarni return 0; 28689c9e97c4SVandita Kulkarni 2869abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2870013d3752SVille Syrjälä bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2871abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2872013d3752SVille Syrjälä 28732e8bf223SDhinakaran Pandiyan /* Even if there is no DMC, frame counter can get stuck when 28742e8bf223SDhinakaran Pandiyan * PSR is active as no frames are generated, so check only for PSR. 28752e8bf223SDhinakaran Pandiyan */ 28762e8bf223SDhinakaran Pandiyan if (HAS_PSR(dev_priv)) 287708fa8fd0SVille Syrjälä drm_crtc_vblank_restore(crtc); 28782e8bf223SDhinakaran Pandiyan 2879abd58f01SBen Widawsky return 0; 2880abd58f01SBen Widawsky } 2881abd58f01SBen Widawsky 288242f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which 288342f52ef8SKeith Packard * we use as a pipe index 288442f52ef8SKeith Packard */ 288508fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc) 288686e83e35SChris Wilson { 288708fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 288808fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 288986e83e35SChris Wilson unsigned long irqflags; 289086e83e35SChris Wilson 289186e83e35SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 289286e83e35SChris Wilson i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); 289386e83e35SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 289486e83e35SChris Wilson } 289586e83e35SChris Wilson 28967d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc) 2897d938da6bSVille Syrjälä { 289808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 2899d938da6bSVille Syrjälä 290008fa8fd0SVille Syrjälä i8xx_disable_vblank(crtc); 2901d938da6bSVille Syrjälä 29027d423af9SVille Syrjälä if (--dev_priv->vblank_enabled == 0) 29032939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); 2904d938da6bSVille Syrjälä } 2905d938da6bSVille Syrjälä 290608fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc) 29070a3e67a4SJesse Barnes { 290808fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 290908fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2910e9d21d7fSKeith Packard unsigned long irqflags; 29110a3e67a4SJesse Barnes 29121ec14ad3SChris Wilson spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 29137c463586SKeith Packard i915_disable_pipestat(dev_priv, pipe, 2914755e9019SImre Deak PIPE_START_VBLANK_INTERRUPT_STATUS); 29151ec14ad3SChris Wilson spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 29160a3e67a4SJesse Barnes } 29170a3e67a4SJesse Barnes 291808fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc) 2919f796cf8fSJesse Barnes { 292008fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 292108fa8fd0SVille Syrjälä enum pipe pipe = to_intel_crtc(crtc)->pipe; 2922f796cf8fSJesse Barnes unsigned long irqflags; 2923a9c287c9SJani Nikula u32 bit = INTEL_GEN(dev_priv) >= 7 ? 292486e83e35SChris Wilson DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); 2925f796cf8fSJesse Barnes 2926f796cf8fSJesse Barnes spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2927fbdedaeaSVille Syrjälä ilk_disable_display_irq(dev_priv, bit); 2928b1f14ad0SJesse Barnes spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2929b1f14ad0SJesse Barnes } 2930b1f14ad0SJesse Barnes 293108fa8fd0SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *crtc) 2932abd58f01SBen Widawsky { 293308fa8fd0SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc->dev); 29349c9e97c4SVandita Kulkarni struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 29359c9e97c4SVandita Kulkarni enum pipe pipe = intel_crtc->pipe; 2936abd58f01SBen Widawsky unsigned long irqflags; 2937abd58f01SBen Widawsky 29389c9e97c4SVandita Kulkarni if (gen11_dsi_configure_te(intel_crtc, false)) 29399c9e97c4SVandita Kulkarni return; 29409c9e97c4SVandita Kulkarni 2941abd58f01SBen Widawsky spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2942013d3752SVille Syrjälä bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2943abd58f01SBen Widawsky spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2944abd58f01SBen Widawsky } 2945abd58f01SBen Widawsky 2946b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv) 294791738a95SPaulo Zanoni { 2948b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2949b16b2a2fSPaulo Zanoni 29506e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 295191738a95SPaulo Zanoni return; 295291738a95SPaulo Zanoni 2953b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 2954105b122eSPaulo Zanoni 29556e266956STvrtko Ursulin if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 29562939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff); 2957622364b6SPaulo Zanoni } 2958105b122eSPaulo Zanoni 295970591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) 296070591a41SVille Syrjälä { 2961b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2962b16b2a2fSPaulo Zanoni 296371b8b41dSVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2964f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 296571b8b41dSVille Syrjälä else 2966f0818984STvrtko Ursulin intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK); 296771b8b41dSVille Syrjälä 2968ad22d106SVille Syrjälä i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); 29692939eb06SJani Nikula intel_uncore_write(uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 297070591a41SVille Syrjälä 297144d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 297270591a41SVille Syrjälä 2973b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, VLV_); 29748bd099a7SChris Wilson dev_priv->irq_mask = ~0u; 297570591a41SVille Syrjälä } 297670591a41SVille Syrjälä 29778bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) 29788bb61306SVille Syrjälä { 2979b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 2980b16b2a2fSPaulo Zanoni 29818bb61306SVille Syrjälä u32 pipestat_mask; 29829ab981f2SVille Syrjälä u32 enable_mask; 29838bb61306SVille Syrjälä enum pipe pipe; 29848bb61306SVille Syrjälä 2985842ebf7aSVille Syrjälä pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; 29868bb61306SVille Syrjälä 29878bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 29888bb61306SVille Syrjälä for_each_pipe(dev_priv, pipe) 29898bb61306SVille Syrjälä i915_enable_pipestat(dev_priv, pipe, pipestat_mask); 29908bb61306SVille Syrjälä 29919ab981f2SVille Syrjälä enable_mask = I915_DISPLAY_PORT_INTERRUPT | 29928bb61306SVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 2993ebf5f921SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 2994ebf5f921SVille Syrjälä I915_LPE_PIPE_A_INTERRUPT | 2995ebf5f921SVille Syrjälä I915_LPE_PIPE_B_INTERRUPT; 2996ebf5f921SVille Syrjälä 29978bb61306SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 2998ebf5f921SVille Syrjälä enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 2999ebf5f921SVille Syrjälä I915_LPE_PIPE_C_INTERRUPT; 30006b7eafc1SVille Syrjälä 300148a1b8d4SPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u); 30026b7eafc1SVille Syrjälä 30039ab981f2SVille Syrjälä dev_priv->irq_mask = ~enable_mask; 30048bb61306SVille Syrjälä 3005b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask); 30068bb61306SVille Syrjälä } 30078bb61306SVille Syrjälä 30088bb61306SVille Syrjälä /* drm_dma.h hooks 30098bb61306SVille Syrjälä */ 30109eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv) 30118bb61306SVille Syrjälä { 3012b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 30138bb61306SVille Syrjälä 3014b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, DE); 3015e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3016e44adb5dSChris Wilson 3017cf819effSLucas De Marchi if (IS_GEN(dev_priv, 7)) 3018f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); 30198bb61306SVille Syrjälä 3020fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3021f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 3022f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 3023fc340442SDaniel Vetter } 3024fc340442SDaniel Vetter 3025cf1c97dcSAndi Shyti gen5_gt_irq_reset(&dev_priv->gt); 30268bb61306SVille Syrjälä 3027b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 30288bb61306SVille Syrjälä } 30298bb61306SVille Syrjälä 3030b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv) 30317e231dbeSJesse Barnes { 30322939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); 30332939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 303434c7b8a7SVille Syrjälä 3035cf1c97dcSAndi Shyti gen5_gt_irq_reset(&dev_priv->gt); 30367e231dbeSJesse Barnes 3037ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 30389918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 303970591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3040ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 30417e231dbeSJesse Barnes } 30427e231dbeSJesse Barnes 3043b318b824SVille Syrjälä static void gen8_irq_reset(struct drm_i915_private *dev_priv) 3044abd58f01SBen Widawsky { 3045b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3046d048a268SVille Syrjälä enum pipe pipe; 3047abd58f01SBen Widawsky 304825286aacSDaniele Ceraolo Spurio gen8_master_intr_disable(dev_priv->uncore.regs); 3049abd58f01SBen Widawsky 3050cf1c97dcSAndi Shyti gen8_gt_irq_reset(&dev_priv->gt); 3051abd58f01SBen Widawsky 3052f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 3053f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 3054e04f7eceSVille Syrjälä 3055055e393fSDamien Lespiau for_each_pipe(dev_priv, pipe) 3056f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3057813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3058b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 3059abd58f01SBen Widawsky 3060b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 3061b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 3062b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 3063abd58f01SBen Widawsky 30646e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 3065b243f530STvrtko Ursulin ibx_irq_reset(dev_priv); 3066abd58f01SBen Widawsky } 3067abd58f01SBen Widawsky 3068a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) 306951951ae7SMika Kuoppala { 3070b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3071d048a268SVille Syrjälä enum pipe pipe; 3072562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 3073562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 307451951ae7SMika Kuoppala 3075f0818984STvrtko Ursulin intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); 307651951ae7SMika Kuoppala 30778241cfbeSJosé Roberto de Souza if (INTEL_GEN(dev_priv) >= 12) { 30788241cfbeSJosé Roberto de Souza enum transcoder trans; 30798241cfbeSJosé Roberto de Souza 3080562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 30818241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 30828241cfbeSJosé Roberto de Souza 30838241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 30848241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 30858241cfbeSJosé Roberto de Souza continue; 30868241cfbeSJosé Roberto de Souza 30878241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff); 30888241cfbeSJosé Roberto de Souza intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff); 30898241cfbeSJosé Roberto de Souza } 30908241cfbeSJosé Roberto de Souza } else { 3091f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 3092f0818984STvrtko Ursulin intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 30938241cfbeSJosé Roberto de Souza } 309462819dfdSJosé Roberto de Souza 309551951ae7SMika Kuoppala for_each_pipe(dev_priv, pipe) 309651951ae7SMika Kuoppala if (intel_display_power_is_enabled(dev_priv, 309751951ae7SMika Kuoppala POWER_DOMAIN_PIPE(pipe))) 3098b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 309951951ae7SMika Kuoppala 3100b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); 3101b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); 3102b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); 310331604222SAnusha Srivatsa 310429b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 3105b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, SDE); 31069b2383a7SMatt Roper 3107b896898cSBob Paauwe /* Wa_14010685332:cnp/cmp,tgp,adp */ 3108b896898cSBob Paauwe if (INTEL_PCH_TYPE(dev_priv) == PCH_CNP || 3109b896898cSBob Paauwe (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && 3110b896898cSBob Paauwe INTEL_PCH_TYPE(dev_priv) < PCH_DG1)) { 31119b2383a7SMatt Roper intel_uncore_rmw(uncore, SOUTH_CHICKEN1, 31129b2383a7SMatt Roper SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS); 31139b2383a7SMatt Roper intel_uncore_rmw(uncore, SOUTH_CHICKEN1, 31149b2383a7SMatt Roper SBCLK_RUN_REFCLK_DIS, 0); 31159b2383a7SMatt Roper } 311651951ae7SMika Kuoppala } 311751951ae7SMika Kuoppala 3118a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv) 3119a3265d85SMatt Roper { 3120a3265d85SMatt Roper struct intel_uncore *uncore = &dev_priv->uncore; 3121a3265d85SMatt Roper 312297b492f5SLucas De Marchi if (HAS_MASTER_UNIT_IRQ(dev_priv)) 312397b492f5SLucas De Marchi dg1_master_intr_disable_and_ack(dev_priv->uncore.regs); 312497b492f5SLucas De Marchi else 3125a3265d85SMatt Roper gen11_master_intr_disable(dev_priv->uncore.regs); 3126a3265d85SMatt Roper 3127a3265d85SMatt Roper gen11_gt_irq_reset(&dev_priv->gt); 3128a3265d85SMatt Roper gen11_display_irq_reset(dev_priv); 3129a3265d85SMatt Roper 3130a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); 3131a3265d85SMatt Roper GEN3_IRQ_RESET(uncore, GEN8_PCU_); 3132a3265d85SMatt Roper } 3133a3265d85SMatt Roper 31344c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, 3135001bd2cbSImre Deak u8 pipe_mask) 3136d49bdb0eSPaulo Zanoni { 3137b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3138cda195f1SVille Syrjälä u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | 3139cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 31406831f3e3SVille Syrjälä enum pipe pipe; 3141d49bdb0eSPaulo Zanoni 314213321786SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 31439dfe2e3aSImre Deak 31449dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 31459dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 31469dfe2e3aSImre Deak return; 31479dfe2e3aSImre Deak } 31489dfe2e3aSImre Deak 31496831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 3150b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 31516831f3e3SVille Syrjälä dev_priv->de_irq_mask[pipe], 31526831f3e3SVille Syrjälä ~dev_priv->de_irq_mask[pipe] | extra_ier); 31539dfe2e3aSImre Deak 315413321786SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3155d49bdb0eSPaulo Zanoni } 3156d49bdb0eSPaulo Zanoni 3157aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, 3158001bd2cbSImre Deak u8 pipe_mask) 3159aae8ba84SVille Syrjälä { 3160b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 31616831f3e3SVille Syrjälä enum pipe pipe; 31626831f3e3SVille Syrjälä 3163aae8ba84SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 31649dfe2e3aSImre Deak 31659dfe2e3aSImre Deak if (!intel_irqs_enabled(dev_priv)) { 31669dfe2e3aSImre Deak spin_unlock_irq(&dev_priv->irq_lock); 31679dfe2e3aSImre Deak return; 31689dfe2e3aSImre Deak } 31699dfe2e3aSImre Deak 31706831f3e3SVille Syrjälä for_each_pipe_masked(dev_priv, pipe, pipe_mask) 3171b16b2a2fSPaulo Zanoni GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe); 31729dfe2e3aSImre Deak 3173aae8ba84SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3174aae8ba84SVille Syrjälä 3175aae8ba84SVille Syrjälä /* make sure we're done processing display irqs */ 3176315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 3177aae8ba84SVille Syrjälä } 3178aae8ba84SVille Syrjälä 3179b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv) 318043f328d7SVille Syrjälä { 3181b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 318243f328d7SVille Syrjälä 31832939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0); 31842939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 318543f328d7SVille Syrjälä 3186cf1c97dcSAndi Shyti gen8_gt_irq_reset(&dev_priv->gt); 318743f328d7SVille Syrjälä 3188b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN8_PCU_); 318943f328d7SVille Syrjälä 3190ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 31919918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 319270591a41SVille Syrjälä vlv_display_irq_reset(dev_priv); 3193ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 319443f328d7SVille Syrjälä } 319543f328d7SVille Syrjälä 31962ea63927SVille Syrjälä static u32 ibx_hotplug_enables(struct drm_i915_private *i915, 31972ea63927SVille Syrjälä enum hpd_pin pin) 31982ea63927SVille Syrjälä { 31992ea63927SVille Syrjälä switch (pin) { 32002ea63927SVille Syrjälä case HPD_PORT_A: 32012ea63927SVille Syrjälä /* 32022ea63927SVille Syrjälä * When CPU and PCH are on the same package, port A 32032ea63927SVille Syrjälä * HPD must be enabled in both north and south. 32042ea63927SVille Syrjälä */ 32052ea63927SVille Syrjälä return HAS_PCH_LPT_LP(i915) ? 32062ea63927SVille Syrjälä PORTA_HOTPLUG_ENABLE : 0; 32072ea63927SVille Syrjälä case HPD_PORT_B: 32082ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE | 32092ea63927SVille Syrjälä PORTB_PULSE_DURATION_2ms; 32102ea63927SVille Syrjälä case HPD_PORT_C: 32112ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE | 32122ea63927SVille Syrjälä PORTC_PULSE_DURATION_2ms; 32132ea63927SVille Syrjälä case HPD_PORT_D: 32142ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE | 32152ea63927SVille Syrjälä PORTD_PULSE_DURATION_2ms; 32162ea63927SVille Syrjälä default: 32172ea63927SVille Syrjälä return 0; 32182ea63927SVille Syrjälä } 32192ea63927SVille Syrjälä } 32202ea63927SVille Syrjälä 32211a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) 32221a56b1a2SImre Deak { 32231a56b1a2SImre Deak u32 hotplug; 32241a56b1a2SImre Deak 32251a56b1a2SImre Deak /* 32261a56b1a2SImre Deak * Enable digital hotplug on the PCH, and configure the DP short pulse 32271a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec). 32281a56b1a2SImre Deak * The pulse duration bits are reserved on LPT+. 32291a56b1a2SImre Deak */ 32302939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 32312ea63927SVille Syrjälä hotplug &= ~(PORTA_HOTPLUG_ENABLE | 32322ea63927SVille Syrjälä PORTB_HOTPLUG_ENABLE | 32332ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 32342ea63927SVille Syrjälä PORTD_HOTPLUG_ENABLE | 32352ea63927SVille Syrjälä PORTB_PULSE_DURATION_MASK | 32361a56b1a2SImre Deak PORTC_PULSE_DURATION_MASK | 32371a56b1a2SImre Deak PORTD_PULSE_DURATION_MASK); 32382ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables); 32392939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); 32401a56b1a2SImre Deak } 32411a56b1a2SImre Deak 324291d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) 324382a28bcfSDaniel Vetter { 32441a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 324582a28bcfSDaniel Vetter 32460398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 32476d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 324882a28bcfSDaniel Vetter 3249fee884edSDaniel Vetter ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 325082a28bcfSDaniel Vetter 32511a56b1a2SImre Deak ibx_hpd_detection_setup(dev_priv); 32526dbf30ceSVille Syrjälä } 325326951cafSXiong Zhang 32542ea63927SVille Syrjälä static u32 icp_ddi_hotplug_enables(struct drm_i915_private *i915, 32552ea63927SVille Syrjälä enum hpd_pin pin) 32562ea63927SVille Syrjälä { 32572ea63927SVille Syrjälä switch (pin) { 32582ea63927SVille Syrjälä case HPD_PORT_A: 32592ea63927SVille Syrjälä case HPD_PORT_B: 32602ea63927SVille Syrjälä case HPD_PORT_C: 32612ea63927SVille Syrjälä case HPD_PORT_D: 32622ea63927SVille Syrjälä return SHOTPLUG_CTL_DDI_HPD_ENABLE(pin); 32632ea63927SVille Syrjälä default: 32642ea63927SVille Syrjälä return 0; 32652ea63927SVille Syrjälä } 32662ea63927SVille Syrjälä } 32672ea63927SVille Syrjälä 32682ea63927SVille Syrjälä static u32 icp_tc_hotplug_enables(struct drm_i915_private *i915, 32692ea63927SVille Syrjälä enum hpd_pin pin) 32702ea63927SVille Syrjälä { 32712ea63927SVille Syrjälä switch (pin) { 32722ea63927SVille Syrjälä case HPD_PORT_TC1: 32732ea63927SVille Syrjälä case HPD_PORT_TC2: 32742ea63927SVille Syrjälä case HPD_PORT_TC3: 32752ea63927SVille Syrjälä case HPD_PORT_TC4: 32762ea63927SVille Syrjälä case HPD_PORT_TC5: 32772ea63927SVille Syrjälä case HPD_PORT_TC6: 32782ea63927SVille Syrjälä return ICP_TC_HPD_ENABLE(pin); 32792ea63927SVille Syrjälä default: 32802ea63927SVille Syrjälä return 0; 32812ea63927SVille Syrjälä } 32822ea63927SVille Syrjälä } 32832ea63927SVille Syrjälä 32842ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv) 328531604222SAnusha Srivatsa { 328631604222SAnusha Srivatsa u32 hotplug; 328731604222SAnusha Srivatsa 32882939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI); 32892ea63927SVille Syrjälä hotplug &= ~(SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) | 32902ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) | 32912ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) | 32922ea63927SVille Syrjälä SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D)); 32932ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables); 32942939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, hotplug); 329531604222SAnusha Srivatsa } 3296815f4ef2SVille Syrjälä 32972ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 3298815f4ef2SVille Syrjälä { 3299815f4ef2SVille Syrjälä u32 hotplug; 3300815f4ef2SVille Syrjälä 33012939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC); 33022ea63927SVille Syrjälä hotplug &= ~(ICP_TC_HPD_ENABLE(HPD_PORT_TC1) | 33032ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC2) | 33042ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC3) | 33052ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC4) | 33062ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC5) | 33072ea63927SVille Syrjälä ICP_TC_HPD_ENABLE(HPD_PORT_TC6)); 33082ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables); 33092939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, hotplug); 33108ef7e340SMatt Roper } 331131604222SAnusha Srivatsa 33122ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) 331331604222SAnusha Srivatsa { 331431604222SAnusha Srivatsa u32 hotplug_irqs, enabled_irqs; 331531604222SAnusha Srivatsa 33160398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 33176d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 331831604222SAnusha Srivatsa 3319f619e516SAnusha Srivatsa if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) 33202939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 3321f49108d0SMatt Roper 332231604222SAnusha Srivatsa ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 332331604222SAnusha Srivatsa 33242ea63927SVille Syrjälä icp_ddi_hpd_detection_setup(dev_priv); 33252ea63927SVille Syrjälä icp_tc_hpd_detection_setup(dev_priv); 332652dfdba0SLucas De Marchi } 332752dfdba0SLucas De Marchi 33282ea63927SVille Syrjälä static u32 gen11_hotplug_enables(struct drm_i915_private *i915, 33292ea63927SVille Syrjälä enum hpd_pin pin) 33308ef7e340SMatt Roper { 33312ea63927SVille Syrjälä switch (pin) { 33322ea63927SVille Syrjälä case HPD_PORT_TC1: 33332ea63927SVille Syrjälä case HPD_PORT_TC2: 33342ea63927SVille Syrjälä case HPD_PORT_TC3: 33352ea63927SVille Syrjälä case HPD_PORT_TC4: 33362ea63927SVille Syrjälä case HPD_PORT_TC5: 33372ea63927SVille Syrjälä case HPD_PORT_TC6: 33382ea63927SVille Syrjälä return GEN11_HOTPLUG_CTL_ENABLE(pin); 33392ea63927SVille Syrjälä default: 33402ea63927SVille Syrjälä return 0; 334131604222SAnusha Srivatsa } 3342943682e3SMatt Roper } 3343943682e3SMatt Roper 3344229f31e2SLucas De Marchi static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) 3345229f31e2SLucas De Marchi { 3346b18c1eb9SClinton A Taylor u32 val; 3347b18c1eb9SClinton A Taylor 33482939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1); 3349b18c1eb9SClinton A Taylor val |= (INVERT_DDIA_HPD | 3350b18c1eb9SClinton A Taylor INVERT_DDIB_HPD | 3351b18c1eb9SClinton A Taylor INVERT_DDIC_HPD | 3352b18c1eb9SClinton A Taylor INVERT_DDID_HPD); 33532939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val); 3354b18c1eb9SClinton A Taylor 33552ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 3356229f31e2SLucas De Marchi } 3357229f31e2SLucas De Marchi 335852c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) 3359121e758eSDhinakaran Pandiyan { 3360121e758eSDhinakaran Pandiyan u32 hotplug; 3361121e758eSDhinakaran Pandiyan 33622939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL); 33632ea63927SVille Syrjälä hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 33645b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 33655b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 33665b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 33675b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 33682ea63927SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); 33692ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); 33702939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, hotplug); 337152c7f5f1SVille Syrjälä } 337252c7f5f1SVille Syrjälä 337352c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv) 337452c7f5f1SVille Syrjälä { 337552c7f5f1SVille Syrjälä u32 hotplug; 3376b796b971SDhinakaran Pandiyan 33772939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL); 33782ea63927SVille Syrjälä hotplug &= ~(GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) | 33795b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) | 33805b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) | 33815b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) | 33825b76e860SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) | 33832ea63927SVille Syrjälä GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6)); 33842ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables); 33852939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, hotplug); 3386121e758eSDhinakaran Pandiyan } 3387121e758eSDhinakaran Pandiyan 3388121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) 3389121e758eSDhinakaran Pandiyan { 3390121e758eSDhinakaran Pandiyan u32 hotplug_irqs, enabled_irqs; 3391121e758eSDhinakaran Pandiyan u32 val; 3392121e758eSDhinakaran Pandiyan 33930398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); 33946d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); 3395121e758eSDhinakaran Pandiyan 33962939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); 3397121e758eSDhinakaran Pandiyan val &= ~hotplug_irqs; 3398587a87b9SImre Deak val |= ~enabled_irqs & hotplug_irqs; 33992939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IMR, val); 34002939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); 3401121e758eSDhinakaran Pandiyan 340252c7f5f1SVille Syrjälä gen11_tc_hpd_detection_setup(dev_priv); 340352c7f5f1SVille Syrjälä gen11_tbt_hpd_detection_setup(dev_priv); 340431604222SAnusha Srivatsa 34052ea63927SVille Syrjälä if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 34062ea63927SVille Syrjälä icp_hpd_irq_setup(dev_priv); 34072ea63927SVille Syrjälä } 34082ea63927SVille Syrjälä 34092ea63927SVille Syrjälä static u32 spt_hotplug_enables(struct drm_i915_private *i915, 34102ea63927SVille Syrjälä enum hpd_pin pin) 34112ea63927SVille Syrjälä { 34122ea63927SVille Syrjälä switch (pin) { 34132ea63927SVille Syrjälä case HPD_PORT_A: 34142ea63927SVille Syrjälä return PORTA_HOTPLUG_ENABLE; 34152ea63927SVille Syrjälä case HPD_PORT_B: 34162ea63927SVille Syrjälä return PORTB_HOTPLUG_ENABLE; 34172ea63927SVille Syrjälä case HPD_PORT_C: 34182ea63927SVille Syrjälä return PORTC_HOTPLUG_ENABLE; 34192ea63927SVille Syrjälä case HPD_PORT_D: 34202ea63927SVille Syrjälä return PORTD_HOTPLUG_ENABLE; 34212ea63927SVille Syrjälä default: 34222ea63927SVille Syrjälä return 0; 34232ea63927SVille Syrjälä } 34242ea63927SVille Syrjälä } 34252ea63927SVille Syrjälä 34262ea63927SVille Syrjälä static u32 spt_hotplug2_enables(struct drm_i915_private *i915, 34272ea63927SVille Syrjälä enum hpd_pin pin) 34282ea63927SVille Syrjälä { 34292ea63927SVille Syrjälä switch (pin) { 34302ea63927SVille Syrjälä case HPD_PORT_E: 34312ea63927SVille Syrjälä return PORTE_HOTPLUG_ENABLE; 34322ea63927SVille Syrjälä default: 34332ea63927SVille Syrjälä return 0; 34342ea63927SVille Syrjälä } 3435121e758eSDhinakaran Pandiyan } 3436121e758eSDhinakaran Pandiyan 34372a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) 34382a57d9ccSImre Deak { 34393b92e263SRodrigo Vivi u32 val, hotplug; 34403b92e263SRodrigo Vivi 34413b92e263SRodrigo Vivi /* Display WA #1179 WaHardHangonHotPlug: cnp */ 34423b92e263SRodrigo Vivi if (HAS_PCH_CNP(dev_priv)) { 34432939eb06SJani Nikula val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1); 34443b92e263SRodrigo Vivi val &= ~CHASSIS_CLK_REQ_DURATION_MASK; 34453b92e263SRodrigo Vivi val |= CHASSIS_CLK_REQ_DURATION(0xf); 34462939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val); 34473b92e263SRodrigo Vivi } 34482a57d9ccSImre Deak 34492a57d9ccSImre Deak /* Enable digital hotplug on the PCH */ 34502939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 34512ea63927SVille Syrjälä hotplug &= ~(PORTA_HOTPLUG_ENABLE | 34522a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 34532a57d9ccSImre Deak PORTC_HOTPLUG_ENABLE | 34542ea63927SVille Syrjälä PORTD_HOTPLUG_ENABLE); 34552ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables); 34562939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); 34572a57d9ccSImre Deak 34582939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2); 34592ea63927SVille Syrjälä hotplug &= ~PORTE_HOTPLUG_ENABLE; 34602ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables); 34612939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, hotplug); 34622a57d9ccSImre Deak } 34632a57d9ccSImre Deak 346491d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) 34656dbf30ceSVille Syrjälä { 34662a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 34676dbf30ceSVille Syrjälä 3468f49108d0SMatt Roper if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) 34692939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); 3470f49108d0SMatt Roper 34710398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 34726d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); 34736dbf30ceSVille Syrjälä 34746dbf30ceSVille Syrjälä ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); 34756dbf30ceSVille Syrjälä 34762a57d9ccSImre Deak spt_hpd_detection_setup(dev_priv); 347726951cafSXiong Zhang } 34787fe0b973SKeith Packard 34792ea63927SVille Syrjälä static u32 ilk_hotplug_enables(struct drm_i915_private *i915, 34802ea63927SVille Syrjälä enum hpd_pin pin) 34812ea63927SVille Syrjälä { 34822ea63927SVille Syrjälä switch (pin) { 34832ea63927SVille Syrjälä case HPD_PORT_A: 34842ea63927SVille Syrjälä return DIGITAL_PORTA_HOTPLUG_ENABLE | 34852ea63927SVille Syrjälä DIGITAL_PORTA_PULSE_DURATION_2ms; 34862ea63927SVille Syrjälä default: 34872ea63927SVille Syrjälä return 0; 34882ea63927SVille Syrjälä } 34892ea63927SVille Syrjälä } 34902ea63927SVille Syrjälä 34911a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) 34921a56b1a2SImre Deak { 34931a56b1a2SImre Deak u32 hotplug; 34941a56b1a2SImre Deak 34951a56b1a2SImre Deak /* 34961a56b1a2SImre Deak * Enable digital hotplug on the CPU, and configure the DP short pulse 34971a56b1a2SImre Deak * duration to 2ms (which is the minimum in the Display Port spec) 34981a56b1a2SImre Deak * The pulse duration bits are reserved on HSW+. 34991a56b1a2SImre Deak */ 35002939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL); 35012ea63927SVille Syrjälä hotplug &= ~(DIGITAL_PORTA_HOTPLUG_ENABLE | 35022ea63927SVille Syrjälä DIGITAL_PORTA_PULSE_DURATION_MASK); 35032ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables); 35042939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, hotplug); 35051a56b1a2SImre Deak } 35061a56b1a2SImre Deak 350791d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) 3508e4ce95aaSVille Syrjälä { 35091a56b1a2SImre Deak u32 hotplug_irqs, enabled_irqs; 3510e4ce95aaSVille Syrjälä 35110398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); 35126d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); 35133a3b3c7dSVille Syrjälä 35146d3144ebSVille Syrjälä if (INTEL_GEN(dev_priv) >= 8) 35153a3b3c7dSVille Syrjälä bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 35166d3144ebSVille Syrjälä else 35173a3b3c7dSVille Syrjälä ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); 3518e4ce95aaSVille Syrjälä 35191a56b1a2SImre Deak ilk_hpd_detection_setup(dev_priv); 3520e4ce95aaSVille Syrjälä 352191d14251STvrtko Ursulin ibx_hpd_irq_setup(dev_priv); 3522e4ce95aaSVille Syrjälä } 3523e4ce95aaSVille Syrjälä 35242ea63927SVille Syrjälä static u32 bxt_hotplug_enables(struct drm_i915_private *i915, 35252ea63927SVille Syrjälä enum hpd_pin pin) 35262ea63927SVille Syrjälä { 35272ea63927SVille Syrjälä u32 hotplug; 35282ea63927SVille Syrjälä 35292ea63927SVille Syrjälä switch (pin) { 35302ea63927SVille Syrjälä case HPD_PORT_A: 35312ea63927SVille Syrjälä hotplug = PORTA_HOTPLUG_ENABLE; 35322ea63927SVille Syrjälä if (intel_bios_is_port_hpd_inverted(i915, PORT_A)) 35332ea63927SVille Syrjälä hotplug |= BXT_DDIA_HPD_INVERT; 35342ea63927SVille Syrjälä return hotplug; 35352ea63927SVille Syrjälä case HPD_PORT_B: 35362ea63927SVille Syrjälä hotplug = PORTB_HOTPLUG_ENABLE; 35372ea63927SVille Syrjälä if (intel_bios_is_port_hpd_inverted(i915, PORT_B)) 35382ea63927SVille Syrjälä hotplug |= BXT_DDIB_HPD_INVERT; 35392ea63927SVille Syrjälä return hotplug; 35402ea63927SVille Syrjälä case HPD_PORT_C: 35412ea63927SVille Syrjälä hotplug = PORTC_HOTPLUG_ENABLE; 35422ea63927SVille Syrjälä if (intel_bios_is_port_hpd_inverted(i915, PORT_C)) 35432ea63927SVille Syrjälä hotplug |= BXT_DDIC_HPD_INVERT; 35442ea63927SVille Syrjälä return hotplug; 35452ea63927SVille Syrjälä default: 35462ea63927SVille Syrjälä return 0; 35472ea63927SVille Syrjälä } 35482ea63927SVille Syrjälä } 35492ea63927SVille Syrjälä 35502ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) 3551e0a20ad7SShashank Sharma { 35522a57d9ccSImre Deak u32 hotplug; 3553e0a20ad7SShashank Sharma 35542939eb06SJani Nikula hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG); 35552ea63927SVille Syrjälä hotplug &= ~(PORTA_HOTPLUG_ENABLE | 35562a57d9ccSImre Deak PORTB_HOTPLUG_ENABLE | 35572ea63927SVille Syrjälä PORTC_HOTPLUG_ENABLE | 35582ea63927SVille Syrjälä BXT_DDIA_HPD_INVERT | 35592ea63927SVille Syrjälä BXT_DDIB_HPD_INVERT | 35602ea63927SVille Syrjälä BXT_DDIC_HPD_INVERT); 35612ea63927SVille Syrjälä hotplug |= intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables); 35622939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug); 3563e0a20ad7SShashank Sharma } 3564e0a20ad7SShashank Sharma 35652a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) 35662a57d9ccSImre Deak { 35672a57d9ccSImre Deak u32 hotplug_irqs, enabled_irqs; 35682a57d9ccSImre Deak 35690398993bSVille Syrjälä enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); 35706d3144ebSVille Syrjälä hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); 35712a57d9ccSImre Deak 35722a57d9ccSImre Deak bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); 35732a57d9ccSImre Deak 35742ea63927SVille Syrjälä bxt_hpd_detection_setup(dev_priv); 35752a57d9ccSImre Deak } 35762a57d9ccSImre Deak 3577a0a6d8cbSVille Syrjälä /* 3578a0a6d8cbSVille Syrjälä * SDEIER is also touched by the interrupt handler to work around missed PCH 3579a0a6d8cbSVille Syrjälä * interrupts. Hence we can't update it after the interrupt handler is enabled - 3580a0a6d8cbSVille Syrjälä * instead we unconditionally enable all PCH interrupt sources here, but then 3581a0a6d8cbSVille Syrjälä * only unmask them as needed with SDEIMR. 3582a0a6d8cbSVille Syrjälä * 3583a0a6d8cbSVille Syrjälä * Note that we currently do this after installing the interrupt handler, 3584a0a6d8cbSVille Syrjälä * but before we enable the master interrupt. That should be sufficient 3585a0a6d8cbSVille Syrjälä * to avoid races with the irq handler, assuming we have MSI. Shared legacy 3586a0a6d8cbSVille Syrjälä * interrupts could still race. 3587a0a6d8cbSVille Syrjälä */ 3588b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) 3589d46da437SPaulo Zanoni { 3590a0a6d8cbSVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 359182a28bcfSDaniel Vetter u32 mask; 3592d46da437SPaulo Zanoni 35936e266956STvrtko Ursulin if (HAS_PCH_NOP(dev_priv)) 3594692a04cfSDaniel Vetter return; 3595692a04cfSDaniel Vetter 35966e266956STvrtko Ursulin if (HAS_PCH_IBX(dev_priv)) 35975c673b60SDaniel Vetter mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; 35984ebc6509SDhinakaran Pandiyan else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) 35995c673b60SDaniel Vetter mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; 36004ebc6509SDhinakaran Pandiyan else 36014ebc6509SDhinakaran Pandiyan mask = SDE_GMBUS_CPT; 36028664281bSPaulo Zanoni 3603a0a6d8cbSVille Syrjälä GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 3604d46da437SPaulo Zanoni } 3605d46da437SPaulo Zanoni 36069eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) 3607036a4a7dSZhenyu Wang { 3608b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 36098e76f8dcSPaulo Zanoni u32 display_mask, extra_mask; 36108e76f8dcSPaulo Zanoni 3611b243f530STvrtko Ursulin if (INTEL_GEN(dev_priv) >= 7) { 36128e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | 3613842ebf7aSVille Syrjälä DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); 36148e76f8dcSPaulo Zanoni extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | 361523bb4cb5SVille Syrjälä DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | 36162a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_C) | 36172a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_B) | 36182a636e24SVille Syrjälä DE_PLANE_FLIP_DONE_IVB(PLANE_A) | 361923bb4cb5SVille Syrjälä DE_DP_A_HOTPLUG_IVB); 36208e76f8dcSPaulo Zanoni } else { 36218e76f8dcSPaulo Zanoni display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 3622842ebf7aSVille Syrjälä DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | 3623842ebf7aSVille Syrjälä DE_PIPEA_CRC_DONE | DE_POISON); 3624c6073d4cSVille Syrjälä extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | 3625e4ce95aaSVille Syrjälä DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | 36264bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_A) | 36274bb18054SVille Syrjälä DE_PLANE_FLIP_DONE(PLANE_B) | 3628e4ce95aaSVille Syrjälä DE_DP_A_HOTPLUG); 36298e76f8dcSPaulo Zanoni } 3630036a4a7dSZhenyu Wang 3631fc340442SDaniel Vetter if (IS_HASWELL(dev_priv)) { 3632b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 3633fc340442SDaniel Vetter display_mask |= DE_EDP_PSR_INT_HSW; 3634fc340442SDaniel Vetter } 3635fc340442SDaniel Vetter 3636c6073d4cSVille Syrjälä if (IS_IRONLAKE_M(dev_priv)) 3637c6073d4cSVille Syrjälä extra_mask |= DE_PCU_EVENT; 3638c6073d4cSVille Syrjälä 36391ec14ad3SChris Wilson dev_priv->irq_mask = ~display_mask; 3640036a4a7dSZhenyu Wang 3641a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3642622364b6SPaulo Zanoni 3643a9922912SVille Syrjälä gen5_gt_irq_postinstall(&dev_priv->gt); 3644a9922912SVille Syrjälä 3645b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, 3646b16b2a2fSPaulo Zanoni display_mask | extra_mask); 3647036a4a7dSZhenyu Wang } 3648036a4a7dSZhenyu Wang 3649f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) 3650f8b79e58SImre Deak { 365167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3652f8b79e58SImre Deak 3653f8b79e58SImre Deak if (dev_priv->display_irqs_enabled) 3654f8b79e58SImre Deak return; 3655f8b79e58SImre Deak 3656f8b79e58SImre Deak dev_priv->display_irqs_enabled = true; 3657f8b79e58SImre Deak 3658d6c69803SVille Syrjälä if (intel_irqs_enabled(dev_priv)) { 3659d6c69803SVille Syrjälä vlv_display_irq_reset(dev_priv); 3660ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3661f8b79e58SImre Deak } 3662d6c69803SVille Syrjälä } 3663f8b79e58SImre Deak 3664f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) 3665f8b79e58SImre Deak { 366667520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 3667f8b79e58SImre Deak 3668f8b79e58SImre Deak if (!dev_priv->display_irqs_enabled) 3669f8b79e58SImre Deak return; 3670f8b79e58SImre Deak 3671f8b79e58SImre Deak dev_priv->display_irqs_enabled = false; 3672f8b79e58SImre Deak 3673950eabafSImre Deak if (intel_irqs_enabled(dev_priv)) 3674ad22d106SVille Syrjälä vlv_display_irq_reset(dev_priv); 3675f8b79e58SImre Deak } 3676f8b79e58SImre Deak 36770e6c9a9eSVille Syrjälä 3678b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) 36790e6c9a9eSVille Syrjälä { 3680cf1c97dcSAndi Shyti gen5_gt_irq_postinstall(&dev_priv->gt); 36817e231dbeSJesse Barnes 3682ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 36839918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3684ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3685ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3686ad22d106SVille Syrjälä 36872939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); 36882939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); 368920afbda2SDaniel Vetter } 369020afbda2SDaniel Vetter 3691abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) 3692abd58f01SBen Widawsky { 3693b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3694b16b2a2fSPaulo Zanoni 3695869129eeSMatt Roper u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) | 3696869129eeSMatt Roper GEN8_PIPE_CDCLK_CRC_DONE; 3697a9c287c9SJani Nikula u32 de_pipe_enables; 3698054318c7SImre Deak u32 de_port_masked = gen8_de_port_aux_mask(dev_priv); 36993a3b3c7dSVille Syrjälä u32 de_port_enables; 3700df0d28c1SDhinakaran Pandiyan u32 de_misc_masked = GEN8_DE_EDP_PSR; 3701562ddcb7SMatt Roper u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 3702562ddcb7SMatt Roper BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 37033a3b3c7dSVille Syrjälä enum pipe pipe; 3704770de83dSDamien Lespiau 3705df0d28c1SDhinakaran Pandiyan if (INTEL_GEN(dev_priv) <= 10) 3706df0d28c1SDhinakaran Pandiyan de_misc_masked |= GEN8_DE_MISC_GSE; 3707df0d28c1SDhinakaran Pandiyan 3708cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 37093a3b3c7dSVille Syrjälä de_port_masked |= BXT_DE_PORT_GMBUS; 3710a324fcacSRodrigo Vivi 37119c9e97c4SVandita Kulkarni if (INTEL_GEN(dev_priv) >= 11) { 37129c9e97c4SVandita Kulkarni enum port port; 37139c9e97c4SVandita Kulkarni 37149c9e97c4SVandita Kulkarni if (intel_bios_is_dsi_present(dev_priv, &port)) 37159c9e97c4SVandita Kulkarni de_port_masked |= DSI0_TE | DSI1_TE; 37169c9e97c4SVandita Kulkarni } 37179c9e97c4SVandita Kulkarni 3718cda195f1SVille Syrjälä de_pipe_enables = de_pipe_masked | 3719cda195f1SVille Syrjälä GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | 3720cda195f1SVille Syrjälä gen8_de_pipe_flip_done_mask(dev_priv); 37211288f9b0SKarthik B S 37223a3b3c7dSVille Syrjälä de_port_enables = de_port_masked; 3723cc3f90f0SAnder Conselvan de Oliveira if (IS_GEN9_LP(dev_priv)) 3724a52bb15bSVille Syrjälä de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK; 3725a52bb15bSVille Syrjälä else if (IS_BROADWELL(dev_priv)) 3726e5abaab3SVille Syrjälä de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK; 37273a3b3c7dSVille Syrjälä 37288241cfbeSJosé Roberto de Souza if (INTEL_GEN(dev_priv) >= 12) { 37298241cfbeSJosé Roberto de Souza enum transcoder trans; 37308241cfbeSJosé Roberto de Souza 3731562ddcb7SMatt Roper for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) { 37328241cfbeSJosé Roberto de Souza enum intel_display_power_domain domain; 37338241cfbeSJosé Roberto de Souza 37348241cfbeSJosé Roberto de Souza domain = POWER_DOMAIN_TRANSCODER(trans); 37358241cfbeSJosé Roberto de Souza if (!intel_display_power_is_enabled(dev_priv, domain)) 37368241cfbeSJosé Roberto de Souza continue; 37378241cfbeSJosé Roberto de Souza 37388241cfbeSJosé Roberto de Souza gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans)); 37398241cfbeSJosé Roberto de Souza } 37408241cfbeSJosé Roberto de Souza } else { 3741b16b2a2fSPaulo Zanoni gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); 37428241cfbeSJosé Roberto de Souza } 3743e04f7eceSVille Syrjälä 37440a195c02SMika Kahola for_each_pipe(dev_priv, pipe) { 37450a195c02SMika Kahola dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; 3746abd58f01SBen Widawsky 3747f458ebbcSDaniel Vetter if (intel_display_power_is_enabled(dev_priv, 3748813bde43SPaulo Zanoni POWER_DOMAIN_PIPE(pipe))) 3749b16b2a2fSPaulo Zanoni GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, 3750813bde43SPaulo Zanoni dev_priv->de_irq_mask[pipe], 375135079899SPaulo Zanoni de_pipe_enables); 37520a195c02SMika Kahola } 3753abd58f01SBen Widawsky 3754b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables); 3755b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); 37562a57d9ccSImre Deak 3757121e758eSDhinakaran Pandiyan if (INTEL_GEN(dev_priv) >= 11) { 3758121e758eSDhinakaran Pandiyan u32 de_hpd_masked = 0; 3759b796b971SDhinakaran Pandiyan u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | 3760b796b971SDhinakaran Pandiyan GEN11_DE_TBT_HOTPLUG_MASK; 3761121e758eSDhinakaran Pandiyan 3762b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked, 3763b16b2a2fSPaulo Zanoni de_hpd_enables); 3764abd58f01SBen Widawsky } 3765121e758eSDhinakaran Pandiyan } 3766abd58f01SBen Widawsky 3767b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) 3768abd58f01SBen Widawsky { 37696e266956STvrtko Ursulin if (HAS_PCH_SPLIT(dev_priv)) 3770a0a6d8cbSVille Syrjälä ibx_irq_postinstall(dev_priv); 3771622364b6SPaulo Zanoni 3772cf1c97dcSAndi Shyti gen8_gt_irq_postinstall(&dev_priv->gt); 3773abd58f01SBen Widawsky gen8_de_irq_postinstall(dev_priv); 3774abd58f01SBen Widawsky 377525286aacSDaniele Ceraolo Spurio gen8_master_intr_enable(dev_priv->uncore.regs); 3776abd58f01SBen Widawsky } 3777abd58f01SBen Widawsky 3778b318b824SVille Syrjälä static void icp_irq_postinstall(struct drm_i915_private *dev_priv) 377931604222SAnusha Srivatsa { 37809696f041SVille Syrjälä struct intel_uncore *uncore = &dev_priv->uncore; 378131604222SAnusha Srivatsa u32 mask = SDE_GMBUS_ICP; 378231604222SAnusha Srivatsa 37839696f041SVille Syrjälä GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff); 378431604222SAnusha Srivatsa } 378531604222SAnusha Srivatsa 3786b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) 378751951ae7SMika Kuoppala { 3788b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3789df0d28c1SDhinakaran Pandiyan u32 gu_misc_masked = GEN11_GU_MISC_GSE; 379051951ae7SMika Kuoppala 379129b43ae2SRodrigo Vivi if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) 3792b318b824SVille Syrjälä icp_irq_postinstall(dev_priv); 379331604222SAnusha Srivatsa 37949b77011eSTvrtko Ursulin gen11_gt_irq_postinstall(&dev_priv->gt); 379551951ae7SMika Kuoppala gen8_de_irq_postinstall(dev_priv); 379651951ae7SMika Kuoppala 3797b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); 3798df0d28c1SDhinakaran Pandiyan 37992939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); 380051951ae7SMika Kuoppala 380197b492f5SLucas De Marchi if (HAS_MASTER_UNIT_IRQ(dev_priv)) { 380297b492f5SLucas De Marchi dg1_master_intr_enable(uncore->regs); 38032939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, DG1_MSTR_UNIT_INTR); 380497b492f5SLucas De Marchi } else { 38059b77011eSTvrtko Ursulin gen11_master_intr_enable(uncore->regs); 38062939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ); 380751951ae7SMika Kuoppala } 380897b492f5SLucas De Marchi } 380951951ae7SMika Kuoppala 3810b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) 381143f328d7SVille Syrjälä { 3812cf1c97dcSAndi Shyti gen8_gt_irq_postinstall(&dev_priv->gt); 381343f328d7SVille Syrjälä 3814ad22d106SVille Syrjälä spin_lock_irq(&dev_priv->irq_lock); 38159918271eSVille Syrjälä if (dev_priv->display_irqs_enabled) 3816ad22d106SVille Syrjälä vlv_display_irq_postinstall(dev_priv); 3817ad22d106SVille Syrjälä spin_unlock_irq(&dev_priv->irq_lock); 3818ad22d106SVille Syrjälä 38192939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); 38202939eb06SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 382143f328d7SVille Syrjälä } 382243f328d7SVille Syrjälä 3823b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv) 3824c2798b19SChris Wilson { 3825b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3826c2798b19SChris Wilson 382744d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 382844d9241eSVille Syrjälä 3829b16b2a2fSPaulo Zanoni GEN2_IRQ_RESET(uncore); 3830e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 3831c2798b19SChris Wilson } 3832c2798b19SChris Wilson 3833b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv) 3834c2798b19SChris Wilson { 3835b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3836e9e9848aSVille Syrjälä u16 enable_mask; 3837c2798b19SChris Wilson 38384f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, 38394f5fd91fSTvrtko Ursulin EMR, 38404f5fd91fSTvrtko Ursulin ~(I915_ERROR_PAGE_TABLE | 3841045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 3842c2798b19SChris Wilson 3843c2798b19SChris Wilson /* Unmask the interrupts that we always want on. */ 3844c2798b19SChris Wilson dev_priv->irq_mask = 3845c2798b19SChris Wilson ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 384616659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 384716659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 3848c2798b19SChris Wilson 3849e9e9848aSVille Syrjälä enable_mask = 3850c2798b19SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 3851c2798b19SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 385216659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 3853e9e9848aSVille Syrjälä I915_USER_INTERRUPT; 3854e9e9848aSVille Syrjälä 3855b16b2a2fSPaulo Zanoni GEN2_IRQ_INIT(uncore, dev_priv->irq_mask, enable_mask); 3856c2798b19SChris Wilson 3857379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 3858379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 3859d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 3860755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 3861755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 3862d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 3863c2798b19SChris Wilson } 3864c2798b19SChris Wilson 38654f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915, 386678c357ddSVille Syrjälä u16 *eir, u16 *eir_stuck) 386778c357ddSVille Syrjälä { 38684f5fd91fSTvrtko Ursulin struct intel_uncore *uncore = &i915->uncore; 386978c357ddSVille Syrjälä u16 emr; 387078c357ddSVille Syrjälä 38714f5fd91fSTvrtko Ursulin *eir = intel_uncore_read16(uncore, EIR); 387278c357ddSVille Syrjälä 387378c357ddSVille Syrjälä if (*eir) 38744f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EIR, *eir); 387578c357ddSVille Syrjälä 38764f5fd91fSTvrtko Ursulin *eir_stuck = intel_uncore_read16(uncore, EIR); 387778c357ddSVille Syrjälä if (*eir_stuck == 0) 387878c357ddSVille Syrjälä return; 387978c357ddSVille Syrjälä 388078c357ddSVille Syrjälä /* 388178c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 388278c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 388378c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 388478c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 388578c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 388678c357ddSVille Syrjälä * cleared except by handling the underlying error 388778c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 388878c357ddSVille Syrjälä * remains set. 388978c357ddSVille Syrjälä */ 38904f5fd91fSTvrtko Ursulin emr = intel_uncore_read16(uncore, EMR); 38914f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, 0xffff); 38924f5fd91fSTvrtko Ursulin intel_uncore_write16(uncore, EMR, emr | *eir_stuck); 389378c357ddSVille Syrjälä } 389478c357ddSVille Syrjälä 389578c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv, 389678c357ddSVille Syrjälä u16 eir, u16 eir_stuck) 389778c357ddSVille Syrjälä { 389878c357ddSVille Syrjälä DRM_DEBUG("Master Error: EIR 0x%04x\n", eir); 389978c357ddSVille Syrjälä 390078c357ddSVille Syrjälä if (eir_stuck) 390100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n", 390200376ccfSWambui Karuga eir_stuck); 390378c357ddSVille Syrjälä } 390478c357ddSVille Syrjälä 390578c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv, 390678c357ddSVille Syrjälä u32 *eir, u32 *eir_stuck) 390778c357ddSVille Syrjälä { 390878c357ddSVille Syrjälä u32 emr; 390978c357ddSVille Syrjälä 39102939eb06SJani Nikula *eir = intel_uncore_read(&dev_priv->uncore, EIR); 391178c357ddSVille Syrjälä 39122939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EIR, *eir); 391378c357ddSVille Syrjälä 39142939eb06SJani Nikula *eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR); 391578c357ddSVille Syrjälä if (*eir_stuck == 0) 391678c357ddSVille Syrjälä return; 391778c357ddSVille Syrjälä 391878c357ddSVille Syrjälä /* 391978c357ddSVille Syrjälä * Toggle all EMR bits to make sure we get an edge 392078c357ddSVille Syrjälä * in the ISR master error bit if we don't clear 392178c357ddSVille Syrjälä * all the EIR bits. Otherwise the edge triggered 392278c357ddSVille Syrjälä * IIR on i965/g4x wouldn't notice that an interrupt 392378c357ddSVille Syrjälä * is still pending. Also some EIR bits can't be 392478c357ddSVille Syrjälä * cleared except by handling the underlying error 392578c357ddSVille Syrjälä * (or by a GPU reset) so we mask any bit that 392678c357ddSVille Syrjälä * remains set. 392778c357ddSVille Syrjälä */ 39282939eb06SJani Nikula emr = intel_uncore_read(&dev_priv->uncore, EMR); 39292939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff); 39302939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck); 393178c357ddSVille Syrjälä } 393278c357ddSVille Syrjälä 393378c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, 393478c357ddSVille Syrjälä u32 eir, u32 eir_stuck) 393578c357ddSVille Syrjälä { 393678c357ddSVille Syrjälä DRM_DEBUG("Master Error, EIR 0x%08x\n", eir); 393778c357ddSVille Syrjälä 393878c357ddSVille Syrjälä if (eir_stuck) 393900376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n", 394000376ccfSWambui Karuga eir_stuck); 394178c357ddSVille Syrjälä } 394278c357ddSVille Syrjälä 3943ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg) 3944c2798b19SChris Wilson { 3945b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 3946af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 3947c2798b19SChris Wilson 39482dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 39492dd2a883SImre Deak return IRQ_NONE; 39502dd2a883SImre Deak 39511f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 39529102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 39531f814dacSImre Deak 3954af722d28SVille Syrjälä do { 3955af722d28SVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 395678c357ddSVille Syrjälä u16 eir = 0, eir_stuck = 0; 3957af722d28SVille Syrjälä u16 iir; 3958af722d28SVille Syrjälä 39594f5fd91fSTvrtko Ursulin iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR); 3960c2798b19SChris Wilson if (iir == 0) 3961af722d28SVille Syrjälä break; 3962c2798b19SChris Wilson 3963af722d28SVille Syrjälä ret = IRQ_HANDLED; 3964c2798b19SChris Wilson 3965eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 3966eb64343cSVille Syrjälä * signalled in iir */ 3967eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 3968c2798b19SChris Wilson 396978c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 397078c357ddSVille Syrjälä i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 397178c357ddSVille Syrjälä 39724f5fd91fSTvrtko Ursulin intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); 3973c2798b19SChris Wilson 3974c2798b19SChris Wilson if (iir & I915_USER_INTERRUPT) 397573c8bfb7SChris Wilson intel_engine_signal_breadcrumbs(dev_priv->gt.engine[RCS0]); 3976c2798b19SChris Wilson 397778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 397878c357ddSVille Syrjälä i8xx_error_irq_handler(dev_priv, eir, eir_stuck); 3979af722d28SVille Syrjälä 3980eb64343cSVille Syrjälä i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); 3981af722d28SVille Syrjälä } while (0); 3982c2798b19SChris Wilson 39839c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 39849c6508b9SThomas Gleixner 39859102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 39861f814dacSImre Deak 39871f814dacSImre Deak return ret; 3988c2798b19SChris Wilson } 3989c2798b19SChris Wilson 3990b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv) 3991a266c7d5SChris Wilson { 3992b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 3993a266c7d5SChris Wilson 399456b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 39950706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 39962939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 3997a266c7d5SChris Wilson } 3998a266c7d5SChris Wilson 399944d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 400044d9241eSVille Syrjälä 4001b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 4002e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 4003a266c7d5SChris Wilson } 4004a266c7d5SChris Wilson 4005b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv) 4006a266c7d5SChris Wilson { 4007b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 400838bde180SChris Wilson u32 enable_mask; 4009a266c7d5SChris Wilson 40102939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, ~(I915_ERROR_PAGE_TABLE | 4011045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH)); 401238bde180SChris Wilson 401338bde180SChris Wilson /* Unmask the interrupts that we always want on. */ 401438bde180SChris Wilson dev_priv->irq_mask = 401538bde180SChris Wilson ~(I915_ASLE_INTERRUPT | 401638bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 401716659bc5SVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 401816659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 401938bde180SChris Wilson 402038bde180SChris Wilson enable_mask = 402138bde180SChris Wilson I915_ASLE_INTERRUPT | 402238bde180SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 402338bde180SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 402416659bc5SVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 402538bde180SChris Wilson I915_USER_INTERRUPT; 402638bde180SChris Wilson 402756b857a5STvrtko Ursulin if (I915_HAS_HOTPLUG(dev_priv)) { 4028a266c7d5SChris Wilson /* Enable in IER... */ 4029a266c7d5SChris Wilson enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 4030a266c7d5SChris Wilson /* and unmask in IMR */ 4031a266c7d5SChris Wilson dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 4032a266c7d5SChris Wilson } 4033a266c7d5SChris Wilson 4034b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 4035a266c7d5SChris Wilson 4036379ef82dSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4037379ef82dSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4038d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4039755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4040755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4041d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4042379ef82dSDaniel Vetter 4043c30bb1fdSVille Syrjälä i915_enable_asle_pipestat(dev_priv); 404420afbda2SDaniel Vetter } 404520afbda2SDaniel Vetter 4046ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg) 4047a266c7d5SChris Wilson { 4048b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 4049af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4050a266c7d5SChris Wilson 40512dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 40522dd2a883SImre Deak return IRQ_NONE; 40532dd2a883SImre Deak 40541f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 40559102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 40561f814dacSImre Deak 405738bde180SChris Wilson do { 4058eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 405978c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4060af722d28SVille Syrjälä u32 hotplug_status = 0; 4061af722d28SVille Syrjälä u32 iir; 4062a266c7d5SChris Wilson 40632939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 4064af722d28SVille Syrjälä if (iir == 0) 4065af722d28SVille Syrjälä break; 4066af722d28SVille Syrjälä 4067af722d28SVille Syrjälä ret = IRQ_HANDLED; 4068af722d28SVille Syrjälä 4069af722d28SVille Syrjälä if (I915_HAS_HOTPLUG(dev_priv) && 4070af722d28SVille Syrjälä iir & I915_DISPLAY_PORT_INTERRUPT) 4071af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4072a266c7d5SChris Wilson 4073eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4074eb64343cSVille Syrjälä * signalled in iir */ 4075eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4076a266c7d5SChris Wilson 407778c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 407878c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 407978c357ddSVille Syrjälä 40802939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 4081a266c7d5SChris Wilson 4082a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 408373c8bfb7SChris Wilson intel_engine_signal_breadcrumbs(dev_priv->gt.engine[RCS0]); 4084a266c7d5SChris Wilson 408578c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 408678c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4087a266c7d5SChris Wilson 4088af722d28SVille Syrjälä if (hotplug_status) 4089af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4090af722d28SVille Syrjälä 4091af722d28SVille Syrjälä i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4092af722d28SVille Syrjälä } while (0); 4093a266c7d5SChris Wilson 40949c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, ret); 40959c6508b9SThomas Gleixner 40969102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 40971f814dacSImre Deak 4098a266c7d5SChris Wilson return ret; 4099a266c7d5SChris Wilson } 4100a266c7d5SChris Wilson 4101b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv) 4102a266c7d5SChris Wilson { 4103b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 4104a266c7d5SChris Wilson 41050706f17cSEgbert Eich i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); 41062939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); 4107a266c7d5SChris Wilson 410844d9241eSVille Syrjälä i9xx_pipestat_irq_reset(dev_priv); 410944d9241eSVille Syrjälä 4110b16b2a2fSPaulo Zanoni GEN3_IRQ_RESET(uncore, GEN2_); 4111e44adb5dSChris Wilson dev_priv->irq_mask = ~0u; 4112a266c7d5SChris Wilson } 4113a266c7d5SChris Wilson 4114b318b824SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv) 4115a266c7d5SChris Wilson { 4116b16b2a2fSPaulo Zanoni struct intel_uncore *uncore = &dev_priv->uncore; 4117bbba0a97SChris Wilson u32 enable_mask; 4118a266c7d5SChris Wilson u32 error_mask; 4119a266c7d5SChris Wilson 4120045cebd2SVille Syrjälä /* 4121045cebd2SVille Syrjälä * Enable some error detection, note the instruction error mask 4122045cebd2SVille Syrjälä * bit is reserved, so we leave it masked. 4123045cebd2SVille Syrjälä */ 4124045cebd2SVille Syrjälä if (IS_G4X(dev_priv)) { 4125045cebd2SVille Syrjälä error_mask = ~(GM45_ERROR_PAGE_TABLE | 4126045cebd2SVille Syrjälä GM45_ERROR_MEM_PRIV | 4127045cebd2SVille Syrjälä GM45_ERROR_CP_PRIV | 4128045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4129045cebd2SVille Syrjälä } else { 4130045cebd2SVille Syrjälä error_mask = ~(I915_ERROR_PAGE_TABLE | 4131045cebd2SVille Syrjälä I915_ERROR_MEMORY_REFRESH); 4132045cebd2SVille Syrjälä } 41332939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, EMR, error_mask); 4134045cebd2SVille Syrjälä 4135a266c7d5SChris Wilson /* Unmask the interrupts that we always want on. */ 4136c30bb1fdSVille Syrjälä dev_priv->irq_mask = 4137c30bb1fdSVille Syrjälä ~(I915_ASLE_INTERRUPT | 4138adca4730SChris Wilson I915_DISPLAY_PORT_INTERRUPT | 4139bbba0a97SChris Wilson I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4140bbba0a97SChris Wilson I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 414178c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT); 4142bbba0a97SChris Wilson 4143c30bb1fdSVille Syrjälä enable_mask = 4144c30bb1fdSVille Syrjälä I915_ASLE_INTERRUPT | 4145c30bb1fdSVille Syrjälä I915_DISPLAY_PORT_INTERRUPT | 4146c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 4147c30bb1fdSVille Syrjälä I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 414878c357ddSVille Syrjälä I915_MASTER_ERROR_INTERRUPT | 4149c30bb1fdSVille Syrjälä I915_USER_INTERRUPT; 4150bbba0a97SChris Wilson 415191d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4152bbba0a97SChris Wilson enable_mask |= I915_BSD_USER_INTERRUPT; 4153a266c7d5SChris Wilson 4154b16b2a2fSPaulo Zanoni GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask); 4155c30bb1fdSVille Syrjälä 4156b79480baSDaniel Vetter /* Interrupt setup is already guaranteed to be single-threaded, this is 4157b79480baSDaniel Vetter * just to make the assert_spin_locked check happy. */ 4158d6207435SDaniel Vetter spin_lock_irq(&dev_priv->irq_lock); 4159755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 4160755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); 4161755e9019SImre Deak i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); 4162d6207435SDaniel Vetter spin_unlock_irq(&dev_priv->irq_lock); 4163a266c7d5SChris Wilson 416491d14251STvrtko Ursulin i915_enable_asle_pipestat(dev_priv); 416520afbda2SDaniel Vetter } 416620afbda2SDaniel Vetter 416791d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) 416820afbda2SDaniel Vetter { 416920afbda2SDaniel Vetter u32 hotplug_en; 417020afbda2SDaniel Vetter 417167520415SChris Wilson lockdep_assert_held(&dev_priv->irq_lock); 4172b5ea2d56SDaniel Vetter 4173adca4730SChris Wilson /* Note HDMI and DP share hotplug bits */ 4174e5868a31SEgbert Eich /* enable bits are the same for all generations */ 417591d14251STvrtko Ursulin hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915); 4176a266c7d5SChris Wilson /* Programming the CRT detection parameters tends 4177a266c7d5SChris Wilson to generate a spurious hotplug event about three 4178a266c7d5SChris Wilson seconds later. So just do it once. 4179a266c7d5SChris Wilson */ 418091d14251STvrtko Ursulin if (IS_G4X(dev_priv)) 4181a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; 4182a266c7d5SChris Wilson hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; 4183a266c7d5SChris Wilson 4184a266c7d5SChris Wilson /* Ignore TV since it's buggy */ 41850706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(dev_priv, 4186f9e3dc78SJani Nikula HOTPLUG_INT_EN_MASK | 4187f9e3dc78SJani Nikula CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | 4188f9e3dc78SJani Nikula CRT_HOTPLUG_ACTIVATION_PERIOD_64, 41890706f17cSEgbert Eich hotplug_en); 4190a266c7d5SChris Wilson } 4191a266c7d5SChris Wilson 4192ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg) 4193a266c7d5SChris Wilson { 4194b318b824SVille Syrjälä struct drm_i915_private *dev_priv = arg; 4195af722d28SVille Syrjälä irqreturn_t ret = IRQ_NONE; 4196a266c7d5SChris Wilson 41972dd2a883SImre Deak if (!intel_irqs_enabled(dev_priv)) 41982dd2a883SImre Deak return IRQ_NONE; 41992dd2a883SImre Deak 42001f814dacSImre Deak /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 42019102650fSDaniele Ceraolo Spurio disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 42021f814dacSImre Deak 4203af722d28SVille Syrjälä do { 4204eb64343cSVille Syrjälä u32 pipe_stats[I915_MAX_PIPES] = {}; 420578c357ddSVille Syrjälä u32 eir = 0, eir_stuck = 0; 4206af722d28SVille Syrjälä u32 hotplug_status = 0; 4207af722d28SVille Syrjälä u32 iir; 42082c8ba29fSChris Wilson 42092939eb06SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR); 4210af722d28SVille Syrjälä if (iir == 0) 4211af722d28SVille Syrjälä break; 4212af722d28SVille Syrjälä 4213af722d28SVille Syrjälä ret = IRQ_HANDLED; 4214af722d28SVille Syrjälä 4215af722d28SVille Syrjälä if (iir & I915_DISPLAY_PORT_INTERRUPT) 4216af722d28SVille Syrjälä hotplug_status = i9xx_hpd_irq_ack(dev_priv); 4217a266c7d5SChris Wilson 4218eb64343cSVille Syrjälä /* Call regardless, as some status bits might not be 4219eb64343cSVille Syrjälä * signalled in iir */ 4220eb64343cSVille Syrjälä i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); 4221a266c7d5SChris Wilson 422278c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 422378c357ddSVille Syrjälä i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck); 422478c357ddSVille Syrjälä 42252939eb06SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir); 4226a266c7d5SChris Wilson 4227a266c7d5SChris Wilson if (iir & I915_USER_INTERRUPT) 422873c8bfb7SChris Wilson intel_engine_signal_breadcrumbs(dev_priv->gt.engine[RCS0]); 4229af722d28SVille Syrjälä 4230a266c7d5SChris Wilson if (iir & I915_BSD_USER_INTERRUPT) 423173c8bfb7SChris Wilson intel_engine_signal_breadcrumbs(dev_priv->gt.engine[VCS0]); 4232a266c7d5SChris Wilson 423378c357ddSVille Syrjälä if (iir & I915_MASTER_ERROR_INTERRUPT) 423478c357ddSVille Syrjälä i9xx_error_irq_handler(dev_priv, eir, eir_stuck); 4235515ac2bbSDaniel Vetter 4236af722d28SVille Syrjälä if (hotplug_status) 4237af722d28SVille Syrjälä i9xx_hpd_irq_handler(dev_priv, hotplug_status); 4238af722d28SVille Syrjälä 4239af722d28SVille Syrjälä i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); 4240af722d28SVille Syrjälä } while (0); 4241a266c7d5SChris Wilson 42429c6508b9SThomas Gleixner pmu_irq_stats(dev_priv, IRQ_HANDLED); 42439c6508b9SThomas Gleixner 42449102650fSDaniele Ceraolo Spurio enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 42451f814dacSImre Deak 4246a266c7d5SChris Wilson return ret; 4247a266c7d5SChris Wilson } 4248a266c7d5SChris Wilson 4249fca52a55SDaniel Vetter /** 4250fca52a55SDaniel Vetter * intel_irq_init - initializes irq support 4251fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4252fca52a55SDaniel Vetter * 4253fca52a55SDaniel Vetter * This function initializes all the irq support including work items, timers 4254fca52a55SDaniel Vetter * and all the vtables. It does not setup the interrupt itself though. 4255fca52a55SDaniel Vetter */ 4256b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv) 4257f71d4af4SJesse Barnes { 425891c8a326SChris Wilson struct drm_device *dev = &dev_priv->drm; 4259cefcff8fSJoonas Lahtinen int i; 42608b2e326dSChris Wilson 426174bb98baSLucas De Marchi INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); 4262cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4263cefcff8fSJoonas Lahtinen dev_priv->l3_parity.remap_info[i] = NULL; 42648b2e326dSChris Wilson 4265633023a4SDaniele Ceraolo Spurio /* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */ 4266702668e6SDaniele Ceraolo Spurio if (HAS_GT_UC(dev_priv) && INTEL_GEN(dev_priv) < 11) 42672239e6dfSDaniele Ceraolo Spurio dev_priv->gt.pm_guc_events = GUC_INTR_GUC2HOST << 16; 426826705e20SSagar Arun Kamble 42699a450b68SLucas De Marchi if (!HAS_DISPLAY(dev_priv)) 42709a450b68SLucas De Marchi return; 42719a450b68SLucas De Marchi 427296bd87b7SLucas De Marchi intel_hpd_init_pins(dev_priv); 427396bd87b7SLucas De Marchi 427496bd87b7SLucas De Marchi intel_hpd_init_work(dev_priv); 427596bd87b7SLucas De Marchi 427621da2700SVille Syrjälä dev->vblank_disable_immediate = true; 427721da2700SVille Syrjälä 4278262fd485SChris Wilson /* Most platforms treat the display irq block as an always-on 4279262fd485SChris Wilson * power domain. vlv/chv can disable it at runtime and need 4280262fd485SChris Wilson * special care to avoid writing any of the display block registers 4281262fd485SChris Wilson * outside of the power domain. We defer setting up the display irqs 4282262fd485SChris Wilson * in this case to the runtime pm. 4283262fd485SChris Wilson */ 4284262fd485SChris Wilson dev_priv->display_irqs_enabled = true; 4285262fd485SChris Wilson if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 4286262fd485SChris Wilson dev_priv->display_irqs_enabled = false; 4287262fd485SChris Wilson 4288317eaa95SLyude dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; 42899a64c650SLyude Paul /* If we have MST support, we want to avoid doing short HPD IRQ storm 42909a64c650SLyude Paul * detection, as short HPD storms will occur as a natural part of 42919a64c650SLyude Paul * sideband messaging with MST. 42929a64c650SLyude Paul * On older platforms however, IRQ storms can occur with both long and 42939a64c650SLyude Paul * short pulses, as seen on some G4x systems. 42949a64c650SLyude Paul */ 42959a64c650SLyude Paul dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); 4296317eaa95SLyude 42972ccf2e03SChris Wilson if (HAS_GMCH(dev_priv)) { 42982ccf2e03SChris Wilson if (I915_HAS_HOTPLUG(dev_priv)) 42992ccf2e03SChris Wilson dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; 43002ccf2e03SChris Wilson } else { 4301229f31e2SLucas De Marchi if (HAS_PCH_DG1(dev_priv)) 4302229f31e2SLucas De Marchi dev_priv->display.hpd_irq_setup = dg1_hpd_irq_setup; 43038ef7e340SMatt Roper else if (INTEL_GEN(dev_priv) >= 11) 4304121e758eSDhinakaran Pandiyan dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; 4305b318b824SVille Syrjälä else if (IS_GEN9_LP(dev_priv)) 4306e0a20ad7SShashank Sharma dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; 4307c6c30b91SRodrigo Vivi else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) 43086dbf30ceSVille Syrjälä dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; 43096dbf30ceSVille Syrjälä else 43103a3b3c7dSVille Syrjälä dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; 4311f71d4af4SJesse Barnes } 43122ccf2e03SChris Wilson } 431320afbda2SDaniel Vetter 4314fca52a55SDaniel Vetter /** 4315cefcff8fSJoonas Lahtinen * intel_irq_fini - deinitializes IRQ support 4316cefcff8fSJoonas Lahtinen * @i915: i915 device instance 4317cefcff8fSJoonas Lahtinen * 4318cefcff8fSJoonas Lahtinen * This function deinitializes all the IRQ support. 4319cefcff8fSJoonas Lahtinen */ 4320cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915) 4321cefcff8fSJoonas Lahtinen { 4322cefcff8fSJoonas Lahtinen int i; 4323cefcff8fSJoonas Lahtinen 4324cefcff8fSJoonas Lahtinen for (i = 0; i < MAX_L3_SLICES; ++i) 4325cefcff8fSJoonas Lahtinen kfree(i915->l3_parity.remap_info[i]); 4326cefcff8fSJoonas Lahtinen } 4327cefcff8fSJoonas Lahtinen 4328b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) 4329b318b824SVille Syrjälä { 4330b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4331b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4332b318b824SVille Syrjälä return cherryview_irq_handler; 4333b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4334b318b824SVille Syrjälä return valleyview_irq_handler; 4335b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 4)) 4336b318b824SVille Syrjälä return i965_irq_handler; 4337b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 3)) 4338b318b824SVille Syrjälä return i915_irq_handler; 4339b318b824SVille Syrjälä else 4340b318b824SVille Syrjälä return i8xx_irq_handler; 4341b318b824SVille Syrjälä } else { 434297b492f5SLucas De Marchi if (HAS_MASTER_UNIT_IRQ(dev_priv)) 434397b492f5SLucas De Marchi return dg1_irq_handler; 4344b318b824SVille Syrjälä if (INTEL_GEN(dev_priv) >= 11) 4345b318b824SVille Syrjälä return gen11_irq_handler; 4346b318b824SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 8) 4347b318b824SVille Syrjälä return gen8_irq_handler; 4348b318b824SVille Syrjälä else 43499eae5e27SLucas De Marchi return ilk_irq_handler; 4350b318b824SVille Syrjälä } 4351b318b824SVille Syrjälä } 4352b318b824SVille Syrjälä 4353b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv) 4354b318b824SVille Syrjälä { 4355b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4356b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4357b318b824SVille Syrjälä cherryview_irq_reset(dev_priv); 4358b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4359b318b824SVille Syrjälä valleyview_irq_reset(dev_priv); 4360b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 4)) 4361b318b824SVille Syrjälä i965_irq_reset(dev_priv); 4362b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 3)) 4363b318b824SVille Syrjälä i915_irq_reset(dev_priv); 4364b318b824SVille Syrjälä else 4365b318b824SVille Syrjälä i8xx_irq_reset(dev_priv); 4366b318b824SVille Syrjälä } else { 4367b318b824SVille Syrjälä if (INTEL_GEN(dev_priv) >= 11) 4368b318b824SVille Syrjälä gen11_irq_reset(dev_priv); 4369b318b824SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 8) 4370b318b824SVille Syrjälä gen8_irq_reset(dev_priv); 4371b318b824SVille Syrjälä else 43729eae5e27SLucas De Marchi ilk_irq_reset(dev_priv); 4373b318b824SVille Syrjälä } 4374b318b824SVille Syrjälä } 4375b318b824SVille Syrjälä 4376b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv) 4377b318b824SVille Syrjälä { 4378b318b824SVille Syrjälä if (HAS_GMCH(dev_priv)) { 4379b318b824SVille Syrjälä if (IS_CHERRYVIEW(dev_priv)) 4380b318b824SVille Syrjälä cherryview_irq_postinstall(dev_priv); 4381b318b824SVille Syrjälä else if (IS_VALLEYVIEW(dev_priv)) 4382b318b824SVille Syrjälä valleyview_irq_postinstall(dev_priv); 4383b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 4)) 4384b318b824SVille Syrjälä i965_irq_postinstall(dev_priv); 4385b318b824SVille Syrjälä else if (IS_GEN(dev_priv, 3)) 4386b318b824SVille Syrjälä i915_irq_postinstall(dev_priv); 4387b318b824SVille Syrjälä else 4388b318b824SVille Syrjälä i8xx_irq_postinstall(dev_priv); 4389b318b824SVille Syrjälä } else { 4390b318b824SVille Syrjälä if (INTEL_GEN(dev_priv) >= 11) 4391b318b824SVille Syrjälä gen11_irq_postinstall(dev_priv); 4392b318b824SVille Syrjälä else if (INTEL_GEN(dev_priv) >= 8) 4393b318b824SVille Syrjälä gen8_irq_postinstall(dev_priv); 4394b318b824SVille Syrjälä else 43959eae5e27SLucas De Marchi ilk_irq_postinstall(dev_priv); 4396b318b824SVille Syrjälä } 4397b318b824SVille Syrjälä } 4398b318b824SVille Syrjälä 4399cefcff8fSJoonas Lahtinen /** 4400fca52a55SDaniel Vetter * intel_irq_install - enables the hardware interrupt 4401fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4402fca52a55SDaniel Vetter * 4403fca52a55SDaniel Vetter * This function enables the hardware interrupt handling, but leaves the hotplug 4404fca52a55SDaniel Vetter * handling still disabled. It is called after intel_irq_init(). 4405fca52a55SDaniel Vetter * 4406fca52a55SDaniel Vetter * In the driver load and resume code we need working interrupts in a few places 4407fca52a55SDaniel Vetter * but don't want to deal with the hassle of concurrent probe and hotplug 4408fca52a55SDaniel Vetter * workers. Hence the split into this two-stage approach. 4409fca52a55SDaniel Vetter */ 44102aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv) 44112aeb7d3aSDaniel Vetter { 44128ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4413b318b824SVille Syrjälä int ret; 4414b318b824SVille Syrjälä 44152aeb7d3aSDaniel Vetter /* 44162aeb7d3aSDaniel Vetter * We enable some interrupt sources in our postinstall hooks, so mark 44172aeb7d3aSDaniel Vetter * interrupts as enabled _before_ actually enabling them to avoid 44182aeb7d3aSDaniel Vetter * special cases in our ordering checks. 44192aeb7d3aSDaniel Vetter */ 4420ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 44212aeb7d3aSDaniel Vetter 4422b318b824SVille Syrjälä dev_priv->drm.irq_enabled = true; 4423b318b824SVille Syrjälä 4424b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4425b318b824SVille Syrjälä 4426b318b824SVille Syrjälä ret = request_irq(irq, intel_irq_handler(dev_priv), 4427b318b824SVille Syrjälä IRQF_SHARED, DRIVER_NAME, dev_priv); 4428b318b824SVille Syrjälä if (ret < 0) { 4429b318b824SVille Syrjälä dev_priv->drm.irq_enabled = false; 4430b318b824SVille Syrjälä return ret; 4431b318b824SVille Syrjälä } 4432b318b824SVille Syrjälä 4433b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4434b318b824SVille Syrjälä 4435b318b824SVille Syrjälä return ret; 44362aeb7d3aSDaniel Vetter } 44372aeb7d3aSDaniel Vetter 4438fca52a55SDaniel Vetter /** 4439fca52a55SDaniel Vetter * intel_irq_uninstall - finilizes all irq handling 4440fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4441fca52a55SDaniel Vetter * 4442fca52a55SDaniel Vetter * This stops interrupt and hotplug handling and unregisters and frees all 4443fca52a55SDaniel Vetter * resources acquired in the init functions. 4444fca52a55SDaniel Vetter */ 44452aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv) 44462aeb7d3aSDaniel Vetter { 44478ff5446aSThomas Zimmermann int irq = to_pci_dev(dev_priv->drm.dev)->irq; 4448b318b824SVille Syrjälä 4449b318b824SVille Syrjälä /* 4450789fa874SJanusz Krzysztofik * FIXME we can get called twice during driver probe 4451789fa874SJanusz Krzysztofik * error handling as well as during driver remove due to 4452789fa874SJanusz Krzysztofik * intel_modeset_driver_remove() calling us out of sequence. 4453789fa874SJanusz Krzysztofik * Would be nice if it didn't do that... 4454b318b824SVille Syrjälä */ 4455b318b824SVille Syrjälä if (!dev_priv->drm.irq_enabled) 4456b318b824SVille Syrjälä return; 4457b318b824SVille Syrjälä 4458b318b824SVille Syrjälä dev_priv->drm.irq_enabled = false; 4459b318b824SVille Syrjälä 4460b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4461b318b824SVille Syrjälä 4462b318b824SVille Syrjälä free_irq(irq, dev_priv); 4463b318b824SVille Syrjälä 44642aeb7d3aSDaniel Vetter intel_hpd_cancel_work(dev_priv); 4465ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 44662aeb7d3aSDaniel Vetter } 44672aeb7d3aSDaniel Vetter 4468fca52a55SDaniel Vetter /** 4469fca52a55SDaniel Vetter * intel_runtime_pm_disable_interrupts - runtime interrupt disabling 4470fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4471fca52a55SDaniel Vetter * 4472fca52a55SDaniel Vetter * This function is used to disable interrupts at runtime, both in the runtime 4473fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4474fca52a55SDaniel Vetter */ 4475b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) 4476c67a470bSPaulo Zanoni { 4477b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4478ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = false; 4479315ca4c4SVille Syrjälä intel_synchronize_irq(dev_priv); 4480c67a470bSPaulo Zanoni } 4481c67a470bSPaulo Zanoni 4482fca52a55SDaniel Vetter /** 4483fca52a55SDaniel Vetter * intel_runtime_pm_enable_interrupts - runtime interrupt enabling 4484fca52a55SDaniel Vetter * @dev_priv: i915 device instance 4485fca52a55SDaniel Vetter * 4486fca52a55SDaniel Vetter * This function is used to enable interrupts at runtime, both in the runtime 4487fca52a55SDaniel Vetter * pm and the system suspend/resume code. 4488fca52a55SDaniel Vetter */ 4489b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) 4490c67a470bSPaulo Zanoni { 4491ad1443f0SSagar Arun Kamble dev_priv->runtime_pm.irqs_enabled = true; 4492b318b824SVille Syrjälä intel_irq_reset(dev_priv); 4493b318b824SVille Syrjälä intel_irq_postinstall(dev_priv); 4494c67a470bSPaulo Zanoni } 4495d64575eeSJani Nikula 4496d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv) 4497d64575eeSJani Nikula { 4498d64575eeSJani Nikula /* 4499d64575eeSJani Nikula * We only use drm_irq_uninstall() at unload and VT switch, so 4500d64575eeSJani Nikula * this is the only thing we need to check. 4501d64575eeSJani Nikula */ 4502d64575eeSJani Nikula return dev_priv->runtime_pm.irqs_enabled; 4503d64575eeSJani Nikula } 4504d64575eeSJani Nikula 4505d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915) 4506d64575eeSJani Nikula { 45078ff5446aSThomas Zimmermann synchronize_irq(to_pci_dev(i915->drm.dev)->irq); 4508d64575eeSJani Nikula } 4509