xref: /openbmc/linux/drivers/gpu/drm/i915/i915_irq.c (revision 40d06b0fae915ec8bbfbde69ee1cfb2d9a2b7a53)
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ä 
2934*40d06b0fSVille Syrjälä static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin)
2935*40d06b0fSVille Syrjälä {
2936*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
2937*40d06b0fSVille Syrjälä 	case HPD_PORT_A:
2938*40d06b0fSVille Syrjälä 		return PORTA_HOTPLUG_ENABLE;
2939*40d06b0fSVille Syrjälä 	case HPD_PORT_B:
2940*40d06b0fSVille Syrjälä 		return PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_MASK;
2941*40d06b0fSVille Syrjälä 	case HPD_PORT_C:
2942*40d06b0fSVille Syrjälä 		return PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_MASK;
2943*40d06b0fSVille Syrjälä 	case HPD_PORT_D:
2944*40d06b0fSVille Syrjälä 		return PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_MASK;
2945*40d06b0fSVille Syrjälä 	default:
2946*40d06b0fSVille Syrjälä 		return 0;
2947*40d06b0fSVille Syrjälä 	}
2948*40d06b0fSVille Syrjälä }
2949*40d06b0fSVille Syrjälä 
2950dfefe7bcSVille Syrjälä static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
29512ea63927SVille Syrjälä {
2952dfefe7bcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2953dfefe7bcSVille Syrjälä 
2954dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
29552ea63927SVille Syrjälä 	case HPD_PORT_A:
29562ea63927SVille Syrjälä 		/*
29572ea63927SVille Syrjälä 		 * When CPU and PCH are on the same package, port A
29582ea63927SVille Syrjälä 		 * HPD must be enabled in both north and south.
29592ea63927SVille Syrjälä 		 */
29602ea63927SVille Syrjälä 		return HAS_PCH_LPT_LP(i915) ?
29612ea63927SVille Syrjälä 			PORTA_HOTPLUG_ENABLE : 0;
29622ea63927SVille Syrjälä 	case HPD_PORT_B:
29632ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE |
29642ea63927SVille Syrjälä 			PORTB_PULSE_DURATION_2ms;
29652ea63927SVille Syrjälä 	case HPD_PORT_C:
29662ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE |
29672ea63927SVille Syrjälä 			PORTC_PULSE_DURATION_2ms;
29682ea63927SVille Syrjälä 	case HPD_PORT_D:
29692ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE |
29702ea63927SVille Syrjälä 			PORTD_PULSE_DURATION_2ms;
29712ea63927SVille Syrjälä 	default:
29722ea63927SVille Syrjälä 		return 0;
29732ea63927SVille Syrjälä 	}
29742ea63927SVille Syrjälä }
29752ea63927SVille Syrjälä 
29761a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
29771a56b1a2SImre Deak {
29781a56b1a2SImre Deak 	/*
29791a56b1a2SImre Deak 	 * Enable digital hotplug on the PCH, and configure the DP short pulse
29801a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec).
29811a56b1a2SImre Deak 	 * The pulse duration bits are reserved on LPT+.
29821a56b1a2SImre Deak 	 */
29838cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
2984*40d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_A) |
2985*40d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_B) |
2986*40d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_C) |
2987*40d06b0fSVille Syrjälä 			 ibx_hotplug_mask(HPD_PORT_D),
29888cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
29891a56b1a2SImre Deak }
29901a56b1a2SImre Deak 
299191d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
299282a28bcfSDaniel Vetter {
29931a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
299482a28bcfSDaniel Vetter 
29955a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
29965a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
299782a28bcfSDaniel Vetter 
2998fee884edSDaniel Vetter 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
299982a28bcfSDaniel Vetter 
30001a56b1a2SImre Deak 	ibx_hpd_detection_setup(dev_priv);
30016dbf30ceSVille Syrjälä }
300226951cafSXiong Zhang 
3003*40d06b0fSVille Syrjälä static u32 icp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
30042ea63927SVille Syrjälä {
3005*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
30062ea63927SVille Syrjälä 	case HPD_PORT_A:
30072ea63927SVille Syrjälä 	case HPD_PORT_B:
30082ea63927SVille Syrjälä 	case HPD_PORT_C:
30092ea63927SVille Syrjälä 	case HPD_PORT_D:
3010*40d06b0fSVille Syrjälä 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
3011*40d06b0fSVille Syrjälä 	default:
3012*40d06b0fSVille Syrjälä 		return 0;
3013*40d06b0fSVille Syrjälä 	}
3014*40d06b0fSVille Syrjälä }
3015*40d06b0fSVille Syrjälä 
3016*40d06b0fSVille Syrjälä static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
3017*40d06b0fSVille Syrjälä {
3018*40d06b0fSVille Syrjälä 	return icp_ddi_hotplug_mask(encoder->hpd_pin);
3019*40d06b0fSVille Syrjälä }
3020*40d06b0fSVille Syrjälä 
3021*40d06b0fSVille Syrjälä static u32 icp_tc_hotplug_mask(enum hpd_pin hpd_pin)
3022*40d06b0fSVille Syrjälä {
3023*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
3024*40d06b0fSVille Syrjälä 	case HPD_PORT_TC1:
3025*40d06b0fSVille Syrjälä 	case HPD_PORT_TC2:
3026*40d06b0fSVille Syrjälä 	case HPD_PORT_TC3:
3027*40d06b0fSVille Syrjälä 	case HPD_PORT_TC4:
3028*40d06b0fSVille Syrjälä 	case HPD_PORT_TC5:
3029*40d06b0fSVille Syrjälä 	case HPD_PORT_TC6:
3030*40d06b0fSVille Syrjälä 		return ICP_TC_HPD_ENABLE(hpd_pin);
30312ea63927SVille Syrjälä 	default:
30322ea63927SVille Syrjälä 		return 0;
30332ea63927SVille Syrjälä 	}
30342ea63927SVille Syrjälä }
30352ea63927SVille Syrjälä 
3036dfefe7bcSVille Syrjälä static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
30372ea63927SVille Syrjälä {
3038*40d06b0fSVille Syrjälä 	return icp_tc_hotplug_mask(encoder->hpd_pin);
30392ea63927SVille Syrjälä }
30402ea63927SVille Syrjälä 
30412ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
304231604222SAnusha Srivatsa {
30438cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
3044*40d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_A) |
3045*40d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_B) |
3046*40d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_C) |
3047*40d06b0fSVille Syrjälä 			 icp_ddi_hotplug_mask(HPD_PORT_D),
30488cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
304931604222SAnusha Srivatsa }
3050815f4ef2SVille Syrjälä 
30512ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3052815f4ef2SVille Syrjälä {
30538cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
3054*40d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC1) |
3055*40d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC2) |
3056*40d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC3) |
3057*40d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC4) |
3058*40d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC5) |
3059*40d06b0fSVille Syrjälä 			 icp_tc_hotplug_mask(HPD_PORT_TC6),
30608cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
30618ef7e340SMatt Roper }
306231604222SAnusha Srivatsa 
30632ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
306431604222SAnusha Srivatsa {
306531604222SAnusha Srivatsa 	u32 hotplug_irqs, enabled_irqs;
306631604222SAnusha Srivatsa 
30675a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
30685a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
306931604222SAnusha Srivatsa 
3070f619e516SAnusha Srivatsa 	if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
30712939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3072f49108d0SMatt Roper 
307331604222SAnusha Srivatsa 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
307431604222SAnusha Srivatsa 
30752ea63927SVille Syrjälä 	icp_ddi_hpd_detection_setup(dev_priv);
30762ea63927SVille Syrjälä 	icp_tc_hpd_detection_setup(dev_priv);
307752dfdba0SLucas De Marchi }
307852dfdba0SLucas De Marchi 
3079*40d06b0fSVille Syrjälä static u32 gen11_hotplug_mask(enum hpd_pin hpd_pin)
30808ef7e340SMatt Roper {
3081*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
30822ea63927SVille Syrjälä 	case HPD_PORT_TC1:
30832ea63927SVille Syrjälä 	case HPD_PORT_TC2:
30842ea63927SVille Syrjälä 	case HPD_PORT_TC3:
30852ea63927SVille Syrjälä 	case HPD_PORT_TC4:
30862ea63927SVille Syrjälä 	case HPD_PORT_TC5:
30872ea63927SVille Syrjälä 	case HPD_PORT_TC6:
3088*40d06b0fSVille Syrjälä 		return GEN11_HOTPLUG_CTL_ENABLE(hpd_pin);
30892ea63927SVille Syrjälä 	default:
30902ea63927SVille Syrjälä 		return 0;
309131604222SAnusha Srivatsa 	}
3092943682e3SMatt Roper }
3093943682e3SMatt Roper 
3094*40d06b0fSVille Syrjälä static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
3095*40d06b0fSVille Syrjälä {
3096*40d06b0fSVille Syrjälä 	return gen11_hotplug_mask(encoder->hpd_pin);
3097*40d06b0fSVille Syrjälä }
3098*40d06b0fSVille Syrjälä 
309971690148SGustavo Sousa static void dg1_hpd_invert(struct drm_i915_private *i915)
3100229f31e2SLucas De Marchi {
310171690148SGustavo Sousa 	u32 val = (INVERT_DDIA_HPD |
3102b18c1eb9SClinton A Taylor 		   INVERT_DDIB_HPD |
3103b18c1eb9SClinton A Taylor 		   INVERT_DDIC_HPD |
3104b18c1eb9SClinton A Taylor 		   INVERT_DDID_HPD);
310571690148SGustavo Sousa 	intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
310671690148SGustavo Sousa }
3107b18c1eb9SClinton A Taylor 
310871690148SGustavo Sousa static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
310971690148SGustavo Sousa {
311071690148SGustavo Sousa 	dg1_hpd_invert(dev_priv);
31112ea63927SVille Syrjälä 	icp_hpd_irq_setup(dev_priv);
3112229f31e2SLucas De Marchi }
3113229f31e2SLucas De Marchi 
311452c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3115121e758eSDhinakaran Pandiyan {
31168cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
3117*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC1) |
3118*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC2) |
3119*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC3) |
3120*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC4) |
3121*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC5) |
3122*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC6),
31238cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
312452c7f5f1SVille Syrjälä }
312552c7f5f1SVille Syrjälä 
312652c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
312752c7f5f1SVille Syrjälä {
31288cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
3129*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC1) |
3130*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC2) |
3131*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC3) |
3132*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC4) |
3133*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC5) |
3134*40d06b0fSVille Syrjälä 			 gen11_hotplug_mask(HPD_PORT_TC6),
31358cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
3136121e758eSDhinakaran Pandiyan }
3137121e758eSDhinakaran Pandiyan 
3138121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
3139121e758eSDhinakaran Pandiyan {
3140121e758eSDhinakaran Pandiyan 	u32 hotplug_irqs, enabled_irqs;
3141121e758eSDhinakaran Pandiyan 
31425a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
31435a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
3144121e758eSDhinakaran Pandiyan 
31458cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
31468cee664dSAndrzej Hajda 			 ~enabled_irqs & hotplug_irqs);
31472939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
3148121e758eSDhinakaran Pandiyan 
314952c7f5f1SVille Syrjälä 	gen11_tc_hpd_detection_setup(dev_priv);
315052c7f5f1SVille Syrjälä 	gen11_tbt_hpd_detection_setup(dev_priv);
315131604222SAnusha Srivatsa 
31522ea63927SVille Syrjälä 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
31532ea63927SVille Syrjälä 		icp_hpd_irq_setup(dev_priv);
31542ea63927SVille Syrjälä }
31552ea63927SVille Syrjälä 
3156*40d06b0fSVille Syrjälä static u32 mtp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
3157babde06dSMika Kahola {
3158*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
3159babde06dSMika Kahola 	case HPD_PORT_A:
3160babde06dSMika Kahola 	case HPD_PORT_B:
3161*40d06b0fSVille Syrjälä 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
3162*40d06b0fSVille Syrjälä 	default:
3163*40d06b0fSVille Syrjälä 		return 0;
3164*40d06b0fSVille Syrjälä 	}
3165*40d06b0fSVille Syrjälä }
3166*40d06b0fSVille Syrjälä 
3167*40d06b0fSVille Syrjälä static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder)
3168*40d06b0fSVille Syrjälä {
3169*40d06b0fSVille Syrjälä 	return mtp_ddi_hotplug_mask(encoder->hpd_pin);
3170*40d06b0fSVille Syrjälä }
3171*40d06b0fSVille Syrjälä 
3172*40d06b0fSVille Syrjälä static u32 mtp_tc_hotplug_mask(enum hpd_pin hpd_pin)
3173*40d06b0fSVille Syrjälä {
3174*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
3175*40d06b0fSVille Syrjälä 	case HPD_PORT_TC1:
3176*40d06b0fSVille Syrjälä 	case HPD_PORT_TC2:
3177*40d06b0fSVille Syrjälä 	case HPD_PORT_TC3:
3178*40d06b0fSVille Syrjälä 	case HPD_PORT_TC4:
3179*40d06b0fSVille Syrjälä 		return ICP_TC_HPD_ENABLE(hpd_pin);
3180babde06dSMika Kahola 	default:
3181babde06dSMika Kahola 		return 0;
3182babde06dSMika Kahola 	}
3183babde06dSMika Kahola }
3184babde06dSMika Kahola 
3185babde06dSMika Kahola static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder)
3186babde06dSMika Kahola {
3187*40d06b0fSVille Syrjälä 	return mtp_tc_hotplug_mask(encoder->hpd_pin);
3188babde06dSMika Kahola }
3189babde06dSMika Kahola 
3190babde06dSMika Kahola static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
3191babde06dSMika Kahola {
3192babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
3193*40d06b0fSVille Syrjälä 		     mtp_ddi_hotplug_mask(HPD_PORT_A) |
3194*40d06b0fSVille Syrjälä 		     mtp_ddi_hotplug_mask(HPD_PORT_B),
3195babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
3196babde06dSMika Kahola }
3197babde06dSMika Kahola 
3198babde06dSMika Kahola static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
3199babde06dSMika Kahola {
3200babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_TC,
3201*40d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC1) |
3202*40d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC2) |
3203*40d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC3) |
3204*40d06b0fSVille Syrjälä 		     mtp_tc_hotplug_mask(HPD_PORT_TC4),
3205babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
3206babde06dSMika Kahola }
3207babde06dSMika Kahola 
3208babde06dSMika Kahola static void mtp_hpd_invert(struct drm_i915_private *i915)
3209babde06dSMika Kahola {
3210babde06dSMika Kahola 	u32 val = (INVERT_DDIA_HPD |
3211babde06dSMika Kahola 		   INVERT_DDIB_HPD |
3212babde06dSMika Kahola 		   INVERT_DDIC_HPD |
3213babde06dSMika Kahola 		   INVERT_TC1_HPD |
3214babde06dSMika Kahola 		   INVERT_TC2_HPD |
3215babde06dSMika Kahola 		   INVERT_TC3_HPD |
3216babde06dSMika Kahola 		   INVERT_TC4_HPD |
3217babde06dSMika Kahola 		   INVERT_DDID_HPD_MTP |
3218babde06dSMika Kahola 		   INVERT_DDIE_HPD);
3219babde06dSMika Kahola 	intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
3220babde06dSMika Kahola }
3221babde06dSMika Kahola 
3222babde06dSMika Kahola static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
3223babde06dSMika Kahola {
3224babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3225babde06dSMika Kahola 
3226babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
3227babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
3228babde06dSMika Kahola 
3229babde06dSMika Kahola 	intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3230babde06dSMika Kahola 
3231babde06dSMika Kahola 	mtp_hpd_invert(i915);
3232babde06dSMika Kahola 	ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
3233babde06dSMika Kahola 
3234babde06dSMika Kahola 	mtp_ddi_hpd_detection_setup(i915);
3235babde06dSMika Kahola 	mtp_tc_hpd_detection_setup(i915);
3236babde06dSMika Kahola }
3237babde06dSMika Kahola 
3238babde06dSMika Kahola static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
3239babde06dSMika Kahola {
3240babde06dSMika Kahola 	struct intel_encoder *encoder;
3241babde06dSMika Kahola 	enum hpd_pin pin;
3242babde06dSMika Kahola 	u32 available_pins = 0;
3243babde06dSMika Kahola 
3244babde06dSMika Kahola 	BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
3245babde06dSMika Kahola 
3246babde06dSMika Kahola 	for_each_intel_encoder(&i915->drm, encoder)
3247babde06dSMika Kahola 		available_pins |= BIT(encoder->hpd_pin);
3248babde06dSMika Kahola 
3249babde06dSMika Kahola 	for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
3250babde06dSMika Kahola 		u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
3251babde06dSMika Kahola 			   XELPDP_DP_ALT_HOTPLUG_ENABLE;
3252babde06dSMika Kahola 
3253babde06dSMika Kahola 		intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(pin),
3254babde06dSMika Kahola 			     mask,
3255babde06dSMika Kahola 			     available_pins & BIT(pin) ?  mask : 0);
3256babde06dSMika Kahola 	}
3257babde06dSMika Kahola }
3258babde06dSMika Kahola 
3259babde06dSMika Kahola static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
3260babde06dSMika Kahola {
3261babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3262babde06dSMika Kahola 
3263babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.hpd);
3264babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.hpd);
3265babde06dSMika Kahola 
3266babde06dSMika Kahola 	intel_de_rmw(i915, PICAINTERRUPT_IMR, hotplug_irqs,
3267babde06dSMika Kahola 		     ~enabled_irqs & hotplug_irqs);
3268babde06dSMika Kahola 	intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR);
3269babde06dSMika Kahola 
3270babde06dSMika Kahola 	xelpdp_pica_hpd_detection_setup(i915);
3271babde06dSMika Kahola 
3272babde06dSMika Kahola 	if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
3273babde06dSMika Kahola 		mtp_hpd_irq_setup(i915);
3274babde06dSMika Kahola }
3275babde06dSMika Kahola 
3276*40d06b0fSVille Syrjälä static u32 spt_hotplug_mask(enum hpd_pin hpd_pin)
32772ea63927SVille Syrjälä {
3278*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
32792ea63927SVille Syrjälä 	case HPD_PORT_A:
32802ea63927SVille Syrjälä 		return PORTA_HOTPLUG_ENABLE;
32812ea63927SVille Syrjälä 	case HPD_PORT_B:
32822ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE;
32832ea63927SVille Syrjälä 	case HPD_PORT_C:
32842ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE;
32852ea63927SVille Syrjälä 	case HPD_PORT_D:
32862ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE;
32872ea63927SVille Syrjälä 	default:
32882ea63927SVille Syrjälä 		return 0;
32892ea63927SVille Syrjälä 	}
32902ea63927SVille Syrjälä }
32912ea63927SVille Syrjälä 
3292*40d06b0fSVille Syrjälä static u32 spt_hotplug_enables(struct intel_encoder *encoder)
32932ea63927SVille Syrjälä {
3294*40d06b0fSVille Syrjälä 	return spt_hotplug_mask(encoder->hpd_pin);
3295*40d06b0fSVille Syrjälä }
3296*40d06b0fSVille Syrjälä 
3297*40d06b0fSVille Syrjälä static u32 spt_hotplug2_mask(enum hpd_pin hpd_pin)
3298*40d06b0fSVille Syrjälä {
3299*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
33002ea63927SVille Syrjälä 	case HPD_PORT_E:
33012ea63927SVille Syrjälä 		return PORTE_HOTPLUG_ENABLE;
33022ea63927SVille Syrjälä 	default:
33032ea63927SVille Syrjälä 		return 0;
33042ea63927SVille Syrjälä 	}
3305121e758eSDhinakaran Pandiyan }
3306121e758eSDhinakaran Pandiyan 
3307*40d06b0fSVille Syrjälä static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
3308*40d06b0fSVille Syrjälä {
3309*40d06b0fSVille Syrjälä 	return spt_hotplug2_mask(encoder->hpd_pin);
3310*40d06b0fSVille Syrjälä }
3311*40d06b0fSVille Syrjälä 
33122a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
33132a57d9ccSImre Deak {
33143b92e263SRodrigo Vivi 	/* Display WA #1179 WaHardHangonHotPlug: cnp */
33153b92e263SRodrigo Vivi 	if (HAS_PCH_CNP(dev_priv)) {
33168cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
33178cee664dSAndrzej Hajda 				 CHASSIS_CLK_REQ_DURATION(0xf));
33183b92e263SRodrigo Vivi 	}
33192a57d9ccSImre Deak 
33202a57d9ccSImre Deak 	/* Enable digital hotplug on the PCH */
33218cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
3322*40d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_A) |
3323*40d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_B) |
3324*40d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_C) |
3325*40d06b0fSVille Syrjälä 			 spt_hotplug_mask(HPD_PORT_D),
33268cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
33272a57d9ccSImre Deak 
3328*40d06b0fSVille Syrjälä 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2,
3329*40d06b0fSVille Syrjälä 			 spt_hotplug2_mask(HPD_PORT_E),
33308cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
33312a57d9ccSImre Deak }
33322a57d9ccSImre Deak 
333391d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
33346dbf30ceSVille Syrjälä {
33352a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
33366dbf30ceSVille Syrjälä 
3337f49108d0SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
33382939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3339f49108d0SMatt Roper 
33405a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
33415a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
33426dbf30ceSVille Syrjälä 
33436dbf30ceSVille Syrjälä 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
33446dbf30ceSVille Syrjälä 
33452a57d9ccSImre Deak 	spt_hpd_detection_setup(dev_priv);
334626951cafSXiong Zhang }
33477fe0b973SKeith Packard 
3348*40d06b0fSVille Syrjälä static u32 ilk_hotplug_mask(enum hpd_pin hpd_pin)
3349*40d06b0fSVille Syrjälä {
3350*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
3351*40d06b0fSVille Syrjälä 	case HPD_PORT_A:
3352*40d06b0fSVille Syrjälä 		return DIGITAL_PORTA_HOTPLUG_ENABLE |
3353*40d06b0fSVille Syrjälä 			DIGITAL_PORTA_PULSE_DURATION_MASK;
3354*40d06b0fSVille Syrjälä 	default:
3355*40d06b0fSVille Syrjälä 		return 0;
3356*40d06b0fSVille Syrjälä 	}
3357*40d06b0fSVille Syrjälä }
3358*40d06b0fSVille Syrjälä 
3359dfefe7bcSVille Syrjälä static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
33602ea63927SVille Syrjälä {
3361dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
33622ea63927SVille Syrjälä 	case HPD_PORT_A:
33632ea63927SVille Syrjälä 		return DIGITAL_PORTA_HOTPLUG_ENABLE |
33642ea63927SVille Syrjälä 			DIGITAL_PORTA_PULSE_DURATION_2ms;
33652ea63927SVille Syrjälä 	default:
33662ea63927SVille Syrjälä 		return 0;
33672ea63927SVille Syrjälä 	}
33682ea63927SVille Syrjälä }
33692ea63927SVille Syrjälä 
33701a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
33711a56b1a2SImre Deak {
33721a56b1a2SImre Deak 	/*
33731a56b1a2SImre Deak 	 * Enable digital hotplug on the CPU, and configure the DP short pulse
33741a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec)
33751a56b1a2SImre Deak 	 * The pulse duration bits are reserved on HSW+.
33761a56b1a2SImre Deak 	 */
33778cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
3378*40d06b0fSVille Syrjälä 			 ilk_hotplug_mask(HPD_PORT_A),
33798cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
33801a56b1a2SImre Deak }
33811a56b1a2SImre Deak 
338291d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
3383e4ce95aaSVille Syrjälä {
33841a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
3385e4ce95aaSVille Syrjälä 
33865a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
33875a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
33883a3b3c7dSVille Syrjälä 
3389373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 8)
33903a3b3c7dSVille Syrjälä 		bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
33916d3144ebSVille Syrjälä 	else
33923a3b3c7dSVille Syrjälä 		ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
3393e4ce95aaSVille Syrjälä 
33941a56b1a2SImre Deak 	ilk_hpd_detection_setup(dev_priv);
3395e4ce95aaSVille Syrjälä 
339691d14251STvrtko Ursulin 	ibx_hpd_irq_setup(dev_priv);
3397e4ce95aaSVille Syrjälä }
3398e4ce95aaSVille Syrjälä 
3399*40d06b0fSVille Syrjälä static u32 bxt_hotplug_mask(enum hpd_pin hpd_pin)
3400*40d06b0fSVille Syrjälä {
3401*40d06b0fSVille Syrjälä 	switch (hpd_pin) {
3402*40d06b0fSVille Syrjälä 	case HPD_PORT_A:
3403*40d06b0fSVille Syrjälä 		return PORTA_HOTPLUG_ENABLE | BXT_DDIA_HPD_INVERT;
3404*40d06b0fSVille Syrjälä 	case HPD_PORT_B:
3405*40d06b0fSVille Syrjälä 		return PORTB_HOTPLUG_ENABLE | BXT_DDIB_HPD_INVERT;
3406*40d06b0fSVille Syrjälä 	case HPD_PORT_C:
3407*40d06b0fSVille Syrjälä 		return PORTC_HOTPLUG_ENABLE | BXT_DDIC_HPD_INVERT;
3408*40d06b0fSVille Syrjälä 	default:
3409*40d06b0fSVille Syrjälä 		return 0;
3410*40d06b0fSVille Syrjälä 	}
3411*40d06b0fSVille Syrjälä }
3412*40d06b0fSVille Syrjälä 
3413dfefe7bcSVille Syrjälä static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
34142ea63927SVille Syrjälä {
34152ea63927SVille Syrjälä 	u32 hotplug;
34162ea63927SVille Syrjälä 
3417dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
34182ea63927SVille Syrjälä 	case HPD_PORT_A:
34192ea63927SVille Syrjälä 		hotplug = PORTA_HOTPLUG_ENABLE;
34209151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
34212ea63927SVille Syrjälä 			hotplug |= BXT_DDIA_HPD_INVERT;
34222ea63927SVille Syrjälä 		return hotplug;
34232ea63927SVille Syrjälä 	case HPD_PORT_B:
34242ea63927SVille Syrjälä 		hotplug = PORTB_HOTPLUG_ENABLE;
34259151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
34262ea63927SVille Syrjälä 			hotplug |= BXT_DDIB_HPD_INVERT;
34272ea63927SVille Syrjälä 		return hotplug;
34282ea63927SVille Syrjälä 	case HPD_PORT_C:
34292ea63927SVille Syrjälä 		hotplug = PORTC_HOTPLUG_ENABLE;
34309151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
34312ea63927SVille Syrjälä 			hotplug |= BXT_DDIC_HPD_INVERT;
34322ea63927SVille Syrjälä 		return hotplug;
34332ea63927SVille Syrjälä 	default:
34342ea63927SVille Syrjälä 		return 0;
34352ea63927SVille Syrjälä 	}
34362ea63927SVille Syrjälä }
34372ea63927SVille Syrjälä 
34382ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
3439e0a20ad7SShashank Sharma {
34408cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
3441*40d06b0fSVille Syrjälä 			 bxt_hotplug_mask(HPD_PORT_A) |
3442*40d06b0fSVille Syrjälä 			 bxt_hotplug_mask(HPD_PORT_B) |
3443*40d06b0fSVille Syrjälä 			 bxt_hotplug_mask(HPD_PORT_C),
34448cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
3445e0a20ad7SShashank Sharma }
3446e0a20ad7SShashank Sharma 
34472a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
34482a57d9ccSImre Deak {
34492a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
34502a57d9ccSImre Deak 
34515a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
34525a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
34532a57d9ccSImre Deak 
34542a57d9ccSImre Deak 	bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
34552a57d9ccSImre Deak 
34562ea63927SVille Syrjälä 	bxt_hpd_detection_setup(dev_priv);
34572a57d9ccSImre Deak }
34582a57d9ccSImre Deak 
3459a0a6d8cbSVille Syrjälä /*
3460a0a6d8cbSVille Syrjälä  * SDEIER is also touched by the interrupt handler to work around missed PCH
3461a0a6d8cbSVille Syrjälä  * interrupts. Hence we can't update it after the interrupt handler is enabled -
3462a0a6d8cbSVille Syrjälä  * instead we unconditionally enable all PCH interrupt sources here, but then
3463a0a6d8cbSVille Syrjälä  * only unmask them as needed with SDEIMR.
3464a0a6d8cbSVille Syrjälä  *
3465a0a6d8cbSVille Syrjälä  * Note that we currently do this after installing the interrupt handler,
3466a0a6d8cbSVille Syrjälä  * but before we enable the master interrupt. That should be sufficient
3467a0a6d8cbSVille Syrjälä  * to avoid races with the irq handler, assuming we have MSI. Shared legacy
3468a0a6d8cbSVille Syrjälä  * interrupts could still race.
3469a0a6d8cbSVille Syrjälä  */
3470b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
3471d46da437SPaulo Zanoni {
3472a0a6d8cbSVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
347382a28bcfSDaniel Vetter 	u32 mask;
3474d46da437SPaulo Zanoni 
34756e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
3476692a04cfSDaniel Vetter 		return;
3477692a04cfSDaniel Vetter 
34786e266956STvrtko Ursulin 	if (HAS_PCH_IBX(dev_priv))
34795c673b60SDaniel Vetter 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
34804ebc6509SDhinakaran Pandiyan 	else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
34815c673b60SDaniel Vetter 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
34824ebc6509SDhinakaran Pandiyan 	else
34834ebc6509SDhinakaran Pandiyan 		mask = SDE_GMBUS_CPT;
34848664281bSPaulo Zanoni 
3485a0a6d8cbSVille Syrjälä 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
3486d46da437SPaulo Zanoni }
3487d46da437SPaulo Zanoni 
34889eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
3489036a4a7dSZhenyu Wang {
3490b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
34918e76f8dcSPaulo Zanoni 	u32 display_mask, extra_mask;
34928e76f8dcSPaulo Zanoni 
3493651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) >= 7) {
34948e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
3495842ebf7aSVille Syrjälä 				DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB);
34968e76f8dcSPaulo Zanoni 		extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
349723bb4cb5SVille Syrjälä 			      DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
34982a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_C) |
34992a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_B) |
35002a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_A) |
350123bb4cb5SVille Syrjälä 			      DE_DP_A_HOTPLUG_IVB);
35028e76f8dcSPaulo Zanoni 	} else {
35038e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
3504842ebf7aSVille Syrjälä 				DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE |
3505842ebf7aSVille Syrjälä 				DE_PIPEA_CRC_DONE | DE_POISON);
3506c6073d4cSVille Syrjälä 		extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK |
3507e4ce95aaSVille Syrjälä 			      DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
35084bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_A) |
35094bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_B) |
3510e4ce95aaSVille Syrjälä 			      DE_DP_A_HOTPLUG);
35118e76f8dcSPaulo Zanoni 	}
3512036a4a7dSZhenyu Wang 
3513fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
3514b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
3515fc340442SDaniel Vetter 		display_mask |= DE_EDP_PSR_INT_HSW;
3516fc340442SDaniel Vetter 	}
3517fc340442SDaniel Vetter 
3518c6073d4cSVille Syrjälä 	if (IS_IRONLAKE_M(dev_priv))
3519c6073d4cSVille Syrjälä 		extra_mask |= DE_PCU_EVENT;
3520c6073d4cSVille Syrjälä 
35211ec14ad3SChris Wilson 	dev_priv->irq_mask = ~display_mask;
3522036a4a7dSZhenyu Wang 
3523a0a6d8cbSVille Syrjälä 	ibx_irq_postinstall(dev_priv);
3524622364b6SPaulo Zanoni 
35252cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
3526a9922912SVille Syrjälä 
3527b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask,
3528b16b2a2fSPaulo Zanoni 		      display_mask | extra_mask);
3529036a4a7dSZhenyu Wang }
3530036a4a7dSZhenyu Wang 
3531f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
3532f8b79e58SImre Deak {
353367520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3534f8b79e58SImre Deak 
3535f8b79e58SImre Deak 	if (dev_priv->display_irqs_enabled)
3536f8b79e58SImre Deak 		return;
3537f8b79e58SImre Deak 
3538f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = true;
3539f8b79e58SImre Deak 
3540d6c69803SVille Syrjälä 	if (intel_irqs_enabled(dev_priv)) {
3541d6c69803SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3542ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3543f8b79e58SImre Deak 	}
3544d6c69803SVille Syrjälä }
3545f8b79e58SImre Deak 
3546f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
3547f8b79e58SImre Deak {
354867520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3549f8b79e58SImre Deak 
3550f8b79e58SImre Deak 	if (!dev_priv->display_irqs_enabled)
3551f8b79e58SImre Deak 		return;
3552f8b79e58SImre Deak 
3553f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = false;
3554f8b79e58SImre Deak 
3555950eabafSImre Deak 	if (intel_irqs_enabled(dev_priv))
3556ad22d106SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3557f8b79e58SImre Deak }
3558f8b79e58SImre Deak 
35590e6c9a9eSVille Syrjälä 
3560b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
35610e6c9a9eSVille Syrjälä {
35622cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
35637e231dbeSJesse Barnes 
3564ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
35659918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3566ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3567ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3568ad22d106SVille Syrjälä 
35692939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
35702939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
357120afbda2SDaniel Vetter }
357220afbda2SDaniel Vetter 
3573abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
3574abd58f01SBen Widawsky {
3575b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3576b16b2a2fSPaulo Zanoni 
3577869129eeSMatt Roper 	u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
3578869129eeSMatt Roper 		GEN8_PIPE_CDCLK_CRC_DONE;
3579a9c287c9SJani Nikula 	u32 de_pipe_enables;
3580054318c7SImre Deak 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
35813a3b3c7dSVille Syrjälä 	u32 de_port_enables;
3582df0d28c1SDhinakaran Pandiyan 	u32 de_misc_masked = GEN8_DE_EDP_PSR;
3583562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
3584562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
35853a3b3c7dSVille Syrjälä 	enum pipe pipe;
3586770de83dSDamien Lespiau 
3587a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3588a844cfbeSJosé Roberto de Souza 		return;
3589a844cfbeSJosé Roberto de Souza 
3590373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) <= 10)
3591df0d28c1SDhinakaran Pandiyan 		de_misc_masked |= GEN8_DE_MISC_GSE;
3592df0d28c1SDhinakaran Pandiyan 
359370bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
35943a3b3c7dSVille Syrjälä 		de_port_masked |= BXT_DE_PORT_GMBUS;
3595a324fcacSRodrigo Vivi 
3596373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
35979c9e97c4SVandita Kulkarni 		enum port port;
35989c9e97c4SVandita Kulkarni 
35999c9e97c4SVandita Kulkarni 		if (intel_bios_is_dsi_present(dev_priv, &port))
36009c9e97c4SVandita Kulkarni 			de_port_masked |= DSI0_TE | DSI1_TE;
36019c9e97c4SVandita Kulkarni 	}
36029c9e97c4SVandita Kulkarni 
3603cda195f1SVille Syrjälä 	de_pipe_enables = de_pipe_masked |
36048bcc0840SMatt Roper 		GEN8_PIPE_VBLANK |
36058bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
3606cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
36071288f9b0SKarthik B S 
36083a3b3c7dSVille Syrjälä 	de_port_enables = de_port_masked;
360970bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3610a52bb15bSVille Syrjälä 		de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
3611a52bb15bSVille Syrjälä 	else if (IS_BROADWELL(dev_priv))
3612e5abaab3SVille Syrjälä 		de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
36133a3b3c7dSVille Syrjälä 
3614373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
36158241cfbeSJosé Roberto de Souza 		enum transcoder trans;
36168241cfbeSJosé Roberto de Souza 
3617562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
36188241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
36198241cfbeSJosé Roberto de Souza 
36208241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
36218241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
36228241cfbeSJosé Roberto de Souza 				continue;
36238241cfbeSJosé Roberto de Souza 
36248241cfbeSJosé Roberto de Souza 			gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
36258241cfbeSJosé Roberto de Souza 		}
36268241cfbeSJosé Roberto de Souza 	} else {
3627b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
36288241cfbeSJosé Roberto de Souza 	}
3629e04f7eceSVille Syrjälä 
36300a195c02SMika Kahola 	for_each_pipe(dev_priv, pipe) {
36310a195c02SMika Kahola 		dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
3632abd58f01SBen Widawsky 
3633f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
3634813bde43SPaulo Zanoni 				POWER_DOMAIN_PIPE(pipe)))
3635b16b2a2fSPaulo Zanoni 			GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
3636813bde43SPaulo Zanoni 					  dev_priv->de_irq_mask[pipe],
363735079899SPaulo Zanoni 					  de_pipe_enables);
36380a195c02SMika Kahola 	}
3639abd58f01SBen Widawsky 
3640b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
3641b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
36422a57d9ccSImre Deak 
3643babde06dSMika Kahola 	if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
3644121e758eSDhinakaran Pandiyan 		u32 de_hpd_masked = 0;
3645b796b971SDhinakaran Pandiyan 		u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
3646b796b971SDhinakaran Pandiyan 				     GEN11_DE_TBT_HOTPLUG_MASK;
3647121e758eSDhinakaran Pandiyan 
3648b16b2a2fSPaulo Zanoni 		GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
3649b16b2a2fSPaulo Zanoni 			      de_hpd_enables);
3650abd58f01SBen Widawsky 	}
3651121e758eSDhinakaran Pandiyan }
3652abd58f01SBen Widawsky 
3653babde06dSMika Kahola static void mtp_irq_postinstall(struct drm_i915_private *i915)
3654babde06dSMika Kahola {
3655babde06dSMika Kahola 	struct intel_uncore *uncore = &i915->uncore;
3656babde06dSMika Kahola 	u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
3657babde06dSMika Kahola 	u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
3658babde06dSMika Kahola 	u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
3659babde06dSMika Kahola 			     XELPDP_TBT_HOTPLUG_MASK;
3660babde06dSMika Kahola 
3661babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
3662babde06dSMika Kahola 		      de_hpd_enables);
3663babde06dSMika Kahola 
3664babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
3665babde06dSMika Kahola }
3666babde06dSMika Kahola 
366759b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
366859b7cb44STejas Upadhyay {
366959b7cb44STejas Upadhyay 	struct intel_uncore *uncore = &dev_priv->uncore;
367059b7cb44STejas Upadhyay 	u32 mask = SDE_GMBUS_ICP;
367159b7cb44STejas Upadhyay 
367259b7cb44STejas Upadhyay 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
367359b7cb44STejas Upadhyay }
367459b7cb44STejas Upadhyay 
3675b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
3676abd58f01SBen Widawsky {
367759b7cb44STejas Upadhyay 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
367859b7cb44STejas Upadhyay 		icp_irq_postinstall(dev_priv);
367959b7cb44STejas Upadhyay 	else if (HAS_PCH_SPLIT(dev_priv))
3680a0a6d8cbSVille Syrjälä 		ibx_irq_postinstall(dev_priv);
3681622364b6SPaulo Zanoni 
36822cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
3683abd58f01SBen Widawsky 	gen8_de_irq_postinstall(dev_priv);
3684abd58f01SBen Widawsky 
368525286aacSDaniele Ceraolo Spurio 	gen8_master_intr_enable(dev_priv->uncore.regs);
3686abd58f01SBen Widawsky }
3687abd58f01SBen Widawsky 
3688a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
3689a844cfbeSJosé Roberto de Souza {
3690a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3691a844cfbeSJosé Roberto de Souza 		return;
3692a844cfbeSJosé Roberto de Souza 
3693a844cfbeSJosé Roberto de Souza 	gen8_de_irq_postinstall(dev_priv);
3694a844cfbeSJosé Roberto de Souza 
3695a844cfbeSJosé Roberto de Souza 	intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
3696a844cfbeSJosé Roberto de Souza 			   GEN11_DISPLAY_IRQ_ENABLE);
3697a844cfbeSJosé Roberto de Souza }
369831604222SAnusha Srivatsa 
3699b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
370051951ae7SMika Kuoppala {
37012cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3702fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
3703df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
370451951ae7SMika Kuoppala 
370529b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
3706b318b824SVille Syrjälä 		icp_irq_postinstall(dev_priv);
370731604222SAnusha Srivatsa 
3708fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
3709a844cfbeSJosé Roberto de Souza 	gen11_de_irq_postinstall(dev_priv);
371051951ae7SMika Kuoppala 
3711b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
3712df0d28c1SDhinakaran Pandiyan 
37139b77011eSTvrtko Ursulin 	gen11_master_intr_enable(uncore->regs);
37142939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
371551951ae7SMika Kuoppala }
371622e26af7SPaulo Zanoni 
371722e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
371822e26af7SPaulo Zanoni {
37192cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3720fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
372122e26af7SPaulo Zanoni 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
372222e26af7SPaulo Zanoni 
3723fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
372422e26af7SPaulo Zanoni 
372522e26af7SPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
372622e26af7SPaulo Zanoni 
372722e26af7SPaulo Zanoni 	if (HAS_DISPLAY(dev_priv)) {
3728babde06dSMika Kahola 		if (DISPLAY_VER(dev_priv) >= 14)
3729babde06dSMika Kahola 			mtp_irq_postinstall(dev_priv);
3730babde06dSMika Kahola 		else
373122e26af7SPaulo Zanoni 			icp_irq_postinstall(dev_priv);
3732babde06dSMika Kahola 
373322e26af7SPaulo Zanoni 		gen8_de_irq_postinstall(dev_priv);
373422e26af7SPaulo Zanoni 		intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
373522e26af7SPaulo Zanoni 				   GEN11_DISPLAY_IRQ_ENABLE);
373622e26af7SPaulo Zanoni 	}
373722e26af7SPaulo Zanoni 
3738fd4d7904SPaulo Zanoni 	dg1_master_intr_enable(uncore->regs);
3739fd4d7904SPaulo Zanoni 	intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR);
374097b492f5SLucas De Marchi }
374151951ae7SMika Kuoppala 
3742b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
374343f328d7SVille Syrjälä {
37442cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
374543f328d7SVille Syrjälä 
3746ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
37479918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3748ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3749ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3750ad22d106SVille Syrjälä 
37512939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
37522939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
375343f328d7SVille Syrjälä }
375443f328d7SVille Syrjälä 
3755b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv)
3756c2798b19SChris Wilson {
3757b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3758c2798b19SChris Wilson 
375944d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
376044d9241eSVille Syrjälä 
3761ad7632ffSJani Nikula 	gen2_irq_reset(uncore);
3762e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
3763c2798b19SChris Wilson }
3764c2798b19SChris Wilson 
37653687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915)
37663687ce75SVille Syrjälä {
3767e7e12f6eSVille Syrjälä 	/*
3768e7e12f6eSVille Syrjälä 	 * On gen2/3 FBC generates (seemingly spurious)
3769e7e12f6eSVille Syrjälä 	 * display INVALID_GTT/INVALID_GTT_PTE table errors.
3770e7e12f6eSVille Syrjälä 	 *
3771e7e12f6eSVille Syrjälä 	 * Also gen3 bspec has this to say:
3772e7e12f6eSVille Syrjälä 	 * "DISPA_INVALID_GTT_PTE
3773e7e12f6eSVille Syrjälä 	 "  [DevNapa] : Reserved. This bit does not reflect the page
3774e7e12f6eSVille Syrjälä 	 "              table error for the display plane A."
3775e7e12f6eSVille Syrjälä 	 *
3776e7e12f6eSVille Syrjälä 	 * Unfortunately we can't mask off individual PGTBL_ER bits,
3777e7e12f6eSVille Syrjälä 	 * so we just have to mask off all page table errors via EMR.
3778e7e12f6eSVille Syrjälä 	 */
3779e7e12f6eSVille Syrjälä 	if (HAS_FBC(i915))
3780e7e12f6eSVille Syrjälä 		return ~I915_ERROR_MEMORY_REFRESH;
3781e7e12f6eSVille Syrjälä 	else
37823687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
37833687ce75SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
37843687ce75SVille Syrjälä }
37853687ce75SVille Syrjälä 
3786b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv)
3787c2798b19SChris Wilson {
3788b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3789e9e9848aSVille Syrjälä 	u16 enable_mask;
3790c2798b19SChris Wilson 
37913687ce75SVille Syrjälä 	intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv));
3792c2798b19SChris Wilson 
3793c2798b19SChris Wilson 	/* Unmask the interrupts that we always want on. */
3794c2798b19SChris Wilson 	dev_priv->irq_mask =
3795c2798b19SChris Wilson 		~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
379616659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
379716659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
3798c2798b19SChris Wilson 
3799e9e9848aSVille Syrjälä 	enable_mask =
3800c2798b19SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
3801c2798b19SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
380216659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
3803e9e9848aSVille Syrjälä 		I915_USER_INTERRUPT;
3804e9e9848aSVille Syrjälä 
3805ad7632ffSJani Nikula 	gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask);
3806c2798b19SChris Wilson 
3807379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
3808379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
3809d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
3810755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
3811755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
3812d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
3813c2798b19SChris Wilson }
3814c2798b19SChris Wilson 
38154f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915,
381678c357ddSVille Syrjälä 			       u16 *eir, u16 *eir_stuck)
381778c357ddSVille Syrjälä {
38184f5fd91fSTvrtko Ursulin 	struct intel_uncore *uncore = &i915->uncore;
381978c357ddSVille Syrjälä 	u16 emr;
382078c357ddSVille Syrjälä 
38214f5fd91fSTvrtko Ursulin 	*eir = intel_uncore_read16(uncore, EIR);
38224f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EIR, *eir);
382378c357ddSVille Syrjälä 
38244f5fd91fSTvrtko Ursulin 	*eir_stuck = intel_uncore_read16(uncore, EIR);
382578c357ddSVille Syrjälä 	if (*eir_stuck == 0)
382678c357ddSVille Syrjälä 		return;
382778c357ddSVille Syrjälä 
382878c357ddSVille Syrjälä 	/*
382978c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
383078c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
383178c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
383278c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
383378c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
383478c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
383578c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
383678c357ddSVille Syrjälä 	 * remains set.
383778c357ddSVille Syrjälä 	 */
38384f5fd91fSTvrtko Ursulin 	emr = intel_uncore_read16(uncore, EMR);
38394f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, 0xffff);
38404f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, emr | *eir_stuck);
384178c357ddSVille Syrjälä }
384278c357ddSVille Syrjälä 
384378c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv,
384478c357ddSVille Syrjälä 				   u16 eir, u16 eir_stuck)
384578c357ddSVille Syrjälä {
3846a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir);
384778c357ddSVille Syrjälä 
384878c357ddSVille Syrjälä 	if (eir_stuck)
384900376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n",
385000376ccfSWambui Karuga 			eir_stuck);
3851d1e89592SVille Syrjälä 
3852d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
3853d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
385478c357ddSVille Syrjälä }
385578c357ddSVille Syrjälä 
385678c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
385778c357ddSVille Syrjälä 			       u32 *eir, u32 *eir_stuck)
385878c357ddSVille Syrjälä {
385978c357ddSVille Syrjälä 	u32 emr;
386078c357ddSVille Syrjälä 
3861839259b8SVille Syrjälä 	*eir = intel_uncore_read(&dev_priv->uncore, EIR);
3862839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EIR, *eir);
386378c357ddSVille Syrjälä 
38642939eb06SJani Nikula 	*eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR);
386578c357ddSVille Syrjälä 	if (*eir_stuck == 0)
386678c357ddSVille Syrjälä 		return;
386778c357ddSVille Syrjälä 
386878c357ddSVille Syrjälä 	/*
386978c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
387078c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
387178c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
387278c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
387378c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
387478c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
387578c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
387678c357ddSVille Syrjälä 	 * remains set.
387778c357ddSVille Syrjälä 	 */
3878839259b8SVille Syrjälä 	emr = intel_uncore_read(&dev_priv->uncore, EMR);
3879839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff);
38802939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck);
388178c357ddSVille Syrjälä }
388278c357ddSVille Syrjälä 
388378c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv,
388478c357ddSVille Syrjälä 				   u32 eir, u32 eir_stuck)
388578c357ddSVille Syrjälä {
3886a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir);
388778c357ddSVille Syrjälä 
388878c357ddSVille Syrjälä 	if (eir_stuck)
388900376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n",
389000376ccfSWambui Karuga 			eir_stuck);
3891d1e89592SVille Syrjälä 
3892d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
3893d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
389478c357ddSVille Syrjälä }
389578c357ddSVille Syrjälä 
3896ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg)
3897c2798b19SChris Wilson {
3898b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
3899af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
3900c2798b19SChris Wilson 
39012dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
39022dd2a883SImre Deak 		return IRQ_NONE;
39032dd2a883SImre Deak 
39041f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
39059102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
39061f814dacSImre Deak 
3907af722d28SVille Syrjälä 	do {
3908af722d28SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
390978c357ddSVille Syrjälä 		u16 eir = 0, eir_stuck = 0;
3910af722d28SVille Syrjälä 		u16 iir;
3911af722d28SVille Syrjälä 
39124f5fd91fSTvrtko Ursulin 		iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR);
3913c2798b19SChris Wilson 		if (iir == 0)
3914af722d28SVille Syrjälä 			break;
3915c2798b19SChris Wilson 
3916af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
3917c2798b19SChris Wilson 
3918eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
3919eb64343cSVille Syrjälä 		 * signalled in iir */
3920eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
3921c2798b19SChris Wilson 
392278c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
392378c357ddSVille Syrjälä 			i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
392478c357ddSVille Syrjälä 
39254f5fd91fSTvrtko Ursulin 		intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir);
3926c2798b19SChris Wilson 
3927c2798b19SChris Wilson 		if (iir & I915_USER_INTERRUPT)
39282cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
3929c2798b19SChris Wilson 
393078c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
393178c357ddSVille Syrjälä 			i8xx_error_irq_handler(dev_priv, eir, eir_stuck);
3932af722d28SVille Syrjälä 
3933eb64343cSVille Syrjälä 		i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats);
3934af722d28SVille Syrjälä 	} while (0);
3935c2798b19SChris Wilson 
39369c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
39379c6508b9SThomas Gleixner 
39389102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
39391f814dacSImre Deak 
39401f814dacSImre Deak 	return ret;
3941c2798b19SChris Wilson }
3942c2798b19SChris Wilson 
3943b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv)
3944a266c7d5SChris Wilson {
3945b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3946a266c7d5SChris Wilson 
394756b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
39480706f17cSEgbert Eich 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
39498cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0);
3950a266c7d5SChris Wilson 	}
3951a266c7d5SChris Wilson 
395244d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
395344d9241eSVille Syrjälä 
3954b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
3955e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
3956a266c7d5SChris Wilson }
3957a266c7d5SChris Wilson 
3958b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
3959a266c7d5SChris Wilson {
3960b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
396138bde180SChris Wilson 	u32 enable_mask;
3962a266c7d5SChris Wilson 
39633687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv));
396438bde180SChris Wilson 
396538bde180SChris Wilson 	/* Unmask the interrupts that we always want on. */
396638bde180SChris Wilson 	dev_priv->irq_mask =
396738bde180SChris Wilson 		~(I915_ASLE_INTERRUPT |
396838bde180SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
396916659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
397016659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
397138bde180SChris Wilson 
397238bde180SChris Wilson 	enable_mask =
397338bde180SChris Wilson 		I915_ASLE_INTERRUPT |
397438bde180SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
397538bde180SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
397616659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
397738bde180SChris Wilson 		I915_USER_INTERRUPT;
397838bde180SChris Wilson 
397956b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
3980a266c7d5SChris Wilson 		/* Enable in IER... */
3981a266c7d5SChris Wilson 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
3982a266c7d5SChris Wilson 		/* and unmask in IMR */
3983a266c7d5SChris Wilson 		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
3984a266c7d5SChris Wilson 	}
3985a266c7d5SChris Wilson 
3986b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
3987a266c7d5SChris Wilson 
3988379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
3989379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
3990d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
3991755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
3992755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
3993d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
3994379ef82dSDaniel Vetter 
3995c30bb1fdSVille Syrjälä 	i915_enable_asle_pipestat(dev_priv);
399620afbda2SDaniel Vetter }
399720afbda2SDaniel Vetter 
3998ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg)
3999a266c7d5SChris Wilson {
4000b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4001af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4002a266c7d5SChris Wilson 
40032dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
40042dd2a883SImre Deak 		return IRQ_NONE;
40052dd2a883SImre Deak 
40061f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
40079102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
40081f814dacSImre Deak 
400938bde180SChris Wilson 	do {
4010eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
401178c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
4012af722d28SVille Syrjälä 		u32 hotplug_status = 0;
4013af722d28SVille Syrjälä 		u32 iir;
4014a266c7d5SChris Wilson 
40152939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
4016af722d28SVille Syrjälä 		if (iir == 0)
4017af722d28SVille Syrjälä 			break;
4018af722d28SVille Syrjälä 
4019af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4020af722d28SVille Syrjälä 
4021af722d28SVille Syrjälä 		if (I915_HAS_HOTPLUG(dev_priv) &&
4022af722d28SVille Syrjälä 		    iir & I915_DISPLAY_PORT_INTERRUPT)
4023af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
4024a266c7d5SChris Wilson 
4025eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4026eb64343cSVille Syrjälä 		 * signalled in iir */
4027eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4028a266c7d5SChris Wilson 
402978c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
403078c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
403178c357ddSVille Syrjälä 
40322939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
4033a266c7d5SChris Wilson 
4034a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
40352cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
4036a266c7d5SChris Wilson 
403778c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
403878c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
4039a266c7d5SChris Wilson 
4040af722d28SVille Syrjälä 		if (hotplug_status)
4041af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
4042af722d28SVille Syrjälä 
4043af722d28SVille Syrjälä 		i915_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4044af722d28SVille Syrjälä 	} while (0);
4045a266c7d5SChris Wilson 
40469c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
40479c6508b9SThomas Gleixner 
40489102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
40491f814dacSImre Deak 
4050a266c7d5SChris Wilson 	return ret;
4051a266c7d5SChris Wilson }
4052a266c7d5SChris Wilson 
4053b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv)
4054a266c7d5SChris Wilson {
4055b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
4056a266c7d5SChris Wilson 
40570706f17cSEgbert Eich 	i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
40588cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
4059a266c7d5SChris Wilson 
406044d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
406144d9241eSVille Syrjälä 
4062b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
4063e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
4064a266c7d5SChris Wilson }
4065a266c7d5SChris Wilson 
40663687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915)
4067a266c7d5SChris Wilson {
4068045cebd2SVille Syrjälä 	/*
4069045cebd2SVille Syrjälä 	 * Enable some error detection, note the instruction error mask
4070045cebd2SVille Syrjälä 	 * bit is reserved, so we leave it masked.
4071e7e12f6eSVille Syrjälä 	 *
4072e7e12f6eSVille Syrjälä 	 * i965 FBC no longer generates spurious GTT errors,
4073e7e12f6eSVille Syrjälä 	 * so we can always enable the page table errors.
4074045cebd2SVille Syrjälä 	 */
40753687ce75SVille Syrjälä 	if (IS_G4X(i915))
40763687ce75SVille Syrjälä 		return ~(GM45_ERROR_PAGE_TABLE |
4077045cebd2SVille Syrjälä 			 GM45_ERROR_MEM_PRIV |
4078045cebd2SVille Syrjälä 			 GM45_ERROR_CP_PRIV |
4079045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
40803687ce75SVille Syrjälä 	else
40813687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
4082045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
4083045cebd2SVille Syrjälä }
40843687ce75SVille Syrjälä 
40853687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
40863687ce75SVille Syrjälä {
40873687ce75SVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
40883687ce75SVille Syrjälä 	u32 enable_mask;
40893687ce75SVille Syrjälä 
40903687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv));
4091045cebd2SVille Syrjälä 
4092a266c7d5SChris Wilson 	/* Unmask the interrupts that we always want on. */
4093c30bb1fdSVille Syrjälä 	dev_priv->irq_mask =
4094c30bb1fdSVille Syrjälä 		~(I915_ASLE_INTERRUPT |
4095adca4730SChris Wilson 		  I915_DISPLAY_PORT_INTERRUPT |
4096bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4097bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
409878c357ddSVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
4099bbba0a97SChris Wilson 
4100c30bb1fdSVille Syrjälä 	enable_mask =
4101c30bb1fdSVille Syrjälä 		I915_ASLE_INTERRUPT |
4102c30bb1fdSVille Syrjälä 		I915_DISPLAY_PORT_INTERRUPT |
4103c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4104c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
410578c357ddSVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
4106c30bb1fdSVille Syrjälä 		I915_USER_INTERRUPT;
4107bbba0a97SChris Wilson 
410891d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4109bbba0a97SChris Wilson 		enable_mask |= I915_BSD_USER_INTERRUPT;
4110a266c7d5SChris Wilson 
4111b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
4112c30bb1fdSVille Syrjälä 
4113b79480baSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
4114b79480baSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
4115d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
4116755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
4117755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
4118755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
4119d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
4120a266c7d5SChris Wilson 
412191d14251STvrtko Ursulin 	i915_enable_asle_pipestat(dev_priv);
412220afbda2SDaniel Vetter }
412320afbda2SDaniel Vetter 
412491d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
412520afbda2SDaniel Vetter {
412620afbda2SDaniel Vetter 	u32 hotplug_en;
412720afbda2SDaniel Vetter 
412867520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
4129b5ea2d56SDaniel Vetter 
4130adca4730SChris Wilson 	/* Note HDMI and DP share hotplug bits */
4131e5868a31SEgbert Eich 	/* enable bits are the same for all generations */
413291d14251STvrtko Ursulin 	hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
4133a266c7d5SChris Wilson 	/* Programming the CRT detection parameters tends
4134a266c7d5SChris Wilson 	   to generate a spurious hotplug event about three
4135a266c7d5SChris Wilson 	   seconds later.  So just do it once.
4136a266c7d5SChris Wilson 	*/
413791d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4138a266c7d5SChris Wilson 		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
4139a266c7d5SChris Wilson 	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
4140a266c7d5SChris Wilson 
4141a266c7d5SChris Wilson 	/* Ignore TV since it's buggy */
41420706f17cSEgbert Eich 	i915_hotplug_interrupt_update_locked(dev_priv,
4143f9e3dc78SJani Nikula 					     HOTPLUG_INT_EN_MASK |
4144f9e3dc78SJani Nikula 					     CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
4145f9e3dc78SJani Nikula 					     CRT_HOTPLUG_ACTIVATION_PERIOD_64,
41460706f17cSEgbert Eich 					     hotplug_en);
4147a266c7d5SChris Wilson }
4148a266c7d5SChris Wilson 
4149ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg)
4150a266c7d5SChris Wilson {
4151b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4152af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4153a266c7d5SChris Wilson 
41542dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
41552dd2a883SImre Deak 		return IRQ_NONE;
41562dd2a883SImre Deak 
41571f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
41589102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
41591f814dacSImre Deak 
4160af722d28SVille Syrjälä 	do {
4161eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
416278c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
4163af722d28SVille Syrjälä 		u32 hotplug_status = 0;
4164af722d28SVille Syrjälä 		u32 iir;
41652c8ba29fSChris Wilson 
41662939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
4167af722d28SVille Syrjälä 		if (iir == 0)
4168af722d28SVille Syrjälä 			break;
4169af722d28SVille Syrjälä 
4170af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4171af722d28SVille Syrjälä 
4172af722d28SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
4173af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
4174a266c7d5SChris Wilson 
4175eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4176eb64343cSVille Syrjälä 		 * signalled in iir */
4177eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4178a266c7d5SChris Wilson 
417978c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
418078c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
418178c357ddSVille Syrjälä 
41822939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
4183a266c7d5SChris Wilson 
4184a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
41852cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0],
41860669a6e1SChris Wilson 					    iir);
4187af722d28SVille Syrjälä 
4188a266c7d5SChris Wilson 		if (iir & I915_BSD_USER_INTERRUPT)
41892cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0],
41900669a6e1SChris Wilson 					    iir >> 25);
4191a266c7d5SChris Wilson 
419278c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
419378c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
4194515ac2bbSDaniel Vetter 
4195af722d28SVille Syrjälä 		if (hotplug_status)
4196af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
4197af722d28SVille Syrjälä 
4198af722d28SVille Syrjälä 		i965_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4199af722d28SVille Syrjälä 	} while (0);
4200a266c7d5SChris Wilson 
42019c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
42029c6508b9SThomas Gleixner 
42039102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
42041f814dacSImre Deak 
4205a266c7d5SChris Wilson 	return ret;
4206a266c7d5SChris Wilson }
4207a266c7d5SChris Wilson 
42087e97596cSJani Nikula struct intel_hotplug_funcs {
42097e97596cSJani Nikula 	void (*hpd_irq_setup)(struct drm_i915_private *i915);
42107e97596cSJani Nikula };
42117e97596cSJani Nikula 
4212cd030c7cSDave Airlie #define HPD_FUNCS(platform)					 \
4213cd030c7cSDave Airlie static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
4214cd030c7cSDave Airlie 	.hpd_irq_setup = platform##_hpd_irq_setup,		 \
4215cd030c7cSDave Airlie }
4216cd030c7cSDave Airlie 
4217cd030c7cSDave Airlie HPD_FUNCS(i915);
4218babde06dSMika Kahola HPD_FUNCS(xelpdp);
4219cd030c7cSDave Airlie HPD_FUNCS(dg1);
4220cd030c7cSDave Airlie HPD_FUNCS(gen11);
4221cd030c7cSDave Airlie HPD_FUNCS(bxt);
4222cd030c7cSDave Airlie HPD_FUNCS(icp);
4223cd030c7cSDave Airlie HPD_FUNCS(spt);
4224cd030c7cSDave Airlie HPD_FUNCS(ilk);
4225cd030c7cSDave Airlie #undef HPD_FUNCS
4226cd030c7cSDave Airlie 
42277e97596cSJani Nikula void intel_hpd_irq_setup(struct drm_i915_private *i915)
42287e97596cSJani Nikula {
42295a04eb5bSJani Nikula 	if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
42305a04eb5bSJani Nikula 		i915->display.funcs.hotplug->hpd_irq_setup(i915);
42317e97596cSJani Nikula }
42327e97596cSJani Nikula 
4233fca52a55SDaniel Vetter /**
4234fca52a55SDaniel Vetter  * intel_irq_init - initializes irq support
4235fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4236fca52a55SDaniel Vetter  *
4237fca52a55SDaniel Vetter  * This function initializes all the irq support including work items, timers
4238fca52a55SDaniel Vetter  * and all the vtables. It does not setup the interrupt itself though.
4239fca52a55SDaniel Vetter  */
4240b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv)
4241f71d4af4SJesse Barnes {
4242cefcff8fSJoonas Lahtinen 	int i;
42438b2e326dSChris Wilson 
424474bb98baSLucas De Marchi 	INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work);
4245cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4246cefcff8fSJoonas Lahtinen 		dev_priv->l3_parity.remap_info[i] = NULL;
42478b2e326dSChris Wilson 
4248633023a4SDaniele Ceraolo Spurio 	/* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */
4249651e7d48SLucas De Marchi 	if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11)
42502cbc876dSMichał Winiarski 		to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16;
425126705e20SSagar Arun Kamble 
42529a450b68SLucas De Marchi 	if (!HAS_DISPLAY(dev_priv))
42539a450b68SLucas De Marchi 		return;
42549a450b68SLucas De Marchi 
425596bd87b7SLucas De Marchi 	intel_hpd_init_pins(dev_priv);
425696bd87b7SLucas De Marchi 
4257dd890d42SJani Nikula 	intel_hpd_init_early(dev_priv);
425896bd87b7SLucas De Marchi 
42593703060dSAndrzej Hajda 	dev_priv->drm.vblank_disable_immediate = true;
426021da2700SVille Syrjälä 
4261262fd485SChris Wilson 	/* Most platforms treat the display irq block as an always-on
4262262fd485SChris Wilson 	 * power domain. vlv/chv can disable it at runtime and need
4263262fd485SChris Wilson 	 * special care to avoid writing any of the display block registers
4264262fd485SChris Wilson 	 * outside of the power domain. We defer setting up the display irqs
4265262fd485SChris Wilson 	 * in this case to the runtime pm.
4266262fd485SChris Wilson 	 */
4267262fd485SChris Wilson 	dev_priv->display_irqs_enabled = true;
4268262fd485SChris Wilson 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
4269262fd485SChris Wilson 		dev_priv->display_irqs_enabled = false;
4270262fd485SChris Wilson 
42712ccf2e03SChris Wilson 	if (HAS_GMCH(dev_priv)) {
42722ccf2e03SChris Wilson 		if (I915_HAS_HOTPLUG(dev_priv))
42735a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &i915_hpd_funcs;
42742ccf2e03SChris Wilson 	} else {
42752f8a6699SMatt Roper 		if (HAS_PCH_DG2(dev_priv))
42765a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
42772f8a6699SMatt Roper 		else if (HAS_PCH_DG1(dev_priv))
42785a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &dg1_hpd_funcs;
4279babde06dSMika Kahola 		else if (DISPLAY_VER(dev_priv) >= 14)
4280babde06dSMika Kahola 			dev_priv->display.funcs.hotplug = &xelpdp_hpd_funcs;
4281373abf1aSMatt Roper 		else if (DISPLAY_VER(dev_priv) >= 11)
42825a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &gen11_hpd_funcs;
428370bfb307SMatt Roper 		else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
42845a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &bxt_hpd_funcs;
4285cec3295bSLyude Paul 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
42865a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
4287c6c30b91SRodrigo Vivi 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
42885a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &spt_hpd_funcs;
42896dbf30ceSVille Syrjälä 		else
42905a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &ilk_hpd_funcs;
4291f71d4af4SJesse Barnes 	}
42922ccf2e03SChris Wilson }
429320afbda2SDaniel Vetter 
4294fca52a55SDaniel Vetter /**
4295cefcff8fSJoonas Lahtinen  * intel_irq_fini - deinitializes IRQ support
4296cefcff8fSJoonas Lahtinen  * @i915: i915 device instance
4297cefcff8fSJoonas Lahtinen  *
4298cefcff8fSJoonas Lahtinen  * This function deinitializes all the IRQ support.
4299cefcff8fSJoonas Lahtinen  */
4300cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915)
4301cefcff8fSJoonas Lahtinen {
4302cefcff8fSJoonas Lahtinen 	int i;
4303cefcff8fSJoonas Lahtinen 
4304cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4305cefcff8fSJoonas Lahtinen 		kfree(i915->l3_parity.remap_info[i]);
4306cefcff8fSJoonas Lahtinen }
4307cefcff8fSJoonas Lahtinen 
4308b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv)
4309b318b824SVille Syrjälä {
4310b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4311b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4312b318b824SVille Syrjälä 			return cherryview_irq_handler;
4313b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4314b318b824SVille Syrjälä 			return valleyview_irq_handler;
4315651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4316b318b824SVille Syrjälä 			return i965_irq_handler;
4317651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4318b318b824SVille Syrjälä 			return i915_irq_handler;
4319b318b824SVille Syrjälä 		else
4320b318b824SVille Syrjälä 			return i8xx_irq_handler;
4321b318b824SVille Syrjälä 	} else {
432222e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
432397b492f5SLucas De Marchi 			return dg1_irq_handler;
432422e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4325b318b824SVille Syrjälä 			return gen11_irq_handler;
4326651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4327b318b824SVille Syrjälä 			return gen8_irq_handler;
4328b318b824SVille Syrjälä 		else
43299eae5e27SLucas De Marchi 			return ilk_irq_handler;
4330b318b824SVille Syrjälä 	}
4331b318b824SVille Syrjälä }
4332b318b824SVille Syrjälä 
4333b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv)
4334b318b824SVille Syrjälä {
4335b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4336b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4337b318b824SVille Syrjälä 			cherryview_irq_reset(dev_priv);
4338b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4339b318b824SVille Syrjälä 			valleyview_irq_reset(dev_priv);
4340651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4341b318b824SVille Syrjälä 			i965_irq_reset(dev_priv);
4342651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4343b318b824SVille Syrjälä 			i915_irq_reset(dev_priv);
4344b318b824SVille Syrjälä 		else
4345b318b824SVille Syrjälä 			i8xx_irq_reset(dev_priv);
4346b318b824SVille Syrjälä 	} else {
434722e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
434822e26af7SPaulo Zanoni 			dg1_irq_reset(dev_priv);
434922e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4350b318b824SVille Syrjälä 			gen11_irq_reset(dev_priv);
4351651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4352b318b824SVille Syrjälä 			gen8_irq_reset(dev_priv);
4353b318b824SVille Syrjälä 		else
43549eae5e27SLucas De Marchi 			ilk_irq_reset(dev_priv);
4355b318b824SVille Syrjälä 	}
4356b318b824SVille Syrjälä }
4357b318b824SVille Syrjälä 
4358b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv)
4359b318b824SVille Syrjälä {
4360b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4361b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4362b318b824SVille Syrjälä 			cherryview_irq_postinstall(dev_priv);
4363b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4364b318b824SVille Syrjälä 			valleyview_irq_postinstall(dev_priv);
4365651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4366b318b824SVille Syrjälä 			i965_irq_postinstall(dev_priv);
4367651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4368b318b824SVille Syrjälä 			i915_irq_postinstall(dev_priv);
4369b318b824SVille Syrjälä 		else
4370b318b824SVille Syrjälä 			i8xx_irq_postinstall(dev_priv);
4371b318b824SVille Syrjälä 	} else {
437222e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
437322e26af7SPaulo Zanoni 			dg1_irq_postinstall(dev_priv);
437422e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4375b318b824SVille Syrjälä 			gen11_irq_postinstall(dev_priv);
4376651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4377b318b824SVille Syrjälä 			gen8_irq_postinstall(dev_priv);
4378b318b824SVille Syrjälä 		else
43799eae5e27SLucas De Marchi 			ilk_irq_postinstall(dev_priv);
4380b318b824SVille Syrjälä 	}
4381b318b824SVille Syrjälä }
4382b318b824SVille Syrjälä 
4383cefcff8fSJoonas Lahtinen /**
4384fca52a55SDaniel Vetter  * intel_irq_install - enables the hardware interrupt
4385fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4386fca52a55SDaniel Vetter  *
4387fca52a55SDaniel Vetter  * This function enables the hardware interrupt handling, but leaves the hotplug
4388fca52a55SDaniel Vetter  * handling still disabled. It is called after intel_irq_init().
4389fca52a55SDaniel Vetter  *
4390fca52a55SDaniel Vetter  * In the driver load and resume code we need working interrupts in a few places
4391fca52a55SDaniel Vetter  * but don't want to deal with the hassle of concurrent probe and hotplug
4392fca52a55SDaniel Vetter  * workers. Hence the split into this two-stage approach.
4393fca52a55SDaniel Vetter  */
43942aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv)
43952aeb7d3aSDaniel Vetter {
43968ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4397b318b824SVille Syrjälä 	int ret;
4398b318b824SVille Syrjälä 
43992aeb7d3aSDaniel Vetter 	/*
44002aeb7d3aSDaniel Vetter 	 * We enable some interrupt sources in our postinstall hooks, so mark
44012aeb7d3aSDaniel Vetter 	 * interrupts as enabled _before_ actually enabling them to avoid
44022aeb7d3aSDaniel Vetter 	 * special cases in our ordering checks.
44032aeb7d3aSDaniel Vetter 	 */
4404ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
44052aeb7d3aSDaniel Vetter 
4406ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = true;
4407b318b824SVille Syrjälä 
4408b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4409b318b824SVille Syrjälä 
4410b318b824SVille Syrjälä 	ret = request_irq(irq, intel_irq_handler(dev_priv),
4411b318b824SVille Syrjälä 			  IRQF_SHARED, DRIVER_NAME, dev_priv);
4412b318b824SVille Syrjälä 	if (ret < 0) {
4413ac1723c1SThomas Zimmermann 		dev_priv->irq_enabled = false;
4414b318b824SVille Syrjälä 		return ret;
4415b318b824SVille Syrjälä 	}
4416b318b824SVille Syrjälä 
4417b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4418b318b824SVille Syrjälä 
4419b318b824SVille Syrjälä 	return ret;
44202aeb7d3aSDaniel Vetter }
44212aeb7d3aSDaniel Vetter 
4422fca52a55SDaniel Vetter /**
4423fca52a55SDaniel Vetter  * intel_irq_uninstall - finilizes all irq handling
4424fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4425fca52a55SDaniel Vetter  *
4426fca52a55SDaniel Vetter  * This stops interrupt and hotplug handling and unregisters and frees all
4427fca52a55SDaniel Vetter  * resources acquired in the init functions.
4428fca52a55SDaniel Vetter  */
44292aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv)
44302aeb7d3aSDaniel Vetter {
44318ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4432b318b824SVille Syrjälä 
4433b318b824SVille Syrjälä 	/*
4434789fa874SJanusz Krzysztofik 	 * FIXME we can get called twice during driver probe
4435789fa874SJanusz Krzysztofik 	 * error handling as well as during driver remove due to
443686a1758dSJani Nikula 	 * intel_display_driver_remove() calling us out of sequence.
4437789fa874SJanusz Krzysztofik 	 * Would be nice if it didn't do that...
4438b318b824SVille Syrjälä 	 */
4439ac1723c1SThomas Zimmermann 	if (!dev_priv->irq_enabled)
4440b318b824SVille Syrjälä 		return;
4441b318b824SVille Syrjälä 
4442ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = false;
4443b318b824SVille Syrjälä 
4444b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4445b318b824SVille Syrjälä 
4446b318b824SVille Syrjälä 	free_irq(irq, dev_priv);
4447b318b824SVille Syrjälä 
44482aeb7d3aSDaniel Vetter 	intel_hpd_cancel_work(dev_priv);
4449ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
44502aeb7d3aSDaniel Vetter }
44512aeb7d3aSDaniel Vetter 
4452fca52a55SDaniel Vetter /**
4453fca52a55SDaniel Vetter  * intel_runtime_pm_disable_interrupts - runtime interrupt disabling
4454fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4455fca52a55SDaniel Vetter  *
4456fca52a55SDaniel Vetter  * This function is used to disable interrupts at runtime, both in the runtime
4457fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4458fca52a55SDaniel Vetter  */
4459b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
4460c67a470bSPaulo Zanoni {
4461b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4462ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
4463315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
4464c67a470bSPaulo Zanoni }
4465c67a470bSPaulo Zanoni 
4466fca52a55SDaniel Vetter /**
4467fca52a55SDaniel Vetter  * intel_runtime_pm_enable_interrupts - runtime interrupt enabling
4468fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4469fca52a55SDaniel Vetter  *
4470fca52a55SDaniel Vetter  * This function is used to enable interrupts at runtime, both in the runtime
4471fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4472fca52a55SDaniel Vetter  */
4473b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv)
4474c67a470bSPaulo Zanoni {
4475ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
4476b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4477b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4478c67a470bSPaulo Zanoni }
4479d64575eeSJani Nikula 
4480d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
4481d64575eeSJani Nikula {
4482d64575eeSJani Nikula 	return dev_priv->runtime_pm.irqs_enabled;
4483d64575eeSJani Nikula }
4484d64575eeSJani Nikula 
4485d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915)
4486d64575eeSJani Nikula {
44878ff5446aSThomas Zimmermann 	synchronize_irq(to_pci_dev(i915->drm.dev)->irq);
4488d64575eeSJani Nikula }
4489320ad343SThomas Zimmermann 
4490320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915)
4491320ad343SThomas Zimmermann {
4492320ad343SThomas Zimmermann 	synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq);
4493320ad343SThomas Zimmermann }
4494