xref: /openbmc/linux/drivers/gpu/drm/i915/i915_irq.c (revision d28cdc43b43b77287d7839ef1b94fdaa24d2a444)
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"
457f6947fdSJani 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 
165babde06dSMika Kahola static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
166babde06dSMika Kahola 	[HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
167babde06dSMika Kahola 	[HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
168babde06dSMika Kahola 	[HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
169babde06dSMika Kahola 	[HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
170babde06dSMika Kahola };
171babde06dSMika Kahola 
17231604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = {
1735f371a81SVille Syrjälä 	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
1745f371a81SVille Syrjälä 	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
1755f371a81SVille Syrjälä 	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
17697011359SVille Syrjälä 	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
17797011359SVille Syrjälä 	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
17897011359SVille Syrjälä 	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
17997011359SVille Syrjälä 	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
18097011359SVille Syrjälä 	[HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5),
18197011359SVille Syrjälä 	[HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6),
18252dfdba0SLucas De Marchi };
18352dfdba0SLucas De Marchi 
184229f31e2SLucas De Marchi static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
1855f371a81SVille Syrjälä 	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
1865f371a81SVille Syrjälä 	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
1875f371a81SVille Syrjälä 	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
1885f371a81SVille Syrjälä 	[HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D),
1892f8a6699SMatt Roper 	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
190229f31e2SLucas De Marchi };
191229f31e2SLucas De Marchi 
192babde06dSMika Kahola static const u32 hpd_mtp[HPD_NUM_PINS] = {
193babde06dSMika Kahola 	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
194babde06dSMika Kahola 	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
195babde06dSMika Kahola 	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
196babde06dSMika Kahola 	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
197babde06dSMika Kahola 	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
198babde06dSMika Kahola 	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
199babde06dSMika Kahola };
200babde06dSMika Kahola 
2010398993bSVille Syrjälä static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
2020398993bSVille Syrjälä {
2035a4dd6f0SJani Nikula 	struct intel_hotplug *hpd = &dev_priv->display.hotplug;
2040398993bSVille Syrjälä 
2050398993bSVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
2060398993bSVille Syrjälä 		if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
2070398993bSVille Syrjälä 		    IS_CHERRYVIEW(dev_priv))
2080398993bSVille Syrjälä 			hpd->hpd = hpd_status_g4x;
2090398993bSVille Syrjälä 		else
2100398993bSVille Syrjälä 			hpd->hpd = hpd_status_i915;
2110398993bSVille Syrjälä 		return;
2120398993bSVille Syrjälä 	}
2130398993bSVille Syrjälä 
214babde06dSMika Kahola 	if (DISPLAY_VER(dev_priv) >= 14)
215babde06dSMika Kahola 		hpd->hpd = hpd_xelpdp;
216babde06dSMika Kahola 	else if (DISPLAY_VER(dev_priv) >= 11)
2170398993bSVille Syrjälä 		hpd->hpd = hpd_gen11;
21870bfb307SMatt Roper 	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
2190398993bSVille Syrjälä 		hpd->hpd = hpd_bxt;
220dded35acSVille Syrjälä 	else if (DISPLAY_VER(dev_priv) == 9)
221dded35acSVille Syrjälä 		hpd->hpd = NULL; /* no north HPD on SKL */
222373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 8)
2230398993bSVille Syrjälä 		hpd->hpd = hpd_bdw;
224373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 7)
2250398993bSVille Syrjälä 		hpd->hpd = hpd_ivb;
2260398993bSVille Syrjälä 	else
2270398993bSVille Syrjälä 		hpd->hpd = hpd_ilk;
2280398993bSVille Syrjälä 
229229f31e2SLucas De Marchi 	if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) &&
230229f31e2SLucas De Marchi 	    (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
2310398993bSVille Syrjälä 		return;
2320398993bSVille Syrjälä 
2333176fb66SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
234229f31e2SLucas De Marchi 		hpd->pch_hpd = hpd_sde_dg1;
235babde06dSMika Kahola 	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
236babde06dSMika Kahola 		hpd->pch_hpd = hpd_mtp;
237fa58c9e4SAnusha Srivatsa 	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
2380398993bSVille Syrjälä 		hpd->pch_hpd = hpd_icp;
2390398993bSVille Syrjälä 	else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
2400398993bSVille Syrjälä 		hpd->pch_hpd = hpd_spt;
2410398993bSVille Syrjälä 	else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv))
2420398993bSVille Syrjälä 		hpd->pch_hpd = hpd_cpt;
2430398993bSVille Syrjälä 	else if (HAS_PCH_IBX(dev_priv))
2440398993bSVille Syrjälä 		hpd->pch_hpd = hpd_ibx;
2450398993bSVille Syrjälä 	else
2460398993bSVille Syrjälä 		MISSING_CASE(INTEL_PCH_TYPE(dev_priv));
2470398993bSVille Syrjälä }
2480398993bSVille Syrjälä 
249aca9310aSAnshuman Gupta static void
250aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
251aca9310aSAnshuman Gupta {
2527794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
253aca9310aSAnshuman Gupta 
254aca9310aSAnshuman Gupta 	drm_crtc_handle_vblank(&crtc->base);
255aca9310aSAnshuman Gupta }
256aca9310aSAnshuman Gupta 
257cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
25868eb49b1SPaulo Zanoni 		    i915_reg_t iir, i915_reg_t ier)
25968eb49b1SPaulo Zanoni {
26065f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, imr, 0xffffffff);
26165f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, imr);
26268eb49b1SPaulo Zanoni 
26365f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, ier, 0);
26468eb49b1SPaulo Zanoni 
2655c502442SPaulo Zanoni 	/* IIR can theoretically queue up two events. Be paranoid. */
26665f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, iir, 0xffffffff);
26765f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, iir);
26865f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, iir, 0xffffffff);
26965f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, iir);
27068eb49b1SPaulo Zanoni }
2715c502442SPaulo Zanoni 
272ad7632ffSJani Nikula static void gen2_irq_reset(struct intel_uncore *uncore)
27368eb49b1SPaulo Zanoni {
27465f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IMR, 0xffff);
27565f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IMR);
276a9d356a6SPaulo Zanoni 
27765f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IER, 0);
27868eb49b1SPaulo Zanoni 
27968eb49b1SPaulo Zanoni 	/* IIR can theoretically queue up two events. Be paranoid. */
28065f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
28165f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
28265f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
28365f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
28468eb49b1SPaulo Zanoni }
28568eb49b1SPaulo Zanoni 
286337ba017SPaulo Zanoni /*
287337ba017SPaulo Zanoni  * We should clear IMR at preinstall/uninstall, and just check at postinstall.
288337ba017SPaulo Zanoni  */
28965f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
290b51a2842SVille Syrjälä {
29165f42cdcSPaulo Zanoni 	u32 val = intel_uncore_read(uncore, reg);
292b51a2842SVille Syrjälä 
293b51a2842SVille Syrjälä 	if (val == 0)
294b51a2842SVille Syrjälä 		return;
295b51a2842SVille Syrjälä 
296a9f236d1SPankaj Bharadiya 	drm_WARN(&uncore->i915->drm, 1,
297a9f236d1SPankaj Bharadiya 		 "Interrupt register 0x%x is not zero: 0x%08x\n",
298f0f59a00SVille Syrjälä 		 i915_mmio_reg_offset(reg), val);
29965f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, reg, 0xffffffff);
30065f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, reg);
30165f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, reg, 0xffffffff);
30265f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, reg);
303b51a2842SVille Syrjälä }
304337ba017SPaulo Zanoni 
30565f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore)
306e9e9848aSVille Syrjälä {
30765f42cdcSPaulo Zanoni 	u16 val = intel_uncore_read16(uncore, GEN2_IIR);
308e9e9848aSVille Syrjälä 
309e9e9848aSVille Syrjälä 	if (val == 0)
310e9e9848aSVille Syrjälä 		return;
311e9e9848aSVille Syrjälä 
312a9f236d1SPankaj Bharadiya 	drm_WARN(&uncore->i915->drm, 1,
313a9f236d1SPankaj Bharadiya 		 "Interrupt register 0x%x is not zero: 0x%08x\n",
3149d9523d8SPaulo Zanoni 		 i915_mmio_reg_offset(GEN2_IIR), val);
31565f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
31665f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
31765f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
31865f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
319e9e9848aSVille Syrjälä }
320e9e9848aSVille Syrjälä 
321cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore,
32268eb49b1SPaulo Zanoni 		   i915_reg_t imr, u32 imr_val,
32368eb49b1SPaulo Zanoni 		   i915_reg_t ier, u32 ier_val,
32468eb49b1SPaulo Zanoni 		   i915_reg_t iir)
32568eb49b1SPaulo Zanoni {
32665f42cdcSPaulo Zanoni 	gen3_assert_iir_is_zero(uncore, iir);
32735079899SPaulo Zanoni 
32865f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, ier, ier_val);
32965f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, imr, imr_val);
33065f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, imr);
33168eb49b1SPaulo Zanoni }
33235079899SPaulo Zanoni 
333ad7632ffSJani Nikula static void gen2_irq_init(struct intel_uncore *uncore,
3342918c3caSPaulo Zanoni 			  u32 imr_val, u32 ier_val)
33568eb49b1SPaulo Zanoni {
33665f42cdcSPaulo Zanoni 	gen2_assert_iir_is_zero(uncore);
33768eb49b1SPaulo Zanoni 
33865f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IER, ier_val);
33965f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IMR, imr_val);
34065f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IMR);
34168eb49b1SPaulo Zanoni }
34268eb49b1SPaulo Zanoni 
3430706f17cSEgbert Eich /* For display hotplug interrupt */
3440706f17cSEgbert Eich static inline void
3450706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
346a9c287c9SJani Nikula 				     u32 mask,
347a9c287c9SJani Nikula 				     u32 bits)
3480706f17cSEgbert Eich {
34967520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
35048a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, bits & ~mask);
3510706f17cSEgbert Eich 
3528cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits);
3530706f17cSEgbert Eich }
3540706f17cSEgbert Eich 
3550706f17cSEgbert Eich /**
3560706f17cSEgbert Eich  * i915_hotplug_interrupt_update - update hotplug interrupt enable
3570706f17cSEgbert Eich  * @dev_priv: driver private
3580706f17cSEgbert Eich  * @mask: bits to update
3590706f17cSEgbert Eich  * @bits: bits to enable
3600706f17cSEgbert Eich  * NOTE: the HPD enable bits are modified both inside and outside
3610706f17cSEgbert Eich  * of an interrupt context. To avoid that read-modify-write cycles
3620706f17cSEgbert Eich  * interfer, these bits are protected by a spinlock. Since this
3630706f17cSEgbert Eich  * function is usually not called from a context where the lock is
3640706f17cSEgbert Eich  * held already, this function acquires the lock itself. A non-locking
3650706f17cSEgbert Eich  * version is also available.
3660706f17cSEgbert Eich  */
3670706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
368a9c287c9SJani Nikula 				   u32 mask,
369a9c287c9SJani Nikula 				   u32 bits)
3700706f17cSEgbert Eich {
3710706f17cSEgbert Eich 	spin_lock_irq(&dev_priv->irq_lock);
3720706f17cSEgbert Eich 	i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
3730706f17cSEgbert Eich 	spin_unlock_irq(&dev_priv->irq_lock);
3740706f17cSEgbert Eich }
3750706f17cSEgbert Eich 
376d9dc34f1SVille Syrjälä /**
377d9dc34f1SVille Syrjälä  * ilk_update_display_irq - update DEIMR
378d9dc34f1SVille Syrjälä  * @dev_priv: driver private
379d9dc34f1SVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
380d9dc34f1SVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
381d9dc34f1SVille Syrjälä  */
3829e6dcf33SJani Nikula static void ilk_update_display_irq(struct drm_i915_private *dev_priv,
3839e6dcf33SJani Nikula 				   u32 interrupt_mask, u32 enabled_irq_mask)
384036a4a7dSZhenyu Wang {
385a9c287c9SJani Nikula 	u32 new_val;
386d9dc34f1SVille Syrjälä 
38767520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
38848a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
389d9dc34f1SVille Syrjälä 
390d9dc34f1SVille Syrjälä 	new_val = dev_priv->irq_mask;
391d9dc34f1SVille Syrjälä 	new_val &= ~interrupt_mask;
392d9dc34f1SVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
393d9dc34f1SVille Syrjälä 
394e44adb5dSChris Wilson 	if (new_val != dev_priv->irq_mask &&
395e44adb5dSChris Wilson 	    !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) {
396d9dc34f1SVille Syrjälä 		dev_priv->irq_mask = new_val;
3972939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask);
3982939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, DEIMR);
399036a4a7dSZhenyu Wang 	}
400036a4a7dSZhenyu Wang }
401036a4a7dSZhenyu Wang 
4029e6dcf33SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits)
4039e6dcf33SJani Nikula {
4049e6dcf33SJani Nikula 	ilk_update_display_irq(i915, bits, bits);
4059e6dcf33SJani Nikula }
4069e6dcf33SJani Nikula 
4079e6dcf33SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits)
4089e6dcf33SJani Nikula {
4099e6dcf33SJani Nikula 	ilk_update_display_irq(i915, bits, 0);
4109e6dcf33SJani Nikula }
4119e6dcf33SJani Nikula 
4120961021aSBen Widawsky /**
4133a3b3c7dSVille Syrjälä  * bdw_update_port_irq - update DE port interrupt
4143a3b3c7dSVille Syrjälä  * @dev_priv: driver private
4153a3b3c7dSVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
4163a3b3c7dSVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
4173a3b3c7dSVille Syrjälä  */
4183a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
419a9c287c9SJani Nikula 				u32 interrupt_mask,
420a9c287c9SJani Nikula 				u32 enabled_irq_mask)
4213a3b3c7dSVille Syrjälä {
422a9c287c9SJani Nikula 	u32 new_val;
423a9c287c9SJani Nikula 	u32 old_val;
4243a3b3c7dSVille Syrjälä 
42567520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
4263a3b3c7dSVille Syrjälä 
42748a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
4283a3b3c7dSVille Syrjälä 
42948a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
4303a3b3c7dSVille Syrjälä 		return;
4313a3b3c7dSVille Syrjälä 
4322939eb06SJani Nikula 	old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
4333a3b3c7dSVille Syrjälä 
4343a3b3c7dSVille Syrjälä 	new_val = old_val;
4353a3b3c7dSVille Syrjälä 	new_val &= ~interrupt_mask;
4363a3b3c7dSVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
4373a3b3c7dSVille Syrjälä 
4383a3b3c7dSVille Syrjälä 	if (new_val != old_val) {
4392939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val);
4402939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
4413a3b3c7dSVille Syrjälä 	}
4423a3b3c7dSVille Syrjälä }
4433a3b3c7dSVille Syrjälä 
4443a3b3c7dSVille Syrjälä /**
445013d3752SVille Syrjälä  * bdw_update_pipe_irq - update DE pipe interrupt
446013d3752SVille Syrjälä  * @dev_priv: driver private
447013d3752SVille Syrjälä  * @pipe: pipe whose interrupt to update
448013d3752SVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
449013d3752SVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
450013d3752SVille Syrjälä  */
4519e6dcf33SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
4529e6dcf33SJani Nikula 				enum pipe pipe, u32 interrupt_mask,
453a9c287c9SJani Nikula 				u32 enabled_irq_mask)
454013d3752SVille Syrjälä {
455a9c287c9SJani Nikula 	u32 new_val;
456013d3752SVille Syrjälä 
45767520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
458013d3752SVille Syrjälä 
45948a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
460013d3752SVille Syrjälä 
46148a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
462013d3752SVille Syrjälä 		return;
463013d3752SVille Syrjälä 
464013d3752SVille Syrjälä 	new_val = dev_priv->de_irq_mask[pipe];
465013d3752SVille Syrjälä 	new_val &= ~interrupt_mask;
466013d3752SVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
467013d3752SVille Syrjälä 
468013d3752SVille Syrjälä 	if (new_val != dev_priv->de_irq_mask[pipe]) {
469013d3752SVille Syrjälä 		dev_priv->de_irq_mask[pipe] = new_val;
4702939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
4712939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe));
472013d3752SVille Syrjälä 	}
473013d3752SVille Syrjälä }
474013d3752SVille Syrjälä 
4759e6dcf33SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915,
4769e6dcf33SJani Nikula 			 enum pipe pipe, u32 bits)
4779e6dcf33SJani Nikula {
4789e6dcf33SJani Nikula 	bdw_update_pipe_irq(i915, pipe, bits, bits);
4799e6dcf33SJani Nikula }
4809e6dcf33SJani Nikula 
4819e6dcf33SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915,
4829e6dcf33SJani Nikula 			  enum pipe pipe, u32 bits)
4839e6dcf33SJani Nikula {
4849e6dcf33SJani Nikula 	bdw_update_pipe_irq(i915, pipe, bits, 0);
4859e6dcf33SJani Nikula }
4869e6dcf33SJani Nikula 
487013d3752SVille Syrjälä /**
488fee884edSDaniel Vetter  * ibx_display_interrupt_update - update SDEIMR
489fee884edSDaniel Vetter  * @dev_priv: driver private
490fee884edSDaniel Vetter  * @interrupt_mask: mask of interrupt bits to update
491fee884edSDaniel Vetter  * @enabled_irq_mask: mask of interrupt bits to enable
492fee884edSDaniel Vetter  */
4939e6dcf33SJani Nikula static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
494a9c287c9SJani Nikula 					 u32 interrupt_mask,
495a9c287c9SJani Nikula 					 u32 enabled_irq_mask)
496fee884edSDaniel Vetter {
4972939eb06SJani Nikula 	u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR);
498fee884edSDaniel Vetter 	sdeimr &= ~interrupt_mask;
499fee884edSDaniel Vetter 	sdeimr |= (~enabled_irq_mask & interrupt_mask);
500fee884edSDaniel Vetter 
50148a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
50215a17aaeSDaniel Vetter 
50367520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
504fee884edSDaniel Vetter 
50548a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
506c67a470bSPaulo Zanoni 		return;
507c67a470bSPaulo Zanoni 
5082939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr);
5092939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, SDEIMR);
510fee884edSDaniel Vetter }
5118664281bSPaulo Zanoni 
5129e6dcf33SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits)
5139e6dcf33SJani Nikula {
5149e6dcf33SJani Nikula 	ibx_display_interrupt_update(i915, bits, bits);
5159e6dcf33SJani Nikula }
5169e6dcf33SJani Nikula 
5179e6dcf33SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits)
5189e6dcf33SJani Nikula {
5199e6dcf33SJani Nikula 	ibx_display_interrupt_update(i915, bits, 0);
5209e6dcf33SJani Nikula }
5219e6dcf33SJani Nikula 
5226b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv,
5236b12ca56SVille Syrjälä 			      enum pipe pipe)
5247c463586SKeith Packard {
5256b12ca56SVille Syrjälä 	u32 status_mask = dev_priv->pipestat_irq_mask[pipe];
52610c59c51SImre Deak 	u32 enable_mask = status_mask << 16;
52710c59c51SImre Deak 
5286b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
5296b12ca56SVille Syrjälä 
530373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) < 5)
5316b12ca56SVille Syrjälä 		goto out;
5326b12ca56SVille Syrjälä 
53310c59c51SImre Deak 	/*
534724a6905SVille Syrjälä 	 * On pipe A we don't support the PSR interrupt yet,
535724a6905SVille Syrjälä 	 * on pipe B and C the same bit MBZ.
53610c59c51SImre Deak 	 */
53748a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON_ONCE(&dev_priv->drm,
53848a1b8d4SPankaj Bharadiya 			     status_mask & PIPE_A_PSR_STATUS_VLV))
53910c59c51SImre Deak 		return 0;
540724a6905SVille Syrjälä 	/*
541724a6905SVille Syrjälä 	 * On pipe B and C we don't support the PSR interrupt yet, on pipe
542724a6905SVille Syrjälä 	 * A the same bit is for perf counters which we don't use either.
543724a6905SVille Syrjälä 	 */
54448a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON_ONCE(&dev_priv->drm,
54548a1b8d4SPankaj Bharadiya 			     status_mask & PIPE_B_PSR_STATUS_VLV))
546724a6905SVille Syrjälä 		return 0;
54710c59c51SImre Deak 
54810c59c51SImre Deak 	enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
54910c59c51SImre Deak 			 SPRITE0_FLIP_DONE_INT_EN_VLV |
55010c59c51SImre Deak 			 SPRITE1_FLIP_DONE_INT_EN_VLV);
55110c59c51SImre Deak 	if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
55210c59c51SImre Deak 		enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
55310c59c51SImre Deak 	if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
55410c59c51SImre Deak 		enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
55510c59c51SImre Deak 
5566b12ca56SVille Syrjälä out:
55748a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm,
55848a1b8d4SPankaj Bharadiya 		      enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
5596b12ca56SVille Syrjälä 		      status_mask & ~PIPESTAT_INT_STATUS_MASK,
5606b12ca56SVille Syrjälä 		      "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
5616b12ca56SVille Syrjälä 		      pipe_name(pipe), enable_mask, status_mask);
5626b12ca56SVille Syrjälä 
56310c59c51SImre Deak 	return enable_mask;
56410c59c51SImre Deak }
56510c59c51SImre Deak 
5666b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv,
5676b12ca56SVille Syrjälä 			  enum pipe pipe, u32 status_mask)
568755e9019SImre Deak {
5696b12ca56SVille Syrjälä 	i915_reg_t reg = PIPESTAT(pipe);
570755e9019SImre Deak 	u32 enable_mask;
571755e9019SImre Deak 
57248a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
5736b12ca56SVille Syrjälä 		      "pipe %c: status_mask=0x%x\n",
5746b12ca56SVille Syrjälä 		      pipe_name(pipe), status_mask);
5756b12ca56SVille Syrjälä 
5766b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
57748a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
5786b12ca56SVille Syrjälä 
5796b12ca56SVille Syrjälä 	if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask)
5806b12ca56SVille Syrjälä 		return;
5816b12ca56SVille Syrjälä 
5826b12ca56SVille Syrjälä 	dev_priv->pipestat_irq_mask[pipe] |= status_mask;
5836b12ca56SVille Syrjälä 	enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
5846b12ca56SVille Syrjälä 
5852939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
5862939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, reg);
587755e9019SImre Deak }
588755e9019SImre Deak 
5896b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv,
5906b12ca56SVille Syrjälä 			   enum pipe pipe, u32 status_mask)
591755e9019SImre Deak {
5926b12ca56SVille Syrjälä 	i915_reg_t reg = PIPESTAT(pipe);
593755e9019SImre Deak 	u32 enable_mask;
594755e9019SImre Deak 
59548a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
5966b12ca56SVille Syrjälä 		      "pipe %c: status_mask=0x%x\n",
5976b12ca56SVille Syrjälä 		      pipe_name(pipe), status_mask);
5986b12ca56SVille Syrjälä 
5996b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
60048a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
6016b12ca56SVille Syrjälä 
6026b12ca56SVille Syrjälä 	if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0)
6036b12ca56SVille Syrjälä 		return;
6046b12ca56SVille Syrjälä 
6056b12ca56SVille Syrjälä 	dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
6066b12ca56SVille Syrjälä 	enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
6076b12ca56SVille Syrjälä 
6082939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
6092939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, reg);
610755e9019SImre Deak }
611755e9019SImre Deak 
612f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv)
613f3e30485SVille Syrjälä {
6147249dfcbSJani Nikula 	if (!dev_priv->display.opregion.asle)
615f3e30485SVille Syrjälä 		return false;
616f3e30485SVille Syrjälä 
617f3e30485SVille Syrjälä 	return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
618f3e30485SVille Syrjälä }
619f3e30485SVille Syrjälä 
620c0e09200SDave Airlie /**
621f49e38ddSJani Nikula  * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
62214bb2c11STvrtko Ursulin  * @dev_priv: i915 device private
62301c66889SZhao Yakui  */
62491d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
62501c66889SZhao Yakui {
626f3e30485SVille Syrjälä 	if (!i915_has_asle(dev_priv))
627f49e38ddSJani Nikula 		return;
628f49e38ddSJani Nikula 
62913321786SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
63001c66889SZhao Yakui 
631755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
632373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 4)
6333b6c42e8SDaniel Vetter 		i915_enable_pipestat(dev_priv, PIPE_A,
634755e9019SImre Deak 				     PIPE_LEGACY_BLC_EVENT_STATUS);
6351ec14ad3SChris Wilson 
63613321786SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
63701c66889SZhao Yakui }
63801c66889SZhao Yakui 
639e3689190SBen Widawsky /**
64074bb98baSLucas De Marchi  * ivb_parity_work - Workqueue called when a parity error interrupt
641e3689190SBen Widawsky  * occurred.
642e3689190SBen Widawsky  * @work: workqueue struct
643e3689190SBen Widawsky  *
644e3689190SBen Widawsky  * Doesn't actually do anything except notify userspace. As a consequence of
645e3689190SBen Widawsky  * this event, userspace should try to remap the bad rows since statistically
646e3689190SBen Widawsky  * it is likely the same row is more likely to go bad again.
647e3689190SBen Widawsky  */
64874bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work)
649e3689190SBen Widawsky {
6502d1013ddSJani Nikula 	struct drm_i915_private *dev_priv =
651cefcff8fSJoonas Lahtinen 		container_of(work, typeof(*dev_priv), l3_parity.error_work);
6522cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
653e3689190SBen Widawsky 	u32 error_status, row, bank, subbank;
65435a85ac6SBen Widawsky 	char *parity_event[6];
655a9c287c9SJani Nikula 	u32 misccpctl;
656a9c287c9SJani Nikula 	u8 slice = 0;
657e3689190SBen Widawsky 
658e3689190SBen Widawsky 	/* We must turn off DOP level clock gating to access the L3 registers.
659e3689190SBen Widawsky 	 * In order to prevent a get/put style interface, acquire struct mutex
660e3689190SBen Widawsky 	 * any time we access those registers.
661e3689190SBen Widawsky 	 */
66291c8a326SChris Wilson 	mutex_lock(&dev_priv->drm.struct_mutex);
663e3689190SBen Widawsky 
66435a85ac6SBen Widawsky 	/* If we've screwed up tracking, just let the interrupt fire again */
66548a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice))
66635a85ac6SBen Widawsky 		goto out;
66735a85ac6SBen Widawsky 
668f7435467SAndrzej Hajda 	misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL,
669f7435467SAndrzej Hajda 				     GEN7_DOP_CLOCK_GATE_ENABLE, 0);
6702939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL);
671e3689190SBen Widawsky 
67235a85ac6SBen Widawsky 	while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) {
673f0f59a00SVille Syrjälä 		i915_reg_t reg;
67435a85ac6SBen Widawsky 
67535a85ac6SBen Widawsky 		slice--;
67648a1b8d4SPankaj Bharadiya 		if (drm_WARN_ON_ONCE(&dev_priv->drm,
67748a1b8d4SPankaj Bharadiya 				     slice >= NUM_L3_SLICES(dev_priv)))
67835a85ac6SBen Widawsky 			break;
67935a85ac6SBen Widawsky 
68035a85ac6SBen Widawsky 		dev_priv->l3_parity.which_slice &= ~(1<<slice);
68135a85ac6SBen Widawsky 
6826fa1c5f1SVille Syrjälä 		reg = GEN7_L3CDERRST1(slice);
68335a85ac6SBen Widawsky 
6842939eb06SJani Nikula 		error_status = intel_uncore_read(&dev_priv->uncore, reg);
685e3689190SBen Widawsky 		row = GEN7_PARITY_ERROR_ROW(error_status);
686e3689190SBen Widawsky 		bank = GEN7_PARITY_ERROR_BANK(error_status);
687e3689190SBen Widawsky 		subbank = GEN7_PARITY_ERROR_SUBBANK(error_status);
688e3689190SBen Widawsky 
6892939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE);
6902939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, reg);
691e3689190SBen Widawsky 
692cce723edSBen Widawsky 		parity_event[0] = I915_L3_PARITY_UEVENT "=1";
693e3689190SBen Widawsky 		parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row);
694e3689190SBen Widawsky 		parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank);
695e3689190SBen Widawsky 		parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank);
69635a85ac6SBen Widawsky 		parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice);
69735a85ac6SBen Widawsky 		parity_event[5] = NULL;
698e3689190SBen Widawsky 
69991c8a326SChris Wilson 		kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj,
700e3689190SBen Widawsky 				   KOBJ_CHANGE, parity_event);
701e3689190SBen Widawsky 
702a10234fdSTvrtko Ursulin 		drm_dbg(&dev_priv->drm,
703a10234fdSTvrtko Ursulin 			"Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
70435a85ac6SBen Widawsky 			slice, row, bank, subbank);
705e3689190SBen Widawsky 
70635a85ac6SBen Widawsky 		kfree(parity_event[4]);
707e3689190SBen Widawsky 		kfree(parity_event[3]);
708e3689190SBen Widawsky 		kfree(parity_event[2]);
709e3689190SBen Widawsky 		kfree(parity_event[1]);
710e3689190SBen Widawsky 	}
711e3689190SBen Widawsky 
7122939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl);
71335a85ac6SBen Widawsky 
71435a85ac6SBen Widawsky out:
71548a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice);
71603d2c54dSMatt Roper 	spin_lock_irq(gt->irq_lock);
717cf1c97dcSAndi Shyti 	gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv));
71803d2c54dSMatt Roper 	spin_unlock_irq(gt->irq_lock);
71935a85ac6SBen Widawsky 
72091c8a326SChris Wilson 	mutex_unlock(&dev_priv->drm.struct_mutex);
72135a85ac6SBen Widawsky }
72235a85ac6SBen Widawsky 
723af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
724121e758eSDhinakaran Pandiyan {
725af92058fSVille Syrjälä 	switch (pin) {
726da51e4baSVille Syrjälä 	case HPD_PORT_TC1:
727da51e4baSVille Syrjälä 	case HPD_PORT_TC2:
728da51e4baSVille Syrjälä 	case HPD_PORT_TC3:
729da51e4baSVille Syrjälä 	case HPD_PORT_TC4:
730da51e4baSVille Syrjälä 	case HPD_PORT_TC5:
731da51e4baSVille Syrjälä 	case HPD_PORT_TC6:
7324294fa5fSVille Syrjälä 		return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin);
73348ef15d3SJosé Roberto de Souza 	default:
73448ef15d3SJosé Roberto de Souza 		return false;
73548ef15d3SJosé Roberto de Souza 	}
73648ef15d3SJosé Roberto de Souza }
73748ef15d3SJosé Roberto de Souza 
738af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
73963c88d22SImre Deak {
740af92058fSVille Syrjälä 	switch (pin) {
741af92058fSVille Syrjälä 	case HPD_PORT_A:
742195baa06SVille Syrjälä 		return val & PORTA_HOTPLUG_LONG_DETECT;
743af92058fSVille Syrjälä 	case HPD_PORT_B:
74463c88d22SImre Deak 		return val & PORTB_HOTPLUG_LONG_DETECT;
745af92058fSVille Syrjälä 	case HPD_PORT_C:
74663c88d22SImre Deak 		return val & PORTC_HOTPLUG_LONG_DETECT;
74763c88d22SImre Deak 	default:
74863c88d22SImre Deak 		return false;
74963c88d22SImre Deak 	}
75063c88d22SImre Deak }
75163c88d22SImre Deak 
752af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
75331604222SAnusha Srivatsa {
754af92058fSVille Syrjälä 	switch (pin) {
755af92058fSVille Syrjälä 	case HPD_PORT_A:
756af92058fSVille Syrjälä 	case HPD_PORT_B:
7578ef7e340SMatt Roper 	case HPD_PORT_C:
758229f31e2SLucas De Marchi 	case HPD_PORT_D:
7594294fa5fSVille Syrjälä 		return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin);
76031604222SAnusha Srivatsa 	default:
76131604222SAnusha Srivatsa 		return false;
76231604222SAnusha Srivatsa 	}
76331604222SAnusha Srivatsa }
76431604222SAnusha Srivatsa 
765af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
76631604222SAnusha Srivatsa {
767af92058fSVille Syrjälä 	switch (pin) {
768da51e4baSVille Syrjälä 	case HPD_PORT_TC1:
769da51e4baSVille Syrjälä 	case HPD_PORT_TC2:
770da51e4baSVille Syrjälä 	case HPD_PORT_TC3:
771da51e4baSVille Syrjälä 	case HPD_PORT_TC4:
772da51e4baSVille Syrjälä 	case HPD_PORT_TC5:
773da51e4baSVille Syrjälä 	case HPD_PORT_TC6:
7744294fa5fSVille Syrjälä 		return val & ICP_TC_HPD_LONG_DETECT(pin);
77552dfdba0SLucas De Marchi 	default:
77652dfdba0SLucas De Marchi 		return false;
77752dfdba0SLucas De Marchi 	}
77852dfdba0SLucas De Marchi }
77952dfdba0SLucas De Marchi 
780af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val)
7816dbf30ceSVille Syrjälä {
782af92058fSVille Syrjälä 	switch (pin) {
783af92058fSVille Syrjälä 	case HPD_PORT_E:
7846dbf30ceSVille Syrjälä 		return val & PORTE_HOTPLUG_LONG_DETECT;
7856dbf30ceSVille Syrjälä 	default:
7866dbf30ceSVille Syrjälä 		return false;
7876dbf30ceSVille Syrjälä 	}
7886dbf30ceSVille Syrjälä }
7896dbf30ceSVille Syrjälä 
790af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
79174c0b395SVille Syrjälä {
792af92058fSVille Syrjälä 	switch (pin) {
793af92058fSVille Syrjälä 	case HPD_PORT_A:
79474c0b395SVille Syrjälä 		return val & PORTA_HOTPLUG_LONG_DETECT;
795af92058fSVille Syrjälä 	case HPD_PORT_B:
79674c0b395SVille Syrjälä 		return val & PORTB_HOTPLUG_LONG_DETECT;
797af92058fSVille Syrjälä 	case HPD_PORT_C:
79874c0b395SVille Syrjälä 		return val & PORTC_HOTPLUG_LONG_DETECT;
799af92058fSVille Syrjälä 	case HPD_PORT_D:
80074c0b395SVille Syrjälä 		return val & PORTD_HOTPLUG_LONG_DETECT;
80174c0b395SVille Syrjälä 	default:
80274c0b395SVille Syrjälä 		return false;
80374c0b395SVille Syrjälä 	}
80474c0b395SVille Syrjälä }
80574c0b395SVille Syrjälä 
806af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
807e4ce95aaSVille Syrjälä {
808af92058fSVille Syrjälä 	switch (pin) {
809af92058fSVille Syrjälä 	case HPD_PORT_A:
810e4ce95aaSVille Syrjälä 		return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
811e4ce95aaSVille Syrjälä 	default:
812e4ce95aaSVille Syrjälä 		return false;
813e4ce95aaSVille Syrjälä 	}
814e4ce95aaSVille Syrjälä }
815e4ce95aaSVille Syrjälä 
816af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
81713cf5504SDave Airlie {
818af92058fSVille Syrjälä 	switch (pin) {
819af92058fSVille Syrjälä 	case HPD_PORT_B:
820676574dfSJani Nikula 		return val & PORTB_HOTPLUG_LONG_DETECT;
821af92058fSVille Syrjälä 	case HPD_PORT_C:
822676574dfSJani Nikula 		return val & PORTC_HOTPLUG_LONG_DETECT;
823af92058fSVille Syrjälä 	case HPD_PORT_D:
824676574dfSJani Nikula 		return val & PORTD_HOTPLUG_LONG_DETECT;
825676574dfSJani Nikula 	default:
826676574dfSJani Nikula 		return false;
82713cf5504SDave Airlie 	}
82813cf5504SDave Airlie }
82913cf5504SDave Airlie 
830af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
83113cf5504SDave Airlie {
832af92058fSVille Syrjälä 	switch (pin) {
833af92058fSVille Syrjälä 	case HPD_PORT_B:
834676574dfSJani Nikula 		return val & PORTB_HOTPLUG_INT_LONG_PULSE;
835af92058fSVille Syrjälä 	case HPD_PORT_C:
836676574dfSJani Nikula 		return val & PORTC_HOTPLUG_INT_LONG_PULSE;
837af92058fSVille Syrjälä 	case HPD_PORT_D:
838676574dfSJani Nikula 		return val & PORTD_HOTPLUG_INT_LONG_PULSE;
839676574dfSJani Nikula 	default:
840676574dfSJani Nikula 		return false;
84113cf5504SDave Airlie 	}
84213cf5504SDave Airlie }
84313cf5504SDave Airlie 
84442db67d6SVille Syrjälä /*
84542db67d6SVille Syrjälä  * Get a bit mask of pins that have triggered, and which ones may be long.
84642db67d6SVille Syrjälä  * This can be called multiple times with the same masks to accumulate
84742db67d6SVille Syrjälä  * hotplug detection results from several registers.
84842db67d6SVille Syrjälä  *
84942db67d6SVille Syrjälä  * Note that the caller is expected to zero out the masks initially.
85042db67d6SVille Syrjälä  */
851cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv,
852cf53902fSRodrigo Vivi 			       u32 *pin_mask, u32 *long_mask,
8538c841e57SJani Nikula 			       u32 hotplug_trigger, u32 dig_hotplug_reg,
854fd63e2a9SImre Deak 			       const u32 hpd[HPD_NUM_PINS],
855af92058fSVille Syrjälä 			       bool long_pulse_detect(enum hpd_pin pin, u32 val))
856676574dfSJani Nikula {
857e9be2850SVille Syrjälä 	enum hpd_pin pin;
858676574dfSJani Nikula 
85952dfdba0SLucas De Marchi 	BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS);
86052dfdba0SLucas De Marchi 
861e9be2850SVille Syrjälä 	for_each_hpd_pin(pin) {
862e9be2850SVille Syrjälä 		if ((hpd[pin] & hotplug_trigger) == 0)
8638c841e57SJani Nikula 			continue;
8648c841e57SJani Nikula 
865e9be2850SVille Syrjälä 		*pin_mask |= BIT(pin);
866676574dfSJani Nikula 
867af92058fSVille Syrjälä 		if (long_pulse_detect(pin, dig_hotplug_reg))
868e9be2850SVille Syrjälä 			*long_mask |= BIT(pin);
869676574dfSJani Nikula 	}
870676574dfSJani Nikula 
87100376ccfSWambui Karuga 	drm_dbg(&dev_priv->drm,
87200376ccfSWambui Karuga 		"hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n",
873f88f0478SVille Syrjälä 		hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask);
874676574dfSJani Nikula 
875676574dfSJani Nikula }
876676574dfSJani Nikula 
877a0e066b8SVille Syrjälä static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
878a0e066b8SVille Syrjälä 				  const u32 hpd[HPD_NUM_PINS])
879a0e066b8SVille Syrjälä {
880a0e066b8SVille Syrjälä 	struct intel_encoder *encoder;
881a0e066b8SVille Syrjälä 	u32 enabled_irqs = 0;
882a0e066b8SVille Syrjälä 
883a0e066b8SVille Syrjälä 	for_each_intel_encoder(&dev_priv->drm, encoder)
8845a4dd6f0SJani Nikula 		if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
885a0e066b8SVille Syrjälä 			enabled_irqs |= hpd[encoder->hpd_pin];
886a0e066b8SVille Syrjälä 
887a0e066b8SVille Syrjälä 	return enabled_irqs;
888a0e066b8SVille Syrjälä }
889a0e066b8SVille Syrjälä 
890a0e066b8SVille Syrjälä static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv,
891a0e066b8SVille Syrjälä 				  const u32 hpd[HPD_NUM_PINS])
892a0e066b8SVille Syrjälä {
893a0e066b8SVille Syrjälä 	struct intel_encoder *encoder;
894a0e066b8SVille Syrjälä 	u32 hotplug_irqs = 0;
895a0e066b8SVille Syrjälä 
896a0e066b8SVille Syrjälä 	for_each_intel_encoder(&dev_priv->drm, encoder)
897a0e066b8SVille Syrjälä 		hotplug_irqs |= hpd[encoder->hpd_pin];
898a0e066b8SVille Syrjälä 
899a0e066b8SVille Syrjälä 	return hotplug_irqs;
900a0e066b8SVille Syrjälä }
901a0e066b8SVille Syrjälä 
9022ea63927SVille Syrjälä static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915,
9032ea63927SVille Syrjälä 				     hotplug_enables_func hotplug_enables)
9042ea63927SVille Syrjälä {
9052ea63927SVille Syrjälä 	struct intel_encoder *encoder;
9062ea63927SVille Syrjälä 	u32 hotplug = 0;
9072ea63927SVille Syrjälä 
9082ea63927SVille Syrjälä 	for_each_intel_encoder(&i915->drm, encoder)
909dfefe7bcSVille Syrjälä 		hotplug |= hotplug_enables(encoder);
9102ea63927SVille Syrjälä 
9112ea63927SVille Syrjälä 	return hotplug;
9122ea63927SVille Syrjälä }
9132ea63927SVille Syrjälä 
91491d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv)
915515ac2bbSDaniel Vetter {
916203eb5a9SJani Nikula 	wake_up_all(&dev_priv->display.gmbus.wait_queue);
917515ac2bbSDaniel Vetter }
918515ac2bbSDaniel Vetter 
91991d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv)
920ce99c256SDaniel Vetter {
921203eb5a9SJani Nikula 	wake_up_all(&dev_priv->display.gmbus.wait_queue);
922ce99c256SDaniel Vetter }
923ce99c256SDaniel Vetter 
9248bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS)
92591d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
92691d14251STvrtko Ursulin 					 enum pipe pipe,
927a9c287c9SJani Nikula 					 u32 crc0, u32 crc1,
928a9c287c9SJani Nikula 					 u32 crc2, u32 crc3,
929a9c287c9SJani Nikula 					 u32 crc4)
9308bf1e9f1SShuang He {
9317794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
93200535527SJani Nikula 	struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
9335cee6c45SVille Syrjälä 	u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 };
9345cee6c45SVille Syrjälä 
9355cee6c45SVille Syrjälä 	trace_intel_pipe_crc(crtc, crcs);
936b2c88f5bSDamien Lespiau 
937d538bbdfSDamien Lespiau 	spin_lock(&pipe_crc->lock);
9388c6b709dSTomeu Vizoso 	/*
9398c6b709dSTomeu Vizoso 	 * For some not yet identified reason, the first CRC is
9408c6b709dSTomeu Vizoso 	 * bonkers. So let's just wait for the next vblank and read
9418c6b709dSTomeu Vizoso 	 * out the buggy result.
9428c6b709dSTomeu Vizoso 	 *
943163e8aecSRodrigo Vivi 	 * On GEN8+ sometimes the second CRC is bonkers as well, so
9448c6b709dSTomeu Vizoso 	 * don't trust that one either.
9458c6b709dSTomeu Vizoso 	 */
946033b7a23SMaarten Lankhorst 	if (pipe_crc->skipped <= 0 ||
947373abf1aSMatt Roper 	    (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) {
9488c6b709dSTomeu Vizoso 		pipe_crc->skipped++;
9498c6b709dSTomeu Vizoso 		spin_unlock(&pipe_crc->lock);
9508c6b709dSTomeu Vizoso 		return;
9518c6b709dSTomeu Vizoso 	}
9528c6b709dSTomeu Vizoso 	spin_unlock(&pipe_crc->lock);
9536cc42152SMaarten Lankhorst 
954246ee524STomeu Vizoso 	drm_crtc_add_crc_entry(&crtc->base, true,
955ca814b25SDaniel Vetter 				drm_crtc_accurate_vblank_count(&crtc->base),
956246ee524STomeu Vizoso 				crcs);
9578c6b709dSTomeu Vizoso }
958277de95eSDaniel Vetter #else
959277de95eSDaniel Vetter static inline void
96091d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
96191d14251STvrtko Ursulin 			     enum pipe pipe,
962a9c287c9SJani Nikula 			     u32 crc0, u32 crc1,
963a9c287c9SJani Nikula 			     u32 crc2, u32 crc3,
964a9c287c9SJani Nikula 			     u32 crc4) {}
965277de95eSDaniel Vetter #endif
966eba94eb9SDaniel Vetter 
9671288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915,
9681288f9b0SKarthik B S 			      enum pipe pipe)
9691288f9b0SKarthik B S {
9707794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
9711288f9b0SKarthik B S 	struct drm_crtc_state *crtc_state = crtc->base.state;
9721288f9b0SKarthik B S 	struct drm_pending_vblank_event *e = crtc_state->event;
9731288f9b0SKarthik B S 	struct drm_device *dev = &i915->drm;
9741288f9b0SKarthik B S 	unsigned long irqflags;
9751288f9b0SKarthik B S 
9761288f9b0SKarthik B S 	spin_lock_irqsave(&dev->event_lock, irqflags);
9771288f9b0SKarthik B S 
9781288f9b0SKarthik B S 	crtc_state->event = NULL;
9791288f9b0SKarthik B S 
9801288f9b0SKarthik B S 	drm_crtc_send_vblank_event(&crtc->base, e);
9811288f9b0SKarthik B S 
9821288f9b0SKarthik B S 	spin_unlock_irqrestore(&dev->event_lock, irqflags);
9831288f9b0SKarthik B S }
984277de95eSDaniel Vetter 
98591d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
98691d14251STvrtko Ursulin 				     enum pipe pipe)
9875a69b89fSDaniel Vetter {
98891d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
9892939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
9905a69b89fSDaniel Vetter 				     0, 0, 0, 0);
9915a69b89fSDaniel Vetter }
9925a69b89fSDaniel Vetter 
99391d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
99491d14251STvrtko Ursulin 				     enum pipe pipe)
995eba94eb9SDaniel Vetter {
99691d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
9972939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
9982939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)),
9992939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)),
10002939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)),
10012939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe)));
1002eba94eb9SDaniel Vetter }
10035b3a856bSDaniel Vetter 
100491d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
100591d14251STvrtko Ursulin 				      enum pipe pipe)
10065b3a856bSDaniel Vetter {
1007a9c287c9SJani Nikula 	u32 res1, res2;
10080b5c5ed0SDaniel Vetter 
1009373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 3)
10102939eb06SJani Nikula 		res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe));
10110b5c5ed0SDaniel Vetter 	else
10120b5c5ed0SDaniel Vetter 		res1 = 0;
10130b5c5ed0SDaniel Vetter 
1014373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
10152939eb06SJani Nikula 		res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe));
10160b5c5ed0SDaniel Vetter 	else
10170b5c5ed0SDaniel Vetter 		res2 = 0;
10185b3a856bSDaniel Vetter 
101991d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
10202939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)),
10212939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)),
10222939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)),
10230b5c5ed0SDaniel Vetter 				     res1, res2);
10245b3a856bSDaniel Vetter }
10258bf1e9f1SShuang He 
102644d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
102744d9241eSVille Syrjälä {
102844d9241eSVille Syrjälä 	enum pipe pipe;
102944d9241eSVille Syrjälä 
103044d9241eSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
10312939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe),
103244d9241eSVille Syrjälä 			   PIPESTAT_INT_STATUS_MASK |
103344d9241eSVille Syrjälä 			   PIPE_FIFO_UNDERRUN_STATUS);
103444d9241eSVille Syrjälä 
103544d9241eSVille Syrjälä 		dev_priv->pipestat_irq_mask[pipe] = 0;
103644d9241eSVille Syrjälä 	}
103744d9241eSVille Syrjälä }
103844d9241eSVille Syrjälä 
1039eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
104091d14251STvrtko Ursulin 				  u32 iir, u32 pipe_stats[I915_MAX_PIPES])
10417e231dbeSJesse Barnes {
1042d048a268SVille Syrjälä 	enum pipe pipe;
10437e231dbeSJesse Barnes 
104458ead0d7SImre Deak 	spin_lock(&dev_priv->irq_lock);
10451ca993d2SVille Syrjälä 
10461ca993d2SVille Syrjälä 	if (!dev_priv->display_irqs_enabled) {
10471ca993d2SVille Syrjälä 		spin_unlock(&dev_priv->irq_lock);
10481ca993d2SVille Syrjälä 		return;
10491ca993d2SVille Syrjälä 	}
10501ca993d2SVille Syrjälä 
1051055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1052f0f59a00SVille Syrjälä 		i915_reg_t reg;
10536b12ca56SVille Syrjälä 		u32 status_mask, enable_mask, iir_bit = 0;
105491d181ddSImre Deak 
1055bbb5eebfSDaniel Vetter 		/*
1056bbb5eebfSDaniel Vetter 		 * PIPESTAT bits get signalled even when the interrupt is
1057bbb5eebfSDaniel Vetter 		 * disabled with the mask bits, and some of the status bits do
1058bbb5eebfSDaniel Vetter 		 * not generate interrupts at all (like the underrun bit). Hence
1059bbb5eebfSDaniel Vetter 		 * we need to be careful that we only handle what we want to
1060bbb5eebfSDaniel Vetter 		 * handle.
1061bbb5eebfSDaniel Vetter 		 */
10620f239f4cSDaniel Vetter 
10630f239f4cSDaniel Vetter 		/* fifo underruns are filterered in the underrun handler. */
10646b12ca56SVille Syrjälä 		status_mask = PIPE_FIFO_UNDERRUN_STATUS;
1065bbb5eebfSDaniel Vetter 
1066bbb5eebfSDaniel Vetter 		switch (pipe) {
1067d048a268SVille Syrjälä 		default:
1068bbb5eebfSDaniel Vetter 		case PIPE_A:
1069bbb5eebfSDaniel Vetter 			iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
1070bbb5eebfSDaniel Vetter 			break;
1071bbb5eebfSDaniel Vetter 		case PIPE_B:
1072bbb5eebfSDaniel Vetter 			iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
1073bbb5eebfSDaniel Vetter 			break;
10743278f67fSVille Syrjälä 		case PIPE_C:
10753278f67fSVille Syrjälä 			iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
10763278f67fSVille Syrjälä 			break;
1077bbb5eebfSDaniel Vetter 		}
1078bbb5eebfSDaniel Vetter 		if (iir & iir_bit)
10796b12ca56SVille Syrjälä 			status_mask |= dev_priv->pipestat_irq_mask[pipe];
1080bbb5eebfSDaniel Vetter 
10816b12ca56SVille Syrjälä 		if (!status_mask)
108291d181ddSImre Deak 			continue;
108391d181ddSImre Deak 
108491d181ddSImre Deak 		reg = PIPESTAT(pipe);
10852939eb06SJani Nikula 		pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask;
10866b12ca56SVille Syrjälä 		enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
10877e231dbeSJesse Barnes 
10887e231dbeSJesse Barnes 		/*
10897e231dbeSJesse Barnes 		 * Clear the PIPE*STAT regs before the IIR
1090132c27c9SVille Syrjälä 		 *
1091132c27c9SVille Syrjälä 		 * Toggle the enable bits to make sure we get an
1092132c27c9SVille Syrjälä 		 * edge in the ISR pipe event bit if we don't clear
1093132c27c9SVille Syrjälä 		 * all the enabled status bits. Otherwise the edge
1094132c27c9SVille Syrjälä 		 * triggered IIR on i965/g4x wouldn't notice that
1095132c27c9SVille Syrjälä 		 * an interrupt is still pending.
10967e231dbeSJesse Barnes 		 */
1097132c27c9SVille Syrjälä 		if (pipe_stats[pipe]) {
10982939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]);
10992939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, reg, enable_mask);
1100132c27c9SVille Syrjälä 		}
11017e231dbeSJesse Barnes 	}
110258ead0d7SImre Deak 	spin_unlock(&dev_priv->irq_lock);
11032ecb8ca4SVille Syrjälä }
11042ecb8ca4SVille Syrjälä 
1105eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv,
1106eb64343cSVille Syrjälä 				      u16 iir, u32 pipe_stats[I915_MAX_PIPES])
1107eb64343cSVille Syrjälä {
1108eb64343cSVille Syrjälä 	enum pipe pipe;
1109eb64343cSVille Syrjälä 
1110eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
1111eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
1112aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1113eb64343cSVille Syrjälä 
1114eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
1115eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1116eb64343cSVille Syrjälä 
1117eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
1118eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1119eb64343cSVille Syrjälä 	}
1120eb64343cSVille Syrjälä }
1121eb64343cSVille Syrjälä 
1122eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv,
1123eb64343cSVille Syrjälä 				      u32 iir, u32 pipe_stats[I915_MAX_PIPES])
1124eb64343cSVille Syrjälä {
1125eb64343cSVille Syrjälä 	bool blc_event = false;
1126eb64343cSVille Syrjälä 	enum pipe pipe;
1127eb64343cSVille Syrjälä 
1128eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
1129eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
1130aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1131eb64343cSVille Syrjälä 
1132eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
1133eb64343cSVille Syrjälä 			blc_event = true;
1134eb64343cSVille Syrjälä 
1135eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
1136eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1137eb64343cSVille Syrjälä 
1138eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
1139eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1140eb64343cSVille Syrjälä 	}
1141eb64343cSVille Syrjälä 
1142eb64343cSVille Syrjälä 	if (blc_event || (iir & I915_ASLE_INTERRUPT))
1143eb64343cSVille Syrjälä 		intel_opregion_asle_intr(dev_priv);
1144eb64343cSVille Syrjälä }
1145eb64343cSVille Syrjälä 
1146eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv,
1147eb64343cSVille Syrjälä 				      u32 iir, u32 pipe_stats[I915_MAX_PIPES])
1148eb64343cSVille Syrjälä {
1149eb64343cSVille Syrjälä 	bool blc_event = false;
1150eb64343cSVille Syrjälä 	enum pipe pipe;
1151eb64343cSVille Syrjälä 
1152eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
1153eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
1154aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1155eb64343cSVille Syrjälä 
1156eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
1157eb64343cSVille Syrjälä 			blc_event = true;
1158eb64343cSVille Syrjälä 
1159eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
1160eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1161eb64343cSVille Syrjälä 
1162eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
1163eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1164eb64343cSVille Syrjälä 	}
1165eb64343cSVille Syrjälä 
1166eb64343cSVille Syrjälä 	if (blc_event || (iir & I915_ASLE_INTERRUPT))
1167eb64343cSVille Syrjälä 		intel_opregion_asle_intr(dev_priv);
1168eb64343cSVille Syrjälä 
1169eb64343cSVille Syrjälä 	if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
1170eb64343cSVille Syrjälä 		gmbus_irq_handler(dev_priv);
1171eb64343cSVille Syrjälä }
1172eb64343cSVille Syrjälä 
117391d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
11742ecb8ca4SVille Syrjälä 					    u32 pipe_stats[I915_MAX_PIPES])
11752ecb8ca4SVille Syrjälä {
11762ecb8ca4SVille Syrjälä 	enum pipe pipe;
11777e231dbeSJesse Barnes 
1178055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1179fd3a4024SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
1180aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
11814356d586SDaniel Vetter 
11826ede6b06SVille Syrjälä 		if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
11836ede6b06SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
11846ede6b06SVille Syrjälä 
11854356d586SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
118691d14251STvrtko Ursulin 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
11872d9d2b0bSVille Syrjälä 
11881f7247c0SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
11891f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
119031acc7f5SJesse Barnes 	}
119131acc7f5SJesse Barnes 
1192c1874ed7SImre Deak 	if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
119391d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
1194c1874ed7SImre Deak }
1195c1874ed7SImre Deak 
11961ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
119716c6c56bSVille Syrjälä {
11980ba7c51aSVille Syrjälä 	u32 hotplug_status = 0, hotplug_status_mask;
11990ba7c51aSVille Syrjälä 	int i;
120016c6c56bSVille Syrjälä 
12010ba7c51aSVille Syrjälä 	if (IS_G4X(dev_priv) ||
12020ba7c51aSVille Syrjälä 	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
12030ba7c51aSVille Syrjälä 		hotplug_status_mask = HOTPLUG_INT_STATUS_G4X |
12040ba7c51aSVille Syrjälä 			DP_AUX_CHANNEL_MASK_INT_STATUS_G4X;
12050ba7c51aSVille Syrjälä 	else
12060ba7c51aSVille Syrjälä 		hotplug_status_mask = HOTPLUG_INT_STATUS_I915;
12070ba7c51aSVille Syrjälä 
12080ba7c51aSVille Syrjälä 	/*
12090ba7c51aSVille Syrjälä 	 * We absolutely have to clear all the pending interrupt
12100ba7c51aSVille Syrjälä 	 * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port
12110ba7c51aSVille Syrjälä 	 * interrupt bit won't have an edge, and the i965/g4x
12120ba7c51aSVille Syrjälä 	 * edge triggered IIR will not notice that an interrupt
12130ba7c51aSVille Syrjälä 	 * is still pending. We can't use PORT_HOTPLUG_EN to
12140ba7c51aSVille Syrjälä 	 * guarantee the edge as the act of toggling the enable
12150ba7c51aSVille Syrjälä 	 * bits can itself generate a new hotplug interrupt :(
12160ba7c51aSVille Syrjälä 	 */
12170ba7c51aSVille Syrjälä 	for (i = 0; i < 10; i++) {
12182939eb06SJani Nikula 		u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask;
12190ba7c51aSVille Syrjälä 
12200ba7c51aSVille Syrjälä 		if (tmp == 0)
12210ba7c51aSVille Syrjälä 			return hotplug_status;
12220ba7c51aSVille Syrjälä 
12230ba7c51aSVille Syrjälä 		hotplug_status |= tmp;
12242939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status);
12250ba7c51aSVille Syrjälä 	}
12260ba7c51aSVille Syrjälä 
122748a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, 1,
12280ba7c51aSVille Syrjälä 		      "PORT_HOTPLUG_STAT did not clear (0x%08x)\n",
12292939eb06SJani Nikula 		      intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
12301ae3c34cSVille Syrjälä 
12311ae3c34cSVille Syrjälä 	return hotplug_status;
12321ae3c34cSVille Syrjälä }
12331ae3c34cSVille Syrjälä 
123491d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv,
12351ae3c34cSVille Syrjälä 				 u32 hotplug_status)
12361ae3c34cSVille Syrjälä {
12371ae3c34cSVille Syrjälä 	u32 pin_mask = 0, long_mask = 0;
12380398993bSVille Syrjälä 	u32 hotplug_trigger;
12393ff60f89SOscar Mateo 
12400398993bSVille Syrjälä 	if (IS_G4X(dev_priv) ||
12410398993bSVille Syrjälä 	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
12420398993bSVille Syrjälä 		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
12430398993bSVille Syrjälä 	else
12440398993bSVille Syrjälä 		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
124516c6c56bSVille Syrjälä 
124658f2cf24SVille Syrjälä 	if (hotplug_trigger) {
1247cf53902fSRodrigo Vivi 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
1248cf53902fSRodrigo Vivi 				   hotplug_trigger, hotplug_trigger,
12495a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.hpd,
1250fd63e2a9SImre Deak 				   i9xx_port_hotplug_long_detect);
125158f2cf24SVille Syrjälä 
125291d14251STvrtko Ursulin 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
125358f2cf24SVille Syrjälä 	}
1254369712e8SJani Nikula 
12550398993bSVille Syrjälä 	if ((IS_G4X(dev_priv) ||
12560398993bSVille Syrjälä 	     IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
12570398993bSVille Syrjälä 	    hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
125891d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
125958f2cf24SVille Syrjälä }
126016c6c56bSVille Syrjälä 
1261c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg)
1262c1874ed7SImre Deak {
1263b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
1264c1874ed7SImre Deak 	irqreturn_t ret = IRQ_NONE;
1265c1874ed7SImre Deak 
12662dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
12672dd2a883SImre Deak 		return IRQ_NONE;
12682dd2a883SImre Deak 
12691f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
12709102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
12711f814dacSImre Deak 
12721e1cace9SVille Syrjälä 	do {
12736e814800SVille Syrjälä 		u32 iir, gt_iir, pm_iir;
12742ecb8ca4SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
12751ae3c34cSVille Syrjälä 		u32 hotplug_status = 0;
1276a5e485a9SVille Syrjälä 		u32 ier = 0;
12773ff60f89SOscar Mateo 
12782939eb06SJani Nikula 		gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR);
12792939eb06SJani Nikula 		pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR);
12802939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
1281c1874ed7SImre Deak 
1282c1874ed7SImre Deak 		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
12831e1cace9SVille Syrjälä 			break;
1284c1874ed7SImre Deak 
1285c1874ed7SImre Deak 		ret = IRQ_HANDLED;
1286c1874ed7SImre Deak 
1287a5e485a9SVille Syrjälä 		/*
1288a5e485a9SVille Syrjälä 		 * Theory on interrupt generation, based on empirical evidence:
1289a5e485a9SVille Syrjälä 		 *
1290a5e485a9SVille Syrjälä 		 * x = ((VLV_IIR & VLV_IER) ||
1291a5e485a9SVille Syrjälä 		 *      (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) &&
1292a5e485a9SVille Syrjälä 		 *       (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE)));
1293a5e485a9SVille Syrjälä 		 *
1294a5e485a9SVille Syrjälä 		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
1295a5e485a9SVille Syrjälä 		 * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to
1296a5e485a9SVille Syrjälä 		 * guarantee the CPU interrupt will be raised again even if we
1297a5e485a9SVille Syrjälä 		 * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR
1298a5e485a9SVille Syrjälä 		 * bits this time around.
1299a5e485a9SVille Syrjälä 		 */
13002939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0);
13018cee664dSAndrzej Hajda 		ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
13024a0a0202SVille Syrjälä 
13034a0a0202SVille Syrjälä 		if (gt_iir)
13042939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir);
13054a0a0202SVille Syrjälä 		if (pm_iir)
13062939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir);
13074a0a0202SVille Syrjälä 
13087ce4d1f2SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
13091ae3c34cSVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
13107ce4d1f2SVille Syrjälä 
13113ff60f89SOscar Mateo 		/* Call regardless, as some status bits might not be
13123ff60f89SOscar Mateo 		 * signalled in iir */
1313eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
13147ce4d1f2SVille Syrjälä 
1315eef57324SJerome Anand 		if (iir & (I915_LPE_PIPE_A_INTERRUPT |
1316eef57324SJerome Anand 			   I915_LPE_PIPE_B_INTERRUPT))
1317eef57324SJerome Anand 			intel_lpe_audio_irq_handler(dev_priv);
1318eef57324SJerome Anand 
13197ce4d1f2SVille Syrjälä 		/*
13207ce4d1f2SVille Syrjälä 		 * VLV_IIR is single buffered, and reflects the level
13217ce4d1f2SVille Syrjälä 		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
13227ce4d1f2SVille Syrjälä 		 */
13237ce4d1f2SVille Syrjälä 		if (iir)
13242939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
13254a0a0202SVille Syrjälä 
13262939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
13272939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
13281ae3c34cSVille Syrjälä 
132952894874SVille Syrjälä 		if (gt_iir)
13302cbc876dSMichał Winiarski 			gen6_gt_irq_handler(to_gt(dev_priv), gt_iir);
133152894874SVille Syrjälä 		if (pm_iir)
13322cbc876dSMichał Winiarski 			gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir);
133352894874SVille Syrjälä 
13341ae3c34cSVille Syrjälä 		if (hotplug_status)
133591d14251STvrtko Ursulin 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
13362ecb8ca4SVille Syrjälä 
133791d14251STvrtko Ursulin 		valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
13381e1cace9SVille Syrjälä 	} while (0);
13397e231dbeSJesse Barnes 
13409c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
13419c6508b9SThomas Gleixner 
13429102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
13431f814dacSImre Deak 
13447e231dbeSJesse Barnes 	return ret;
13457e231dbeSJesse Barnes }
13467e231dbeSJesse Barnes 
134743f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg)
134843f328d7SVille Syrjälä {
1349b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
135043f328d7SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
135143f328d7SVille Syrjälä 
13522dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
13532dd2a883SImre Deak 		return IRQ_NONE;
13542dd2a883SImre Deak 
13551f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
13569102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
13571f814dacSImre Deak 
1358579de73bSChris Wilson 	do {
13596e814800SVille Syrjälä 		u32 master_ctl, iir;
13602ecb8ca4SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
13611ae3c34cSVille Syrjälä 		u32 hotplug_status = 0;
1362a5e485a9SVille Syrjälä 		u32 ier = 0;
1363a5e485a9SVille Syrjälä 
13642939eb06SJani Nikula 		master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
13652939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
13663278f67fSVille Syrjälä 
13673278f67fSVille Syrjälä 		if (master_ctl == 0 && iir == 0)
13688e5fd599SVille Syrjälä 			break;
136943f328d7SVille Syrjälä 
137027b6c122SOscar Mateo 		ret = IRQ_HANDLED;
137127b6c122SOscar Mateo 
1372a5e485a9SVille Syrjälä 		/*
1373a5e485a9SVille Syrjälä 		 * Theory on interrupt generation, based on empirical evidence:
1374a5e485a9SVille Syrjälä 		 *
1375a5e485a9SVille Syrjälä 		 * x = ((VLV_IIR & VLV_IER) ||
1376a5e485a9SVille Syrjälä 		 *      ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) &&
1377a5e485a9SVille Syrjälä 		 *       (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL)));
1378a5e485a9SVille Syrjälä 		 *
1379a5e485a9SVille Syrjälä 		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
1380a5e485a9SVille Syrjälä 		 * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to
1381a5e485a9SVille Syrjälä 		 * guarantee the CPU interrupt will be raised again even if we
1382a5e485a9SVille Syrjälä 		 * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL
1383a5e485a9SVille Syrjälä 		 * bits this time around.
1384a5e485a9SVille Syrjälä 		 */
13852939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0);
13868cee664dSAndrzej Hajda 		ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
138743f328d7SVille Syrjälä 
13882cbc876dSMichał Winiarski 		gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
138927b6c122SOscar Mateo 
139027b6c122SOscar Mateo 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
13911ae3c34cSVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
139243f328d7SVille Syrjälä 
139327b6c122SOscar Mateo 		/* Call regardless, as some status bits might not be
139427b6c122SOscar Mateo 		 * signalled in iir */
1395eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
139643f328d7SVille Syrjälä 
1397eef57324SJerome Anand 		if (iir & (I915_LPE_PIPE_A_INTERRUPT |
1398eef57324SJerome Anand 			   I915_LPE_PIPE_B_INTERRUPT |
1399eef57324SJerome Anand 			   I915_LPE_PIPE_C_INTERRUPT))
1400eef57324SJerome Anand 			intel_lpe_audio_irq_handler(dev_priv);
1401eef57324SJerome Anand 
14027ce4d1f2SVille Syrjälä 		/*
14037ce4d1f2SVille Syrjälä 		 * VLV_IIR is single buffered, and reflects the level
14047ce4d1f2SVille Syrjälä 		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
14057ce4d1f2SVille Syrjälä 		 */
14067ce4d1f2SVille Syrjälä 		if (iir)
14072939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
14087ce4d1f2SVille Syrjälä 
14092939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
14102939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
14111ae3c34cSVille Syrjälä 
14121ae3c34cSVille Syrjälä 		if (hotplug_status)
141391d14251STvrtko Ursulin 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
14142ecb8ca4SVille Syrjälä 
141591d14251STvrtko Ursulin 		valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
1416579de73bSChris Wilson 	} while (0);
14173278f67fSVille Syrjälä 
14189c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
14199c6508b9SThomas Gleixner 
14209102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
14211f814dacSImre Deak 
142243f328d7SVille Syrjälä 	return ret;
142343f328d7SVille Syrjälä }
142443f328d7SVille Syrjälä 
142591d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv,
14260398993bSVille Syrjälä 				u32 hotplug_trigger)
1427776ad806SJesse Barnes {
142842db67d6SVille Syrjälä 	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
1429776ad806SJesse Barnes 
14306a39d7c9SJani Nikula 	/*
14316a39d7c9SJani Nikula 	 * Somehow the PCH doesn't seem to really ack the interrupt to the CPU
14326a39d7c9SJani Nikula 	 * unless we touch the hotplug register, even if hotplug_trigger is
14336a39d7c9SJani Nikula 	 * zero. Not acking leads to "The master control interrupt lied (SDE)!"
14346a39d7c9SJani Nikula 	 * errors.
14356a39d7c9SJani Nikula 	 */
14362939eb06SJani Nikula 	dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
14376a39d7c9SJani Nikula 	if (!hotplug_trigger) {
14386a39d7c9SJani Nikula 		u32 mask = PORTA_HOTPLUG_STATUS_MASK |
14396a39d7c9SJani Nikula 			PORTD_HOTPLUG_STATUS_MASK |
14406a39d7c9SJani Nikula 			PORTC_HOTPLUG_STATUS_MASK |
14416a39d7c9SJani Nikula 			PORTB_HOTPLUG_STATUS_MASK;
14426a39d7c9SJani Nikula 		dig_hotplug_reg &= ~mask;
14436a39d7c9SJani Nikula 	}
14446a39d7c9SJani Nikula 
14452939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg);
14466a39d7c9SJani Nikula 	if (!hotplug_trigger)
14476a39d7c9SJani Nikula 		return;
144813cf5504SDave Airlie 
14490398993bSVille Syrjälä 	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
14500398993bSVille Syrjälä 			   hotplug_trigger, dig_hotplug_reg,
14515a4dd6f0SJani Nikula 			   dev_priv->display.hotplug.pch_hpd,
1452fd63e2a9SImre Deak 			   pch_port_hotplug_long_detect);
145340e56410SVille Syrjälä 
145491d14251STvrtko Ursulin 	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1455aaf5ec2eSSonika Jindal }
145691d131d2SDaniel Vetter 
145791d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
145840e56410SVille Syrjälä {
1459d048a268SVille Syrjälä 	enum pipe pipe;
146040e56410SVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
146140e56410SVille Syrjälä 
14620398993bSVille Syrjälä 	ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
146340e56410SVille Syrjälä 
1464cfc33bf7SVille Syrjälä 	if (pch_iir & SDE_AUDIO_POWER_MASK) {
1465cfc33bf7SVille Syrjälä 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
1466776ad806SJesse Barnes 			       SDE_AUDIO_POWER_SHIFT);
146700376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n",
1468cfc33bf7SVille Syrjälä 			port_name(port));
1469cfc33bf7SVille Syrjälä 	}
1470776ad806SJesse Barnes 
1471ce99c256SDaniel Vetter 	if (pch_iir & SDE_AUX_MASK)
147291d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
1473ce99c256SDaniel Vetter 
1474776ad806SJesse Barnes 	if (pch_iir & SDE_GMBUS)
147591d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
1476776ad806SJesse Barnes 
1477776ad806SJesse Barnes 	if (pch_iir & SDE_AUDIO_HDCP_MASK)
147800376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n");
1479776ad806SJesse Barnes 
1480776ad806SJesse Barnes 	if (pch_iir & SDE_AUDIO_TRANS_MASK)
148100376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n");
1482776ad806SJesse Barnes 
1483776ad806SJesse Barnes 	if (pch_iir & SDE_POISON)
148400376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "PCH poison interrupt\n");
1485776ad806SJesse Barnes 
1486b8b65ccdSAnshuman Gupta 	if (pch_iir & SDE_FDI_MASK) {
1487055e393fSDamien Lespiau 		for_each_pipe(dev_priv, pipe)
148800376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm, "  pipe %c FDI IIR: 0x%08x\n",
14899db4a9c7SJesse Barnes 				pipe_name(pipe),
14902939eb06SJani Nikula 				intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
1491b8b65ccdSAnshuman Gupta 	}
1492776ad806SJesse Barnes 
1493776ad806SJesse Barnes 	if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
149400376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n");
1495776ad806SJesse Barnes 
1496776ad806SJesse Barnes 	if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
149700376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm,
149800376ccfSWambui Karuga 			"PCH transcoder CRC error interrupt\n");
1499776ad806SJesse Barnes 
1500776ad806SJesse Barnes 	if (pch_iir & SDE_TRANSA_FIFO_UNDER)
1501a2196033SMatthias Kaehlcke 		intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A);
15028664281bSPaulo Zanoni 
15038664281bSPaulo Zanoni 	if (pch_iir & SDE_TRANSB_FIFO_UNDER)
1504a2196033SMatthias Kaehlcke 		intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B);
15058664281bSPaulo Zanoni }
15068664281bSPaulo Zanoni 
150791d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv)
15088664281bSPaulo Zanoni {
15092939eb06SJani Nikula 	u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT);
15105a69b89fSDaniel Vetter 	enum pipe pipe;
15118664281bSPaulo Zanoni 
1512de032bf4SPaulo Zanoni 	if (err_int & ERR_INT_POISON)
151300376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Poison interrupt\n");
1514de032bf4SPaulo Zanoni 
1515055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
15161f7247c0SDaniel Vetter 		if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
15171f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
15188664281bSPaulo Zanoni 
15195a69b89fSDaniel Vetter 		if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
152091d14251STvrtko Ursulin 			if (IS_IVYBRIDGE(dev_priv))
152191d14251STvrtko Ursulin 				ivb_pipe_crc_irq_handler(dev_priv, pipe);
15225a69b89fSDaniel Vetter 			else
152391d14251STvrtko Ursulin 				hsw_pipe_crc_irq_handler(dev_priv, pipe);
15245a69b89fSDaniel Vetter 		}
15255a69b89fSDaniel Vetter 	}
15268bf1e9f1SShuang He 
15272939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int);
15288664281bSPaulo Zanoni }
15298664281bSPaulo Zanoni 
153091d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv)
15318664281bSPaulo Zanoni {
15322939eb06SJani Nikula 	u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT);
153345c1cd87SMika Kahola 	enum pipe pipe;
15348664281bSPaulo Zanoni 
1535de032bf4SPaulo Zanoni 	if (serr_int & SERR_INT_POISON)
153600376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "PCH poison interrupt\n");
1537de032bf4SPaulo Zanoni 
153845c1cd87SMika Kahola 	for_each_pipe(dev_priv, pipe)
153945c1cd87SMika Kahola 		if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe))
154045c1cd87SMika Kahola 			intel_pch_fifo_underrun_irq_handler(dev_priv, pipe);
15418664281bSPaulo Zanoni 
15422939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int);
1543776ad806SJesse Barnes }
1544776ad806SJesse Barnes 
154591d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
154623e81d69SAdam Jackson {
1547d048a268SVille Syrjälä 	enum pipe pipe;
15486dbf30ceSVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
1549aaf5ec2eSSonika Jindal 
15500398993bSVille Syrjälä 	ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
155191d131d2SDaniel Vetter 
1552cfc33bf7SVille Syrjälä 	if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
1553cfc33bf7SVille Syrjälä 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
155423e81d69SAdam Jackson 			       SDE_AUDIO_POWER_SHIFT_CPT);
155500376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n",
1556cfc33bf7SVille Syrjälä 			port_name(port));
1557cfc33bf7SVille Syrjälä 	}
155823e81d69SAdam Jackson 
155923e81d69SAdam Jackson 	if (pch_iir & SDE_AUX_MASK_CPT)
156091d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
156123e81d69SAdam Jackson 
156223e81d69SAdam Jackson 	if (pch_iir & SDE_GMBUS_CPT)
156391d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
156423e81d69SAdam Jackson 
156523e81d69SAdam Jackson 	if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
156600376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n");
156723e81d69SAdam Jackson 
156823e81d69SAdam Jackson 	if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
156900376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n");
157023e81d69SAdam Jackson 
1571b8b65ccdSAnshuman Gupta 	if (pch_iir & SDE_FDI_MASK_CPT) {
1572055e393fSDamien Lespiau 		for_each_pipe(dev_priv, pipe)
157300376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm, "  pipe %c FDI IIR: 0x%08x\n",
157423e81d69SAdam Jackson 				pipe_name(pipe),
15752939eb06SJani Nikula 				intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
1576b8b65ccdSAnshuman Gupta 	}
15778664281bSPaulo Zanoni 
15788664281bSPaulo Zanoni 	if (pch_iir & SDE_ERROR_CPT)
157991d14251STvrtko Ursulin 		cpt_serr_int_handler(dev_priv);
158023e81d69SAdam Jackson }
158123e81d69SAdam Jackson 
1582babde06dSMika Kahola static void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
1583babde06dSMika Kahola {
1584babde06dSMika Kahola 	enum hpd_pin pin;
1585babde06dSMika Kahola 	u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK);
1586babde06dSMika Kahola 	u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
1587babde06dSMika Kahola 	u32 pin_mask = 0, long_mask = 0;
1588babde06dSMika Kahola 
1589babde06dSMika Kahola 	for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
1590babde06dSMika Kahola 		u32 val;
1591babde06dSMika Kahola 
1592babde06dSMika Kahola 		if (!(i915->display.hotplug.hpd[pin] & hotplug_trigger))
1593babde06dSMika Kahola 			continue;
1594babde06dSMika Kahola 
1595babde06dSMika Kahola 		pin_mask |= BIT(pin);
1596babde06dSMika Kahola 
1597babde06dSMika Kahola 		val = intel_de_read(i915, XELPDP_PORT_HOTPLUG_CTL(pin));
1598babde06dSMika Kahola 		intel_de_write(i915, XELPDP_PORT_HOTPLUG_CTL(pin), val);
1599babde06dSMika Kahola 
1600babde06dSMika Kahola 		if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | XELPDP_TBT_HPD_LONG_DETECT))
1601babde06dSMika Kahola 			long_mask |= BIT(pin);
1602babde06dSMika Kahola 	}
1603babde06dSMika Kahola 
1604babde06dSMika Kahola 	if (pin_mask) {
1605babde06dSMika Kahola 		drm_dbg(&i915->drm,
1606babde06dSMika Kahola 			"pica hotplug event received, stat 0x%08x, pins 0x%08x, long 0x%08x\n",
1607babde06dSMika Kahola 			hotplug_trigger, pin_mask, long_mask);
1608babde06dSMika Kahola 
1609babde06dSMika Kahola 		intel_hpd_irq_handler(i915, pin_mask, long_mask);
1610babde06dSMika Kahola 	}
1611babde06dSMika Kahola 
1612babde06dSMika Kahola 	if (trigger_aux)
1613babde06dSMika Kahola 		dp_aux_irq_handler(i915);
1614babde06dSMika Kahola 
1615babde06dSMika Kahola 	if (!pin_mask && !trigger_aux)
1616babde06dSMika Kahola 		drm_err(&i915->drm,
1617babde06dSMika Kahola 			"Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
1618babde06dSMika Kahola }
1619babde06dSMika Kahola 
162058676af6SLucas De Marchi static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
162131604222SAnusha Srivatsa {
1622e76ab2cfSVille Syrjälä 	u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
1623e76ab2cfSVille Syrjälä 	u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
162431604222SAnusha Srivatsa 	u32 pin_mask = 0, long_mask = 0;
162531604222SAnusha Srivatsa 
162631604222SAnusha Srivatsa 	if (ddi_hotplug_trigger) {
162731604222SAnusha Srivatsa 		u32 dig_hotplug_reg;
162831604222SAnusha Srivatsa 
1629f087cfe6SJani Nikula 		/* Locking due to DSI native GPIO sequences */
1630f087cfe6SJani Nikula 		spin_lock(&dev_priv->irq_lock);
16318cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
1632f087cfe6SJani Nikula 		spin_unlock(&dev_priv->irq_lock);
163331604222SAnusha Srivatsa 
163431604222SAnusha Srivatsa 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16350398993bSVille Syrjälä 				   ddi_hotplug_trigger, dig_hotplug_reg,
16365a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
163731604222SAnusha Srivatsa 				   icp_ddi_port_hotplug_long_detect);
163831604222SAnusha Srivatsa 	}
163931604222SAnusha Srivatsa 
164031604222SAnusha Srivatsa 	if (tc_hotplug_trigger) {
164131604222SAnusha Srivatsa 		u32 dig_hotplug_reg;
164231604222SAnusha Srivatsa 
16438cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0);
164431604222SAnusha Srivatsa 
164531604222SAnusha Srivatsa 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16460398993bSVille Syrjälä 				   tc_hotplug_trigger, dig_hotplug_reg,
16475a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
1648da51e4baSVille Syrjälä 				   icp_tc_port_hotplug_long_detect);
164952dfdba0SLucas De Marchi 	}
165052dfdba0SLucas De Marchi 
165152dfdba0SLucas De Marchi 	if (pin_mask)
165252dfdba0SLucas De Marchi 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
165352dfdba0SLucas De Marchi 
165452dfdba0SLucas De Marchi 	if (pch_iir & SDE_GMBUS_ICP)
165552dfdba0SLucas De Marchi 		gmbus_irq_handler(dev_priv);
165652dfdba0SLucas De Marchi }
165752dfdba0SLucas De Marchi 
165891d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
16596dbf30ceSVille Syrjälä {
16606dbf30ceSVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
16616dbf30ceSVille Syrjälä 		~SDE_PORTE_HOTPLUG_SPT;
16626dbf30ceSVille Syrjälä 	u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
16636dbf30ceSVille Syrjälä 	u32 pin_mask = 0, long_mask = 0;
16646dbf30ceSVille Syrjälä 
16656dbf30ceSVille Syrjälä 	if (hotplug_trigger) {
16666dbf30ceSVille Syrjälä 		u32 dig_hotplug_reg;
16676dbf30ceSVille Syrjälä 
16688cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
16696dbf30ceSVille Syrjälä 
1670cf53902fSRodrigo Vivi 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16710398993bSVille Syrjälä 				   hotplug_trigger, dig_hotplug_reg,
16725a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
167374c0b395SVille Syrjälä 				   spt_port_hotplug_long_detect);
16746dbf30ceSVille Syrjälä 	}
16756dbf30ceSVille Syrjälä 
16766dbf30ceSVille Syrjälä 	if (hotplug2_trigger) {
16776dbf30ceSVille Syrjälä 		u32 dig_hotplug_reg;
16786dbf30ceSVille Syrjälä 
16798cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0);
16806dbf30ceSVille Syrjälä 
1681cf53902fSRodrigo Vivi 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16820398993bSVille Syrjälä 				   hotplug2_trigger, dig_hotplug_reg,
16835a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
16846dbf30ceSVille Syrjälä 				   spt_port_hotplug2_long_detect);
16856dbf30ceSVille Syrjälä 	}
16866dbf30ceSVille Syrjälä 
16876dbf30ceSVille Syrjälä 	if (pin_mask)
168891d14251STvrtko Ursulin 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
16896dbf30ceSVille Syrjälä 
16906dbf30ceSVille Syrjälä 	if (pch_iir & SDE_GMBUS_CPT)
169191d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
16926dbf30ceSVille Syrjälä }
16936dbf30ceSVille Syrjälä 
169491d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv,
16950398993bSVille Syrjälä 				u32 hotplug_trigger)
1696c008bc6eSPaulo Zanoni {
1697e4ce95aaSVille Syrjälä 	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
1698e4ce95aaSVille Syrjälä 
16998cee664dSAndrzej Hajda 	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0);
1700e4ce95aaSVille Syrjälä 
17010398993bSVille Syrjälä 	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
17020398993bSVille Syrjälä 			   hotplug_trigger, dig_hotplug_reg,
17035a4dd6f0SJani Nikula 			   dev_priv->display.hotplug.hpd,
1704e4ce95aaSVille Syrjälä 			   ilk_port_hotplug_long_detect);
170540e56410SVille Syrjälä 
170691d14251STvrtko Ursulin 	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1707e4ce95aaSVille Syrjälä }
1708c008bc6eSPaulo Zanoni 
170991d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
171091d14251STvrtko Ursulin 				    u32 de_iir)
171140e56410SVille Syrjälä {
171240e56410SVille Syrjälä 	enum pipe pipe;
171340e56410SVille Syrjälä 	u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
171440e56410SVille Syrjälä 
171540e56410SVille Syrjälä 	if (hotplug_trigger)
17160398993bSVille Syrjälä 		ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
171740e56410SVille Syrjälä 
1718c008bc6eSPaulo Zanoni 	if (de_iir & DE_AUX_CHANNEL_A)
171991d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
1720c008bc6eSPaulo Zanoni 
1721c008bc6eSPaulo Zanoni 	if (de_iir & DE_GSE)
172291d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
1723c008bc6eSPaulo Zanoni 
1724c008bc6eSPaulo Zanoni 	if (de_iir & DE_POISON)
172500376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Poison interrupt\n");
1726c008bc6eSPaulo Zanoni 
1727055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1728fd3a4024SDaniel Vetter 		if (de_iir & DE_PIPE_VBLANK(pipe))
1729aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1730c008bc6eSPaulo Zanoni 
17314bb18054SVille Syrjälä 		if (de_iir & DE_PLANE_FLIP_DONE(pipe))
17324bb18054SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
17334bb18054SVille Syrjälä 
173440da17c2SDaniel Vetter 		if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
17351f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1736c008bc6eSPaulo Zanoni 
173740da17c2SDaniel Vetter 		if (de_iir & DE_PIPE_CRC_DONE(pipe))
173891d14251STvrtko Ursulin 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1739c008bc6eSPaulo Zanoni 	}
1740c008bc6eSPaulo Zanoni 
1741c008bc6eSPaulo Zanoni 	/* check event from PCH */
1742c008bc6eSPaulo Zanoni 	if (de_iir & DE_PCH_EVENT) {
17432939eb06SJani Nikula 		u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
1744c008bc6eSPaulo Zanoni 
174591d14251STvrtko Ursulin 		if (HAS_PCH_CPT(dev_priv))
174691d14251STvrtko Ursulin 			cpt_irq_handler(dev_priv, pch_iir);
1747c008bc6eSPaulo Zanoni 		else
174891d14251STvrtko Ursulin 			ibx_irq_handler(dev_priv, pch_iir);
1749c008bc6eSPaulo Zanoni 
1750c008bc6eSPaulo Zanoni 		/* should clear PCH hotplug event before clear CPU irq */
17512939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
1752c008bc6eSPaulo Zanoni 	}
1753c008bc6eSPaulo Zanoni 
175493e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT)
17552cbc876dSMichał Winiarski 		gen5_rps_irq_handler(&to_gt(dev_priv)->rps);
1756c008bc6eSPaulo Zanoni }
1757c008bc6eSPaulo Zanoni 
175891d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
175991d14251STvrtko Ursulin 				    u32 de_iir)
17609719fb98SPaulo Zanoni {
176107d27e20SDamien Lespiau 	enum pipe pipe;
176223bb4cb5SVille Syrjälä 	u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
176323bb4cb5SVille Syrjälä 
176440e56410SVille Syrjälä 	if (hotplug_trigger)
17650398993bSVille Syrjälä 		ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
17669719fb98SPaulo Zanoni 
17679719fb98SPaulo Zanoni 	if (de_iir & DE_ERR_INT_IVB)
176891d14251STvrtko Ursulin 		ivb_err_int_handler(dev_priv);
17699719fb98SPaulo Zanoni 
17709719fb98SPaulo Zanoni 	if (de_iir & DE_AUX_CHANNEL_A_IVB)
177191d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
17729719fb98SPaulo Zanoni 
17739719fb98SPaulo Zanoni 	if (de_iir & DE_GSE_IVB)
177491d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
17759719fb98SPaulo Zanoni 
1776055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
177733ef04faSVille Syrjälä 		if (de_iir & DE_PIPE_VBLANK_IVB(pipe))
1778aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
17792a636e24SVille Syrjälä 
17802a636e24SVille Syrjälä 		if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
17812a636e24SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
17829719fb98SPaulo Zanoni 	}
17839719fb98SPaulo Zanoni 
17849719fb98SPaulo Zanoni 	/* check event from PCH */
178591d14251STvrtko Ursulin 	if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
17862939eb06SJani Nikula 		u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
17879719fb98SPaulo Zanoni 
178891d14251STvrtko Ursulin 		cpt_irq_handler(dev_priv, pch_iir);
17899719fb98SPaulo Zanoni 
17909719fb98SPaulo Zanoni 		/* clear PCH hotplug event before clear CPU irq */
17912939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
17929719fb98SPaulo Zanoni 	}
17939719fb98SPaulo Zanoni }
17949719fb98SPaulo Zanoni 
179572c90f62SOscar Mateo /*
179672c90f62SOscar Mateo  * To handle irqs with the minimum potential races with fresh interrupts, we:
179772c90f62SOscar Mateo  * 1 - Disable Master Interrupt Control.
179872c90f62SOscar Mateo  * 2 - Find the source(s) of the interrupt.
179972c90f62SOscar Mateo  * 3 - Clear the Interrupt Identity bits (IIR).
180072c90f62SOscar Mateo  * 4 - Process the interrupt(s) that had bits set in the IIRs.
180172c90f62SOscar Mateo  * 5 - Re-enable Master Interrupt Control.
180272c90f62SOscar Mateo  */
18039eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg)
1804b1f14ad0SJesse Barnes {
1805c48a798aSChris Wilson 	struct drm_i915_private *i915 = arg;
1806c48a798aSChris Wilson 	void __iomem * const regs = i915->uncore.regs;
1807f1af8fc1SPaulo Zanoni 	u32 de_iir, gt_iir, de_ier, sde_ier = 0;
18080e43406bSChris Wilson 	irqreturn_t ret = IRQ_NONE;
1809b1f14ad0SJesse Barnes 
1810c48a798aSChris Wilson 	if (unlikely(!intel_irqs_enabled(i915)))
18112dd2a883SImre Deak 		return IRQ_NONE;
18122dd2a883SImre Deak 
18131f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1814c48a798aSChris Wilson 	disable_rpm_wakeref_asserts(&i915->runtime_pm);
18151f814dacSImre Deak 
1816b1f14ad0SJesse Barnes 	/* disable master interrupt before clearing iir  */
1817c48a798aSChris Wilson 	de_ier = raw_reg_read(regs, DEIER);
1818c48a798aSChris Wilson 	raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
18190e43406bSChris Wilson 
182044498aeaSPaulo Zanoni 	/* Disable south interrupts. We'll only write to SDEIIR once, so further
182144498aeaSPaulo Zanoni 	 * interrupts will will be stored on its back queue, and then we'll be
182244498aeaSPaulo Zanoni 	 * able to process them after we restore SDEIER (as soon as we restore
182344498aeaSPaulo Zanoni 	 * it, we'll get an interrupt if SDEIIR still has something to process
182444498aeaSPaulo Zanoni 	 * due to its back queue). */
1825c48a798aSChris Wilson 	if (!HAS_PCH_NOP(i915)) {
1826c48a798aSChris Wilson 		sde_ier = raw_reg_read(regs, SDEIER);
1827c48a798aSChris Wilson 		raw_reg_write(regs, SDEIER, 0);
1828ab5c608bSBen Widawsky 	}
182944498aeaSPaulo Zanoni 
183072c90f62SOscar Mateo 	/* Find, clear, then process each source of interrupt */
183172c90f62SOscar Mateo 
1832c48a798aSChris Wilson 	gt_iir = raw_reg_read(regs, GTIIR);
18330e43406bSChris Wilson 	if (gt_iir) {
1834c48a798aSChris Wilson 		raw_reg_write(regs, GTIIR, gt_iir);
1835651e7d48SLucas De Marchi 		if (GRAPHICS_VER(i915) >= 6)
18362cbc876dSMichał Winiarski 			gen6_gt_irq_handler(to_gt(i915), gt_iir);
1837d8fc8a47SPaulo Zanoni 		else
18382cbc876dSMichał Winiarski 			gen5_gt_irq_handler(to_gt(i915), gt_iir);
1839c48a798aSChris Wilson 		ret = IRQ_HANDLED;
18400e43406bSChris Wilson 	}
1841b1f14ad0SJesse Barnes 
1842c48a798aSChris Wilson 	de_iir = raw_reg_read(regs, DEIIR);
18430e43406bSChris Wilson 	if (de_iir) {
1844c48a798aSChris Wilson 		raw_reg_write(regs, DEIIR, de_iir);
1845373abf1aSMatt Roper 		if (DISPLAY_VER(i915) >= 7)
1846c48a798aSChris Wilson 			ivb_display_irq_handler(i915, de_iir);
1847f1af8fc1SPaulo Zanoni 		else
1848c48a798aSChris Wilson 			ilk_display_irq_handler(i915, de_iir);
18490e43406bSChris Wilson 		ret = IRQ_HANDLED;
1850c48a798aSChris Wilson 	}
1851c48a798aSChris Wilson 
1852651e7d48SLucas De Marchi 	if (GRAPHICS_VER(i915) >= 6) {
1853c48a798aSChris Wilson 		u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR);
1854c48a798aSChris Wilson 		if (pm_iir) {
1855c48a798aSChris Wilson 			raw_reg_write(regs, GEN6_PMIIR, pm_iir);
18562cbc876dSMichał Winiarski 			gen6_rps_irq_handler(&to_gt(i915)->rps, pm_iir);
1857c48a798aSChris Wilson 			ret = IRQ_HANDLED;
18580e43406bSChris Wilson 		}
1859f1af8fc1SPaulo Zanoni 	}
1860b1f14ad0SJesse Barnes 
1861c48a798aSChris Wilson 	raw_reg_write(regs, DEIER, de_ier);
1862c48a798aSChris Wilson 	if (sde_ier)
1863c48a798aSChris Wilson 		raw_reg_write(regs, SDEIER, sde_ier);
1864b1f14ad0SJesse Barnes 
18659c6508b9SThomas Gleixner 	pmu_irq_stats(i915, ret);
18669c6508b9SThomas Gleixner 
18671f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1868c48a798aSChris Wilson 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
18691f814dacSImre Deak 
1870b1f14ad0SJesse Barnes 	return ret;
1871b1f14ad0SJesse Barnes }
1872b1f14ad0SJesse Barnes 
187391d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv,
18740398993bSVille Syrjälä 				u32 hotplug_trigger)
1875d04a492dSShashank Sharma {
1876cebd87a0SVille Syrjälä 	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
1877d04a492dSShashank Sharma 
18788cee664dSAndrzej Hajda 	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
1879d04a492dSShashank Sharma 
18800398993bSVille Syrjälä 	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
18810398993bSVille Syrjälä 			   hotplug_trigger, dig_hotplug_reg,
18825a4dd6f0SJani Nikula 			   dev_priv->display.hotplug.hpd,
1883cebd87a0SVille Syrjälä 			   bxt_port_hotplug_long_detect);
188440e56410SVille Syrjälä 
188591d14251STvrtko Ursulin 	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1886d04a492dSShashank Sharma }
1887d04a492dSShashank Sharma 
1888121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
1889121e758eSDhinakaran Pandiyan {
1890121e758eSDhinakaran Pandiyan 	u32 pin_mask = 0, long_mask = 0;
1891b796b971SDhinakaran Pandiyan 	u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK;
1892b796b971SDhinakaran Pandiyan 	u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK;
1893121e758eSDhinakaran Pandiyan 
1894121e758eSDhinakaran Pandiyan 	if (trigger_tc) {
1895b796b971SDhinakaran Pandiyan 		u32 dig_hotplug_reg;
1896b796b971SDhinakaran Pandiyan 
18978cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0);
1898121e758eSDhinakaran Pandiyan 
18990398993bSVille Syrjälä 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
19000398993bSVille Syrjälä 				   trigger_tc, dig_hotplug_reg,
19015a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.hpd,
1902da51e4baSVille Syrjälä 				   gen11_port_hotplug_long_detect);
1903121e758eSDhinakaran Pandiyan 	}
1904b796b971SDhinakaran Pandiyan 
1905b796b971SDhinakaran Pandiyan 	if (trigger_tbt) {
1906b796b971SDhinakaran Pandiyan 		u32 dig_hotplug_reg;
1907b796b971SDhinakaran Pandiyan 
19088cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0);
1909b796b971SDhinakaran Pandiyan 
19100398993bSVille Syrjälä 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
19110398993bSVille Syrjälä 				   trigger_tbt, dig_hotplug_reg,
19125a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.hpd,
1913da51e4baSVille Syrjälä 				   gen11_port_hotplug_long_detect);
1914b796b971SDhinakaran Pandiyan 	}
1915b796b971SDhinakaran Pandiyan 
1916b796b971SDhinakaran Pandiyan 	if (pin_mask)
1917b796b971SDhinakaran Pandiyan 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1918b796b971SDhinakaran Pandiyan 	else
191900376ccfSWambui Karuga 		drm_err(&dev_priv->drm,
192000376ccfSWambui Karuga 			"Unexpected DE HPD interrupt 0x%08x\n", iir);
1921121e758eSDhinakaran Pandiyan }
1922121e758eSDhinakaran Pandiyan 
19239d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
19249d17210fSLucas De Marchi {
192555523360SLucas De Marchi 	u32 mask;
19269d17210fSLucas De Marchi 
192720fe778fSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
192820fe778fSMatt Roper 		return TGL_DE_PORT_AUX_DDIA |
192920fe778fSMatt Roper 			TGL_DE_PORT_AUX_DDIB |
193020fe778fSMatt Roper 			TGL_DE_PORT_AUX_DDIC |
193120fe778fSMatt Roper 			XELPD_DE_PORT_AUX_DDID |
193220fe778fSMatt Roper 			XELPD_DE_PORT_AUX_DDIE |
193320fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC1 |
193420fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC2 |
193520fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC3 |
193620fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC4;
193720fe778fSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
193855523360SLucas De Marchi 		return TGL_DE_PORT_AUX_DDIA |
193955523360SLucas De Marchi 			TGL_DE_PORT_AUX_DDIB |
1940e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_DDIC |
1941e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC1 |
1942e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC2 |
1943e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC3 |
1944e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC4 |
1945e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC5 |
1946e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC6;
1947e5df52dcSMatt Roper 
194855523360SLucas De Marchi 
194955523360SLucas De Marchi 	mask = GEN8_AUX_CHANNEL_A;
1950373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 9)
19519d17210fSLucas De Marchi 		mask |= GEN9_AUX_CHANNEL_B |
19529d17210fSLucas De Marchi 			GEN9_AUX_CHANNEL_C |
19539d17210fSLucas De Marchi 			GEN9_AUX_CHANNEL_D;
19549d17210fSLucas De Marchi 
1955938a8a9aSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 11) {
1956938a8a9aSLucas De Marchi 		mask |= ICL_AUX_CHANNEL_F;
195755523360SLucas De Marchi 		mask |= ICL_AUX_CHANNEL_E;
1958938a8a9aSLucas De Marchi 	}
19599d17210fSLucas De Marchi 
19609d17210fSLucas De Marchi 	return mask;
19619d17210fSLucas De Marchi }
19629d17210fSLucas De Marchi 
19635270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
19645270130dSVille Syrjälä {
19651649a4ccSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
196699e2d8bcSMatt Roper 		return RKL_DE_PIPE_IRQ_FAULT_ERRORS;
1967373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11)
1968d506a65dSMatt Roper 		return GEN11_DE_PIPE_IRQ_FAULT_ERRORS;
1969373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 9)
19705270130dSVille Syrjälä 		return GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
19715270130dSVille Syrjälä 	else
19725270130dSVille Syrjälä 		return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
19735270130dSVille Syrjälä }
19745270130dSVille Syrjälä 
197546c63d24SJosé Roberto de Souza static void
197646c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
1977abd58f01SBen Widawsky {
1978e04f7eceSVille Syrjälä 	bool found = false;
1979e04f7eceSVille Syrjälä 
1980e04f7eceSVille Syrjälä 	if (iir & GEN8_DE_MISC_GSE) {
198191d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
1982e04f7eceSVille Syrjälä 		found = true;
1983e04f7eceSVille Syrjälä 	}
1984e04f7eceSVille Syrjälä 
1985e04f7eceSVille Syrjälä 	if (iir & GEN8_DE_EDP_PSR) {
1986b64d6c51SGwan-gyeong Mun 		struct intel_encoder *encoder;
19878241cfbeSJosé Roberto de Souza 		u32 psr_iir;
19888241cfbeSJosé Roberto de Souza 		i915_reg_t iir_reg;
19898241cfbeSJosé Roberto de Souza 
1990a22af61dSJosé Roberto de Souza 		for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
1991b64d6c51SGwan-gyeong Mun 			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1992b64d6c51SGwan-gyeong Mun 
1993373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) >= 12)
1994b64d6c51SGwan-gyeong Mun 				iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder);
19958241cfbeSJosé Roberto de Souza 			else
19968241cfbeSJosé Roberto de Souza 				iir_reg = EDP_PSR_IIR;
19978241cfbeSJosé Roberto de Souza 
19988cee664dSAndrzej Hajda 			psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0);
19998241cfbeSJosé Roberto de Souza 
20008241cfbeSJosé Roberto de Souza 			if (psr_iir)
20018241cfbeSJosé Roberto de Souza 				found = true;
200254fd3149SDhinakaran Pandiyan 
2003b64d6c51SGwan-gyeong Mun 			intel_psr_irq_handler(intel_dp, psr_iir);
2004b64d6c51SGwan-gyeong Mun 
2005b64d6c51SGwan-gyeong Mun 			/* prior GEN12 only have one EDP PSR */
2006373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) < 12)
2007b64d6c51SGwan-gyeong Mun 				break;
2008b64d6c51SGwan-gyeong Mun 		}
2009e04f7eceSVille Syrjälä 	}
2010e04f7eceSVille Syrjälä 
2011e04f7eceSVille Syrjälä 	if (!found)
201200376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n");
2013abd58f01SBen Widawsky }
201446c63d24SJosé Roberto de Souza 
201500acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv,
201600acb329SVandita Kulkarni 					   u32 te_trigger)
201700acb329SVandita Kulkarni {
201800acb329SVandita Kulkarni 	enum pipe pipe = INVALID_PIPE;
201900acb329SVandita Kulkarni 	enum transcoder dsi_trans;
202000acb329SVandita Kulkarni 	enum port port;
202100acb329SVandita Kulkarni 	u32 val, tmp;
202200acb329SVandita Kulkarni 
202300acb329SVandita Kulkarni 	/*
202400acb329SVandita Kulkarni 	 * Incase of dual link, TE comes from DSI_1
202500acb329SVandita Kulkarni 	 * this is to check if dual link is enabled
202600acb329SVandita Kulkarni 	 */
20272939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0));
202800acb329SVandita Kulkarni 	val &= PORT_SYNC_MODE_ENABLE;
202900acb329SVandita Kulkarni 
203000acb329SVandita Kulkarni 	/*
203100acb329SVandita Kulkarni 	 * if dual link is enabled, then read DSI_0
203200acb329SVandita Kulkarni 	 * transcoder registers
203300acb329SVandita Kulkarni 	 */
203400acb329SVandita Kulkarni 	port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ?
203500acb329SVandita Kulkarni 						  PORT_A : PORT_B;
203600acb329SVandita Kulkarni 	dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1;
203700acb329SVandita Kulkarni 
203800acb329SVandita Kulkarni 	/* Check if DSI configured in command mode */
20392939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans));
204000acb329SVandita Kulkarni 	val = val & OP_MODE_MASK;
204100acb329SVandita Kulkarni 
204200acb329SVandita Kulkarni 	if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) {
204300acb329SVandita Kulkarni 		drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n");
204400acb329SVandita Kulkarni 		return;
204500acb329SVandita Kulkarni 	}
204600acb329SVandita Kulkarni 
204700acb329SVandita Kulkarni 	/* Get PIPE for handling VBLANK event */
20482939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans));
204900acb329SVandita Kulkarni 	switch (val & TRANS_DDI_EDP_INPUT_MASK) {
205000acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_A_ON:
205100acb329SVandita Kulkarni 		pipe = PIPE_A;
205200acb329SVandita Kulkarni 		break;
205300acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_B_ONOFF:
205400acb329SVandita Kulkarni 		pipe = PIPE_B;
205500acb329SVandita Kulkarni 		break;
205600acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_C_ONOFF:
205700acb329SVandita Kulkarni 		pipe = PIPE_C;
205800acb329SVandita Kulkarni 		break;
205900acb329SVandita Kulkarni 	default:
206000acb329SVandita Kulkarni 		drm_err(&dev_priv->drm, "Invalid PIPE\n");
206100acb329SVandita Kulkarni 		return;
206200acb329SVandita Kulkarni 	}
206300acb329SVandita Kulkarni 
206400acb329SVandita Kulkarni 	intel_handle_vblank(dev_priv, pipe);
206500acb329SVandita Kulkarni 
206600acb329SVandita Kulkarni 	/* clear TE in dsi IIR */
206700acb329SVandita Kulkarni 	port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A;
20688cee664dSAndrzej Hajda 	tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
206900acb329SVandita Kulkarni }
207000acb329SVandita Kulkarni 
2071cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915)
2072cda195f1SVille Syrjälä {
2073373abf1aSMatt Roper 	if (DISPLAY_VER(i915) >= 9)
2074cda195f1SVille Syrjälä 		return GEN9_PIPE_PLANE1_FLIP_DONE;
2075cda195f1SVille Syrjälä 	else
2076cda195f1SVille Syrjälä 		return GEN8_PIPE_PRIMARY_FLIP_DONE;
2077cda195f1SVille Syrjälä }
2078cda195f1SVille Syrjälä 
20798bcc0840SMatt Roper u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv)
20808bcc0840SMatt Roper {
20818bcc0840SMatt Roper 	u32 mask = GEN8_PIPE_FIFO_UNDERRUN;
20828bcc0840SMatt Roper 
20838bcc0840SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
20848bcc0840SMatt Roper 		mask |= XELPD_PIPE_SOFT_UNDERRUN |
20858bcc0840SMatt Roper 			XELPD_PIPE_HARD_UNDERRUN;
20868bcc0840SMatt Roper 
20878bcc0840SMatt Roper 	return mask;
20888bcc0840SMatt Roper }
20898bcc0840SMatt Roper 
2090babde06dSMika Kahola static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir)
2091babde06dSMika Kahola {
2092babde06dSMika Kahola 	u32 pica_ier = 0;
2093babde06dSMika Kahola 
2094babde06dSMika Kahola 	*pica_iir = 0;
2095babde06dSMika Kahola 	*pch_iir = intel_de_read(i915, SDEIIR);
2096babde06dSMika Kahola 	if (!*pch_iir)
2097babde06dSMika Kahola 		return;
2098babde06dSMika Kahola 
2099babde06dSMika Kahola 	/**
2100babde06dSMika Kahola 	 * PICA IER must be disabled/re-enabled around clearing PICA IIR and
2101babde06dSMika Kahola 	 * SDEIIR, to avoid losing PICA IRQs and to ensure that such IRQs set
2102babde06dSMika Kahola 	 * their flags both in the PICA and SDE IIR.
2103babde06dSMika Kahola 	 */
2104babde06dSMika Kahola 	if (*pch_iir & SDE_PICAINTERRUPT) {
2105babde06dSMika Kahola 		drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTP);
2106babde06dSMika Kahola 
2107babde06dSMika Kahola 		pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0);
2108babde06dSMika Kahola 		*pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR);
2109babde06dSMika Kahola 		intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir);
2110babde06dSMika Kahola 	}
2111babde06dSMika Kahola 
2112babde06dSMika Kahola 	intel_de_write(i915, SDEIIR, *pch_iir);
2113babde06dSMika Kahola 
2114babde06dSMika Kahola 	if (pica_ier)
2115babde06dSMika Kahola 		intel_de_write(i915, PICAINTERRUPT_IER, pica_ier);
2116babde06dSMika Kahola }
2117babde06dSMika Kahola 
211846c63d24SJosé Roberto de Souza static irqreturn_t
211946c63d24SJosé Roberto de Souza gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
212046c63d24SJosé Roberto de Souza {
212146c63d24SJosé Roberto de Souza 	irqreturn_t ret = IRQ_NONE;
212246c63d24SJosé Roberto de Souza 	u32 iir;
212346c63d24SJosé Roberto de Souza 	enum pipe pipe;
212446c63d24SJosé Roberto de Souza 
2125a844cfbeSJosé Roberto de Souza 	drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv));
2126a844cfbeSJosé Roberto de Souza 
212746c63d24SJosé Roberto de Souza 	if (master_ctl & GEN8_DE_MISC_IRQ) {
21282939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR);
212946c63d24SJosé Roberto de Souza 		if (iir) {
21302939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir);
213146c63d24SJosé Roberto de Souza 			ret = IRQ_HANDLED;
213246c63d24SJosé Roberto de Souza 			gen8_de_misc_irq_handler(dev_priv, iir);
213346c63d24SJosé Roberto de Souza 		} else {
21349a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
213500376ccfSWambui Karuga 					    "The master control interrupt lied (DE MISC)!\n");
2136abd58f01SBen Widawsky 		}
213746c63d24SJosé Roberto de Souza 	}
2138abd58f01SBen Widawsky 
2139373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
21402939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR);
2141121e758eSDhinakaran Pandiyan 		if (iir) {
21422939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir);
2143121e758eSDhinakaran Pandiyan 			ret = IRQ_HANDLED;
2144121e758eSDhinakaran Pandiyan 			gen11_hpd_irq_handler(dev_priv, iir);
2145121e758eSDhinakaran Pandiyan 		} else {
21469a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
214700376ccfSWambui Karuga 					    "The master control interrupt lied, (DE HPD)!\n");
2148121e758eSDhinakaran Pandiyan 		}
2149121e758eSDhinakaran Pandiyan 	}
2150121e758eSDhinakaran Pandiyan 
21516d766f02SDaniel Vetter 	if (master_ctl & GEN8_DE_PORT_IRQ) {
21522939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR);
2153e32192e1STvrtko Ursulin 		if (iir) {
2154d04a492dSShashank Sharma 			bool found = false;
2155cebd87a0SVille Syrjälä 
21562939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir);
21576d766f02SDaniel Vetter 			ret = IRQ_HANDLED;
215888e04703SJesse Barnes 
21599d17210fSLucas De Marchi 			if (iir & gen8_de_port_aux_mask(dev_priv)) {
216091d14251STvrtko Ursulin 				dp_aux_irq_handler(dev_priv);
2161d04a492dSShashank Sharma 				found = true;
2162d04a492dSShashank Sharma 			}
2163d04a492dSShashank Sharma 
216470bfb307SMatt Roper 			if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
21659a55a620SVille Syrjälä 				u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK;
21669a55a620SVille Syrjälä 
21679a55a620SVille Syrjälä 				if (hotplug_trigger) {
21689a55a620SVille Syrjälä 					bxt_hpd_irq_handler(dev_priv, hotplug_trigger);
2169d04a492dSShashank Sharma 					found = true;
2170d04a492dSShashank Sharma 				}
2171e32192e1STvrtko Ursulin 			} else if (IS_BROADWELL(dev_priv)) {
21729a55a620SVille Syrjälä 				u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK;
21739a55a620SVille Syrjälä 
21749a55a620SVille Syrjälä 				if (hotplug_trigger) {
21759a55a620SVille Syrjälä 					ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
2176e32192e1STvrtko Ursulin 					found = true;
2177e32192e1STvrtko Ursulin 				}
2178e32192e1STvrtko Ursulin 			}
2179d04a492dSShashank Sharma 
218070bfb307SMatt Roper 			if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
218170bfb307SMatt Roper 			    (iir & BXT_DE_PORT_GMBUS)) {
218291d14251STvrtko Ursulin 				gmbus_irq_handler(dev_priv);
21839e63743eSShashank Sharma 				found = true;
21849e63743eSShashank Sharma 			}
21859e63743eSShashank Sharma 
2186373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) >= 11) {
21879a55a620SVille Syrjälä 				u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
21889a55a620SVille Syrjälä 
21899a55a620SVille Syrjälä 				if (te_trigger) {
21909a55a620SVille Syrjälä 					gen11_dsi_te_interrupt_handler(dev_priv, te_trigger);
219100acb329SVandita Kulkarni 					found = true;
219200acb329SVandita Kulkarni 				}
219300acb329SVandita Kulkarni 			}
219400acb329SVandita Kulkarni 
2195d04a492dSShashank Sharma 			if (!found)
21969a4cea62SLucas De Marchi 				drm_err_ratelimited(&dev_priv->drm,
219700376ccfSWambui Karuga 						    "Unexpected DE Port interrupt\n");
21986d766f02SDaniel Vetter 		}
219938cc46d7SOscar Mateo 		else
22009a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
220100376ccfSWambui Karuga 					    "The master control interrupt lied (DE PORT)!\n");
22026d766f02SDaniel Vetter 	}
22036d766f02SDaniel Vetter 
2204055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
2205fd3a4024SDaniel Vetter 		u32 fault_errors;
2206abd58f01SBen Widawsky 
2207c42664ccSDaniel Vetter 		if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
2208c42664ccSDaniel Vetter 			continue;
2209c42664ccSDaniel Vetter 
22102939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe));
2211e32192e1STvrtko Ursulin 		if (!iir) {
22129a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
221300376ccfSWambui Karuga 					    "The master control interrupt lied (DE PIPE)!\n");
2214e32192e1STvrtko Ursulin 			continue;
2215e32192e1STvrtko Ursulin 		}
2216770de83dSDamien Lespiau 
2217e32192e1STvrtko Ursulin 		ret = IRQ_HANDLED;
22182939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir);
2219e32192e1STvrtko Ursulin 
2220fd3a4024SDaniel Vetter 		if (iir & GEN8_PIPE_VBLANK)
2221aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
2222abd58f01SBen Widawsky 
2223cda195f1SVille Syrjälä 		if (iir & gen8_de_pipe_flip_done_mask(dev_priv))
22241288f9b0SKarthik B S 			flip_done_handler(dev_priv, pipe);
22251288f9b0SKarthik B S 
2226e32192e1STvrtko Ursulin 		if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
222791d14251STvrtko Ursulin 			hsw_pipe_crc_irq_handler(dev_priv, pipe);
22280fbe7870SDaniel Vetter 
22298bcc0840SMatt Roper 		if (iir & gen8_de_pipe_underrun_mask(dev_priv))
2230e32192e1STvrtko Ursulin 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
223138d83c96SDaniel Vetter 
22325270130dSVille Syrjälä 		fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
2233770de83dSDamien Lespiau 		if (fault_errors)
22349a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
223500376ccfSWambui Karuga 					    "Fault errors on pipe %c: 0x%08x\n",
223630100f2bSDaniel Vetter 					    pipe_name(pipe),
2237e32192e1STvrtko Ursulin 					    fault_errors);
2238abd58f01SBen Widawsky 	}
2239abd58f01SBen Widawsky 
224091d14251STvrtko Ursulin 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
2241266ea3d9SShashank Sharma 	    master_ctl & GEN8_DE_PCH_IRQ) {
2242babde06dSMika Kahola 		u32 pica_iir;
2243babde06dSMika Kahola 
224492d03a80SDaniel Vetter 		/*
224592d03a80SDaniel Vetter 		 * FIXME(BDW): Assume for now that the new interrupt handling
224692d03a80SDaniel Vetter 		 * scheme also closed the SDE interrupt handling race we've seen
224792d03a80SDaniel Vetter 		 * on older pch-split platforms. But this needs testing.
224892d03a80SDaniel Vetter 		 */
2249babde06dSMika Kahola 		gen8_read_and_ack_pch_irqs(dev_priv, &iir, &pica_iir);
2250e32192e1STvrtko Ursulin 		if (iir) {
225192d03a80SDaniel Vetter 			ret = IRQ_HANDLED;
22526dbf30ceSVille Syrjälä 
2253babde06dSMika Kahola 			if (pica_iir)
2254babde06dSMika Kahola 				xelpdp_pica_irq_handler(dev_priv, pica_iir);
2255babde06dSMika Kahola 
225658676af6SLucas De Marchi 			if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
225758676af6SLucas De Marchi 				icp_irq_handler(dev_priv, iir);
2258c6c30b91SRodrigo Vivi 			else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
225991d14251STvrtko Ursulin 				spt_irq_handler(dev_priv, iir);
22606dbf30ceSVille Syrjälä 			else
226191d14251STvrtko Ursulin 				cpt_irq_handler(dev_priv, iir);
22622dfb0b81SJani Nikula 		} else {
22632dfb0b81SJani Nikula 			/*
22642dfb0b81SJani Nikula 			 * Like on previous PCH there seems to be something
22652dfb0b81SJani Nikula 			 * fishy going on with forwarding PCH interrupts.
22662dfb0b81SJani Nikula 			 */
226700376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm,
226800376ccfSWambui Karuga 				"The master control interrupt lied (SDE)!\n");
22692dfb0b81SJani Nikula 		}
227092d03a80SDaniel Vetter 	}
227192d03a80SDaniel Vetter 
2272f11a0f46STvrtko Ursulin 	return ret;
2273f11a0f46STvrtko Ursulin }
2274f11a0f46STvrtko Ursulin 
22754376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs)
22764376b9c9SMika Kuoppala {
22774376b9c9SMika Kuoppala 	raw_reg_write(regs, GEN8_MASTER_IRQ, 0);
22784376b9c9SMika Kuoppala 
22794376b9c9SMika Kuoppala 	/*
22804376b9c9SMika Kuoppala 	 * Now with master disabled, get a sample of level indications
22814376b9c9SMika Kuoppala 	 * for this interrupt. Indications will be cleared on related acks.
22824376b9c9SMika Kuoppala 	 * New indications can and will light up during processing,
22834376b9c9SMika Kuoppala 	 * and will generate new interrupt after enabling master.
22844376b9c9SMika Kuoppala 	 */
22854376b9c9SMika Kuoppala 	return raw_reg_read(regs, GEN8_MASTER_IRQ);
22864376b9c9SMika Kuoppala }
22874376b9c9SMika Kuoppala 
22884376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs)
22894376b9c9SMika Kuoppala {
22904376b9c9SMika Kuoppala 	raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
22914376b9c9SMika Kuoppala }
22924376b9c9SMika Kuoppala 
2293f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg)
2294f11a0f46STvrtko Ursulin {
2295b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
229625286aacSDaniele Ceraolo Spurio 	void __iomem * const regs = dev_priv->uncore.regs;
2297f11a0f46STvrtko Ursulin 	u32 master_ctl;
2298f11a0f46STvrtko Ursulin 
2299f11a0f46STvrtko Ursulin 	if (!intel_irqs_enabled(dev_priv))
2300f11a0f46STvrtko Ursulin 		return IRQ_NONE;
2301f11a0f46STvrtko Ursulin 
23024376b9c9SMika Kuoppala 	master_ctl = gen8_master_intr_disable(regs);
23034376b9c9SMika Kuoppala 	if (!master_ctl) {
23044376b9c9SMika Kuoppala 		gen8_master_intr_enable(regs);
2305f11a0f46STvrtko Ursulin 		return IRQ_NONE;
23064376b9c9SMika Kuoppala 	}
2307f11a0f46STvrtko Ursulin 
23086cc32f15SChris Wilson 	/* Find, queue (onto bottom-halves), then clear each source */
23092cbc876dSMichał Winiarski 	gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
2310f0fd96f5SChris Wilson 
2311f0fd96f5SChris Wilson 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
2312f0fd96f5SChris Wilson 	if (master_ctl & ~GEN8_GT_IRQS) {
23139102650fSDaniele Ceraolo Spurio 		disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
231455ef72f2SChris Wilson 		gen8_de_irq_handler(dev_priv, master_ctl);
23159102650fSDaniele Ceraolo Spurio 		enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
2316f0fd96f5SChris Wilson 	}
2317f11a0f46STvrtko Ursulin 
23184376b9c9SMika Kuoppala 	gen8_master_intr_enable(regs);
2319abd58f01SBen Widawsky 
23209c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
23219c6508b9SThomas Gleixner 
232255ef72f2SChris Wilson 	return IRQ_HANDLED;
2323abd58f01SBen Widawsky }
2324abd58f01SBen Widawsky 
232551951ae7SMika Kuoppala static u32
2326ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl)
2327df0d28c1SDhinakaran Pandiyan {
2328ddcf980fSAnusha Srivatsa 	void __iomem * const regs = i915->uncore.regs;
23297a909383SChris Wilson 	u32 iir;
2330df0d28c1SDhinakaran Pandiyan 
2331df0d28c1SDhinakaran Pandiyan 	if (!(master_ctl & GEN11_GU_MISC_IRQ))
23327a909383SChris Wilson 		return 0;
2333df0d28c1SDhinakaran Pandiyan 
23347a909383SChris Wilson 	iir = raw_reg_read(regs, GEN11_GU_MISC_IIR);
23357a909383SChris Wilson 	if (likely(iir))
23367a909383SChris Wilson 		raw_reg_write(regs, GEN11_GU_MISC_IIR, iir);
23377a909383SChris Wilson 
23387a909383SChris Wilson 	return iir;
2339df0d28c1SDhinakaran Pandiyan }
2340df0d28c1SDhinakaran Pandiyan 
2341df0d28c1SDhinakaran Pandiyan static void
2342ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir)
2343df0d28c1SDhinakaran Pandiyan {
2344df0d28c1SDhinakaran Pandiyan 	if (iir & GEN11_GU_MISC_GSE)
2345ddcf980fSAnusha Srivatsa 		intel_opregion_asle_intr(i915);
2346df0d28c1SDhinakaran Pandiyan }
2347df0d28c1SDhinakaran Pandiyan 
234881067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs)
234981067b71SMika Kuoppala {
235081067b71SMika Kuoppala 	raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0);
235181067b71SMika Kuoppala 
235281067b71SMika Kuoppala 	/*
235381067b71SMika Kuoppala 	 * Now with master disabled, get a sample of level indications
235481067b71SMika Kuoppala 	 * for this interrupt. Indications will be cleared on related acks.
235581067b71SMika Kuoppala 	 * New indications can and will light up during processing,
235681067b71SMika Kuoppala 	 * and will generate new interrupt after enabling master.
235781067b71SMika Kuoppala 	 */
235881067b71SMika Kuoppala 	return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
235981067b71SMika Kuoppala }
236081067b71SMika Kuoppala 
236181067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs)
236281067b71SMika Kuoppala {
236381067b71SMika Kuoppala 	raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ);
236481067b71SMika Kuoppala }
236581067b71SMika Kuoppala 
2366a3265d85SMatt Roper static void
2367a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915)
2368a3265d85SMatt Roper {
2369a3265d85SMatt Roper 	void __iomem * const regs = i915->uncore.regs;
2370a3265d85SMatt Roper 	const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
2371a3265d85SMatt Roper 
2372a3265d85SMatt Roper 	disable_rpm_wakeref_asserts(&i915->runtime_pm);
2373a3265d85SMatt Roper 	/*
2374a3265d85SMatt Roper 	 * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
2375a3265d85SMatt Roper 	 * for the display related bits.
2376a3265d85SMatt Roper 	 */
2377a3265d85SMatt Roper 	raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0);
2378a3265d85SMatt Roper 	gen8_de_irq_handler(i915, disp_ctl);
2379a3265d85SMatt Roper 	raw_reg_write(regs, GEN11_DISPLAY_INT_CTL,
2380a3265d85SMatt Roper 		      GEN11_DISPLAY_IRQ_ENABLE);
2381a3265d85SMatt Roper 
2382a3265d85SMatt Roper 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
2383a3265d85SMatt Roper }
2384a3265d85SMatt Roper 
238522e26af7SPaulo Zanoni static irqreturn_t gen11_irq_handler(int irq, void *arg)
238651951ae7SMika Kuoppala {
238722e26af7SPaulo Zanoni 	struct drm_i915_private *i915 = arg;
238825286aacSDaniele Ceraolo Spurio 	void __iomem * const regs = i915->uncore.regs;
23892cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(i915);
239051951ae7SMika Kuoppala 	u32 master_ctl;
2391df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_iir;
239251951ae7SMika Kuoppala 
239351951ae7SMika Kuoppala 	if (!intel_irqs_enabled(i915))
239451951ae7SMika Kuoppala 		return IRQ_NONE;
239551951ae7SMika Kuoppala 
239622e26af7SPaulo Zanoni 	master_ctl = gen11_master_intr_disable(regs);
239781067b71SMika Kuoppala 	if (!master_ctl) {
239822e26af7SPaulo Zanoni 		gen11_master_intr_enable(regs);
239951951ae7SMika Kuoppala 		return IRQ_NONE;
240081067b71SMika Kuoppala 	}
240151951ae7SMika Kuoppala 
24026cc32f15SChris Wilson 	/* Find, queue (onto bottom-halves), then clear each source */
24039b77011eSTvrtko Ursulin 	gen11_gt_irq_handler(gt, master_ctl);
240451951ae7SMika Kuoppala 
240551951ae7SMika Kuoppala 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
2406a3265d85SMatt Roper 	if (master_ctl & GEN11_DISPLAY_IRQ)
2407a3265d85SMatt Roper 		gen11_display_irq_handler(i915);
240851951ae7SMika Kuoppala 
2409ddcf980fSAnusha Srivatsa 	gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl);
2410df0d28c1SDhinakaran Pandiyan 
241122e26af7SPaulo Zanoni 	gen11_master_intr_enable(regs);
241251951ae7SMika Kuoppala 
2413ddcf980fSAnusha Srivatsa 	gen11_gu_misc_irq_handler(i915, gu_misc_iir);
2414df0d28c1SDhinakaran Pandiyan 
24159c6508b9SThomas Gleixner 	pmu_irq_stats(i915, IRQ_HANDLED);
24169c6508b9SThomas Gleixner 
241751951ae7SMika Kuoppala 	return IRQ_HANDLED;
241851951ae7SMika Kuoppala }
241951951ae7SMika Kuoppala 
242022e26af7SPaulo Zanoni static inline u32 dg1_master_intr_disable(void __iomem * const regs)
242197b492f5SLucas De Marchi {
242297b492f5SLucas De Marchi 	u32 val;
242397b492f5SLucas De Marchi 
242497b492f5SLucas De Marchi 	/* First disable interrupts */
242522e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0);
242697b492f5SLucas De Marchi 
242797b492f5SLucas De Marchi 	/* Get the indication levels and ack the master unit */
242822e26af7SPaulo Zanoni 	val = raw_reg_read(regs, DG1_MSTR_TILE_INTR);
242997b492f5SLucas De Marchi 	if (unlikely(!val))
243097b492f5SLucas De Marchi 		return 0;
243197b492f5SLucas De Marchi 
243222e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, val);
243397b492f5SLucas De Marchi 
243497b492f5SLucas De Marchi 	return val;
243597b492f5SLucas De Marchi }
243697b492f5SLucas De Marchi 
243797b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs)
243897b492f5SLucas De Marchi {
243922e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ);
244097b492f5SLucas De Marchi }
244197b492f5SLucas De Marchi 
244297b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg)
244397b492f5SLucas De Marchi {
244422e26af7SPaulo Zanoni 	struct drm_i915_private * const i915 = arg;
24452cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(i915);
2446fd4d7904SPaulo Zanoni 	void __iomem * const regs = gt->uncore->regs;
244722e26af7SPaulo Zanoni 	u32 master_tile_ctl, master_ctl;
244822e26af7SPaulo Zanoni 	u32 gu_misc_iir;
244922e26af7SPaulo Zanoni 
245022e26af7SPaulo Zanoni 	if (!intel_irqs_enabled(i915))
245122e26af7SPaulo Zanoni 		return IRQ_NONE;
245222e26af7SPaulo Zanoni 
245322e26af7SPaulo Zanoni 	master_tile_ctl = dg1_master_intr_disable(regs);
245422e26af7SPaulo Zanoni 	if (!master_tile_ctl) {
245522e26af7SPaulo Zanoni 		dg1_master_intr_enable(regs);
245622e26af7SPaulo Zanoni 		return IRQ_NONE;
245722e26af7SPaulo Zanoni 	}
245822e26af7SPaulo Zanoni 
245922e26af7SPaulo Zanoni 	/* FIXME: we only support tile 0 for now. */
246022e26af7SPaulo Zanoni 	if (master_tile_ctl & DG1_MSTR_TILE(0)) {
246122e26af7SPaulo Zanoni 		master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
246222e26af7SPaulo Zanoni 		raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl);
246322e26af7SPaulo Zanoni 	} else {
2464a10234fdSTvrtko Ursulin 		drm_err(&i915->drm, "Tile not supported: 0x%08x\n",
2465a10234fdSTvrtko Ursulin 			master_tile_ctl);
246622e26af7SPaulo Zanoni 		dg1_master_intr_enable(regs);
246722e26af7SPaulo Zanoni 		return IRQ_NONE;
246822e26af7SPaulo Zanoni 	}
246922e26af7SPaulo Zanoni 
247022e26af7SPaulo Zanoni 	gen11_gt_irq_handler(gt, master_ctl);
247122e26af7SPaulo Zanoni 
247222e26af7SPaulo Zanoni 	if (master_ctl & GEN11_DISPLAY_IRQ)
247322e26af7SPaulo Zanoni 		gen11_display_irq_handler(i915);
247422e26af7SPaulo Zanoni 
2475ddcf980fSAnusha Srivatsa 	gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl);
247622e26af7SPaulo Zanoni 
247722e26af7SPaulo Zanoni 	dg1_master_intr_enable(regs);
247822e26af7SPaulo Zanoni 
2479ddcf980fSAnusha Srivatsa 	gen11_gu_misc_irq_handler(i915, gu_misc_iir);
248022e26af7SPaulo Zanoni 
248122e26af7SPaulo Zanoni 	pmu_irq_stats(i915, IRQ_HANDLED);
248222e26af7SPaulo Zanoni 
248322e26af7SPaulo Zanoni 	return IRQ_HANDLED;
248497b492f5SLucas De Marchi }
248597b492f5SLucas De Marchi 
248642f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which
248742f52ef8SKeith Packard  * we use as a pipe index
248842f52ef8SKeith Packard  */
248908fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc)
24900a3e67a4SJesse Barnes {
249108fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
249208fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2493e9d21d7fSKeith Packard 	unsigned long irqflags;
249471e0ffa5SJesse Barnes 
24951ec14ad3SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
249686e83e35SChris Wilson 	i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
249786e83e35SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
249886e83e35SChris Wilson 
249986e83e35SChris Wilson 	return 0;
250086e83e35SChris Wilson }
250186e83e35SChris Wilson 
25027d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc)
2503d938da6bSVille Syrjälä {
250408fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
2505d938da6bSVille Syrjälä 
25067d423af9SVille Syrjälä 	/*
25077d423af9SVille Syrjälä 	 * Vblank interrupts fail to wake the device up from C2+.
25087d423af9SVille Syrjälä 	 * Disabling render clock gating during C-states avoids
25097d423af9SVille Syrjälä 	 * the problem. There is a small power cost so we do this
25107d423af9SVille Syrjälä 	 * only when vblank interrupts are actually enabled.
25117d423af9SVille Syrjälä 	 */
25127d423af9SVille Syrjälä 	if (dev_priv->vblank_enabled++ == 0)
25132939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
2514d938da6bSVille Syrjälä 
251508fa8fd0SVille Syrjälä 	return i8xx_enable_vblank(crtc);
2516d938da6bSVille Syrjälä }
2517d938da6bSVille Syrjälä 
251808fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc)
251986e83e35SChris Wilson {
252008fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
252108fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
252286e83e35SChris Wilson 	unsigned long irqflags;
252386e83e35SChris Wilson 
252486e83e35SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
25257c463586SKeith Packard 	i915_enable_pipestat(dev_priv, pipe,
2526755e9019SImre Deak 			     PIPE_START_VBLANK_INTERRUPT_STATUS);
25271ec14ad3SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
25288692d00eSChris Wilson 
25290a3e67a4SJesse Barnes 	return 0;
25300a3e67a4SJesse Barnes }
25310a3e67a4SJesse Barnes 
253208fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc)
2533f796cf8fSJesse Barnes {
253408fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
253508fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2536f796cf8fSJesse Barnes 	unsigned long irqflags;
2537373abf1aSMatt Roper 	u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
253886e83e35SChris Wilson 		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
2539f796cf8fSJesse Barnes 
2540f796cf8fSJesse Barnes 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2541fbdedaeaSVille Syrjälä 	ilk_enable_display_irq(dev_priv, bit);
2542b1f14ad0SJesse Barnes 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2543b1f14ad0SJesse Barnes 
25442e8bf223SDhinakaran Pandiyan 	/* Even though there is no DMC, frame counter can get stuck when
25452e8bf223SDhinakaran Pandiyan 	 * PSR is active as no frames are generated.
25462e8bf223SDhinakaran Pandiyan 	 */
25472e8bf223SDhinakaran Pandiyan 	if (HAS_PSR(dev_priv))
254808fa8fd0SVille Syrjälä 		drm_crtc_vblank_restore(crtc);
25492e8bf223SDhinakaran Pandiyan 
2550b1f14ad0SJesse Barnes 	return 0;
2551b1f14ad0SJesse Barnes }
2552b1f14ad0SJesse Barnes 
25539c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
25549c9e97c4SVandita Kulkarni 				   bool enable)
25559c9e97c4SVandita Kulkarni {
25569c9e97c4SVandita Kulkarni 	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
25579c9e97c4SVandita Kulkarni 	enum port port;
25589c9e97c4SVandita Kulkarni 
25599c9e97c4SVandita Kulkarni 	if (!(intel_crtc->mode_flags &
25609c9e97c4SVandita Kulkarni 	    (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0)))
25619c9e97c4SVandita Kulkarni 		return false;
25629c9e97c4SVandita Kulkarni 
25639c9e97c4SVandita Kulkarni 	/* for dual link cases we consider TE from slave */
25649c9e97c4SVandita Kulkarni 	if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1)
25659c9e97c4SVandita Kulkarni 		port = PORT_B;
25669c9e97c4SVandita Kulkarni 	else
25679c9e97c4SVandita Kulkarni 		port = PORT_A;
25689c9e97c4SVandita Kulkarni 
25698cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT,
25708cee664dSAndrzej Hajda 			 enable ? 0 : DSI_TE_EVENT);
25719c9e97c4SVandita Kulkarni 
25728cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
25739c9e97c4SVandita Kulkarni 
25749c9e97c4SVandita Kulkarni 	return true;
25759c9e97c4SVandita Kulkarni }
25769c9e97c4SVandita Kulkarni 
2577f15f01a7SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *_crtc)
2578abd58f01SBen Widawsky {
2579f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(_crtc);
2580f15f01a7SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2581f15f01a7SVille Syrjälä 	enum pipe pipe = crtc->pipe;
2582abd58f01SBen Widawsky 	unsigned long irqflags;
2583abd58f01SBen Widawsky 
2584f15f01a7SVille Syrjälä 	if (gen11_dsi_configure_te(crtc, true))
25859c9e97c4SVandita Kulkarni 		return 0;
25869c9e97c4SVandita Kulkarni 
2587abd58f01SBen Widawsky 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2588013d3752SVille Syrjälä 	bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
2589abd58f01SBen Widawsky 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2590013d3752SVille Syrjälä 
25912e8bf223SDhinakaran Pandiyan 	/* Even if there is no DMC, frame counter can get stuck when
25922e8bf223SDhinakaran Pandiyan 	 * PSR is active as no frames are generated, so check only for PSR.
25932e8bf223SDhinakaran Pandiyan 	 */
25942e8bf223SDhinakaran Pandiyan 	if (HAS_PSR(dev_priv))
2595f15f01a7SVille Syrjälä 		drm_crtc_vblank_restore(&crtc->base);
25962e8bf223SDhinakaran Pandiyan 
2597abd58f01SBen Widawsky 	return 0;
2598abd58f01SBen Widawsky }
2599abd58f01SBen Widawsky 
260042f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which
260142f52ef8SKeith Packard  * we use as a pipe index
260242f52ef8SKeith Packard  */
260308fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc)
260486e83e35SChris Wilson {
260508fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
260608fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
260786e83e35SChris Wilson 	unsigned long irqflags;
260886e83e35SChris Wilson 
260986e83e35SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
261086e83e35SChris Wilson 	i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
261186e83e35SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
261286e83e35SChris Wilson }
261386e83e35SChris Wilson 
26147d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc)
2615d938da6bSVille Syrjälä {
261608fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
2617d938da6bSVille Syrjälä 
261808fa8fd0SVille Syrjälä 	i8xx_disable_vblank(crtc);
2619d938da6bSVille Syrjälä 
26207d423af9SVille Syrjälä 	if (--dev_priv->vblank_enabled == 0)
26212939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
2622d938da6bSVille Syrjälä }
2623d938da6bSVille Syrjälä 
262408fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc)
26250a3e67a4SJesse Barnes {
262608fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
262708fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2628e9d21d7fSKeith Packard 	unsigned long irqflags;
26290a3e67a4SJesse Barnes 
26301ec14ad3SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
26317c463586SKeith Packard 	i915_disable_pipestat(dev_priv, pipe,
2632755e9019SImre Deak 			      PIPE_START_VBLANK_INTERRUPT_STATUS);
26331ec14ad3SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
26340a3e67a4SJesse Barnes }
26350a3e67a4SJesse Barnes 
263608fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc)
2637f796cf8fSJesse Barnes {
263808fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
263908fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2640f796cf8fSJesse Barnes 	unsigned long irqflags;
2641373abf1aSMatt Roper 	u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
264286e83e35SChris Wilson 		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
2643f796cf8fSJesse Barnes 
2644f796cf8fSJesse Barnes 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2645fbdedaeaSVille Syrjälä 	ilk_disable_display_irq(dev_priv, bit);
2646b1f14ad0SJesse Barnes 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2647b1f14ad0SJesse Barnes }
2648b1f14ad0SJesse Barnes 
2649f15f01a7SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *_crtc)
2650abd58f01SBen Widawsky {
2651f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(_crtc);
2652f15f01a7SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2653f15f01a7SVille Syrjälä 	enum pipe pipe = crtc->pipe;
2654abd58f01SBen Widawsky 	unsigned long irqflags;
2655abd58f01SBen Widawsky 
2656f15f01a7SVille Syrjälä 	if (gen11_dsi_configure_te(crtc, false))
26579c9e97c4SVandita Kulkarni 		return;
26589c9e97c4SVandita Kulkarni 
2659abd58f01SBen Widawsky 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2660013d3752SVille Syrjälä 	bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
2661abd58f01SBen Widawsky 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2662abd58f01SBen Widawsky }
2663abd58f01SBen Widawsky 
2664b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv)
266591738a95SPaulo Zanoni {
2666b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2667b16b2a2fSPaulo Zanoni 
26686e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
266991738a95SPaulo Zanoni 		return;
267091738a95SPaulo Zanoni 
2671b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, SDE);
2672105b122eSPaulo Zanoni 
26736e266956STvrtko Ursulin 	if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
26742939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff);
2675622364b6SPaulo Zanoni }
2676105b122eSPaulo Zanoni 
267770591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
267870591a41SVille Syrjälä {
2679b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2680b16b2a2fSPaulo Zanoni 
268171b8b41dSVille Syrjälä 	if (IS_CHERRYVIEW(dev_priv))
2682f0818984STvrtko Ursulin 		intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
268371b8b41dSVille Syrjälä 	else
26847d938bc0SVille Syrjälä 		intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
268571b8b41dSVille Syrjälä 
2686ad22d106SVille Syrjälä 	i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
26878cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
268870591a41SVille Syrjälä 
268944d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
269070591a41SVille Syrjälä 
2691b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, VLV_);
26928bd099a7SChris Wilson 	dev_priv->irq_mask = ~0u;
269370591a41SVille Syrjälä }
269470591a41SVille Syrjälä 
26958bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
26968bb61306SVille Syrjälä {
2697b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2698b16b2a2fSPaulo Zanoni 
26998bb61306SVille Syrjälä 	u32 pipestat_mask;
27009ab981f2SVille Syrjälä 	u32 enable_mask;
27018bb61306SVille Syrjälä 	enum pipe pipe;
27028bb61306SVille Syrjälä 
2703842ebf7aSVille Syrjälä 	pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
27048bb61306SVille Syrjälä 
27058bb61306SVille Syrjälä 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
27068bb61306SVille Syrjälä 	for_each_pipe(dev_priv, pipe)
27078bb61306SVille Syrjälä 		i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
27088bb61306SVille Syrjälä 
27099ab981f2SVille Syrjälä 	enable_mask = I915_DISPLAY_PORT_INTERRUPT |
27108bb61306SVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
2711ebf5f921SVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
2712ebf5f921SVille Syrjälä 		I915_LPE_PIPE_A_INTERRUPT |
2713ebf5f921SVille Syrjälä 		I915_LPE_PIPE_B_INTERRUPT;
2714ebf5f921SVille Syrjälä 
27158bb61306SVille Syrjälä 	if (IS_CHERRYVIEW(dev_priv))
2716ebf5f921SVille Syrjälä 		enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
2717ebf5f921SVille Syrjälä 			I915_LPE_PIPE_C_INTERRUPT;
27186b7eafc1SVille Syrjälä 
271948a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u);
27206b7eafc1SVille Syrjälä 
27219ab981f2SVille Syrjälä 	dev_priv->irq_mask = ~enable_mask;
27228bb61306SVille Syrjälä 
2723b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask);
27248bb61306SVille Syrjälä }
27258bb61306SVille Syrjälä 
27268bb61306SVille Syrjälä /* drm_dma.h hooks
27278bb61306SVille Syrjälä */
27289eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv)
27298bb61306SVille Syrjälä {
2730b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
27318bb61306SVille Syrjälä 
2732b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, DE);
2733e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
2734e44adb5dSChris Wilson 
2735651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) == 7)
2736f0818984STvrtko Ursulin 		intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff);
27378bb61306SVille Syrjälä 
2738fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
2739f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2740f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
2741fc340442SDaniel Vetter 	}
2742fc340442SDaniel Vetter 
27432cbc876dSMichał Winiarski 	gen5_gt_irq_reset(to_gt(dev_priv));
27448bb61306SVille Syrjälä 
2745b243f530STvrtko Ursulin 	ibx_irq_reset(dev_priv);
27468bb61306SVille Syrjälä }
27478bb61306SVille Syrjälä 
2748b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
27497e231dbeSJesse Barnes {
27502939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0);
27512939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
275234c7b8a7SVille Syrjälä 
27532cbc876dSMichał Winiarski 	gen5_gt_irq_reset(to_gt(dev_priv));
27547e231dbeSJesse Barnes 
2755ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
27569918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
275770591a41SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2758ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
27597e231dbeSJesse Barnes }
27607e231dbeSJesse Barnes 
2761a844cfbeSJosé Roberto de Souza static void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
2762abd58f01SBen Widawsky {
2763b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2764d048a268SVille Syrjälä 	enum pipe pipe;
2765abd58f01SBen Widawsky 
2766a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2767a844cfbeSJosé Roberto de Souza 		return;
2768abd58f01SBen Widawsky 
2769f0818984STvrtko Ursulin 	intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2770f0818984STvrtko Ursulin 	intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
2771e04f7eceSVille Syrjälä 
2772055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe)
2773f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
2774813bde43SPaulo Zanoni 						   POWER_DOMAIN_PIPE(pipe)))
2775b16b2a2fSPaulo Zanoni 			GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
2776abd58f01SBen Widawsky 
2777b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
2778b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
2779a844cfbeSJosé Roberto de Souza }
2780a844cfbeSJosé Roberto de Souza 
2781a844cfbeSJosé Roberto de Souza static void gen8_irq_reset(struct drm_i915_private *dev_priv)
2782a844cfbeSJosé Roberto de Souza {
2783a844cfbeSJosé Roberto de Souza 	struct intel_uncore *uncore = &dev_priv->uncore;
2784a844cfbeSJosé Roberto de Souza 
2785e58c2cacSAndrzej Hajda 	gen8_master_intr_disable(uncore->regs);
2786a844cfbeSJosé Roberto de Souza 
27872cbc876dSMichał Winiarski 	gen8_gt_irq_reset(to_gt(dev_priv));
2788a844cfbeSJosé Roberto de Souza 	gen8_display_irq_reset(dev_priv);
2789b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
2790abd58f01SBen Widawsky 
27916e266956STvrtko Ursulin 	if (HAS_PCH_SPLIT(dev_priv))
2792b243f530STvrtko Ursulin 		ibx_irq_reset(dev_priv);
279359b7cb44STejas Upadhyay 
2794abd58f01SBen Widawsky }
2795abd58f01SBen Widawsky 
2796a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
279751951ae7SMika Kuoppala {
2798b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2799d048a268SVille Syrjälä 	enum pipe pipe;
2800562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
2801562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
280251951ae7SMika Kuoppala 
2803a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2804a844cfbeSJosé Roberto de Souza 		return;
2805a844cfbeSJosé Roberto de Souza 
2806f0818984STvrtko Ursulin 	intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0);
280751951ae7SMika Kuoppala 
2808373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
28098241cfbeSJosé Roberto de Souza 		enum transcoder trans;
28108241cfbeSJosé Roberto de Souza 
2811562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
28128241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
28138241cfbeSJosé Roberto de Souza 
28148241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
28158241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
28168241cfbeSJosé Roberto de Souza 				continue;
28178241cfbeSJosé Roberto de Souza 
28188241cfbeSJosé Roberto de Souza 			intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff);
28198241cfbeSJosé Roberto de Souza 			intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff);
28208241cfbeSJosé Roberto de Souza 		}
28218241cfbeSJosé Roberto de Souza 	} else {
2822f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2823f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
28248241cfbeSJosé Roberto de Souza 	}
282562819dfdSJosé Roberto de Souza 
282651951ae7SMika Kuoppala 	for_each_pipe(dev_priv, pipe)
282751951ae7SMika Kuoppala 		if (intel_display_power_is_enabled(dev_priv,
282851951ae7SMika Kuoppala 						   POWER_DOMAIN_PIPE(pipe)))
2829b16b2a2fSPaulo Zanoni 			GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
283051951ae7SMika Kuoppala 
2831b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
2832b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
2833babde06dSMika Kahola 
2834babde06dSMika Kahola 	if (DISPLAY_VER(dev_priv) >= 14)
2835babde06dSMika Kahola 		GEN3_IRQ_RESET(uncore, PICAINTERRUPT_);
2836babde06dSMika Kahola 	else
2837b16b2a2fSPaulo Zanoni 		GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_);
283831604222SAnusha Srivatsa 
283929b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
2840b16b2a2fSPaulo Zanoni 		GEN3_IRQ_RESET(uncore, SDE);
284151951ae7SMika Kuoppala }
284251951ae7SMika Kuoppala 
2843a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv)
2844a3265d85SMatt Roper {
28452cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2846fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
2847a3265d85SMatt Roper 
2848a3265d85SMatt Roper 	gen11_master_intr_disable(dev_priv->uncore.regs);
2849a3265d85SMatt Roper 
2850fd4d7904SPaulo Zanoni 	gen11_gt_irq_reset(gt);
2851a3265d85SMatt Roper 	gen11_display_irq_reset(dev_priv);
2852a3265d85SMatt Roper 
2853a3265d85SMatt Roper 	GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
2854a3265d85SMatt Roper 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
2855a3265d85SMatt Roper }
2856a3265d85SMatt Roper 
285722e26af7SPaulo Zanoni static void dg1_irq_reset(struct drm_i915_private *dev_priv)
285822e26af7SPaulo Zanoni {
28592cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2860fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
286122e26af7SPaulo Zanoni 
286222e26af7SPaulo Zanoni 	dg1_master_intr_disable(dev_priv->uncore.regs);
286322e26af7SPaulo Zanoni 
2864fd4d7904SPaulo Zanoni 	gen11_gt_irq_reset(gt);
286522e26af7SPaulo Zanoni 	gen11_display_irq_reset(dev_priv);
286622e26af7SPaulo Zanoni 
286722e26af7SPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
286822e26af7SPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
286922e26af7SPaulo Zanoni }
287022e26af7SPaulo Zanoni 
28714c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
2872001bd2cbSImre Deak 				     u8 pipe_mask)
2873d49bdb0eSPaulo Zanoni {
2874b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
28758bcc0840SMatt Roper 	u32 extra_ier = GEN8_PIPE_VBLANK |
28768bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
2877cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
28786831f3e3SVille Syrjälä 	enum pipe pipe;
2879d49bdb0eSPaulo Zanoni 
288013321786SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
28819dfe2e3aSImre Deak 
28829dfe2e3aSImre Deak 	if (!intel_irqs_enabled(dev_priv)) {
28839dfe2e3aSImre Deak 		spin_unlock_irq(&dev_priv->irq_lock);
28849dfe2e3aSImre Deak 		return;
28859dfe2e3aSImre Deak 	}
28869dfe2e3aSImre Deak 
28876831f3e3SVille Syrjälä 	for_each_pipe_masked(dev_priv, pipe, pipe_mask)
2888b16b2a2fSPaulo Zanoni 		GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
28896831f3e3SVille Syrjälä 				  dev_priv->de_irq_mask[pipe],
28906831f3e3SVille Syrjälä 				  ~dev_priv->de_irq_mask[pipe] | extra_ier);
28919dfe2e3aSImre Deak 
289213321786SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
2893d49bdb0eSPaulo Zanoni }
2894d49bdb0eSPaulo Zanoni 
2895aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
2896001bd2cbSImre Deak 				     u8 pipe_mask)
2897aae8ba84SVille Syrjälä {
2898b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
28996831f3e3SVille Syrjälä 	enum pipe pipe;
29006831f3e3SVille Syrjälä 
2901aae8ba84SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
29029dfe2e3aSImre Deak 
29039dfe2e3aSImre Deak 	if (!intel_irqs_enabled(dev_priv)) {
29049dfe2e3aSImre Deak 		spin_unlock_irq(&dev_priv->irq_lock);
29059dfe2e3aSImre Deak 		return;
29069dfe2e3aSImre Deak 	}
29079dfe2e3aSImre Deak 
29086831f3e3SVille Syrjälä 	for_each_pipe_masked(dev_priv, pipe, pipe_mask)
2909b16b2a2fSPaulo Zanoni 		GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
29109dfe2e3aSImre Deak 
2911aae8ba84SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
2912aae8ba84SVille Syrjälä 
2913aae8ba84SVille Syrjälä 	/* make sure we're done processing display irqs */
2914315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
2915aae8ba84SVille Syrjälä }
2916aae8ba84SVille Syrjälä 
2917b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
291843f328d7SVille Syrjälä {
2919b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
292043f328d7SVille Syrjälä 
2921e58c2cacSAndrzej Hajda 	intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0);
29222939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
292343f328d7SVille Syrjälä 
29242cbc876dSMichał Winiarski 	gen8_gt_irq_reset(to_gt(dev_priv));
292543f328d7SVille Syrjälä 
2926b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
292743f328d7SVille Syrjälä 
2928ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
29299918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
293070591a41SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2931ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
293243f328d7SVille Syrjälä }
293343f328d7SVille Syrjälä 
293440d06b0fSVille Syrjälä static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin)
293540d06b0fSVille Syrjälä {
293640d06b0fSVille Syrjälä 	switch (hpd_pin) {
293740d06b0fSVille Syrjälä 	case HPD_PORT_A:
293840d06b0fSVille Syrjälä 		return PORTA_HOTPLUG_ENABLE;
293940d06b0fSVille Syrjälä 	case HPD_PORT_B:
294040d06b0fSVille Syrjälä 		return PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_MASK;
294140d06b0fSVille Syrjälä 	case HPD_PORT_C:
294240d06b0fSVille Syrjälä 		return PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_MASK;
294340d06b0fSVille Syrjälä 	case HPD_PORT_D:
294440d06b0fSVille Syrjälä 		return PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_MASK;
294540d06b0fSVille Syrjälä 	default:
294640d06b0fSVille Syrjälä 		return 0;
294740d06b0fSVille Syrjälä 	}
294840d06b0fSVille Syrjälä }
294940d06b0fSVille Syrjälä 
2950dfefe7bcSVille Syrjälä static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
29512ea63927SVille Syrjälä {
2952dfefe7bcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2953dfefe7bcSVille Syrjälä 
2954dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
29552ea63927SVille Syrjälä 	case HPD_PORT_A:
29562ea63927SVille Syrjälä 		/*
29572ea63927SVille Syrjälä 		 * When CPU and PCH are on the same package, port A
29582ea63927SVille Syrjälä 		 * HPD must be enabled in both north and south.
29592ea63927SVille Syrjälä 		 */
29602ea63927SVille Syrjälä 		return HAS_PCH_LPT_LP(i915) ?
29612ea63927SVille Syrjälä 			PORTA_HOTPLUG_ENABLE : 0;
29622ea63927SVille Syrjälä 	case HPD_PORT_B:
29632ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE |
29642ea63927SVille Syrjälä 			PORTB_PULSE_DURATION_2ms;
29652ea63927SVille Syrjälä 	case HPD_PORT_C:
29662ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE |
29672ea63927SVille Syrjälä 			PORTC_PULSE_DURATION_2ms;
29682ea63927SVille Syrjälä 	case HPD_PORT_D:
29692ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE |
29702ea63927SVille Syrjälä 			PORTD_PULSE_DURATION_2ms;
29712ea63927SVille Syrjälä 	default:
29722ea63927SVille Syrjälä 		return 0;
29732ea63927SVille Syrjälä 	}
29742ea63927SVille Syrjälä }
29752ea63927SVille Syrjälä 
29761a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
29771a56b1a2SImre Deak {
29781a56b1a2SImre Deak 	/*
29791a56b1a2SImre Deak 	 * Enable digital hotplug on the PCH, and configure the DP short pulse
29801a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec).
29811a56b1a2SImre Deak 	 * The pulse duration bits are reserved on LPT+.
29821a56b1a2SImre Deak 	 */
29838cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
298440d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_A) |
298540d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_B) |
298640d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_C) |
298740d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_D),
29888cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
29891a56b1a2SImre Deak }
29901a56b1a2SImre Deak 
2991*d28cdc43SVille Syrjälä static void ibx_hpd_enable_detection(struct intel_encoder *encoder)
2992*d28cdc43SVille Syrjälä {
2993*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2994*d28cdc43SVille Syrjälä 
2995*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
2996*d28cdc43SVille Syrjälä 			 ibx_hotplug_mask(encoder->hpd_pin),
2997*d28cdc43SVille Syrjälä 			 ibx_hotplug_enables(encoder));
2998*d28cdc43SVille Syrjälä }
2999*d28cdc43SVille Syrjälä 
300091d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
300182a28bcfSDaniel Vetter {
30021a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
300382a28bcfSDaniel Vetter 
30045a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
30055a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
300682a28bcfSDaniel Vetter 
3007fee884edSDaniel Vetter 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
300882a28bcfSDaniel Vetter 
30091a56b1a2SImre Deak 	ibx_hpd_detection_setup(dev_priv);
30106dbf30ceSVille Syrjälä }
301126951cafSXiong Zhang 
301240d06b0fSVille Syrjälä static u32 icp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
30132ea63927SVille Syrjälä {
301440d06b0fSVille Syrjälä 	switch (hpd_pin) {
30152ea63927SVille Syrjälä 	case HPD_PORT_A:
30162ea63927SVille Syrjälä 	case HPD_PORT_B:
30172ea63927SVille Syrjälä 	case HPD_PORT_C:
30182ea63927SVille Syrjälä 	case HPD_PORT_D:
301940d06b0fSVille Syrjälä 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
302040d06b0fSVille Syrjälä 	default:
302140d06b0fSVille Syrjälä 		return 0;
302240d06b0fSVille Syrjälä 	}
302340d06b0fSVille Syrjälä }
302440d06b0fSVille Syrjälä 
302540d06b0fSVille Syrjälä static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
302640d06b0fSVille Syrjälä {
302740d06b0fSVille Syrjälä 	return icp_ddi_hotplug_mask(encoder->hpd_pin);
302840d06b0fSVille Syrjälä }
302940d06b0fSVille Syrjälä 
303040d06b0fSVille Syrjälä static u32 icp_tc_hotplug_mask(enum hpd_pin hpd_pin)
303140d06b0fSVille Syrjälä {
303240d06b0fSVille Syrjälä 	switch (hpd_pin) {
303340d06b0fSVille Syrjälä 	case HPD_PORT_TC1:
303440d06b0fSVille Syrjälä 	case HPD_PORT_TC2:
303540d06b0fSVille Syrjälä 	case HPD_PORT_TC3:
303640d06b0fSVille Syrjälä 	case HPD_PORT_TC4:
303740d06b0fSVille Syrjälä 	case HPD_PORT_TC5:
303840d06b0fSVille Syrjälä 	case HPD_PORT_TC6:
303940d06b0fSVille Syrjälä 		return ICP_TC_HPD_ENABLE(hpd_pin);
30402ea63927SVille Syrjälä 	default:
30412ea63927SVille Syrjälä 		return 0;
30422ea63927SVille Syrjälä 	}
30432ea63927SVille Syrjälä }
30442ea63927SVille Syrjälä 
3045dfefe7bcSVille Syrjälä static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
30462ea63927SVille Syrjälä {
304740d06b0fSVille Syrjälä 	return icp_tc_hotplug_mask(encoder->hpd_pin);
30482ea63927SVille Syrjälä }
30492ea63927SVille Syrjälä 
30502ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
305131604222SAnusha Srivatsa {
30528cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
305340d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_A) |
305440d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_B) |
305540d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_C) |
305640d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_D),
30578cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
305831604222SAnusha Srivatsa }
3059815f4ef2SVille Syrjälä 
3060*d28cdc43SVille Syrjälä static void icp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
3061*d28cdc43SVille Syrjälä {
3062*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3063*d28cdc43SVille Syrjälä 
3064*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_DDI,
3065*d28cdc43SVille Syrjälä 			 icp_ddi_hotplug_mask(encoder->hpd_pin),
3066*d28cdc43SVille Syrjälä 			 icp_ddi_hotplug_enables(encoder));
3067*d28cdc43SVille Syrjälä }
3068*d28cdc43SVille Syrjälä 
30692ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3070815f4ef2SVille Syrjälä {
30718cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
307240d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC1) |
307340d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC2) |
307440d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC3) |
307540d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC4) |
307640d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC5) |
307740d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC6),
30788cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
30798ef7e340SMatt Roper }
308031604222SAnusha Srivatsa 
3081*d28cdc43SVille Syrjälä static void icp_tc_hpd_enable_detection(struct intel_encoder *encoder)
3082*d28cdc43SVille Syrjälä {
3083*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3084*d28cdc43SVille Syrjälä 
3085*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_TC,
3086*d28cdc43SVille Syrjälä 			 icp_tc_hotplug_mask(encoder->hpd_pin),
3087*d28cdc43SVille Syrjälä 			 icp_tc_hotplug_enables(encoder));
3088*d28cdc43SVille Syrjälä }
3089*d28cdc43SVille Syrjälä 
3090*d28cdc43SVille Syrjälä static void icp_hpd_enable_detection(struct intel_encoder *encoder)
3091*d28cdc43SVille Syrjälä {
3092*d28cdc43SVille Syrjälä 	icp_ddi_hpd_enable_detection(encoder);
3093*d28cdc43SVille Syrjälä 	icp_tc_hpd_enable_detection(encoder);
3094*d28cdc43SVille Syrjälä }
3095*d28cdc43SVille Syrjälä 
30962ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
309731604222SAnusha Srivatsa {
309831604222SAnusha Srivatsa 	u32 hotplug_irqs, enabled_irqs;
309931604222SAnusha Srivatsa 
31005a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
31015a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
310231604222SAnusha Srivatsa 
3103f619e516SAnusha Srivatsa 	if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
31042939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3105f49108d0SMatt Roper 
310631604222SAnusha Srivatsa 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
310731604222SAnusha Srivatsa 
31082ea63927SVille Syrjälä 	icp_ddi_hpd_detection_setup(dev_priv);
31092ea63927SVille Syrjälä 	icp_tc_hpd_detection_setup(dev_priv);
311052dfdba0SLucas De Marchi }
311152dfdba0SLucas De Marchi 
311240d06b0fSVille Syrjälä static u32 gen11_hotplug_mask(enum hpd_pin hpd_pin)
31138ef7e340SMatt Roper {
311440d06b0fSVille Syrjälä 	switch (hpd_pin) {
31152ea63927SVille Syrjälä 	case HPD_PORT_TC1:
31162ea63927SVille Syrjälä 	case HPD_PORT_TC2:
31172ea63927SVille Syrjälä 	case HPD_PORT_TC3:
31182ea63927SVille Syrjälä 	case HPD_PORT_TC4:
31192ea63927SVille Syrjälä 	case HPD_PORT_TC5:
31202ea63927SVille Syrjälä 	case HPD_PORT_TC6:
312140d06b0fSVille Syrjälä 		return GEN11_HOTPLUG_CTL_ENABLE(hpd_pin);
31222ea63927SVille Syrjälä 	default:
31232ea63927SVille Syrjälä 		return 0;
312431604222SAnusha Srivatsa 	}
3125943682e3SMatt Roper }
3126943682e3SMatt Roper 
312740d06b0fSVille Syrjälä static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
312840d06b0fSVille Syrjälä {
312940d06b0fSVille Syrjälä 	return gen11_hotplug_mask(encoder->hpd_pin);
313040d06b0fSVille Syrjälä }
313140d06b0fSVille Syrjälä 
313271690148SGustavo Sousa static void dg1_hpd_invert(struct drm_i915_private *i915)
3133229f31e2SLucas De Marchi {
313471690148SGustavo Sousa 	u32 val = (INVERT_DDIA_HPD |
3135b18c1eb9SClinton A Taylor 		   INVERT_DDIB_HPD |
3136b18c1eb9SClinton A Taylor 		   INVERT_DDIC_HPD |
3137b18c1eb9SClinton A Taylor 		   INVERT_DDID_HPD);
313871690148SGustavo Sousa 	intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
313971690148SGustavo Sousa }
3140b18c1eb9SClinton A Taylor 
3141*d28cdc43SVille Syrjälä static void dg1_hpd_enable_detection(struct intel_encoder *encoder)
3142*d28cdc43SVille Syrjälä {
3143*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3144*d28cdc43SVille Syrjälä 
3145*d28cdc43SVille Syrjälä 	dg1_hpd_invert(i915);
3146*d28cdc43SVille Syrjälä 	icp_hpd_enable_detection(encoder);
3147*d28cdc43SVille Syrjälä }
3148*d28cdc43SVille Syrjälä 
314971690148SGustavo Sousa static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
315071690148SGustavo Sousa {
315171690148SGustavo Sousa 	dg1_hpd_invert(dev_priv);
31522ea63927SVille Syrjälä 	icp_hpd_irq_setup(dev_priv);
3153229f31e2SLucas De Marchi }
3154229f31e2SLucas De Marchi 
315552c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3156121e758eSDhinakaran Pandiyan {
31578cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
315840d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC1) |
315940d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC2) |
316040d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC3) |
316140d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC4) |
316240d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC5) |
316340d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC6),
31648cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
316552c7f5f1SVille Syrjälä }
316652c7f5f1SVille Syrjälä 
3167*d28cdc43SVille Syrjälä static void gen11_tc_hpd_enable_detection(struct intel_encoder *encoder)
3168*d28cdc43SVille Syrjälä {
3169*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3170*d28cdc43SVille Syrjälä 
3171*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, GEN11_TC_HOTPLUG_CTL,
3172*d28cdc43SVille Syrjälä 			 gen11_hotplug_mask(encoder->hpd_pin),
3173*d28cdc43SVille Syrjälä 			 gen11_hotplug_enables(encoder));
3174*d28cdc43SVille Syrjälä }
3175*d28cdc43SVille Syrjälä 
317652c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
317752c7f5f1SVille Syrjälä {
31788cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
317940d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC1) |
318040d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC2) |
318140d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC3) |
318240d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC4) |
318340d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC5) |
318440d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC6),
31858cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
3186121e758eSDhinakaran Pandiyan }
3187121e758eSDhinakaran Pandiyan 
3188*d28cdc43SVille Syrjälä static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder)
3189*d28cdc43SVille Syrjälä {
3190*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3191*d28cdc43SVille Syrjälä 
3192*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, GEN11_TBT_HOTPLUG_CTL,
3193*d28cdc43SVille Syrjälä 			 gen11_hotplug_mask(encoder->hpd_pin),
3194*d28cdc43SVille Syrjälä 			 gen11_hotplug_enables(encoder));
3195*d28cdc43SVille Syrjälä }
3196*d28cdc43SVille Syrjälä 
3197*d28cdc43SVille Syrjälä static void gen11_hpd_enable_detection(struct intel_encoder *encoder)
3198*d28cdc43SVille Syrjälä {
3199*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3200*d28cdc43SVille Syrjälä 
3201*d28cdc43SVille Syrjälä 	gen11_tc_hpd_enable_detection(encoder);
3202*d28cdc43SVille Syrjälä 	gen11_tbt_hpd_enable_detection(encoder);
3203*d28cdc43SVille Syrjälä 
3204*d28cdc43SVille Syrjälä 	if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
3205*d28cdc43SVille Syrjälä 		icp_hpd_enable_detection(encoder);
3206*d28cdc43SVille Syrjälä }
3207*d28cdc43SVille Syrjälä 
3208121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
3209121e758eSDhinakaran Pandiyan {
3210121e758eSDhinakaran Pandiyan 	u32 hotplug_irqs, enabled_irqs;
3211121e758eSDhinakaran Pandiyan 
32125a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
32135a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
3214121e758eSDhinakaran Pandiyan 
32158cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
32168cee664dSAndrzej Hajda 			 ~enabled_irqs & hotplug_irqs);
32172939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
3218121e758eSDhinakaran Pandiyan 
321952c7f5f1SVille Syrjälä 	gen11_tc_hpd_detection_setup(dev_priv);
322052c7f5f1SVille Syrjälä 	gen11_tbt_hpd_detection_setup(dev_priv);
322131604222SAnusha Srivatsa 
32222ea63927SVille Syrjälä 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
32232ea63927SVille Syrjälä 		icp_hpd_irq_setup(dev_priv);
32242ea63927SVille Syrjälä }
32252ea63927SVille Syrjälä 
322640d06b0fSVille Syrjälä static u32 mtp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
3227babde06dSMika Kahola {
322840d06b0fSVille Syrjälä 	switch (hpd_pin) {
3229babde06dSMika Kahola 	case HPD_PORT_A:
3230babde06dSMika Kahola 	case HPD_PORT_B:
323140d06b0fSVille Syrjälä 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
323240d06b0fSVille Syrjälä 	default:
323340d06b0fSVille Syrjälä 		return 0;
323440d06b0fSVille Syrjälä 	}
323540d06b0fSVille Syrjälä }
323640d06b0fSVille Syrjälä 
323740d06b0fSVille Syrjälä static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder)
323840d06b0fSVille Syrjälä {
323940d06b0fSVille Syrjälä 	return mtp_ddi_hotplug_mask(encoder->hpd_pin);
324040d06b0fSVille Syrjälä }
324140d06b0fSVille Syrjälä 
324240d06b0fSVille Syrjälä static u32 mtp_tc_hotplug_mask(enum hpd_pin hpd_pin)
324340d06b0fSVille Syrjälä {
324440d06b0fSVille Syrjälä 	switch (hpd_pin) {
324540d06b0fSVille Syrjälä 	case HPD_PORT_TC1:
324640d06b0fSVille Syrjälä 	case HPD_PORT_TC2:
324740d06b0fSVille Syrjälä 	case HPD_PORT_TC3:
324840d06b0fSVille Syrjälä 	case HPD_PORT_TC4:
324940d06b0fSVille Syrjälä 		return ICP_TC_HPD_ENABLE(hpd_pin);
3250babde06dSMika Kahola 	default:
3251babde06dSMika Kahola 		return 0;
3252babde06dSMika Kahola 	}
3253babde06dSMika Kahola }
3254babde06dSMika Kahola 
3255babde06dSMika Kahola static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder)
3256babde06dSMika Kahola {
325740d06b0fSVille Syrjälä 	return mtp_tc_hotplug_mask(encoder->hpd_pin);
3258babde06dSMika Kahola }
3259babde06dSMika Kahola 
3260babde06dSMika Kahola static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
3261babde06dSMika Kahola {
3262babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
326340d06b0fSVille Syrjälä 		     mtp_ddi_hotplug_mask(HPD_PORT_A) |
326440d06b0fSVille Syrjälä 		     mtp_ddi_hotplug_mask(HPD_PORT_B),
3265babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
3266babde06dSMika Kahola }
3267babde06dSMika Kahola 
3268*d28cdc43SVille Syrjälä static void mtp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
3269*d28cdc43SVille Syrjälä {
3270*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3271*d28cdc43SVille Syrjälä 
3272*d28cdc43SVille Syrjälä 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
3273*d28cdc43SVille Syrjälä 		     mtp_ddi_hotplug_mask(encoder->hpd_pin),
3274*d28cdc43SVille Syrjälä 		     mtp_ddi_hotplug_enables(encoder));
3275*d28cdc43SVille Syrjälä }
3276*d28cdc43SVille Syrjälä 
3277babde06dSMika Kahola static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
3278babde06dSMika Kahola {
3279babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_TC,
328040d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC1) |
328140d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC2) |
328240d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC3) |
328340d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC4),
3284babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
3285babde06dSMika Kahola }
3286babde06dSMika Kahola 
3287*d28cdc43SVille Syrjälä static void mtp_tc_hpd_enable_detection(struct intel_encoder *encoder)
3288*d28cdc43SVille Syrjälä {
3289*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3290*d28cdc43SVille Syrjälä 
3291*d28cdc43SVille Syrjälä 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
3292*d28cdc43SVille Syrjälä 		     mtp_tc_hotplug_mask(encoder->hpd_pin),
3293*d28cdc43SVille Syrjälä 		     mtp_tc_hotplug_enables(encoder));
3294*d28cdc43SVille Syrjälä }
3295*d28cdc43SVille Syrjälä 
3296babde06dSMika Kahola static void mtp_hpd_invert(struct drm_i915_private *i915)
3297babde06dSMika Kahola {
3298babde06dSMika Kahola 	u32 val = (INVERT_DDIA_HPD |
3299babde06dSMika Kahola 		   INVERT_DDIB_HPD |
3300babde06dSMika Kahola 		   INVERT_DDIC_HPD |
3301babde06dSMika Kahola 		   INVERT_TC1_HPD |
3302babde06dSMika Kahola 		   INVERT_TC2_HPD |
3303babde06dSMika Kahola 		   INVERT_TC3_HPD |
3304babde06dSMika Kahola 		   INVERT_TC4_HPD |
3305babde06dSMika Kahola 		   INVERT_DDID_HPD_MTP |
3306babde06dSMika Kahola 		   INVERT_DDIE_HPD);
3307babde06dSMika Kahola 	intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
3308babde06dSMika Kahola }
3309babde06dSMika Kahola 
3310*d28cdc43SVille Syrjälä static void mtp_hpd_enable_detection(struct intel_encoder *encoder)
3311*d28cdc43SVille Syrjälä {
3312*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3313*d28cdc43SVille Syrjälä 
3314*d28cdc43SVille Syrjälä 	mtp_hpd_invert(i915);
3315*d28cdc43SVille Syrjälä 	mtp_ddi_hpd_enable_detection(encoder);
3316*d28cdc43SVille Syrjälä 	mtp_tc_hpd_enable_detection(encoder);
3317*d28cdc43SVille Syrjälä }
3318*d28cdc43SVille Syrjälä 
3319babde06dSMika Kahola static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
3320babde06dSMika Kahola {
3321babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3322babde06dSMika Kahola 
3323babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
3324babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
3325babde06dSMika Kahola 
3326babde06dSMika Kahola 	intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3327babde06dSMika Kahola 
3328babde06dSMika Kahola 	mtp_hpd_invert(i915);
3329babde06dSMika Kahola 	ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
3330babde06dSMika Kahola 
3331babde06dSMika Kahola 	mtp_ddi_hpd_detection_setup(i915);
3332babde06dSMika Kahola 	mtp_tc_hpd_detection_setup(i915);
3333babde06dSMika Kahola }
3334babde06dSMika Kahola 
3335*d28cdc43SVille Syrjälä static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
3336*d28cdc43SVille Syrjälä {
3337*d28cdc43SVille Syrjälä 	return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
3338*d28cdc43SVille Syrjälä }
3339*d28cdc43SVille Syrjälä 
3340*d28cdc43SVille Syrjälä static void _xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915,
3341*d28cdc43SVille Syrjälä 					     enum hpd_pin hpd_pin, bool enable)
3342*d28cdc43SVille Syrjälä {
3343*d28cdc43SVille Syrjälä 	u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
3344*d28cdc43SVille Syrjälä 		XELPDP_DP_ALT_HOTPLUG_ENABLE;
3345*d28cdc43SVille Syrjälä 
3346*d28cdc43SVille Syrjälä 	if (!is_xelpdp_pica_hpd_pin(hpd_pin))
3347*d28cdc43SVille Syrjälä 		return;
3348*d28cdc43SVille Syrjälä 
3349*d28cdc43SVille Syrjälä 	intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(hpd_pin),
3350*d28cdc43SVille Syrjälä 		     mask, enable ? mask : 0);
3351*d28cdc43SVille Syrjälä }
3352*d28cdc43SVille Syrjälä 
3353*d28cdc43SVille Syrjälä static void xelpdp_pica_hpd_enable_detection(struct intel_encoder *encoder)
3354*d28cdc43SVille Syrjälä {
3355*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3356*d28cdc43SVille Syrjälä 
3357*d28cdc43SVille Syrjälä 	_xelpdp_pica_hpd_detection_setup(i915, encoder->hpd_pin, true);
3358*d28cdc43SVille Syrjälä }
3359*d28cdc43SVille Syrjälä 
3360babde06dSMika Kahola static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
3361babde06dSMika Kahola {
3362babde06dSMika Kahola 	struct intel_encoder *encoder;
3363babde06dSMika Kahola 	u32 available_pins = 0;
3364*d28cdc43SVille Syrjälä 	enum hpd_pin pin;
3365babde06dSMika Kahola 
3366babde06dSMika Kahola 	BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
3367babde06dSMika Kahola 
3368babde06dSMika Kahola 	for_each_intel_encoder(&i915->drm, encoder)
3369babde06dSMika Kahola 		available_pins |= BIT(encoder->hpd_pin);
3370babde06dSMika Kahola 
3371*d28cdc43SVille Syrjälä 	for_each_hpd_pin(pin)
3372*d28cdc43SVille Syrjälä 		_xelpdp_pica_hpd_detection_setup(i915, pin, available_pins & BIT(pin));
3373babde06dSMika Kahola }
3374*d28cdc43SVille Syrjälä 
3375*d28cdc43SVille Syrjälä static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder)
3376*d28cdc43SVille Syrjälä {
3377*d28cdc43SVille Syrjälä 	xelpdp_pica_hpd_enable_detection(encoder);
3378*d28cdc43SVille Syrjälä 	mtp_hpd_enable_detection(encoder);
3379babde06dSMika Kahola }
3380babde06dSMika Kahola 
3381babde06dSMika Kahola static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
3382babde06dSMika Kahola {
3383babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3384babde06dSMika Kahola 
3385babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.hpd);
3386babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.hpd);
3387babde06dSMika Kahola 
3388babde06dSMika Kahola 	intel_de_rmw(i915, PICAINTERRUPT_IMR, hotplug_irqs,
3389babde06dSMika Kahola 		     ~enabled_irqs & hotplug_irqs);
3390babde06dSMika Kahola 	intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR);
3391babde06dSMika Kahola 
3392babde06dSMika Kahola 	xelpdp_pica_hpd_detection_setup(i915);
3393babde06dSMika Kahola 
3394babde06dSMika Kahola 	if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
3395babde06dSMika Kahola 		mtp_hpd_irq_setup(i915);
3396babde06dSMika Kahola }
3397babde06dSMika Kahola 
339840d06b0fSVille Syrjälä static u32 spt_hotplug_mask(enum hpd_pin hpd_pin)
33992ea63927SVille Syrjälä {
340040d06b0fSVille Syrjälä 	switch (hpd_pin) {
34012ea63927SVille Syrjälä 	case HPD_PORT_A:
34022ea63927SVille Syrjälä 		return PORTA_HOTPLUG_ENABLE;
34032ea63927SVille Syrjälä 	case HPD_PORT_B:
34042ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE;
34052ea63927SVille Syrjälä 	case HPD_PORT_C:
34062ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE;
34072ea63927SVille Syrjälä 	case HPD_PORT_D:
34082ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE;
34092ea63927SVille Syrjälä 	default:
34102ea63927SVille Syrjälä 		return 0;
34112ea63927SVille Syrjälä 	}
34122ea63927SVille Syrjälä }
34132ea63927SVille Syrjälä 
341440d06b0fSVille Syrjälä static u32 spt_hotplug_enables(struct intel_encoder *encoder)
34152ea63927SVille Syrjälä {
341640d06b0fSVille Syrjälä 	return spt_hotplug_mask(encoder->hpd_pin);
341740d06b0fSVille Syrjälä }
341840d06b0fSVille Syrjälä 
341940d06b0fSVille Syrjälä static u32 spt_hotplug2_mask(enum hpd_pin hpd_pin)
342040d06b0fSVille Syrjälä {
342140d06b0fSVille Syrjälä 	switch (hpd_pin) {
34222ea63927SVille Syrjälä 	case HPD_PORT_E:
34232ea63927SVille Syrjälä 		return PORTE_HOTPLUG_ENABLE;
34242ea63927SVille Syrjälä 	default:
34252ea63927SVille Syrjälä 		return 0;
34262ea63927SVille Syrjälä 	}
3427121e758eSDhinakaran Pandiyan }
3428121e758eSDhinakaran Pandiyan 
342940d06b0fSVille Syrjälä static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
343040d06b0fSVille Syrjälä {
343140d06b0fSVille Syrjälä 	return spt_hotplug2_mask(encoder->hpd_pin);
343240d06b0fSVille Syrjälä }
343340d06b0fSVille Syrjälä 
34342a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
34352a57d9ccSImre Deak {
34363b92e263SRodrigo Vivi 	/* Display WA #1179 WaHardHangonHotPlug: cnp */
34373b92e263SRodrigo Vivi 	if (HAS_PCH_CNP(dev_priv)) {
34388cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
34398cee664dSAndrzej Hajda 				 CHASSIS_CLK_REQ_DURATION(0xf));
34403b92e263SRodrigo Vivi 	}
34412a57d9ccSImre Deak 
34422a57d9ccSImre Deak 	/* Enable digital hotplug on the PCH */
34438cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
344440d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_A) |
344540d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_B) |
344640d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_C) |
344740d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_D),
34488cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
34492a57d9ccSImre Deak 
345040d06b0fSVille Syrjälä 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2,
345140d06b0fSVille Syrjälä 			 spt_hotplug2_mask(HPD_PORT_E),
34528cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
34532a57d9ccSImre Deak }
34542a57d9ccSImre Deak 
3455*d28cdc43SVille Syrjälä static void spt_hpd_enable_detection(struct intel_encoder *encoder)
3456*d28cdc43SVille Syrjälä {
3457*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3458*d28cdc43SVille Syrjälä 
3459*d28cdc43SVille Syrjälä 	/* Display WA #1179 WaHardHangonHotPlug: cnp */
3460*d28cdc43SVille Syrjälä 	if (HAS_PCH_CNP(i915)) {
3461*d28cdc43SVille Syrjälä 		intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1,
3462*d28cdc43SVille Syrjälä 				 CHASSIS_CLK_REQ_DURATION_MASK,
3463*d28cdc43SVille Syrjälä 				 CHASSIS_CLK_REQ_DURATION(0xf));
3464*d28cdc43SVille Syrjälä 	}
3465*d28cdc43SVille Syrjälä 
3466*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
3467*d28cdc43SVille Syrjälä 			 spt_hotplug_mask(encoder->hpd_pin),
3468*d28cdc43SVille Syrjälä 			 spt_hotplug_enables(encoder));
3469*d28cdc43SVille Syrjälä 
3470*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG2,
3471*d28cdc43SVille Syrjälä 			 spt_hotplug2_mask(encoder->hpd_pin),
3472*d28cdc43SVille Syrjälä 			 spt_hotplug2_enables(encoder));
3473*d28cdc43SVille Syrjälä }
3474*d28cdc43SVille Syrjälä 
347591d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
34766dbf30ceSVille Syrjälä {
34772a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
34786dbf30ceSVille Syrjälä 
3479f49108d0SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
34802939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3481f49108d0SMatt Roper 
34825a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
34835a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
34846dbf30ceSVille Syrjälä 
34856dbf30ceSVille Syrjälä 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
34866dbf30ceSVille Syrjälä 
34872a57d9ccSImre Deak 	spt_hpd_detection_setup(dev_priv);
348826951cafSXiong Zhang }
34897fe0b973SKeith Packard 
349040d06b0fSVille Syrjälä static u32 ilk_hotplug_mask(enum hpd_pin hpd_pin)
349140d06b0fSVille Syrjälä {
349240d06b0fSVille Syrjälä 	switch (hpd_pin) {
349340d06b0fSVille Syrjälä 	case HPD_PORT_A:
349440d06b0fSVille Syrjälä 		return DIGITAL_PORTA_HOTPLUG_ENABLE |
349540d06b0fSVille Syrjälä 			DIGITAL_PORTA_PULSE_DURATION_MASK;
349640d06b0fSVille Syrjälä 	default:
349740d06b0fSVille Syrjälä 		return 0;
349840d06b0fSVille Syrjälä 	}
349940d06b0fSVille Syrjälä }
350040d06b0fSVille Syrjälä 
3501dfefe7bcSVille Syrjälä static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
35022ea63927SVille Syrjälä {
3503dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
35042ea63927SVille Syrjälä 	case HPD_PORT_A:
35052ea63927SVille Syrjälä 		return DIGITAL_PORTA_HOTPLUG_ENABLE |
35062ea63927SVille Syrjälä 			DIGITAL_PORTA_PULSE_DURATION_2ms;
35072ea63927SVille Syrjälä 	default:
35082ea63927SVille Syrjälä 		return 0;
35092ea63927SVille Syrjälä 	}
35102ea63927SVille Syrjälä }
35112ea63927SVille Syrjälä 
35121a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
35131a56b1a2SImre Deak {
35141a56b1a2SImre Deak 	/*
35151a56b1a2SImre Deak 	 * Enable digital hotplug on the CPU, and configure the DP short pulse
35161a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec)
35171a56b1a2SImre Deak 	 * The pulse duration bits are reserved on HSW+.
35181a56b1a2SImre Deak 	 */
35198cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
352040d06b0fSVille Syrjälä 			 ilk_hotplug_mask(HPD_PORT_A),
35218cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
35221a56b1a2SImre Deak }
35231a56b1a2SImre Deak 
3524*d28cdc43SVille Syrjälä static void ilk_hpd_enable_detection(struct intel_encoder *encoder)
3525*d28cdc43SVille Syrjälä {
3526*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3527*d28cdc43SVille Syrjälä 
3528*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
3529*d28cdc43SVille Syrjälä 			 ilk_hotplug_mask(encoder->hpd_pin),
3530*d28cdc43SVille Syrjälä 			 ilk_hotplug_enables(encoder));
3531*d28cdc43SVille Syrjälä 
3532*d28cdc43SVille Syrjälä 	ibx_hpd_enable_detection(encoder);
3533*d28cdc43SVille Syrjälä }
3534*d28cdc43SVille Syrjälä 
353591d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
3536e4ce95aaSVille Syrjälä {
35371a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
3538e4ce95aaSVille Syrjälä 
35395a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
35405a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
35413a3b3c7dSVille Syrjälä 
3542373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 8)
35433a3b3c7dSVille Syrjälä 		bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
35446d3144ebSVille Syrjälä 	else
35453a3b3c7dSVille Syrjälä 		ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
3546e4ce95aaSVille Syrjälä 
35471a56b1a2SImre Deak 	ilk_hpd_detection_setup(dev_priv);
3548e4ce95aaSVille Syrjälä 
354991d14251STvrtko Ursulin 	ibx_hpd_irq_setup(dev_priv);
3550e4ce95aaSVille Syrjälä }
3551e4ce95aaSVille Syrjälä 
355240d06b0fSVille Syrjälä static u32 bxt_hotplug_mask(enum hpd_pin hpd_pin)
355340d06b0fSVille Syrjälä {
355440d06b0fSVille Syrjälä 	switch (hpd_pin) {
355540d06b0fSVille Syrjälä 	case HPD_PORT_A:
355640d06b0fSVille Syrjälä 		return PORTA_HOTPLUG_ENABLE | BXT_DDIA_HPD_INVERT;
355740d06b0fSVille Syrjälä 	case HPD_PORT_B:
355840d06b0fSVille Syrjälä 		return PORTB_HOTPLUG_ENABLE | BXT_DDIB_HPD_INVERT;
355940d06b0fSVille Syrjälä 	case HPD_PORT_C:
356040d06b0fSVille Syrjälä 		return PORTC_HOTPLUG_ENABLE | BXT_DDIC_HPD_INVERT;
356140d06b0fSVille Syrjälä 	default:
356240d06b0fSVille Syrjälä 		return 0;
356340d06b0fSVille Syrjälä 	}
356440d06b0fSVille Syrjälä }
356540d06b0fSVille Syrjälä 
3566dfefe7bcSVille Syrjälä static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
35672ea63927SVille Syrjälä {
35682ea63927SVille Syrjälä 	u32 hotplug;
35692ea63927SVille Syrjälä 
3570dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
35712ea63927SVille Syrjälä 	case HPD_PORT_A:
35722ea63927SVille Syrjälä 		hotplug = PORTA_HOTPLUG_ENABLE;
35739151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
35742ea63927SVille Syrjälä 			hotplug |= BXT_DDIA_HPD_INVERT;
35752ea63927SVille Syrjälä 		return hotplug;
35762ea63927SVille Syrjälä 	case HPD_PORT_B:
35772ea63927SVille Syrjälä 		hotplug = PORTB_HOTPLUG_ENABLE;
35789151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
35792ea63927SVille Syrjälä 			hotplug |= BXT_DDIB_HPD_INVERT;
35802ea63927SVille Syrjälä 		return hotplug;
35812ea63927SVille Syrjälä 	case HPD_PORT_C:
35822ea63927SVille Syrjälä 		hotplug = PORTC_HOTPLUG_ENABLE;
35839151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
35842ea63927SVille Syrjälä 			hotplug |= BXT_DDIC_HPD_INVERT;
35852ea63927SVille Syrjälä 		return hotplug;
35862ea63927SVille Syrjälä 	default:
35872ea63927SVille Syrjälä 		return 0;
35882ea63927SVille Syrjälä 	}
35892ea63927SVille Syrjälä }
35902ea63927SVille Syrjälä 
35912ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
3592e0a20ad7SShashank Sharma {
35938cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
359440d06b0fSVille Syrjälä 			 bxt_hotplug_mask(HPD_PORT_A) |
359540d06b0fSVille Syrjälä 			 bxt_hotplug_mask(HPD_PORT_B) |
359640d06b0fSVille Syrjälä 			 bxt_hotplug_mask(HPD_PORT_C),
35978cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
3598e0a20ad7SShashank Sharma }
3599e0a20ad7SShashank Sharma 
3600*d28cdc43SVille Syrjälä static void bxt_hpd_enable_detection(struct intel_encoder *encoder)
3601*d28cdc43SVille Syrjälä {
3602*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3603*d28cdc43SVille Syrjälä 
3604*d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
3605*d28cdc43SVille Syrjälä 			 bxt_hotplug_mask(encoder->hpd_pin),
3606*d28cdc43SVille Syrjälä 			 bxt_hotplug_enables(encoder));
3607*d28cdc43SVille Syrjälä }
3608*d28cdc43SVille Syrjälä 
36092a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
36102a57d9ccSImre Deak {
36112a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
36122a57d9ccSImre Deak 
36135a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
36145a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
36152a57d9ccSImre Deak 
36162a57d9ccSImre Deak 	bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
36172a57d9ccSImre Deak 
36182ea63927SVille Syrjälä 	bxt_hpd_detection_setup(dev_priv);
36192a57d9ccSImre Deak }
36202a57d9ccSImre Deak 
3621a0a6d8cbSVille Syrjälä /*
3622a0a6d8cbSVille Syrjälä  * SDEIER is also touched by the interrupt handler to work around missed PCH
3623a0a6d8cbSVille Syrjälä  * interrupts. Hence we can't update it after the interrupt handler is enabled -
3624a0a6d8cbSVille Syrjälä  * instead we unconditionally enable all PCH interrupt sources here, but then
3625a0a6d8cbSVille Syrjälä  * only unmask them as needed with SDEIMR.
3626a0a6d8cbSVille Syrjälä  *
3627a0a6d8cbSVille Syrjälä  * Note that we currently do this after installing the interrupt handler,
3628a0a6d8cbSVille Syrjälä  * but before we enable the master interrupt. That should be sufficient
3629a0a6d8cbSVille Syrjälä  * to avoid races with the irq handler, assuming we have MSI. Shared legacy
3630a0a6d8cbSVille Syrjälä  * interrupts could still race.
3631a0a6d8cbSVille Syrjälä  */
3632b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
3633d46da437SPaulo Zanoni {
3634a0a6d8cbSVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
363582a28bcfSDaniel Vetter 	u32 mask;
3636d46da437SPaulo Zanoni 
36376e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
3638692a04cfSDaniel Vetter 		return;
3639692a04cfSDaniel Vetter 
36406e266956STvrtko Ursulin 	if (HAS_PCH_IBX(dev_priv))
36415c673b60SDaniel Vetter 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
36424ebc6509SDhinakaran Pandiyan 	else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
36435c673b60SDaniel Vetter 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
36444ebc6509SDhinakaran Pandiyan 	else
36454ebc6509SDhinakaran Pandiyan 		mask = SDE_GMBUS_CPT;
36468664281bSPaulo Zanoni 
3647a0a6d8cbSVille Syrjälä 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
3648d46da437SPaulo Zanoni }
3649d46da437SPaulo Zanoni 
36509eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
3651036a4a7dSZhenyu Wang {
3652b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
36538e76f8dcSPaulo Zanoni 	u32 display_mask, extra_mask;
36548e76f8dcSPaulo Zanoni 
3655651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) >= 7) {
36568e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
3657842ebf7aSVille Syrjälä 				DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB);
36588e76f8dcSPaulo Zanoni 		extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
365923bb4cb5SVille Syrjälä 			      DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
36602a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_C) |
36612a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_B) |
36622a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_A) |
366323bb4cb5SVille Syrjälä 			      DE_DP_A_HOTPLUG_IVB);
36648e76f8dcSPaulo Zanoni 	} else {
36658e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
3666842ebf7aSVille Syrjälä 				DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE |
3667842ebf7aSVille Syrjälä 				DE_PIPEA_CRC_DONE | DE_POISON);
3668c6073d4cSVille Syrjälä 		extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK |
3669e4ce95aaSVille Syrjälä 			      DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
36704bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_A) |
36714bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_B) |
3672e4ce95aaSVille Syrjälä 			      DE_DP_A_HOTPLUG);
36738e76f8dcSPaulo Zanoni 	}
3674036a4a7dSZhenyu Wang 
3675fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
3676b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
3677fc340442SDaniel Vetter 		display_mask |= DE_EDP_PSR_INT_HSW;
3678fc340442SDaniel Vetter 	}
3679fc340442SDaniel Vetter 
3680c6073d4cSVille Syrjälä 	if (IS_IRONLAKE_M(dev_priv))
3681c6073d4cSVille Syrjälä 		extra_mask |= DE_PCU_EVENT;
3682c6073d4cSVille Syrjälä 
36831ec14ad3SChris Wilson 	dev_priv->irq_mask = ~display_mask;
3684036a4a7dSZhenyu Wang 
3685a0a6d8cbSVille Syrjälä 	ibx_irq_postinstall(dev_priv);
3686622364b6SPaulo Zanoni 
36872cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
3688a9922912SVille Syrjälä 
3689b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask,
3690b16b2a2fSPaulo Zanoni 		      display_mask | extra_mask);
3691036a4a7dSZhenyu Wang }
3692036a4a7dSZhenyu Wang 
3693f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
3694f8b79e58SImre Deak {
369567520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3696f8b79e58SImre Deak 
3697f8b79e58SImre Deak 	if (dev_priv->display_irqs_enabled)
3698f8b79e58SImre Deak 		return;
3699f8b79e58SImre Deak 
3700f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = true;
3701f8b79e58SImre Deak 
3702d6c69803SVille Syrjälä 	if (intel_irqs_enabled(dev_priv)) {
3703d6c69803SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3704ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3705f8b79e58SImre Deak 	}
3706d6c69803SVille Syrjälä }
3707f8b79e58SImre Deak 
3708f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
3709f8b79e58SImre Deak {
371067520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3711f8b79e58SImre Deak 
3712f8b79e58SImre Deak 	if (!dev_priv->display_irqs_enabled)
3713f8b79e58SImre Deak 		return;
3714f8b79e58SImre Deak 
3715f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = false;
3716f8b79e58SImre Deak 
3717950eabafSImre Deak 	if (intel_irqs_enabled(dev_priv))
3718ad22d106SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3719f8b79e58SImre Deak }
3720f8b79e58SImre Deak 
37210e6c9a9eSVille Syrjälä 
3722b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
37230e6c9a9eSVille Syrjälä {
37242cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
37257e231dbeSJesse Barnes 
3726ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
37279918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3728ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3729ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3730ad22d106SVille Syrjälä 
37312939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
37322939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
373320afbda2SDaniel Vetter }
373420afbda2SDaniel Vetter 
3735abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
3736abd58f01SBen Widawsky {
3737b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3738b16b2a2fSPaulo Zanoni 
3739869129eeSMatt Roper 	u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
3740869129eeSMatt Roper 		GEN8_PIPE_CDCLK_CRC_DONE;
3741a9c287c9SJani Nikula 	u32 de_pipe_enables;
3742054318c7SImre Deak 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
37433a3b3c7dSVille Syrjälä 	u32 de_port_enables;
3744df0d28c1SDhinakaran Pandiyan 	u32 de_misc_masked = GEN8_DE_EDP_PSR;
3745562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
3746562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
37473a3b3c7dSVille Syrjälä 	enum pipe pipe;
3748770de83dSDamien Lespiau 
3749a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3750a844cfbeSJosé Roberto de Souza 		return;
3751a844cfbeSJosé Roberto de Souza 
3752373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) <= 10)
3753df0d28c1SDhinakaran Pandiyan 		de_misc_masked |= GEN8_DE_MISC_GSE;
3754df0d28c1SDhinakaran Pandiyan 
375570bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
37563a3b3c7dSVille Syrjälä 		de_port_masked |= BXT_DE_PORT_GMBUS;
3757a324fcacSRodrigo Vivi 
3758373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
37599c9e97c4SVandita Kulkarni 		enum port port;
37609c9e97c4SVandita Kulkarni 
37619c9e97c4SVandita Kulkarni 		if (intel_bios_is_dsi_present(dev_priv, &port))
37629c9e97c4SVandita Kulkarni 			de_port_masked |= DSI0_TE | DSI1_TE;
37639c9e97c4SVandita Kulkarni 	}
37649c9e97c4SVandita Kulkarni 
3765cda195f1SVille Syrjälä 	de_pipe_enables = de_pipe_masked |
37668bcc0840SMatt Roper 		GEN8_PIPE_VBLANK |
37678bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
3768cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
37691288f9b0SKarthik B S 
37703a3b3c7dSVille Syrjälä 	de_port_enables = de_port_masked;
377170bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3772a52bb15bSVille Syrjälä 		de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
3773a52bb15bSVille Syrjälä 	else if (IS_BROADWELL(dev_priv))
3774e5abaab3SVille Syrjälä 		de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
37753a3b3c7dSVille Syrjälä 
3776373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
37778241cfbeSJosé Roberto de Souza 		enum transcoder trans;
37788241cfbeSJosé Roberto de Souza 
3779562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
37808241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
37818241cfbeSJosé Roberto de Souza 
37828241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
37838241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
37848241cfbeSJosé Roberto de Souza 				continue;
37858241cfbeSJosé Roberto de Souza 
37868241cfbeSJosé Roberto de Souza 			gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
37878241cfbeSJosé Roberto de Souza 		}
37888241cfbeSJosé Roberto de Souza 	} else {
3789b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
37908241cfbeSJosé Roberto de Souza 	}
3791e04f7eceSVille Syrjälä 
37920a195c02SMika Kahola 	for_each_pipe(dev_priv, pipe) {
37930a195c02SMika Kahola 		dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
3794abd58f01SBen Widawsky 
3795f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
3796813bde43SPaulo Zanoni 				POWER_DOMAIN_PIPE(pipe)))
3797b16b2a2fSPaulo Zanoni 			GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
3798813bde43SPaulo Zanoni 					  dev_priv->de_irq_mask[pipe],
379935079899SPaulo Zanoni 					  de_pipe_enables);
38000a195c02SMika Kahola 	}
3801abd58f01SBen Widawsky 
3802b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
3803b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
38042a57d9ccSImre Deak 
3805babde06dSMika Kahola 	if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
3806121e758eSDhinakaran Pandiyan 		u32 de_hpd_masked = 0;
3807b796b971SDhinakaran Pandiyan 		u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
3808b796b971SDhinakaran Pandiyan 				     GEN11_DE_TBT_HOTPLUG_MASK;
3809121e758eSDhinakaran Pandiyan 
3810b16b2a2fSPaulo Zanoni 		GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
3811b16b2a2fSPaulo Zanoni 			      de_hpd_enables);
3812abd58f01SBen Widawsky 	}
3813121e758eSDhinakaran Pandiyan }
3814abd58f01SBen Widawsky 
3815babde06dSMika Kahola static void mtp_irq_postinstall(struct drm_i915_private *i915)
3816babde06dSMika Kahola {
3817babde06dSMika Kahola 	struct intel_uncore *uncore = &i915->uncore;
3818babde06dSMika Kahola 	u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
3819babde06dSMika Kahola 	u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
3820babde06dSMika Kahola 	u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
3821babde06dSMika Kahola 			     XELPDP_TBT_HOTPLUG_MASK;
3822babde06dSMika Kahola 
3823babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
3824babde06dSMika Kahola 		      de_hpd_enables);
3825babde06dSMika Kahola 
3826babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
3827babde06dSMika Kahola }
3828babde06dSMika Kahola 
382959b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
383059b7cb44STejas Upadhyay {
383159b7cb44STejas Upadhyay 	struct intel_uncore *uncore = &dev_priv->uncore;
383259b7cb44STejas Upadhyay 	u32 mask = SDE_GMBUS_ICP;
383359b7cb44STejas Upadhyay 
383459b7cb44STejas Upadhyay 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
383559b7cb44STejas Upadhyay }
383659b7cb44STejas Upadhyay 
3837b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
3838abd58f01SBen Widawsky {
383959b7cb44STejas Upadhyay 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
384059b7cb44STejas Upadhyay 		icp_irq_postinstall(dev_priv);
384159b7cb44STejas Upadhyay 	else if (HAS_PCH_SPLIT(dev_priv))
3842a0a6d8cbSVille Syrjälä 		ibx_irq_postinstall(dev_priv);
3843622364b6SPaulo Zanoni 
38442cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
3845abd58f01SBen Widawsky 	gen8_de_irq_postinstall(dev_priv);
3846abd58f01SBen Widawsky 
384725286aacSDaniele Ceraolo Spurio 	gen8_master_intr_enable(dev_priv->uncore.regs);
3848abd58f01SBen Widawsky }
3849abd58f01SBen Widawsky 
3850a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
3851a844cfbeSJosé Roberto de Souza {
3852a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3853a844cfbeSJosé Roberto de Souza 		return;
3854a844cfbeSJosé Roberto de Souza 
3855a844cfbeSJosé Roberto de Souza 	gen8_de_irq_postinstall(dev_priv);
3856a844cfbeSJosé Roberto de Souza 
3857a844cfbeSJosé Roberto de Souza 	intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
3858a844cfbeSJosé Roberto de Souza 			   GEN11_DISPLAY_IRQ_ENABLE);
3859a844cfbeSJosé Roberto de Souza }
386031604222SAnusha Srivatsa 
3861b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
386251951ae7SMika Kuoppala {
38632cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3864fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
3865df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
386651951ae7SMika Kuoppala 
386729b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
3868b318b824SVille Syrjälä 		icp_irq_postinstall(dev_priv);
386931604222SAnusha Srivatsa 
3870fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
3871a844cfbeSJosé Roberto de Souza 	gen11_de_irq_postinstall(dev_priv);
387251951ae7SMika Kuoppala 
3873b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
3874df0d28c1SDhinakaran Pandiyan 
38759b77011eSTvrtko Ursulin 	gen11_master_intr_enable(uncore->regs);
38762939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
387751951ae7SMika Kuoppala }
387822e26af7SPaulo Zanoni 
387922e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
388022e26af7SPaulo Zanoni {
38812cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3882fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
388322e26af7SPaulo Zanoni 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
388422e26af7SPaulo Zanoni 
3885fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
388622e26af7SPaulo Zanoni 
388722e26af7SPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
388822e26af7SPaulo Zanoni 
388922e26af7SPaulo Zanoni 	if (HAS_DISPLAY(dev_priv)) {
3890babde06dSMika Kahola 		if (DISPLAY_VER(dev_priv) >= 14)
3891babde06dSMika Kahola 			mtp_irq_postinstall(dev_priv);
3892babde06dSMika Kahola 		else
389322e26af7SPaulo Zanoni 			icp_irq_postinstall(dev_priv);
3894babde06dSMika Kahola 
389522e26af7SPaulo Zanoni 		gen8_de_irq_postinstall(dev_priv);
389622e26af7SPaulo Zanoni 		intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
389722e26af7SPaulo Zanoni 				   GEN11_DISPLAY_IRQ_ENABLE);
389822e26af7SPaulo Zanoni 	}
389922e26af7SPaulo Zanoni 
3900fd4d7904SPaulo Zanoni 	dg1_master_intr_enable(uncore->regs);
3901fd4d7904SPaulo Zanoni 	intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR);
390297b492f5SLucas De Marchi }
390351951ae7SMika Kuoppala 
3904b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
390543f328d7SVille Syrjälä {
39062cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
390743f328d7SVille Syrjälä 
3908ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
39099918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3910ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3911ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3912ad22d106SVille Syrjälä 
39132939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
39142939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
391543f328d7SVille Syrjälä }
391643f328d7SVille Syrjälä 
3917b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv)
3918c2798b19SChris Wilson {
3919b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3920c2798b19SChris Wilson 
392144d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
392244d9241eSVille Syrjälä 
3923ad7632ffSJani Nikula 	gen2_irq_reset(uncore);
3924e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
3925c2798b19SChris Wilson }
3926c2798b19SChris Wilson 
39273687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915)
39283687ce75SVille Syrjälä {
3929e7e12f6eSVille Syrjälä 	/*
3930e7e12f6eSVille Syrjälä 	 * On gen2/3 FBC generates (seemingly spurious)
3931e7e12f6eSVille Syrjälä 	 * display INVALID_GTT/INVALID_GTT_PTE table errors.
3932e7e12f6eSVille Syrjälä 	 *
3933e7e12f6eSVille Syrjälä 	 * Also gen3 bspec has this to say:
3934e7e12f6eSVille Syrjälä 	 * "DISPA_INVALID_GTT_PTE
3935e7e12f6eSVille Syrjälä 	 "  [DevNapa] : Reserved. This bit does not reflect the page
3936e7e12f6eSVille Syrjälä 	 "              table error for the display plane A."
3937e7e12f6eSVille Syrjälä 	 *
3938e7e12f6eSVille Syrjälä 	 * Unfortunately we can't mask off individual PGTBL_ER bits,
3939e7e12f6eSVille Syrjälä 	 * so we just have to mask off all page table errors via EMR.
3940e7e12f6eSVille Syrjälä 	 */
3941e7e12f6eSVille Syrjälä 	if (HAS_FBC(i915))
3942e7e12f6eSVille Syrjälä 		return ~I915_ERROR_MEMORY_REFRESH;
3943e7e12f6eSVille Syrjälä 	else
39443687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
39453687ce75SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
39463687ce75SVille Syrjälä }
39473687ce75SVille Syrjälä 
3948b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv)
3949c2798b19SChris Wilson {
3950b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3951e9e9848aSVille Syrjälä 	u16 enable_mask;
3952c2798b19SChris Wilson 
39533687ce75SVille Syrjälä 	intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv));
3954c2798b19SChris Wilson 
3955c2798b19SChris Wilson 	/* Unmask the interrupts that we always want on. */
3956c2798b19SChris Wilson 	dev_priv->irq_mask =
3957c2798b19SChris Wilson 		~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
395816659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
395916659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
3960c2798b19SChris Wilson 
3961e9e9848aSVille Syrjälä 	enable_mask =
3962c2798b19SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
3963c2798b19SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
396416659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
3965e9e9848aSVille Syrjälä 		I915_USER_INTERRUPT;
3966e9e9848aSVille Syrjälä 
3967ad7632ffSJani Nikula 	gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask);
3968c2798b19SChris Wilson 
3969379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
3970379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
3971d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
3972755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
3973755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
3974d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
3975c2798b19SChris Wilson }
3976c2798b19SChris Wilson 
39774f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915,
397878c357ddSVille Syrjälä 			       u16 *eir, u16 *eir_stuck)
397978c357ddSVille Syrjälä {
39804f5fd91fSTvrtko Ursulin 	struct intel_uncore *uncore = &i915->uncore;
398178c357ddSVille Syrjälä 	u16 emr;
398278c357ddSVille Syrjälä 
39834f5fd91fSTvrtko Ursulin 	*eir = intel_uncore_read16(uncore, EIR);
39844f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EIR, *eir);
398578c357ddSVille Syrjälä 
39864f5fd91fSTvrtko Ursulin 	*eir_stuck = intel_uncore_read16(uncore, EIR);
398778c357ddSVille Syrjälä 	if (*eir_stuck == 0)
398878c357ddSVille Syrjälä 		return;
398978c357ddSVille Syrjälä 
399078c357ddSVille Syrjälä 	/*
399178c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
399278c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
399378c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
399478c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
399578c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
399678c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
399778c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
399878c357ddSVille Syrjälä 	 * remains set.
399978c357ddSVille Syrjälä 	 */
40004f5fd91fSTvrtko Ursulin 	emr = intel_uncore_read16(uncore, EMR);
40014f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, 0xffff);
40024f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, emr | *eir_stuck);
400378c357ddSVille Syrjälä }
400478c357ddSVille Syrjälä 
400578c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv,
400678c357ddSVille Syrjälä 				   u16 eir, u16 eir_stuck)
400778c357ddSVille Syrjälä {
4008a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir);
400978c357ddSVille Syrjälä 
401078c357ddSVille Syrjälä 	if (eir_stuck)
401100376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n",
401200376ccfSWambui Karuga 			eir_stuck);
4013d1e89592SVille Syrjälä 
4014d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
4015d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
401678c357ddSVille Syrjälä }
401778c357ddSVille Syrjälä 
401878c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
401978c357ddSVille Syrjälä 			       u32 *eir, u32 *eir_stuck)
402078c357ddSVille Syrjälä {
402178c357ddSVille Syrjälä 	u32 emr;
402278c357ddSVille Syrjälä 
4023839259b8SVille Syrjälä 	*eir = intel_uncore_read(&dev_priv->uncore, EIR);
4024839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EIR, *eir);
402578c357ddSVille Syrjälä 
40262939eb06SJani Nikula 	*eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR);
402778c357ddSVille Syrjälä 	if (*eir_stuck == 0)
402878c357ddSVille Syrjälä 		return;
402978c357ddSVille Syrjälä 
403078c357ddSVille Syrjälä 	/*
403178c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
403278c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
403378c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
403478c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
403578c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
403678c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
403778c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
403878c357ddSVille Syrjälä 	 * remains set.
403978c357ddSVille Syrjälä 	 */
4040839259b8SVille Syrjälä 	emr = intel_uncore_read(&dev_priv->uncore, EMR);
4041839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff);
40422939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck);
404378c357ddSVille Syrjälä }
404478c357ddSVille Syrjälä 
404578c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv,
404678c357ddSVille Syrjälä 				   u32 eir, u32 eir_stuck)
404778c357ddSVille Syrjälä {
4048a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir);
404978c357ddSVille Syrjälä 
405078c357ddSVille Syrjälä 	if (eir_stuck)
405100376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n",
405200376ccfSWambui Karuga 			eir_stuck);
4053d1e89592SVille Syrjälä 
4054d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
4055d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
405678c357ddSVille Syrjälä }
405778c357ddSVille Syrjälä 
4058ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg)
4059c2798b19SChris Wilson {
4060b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4061af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4062c2798b19SChris Wilson 
40632dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
40642dd2a883SImre Deak 		return IRQ_NONE;
40652dd2a883SImre Deak 
40661f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
40679102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
40681f814dacSImre Deak 
4069af722d28SVille Syrjälä 	do {
4070af722d28SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
407178c357ddSVille Syrjälä 		u16 eir = 0, eir_stuck = 0;
4072af722d28SVille Syrjälä 		u16 iir;
4073af722d28SVille Syrjälä 
40744f5fd91fSTvrtko Ursulin 		iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR);
4075c2798b19SChris Wilson 		if (iir == 0)
4076af722d28SVille Syrjälä 			break;
4077c2798b19SChris Wilson 
4078af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4079c2798b19SChris Wilson 
4080eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4081eb64343cSVille Syrjälä 		 * signalled in iir */
4082eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4083c2798b19SChris Wilson 
408478c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
408578c357ddSVille Syrjälä 			i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
408678c357ddSVille Syrjälä 
40874f5fd91fSTvrtko Ursulin 		intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir);
4088c2798b19SChris Wilson 
4089c2798b19SChris Wilson 		if (iir & I915_USER_INTERRUPT)
40902cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
4091c2798b19SChris Wilson 
409278c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
409378c357ddSVille Syrjälä 			i8xx_error_irq_handler(dev_priv, eir, eir_stuck);
4094af722d28SVille Syrjälä 
4095eb64343cSVille Syrjälä 		i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4096af722d28SVille Syrjälä 	} while (0);
4097c2798b19SChris Wilson 
40989c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
40999c6508b9SThomas Gleixner 
41009102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
41011f814dacSImre Deak 
41021f814dacSImre Deak 	return ret;
4103c2798b19SChris Wilson }
4104c2798b19SChris Wilson 
4105b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv)
4106a266c7d5SChris Wilson {
4107b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
4108a266c7d5SChris Wilson 
410956b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
41100706f17cSEgbert Eich 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
41118cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0);
4112a266c7d5SChris Wilson 	}
4113a266c7d5SChris Wilson 
411444d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
411544d9241eSVille Syrjälä 
4116b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
4117e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
4118a266c7d5SChris Wilson }
4119a266c7d5SChris Wilson 
4120b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
4121a266c7d5SChris Wilson {
4122b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
412338bde180SChris Wilson 	u32 enable_mask;
4124a266c7d5SChris Wilson 
41253687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv));
412638bde180SChris Wilson 
412738bde180SChris Wilson 	/* Unmask the interrupts that we always want on. */
412838bde180SChris Wilson 	dev_priv->irq_mask =
412938bde180SChris Wilson 		~(I915_ASLE_INTERRUPT |
413038bde180SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
413116659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
413216659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
413338bde180SChris Wilson 
413438bde180SChris Wilson 	enable_mask =
413538bde180SChris Wilson 		I915_ASLE_INTERRUPT |
413638bde180SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
413738bde180SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
413816659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
413938bde180SChris Wilson 		I915_USER_INTERRUPT;
414038bde180SChris Wilson 
414156b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
4142a266c7d5SChris Wilson 		/* Enable in IER... */
4143a266c7d5SChris Wilson 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
4144a266c7d5SChris Wilson 		/* and unmask in IMR */
4145a266c7d5SChris Wilson 		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
4146a266c7d5SChris Wilson 	}
4147a266c7d5SChris Wilson 
4148b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
4149a266c7d5SChris Wilson 
4150379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
4151379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
4152d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
4153755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
4154755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
4155d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
4156379ef82dSDaniel Vetter 
4157c30bb1fdSVille Syrjälä 	i915_enable_asle_pipestat(dev_priv);
415820afbda2SDaniel Vetter }
415920afbda2SDaniel Vetter 
4160ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg)
4161a266c7d5SChris Wilson {
4162b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4163af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4164a266c7d5SChris Wilson 
41652dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
41662dd2a883SImre Deak 		return IRQ_NONE;
41672dd2a883SImre Deak 
41681f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
41699102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
41701f814dacSImre Deak 
417138bde180SChris Wilson 	do {
4172eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
417378c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
4174af722d28SVille Syrjälä 		u32 hotplug_status = 0;
4175af722d28SVille Syrjälä 		u32 iir;
4176a266c7d5SChris Wilson 
41772939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
4178af722d28SVille Syrjälä 		if (iir == 0)
4179af722d28SVille Syrjälä 			break;
4180af722d28SVille Syrjälä 
4181af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4182af722d28SVille Syrjälä 
4183af722d28SVille Syrjälä 		if (I915_HAS_HOTPLUG(dev_priv) &&
4184af722d28SVille Syrjälä 		    iir & I915_DISPLAY_PORT_INTERRUPT)
4185af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
4186a266c7d5SChris Wilson 
4187eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4188eb64343cSVille Syrjälä 		 * signalled in iir */
4189eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4190a266c7d5SChris Wilson 
419178c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
419278c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
419378c357ddSVille Syrjälä 
41942939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
4195a266c7d5SChris Wilson 
4196a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
41972cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
4198a266c7d5SChris Wilson 
419978c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
420078c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
4201a266c7d5SChris Wilson 
4202af722d28SVille Syrjälä 		if (hotplug_status)
4203af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
4204af722d28SVille Syrjälä 
4205af722d28SVille Syrjälä 		i915_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4206af722d28SVille Syrjälä 	} while (0);
4207a266c7d5SChris Wilson 
42089c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
42099c6508b9SThomas Gleixner 
42109102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
42111f814dacSImre Deak 
4212a266c7d5SChris Wilson 	return ret;
4213a266c7d5SChris Wilson }
4214a266c7d5SChris Wilson 
4215b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv)
4216a266c7d5SChris Wilson {
4217b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
4218a266c7d5SChris Wilson 
42190706f17cSEgbert Eich 	i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
42208cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
4221a266c7d5SChris Wilson 
422244d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
422344d9241eSVille Syrjälä 
4224b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
4225e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
4226a266c7d5SChris Wilson }
4227a266c7d5SChris Wilson 
42283687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915)
4229a266c7d5SChris Wilson {
4230045cebd2SVille Syrjälä 	/*
4231045cebd2SVille Syrjälä 	 * Enable some error detection, note the instruction error mask
4232045cebd2SVille Syrjälä 	 * bit is reserved, so we leave it masked.
4233e7e12f6eSVille Syrjälä 	 *
4234e7e12f6eSVille Syrjälä 	 * i965 FBC no longer generates spurious GTT errors,
4235e7e12f6eSVille Syrjälä 	 * so we can always enable the page table errors.
4236045cebd2SVille Syrjälä 	 */
42373687ce75SVille Syrjälä 	if (IS_G4X(i915))
42383687ce75SVille Syrjälä 		return ~(GM45_ERROR_PAGE_TABLE |
4239045cebd2SVille Syrjälä 			 GM45_ERROR_MEM_PRIV |
4240045cebd2SVille Syrjälä 			 GM45_ERROR_CP_PRIV |
4241045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
42423687ce75SVille Syrjälä 	else
42433687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
4244045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
4245045cebd2SVille Syrjälä }
42463687ce75SVille Syrjälä 
42473687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
42483687ce75SVille Syrjälä {
42493687ce75SVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
42503687ce75SVille Syrjälä 	u32 enable_mask;
42513687ce75SVille Syrjälä 
42523687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv));
4253045cebd2SVille Syrjälä 
4254a266c7d5SChris Wilson 	/* Unmask the interrupts that we always want on. */
4255c30bb1fdSVille Syrjälä 	dev_priv->irq_mask =
4256c30bb1fdSVille Syrjälä 		~(I915_ASLE_INTERRUPT |
4257adca4730SChris Wilson 		  I915_DISPLAY_PORT_INTERRUPT |
4258bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4259bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
426078c357ddSVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
4261bbba0a97SChris Wilson 
4262c30bb1fdSVille Syrjälä 	enable_mask =
4263c30bb1fdSVille Syrjälä 		I915_ASLE_INTERRUPT |
4264c30bb1fdSVille Syrjälä 		I915_DISPLAY_PORT_INTERRUPT |
4265c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4266c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
426778c357ddSVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
4268c30bb1fdSVille Syrjälä 		I915_USER_INTERRUPT;
4269bbba0a97SChris Wilson 
427091d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4271bbba0a97SChris Wilson 		enable_mask |= I915_BSD_USER_INTERRUPT;
4272a266c7d5SChris Wilson 
4273b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
4274c30bb1fdSVille Syrjälä 
4275b79480baSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
4276b79480baSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
4277d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
4278755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
4279755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
4280755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
4281d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
4282a266c7d5SChris Wilson 
428391d14251STvrtko Ursulin 	i915_enable_asle_pipestat(dev_priv);
428420afbda2SDaniel Vetter }
428520afbda2SDaniel Vetter 
4286*d28cdc43SVille Syrjälä static void i915_hpd_enable_detection(struct intel_encoder *encoder)
4287*d28cdc43SVille Syrjälä {
4288*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4289*d28cdc43SVille Syrjälä 	u32 hotplug_en = hpd_mask_i915[encoder->hpd_pin];
4290*d28cdc43SVille Syrjälä 
4291*d28cdc43SVille Syrjälä 	/* HPD sense and interrupt enable are one and the same */
4292*d28cdc43SVille Syrjälä 	i915_hotplug_interrupt_update(i915, hotplug_en, hotplug_en);
4293*d28cdc43SVille Syrjälä }
4294*d28cdc43SVille Syrjälä 
429591d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
429620afbda2SDaniel Vetter {
429720afbda2SDaniel Vetter 	u32 hotplug_en;
429820afbda2SDaniel Vetter 
429967520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
4300b5ea2d56SDaniel Vetter 
4301adca4730SChris Wilson 	/* Note HDMI and DP share hotplug bits */
4302e5868a31SEgbert Eich 	/* enable bits are the same for all generations */
430391d14251STvrtko Ursulin 	hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
4304a266c7d5SChris Wilson 	/* Programming the CRT detection parameters tends
4305a266c7d5SChris Wilson 	   to generate a spurious hotplug event about three
4306a266c7d5SChris Wilson 	   seconds later.  So just do it once.
4307a266c7d5SChris Wilson 	*/
430891d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4309a266c7d5SChris Wilson 		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
4310a266c7d5SChris Wilson 	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
4311a266c7d5SChris Wilson 
4312a266c7d5SChris Wilson 	/* Ignore TV since it's buggy */
43130706f17cSEgbert Eich 	i915_hotplug_interrupt_update_locked(dev_priv,
4314f9e3dc78SJani Nikula 					     HOTPLUG_INT_EN_MASK |
4315f9e3dc78SJani Nikula 					     CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
4316f9e3dc78SJani Nikula 					     CRT_HOTPLUG_ACTIVATION_PERIOD_64,
43170706f17cSEgbert Eich 					     hotplug_en);
4318a266c7d5SChris Wilson }
4319a266c7d5SChris Wilson 
4320ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg)
4321a266c7d5SChris Wilson {
4322b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4323af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4324a266c7d5SChris Wilson 
43252dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
43262dd2a883SImre Deak 		return IRQ_NONE;
43272dd2a883SImre Deak 
43281f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
43299102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
43301f814dacSImre Deak 
4331af722d28SVille Syrjälä 	do {
4332eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
433378c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
4334af722d28SVille Syrjälä 		u32 hotplug_status = 0;
4335af722d28SVille Syrjälä 		u32 iir;
43362c8ba29fSChris Wilson 
43372939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
4338af722d28SVille Syrjälä 		if (iir == 0)
4339af722d28SVille Syrjälä 			break;
4340af722d28SVille Syrjälä 
4341af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4342af722d28SVille Syrjälä 
4343af722d28SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
4344af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
4345a266c7d5SChris Wilson 
4346eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4347eb64343cSVille Syrjälä 		 * signalled in iir */
4348eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4349a266c7d5SChris Wilson 
435078c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
435178c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
435278c357ddSVille Syrjälä 
43532939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
4354a266c7d5SChris Wilson 
4355a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
43562cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0],
43570669a6e1SChris Wilson 					    iir);
4358af722d28SVille Syrjälä 
4359a266c7d5SChris Wilson 		if (iir & I915_BSD_USER_INTERRUPT)
43602cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0],
43610669a6e1SChris Wilson 					    iir >> 25);
4362a266c7d5SChris Wilson 
436378c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
436478c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
4365515ac2bbSDaniel Vetter 
4366af722d28SVille Syrjälä 		if (hotplug_status)
4367af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
4368af722d28SVille Syrjälä 
4369af722d28SVille Syrjälä 		i965_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4370af722d28SVille Syrjälä 	} while (0);
4371a266c7d5SChris Wilson 
43729c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
43739c6508b9SThomas Gleixner 
43749102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
43751f814dacSImre Deak 
4376a266c7d5SChris Wilson 	return ret;
4377a266c7d5SChris Wilson }
4378a266c7d5SChris Wilson 
43797e97596cSJani Nikula struct intel_hotplug_funcs {
4380*d28cdc43SVille Syrjälä 	/* Enable HPD sense and interrupts for all present encoders */
43817e97596cSJani Nikula 	void (*hpd_irq_setup)(struct drm_i915_private *i915);
4382*d28cdc43SVille Syrjälä 	/* Enable HPD sense for a single encoder */
4383*d28cdc43SVille Syrjälä 	void (*hpd_enable_detection)(struct intel_encoder *encoder);
43847e97596cSJani Nikula };
43857e97596cSJani Nikula 
4386cd030c7cSDave Airlie #define HPD_FUNCS(platform)					 \
4387cd030c7cSDave Airlie static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
4388cd030c7cSDave Airlie 	.hpd_irq_setup = platform##_hpd_irq_setup,		 \
4389*d28cdc43SVille Syrjälä 	.hpd_enable_detection = platform##_hpd_enable_detection, \
4390cd030c7cSDave Airlie }
4391cd030c7cSDave Airlie 
4392cd030c7cSDave Airlie HPD_FUNCS(i915);
4393babde06dSMika Kahola HPD_FUNCS(xelpdp);
4394cd030c7cSDave Airlie HPD_FUNCS(dg1);
4395cd030c7cSDave Airlie HPD_FUNCS(gen11);
4396cd030c7cSDave Airlie HPD_FUNCS(bxt);
4397cd030c7cSDave Airlie HPD_FUNCS(icp);
4398cd030c7cSDave Airlie HPD_FUNCS(spt);
4399cd030c7cSDave Airlie HPD_FUNCS(ilk);
4400cd030c7cSDave Airlie #undef HPD_FUNCS
4401cd030c7cSDave Airlie 
4402*d28cdc43SVille Syrjälä void intel_hpd_enable_detection(struct intel_encoder *encoder)
4403*d28cdc43SVille Syrjälä {
4404*d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4405*d28cdc43SVille Syrjälä 
4406*d28cdc43SVille Syrjälä 	if (i915->display.funcs.hotplug)
4407*d28cdc43SVille Syrjälä 		i915->display.funcs.hotplug->hpd_enable_detection(encoder);
4408*d28cdc43SVille Syrjälä }
4409*d28cdc43SVille Syrjälä 
44107e97596cSJani Nikula void intel_hpd_irq_setup(struct drm_i915_private *i915)
44117e97596cSJani Nikula {
44125a04eb5bSJani Nikula 	if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
44135a04eb5bSJani Nikula 		i915->display.funcs.hotplug->hpd_irq_setup(i915);
44147e97596cSJani Nikula }
44157e97596cSJani Nikula 
4416fca52a55SDaniel Vetter /**
4417fca52a55SDaniel Vetter  * intel_irq_init - initializes irq support
4418fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4419fca52a55SDaniel Vetter  *
4420fca52a55SDaniel Vetter  * This function initializes all the irq support including work items, timers
4421fca52a55SDaniel Vetter  * and all the vtables. It does not setup the interrupt itself though.
4422fca52a55SDaniel Vetter  */
4423b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv)
4424f71d4af4SJesse Barnes {
4425cefcff8fSJoonas Lahtinen 	int i;
44268b2e326dSChris Wilson 
442774bb98baSLucas De Marchi 	INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work);
4428cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4429cefcff8fSJoonas Lahtinen 		dev_priv->l3_parity.remap_info[i] = NULL;
44308b2e326dSChris Wilson 
4431633023a4SDaniele Ceraolo Spurio 	/* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */
4432651e7d48SLucas De Marchi 	if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11)
44332cbc876dSMichał Winiarski 		to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16;
443426705e20SSagar Arun Kamble 
44359a450b68SLucas De Marchi 	if (!HAS_DISPLAY(dev_priv))
44369a450b68SLucas De Marchi 		return;
44379a450b68SLucas De Marchi 
443896bd87b7SLucas De Marchi 	intel_hpd_init_pins(dev_priv);
443996bd87b7SLucas De Marchi 
4440dd890d42SJani Nikula 	intel_hpd_init_early(dev_priv);
444196bd87b7SLucas De Marchi 
44423703060dSAndrzej Hajda 	dev_priv->drm.vblank_disable_immediate = true;
444321da2700SVille Syrjälä 
4444262fd485SChris Wilson 	/* Most platforms treat the display irq block as an always-on
4445262fd485SChris Wilson 	 * power domain. vlv/chv can disable it at runtime and need
4446262fd485SChris Wilson 	 * special care to avoid writing any of the display block registers
4447262fd485SChris Wilson 	 * outside of the power domain. We defer setting up the display irqs
4448262fd485SChris Wilson 	 * in this case to the runtime pm.
4449262fd485SChris Wilson 	 */
4450262fd485SChris Wilson 	dev_priv->display_irqs_enabled = true;
4451262fd485SChris Wilson 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
4452262fd485SChris Wilson 		dev_priv->display_irqs_enabled = false;
4453262fd485SChris Wilson 
44542ccf2e03SChris Wilson 	if (HAS_GMCH(dev_priv)) {
44552ccf2e03SChris Wilson 		if (I915_HAS_HOTPLUG(dev_priv))
44565a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &i915_hpd_funcs;
44572ccf2e03SChris Wilson 	} else {
44582f8a6699SMatt Roper 		if (HAS_PCH_DG2(dev_priv))
44595a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
44602f8a6699SMatt Roper 		else if (HAS_PCH_DG1(dev_priv))
44615a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &dg1_hpd_funcs;
4462babde06dSMika Kahola 		else if (DISPLAY_VER(dev_priv) >= 14)
4463babde06dSMika Kahola 			dev_priv->display.funcs.hotplug = &xelpdp_hpd_funcs;
4464373abf1aSMatt Roper 		else if (DISPLAY_VER(dev_priv) >= 11)
44655a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &gen11_hpd_funcs;
446670bfb307SMatt Roper 		else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
44675a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &bxt_hpd_funcs;
4468cec3295bSLyude Paul 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
44695a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
4470c6c30b91SRodrigo Vivi 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
44715a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &spt_hpd_funcs;
44726dbf30ceSVille Syrjälä 		else
44735a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &ilk_hpd_funcs;
4474f71d4af4SJesse Barnes 	}
44752ccf2e03SChris Wilson }
447620afbda2SDaniel Vetter 
4477fca52a55SDaniel Vetter /**
4478cefcff8fSJoonas Lahtinen  * intel_irq_fini - deinitializes IRQ support
4479cefcff8fSJoonas Lahtinen  * @i915: i915 device instance
4480cefcff8fSJoonas Lahtinen  *
4481cefcff8fSJoonas Lahtinen  * This function deinitializes all the IRQ support.
4482cefcff8fSJoonas Lahtinen  */
4483cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915)
4484cefcff8fSJoonas Lahtinen {
4485cefcff8fSJoonas Lahtinen 	int i;
4486cefcff8fSJoonas Lahtinen 
4487cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4488cefcff8fSJoonas Lahtinen 		kfree(i915->l3_parity.remap_info[i]);
4489cefcff8fSJoonas Lahtinen }
4490cefcff8fSJoonas Lahtinen 
4491b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv)
4492b318b824SVille Syrjälä {
4493b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4494b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4495b318b824SVille Syrjälä 			return cherryview_irq_handler;
4496b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4497b318b824SVille Syrjälä 			return valleyview_irq_handler;
4498651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4499b318b824SVille Syrjälä 			return i965_irq_handler;
4500651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4501b318b824SVille Syrjälä 			return i915_irq_handler;
4502b318b824SVille Syrjälä 		else
4503b318b824SVille Syrjälä 			return i8xx_irq_handler;
4504b318b824SVille Syrjälä 	} else {
450522e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
450697b492f5SLucas De Marchi 			return dg1_irq_handler;
450722e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4508b318b824SVille Syrjälä 			return gen11_irq_handler;
4509651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4510b318b824SVille Syrjälä 			return gen8_irq_handler;
4511b318b824SVille Syrjälä 		else
45129eae5e27SLucas De Marchi 			return ilk_irq_handler;
4513b318b824SVille Syrjälä 	}
4514b318b824SVille Syrjälä }
4515b318b824SVille Syrjälä 
4516b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv)
4517b318b824SVille Syrjälä {
4518b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4519b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4520b318b824SVille Syrjälä 			cherryview_irq_reset(dev_priv);
4521b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4522b318b824SVille Syrjälä 			valleyview_irq_reset(dev_priv);
4523651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4524b318b824SVille Syrjälä 			i965_irq_reset(dev_priv);
4525651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4526b318b824SVille Syrjälä 			i915_irq_reset(dev_priv);
4527b318b824SVille Syrjälä 		else
4528b318b824SVille Syrjälä 			i8xx_irq_reset(dev_priv);
4529b318b824SVille Syrjälä 	} else {
453022e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
453122e26af7SPaulo Zanoni 			dg1_irq_reset(dev_priv);
453222e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4533b318b824SVille Syrjälä 			gen11_irq_reset(dev_priv);
4534651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4535b318b824SVille Syrjälä 			gen8_irq_reset(dev_priv);
4536b318b824SVille Syrjälä 		else
45379eae5e27SLucas De Marchi 			ilk_irq_reset(dev_priv);
4538b318b824SVille Syrjälä 	}
4539b318b824SVille Syrjälä }
4540b318b824SVille Syrjälä 
4541b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv)
4542b318b824SVille Syrjälä {
4543b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4544b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4545b318b824SVille Syrjälä 			cherryview_irq_postinstall(dev_priv);
4546b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4547b318b824SVille Syrjälä 			valleyview_irq_postinstall(dev_priv);
4548651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4549b318b824SVille Syrjälä 			i965_irq_postinstall(dev_priv);
4550651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4551b318b824SVille Syrjälä 			i915_irq_postinstall(dev_priv);
4552b318b824SVille Syrjälä 		else
4553b318b824SVille Syrjälä 			i8xx_irq_postinstall(dev_priv);
4554b318b824SVille Syrjälä 	} else {
455522e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
455622e26af7SPaulo Zanoni 			dg1_irq_postinstall(dev_priv);
455722e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4558b318b824SVille Syrjälä 			gen11_irq_postinstall(dev_priv);
4559651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4560b318b824SVille Syrjälä 			gen8_irq_postinstall(dev_priv);
4561b318b824SVille Syrjälä 		else
45629eae5e27SLucas De Marchi 			ilk_irq_postinstall(dev_priv);
4563b318b824SVille Syrjälä 	}
4564b318b824SVille Syrjälä }
4565b318b824SVille Syrjälä 
4566cefcff8fSJoonas Lahtinen /**
4567fca52a55SDaniel Vetter  * intel_irq_install - enables the hardware interrupt
4568fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4569fca52a55SDaniel Vetter  *
4570fca52a55SDaniel Vetter  * This function enables the hardware interrupt handling, but leaves the hotplug
4571fca52a55SDaniel Vetter  * handling still disabled. It is called after intel_irq_init().
4572fca52a55SDaniel Vetter  *
4573fca52a55SDaniel Vetter  * In the driver load and resume code we need working interrupts in a few places
4574fca52a55SDaniel Vetter  * but don't want to deal with the hassle of concurrent probe and hotplug
4575fca52a55SDaniel Vetter  * workers. Hence the split into this two-stage approach.
4576fca52a55SDaniel Vetter  */
45772aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv)
45782aeb7d3aSDaniel Vetter {
45798ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4580b318b824SVille Syrjälä 	int ret;
4581b318b824SVille Syrjälä 
45822aeb7d3aSDaniel Vetter 	/*
45832aeb7d3aSDaniel Vetter 	 * We enable some interrupt sources in our postinstall hooks, so mark
45842aeb7d3aSDaniel Vetter 	 * interrupts as enabled _before_ actually enabling them to avoid
45852aeb7d3aSDaniel Vetter 	 * special cases in our ordering checks.
45862aeb7d3aSDaniel Vetter 	 */
4587ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
45882aeb7d3aSDaniel Vetter 
4589ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = true;
4590b318b824SVille Syrjälä 
4591b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4592b318b824SVille Syrjälä 
4593b318b824SVille Syrjälä 	ret = request_irq(irq, intel_irq_handler(dev_priv),
4594b318b824SVille Syrjälä 			  IRQF_SHARED, DRIVER_NAME, dev_priv);
4595b318b824SVille Syrjälä 	if (ret < 0) {
4596ac1723c1SThomas Zimmermann 		dev_priv->irq_enabled = false;
4597b318b824SVille Syrjälä 		return ret;
4598b318b824SVille Syrjälä 	}
4599b318b824SVille Syrjälä 
4600b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4601b318b824SVille Syrjälä 
4602b318b824SVille Syrjälä 	return ret;
46032aeb7d3aSDaniel Vetter }
46042aeb7d3aSDaniel Vetter 
4605fca52a55SDaniel Vetter /**
4606fca52a55SDaniel Vetter  * intel_irq_uninstall - finilizes all irq handling
4607fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4608fca52a55SDaniel Vetter  *
4609fca52a55SDaniel Vetter  * This stops interrupt and hotplug handling and unregisters and frees all
4610fca52a55SDaniel Vetter  * resources acquired in the init functions.
4611fca52a55SDaniel Vetter  */
46122aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv)
46132aeb7d3aSDaniel Vetter {
46148ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4615b318b824SVille Syrjälä 
4616b318b824SVille Syrjälä 	/*
4617789fa874SJanusz Krzysztofik 	 * FIXME we can get called twice during driver probe
4618789fa874SJanusz Krzysztofik 	 * error handling as well as during driver remove due to
461986a1758dSJani Nikula 	 * intel_display_driver_remove() calling us out of sequence.
4620789fa874SJanusz Krzysztofik 	 * Would be nice if it didn't do that...
4621b318b824SVille Syrjälä 	 */
4622ac1723c1SThomas Zimmermann 	if (!dev_priv->irq_enabled)
4623b318b824SVille Syrjälä 		return;
4624b318b824SVille Syrjälä 
4625ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = false;
4626b318b824SVille Syrjälä 
4627b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4628b318b824SVille Syrjälä 
4629b318b824SVille Syrjälä 	free_irq(irq, dev_priv);
4630b318b824SVille Syrjälä 
46312aeb7d3aSDaniel Vetter 	intel_hpd_cancel_work(dev_priv);
4632ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
46332aeb7d3aSDaniel Vetter }
46342aeb7d3aSDaniel Vetter 
4635fca52a55SDaniel Vetter /**
4636fca52a55SDaniel Vetter  * intel_runtime_pm_disable_interrupts - runtime interrupt disabling
4637fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4638fca52a55SDaniel Vetter  *
4639fca52a55SDaniel Vetter  * This function is used to disable interrupts at runtime, both in the runtime
4640fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4641fca52a55SDaniel Vetter  */
4642b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
4643c67a470bSPaulo Zanoni {
4644b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4645ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
4646315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
4647c67a470bSPaulo Zanoni }
4648c67a470bSPaulo Zanoni 
4649fca52a55SDaniel Vetter /**
4650fca52a55SDaniel Vetter  * intel_runtime_pm_enable_interrupts - runtime interrupt enabling
4651fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4652fca52a55SDaniel Vetter  *
4653fca52a55SDaniel Vetter  * This function is used to enable interrupts at runtime, both in the runtime
4654fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4655fca52a55SDaniel Vetter  */
4656b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv)
4657c67a470bSPaulo Zanoni {
4658ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
4659b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4660b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4661c67a470bSPaulo Zanoni }
4662d64575eeSJani Nikula 
4663d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
4664d64575eeSJani Nikula {
4665d64575eeSJani Nikula 	return dev_priv->runtime_pm.irqs_enabled;
4666d64575eeSJani Nikula }
4667d64575eeSJani Nikula 
4668d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915)
4669d64575eeSJani Nikula {
46708ff5446aSThomas Zimmermann 	synchronize_irq(to_pci_dev(i915->drm.dev)->irq);
4671d64575eeSJani Nikula }
4672320ad343SThomas Zimmermann 
4673320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915)
4674320ad343SThomas Zimmermann {
4675320ad343SThomas Zimmermann 	synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq);
4676320ad343SThomas Zimmermann }
4677