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