xref: /openbmc/linux/drivers/gpu/drm/i915/i915_irq.c (revision c0f3faaf936b67e124e9159fb1223a689cf9e15e)
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"
57476f62b8SJani Nikula #include "i915_reg.h"
58c0e09200SDave Airlie 
59fca52a55SDaniel Vetter /**
60fca52a55SDaniel Vetter  * DOC: interrupt handling
61fca52a55SDaniel Vetter  *
62fca52a55SDaniel Vetter  * These functions provide the basic support for enabling and disabling the
63fca52a55SDaniel Vetter  * interrupt handling support. There's a lot more functionality in i915_irq.c
64fca52a55SDaniel Vetter  * and related files, but that will be described in separate chapters.
65fca52a55SDaniel Vetter  */
66fca52a55SDaniel Vetter 
679c6508b9SThomas Gleixner /*
689c6508b9SThomas Gleixner  * Interrupt statistic for PMU. Increments the counter only if the
6978f48aa6SBo Liu  * interrupt originated from the GPU so interrupts from a device which
709c6508b9SThomas Gleixner  * shares the interrupt line are not accounted.
719c6508b9SThomas Gleixner  */
729c6508b9SThomas Gleixner static inline void pmu_irq_stats(struct drm_i915_private *i915,
739c6508b9SThomas Gleixner 				 irqreturn_t res)
749c6508b9SThomas Gleixner {
759c6508b9SThomas Gleixner 	if (unlikely(res != IRQ_HANDLED))
769c6508b9SThomas Gleixner 		return;
779c6508b9SThomas Gleixner 
789c6508b9SThomas Gleixner 	/*
799c6508b9SThomas Gleixner 	 * A clever compiler translates that into INC. A not so clever one
809c6508b9SThomas Gleixner 	 * should at least prevent store tearing.
819c6508b9SThomas Gleixner 	 */
829c6508b9SThomas Gleixner 	WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1);
839c6508b9SThomas Gleixner }
849c6508b9SThomas Gleixner 
8548ef15d3SJosé Roberto de Souza typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val);
86dfefe7bcSVille Syrjälä typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder);
87a823c5a8SVille Syrjälä typedef u32 (*hotplug_mask_func)(enum hpd_pin pin);
8848ef15d3SJosé Roberto de Souza 
89e4ce95aaSVille Syrjälä static const u32 hpd_ilk[HPD_NUM_PINS] = {
90e4ce95aaSVille Syrjälä 	[HPD_PORT_A] = DE_DP_A_HOTPLUG,
91e4ce95aaSVille Syrjälä };
92e4ce95aaSVille Syrjälä 
9323bb4cb5SVille Syrjälä static const u32 hpd_ivb[HPD_NUM_PINS] = {
9423bb4cb5SVille Syrjälä 	[HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB,
9523bb4cb5SVille Syrjälä };
9623bb4cb5SVille Syrjälä 
973a3b3c7dSVille Syrjälä static const u32 hpd_bdw[HPD_NUM_PINS] = {
98e5abaab3SVille Syrjälä 	[HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
993a3b3c7dSVille Syrjälä };
1003a3b3c7dSVille Syrjälä 
1017c7e10dbSVille Syrjälä static const u32 hpd_ibx[HPD_NUM_PINS] = {
102e5868a31SEgbert Eich 	[HPD_CRT] = SDE_CRT_HOTPLUG,
103e5868a31SEgbert Eich 	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
104e5868a31SEgbert Eich 	[HPD_PORT_B] = SDE_PORTB_HOTPLUG,
105e5868a31SEgbert Eich 	[HPD_PORT_C] = SDE_PORTC_HOTPLUG,
1067203d49cSVille Syrjälä 	[HPD_PORT_D] = SDE_PORTD_HOTPLUG,
107e5868a31SEgbert Eich };
108e5868a31SEgbert Eich 
1097c7e10dbSVille Syrjälä static const u32 hpd_cpt[HPD_NUM_PINS] = {
110e5868a31SEgbert Eich 	[HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
11173c352a2SDaniel Vetter 	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
112e5868a31SEgbert Eich 	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
113e5868a31SEgbert Eich 	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
1147203d49cSVille Syrjälä 	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
115e5868a31SEgbert Eich };
116e5868a31SEgbert Eich 
11726951cafSXiong Zhang static const u32 hpd_spt[HPD_NUM_PINS] = {
11874c0b395SVille Syrjälä 	[HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT,
11926951cafSXiong Zhang 	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
12026951cafSXiong Zhang 	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
12126951cafSXiong Zhang 	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
1227203d49cSVille Syrjälä 	[HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT,
12326951cafSXiong Zhang };
12426951cafSXiong Zhang 
1257c7e10dbSVille Syrjälä static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
126e5868a31SEgbert Eich 	[HPD_CRT] = CRT_HOTPLUG_INT_EN,
127e5868a31SEgbert Eich 	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
128e5868a31SEgbert Eich 	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
129e5868a31SEgbert Eich 	[HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
130e5868a31SEgbert Eich 	[HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
1317203d49cSVille Syrjälä 	[HPD_PORT_D] = PORTD_HOTPLUG_INT_EN,
132e5868a31SEgbert Eich };
133e5868a31SEgbert Eich 
1347c7e10dbSVille Syrjälä static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
135e5868a31SEgbert Eich 	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
136e5868a31SEgbert Eich 	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
137e5868a31SEgbert Eich 	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
138e5868a31SEgbert Eich 	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
139e5868a31SEgbert Eich 	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
1407203d49cSVille Syrjälä 	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
141e5868a31SEgbert Eich };
142e5868a31SEgbert Eich 
1434bca26d0SVille Syrjälä static const u32 hpd_status_i915[HPD_NUM_PINS] = {
144e5868a31SEgbert Eich 	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
145e5868a31SEgbert Eich 	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
146e5868a31SEgbert Eich 	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
147e5868a31SEgbert Eich 	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
148e5868a31SEgbert Eich 	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
1497203d49cSVille Syrjälä 	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
150e5868a31SEgbert Eich };
151e5868a31SEgbert Eich 
152e0a20ad7SShashank Sharma static const u32 hpd_bxt[HPD_NUM_PINS] = {
153e5abaab3SVille Syrjälä 	[HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
154e5abaab3SVille Syrjälä 	[HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B),
155e5abaab3SVille Syrjälä 	[HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C),
156e0a20ad7SShashank Sharma };
157e0a20ad7SShashank Sharma 
158b796b971SDhinakaran Pandiyan static const u32 hpd_gen11[HPD_NUM_PINS] = {
1595b76e860SVille Syrjälä 	[HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1),
1605b76e860SVille Syrjälä 	[HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2),
1615b76e860SVille Syrjälä 	[HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3),
1625b76e860SVille Syrjälä 	[HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4),
1635b76e860SVille Syrjälä 	[HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5),
1645b76e860SVille Syrjälä 	[HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
16548ef15d3SJosé Roberto de Souza };
16648ef15d3SJosé Roberto de Souza 
167babde06dSMika Kahola static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
168babde06dSMika Kahola 	[HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
169babde06dSMika Kahola 	[HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
170babde06dSMika Kahola 	[HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
171babde06dSMika Kahola 	[HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
172babde06dSMika Kahola };
173babde06dSMika Kahola 
17431604222SAnusha Srivatsa static const u32 hpd_icp[HPD_NUM_PINS] = {
1755f371a81SVille Syrjälä 	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
1765f371a81SVille Syrjälä 	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
1775f371a81SVille Syrjälä 	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
17897011359SVille Syrjälä 	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
17997011359SVille Syrjälä 	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
18097011359SVille Syrjälä 	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
18197011359SVille Syrjälä 	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
18297011359SVille Syrjälä 	[HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5),
18397011359SVille Syrjälä 	[HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6),
18452dfdba0SLucas De Marchi };
18552dfdba0SLucas De Marchi 
186229f31e2SLucas De Marchi static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
1875f371a81SVille Syrjälä 	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
1885f371a81SVille Syrjälä 	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
1895f371a81SVille Syrjälä 	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
1905f371a81SVille Syrjälä 	[HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D),
1912f8a6699SMatt Roper 	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
192229f31e2SLucas De Marchi };
193229f31e2SLucas De Marchi 
194babde06dSMika Kahola static const u32 hpd_mtp[HPD_NUM_PINS] = {
195babde06dSMika Kahola 	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
196babde06dSMika Kahola 	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
197babde06dSMika Kahola 	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
198babde06dSMika Kahola 	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
199babde06dSMika Kahola 	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
200babde06dSMika Kahola 	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
201babde06dSMika Kahola };
202babde06dSMika Kahola 
2030398993bSVille Syrjälä static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
2040398993bSVille Syrjälä {
2055a4dd6f0SJani Nikula 	struct intel_hotplug *hpd = &dev_priv->display.hotplug;
2060398993bSVille Syrjälä 
2070398993bSVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
2080398993bSVille Syrjälä 		if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
2090398993bSVille Syrjälä 		    IS_CHERRYVIEW(dev_priv))
2100398993bSVille Syrjälä 			hpd->hpd = hpd_status_g4x;
2110398993bSVille Syrjälä 		else
2120398993bSVille Syrjälä 			hpd->hpd = hpd_status_i915;
2130398993bSVille Syrjälä 		return;
2140398993bSVille Syrjälä 	}
2150398993bSVille Syrjälä 
216babde06dSMika Kahola 	if (DISPLAY_VER(dev_priv) >= 14)
217babde06dSMika Kahola 		hpd->hpd = hpd_xelpdp;
218babde06dSMika Kahola 	else if (DISPLAY_VER(dev_priv) >= 11)
2190398993bSVille Syrjälä 		hpd->hpd = hpd_gen11;
22070bfb307SMatt Roper 	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
2210398993bSVille Syrjälä 		hpd->hpd = hpd_bxt;
222dded35acSVille Syrjälä 	else if (DISPLAY_VER(dev_priv) == 9)
223dded35acSVille Syrjälä 		hpd->hpd = NULL; /* no north HPD on SKL */
224373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 8)
2250398993bSVille Syrjälä 		hpd->hpd = hpd_bdw;
226373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 7)
2270398993bSVille Syrjälä 		hpd->hpd = hpd_ivb;
2280398993bSVille Syrjälä 	else
2290398993bSVille Syrjälä 		hpd->hpd = hpd_ilk;
2300398993bSVille Syrjälä 
231229f31e2SLucas De Marchi 	if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) &&
232229f31e2SLucas De Marchi 	    (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
2330398993bSVille Syrjälä 		return;
2340398993bSVille Syrjälä 
2353176fb66SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
236229f31e2SLucas De Marchi 		hpd->pch_hpd = hpd_sde_dg1;
237babde06dSMika Kahola 	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
238babde06dSMika Kahola 		hpd->pch_hpd = hpd_mtp;
239fa58c9e4SAnusha Srivatsa 	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
2400398993bSVille Syrjälä 		hpd->pch_hpd = hpd_icp;
2410398993bSVille Syrjälä 	else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
2420398993bSVille Syrjälä 		hpd->pch_hpd = hpd_spt;
2430398993bSVille Syrjälä 	else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv))
2440398993bSVille Syrjälä 		hpd->pch_hpd = hpd_cpt;
2450398993bSVille Syrjälä 	else if (HAS_PCH_IBX(dev_priv))
2460398993bSVille Syrjälä 		hpd->pch_hpd = hpd_ibx;
2470398993bSVille Syrjälä 	else
2480398993bSVille Syrjälä 		MISSING_CASE(INTEL_PCH_TYPE(dev_priv));
2490398993bSVille Syrjälä }
2500398993bSVille Syrjälä 
251aca9310aSAnshuman Gupta static void
252aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
253aca9310aSAnshuman Gupta {
2547794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
255aca9310aSAnshuman Gupta 
256aca9310aSAnshuman Gupta 	drm_crtc_handle_vblank(&crtc->base);
257aca9310aSAnshuman Gupta }
258aca9310aSAnshuman Gupta 
259cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
26068eb49b1SPaulo Zanoni 		    i915_reg_t iir, i915_reg_t ier)
26168eb49b1SPaulo Zanoni {
26265f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, imr, 0xffffffff);
26365f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, imr);
26468eb49b1SPaulo Zanoni 
26565f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, ier, 0);
26668eb49b1SPaulo Zanoni 
2675c502442SPaulo Zanoni 	/* IIR can theoretically queue up two events. Be paranoid. */
26865f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, iir, 0xffffffff);
26965f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, iir);
27065f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, iir, 0xffffffff);
27165f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, iir);
27268eb49b1SPaulo Zanoni }
2735c502442SPaulo Zanoni 
274ad7632ffSJani Nikula static void gen2_irq_reset(struct intel_uncore *uncore)
27568eb49b1SPaulo Zanoni {
27665f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IMR, 0xffff);
27765f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IMR);
278a9d356a6SPaulo Zanoni 
27965f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IER, 0);
28068eb49b1SPaulo Zanoni 
28168eb49b1SPaulo Zanoni 	/* IIR can theoretically queue up two events. Be paranoid. */
28265f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
28365f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
28465f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
28565f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
28668eb49b1SPaulo Zanoni }
28768eb49b1SPaulo Zanoni 
288337ba017SPaulo Zanoni /*
289337ba017SPaulo Zanoni  * We should clear IMR at preinstall/uninstall, and just check at postinstall.
290337ba017SPaulo Zanoni  */
29165f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
292b51a2842SVille Syrjälä {
29365f42cdcSPaulo Zanoni 	u32 val = intel_uncore_read(uncore, reg);
294b51a2842SVille Syrjälä 
295b51a2842SVille Syrjälä 	if (val == 0)
296b51a2842SVille Syrjälä 		return;
297b51a2842SVille Syrjälä 
298a9f236d1SPankaj Bharadiya 	drm_WARN(&uncore->i915->drm, 1,
299a9f236d1SPankaj Bharadiya 		 "Interrupt register 0x%x is not zero: 0x%08x\n",
300f0f59a00SVille Syrjälä 		 i915_mmio_reg_offset(reg), val);
30165f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, reg, 0xffffffff);
30265f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, reg);
30365f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, reg, 0xffffffff);
30465f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, reg);
305b51a2842SVille Syrjälä }
306337ba017SPaulo Zanoni 
30765f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore)
308e9e9848aSVille Syrjälä {
30965f42cdcSPaulo Zanoni 	u16 val = intel_uncore_read16(uncore, GEN2_IIR);
310e9e9848aSVille Syrjälä 
311e9e9848aSVille Syrjälä 	if (val == 0)
312e9e9848aSVille Syrjälä 		return;
313e9e9848aSVille Syrjälä 
314a9f236d1SPankaj Bharadiya 	drm_WARN(&uncore->i915->drm, 1,
315a9f236d1SPankaj Bharadiya 		 "Interrupt register 0x%x is not zero: 0x%08x\n",
3169d9523d8SPaulo Zanoni 		 i915_mmio_reg_offset(GEN2_IIR), val);
31765f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
31865f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
31965f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
32065f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
321e9e9848aSVille Syrjälä }
322e9e9848aSVille Syrjälä 
323cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore,
32468eb49b1SPaulo Zanoni 		   i915_reg_t imr, u32 imr_val,
32568eb49b1SPaulo Zanoni 		   i915_reg_t ier, u32 ier_val,
32668eb49b1SPaulo Zanoni 		   i915_reg_t iir)
32768eb49b1SPaulo Zanoni {
32865f42cdcSPaulo Zanoni 	gen3_assert_iir_is_zero(uncore, iir);
32935079899SPaulo Zanoni 
33065f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, ier, ier_val);
33165f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, imr, imr_val);
33265f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, imr);
33368eb49b1SPaulo Zanoni }
33435079899SPaulo Zanoni 
335ad7632ffSJani Nikula static void gen2_irq_init(struct intel_uncore *uncore,
3362918c3caSPaulo Zanoni 			  u32 imr_val, u32 ier_val)
33768eb49b1SPaulo Zanoni {
33865f42cdcSPaulo Zanoni 	gen2_assert_iir_is_zero(uncore);
33968eb49b1SPaulo Zanoni 
34065f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IER, ier_val);
34165f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IMR, imr_val);
34265f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IMR);
34368eb49b1SPaulo Zanoni }
34468eb49b1SPaulo Zanoni 
3450706f17cSEgbert Eich /* For display hotplug interrupt */
3460706f17cSEgbert Eich static inline void
3470706f17cSEgbert Eich i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
348a9c287c9SJani Nikula 				     u32 mask,
349a9c287c9SJani Nikula 				     u32 bits)
3500706f17cSEgbert Eich {
35167520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
35248a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, bits & ~mask);
3530706f17cSEgbert Eich 
3548cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits);
3550706f17cSEgbert Eich }
3560706f17cSEgbert Eich 
3570706f17cSEgbert Eich /**
3580706f17cSEgbert Eich  * i915_hotplug_interrupt_update - update hotplug interrupt enable
3590706f17cSEgbert Eich  * @dev_priv: driver private
3600706f17cSEgbert Eich  * @mask: bits to update
3610706f17cSEgbert Eich  * @bits: bits to enable
3620706f17cSEgbert Eich  * NOTE: the HPD enable bits are modified both inside and outside
3630706f17cSEgbert Eich  * of an interrupt context. To avoid that read-modify-write cycles
3640706f17cSEgbert Eich  * interfer, these bits are protected by a spinlock. Since this
3650706f17cSEgbert Eich  * function is usually not called from a context where the lock is
3660706f17cSEgbert Eich  * held already, this function acquires the lock itself. A non-locking
3670706f17cSEgbert Eich  * version is also available.
3680706f17cSEgbert Eich  */
3690706f17cSEgbert Eich void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
370a9c287c9SJani Nikula 				   u32 mask,
371a9c287c9SJani Nikula 				   u32 bits)
3720706f17cSEgbert Eich {
3730706f17cSEgbert Eich 	spin_lock_irq(&dev_priv->irq_lock);
3740706f17cSEgbert Eich 	i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
3750706f17cSEgbert Eich 	spin_unlock_irq(&dev_priv->irq_lock);
3760706f17cSEgbert Eich }
3770706f17cSEgbert Eich 
378d9dc34f1SVille Syrjälä /**
379d9dc34f1SVille Syrjälä  * ilk_update_display_irq - update DEIMR
380d9dc34f1SVille Syrjälä  * @dev_priv: driver private
381d9dc34f1SVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
382d9dc34f1SVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
383d9dc34f1SVille Syrjälä  */
3849e6dcf33SJani Nikula static void ilk_update_display_irq(struct drm_i915_private *dev_priv,
3859e6dcf33SJani Nikula 				   u32 interrupt_mask, u32 enabled_irq_mask)
386036a4a7dSZhenyu Wang {
387a9c287c9SJani Nikula 	u32 new_val;
388d9dc34f1SVille Syrjälä 
38967520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
39048a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
391d9dc34f1SVille Syrjälä 
392d9dc34f1SVille Syrjälä 	new_val = dev_priv->irq_mask;
393d9dc34f1SVille Syrjälä 	new_val &= ~interrupt_mask;
394d9dc34f1SVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
395d9dc34f1SVille Syrjälä 
396e44adb5dSChris Wilson 	if (new_val != dev_priv->irq_mask &&
397e44adb5dSChris Wilson 	    !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) {
398d9dc34f1SVille Syrjälä 		dev_priv->irq_mask = new_val;
3992939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask);
4002939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, DEIMR);
401036a4a7dSZhenyu Wang 	}
402036a4a7dSZhenyu Wang }
403036a4a7dSZhenyu Wang 
4049e6dcf33SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits)
4059e6dcf33SJani Nikula {
4069e6dcf33SJani Nikula 	ilk_update_display_irq(i915, bits, bits);
4079e6dcf33SJani Nikula }
4089e6dcf33SJani Nikula 
4099e6dcf33SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits)
4109e6dcf33SJani Nikula {
4119e6dcf33SJani Nikula 	ilk_update_display_irq(i915, bits, 0);
4129e6dcf33SJani Nikula }
4139e6dcf33SJani Nikula 
4140961021aSBen Widawsky /**
4153a3b3c7dSVille Syrjälä  * bdw_update_port_irq - update DE port interrupt
4163a3b3c7dSVille Syrjälä  * @dev_priv: driver private
4173a3b3c7dSVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
4183a3b3c7dSVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
4193a3b3c7dSVille Syrjälä  */
4203a3b3c7dSVille Syrjälä static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
421a9c287c9SJani Nikula 				u32 interrupt_mask,
422a9c287c9SJani Nikula 				u32 enabled_irq_mask)
4233a3b3c7dSVille Syrjälä {
424a9c287c9SJani Nikula 	u32 new_val;
425a9c287c9SJani Nikula 	u32 old_val;
4263a3b3c7dSVille Syrjälä 
42767520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
4283a3b3c7dSVille Syrjälä 
42948a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
4303a3b3c7dSVille Syrjälä 
43148a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
4323a3b3c7dSVille Syrjälä 		return;
4333a3b3c7dSVille Syrjälä 
4342939eb06SJani Nikula 	old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
4353a3b3c7dSVille Syrjälä 
4363a3b3c7dSVille Syrjälä 	new_val = old_val;
4373a3b3c7dSVille Syrjälä 	new_val &= ~interrupt_mask;
4383a3b3c7dSVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
4393a3b3c7dSVille Syrjälä 
4403a3b3c7dSVille Syrjälä 	if (new_val != old_val) {
4412939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val);
4422939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
4433a3b3c7dSVille Syrjälä 	}
4443a3b3c7dSVille Syrjälä }
4453a3b3c7dSVille Syrjälä 
4463a3b3c7dSVille Syrjälä /**
447013d3752SVille Syrjälä  * bdw_update_pipe_irq - update DE pipe interrupt
448013d3752SVille Syrjälä  * @dev_priv: driver private
449013d3752SVille Syrjälä  * @pipe: pipe whose interrupt to update
450013d3752SVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
451013d3752SVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
452013d3752SVille Syrjälä  */
4539e6dcf33SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
4549e6dcf33SJani Nikula 				enum pipe pipe, u32 interrupt_mask,
455a9c287c9SJani Nikula 				u32 enabled_irq_mask)
456013d3752SVille Syrjälä {
457a9c287c9SJani Nikula 	u32 new_val;
458013d3752SVille Syrjälä 
45967520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
460013d3752SVille Syrjälä 
46148a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
462013d3752SVille Syrjälä 
46348a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
464013d3752SVille Syrjälä 		return;
465013d3752SVille Syrjälä 
466013d3752SVille Syrjälä 	new_val = dev_priv->de_irq_mask[pipe];
467013d3752SVille Syrjälä 	new_val &= ~interrupt_mask;
468013d3752SVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
469013d3752SVille Syrjälä 
470013d3752SVille Syrjälä 	if (new_val != dev_priv->de_irq_mask[pipe]) {
471013d3752SVille Syrjälä 		dev_priv->de_irq_mask[pipe] = new_val;
4722939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
4732939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe));
474013d3752SVille Syrjälä 	}
475013d3752SVille Syrjälä }
476013d3752SVille Syrjälä 
4779e6dcf33SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915,
4789e6dcf33SJani Nikula 			 enum pipe pipe, u32 bits)
4799e6dcf33SJani Nikula {
4809e6dcf33SJani Nikula 	bdw_update_pipe_irq(i915, pipe, bits, bits);
4819e6dcf33SJani Nikula }
4829e6dcf33SJani Nikula 
4839e6dcf33SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915,
4849e6dcf33SJani Nikula 			  enum pipe pipe, u32 bits)
4859e6dcf33SJani Nikula {
4869e6dcf33SJani Nikula 	bdw_update_pipe_irq(i915, pipe, bits, 0);
4879e6dcf33SJani Nikula }
4889e6dcf33SJani Nikula 
489013d3752SVille Syrjälä /**
490fee884edSDaniel Vetter  * ibx_display_interrupt_update - update SDEIMR
491fee884edSDaniel Vetter  * @dev_priv: driver private
492fee884edSDaniel Vetter  * @interrupt_mask: mask of interrupt bits to update
493fee884edSDaniel Vetter  * @enabled_irq_mask: mask of interrupt bits to enable
494fee884edSDaniel Vetter  */
4959e6dcf33SJani Nikula static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
496a9c287c9SJani Nikula 					 u32 interrupt_mask,
497a9c287c9SJani Nikula 					 u32 enabled_irq_mask)
498fee884edSDaniel Vetter {
4992939eb06SJani Nikula 	u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR);
500fee884edSDaniel Vetter 	sdeimr &= ~interrupt_mask;
501fee884edSDaniel Vetter 	sdeimr |= (~enabled_irq_mask & interrupt_mask);
502fee884edSDaniel Vetter 
50348a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
50415a17aaeSDaniel Vetter 
50567520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
506fee884edSDaniel Vetter 
50748a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
508c67a470bSPaulo Zanoni 		return;
509c67a470bSPaulo Zanoni 
5102939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr);
5112939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, SDEIMR);
512fee884edSDaniel Vetter }
5138664281bSPaulo Zanoni 
5149e6dcf33SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits)
5159e6dcf33SJani Nikula {
5169e6dcf33SJani Nikula 	ibx_display_interrupt_update(i915, bits, bits);
5179e6dcf33SJani Nikula }
5189e6dcf33SJani Nikula 
5199e6dcf33SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits)
5209e6dcf33SJani Nikula {
5219e6dcf33SJani Nikula 	ibx_display_interrupt_update(i915, bits, 0);
5229e6dcf33SJani Nikula }
5239e6dcf33SJani Nikula 
5246b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv,
5256b12ca56SVille Syrjälä 			      enum pipe pipe)
5267c463586SKeith Packard {
5276b12ca56SVille Syrjälä 	u32 status_mask = dev_priv->pipestat_irq_mask[pipe];
52810c59c51SImre Deak 	u32 enable_mask = status_mask << 16;
52910c59c51SImre Deak 
5306b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
5316b12ca56SVille Syrjälä 
532373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) < 5)
5336b12ca56SVille Syrjälä 		goto out;
5346b12ca56SVille Syrjälä 
53510c59c51SImre Deak 	/*
536724a6905SVille Syrjälä 	 * On pipe A we don't support the PSR interrupt yet,
537724a6905SVille Syrjälä 	 * on pipe B and C the same bit MBZ.
53810c59c51SImre Deak 	 */
53948a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON_ONCE(&dev_priv->drm,
54048a1b8d4SPankaj Bharadiya 			     status_mask & PIPE_A_PSR_STATUS_VLV))
54110c59c51SImre Deak 		return 0;
542724a6905SVille Syrjälä 	/*
543724a6905SVille Syrjälä 	 * On pipe B and C we don't support the PSR interrupt yet, on pipe
544724a6905SVille Syrjälä 	 * A the same bit is for perf counters which we don't use either.
545724a6905SVille Syrjälä 	 */
54648a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON_ONCE(&dev_priv->drm,
54748a1b8d4SPankaj Bharadiya 			     status_mask & PIPE_B_PSR_STATUS_VLV))
548724a6905SVille Syrjälä 		return 0;
54910c59c51SImre Deak 
55010c59c51SImre Deak 	enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
55110c59c51SImre Deak 			 SPRITE0_FLIP_DONE_INT_EN_VLV |
55210c59c51SImre Deak 			 SPRITE1_FLIP_DONE_INT_EN_VLV);
55310c59c51SImre Deak 	if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
55410c59c51SImre Deak 		enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
55510c59c51SImre Deak 	if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
55610c59c51SImre Deak 		enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
55710c59c51SImre Deak 
5586b12ca56SVille Syrjälä out:
55948a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm,
56048a1b8d4SPankaj Bharadiya 		      enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
5616b12ca56SVille Syrjälä 		      status_mask & ~PIPESTAT_INT_STATUS_MASK,
5626b12ca56SVille Syrjälä 		      "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
5636b12ca56SVille Syrjälä 		      pipe_name(pipe), enable_mask, status_mask);
5646b12ca56SVille Syrjälä 
56510c59c51SImre Deak 	return enable_mask;
56610c59c51SImre Deak }
56710c59c51SImre Deak 
5686b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv,
5696b12ca56SVille Syrjälä 			  enum pipe pipe, u32 status_mask)
570755e9019SImre Deak {
5716b12ca56SVille Syrjälä 	i915_reg_t reg = PIPESTAT(pipe);
572755e9019SImre Deak 	u32 enable_mask;
573755e9019SImre Deak 
57448a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
5756b12ca56SVille Syrjälä 		      "pipe %c: status_mask=0x%x\n",
5766b12ca56SVille Syrjälä 		      pipe_name(pipe), status_mask);
5776b12ca56SVille Syrjälä 
5786b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
57948a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
5806b12ca56SVille Syrjälä 
5816b12ca56SVille Syrjälä 	if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask)
5826b12ca56SVille Syrjälä 		return;
5836b12ca56SVille Syrjälä 
5846b12ca56SVille Syrjälä 	dev_priv->pipestat_irq_mask[pipe] |= status_mask;
5856b12ca56SVille Syrjälä 	enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
5866b12ca56SVille Syrjälä 
5872939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
5882939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, reg);
589755e9019SImre Deak }
590755e9019SImre Deak 
5916b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv,
5926b12ca56SVille Syrjälä 			   enum pipe pipe, u32 status_mask)
593755e9019SImre Deak {
5946b12ca56SVille Syrjälä 	i915_reg_t reg = PIPESTAT(pipe);
595755e9019SImre Deak 	u32 enable_mask;
596755e9019SImre Deak 
59748a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
5986b12ca56SVille Syrjälä 		      "pipe %c: status_mask=0x%x\n",
5996b12ca56SVille Syrjälä 		      pipe_name(pipe), status_mask);
6006b12ca56SVille Syrjälä 
6016b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
60248a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
6036b12ca56SVille Syrjälä 
6046b12ca56SVille Syrjälä 	if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0)
6056b12ca56SVille Syrjälä 		return;
6066b12ca56SVille Syrjälä 
6076b12ca56SVille Syrjälä 	dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
6086b12ca56SVille Syrjälä 	enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
6096b12ca56SVille Syrjälä 
6102939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
6112939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, reg);
612755e9019SImre Deak }
613755e9019SImre Deak 
614f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv)
615f3e30485SVille Syrjälä {
6167249dfcbSJani Nikula 	if (!dev_priv->display.opregion.asle)
617f3e30485SVille Syrjälä 		return false;
618f3e30485SVille Syrjälä 
619f3e30485SVille Syrjälä 	return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
620f3e30485SVille Syrjälä }
621f3e30485SVille Syrjälä 
622c0e09200SDave Airlie /**
623f49e38ddSJani Nikula  * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
62414bb2c11STvrtko Ursulin  * @dev_priv: i915 device private
62501c66889SZhao Yakui  */
62691d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
62701c66889SZhao Yakui {
628f3e30485SVille Syrjälä 	if (!i915_has_asle(dev_priv))
629f49e38ddSJani Nikula 		return;
630f49e38ddSJani Nikula 
63113321786SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
63201c66889SZhao Yakui 
633755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
634373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 4)
6353b6c42e8SDaniel Vetter 		i915_enable_pipestat(dev_priv, PIPE_A,
636755e9019SImre Deak 				     PIPE_LEGACY_BLC_EVENT_STATUS);
6371ec14ad3SChris Wilson 
63813321786SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
63901c66889SZhao Yakui }
64001c66889SZhao Yakui 
641e3689190SBen Widawsky /**
64274bb98baSLucas De Marchi  * ivb_parity_work - Workqueue called when a parity error interrupt
643e3689190SBen Widawsky  * occurred.
644e3689190SBen Widawsky  * @work: workqueue struct
645e3689190SBen Widawsky  *
646e3689190SBen Widawsky  * Doesn't actually do anything except notify userspace. As a consequence of
647e3689190SBen Widawsky  * this event, userspace should try to remap the bad rows since statistically
648e3689190SBen Widawsky  * it is likely the same row is more likely to go bad again.
649e3689190SBen Widawsky  */
65074bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work)
651e3689190SBen Widawsky {
6522d1013ddSJani Nikula 	struct drm_i915_private *dev_priv =
653cefcff8fSJoonas Lahtinen 		container_of(work, typeof(*dev_priv), l3_parity.error_work);
6542cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
655e3689190SBen Widawsky 	u32 error_status, row, bank, subbank;
65635a85ac6SBen Widawsky 	char *parity_event[6];
657a9c287c9SJani Nikula 	u32 misccpctl;
658a9c287c9SJani Nikula 	u8 slice = 0;
659e3689190SBen Widawsky 
660e3689190SBen Widawsky 	/* We must turn off DOP level clock gating to access the L3 registers.
661e3689190SBen Widawsky 	 * In order to prevent a get/put style interface, acquire struct mutex
662e3689190SBen Widawsky 	 * any time we access those registers.
663e3689190SBen Widawsky 	 */
66491c8a326SChris Wilson 	mutex_lock(&dev_priv->drm.struct_mutex);
665e3689190SBen Widawsky 
66635a85ac6SBen Widawsky 	/* If we've screwed up tracking, just let the interrupt fire again */
66748a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice))
66835a85ac6SBen Widawsky 		goto out;
66935a85ac6SBen Widawsky 
670f7435467SAndrzej Hajda 	misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL,
671f7435467SAndrzej Hajda 				     GEN7_DOP_CLOCK_GATE_ENABLE, 0);
6722939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL);
673e3689190SBen Widawsky 
67435a85ac6SBen Widawsky 	while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) {
675f0f59a00SVille Syrjälä 		i915_reg_t reg;
67635a85ac6SBen Widawsky 
67735a85ac6SBen Widawsky 		slice--;
67848a1b8d4SPankaj Bharadiya 		if (drm_WARN_ON_ONCE(&dev_priv->drm,
67948a1b8d4SPankaj Bharadiya 				     slice >= NUM_L3_SLICES(dev_priv)))
68035a85ac6SBen Widawsky 			break;
68135a85ac6SBen Widawsky 
68235a85ac6SBen Widawsky 		dev_priv->l3_parity.which_slice &= ~(1<<slice);
68335a85ac6SBen Widawsky 
6846fa1c5f1SVille Syrjälä 		reg = GEN7_L3CDERRST1(slice);
68535a85ac6SBen Widawsky 
6862939eb06SJani Nikula 		error_status = intel_uncore_read(&dev_priv->uncore, reg);
687e3689190SBen Widawsky 		row = GEN7_PARITY_ERROR_ROW(error_status);
688e3689190SBen Widawsky 		bank = GEN7_PARITY_ERROR_BANK(error_status);
689e3689190SBen Widawsky 		subbank = GEN7_PARITY_ERROR_SUBBANK(error_status);
690e3689190SBen Widawsky 
6912939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE);
6922939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, reg);
693e3689190SBen Widawsky 
694cce723edSBen Widawsky 		parity_event[0] = I915_L3_PARITY_UEVENT "=1";
695e3689190SBen Widawsky 		parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row);
696e3689190SBen Widawsky 		parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank);
697e3689190SBen Widawsky 		parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank);
69835a85ac6SBen Widawsky 		parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice);
69935a85ac6SBen Widawsky 		parity_event[5] = NULL;
700e3689190SBen Widawsky 
70191c8a326SChris Wilson 		kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj,
702e3689190SBen Widawsky 				   KOBJ_CHANGE, parity_event);
703e3689190SBen Widawsky 
704a10234fdSTvrtko Ursulin 		drm_dbg(&dev_priv->drm,
705a10234fdSTvrtko Ursulin 			"Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
70635a85ac6SBen Widawsky 			slice, row, bank, subbank);
707e3689190SBen Widawsky 
70835a85ac6SBen Widawsky 		kfree(parity_event[4]);
709e3689190SBen Widawsky 		kfree(parity_event[3]);
710e3689190SBen Widawsky 		kfree(parity_event[2]);
711e3689190SBen Widawsky 		kfree(parity_event[1]);
712e3689190SBen Widawsky 	}
713e3689190SBen Widawsky 
7142939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl);
71535a85ac6SBen Widawsky 
71635a85ac6SBen Widawsky out:
71748a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice);
71803d2c54dSMatt Roper 	spin_lock_irq(gt->irq_lock);
719cf1c97dcSAndi Shyti 	gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv));
72003d2c54dSMatt Roper 	spin_unlock_irq(gt->irq_lock);
72135a85ac6SBen Widawsky 
72291c8a326SChris Wilson 	mutex_unlock(&dev_priv->drm.struct_mutex);
72335a85ac6SBen Widawsky }
72435a85ac6SBen Widawsky 
725af92058fSVille Syrjälä static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
726121e758eSDhinakaran Pandiyan {
727af92058fSVille Syrjälä 	switch (pin) {
728da51e4baSVille Syrjälä 	case HPD_PORT_TC1:
729da51e4baSVille Syrjälä 	case HPD_PORT_TC2:
730da51e4baSVille Syrjälä 	case HPD_PORT_TC3:
731da51e4baSVille Syrjälä 	case HPD_PORT_TC4:
732da51e4baSVille Syrjälä 	case HPD_PORT_TC5:
733da51e4baSVille Syrjälä 	case HPD_PORT_TC6:
7344294fa5fSVille Syrjälä 		return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin);
73548ef15d3SJosé Roberto de Souza 	default:
73648ef15d3SJosé Roberto de Souza 		return false;
73748ef15d3SJosé Roberto de Souza 	}
73848ef15d3SJosé Roberto de Souza }
73948ef15d3SJosé Roberto de Souza 
740af92058fSVille Syrjälä static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
74163c88d22SImre Deak {
742af92058fSVille Syrjälä 	switch (pin) {
743af92058fSVille Syrjälä 	case HPD_PORT_A:
744195baa06SVille Syrjälä 		return val & PORTA_HOTPLUG_LONG_DETECT;
745af92058fSVille Syrjälä 	case HPD_PORT_B:
74663c88d22SImre Deak 		return val & PORTB_HOTPLUG_LONG_DETECT;
747af92058fSVille Syrjälä 	case HPD_PORT_C:
74863c88d22SImre Deak 		return val & PORTC_HOTPLUG_LONG_DETECT;
74963c88d22SImre Deak 	default:
75063c88d22SImre Deak 		return false;
75163c88d22SImre Deak 	}
75263c88d22SImre Deak }
75363c88d22SImre Deak 
754af92058fSVille Syrjälä static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
75531604222SAnusha Srivatsa {
756af92058fSVille Syrjälä 	switch (pin) {
757af92058fSVille Syrjälä 	case HPD_PORT_A:
758af92058fSVille Syrjälä 	case HPD_PORT_B:
7598ef7e340SMatt Roper 	case HPD_PORT_C:
760229f31e2SLucas De Marchi 	case HPD_PORT_D:
7614294fa5fSVille Syrjälä 		return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin);
76231604222SAnusha Srivatsa 	default:
76331604222SAnusha Srivatsa 		return false;
76431604222SAnusha Srivatsa 	}
76531604222SAnusha Srivatsa }
76631604222SAnusha Srivatsa 
767af92058fSVille Syrjälä static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
76831604222SAnusha Srivatsa {
769af92058fSVille Syrjälä 	switch (pin) {
770da51e4baSVille Syrjälä 	case HPD_PORT_TC1:
771da51e4baSVille Syrjälä 	case HPD_PORT_TC2:
772da51e4baSVille Syrjälä 	case HPD_PORT_TC3:
773da51e4baSVille Syrjälä 	case HPD_PORT_TC4:
774da51e4baSVille Syrjälä 	case HPD_PORT_TC5:
775da51e4baSVille Syrjälä 	case HPD_PORT_TC6:
7764294fa5fSVille Syrjälä 		return val & ICP_TC_HPD_LONG_DETECT(pin);
77752dfdba0SLucas De Marchi 	default:
77852dfdba0SLucas De Marchi 		return false;
77952dfdba0SLucas De Marchi 	}
78052dfdba0SLucas De Marchi }
78152dfdba0SLucas De Marchi 
782af92058fSVille Syrjälä static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val)
7836dbf30ceSVille Syrjälä {
784af92058fSVille Syrjälä 	switch (pin) {
785af92058fSVille Syrjälä 	case HPD_PORT_E:
7866dbf30ceSVille Syrjälä 		return val & PORTE_HOTPLUG_LONG_DETECT;
7876dbf30ceSVille Syrjälä 	default:
7886dbf30ceSVille Syrjälä 		return false;
7896dbf30ceSVille Syrjälä 	}
7906dbf30ceSVille Syrjälä }
7916dbf30ceSVille Syrjälä 
792af92058fSVille Syrjälä static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
79374c0b395SVille Syrjälä {
794af92058fSVille Syrjälä 	switch (pin) {
795af92058fSVille Syrjälä 	case HPD_PORT_A:
79674c0b395SVille Syrjälä 		return val & PORTA_HOTPLUG_LONG_DETECT;
797af92058fSVille Syrjälä 	case HPD_PORT_B:
79874c0b395SVille Syrjälä 		return val & PORTB_HOTPLUG_LONG_DETECT;
799af92058fSVille Syrjälä 	case HPD_PORT_C:
80074c0b395SVille Syrjälä 		return val & PORTC_HOTPLUG_LONG_DETECT;
801af92058fSVille Syrjälä 	case HPD_PORT_D:
80274c0b395SVille Syrjälä 		return val & PORTD_HOTPLUG_LONG_DETECT;
80374c0b395SVille Syrjälä 	default:
80474c0b395SVille Syrjälä 		return false;
80574c0b395SVille Syrjälä 	}
80674c0b395SVille Syrjälä }
80774c0b395SVille Syrjälä 
808af92058fSVille Syrjälä static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
809e4ce95aaSVille Syrjälä {
810af92058fSVille Syrjälä 	switch (pin) {
811af92058fSVille Syrjälä 	case HPD_PORT_A:
812e4ce95aaSVille Syrjälä 		return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
813e4ce95aaSVille Syrjälä 	default:
814e4ce95aaSVille Syrjälä 		return false;
815e4ce95aaSVille Syrjälä 	}
816e4ce95aaSVille Syrjälä }
817e4ce95aaSVille Syrjälä 
818af92058fSVille Syrjälä static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
81913cf5504SDave Airlie {
820af92058fSVille Syrjälä 	switch (pin) {
821af92058fSVille Syrjälä 	case HPD_PORT_B:
822676574dfSJani Nikula 		return val & PORTB_HOTPLUG_LONG_DETECT;
823af92058fSVille Syrjälä 	case HPD_PORT_C:
824676574dfSJani Nikula 		return val & PORTC_HOTPLUG_LONG_DETECT;
825af92058fSVille Syrjälä 	case HPD_PORT_D:
826676574dfSJani Nikula 		return val & PORTD_HOTPLUG_LONG_DETECT;
827676574dfSJani Nikula 	default:
828676574dfSJani Nikula 		return false;
82913cf5504SDave Airlie 	}
83013cf5504SDave Airlie }
83113cf5504SDave Airlie 
832af92058fSVille Syrjälä static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
83313cf5504SDave Airlie {
834af92058fSVille Syrjälä 	switch (pin) {
835af92058fSVille Syrjälä 	case HPD_PORT_B:
836676574dfSJani Nikula 		return val & PORTB_HOTPLUG_INT_LONG_PULSE;
837af92058fSVille Syrjälä 	case HPD_PORT_C:
838676574dfSJani Nikula 		return val & PORTC_HOTPLUG_INT_LONG_PULSE;
839af92058fSVille Syrjälä 	case HPD_PORT_D:
840676574dfSJani Nikula 		return val & PORTD_HOTPLUG_INT_LONG_PULSE;
841676574dfSJani Nikula 	default:
842676574dfSJani Nikula 		return false;
84313cf5504SDave Airlie 	}
84413cf5504SDave Airlie }
84513cf5504SDave Airlie 
84642db67d6SVille Syrjälä /*
84742db67d6SVille Syrjälä  * Get a bit mask of pins that have triggered, and which ones may be long.
84842db67d6SVille Syrjälä  * This can be called multiple times with the same masks to accumulate
84942db67d6SVille Syrjälä  * hotplug detection results from several registers.
85042db67d6SVille Syrjälä  *
85142db67d6SVille Syrjälä  * Note that the caller is expected to zero out the masks initially.
85242db67d6SVille Syrjälä  */
853cf53902fSRodrigo Vivi static void intel_get_hpd_pins(struct drm_i915_private *dev_priv,
854cf53902fSRodrigo Vivi 			       u32 *pin_mask, u32 *long_mask,
8558c841e57SJani Nikula 			       u32 hotplug_trigger, u32 dig_hotplug_reg,
856fd63e2a9SImre Deak 			       const u32 hpd[HPD_NUM_PINS],
857af92058fSVille Syrjälä 			       bool long_pulse_detect(enum hpd_pin pin, u32 val))
858676574dfSJani Nikula {
859e9be2850SVille Syrjälä 	enum hpd_pin pin;
860676574dfSJani Nikula 
86152dfdba0SLucas De Marchi 	BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS);
86252dfdba0SLucas De Marchi 
863e9be2850SVille Syrjälä 	for_each_hpd_pin(pin) {
864e9be2850SVille Syrjälä 		if ((hpd[pin] & hotplug_trigger) == 0)
8658c841e57SJani Nikula 			continue;
8668c841e57SJani Nikula 
867e9be2850SVille Syrjälä 		*pin_mask |= BIT(pin);
868676574dfSJani Nikula 
869af92058fSVille Syrjälä 		if (long_pulse_detect(pin, dig_hotplug_reg))
870e9be2850SVille Syrjälä 			*long_mask |= BIT(pin);
871676574dfSJani Nikula 	}
872676574dfSJani Nikula 
87300376ccfSWambui Karuga 	drm_dbg(&dev_priv->drm,
87400376ccfSWambui Karuga 		"hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n",
875f88f0478SVille Syrjälä 		hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask);
876676574dfSJani Nikula 
877676574dfSJani Nikula }
878676574dfSJani Nikula 
879a0e066b8SVille Syrjälä static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
880a0e066b8SVille Syrjälä 				  const u32 hpd[HPD_NUM_PINS])
881a0e066b8SVille Syrjälä {
882a0e066b8SVille Syrjälä 	struct intel_encoder *encoder;
883a0e066b8SVille Syrjälä 	u32 enabled_irqs = 0;
884a0e066b8SVille Syrjälä 
885a0e066b8SVille Syrjälä 	for_each_intel_encoder(&dev_priv->drm, encoder)
8865a4dd6f0SJani Nikula 		if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
887a0e066b8SVille Syrjälä 			enabled_irqs |= hpd[encoder->hpd_pin];
888a0e066b8SVille Syrjälä 
889a0e066b8SVille Syrjälä 	return enabled_irqs;
890a0e066b8SVille Syrjälä }
891a0e066b8SVille Syrjälä 
892a0e066b8SVille Syrjälä static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv,
893a0e066b8SVille Syrjälä 				  const u32 hpd[HPD_NUM_PINS])
894a0e066b8SVille Syrjälä {
895a0e066b8SVille Syrjälä 	struct intel_encoder *encoder;
896a0e066b8SVille Syrjälä 	u32 hotplug_irqs = 0;
897a0e066b8SVille Syrjälä 
898a0e066b8SVille Syrjälä 	for_each_intel_encoder(&dev_priv->drm, encoder)
899a0e066b8SVille Syrjälä 		hotplug_irqs |= hpd[encoder->hpd_pin];
900a0e066b8SVille Syrjälä 
901a0e066b8SVille Syrjälä 	return hotplug_irqs;
902a0e066b8SVille Syrjälä }
903a0e066b8SVille Syrjälä 
904a823c5a8SVille Syrjälä static u32 intel_hpd_hotplug_mask(struct drm_i915_private *i915,
905a823c5a8SVille Syrjälä 				  hotplug_mask_func hotplug_mask)
906a823c5a8SVille Syrjälä {
907a823c5a8SVille Syrjälä 	enum hpd_pin pin;
908a823c5a8SVille Syrjälä 	u32 hotplug = 0;
909a823c5a8SVille Syrjälä 
910a823c5a8SVille Syrjälä 	for_each_hpd_pin(pin)
911a823c5a8SVille Syrjälä 		hotplug |= hotplug_mask(pin);
912a823c5a8SVille Syrjälä 
913a823c5a8SVille Syrjälä 	return hotplug;
914a823c5a8SVille Syrjälä }
915a823c5a8SVille Syrjälä 
9162ea63927SVille Syrjälä static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915,
9172ea63927SVille Syrjälä 				     hotplug_enables_func hotplug_enables)
9182ea63927SVille Syrjälä {
9192ea63927SVille Syrjälä 	struct intel_encoder *encoder;
9202ea63927SVille Syrjälä 	u32 hotplug = 0;
9212ea63927SVille Syrjälä 
9222ea63927SVille Syrjälä 	for_each_intel_encoder(&i915->drm, encoder)
923dfefe7bcSVille Syrjälä 		hotplug |= hotplug_enables(encoder);
9242ea63927SVille Syrjälä 
9252ea63927SVille Syrjälä 	return hotplug;
9262ea63927SVille Syrjälä }
9272ea63927SVille Syrjälä 
92891d14251STvrtko Ursulin static void gmbus_irq_handler(struct drm_i915_private *dev_priv)
929515ac2bbSDaniel Vetter {
930203eb5a9SJani Nikula 	wake_up_all(&dev_priv->display.gmbus.wait_queue);
931515ac2bbSDaniel Vetter }
932515ac2bbSDaniel Vetter 
93391d14251STvrtko Ursulin static void dp_aux_irq_handler(struct drm_i915_private *dev_priv)
934ce99c256SDaniel Vetter {
935203eb5a9SJani Nikula 	wake_up_all(&dev_priv->display.gmbus.wait_queue);
936ce99c256SDaniel Vetter }
937ce99c256SDaniel Vetter 
9388bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS)
93991d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
94091d14251STvrtko Ursulin 					 enum pipe pipe,
941a9c287c9SJani Nikula 					 u32 crc0, u32 crc1,
942a9c287c9SJani Nikula 					 u32 crc2, u32 crc3,
943a9c287c9SJani Nikula 					 u32 crc4)
9448bf1e9f1SShuang He {
9457794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
94600535527SJani Nikula 	struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
9475cee6c45SVille Syrjälä 	u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 };
9485cee6c45SVille Syrjälä 
9495cee6c45SVille Syrjälä 	trace_intel_pipe_crc(crtc, crcs);
950b2c88f5bSDamien Lespiau 
951d538bbdfSDamien Lespiau 	spin_lock(&pipe_crc->lock);
9528c6b709dSTomeu Vizoso 	/*
9538c6b709dSTomeu Vizoso 	 * For some not yet identified reason, the first CRC is
9548c6b709dSTomeu Vizoso 	 * bonkers. So let's just wait for the next vblank and read
9558c6b709dSTomeu Vizoso 	 * out the buggy result.
9568c6b709dSTomeu Vizoso 	 *
957163e8aecSRodrigo Vivi 	 * On GEN8+ sometimes the second CRC is bonkers as well, so
9588c6b709dSTomeu Vizoso 	 * don't trust that one either.
9598c6b709dSTomeu Vizoso 	 */
960033b7a23SMaarten Lankhorst 	if (pipe_crc->skipped <= 0 ||
961373abf1aSMatt Roper 	    (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) {
9628c6b709dSTomeu Vizoso 		pipe_crc->skipped++;
9638c6b709dSTomeu Vizoso 		spin_unlock(&pipe_crc->lock);
9648c6b709dSTomeu Vizoso 		return;
9658c6b709dSTomeu Vizoso 	}
9668c6b709dSTomeu Vizoso 	spin_unlock(&pipe_crc->lock);
9676cc42152SMaarten Lankhorst 
968246ee524STomeu Vizoso 	drm_crtc_add_crc_entry(&crtc->base, true,
969ca814b25SDaniel Vetter 				drm_crtc_accurate_vblank_count(&crtc->base),
970246ee524STomeu Vizoso 				crcs);
9718c6b709dSTomeu Vizoso }
972277de95eSDaniel Vetter #else
973277de95eSDaniel Vetter static inline void
97491d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
97591d14251STvrtko Ursulin 			     enum pipe pipe,
976a9c287c9SJani Nikula 			     u32 crc0, u32 crc1,
977a9c287c9SJani Nikula 			     u32 crc2, u32 crc3,
978a9c287c9SJani Nikula 			     u32 crc4) {}
979277de95eSDaniel Vetter #endif
980eba94eb9SDaniel Vetter 
9811288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915,
9821288f9b0SKarthik B S 			      enum pipe pipe)
9831288f9b0SKarthik B S {
9847794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
9851288f9b0SKarthik B S 	struct drm_crtc_state *crtc_state = crtc->base.state;
9861288f9b0SKarthik B S 	struct drm_pending_vblank_event *e = crtc_state->event;
9871288f9b0SKarthik B S 	struct drm_device *dev = &i915->drm;
9881288f9b0SKarthik B S 	unsigned long irqflags;
9891288f9b0SKarthik B S 
9901288f9b0SKarthik B S 	spin_lock_irqsave(&dev->event_lock, irqflags);
9911288f9b0SKarthik B S 
9921288f9b0SKarthik B S 	crtc_state->event = NULL;
9931288f9b0SKarthik B S 
9941288f9b0SKarthik B S 	drm_crtc_send_vblank_event(&crtc->base, e);
9951288f9b0SKarthik B S 
9961288f9b0SKarthik B S 	spin_unlock_irqrestore(&dev->event_lock, irqflags);
9971288f9b0SKarthik B S }
998277de95eSDaniel Vetter 
99991d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
100091d14251STvrtko Ursulin 				     enum pipe pipe)
10015a69b89fSDaniel Vetter {
100291d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
10032939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
10045a69b89fSDaniel Vetter 				     0, 0, 0, 0);
10055a69b89fSDaniel Vetter }
10065a69b89fSDaniel Vetter 
100791d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
100891d14251STvrtko Ursulin 				     enum pipe pipe)
1009eba94eb9SDaniel Vetter {
101091d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
10112939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
10122939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)),
10132939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)),
10142939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)),
10152939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe)));
1016eba94eb9SDaniel Vetter }
10175b3a856bSDaniel Vetter 
101891d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
101991d14251STvrtko Ursulin 				      enum pipe pipe)
10205b3a856bSDaniel Vetter {
1021a9c287c9SJani Nikula 	u32 res1, res2;
10220b5c5ed0SDaniel Vetter 
1023373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 3)
10242939eb06SJani Nikula 		res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe));
10250b5c5ed0SDaniel Vetter 	else
10260b5c5ed0SDaniel Vetter 		res1 = 0;
10270b5c5ed0SDaniel Vetter 
1028373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
10292939eb06SJani Nikula 		res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe));
10300b5c5ed0SDaniel Vetter 	else
10310b5c5ed0SDaniel Vetter 		res2 = 0;
10325b3a856bSDaniel Vetter 
103391d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
10342939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)),
10352939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)),
10362939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)),
10370b5c5ed0SDaniel Vetter 				     res1, res2);
10385b3a856bSDaniel Vetter }
10398bf1e9f1SShuang He 
104044d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
104144d9241eSVille Syrjälä {
104244d9241eSVille Syrjälä 	enum pipe pipe;
104344d9241eSVille Syrjälä 
104444d9241eSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
10452939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe),
104644d9241eSVille Syrjälä 			   PIPESTAT_INT_STATUS_MASK |
104744d9241eSVille Syrjälä 			   PIPE_FIFO_UNDERRUN_STATUS);
104844d9241eSVille Syrjälä 
104944d9241eSVille Syrjälä 		dev_priv->pipestat_irq_mask[pipe] = 0;
105044d9241eSVille Syrjälä 	}
105144d9241eSVille Syrjälä }
105244d9241eSVille Syrjälä 
1053eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
105491d14251STvrtko Ursulin 				  u32 iir, u32 pipe_stats[I915_MAX_PIPES])
10557e231dbeSJesse Barnes {
1056d048a268SVille Syrjälä 	enum pipe pipe;
10577e231dbeSJesse Barnes 
105858ead0d7SImre Deak 	spin_lock(&dev_priv->irq_lock);
10591ca993d2SVille Syrjälä 
10601ca993d2SVille Syrjälä 	if (!dev_priv->display_irqs_enabled) {
10611ca993d2SVille Syrjälä 		spin_unlock(&dev_priv->irq_lock);
10621ca993d2SVille Syrjälä 		return;
10631ca993d2SVille Syrjälä 	}
10641ca993d2SVille Syrjälä 
1065055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1066f0f59a00SVille Syrjälä 		i915_reg_t reg;
10676b12ca56SVille Syrjälä 		u32 status_mask, enable_mask, iir_bit = 0;
106891d181ddSImre Deak 
1069bbb5eebfSDaniel Vetter 		/*
1070bbb5eebfSDaniel Vetter 		 * PIPESTAT bits get signalled even when the interrupt is
1071bbb5eebfSDaniel Vetter 		 * disabled with the mask bits, and some of the status bits do
1072bbb5eebfSDaniel Vetter 		 * not generate interrupts at all (like the underrun bit). Hence
1073bbb5eebfSDaniel Vetter 		 * we need to be careful that we only handle what we want to
1074bbb5eebfSDaniel Vetter 		 * handle.
1075bbb5eebfSDaniel Vetter 		 */
10760f239f4cSDaniel Vetter 
10770f239f4cSDaniel Vetter 		/* fifo underruns are filterered in the underrun handler. */
10786b12ca56SVille Syrjälä 		status_mask = PIPE_FIFO_UNDERRUN_STATUS;
1079bbb5eebfSDaniel Vetter 
1080bbb5eebfSDaniel Vetter 		switch (pipe) {
1081d048a268SVille Syrjälä 		default:
1082bbb5eebfSDaniel Vetter 		case PIPE_A:
1083bbb5eebfSDaniel Vetter 			iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
1084bbb5eebfSDaniel Vetter 			break;
1085bbb5eebfSDaniel Vetter 		case PIPE_B:
1086bbb5eebfSDaniel Vetter 			iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
1087bbb5eebfSDaniel Vetter 			break;
10883278f67fSVille Syrjälä 		case PIPE_C:
10893278f67fSVille Syrjälä 			iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
10903278f67fSVille Syrjälä 			break;
1091bbb5eebfSDaniel Vetter 		}
1092bbb5eebfSDaniel Vetter 		if (iir & iir_bit)
10936b12ca56SVille Syrjälä 			status_mask |= dev_priv->pipestat_irq_mask[pipe];
1094bbb5eebfSDaniel Vetter 
10956b12ca56SVille Syrjälä 		if (!status_mask)
109691d181ddSImre Deak 			continue;
109791d181ddSImre Deak 
109891d181ddSImre Deak 		reg = PIPESTAT(pipe);
10992939eb06SJani Nikula 		pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask;
11006b12ca56SVille Syrjälä 		enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
11017e231dbeSJesse Barnes 
11027e231dbeSJesse Barnes 		/*
11037e231dbeSJesse Barnes 		 * Clear the PIPE*STAT regs before the IIR
1104132c27c9SVille Syrjälä 		 *
1105132c27c9SVille Syrjälä 		 * Toggle the enable bits to make sure we get an
1106132c27c9SVille Syrjälä 		 * edge in the ISR pipe event bit if we don't clear
1107132c27c9SVille Syrjälä 		 * all the enabled status bits. Otherwise the edge
1108132c27c9SVille Syrjälä 		 * triggered IIR on i965/g4x wouldn't notice that
1109132c27c9SVille Syrjälä 		 * an interrupt is still pending.
11107e231dbeSJesse Barnes 		 */
1111132c27c9SVille Syrjälä 		if (pipe_stats[pipe]) {
11122939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]);
11132939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, reg, enable_mask);
1114132c27c9SVille Syrjälä 		}
11157e231dbeSJesse Barnes 	}
111658ead0d7SImre Deak 	spin_unlock(&dev_priv->irq_lock);
11172ecb8ca4SVille Syrjälä }
11182ecb8ca4SVille Syrjälä 
1119eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv,
1120eb64343cSVille Syrjälä 				      u16 iir, u32 pipe_stats[I915_MAX_PIPES])
1121eb64343cSVille Syrjälä {
1122eb64343cSVille Syrjälä 	enum pipe pipe;
1123eb64343cSVille Syrjälä 
1124eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
1125eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
1126aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1127eb64343cSVille Syrjälä 
1128eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
1129eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1130eb64343cSVille Syrjälä 
1131eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
1132eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1133eb64343cSVille Syrjälä 	}
1134eb64343cSVille Syrjälä }
1135eb64343cSVille Syrjälä 
1136eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv,
1137eb64343cSVille Syrjälä 				      u32 iir, u32 pipe_stats[I915_MAX_PIPES])
1138eb64343cSVille Syrjälä {
1139eb64343cSVille Syrjälä 	bool blc_event = false;
1140eb64343cSVille Syrjälä 	enum pipe pipe;
1141eb64343cSVille Syrjälä 
1142eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
1143eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
1144aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1145eb64343cSVille Syrjälä 
1146eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
1147eb64343cSVille Syrjälä 			blc_event = true;
1148eb64343cSVille Syrjälä 
1149eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
1150eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1151eb64343cSVille Syrjälä 
1152eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
1153eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1154eb64343cSVille Syrjälä 	}
1155eb64343cSVille Syrjälä 
1156eb64343cSVille Syrjälä 	if (blc_event || (iir & I915_ASLE_INTERRUPT))
1157eb64343cSVille Syrjälä 		intel_opregion_asle_intr(dev_priv);
1158eb64343cSVille Syrjälä }
1159eb64343cSVille Syrjälä 
1160eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv,
1161eb64343cSVille Syrjälä 				      u32 iir, u32 pipe_stats[I915_MAX_PIPES])
1162eb64343cSVille Syrjälä {
1163eb64343cSVille Syrjälä 	bool blc_event = false;
1164eb64343cSVille Syrjälä 	enum pipe pipe;
1165eb64343cSVille Syrjälä 
1166eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
1167eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
1168aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1169eb64343cSVille Syrjälä 
1170eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
1171eb64343cSVille Syrjälä 			blc_event = true;
1172eb64343cSVille Syrjälä 
1173eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
1174eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1175eb64343cSVille Syrjälä 
1176eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
1177eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1178eb64343cSVille Syrjälä 	}
1179eb64343cSVille Syrjälä 
1180eb64343cSVille Syrjälä 	if (blc_event || (iir & I915_ASLE_INTERRUPT))
1181eb64343cSVille Syrjälä 		intel_opregion_asle_intr(dev_priv);
1182eb64343cSVille Syrjälä 
1183eb64343cSVille Syrjälä 	if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
1184eb64343cSVille Syrjälä 		gmbus_irq_handler(dev_priv);
1185eb64343cSVille Syrjälä }
1186eb64343cSVille Syrjälä 
118791d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
11882ecb8ca4SVille Syrjälä 					    u32 pipe_stats[I915_MAX_PIPES])
11892ecb8ca4SVille Syrjälä {
11902ecb8ca4SVille Syrjälä 	enum pipe pipe;
11917e231dbeSJesse Barnes 
1192055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1193fd3a4024SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
1194aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
11954356d586SDaniel Vetter 
11966ede6b06SVille Syrjälä 		if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
11976ede6b06SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
11986ede6b06SVille Syrjälä 
11994356d586SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
120091d14251STvrtko Ursulin 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
12012d9d2b0bSVille Syrjälä 
12021f7247c0SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
12031f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
120431acc7f5SJesse Barnes 	}
120531acc7f5SJesse Barnes 
1206c1874ed7SImre Deak 	if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
120791d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
1208c1874ed7SImre Deak }
1209c1874ed7SImre Deak 
12101ae3c34cSVille Syrjälä static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
121116c6c56bSVille Syrjälä {
12120ba7c51aSVille Syrjälä 	u32 hotplug_status = 0, hotplug_status_mask;
12130ba7c51aSVille Syrjälä 	int i;
121416c6c56bSVille Syrjälä 
12150ba7c51aSVille Syrjälä 	if (IS_G4X(dev_priv) ||
12160ba7c51aSVille Syrjälä 	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
12170ba7c51aSVille Syrjälä 		hotplug_status_mask = HOTPLUG_INT_STATUS_G4X |
12180ba7c51aSVille Syrjälä 			DP_AUX_CHANNEL_MASK_INT_STATUS_G4X;
12190ba7c51aSVille Syrjälä 	else
12200ba7c51aSVille Syrjälä 		hotplug_status_mask = HOTPLUG_INT_STATUS_I915;
12210ba7c51aSVille Syrjälä 
12220ba7c51aSVille Syrjälä 	/*
12230ba7c51aSVille Syrjälä 	 * We absolutely have to clear all the pending interrupt
12240ba7c51aSVille Syrjälä 	 * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port
12250ba7c51aSVille Syrjälä 	 * interrupt bit won't have an edge, and the i965/g4x
12260ba7c51aSVille Syrjälä 	 * edge triggered IIR will not notice that an interrupt
12270ba7c51aSVille Syrjälä 	 * is still pending. We can't use PORT_HOTPLUG_EN to
12280ba7c51aSVille Syrjälä 	 * guarantee the edge as the act of toggling the enable
12290ba7c51aSVille Syrjälä 	 * bits can itself generate a new hotplug interrupt :(
12300ba7c51aSVille Syrjälä 	 */
12310ba7c51aSVille Syrjälä 	for (i = 0; i < 10; i++) {
12322939eb06SJani Nikula 		u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask;
12330ba7c51aSVille Syrjälä 
12340ba7c51aSVille Syrjälä 		if (tmp == 0)
12350ba7c51aSVille Syrjälä 			return hotplug_status;
12360ba7c51aSVille Syrjälä 
12370ba7c51aSVille Syrjälä 		hotplug_status |= tmp;
12382939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status);
12390ba7c51aSVille Syrjälä 	}
12400ba7c51aSVille Syrjälä 
124148a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, 1,
12420ba7c51aSVille Syrjälä 		      "PORT_HOTPLUG_STAT did not clear (0x%08x)\n",
12432939eb06SJani Nikula 		      intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
12441ae3c34cSVille Syrjälä 
12451ae3c34cSVille Syrjälä 	return hotplug_status;
12461ae3c34cSVille Syrjälä }
12471ae3c34cSVille Syrjälä 
124891d14251STvrtko Ursulin static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv,
12491ae3c34cSVille Syrjälä 				 u32 hotplug_status)
12501ae3c34cSVille Syrjälä {
12511ae3c34cSVille Syrjälä 	u32 pin_mask = 0, long_mask = 0;
12520398993bSVille Syrjälä 	u32 hotplug_trigger;
12533ff60f89SOscar Mateo 
12540398993bSVille Syrjälä 	if (IS_G4X(dev_priv) ||
12550398993bSVille Syrjälä 	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
12560398993bSVille Syrjälä 		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
12570398993bSVille Syrjälä 	else
12580398993bSVille Syrjälä 		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
125916c6c56bSVille Syrjälä 
126058f2cf24SVille Syrjälä 	if (hotplug_trigger) {
1261cf53902fSRodrigo Vivi 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
1262cf53902fSRodrigo Vivi 				   hotplug_trigger, hotplug_trigger,
12635a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.hpd,
1264fd63e2a9SImre Deak 				   i9xx_port_hotplug_long_detect);
126558f2cf24SVille Syrjälä 
126691d14251STvrtko Ursulin 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
126758f2cf24SVille Syrjälä 	}
1268369712e8SJani Nikula 
12690398993bSVille Syrjälä 	if ((IS_G4X(dev_priv) ||
12700398993bSVille Syrjälä 	     IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
12710398993bSVille Syrjälä 	    hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
127291d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
127358f2cf24SVille Syrjälä }
127416c6c56bSVille Syrjälä 
1275c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg)
1276c1874ed7SImre Deak {
1277b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
1278c1874ed7SImre Deak 	irqreturn_t ret = IRQ_NONE;
1279c1874ed7SImre Deak 
12802dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
12812dd2a883SImre Deak 		return IRQ_NONE;
12822dd2a883SImre Deak 
12831f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
12849102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
12851f814dacSImre Deak 
12861e1cace9SVille Syrjälä 	do {
12876e814800SVille Syrjälä 		u32 iir, gt_iir, pm_iir;
12882ecb8ca4SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
12891ae3c34cSVille Syrjälä 		u32 hotplug_status = 0;
1290a5e485a9SVille Syrjälä 		u32 ier = 0;
12913ff60f89SOscar Mateo 
12922939eb06SJani Nikula 		gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR);
12932939eb06SJani Nikula 		pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR);
12942939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
1295c1874ed7SImre Deak 
1296c1874ed7SImre Deak 		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
12971e1cace9SVille Syrjälä 			break;
1298c1874ed7SImre Deak 
1299c1874ed7SImre Deak 		ret = IRQ_HANDLED;
1300c1874ed7SImre Deak 
1301a5e485a9SVille Syrjälä 		/*
1302a5e485a9SVille Syrjälä 		 * Theory on interrupt generation, based on empirical evidence:
1303a5e485a9SVille Syrjälä 		 *
1304a5e485a9SVille Syrjälä 		 * x = ((VLV_IIR & VLV_IER) ||
1305a5e485a9SVille Syrjälä 		 *      (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) &&
1306a5e485a9SVille Syrjälä 		 *       (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE)));
1307a5e485a9SVille Syrjälä 		 *
1308a5e485a9SVille Syrjälä 		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
1309a5e485a9SVille Syrjälä 		 * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to
1310a5e485a9SVille Syrjälä 		 * guarantee the CPU interrupt will be raised again even if we
1311a5e485a9SVille Syrjälä 		 * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR
1312a5e485a9SVille Syrjälä 		 * bits this time around.
1313a5e485a9SVille Syrjälä 		 */
13142939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0);
13158cee664dSAndrzej Hajda 		ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
13164a0a0202SVille Syrjälä 
13174a0a0202SVille Syrjälä 		if (gt_iir)
13182939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir);
13194a0a0202SVille Syrjälä 		if (pm_iir)
13202939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir);
13214a0a0202SVille Syrjälä 
13227ce4d1f2SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
13231ae3c34cSVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
13247ce4d1f2SVille Syrjälä 
13253ff60f89SOscar Mateo 		/* Call regardless, as some status bits might not be
13263ff60f89SOscar Mateo 		 * signalled in iir */
1327eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
13287ce4d1f2SVille Syrjälä 
1329eef57324SJerome Anand 		if (iir & (I915_LPE_PIPE_A_INTERRUPT |
1330eef57324SJerome Anand 			   I915_LPE_PIPE_B_INTERRUPT))
1331eef57324SJerome Anand 			intel_lpe_audio_irq_handler(dev_priv);
1332eef57324SJerome Anand 
13337ce4d1f2SVille Syrjälä 		/*
13347ce4d1f2SVille Syrjälä 		 * VLV_IIR is single buffered, and reflects the level
13357ce4d1f2SVille Syrjälä 		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
13367ce4d1f2SVille Syrjälä 		 */
13377ce4d1f2SVille Syrjälä 		if (iir)
13382939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
13394a0a0202SVille Syrjälä 
13402939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
13412939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
13421ae3c34cSVille Syrjälä 
134352894874SVille Syrjälä 		if (gt_iir)
13442cbc876dSMichał Winiarski 			gen6_gt_irq_handler(to_gt(dev_priv), gt_iir);
134552894874SVille Syrjälä 		if (pm_iir)
13462cbc876dSMichał Winiarski 			gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir);
134752894874SVille Syrjälä 
13481ae3c34cSVille Syrjälä 		if (hotplug_status)
134991d14251STvrtko Ursulin 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
13502ecb8ca4SVille Syrjälä 
135191d14251STvrtko Ursulin 		valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
13521e1cace9SVille Syrjälä 	} while (0);
13537e231dbeSJesse Barnes 
13549c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
13559c6508b9SThomas Gleixner 
13569102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
13571f814dacSImre Deak 
13587e231dbeSJesse Barnes 	return ret;
13597e231dbeSJesse Barnes }
13607e231dbeSJesse Barnes 
136143f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg)
136243f328d7SVille Syrjälä {
1363b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
136443f328d7SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
136543f328d7SVille Syrjälä 
13662dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
13672dd2a883SImre Deak 		return IRQ_NONE;
13682dd2a883SImre Deak 
13691f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
13709102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
13711f814dacSImre Deak 
1372579de73bSChris Wilson 	do {
13736e814800SVille Syrjälä 		u32 master_ctl, iir;
13742ecb8ca4SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
13751ae3c34cSVille Syrjälä 		u32 hotplug_status = 0;
1376a5e485a9SVille Syrjälä 		u32 ier = 0;
1377a5e485a9SVille Syrjälä 
13782939eb06SJani Nikula 		master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
13792939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
13803278f67fSVille Syrjälä 
13813278f67fSVille Syrjälä 		if (master_ctl == 0 && iir == 0)
13828e5fd599SVille Syrjälä 			break;
138343f328d7SVille Syrjälä 
138427b6c122SOscar Mateo 		ret = IRQ_HANDLED;
138527b6c122SOscar Mateo 
1386a5e485a9SVille Syrjälä 		/*
1387a5e485a9SVille Syrjälä 		 * Theory on interrupt generation, based on empirical evidence:
1388a5e485a9SVille Syrjälä 		 *
1389a5e485a9SVille Syrjälä 		 * x = ((VLV_IIR & VLV_IER) ||
1390a5e485a9SVille Syrjälä 		 *      ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) &&
1391a5e485a9SVille Syrjälä 		 *       (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL)));
1392a5e485a9SVille Syrjälä 		 *
1393a5e485a9SVille Syrjälä 		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
1394a5e485a9SVille Syrjälä 		 * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to
1395a5e485a9SVille Syrjälä 		 * guarantee the CPU interrupt will be raised again even if we
1396a5e485a9SVille Syrjälä 		 * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL
1397a5e485a9SVille Syrjälä 		 * bits this time around.
1398a5e485a9SVille Syrjälä 		 */
13992939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0);
14008cee664dSAndrzej Hajda 		ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
140143f328d7SVille Syrjälä 
14022cbc876dSMichał Winiarski 		gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
140327b6c122SOscar Mateo 
140427b6c122SOscar Mateo 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
14051ae3c34cSVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
140643f328d7SVille Syrjälä 
140727b6c122SOscar Mateo 		/* Call regardless, as some status bits might not be
140827b6c122SOscar Mateo 		 * signalled in iir */
1409eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
141043f328d7SVille Syrjälä 
1411eef57324SJerome Anand 		if (iir & (I915_LPE_PIPE_A_INTERRUPT |
1412eef57324SJerome Anand 			   I915_LPE_PIPE_B_INTERRUPT |
1413eef57324SJerome Anand 			   I915_LPE_PIPE_C_INTERRUPT))
1414eef57324SJerome Anand 			intel_lpe_audio_irq_handler(dev_priv);
1415eef57324SJerome Anand 
14167ce4d1f2SVille Syrjälä 		/*
14177ce4d1f2SVille Syrjälä 		 * VLV_IIR is single buffered, and reflects the level
14187ce4d1f2SVille Syrjälä 		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
14197ce4d1f2SVille Syrjälä 		 */
14207ce4d1f2SVille Syrjälä 		if (iir)
14212939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
14227ce4d1f2SVille Syrjälä 
14232939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
14242939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
14251ae3c34cSVille Syrjälä 
14261ae3c34cSVille Syrjälä 		if (hotplug_status)
142791d14251STvrtko Ursulin 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
14282ecb8ca4SVille Syrjälä 
142991d14251STvrtko Ursulin 		valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
1430579de73bSChris Wilson 	} while (0);
14313278f67fSVille Syrjälä 
14329c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
14339c6508b9SThomas Gleixner 
14349102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
14351f814dacSImre Deak 
143643f328d7SVille Syrjälä 	return ret;
143743f328d7SVille Syrjälä }
143843f328d7SVille Syrjälä 
143991d14251STvrtko Ursulin static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv,
14400398993bSVille Syrjälä 				u32 hotplug_trigger)
1441776ad806SJesse Barnes {
144242db67d6SVille Syrjälä 	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
1443776ad806SJesse Barnes 
14446a39d7c9SJani Nikula 	/*
14456a39d7c9SJani Nikula 	 * Somehow the PCH doesn't seem to really ack the interrupt to the CPU
14466a39d7c9SJani Nikula 	 * unless we touch the hotplug register, even if hotplug_trigger is
14476a39d7c9SJani Nikula 	 * zero. Not acking leads to "The master control interrupt lied (SDE)!"
14486a39d7c9SJani Nikula 	 * errors.
14496a39d7c9SJani Nikula 	 */
14502939eb06SJani Nikula 	dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
14516a39d7c9SJani Nikula 	if (!hotplug_trigger) {
14526a39d7c9SJani Nikula 		u32 mask = PORTA_HOTPLUG_STATUS_MASK |
14536a39d7c9SJani Nikula 			PORTD_HOTPLUG_STATUS_MASK |
14546a39d7c9SJani Nikula 			PORTC_HOTPLUG_STATUS_MASK |
14556a39d7c9SJani Nikula 			PORTB_HOTPLUG_STATUS_MASK;
14566a39d7c9SJani Nikula 		dig_hotplug_reg &= ~mask;
14576a39d7c9SJani Nikula 	}
14586a39d7c9SJani Nikula 
14592939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg);
14606a39d7c9SJani Nikula 	if (!hotplug_trigger)
14616a39d7c9SJani Nikula 		return;
146213cf5504SDave Airlie 
14630398993bSVille Syrjälä 	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
14640398993bSVille Syrjälä 			   hotplug_trigger, dig_hotplug_reg,
14655a4dd6f0SJani Nikula 			   dev_priv->display.hotplug.pch_hpd,
1466fd63e2a9SImre Deak 			   pch_port_hotplug_long_detect);
146740e56410SVille Syrjälä 
146891d14251STvrtko Ursulin 	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1469aaf5ec2eSSonika Jindal }
147091d131d2SDaniel Vetter 
147191d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
147240e56410SVille Syrjälä {
1473d048a268SVille Syrjälä 	enum pipe pipe;
147440e56410SVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
147540e56410SVille Syrjälä 
14760398993bSVille Syrjälä 	ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
147740e56410SVille Syrjälä 
1478cfc33bf7SVille Syrjälä 	if (pch_iir & SDE_AUDIO_POWER_MASK) {
1479cfc33bf7SVille Syrjälä 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
1480776ad806SJesse Barnes 			       SDE_AUDIO_POWER_SHIFT);
148100376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n",
1482cfc33bf7SVille Syrjälä 			port_name(port));
1483cfc33bf7SVille Syrjälä 	}
1484776ad806SJesse Barnes 
1485ce99c256SDaniel Vetter 	if (pch_iir & SDE_AUX_MASK)
148691d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
1487ce99c256SDaniel Vetter 
1488776ad806SJesse Barnes 	if (pch_iir & SDE_GMBUS)
148991d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
1490776ad806SJesse Barnes 
1491776ad806SJesse Barnes 	if (pch_iir & SDE_AUDIO_HDCP_MASK)
149200376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n");
1493776ad806SJesse Barnes 
1494776ad806SJesse Barnes 	if (pch_iir & SDE_AUDIO_TRANS_MASK)
149500376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n");
1496776ad806SJesse Barnes 
1497776ad806SJesse Barnes 	if (pch_iir & SDE_POISON)
149800376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "PCH poison interrupt\n");
1499776ad806SJesse Barnes 
1500b8b65ccdSAnshuman Gupta 	if (pch_iir & SDE_FDI_MASK) {
1501055e393fSDamien Lespiau 		for_each_pipe(dev_priv, pipe)
150200376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm, "  pipe %c FDI IIR: 0x%08x\n",
15039db4a9c7SJesse Barnes 				pipe_name(pipe),
15042939eb06SJani Nikula 				intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
1505b8b65ccdSAnshuman Gupta 	}
1506776ad806SJesse Barnes 
1507776ad806SJesse Barnes 	if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
150800376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n");
1509776ad806SJesse Barnes 
1510776ad806SJesse Barnes 	if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
151100376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm,
151200376ccfSWambui Karuga 			"PCH transcoder CRC error interrupt\n");
1513776ad806SJesse Barnes 
1514776ad806SJesse Barnes 	if (pch_iir & SDE_TRANSA_FIFO_UNDER)
1515a2196033SMatthias Kaehlcke 		intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A);
15168664281bSPaulo Zanoni 
15178664281bSPaulo Zanoni 	if (pch_iir & SDE_TRANSB_FIFO_UNDER)
1518a2196033SMatthias Kaehlcke 		intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B);
15198664281bSPaulo Zanoni }
15208664281bSPaulo Zanoni 
152191d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv)
15228664281bSPaulo Zanoni {
15232939eb06SJani Nikula 	u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT);
15245a69b89fSDaniel Vetter 	enum pipe pipe;
15258664281bSPaulo Zanoni 
1526de032bf4SPaulo Zanoni 	if (err_int & ERR_INT_POISON)
152700376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Poison interrupt\n");
1528de032bf4SPaulo Zanoni 
1529055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
15301f7247c0SDaniel Vetter 		if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
15311f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
15328664281bSPaulo Zanoni 
15335a69b89fSDaniel Vetter 		if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
153491d14251STvrtko Ursulin 			if (IS_IVYBRIDGE(dev_priv))
153591d14251STvrtko Ursulin 				ivb_pipe_crc_irq_handler(dev_priv, pipe);
15365a69b89fSDaniel Vetter 			else
153791d14251STvrtko Ursulin 				hsw_pipe_crc_irq_handler(dev_priv, pipe);
15385a69b89fSDaniel Vetter 		}
15395a69b89fSDaniel Vetter 	}
15408bf1e9f1SShuang He 
15412939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int);
15428664281bSPaulo Zanoni }
15438664281bSPaulo Zanoni 
154491d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv)
15458664281bSPaulo Zanoni {
15462939eb06SJani Nikula 	u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT);
154745c1cd87SMika Kahola 	enum pipe pipe;
15488664281bSPaulo Zanoni 
1549de032bf4SPaulo Zanoni 	if (serr_int & SERR_INT_POISON)
155000376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "PCH poison interrupt\n");
1551de032bf4SPaulo Zanoni 
155245c1cd87SMika Kahola 	for_each_pipe(dev_priv, pipe)
155345c1cd87SMika Kahola 		if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe))
155445c1cd87SMika Kahola 			intel_pch_fifo_underrun_irq_handler(dev_priv, pipe);
15558664281bSPaulo Zanoni 
15562939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int);
1557776ad806SJesse Barnes }
1558776ad806SJesse Barnes 
155991d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
156023e81d69SAdam Jackson {
1561d048a268SVille Syrjälä 	enum pipe pipe;
15626dbf30ceSVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
1563aaf5ec2eSSonika Jindal 
15640398993bSVille Syrjälä 	ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
156591d131d2SDaniel Vetter 
1566cfc33bf7SVille Syrjälä 	if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
1567cfc33bf7SVille Syrjälä 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
156823e81d69SAdam Jackson 			       SDE_AUDIO_POWER_SHIFT_CPT);
156900376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n",
1570cfc33bf7SVille Syrjälä 			port_name(port));
1571cfc33bf7SVille Syrjälä 	}
157223e81d69SAdam Jackson 
157323e81d69SAdam Jackson 	if (pch_iir & SDE_AUX_MASK_CPT)
157491d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
157523e81d69SAdam Jackson 
157623e81d69SAdam Jackson 	if (pch_iir & SDE_GMBUS_CPT)
157791d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
157823e81d69SAdam Jackson 
157923e81d69SAdam Jackson 	if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
158000376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n");
158123e81d69SAdam Jackson 
158223e81d69SAdam Jackson 	if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
158300376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n");
158423e81d69SAdam Jackson 
1585b8b65ccdSAnshuman Gupta 	if (pch_iir & SDE_FDI_MASK_CPT) {
1586055e393fSDamien Lespiau 		for_each_pipe(dev_priv, pipe)
158700376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm, "  pipe %c FDI IIR: 0x%08x\n",
158823e81d69SAdam Jackson 				pipe_name(pipe),
15892939eb06SJani Nikula 				intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
1590b8b65ccdSAnshuman Gupta 	}
15918664281bSPaulo Zanoni 
15928664281bSPaulo Zanoni 	if (pch_iir & SDE_ERROR_CPT)
159391d14251STvrtko Ursulin 		cpt_serr_int_handler(dev_priv);
159423e81d69SAdam Jackson }
159523e81d69SAdam Jackson 
1596babde06dSMika Kahola static void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
1597babde06dSMika Kahola {
1598babde06dSMika Kahola 	enum hpd_pin pin;
1599babde06dSMika Kahola 	u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK);
1600babde06dSMika Kahola 	u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
1601babde06dSMika Kahola 	u32 pin_mask = 0, long_mask = 0;
1602babde06dSMika Kahola 
1603babde06dSMika Kahola 	for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
1604babde06dSMika Kahola 		u32 val;
1605babde06dSMika Kahola 
1606babde06dSMika Kahola 		if (!(i915->display.hotplug.hpd[pin] & hotplug_trigger))
1607babde06dSMika Kahola 			continue;
1608babde06dSMika Kahola 
1609babde06dSMika Kahola 		pin_mask |= BIT(pin);
1610babde06dSMika Kahola 
1611babde06dSMika Kahola 		val = intel_de_read(i915, XELPDP_PORT_HOTPLUG_CTL(pin));
1612babde06dSMika Kahola 		intel_de_write(i915, XELPDP_PORT_HOTPLUG_CTL(pin), val);
1613babde06dSMika Kahola 
1614babde06dSMika Kahola 		if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | XELPDP_TBT_HPD_LONG_DETECT))
1615babde06dSMika Kahola 			long_mask |= BIT(pin);
1616babde06dSMika Kahola 	}
1617babde06dSMika Kahola 
1618babde06dSMika Kahola 	if (pin_mask) {
1619babde06dSMika Kahola 		drm_dbg(&i915->drm,
1620babde06dSMika Kahola 			"pica hotplug event received, stat 0x%08x, pins 0x%08x, long 0x%08x\n",
1621babde06dSMika Kahola 			hotplug_trigger, pin_mask, long_mask);
1622babde06dSMika Kahola 
1623babde06dSMika Kahola 		intel_hpd_irq_handler(i915, pin_mask, long_mask);
1624babde06dSMika Kahola 	}
1625babde06dSMika Kahola 
1626babde06dSMika Kahola 	if (trigger_aux)
1627babde06dSMika Kahola 		dp_aux_irq_handler(i915);
1628babde06dSMika Kahola 
1629babde06dSMika Kahola 	if (!pin_mask && !trigger_aux)
1630babde06dSMika Kahola 		drm_err(&i915->drm,
1631babde06dSMika Kahola 			"Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
1632babde06dSMika Kahola }
1633babde06dSMika Kahola 
163458676af6SLucas De Marchi static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
163531604222SAnusha Srivatsa {
1636e76ab2cfSVille Syrjälä 	u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
1637e76ab2cfSVille Syrjälä 	u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
163831604222SAnusha Srivatsa 	u32 pin_mask = 0, long_mask = 0;
163931604222SAnusha Srivatsa 
164031604222SAnusha Srivatsa 	if (ddi_hotplug_trigger) {
164131604222SAnusha Srivatsa 		u32 dig_hotplug_reg;
164231604222SAnusha Srivatsa 
1643f087cfe6SJani Nikula 		/* Locking due to DSI native GPIO sequences */
1644f087cfe6SJani Nikula 		spin_lock(&dev_priv->irq_lock);
16458cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
1646f087cfe6SJani Nikula 		spin_unlock(&dev_priv->irq_lock);
164731604222SAnusha Srivatsa 
164831604222SAnusha Srivatsa 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16490398993bSVille Syrjälä 				   ddi_hotplug_trigger, dig_hotplug_reg,
16505a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
165131604222SAnusha Srivatsa 				   icp_ddi_port_hotplug_long_detect);
165231604222SAnusha Srivatsa 	}
165331604222SAnusha Srivatsa 
165431604222SAnusha Srivatsa 	if (tc_hotplug_trigger) {
165531604222SAnusha Srivatsa 		u32 dig_hotplug_reg;
165631604222SAnusha Srivatsa 
16578cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0);
165831604222SAnusha Srivatsa 
165931604222SAnusha Srivatsa 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16600398993bSVille Syrjälä 				   tc_hotplug_trigger, dig_hotplug_reg,
16615a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
1662da51e4baSVille Syrjälä 				   icp_tc_port_hotplug_long_detect);
166352dfdba0SLucas De Marchi 	}
166452dfdba0SLucas De Marchi 
166552dfdba0SLucas De Marchi 	if (pin_mask)
166652dfdba0SLucas De Marchi 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
166752dfdba0SLucas De Marchi 
166852dfdba0SLucas De Marchi 	if (pch_iir & SDE_GMBUS_ICP)
166952dfdba0SLucas De Marchi 		gmbus_irq_handler(dev_priv);
167052dfdba0SLucas De Marchi }
167152dfdba0SLucas De Marchi 
167291d14251STvrtko Ursulin static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
16736dbf30ceSVille Syrjälä {
16746dbf30ceSVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
16756dbf30ceSVille Syrjälä 		~SDE_PORTE_HOTPLUG_SPT;
16766dbf30ceSVille Syrjälä 	u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
16776dbf30ceSVille Syrjälä 	u32 pin_mask = 0, long_mask = 0;
16786dbf30ceSVille Syrjälä 
16796dbf30ceSVille Syrjälä 	if (hotplug_trigger) {
16806dbf30ceSVille Syrjälä 		u32 dig_hotplug_reg;
16816dbf30ceSVille Syrjälä 
16828cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
16836dbf30ceSVille Syrjälä 
1684cf53902fSRodrigo Vivi 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16850398993bSVille Syrjälä 				   hotplug_trigger, dig_hotplug_reg,
16865a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
168774c0b395SVille Syrjälä 				   spt_port_hotplug_long_detect);
16886dbf30ceSVille Syrjälä 	}
16896dbf30ceSVille Syrjälä 
16906dbf30ceSVille Syrjälä 	if (hotplug2_trigger) {
16916dbf30ceSVille Syrjälä 		u32 dig_hotplug_reg;
16926dbf30ceSVille Syrjälä 
16938cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0);
16946dbf30ceSVille Syrjälä 
1695cf53902fSRodrigo Vivi 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
16960398993bSVille Syrjälä 				   hotplug2_trigger, dig_hotplug_reg,
16975a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.pch_hpd,
16986dbf30ceSVille Syrjälä 				   spt_port_hotplug2_long_detect);
16996dbf30ceSVille Syrjälä 	}
17006dbf30ceSVille Syrjälä 
17016dbf30ceSVille Syrjälä 	if (pin_mask)
170291d14251STvrtko Ursulin 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
17036dbf30ceSVille Syrjälä 
17046dbf30ceSVille Syrjälä 	if (pch_iir & SDE_GMBUS_CPT)
170591d14251STvrtko Ursulin 		gmbus_irq_handler(dev_priv);
17066dbf30ceSVille Syrjälä }
17076dbf30ceSVille Syrjälä 
170891d14251STvrtko Ursulin static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv,
17090398993bSVille Syrjälä 				u32 hotplug_trigger)
1710c008bc6eSPaulo Zanoni {
1711e4ce95aaSVille Syrjälä 	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
1712e4ce95aaSVille Syrjälä 
17138cee664dSAndrzej Hajda 	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0);
1714e4ce95aaSVille Syrjälä 
17150398993bSVille Syrjälä 	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
17160398993bSVille Syrjälä 			   hotplug_trigger, dig_hotplug_reg,
17175a4dd6f0SJani Nikula 			   dev_priv->display.hotplug.hpd,
1718e4ce95aaSVille Syrjälä 			   ilk_port_hotplug_long_detect);
171940e56410SVille Syrjälä 
172091d14251STvrtko Ursulin 	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1721e4ce95aaSVille Syrjälä }
1722c008bc6eSPaulo Zanoni 
172391d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
172491d14251STvrtko Ursulin 				    u32 de_iir)
172540e56410SVille Syrjälä {
172640e56410SVille Syrjälä 	enum pipe pipe;
172740e56410SVille Syrjälä 	u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
172840e56410SVille Syrjälä 
172940e56410SVille Syrjälä 	if (hotplug_trigger)
17300398993bSVille Syrjälä 		ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
173140e56410SVille Syrjälä 
1732c008bc6eSPaulo Zanoni 	if (de_iir & DE_AUX_CHANNEL_A)
173391d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
1734c008bc6eSPaulo Zanoni 
1735c008bc6eSPaulo Zanoni 	if (de_iir & DE_GSE)
173691d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
1737c008bc6eSPaulo Zanoni 
1738c008bc6eSPaulo Zanoni 	if (de_iir & DE_POISON)
173900376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Poison interrupt\n");
1740c008bc6eSPaulo Zanoni 
1741055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1742fd3a4024SDaniel Vetter 		if (de_iir & DE_PIPE_VBLANK(pipe))
1743aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1744c008bc6eSPaulo Zanoni 
17454bb18054SVille Syrjälä 		if (de_iir & DE_PLANE_FLIP_DONE(pipe))
17464bb18054SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
17474bb18054SVille Syrjälä 
174840da17c2SDaniel Vetter 		if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
17491f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1750c008bc6eSPaulo Zanoni 
175140da17c2SDaniel Vetter 		if (de_iir & DE_PIPE_CRC_DONE(pipe))
175291d14251STvrtko Ursulin 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1753c008bc6eSPaulo Zanoni 	}
1754c008bc6eSPaulo Zanoni 
1755c008bc6eSPaulo Zanoni 	/* check event from PCH */
1756c008bc6eSPaulo Zanoni 	if (de_iir & DE_PCH_EVENT) {
17572939eb06SJani Nikula 		u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
1758c008bc6eSPaulo Zanoni 
175991d14251STvrtko Ursulin 		if (HAS_PCH_CPT(dev_priv))
176091d14251STvrtko Ursulin 			cpt_irq_handler(dev_priv, pch_iir);
1761c008bc6eSPaulo Zanoni 		else
176291d14251STvrtko Ursulin 			ibx_irq_handler(dev_priv, pch_iir);
1763c008bc6eSPaulo Zanoni 
1764c008bc6eSPaulo Zanoni 		/* should clear PCH hotplug event before clear CPU irq */
17652939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
1766c008bc6eSPaulo Zanoni 	}
1767c008bc6eSPaulo Zanoni 
176893e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT)
17692cbc876dSMichał Winiarski 		gen5_rps_irq_handler(&to_gt(dev_priv)->rps);
1770c008bc6eSPaulo Zanoni }
1771c008bc6eSPaulo Zanoni 
177291d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
177391d14251STvrtko Ursulin 				    u32 de_iir)
17749719fb98SPaulo Zanoni {
177507d27e20SDamien Lespiau 	enum pipe pipe;
177623bb4cb5SVille Syrjälä 	u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
177723bb4cb5SVille Syrjälä 
177840e56410SVille Syrjälä 	if (hotplug_trigger)
17790398993bSVille Syrjälä 		ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
17809719fb98SPaulo Zanoni 
17819719fb98SPaulo Zanoni 	if (de_iir & DE_ERR_INT_IVB)
178291d14251STvrtko Ursulin 		ivb_err_int_handler(dev_priv);
17839719fb98SPaulo Zanoni 
17849719fb98SPaulo Zanoni 	if (de_iir & DE_AUX_CHANNEL_A_IVB)
178591d14251STvrtko Ursulin 		dp_aux_irq_handler(dev_priv);
17869719fb98SPaulo Zanoni 
17879719fb98SPaulo Zanoni 	if (de_iir & DE_GSE_IVB)
178891d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
17899719fb98SPaulo Zanoni 
1790055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
179133ef04faSVille Syrjälä 		if (de_iir & DE_PIPE_VBLANK_IVB(pipe))
1792aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
17932a636e24SVille Syrjälä 
17942a636e24SVille Syrjälä 		if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
17952a636e24SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
17969719fb98SPaulo Zanoni 	}
17979719fb98SPaulo Zanoni 
17989719fb98SPaulo Zanoni 	/* check event from PCH */
179991d14251STvrtko Ursulin 	if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
18002939eb06SJani Nikula 		u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
18019719fb98SPaulo Zanoni 
180291d14251STvrtko Ursulin 		cpt_irq_handler(dev_priv, pch_iir);
18039719fb98SPaulo Zanoni 
18049719fb98SPaulo Zanoni 		/* clear PCH hotplug event before clear CPU irq */
18052939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
18069719fb98SPaulo Zanoni 	}
18079719fb98SPaulo Zanoni }
18089719fb98SPaulo Zanoni 
180972c90f62SOscar Mateo /*
181072c90f62SOscar Mateo  * To handle irqs with the minimum potential races with fresh interrupts, we:
181172c90f62SOscar Mateo  * 1 - Disable Master Interrupt Control.
181272c90f62SOscar Mateo  * 2 - Find the source(s) of the interrupt.
181372c90f62SOscar Mateo  * 3 - Clear the Interrupt Identity bits (IIR).
181472c90f62SOscar Mateo  * 4 - Process the interrupt(s) that had bits set in the IIRs.
181572c90f62SOscar Mateo  * 5 - Re-enable Master Interrupt Control.
181672c90f62SOscar Mateo  */
18179eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg)
1818b1f14ad0SJesse Barnes {
1819c48a798aSChris Wilson 	struct drm_i915_private *i915 = arg;
1820c48a798aSChris Wilson 	void __iomem * const regs = i915->uncore.regs;
1821f1af8fc1SPaulo Zanoni 	u32 de_iir, gt_iir, de_ier, sde_ier = 0;
18220e43406bSChris Wilson 	irqreturn_t ret = IRQ_NONE;
1823b1f14ad0SJesse Barnes 
1824c48a798aSChris Wilson 	if (unlikely(!intel_irqs_enabled(i915)))
18252dd2a883SImre Deak 		return IRQ_NONE;
18262dd2a883SImre Deak 
18271f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1828c48a798aSChris Wilson 	disable_rpm_wakeref_asserts(&i915->runtime_pm);
18291f814dacSImre Deak 
1830b1f14ad0SJesse Barnes 	/* disable master interrupt before clearing iir  */
1831c48a798aSChris Wilson 	de_ier = raw_reg_read(regs, DEIER);
1832c48a798aSChris Wilson 	raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
18330e43406bSChris Wilson 
183444498aeaSPaulo Zanoni 	/* Disable south interrupts. We'll only write to SDEIIR once, so further
183544498aeaSPaulo Zanoni 	 * interrupts will will be stored on its back queue, and then we'll be
183644498aeaSPaulo Zanoni 	 * able to process them after we restore SDEIER (as soon as we restore
183744498aeaSPaulo Zanoni 	 * it, we'll get an interrupt if SDEIIR still has something to process
183844498aeaSPaulo Zanoni 	 * due to its back queue). */
1839c48a798aSChris Wilson 	if (!HAS_PCH_NOP(i915)) {
1840c48a798aSChris Wilson 		sde_ier = raw_reg_read(regs, SDEIER);
1841c48a798aSChris Wilson 		raw_reg_write(regs, SDEIER, 0);
1842ab5c608bSBen Widawsky 	}
184344498aeaSPaulo Zanoni 
184472c90f62SOscar Mateo 	/* Find, clear, then process each source of interrupt */
184572c90f62SOscar Mateo 
1846c48a798aSChris Wilson 	gt_iir = raw_reg_read(regs, GTIIR);
18470e43406bSChris Wilson 	if (gt_iir) {
1848c48a798aSChris Wilson 		raw_reg_write(regs, GTIIR, gt_iir);
1849651e7d48SLucas De Marchi 		if (GRAPHICS_VER(i915) >= 6)
18502cbc876dSMichał Winiarski 			gen6_gt_irq_handler(to_gt(i915), gt_iir);
1851d8fc8a47SPaulo Zanoni 		else
18522cbc876dSMichał Winiarski 			gen5_gt_irq_handler(to_gt(i915), gt_iir);
1853c48a798aSChris Wilson 		ret = IRQ_HANDLED;
18540e43406bSChris Wilson 	}
1855b1f14ad0SJesse Barnes 
1856c48a798aSChris Wilson 	de_iir = raw_reg_read(regs, DEIIR);
18570e43406bSChris Wilson 	if (de_iir) {
1858c48a798aSChris Wilson 		raw_reg_write(regs, DEIIR, de_iir);
1859373abf1aSMatt Roper 		if (DISPLAY_VER(i915) >= 7)
1860c48a798aSChris Wilson 			ivb_display_irq_handler(i915, de_iir);
1861f1af8fc1SPaulo Zanoni 		else
1862c48a798aSChris Wilson 			ilk_display_irq_handler(i915, de_iir);
18630e43406bSChris Wilson 		ret = IRQ_HANDLED;
1864c48a798aSChris Wilson 	}
1865c48a798aSChris Wilson 
1866651e7d48SLucas De Marchi 	if (GRAPHICS_VER(i915) >= 6) {
1867c48a798aSChris Wilson 		u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR);
1868c48a798aSChris Wilson 		if (pm_iir) {
1869c48a798aSChris Wilson 			raw_reg_write(regs, GEN6_PMIIR, pm_iir);
18702cbc876dSMichał Winiarski 			gen6_rps_irq_handler(&to_gt(i915)->rps, pm_iir);
1871c48a798aSChris Wilson 			ret = IRQ_HANDLED;
18720e43406bSChris Wilson 		}
1873f1af8fc1SPaulo Zanoni 	}
1874b1f14ad0SJesse Barnes 
1875c48a798aSChris Wilson 	raw_reg_write(regs, DEIER, de_ier);
1876c48a798aSChris Wilson 	if (sde_ier)
1877c48a798aSChris Wilson 		raw_reg_write(regs, SDEIER, sde_ier);
1878b1f14ad0SJesse Barnes 
18799c6508b9SThomas Gleixner 	pmu_irq_stats(i915, ret);
18809c6508b9SThomas Gleixner 
18811f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1882c48a798aSChris Wilson 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
18831f814dacSImre Deak 
1884b1f14ad0SJesse Barnes 	return ret;
1885b1f14ad0SJesse Barnes }
1886b1f14ad0SJesse Barnes 
188791d14251STvrtko Ursulin static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv,
18880398993bSVille Syrjälä 				u32 hotplug_trigger)
1889d04a492dSShashank Sharma {
1890cebd87a0SVille Syrjälä 	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
1891d04a492dSShashank Sharma 
18928cee664dSAndrzej Hajda 	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
1893d04a492dSShashank Sharma 
18940398993bSVille Syrjälä 	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
18950398993bSVille Syrjälä 			   hotplug_trigger, dig_hotplug_reg,
18965a4dd6f0SJani Nikula 			   dev_priv->display.hotplug.hpd,
1897cebd87a0SVille Syrjälä 			   bxt_port_hotplug_long_detect);
189840e56410SVille Syrjälä 
189991d14251STvrtko Ursulin 	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1900d04a492dSShashank Sharma }
1901d04a492dSShashank Sharma 
1902121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
1903121e758eSDhinakaran Pandiyan {
1904121e758eSDhinakaran Pandiyan 	u32 pin_mask = 0, long_mask = 0;
1905b796b971SDhinakaran Pandiyan 	u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK;
1906b796b971SDhinakaran Pandiyan 	u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK;
1907121e758eSDhinakaran Pandiyan 
1908121e758eSDhinakaran Pandiyan 	if (trigger_tc) {
1909b796b971SDhinakaran Pandiyan 		u32 dig_hotplug_reg;
1910b796b971SDhinakaran Pandiyan 
19118cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0);
1912121e758eSDhinakaran Pandiyan 
19130398993bSVille Syrjälä 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
19140398993bSVille Syrjälä 				   trigger_tc, dig_hotplug_reg,
19155a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.hpd,
1916da51e4baSVille Syrjälä 				   gen11_port_hotplug_long_detect);
1917121e758eSDhinakaran Pandiyan 	}
1918b796b971SDhinakaran Pandiyan 
1919b796b971SDhinakaran Pandiyan 	if (trigger_tbt) {
1920b796b971SDhinakaran Pandiyan 		u32 dig_hotplug_reg;
1921b796b971SDhinakaran Pandiyan 
19228cee664dSAndrzej Hajda 		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0);
1923b796b971SDhinakaran Pandiyan 
19240398993bSVille Syrjälä 		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
19250398993bSVille Syrjälä 				   trigger_tbt, dig_hotplug_reg,
19265a4dd6f0SJani Nikula 				   dev_priv->display.hotplug.hpd,
1927da51e4baSVille Syrjälä 				   gen11_port_hotplug_long_detect);
1928b796b971SDhinakaran Pandiyan 	}
1929b796b971SDhinakaran Pandiyan 
1930b796b971SDhinakaran Pandiyan 	if (pin_mask)
1931b796b971SDhinakaran Pandiyan 		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
1932b796b971SDhinakaran Pandiyan 	else
193300376ccfSWambui Karuga 		drm_err(&dev_priv->drm,
193400376ccfSWambui Karuga 			"Unexpected DE HPD interrupt 0x%08x\n", iir);
1935121e758eSDhinakaran Pandiyan }
1936121e758eSDhinakaran Pandiyan 
19379d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
19389d17210fSLucas De Marchi {
193955523360SLucas De Marchi 	u32 mask;
19409d17210fSLucas De Marchi 
1941*c0f3faafSGustavo Sousa 	if (DISPLAY_VER(dev_priv) >= 14)
1942*c0f3faafSGustavo Sousa 		return TGL_DE_PORT_AUX_DDIA |
1943*c0f3faafSGustavo Sousa 			TGL_DE_PORT_AUX_DDIB;
1944*c0f3faafSGustavo Sousa 	else if (DISPLAY_VER(dev_priv) >= 13)
194520fe778fSMatt Roper 		return TGL_DE_PORT_AUX_DDIA |
194620fe778fSMatt Roper 			TGL_DE_PORT_AUX_DDIB |
194720fe778fSMatt Roper 			TGL_DE_PORT_AUX_DDIC |
194820fe778fSMatt Roper 			XELPD_DE_PORT_AUX_DDID |
194920fe778fSMatt Roper 			XELPD_DE_PORT_AUX_DDIE |
195020fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC1 |
195120fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC2 |
195220fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC3 |
195320fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC4;
195420fe778fSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
195555523360SLucas De Marchi 		return TGL_DE_PORT_AUX_DDIA |
195655523360SLucas De Marchi 			TGL_DE_PORT_AUX_DDIB |
1957e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_DDIC |
1958e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC1 |
1959e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC2 |
1960e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC3 |
1961e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC4 |
1962e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC5 |
1963e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC6;
1964e5df52dcSMatt Roper 
196555523360SLucas De Marchi 
196655523360SLucas De Marchi 	mask = GEN8_AUX_CHANNEL_A;
1967373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 9)
19689d17210fSLucas De Marchi 		mask |= GEN9_AUX_CHANNEL_B |
19699d17210fSLucas De Marchi 			GEN9_AUX_CHANNEL_C |
19709d17210fSLucas De Marchi 			GEN9_AUX_CHANNEL_D;
19719d17210fSLucas De Marchi 
1972938a8a9aSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 11) {
1973938a8a9aSLucas De Marchi 		mask |= ICL_AUX_CHANNEL_F;
197455523360SLucas De Marchi 		mask |= ICL_AUX_CHANNEL_E;
1975938a8a9aSLucas De Marchi 	}
19769d17210fSLucas De Marchi 
19779d17210fSLucas De Marchi 	return mask;
19789d17210fSLucas De Marchi }
19799d17210fSLucas De Marchi 
19805270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
19815270130dSVille Syrjälä {
19821649a4ccSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
198399e2d8bcSMatt Roper 		return RKL_DE_PIPE_IRQ_FAULT_ERRORS;
1984373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11)
1985d506a65dSMatt Roper 		return GEN11_DE_PIPE_IRQ_FAULT_ERRORS;
1986373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 9)
19875270130dSVille Syrjälä 		return GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
19885270130dSVille Syrjälä 	else
19895270130dSVille Syrjälä 		return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
19905270130dSVille Syrjälä }
19915270130dSVille Syrjälä 
199246c63d24SJosé Roberto de Souza static void
199346c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
1994abd58f01SBen Widawsky {
1995e04f7eceSVille Syrjälä 	bool found = false;
1996e04f7eceSVille Syrjälä 
1997e04f7eceSVille Syrjälä 	if (iir & GEN8_DE_MISC_GSE) {
199891d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
1999e04f7eceSVille Syrjälä 		found = true;
2000e04f7eceSVille Syrjälä 	}
2001e04f7eceSVille Syrjälä 
2002e04f7eceSVille Syrjälä 	if (iir & GEN8_DE_EDP_PSR) {
2003b64d6c51SGwan-gyeong Mun 		struct intel_encoder *encoder;
20048241cfbeSJosé Roberto de Souza 		u32 psr_iir;
20058241cfbeSJosé Roberto de Souza 		i915_reg_t iir_reg;
20068241cfbeSJosé Roberto de Souza 
2007a22af61dSJosé Roberto de Souza 		for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
2008b64d6c51SGwan-gyeong Mun 			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2009b64d6c51SGwan-gyeong Mun 
2010373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) >= 12)
2011b64d6c51SGwan-gyeong Mun 				iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder);
20128241cfbeSJosé Roberto de Souza 			else
20138241cfbeSJosé Roberto de Souza 				iir_reg = EDP_PSR_IIR;
20148241cfbeSJosé Roberto de Souza 
20158cee664dSAndrzej Hajda 			psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0);
20168241cfbeSJosé Roberto de Souza 
20178241cfbeSJosé Roberto de Souza 			if (psr_iir)
20188241cfbeSJosé Roberto de Souza 				found = true;
201954fd3149SDhinakaran Pandiyan 
2020b64d6c51SGwan-gyeong Mun 			intel_psr_irq_handler(intel_dp, psr_iir);
2021b64d6c51SGwan-gyeong Mun 
2022b64d6c51SGwan-gyeong Mun 			/* prior GEN12 only have one EDP PSR */
2023373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) < 12)
2024b64d6c51SGwan-gyeong Mun 				break;
2025b64d6c51SGwan-gyeong Mun 		}
2026e04f7eceSVille Syrjälä 	}
2027e04f7eceSVille Syrjälä 
2028e04f7eceSVille Syrjälä 	if (!found)
202900376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n");
2030abd58f01SBen Widawsky }
203146c63d24SJosé Roberto de Souza 
203200acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv,
203300acb329SVandita Kulkarni 					   u32 te_trigger)
203400acb329SVandita Kulkarni {
203500acb329SVandita Kulkarni 	enum pipe pipe = INVALID_PIPE;
203600acb329SVandita Kulkarni 	enum transcoder dsi_trans;
203700acb329SVandita Kulkarni 	enum port port;
203800acb329SVandita Kulkarni 	u32 val, tmp;
203900acb329SVandita Kulkarni 
204000acb329SVandita Kulkarni 	/*
204100acb329SVandita Kulkarni 	 * Incase of dual link, TE comes from DSI_1
204200acb329SVandita Kulkarni 	 * this is to check if dual link is enabled
204300acb329SVandita Kulkarni 	 */
20442939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0));
204500acb329SVandita Kulkarni 	val &= PORT_SYNC_MODE_ENABLE;
204600acb329SVandita Kulkarni 
204700acb329SVandita Kulkarni 	/*
204800acb329SVandita Kulkarni 	 * if dual link is enabled, then read DSI_0
204900acb329SVandita Kulkarni 	 * transcoder registers
205000acb329SVandita Kulkarni 	 */
205100acb329SVandita Kulkarni 	port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ?
205200acb329SVandita Kulkarni 						  PORT_A : PORT_B;
205300acb329SVandita Kulkarni 	dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1;
205400acb329SVandita Kulkarni 
205500acb329SVandita Kulkarni 	/* Check if DSI configured in command mode */
20562939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans));
205700acb329SVandita Kulkarni 	val = val & OP_MODE_MASK;
205800acb329SVandita Kulkarni 
205900acb329SVandita Kulkarni 	if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) {
206000acb329SVandita Kulkarni 		drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n");
206100acb329SVandita Kulkarni 		return;
206200acb329SVandita Kulkarni 	}
206300acb329SVandita Kulkarni 
206400acb329SVandita Kulkarni 	/* Get PIPE for handling VBLANK event */
20652939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans));
206600acb329SVandita Kulkarni 	switch (val & TRANS_DDI_EDP_INPUT_MASK) {
206700acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_A_ON:
206800acb329SVandita Kulkarni 		pipe = PIPE_A;
206900acb329SVandita Kulkarni 		break;
207000acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_B_ONOFF:
207100acb329SVandita Kulkarni 		pipe = PIPE_B;
207200acb329SVandita Kulkarni 		break;
207300acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_C_ONOFF:
207400acb329SVandita Kulkarni 		pipe = PIPE_C;
207500acb329SVandita Kulkarni 		break;
207600acb329SVandita Kulkarni 	default:
207700acb329SVandita Kulkarni 		drm_err(&dev_priv->drm, "Invalid PIPE\n");
207800acb329SVandita Kulkarni 		return;
207900acb329SVandita Kulkarni 	}
208000acb329SVandita Kulkarni 
208100acb329SVandita Kulkarni 	intel_handle_vblank(dev_priv, pipe);
208200acb329SVandita Kulkarni 
208300acb329SVandita Kulkarni 	/* clear TE in dsi IIR */
208400acb329SVandita Kulkarni 	port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A;
20858cee664dSAndrzej Hajda 	tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
208600acb329SVandita Kulkarni }
208700acb329SVandita Kulkarni 
2088cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915)
2089cda195f1SVille Syrjälä {
2090373abf1aSMatt Roper 	if (DISPLAY_VER(i915) >= 9)
2091cda195f1SVille Syrjälä 		return GEN9_PIPE_PLANE1_FLIP_DONE;
2092cda195f1SVille Syrjälä 	else
2093cda195f1SVille Syrjälä 		return GEN8_PIPE_PRIMARY_FLIP_DONE;
2094cda195f1SVille Syrjälä }
2095cda195f1SVille Syrjälä 
20968bcc0840SMatt Roper u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv)
20978bcc0840SMatt Roper {
20988bcc0840SMatt Roper 	u32 mask = GEN8_PIPE_FIFO_UNDERRUN;
20998bcc0840SMatt Roper 
21008bcc0840SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
21018bcc0840SMatt Roper 		mask |= XELPD_PIPE_SOFT_UNDERRUN |
21028bcc0840SMatt Roper 			XELPD_PIPE_HARD_UNDERRUN;
21038bcc0840SMatt Roper 
21048bcc0840SMatt Roper 	return mask;
21058bcc0840SMatt Roper }
21068bcc0840SMatt Roper 
2107babde06dSMika Kahola static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir)
2108babde06dSMika Kahola {
2109babde06dSMika Kahola 	u32 pica_ier = 0;
2110babde06dSMika Kahola 
2111babde06dSMika Kahola 	*pica_iir = 0;
2112babde06dSMika Kahola 	*pch_iir = intel_de_read(i915, SDEIIR);
2113babde06dSMika Kahola 	if (!*pch_iir)
2114babde06dSMika Kahola 		return;
2115babde06dSMika Kahola 
2116babde06dSMika Kahola 	/**
2117babde06dSMika Kahola 	 * PICA IER must be disabled/re-enabled around clearing PICA IIR and
2118babde06dSMika Kahola 	 * SDEIIR, to avoid losing PICA IRQs and to ensure that such IRQs set
2119babde06dSMika Kahola 	 * their flags both in the PICA and SDE IIR.
2120babde06dSMika Kahola 	 */
2121babde06dSMika Kahola 	if (*pch_iir & SDE_PICAINTERRUPT) {
2122babde06dSMika Kahola 		drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTP);
2123babde06dSMika Kahola 
2124babde06dSMika Kahola 		pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0);
2125babde06dSMika Kahola 		*pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR);
2126babde06dSMika Kahola 		intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir);
2127babde06dSMika Kahola 	}
2128babde06dSMika Kahola 
2129babde06dSMika Kahola 	intel_de_write(i915, SDEIIR, *pch_iir);
2130babde06dSMika Kahola 
2131babde06dSMika Kahola 	if (pica_ier)
2132babde06dSMika Kahola 		intel_de_write(i915, PICAINTERRUPT_IER, pica_ier);
2133babde06dSMika Kahola }
2134babde06dSMika Kahola 
213546c63d24SJosé Roberto de Souza static irqreturn_t
213646c63d24SJosé Roberto de Souza gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
213746c63d24SJosé Roberto de Souza {
213846c63d24SJosé Roberto de Souza 	irqreturn_t ret = IRQ_NONE;
213946c63d24SJosé Roberto de Souza 	u32 iir;
214046c63d24SJosé Roberto de Souza 	enum pipe pipe;
214146c63d24SJosé Roberto de Souza 
2142a844cfbeSJosé Roberto de Souza 	drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv));
2143a844cfbeSJosé Roberto de Souza 
214446c63d24SJosé Roberto de Souza 	if (master_ctl & GEN8_DE_MISC_IRQ) {
21452939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR);
214646c63d24SJosé Roberto de Souza 		if (iir) {
21472939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir);
214846c63d24SJosé Roberto de Souza 			ret = IRQ_HANDLED;
214946c63d24SJosé Roberto de Souza 			gen8_de_misc_irq_handler(dev_priv, iir);
215046c63d24SJosé Roberto de Souza 		} else {
21519a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
215200376ccfSWambui Karuga 					    "The master control interrupt lied (DE MISC)!\n");
2153abd58f01SBen Widawsky 		}
215446c63d24SJosé Roberto de Souza 	}
2155abd58f01SBen Widawsky 
2156373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
21572939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR);
2158121e758eSDhinakaran Pandiyan 		if (iir) {
21592939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir);
2160121e758eSDhinakaran Pandiyan 			ret = IRQ_HANDLED;
2161121e758eSDhinakaran Pandiyan 			gen11_hpd_irq_handler(dev_priv, iir);
2162121e758eSDhinakaran Pandiyan 		} else {
21639a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
216400376ccfSWambui Karuga 					    "The master control interrupt lied, (DE HPD)!\n");
2165121e758eSDhinakaran Pandiyan 		}
2166121e758eSDhinakaran Pandiyan 	}
2167121e758eSDhinakaran Pandiyan 
21686d766f02SDaniel Vetter 	if (master_ctl & GEN8_DE_PORT_IRQ) {
21692939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR);
2170e32192e1STvrtko Ursulin 		if (iir) {
2171d04a492dSShashank Sharma 			bool found = false;
2172cebd87a0SVille Syrjälä 
21732939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir);
21746d766f02SDaniel Vetter 			ret = IRQ_HANDLED;
217588e04703SJesse Barnes 
21769d17210fSLucas De Marchi 			if (iir & gen8_de_port_aux_mask(dev_priv)) {
217791d14251STvrtko Ursulin 				dp_aux_irq_handler(dev_priv);
2178d04a492dSShashank Sharma 				found = true;
2179d04a492dSShashank Sharma 			}
2180d04a492dSShashank Sharma 
218170bfb307SMatt Roper 			if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
21829a55a620SVille Syrjälä 				u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK;
21839a55a620SVille Syrjälä 
21849a55a620SVille Syrjälä 				if (hotplug_trigger) {
21859a55a620SVille Syrjälä 					bxt_hpd_irq_handler(dev_priv, hotplug_trigger);
2186d04a492dSShashank Sharma 					found = true;
2187d04a492dSShashank Sharma 				}
2188e32192e1STvrtko Ursulin 			} else if (IS_BROADWELL(dev_priv)) {
21899a55a620SVille Syrjälä 				u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK;
21909a55a620SVille Syrjälä 
21919a55a620SVille Syrjälä 				if (hotplug_trigger) {
21929a55a620SVille Syrjälä 					ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
2193e32192e1STvrtko Ursulin 					found = true;
2194e32192e1STvrtko Ursulin 				}
2195e32192e1STvrtko Ursulin 			}
2196d04a492dSShashank Sharma 
219770bfb307SMatt Roper 			if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
219870bfb307SMatt Roper 			    (iir & BXT_DE_PORT_GMBUS)) {
219991d14251STvrtko Ursulin 				gmbus_irq_handler(dev_priv);
22009e63743eSShashank Sharma 				found = true;
22019e63743eSShashank Sharma 			}
22029e63743eSShashank Sharma 
2203373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) >= 11) {
22049a55a620SVille Syrjälä 				u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
22059a55a620SVille Syrjälä 
22069a55a620SVille Syrjälä 				if (te_trigger) {
22079a55a620SVille Syrjälä 					gen11_dsi_te_interrupt_handler(dev_priv, te_trigger);
220800acb329SVandita Kulkarni 					found = true;
220900acb329SVandita Kulkarni 				}
221000acb329SVandita Kulkarni 			}
221100acb329SVandita Kulkarni 
2212d04a492dSShashank Sharma 			if (!found)
22139a4cea62SLucas De Marchi 				drm_err_ratelimited(&dev_priv->drm,
221400376ccfSWambui Karuga 						    "Unexpected DE Port interrupt\n");
22156d766f02SDaniel Vetter 		}
221638cc46d7SOscar Mateo 		else
22179a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
221800376ccfSWambui Karuga 					    "The master control interrupt lied (DE PORT)!\n");
22196d766f02SDaniel Vetter 	}
22206d766f02SDaniel Vetter 
2221055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
2222fd3a4024SDaniel Vetter 		u32 fault_errors;
2223abd58f01SBen Widawsky 
2224c42664ccSDaniel Vetter 		if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
2225c42664ccSDaniel Vetter 			continue;
2226c42664ccSDaniel Vetter 
22272939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe));
2228e32192e1STvrtko Ursulin 		if (!iir) {
22299a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
223000376ccfSWambui Karuga 					    "The master control interrupt lied (DE PIPE)!\n");
2231e32192e1STvrtko Ursulin 			continue;
2232e32192e1STvrtko Ursulin 		}
2233770de83dSDamien Lespiau 
2234e32192e1STvrtko Ursulin 		ret = IRQ_HANDLED;
22352939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir);
2236e32192e1STvrtko Ursulin 
2237fd3a4024SDaniel Vetter 		if (iir & GEN8_PIPE_VBLANK)
2238aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
2239abd58f01SBen Widawsky 
2240cda195f1SVille Syrjälä 		if (iir & gen8_de_pipe_flip_done_mask(dev_priv))
22411288f9b0SKarthik B S 			flip_done_handler(dev_priv, pipe);
22421288f9b0SKarthik B S 
2243e32192e1STvrtko Ursulin 		if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
224491d14251STvrtko Ursulin 			hsw_pipe_crc_irq_handler(dev_priv, pipe);
22450fbe7870SDaniel Vetter 
22468bcc0840SMatt Roper 		if (iir & gen8_de_pipe_underrun_mask(dev_priv))
2247e32192e1STvrtko Ursulin 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
224838d83c96SDaniel Vetter 
22495270130dSVille Syrjälä 		fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
2250770de83dSDamien Lespiau 		if (fault_errors)
22519a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
225200376ccfSWambui Karuga 					    "Fault errors on pipe %c: 0x%08x\n",
225330100f2bSDaniel Vetter 					    pipe_name(pipe),
2254e32192e1STvrtko Ursulin 					    fault_errors);
2255abd58f01SBen Widawsky 	}
2256abd58f01SBen Widawsky 
225791d14251STvrtko Ursulin 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
2258266ea3d9SShashank Sharma 	    master_ctl & GEN8_DE_PCH_IRQ) {
2259babde06dSMika Kahola 		u32 pica_iir;
2260babde06dSMika Kahola 
226192d03a80SDaniel Vetter 		/*
226292d03a80SDaniel Vetter 		 * FIXME(BDW): Assume for now that the new interrupt handling
226392d03a80SDaniel Vetter 		 * scheme also closed the SDE interrupt handling race we've seen
226492d03a80SDaniel Vetter 		 * on older pch-split platforms. But this needs testing.
226592d03a80SDaniel Vetter 		 */
2266babde06dSMika Kahola 		gen8_read_and_ack_pch_irqs(dev_priv, &iir, &pica_iir);
2267e32192e1STvrtko Ursulin 		if (iir) {
226892d03a80SDaniel Vetter 			ret = IRQ_HANDLED;
22696dbf30ceSVille Syrjälä 
2270babde06dSMika Kahola 			if (pica_iir)
2271babde06dSMika Kahola 				xelpdp_pica_irq_handler(dev_priv, pica_iir);
2272babde06dSMika Kahola 
227358676af6SLucas De Marchi 			if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
227458676af6SLucas De Marchi 				icp_irq_handler(dev_priv, iir);
2275c6c30b91SRodrigo Vivi 			else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
227691d14251STvrtko Ursulin 				spt_irq_handler(dev_priv, iir);
22776dbf30ceSVille Syrjälä 			else
227891d14251STvrtko Ursulin 				cpt_irq_handler(dev_priv, iir);
22792dfb0b81SJani Nikula 		} else {
22802dfb0b81SJani Nikula 			/*
22812dfb0b81SJani Nikula 			 * Like on previous PCH there seems to be something
22822dfb0b81SJani Nikula 			 * fishy going on with forwarding PCH interrupts.
22832dfb0b81SJani Nikula 			 */
228400376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm,
228500376ccfSWambui Karuga 				"The master control interrupt lied (SDE)!\n");
22862dfb0b81SJani Nikula 		}
228792d03a80SDaniel Vetter 	}
228892d03a80SDaniel Vetter 
2289f11a0f46STvrtko Ursulin 	return ret;
2290f11a0f46STvrtko Ursulin }
2291f11a0f46STvrtko Ursulin 
22924376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs)
22934376b9c9SMika Kuoppala {
22944376b9c9SMika Kuoppala 	raw_reg_write(regs, GEN8_MASTER_IRQ, 0);
22954376b9c9SMika Kuoppala 
22964376b9c9SMika Kuoppala 	/*
22974376b9c9SMika Kuoppala 	 * Now with master disabled, get a sample of level indications
22984376b9c9SMika Kuoppala 	 * for this interrupt. Indications will be cleared on related acks.
22994376b9c9SMika Kuoppala 	 * New indications can and will light up during processing,
23004376b9c9SMika Kuoppala 	 * and will generate new interrupt after enabling master.
23014376b9c9SMika Kuoppala 	 */
23024376b9c9SMika Kuoppala 	return raw_reg_read(regs, GEN8_MASTER_IRQ);
23034376b9c9SMika Kuoppala }
23044376b9c9SMika Kuoppala 
23054376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs)
23064376b9c9SMika Kuoppala {
23074376b9c9SMika Kuoppala 	raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
23084376b9c9SMika Kuoppala }
23094376b9c9SMika Kuoppala 
2310f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg)
2311f11a0f46STvrtko Ursulin {
2312b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
231325286aacSDaniele Ceraolo Spurio 	void __iomem * const regs = dev_priv->uncore.regs;
2314f11a0f46STvrtko Ursulin 	u32 master_ctl;
2315f11a0f46STvrtko Ursulin 
2316f11a0f46STvrtko Ursulin 	if (!intel_irqs_enabled(dev_priv))
2317f11a0f46STvrtko Ursulin 		return IRQ_NONE;
2318f11a0f46STvrtko Ursulin 
23194376b9c9SMika Kuoppala 	master_ctl = gen8_master_intr_disable(regs);
23204376b9c9SMika Kuoppala 	if (!master_ctl) {
23214376b9c9SMika Kuoppala 		gen8_master_intr_enable(regs);
2322f11a0f46STvrtko Ursulin 		return IRQ_NONE;
23234376b9c9SMika Kuoppala 	}
2324f11a0f46STvrtko Ursulin 
23256cc32f15SChris Wilson 	/* Find, queue (onto bottom-halves), then clear each source */
23262cbc876dSMichał Winiarski 	gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
2327f0fd96f5SChris Wilson 
2328f0fd96f5SChris Wilson 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
2329f0fd96f5SChris Wilson 	if (master_ctl & ~GEN8_GT_IRQS) {
23309102650fSDaniele Ceraolo Spurio 		disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
233155ef72f2SChris Wilson 		gen8_de_irq_handler(dev_priv, master_ctl);
23329102650fSDaniele Ceraolo Spurio 		enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
2333f0fd96f5SChris Wilson 	}
2334f11a0f46STvrtko Ursulin 
23354376b9c9SMika Kuoppala 	gen8_master_intr_enable(regs);
2336abd58f01SBen Widawsky 
23379c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
23389c6508b9SThomas Gleixner 
233955ef72f2SChris Wilson 	return IRQ_HANDLED;
2340abd58f01SBen Widawsky }
2341abd58f01SBen Widawsky 
234251951ae7SMika Kuoppala static u32
2343ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl)
2344df0d28c1SDhinakaran Pandiyan {
2345ddcf980fSAnusha Srivatsa 	void __iomem * const regs = i915->uncore.regs;
23467a909383SChris Wilson 	u32 iir;
2347df0d28c1SDhinakaran Pandiyan 
2348df0d28c1SDhinakaran Pandiyan 	if (!(master_ctl & GEN11_GU_MISC_IRQ))
23497a909383SChris Wilson 		return 0;
2350df0d28c1SDhinakaran Pandiyan 
23517a909383SChris Wilson 	iir = raw_reg_read(regs, GEN11_GU_MISC_IIR);
23527a909383SChris Wilson 	if (likely(iir))
23537a909383SChris Wilson 		raw_reg_write(regs, GEN11_GU_MISC_IIR, iir);
23547a909383SChris Wilson 
23557a909383SChris Wilson 	return iir;
2356df0d28c1SDhinakaran Pandiyan }
2357df0d28c1SDhinakaran Pandiyan 
2358df0d28c1SDhinakaran Pandiyan static void
2359ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir)
2360df0d28c1SDhinakaran Pandiyan {
2361df0d28c1SDhinakaran Pandiyan 	if (iir & GEN11_GU_MISC_GSE)
2362ddcf980fSAnusha Srivatsa 		intel_opregion_asle_intr(i915);
2363df0d28c1SDhinakaran Pandiyan }
2364df0d28c1SDhinakaran Pandiyan 
236581067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs)
236681067b71SMika Kuoppala {
236781067b71SMika Kuoppala 	raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0);
236881067b71SMika Kuoppala 
236981067b71SMika Kuoppala 	/*
237081067b71SMika Kuoppala 	 * Now with master disabled, get a sample of level indications
237181067b71SMika Kuoppala 	 * for this interrupt. Indications will be cleared on related acks.
237281067b71SMika Kuoppala 	 * New indications can and will light up during processing,
237381067b71SMika Kuoppala 	 * and will generate new interrupt after enabling master.
237481067b71SMika Kuoppala 	 */
237581067b71SMika Kuoppala 	return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
237681067b71SMika Kuoppala }
237781067b71SMika Kuoppala 
237881067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs)
237981067b71SMika Kuoppala {
238081067b71SMika Kuoppala 	raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ);
238181067b71SMika Kuoppala }
238281067b71SMika Kuoppala 
2383a3265d85SMatt Roper static void
2384a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915)
2385a3265d85SMatt Roper {
2386a3265d85SMatt Roper 	void __iomem * const regs = i915->uncore.regs;
2387a3265d85SMatt Roper 	const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
2388a3265d85SMatt Roper 
2389a3265d85SMatt Roper 	disable_rpm_wakeref_asserts(&i915->runtime_pm);
2390a3265d85SMatt Roper 	/*
2391a3265d85SMatt Roper 	 * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
2392a3265d85SMatt Roper 	 * for the display related bits.
2393a3265d85SMatt Roper 	 */
2394a3265d85SMatt Roper 	raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0);
2395a3265d85SMatt Roper 	gen8_de_irq_handler(i915, disp_ctl);
2396a3265d85SMatt Roper 	raw_reg_write(regs, GEN11_DISPLAY_INT_CTL,
2397a3265d85SMatt Roper 		      GEN11_DISPLAY_IRQ_ENABLE);
2398a3265d85SMatt Roper 
2399a3265d85SMatt Roper 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
2400a3265d85SMatt Roper }
2401a3265d85SMatt Roper 
240222e26af7SPaulo Zanoni static irqreturn_t gen11_irq_handler(int irq, void *arg)
240351951ae7SMika Kuoppala {
240422e26af7SPaulo Zanoni 	struct drm_i915_private *i915 = arg;
240525286aacSDaniele Ceraolo Spurio 	void __iomem * const regs = i915->uncore.regs;
24062cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(i915);
240751951ae7SMika Kuoppala 	u32 master_ctl;
2408df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_iir;
240951951ae7SMika Kuoppala 
241051951ae7SMika Kuoppala 	if (!intel_irqs_enabled(i915))
241151951ae7SMika Kuoppala 		return IRQ_NONE;
241251951ae7SMika Kuoppala 
241322e26af7SPaulo Zanoni 	master_ctl = gen11_master_intr_disable(regs);
241481067b71SMika Kuoppala 	if (!master_ctl) {
241522e26af7SPaulo Zanoni 		gen11_master_intr_enable(regs);
241651951ae7SMika Kuoppala 		return IRQ_NONE;
241781067b71SMika Kuoppala 	}
241851951ae7SMika Kuoppala 
24196cc32f15SChris Wilson 	/* Find, queue (onto bottom-halves), then clear each source */
24209b77011eSTvrtko Ursulin 	gen11_gt_irq_handler(gt, master_ctl);
242151951ae7SMika Kuoppala 
242251951ae7SMika Kuoppala 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
2423a3265d85SMatt Roper 	if (master_ctl & GEN11_DISPLAY_IRQ)
2424a3265d85SMatt Roper 		gen11_display_irq_handler(i915);
242551951ae7SMika Kuoppala 
2426ddcf980fSAnusha Srivatsa 	gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl);
2427df0d28c1SDhinakaran Pandiyan 
242822e26af7SPaulo Zanoni 	gen11_master_intr_enable(regs);
242951951ae7SMika Kuoppala 
2430ddcf980fSAnusha Srivatsa 	gen11_gu_misc_irq_handler(i915, gu_misc_iir);
2431df0d28c1SDhinakaran Pandiyan 
24329c6508b9SThomas Gleixner 	pmu_irq_stats(i915, IRQ_HANDLED);
24339c6508b9SThomas Gleixner 
243451951ae7SMika Kuoppala 	return IRQ_HANDLED;
243551951ae7SMika Kuoppala }
243651951ae7SMika Kuoppala 
243722e26af7SPaulo Zanoni static inline u32 dg1_master_intr_disable(void __iomem * const regs)
243897b492f5SLucas De Marchi {
243997b492f5SLucas De Marchi 	u32 val;
244097b492f5SLucas De Marchi 
244197b492f5SLucas De Marchi 	/* First disable interrupts */
244222e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0);
244397b492f5SLucas De Marchi 
244497b492f5SLucas De Marchi 	/* Get the indication levels and ack the master unit */
244522e26af7SPaulo Zanoni 	val = raw_reg_read(regs, DG1_MSTR_TILE_INTR);
244697b492f5SLucas De Marchi 	if (unlikely(!val))
244797b492f5SLucas De Marchi 		return 0;
244897b492f5SLucas De Marchi 
244922e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, val);
245097b492f5SLucas De Marchi 
245197b492f5SLucas De Marchi 	return val;
245297b492f5SLucas De Marchi }
245397b492f5SLucas De Marchi 
245497b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs)
245597b492f5SLucas De Marchi {
245622e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ);
245797b492f5SLucas De Marchi }
245897b492f5SLucas De Marchi 
245997b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg)
246097b492f5SLucas De Marchi {
246122e26af7SPaulo Zanoni 	struct drm_i915_private * const i915 = arg;
24622cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(i915);
2463fd4d7904SPaulo Zanoni 	void __iomem * const regs = gt->uncore->regs;
246422e26af7SPaulo Zanoni 	u32 master_tile_ctl, master_ctl;
246522e26af7SPaulo Zanoni 	u32 gu_misc_iir;
246622e26af7SPaulo Zanoni 
246722e26af7SPaulo Zanoni 	if (!intel_irqs_enabled(i915))
246822e26af7SPaulo Zanoni 		return IRQ_NONE;
246922e26af7SPaulo Zanoni 
247022e26af7SPaulo Zanoni 	master_tile_ctl = dg1_master_intr_disable(regs);
247122e26af7SPaulo Zanoni 	if (!master_tile_ctl) {
247222e26af7SPaulo Zanoni 		dg1_master_intr_enable(regs);
247322e26af7SPaulo Zanoni 		return IRQ_NONE;
247422e26af7SPaulo Zanoni 	}
247522e26af7SPaulo Zanoni 
247622e26af7SPaulo Zanoni 	/* FIXME: we only support tile 0 for now. */
247722e26af7SPaulo Zanoni 	if (master_tile_ctl & DG1_MSTR_TILE(0)) {
247822e26af7SPaulo Zanoni 		master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
247922e26af7SPaulo Zanoni 		raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl);
248022e26af7SPaulo Zanoni 	} else {
2481a10234fdSTvrtko Ursulin 		drm_err(&i915->drm, "Tile not supported: 0x%08x\n",
2482a10234fdSTvrtko Ursulin 			master_tile_ctl);
248322e26af7SPaulo Zanoni 		dg1_master_intr_enable(regs);
248422e26af7SPaulo Zanoni 		return IRQ_NONE;
248522e26af7SPaulo Zanoni 	}
248622e26af7SPaulo Zanoni 
248722e26af7SPaulo Zanoni 	gen11_gt_irq_handler(gt, master_ctl);
248822e26af7SPaulo Zanoni 
248922e26af7SPaulo Zanoni 	if (master_ctl & GEN11_DISPLAY_IRQ)
249022e26af7SPaulo Zanoni 		gen11_display_irq_handler(i915);
249122e26af7SPaulo Zanoni 
2492ddcf980fSAnusha Srivatsa 	gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl);
249322e26af7SPaulo Zanoni 
249422e26af7SPaulo Zanoni 	dg1_master_intr_enable(regs);
249522e26af7SPaulo Zanoni 
2496ddcf980fSAnusha Srivatsa 	gen11_gu_misc_irq_handler(i915, gu_misc_iir);
249722e26af7SPaulo Zanoni 
249822e26af7SPaulo Zanoni 	pmu_irq_stats(i915, IRQ_HANDLED);
249922e26af7SPaulo Zanoni 
250022e26af7SPaulo Zanoni 	return IRQ_HANDLED;
250197b492f5SLucas De Marchi }
250297b492f5SLucas De Marchi 
250342f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which
250442f52ef8SKeith Packard  * we use as a pipe index
250542f52ef8SKeith Packard  */
250608fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc)
25070a3e67a4SJesse Barnes {
250808fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
250908fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2510e9d21d7fSKeith Packard 	unsigned long irqflags;
251171e0ffa5SJesse Barnes 
25121ec14ad3SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
251386e83e35SChris Wilson 	i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
251486e83e35SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
251586e83e35SChris Wilson 
251686e83e35SChris Wilson 	return 0;
251786e83e35SChris Wilson }
251886e83e35SChris Wilson 
25197d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc)
2520d938da6bSVille Syrjälä {
252108fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
2522d938da6bSVille Syrjälä 
25237d423af9SVille Syrjälä 	/*
25247d423af9SVille Syrjälä 	 * Vblank interrupts fail to wake the device up from C2+.
25257d423af9SVille Syrjälä 	 * Disabling render clock gating during C-states avoids
25267d423af9SVille Syrjälä 	 * the problem. There is a small power cost so we do this
25277d423af9SVille Syrjälä 	 * only when vblank interrupts are actually enabled.
25287d423af9SVille Syrjälä 	 */
25297d423af9SVille Syrjälä 	if (dev_priv->vblank_enabled++ == 0)
25302939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
2531d938da6bSVille Syrjälä 
253208fa8fd0SVille Syrjälä 	return i8xx_enable_vblank(crtc);
2533d938da6bSVille Syrjälä }
2534d938da6bSVille Syrjälä 
253508fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc)
253686e83e35SChris Wilson {
253708fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
253808fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
253986e83e35SChris Wilson 	unsigned long irqflags;
254086e83e35SChris Wilson 
254186e83e35SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
25427c463586SKeith Packard 	i915_enable_pipestat(dev_priv, pipe,
2543755e9019SImre Deak 			     PIPE_START_VBLANK_INTERRUPT_STATUS);
25441ec14ad3SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
25458692d00eSChris Wilson 
25460a3e67a4SJesse Barnes 	return 0;
25470a3e67a4SJesse Barnes }
25480a3e67a4SJesse Barnes 
254908fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc)
2550f796cf8fSJesse Barnes {
255108fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
255208fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2553f796cf8fSJesse Barnes 	unsigned long irqflags;
2554373abf1aSMatt Roper 	u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
255586e83e35SChris Wilson 		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
2556f796cf8fSJesse Barnes 
2557f796cf8fSJesse Barnes 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2558fbdedaeaSVille Syrjälä 	ilk_enable_display_irq(dev_priv, bit);
2559b1f14ad0SJesse Barnes 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2560b1f14ad0SJesse Barnes 
25612e8bf223SDhinakaran Pandiyan 	/* Even though there is no DMC, frame counter can get stuck when
25622e8bf223SDhinakaran Pandiyan 	 * PSR is active as no frames are generated.
25632e8bf223SDhinakaran Pandiyan 	 */
25642e8bf223SDhinakaran Pandiyan 	if (HAS_PSR(dev_priv))
256508fa8fd0SVille Syrjälä 		drm_crtc_vblank_restore(crtc);
25662e8bf223SDhinakaran Pandiyan 
2567b1f14ad0SJesse Barnes 	return 0;
2568b1f14ad0SJesse Barnes }
2569b1f14ad0SJesse Barnes 
25709c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
25719c9e97c4SVandita Kulkarni 				   bool enable)
25729c9e97c4SVandita Kulkarni {
25739c9e97c4SVandita Kulkarni 	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
25749c9e97c4SVandita Kulkarni 	enum port port;
25759c9e97c4SVandita Kulkarni 
25769c9e97c4SVandita Kulkarni 	if (!(intel_crtc->mode_flags &
25779c9e97c4SVandita Kulkarni 	    (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0)))
25789c9e97c4SVandita Kulkarni 		return false;
25799c9e97c4SVandita Kulkarni 
25809c9e97c4SVandita Kulkarni 	/* for dual link cases we consider TE from slave */
25819c9e97c4SVandita Kulkarni 	if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1)
25829c9e97c4SVandita Kulkarni 		port = PORT_B;
25839c9e97c4SVandita Kulkarni 	else
25849c9e97c4SVandita Kulkarni 		port = PORT_A;
25859c9e97c4SVandita Kulkarni 
25868cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT,
25878cee664dSAndrzej Hajda 			 enable ? 0 : DSI_TE_EVENT);
25889c9e97c4SVandita Kulkarni 
25898cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
25909c9e97c4SVandita Kulkarni 
25919c9e97c4SVandita Kulkarni 	return true;
25929c9e97c4SVandita Kulkarni }
25939c9e97c4SVandita Kulkarni 
2594f15f01a7SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *_crtc)
2595abd58f01SBen Widawsky {
2596f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(_crtc);
2597f15f01a7SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2598f15f01a7SVille Syrjälä 	enum pipe pipe = crtc->pipe;
2599abd58f01SBen Widawsky 	unsigned long irqflags;
2600abd58f01SBen Widawsky 
2601f15f01a7SVille Syrjälä 	if (gen11_dsi_configure_te(crtc, true))
26029c9e97c4SVandita Kulkarni 		return 0;
26039c9e97c4SVandita Kulkarni 
2604abd58f01SBen Widawsky 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2605013d3752SVille Syrjälä 	bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
2606abd58f01SBen Widawsky 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2607013d3752SVille Syrjälä 
26082e8bf223SDhinakaran Pandiyan 	/* Even if there is no DMC, frame counter can get stuck when
26092e8bf223SDhinakaran Pandiyan 	 * PSR is active as no frames are generated, so check only for PSR.
26102e8bf223SDhinakaran Pandiyan 	 */
26112e8bf223SDhinakaran Pandiyan 	if (HAS_PSR(dev_priv))
2612f15f01a7SVille Syrjälä 		drm_crtc_vblank_restore(&crtc->base);
26132e8bf223SDhinakaran Pandiyan 
2614abd58f01SBen Widawsky 	return 0;
2615abd58f01SBen Widawsky }
2616abd58f01SBen Widawsky 
261742f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which
261842f52ef8SKeith Packard  * we use as a pipe index
261942f52ef8SKeith Packard  */
262008fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc)
262186e83e35SChris Wilson {
262208fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
262308fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
262486e83e35SChris Wilson 	unsigned long irqflags;
262586e83e35SChris Wilson 
262686e83e35SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
262786e83e35SChris Wilson 	i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
262886e83e35SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
262986e83e35SChris Wilson }
263086e83e35SChris Wilson 
26317d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc)
2632d938da6bSVille Syrjälä {
263308fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
2634d938da6bSVille Syrjälä 
263508fa8fd0SVille Syrjälä 	i8xx_disable_vblank(crtc);
2636d938da6bSVille Syrjälä 
26377d423af9SVille Syrjälä 	if (--dev_priv->vblank_enabled == 0)
26382939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
2639d938da6bSVille Syrjälä }
2640d938da6bSVille Syrjälä 
264108fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc)
26420a3e67a4SJesse Barnes {
264308fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
264408fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2645e9d21d7fSKeith Packard 	unsigned long irqflags;
26460a3e67a4SJesse Barnes 
26471ec14ad3SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
26487c463586SKeith Packard 	i915_disable_pipestat(dev_priv, pipe,
2649755e9019SImre Deak 			      PIPE_START_VBLANK_INTERRUPT_STATUS);
26501ec14ad3SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
26510a3e67a4SJesse Barnes }
26520a3e67a4SJesse Barnes 
265308fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc)
2654f796cf8fSJesse Barnes {
265508fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
265608fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
2657f796cf8fSJesse Barnes 	unsigned long irqflags;
2658373abf1aSMatt Roper 	u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
265986e83e35SChris Wilson 		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
2660f796cf8fSJesse Barnes 
2661f796cf8fSJesse Barnes 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2662fbdedaeaSVille Syrjälä 	ilk_disable_display_irq(dev_priv, bit);
2663b1f14ad0SJesse Barnes 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2664b1f14ad0SJesse Barnes }
2665b1f14ad0SJesse Barnes 
2666f15f01a7SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *_crtc)
2667abd58f01SBen Widawsky {
2668f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(_crtc);
2669f15f01a7SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2670f15f01a7SVille Syrjälä 	enum pipe pipe = crtc->pipe;
2671abd58f01SBen Widawsky 	unsigned long irqflags;
2672abd58f01SBen Widawsky 
2673f15f01a7SVille Syrjälä 	if (gen11_dsi_configure_te(crtc, false))
26749c9e97c4SVandita Kulkarni 		return;
26759c9e97c4SVandita Kulkarni 
2676abd58f01SBen Widawsky 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
2677013d3752SVille Syrjälä 	bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
2678abd58f01SBen Widawsky 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
2679abd58f01SBen Widawsky }
2680abd58f01SBen Widawsky 
2681b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv)
268291738a95SPaulo Zanoni {
2683b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2684b16b2a2fSPaulo Zanoni 
26856e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
268691738a95SPaulo Zanoni 		return;
268791738a95SPaulo Zanoni 
2688b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, SDE);
2689105b122eSPaulo Zanoni 
26906e266956STvrtko Ursulin 	if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
26912939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff);
2692622364b6SPaulo Zanoni }
2693105b122eSPaulo Zanoni 
269470591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
269570591a41SVille Syrjälä {
2696b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2697b16b2a2fSPaulo Zanoni 
269871b8b41dSVille Syrjälä 	if (IS_CHERRYVIEW(dev_priv))
2699f0818984STvrtko Ursulin 		intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
270071b8b41dSVille Syrjälä 	else
27017d938bc0SVille Syrjälä 		intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
270271b8b41dSVille Syrjälä 
2703ad22d106SVille Syrjälä 	i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
27048cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
270570591a41SVille Syrjälä 
270644d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
270770591a41SVille Syrjälä 
2708b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, VLV_);
27098bd099a7SChris Wilson 	dev_priv->irq_mask = ~0u;
271070591a41SVille Syrjälä }
271170591a41SVille Syrjälä 
27128bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
27138bb61306SVille Syrjälä {
2714b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2715b16b2a2fSPaulo Zanoni 
27168bb61306SVille Syrjälä 	u32 pipestat_mask;
27179ab981f2SVille Syrjälä 	u32 enable_mask;
27188bb61306SVille Syrjälä 	enum pipe pipe;
27198bb61306SVille Syrjälä 
2720842ebf7aSVille Syrjälä 	pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
27218bb61306SVille Syrjälä 
27228bb61306SVille Syrjälä 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
27238bb61306SVille Syrjälä 	for_each_pipe(dev_priv, pipe)
27248bb61306SVille Syrjälä 		i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
27258bb61306SVille Syrjälä 
27269ab981f2SVille Syrjälä 	enable_mask = I915_DISPLAY_PORT_INTERRUPT |
27278bb61306SVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
2728ebf5f921SVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
2729ebf5f921SVille Syrjälä 		I915_LPE_PIPE_A_INTERRUPT |
2730ebf5f921SVille Syrjälä 		I915_LPE_PIPE_B_INTERRUPT;
2731ebf5f921SVille Syrjälä 
27328bb61306SVille Syrjälä 	if (IS_CHERRYVIEW(dev_priv))
2733ebf5f921SVille Syrjälä 		enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
2734ebf5f921SVille Syrjälä 			I915_LPE_PIPE_C_INTERRUPT;
27356b7eafc1SVille Syrjälä 
273648a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u);
27376b7eafc1SVille Syrjälä 
27389ab981f2SVille Syrjälä 	dev_priv->irq_mask = ~enable_mask;
27398bb61306SVille Syrjälä 
2740b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask);
27418bb61306SVille Syrjälä }
27428bb61306SVille Syrjälä 
27438bb61306SVille Syrjälä /* drm_dma.h hooks
27448bb61306SVille Syrjälä */
27459eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv)
27468bb61306SVille Syrjälä {
2747b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
27488bb61306SVille Syrjälä 
2749b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, DE);
2750e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
2751e44adb5dSChris Wilson 
2752651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) == 7)
2753f0818984STvrtko Ursulin 		intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff);
27548bb61306SVille Syrjälä 
2755fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
2756f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2757f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
2758fc340442SDaniel Vetter 	}
2759fc340442SDaniel Vetter 
27602cbc876dSMichał Winiarski 	gen5_gt_irq_reset(to_gt(dev_priv));
27618bb61306SVille Syrjälä 
2762b243f530STvrtko Ursulin 	ibx_irq_reset(dev_priv);
27638bb61306SVille Syrjälä }
27648bb61306SVille Syrjälä 
2765b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
27667e231dbeSJesse Barnes {
27672939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0);
27682939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
276934c7b8a7SVille Syrjälä 
27702cbc876dSMichał Winiarski 	gen5_gt_irq_reset(to_gt(dev_priv));
27717e231dbeSJesse Barnes 
2772ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
27739918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
277470591a41SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2775ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
27767e231dbeSJesse Barnes }
27777e231dbeSJesse Barnes 
2778a844cfbeSJosé Roberto de Souza static void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
2779abd58f01SBen Widawsky {
2780b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2781d048a268SVille Syrjälä 	enum pipe pipe;
2782abd58f01SBen Widawsky 
2783a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2784a844cfbeSJosé Roberto de Souza 		return;
2785abd58f01SBen Widawsky 
2786f0818984STvrtko Ursulin 	intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2787f0818984STvrtko Ursulin 	intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
2788e04f7eceSVille Syrjälä 
2789055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe)
2790f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
2791813bde43SPaulo Zanoni 						   POWER_DOMAIN_PIPE(pipe)))
2792b16b2a2fSPaulo Zanoni 			GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
2793abd58f01SBen Widawsky 
2794b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
2795b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
2796a844cfbeSJosé Roberto de Souza }
2797a844cfbeSJosé Roberto de Souza 
2798a844cfbeSJosé Roberto de Souza static void gen8_irq_reset(struct drm_i915_private *dev_priv)
2799a844cfbeSJosé Roberto de Souza {
2800a844cfbeSJosé Roberto de Souza 	struct intel_uncore *uncore = &dev_priv->uncore;
2801a844cfbeSJosé Roberto de Souza 
2802e58c2cacSAndrzej Hajda 	gen8_master_intr_disable(uncore->regs);
2803a844cfbeSJosé Roberto de Souza 
28042cbc876dSMichał Winiarski 	gen8_gt_irq_reset(to_gt(dev_priv));
2805a844cfbeSJosé Roberto de Souza 	gen8_display_irq_reset(dev_priv);
2806b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
2807abd58f01SBen Widawsky 
28086e266956STvrtko Ursulin 	if (HAS_PCH_SPLIT(dev_priv))
2809b243f530STvrtko Ursulin 		ibx_irq_reset(dev_priv);
281059b7cb44STejas Upadhyay 
2811abd58f01SBen Widawsky }
2812abd58f01SBen Widawsky 
2813a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
281451951ae7SMika Kuoppala {
2815b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2816d048a268SVille Syrjälä 	enum pipe pipe;
2817562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
2818562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
281951951ae7SMika Kuoppala 
2820a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2821a844cfbeSJosé Roberto de Souza 		return;
2822a844cfbeSJosé Roberto de Souza 
2823f0818984STvrtko Ursulin 	intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0);
282451951ae7SMika Kuoppala 
2825373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
28268241cfbeSJosé Roberto de Souza 		enum transcoder trans;
28278241cfbeSJosé Roberto de Souza 
2828562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
28298241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
28308241cfbeSJosé Roberto de Souza 
28318241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
28328241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
28338241cfbeSJosé Roberto de Souza 				continue;
28348241cfbeSJosé Roberto de Souza 
28358241cfbeSJosé Roberto de Souza 			intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff);
28368241cfbeSJosé Roberto de Souza 			intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff);
28378241cfbeSJosé Roberto de Souza 		}
28388241cfbeSJosé Roberto de Souza 	} else {
2839f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2840f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
28418241cfbeSJosé Roberto de Souza 	}
284262819dfdSJosé Roberto de Souza 
284351951ae7SMika Kuoppala 	for_each_pipe(dev_priv, pipe)
284451951ae7SMika Kuoppala 		if (intel_display_power_is_enabled(dev_priv,
284551951ae7SMika Kuoppala 						   POWER_DOMAIN_PIPE(pipe)))
2846b16b2a2fSPaulo Zanoni 			GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
284751951ae7SMika Kuoppala 
2848b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
2849b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
2850babde06dSMika Kahola 
2851babde06dSMika Kahola 	if (DISPLAY_VER(dev_priv) >= 14)
2852babde06dSMika Kahola 		GEN3_IRQ_RESET(uncore, PICAINTERRUPT_);
2853babde06dSMika Kahola 	else
2854b16b2a2fSPaulo Zanoni 		GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_);
285531604222SAnusha Srivatsa 
285629b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
2857b16b2a2fSPaulo Zanoni 		GEN3_IRQ_RESET(uncore, SDE);
285851951ae7SMika Kuoppala }
285951951ae7SMika Kuoppala 
2860a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv)
2861a3265d85SMatt Roper {
28622cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2863fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
2864a3265d85SMatt Roper 
2865a3265d85SMatt Roper 	gen11_master_intr_disable(dev_priv->uncore.regs);
2866a3265d85SMatt Roper 
2867fd4d7904SPaulo Zanoni 	gen11_gt_irq_reset(gt);
2868a3265d85SMatt Roper 	gen11_display_irq_reset(dev_priv);
2869a3265d85SMatt Roper 
2870a3265d85SMatt Roper 	GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
2871a3265d85SMatt Roper 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
2872a3265d85SMatt Roper }
2873a3265d85SMatt Roper 
287422e26af7SPaulo Zanoni static void dg1_irq_reset(struct drm_i915_private *dev_priv)
287522e26af7SPaulo Zanoni {
28762cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2877fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
287822e26af7SPaulo Zanoni 
287922e26af7SPaulo Zanoni 	dg1_master_intr_disable(dev_priv->uncore.regs);
288022e26af7SPaulo Zanoni 
2881fd4d7904SPaulo Zanoni 	gen11_gt_irq_reset(gt);
288222e26af7SPaulo Zanoni 	gen11_display_irq_reset(dev_priv);
288322e26af7SPaulo Zanoni 
288422e26af7SPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
288522e26af7SPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
288622e26af7SPaulo Zanoni }
288722e26af7SPaulo Zanoni 
28884c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
2889001bd2cbSImre Deak 				     u8 pipe_mask)
2890d49bdb0eSPaulo Zanoni {
2891b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
28928bcc0840SMatt Roper 	u32 extra_ier = GEN8_PIPE_VBLANK |
28938bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
2894cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
28956831f3e3SVille Syrjälä 	enum pipe pipe;
2896d49bdb0eSPaulo Zanoni 
289713321786SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
28989dfe2e3aSImre Deak 
28999dfe2e3aSImre Deak 	if (!intel_irqs_enabled(dev_priv)) {
29009dfe2e3aSImre Deak 		spin_unlock_irq(&dev_priv->irq_lock);
29019dfe2e3aSImre Deak 		return;
29029dfe2e3aSImre Deak 	}
29039dfe2e3aSImre Deak 
29046831f3e3SVille Syrjälä 	for_each_pipe_masked(dev_priv, pipe, pipe_mask)
2905b16b2a2fSPaulo Zanoni 		GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
29066831f3e3SVille Syrjälä 				  dev_priv->de_irq_mask[pipe],
29076831f3e3SVille Syrjälä 				  ~dev_priv->de_irq_mask[pipe] | extra_ier);
29089dfe2e3aSImre Deak 
290913321786SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
2910d49bdb0eSPaulo Zanoni }
2911d49bdb0eSPaulo Zanoni 
2912aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
2913001bd2cbSImre Deak 				     u8 pipe_mask)
2914aae8ba84SVille Syrjälä {
2915b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
29166831f3e3SVille Syrjälä 	enum pipe pipe;
29176831f3e3SVille Syrjälä 
2918aae8ba84SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
29199dfe2e3aSImre Deak 
29209dfe2e3aSImre Deak 	if (!intel_irqs_enabled(dev_priv)) {
29219dfe2e3aSImre Deak 		spin_unlock_irq(&dev_priv->irq_lock);
29229dfe2e3aSImre Deak 		return;
29239dfe2e3aSImre Deak 	}
29249dfe2e3aSImre Deak 
29256831f3e3SVille Syrjälä 	for_each_pipe_masked(dev_priv, pipe, pipe_mask)
2926b16b2a2fSPaulo Zanoni 		GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
29279dfe2e3aSImre Deak 
2928aae8ba84SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
2929aae8ba84SVille Syrjälä 
2930aae8ba84SVille Syrjälä 	/* make sure we're done processing display irqs */
2931315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
2932aae8ba84SVille Syrjälä }
2933aae8ba84SVille Syrjälä 
2934b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
293543f328d7SVille Syrjälä {
2936b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
293743f328d7SVille Syrjälä 
2938e58c2cacSAndrzej Hajda 	intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0);
29392939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
294043f328d7SVille Syrjälä 
29412cbc876dSMichał Winiarski 	gen8_gt_irq_reset(to_gt(dev_priv));
294243f328d7SVille Syrjälä 
2943b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
294443f328d7SVille Syrjälä 
2945ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
29469918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
294770591a41SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2948ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
294943f328d7SVille Syrjälä }
295043f328d7SVille Syrjälä 
295140d06b0fSVille Syrjälä static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin)
295240d06b0fSVille Syrjälä {
295340d06b0fSVille Syrjälä 	switch (hpd_pin) {
295440d06b0fSVille Syrjälä 	case HPD_PORT_A:
295540d06b0fSVille Syrjälä 		return PORTA_HOTPLUG_ENABLE;
295640d06b0fSVille Syrjälä 	case HPD_PORT_B:
295740d06b0fSVille Syrjälä 		return PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_MASK;
295840d06b0fSVille Syrjälä 	case HPD_PORT_C:
295940d06b0fSVille Syrjälä 		return PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_MASK;
296040d06b0fSVille Syrjälä 	case HPD_PORT_D:
296140d06b0fSVille Syrjälä 		return PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_MASK;
296240d06b0fSVille Syrjälä 	default:
296340d06b0fSVille Syrjälä 		return 0;
296440d06b0fSVille Syrjälä 	}
296540d06b0fSVille Syrjälä }
296640d06b0fSVille Syrjälä 
2967dfefe7bcSVille Syrjälä static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
29682ea63927SVille Syrjälä {
2969dfefe7bcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2970dfefe7bcSVille Syrjälä 
2971dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
29722ea63927SVille Syrjälä 	case HPD_PORT_A:
29732ea63927SVille Syrjälä 		/*
29742ea63927SVille Syrjälä 		 * When CPU and PCH are on the same package, port A
29752ea63927SVille Syrjälä 		 * HPD must be enabled in both north and south.
29762ea63927SVille Syrjälä 		 */
29772ea63927SVille Syrjälä 		return HAS_PCH_LPT_LP(i915) ?
29782ea63927SVille Syrjälä 			PORTA_HOTPLUG_ENABLE : 0;
29792ea63927SVille Syrjälä 	case HPD_PORT_B:
29802ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE |
29812ea63927SVille Syrjälä 			PORTB_PULSE_DURATION_2ms;
29822ea63927SVille Syrjälä 	case HPD_PORT_C:
29832ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE |
29842ea63927SVille Syrjälä 			PORTC_PULSE_DURATION_2ms;
29852ea63927SVille Syrjälä 	case HPD_PORT_D:
29862ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE |
29872ea63927SVille Syrjälä 			PORTD_PULSE_DURATION_2ms;
29882ea63927SVille Syrjälä 	default:
29892ea63927SVille Syrjälä 		return 0;
29902ea63927SVille Syrjälä 	}
29912ea63927SVille Syrjälä }
29922ea63927SVille Syrjälä 
29931a56b1a2SImre Deak static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
29941a56b1a2SImre Deak {
29951a56b1a2SImre Deak 	/*
29961a56b1a2SImre Deak 	 * Enable digital hotplug on the PCH, and configure the DP short pulse
29971a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec).
29981a56b1a2SImre Deak 	 * The pulse duration bits are reserved on LPT+.
29991a56b1a2SImre Deak 	 */
30008cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
3001a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, ibx_hotplug_mask),
30028cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
30031a56b1a2SImre Deak }
30041a56b1a2SImre Deak 
3005d28cdc43SVille Syrjälä static void ibx_hpd_enable_detection(struct intel_encoder *encoder)
3006d28cdc43SVille Syrjälä {
3007d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3008d28cdc43SVille Syrjälä 
3009d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
3010d28cdc43SVille Syrjälä 			 ibx_hotplug_mask(encoder->hpd_pin),
3011d28cdc43SVille Syrjälä 			 ibx_hotplug_enables(encoder));
3012d28cdc43SVille Syrjälä }
3013d28cdc43SVille Syrjälä 
301491d14251STvrtko Ursulin static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
301582a28bcfSDaniel Vetter {
30161a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
301782a28bcfSDaniel Vetter 
30185a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
30195a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
302082a28bcfSDaniel Vetter 
3021fee884edSDaniel Vetter 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
302282a28bcfSDaniel Vetter 
30231a56b1a2SImre Deak 	ibx_hpd_detection_setup(dev_priv);
30246dbf30ceSVille Syrjälä }
302526951cafSXiong Zhang 
302640d06b0fSVille Syrjälä static u32 icp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
30272ea63927SVille Syrjälä {
302840d06b0fSVille Syrjälä 	switch (hpd_pin) {
30292ea63927SVille Syrjälä 	case HPD_PORT_A:
30302ea63927SVille Syrjälä 	case HPD_PORT_B:
30312ea63927SVille Syrjälä 	case HPD_PORT_C:
30322ea63927SVille Syrjälä 	case HPD_PORT_D:
303340d06b0fSVille Syrjälä 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
303440d06b0fSVille Syrjälä 	default:
303540d06b0fSVille Syrjälä 		return 0;
303640d06b0fSVille Syrjälä 	}
303740d06b0fSVille Syrjälä }
303840d06b0fSVille Syrjälä 
303940d06b0fSVille Syrjälä static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
304040d06b0fSVille Syrjälä {
304140d06b0fSVille Syrjälä 	return icp_ddi_hotplug_mask(encoder->hpd_pin);
304240d06b0fSVille Syrjälä }
304340d06b0fSVille Syrjälä 
304440d06b0fSVille Syrjälä static u32 icp_tc_hotplug_mask(enum hpd_pin hpd_pin)
304540d06b0fSVille Syrjälä {
304640d06b0fSVille Syrjälä 	switch (hpd_pin) {
304740d06b0fSVille Syrjälä 	case HPD_PORT_TC1:
304840d06b0fSVille Syrjälä 	case HPD_PORT_TC2:
304940d06b0fSVille Syrjälä 	case HPD_PORT_TC3:
305040d06b0fSVille Syrjälä 	case HPD_PORT_TC4:
305140d06b0fSVille Syrjälä 	case HPD_PORT_TC5:
305240d06b0fSVille Syrjälä 	case HPD_PORT_TC6:
305340d06b0fSVille Syrjälä 		return ICP_TC_HPD_ENABLE(hpd_pin);
30542ea63927SVille Syrjälä 	default:
30552ea63927SVille Syrjälä 		return 0;
30562ea63927SVille Syrjälä 	}
30572ea63927SVille Syrjälä }
30582ea63927SVille Syrjälä 
3059dfefe7bcSVille Syrjälä static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
30602ea63927SVille Syrjälä {
306140d06b0fSVille Syrjälä 	return icp_tc_hotplug_mask(encoder->hpd_pin);
30622ea63927SVille Syrjälä }
30632ea63927SVille Syrjälä 
30642ea63927SVille Syrjälä static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
306531604222SAnusha Srivatsa {
30668cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
3067a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, icp_ddi_hotplug_mask),
30688cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
306931604222SAnusha Srivatsa }
3070815f4ef2SVille Syrjälä 
3071d28cdc43SVille Syrjälä static void icp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
3072d28cdc43SVille Syrjälä {
3073d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3074d28cdc43SVille Syrjälä 
3075d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_DDI,
3076d28cdc43SVille Syrjälä 			 icp_ddi_hotplug_mask(encoder->hpd_pin),
3077d28cdc43SVille Syrjälä 			 icp_ddi_hotplug_enables(encoder));
3078d28cdc43SVille Syrjälä }
3079d28cdc43SVille Syrjälä 
30802ea63927SVille Syrjälä static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3081815f4ef2SVille Syrjälä {
30828cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
3083a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, icp_tc_hotplug_mask),
30848cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
30858ef7e340SMatt Roper }
308631604222SAnusha Srivatsa 
3087d28cdc43SVille Syrjälä static void icp_tc_hpd_enable_detection(struct intel_encoder *encoder)
3088d28cdc43SVille Syrjälä {
3089d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3090d28cdc43SVille Syrjälä 
3091d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_TC,
3092d28cdc43SVille Syrjälä 			 icp_tc_hotplug_mask(encoder->hpd_pin),
3093d28cdc43SVille Syrjälä 			 icp_tc_hotplug_enables(encoder));
3094d28cdc43SVille Syrjälä }
3095d28cdc43SVille Syrjälä 
3096d28cdc43SVille Syrjälä static void icp_hpd_enable_detection(struct intel_encoder *encoder)
3097d28cdc43SVille Syrjälä {
3098d28cdc43SVille Syrjälä 	icp_ddi_hpd_enable_detection(encoder);
3099d28cdc43SVille Syrjälä 	icp_tc_hpd_enable_detection(encoder);
3100d28cdc43SVille Syrjälä }
3101d28cdc43SVille Syrjälä 
31022ea63927SVille Syrjälä static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
310331604222SAnusha Srivatsa {
310431604222SAnusha Srivatsa 	u32 hotplug_irqs, enabled_irqs;
310531604222SAnusha Srivatsa 
31065a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
31075a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
310831604222SAnusha Srivatsa 
3109f619e516SAnusha Srivatsa 	if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
31102939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3111f49108d0SMatt Roper 
311231604222SAnusha Srivatsa 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
311331604222SAnusha Srivatsa 
31142ea63927SVille Syrjälä 	icp_ddi_hpd_detection_setup(dev_priv);
31152ea63927SVille Syrjälä 	icp_tc_hpd_detection_setup(dev_priv);
311652dfdba0SLucas De Marchi }
311752dfdba0SLucas De Marchi 
311840d06b0fSVille Syrjälä static u32 gen11_hotplug_mask(enum hpd_pin hpd_pin)
31198ef7e340SMatt Roper {
312040d06b0fSVille Syrjälä 	switch (hpd_pin) {
31212ea63927SVille Syrjälä 	case HPD_PORT_TC1:
31222ea63927SVille Syrjälä 	case HPD_PORT_TC2:
31232ea63927SVille Syrjälä 	case HPD_PORT_TC3:
31242ea63927SVille Syrjälä 	case HPD_PORT_TC4:
31252ea63927SVille Syrjälä 	case HPD_PORT_TC5:
31262ea63927SVille Syrjälä 	case HPD_PORT_TC6:
312740d06b0fSVille Syrjälä 		return GEN11_HOTPLUG_CTL_ENABLE(hpd_pin);
31282ea63927SVille Syrjälä 	default:
31292ea63927SVille Syrjälä 		return 0;
313031604222SAnusha Srivatsa 	}
3131943682e3SMatt Roper }
3132943682e3SMatt Roper 
313340d06b0fSVille Syrjälä static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
313440d06b0fSVille Syrjälä {
313540d06b0fSVille Syrjälä 	return gen11_hotplug_mask(encoder->hpd_pin);
313640d06b0fSVille Syrjälä }
313740d06b0fSVille Syrjälä 
313871690148SGustavo Sousa static void dg1_hpd_invert(struct drm_i915_private *i915)
3139229f31e2SLucas De Marchi {
314071690148SGustavo Sousa 	u32 val = (INVERT_DDIA_HPD |
3141b18c1eb9SClinton A Taylor 		   INVERT_DDIB_HPD |
3142b18c1eb9SClinton A Taylor 		   INVERT_DDIC_HPD |
3143b18c1eb9SClinton A Taylor 		   INVERT_DDID_HPD);
314471690148SGustavo Sousa 	intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
314571690148SGustavo Sousa }
3146b18c1eb9SClinton A Taylor 
3147d28cdc43SVille Syrjälä static void dg1_hpd_enable_detection(struct intel_encoder *encoder)
3148d28cdc43SVille Syrjälä {
3149d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3150d28cdc43SVille Syrjälä 
3151d28cdc43SVille Syrjälä 	dg1_hpd_invert(i915);
3152d28cdc43SVille Syrjälä 	icp_hpd_enable_detection(encoder);
3153d28cdc43SVille Syrjälä }
3154d28cdc43SVille Syrjälä 
315571690148SGustavo Sousa static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
315671690148SGustavo Sousa {
315771690148SGustavo Sousa 	dg1_hpd_invert(dev_priv);
31582ea63927SVille Syrjälä 	icp_hpd_irq_setup(dev_priv);
3159229f31e2SLucas De Marchi }
3160229f31e2SLucas De Marchi 
316152c7f5f1SVille Syrjälä static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
3162121e758eSDhinakaran Pandiyan {
31638cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
3164a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
31658cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
316652c7f5f1SVille Syrjälä }
316752c7f5f1SVille Syrjälä 
3168d28cdc43SVille Syrjälä static void gen11_tc_hpd_enable_detection(struct intel_encoder *encoder)
3169d28cdc43SVille Syrjälä {
3170d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3171d28cdc43SVille Syrjälä 
3172d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, GEN11_TC_HOTPLUG_CTL,
3173d28cdc43SVille Syrjälä 			 gen11_hotplug_mask(encoder->hpd_pin),
3174d28cdc43SVille Syrjälä 			 gen11_hotplug_enables(encoder));
3175d28cdc43SVille Syrjälä }
3176d28cdc43SVille Syrjälä 
317752c7f5f1SVille Syrjälä static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
317852c7f5f1SVille Syrjälä {
31798cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
3180a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
31818cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
3182121e758eSDhinakaran Pandiyan }
3183121e758eSDhinakaran Pandiyan 
3184d28cdc43SVille Syrjälä static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder)
3185d28cdc43SVille Syrjälä {
3186d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3187d28cdc43SVille Syrjälä 
3188d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, GEN11_TBT_HOTPLUG_CTL,
3189d28cdc43SVille Syrjälä 			 gen11_hotplug_mask(encoder->hpd_pin),
3190d28cdc43SVille Syrjälä 			 gen11_hotplug_enables(encoder));
3191d28cdc43SVille Syrjälä }
3192d28cdc43SVille Syrjälä 
3193d28cdc43SVille Syrjälä static void gen11_hpd_enable_detection(struct intel_encoder *encoder)
3194d28cdc43SVille Syrjälä {
3195d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3196d28cdc43SVille Syrjälä 
3197d28cdc43SVille Syrjälä 	gen11_tc_hpd_enable_detection(encoder);
3198d28cdc43SVille Syrjälä 	gen11_tbt_hpd_enable_detection(encoder);
3199d28cdc43SVille Syrjälä 
3200d28cdc43SVille Syrjälä 	if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
3201d28cdc43SVille Syrjälä 		icp_hpd_enable_detection(encoder);
3202d28cdc43SVille Syrjälä }
3203d28cdc43SVille Syrjälä 
3204121e758eSDhinakaran Pandiyan static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
3205121e758eSDhinakaran Pandiyan {
3206121e758eSDhinakaran Pandiyan 	u32 hotplug_irqs, enabled_irqs;
3207121e758eSDhinakaran Pandiyan 
32085a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
32095a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
3210121e758eSDhinakaran Pandiyan 
32118cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
32128cee664dSAndrzej Hajda 			 ~enabled_irqs & hotplug_irqs);
32132939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
3214121e758eSDhinakaran Pandiyan 
321552c7f5f1SVille Syrjälä 	gen11_tc_hpd_detection_setup(dev_priv);
321652c7f5f1SVille Syrjälä 	gen11_tbt_hpd_detection_setup(dev_priv);
321731604222SAnusha Srivatsa 
32182ea63927SVille Syrjälä 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
32192ea63927SVille Syrjälä 		icp_hpd_irq_setup(dev_priv);
32202ea63927SVille Syrjälä }
32212ea63927SVille Syrjälä 
322240d06b0fSVille Syrjälä static u32 mtp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
3223babde06dSMika Kahola {
322440d06b0fSVille Syrjälä 	switch (hpd_pin) {
3225babde06dSMika Kahola 	case HPD_PORT_A:
3226babde06dSMika Kahola 	case HPD_PORT_B:
322740d06b0fSVille Syrjälä 		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
322840d06b0fSVille Syrjälä 	default:
322940d06b0fSVille Syrjälä 		return 0;
323040d06b0fSVille Syrjälä 	}
323140d06b0fSVille Syrjälä }
323240d06b0fSVille Syrjälä 
323340d06b0fSVille Syrjälä static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder)
323440d06b0fSVille Syrjälä {
323540d06b0fSVille Syrjälä 	return mtp_ddi_hotplug_mask(encoder->hpd_pin);
323640d06b0fSVille Syrjälä }
323740d06b0fSVille Syrjälä 
323840d06b0fSVille Syrjälä static u32 mtp_tc_hotplug_mask(enum hpd_pin hpd_pin)
323940d06b0fSVille Syrjälä {
324040d06b0fSVille Syrjälä 	switch (hpd_pin) {
324140d06b0fSVille Syrjälä 	case HPD_PORT_TC1:
324240d06b0fSVille Syrjälä 	case HPD_PORT_TC2:
324340d06b0fSVille Syrjälä 	case HPD_PORT_TC3:
324440d06b0fSVille Syrjälä 	case HPD_PORT_TC4:
324540d06b0fSVille Syrjälä 		return ICP_TC_HPD_ENABLE(hpd_pin);
3246babde06dSMika Kahola 	default:
3247babde06dSMika Kahola 		return 0;
3248babde06dSMika Kahola 	}
3249babde06dSMika Kahola }
3250babde06dSMika Kahola 
3251babde06dSMika Kahola static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder)
3252babde06dSMika Kahola {
325340d06b0fSVille Syrjälä 	return mtp_tc_hotplug_mask(encoder->hpd_pin);
3254babde06dSMika Kahola }
3255babde06dSMika Kahola 
3256babde06dSMika Kahola static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
3257babde06dSMika Kahola {
3258babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
3259a823c5a8SVille Syrjälä 		     intel_hpd_hotplug_mask(i915, mtp_ddi_hotplug_mask),
3260babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
3261babde06dSMika Kahola }
3262babde06dSMika Kahola 
3263d28cdc43SVille Syrjälä static void mtp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
3264d28cdc43SVille Syrjälä {
3265d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3266d28cdc43SVille Syrjälä 
3267d28cdc43SVille Syrjälä 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
3268d28cdc43SVille Syrjälä 		     mtp_ddi_hotplug_mask(encoder->hpd_pin),
3269d28cdc43SVille Syrjälä 		     mtp_ddi_hotplug_enables(encoder));
3270d28cdc43SVille Syrjälä }
3271d28cdc43SVille Syrjälä 
3272babde06dSMika Kahola static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
3273babde06dSMika Kahola {
3274babde06dSMika Kahola 	intel_de_rmw(i915, SHOTPLUG_CTL_TC,
3275a823c5a8SVille Syrjälä 		     intel_hpd_hotplug_mask(i915, mtp_tc_hotplug_mask),
3276babde06dSMika Kahola 		     intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
3277babde06dSMika Kahola }
3278babde06dSMika Kahola 
3279d28cdc43SVille Syrjälä static void mtp_tc_hpd_enable_detection(struct intel_encoder *encoder)
3280d28cdc43SVille Syrjälä {
3281d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3282d28cdc43SVille Syrjälä 
3283d28cdc43SVille Syrjälä 	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
3284d28cdc43SVille Syrjälä 		     mtp_tc_hotplug_mask(encoder->hpd_pin),
3285d28cdc43SVille Syrjälä 		     mtp_tc_hotplug_enables(encoder));
3286d28cdc43SVille Syrjälä }
3287d28cdc43SVille Syrjälä 
3288babde06dSMika Kahola static void mtp_hpd_invert(struct drm_i915_private *i915)
3289babde06dSMika Kahola {
3290babde06dSMika Kahola 	u32 val = (INVERT_DDIA_HPD |
3291babde06dSMika Kahola 		   INVERT_DDIB_HPD |
3292babde06dSMika Kahola 		   INVERT_DDIC_HPD |
3293babde06dSMika Kahola 		   INVERT_TC1_HPD |
3294babde06dSMika Kahola 		   INVERT_TC2_HPD |
3295babde06dSMika Kahola 		   INVERT_TC3_HPD |
3296babde06dSMika Kahola 		   INVERT_TC4_HPD |
3297babde06dSMika Kahola 		   INVERT_DDID_HPD_MTP |
3298babde06dSMika Kahola 		   INVERT_DDIE_HPD);
3299babde06dSMika Kahola 	intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
3300babde06dSMika Kahola }
3301babde06dSMika Kahola 
3302d28cdc43SVille Syrjälä static void mtp_hpd_enable_detection(struct intel_encoder *encoder)
3303d28cdc43SVille Syrjälä {
3304d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3305d28cdc43SVille Syrjälä 
3306d28cdc43SVille Syrjälä 	mtp_hpd_invert(i915);
3307d28cdc43SVille Syrjälä 	mtp_ddi_hpd_enable_detection(encoder);
3308d28cdc43SVille Syrjälä 	mtp_tc_hpd_enable_detection(encoder);
3309d28cdc43SVille Syrjälä }
3310d28cdc43SVille Syrjälä 
3311babde06dSMika Kahola static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
3312babde06dSMika Kahola {
3313babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3314babde06dSMika Kahola 
3315babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
3316babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
3317babde06dSMika Kahola 
3318babde06dSMika Kahola 	intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3319babde06dSMika Kahola 
3320babde06dSMika Kahola 	mtp_hpd_invert(i915);
3321babde06dSMika Kahola 	ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
3322babde06dSMika Kahola 
3323babde06dSMika Kahola 	mtp_ddi_hpd_detection_setup(i915);
3324babde06dSMika Kahola 	mtp_tc_hpd_detection_setup(i915);
3325babde06dSMika Kahola }
3326babde06dSMika Kahola 
3327d28cdc43SVille Syrjälä static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
3328d28cdc43SVille Syrjälä {
3329d28cdc43SVille Syrjälä 	return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
3330d28cdc43SVille Syrjälä }
3331d28cdc43SVille Syrjälä 
3332d28cdc43SVille Syrjälä static void _xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915,
3333d28cdc43SVille Syrjälä 					     enum hpd_pin hpd_pin, bool enable)
3334d28cdc43SVille Syrjälä {
3335d28cdc43SVille Syrjälä 	u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
3336d28cdc43SVille Syrjälä 		XELPDP_DP_ALT_HOTPLUG_ENABLE;
3337d28cdc43SVille Syrjälä 
3338d28cdc43SVille Syrjälä 	if (!is_xelpdp_pica_hpd_pin(hpd_pin))
3339d28cdc43SVille Syrjälä 		return;
3340d28cdc43SVille Syrjälä 
3341d28cdc43SVille Syrjälä 	intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(hpd_pin),
3342d28cdc43SVille Syrjälä 		     mask, enable ? mask : 0);
3343d28cdc43SVille Syrjälä }
3344d28cdc43SVille Syrjälä 
3345d28cdc43SVille Syrjälä static void xelpdp_pica_hpd_enable_detection(struct intel_encoder *encoder)
3346d28cdc43SVille Syrjälä {
3347d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3348d28cdc43SVille Syrjälä 
3349d28cdc43SVille Syrjälä 	_xelpdp_pica_hpd_detection_setup(i915, encoder->hpd_pin, true);
3350d28cdc43SVille Syrjälä }
3351d28cdc43SVille Syrjälä 
3352babde06dSMika Kahola static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
3353babde06dSMika Kahola {
3354babde06dSMika Kahola 	struct intel_encoder *encoder;
3355babde06dSMika Kahola 	u32 available_pins = 0;
3356d28cdc43SVille Syrjälä 	enum hpd_pin pin;
3357babde06dSMika Kahola 
3358babde06dSMika Kahola 	BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
3359babde06dSMika Kahola 
3360babde06dSMika Kahola 	for_each_intel_encoder(&i915->drm, encoder)
3361babde06dSMika Kahola 		available_pins |= BIT(encoder->hpd_pin);
3362babde06dSMika Kahola 
3363d28cdc43SVille Syrjälä 	for_each_hpd_pin(pin)
3364d28cdc43SVille Syrjälä 		_xelpdp_pica_hpd_detection_setup(i915, pin, available_pins & BIT(pin));
3365babde06dSMika Kahola }
3366d28cdc43SVille Syrjälä 
3367d28cdc43SVille Syrjälä static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder)
3368d28cdc43SVille Syrjälä {
3369d28cdc43SVille Syrjälä 	xelpdp_pica_hpd_enable_detection(encoder);
3370d28cdc43SVille Syrjälä 	mtp_hpd_enable_detection(encoder);
3371babde06dSMika Kahola }
3372babde06dSMika Kahola 
3373babde06dSMika Kahola static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
3374babde06dSMika Kahola {
3375babde06dSMika Kahola 	u32 hotplug_irqs, enabled_irqs;
3376babde06dSMika Kahola 
3377babde06dSMika Kahola 	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.hpd);
3378babde06dSMika Kahola 	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.hpd);
3379babde06dSMika Kahola 
3380babde06dSMika Kahola 	intel_de_rmw(i915, PICAINTERRUPT_IMR, hotplug_irqs,
3381babde06dSMika Kahola 		     ~enabled_irqs & hotplug_irqs);
3382babde06dSMika Kahola 	intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR);
3383babde06dSMika Kahola 
3384babde06dSMika Kahola 	xelpdp_pica_hpd_detection_setup(i915);
3385babde06dSMika Kahola 
3386babde06dSMika Kahola 	if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
3387babde06dSMika Kahola 		mtp_hpd_irq_setup(i915);
3388babde06dSMika Kahola }
3389babde06dSMika Kahola 
339040d06b0fSVille Syrjälä static u32 spt_hotplug_mask(enum hpd_pin hpd_pin)
33912ea63927SVille Syrjälä {
339240d06b0fSVille Syrjälä 	switch (hpd_pin) {
33932ea63927SVille Syrjälä 	case HPD_PORT_A:
33942ea63927SVille Syrjälä 		return PORTA_HOTPLUG_ENABLE;
33952ea63927SVille Syrjälä 	case HPD_PORT_B:
33962ea63927SVille Syrjälä 		return PORTB_HOTPLUG_ENABLE;
33972ea63927SVille Syrjälä 	case HPD_PORT_C:
33982ea63927SVille Syrjälä 		return PORTC_HOTPLUG_ENABLE;
33992ea63927SVille Syrjälä 	case HPD_PORT_D:
34002ea63927SVille Syrjälä 		return PORTD_HOTPLUG_ENABLE;
34012ea63927SVille Syrjälä 	default:
34022ea63927SVille Syrjälä 		return 0;
34032ea63927SVille Syrjälä 	}
34042ea63927SVille Syrjälä }
34052ea63927SVille Syrjälä 
340640d06b0fSVille Syrjälä static u32 spt_hotplug_enables(struct intel_encoder *encoder)
34072ea63927SVille Syrjälä {
340840d06b0fSVille Syrjälä 	return spt_hotplug_mask(encoder->hpd_pin);
340940d06b0fSVille Syrjälä }
341040d06b0fSVille Syrjälä 
341140d06b0fSVille Syrjälä static u32 spt_hotplug2_mask(enum hpd_pin hpd_pin)
341240d06b0fSVille Syrjälä {
341340d06b0fSVille Syrjälä 	switch (hpd_pin) {
34142ea63927SVille Syrjälä 	case HPD_PORT_E:
34152ea63927SVille Syrjälä 		return PORTE_HOTPLUG_ENABLE;
34162ea63927SVille Syrjälä 	default:
34172ea63927SVille Syrjälä 		return 0;
34182ea63927SVille Syrjälä 	}
3419121e758eSDhinakaran Pandiyan }
3420121e758eSDhinakaran Pandiyan 
342140d06b0fSVille Syrjälä static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
342240d06b0fSVille Syrjälä {
342340d06b0fSVille Syrjälä 	return spt_hotplug2_mask(encoder->hpd_pin);
342440d06b0fSVille Syrjälä }
342540d06b0fSVille Syrjälä 
34262a57d9ccSImre Deak static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
34272a57d9ccSImre Deak {
34283b92e263SRodrigo Vivi 	/* Display WA #1179 WaHardHangonHotPlug: cnp */
34293b92e263SRodrigo Vivi 	if (HAS_PCH_CNP(dev_priv)) {
34308cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
34318cee664dSAndrzej Hajda 				 CHASSIS_CLK_REQ_DURATION(0xf));
34323b92e263SRodrigo Vivi 	}
34332a57d9ccSImre Deak 
34342a57d9ccSImre Deak 	/* Enable digital hotplug on the PCH */
34358cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
3436a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, spt_hotplug_mask),
34378cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
34382a57d9ccSImre Deak 
343940d06b0fSVille Syrjälä 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2,
3440a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, spt_hotplug2_mask),
34418cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
34422a57d9ccSImre Deak }
34432a57d9ccSImre Deak 
3444d28cdc43SVille Syrjälä static void spt_hpd_enable_detection(struct intel_encoder *encoder)
3445d28cdc43SVille Syrjälä {
3446d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3447d28cdc43SVille Syrjälä 
3448d28cdc43SVille Syrjälä 	/* Display WA #1179 WaHardHangonHotPlug: cnp */
3449d28cdc43SVille Syrjälä 	if (HAS_PCH_CNP(i915)) {
3450d28cdc43SVille Syrjälä 		intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1,
3451d28cdc43SVille Syrjälä 				 CHASSIS_CLK_REQ_DURATION_MASK,
3452d28cdc43SVille Syrjälä 				 CHASSIS_CLK_REQ_DURATION(0xf));
3453d28cdc43SVille Syrjälä 	}
3454d28cdc43SVille Syrjälä 
3455d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
3456d28cdc43SVille Syrjälä 			 spt_hotplug_mask(encoder->hpd_pin),
3457d28cdc43SVille Syrjälä 			 spt_hotplug_enables(encoder));
3458d28cdc43SVille Syrjälä 
3459d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG2,
3460d28cdc43SVille Syrjälä 			 spt_hotplug2_mask(encoder->hpd_pin),
3461d28cdc43SVille Syrjälä 			 spt_hotplug2_enables(encoder));
3462d28cdc43SVille Syrjälä }
3463d28cdc43SVille Syrjälä 
346491d14251STvrtko Ursulin static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
34656dbf30ceSVille Syrjälä {
34662a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
34676dbf30ceSVille Syrjälä 
3468f49108d0SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
34692939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
3470f49108d0SMatt Roper 
34715a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
34725a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
34736dbf30ceSVille Syrjälä 
34746dbf30ceSVille Syrjälä 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
34756dbf30ceSVille Syrjälä 
34762a57d9ccSImre Deak 	spt_hpd_detection_setup(dev_priv);
347726951cafSXiong Zhang }
34787fe0b973SKeith Packard 
347940d06b0fSVille Syrjälä static u32 ilk_hotplug_mask(enum hpd_pin hpd_pin)
348040d06b0fSVille Syrjälä {
348140d06b0fSVille Syrjälä 	switch (hpd_pin) {
348240d06b0fSVille Syrjälä 	case HPD_PORT_A:
348340d06b0fSVille Syrjälä 		return DIGITAL_PORTA_HOTPLUG_ENABLE |
348440d06b0fSVille Syrjälä 			DIGITAL_PORTA_PULSE_DURATION_MASK;
348540d06b0fSVille Syrjälä 	default:
348640d06b0fSVille Syrjälä 		return 0;
348740d06b0fSVille Syrjälä 	}
348840d06b0fSVille Syrjälä }
348940d06b0fSVille Syrjälä 
3490dfefe7bcSVille Syrjälä static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
34912ea63927SVille Syrjälä {
3492dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
34932ea63927SVille Syrjälä 	case HPD_PORT_A:
34942ea63927SVille Syrjälä 		return DIGITAL_PORTA_HOTPLUG_ENABLE |
34952ea63927SVille Syrjälä 			DIGITAL_PORTA_PULSE_DURATION_2ms;
34962ea63927SVille Syrjälä 	default:
34972ea63927SVille Syrjälä 		return 0;
34982ea63927SVille Syrjälä 	}
34992ea63927SVille Syrjälä }
35002ea63927SVille Syrjälä 
35011a56b1a2SImre Deak static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
35021a56b1a2SImre Deak {
35031a56b1a2SImre Deak 	/*
35041a56b1a2SImre Deak 	 * Enable digital hotplug on the CPU, and configure the DP short pulse
35051a56b1a2SImre Deak 	 * duration to 2ms (which is the minimum in the Display Port spec)
35061a56b1a2SImre Deak 	 * The pulse duration bits are reserved on HSW+.
35071a56b1a2SImre Deak 	 */
35088cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
3509a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, ilk_hotplug_mask),
35108cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
35111a56b1a2SImre Deak }
35121a56b1a2SImre Deak 
3513d28cdc43SVille Syrjälä static void ilk_hpd_enable_detection(struct intel_encoder *encoder)
3514d28cdc43SVille Syrjälä {
3515d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3516d28cdc43SVille Syrjälä 
3517d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
3518d28cdc43SVille Syrjälä 			 ilk_hotplug_mask(encoder->hpd_pin),
3519d28cdc43SVille Syrjälä 			 ilk_hotplug_enables(encoder));
3520d28cdc43SVille Syrjälä 
3521d28cdc43SVille Syrjälä 	ibx_hpd_enable_detection(encoder);
3522d28cdc43SVille Syrjälä }
3523d28cdc43SVille Syrjälä 
352491d14251STvrtko Ursulin static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
3525e4ce95aaSVille Syrjälä {
35261a56b1a2SImre Deak 	u32 hotplug_irqs, enabled_irqs;
3527e4ce95aaSVille Syrjälä 
35285a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
35295a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
35303a3b3c7dSVille Syrjälä 
3531373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 8)
35323a3b3c7dSVille Syrjälä 		bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
35336d3144ebSVille Syrjälä 	else
35343a3b3c7dSVille Syrjälä 		ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
3535e4ce95aaSVille Syrjälä 
35361a56b1a2SImre Deak 	ilk_hpd_detection_setup(dev_priv);
3537e4ce95aaSVille Syrjälä 
353891d14251STvrtko Ursulin 	ibx_hpd_irq_setup(dev_priv);
3539e4ce95aaSVille Syrjälä }
3540e4ce95aaSVille Syrjälä 
354140d06b0fSVille Syrjälä static u32 bxt_hotplug_mask(enum hpd_pin hpd_pin)
354240d06b0fSVille Syrjälä {
354340d06b0fSVille Syrjälä 	switch (hpd_pin) {
354440d06b0fSVille Syrjälä 	case HPD_PORT_A:
354540d06b0fSVille Syrjälä 		return PORTA_HOTPLUG_ENABLE | BXT_DDIA_HPD_INVERT;
354640d06b0fSVille Syrjälä 	case HPD_PORT_B:
354740d06b0fSVille Syrjälä 		return PORTB_HOTPLUG_ENABLE | BXT_DDIB_HPD_INVERT;
354840d06b0fSVille Syrjälä 	case HPD_PORT_C:
354940d06b0fSVille Syrjälä 		return PORTC_HOTPLUG_ENABLE | BXT_DDIC_HPD_INVERT;
355040d06b0fSVille Syrjälä 	default:
355140d06b0fSVille Syrjälä 		return 0;
355240d06b0fSVille Syrjälä 	}
355340d06b0fSVille Syrjälä }
355440d06b0fSVille Syrjälä 
3555dfefe7bcSVille Syrjälä static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
35562ea63927SVille Syrjälä {
35572ea63927SVille Syrjälä 	u32 hotplug;
35582ea63927SVille Syrjälä 
3559dfefe7bcSVille Syrjälä 	switch (encoder->hpd_pin) {
35602ea63927SVille Syrjälä 	case HPD_PORT_A:
35612ea63927SVille Syrjälä 		hotplug = PORTA_HOTPLUG_ENABLE;
35629151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
35632ea63927SVille Syrjälä 			hotplug |= BXT_DDIA_HPD_INVERT;
35642ea63927SVille Syrjälä 		return hotplug;
35652ea63927SVille Syrjälä 	case HPD_PORT_B:
35662ea63927SVille Syrjälä 		hotplug = PORTB_HOTPLUG_ENABLE;
35679151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
35682ea63927SVille Syrjälä 			hotplug |= BXT_DDIB_HPD_INVERT;
35692ea63927SVille Syrjälä 		return hotplug;
35702ea63927SVille Syrjälä 	case HPD_PORT_C:
35712ea63927SVille Syrjälä 		hotplug = PORTC_HOTPLUG_ENABLE;
35729151c85cSVille Syrjälä 		if (intel_bios_encoder_hpd_invert(encoder->devdata))
35732ea63927SVille Syrjälä 			hotplug |= BXT_DDIC_HPD_INVERT;
35742ea63927SVille Syrjälä 		return hotplug;
35752ea63927SVille Syrjälä 	default:
35762ea63927SVille Syrjälä 		return 0;
35772ea63927SVille Syrjälä 	}
35782ea63927SVille Syrjälä }
35792ea63927SVille Syrjälä 
35802ea63927SVille Syrjälä static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
3581e0a20ad7SShashank Sharma {
35828cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
3583a823c5a8SVille Syrjälä 			 intel_hpd_hotplug_mask(dev_priv, bxt_hotplug_mask),
35848cee664dSAndrzej Hajda 			 intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
3585e0a20ad7SShashank Sharma }
3586e0a20ad7SShashank Sharma 
3587d28cdc43SVille Syrjälä static void bxt_hpd_enable_detection(struct intel_encoder *encoder)
3588d28cdc43SVille Syrjälä {
3589d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3590d28cdc43SVille Syrjälä 
3591d28cdc43SVille Syrjälä 	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
3592d28cdc43SVille Syrjälä 			 bxt_hotplug_mask(encoder->hpd_pin),
3593d28cdc43SVille Syrjälä 			 bxt_hotplug_enables(encoder));
3594d28cdc43SVille Syrjälä }
3595d28cdc43SVille Syrjälä 
35962a57d9ccSImre Deak static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
35972a57d9ccSImre Deak {
35982a57d9ccSImre Deak 	u32 hotplug_irqs, enabled_irqs;
35992a57d9ccSImre Deak 
36005a4dd6f0SJani Nikula 	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
36015a4dd6f0SJani Nikula 	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
36022a57d9ccSImre Deak 
36032a57d9ccSImre Deak 	bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
36042a57d9ccSImre Deak 
36052ea63927SVille Syrjälä 	bxt_hpd_detection_setup(dev_priv);
36062a57d9ccSImre Deak }
36072a57d9ccSImre Deak 
3608a0a6d8cbSVille Syrjälä /*
3609a0a6d8cbSVille Syrjälä  * SDEIER is also touched by the interrupt handler to work around missed PCH
3610a0a6d8cbSVille Syrjälä  * interrupts. Hence we can't update it after the interrupt handler is enabled -
3611a0a6d8cbSVille Syrjälä  * instead we unconditionally enable all PCH interrupt sources here, but then
3612a0a6d8cbSVille Syrjälä  * only unmask them as needed with SDEIMR.
3613a0a6d8cbSVille Syrjälä  *
3614a0a6d8cbSVille Syrjälä  * Note that we currently do this after installing the interrupt handler,
3615a0a6d8cbSVille Syrjälä  * but before we enable the master interrupt. That should be sufficient
3616a0a6d8cbSVille Syrjälä  * to avoid races with the irq handler, assuming we have MSI. Shared legacy
3617a0a6d8cbSVille Syrjälä  * interrupts could still race.
3618a0a6d8cbSVille Syrjälä  */
3619b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
3620d46da437SPaulo Zanoni {
3621a0a6d8cbSVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
362282a28bcfSDaniel Vetter 	u32 mask;
3623d46da437SPaulo Zanoni 
36246e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
3625692a04cfSDaniel Vetter 		return;
3626692a04cfSDaniel Vetter 
36276e266956STvrtko Ursulin 	if (HAS_PCH_IBX(dev_priv))
36285c673b60SDaniel Vetter 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
36294ebc6509SDhinakaran Pandiyan 	else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
36305c673b60SDaniel Vetter 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
36314ebc6509SDhinakaran Pandiyan 	else
36324ebc6509SDhinakaran Pandiyan 		mask = SDE_GMBUS_CPT;
36338664281bSPaulo Zanoni 
3634a0a6d8cbSVille Syrjälä 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
3635d46da437SPaulo Zanoni }
3636d46da437SPaulo Zanoni 
36379eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
3638036a4a7dSZhenyu Wang {
3639b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
36408e76f8dcSPaulo Zanoni 	u32 display_mask, extra_mask;
36418e76f8dcSPaulo Zanoni 
3642651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) >= 7) {
36438e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
3644842ebf7aSVille Syrjälä 				DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB);
36458e76f8dcSPaulo Zanoni 		extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
364623bb4cb5SVille Syrjälä 			      DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
36472a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_C) |
36482a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_B) |
36492a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_A) |
365023bb4cb5SVille Syrjälä 			      DE_DP_A_HOTPLUG_IVB);
36518e76f8dcSPaulo Zanoni 	} else {
36528e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
3653842ebf7aSVille Syrjälä 				DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE |
3654842ebf7aSVille Syrjälä 				DE_PIPEA_CRC_DONE | DE_POISON);
3655c6073d4cSVille Syrjälä 		extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK |
3656e4ce95aaSVille Syrjälä 			      DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
36574bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_A) |
36584bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_B) |
3659e4ce95aaSVille Syrjälä 			      DE_DP_A_HOTPLUG);
36608e76f8dcSPaulo Zanoni 	}
3661036a4a7dSZhenyu Wang 
3662fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
3663b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
3664fc340442SDaniel Vetter 		display_mask |= DE_EDP_PSR_INT_HSW;
3665fc340442SDaniel Vetter 	}
3666fc340442SDaniel Vetter 
3667c6073d4cSVille Syrjälä 	if (IS_IRONLAKE_M(dev_priv))
3668c6073d4cSVille Syrjälä 		extra_mask |= DE_PCU_EVENT;
3669c6073d4cSVille Syrjälä 
36701ec14ad3SChris Wilson 	dev_priv->irq_mask = ~display_mask;
3671036a4a7dSZhenyu Wang 
3672a0a6d8cbSVille Syrjälä 	ibx_irq_postinstall(dev_priv);
3673622364b6SPaulo Zanoni 
36742cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
3675a9922912SVille Syrjälä 
3676b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask,
3677b16b2a2fSPaulo Zanoni 		      display_mask | extra_mask);
3678036a4a7dSZhenyu Wang }
3679036a4a7dSZhenyu Wang 
3680f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
3681f8b79e58SImre Deak {
368267520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3683f8b79e58SImre Deak 
3684f8b79e58SImre Deak 	if (dev_priv->display_irqs_enabled)
3685f8b79e58SImre Deak 		return;
3686f8b79e58SImre Deak 
3687f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = true;
3688f8b79e58SImre Deak 
3689d6c69803SVille Syrjälä 	if (intel_irqs_enabled(dev_priv)) {
3690d6c69803SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3691ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3692f8b79e58SImre Deak 	}
3693d6c69803SVille Syrjälä }
3694f8b79e58SImre Deak 
3695f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
3696f8b79e58SImre Deak {
369767520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
3698f8b79e58SImre Deak 
3699f8b79e58SImre Deak 	if (!dev_priv->display_irqs_enabled)
3700f8b79e58SImre Deak 		return;
3701f8b79e58SImre Deak 
3702f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = false;
3703f8b79e58SImre Deak 
3704950eabafSImre Deak 	if (intel_irqs_enabled(dev_priv))
3705ad22d106SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
3706f8b79e58SImre Deak }
3707f8b79e58SImre Deak 
37080e6c9a9eSVille Syrjälä 
3709b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
37100e6c9a9eSVille Syrjälä {
37112cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
37127e231dbeSJesse Barnes 
3713ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
37149918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3715ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3716ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3717ad22d106SVille Syrjälä 
37182939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
37192939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
372020afbda2SDaniel Vetter }
372120afbda2SDaniel Vetter 
3722abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
3723abd58f01SBen Widawsky {
3724b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3725b16b2a2fSPaulo Zanoni 
3726869129eeSMatt Roper 	u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
3727869129eeSMatt Roper 		GEN8_PIPE_CDCLK_CRC_DONE;
3728a9c287c9SJani Nikula 	u32 de_pipe_enables;
3729054318c7SImre Deak 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
37303a3b3c7dSVille Syrjälä 	u32 de_port_enables;
3731df0d28c1SDhinakaran Pandiyan 	u32 de_misc_masked = GEN8_DE_EDP_PSR;
3732562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
3733562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
37343a3b3c7dSVille Syrjälä 	enum pipe pipe;
3735770de83dSDamien Lespiau 
3736a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3737a844cfbeSJosé Roberto de Souza 		return;
3738a844cfbeSJosé Roberto de Souza 
3739373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) <= 10)
3740df0d28c1SDhinakaran Pandiyan 		de_misc_masked |= GEN8_DE_MISC_GSE;
3741df0d28c1SDhinakaran Pandiyan 
374270bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
37433a3b3c7dSVille Syrjälä 		de_port_masked |= BXT_DE_PORT_GMBUS;
3744a324fcacSRodrigo Vivi 
3745373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
37469c9e97c4SVandita Kulkarni 		enum port port;
37479c9e97c4SVandita Kulkarni 
37489c9e97c4SVandita Kulkarni 		if (intel_bios_is_dsi_present(dev_priv, &port))
37499c9e97c4SVandita Kulkarni 			de_port_masked |= DSI0_TE | DSI1_TE;
37509c9e97c4SVandita Kulkarni 	}
37519c9e97c4SVandita Kulkarni 
3752cda195f1SVille Syrjälä 	de_pipe_enables = de_pipe_masked |
37538bcc0840SMatt Roper 		GEN8_PIPE_VBLANK |
37548bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
3755cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
37561288f9b0SKarthik B S 
37573a3b3c7dSVille Syrjälä 	de_port_enables = de_port_masked;
375870bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3759a52bb15bSVille Syrjälä 		de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
3760a52bb15bSVille Syrjälä 	else if (IS_BROADWELL(dev_priv))
3761e5abaab3SVille Syrjälä 		de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
37623a3b3c7dSVille Syrjälä 
3763373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
37648241cfbeSJosé Roberto de Souza 		enum transcoder trans;
37658241cfbeSJosé Roberto de Souza 
3766562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
37678241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
37688241cfbeSJosé Roberto de Souza 
37698241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
37708241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
37718241cfbeSJosé Roberto de Souza 				continue;
37728241cfbeSJosé Roberto de Souza 
37738241cfbeSJosé Roberto de Souza 			gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
37748241cfbeSJosé Roberto de Souza 		}
37758241cfbeSJosé Roberto de Souza 	} else {
3776b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
37778241cfbeSJosé Roberto de Souza 	}
3778e04f7eceSVille Syrjälä 
37790a195c02SMika Kahola 	for_each_pipe(dev_priv, pipe) {
37800a195c02SMika Kahola 		dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
3781abd58f01SBen Widawsky 
3782f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
3783813bde43SPaulo Zanoni 				POWER_DOMAIN_PIPE(pipe)))
3784b16b2a2fSPaulo Zanoni 			GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
3785813bde43SPaulo Zanoni 					  dev_priv->de_irq_mask[pipe],
378635079899SPaulo Zanoni 					  de_pipe_enables);
37870a195c02SMika Kahola 	}
3788abd58f01SBen Widawsky 
3789b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
3790b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
37912a57d9ccSImre Deak 
3792babde06dSMika Kahola 	if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
3793121e758eSDhinakaran Pandiyan 		u32 de_hpd_masked = 0;
3794b796b971SDhinakaran Pandiyan 		u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
3795b796b971SDhinakaran Pandiyan 				     GEN11_DE_TBT_HOTPLUG_MASK;
3796121e758eSDhinakaran Pandiyan 
3797b16b2a2fSPaulo Zanoni 		GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
3798b16b2a2fSPaulo Zanoni 			      de_hpd_enables);
3799abd58f01SBen Widawsky 	}
3800121e758eSDhinakaran Pandiyan }
3801abd58f01SBen Widawsky 
3802babde06dSMika Kahola static void mtp_irq_postinstall(struct drm_i915_private *i915)
3803babde06dSMika Kahola {
3804babde06dSMika Kahola 	struct intel_uncore *uncore = &i915->uncore;
3805babde06dSMika Kahola 	u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
3806babde06dSMika Kahola 	u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
3807babde06dSMika Kahola 	u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
3808babde06dSMika Kahola 			     XELPDP_TBT_HOTPLUG_MASK;
3809babde06dSMika Kahola 
3810babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
3811babde06dSMika Kahola 		      de_hpd_enables);
3812babde06dSMika Kahola 
3813babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
3814babde06dSMika Kahola }
3815babde06dSMika Kahola 
381659b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
381759b7cb44STejas Upadhyay {
381859b7cb44STejas Upadhyay 	struct intel_uncore *uncore = &dev_priv->uncore;
381959b7cb44STejas Upadhyay 	u32 mask = SDE_GMBUS_ICP;
382059b7cb44STejas Upadhyay 
382159b7cb44STejas Upadhyay 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
382259b7cb44STejas Upadhyay }
382359b7cb44STejas Upadhyay 
3824b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
3825abd58f01SBen Widawsky {
382659b7cb44STejas Upadhyay 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
382759b7cb44STejas Upadhyay 		icp_irq_postinstall(dev_priv);
382859b7cb44STejas Upadhyay 	else if (HAS_PCH_SPLIT(dev_priv))
3829a0a6d8cbSVille Syrjälä 		ibx_irq_postinstall(dev_priv);
3830622364b6SPaulo Zanoni 
38312cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
3832abd58f01SBen Widawsky 	gen8_de_irq_postinstall(dev_priv);
3833abd58f01SBen Widawsky 
383425286aacSDaniele Ceraolo Spurio 	gen8_master_intr_enable(dev_priv->uncore.regs);
3835abd58f01SBen Widawsky }
3836abd58f01SBen Widawsky 
3837a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
3838a844cfbeSJosé Roberto de Souza {
3839a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
3840a844cfbeSJosé Roberto de Souza 		return;
3841a844cfbeSJosé Roberto de Souza 
3842a844cfbeSJosé Roberto de Souza 	gen8_de_irq_postinstall(dev_priv);
3843a844cfbeSJosé Roberto de Souza 
3844a844cfbeSJosé Roberto de Souza 	intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
3845a844cfbeSJosé Roberto de Souza 			   GEN11_DISPLAY_IRQ_ENABLE);
3846a844cfbeSJosé Roberto de Souza }
384731604222SAnusha Srivatsa 
3848b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
384951951ae7SMika Kuoppala {
38502cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3851fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
3852df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
385351951ae7SMika Kuoppala 
385429b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
3855b318b824SVille Syrjälä 		icp_irq_postinstall(dev_priv);
385631604222SAnusha Srivatsa 
3857fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
3858a844cfbeSJosé Roberto de Souza 	gen11_de_irq_postinstall(dev_priv);
385951951ae7SMika Kuoppala 
3860b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
3861df0d28c1SDhinakaran Pandiyan 
38629b77011eSTvrtko Ursulin 	gen11_master_intr_enable(uncore->regs);
38632939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
386451951ae7SMika Kuoppala }
386522e26af7SPaulo Zanoni 
386622e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
386722e26af7SPaulo Zanoni {
38682cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
3869fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
387022e26af7SPaulo Zanoni 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
387122e26af7SPaulo Zanoni 
3872fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
387322e26af7SPaulo Zanoni 
387422e26af7SPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
387522e26af7SPaulo Zanoni 
387622e26af7SPaulo Zanoni 	if (HAS_DISPLAY(dev_priv)) {
3877babde06dSMika Kahola 		if (DISPLAY_VER(dev_priv) >= 14)
3878babde06dSMika Kahola 			mtp_irq_postinstall(dev_priv);
3879babde06dSMika Kahola 		else
388022e26af7SPaulo Zanoni 			icp_irq_postinstall(dev_priv);
3881babde06dSMika Kahola 
388222e26af7SPaulo Zanoni 		gen8_de_irq_postinstall(dev_priv);
388322e26af7SPaulo Zanoni 		intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
388422e26af7SPaulo Zanoni 				   GEN11_DISPLAY_IRQ_ENABLE);
388522e26af7SPaulo Zanoni 	}
388622e26af7SPaulo Zanoni 
3887fd4d7904SPaulo Zanoni 	dg1_master_intr_enable(uncore->regs);
3888fd4d7904SPaulo Zanoni 	intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR);
388997b492f5SLucas De Marchi }
389051951ae7SMika Kuoppala 
3891b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
389243f328d7SVille Syrjälä {
38932cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
389443f328d7SVille Syrjälä 
3895ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
38969918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
3897ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
3898ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
3899ad22d106SVille Syrjälä 
39002939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
39012939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
390243f328d7SVille Syrjälä }
390343f328d7SVille Syrjälä 
3904b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv)
3905c2798b19SChris Wilson {
3906b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3907c2798b19SChris Wilson 
390844d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
390944d9241eSVille Syrjälä 
3910ad7632ffSJani Nikula 	gen2_irq_reset(uncore);
3911e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
3912c2798b19SChris Wilson }
3913c2798b19SChris Wilson 
39143687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915)
39153687ce75SVille Syrjälä {
3916e7e12f6eSVille Syrjälä 	/*
3917e7e12f6eSVille Syrjälä 	 * On gen2/3 FBC generates (seemingly spurious)
3918e7e12f6eSVille Syrjälä 	 * display INVALID_GTT/INVALID_GTT_PTE table errors.
3919e7e12f6eSVille Syrjälä 	 *
3920e7e12f6eSVille Syrjälä 	 * Also gen3 bspec has this to say:
3921e7e12f6eSVille Syrjälä 	 * "DISPA_INVALID_GTT_PTE
3922e7e12f6eSVille Syrjälä 	 "  [DevNapa] : Reserved. This bit does not reflect the page
3923e7e12f6eSVille Syrjälä 	 "              table error for the display plane A."
3924e7e12f6eSVille Syrjälä 	 *
3925e7e12f6eSVille Syrjälä 	 * Unfortunately we can't mask off individual PGTBL_ER bits,
3926e7e12f6eSVille Syrjälä 	 * so we just have to mask off all page table errors via EMR.
3927e7e12f6eSVille Syrjälä 	 */
3928e7e12f6eSVille Syrjälä 	if (HAS_FBC(i915))
3929e7e12f6eSVille Syrjälä 		return ~I915_ERROR_MEMORY_REFRESH;
3930e7e12f6eSVille Syrjälä 	else
39313687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
39323687ce75SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
39333687ce75SVille Syrjälä }
39343687ce75SVille Syrjälä 
3935b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv)
3936c2798b19SChris Wilson {
3937b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
3938e9e9848aSVille Syrjälä 	u16 enable_mask;
3939c2798b19SChris Wilson 
39403687ce75SVille Syrjälä 	intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv));
3941c2798b19SChris Wilson 
3942c2798b19SChris Wilson 	/* Unmask the interrupts that we always want on. */
3943c2798b19SChris Wilson 	dev_priv->irq_mask =
3944c2798b19SChris Wilson 		~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
394516659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
394616659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
3947c2798b19SChris Wilson 
3948e9e9848aSVille Syrjälä 	enable_mask =
3949c2798b19SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
3950c2798b19SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
395116659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
3952e9e9848aSVille Syrjälä 		I915_USER_INTERRUPT;
3953e9e9848aSVille Syrjälä 
3954ad7632ffSJani Nikula 	gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask);
3955c2798b19SChris Wilson 
3956379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
3957379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
3958d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
3959755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
3960755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
3961d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
3962c2798b19SChris Wilson }
3963c2798b19SChris Wilson 
39644f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915,
396578c357ddSVille Syrjälä 			       u16 *eir, u16 *eir_stuck)
396678c357ddSVille Syrjälä {
39674f5fd91fSTvrtko Ursulin 	struct intel_uncore *uncore = &i915->uncore;
396878c357ddSVille Syrjälä 	u16 emr;
396978c357ddSVille Syrjälä 
39704f5fd91fSTvrtko Ursulin 	*eir = intel_uncore_read16(uncore, EIR);
39714f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EIR, *eir);
397278c357ddSVille Syrjälä 
39734f5fd91fSTvrtko Ursulin 	*eir_stuck = intel_uncore_read16(uncore, EIR);
397478c357ddSVille Syrjälä 	if (*eir_stuck == 0)
397578c357ddSVille Syrjälä 		return;
397678c357ddSVille Syrjälä 
397778c357ddSVille Syrjälä 	/*
397878c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
397978c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
398078c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
398178c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
398278c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
398378c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
398478c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
398578c357ddSVille Syrjälä 	 * remains set.
398678c357ddSVille Syrjälä 	 */
39874f5fd91fSTvrtko Ursulin 	emr = intel_uncore_read16(uncore, EMR);
39884f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, 0xffff);
39894f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, emr | *eir_stuck);
399078c357ddSVille Syrjälä }
399178c357ddSVille Syrjälä 
399278c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv,
399378c357ddSVille Syrjälä 				   u16 eir, u16 eir_stuck)
399478c357ddSVille Syrjälä {
3995a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir);
399678c357ddSVille Syrjälä 
399778c357ddSVille Syrjälä 	if (eir_stuck)
399800376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n",
399900376ccfSWambui Karuga 			eir_stuck);
4000d1e89592SVille Syrjälä 
4001d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
4002d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
400378c357ddSVille Syrjälä }
400478c357ddSVille Syrjälä 
400578c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
400678c357ddSVille Syrjälä 			       u32 *eir, u32 *eir_stuck)
400778c357ddSVille Syrjälä {
400878c357ddSVille Syrjälä 	u32 emr;
400978c357ddSVille Syrjälä 
4010839259b8SVille Syrjälä 	*eir = intel_uncore_read(&dev_priv->uncore, EIR);
4011839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EIR, *eir);
401278c357ddSVille Syrjälä 
40132939eb06SJani Nikula 	*eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR);
401478c357ddSVille Syrjälä 	if (*eir_stuck == 0)
401578c357ddSVille Syrjälä 		return;
401678c357ddSVille Syrjälä 
401778c357ddSVille Syrjälä 	/*
401878c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
401978c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
402078c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
402178c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
402278c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
402378c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
402478c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
402578c357ddSVille Syrjälä 	 * remains set.
402678c357ddSVille Syrjälä 	 */
4027839259b8SVille Syrjälä 	emr = intel_uncore_read(&dev_priv->uncore, EMR);
4028839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff);
40292939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck);
403078c357ddSVille Syrjälä }
403178c357ddSVille Syrjälä 
403278c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv,
403378c357ddSVille Syrjälä 				   u32 eir, u32 eir_stuck)
403478c357ddSVille Syrjälä {
4035a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir);
403678c357ddSVille Syrjälä 
403778c357ddSVille Syrjälä 	if (eir_stuck)
403800376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n",
403900376ccfSWambui Karuga 			eir_stuck);
4040d1e89592SVille Syrjälä 
4041d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
4042d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
404378c357ddSVille Syrjälä }
404478c357ddSVille Syrjälä 
4045ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg)
4046c2798b19SChris Wilson {
4047b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4048af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4049c2798b19SChris Wilson 
40502dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
40512dd2a883SImre Deak 		return IRQ_NONE;
40522dd2a883SImre Deak 
40531f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
40549102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
40551f814dacSImre Deak 
4056af722d28SVille Syrjälä 	do {
4057af722d28SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
405878c357ddSVille Syrjälä 		u16 eir = 0, eir_stuck = 0;
4059af722d28SVille Syrjälä 		u16 iir;
4060af722d28SVille Syrjälä 
40614f5fd91fSTvrtko Ursulin 		iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR);
4062c2798b19SChris Wilson 		if (iir == 0)
4063af722d28SVille Syrjälä 			break;
4064c2798b19SChris Wilson 
4065af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4066c2798b19SChris Wilson 
4067eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4068eb64343cSVille Syrjälä 		 * signalled in iir */
4069eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4070c2798b19SChris Wilson 
407178c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
407278c357ddSVille Syrjälä 			i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
407378c357ddSVille Syrjälä 
40744f5fd91fSTvrtko Ursulin 		intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir);
4075c2798b19SChris Wilson 
4076c2798b19SChris Wilson 		if (iir & I915_USER_INTERRUPT)
40772cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
4078c2798b19SChris Wilson 
407978c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
408078c357ddSVille Syrjälä 			i8xx_error_irq_handler(dev_priv, eir, eir_stuck);
4081af722d28SVille Syrjälä 
4082eb64343cSVille Syrjälä 		i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4083af722d28SVille Syrjälä 	} while (0);
4084c2798b19SChris Wilson 
40859c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
40869c6508b9SThomas Gleixner 
40879102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
40881f814dacSImre Deak 
40891f814dacSImre Deak 	return ret;
4090c2798b19SChris Wilson }
4091c2798b19SChris Wilson 
4092b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv)
4093a266c7d5SChris Wilson {
4094b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
4095a266c7d5SChris Wilson 
409656b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
40970706f17cSEgbert Eich 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
40988cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0);
4099a266c7d5SChris Wilson 	}
4100a266c7d5SChris Wilson 
410144d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
410244d9241eSVille Syrjälä 
4103b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
4104e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
4105a266c7d5SChris Wilson }
4106a266c7d5SChris Wilson 
4107b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
4108a266c7d5SChris Wilson {
4109b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
411038bde180SChris Wilson 	u32 enable_mask;
4111a266c7d5SChris Wilson 
41123687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv));
411338bde180SChris Wilson 
411438bde180SChris Wilson 	/* Unmask the interrupts that we always want on. */
411538bde180SChris Wilson 	dev_priv->irq_mask =
411638bde180SChris Wilson 		~(I915_ASLE_INTERRUPT |
411738bde180SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
411816659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
411916659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
412038bde180SChris Wilson 
412138bde180SChris Wilson 	enable_mask =
412238bde180SChris Wilson 		I915_ASLE_INTERRUPT |
412338bde180SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
412438bde180SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
412516659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
412638bde180SChris Wilson 		I915_USER_INTERRUPT;
412738bde180SChris Wilson 
412856b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
4129a266c7d5SChris Wilson 		/* Enable in IER... */
4130a266c7d5SChris Wilson 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
4131a266c7d5SChris Wilson 		/* and unmask in IMR */
4132a266c7d5SChris Wilson 		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
4133a266c7d5SChris Wilson 	}
4134a266c7d5SChris Wilson 
4135b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
4136a266c7d5SChris Wilson 
4137379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
4138379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
4139d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
4140755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
4141755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
4142d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
4143379ef82dSDaniel Vetter 
4144c30bb1fdSVille Syrjälä 	i915_enable_asle_pipestat(dev_priv);
414520afbda2SDaniel Vetter }
414620afbda2SDaniel Vetter 
4147ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg)
4148a266c7d5SChris Wilson {
4149b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4150af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4151a266c7d5SChris Wilson 
41522dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
41532dd2a883SImre Deak 		return IRQ_NONE;
41542dd2a883SImre Deak 
41551f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
41569102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
41571f814dacSImre Deak 
415838bde180SChris Wilson 	do {
4159eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
416078c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
4161af722d28SVille Syrjälä 		u32 hotplug_status = 0;
4162af722d28SVille Syrjälä 		u32 iir;
4163a266c7d5SChris Wilson 
41642939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
4165af722d28SVille Syrjälä 		if (iir == 0)
4166af722d28SVille Syrjälä 			break;
4167af722d28SVille Syrjälä 
4168af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4169af722d28SVille Syrjälä 
4170af722d28SVille Syrjälä 		if (I915_HAS_HOTPLUG(dev_priv) &&
4171af722d28SVille Syrjälä 		    iir & I915_DISPLAY_PORT_INTERRUPT)
4172af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
4173a266c7d5SChris Wilson 
4174eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4175eb64343cSVille Syrjälä 		 * signalled in iir */
4176eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4177a266c7d5SChris Wilson 
417878c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
417978c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
418078c357ddSVille Syrjälä 
41812939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
4182a266c7d5SChris Wilson 
4183a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
41842cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
4185a266c7d5SChris Wilson 
418678c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
418778c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
4188a266c7d5SChris Wilson 
4189af722d28SVille Syrjälä 		if (hotplug_status)
4190af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
4191af722d28SVille Syrjälä 
4192af722d28SVille Syrjälä 		i915_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4193af722d28SVille Syrjälä 	} while (0);
4194a266c7d5SChris Wilson 
41959c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
41969c6508b9SThomas Gleixner 
41979102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
41981f814dacSImre Deak 
4199a266c7d5SChris Wilson 	return ret;
4200a266c7d5SChris Wilson }
4201a266c7d5SChris Wilson 
4202b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv)
4203a266c7d5SChris Wilson {
4204b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
4205a266c7d5SChris Wilson 
42060706f17cSEgbert Eich 	i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
42078cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
4208a266c7d5SChris Wilson 
420944d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
421044d9241eSVille Syrjälä 
4211b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
4212e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
4213a266c7d5SChris Wilson }
4214a266c7d5SChris Wilson 
42153687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915)
4216a266c7d5SChris Wilson {
4217045cebd2SVille Syrjälä 	/*
4218045cebd2SVille Syrjälä 	 * Enable some error detection, note the instruction error mask
4219045cebd2SVille Syrjälä 	 * bit is reserved, so we leave it masked.
4220e7e12f6eSVille Syrjälä 	 *
4221e7e12f6eSVille Syrjälä 	 * i965 FBC no longer generates spurious GTT errors,
4222e7e12f6eSVille Syrjälä 	 * so we can always enable the page table errors.
4223045cebd2SVille Syrjälä 	 */
42243687ce75SVille Syrjälä 	if (IS_G4X(i915))
42253687ce75SVille Syrjälä 		return ~(GM45_ERROR_PAGE_TABLE |
4226045cebd2SVille Syrjälä 			 GM45_ERROR_MEM_PRIV |
4227045cebd2SVille Syrjälä 			 GM45_ERROR_CP_PRIV |
4228045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
42293687ce75SVille Syrjälä 	else
42303687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
4231045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
4232045cebd2SVille Syrjälä }
42333687ce75SVille Syrjälä 
42343687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
42353687ce75SVille Syrjälä {
42363687ce75SVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
42373687ce75SVille Syrjälä 	u32 enable_mask;
42383687ce75SVille Syrjälä 
42393687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv));
4240045cebd2SVille Syrjälä 
4241a266c7d5SChris Wilson 	/* Unmask the interrupts that we always want on. */
4242c30bb1fdSVille Syrjälä 	dev_priv->irq_mask =
4243c30bb1fdSVille Syrjälä 		~(I915_ASLE_INTERRUPT |
4244adca4730SChris Wilson 		  I915_DISPLAY_PORT_INTERRUPT |
4245bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4246bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
424778c357ddSVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
4248bbba0a97SChris Wilson 
4249c30bb1fdSVille Syrjälä 	enable_mask =
4250c30bb1fdSVille Syrjälä 		I915_ASLE_INTERRUPT |
4251c30bb1fdSVille Syrjälä 		I915_DISPLAY_PORT_INTERRUPT |
4252c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
4253c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
425478c357ddSVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
4255c30bb1fdSVille Syrjälä 		I915_USER_INTERRUPT;
4256bbba0a97SChris Wilson 
425791d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4258bbba0a97SChris Wilson 		enable_mask |= I915_BSD_USER_INTERRUPT;
4259a266c7d5SChris Wilson 
4260b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
4261c30bb1fdSVille Syrjälä 
4262b79480baSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
4263b79480baSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
4264d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
4265755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
4266755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
4267755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
4268d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
4269a266c7d5SChris Wilson 
427091d14251STvrtko Ursulin 	i915_enable_asle_pipestat(dev_priv);
427120afbda2SDaniel Vetter }
427220afbda2SDaniel Vetter 
4273d28cdc43SVille Syrjälä static void i915_hpd_enable_detection(struct intel_encoder *encoder)
4274d28cdc43SVille Syrjälä {
4275d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4276d28cdc43SVille Syrjälä 	u32 hotplug_en = hpd_mask_i915[encoder->hpd_pin];
4277d28cdc43SVille Syrjälä 
4278d28cdc43SVille Syrjälä 	/* HPD sense and interrupt enable are one and the same */
4279d28cdc43SVille Syrjälä 	i915_hotplug_interrupt_update(i915, hotplug_en, hotplug_en);
4280d28cdc43SVille Syrjälä }
4281d28cdc43SVille Syrjälä 
428291d14251STvrtko Ursulin static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
428320afbda2SDaniel Vetter {
428420afbda2SDaniel Vetter 	u32 hotplug_en;
428520afbda2SDaniel Vetter 
428667520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
4287b5ea2d56SDaniel Vetter 
4288adca4730SChris Wilson 	/* Note HDMI and DP share hotplug bits */
4289e5868a31SEgbert Eich 	/* enable bits are the same for all generations */
429091d14251STvrtko Ursulin 	hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
4291a266c7d5SChris Wilson 	/* Programming the CRT detection parameters tends
4292a266c7d5SChris Wilson 	   to generate a spurious hotplug event about three
4293a266c7d5SChris Wilson 	   seconds later.  So just do it once.
4294a266c7d5SChris Wilson 	*/
429591d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
4296a266c7d5SChris Wilson 		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
4297a266c7d5SChris Wilson 	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
4298a266c7d5SChris Wilson 
4299a266c7d5SChris Wilson 	/* Ignore TV since it's buggy */
43000706f17cSEgbert Eich 	i915_hotplug_interrupt_update_locked(dev_priv,
4301f9e3dc78SJani Nikula 					     HOTPLUG_INT_EN_MASK |
4302f9e3dc78SJani Nikula 					     CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
4303f9e3dc78SJani Nikula 					     CRT_HOTPLUG_ACTIVATION_PERIOD_64,
43040706f17cSEgbert Eich 					     hotplug_en);
4305a266c7d5SChris Wilson }
4306a266c7d5SChris Wilson 
4307ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg)
4308a266c7d5SChris Wilson {
4309b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
4310af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
4311a266c7d5SChris Wilson 
43122dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
43132dd2a883SImre Deak 		return IRQ_NONE;
43142dd2a883SImre Deak 
43151f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
43169102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
43171f814dacSImre Deak 
4318af722d28SVille Syrjälä 	do {
4319eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
432078c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
4321af722d28SVille Syrjälä 		u32 hotplug_status = 0;
4322af722d28SVille Syrjälä 		u32 iir;
43232c8ba29fSChris Wilson 
43242939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
4325af722d28SVille Syrjälä 		if (iir == 0)
4326af722d28SVille Syrjälä 			break;
4327af722d28SVille Syrjälä 
4328af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
4329af722d28SVille Syrjälä 
4330af722d28SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
4331af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
4332a266c7d5SChris Wilson 
4333eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
4334eb64343cSVille Syrjälä 		 * signalled in iir */
4335eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
4336a266c7d5SChris Wilson 
433778c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
433878c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
433978c357ddSVille Syrjälä 
43402939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
4341a266c7d5SChris Wilson 
4342a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
43432cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0],
43440669a6e1SChris Wilson 					    iir);
4345af722d28SVille Syrjälä 
4346a266c7d5SChris Wilson 		if (iir & I915_BSD_USER_INTERRUPT)
43472cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0],
43480669a6e1SChris Wilson 					    iir >> 25);
4349a266c7d5SChris Wilson 
435078c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
435178c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
4352515ac2bbSDaniel Vetter 
4353af722d28SVille Syrjälä 		if (hotplug_status)
4354af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
4355af722d28SVille Syrjälä 
4356af722d28SVille Syrjälä 		i965_pipestat_irq_handler(dev_priv, iir, pipe_stats);
4357af722d28SVille Syrjälä 	} while (0);
4358a266c7d5SChris Wilson 
43599c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
43609c6508b9SThomas Gleixner 
43619102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
43621f814dacSImre Deak 
4363a266c7d5SChris Wilson 	return ret;
4364a266c7d5SChris Wilson }
4365a266c7d5SChris Wilson 
43667e97596cSJani Nikula struct intel_hotplug_funcs {
4367d28cdc43SVille Syrjälä 	/* Enable HPD sense and interrupts for all present encoders */
43687e97596cSJani Nikula 	void (*hpd_irq_setup)(struct drm_i915_private *i915);
4369d28cdc43SVille Syrjälä 	/* Enable HPD sense for a single encoder */
4370d28cdc43SVille Syrjälä 	void (*hpd_enable_detection)(struct intel_encoder *encoder);
43717e97596cSJani Nikula };
43727e97596cSJani Nikula 
4373cd030c7cSDave Airlie #define HPD_FUNCS(platform)					 \
4374cd030c7cSDave Airlie static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
4375cd030c7cSDave Airlie 	.hpd_irq_setup = platform##_hpd_irq_setup,		 \
4376d28cdc43SVille Syrjälä 	.hpd_enable_detection = platform##_hpd_enable_detection, \
4377cd030c7cSDave Airlie }
4378cd030c7cSDave Airlie 
4379cd030c7cSDave Airlie HPD_FUNCS(i915);
4380babde06dSMika Kahola HPD_FUNCS(xelpdp);
4381cd030c7cSDave Airlie HPD_FUNCS(dg1);
4382cd030c7cSDave Airlie HPD_FUNCS(gen11);
4383cd030c7cSDave Airlie HPD_FUNCS(bxt);
4384cd030c7cSDave Airlie HPD_FUNCS(icp);
4385cd030c7cSDave Airlie HPD_FUNCS(spt);
4386cd030c7cSDave Airlie HPD_FUNCS(ilk);
4387cd030c7cSDave Airlie #undef HPD_FUNCS
4388cd030c7cSDave Airlie 
4389d28cdc43SVille Syrjälä void intel_hpd_enable_detection(struct intel_encoder *encoder)
4390d28cdc43SVille Syrjälä {
4391d28cdc43SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4392d28cdc43SVille Syrjälä 
4393d28cdc43SVille Syrjälä 	if (i915->display.funcs.hotplug)
4394d28cdc43SVille Syrjälä 		i915->display.funcs.hotplug->hpd_enable_detection(encoder);
4395d28cdc43SVille Syrjälä }
4396d28cdc43SVille Syrjälä 
43977e97596cSJani Nikula void intel_hpd_irq_setup(struct drm_i915_private *i915)
43987e97596cSJani Nikula {
43995a04eb5bSJani Nikula 	if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
44005a04eb5bSJani Nikula 		i915->display.funcs.hotplug->hpd_irq_setup(i915);
44017e97596cSJani Nikula }
44027e97596cSJani Nikula 
4403fca52a55SDaniel Vetter /**
4404fca52a55SDaniel Vetter  * intel_irq_init - initializes irq support
4405fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4406fca52a55SDaniel Vetter  *
4407fca52a55SDaniel Vetter  * This function initializes all the irq support including work items, timers
4408fca52a55SDaniel Vetter  * and all the vtables. It does not setup the interrupt itself though.
4409fca52a55SDaniel Vetter  */
4410b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv)
4411f71d4af4SJesse Barnes {
4412cefcff8fSJoonas Lahtinen 	int i;
44138b2e326dSChris Wilson 
441474bb98baSLucas De Marchi 	INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work);
4415cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4416cefcff8fSJoonas Lahtinen 		dev_priv->l3_parity.remap_info[i] = NULL;
44178b2e326dSChris Wilson 
4418633023a4SDaniele Ceraolo Spurio 	/* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */
4419651e7d48SLucas De Marchi 	if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11)
44202cbc876dSMichał Winiarski 		to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16;
442126705e20SSagar Arun Kamble 
44229a450b68SLucas De Marchi 	if (!HAS_DISPLAY(dev_priv))
44239a450b68SLucas De Marchi 		return;
44249a450b68SLucas De Marchi 
442596bd87b7SLucas De Marchi 	intel_hpd_init_pins(dev_priv);
442696bd87b7SLucas De Marchi 
4427dd890d42SJani Nikula 	intel_hpd_init_early(dev_priv);
442896bd87b7SLucas De Marchi 
44293703060dSAndrzej Hajda 	dev_priv->drm.vblank_disable_immediate = true;
443021da2700SVille Syrjälä 
4431262fd485SChris Wilson 	/* Most platforms treat the display irq block as an always-on
4432262fd485SChris Wilson 	 * power domain. vlv/chv can disable it at runtime and need
4433262fd485SChris Wilson 	 * special care to avoid writing any of the display block registers
4434262fd485SChris Wilson 	 * outside of the power domain. We defer setting up the display irqs
4435262fd485SChris Wilson 	 * in this case to the runtime pm.
4436262fd485SChris Wilson 	 */
4437262fd485SChris Wilson 	dev_priv->display_irqs_enabled = true;
4438262fd485SChris Wilson 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
4439262fd485SChris Wilson 		dev_priv->display_irqs_enabled = false;
4440262fd485SChris Wilson 
44412ccf2e03SChris Wilson 	if (HAS_GMCH(dev_priv)) {
44422ccf2e03SChris Wilson 		if (I915_HAS_HOTPLUG(dev_priv))
44435a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &i915_hpd_funcs;
44442ccf2e03SChris Wilson 	} else {
44452f8a6699SMatt Roper 		if (HAS_PCH_DG2(dev_priv))
44465a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
44472f8a6699SMatt Roper 		else if (HAS_PCH_DG1(dev_priv))
44485a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &dg1_hpd_funcs;
4449babde06dSMika Kahola 		else if (DISPLAY_VER(dev_priv) >= 14)
4450babde06dSMika Kahola 			dev_priv->display.funcs.hotplug = &xelpdp_hpd_funcs;
4451373abf1aSMatt Roper 		else if (DISPLAY_VER(dev_priv) >= 11)
44525a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &gen11_hpd_funcs;
445370bfb307SMatt Roper 		else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
44545a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &bxt_hpd_funcs;
4455cec3295bSLyude Paul 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
44565a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
4457c6c30b91SRodrigo Vivi 		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
44585a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &spt_hpd_funcs;
44596dbf30ceSVille Syrjälä 		else
44605a04eb5bSJani Nikula 			dev_priv->display.funcs.hotplug = &ilk_hpd_funcs;
4461f71d4af4SJesse Barnes 	}
44622ccf2e03SChris Wilson }
446320afbda2SDaniel Vetter 
4464fca52a55SDaniel Vetter /**
4465cefcff8fSJoonas Lahtinen  * intel_irq_fini - deinitializes IRQ support
4466cefcff8fSJoonas Lahtinen  * @i915: i915 device instance
4467cefcff8fSJoonas Lahtinen  *
4468cefcff8fSJoonas Lahtinen  * This function deinitializes all the IRQ support.
4469cefcff8fSJoonas Lahtinen  */
4470cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915)
4471cefcff8fSJoonas Lahtinen {
4472cefcff8fSJoonas Lahtinen 	int i;
4473cefcff8fSJoonas Lahtinen 
4474cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
4475cefcff8fSJoonas Lahtinen 		kfree(i915->l3_parity.remap_info[i]);
4476cefcff8fSJoonas Lahtinen }
4477cefcff8fSJoonas Lahtinen 
4478b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv)
4479b318b824SVille Syrjälä {
4480b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4481b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4482b318b824SVille Syrjälä 			return cherryview_irq_handler;
4483b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4484b318b824SVille Syrjälä 			return valleyview_irq_handler;
4485651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4486b318b824SVille Syrjälä 			return i965_irq_handler;
4487651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4488b318b824SVille Syrjälä 			return i915_irq_handler;
4489b318b824SVille Syrjälä 		else
4490b318b824SVille Syrjälä 			return i8xx_irq_handler;
4491b318b824SVille Syrjälä 	} else {
449222e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
449397b492f5SLucas De Marchi 			return dg1_irq_handler;
449422e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4495b318b824SVille Syrjälä 			return gen11_irq_handler;
4496651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4497b318b824SVille Syrjälä 			return gen8_irq_handler;
4498b318b824SVille Syrjälä 		else
44999eae5e27SLucas De Marchi 			return ilk_irq_handler;
4500b318b824SVille Syrjälä 	}
4501b318b824SVille Syrjälä }
4502b318b824SVille Syrjälä 
4503b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv)
4504b318b824SVille Syrjälä {
4505b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4506b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4507b318b824SVille Syrjälä 			cherryview_irq_reset(dev_priv);
4508b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4509b318b824SVille Syrjälä 			valleyview_irq_reset(dev_priv);
4510651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4511b318b824SVille Syrjälä 			i965_irq_reset(dev_priv);
4512651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4513b318b824SVille Syrjälä 			i915_irq_reset(dev_priv);
4514b318b824SVille Syrjälä 		else
4515b318b824SVille Syrjälä 			i8xx_irq_reset(dev_priv);
4516b318b824SVille Syrjälä 	} else {
451722e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
451822e26af7SPaulo Zanoni 			dg1_irq_reset(dev_priv);
451922e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4520b318b824SVille Syrjälä 			gen11_irq_reset(dev_priv);
4521651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4522b318b824SVille Syrjälä 			gen8_irq_reset(dev_priv);
4523b318b824SVille Syrjälä 		else
45249eae5e27SLucas De Marchi 			ilk_irq_reset(dev_priv);
4525b318b824SVille Syrjälä 	}
4526b318b824SVille Syrjälä }
4527b318b824SVille Syrjälä 
4528b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv)
4529b318b824SVille Syrjälä {
4530b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
4531b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
4532b318b824SVille Syrjälä 			cherryview_irq_postinstall(dev_priv);
4533b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
4534b318b824SVille Syrjälä 			valleyview_irq_postinstall(dev_priv);
4535651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
4536b318b824SVille Syrjälä 			i965_irq_postinstall(dev_priv);
4537651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
4538b318b824SVille Syrjälä 			i915_irq_postinstall(dev_priv);
4539b318b824SVille Syrjälä 		else
4540b318b824SVille Syrjälä 			i8xx_irq_postinstall(dev_priv);
4541b318b824SVille Syrjälä 	} else {
454222e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
454322e26af7SPaulo Zanoni 			dg1_irq_postinstall(dev_priv);
454422e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
4545b318b824SVille Syrjälä 			gen11_irq_postinstall(dev_priv);
4546651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
4547b318b824SVille Syrjälä 			gen8_irq_postinstall(dev_priv);
4548b318b824SVille Syrjälä 		else
45499eae5e27SLucas De Marchi 			ilk_irq_postinstall(dev_priv);
4550b318b824SVille Syrjälä 	}
4551b318b824SVille Syrjälä }
4552b318b824SVille Syrjälä 
4553cefcff8fSJoonas Lahtinen /**
4554fca52a55SDaniel Vetter  * intel_irq_install - enables the hardware interrupt
4555fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4556fca52a55SDaniel Vetter  *
4557fca52a55SDaniel Vetter  * This function enables the hardware interrupt handling, but leaves the hotplug
4558fca52a55SDaniel Vetter  * handling still disabled. It is called after intel_irq_init().
4559fca52a55SDaniel Vetter  *
4560fca52a55SDaniel Vetter  * In the driver load and resume code we need working interrupts in a few places
4561fca52a55SDaniel Vetter  * but don't want to deal with the hassle of concurrent probe and hotplug
4562fca52a55SDaniel Vetter  * workers. Hence the split into this two-stage approach.
4563fca52a55SDaniel Vetter  */
45642aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv)
45652aeb7d3aSDaniel Vetter {
45668ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4567b318b824SVille Syrjälä 	int ret;
4568b318b824SVille Syrjälä 
45692aeb7d3aSDaniel Vetter 	/*
45702aeb7d3aSDaniel Vetter 	 * We enable some interrupt sources in our postinstall hooks, so mark
45712aeb7d3aSDaniel Vetter 	 * interrupts as enabled _before_ actually enabling them to avoid
45722aeb7d3aSDaniel Vetter 	 * special cases in our ordering checks.
45732aeb7d3aSDaniel Vetter 	 */
4574ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
45752aeb7d3aSDaniel Vetter 
4576ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = true;
4577b318b824SVille Syrjälä 
4578b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4579b318b824SVille Syrjälä 
4580b318b824SVille Syrjälä 	ret = request_irq(irq, intel_irq_handler(dev_priv),
4581b318b824SVille Syrjälä 			  IRQF_SHARED, DRIVER_NAME, dev_priv);
4582b318b824SVille Syrjälä 	if (ret < 0) {
4583ac1723c1SThomas Zimmermann 		dev_priv->irq_enabled = false;
4584b318b824SVille Syrjälä 		return ret;
4585b318b824SVille Syrjälä 	}
4586b318b824SVille Syrjälä 
4587b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4588b318b824SVille Syrjälä 
4589b318b824SVille Syrjälä 	return ret;
45902aeb7d3aSDaniel Vetter }
45912aeb7d3aSDaniel Vetter 
4592fca52a55SDaniel Vetter /**
4593fca52a55SDaniel Vetter  * intel_irq_uninstall - finilizes all irq handling
4594fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4595fca52a55SDaniel Vetter  *
4596fca52a55SDaniel Vetter  * This stops interrupt and hotplug handling and unregisters and frees all
4597fca52a55SDaniel Vetter  * resources acquired in the init functions.
4598fca52a55SDaniel Vetter  */
45992aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv)
46002aeb7d3aSDaniel Vetter {
46018ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
4602b318b824SVille Syrjälä 
4603b318b824SVille Syrjälä 	/*
4604789fa874SJanusz Krzysztofik 	 * FIXME we can get called twice during driver probe
4605789fa874SJanusz Krzysztofik 	 * error handling as well as during driver remove due to
460686a1758dSJani Nikula 	 * intel_display_driver_remove() calling us out of sequence.
4607789fa874SJanusz Krzysztofik 	 * Would be nice if it didn't do that...
4608b318b824SVille Syrjälä 	 */
4609ac1723c1SThomas Zimmermann 	if (!dev_priv->irq_enabled)
4610b318b824SVille Syrjälä 		return;
4611b318b824SVille Syrjälä 
4612ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = false;
4613b318b824SVille Syrjälä 
4614b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4615b318b824SVille Syrjälä 
4616b318b824SVille Syrjälä 	free_irq(irq, dev_priv);
4617b318b824SVille Syrjälä 
46182aeb7d3aSDaniel Vetter 	intel_hpd_cancel_work(dev_priv);
4619ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
46202aeb7d3aSDaniel Vetter }
46212aeb7d3aSDaniel Vetter 
4622fca52a55SDaniel Vetter /**
4623fca52a55SDaniel Vetter  * intel_runtime_pm_disable_interrupts - runtime interrupt disabling
4624fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4625fca52a55SDaniel Vetter  *
4626fca52a55SDaniel Vetter  * This function is used to disable interrupts at runtime, both in the runtime
4627fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4628fca52a55SDaniel Vetter  */
4629b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
4630c67a470bSPaulo Zanoni {
4631b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4632ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
4633315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
4634c67a470bSPaulo Zanoni }
4635c67a470bSPaulo Zanoni 
4636fca52a55SDaniel Vetter /**
4637fca52a55SDaniel Vetter  * intel_runtime_pm_enable_interrupts - runtime interrupt enabling
4638fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
4639fca52a55SDaniel Vetter  *
4640fca52a55SDaniel Vetter  * This function is used to enable interrupts at runtime, both in the runtime
4641fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
4642fca52a55SDaniel Vetter  */
4643b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv)
4644c67a470bSPaulo Zanoni {
4645ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
4646b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
4647b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
4648c67a470bSPaulo Zanoni }
4649d64575eeSJani Nikula 
4650d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
4651d64575eeSJani Nikula {
4652d64575eeSJani Nikula 	return dev_priv->runtime_pm.irqs_enabled;
4653d64575eeSJani Nikula }
4654d64575eeSJani Nikula 
4655d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915)
4656d64575eeSJani Nikula {
46578ff5446aSThomas Zimmermann 	synchronize_irq(to_pci_dev(i915->drm.dev)->irq);
4658d64575eeSJani Nikula }
4659320ad343SThomas Zimmermann 
4660320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915)
4661320ad343SThomas Zimmermann {
4662320ad343SThomas Zimmermann 	synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq);
4663320ad343SThomas Zimmermann }
4664