xref: /openbmc/linux/drivers/gpu/drm/i915/i915_irq.c (revision 86a1758d751de03e8f3d8810fe22eaf571798871)
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ä 
2934dfefe7bcSVille Syrjälä static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
29352ea63927SVille Syrjälä {
2936dfefe7bcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2937dfefe7bcSVille Syrjälä 
2938dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
29392ea63927SVille Syrjälä 	case HPD_PORT_A:
29402ea63927SVille Syrjälä 		/*
29412ea63927SVille Syrjälä 		 * When CPU and PCH are on the same package, port A
29422ea63927SVille Syrjälä 		 * HPD must be enabled in both north and south.
29432ea63927SVille Syrjälä 		 */
29442ea63927SVille Syrjälä 		return HAS_PCH_LPT_LP(i915) ?
29452ea63927SVille Syrjälä 			PORTA_HOTPLUG_ENABLE : 0;
29462ea63927SVille Syrjälä 	case HPD_PORT_B:
29472ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE |
29482ea63927SVille Syrjälä 			PORTB_PULSE_DURATION_2ms;
29492ea63927SVille Syrjälä 	case HPD_PORT_C:
29502ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE |
29512ea63927SVille Syrjälä 			PORTC_PULSE_DURATION_2ms;
29522ea63927SVille Syrjälä 	case HPD_PORT_D:
29532ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE |
29542ea63927SVille Syrjälä 			PORTD_PULSE_DURATION_2ms;
29552ea63927SVille Syrjälä 	default:
29562ea63927SVille Syrjälä 		return 0;
29572ea63927SVille Syrjälä 	}
29582ea63927SVille Syrjälä }
29592ea63927SVille Syrjälä 
29601a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
29611a56b1a2SImre Deak {
29621a56b1a2SImre Deak 	/*
29631a56b1a2SImre Deak 	 * Enable digital hotplug on the PCH, and configure the DP short pulse
29641a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec).
29651a56b1a2SImre Deak 	 * The pulse duration bits are reserved on LPT+.
29661a56b1a2SImre Deak 	 */
29678cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
29688cee664dSAndrzej Hajda 			 PORTA_HOTPLUG_ENABLE |
29692ea63927SVille Syrjälä 			 PORTB_HOTPLUG_ENABLE |
29702ea63927SVille Syrjälä 			 PORTC_HOTPLUG_ENABLE |
29712ea63927SVille Syrjälä 			 PORTD_HOTPLUG_ENABLE |
29722ea63927SVille Syrjälä 			 PORTB_PULSE_DURATION_MASK |
29731a56b1a2SImre Deak 			 PORTC_PULSE_DURATION_MASK |
29748cee664dSAndrzej Hajda 			 PORTD_PULSE_DURATION_MASK,
29758cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
29761a56b1a2SImre Deak }
29771a56b1a2SImre Deak 
297891d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
297982a28bcfSDaniel Vetter {
29801a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
298182a28bcfSDaniel Vetter 
29825a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
29835a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
298482a28bcfSDaniel Vetter 
2985fee884edSDaniel Vetter 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
298682a28bcfSDaniel Vetter 
29871a56b1a2SImre Deak 	ibx_hpd_detection_setup(dev_priv);
29886dbf30ceSVille Syrjälä }
298926951cafSXiong Zhang 
2990dfefe7bcSVille Syrjälä static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
29912ea63927SVille Syrjälä {
2992dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
29932ea63927SVille Syrjälä 	case HPD_PORT_A:
29942ea63927SVille Syrjälä 	case HPD_PORT_B:
29952ea63927SVille Syrjälä 	case HPD_PORT_C:
29962ea63927SVille Syrjälä 	case HPD_PORT_D:
2997dfefe7bcSVille Syrjälä 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(encoder->hpd_pin);
29982ea63927SVille Syrjälä 	default:
29992ea63927SVille Syrjälä 		return 0;
30002ea63927SVille Syrjälä 	}
30012ea63927SVille Syrjälä }
30022ea63927SVille Syrjälä 
3003dfefe7bcSVille Syrjälä static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
30042ea63927SVille Syrjälä {
3005dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
30062ea63927SVille Syrjälä 	case HPD_PORT_TC1:
30072ea63927SVille Syrjälä 	case HPD_PORT_TC2:
30082ea63927SVille Syrjälä 	case HPD_PORT_TC3:
30092ea63927SVille Syrjälä 	case HPD_PORT_TC4:
30102ea63927SVille Syrjälä 	case HPD_PORT_TC5:
30112ea63927SVille Syrjälä 	case HPD_PORT_TC6:
3012dfefe7bcSVille Syrjälä 		return ICP_TC_HPD_ENABLE(encoder->hpd_pin);
30132ea63927SVille Syrjälä 	default:
30142ea63927SVille Syrjälä 		return 0;
30152ea63927SVille Syrjälä 	}
30162ea63927SVille Syrjälä }
30172ea63927SVille Syrjälä 
30182ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
301931604222SAnusha Srivatsa {
30208cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
30218cee664dSAndrzej Hajda 			 SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) |
30222ea63927SVille Syrjälä 			 SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) |
30232ea63927SVille Syrjälä 			 SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) |
30248cee664dSAndrzej Hajda 			 SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D),
30258cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
302631604222SAnusha Srivatsa }
3027815f4ef2SVille Syrjälä 
30282ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3029815f4ef2SVille Syrjälä {
30308cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
30318cee664dSAndrzej Hajda 			 ICP_TC_HPD_ENABLE(HPD_PORT_TC1) |
30322ea63927SVille Syrjälä 			 ICP_TC_HPD_ENABLE(HPD_PORT_TC2) |
30332ea63927SVille Syrjälä 			 ICP_TC_HPD_ENABLE(HPD_PORT_TC3) |
30342ea63927SVille Syrjälä 			 ICP_TC_HPD_ENABLE(HPD_PORT_TC4) |
30352ea63927SVille Syrjälä 			 ICP_TC_HPD_ENABLE(HPD_PORT_TC5) |
30368cee664dSAndrzej Hajda 			 ICP_TC_HPD_ENABLE(HPD_PORT_TC6),
30378cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
30388ef7e340SMatt Roper }
303931604222SAnusha Srivatsa 
30402ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
304131604222SAnusha Srivatsa {
304231604222SAnusha Srivatsa 	u32 hotplug_irqs, enabled_irqs;
304331604222SAnusha Srivatsa 
30445a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
30455a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
304631604222SAnusha Srivatsa 
3047f619e516SAnusha Srivatsa 	if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
30482939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3049f49108d0SMatt Roper 
305031604222SAnusha Srivatsa 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
305131604222SAnusha Srivatsa 
30522ea63927SVille Syrjälä 	icp_ddi_hpd_detection_setup(dev_priv);
30532ea63927SVille Syrjälä 	icp_tc_hpd_detection_setup(dev_priv);
305452dfdba0SLucas De Marchi }
305552dfdba0SLucas De Marchi 
3056dfefe7bcSVille Syrjälä static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
30578ef7e340SMatt Roper {
3058dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
30592ea63927SVille Syrjälä 	case HPD_PORT_TC1:
30602ea63927SVille Syrjälä 	case HPD_PORT_TC2:
30612ea63927SVille Syrjälä 	case HPD_PORT_TC3:
30622ea63927SVille Syrjälä 	case HPD_PORT_TC4:
30632ea63927SVille Syrjälä 	case HPD_PORT_TC5:
30642ea63927SVille Syrjälä 	case HPD_PORT_TC6:
3065dfefe7bcSVille Syrjälä 		return GEN11_HOTPLUG_CTL_ENABLE(encoder->hpd_pin);
30662ea63927SVille Syrjälä 	default:
30672ea63927SVille Syrjälä 		return 0;
306831604222SAnusha Srivatsa 	}
3069943682e3SMatt Roper }
3070943682e3SMatt Roper 
307171690148SGustavo Sousa static void dg1_hpd_invert(struct drm_i915_private *i915)
3072229f31e2SLucas De Marchi {
307371690148SGustavo Sousa 	u32 val = (INVERT_DDIA_HPD |
3074b18c1eb9SClinton A Taylor 		   INVERT_DDIB_HPD |
3075b18c1eb9SClinton A Taylor 		   INVERT_DDIC_HPD |
3076b18c1eb9SClinton A Taylor 		   INVERT_DDID_HPD);
307771690148SGustavo Sousa 	intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
307871690148SGustavo Sousa }
3079b18c1eb9SClinton A Taylor 
308071690148SGustavo Sousa static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
308171690148SGustavo Sousa {
308271690148SGustavo Sousa 	dg1_hpd_invert(dev_priv);
30832ea63927SVille Syrjälä 	icp_hpd_irq_setup(dev_priv);
3084229f31e2SLucas De Marchi }
3085229f31e2SLucas De Marchi 
308652c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3087121e758eSDhinakaran Pandiyan {
30888cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
30898cee664dSAndrzej Hajda 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
30905b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
30915b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
30925b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
30935b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
30948cee664dSAndrzej Hajda 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6),
30958cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
309652c7f5f1SVille Syrjälä }
309752c7f5f1SVille Syrjälä 
309852c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
309952c7f5f1SVille Syrjälä {
31008cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
31018cee664dSAndrzej Hajda 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC1) |
31025b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC2) |
31035b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC3) |
31045b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC4) |
31055b76e860SVille Syrjälä 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC5) |
31068cee664dSAndrzej Hajda 			 GEN11_HOTPLUG_CTL_ENABLE(HPD_PORT_TC6),
31078cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
3108121e758eSDhinakaran Pandiyan }
3109121e758eSDhinakaran Pandiyan 
3110121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
3111121e758eSDhinakaran Pandiyan {
3112121e758eSDhinakaran Pandiyan 	u32 hotplug_irqs, enabled_irqs;
3113121e758eSDhinakaran Pandiyan 
31145a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
31155a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
3116121e758eSDhinakaran Pandiyan 
31178cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
31188cee664dSAndrzej Hajda 			 ~enabled_irqs & hotplug_irqs);
31192939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
3120121e758eSDhinakaran Pandiyan 
312152c7f5f1SVille Syrjälä 	gen11_tc_hpd_detection_setup(dev_priv);
312252c7f5f1SVille Syrjälä 	gen11_tbt_hpd_detection_setup(dev_priv);
312331604222SAnusha Srivatsa 
31242ea63927SVille Syrjälä 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
31252ea63927SVille Syrjälä 		icp_hpd_irq_setup(dev_priv);
31262ea63927SVille Syrjälä }
31272ea63927SVille Syrjälä 
3128babde06dSMika Kahola static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder)
3129babde06dSMika Kahola {
3130babde06dSMika Kahola 	switch (encoder->hpd_pin) {
3131babde06dSMika Kahola 	case HPD_PORT_A:
3132babde06dSMika Kahola 	case HPD_PORT_B:
3133babde06dSMika Kahola 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(encoder->hpd_pin);
3134babde06dSMika Kahola 	default:
3135babde06dSMika Kahola 		return 0;
3136babde06dSMika Kahola 	}
3137babde06dSMika Kahola }
3138babde06dSMika Kahola 
3139babde06dSMika Kahola static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder)
3140babde06dSMika Kahola {
3141babde06dSMika Kahola 	switch (encoder->hpd_pin) {
3142babde06dSMika Kahola 	case HPD_PORT_TC1:
3143babde06dSMika Kahola 	case HPD_PORT_TC2:
3144babde06dSMika Kahola 	case HPD_PORT_TC3:
3145babde06dSMika Kahola 	case HPD_PORT_TC4:
3146babde06dSMika Kahola 		return ICP_TC_HPD_ENABLE(encoder->hpd_pin);
3147babde06dSMika Kahola 	default:
3148babde06dSMika Kahola 		return 0;
3149babde06dSMika Kahola 	}
3150babde06dSMika Kahola }
3151babde06dSMika Kahola 
3152babde06dSMika Kahola static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
3153babde06dSMika Kahola {
3154babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
3155babde06dSMika Kahola 		     (SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) |
3156babde06dSMika Kahola 		      SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B)),
3157babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
3158babde06dSMika Kahola }
3159babde06dSMika Kahola 
3160babde06dSMika Kahola static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
3161babde06dSMika Kahola {
3162babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_TC,
3163babde06dSMika Kahola 		     (ICP_TC_HPD_ENABLE(HPD_PORT_TC1) |
3164babde06dSMika Kahola 		      ICP_TC_HPD_ENABLE(HPD_PORT_TC2) |
3165babde06dSMika Kahola 		      ICP_TC_HPD_ENABLE(HPD_PORT_TC3) |
3166babde06dSMika Kahola 		      ICP_TC_HPD_ENABLE(HPD_PORT_TC4)),
3167babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
3168babde06dSMika Kahola }
3169babde06dSMika Kahola 
3170babde06dSMika Kahola static void mtp_hpd_invert(struct drm_i915_private *i915)
3171babde06dSMika Kahola {
3172babde06dSMika Kahola 	u32 val = (INVERT_DDIA_HPD |
3173babde06dSMika Kahola 		   INVERT_DDIB_HPD |
3174babde06dSMika Kahola 		   INVERT_DDIC_HPD |
3175babde06dSMika Kahola 		   INVERT_TC1_HPD |
3176babde06dSMika Kahola 		   INVERT_TC2_HPD |
3177babde06dSMika Kahola 		   INVERT_TC3_HPD |
3178babde06dSMika Kahola 		   INVERT_TC4_HPD |
3179babde06dSMika Kahola 		   INVERT_DDID_HPD_MTP |
3180babde06dSMika Kahola 		   INVERT_DDIE_HPD);
3181babde06dSMika Kahola 	intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
3182babde06dSMika Kahola }
3183babde06dSMika Kahola 
3184babde06dSMika Kahola static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
3185babde06dSMika Kahola {
3186babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3187babde06dSMika Kahola 
3188babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
3189babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
3190babde06dSMika Kahola 
3191babde06dSMika Kahola 	intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3192babde06dSMika Kahola 
3193babde06dSMika Kahola 	mtp_hpd_invert(i915);
3194babde06dSMika Kahola 	ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
3195babde06dSMika Kahola 
3196babde06dSMika Kahola 	mtp_ddi_hpd_detection_setup(i915);
3197babde06dSMika Kahola 	mtp_tc_hpd_detection_setup(i915);
3198babde06dSMika Kahola }
3199babde06dSMika Kahola 
3200babde06dSMika Kahola static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
3201babde06dSMika Kahola {
3202babde06dSMika Kahola 	struct intel_encoder *encoder;
3203babde06dSMika Kahola 	enum hpd_pin pin;
3204babde06dSMika Kahola 	u32 available_pins = 0;
3205babde06dSMika Kahola 
3206babde06dSMika Kahola 	BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
3207babde06dSMika Kahola 
3208babde06dSMika Kahola 	for_each_intel_encoder(&i915->drm, encoder)
3209babde06dSMika Kahola 		available_pins |= BIT(encoder->hpd_pin);
3210babde06dSMika Kahola 
3211babde06dSMika Kahola 	for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
3212babde06dSMika Kahola 		u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
3213babde06dSMika Kahola 			   XELPDP_DP_ALT_HOTPLUG_ENABLE;
3214babde06dSMika Kahola 
3215babde06dSMika Kahola 		intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(pin),
3216babde06dSMika Kahola 			     mask,
3217babde06dSMika Kahola 			     available_pins & BIT(pin) ?  mask : 0);
3218babde06dSMika Kahola 	}
3219babde06dSMika Kahola }
3220babde06dSMika Kahola 
3221babde06dSMika Kahola static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
3222babde06dSMika Kahola {
3223babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3224babde06dSMika Kahola 
3225babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.hpd);
3226babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.hpd);
3227babde06dSMika Kahola 
3228babde06dSMika Kahola 	intel_de_rmw(i915, PICAINTERRUPT_IMR, hotplug_irqs,
3229babde06dSMika Kahola 		     ~enabled_irqs & hotplug_irqs);
3230babde06dSMika Kahola 	intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR);
3231babde06dSMika Kahola 
3232babde06dSMika Kahola 	xelpdp_pica_hpd_detection_setup(i915);
3233babde06dSMika Kahola 
3234babde06dSMika Kahola 	if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
3235babde06dSMika Kahola 		mtp_hpd_irq_setup(i915);
3236babde06dSMika Kahola }
3237babde06dSMika Kahola 
3238dfefe7bcSVille Syrjälä static u32 spt_hotplug_enables(struct intel_encoder *encoder)
32392ea63927SVille Syrjälä {
3240dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
32412ea63927SVille Syrjälä 	case HPD_PORT_A:
32422ea63927SVille Syrjälä 		return PORTA_HOTPLUG_ENABLE;
32432ea63927SVille Syrjälä 	case HPD_PORT_B:
32442ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE;
32452ea63927SVille Syrjälä 	case HPD_PORT_C:
32462ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE;
32472ea63927SVille Syrjälä 	case HPD_PORT_D:
32482ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE;
32492ea63927SVille Syrjälä 	default:
32502ea63927SVille Syrjälä 		return 0;
32512ea63927SVille Syrjälä 	}
32522ea63927SVille Syrjälä }
32532ea63927SVille Syrjälä 
3254dfefe7bcSVille Syrjälä static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
32552ea63927SVille Syrjälä {
3256dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
32572ea63927SVille Syrjälä 	case HPD_PORT_E:
32582ea63927SVille Syrjälä 		return PORTE_HOTPLUG_ENABLE;
32592ea63927SVille Syrjälä 	default:
32602ea63927SVille Syrjälä 		return 0;
32612ea63927SVille Syrjälä 	}
3262121e758eSDhinakaran Pandiyan }
3263121e758eSDhinakaran Pandiyan 
32642a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
32652a57d9ccSImre Deak {
32663b92e263SRodrigo Vivi 	/* Display WA #1179 WaHardHangonHotPlug: cnp */
32673b92e263SRodrigo Vivi 	if (HAS_PCH_CNP(dev_priv)) {
32688cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
32698cee664dSAndrzej Hajda 				 CHASSIS_CLK_REQ_DURATION(0xf));
32703b92e263SRodrigo Vivi 	}
32712a57d9ccSImre Deak 
32722a57d9ccSImre Deak 	/* Enable digital hotplug on the PCH */
32738cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
32748cee664dSAndrzej Hajda 			 PORTA_HOTPLUG_ENABLE |
32752a57d9ccSImre Deak 			 PORTB_HOTPLUG_ENABLE |
32762a57d9ccSImre Deak 			 PORTC_HOTPLUG_ENABLE |
32778cee664dSAndrzej Hajda 			 PORTD_HOTPLUG_ENABLE,
32788cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
32792a57d9ccSImre Deak 
32808cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, PORTE_HOTPLUG_ENABLE,
32818cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
32822a57d9ccSImre Deak }
32832a57d9ccSImre Deak 
328491d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
32856dbf30ceSVille Syrjälä {
32862a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
32876dbf30ceSVille Syrjälä 
3288f49108d0SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
32892939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3290f49108d0SMatt Roper 
32915a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
32925a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
32936dbf30ceSVille Syrjälä 
32946dbf30ceSVille Syrjälä 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
32956dbf30ceSVille Syrjälä 
32962a57d9ccSImre Deak 	spt_hpd_detection_setup(dev_priv);
329726951cafSXiong Zhang }
32987fe0b973SKeith Packard 
3299dfefe7bcSVille Syrjälä static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
33002ea63927SVille Syrjälä {
3301dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
33022ea63927SVille Syrjälä 	case HPD_PORT_A:
33032ea63927SVille Syrjälä 		return DIGITAL_PORTA_HOTPLUG_ENABLE |
33042ea63927SVille Syrjälä 			DIGITAL_PORTA_PULSE_DURATION_2ms;
33052ea63927SVille Syrjälä 	default:
33062ea63927SVille Syrjälä 		return 0;
33072ea63927SVille Syrjälä 	}
33082ea63927SVille Syrjälä }
33092ea63927SVille Syrjälä 
33101a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
33111a56b1a2SImre Deak {
33121a56b1a2SImre Deak 	/*
33131a56b1a2SImre Deak 	 * Enable digital hotplug on the CPU, and configure the DP short pulse
33141a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec)
33151a56b1a2SImre Deak 	 * The pulse duration bits are reserved on HSW+.
33161a56b1a2SImre Deak 	 */
33178cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
33188cee664dSAndrzej Hajda 			 DIGITAL_PORTA_HOTPLUG_ENABLE | DIGITAL_PORTA_PULSE_DURATION_MASK,
33198cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
33201a56b1a2SImre Deak }
33211a56b1a2SImre Deak 
332291d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
3323e4ce95aaSVille Syrjälä {
33241a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
3325e4ce95aaSVille Syrjälä 
33265a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
33275a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
33283a3b3c7dSVille Syrjälä 
3329373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 8)
33303a3b3c7dSVille Syrjälä 		bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
33316d3144ebSVille Syrjälä 	else
33323a3b3c7dSVille Syrjälä 		ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
3333e4ce95aaSVille Syrjälä 
33341a56b1a2SImre Deak 	ilk_hpd_detection_setup(dev_priv);
3335e4ce95aaSVille Syrjälä 
333691d14251STvrtko Ursulin 	ibx_hpd_irq_setup(dev_priv);
3337e4ce95aaSVille Syrjälä }
3338e4ce95aaSVille Syrjälä 
3339dfefe7bcSVille Syrjälä static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
33402ea63927SVille Syrjälä {
33412ea63927SVille Syrjälä 	u32 hotplug;
33422ea63927SVille Syrjälä 
3343dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
33442ea63927SVille Syrjälä 	case HPD_PORT_A:
33452ea63927SVille Syrjälä 		hotplug = PORTA_HOTPLUG_ENABLE;
33469151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
33472ea63927SVille Syrjälä 			hotplug |= BXT_DDIA_HPD_INVERT;
33482ea63927SVille Syrjälä 		return hotplug;
33492ea63927SVille Syrjälä 	case HPD_PORT_B:
33502ea63927SVille Syrjälä 		hotplug = PORTB_HOTPLUG_ENABLE;
33519151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
33522ea63927SVille Syrjälä 			hotplug |= BXT_DDIB_HPD_INVERT;
33532ea63927SVille Syrjälä 		return hotplug;
33542ea63927SVille Syrjälä 	case HPD_PORT_C:
33552ea63927SVille Syrjälä 		hotplug = PORTC_HOTPLUG_ENABLE;
33569151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
33572ea63927SVille Syrjälä 			hotplug |= BXT_DDIC_HPD_INVERT;
33582ea63927SVille Syrjälä 		return hotplug;
33592ea63927SVille Syrjälä 	default:
33602ea63927SVille Syrjälä 		return 0;
33612ea63927SVille Syrjälä 	}
33622ea63927SVille Syrjälä }
33632ea63927SVille Syrjälä 
33642ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
3365e0a20ad7SShashank Sharma {
33668cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
33678cee664dSAndrzej Hajda 			 PORTA_HOTPLUG_ENABLE |
33682a57d9ccSImre Deak 			 PORTB_HOTPLUG_ENABLE |
33692ea63927SVille Syrjälä 			 PORTC_HOTPLUG_ENABLE |
33708cee664dSAndrzej Hajda 			 BXT_DDI_HPD_INVERT_MASK,
33718cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
3372e0a20ad7SShashank Sharma }
3373e0a20ad7SShashank Sharma 
33742a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
33752a57d9ccSImre Deak {
33762a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
33772a57d9ccSImre Deak 
33785a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
33795a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
33802a57d9ccSImre Deak 
33812a57d9ccSImre Deak 	bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
33822a57d9ccSImre Deak 
33832ea63927SVille Syrjälä 	bxt_hpd_detection_setup(dev_priv);
33842a57d9ccSImre Deak }
33852a57d9ccSImre Deak 
3386a0a6d8cbSVille Syrjälä /*
3387a0a6d8cbSVille Syrjälä  * SDEIER is also touched by the interrupt handler to work around missed PCH
3388a0a6d8cbSVille Syrjälä  * interrupts. Hence we can't update it after the interrupt handler is enabled -
3389a0a6d8cbSVille Syrjälä  * instead we unconditionally enable all PCH interrupt sources here, but then
3390a0a6d8cbSVille Syrjälä  * only unmask them as needed with SDEIMR.
3391a0a6d8cbSVille Syrjälä  *
3392a0a6d8cbSVille Syrjälä  * Note that we currently do this after installing the interrupt handler,
3393a0a6d8cbSVille Syrjälä  * but before we enable the master interrupt. That should be sufficient
3394a0a6d8cbSVille Syrjälä  * to avoid races with the irq handler, assuming we have MSI. Shared legacy
3395a0a6d8cbSVille Syrjälä  * interrupts could still race.
3396a0a6d8cbSVille Syrjälä  */
3397b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
3398d46da437SPaulo Zanoni {
3399a0a6d8cbSVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
340082a28bcfSDaniel Vetter 	u32 mask;
3401d46da437SPaulo Zanoni 
34026e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
3403692a04cfSDaniel Vetter 		return;
3404692a04cfSDaniel Vetter 
34056e266956STvrtko Ursulin 	if (HAS_PCH_IBX(dev_priv))
34065c673b60SDaniel Vetter 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
34074ebc6509SDhinakaran Pandiyan 	else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
34085c673b60SDaniel Vetter 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
34094ebc6509SDhinakaran Pandiyan 	else
34104ebc6509SDhinakaran Pandiyan 		mask = SDE_GMBUS_CPT;
34118664281bSPaulo Zanoni 
3412a0a6d8cbSVille Syrjälä 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
3413d46da437SPaulo Zanoni }
3414d46da437SPaulo Zanoni 
34159eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
3416036a4a7dSZhenyu Wang {
3417b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
34188e76f8dcSPaulo Zanoni 	u32 display_mask, extra_mask;
34198e76f8dcSPaulo Zanoni 
3420651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) >= 7) {
34218e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
3422842ebf7aSVille Syrjälä 				DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB);
34238e76f8dcSPaulo Zanoni 		extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
342423bb4cb5SVille Syrjälä 			      DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
34252a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_C) |
34262a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_B) |
34272a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_A) |
342823bb4cb5SVille Syrjälä 			      DE_DP_A_HOTPLUG_IVB);
34298e76f8dcSPaulo Zanoni 	} else {
34308e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
3431842ebf7aSVille Syrjälä 				DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE |
3432842ebf7aSVille Syrjälä 				DE_PIPEA_CRC_DONE | DE_POISON);
3433c6073d4cSVille Syrjälä 		extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK |
3434e4ce95aaSVille Syrjälä 			      DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
34354bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_A) |
34364bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_B) |
3437e4ce95aaSVille Syrjälä 			      DE_DP_A_HOTPLUG);
34388e76f8dcSPaulo Zanoni 	}
3439036a4a7dSZhenyu Wang 
3440fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
3441b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
3442fc340442SDaniel Vetter 		display_mask |= DE_EDP_PSR_INT_HSW;
3443fc340442SDaniel Vetter 	}
3444fc340442SDaniel Vetter 
3445c6073d4cSVille Syrjälä 	if (IS_IRONLAKE_M(dev_priv))
3446c6073d4cSVille Syrjälä 		extra_mask |= DE_PCU_EVENT;
3447c6073d4cSVille Syrjälä 
34481ec14ad3SChris Wilson 	dev_priv->irq_mask = ~display_mask;
3449036a4a7dSZhenyu Wang 
3450a0a6d8cbSVille Syrjälä 	ibx_irq_postinstall(dev_priv);
3451622364b6SPaulo Zanoni 
34522cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
3453a9922912SVille Syrjälä 
3454b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask,
3455b16b2a2fSPaulo Zanoni 		      display_mask | extra_mask);
3456036a4a7dSZhenyu Wang }
3457036a4a7dSZhenyu Wang 
3458f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
3459f8b79e58SImre Deak {
346067520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3461f8b79e58SImre Deak 
3462f8b79e58SImre Deak 	if (dev_priv->display_irqs_enabled)
3463f8b79e58SImre Deak 		return;
3464f8b79e58SImre Deak 
3465f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = true;
3466f8b79e58SImre Deak 
3467d6c69803SVille Syrjälä 	if (intel_irqs_enabled(dev_priv)) {
3468d6c69803SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3469ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3470f8b79e58SImre Deak 	}
3471d6c69803SVille Syrjälä }
3472f8b79e58SImre Deak 
3473f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
3474f8b79e58SImre Deak {
347567520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3476f8b79e58SImre Deak 
3477f8b79e58SImre Deak 	if (!dev_priv->display_irqs_enabled)
3478f8b79e58SImre Deak 		return;
3479f8b79e58SImre Deak 
3480f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = false;
3481f8b79e58SImre Deak 
3482950eabafSImre Deak 	if (intel_irqs_enabled(dev_priv))
3483ad22d106SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3484f8b79e58SImre Deak }
3485f8b79e58SImre Deak 
34860e6c9a9eSVille Syrjälä 
3487b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
34880e6c9a9eSVille Syrjälä {
34892cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
34907e231dbeSJesse Barnes 
3491ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
34929918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3493ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3494ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3495ad22d106SVille Syrjälä 
34962939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
34972939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
349820afbda2SDaniel Vetter }
349920afbda2SDaniel Vetter 
3500abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
3501abd58f01SBen Widawsky {
3502b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3503b16b2a2fSPaulo Zanoni 
3504869129eeSMatt Roper 	u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
3505869129eeSMatt Roper 		GEN8_PIPE_CDCLK_CRC_DONE;
3506a9c287c9SJani Nikula 	u32 de_pipe_enables;
3507054318c7SImre Deak 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
35083a3b3c7dSVille Syrjälä 	u32 de_port_enables;
3509df0d28c1SDhinakaran Pandiyan 	u32 de_misc_masked = GEN8_DE_EDP_PSR;
3510562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
3511562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
35123a3b3c7dSVille Syrjälä 	enum pipe pipe;
3513770de83dSDamien Lespiau 
3514a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3515a844cfbeSJosé Roberto de Souza 		return;
3516a844cfbeSJosé Roberto de Souza 
3517373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) <= 10)
3518df0d28c1SDhinakaran Pandiyan 		de_misc_masked |= GEN8_DE_MISC_GSE;
3519df0d28c1SDhinakaran Pandiyan 
352070bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
35213a3b3c7dSVille Syrjälä 		de_port_masked |= BXT_DE_PORT_GMBUS;
3522a324fcacSRodrigo Vivi 
3523373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
35249c9e97c4SVandita Kulkarni 		enum port port;
35259c9e97c4SVandita Kulkarni 
35269c9e97c4SVandita Kulkarni 		if (intel_bios_is_dsi_present(dev_priv, &port))
35279c9e97c4SVandita Kulkarni 			de_port_masked |= DSI0_TE | DSI1_TE;
35289c9e97c4SVandita Kulkarni 	}
35299c9e97c4SVandita Kulkarni 
3530cda195f1SVille Syrjälä 	de_pipe_enables = de_pipe_masked |
35318bcc0840SMatt Roper 		GEN8_PIPE_VBLANK |
35328bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
3533cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
35341288f9b0SKarthik B S 
35353a3b3c7dSVille Syrjälä 	de_port_enables = de_port_masked;
353670bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3537a52bb15bSVille Syrjälä 		de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
3538a52bb15bSVille Syrjälä 	else if (IS_BROADWELL(dev_priv))
3539e5abaab3SVille Syrjälä 		de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
35403a3b3c7dSVille Syrjälä 
3541373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
35428241cfbeSJosé Roberto de Souza 		enum transcoder trans;
35438241cfbeSJosé Roberto de Souza 
3544562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
35458241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
35468241cfbeSJosé Roberto de Souza 
35478241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
35488241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
35498241cfbeSJosé Roberto de Souza 				continue;
35508241cfbeSJosé Roberto de Souza 
35518241cfbeSJosé Roberto de Souza 			gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
35528241cfbeSJosé Roberto de Souza 		}
35538241cfbeSJosé Roberto de Souza 	} else {
3554b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
35558241cfbeSJosé Roberto de Souza 	}
3556e04f7eceSVille Syrjälä 
35570a195c02SMika Kahola 	for_each_pipe(dev_priv, pipe) {
35580a195c02SMika Kahola 		dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
3559abd58f01SBen Widawsky 
3560f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
3561813bde43SPaulo Zanoni 				POWER_DOMAIN_PIPE(pipe)))
3562b16b2a2fSPaulo Zanoni 			GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
3563813bde43SPaulo Zanoni 					  dev_priv->de_irq_mask[pipe],
356435079899SPaulo Zanoni 					  de_pipe_enables);
35650a195c02SMika Kahola 	}
3566abd58f01SBen Widawsky 
3567b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
3568b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
35692a57d9ccSImre Deak 
3570babde06dSMika Kahola 	if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
3571121e758eSDhinakaran Pandiyan 		u32 de_hpd_masked = 0;
3572b796b971SDhinakaran Pandiyan 		u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
3573b796b971SDhinakaran Pandiyan 				     GEN11_DE_TBT_HOTPLUG_MASK;
3574121e758eSDhinakaran Pandiyan 
3575b16b2a2fSPaulo Zanoni 		GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
3576b16b2a2fSPaulo Zanoni 			      de_hpd_enables);
3577abd58f01SBen Widawsky 	}
3578121e758eSDhinakaran Pandiyan }
3579abd58f01SBen Widawsky 
3580babde06dSMika Kahola static void mtp_irq_postinstall(struct drm_i915_private *i915)
3581babde06dSMika Kahola {
3582babde06dSMika Kahola 	struct intel_uncore *uncore = &i915->uncore;
3583babde06dSMika Kahola 	u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
3584babde06dSMika Kahola 	u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
3585babde06dSMika Kahola 	u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
3586babde06dSMika Kahola 			     XELPDP_TBT_HOTPLUG_MASK;
3587babde06dSMika Kahola 
3588babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
3589babde06dSMika Kahola 		      de_hpd_enables);
3590babde06dSMika Kahola 
3591babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
3592babde06dSMika Kahola }
3593babde06dSMika Kahola 
359459b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
359559b7cb44STejas Upadhyay {
359659b7cb44STejas Upadhyay 	struct intel_uncore *uncore = &dev_priv->uncore;
359759b7cb44STejas Upadhyay 	u32 mask = SDE_GMBUS_ICP;
359859b7cb44STejas Upadhyay 
359959b7cb44STejas Upadhyay 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
360059b7cb44STejas Upadhyay }
360159b7cb44STejas Upadhyay 
3602b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
3603abd58f01SBen Widawsky {
360459b7cb44STejas Upadhyay 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
360559b7cb44STejas Upadhyay 		icp_irq_postinstall(dev_priv);
360659b7cb44STejas Upadhyay 	else if (HAS_PCH_SPLIT(dev_priv))
3607a0a6d8cbSVille Syrjälä 		ibx_irq_postinstall(dev_priv);
3608622364b6SPaulo Zanoni 
36092cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
3610abd58f01SBen Widawsky 	gen8_de_irq_postinstall(dev_priv);
3611abd58f01SBen Widawsky 
361225286aacSDaniele Ceraolo Spurio 	gen8_master_intr_enable(dev_priv->uncore.regs);
3613abd58f01SBen Widawsky }
3614abd58f01SBen Widawsky 
3615a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
3616a844cfbeSJosé Roberto de Souza {
3617a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3618a844cfbeSJosé Roberto de Souza 		return;
3619a844cfbeSJosé Roberto de Souza 
3620a844cfbeSJosé Roberto de Souza 	gen8_de_irq_postinstall(dev_priv);
3621a844cfbeSJosé Roberto de Souza 
3622a844cfbeSJosé Roberto de Souza 	intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
3623a844cfbeSJosé Roberto de Souza 			   GEN11_DISPLAY_IRQ_ENABLE);
3624a844cfbeSJosé Roberto de Souza }
362531604222SAnusha Srivatsa 
3626b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
362751951ae7SMika Kuoppala {
36282cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3629fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
3630df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
363151951ae7SMika Kuoppala 
363229b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
3633b318b824SVille Syrjälä 		icp_irq_postinstall(dev_priv);
363431604222SAnusha Srivatsa 
3635fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
3636a844cfbeSJosé Roberto de Souza 	gen11_de_irq_postinstall(dev_priv);
363751951ae7SMika Kuoppala 
3638b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
3639df0d28c1SDhinakaran Pandiyan 
36409b77011eSTvrtko Ursulin 	gen11_master_intr_enable(uncore->regs);
36412939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
364251951ae7SMika Kuoppala }
364322e26af7SPaulo Zanoni 
364422e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
364522e26af7SPaulo Zanoni {
36462cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3647fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
364822e26af7SPaulo Zanoni 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
364922e26af7SPaulo Zanoni 
3650fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
365122e26af7SPaulo Zanoni 
365222e26af7SPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
365322e26af7SPaulo Zanoni 
365422e26af7SPaulo Zanoni 	if (HAS_DISPLAY(dev_priv)) {
3655babde06dSMika Kahola 		if (DISPLAY_VER(dev_priv) >= 14)
3656babde06dSMika Kahola 			mtp_irq_postinstall(dev_priv);
3657babde06dSMika Kahola 		else
365822e26af7SPaulo Zanoni 			icp_irq_postinstall(dev_priv);
3659babde06dSMika Kahola 
366022e26af7SPaulo Zanoni 		gen8_de_irq_postinstall(dev_priv);
366122e26af7SPaulo Zanoni 		intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
366222e26af7SPaulo Zanoni 				   GEN11_DISPLAY_IRQ_ENABLE);
366322e26af7SPaulo Zanoni 	}
366422e26af7SPaulo Zanoni 
3665fd4d7904SPaulo Zanoni 	dg1_master_intr_enable(uncore->regs);
3666fd4d7904SPaulo Zanoni 	intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR);
366797b492f5SLucas De Marchi }
366851951ae7SMika Kuoppala 
3669b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
367043f328d7SVille Syrjälä {
36712cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
367243f328d7SVille Syrjälä 
3673ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
36749918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3675ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3676ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3677ad22d106SVille Syrjälä 
36782939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
36792939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
368043f328d7SVille Syrjälä }
368143f328d7SVille Syrjälä 
3682b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv)
3683c2798b19SChris Wilson {
3684b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3685c2798b19SChris Wilson 
368644d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
368744d9241eSVille Syrjälä 
3688ad7632ffSJani Nikula 	gen2_irq_reset(uncore);
3689e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
3690c2798b19SChris Wilson }
3691c2798b19SChris Wilson 
36923687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915)
36933687ce75SVille Syrjälä {
3694e7e12f6eSVille Syrjälä 	/*
3695e7e12f6eSVille Syrjälä 	 * On gen2/3 FBC generates (seemingly spurious)
3696e7e12f6eSVille Syrjälä 	 * display INVALID_GTT/INVALID_GTT_PTE table errors.
3697e7e12f6eSVille Syrjälä 	 *
3698e7e12f6eSVille Syrjälä 	 * Also gen3 bspec has this to say:
3699e7e12f6eSVille Syrjälä 	 * "DISPA_INVALID_GTT_PTE
3700e7e12f6eSVille Syrjälä 	 "  [DevNapa] : Reserved. This bit does not reflect the page
3701e7e12f6eSVille Syrjälä 	 "              table error for the display plane A."
3702e7e12f6eSVille Syrjälä 	 *
3703e7e12f6eSVille Syrjälä 	 * Unfortunately we can't mask off individual PGTBL_ER bits,
3704e7e12f6eSVille Syrjälä 	 * so we just have to mask off all page table errors via EMR.
3705e7e12f6eSVille Syrjälä 	 */
3706e7e12f6eSVille Syrjälä 	if (HAS_FBC(i915))
3707e7e12f6eSVille Syrjälä 		return ~I915_ERROR_MEMORY_REFRESH;
3708e7e12f6eSVille Syrjälä 	else
37093687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
37103687ce75SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
37113687ce75SVille Syrjälä }
37123687ce75SVille Syrjälä 
3713b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv)
3714c2798b19SChris Wilson {
3715b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3716e9e9848aSVille Syrjälä 	u16 enable_mask;
3717c2798b19SChris Wilson 
37183687ce75SVille Syrjälä 	intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv));
3719c2798b19SChris Wilson 
3720c2798b19SChris Wilson 	/* Unmask the interrupts that we always want on. */
3721c2798b19SChris Wilson 	dev_priv->irq_mask =
3722c2798b19SChris Wilson 		~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
372316659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
372416659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
3725c2798b19SChris Wilson 
3726e9e9848aSVille Syrjälä 	enable_mask =
3727c2798b19SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
3728c2798b19SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
372916659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
3730e9e9848aSVille Syrjälä 		I915_USER_INTERRUPT;
3731e9e9848aSVille Syrjälä 
3732ad7632ffSJani Nikula 	gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask);
3733c2798b19SChris Wilson 
3734379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
3735379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
3736d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
3737755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
3738755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
3739d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
3740c2798b19SChris Wilson }
3741c2798b19SChris Wilson 
37424f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915,
374378c357ddSVille Syrjälä 			       u16 *eir, u16 *eir_stuck)
374478c357ddSVille Syrjälä {
37454f5fd91fSTvrtko Ursulin 	struct intel_uncore *uncore = &i915->uncore;
374678c357ddSVille Syrjälä 	u16 emr;
374778c357ddSVille Syrjälä 
37484f5fd91fSTvrtko Ursulin 	*eir = intel_uncore_read16(uncore, EIR);
37494f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EIR, *eir);
375078c357ddSVille Syrjälä 
37514f5fd91fSTvrtko Ursulin 	*eir_stuck = intel_uncore_read16(uncore, EIR);
375278c357ddSVille Syrjälä 	if (*eir_stuck == 0)
375378c357ddSVille Syrjälä 		return;
375478c357ddSVille Syrjälä 
375578c357ddSVille Syrjälä 	/*
375678c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
375778c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
375878c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
375978c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
376078c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
376178c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
376278c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
376378c357ddSVille Syrjälä 	 * remains set.
376478c357ddSVille Syrjälä 	 */
37654f5fd91fSTvrtko Ursulin 	emr = intel_uncore_read16(uncore, EMR);
37664f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, 0xffff);
37674f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, emr | *eir_stuck);
376878c357ddSVille Syrjälä }
376978c357ddSVille Syrjälä 
377078c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv,
377178c357ddSVille Syrjälä 				   u16 eir, u16 eir_stuck)
377278c357ddSVille Syrjälä {
3773a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir);
377478c357ddSVille Syrjälä 
377578c357ddSVille Syrjälä 	if (eir_stuck)
377600376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n",
377700376ccfSWambui Karuga 			eir_stuck);
3778d1e89592SVille Syrjälä 
3779d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
3780d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
378178c357ddSVille Syrjälä }
378278c357ddSVille Syrjälä 
378378c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
378478c357ddSVille Syrjälä 			       u32 *eir, u32 *eir_stuck)
378578c357ddSVille Syrjälä {
378678c357ddSVille Syrjälä 	u32 emr;
378778c357ddSVille Syrjälä 
3788839259b8SVille Syrjälä 	*eir = intel_uncore_read(&dev_priv->uncore, EIR);
3789839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EIR, *eir);
379078c357ddSVille Syrjälä 
37912939eb06SJani Nikula 	*eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR);
379278c357ddSVille Syrjälä 	if (*eir_stuck == 0)
379378c357ddSVille Syrjälä 		return;
379478c357ddSVille Syrjälä 
379578c357ddSVille Syrjälä 	/*
379678c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
379778c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
379878c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
379978c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
380078c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
380178c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
380278c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
380378c357ddSVille Syrjälä 	 * remains set.
380478c357ddSVille Syrjälä 	 */
3805839259b8SVille Syrjälä 	emr = intel_uncore_read(&dev_priv->uncore, EMR);
3806839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff);
38072939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck);
380878c357ddSVille Syrjälä }
380978c357ddSVille Syrjälä 
381078c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv,
381178c357ddSVille Syrjälä 				   u32 eir, u32 eir_stuck)
381278c357ddSVille Syrjälä {
3813a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir);
381478c357ddSVille Syrjälä 
381578c357ddSVille Syrjälä 	if (eir_stuck)
381600376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n",
381700376ccfSWambui Karuga 			eir_stuck);
3818d1e89592SVille Syrjälä 
3819d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
3820d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
382178c357ddSVille Syrjälä }
382278c357ddSVille Syrjälä 
3823ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg)
3824c2798b19SChris Wilson {
3825b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
3826af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
3827c2798b19SChris Wilson 
38282dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
38292dd2a883SImre Deak 		return IRQ_NONE;
38302dd2a883SImre Deak 
38311f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
38329102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
38331f814dacSImre Deak 
3834af722d28SVille Syrjälä 	do {
3835af722d28SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
383678c357ddSVille Syrjälä 		u16 eir = 0, eir_stuck = 0;
3837af722d28SVille Syrjälä 		u16 iir;
3838af722d28SVille Syrjälä 
38394f5fd91fSTvrtko Ursulin 		iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR);
3840c2798b19SChris Wilson 		if (iir == 0)
3841af722d28SVille Syrjälä 			break;
3842c2798b19SChris Wilson 
3843af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
3844c2798b19SChris Wilson 
3845eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
3846eb64343cSVille Syrjälä 		 * signalled in iir */
3847eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
3848c2798b19SChris Wilson 
384978c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
385078c357ddSVille Syrjälä 			i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
385178c357ddSVille Syrjälä 
38524f5fd91fSTvrtko Ursulin 		intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir);
3853c2798b19SChris Wilson 
3854c2798b19SChris Wilson 		if (iir & I915_USER_INTERRUPT)
38552cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
3856c2798b19SChris Wilson 
385778c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
385878c357ddSVille Syrjälä 			i8xx_error_irq_handler(dev_priv, eir, eir_stuck);
3859af722d28SVille Syrjälä 
3860eb64343cSVille Syrjälä 		i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats);
3861af722d28SVille Syrjälä 	} while (0);
3862c2798b19SChris Wilson 
38639c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
38649c6508b9SThomas Gleixner 
38659102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
38661f814dacSImre Deak 
38671f814dacSImre Deak 	return ret;
3868c2798b19SChris Wilson }
3869c2798b19SChris Wilson 
3870b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv)
3871a266c7d5SChris Wilson {
3872b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3873a266c7d5SChris Wilson 
387456b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
38750706f17cSEgbert Eich 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
38768cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0);
3877a266c7d5SChris Wilson 	}
3878a266c7d5SChris Wilson 
387944d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
388044d9241eSVille Syrjälä 
3881b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
3882e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
3883a266c7d5SChris Wilson }
3884a266c7d5SChris Wilson 
3885b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
3886a266c7d5SChris Wilson {
3887b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
388838bde180SChris Wilson 	u32 enable_mask;
3889a266c7d5SChris Wilson 
38903687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv));
389138bde180SChris Wilson 
389238bde180SChris Wilson 	/* Unmask the interrupts that we always want on. */
389338bde180SChris Wilson 	dev_priv->irq_mask =
389438bde180SChris Wilson 		~(I915_ASLE_INTERRUPT |
389538bde180SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
389616659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
389716659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
389838bde180SChris Wilson 
389938bde180SChris Wilson 	enable_mask =
390038bde180SChris Wilson 		I915_ASLE_INTERRUPT |
390138bde180SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
390238bde180SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
390316659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
390438bde180SChris Wilson 		I915_USER_INTERRUPT;
390538bde180SChris Wilson 
390656b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
3907a266c7d5SChris Wilson 		/* Enable in IER... */
3908a266c7d5SChris Wilson 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
3909a266c7d5SChris Wilson 		/* and unmask in IMR */
3910a266c7d5SChris Wilson 		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
3911a266c7d5SChris Wilson 	}
3912a266c7d5SChris Wilson 
3913b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
3914a266c7d5SChris Wilson 
3915379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
3916379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
3917d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
3918755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
3919755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
3920d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
3921379ef82dSDaniel Vetter 
3922c30bb1fdSVille Syrjälä 	i915_enable_asle_pipestat(dev_priv);
392320afbda2SDaniel Vetter }
392420afbda2SDaniel Vetter 
3925ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg)
3926a266c7d5SChris Wilson {
3927b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
3928af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
3929a266c7d5SChris Wilson 
39302dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
39312dd2a883SImre Deak 		return IRQ_NONE;
39322dd2a883SImre Deak 
39331f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
39349102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
39351f814dacSImre Deak 
393638bde180SChris Wilson 	do {
3937eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
393878c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
3939af722d28SVille Syrjälä 		u32 hotplug_status = 0;
3940af722d28SVille Syrjälä 		u32 iir;
3941a266c7d5SChris Wilson 
39422939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
3943af722d28SVille Syrjälä 		if (iir == 0)
3944af722d28SVille Syrjälä 			break;
3945af722d28SVille Syrjälä 
3946af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
3947af722d28SVille Syrjälä 
3948af722d28SVille Syrjälä 		if (I915_HAS_HOTPLUG(dev_priv) &&
3949af722d28SVille Syrjälä 		    iir & I915_DISPLAY_PORT_INTERRUPT)
3950af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
3951a266c7d5SChris Wilson 
3952eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
3953eb64343cSVille Syrjälä 		 * signalled in iir */
3954eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
3955a266c7d5SChris Wilson 
395678c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
395778c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
395878c357ddSVille Syrjälä 
39592939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
3960a266c7d5SChris Wilson 
3961a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
39622cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
3963a266c7d5SChris Wilson 
396478c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
396578c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
3966a266c7d5SChris Wilson 
3967af722d28SVille Syrjälä 		if (hotplug_status)
3968af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
3969af722d28SVille Syrjälä 
3970af722d28SVille Syrjälä 		i915_pipestat_irq_handler(dev_priv, iir, pipe_stats);
3971af722d28SVille Syrjälä 	} while (0);
3972a266c7d5SChris Wilson 
39739c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
39749c6508b9SThomas Gleixner 
39759102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
39761f814dacSImre Deak 
3977a266c7d5SChris Wilson 	return ret;
3978a266c7d5SChris Wilson }
3979a266c7d5SChris Wilson 
3980b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv)
3981a266c7d5SChris Wilson {
3982b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3983a266c7d5SChris Wilson 
39840706f17cSEgbert Eich 	i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
39858cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
3986a266c7d5SChris Wilson 
398744d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
398844d9241eSVille Syrjälä 
3989b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
3990e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
3991a266c7d5SChris Wilson }
3992a266c7d5SChris Wilson 
39933687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915)
3994a266c7d5SChris Wilson {
3995045cebd2SVille Syrjälä 	/*
3996045cebd2SVille Syrjälä 	 * Enable some error detection, note the instruction error mask
3997045cebd2SVille Syrjälä 	 * bit is reserved, so we leave it masked.
3998e7e12f6eSVille Syrjälä 	 *
3999e7e12f6eSVille Syrjälä 	 * i965 FBC no longer generates spurious GTT errors,
4000e7e12f6eSVille Syrjälä 	 * so we can always enable the page table errors.
4001045cebd2SVille Syrjälä 	 */
40023687ce75SVille Syrjälä 	if (IS_G4X(i915))
40033687ce75SVille Syrjälä 		return ~(GM45_ERROR_PAGE_TABLE |
4004045cebd2SVille Syrjälä 			 GM45_ERROR_MEM_PRIV |
4005045cebd2SVille Syrjälä 			 GM45_ERROR_CP_PRIV |
4006045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
40073687ce75SVille Syrjälä 	else
40083687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
4009045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
4010045cebd2SVille Syrjälä }
40113687ce75SVille Syrjälä 
40123687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
40133687ce75SVille Syrjälä {
40143687ce75SVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
40153687ce75SVille Syrjälä 	u32 enable_mask;
40163687ce75SVille Syrjälä 
40173687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv));
4018045cebd2SVille Syrjälä 
4019a266c7d5SChris Wilson 	/* Unmask the interrupts that we always want on. */
4020c30bb1fdSVille Syrjälä 	dev_priv->irq_mask =
4021c30bb1fdSVille Syrjälä 		~(I915_ASLE_INTERRUPT |
4022adca4730SChris Wilson 		  I915_DISPLAY_PORT_INTERRUPT |
4023bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4024bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
402578c357ddSVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
4026bbba0a97SChris Wilson 
4027c30bb1fdSVille Syrjälä 	enable_mask =
4028c30bb1fdSVille Syrjälä 		I915_ASLE_INTERRUPT |
4029c30bb1fdSVille Syrjälä 		I915_DISPLAY_PORT_INTERRUPT |
4030c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4031c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
403278c357ddSVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
4033c30bb1fdSVille Syrjälä 		I915_USER_INTERRUPT;
4034bbba0a97SChris Wilson 
403591d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4036bbba0a97SChris Wilson 		enable_mask |= I915_BSD_USER_INTERRUPT;
4037a266c7d5SChris Wilson 
4038b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
4039c30bb1fdSVille Syrjälä 
4040b79480baSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
4041b79480baSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
4042d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
4043755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
4044755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
4045755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
4046d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
4047a266c7d5SChris Wilson 
404891d14251STvrtko Ursulin 	i915_enable_asle_pipestat(dev_priv);
404920afbda2SDaniel Vetter }
405020afbda2SDaniel Vetter 
405191d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
405220afbda2SDaniel Vetter {
405320afbda2SDaniel Vetter 	u32 hotplug_en;
405420afbda2SDaniel Vetter 
405567520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
4056b5ea2d56SDaniel Vetter 
4057adca4730SChris Wilson 	/* Note HDMI and DP share hotplug bits */
4058e5868a31SEgbert Eich 	/* enable bits are the same for all generations */
405991d14251STvrtko Ursulin 	hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
4060a266c7d5SChris Wilson 	/* Programming the CRT detection parameters tends
4061a266c7d5SChris Wilson 	   to generate a spurious hotplug event about three
4062a266c7d5SChris Wilson 	   seconds later.  So just do it once.
4063a266c7d5SChris Wilson 	*/
406491d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4065a266c7d5SChris Wilson 		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
4066a266c7d5SChris Wilson 	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
4067a266c7d5SChris Wilson 
4068a266c7d5SChris Wilson 	/* Ignore TV since it's buggy */
40690706f17cSEgbert Eich 	i915_hotplug_interrupt_update_locked(dev_priv,
4070f9e3dc78SJani Nikula 					     HOTPLUG_INT_EN_MASK |
4071f9e3dc78SJani Nikula 					     CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
4072f9e3dc78SJani Nikula 					     CRT_HOTPLUG_ACTIVATION_PERIOD_64,
40730706f17cSEgbert Eich 					     hotplug_en);
4074a266c7d5SChris Wilson }
4075a266c7d5SChris Wilson 
4076ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg)
4077a266c7d5SChris Wilson {
4078b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4079af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4080a266c7d5SChris Wilson 
40812dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
40822dd2a883SImre Deak 		return IRQ_NONE;
40832dd2a883SImre Deak 
40841f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
40859102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
40861f814dacSImre Deak 
4087af722d28SVille Syrjälä 	do {
4088eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
408978c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
4090af722d28SVille Syrjälä 		u32 hotplug_status = 0;
4091af722d28SVille Syrjälä 		u32 iir;
40922c8ba29fSChris Wilson 
40932939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
4094af722d28SVille Syrjälä 		if (iir == 0)
4095af722d28SVille Syrjälä 			break;
4096af722d28SVille Syrjälä 
4097af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4098af722d28SVille Syrjälä 
4099af722d28SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
4100af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
4101a266c7d5SChris Wilson 
4102eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4103eb64343cSVille Syrjälä 		 * signalled in iir */
4104eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4105a266c7d5SChris Wilson 
410678c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
410778c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
410878c357ddSVille Syrjälä 
41092939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
4110a266c7d5SChris Wilson 
4111a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
41122cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0],
41130669a6e1SChris Wilson 					    iir);
4114af722d28SVille Syrjälä 
4115a266c7d5SChris Wilson 		if (iir & I915_BSD_USER_INTERRUPT)
41162cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0],
41170669a6e1SChris Wilson 					    iir >> 25);
4118a266c7d5SChris Wilson 
411978c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
412078c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
4121515ac2bbSDaniel Vetter 
4122af722d28SVille Syrjälä 		if (hotplug_status)
4123af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
4124af722d28SVille Syrjälä 
4125af722d28SVille Syrjälä 		i965_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4126af722d28SVille Syrjälä 	} while (0);
4127a266c7d5SChris Wilson 
41289c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
41299c6508b9SThomas Gleixner 
41309102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
41311f814dacSImre Deak 
4132a266c7d5SChris Wilson 	return ret;
4133a266c7d5SChris Wilson }
4134a266c7d5SChris Wilson 
41357e97596cSJani Nikula struct intel_hotplug_funcs {
41367e97596cSJani Nikula 	void (*hpd_irq_setup)(struct drm_i915_private *i915);
41377e97596cSJani Nikula };
41387e97596cSJani Nikula 
4139cd030c7cSDave Airlie #define HPD_FUNCS(platform)					 \
4140cd030c7cSDave Airlie static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
4141cd030c7cSDave Airlie 	.hpd_irq_setup = platform##_hpd_irq_setup,		 \
4142cd030c7cSDave Airlie }
4143cd030c7cSDave Airlie 
4144cd030c7cSDave Airlie HPD_FUNCS(i915);
4145babde06dSMika Kahola HPD_FUNCS(xelpdp);
4146cd030c7cSDave Airlie HPD_FUNCS(dg1);
4147cd030c7cSDave Airlie HPD_FUNCS(gen11);
4148cd030c7cSDave Airlie HPD_FUNCS(bxt);
4149cd030c7cSDave Airlie HPD_FUNCS(icp);
4150cd030c7cSDave Airlie HPD_FUNCS(spt);
4151cd030c7cSDave Airlie HPD_FUNCS(ilk);
4152cd030c7cSDave Airlie #undef HPD_FUNCS
4153cd030c7cSDave Airlie 
41547e97596cSJani Nikula void intel_hpd_irq_setup(struct drm_i915_private *i915)
41557e97596cSJani Nikula {
41565a04eb5bSJani Nikula 	if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
41575a04eb5bSJani Nikula 		i915->display.funcs.hotplug->hpd_irq_setup(i915);
41587e97596cSJani Nikula }
41597e97596cSJani Nikula 
4160fca52a55SDaniel Vetter /**
4161fca52a55SDaniel Vetter  * intel_irq_init - initializes irq support
4162fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4163fca52a55SDaniel Vetter  *
4164fca52a55SDaniel Vetter  * This function initializes all the irq support including work items, timers
4165fca52a55SDaniel Vetter  * and all the vtables. It does not setup the interrupt itself though.
4166fca52a55SDaniel Vetter  */
4167b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv)
4168f71d4af4SJesse Barnes {
4169cefcff8fSJoonas Lahtinen 	int i;
41708b2e326dSChris Wilson 
417174bb98baSLucas De Marchi 	INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work);
4172cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4173cefcff8fSJoonas Lahtinen 		dev_priv->l3_parity.remap_info[i] = NULL;
41748b2e326dSChris Wilson 
4175633023a4SDaniele Ceraolo Spurio 	/* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */
4176651e7d48SLucas De Marchi 	if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11)
41772cbc876dSMichał Winiarski 		to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16;
417826705e20SSagar Arun Kamble 
41799a450b68SLucas De Marchi 	if (!HAS_DISPLAY(dev_priv))
41809a450b68SLucas De Marchi 		return;
41819a450b68SLucas De Marchi 
418296bd87b7SLucas De Marchi 	intel_hpd_init_pins(dev_priv);
418396bd87b7SLucas De Marchi 
4184dd890d42SJani Nikula 	intel_hpd_init_early(dev_priv);
418596bd87b7SLucas De Marchi 
41863703060dSAndrzej Hajda 	dev_priv->drm.vblank_disable_immediate = true;
418721da2700SVille Syrjälä 
4188262fd485SChris Wilson 	/* Most platforms treat the display irq block as an always-on
4189262fd485SChris Wilson 	 * power domain. vlv/chv can disable it at runtime and need
4190262fd485SChris Wilson 	 * special care to avoid writing any of the display block registers
4191262fd485SChris Wilson 	 * outside of the power domain. We defer setting up the display irqs
4192262fd485SChris Wilson 	 * in this case to the runtime pm.
4193262fd485SChris Wilson 	 */
4194262fd485SChris Wilson 	dev_priv->display_irqs_enabled = true;
4195262fd485SChris Wilson 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
4196262fd485SChris Wilson 		dev_priv->display_irqs_enabled = false;
4197262fd485SChris Wilson 
41982ccf2e03SChris Wilson 	if (HAS_GMCH(dev_priv)) {
41992ccf2e03SChris Wilson 		if (I915_HAS_HOTPLUG(dev_priv))
42005a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &i915_hpd_funcs;
42012ccf2e03SChris Wilson 	} else {
42022f8a6699SMatt Roper 		if (HAS_PCH_DG2(dev_priv))
42035a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
42042f8a6699SMatt Roper 		else if (HAS_PCH_DG1(dev_priv))
42055a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &dg1_hpd_funcs;
4206babde06dSMika Kahola 		else if (DISPLAY_VER(dev_priv) >= 14)
4207babde06dSMika Kahola 			dev_priv->display.funcs.hotplug = &xelpdp_hpd_funcs;
4208373abf1aSMatt Roper 		else if (DISPLAY_VER(dev_priv) >= 11)
42095a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &gen11_hpd_funcs;
421070bfb307SMatt Roper 		else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
42115a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &bxt_hpd_funcs;
4212cec3295bSLyude Paul 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
42135a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
4214c6c30b91SRodrigo Vivi 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
42155a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &spt_hpd_funcs;
42166dbf30ceSVille Syrjälä 		else
42175a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &ilk_hpd_funcs;
4218f71d4af4SJesse Barnes 	}
42192ccf2e03SChris Wilson }
422020afbda2SDaniel Vetter 
4221fca52a55SDaniel Vetter /**
4222cefcff8fSJoonas Lahtinen  * intel_irq_fini - deinitializes IRQ support
4223cefcff8fSJoonas Lahtinen  * @i915: i915 device instance
4224cefcff8fSJoonas Lahtinen  *
4225cefcff8fSJoonas Lahtinen  * This function deinitializes all the IRQ support.
4226cefcff8fSJoonas Lahtinen  */
4227cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915)
4228cefcff8fSJoonas Lahtinen {
4229cefcff8fSJoonas Lahtinen 	int i;
4230cefcff8fSJoonas Lahtinen 
4231cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4232cefcff8fSJoonas Lahtinen 		kfree(i915->l3_parity.remap_info[i]);
4233cefcff8fSJoonas Lahtinen }
4234cefcff8fSJoonas Lahtinen 
4235b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv)
4236b318b824SVille Syrjälä {
4237b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4238b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4239b318b824SVille Syrjälä 			return cherryview_irq_handler;
4240b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4241b318b824SVille Syrjälä 			return valleyview_irq_handler;
4242651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4243b318b824SVille Syrjälä 			return i965_irq_handler;
4244651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4245b318b824SVille Syrjälä 			return i915_irq_handler;
4246b318b824SVille Syrjälä 		else
4247b318b824SVille Syrjälä 			return i8xx_irq_handler;
4248b318b824SVille Syrjälä 	} else {
424922e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
425097b492f5SLucas De Marchi 			return dg1_irq_handler;
425122e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4252b318b824SVille Syrjälä 			return gen11_irq_handler;
4253651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4254b318b824SVille Syrjälä 			return gen8_irq_handler;
4255b318b824SVille Syrjälä 		else
42569eae5e27SLucas De Marchi 			return ilk_irq_handler;
4257b318b824SVille Syrjälä 	}
4258b318b824SVille Syrjälä }
4259b318b824SVille Syrjälä 
4260b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv)
4261b318b824SVille Syrjälä {
4262b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4263b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4264b318b824SVille Syrjälä 			cherryview_irq_reset(dev_priv);
4265b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4266b318b824SVille Syrjälä 			valleyview_irq_reset(dev_priv);
4267651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4268b318b824SVille Syrjälä 			i965_irq_reset(dev_priv);
4269651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4270b318b824SVille Syrjälä 			i915_irq_reset(dev_priv);
4271b318b824SVille Syrjälä 		else
4272b318b824SVille Syrjälä 			i8xx_irq_reset(dev_priv);
4273b318b824SVille Syrjälä 	} else {
427422e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
427522e26af7SPaulo Zanoni 			dg1_irq_reset(dev_priv);
427622e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4277b318b824SVille Syrjälä 			gen11_irq_reset(dev_priv);
4278651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4279b318b824SVille Syrjälä 			gen8_irq_reset(dev_priv);
4280b318b824SVille Syrjälä 		else
42819eae5e27SLucas De Marchi 			ilk_irq_reset(dev_priv);
4282b318b824SVille Syrjälä 	}
4283b318b824SVille Syrjälä }
4284b318b824SVille Syrjälä 
4285b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv)
4286b318b824SVille Syrjälä {
4287b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4288b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4289b318b824SVille Syrjälä 			cherryview_irq_postinstall(dev_priv);
4290b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4291b318b824SVille Syrjälä 			valleyview_irq_postinstall(dev_priv);
4292651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4293b318b824SVille Syrjälä 			i965_irq_postinstall(dev_priv);
4294651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4295b318b824SVille Syrjälä 			i915_irq_postinstall(dev_priv);
4296b318b824SVille Syrjälä 		else
4297b318b824SVille Syrjälä 			i8xx_irq_postinstall(dev_priv);
4298b318b824SVille Syrjälä 	} else {
429922e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
430022e26af7SPaulo Zanoni 			dg1_irq_postinstall(dev_priv);
430122e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4302b318b824SVille Syrjälä 			gen11_irq_postinstall(dev_priv);
4303651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4304b318b824SVille Syrjälä 			gen8_irq_postinstall(dev_priv);
4305b318b824SVille Syrjälä 		else
43069eae5e27SLucas De Marchi 			ilk_irq_postinstall(dev_priv);
4307b318b824SVille Syrjälä 	}
4308b318b824SVille Syrjälä }
4309b318b824SVille Syrjälä 
4310cefcff8fSJoonas Lahtinen /**
4311fca52a55SDaniel Vetter  * intel_irq_install - enables the hardware interrupt
4312fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4313fca52a55SDaniel Vetter  *
4314fca52a55SDaniel Vetter  * This function enables the hardware interrupt handling, but leaves the hotplug
4315fca52a55SDaniel Vetter  * handling still disabled. It is called after intel_irq_init().
4316fca52a55SDaniel Vetter  *
4317fca52a55SDaniel Vetter  * In the driver load and resume code we need working interrupts in a few places
4318fca52a55SDaniel Vetter  * but don't want to deal with the hassle of concurrent probe and hotplug
4319fca52a55SDaniel Vetter  * workers. Hence the split into this two-stage approach.
4320fca52a55SDaniel Vetter  */
43212aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv)
43222aeb7d3aSDaniel Vetter {
43238ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4324b318b824SVille Syrjälä 	int ret;
4325b318b824SVille Syrjälä 
43262aeb7d3aSDaniel Vetter 	/*
43272aeb7d3aSDaniel Vetter 	 * We enable some interrupt sources in our postinstall hooks, so mark
43282aeb7d3aSDaniel Vetter 	 * interrupts as enabled _before_ actually enabling them to avoid
43292aeb7d3aSDaniel Vetter 	 * special cases in our ordering checks.
43302aeb7d3aSDaniel Vetter 	 */
4331ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
43322aeb7d3aSDaniel Vetter 
4333ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = true;
4334b318b824SVille Syrjälä 
4335b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4336b318b824SVille Syrjälä 
4337b318b824SVille Syrjälä 	ret = request_irq(irq, intel_irq_handler(dev_priv),
4338b318b824SVille Syrjälä 			  IRQF_SHARED, DRIVER_NAME, dev_priv);
4339b318b824SVille Syrjälä 	if (ret < 0) {
4340ac1723c1SThomas Zimmermann 		dev_priv->irq_enabled = false;
4341b318b824SVille Syrjälä 		return ret;
4342b318b824SVille Syrjälä 	}
4343b318b824SVille Syrjälä 
4344b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4345b318b824SVille Syrjälä 
4346b318b824SVille Syrjälä 	return ret;
43472aeb7d3aSDaniel Vetter }
43482aeb7d3aSDaniel Vetter 
4349fca52a55SDaniel Vetter /**
4350fca52a55SDaniel Vetter  * intel_irq_uninstall - finilizes all irq handling
4351fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4352fca52a55SDaniel Vetter  *
4353fca52a55SDaniel Vetter  * This stops interrupt and hotplug handling and unregisters and frees all
4354fca52a55SDaniel Vetter  * resources acquired in the init functions.
4355fca52a55SDaniel Vetter  */
43562aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv)
43572aeb7d3aSDaniel Vetter {
43588ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4359b318b824SVille Syrjälä 
4360b318b824SVille Syrjälä 	/*
4361789fa874SJanusz Krzysztofik 	 * FIXME we can get called twice during driver probe
4362789fa874SJanusz Krzysztofik 	 * error handling as well as during driver remove due to
4363*86a1758dSJani Nikula 	 * intel_display_driver_remove() calling us out of sequence.
4364789fa874SJanusz Krzysztofik 	 * Would be nice if it didn't do that...
4365b318b824SVille Syrjälä 	 */
4366ac1723c1SThomas Zimmermann 	if (!dev_priv->irq_enabled)
4367b318b824SVille Syrjälä 		return;
4368b318b824SVille Syrjälä 
4369ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = false;
4370b318b824SVille Syrjälä 
4371b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4372b318b824SVille Syrjälä 
4373b318b824SVille Syrjälä 	free_irq(irq, dev_priv);
4374b318b824SVille Syrjälä 
43752aeb7d3aSDaniel Vetter 	intel_hpd_cancel_work(dev_priv);
4376ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
43772aeb7d3aSDaniel Vetter }
43782aeb7d3aSDaniel Vetter 
4379fca52a55SDaniel Vetter /**
4380fca52a55SDaniel Vetter  * intel_runtime_pm_disable_interrupts - runtime interrupt disabling
4381fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4382fca52a55SDaniel Vetter  *
4383fca52a55SDaniel Vetter  * This function is used to disable interrupts at runtime, both in the runtime
4384fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4385fca52a55SDaniel Vetter  */
4386b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
4387c67a470bSPaulo Zanoni {
4388b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4389ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
4390315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
4391c67a470bSPaulo Zanoni }
4392c67a470bSPaulo Zanoni 
4393fca52a55SDaniel Vetter /**
4394fca52a55SDaniel Vetter  * intel_runtime_pm_enable_interrupts - runtime interrupt enabling
4395fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4396fca52a55SDaniel Vetter  *
4397fca52a55SDaniel Vetter  * This function is used to enable interrupts at runtime, both in the runtime
4398fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4399fca52a55SDaniel Vetter  */
4400b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv)
4401c67a470bSPaulo Zanoni {
4402ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
4403b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4404b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4405c67a470bSPaulo Zanoni }
4406d64575eeSJani Nikula 
4407d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
4408d64575eeSJani Nikula {
4409d64575eeSJani Nikula 	return dev_priv->runtime_pm.irqs_enabled;
4410d64575eeSJani Nikula }
4411d64575eeSJani Nikula 
4412d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915)
4413d64575eeSJani Nikula {
44148ff5446aSThomas Zimmermann 	synchronize_irq(to_pci_dev(i915->drm.dev)->irq);
4415d64575eeSJani Nikula }
4416320ad343SThomas Zimmermann 
4417320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915)
4418320ad343SThomas Zimmermann {
4419320ad343SThomas Zimmermann 	synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq);
4420320ad343SThomas Zimmermann }
4421