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