xref: /openbmc/linux/drivers/gpu/drm/i915/i915_irq.c (revision da38ba98645d789ddda2a584d40e2de00139e98b)
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"
40685282a3SJani Nikula #include "display/intel_dp_aux.h"
4104500bfdSJani Nikula #include "display/intel_fdi_regs.h"
42df0566a6SJani Nikula #include "display/intel_fifo_underrun.h"
43685282a3SJani Nikula #include "display/intel_gmbus.h"
44df0566a6SJani Nikula #include "display/intel_hotplug.h"
45*da38ba98SJani Nikula #include "display/intel_hotplug_irq.h"
46df0566a6SJani Nikula #include "display/intel_lpe_audio.h"
47df0566a6SJani Nikula #include "display/intel_psr.h"
487f6947fdSJani Nikula #include "display/intel_psr_regs.h"
49df0566a6SJani Nikula 
50b3786b29SChris Wilson #include "gt/intel_breadcrumbs.h"
512239e6dfSDaniele Ceraolo Spurio #include "gt/intel_gt.h"
52cf1c97dcSAndi Shyti #include "gt/intel_gt_irq.h"
53d762043fSAndi Shyti #include "gt/intel_gt_pm_irq.h"
540d6419e9SMatt Roper #include "gt/intel_gt_regs.h"
553e7abf81SAndi Shyti #include "gt/intel_rps.h"
562239e6dfSDaniele Ceraolo Spurio 
5724524e3fSJani Nikula #include "i915_driver.h"
58c0e09200SDave Airlie #include "i915_drv.h"
59440e2b3dSJani Nikula #include "i915_irq.h"
60476f62b8SJani Nikula #include "i915_reg.h"
61c0e09200SDave Airlie 
62fca52a55SDaniel Vetter /**
63fca52a55SDaniel Vetter  * DOC: interrupt handling
64fca52a55SDaniel Vetter  *
65fca52a55SDaniel Vetter  * These functions provide the basic support for enabling and disabling the
66fca52a55SDaniel Vetter  * interrupt handling support. There's a lot more functionality in i915_irq.c
67fca52a55SDaniel Vetter  * and related files, but that will be described in separate chapters.
68fca52a55SDaniel Vetter  */
69fca52a55SDaniel Vetter 
709c6508b9SThomas Gleixner /*
719c6508b9SThomas Gleixner  * Interrupt statistic for PMU. Increments the counter only if the
7278f48aa6SBo Liu  * interrupt originated from the GPU so interrupts from a device which
739c6508b9SThomas Gleixner  * shares the interrupt line are not accounted.
749c6508b9SThomas Gleixner  */
759c6508b9SThomas Gleixner static inline void pmu_irq_stats(struct drm_i915_private *i915,
769c6508b9SThomas Gleixner 				 irqreturn_t res)
779c6508b9SThomas Gleixner {
789c6508b9SThomas Gleixner 	if (unlikely(res != IRQ_HANDLED))
799c6508b9SThomas Gleixner 		return;
809c6508b9SThomas Gleixner 
819c6508b9SThomas Gleixner 	/*
829c6508b9SThomas Gleixner 	 * A clever compiler translates that into INC. A not so clever one
839c6508b9SThomas Gleixner 	 * should at least prevent store tearing.
849c6508b9SThomas Gleixner 	 */
859c6508b9SThomas Gleixner 	WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1);
869c6508b9SThomas Gleixner }
879c6508b9SThomas Gleixner 
88aca9310aSAnshuman Gupta static void
89aca9310aSAnshuman Gupta intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
90aca9310aSAnshuman Gupta {
917794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
92aca9310aSAnshuman Gupta 
93aca9310aSAnshuman Gupta 	drm_crtc_handle_vblank(&crtc->base);
94aca9310aSAnshuman Gupta }
95aca9310aSAnshuman Gupta 
96cf1c97dcSAndi Shyti void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
9768eb49b1SPaulo Zanoni 		    i915_reg_t iir, i915_reg_t ier)
9868eb49b1SPaulo Zanoni {
9965f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, imr, 0xffffffff);
10065f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, imr);
10168eb49b1SPaulo Zanoni 
10265f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, ier, 0);
10368eb49b1SPaulo Zanoni 
1045c502442SPaulo Zanoni 	/* IIR can theoretically queue up two events. Be paranoid. */
10565f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, iir, 0xffffffff);
10665f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, iir);
10765f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, iir, 0xffffffff);
10865f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, iir);
10968eb49b1SPaulo Zanoni }
1105c502442SPaulo Zanoni 
111ad7632ffSJani Nikula static void gen2_irq_reset(struct intel_uncore *uncore)
11268eb49b1SPaulo Zanoni {
11365f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IMR, 0xffff);
11465f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IMR);
115a9d356a6SPaulo Zanoni 
11665f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IER, 0);
11768eb49b1SPaulo Zanoni 
11868eb49b1SPaulo Zanoni 	/* IIR can theoretically queue up two events. Be paranoid. */
11965f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
12065f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
12165f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
12265f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
12368eb49b1SPaulo Zanoni }
12468eb49b1SPaulo Zanoni 
125337ba017SPaulo Zanoni /*
126337ba017SPaulo Zanoni  * We should clear IMR at preinstall/uninstall, and just check at postinstall.
127337ba017SPaulo Zanoni  */
12865f42cdcSPaulo Zanoni static void gen3_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg)
129b51a2842SVille Syrjälä {
13065f42cdcSPaulo Zanoni 	u32 val = intel_uncore_read(uncore, reg);
131b51a2842SVille Syrjälä 
132b51a2842SVille Syrjälä 	if (val == 0)
133b51a2842SVille Syrjälä 		return;
134b51a2842SVille Syrjälä 
135a9f236d1SPankaj Bharadiya 	drm_WARN(&uncore->i915->drm, 1,
136a9f236d1SPankaj Bharadiya 		 "Interrupt register 0x%x is not zero: 0x%08x\n",
137f0f59a00SVille Syrjälä 		 i915_mmio_reg_offset(reg), val);
13865f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, reg, 0xffffffff);
13965f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, reg);
14065f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, reg, 0xffffffff);
14165f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, reg);
142b51a2842SVille Syrjälä }
143337ba017SPaulo Zanoni 
14465f42cdcSPaulo Zanoni static void gen2_assert_iir_is_zero(struct intel_uncore *uncore)
145e9e9848aSVille Syrjälä {
14665f42cdcSPaulo Zanoni 	u16 val = intel_uncore_read16(uncore, GEN2_IIR);
147e9e9848aSVille Syrjälä 
148e9e9848aSVille Syrjälä 	if (val == 0)
149e9e9848aSVille Syrjälä 		return;
150e9e9848aSVille Syrjälä 
151a9f236d1SPankaj Bharadiya 	drm_WARN(&uncore->i915->drm, 1,
152a9f236d1SPankaj Bharadiya 		 "Interrupt register 0x%x is not zero: 0x%08x\n",
1539d9523d8SPaulo Zanoni 		 i915_mmio_reg_offset(GEN2_IIR), val);
15465f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
15565f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
15665f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IIR, 0xffff);
15765f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IIR);
158e9e9848aSVille Syrjälä }
159e9e9848aSVille Syrjälä 
160cf1c97dcSAndi Shyti void gen3_irq_init(struct intel_uncore *uncore,
16168eb49b1SPaulo Zanoni 		   i915_reg_t imr, u32 imr_val,
16268eb49b1SPaulo Zanoni 		   i915_reg_t ier, u32 ier_val,
16368eb49b1SPaulo Zanoni 		   i915_reg_t iir)
16468eb49b1SPaulo Zanoni {
16565f42cdcSPaulo Zanoni 	gen3_assert_iir_is_zero(uncore, iir);
16635079899SPaulo Zanoni 
16765f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, ier, ier_val);
16865f42cdcSPaulo Zanoni 	intel_uncore_write(uncore, imr, imr_val);
16965f42cdcSPaulo Zanoni 	intel_uncore_posting_read(uncore, imr);
17068eb49b1SPaulo Zanoni }
17135079899SPaulo Zanoni 
172ad7632ffSJani Nikula static void gen2_irq_init(struct intel_uncore *uncore,
1732918c3caSPaulo Zanoni 			  u32 imr_val, u32 ier_val)
17468eb49b1SPaulo Zanoni {
17565f42cdcSPaulo Zanoni 	gen2_assert_iir_is_zero(uncore);
17668eb49b1SPaulo Zanoni 
17765f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IER, ier_val);
17865f42cdcSPaulo Zanoni 	intel_uncore_write16(uncore, GEN2_IMR, imr_val);
17965f42cdcSPaulo Zanoni 	intel_uncore_posting_read16(uncore, GEN2_IMR);
18068eb49b1SPaulo Zanoni }
18168eb49b1SPaulo Zanoni 
182d9dc34f1SVille Syrjälä /**
183d9dc34f1SVille Syrjälä  * ilk_update_display_irq - update DEIMR
184d9dc34f1SVille Syrjälä  * @dev_priv: driver private
185d9dc34f1SVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
186d9dc34f1SVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
187d9dc34f1SVille Syrjälä  */
188*da38ba98SJani Nikula void ilk_update_display_irq(struct drm_i915_private *dev_priv,
1899e6dcf33SJani Nikula 			    u32 interrupt_mask, u32 enabled_irq_mask)
190036a4a7dSZhenyu Wang {
191a9c287c9SJani Nikula 	u32 new_val;
192d9dc34f1SVille Syrjälä 
19367520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
19448a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
195d9dc34f1SVille Syrjälä 
196d9dc34f1SVille Syrjälä 	new_val = dev_priv->irq_mask;
197d9dc34f1SVille Syrjälä 	new_val &= ~interrupt_mask;
198d9dc34f1SVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
199d9dc34f1SVille Syrjälä 
200e44adb5dSChris Wilson 	if (new_val != dev_priv->irq_mask &&
201e44adb5dSChris Wilson 	    !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) {
202d9dc34f1SVille Syrjälä 		dev_priv->irq_mask = new_val;
2032939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask);
2042939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, DEIMR);
205036a4a7dSZhenyu Wang 	}
206036a4a7dSZhenyu Wang }
207036a4a7dSZhenyu Wang 
2089e6dcf33SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits)
2099e6dcf33SJani Nikula {
2109e6dcf33SJani Nikula 	ilk_update_display_irq(i915, bits, bits);
2119e6dcf33SJani Nikula }
2129e6dcf33SJani Nikula 
2139e6dcf33SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits)
2149e6dcf33SJani Nikula {
2159e6dcf33SJani Nikula 	ilk_update_display_irq(i915, bits, 0);
2169e6dcf33SJani Nikula }
2179e6dcf33SJani Nikula 
2180961021aSBen Widawsky /**
2193a3b3c7dSVille Syrjälä  * bdw_update_port_irq - update DE port interrupt
2203a3b3c7dSVille Syrjälä  * @dev_priv: driver private
2213a3b3c7dSVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
2223a3b3c7dSVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
2233a3b3c7dSVille Syrjälä  */
224*da38ba98SJani Nikula void bdw_update_port_irq(struct drm_i915_private *dev_priv,
225*da38ba98SJani Nikula 			 u32 interrupt_mask, u32 enabled_irq_mask)
2263a3b3c7dSVille Syrjälä {
227a9c287c9SJani Nikula 	u32 new_val;
228a9c287c9SJani Nikula 	u32 old_val;
2293a3b3c7dSVille Syrjälä 
23067520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
2313a3b3c7dSVille Syrjälä 
23248a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
2333a3b3c7dSVille Syrjälä 
23448a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
2353a3b3c7dSVille Syrjälä 		return;
2363a3b3c7dSVille Syrjälä 
2372939eb06SJani Nikula 	old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
2383a3b3c7dSVille Syrjälä 
2393a3b3c7dSVille Syrjälä 	new_val = old_val;
2403a3b3c7dSVille Syrjälä 	new_val &= ~interrupt_mask;
2413a3b3c7dSVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
2423a3b3c7dSVille Syrjälä 
2433a3b3c7dSVille Syrjälä 	if (new_val != old_val) {
2442939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val);
2452939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
2463a3b3c7dSVille Syrjälä 	}
2473a3b3c7dSVille Syrjälä }
2483a3b3c7dSVille Syrjälä 
2493a3b3c7dSVille Syrjälä /**
250013d3752SVille Syrjälä  * bdw_update_pipe_irq - update DE pipe interrupt
251013d3752SVille Syrjälä  * @dev_priv: driver private
252013d3752SVille Syrjälä  * @pipe: pipe whose interrupt to update
253013d3752SVille Syrjälä  * @interrupt_mask: mask of interrupt bits to update
254013d3752SVille Syrjälä  * @enabled_irq_mask: mask of interrupt bits to enable
255013d3752SVille Syrjälä  */
2569e6dcf33SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
2579e6dcf33SJani Nikula 				enum pipe pipe, u32 interrupt_mask,
258a9c287c9SJani Nikula 				u32 enabled_irq_mask)
259013d3752SVille Syrjälä {
260a9c287c9SJani Nikula 	u32 new_val;
261013d3752SVille Syrjälä 
26267520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
263013d3752SVille Syrjälä 
26448a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
265013d3752SVille Syrjälä 
26648a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
267013d3752SVille Syrjälä 		return;
268013d3752SVille Syrjälä 
269013d3752SVille Syrjälä 	new_val = dev_priv->de_irq_mask[pipe];
270013d3752SVille Syrjälä 	new_val &= ~interrupt_mask;
271013d3752SVille Syrjälä 	new_val |= (~enabled_irq_mask & interrupt_mask);
272013d3752SVille Syrjälä 
273013d3752SVille Syrjälä 	if (new_val != dev_priv->de_irq_mask[pipe]) {
274013d3752SVille Syrjälä 		dev_priv->de_irq_mask[pipe] = new_val;
2752939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
2762939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe));
277013d3752SVille Syrjälä 	}
278013d3752SVille Syrjälä }
279013d3752SVille Syrjälä 
2809e6dcf33SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915,
2819e6dcf33SJani Nikula 			 enum pipe pipe, u32 bits)
2829e6dcf33SJani Nikula {
2839e6dcf33SJani Nikula 	bdw_update_pipe_irq(i915, pipe, bits, bits);
2849e6dcf33SJani Nikula }
2859e6dcf33SJani Nikula 
2869e6dcf33SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915,
2879e6dcf33SJani Nikula 			  enum pipe pipe, u32 bits)
2889e6dcf33SJani Nikula {
2899e6dcf33SJani Nikula 	bdw_update_pipe_irq(i915, pipe, bits, 0);
2909e6dcf33SJani Nikula }
2919e6dcf33SJani Nikula 
292013d3752SVille Syrjälä /**
293fee884edSDaniel Vetter  * ibx_display_interrupt_update - update SDEIMR
294fee884edSDaniel Vetter  * @dev_priv: driver private
295fee884edSDaniel Vetter  * @interrupt_mask: mask of interrupt bits to update
296fee884edSDaniel Vetter  * @enabled_irq_mask: mask of interrupt bits to enable
297fee884edSDaniel Vetter  */
298*da38ba98SJani Nikula void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
299a9c287c9SJani Nikula 				  u32 interrupt_mask,
300a9c287c9SJani Nikula 				  u32 enabled_irq_mask)
301fee884edSDaniel Vetter {
3022939eb06SJani Nikula 	u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR);
303fee884edSDaniel Vetter 	sdeimr &= ~interrupt_mask;
304fee884edSDaniel Vetter 	sdeimr |= (~enabled_irq_mask & interrupt_mask);
305fee884edSDaniel Vetter 
30648a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
30715a17aaeSDaniel Vetter 
30867520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
309fee884edSDaniel Vetter 
31048a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
311c67a470bSPaulo Zanoni 		return;
312c67a470bSPaulo Zanoni 
3132939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr);
3142939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, SDEIMR);
315fee884edSDaniel Vetter }
3168664281bSPaulo Zanoni 
3179e6dcf33SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits)
3189e6dcf33SJani Nikula {
3199e6dcf33SJani Nikula 	ibx_display_interrupt_update(i915, bits, bits);
3209e6dcf33SJani Nikula }
3219e6dcf33SJani Nikula 
3229e6dcf33SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits)
3239e6dcf33SJani Nikula {
3249e6dcf33SJani Nikula 	ibx_display_interrupt_update(i915, bits, 0);
3259e6dcf33SJani Nikula }
3269e6dcf33SJani Nikula 
3276b12ca56SVille Syrjälä u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv,
3286b12ca56SVille Syrjälä 			      enum pipe pipe)
3297c463586SKeith Packard {
3306b12ca56SVille Syrjälä 	u32 status_mask = dev_priv->pipestat_irq_mask[pipe];
33110c59c51SImre Deak 	u32 enable_mask = status_mask << 16;
33210c59c51SImre Deak 
3336b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
3346b12ca56SVille Syrjälä 
335373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) < 5)
3366b12ca56SVille Syrjälä 		goto out;
3376b12ca56SVille Syrjälä 
33810c59c51SImre Deak 	/*
339724a6905SVille Syrjälä 	 * On pipe A we don't support the PSR interrupt yet,
340724a6905SVille Syrjälä 	 * on pipe B and C the same bit MBZ.
34110c59c51SImre Deak 	 */
34248a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON_ONCE(&dev_priv->drm,
34348a1b8d4SPankaj Bharadiya 			     status_mask & PIPE_A_PSR_STATUS_VLV))
34410c59c51SImre Deak 		return 0;
345724a6905SVille Syrjälä 	/*
346724a6905SVille Syrjälä 	 * On pipe B and C we don't support the PSR interrupt yet, on pipe
347724a6905SVille Syrjälä 	 * A the same bit is for perf counters which we don't use either.
348724a6905SVille Syrjälä 	 */
34948a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON_ONCE(&dev_priv->drm,
35048a1b8d4SPankaj Bharadiya 			     status_mask & PIPE_B_PSR_STATUS_VLV))
351724a6905SVille Syrjälä 		return 0;
35210c59c51SImre Deak 
35310c59c51SImre Deak 	enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
35410c59c51SImre Deak 			 SPRITE0_FLIP_DONE_INT_EN_VLV |
35510c59c51SImre Deak 			 SPRITE1_FLIP_DONE_INT_EN_VLV);
35610c59c51SImre Deak 	if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
35710c59c51SImre Deak 		enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
35810c59c51SImre Deak 	if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
35910c59c51SImre Deak 		enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
36010c59c51SImre Deak 
3616b12ca56SVille Syrjälä out:
36248a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm,
36348a1b8d4SPankaj Bharadiya 		      enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
3646b12ca56SVille Syrjälä 		      status_mask & ~PIPESTAT_INT_STATUS_MASK,
3656b12ca56SVille Syrjälä 		      "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
3666b12ca56SVille Syrjälä 		      pipe_name(pipe), enable_mask, status_mask);
3676b12ca56SVille Syrjälä 
36810c59c51SImre Deak 	return enable_mask;
36910c59c51SImre Deak }
37010c59c51SImre Deak 
3716b12ca56SVille Syrjälä void i915_enable_pipestat(struct drm_i915_private *dev_priv,
3726b12ca56SVille Syrjälä 			  enum pipe pipe, u32 status_mask)
373755e9019SImre Deak {
3746b12ca56SVille Syrjälä 	i915_reg_t reg = PIPESTAT(pipe);
375755e9019SImre Deak 	u32 enable_mask;
376755e9019SImre Deak 
37748a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
3786b12ca56SVille Syrjälä 		      "pipe %c: status_mask=0x%x\n",
3796b12ca56SVille Syrjälä 		      pipe_name(pipe), status_mask);
3806b12ca56SVille Syrjälä 
3816b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
38248a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
3836b12ca56SVille Syrjälä 
3846b12ca56SVille Syrjälä 	if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask)
3856b12ca56SVille Syrjälä 		return;
3866b12ca56SVille Syrjälä 
3876b12ca56SVille Syrjälä 	dev_priv->pipestat_irq_mask[pipe] |= status_mask;
3886b12ca56SVille Syrjälä 	enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
3896b12ca56SVille Syrjälä 
3902939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
3912939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, reg);
392755e9019SImre Deak }
393755e9019SImre Deak 
3946b12ca56SVille Syrjälä void i915_disable_pipestat(struct drm_i915_private *dev_priv,
3956b12ca56SVille Syrjälä 			   enum pipe pipe, u32 status_mask)
396755e9019SImre Deak {
3976b12ca56SVille Syrjälä 	i915_reg_t reg = PIPESTAT(pipe);
398755e9019SImre Deak 	u32 enable_mask;
399755e9019SImre Deak 
40048a1b8d4SPankaj Bharadiya 	drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
4016b12ca56SVille Syrjälä 		      "pipe %c: status_mask=0x%x\n",
4026b12ca56SVille Syrjälä 		      pipe_name(pipe), status_mask);
4036b12ca56SVille Syrjälä 
4046b12ca56SVille Syrjälä 	lockdep_assert_held(&dev_priv->irq_lock);
40548a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
4066b12ca56SVille Syrjälä 
4076b12ca56SVille Syrjälä 	if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0)
4086b12ca56SVille Syrjälä 		return;
4096b12ca56SVille Syrjälä 
4106b12ca56SVille Syrjälä 	dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
4116b12ca56SVille Syrjälä 	enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
4126b12ca56SVille Syrjälä 
4132939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
4142939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, reg);
415755e9019SImre Deak }
416755e9019SImre Deak 
417f3e30485SVille Syrjälä static bool i915_has_asle(struct drm_i915_private *dev_priv)
418f3e30485SVille Syrjälä {
4197249dfcbSJani Nikula 	if (!dev_priv->display.opregion.asle)
420f3e30485SVille Syrjälä 		return false;
421f3e30485SVille Syrjälä 
422f3e30485SVille Syrjälä 	return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
423f3e30485SVille Syrjälä }
424f3e30485SVille Syrjälä 
425c0e09200SDave Airlie /**
426f49e38ddSJani Nikula  * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
42714bb2c11STvrtko Ursulin  * @dev_priv: i915 device private
42801c66889SZhao Yakui  */
42991d14251STvrtko Ursulin static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
43001c66889SZhao Yakui {
431f3e30485SVille Syrjälä 	if (!i915_has_asle(dev_priv))
432f49e38ddSJani Nikula 		return;
433f49e38ddSJani Nikula 
43413321786SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
43501c66889SZhao Yakui 
436755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
437373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 4)
4383b6c42e8SDaniel Vetter 		i915_enable_pipestat(dev_priv, PIPE_A,
439755e9019SImre Deak 				     PIPE_LEGACY_BLC_EVENT_STATUS);
4401ec14ad3SChris Wilson 
44113321786SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
44201c66889SZhao Yakui }
44301c66889SZhao Yakui 
444e3689190SBen Widawsky /**
44574bb98baSLucas De Marchi  * ivb_parity_work - Workqueue called when a parity error interrupt
446e3689190SBen Widawsky  * occurred.
447e3689190SBen Widawsky  * @work: workqueue struct
448e3689190SBen Widawsky  *
449e3689190SBen Widawsky  * Doesn't actually do anything except notify userspace. As a consequence of
450e3689190SBen Widawsky  * this event, userspace should try to remap the bad rows since statistically
451e3689190SBen Widawsky  * it is likely the same row is more likely to go bad again.
452e3689190SBen Widawsky  */
45374bb98baSLucas De Marchi static void ivb_parity_work(struct work_struct *work)
454e3689190SBen Widawsky {
4552d1013ddSJani Nikula 	struct drm_i915_private *dev_priv =
456cefcff8fSJoonas Lahtinen 		container_of(work, typeof(*dev_priv), l3_parity.error_work);
4572cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
458e3689190SBen Widawsky 	u32 error_status, row, bank, subbank;
45935a85ac6SBen Widawsky 	char *parity_event[6];
460a9c287c9SJani Nikula 	u32 misccpctl;
461a9c287c9SJani Nikula 	u8 slice = 0;
462e3689190SBen Widawsky 
463e3689190SBen Widawsky 	/* We must turn off DOP level clock gating to access the L3 registers.
464e3689190SBen Widawsky 	 * In order to prevent a get/put style interface, acquire struct mutex
465e3689190SBen Widawsky 	 * any time we access those registers.
466e3689190SBen Widawsky 	 */
46791c8a326SChris Wilson 	mutex_lock(&dev_priv->drm.struct_mutex);
468e3689190SBen Widawsky 
46935a85ac6SBen Widawsky 	/* If we've screwed up tracking, just let the interrupt fire again */
47048a1b8d4SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice))
47135a85ac6SBen Widawsky 		goto out;
47235a85ac6SBen Widawsky 
473f7435467SAndrzej Hajda 	misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL,
474f7435467SAndrzej Hajda 				     GEN7_DOP_CLOCK_GATE_ENABLE, 0);
4752939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL);
476e3689190SBen Widawsky 
47735a85ac6SBen Widawsky 	while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) {
478f0f59a00SVille Syrjälä 		i915_reg_t reg;
47935a85ac6SBen Widawsky 
48035a85ac6SBen Widawsky 		slice--;
48148a1b8d4SPankaj Bharadiya 		if (drm_WARN_ON_ONCE(&dev_priv->drm,
48248a1b8d4SPankaj Bharadiya 				     slice >= NUM_L3_SLICES(dev_priv)))
48335a85ac6SBen Widawsky 			break;
48435a85ac6SBen Widawsky 
48535a85ac6SBen Widawsky 		dev_priv->l3_parity.which_slice &= ~(1<<slice);
48635a85ac6SBen Widawsky 
4876fa1c5f1SVille Syrjälä 		reg = GEN7_L3CDERRST1(slice);
48835a85ac6SBen Widawsky 
4892939eb06SJani Nikula 		error_status = intel_uncore_read(&dev_priv->uncore, reg);
490e3689190SBen Widawsky 		row = GEN7_PARITY_ERROR_ROW(error_status);
491e3689190SBen Widawsky 		bank = GEN7_PARITY_ERROR_BANK(error_status);
492e3689190SBen Widawsky 		subbank = GEN7_PARITY_ERROR_SUBBANK(error_status);
493e3689190SBen Widawsky 
4942939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE);
4952939eb06SJani Nikula 		intel_uncore_posting_read(&dev_priv->uncore, reg);
496e3689190SBen Widawsky 
497cce723edSBen Widawsky 		parity_event[0] = I915_L3_PARITY_UEVENT "=1";
498e3689190SBen Widawsky 		parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row);
499e3689190SBen Widawsky 		parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank);
500e3689190SBen Widawsky 		parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank);
50135a85ac6SBen Widawsky 		parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice);
50235a85ac6SBen Widawsky 		parity_event[5] = NULL;
503e3689190SBen Widawsky 
50491c8a326SChris Wilson 		kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj,
505e3689190SBen Widawsky 				   KOBJ_CHANGE, parity_event);
506e3689190SBen Widawsky 
507a10234fdSTvrtko Ursulin 		drm_dbg(&dev_priv->drm,
508a10234fdSTvrtko Ursulin 			"Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
50935a85ac6SBen Widawsky 			slice, row, bank, subbank);
510e3689190SBen Widawsky 
51135a85ac6SBen Widawsky 		kfree(parity_event[4]);
512e3689190SBen Widawsky 		kfree(parity_event[3]);
513e3689190SBen Widawsky 		kfree(parity_event[2]);
514e3689190SBen Widawsky 		kfree(parity_event[1]);
515e3689190SBen Widawsky 	}
516e3689190SBen Widawsky 
5172939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl);
51835a85ac6SBen Widawsky 
51935a85ac6SBen Widawsky out:
52048a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, dev_priv->l3_parity.which_slice);
52103d2c54dSMatt Roper 	spin_lock_irq(gt->irq_lock);
522cf1c97dcSAndi Shyti 	gen5_gt_enable_irq(gt, GT_PARITY_ERROR(dev_priv));
52303d2c54dSMatt Roper 	spin_unlock_irq(gt->irq_lock);
52435a85ac6SBen Widawsky 
52591c8a326SChris Wilson 	mutex_unlock(&dev_priv->drm.struct_mutex);
52635a85ac6SBen Widawsky }
52735a85ac6SBen Widawsky 
5288bf1e9f1SShuang He #if defined(CONFIG_DEBUG_FS)
52991d14251STvrtko Ursulin static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
53091d14251STvrtko Ursulin 					 enum pipe pipe,
531a9c287c9SJani Nikula 					 u32 crc0, u32 crc1,
532a9c287c9SJani Nikula 					 u32 crc2, u32 crc3,
533a9c287c9SJani Nikula 					 u32 crc4)
5348bf1e9f1SShuang He {
5357794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
53600535527SJani Nikula 	struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
5375cee6c45SVille Syrjälä 	u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 };
5385cee6c45SVille Syrjälä 
5395cee6c45SVille Syrjälä 	trace_intel_pipe_crc(crtc, crcs);
540b2c88f5bSDamien Lespiau 
541d538bbdfSDamien Lespiau 	spin_lock(&pipe_crc->lock);
5428c6b709dSTomeu Vizoso 	/*
5438c6b709dSTomeu Vizoso 	 * For some not yet identified reason, the first CRC is
5448c6b709dSTomeu Vizoso 	 * bonkers. So let's just wait for the next vblank and read
5458c6b709dSTomeu Vizoso 	 * out the buggy result.
5468c6b709dSTomeu Vizoso 	 *
547163e8aecSRodrigo Vivi 	 * On GEN8+ sometimes the second CRC is bonkers as well, so
5488c6b709dSTomeu Vizoso 	 * don't trust that one either.
5498c6b709dSTomeu Vizoso 	 */
550033b7a23SMaarten Lankhorst 	if (pipe_crc->skipped <= 0 ||
551373abf1aSMatt Roper 	    (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) {
5528c6b709dSTomeu Vizoso 		pipe_crc->skipped++;
5538c6b709dSTomeu Vizoso 		spin_unlock(&pipe_crc->lock);
5548c6b709dSTomeu Vizoso 		return;
5558c6b709dSTomeu Vizoso 	}
5568c6b709dSTomeu Vizoso 	spin_unlock(&pipe_crc->lock);
5576cc42152SMaarten Lankhorst 
558246ee524STomeu Vizoso 	drm_crtc_add_crc_entry(&crtc->base, true,
559ca814b25SDaniel Vetter 				drm_crtc_accurate_vblank_count(&crtc->base),
560246ee524STomeu Vizoso 				crcs);
5618c6b709dSTomeu Vizoso }
562277de95eSDaniel Vetter #else
563277de95eSDaniel Vetter static inline void
56491d14251STvrtko Ursulin display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
56591d14251STvrtko Ursulin 			     enum pipe pipe,
566a9c287c9SJani Nikula 			     u32 crc0, u32 crc1,
567a9c287c9SJani Nikula 			     u32 crc2, u32 crc3,
568a9c287c9SJani Nikula 			     u32 crc4) {}
569277de95eSDaniel Vetter #endif
570eba94eb9SDaniel Vetter 
5711288f9b0SKarthik B S static void flip_done_handler(struct drm_i915_private *i915,
5721288f9b0SKarthik B S 			      enum pipe pipe)
5731288f9b0SKarthik B S {
5747794b6deSJani Nikula 	struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
5751288f9b0SKarthik B S 	struct drm_crtc_state *crtc_state = crtc->base.state;
5761288f9b0SKarthik B S 	struct drm_pending_vblank_event *e = crtc_state->event;
5771288f9b0SKarthik B S 	struct drm_device *dev = &i915->drm;
5781288f9b0SKarthik B S 	unsigned long irqflags;
5791288f9b0SKarthik B S 
5801288f9b0SKarthik B S 	spin_lock_irqsave(&dev->event_lock, irqflags);
5811288f9b0SKarthik B S 
5821288f9b0SKarthik B S 	crtc_state->event = NULL;
5831288f9b0SKarthik B S 
5841288f9b0SKarthik B S 	drm_crtc_send_vblank_event(&crtc->base, e);
5851288f9b0SKarthik B S 
5861288f9b0SKarthik B S 	spin_unlock_irqrestore(&dev->event_lock, irqflags);
5871288f9b0SKarthik B S }
588277de95eSDaniel Vetter 
58991d14251STvrtko Ursulin static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
59091d14251STvrtko Ursulin 				     enum pipe pipe)
5915a69b89fSDaniel Vetter {
59291d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
5932939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
5945a69b89fSDaniel Vetter 				     0, 0, 0, 0);
5955a69b89fSDaniel Vetter }
5965a69b89fSDaniel Vetter 
59791d14251STvrtko Ursulin static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
59891d14251STvrtko Ursulin 				     enum pipe pipe)
599eba94eb9SDaniel Vetter {
60091d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
6012939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
6022939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)),
6032939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)),
6042939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)),
6052939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe)));
606eba94eb9SDaniel Vetter }
6075b3a856bSDaniel Vetter 
60891d14251STvrtko Ursulin static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
60991d14251STvrtko Ursulin 				      enum pipe pipe)
6105b3a856bSDaniel Vetter {
611a9c287c9SJani Nikula 	u32 res1, res2;
6120b5c5ed0SDaniel Vetter 
613373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 3)
6142939eb06SJani Nikula 		res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe));
6150b5c5ed0SDaniel Vetter 	else
6160b5c5ed0SDaniel Vetter 		res1 = 0;
6170b5c5ed0SDaniel Vetter 
618373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
6192939eb06SJani Nikula 		res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe));
6200b5c5ed0SDaniel Vetter 	else
6210b5c5ed0SDaniel Vetter 		res2 = 0;
6225b3a856bSDaniel Vetter 
62391d14251STvrtko Ursulin 	display_pipe_crc_irq_handler(dev_priv, pipe,
6242939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)),
6252939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)),
6262939eb06SJani Nikula 				     intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)),
6270b5c5ed0SDaniel Vetter 				     res1, res2);
6285b3a856bSDaniel Vetter }
6298bf1e9f1SShuang He 
63044d9241eSVille Syrjälä static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
63144d9241eSVille Syrjälä {
63244d9241eSVille Syrjälä 	enum pipe pipe;
63344d9241eSVille Syrjälä 
63444d9241eSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
6352939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe),
63644d9241eSVille Syrjälä 			   PIPESTAT_INT_STATUS_MASK |
63744d9241eSVille Syrjälä 			   PIPE_FIFO_UNDERRUN_STATUS);
63844d9241eSVille Syrjälä 
63944d9241eSVille Syrjälä 		dev_priv->pipestat_irq_mask[pipe] = 0;
64044d9241eSVille Syrjälä 	}
64144d9241eSVille Syrjälä }
64244d9241eSVille Syrjälä 
643eb64343cSVille Syrjälä static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
64491d14251STvrtko Ursulin 				  u32 iir, u32 pipe_stats[I915_MAX_PIPES])
6457e231dbeSJesse Barnes {
646d048a268SVille Syrjälä 	enum pipe pipe;
6477e231dbeSJesse Barnes 
64858ead0d7SImre Deak 	spin_lock(&dev_priv->irq_lock);
6491ca993d2SVille Syrjälä 
6501ca993d2SVille Syrjälä 	if (!dev_priv->display_irqs_enabled) {
6511ca993d2SVille Syrjälä 		spin_unlock(&dev_priv->irq_lock);
6521ca993d2SVille Syrjälä 		return;
6531ca993d2SVille Syrjälä 	}
6541ca993d2SVille Syrjälä 
655055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
656f0f59a00SVille Syrjälä 		i915_reg_t reg;
6576b12ca56SVille Syrjälä 		u32 status_mask, enable_mask, iir_bit = 0;
65891d181ddSImre Deak 
659bbb5eebfSDaniel Vetter 		/*
660bbb5eebfSDaniel Vetter 		 * PIPESTAT bits get signalled even when the interrupt is
661bbb5eebfSDaniel Vetter 		 * disabled with the mask bits, and some of the status bits do
662bbb5eebfSDaniel Vetter 		 * not generate interrupts at all (like the underrun bit). Hence
663bbb5eebfSDaniel Vetter 		 * we need to be careful that we only handle what we want to
664bbb5eebfSDaniel Vetter 		 * handle.
665bbb5eebfSDaniel Vetter 		 */
6660f239f4cSDaniel Vetter 
6670f239f4cSDaniel Vetter 		/* fifo underruns are filterered in the underrun handler. */
6686b12ca56SVille Syrjälä 		status_mask = PIPE_FIFO_UNDERRUN_STATUS;
669bbb5eebfSDaniel Vetter 
670bbb5eebfSDaniel Vetter 		switch (pipe) {
671d048a268SVille Syrjälä 		default:
672bbb5eebfSDaniel Vetter 		case PIPE_A:
673bbb5eebfSDaniel Vetter 			iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
674bbb5eebfSDaniel Vetter 			break;
675bbb5eebfSDaniel Vetter 		case PIPE_B:
676bbb5eebfSDaniel Vetter 			iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
677bbb5eebfSDaniel Vetter 			break;
6783278f67fSVille Syrjälä 		case PIPE_C:
6793278f67fSVille Syrjälä 			iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
6803278f67fSVille Syrjälä 			break;
681bbb5eebfSDaniel Vetter 		}
682bbb5eebfSDaniel Vetter 		if (iir & iir_bit)
6836b12ca56SVille Syrjälä 			status_mask |= dev_priv->pipestat_irq_mask[pipe];
684bbb5eebfSDaniel Vetter 
6856b12ca56SVille Syrjälä 		if (!status_mask)
68691d181ddSImre Deak 			continue;
68791d181ddSImre Deak 
68891d181ddSImre Deak 		reg = PIPESTAT(pipe);
6892939eb06SJani Nikula 		pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask;
6906b12ca56SVille Syrjälä 		enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
6917e231dbeSJesse Barnes 
6927e231dbeSJesse Barnes 		/*
6937e231dbeSJesse Barnes 		 * Clear the PIPE*STAT regs before the IIR
694132c27c9SVille Syrjälä 		 *
695132c27c9SVille Syrjälä 		 * Toggle the enable bits to make sure we get an
696132c27c9SVille Syrjälä 		 * edge in the ISR pipe event bit if we don't clear
697132c27c9SVille Syrjälä 		 * all the enabled status bits. Otherwise the edge
698132c27c9SVille Syrjälä 		 * triggered IIR on i965/g4x wouldn't notice that
699132c27c9SVille Syrjälä 		 * an interrupt is still pending.
7007e231dbeSJesse Barnes 		 */
701132c27c9SVille Syrjälä 		if (pipe_stats[pipe]) {
7022939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]);
7032939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, reg, enable_mask);
704132c27c9SVille Syrjälä 		}
7057e231dbeSJesse Barnes 	}
70658ead0d7SImre Deak 	spin_unlock(&dev_priv->irq_lock);
7072ecb8ca4SVille Syrjälä }
7082ecb8ca4SVille Syrjälä 
709eb64343cSVille Syrjälä static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv,
710eb64343cSVille Syrjälä 				      u16 iir, u32 pipe_stats[I915_MAX_PIPES])
711eb64343cSVille Syrjälä {
712eb64343cSVille Syrjälä 	enum pipe pipe;
713eb64343cSVille Syrjälä 
714eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
715eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
716aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
717eb64343cSVille Syrjälä 
718eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
719eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
720eb64343cSVille Syrjälä 
721eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
722eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
723eb64343cSVille Syrjälä 	}
724eb64343cSVille Syrjälä }
725eb64343cSVille Syrjälä 
726eb64343cSVille Syrjälä static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv,
727eb64343cSVille Syrjälä 				      u32 iir, u32 pipe_stats[I915_MAX_PIPES])
728eb64343cSVille Syrjälä {
729eb64343cSVille Syrjälä 	bool blc_event = false;
730eb64343cSVille Syrjälä 	enum pipe pipe;
731eb64343cSVille Syrjälä 
732eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
733eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
734aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
735eb64343cSVille Syrjälä 
736eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
737eb64343cSVille Syrjälä 			blc_event = true;
738eb64343cSVille Syrjälä 
739eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
740eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
741eb64343cSVille Syrjälä 
742eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
743eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
744eb64343cSVille Syrjälä 	}
745eb64343cSVille Syrjälä 
746eb64343cSVille Syrjälä 	if (blc_event || (iir & I915_ASLE_INTERRUPT))
747eb64343cSVille Syrjälä 		intel_opregion_asle_intr(dev_priv);
748eb64343cSVille Syrjälä }
749eb64343cSVille Syrjälä 
750eb64343cSVille Syrjälä static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv,
751eb64343cSVille Syrjälä 				      u32 iir, u32 pipe_stats[I915_MAX_PIPES])
752eb64343cSVille Syrjälä {
753eb64343cSVille Syrjälä 	bool blc_event = false;
754eb64343cSVille Syrjälä 	enum pipe pipe;
755eb64343cSVille Syrjälä 
756eb64343cSVille Syrjälä 	for_each_pipe(dev_priv, pipe) {
757eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
758aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
759eb64343cSVille Syrjälä 
760eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
761eb64343cSVille Syrjälä 			blc_event = true;
762eb64343cSVille Syrjälä 
763eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
764eb64343cSVille Syrjälä 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
765eb64343cSVille Syrjälä 
766eb64343cSVille Syrjälä 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
767eb64343cSVille Syrjälä 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
768eb64343cSVille Syrjälä 	}
769eb64343cSVille Syrjälä 
770eb64343cSVille Syrjälä 	if (blc_event || (iir & I915_ASLE_INTERRUPT))
771eb64343cSVille Syrjälä 		intel_opregion_asle_intr(dev_priv);
772eb64343cSVille Syrjälä 
773eb64343cSVille Syrjälä 	if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
774685282a3SJani Nikula 		intel_gmbus_irq_handler(dev_priv);
775eb64343cSVille Syrjälä }
776eb64343cSVille Syrjälä 
77791d14251STvrtko Ursulin static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
7782ecb8ca4SVille Syrjälä 					    u32 pipe_stats[I915_MAX_PIPES])
7792ecb8ca4SVille Syrjälä {
7802ecb8ca4SVille Syrjälä 	enum pipe pipe;
7817e231dbeSJesse Barnes 
782055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
783fd3a4024SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
784aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
7854356d586SDaniel Vetter 
7866ede6b06SVille Syrjälä 		if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
7876ede6b06SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
7886ede6b06SVille Syrjälä 
7894356d586SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
79091d14251STvrtko Ursulin 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
7912d9d2b0bSVille Syrjälä 
7921f7247c0SDaniel Vetter 		if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
7931f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
79431acc7f5SJesse Barnes 	}
79531acc7f5SJesse Barnes 
796c1874ed7SImre Deak 	if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
797685282a3SJani Nikula 		intel_gmbus_irq_handler(dev_priv);
798c1874ed7SImre Deak }
799c1874ed7SImre Deak 
800c1874ed7SImre Deak static irqreturn_t valleyview_irq_handler(int irq, void *arg)
801c1874ed7SImre Deak {
802b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
803c1874ed7SImre Deak 	irqreturn_t ret = IRQ_NONE;
804c1874ed7SImre Deak 
8052dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
8062dd2a883SImre Deak 		return IRQ_NONE;
8072dd2a883SImre Deak 
8081f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
8099102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
8101f814dacSImre Deak 
8111e1cace9SVille Syrjälä 	do {
8126e814800SVille Syrjälä 		u32 iir, gt_iir, pm_iir;
8132ecb8ca4SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
8141ae3c34cSVille Syrjälä 		u32 hotplug_status = 0;
815a5e485a9SVille Syrjälä 		u32 ier = 0;
8163ff60f89SOscar Mateo 
8172939eb06SJani Nikula 		gt_iir = intel_uncore_read(&dev_priv->uncore, GTIIR);
8182939eb06SJani Nikula 		pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR);
8192939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
820c1874ed7SImre Deak 
821c1874ed7SImre Deak 		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
8221e1cace9SVille Syrjälä 			break;
823c1874ed7SImre Deak 
824c1874ed7SImre Deak 		ret = IRQ_HANDLED;
825c1874ed7SImre Deak 
826a5e485a9SVille Syrjälä 		/*
827a5e485a9SVille Syrjälä 		 * Theory on interrupt generation, based on empirical evidence:
828a5e485a9SVille Syrjälä 		 *
829a5e485a9SVille Syrjälä 		 * x = ((VLV_IIR & VLV_IER) ||
830a5e485a9SVille Syrjälä 		 *      (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) &&
831a5e485a9SVille Syrjälä 		 *       (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE)));
832a5e485a9SVille Syrjälä 		 *
833a5e485a9SVille Syrjälä 		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
834a5e485a9SVille Syrjälä 		 * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to
835a5e485a9SVille Syrjälä 		 * guarantee the CPU interrupt will be raised again even if we
836a5e485a9SVille Syrjälä 		 * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR
837a5e485a9SVille Syrjälä 		 * bits this time around.
838a5e485a9SVille Syrjälä 		 */
8392939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0);
8408cee664dSAndrzej Hajda 		ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
8414a0a0202SVille Syrjälä 
8424a0a0202SVille Syrjälä 		if (gt_iir)
8432939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir);
8444a0a0202SVille Syrjälä 		if (pm_iir)
8452939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN6_PMIIR, pm_iir);
8464a0a0202SVille Syrjälä 
8477ce4d1f2SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
8481ae3c34cSVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
8497ce4d1f2SVille Syrjälä 
8503ff60f89SOscar Mateo 		/* Call regardless, as some status bits might not be
8513ff60f89SOscar Mateo 		 * signalled in iir */
852eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
8537ce4d1f2SVille Syrjälä 
854eef57324SJerome Anand 		if (iir & (I915_LPE_PIPE_A_INTERRUPT |
855eef57324SJerome Anand 			   I915_LPE_PIPE_B_INTERRUPT))
856eef57324SJerome Anand 			intel_lpe_audio_irq_handler(dev_priv);
857eef57324SJerome Anand 
8587ce4d1f2SVille Syrjälä 		/*
8597ce4d1f2SVille Syrjälä 		 * VLV_IIR is single buffered, and reflects the level
8607ce4d1f2SVille Syrjälä 		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
8617ce4d1f2SVille Syrjälä 		 */
8627ce4d1f2SVille Syrjälä 		if (iir)
8632939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
8644a0a0202SVille Syrjälä 
8652939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
8662939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
8671ae3c34cSVille Syrjälä 
86852894874SVille Syrjälä 		if (gt_iir)
8692cbc876dSMichał Winiarski 			gen6_gt_irq_handler(to_gt(dev_priv), gt_iir);
87052894874SVille Syrjälä 		if (pm_iir)
8712cbc876dSMichał Winiarski 			gen6_rps_irq_handler(&to_gt(dev_priv)->rps, pm_iir);
87252894874SVille Syrjälä 
8731ae3c34cSVille Syrjälä 		if (hotplug_status)
87491d14251STvrtko Ursulin 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
8752ecb8ca4SVille Syrjälä 
87691d14251STvrtko Ursulin 		valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
8771e1cace9SVille Syrjälä 	} while (0);
8787e231dbeSJesse Barnes 
8799c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
8809c6508b9SThomas Gleixner 
8819102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
8821f814dacSImre Deak 
8837e231dbeSJesse Barnes 	return ret;
8847e231dbeSJesse Barnes }
8857e231dbeSJesse Barnes 
88643f328d7SVille Syrjälä static irqreturn_t cherryview_irq_handler(int irq, void *arg)
88743f328d7SVille Syrjälä {
888b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
88943f328d7SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
89043f328d7SVille Syrjälä 
8912dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
8922dd2a883SImre Deak 		return IRQ_NONE;
8932dd2a883SImre Deak 
8941f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
8959102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
8961f814dacSImre Deak 
897579de73bSChris Wilson 	do {
8986e814800SVille Syrjälä 		u32 master_ctl, iir;
8992ecb8ca4SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
9001ae3c34cSVille Syrjälä 		u32 hotplug_status = 0;
901a5e485a9SVille Syrjälä 		u32 ier = 0;
902a5e485a9SVille Syrjälä 
9032939eb06SJani Nikula 		master_ctl = intel_uncore_read(&dev_priv->uncore, GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
9042939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, VLV_IIR);
9053278f67fSVille Syrjälä 
9063278f67fSVille Syrjälä 		if (master_ctl == 0 && iir == 0)
9078e5fd599SVille Syrjälä 			break;
90843f328d7SVille Syrjälä 
90927b6c122SOscar Mateo 		ret = IRQ_HANDLED;
91027b6c122SOscar Mateo 
911a5e485a9SVille Syrjälä 		/*
912a5e485a9SVille Syrjälä 		 * Theory on interrupt generation, based on empirical evidence:
913a5e485a9SVille Syrjälä 		 *
914a5e485a9SVille Syrjälä 		 * x = ((VLV_IIR & VLV_IER) ||
915a5e485a9SVille Syrjälä 		 *      ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) &&
916a5e485a9SVille Syrjälä 		 *       (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL)));
917a5e485a9SVille Syrjälä 		 *
918a5e485a9SVille Syrjälä 		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
919a5e485a9SVille Syrjälä 		 * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to
920a5e485a9SVille Syrjälä 		 * guarantee the CPU interrupt will be raised again even if we
921a5e485a9SVille Syrjälä 		 * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL
922a5e485a9SVille Syrjälä 		 * bits this time around.
923a5e485a9SVille Syrjälä 		 */
9242939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0);
9258cee664dSAndrzej Hajda 		ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
92643f328d7SVille Syrjälä 
9272cbc876dSMichał Winiarski 		gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
92827b6c122SOscar Mateo 
92927b6c122SOscar Mateo 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
9301ae3c34cSVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
93143f328d7SVille Syrjälä 
93227b6c122SOscar Mateo 		/* Call regardless, as some status bits might not be
93327b6c122SOscar Mateo 		 * signalled in iir */
934eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
93543f328d7SVille Syrjälä 
936eef57324SJerome Anand 		if (iir & (I915_LPE_PIPE_A_INTERRUPT |
937eef57324SJerome Anand 			   I915_LPE_PIPE_B_INTERRUPT |
938eef57324SJerome Anand 			   I915_LPE_PIPE_C_INTERRUPT))
939eef57324SJerome Anand 			intel_lpe_audio_irq_handler(dev_priv);
940eef57324SJerome Anand 
9417ce4d1f2SVille Syrjälä 		/*
9427ce4d1f2SVille Syrjälä 		 * VLV_IIR is single buffered, and reflects the level
9437ce4d1f2SVille Syrjälä 		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
9447ce4d1f2SVille Syrjälä 		 */
9457ce4d1f2SVille Syrjälä 		if (iir)
9462939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, VLV_IIR, iir);
9477ce4d1f2SVille Syrjälä 
9482939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, VLV_IER, ier);
9492939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
9501ae3c34cSVille Syrjälä 
9511ae3c34cSVille Syrjälä 		if (hotplug_status)
95291d14251STvrtko Ursulin 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
9532ecb8ca4SVille Syrjälä 
95491d14251STvrtko Ursulin 		valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
955579de73bSChris Wilson 	} while (0);
9563278f67fSVille Syrjälä 
9579c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
9589c6508b9SThomas Gleixner 
9599102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
9601f814dacSImre Deak 
96143f328d7SVille Syrjälä 	return ret;
96243f328d7SVille Syrjälä }
96343f328d7SVille Syrjälä 
96491d14251STvrtko Ursulin static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
96540e56410SVille Syrjälä {
966d048a268SVille Syrjälä 	enum pipe pipe;
96740e56410SVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
96840e56410SVille Syrjälä 
9690398993bSVille Syrjälä 	ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
97040e56410SVille Syrjälä 
971cfc33bf7SVille Syrjälä 	if (pch_iir & SDE_AUDIO_POWER_MASK) {
972cfc33bf7SVille Syrjälä 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
973776ad806SJesse Barnes 			       SDE_AUDIO_POWER_SHIFT);
97400376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n",
975cfc33bf7SVille Syrjälä 			port_name(port));
976cfc33bf7SVille Syrjälä 	}
977776ad806SJesse Barnes 
978ce99c256SDaniel Vetter 	if (pch_iir & SDE_AUX_MASK)
979685282a3SJani Nikula 		intel_dp_aux_irq_handler(dev_priv);
980ce99c256SDaniel Vetter 
981776ad806SJesse Barnes 	if (pch_iir & SDE_GMBUS)
982685282a3SJani Nikula 		intel_gmbus_irq_handler(dev_priv);
983776ad806SJesse Barnes 
984776ad806SJesse Barnes 	if (pch_iir & SDE_AUDIO_HDCP_MASK)
98500376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n");
986776ad806SJesse Barnes 
987776ad806SJesse Barnes 	if (pch_iir & SDE_AUDIO_TRANS_MASK)
98800376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n");
989776ad806SJesse Barnes 
990776ad806SJesse Barnes 	if (pch_iir & SDE_POISON)
99100376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "PCH poison interrupt\n");
992776ad806SJesse Barnes 
993b8b65ccdSAnshuman Gupta 	if (pch_iir & SDE_FDI_MASK) {
994055e393fSDamien Lespiau 		for_each_pipe(dev_priv, pipe)
99500376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm, "  pipe %c FDI IIR: 0x%08x\n",
9969db4a9c7SJesse Barnes 				pipe_name(pipe),
9972939eb06SJani Nikula 				intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
998b8b65ccdSAnshuman Gupta 	}
999776ad806SJesse Barnes 
1000776ad806SJesse Barnes 	if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
100100376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n");
1002776ad806SJesse Barnes 
1003776ad806SJesse Barnes 	if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
100400376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm,
100500376ccfSWambui Karuga 			"PCH transcoder CRC error interrupt\n");
1006776ad806SJesse Barnes 
1007776ad806SJesse Barnes 	if (pch_iir & SDE_TRANSA_FIFO_UNDER)
1008a2196033SMatthias Kaehlcke 		intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A);
10098664281bSPaulo Zanoni 
10108664281bSPaulo Zanoni 	if (pch_iir & SDE_TRANSB_FIFO_UNDER)
1011a2196033SMatthias Kaehlcke 		intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B);
10128664281bSPaulo Zanoni }
10138664281bSPaulo Zanoni 
101491d14251STvrtko Ursulin static void ivb_err_int_handler(struct drm_i915_private *dev_priv)
10158664281bSPaulo Zanoni {
10162939eb06SJani Nikula 	u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT);
10175a69b89fSDaniel Vetter 	enum pipe pipe;
10188664281bSPaulo Zanoni 
1019de032bf4SPaulo Zanoni 	if (err_int & ERR_INT_POISON)
102000376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Poison interrupt\n");
1021de032bf4SPaulo Zanoni 
1022055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
10231f7247c0SDaniel Vetter 		if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
10241f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
10258664281bSPaulo Zanoni 
10265a69b89fSDaniel Vetter 		if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
102791d14251STvrtko Ursulin 			if (IS_IVYBRIDGE(dev_priv))
102891d14251STvrtko Ursulin 				ivb_pipe_crc_irq_handler(dev_priv, pipe);
10295a69b89fSDaniel Vetter 			else
103091d14251STvrtko Ursulin 				hsw_pipe_crc_irq_handler(dev_priv, pipe);
10315a69b89fSDaniel Vetter 		}
10325a69b89fSDaniel Vetter 	}
10338bf1e9f1SShuang He 
10342939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int);
10358664281bSPaulo Zanoni }
10368664281bSPaulo Zanoni 
103791d14251STvrtko Ursulin static void cpt_serr_int_handler(struct drm_i915_private *dev_priv)
10388664281bSPaulo Zanoni {
10392939eb06SJani Nikula 	u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT);
104045c1cd87SMika Kahola 	enum pipe pipe;
10418664281bSPaulo Zanoni 
1042de032bf4SPaulo Zanoni 	if (serr_int & SERR_INT_POISON)
104300376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "PCH poison interrupt\n");
1044de032bf4SPaulo Zanoni 
104545c1cd87SMika Kahola 	for_each_pipe(dev_priv, pipe)
104645c1cd87SMika Kahola 		if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe))
104745c1cd87SMika Kahola 			intel_pch_fifo_underrun_irq_handler(dev_priv, pipe);
10488664281bSPaulo Zanoni 
10492939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int);
1050776ad806SJesse Barnes }
1051776ad806SJesse Barnes 
105291d14251STvrtko Ursulin static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
105323e81d69SAdam Jackson {
1054d048a268SVille Syrjälä 	enum pipe pipe;
10556dbf30ceSVille Syrjälä 	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
1056aaf5ec2eSSonika Jindal 
10570398993bSVille Syrjälä 	ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
105891d131d2SDaniel Vetter 
1059cfc33bf7SVille Syrjälä 	if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
1060cfc33bf7SVille Syrjälä 		int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
106123e81d69SAdam Jackson 			       SDE_AUDIO_POWER_SHIFT_CPT);
106200376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n",
1063cfc33bf7SVille Syrjälä 			port_name(port));
1064cfc33bf7SVille Syrjälä 	}
106523e81d69SAdam Jackson 
106623e81d69SAdam Jackson 	if (pch_iir & SDE_AUX_MASK_CPT)
1067685282a3SJani Nikula 		intel_dp_aux_irq_handler(dev_priv);
106823e81d69SAdam Jackson 
106923e81d69SAdam Jackson 	if (pch_iir & SDE_GMBUS_CPT)
1070685282a3SJani Nikula 		intel_gmbus_irq_handler(dev_priv);
107123e81d69SAdam Jackson 
107223e81d69SAdam Jackson 	if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
107300376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n");
107423e81d69SAdam Jackson 
107523e81d69SAdam Jackson 	if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
107600376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n");
107723e81d69SAdam Jackson 
1078b8b65ccdSAnshuman Gupta 	if (pch_iir & SDE_FDI_MASK_CPT) {
1079055e393fSDamien Lespiau 		for_each_pipe(dev_priv, pipe)
108000376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm, "  pipe %c FDI IIR: 0x%08x\n",
108123e81d69SAdam Jackson 				pipe_name(pipe),
10822939eb06SJani Nikula 				intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
1083b8b65ccdSAnshuman Gupta 	}
10848664281bSPaulo Zanoni 
10858664281bSPaulo Zanoni 	if (pch_iir & SDE_ERROR_CPT)
108691d14251STvrtko Ursulin 		cpt_serr_int_handler(dev_priv);
108723e81d69SAdam Jackson }
108823e81d69SAdam Jackson 
108991d14251STvrtko Ursulin static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
109091d14251STvrtko Ursulin 				    u32 de_iir)
109140e56410SVille Syrjälä {
109240e56410SVille Syrjälä 	enum pipe pipe;
109340e56410SVille Syrjälä 	u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
109440e56410SVille Syrjälä 
109540e56410SVille Syrjälä 	if (hotplug_trigger)
10960398993bSVille Syrjälä 		ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
109740e56410SVille Syrjälä 
1098c008bc6eSPaulo Zanoni 	if (de_iir & DE_AUX_CHANNEL_A)
1099685282a3SJani Nikula 		intel_dp_aux_irq_handler(dev_priv);
1100c008bc6eSPaulo Zanoni 
1101c008bc6eSPaulo Zanoni 	if (de_iir & DE_GSE)
110291d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
1103c008bc6eSPaulo Zanoni 
1104c008bc6eSPaulo Zanoni 	if (de_iir & DE_POISON)
110500376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Poison interrupt\n");
1106c008bc6eSPaulo Zanoni 
1107055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1108fd3a4024SDaniel Vetter 		if (de_iir & DE_PIPE_VBLANK(pipe))
1109aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1110c008bc6eSPaulo Zanoni 
11114bb18054SVille Syrjälä 		if (de_iir & DE_PLANE_FLIP_DONE(pipe))
11124bb18054SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
11134bb18054SVille Syrjälä 
111440da17c2SDaniel Vetter 		if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
11151f7247c0SDaniel Vetter 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
1116c008bc6eSPaulo Zanoni 
111740da17c2SDaniel Vetter 		if (de_iir & DE_PIPE_CRC_DONE(pipe))
111891d14251STvrtko Ursulin 			i9xx_pipe_crc_irq_handler(dev_priv, pipe);
1119c008bc6eSPaulo Zanoni 	}
1120c008bc6eSPaulo Zanoni 
1121c008bc6eSPaulo Zanoni 	/* check event from PCH */
1122c008bc6eSPaulo Zanoni 	if (de_iir & DE_PCH_EVENT) {
11232939eb06SJani Nikula 		u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
1124c008bc6eSPaulo Zanoni 
112591d14251STvrtko Ursulin 		if (HAS_PCH_CPT(dev_priv))
112691d14251STvrtko Ursulin 			cpt_irq_handler(dev_priv, pch_iir);
1127c008bc6eSPaulo Zanoni 		else
112891d14251STvrtko Ursulin 			ibx_irq_handler(dev_priv, pch_iir);
1129c008bc6eSPaulo Zanoni 
1130c008bc6eSPaulo Zanoni 		/* should clear PCH hotplug event before clear CPU irq */
11312939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
1132c008bc6eSPaulo Zanoni 	}
1133c008bc6eSPaulo Zanoni 
113493e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT)
11352cbc876dSMichał Winiarski 		gen5_rps_irq_handler(&to_gt(dev_priv)->rps);
1136c008bc6eSPaulo Zanoni }
1137c008bc6eSPaulo Zanoni 
113891d14251STvrtko Ursulin static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
113991d14251STvrtko Ursulin 				    u32 de_iir)
11409719fb98SPaulo Zanoni {
114107d27e20SDamien Lespiau 	enum pipe pipe;
114223bb4cb5SVille Syrjälä 	u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
114323bb4cb5SVille Syrjälä 
114440e56410SVille Syrjälä 	if (hotplug_trigger)
11450398993bSVille Syrjälä 		ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
11469719fb98SPaulo Zanoni 
11479719fb98SPaulo Zanoni 	if (de_iir & DE_ERR_INT_IVB)
114891d14251STvrtko Ursulin 		ivb_err_int_handler(dev_priv);
11499719fb98SPaulo Zanoni 
11509719fb98SPaulo Zanoni 	if (de_iir & DE_AUX_CHANNEL_A_IVB)
1151685282a3SJani Nikula 		intel_dp_aux_irq_handler(dev_priv);
11529719fb98SPaulo Zanoni 
11539719fb98SPaulo Zanoni 	if (de_iir & DE_GSE_IVB)
115491d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
11559719fb98SPaulo Zanoni 
1156055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
115733ef04faSVille Syrjälä 		if (de_iir & DE_PIPE_VBLANK_IVB(pipe))
1158aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
11592a636e24SVille Syrjälä 
11602a636e24SVille Syrjälä 		if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
11612a636e24SVille Syrjälä 			flip_done_handler(dev_priv, pipe);
11629719fb98SPaulo Zanoni 	}
11639719fb98SPaulo Zanoni 
11649719fb98SPaulo Zanoni 	/* check event from PCH */
116591d14251STvrtko Ursulin 	if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
11662939eb06SJani Nikula 		u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
11679719fb98SPaulo Zanoni 
116891d14251STvrtko Ursulin 		cpt_irq_handler(dev_priv, pch_iir);
11699719fb98SPaulo Zanoni 
11709719fb98SPaulo Zanoni 		/* clear PCH hotplug event before clear CPU irq */
11712939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
11729719fb98SPaulo Zanoni 	}
11739719fb98SPaulo Zanoni }
11749719fb98SPaulo Zanoni 
117572c90f62SOscar Mateo /*
117672c90f62SOscar Mateo  * To handle irqs with the minimum potential races with fresh interrupts, we:
117772c90f62SOscar Mateo  * 1 - Disable Master Interrupt Control.
117872c90f62SOscar Mateo  * 2 - Find the source(s) of the interrupt.
117972c90f62SOscar Mateo  * 3 - Clear the Interrupt Identity bits (IIR).
118072c90f62SOscar Mateo  * 4 - Process the interrupt(s) that had bits set in the IIRs.
118172c90f62SOscar Mateo  * 5 - Re-enable Master Interrupt Control.
118272c90f62SOscar Mateo  */
11839eae5e27SLucas De Marchi static irqreturn_t ilk_irq_handler(int irq, void *arg)
1184b1f14ad0SJesse Barnes {
1185c48a798aSChris Wilson 	struct drm_i915_private *i915 = arg;
1186c48a798aSChris Wilson 	void __iomem * const regs = i915->uncore.regs;
1187f1af8fc1SPaulo Zanoni 	u32 de_iir, gt_iir, de_ier, sde_ier = 0;
11880e43406bSChris Wilson 	irqreturn_t ret = IRQ_NONE;
1189b1f14ad0SJesse Barnes 
1190c48a798aSChris Wilson 	if (unlikely(!intel_irqs_enabled(i915)))
11912dd2a883SImre Deak 		return IRQ_NONE;
11922dd2a883SImre Deak 
11931f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1194c48a798aSChris Wilson 	disable_rpm_wakeref_asserts(&i915->runtime_pm);
11951f814dacSImre Deak 
1196b1f14ad0SJesse Barnes 	/* disable master interrupt before clearing iir  */
1197c48a798aSChris Wilson 	de_ier = raw_reg_read(regs, DEIER);
1198c48a798aSChris Wilson 	raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
11990e43406bSChris Wilson 
120044498aeaSPaulo Zanoni 	/* Disable south interrupts. We'll only write to SDEIIR once, so further
120144498aeaSPaulo Zanoni 	 * interrupts will will be stored on its back queue, and then we'll be
120244498aeaSPaulo Zanoni 	 * able to process them after we restore SDEIER (as soon as we restore
120344498aeaSPaulo Zanoni 	 * it, we'll get an interrupt if SDEIIR still has something to process
120444498aeaSPaulo Zanoni 	 * due to its back queue). */
1205c48a798aSChris Wilson 	if (!HAS_PCH_NOP(i915)) {
1206c48a798aSChris Wilson 		sde_ier = raw_reg_read(regs, SDEIER);
1207c48a798aSChris Wilson 		raw_reg_write(regs, SDEIER, 0);
1208ab5c608bSBen Widawsky 	}
120944498aeaSPaulo Zanoni 
121072c90f62SOscar Mateo 	/* Find, clear, then process each source of interrupt */
121172c90f62SOscar Mateo 
1212c48a798aSChris Wilson 	gt_iir = raw_reg_read(regs, GTIIR);
12130e43406bSChris Wilson 	if (gt_iir) {
1214c48a798aSChris Wilson 		raw_reg_write(regs, GTIIR, gt_iir);
1215651e7d48SLucas De Marchi 		if (GRAPHICS_VER(i915) >= 6)
12162cbc876dSMichał Winiarski 			gen6_gt_irq_handler(to_gt(i915), gt_iir);
1217d8fc8a47SPaulo Zanoni 		else
12182cbc876dSMichał Winiarski 			gen5_gt_irq_handler(to_gt(i915), gt_iir);
1219c48a798aSChris Wilson 		ret = IRQ_HANDLED;
12200e43406bSChris Wilson 	}
1221b1f14ad0SJesse Barnes 
1222c48a798aSChris Wilson 	de_iir = raw_reg_read(regs, DEIIR);
12230e43406bSChris Wilson 	if (de_iir) {
1224c48a798aSChris Wilson 		raw_reg_write(regs, DEIIR, de_iir);
1225373abf1aSMatt Roper 		if (DISPLAY_VER(i915) >= 7)
1226c48a798aSChris Wilson 			ivb_display_irq_handler(i915, de_iir);
1227f1af8fc1SPaulo Zanoni 		else
1228c48a798aSChris Wilson 			ilk_display_irq_handler(i915, de_iir);
12290e43406bSChris Wilson 		ret = IRQ_HANDLED;
1230c48a798aSChris Wilson 	}
1231c48a798aSChris Wilson 
1232651e7d48SLucas De Marchi 	if (GRAPHICS_VER(i915) >= 6) {
1233c48a798aSChris Wilson 		u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR);
1234c48a798aSChris Wilson 		if (pm_iir) {
1235c48a798aSChris Wilson 			raw_reg_write(regs, GEN6_PMIIR, pm_iir);
12362cbc876dSMichał Winiarski 			gen6_rps_irq_handler(&to_gt(i915)->rps, pm_iir);
1237c48a798aSChris Wilson 			ret = IRQ_HANDLED;
12380e43406bSChris Wilson 		}
1239f1af8fc1SPaulo Zanoni 	}
1240b1f14ad0SJesse Barnes 
1241c48a798aSChris Wilson 	raw_reg_write(regs, DEIER, de_ier);
1242c48a798aSChris Wilson 	if (sde_ier)
1243c48a798aSChris Wilson 		raw_reg_write(regs, SDEIER, sde_ier);
1244b1f14ad0SJesse Barnes 
12459c6508b9SThomas Gleixner 	pmu_irq_stats(i915, ret);
12469c6508b9SThomas Gleixner 
12471f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1248c48a798aSChris Wilson 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
12491f814dacSImre Deak 
1250b1f14ad0SJesse Barnes 	return ret;
1251b1f14ad0SJesse Barnes }
1252b1f14ad0SJesse Barnes 
12539d17210fSLucas De Marchi static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
12549d17210fSLucas De Marchi {
125555523360SLucas De Marchi 	u32 mask;
12569d17210fSLucas De Marchi 
1257c0f3faafSGustavo Sousa 	if (DISPLAY_VER(dev_priv) >= 14)
1258c0f3faafSGustavo Sousa 		return TGL_DE_PORT_AUX_DDIA |
1259c0f3faafSGustavo Sousa 			TGL_DE_PORT_AUX_DDIB;
1260c0f3faafSGustavo Sousa 	else if (DISPLAY_VER(dev_priv) >= 13)
126120fe778fSMatt Roper 		return TGL_DE_PORT_AUX_DDIA |
126220fe778fSMatt Roper 			TGL_DE_PORT_AUX_DDIB |
126320fe778fSMatt Roper 			TGL_DE_PORT_AUX_DDIC |
126420fe778fSMatt Roper 			XELPD_DE_PORT_AUX_DDID |
126520fe778fSMatt Roper 			XELPD_DE_PORT_AUX_DDIE |
126620fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC1 |
126720fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC2 |
126820fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC3 |
126920fe778fSMatt Roper 			TGL_DE_PORT_AUX_USBC4;
127020fe778fSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
127155523360SLucas De Marchi 		return TGL_DE_PORT_AUX_DDIA |
127255523360SLucas De Marchi 			TGL_DE_PORT_AUX_DDIB |
1273e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_DDIC |
1274e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC1 |
1275e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC2 |
1276e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC3 |
1277e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC4 |
1278e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC5 |
1279e5df52dcSMatt Roper 			TGL_DE_PORT_AUX_USBC6;
1280e5df52dcSMatt Roper 
128155523360SLucas De Marchi 
128255523360SLucas De Marchi 	mask = GEN8_AUX_CHANNEL_A;
1283373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 9)
12849d17210fSLucas De Marchi 		mask |= GEN9_AUX_CHANNEL_B |
12859d17210fSLucas De Marchi 			GEN9_AUX_CHANNEL_C |
12869d17210fSLucas De Marchi 			GEN9_AUX_CHANNEL_D;
12879d17210fSLucas De Marchi 
1288938a8a9aSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 11) {
1289938a8a9aSLucas De Marchi 		mask |= ICL_AUX_CHANNEL_F;
129055523360SLucas De Marchi 		mask |= ICL_AUX_CHANNEL_E;
1291938a8a9aSLucas De Marchi 	}
12929d17210fSLucas De Marchi 
12939d17210fSLucas De Marchi 	return mask;
12949d17210fSLucas De Marchi }
12959d17210fSLucas De Marchi 
12965270130dSVille Syrjälä static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
12975270130dSVille Syrjälä {
12981649a4ccSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
129999e2d8bcSMatt Roper 		return RKL_DE_PIPE_IRQ_FAULT_ERRORS;
1300373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11)
1301d506a65dSMatt Roper 		return GEN11_DE_PIPE_IRQ_FAULT_ERRORS;
1302373abf1aSMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 9)
13035270130dSVille Syrjälä 		return GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
13045270130dSVille Syrjälä 	else
13055270130dSVille Syrjälä 		return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
13065270130dSVille Syrjälä }
13075270130dSVille Syrjälä 
130846c63d24SJosé Roberto de Souza static void
130946c63d24SJosé Roberto de Souza gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
1310abd58f01SBen Widawsky {
1311e04f7eceSVille Syrjälä 	bool found = false;
1312e04f7eceSVille Syrjälä 
1313e04f7eceSVille Syrjälä 	if (iir & GEN8_DE_MISC_GSE) {
131491d14251STvrtko Ursulin 		intel_opregion_asle_intr(dev_priv);
1315e04f7eceSVille Syrjälä 		found = true;
1316e04f7eceSVille Syrjälä 	}
1317e04f7eceSVille Syrjälä 
1318e04f7eceSVille Syrjälä 	if (iir & GEN8_DE_EDP_PSR) {
1319b64d6c51SGwan-gyeong Mun 		struct intel_encoder *encoder;
13208241cfbeSJosé Roberto de Souza 		u32 psr_iir;
13218241cfbeSJosé Roberto de Souza 		i915_reg_t iir_reg;
13228241cfbeSJosé Roberto de Souza 
1323a22af61dSJosé Roberto de Souza 		for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
1324b64d6c51SGwan-gyeong Mun 			struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1325b64d6c51SGwan-gyeong Mun 
1326373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) >= 12)
1327b64d6c51SGwan-gyeong Mun 				iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder);
13288241cfbeSJosé Roberto de Souza 			else
13298241cfbeSJosé Roberto de Souza 				iir_reg = EDP_PSR_IIR;
13308241cfbeSJosé Roberto de Souza 
13318cee664dSAndrzej Hajda 			psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0);
13328241cfbeSJosé Roberto de Souza 
13338241cfbeSJosé Roberto de Souza 			if (psr_iir)
13348241cfbeSJosé Roberto de Souza 				found = true;
133554fd3149SDhinakaran Pandiyan 
1336b64d6c51SGwan-gyeong Mun 			intel_psr_irq_handler(intel_dp, psr_iir);
1337b64d6c51SGwan-gyeong Mun 
1338b64d6c51SGwan-gyeong Mun 			/* prior GEN12 only have one EDP PSR */
1339373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) < 12)
1340b64d6c51SGwan-gyeong Mun 				break;
1341b64d6c51SGwan-gyeong Mun 		}
1342e04f7eceSVille Syrjälä 	}
1343e04f7eceSVille Syrjälä 
1344e04f7eceSVille Syrjälä 	if (!found)
134500376ccfSWambui Karuga 		drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n");
1346abd58f01SBen Widawsky }
134746c63d24SJosé Roberto de Souza 
134800acb329SVandita Kulkarni static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv,
134900acb329SVandita Kulkarni 					   u32 te_trigger)
135000acb329SVandita Kulkarni {
135100acb329SVandita Kulkarni 	enum pipe pipe = INVALID_PIPE;
135200acb329SVandita Kulkarni 	enum transcoder dsi_trans;
135300acb329SVandita Kulkarni 	enum port port;
135400acb329SVandita Kulkarni 	u32 val, tmp;
135500acb329SVandita Kulkarni 
135600acb329SVandita Kulkarni 	/*
135700acb329SVandita Kulkarni 	 * Incase of dual link, TE comes from DSI_1
135800acb329SVandita Kulkarni 	 * this is to check if dual link is enabled
135900acb329SVandita Kulkarni 	 */
13602939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0));
136100acb329SVandita Kulkarni 	val &= PORT_SYNC_MODE_ENABLE;
136200acb329SVandita Kulkarni 
136300acb329SVandita Kulkarni 	/*
136400acb329SVandita Kulkarni 	 * if dual link is enabled, then read DSI_0
136500acb329SVandita Kulkarni 	 * transcoder registers
136600acb329SVandita Kulkarni 	 */
136700acb329SVandita Kulkarni 	port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ?
136800acb329SVandita Kulkarni 						  PORT_A : PORT_B;
136900acb329SVandita Kulkarni 	dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1;
137000acb329SVandita Kulkarni 
137100acb329SVandita Kulkarni 	/* Check if DSI configured in command mode */
13722939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans));
137300acb329SVandita Kulkarni 	val = val & OP_MODE_MASK;
137400acb329SVandita Kulkarni 
137500acb329SVandita Kulkarni 	if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) {
137600acb329SVandita Kulkarni 		drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n");
137700acb329SVandita Kulkarni 		return;
137800acb329SVandita Kulkarni 	}
137900acb329SVandita Kulkarni 
138000acb329SVandita Kulkarni 	/* Get PIPE for handling VBLANK event */
13812939eb06SJani Nikula 	val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans));
138200acb329SVandita Kulkarni 	switch (val & TRANS_DDI_EDP_INPUT_MASK) {
138300acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_A_ON:
138400acb329SVandita Kulkarni 		pipe = PIPE_A;
138500acb329SVandita Kulkarni 		break;
138600acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_B_ONOFF:
138700acb329SVandita Kulkarni 		pipe = PIPE_B;
138800acb329SVandita Kulkarni 		break;
138900acb329SVandita Kulkarni 	case TRANS_DDI_EDP_INPUT_C_ONOFF:
139000acb329SVandita Kulkarni 		pipe = PIPE_C;
139100acb329SVandita Kulkarni 		break;
139200acb329SVandita Kulkarni 	default:
139300acb329SVandita Kulkarni 		drm_err(&dev_priv->drm, "Invalid PIPE\n");
139400acb329SVandita Kulkarni 		return;
139500acb329SVandita Kulkarni 	}
139600acb329SVandita Kulkarni 
139700acb329SVandita Kulkarni 	intel_handle_vblank(dev_priv, pipe);
139800acb329SVandita Kulkarni 
139900acb329SVandita Kulkarni 	/* clear TE in dsi IIR */
140000acb329SVandita Kulkarni 	port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A;
14018cee664dSAndrzej Hajda 	tmp = intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
140200acb329SVandita Kulkarni }
140300acb329SVandita Kulkarni 
1404cda195f1SVille Syrjälä static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915)
1405cda195f1SVille Syrjälä {
1406373abf1aSMatt Roper 	if (DISPLAY_VER(i915) >= 9)
1407cda195f1SVille Syrjälä 		return GEN9_PIPE_PLANE1_FLIP_DONE;
1408cda195f1SVille Syrjälä 	else
1409cda195f1SVille Syrjälä 		return GEN8_PIPE_PRIMARY_FLIP_DONE;
1410cda195f1SVille Syrjälä }
1411cda195f1SVille Syrjälä 
14128bcc0840SMatt Roper u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv)
14138bcc0840SMatt Roper {
14148bcc0840SMatt Roper 	u32 mask = GEN8_PIPE_FIFO_UNDERRUN;
14158bcc0840SMatt Roper 
14168bcc0840SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
14178bcc0840SMatt Roper 		mask |= XELPD_PIPE_SOFT_UNDERRUN |
14188bcc0840SMatt Roper 			XELPD_PIPE_HARD_UNDERRUN;
14198bcc0840SMatt Roper 
14208bcc0840SMatt Roper 	return mask;
14218bcc0840SMatt Roper }
14228bcc0840SMatt Roper 
1423babde06dSMika Kahola static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir)
1424babde06dSMika Kahola {
1425babde06dSMika Kahola 	u32 pica_ier = 0;
1426babde06dSMika Kahola 
1427babde06dSMika Kahola 	*pica_iir = 0;
1428babde06dSMika Kahola 	*pch_iir = intel_de_read(i915, SDEIIR);
1429babde06dSMika Kahola 	if (!*pch_iir)
1430babde06dSMika Kahola 		return;
1431babde06dSMika Kahola 
1432babde06dSMika Kahola 	/**
1433babde06dSMika Kahola 	 * PICA IER must be disabled/re-enabled around clearing PICA IIR and
1434babde06dSMika Kahola 	 * SDEIIR, to avoid losing PICA IRQs and to ensure that such IRQs set
1435babde06dSMika Kahola 	 * their flags both in the PICA and SDE IIR.
1436babde06dSMika Kahola 	 */
1437babde06dSMika Kahola 	if (*pch_iir & SDE_PICAINTERRUPT) {
1438babde06dSMika Kahola 		drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTP);
1439babde06dSMika Kahola 
1440babde06dSMika Kahola 		pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0);
1441babde06dSMika Kahola 		*pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR);
1442babde06dSMika Kahola 		intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir);
1443babde06dSMika Kahola 	}
1444babde06dSMika Kahola 
1445babde06dSMika Kahola 	intel_de_write(i915, SDEIIR, *pch_iir);
1446babde06dSMika Kahola 
1447babde06dSMika Kahola 	if (pica_ier)
1448babde06dSMika Kahola 		intel_de_write(i915, PICAINTERRUPT_IER, pica_ier);
1449babde06dSMika Kahola }
1450babde06dSMika Kahola 
145108d8f430SJani Nikula static void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
145246c63d24SJosé Roberto de Souza {
145346c63d24SJosé Roberto de Souza 	u32 iir;
145446c63d24SJosé Roberto de Souza 	enum pipe pipe;
145546c63d24SJosé Roberto de Souza 
1456a844cfbeSJosé Roberto de Souza 	drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv));
1457a844cfbeSJosé Roberto de Souza 
145846c63d24SJosé Roberto de Souza 	if (master_ctl & GEN8_DE_MISC_IRQ) {
14592939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR);
146046c63d24SJosé Roberto de Souza 		if (iir) {
14612939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir);
146246c63d24SJosé Roberto de Souza 			gen8_de_misc_irq_handler(dev_priv, iir);
146346c63d24SJosé Roberto de Souza 		} else {
14649a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
146500376ccfSWambui Karuga 					    "The master control interrupt lied (DE MISC)!\n");
1466abd58f01SBen Widawsky 		}
146746c63d24SJosé Roberto de Souza 	}
1468abd58f01SBen Widawsky 
1469373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
14702939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR);
1471121e758eSDhinakaran Pandiyan 		if (iir) {
14722939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir);
1473121e758eSDhinakaran Pandiyan 			gen11_hpd_irq_handler(dev_priv, iir);
1474121e758eSDhinakaran Pandiyan 		} else {
14759a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
147600376ccfSWambui Karuga 					    "The master control interrupt lied, (DE HPD)!\n");
1477121e758eSDhinakaran Pandiyan 		}
1478121e758eSDhinakaran Pandiyan 	}
1479121e758eSDhinakaran Pandiyan 
14806d766f02SDaniel Vetter 	if (master_ctl & GEN8_DE_PORT_IRQ) {
14812939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR);
1482e32192e1STvrtko Ursulin 		if (iir) {
1483d04a492dSShashank Sharma 			bool found = false;
1484cebd87a0SVille Syrjälä 
14852939eb06SJani Nikula 			intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir);
148688e04703SJesse Barnes 
14879d17210fSLucas De Marchi 			if (iir & gen8_de_port_aux_mask(dev_priv)) {
1488685282a3SJani Nikula 				intel_dp_aux_irq_handler(dev_priv);
1489d04a492dSShashank Sharma 				found = true;
1490d04a492dSShashank Sharma 			}
1491d04a492dSShashank Sharma 
149270bfb307SMatt Roper 			if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
14939a55a620SVille Syrjälä 				u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK;
14949a55a620SVille Syrjälä 
14959a55a620SVille Syrjälä 				if (hotplug_trigger) {
14969a55a620SVille Syrjälä 					bxt_hpd_irq_handler(dev_priv, hotplug_trigger);
1497d04a492dSShashank Sharma 					found = true;
1498d04a492dSShashank Sharma 				}
1499e32192e1STvrtko Ursulin 			} else if (IS_BROADWELL(dev_priv)) {
15009a55a620SVille Syrjälä 				u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK;
15019a55a620SVille Syrjälä 
15029a55a620SVille Syrjälä 				if (hotplug_trigger) {
15039a55a620SVille Syrjälä 					ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
1504e32192e1STvrtko Ursulin 					found = true;
1505e32192e1STvrtko Ursulin 				}
1506e32192e1STvrtko Ursulin 			}
1507d04a492dSShashank Sharma 
150870bfb307SMatt Roper 			if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
150970bfb307SMatt Roper 			    (iir & BXT_DE_PORT_GMBUS)) {
1510685282a3SJani Nikula 				intel_gmbus_irq_handler(dev_priv);
15119e63743eSShashank Sharma 				found = true;
15129e63743eSShashank Sharma 			}
15139e63743eSShashank Sharma 
1514373abf1aSMatt Roper 			if (DISPLAY_VER(dev_priv) >= 11) {
15159a55a620SVille Syrjälä 				u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
15169a55a620SVille Syrjälä 
15179a55a620SVille Syrjälä 				if (te_trigger) {
15189a55a620SVille Syrjälä 					gen11_dsi_te_interrupt_handler(dev_priv, te_trigger);
151900acb329SVandita Kulkarni 					found = true;
152000acb329SVandita Kulkarni 				}
152100acb329SVandita Kulkarni 			}
152200acb329SVandita Kulkarni 
1523d04a492dSShashank Sharma 			if (!found)
15249a4cea62SLucas De Marchi 				drm_err_ratelimited(&dev_priv->drm,
152500376ccfSWambui Karuga 						    "Unexpected DE Port interrupt\n");
15266d766f02SDaniel Vetter 		}
152738cc46d7SOscar Mateo 		else
15289a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
152900376ccfSWambui Karuga 					    "The master control interrupt lied (DE PORT)!\n");
15306d766f02SDaniel Vetter 	}
15316d766f02SDaniel Vetter 
1532055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe) {
1533fd3a4024SDaniel Vetter 		u32 fault_errors;
1534abd58f01SBen Widawsky 
1535c42664ccSDaniel Vetter 		if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
1536c42664ccSDaniel Vetter 			continue;
1537c42664ccSDaniel Vetter 
15382939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe));
1539e32192e1STvrtko Ursulin 		if (!iir) {
15409a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
154100376ccfSWambui Karuga 					    "The master control interrupt lied (DE PIPE)!\n");
1542e32192e1STvrtko Ursulin 			continue;
1543e32192e1STvrtko Ursulin 		}
1544770de83dSDamien Lespiau 
15452939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir);
1546e32192e1STvrtko Ursulin 
1547fd3a4024SDaniel Vetter 		if (iir & GEN8_PIPE_VBLANK)
1548aca9310aSAnshuman Gupta 			intel_handle_vblank(dev_priv, pipe);
1549abd58f01SBen Widawsky 
1550cda195f1SVille Syrjälä 		if (iir & gen8_de_pipe_flip_done_mask(dev_priv))
15511288f9b0SKarthik B S 			flip_done_handler(dev_priv, pipe);
15521288f9b0SKarthik B S 
1553e32192e1STvrtko Ursulin 		if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
155491d14251STvrtko Ursulin 			hsw_pipe_crc_irq_handler(dev_priv, pipe);
15550fbe7870SDaniel Vetter 
15568bcc0840SMatt Roper 		if (iir & gen8_de_pipe_underrun_mask(dev_priv))
1557e32192e1STvrtko Ursulin 			intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
155838d83c96SDaniel Vetter 
15595270130dSVille Syrjälä 		fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
1560770de83dSDamien Lespiau 		if (fault_errors)
15619a4cea62SLucas De Marchi 			drm_err_ratelimited(&dev_priv->drm,
156200376ccfSWambui Karuga 					    "Fault errors on pipe %c: 0x%08x\n",
156330100f2bSDaniel Vetter 					    pipe_name(pipe),
1564e32192e1STvrtko Ursulin 					    fault_errors);
1565abd58f01SBen Widawsky 	}
1566abd58f01SBen Widawsky 
156791d14251STvrtko Ursulin 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
1568266ea3d9SShashank Sharma 	    master_ctl & GEN8_DE_PCH_IRQ) {
1569babde06dSMika Kahola 		u32 pica_iir;
1570babde06dSMika Kahola 
157192d03a80SDaniel Vetter 		/*
157292d03a80SDaniel Vetter 		 * FIXME(BDW): Assume for now that the new interrupt handling
157392d03a80SDaniel Vetter 		 * scheme also closed the SDE interrupt handling race we've seen
157492d03a80SDaniel Vetter 		 * on older pch-split platforms. But this needs testing.
157592d03a80SDaniel Vetter 		 */
1576babde06dSMika Kahola 		gen8_read_and_ack_pch_irqs(dev_priv, &iir, &pica_iir);
1577e32192e1STvrtko Ursulin 		if (iir) {
1578babde06dSMika Kahola 			if (pica_iir)
1579babde06dSMika Kahola 				xelpdp_pica_irq_handler(dev_priv, pica_iir);
1580babde06dSMika Kahola 
158158676af6SLucas De Marchi 			if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
158258676af6SLucas De Marchi 				icp_irq_handler(dev_priv, iir);
1583c6c30b91SRodrigo Vivi 			else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
158491d14251STvrtko Ursulin 				spt_irq_handler(dev_priv, iir);
15856dbf30ceSVille Syrjälä 			else
158691d14251STvrtko Ursulin 				cpt_irq_handler(dev_priv, iir);
15872dfb0b81SJani Nikula 		} else {
15882dfb0b81SJani Nikula 			/*
15892dfb0b81SJani Nikula 			 * Like on previous PCH there seems to be something
15902dfb0b81SJani Nikula 			 * fishy going on with forwarding PCH interrupts.
15912dfb0b81SJani Nikula 			 */
159200376ccfSWambui Karuga 			drm_dbg(&dev_priv->drm,
159300376ccfSWambui Karuga 				"The master control interrupt lied (SDE)!\n");
15942dfb0b81SJani Nikula 		}
159592d03a80SDaniel Vetter 	}
1596f11a0f46STvrtko Ursulin }
1597f11a0f46STvrtko Ursulin 
15984376b9c9SMika Kuoppala static inline u32 gen8_master_intr_disable(void __iomem * const regs)
15994376b9c9SMika Kuoppala {
16004376b9c9SMika Kuoppala 	raw_reg_write(regs, GEN8_MASTER_IRQ, 0);
16014376b9c9SMika Kuoppala 
16024376b9c9SMika Kuoppala 	/*
16034376b9c9SMika Kuoppala 	 * Now with master disabled, get a sample of level indications
16044376b9c9SMika Kuoppala 	 * for this interrupt. Indications will be cleared on related acks.
16054376b9c9SMika Kuoppala 	 * New indications can and will light up during processing,
16064376b9c9SMika Kuoppala 	 * and will generate new interrupt after enabling master.
16074376b9c9SMika Kuoppala 	 */
16084376b9c9SMika Kuoppala 	return raw_reg_read(regs, GEN8_MASTER_IRQ);
16094376b9c9SMika Kuoppala }
16104376b9c9SMika Kuoppala 
16114376b9c9SMika Kuoppala static inline void gen8_master_intr_enable(void __iomem * const regs)
16124376b9c9SMika Kuoppala {
16134376b9c9SMika Kuoppala 	raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
16144376b9c9SMika Kuoppala }
16154376b9c9SMika Kuoppala 
1616f11a0f46STvrtko Ursulin static irqreturn_t gen8_irq_handler(int irq, void *arg)
1617f11a0f46STvrtko Ursulin {
1618b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
161925286aacSDaniele Ceraolo Spurio 	void __iomem * const regs = dev_priv->uncore.regs;
1620f11a0f46STvrtko Ursulin 	u32 master_ctl;
1621f11a0f46STvrtko Ursulin 
1622f11a0f46STvrtko Ursulin 	if (!intel_irqs_enabled(dev_priv))
1623f11a0f46STvrtko Ursulin 		return IRQ_NONE;
1624f11a0f46STvrtko Ursulin 
16254376b9c9SMika Kuoppala 	master_ctl = gen8_master_intr_disable(regs);
16264376b9c9SMika Kuoppala 	if (!master_ctl) {
16274376b9c9SMika Kuoppala 		gen8_master_intr_enable(regs);
1628f11a0f46STvrtko Ursulin 		return IRQ_NONE;
16294376b9c9SMika Kuoppala 	}
1630f11a0f46STvrtko Ursulin 
16316cc32f15SChris Wilson 	/* Find, queue (onto bottom-halves), then clear each source */
16322cbc876dSMichał Winiarski 	gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
1633f0fd96f5SChris Wilson 
1634f0fd96f5SChris Wilson 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1635f0fd96f5SChris Wilson 	if (master_ctl & ~GEN8_GT_IRQS) {
16369102650fSDaniele Ceraolo Spurio 		disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
163755ef72f2SChris Wilson 		gen8_de_irq_handler(dev_priv, master_ctl);
16389102650fSDaniele Ceraolo Spurio 		enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
1639f0fd96f5SChris Wilson 	}
1640f11a0f46STvrtko Ursulin 
16414376b9c9SMika Kuoppala 	gen8_master_intr_enable(regs);
1642abd58f01SBen Widawsky 
16439c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
16449c6508b9SThomas Gleixner 
164555ef72f2SChris Wilson 	return IRQ_HANDLED;
1646abd58f01SBen Widawsky }
1647abd58f01SBen Widawsky 
164851951ae7SMika Kuoppala static u32
1649ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl)
1650df0d28c1SDhinakaran Pandiyan {
1651ddcf980fSAnusha Srivatsa 	void __iomem * const regs = i915->uncore.regs;
16527a909383SChris Wilson 	u32 iir;
1653df0d28c1SDhinakaran Pandiyan 
1654df0d28c1SDhinakaran Pandiyan 	if (!(master_ctl & GEN11_GU_MISC_IRQ))
16557a909383SChris Wilson 		return 0;
1656df0d28c1SDhinakaran Pandiyan 
16577a909383SChris Wilson 	iir = raw_reg_read(regs, GEN11_GU_MISC_IIR);
16587a909383SChris Wilson 	if (likely(iir))
16597a909383SChris Wilson 		raw_reg_write(regs, GEN11_GU_MISC_IIR, iir);
16607a909383SChris Wilson 
16617a909383SChris Wilson 	return iir;
1662df0d28c1SDhinakaran Pandiyan }
1663df0d28c1SDhinakaran Pandiyan 
1664df0d28c1SDhinakaran Pandiyan static void
1665ddcf980fSAnusha Srivatsa gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir)
1666df0d28c1SDhinakaran Pandiyan {
1667df0d28c1SDhinakaran Pandiyan 	if (iir & GEN11_GU_MISC_GSE)
1668ddcf980fSAnusha Srivatsa 		intel_opregion_asle_intr(i915);
1669df0d28c1SDhinakaran Pandiyan }
1670df0d28c1SDhinakaran Pandiyan 
167181067b71SMika Kuoppala static inline u32 gen11_master_intr_disable(void __iomem * const regs)
167281067b71SMika Kuoppala {
167381067b71SMika Kuoppala 	raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0);
167481067b71SMika Kuoppala 
167581067b71SMika Kuoppala 	/*
167681067b71SMika Kuoppala 	 * Now with master disabled, get a sample of level indications
167781067b71SMika Kuoppala 	 * for this interrupt. Indications will be cleared on related acks.
167881067b71SMika Kuoppala 	 * New indications can and will light up during processing,
167981067b71SMika Kuoppala 	 * and will generate new interrupt after enabling master.
168081067b71SMika Kuoppala 	 */
168181067b71SMika Kuoppala 	return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
168281067b71SMika Kuoppala }
168381067b71SMika Kuoppala 
168481067b71SMika Kuoppala static inline void gen11_master_intr_enable(void __iomem * const regs)
168581067b71SMika Kuoppala {
168681067b71SMika Kuoppala 	raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ);
168781067b71SMika Kuoppala }
168881067b71SMika Kuoppala 
1689a3265d85SMatt Roper static void
1690a3265d85SMatt Roper gen11_display_irq_handler(struct drm_i915_private *i915)
1691a3265d85SMatt Roper {
1692a3265d85SMatt Roper 	void __iomem * const regs = i915->uncore.regs;
1693a3265d85SMatt Roper 	const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
1694a3265d85SMatt Roper 
1695a3265d85SMatt Roper 	disable_rpm_wakeref_asserts(&i915->runtime_pm);
1696a3265d85SMatt Roper 	/*
1697a3265d85SMatt Roper 	 * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
1698a3265d85SMatt Roper 	 * for the display related bits.
1699a3265d85SMatt Roper 	 */
1700a3265d85SMatt Roper 	raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0);
1701a3265d85SMatt Roper 	gen8_de_irq_handler(i915, disp_ctl);
1702a3265d85SMatt Roper 	raw_reg_write(regs, GEN11_DISPLAY_INT_CTL,
1703a3265d85SMatt Roper 		      GEN11_DISPLAY_IRQ_ENABLE);
1704a3265d85SMatt Roper 
1705a3265d85SMatt Roper 	enable_rpm_wakeref_asserts(&i915->runtime_pm);
1706a3265d85SMatt Roper }
1707a3265d85SMatt Roper 
170822e26af7SPaulo Zanoni static irqreturn_t gen11_irq_handler(int irq, void *arg)
170951951ae7SMika Kuoppala {
171022e26af7SPaulo Zanoni 	struct drm_i915_private *i915 = arg;
171125286aacSDaniele Ceraolo Spurio 	void __iomem * const regs = i915->uncore.regs;
17122cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(i915);
171351951ae7SMika Kuoppala 	u32 master_ctl;
1714df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_iir;
171551951ae7SMika Kuoppala 
171651951ae7SMika Kuoppala 	if (!intel_irqs_enabled(i915))
171751951ae7SMika Kuoppala 		return IRQ_NONE;
171851951ae7SMika Kuoppala 
171922e26af7SPaulo Zanoni 	master_ctl = gen11_master_intr_disable(regs);
172081067b71SMika Kuoppala 	if (!master_ctl) {
172122e26af7SPaulo Zanoni 		gen11_master_intr_enable(regs);
172251951ae7SMika Kuoppala 		return IRQ_NONE;
172381067b71SMika Kuoppala 	}
172451951ae7SMika Kuoppala 
17256cc32f15SChris Wilson 	/* Find, queue (onto bottom-halves), then clear each source */
17269b77011eSTvrtko Ursulin 	gen11_gt_irq_handler(gt, master_ctl);
172751951ae7SMika Kuoppala 
172851951ae7SMika Kuoppala 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
1729a3265d85SMatt Roper 	if (master_ctl & GEN11_DISPLAY_IRQ)
1730a3265d85SMatt Roper 		gen11_display_irq_handler(i915);
173151951ae7SMika Kuoppala 
1732ddcf980fSAnusha Srivatsa 	gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl);
1733df0d28c1SDhinakaran Pandiyan 
173422e26af7SPaulo Zanoni 	gen11_master_intr_enable(regs);
173551951ae7SMika Kuoppala 
1736ddcf980fSAnusha Srivatsa 	gen11_gu_misc_irq_handler(i915, gu_misc_iir);
1737df0d28c1SDhinakaran Pandiyan 
17389c6508b9SThomas Gleixner 	pmu_irq_stats(i915, IRQ_HANDLED);
17399c6508b9SThomas Gleixner 
174051951ae7SMika Kuoppala 	return IRQ_HANDLED;
174151951ae7SMika Kuoppala }
174251951ae7SMika Kuoppala 
174322e26af7SPaulo Zanoni static inline u32 dg1_master_intr_disable(void __iomem * const regs)
174497b492f5SLucas De Marchi {
174597b492f5SLucas De Marchi 	u32 val;
174697b492f5SLucas De Marchi 
174797b492f5SLucas De Marchi 	/* First disable interrupts */
174822e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, 0);
174997b492f5SLucas De Marchi 
175097b492f5SLucas De Marchi 	/* Get the indication levels and ack the master unit */
175122e26af7SPaulo Zanoni 	val = raw_reg_read(regs, DG1_MSTR_TILE_INTR);
175297b492f5SLucas De Marchi 	if (unlikely(!val))
175397b492f5SLucas De Marchi 		return 0;
175497b492f5SLucas De Marchi 
175522e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, val);
175697b492f5SLucas De Marchi 
175797b492f5SLucas De Marchi 	return val;
175897b492f5SLucas De Marchi }
175997b492f5SLucas De Marchi 
176097b492f5SLucas De Marchi static inline void dg1_master_intr_enable(void __iomem * const regs)
176197b492f5SLucas De Marchi {
176222e26af7SPaulo Zanoni 	raw_reg_write(regs, DG1_MSTR_TILE_INTR, DG1_MSTR_IRQ);
176397b492f5SLucas De Marchi }
176497b492f5SLucas De Marchi 
176597b492f5SLucas De Marchi static irqreturn_t dg1_irq_handler(int irq, void *arg)
176697b492f5SLucas De Marchi {
176722e26af7SPaulo Zanoni 	struct drm_i915_private * const i915 = arg;
17682cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(i915);
1769fd4d7904SPaulo Zanoni 	void __iomem * const regs = gt->uncore->regs;
177022e26af7SPaulo Zanoni 	u32 master_tile_ctl, master_ctl;
177122e26af7SPaulo Zanoni 	u32 gu_misc_iir;
177222e26af7SPaulo Zanoni 
177322e26af7SPaulo Zanoni 	if (!intel_irqs_enabled(i915))
177422e26af7SPaulo Zanoni 		return IRQ_NONE;
177522e26af7SPaulo Zanoni 
177622e26af7SPaulo Zanoni 	master_tile_ctl = dg1_master_intr_disable(regs);
177722e26af7SPaulo Zanoni 	if (!master_tile_ctl) {
177822e26af7SPaulo Zanoni 		dg1_master_intr_enable(regs);
177922e26af7SPaulo Zanoni 		return IRQ_NONE;
178022e26af7SPaulo Zanoni 	}
178122e26af7SPaulo Zanoni 
178222e26af7SPaulo Zanoni 	/* FIXME: we only support tile 0 for now. */
178322e26af7SPaulo Zanoni 	if (master_tile_ctl & DG1_MSTR_TILE(0)) {
178422e26af7SPaulo Zanoni 		master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
178522e26af7SPaulo Zanoni 		raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl);
178622e26af7SPaulo Zanoni 	} else {
1787a10234fdSTvrtko Ursulin 		drm_err(&i915->drm, "Tile not supported: 0x%08x\n",
1788a10234fdSTvrtko Ursulin 			master_tile_ctl);
178922e26af7SPaulo Zanoni 		dg1_master_intr_enable(regs);
179022e26af7SPaulo Zanoni 		return IRQ_NONE;
179122e26af7SPaulo Zanoni 	}
179222e26af7SPaulo Zanoni 
179322e26af7SPaulo Zanoni 	gen11_gt_irq_handler(gt, master_ctl);
179422e26af7SPaulo Zanoni 
179522e26af7SPaulo Zanoni 	if (master_ctl & GEN11_DISPLAY_IRQ)
179622e26af7SPaulo Zanoni 		gen11_display_irq_handler(i915);
179722e26af7SPaulo Zanoni 
1798ddcf980fSAnusha Srivatsa 	gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl);
179922e26af7SPaulo Zanoni 
180022e26af7SPaulo Zanoni 	dg1_master_intr_enable(regs);
180122e26af7SPaulo Zanoni 
1802ddcf980fSAnusha Srivatsa 	gen11_gu_misc_irq_handler(i915, gu_misc_iir);
180322e26af7SPaulo Zanoni 
180422e26af7SPaulo Zanoni 	pmu_irq_stats(i915, IRQ_HANDLED);
180522e26af7SPaulo Zanoni 
180622e26af7SPaulo Zanoni 	return IRQ_HANDLED;
180797b492f5SLucas De Marchi }
180897b492f5SLucas De Marchi 
180942f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which
181042f52ef8SKeith Packard  * we use as a pipe index
181142f52ef8SKeith Packard  */
181208fa8fd0SVille Syrjälä int i8xx_enable_vblank(struct drm_crtc *crtc)
18130a3e67a4SJesse Barnes {
181408fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
181508fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
1816e9d21d7fSKeith Packard 	unsigned long irqflags;
181771e0ffa5SJesse Barnes 
18181ec14ad3SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
181986e83e35SChris Wilson 	i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
182086e83e35SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
182186e83e35SChris Wilson 
182286e83e35SChris Wilson 	return 0;
182386e83e35SChris Wilson }
182486e83e35SChris Wilson 
18257d423af9SVille Syrjälä int i915gm_enable_vblank(struct drm_crtc *crtc)
1826d938da6bSVille Syrjälä {
182708fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
1828d938da6bSVille Syrjälä 
18297d423af9SVille Syrjälä 	/*
18307d423af9SVille Syrjälä 	 * Vblank interrupts fail to wake the device up from C2+.
18317d423af9SVille Syrjälä 	 * Disabling render clock gating during C-states avoids
18327d423af9SVille Syrjälä 	 * the problem. There is a small power cost so we do this
18337d423af9SVille Syrjälä 	 * only when vblank interrupts are actually enabled.
18347d423af9SVille Syrjälä 	 */
18357d423af9SVille Syrjälä 	if (dev_priv->vblank_enabled++ == 0)
18362939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
1837d938da6bSVille Syrjälä 
183808fa8fd0SVille Syrjälä 	return i8xx_enable_vblank(crtc);
1839d938da6bSVille Syrjälä }
1840d938da6bSVille Syrjälä 
184108fa8fd0SVille Syrjälä int i965_enable_vblank(struct drm_crtc *crtc)
184286e83e35SChris Wilson {
184308fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
184408fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
184586e83e35SChris Wilson 	unsigned long irqflags;
184686e83e35SChris Wilson 
184786e83e35SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
18487c463586SKeith Packard 	i915_enable_pipestat(dev_priv, pipe,
1849755e9019SImre Deak 			     PIPE_START_VBLANK_INTERRUPT_STATUS);
18501ec14ad3SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
18518692d00eSChris Wilson 
18520a3e67a4SJesse Barnes 	return 0;
18530a3e67a4SJesse Barnes }
18540a3e67a4SJesse Barnes 
185508fa8fd0SVille Syrjälä int ilk_enable_vblank(struct drm_crtc *crtc)
1856f796cf8fSJesse Barnes {
185708fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
185808fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
1859f796cf8fSJesse Barnes 	unsigned long irqflags;
1860373abf1aSMatt Roper 	u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
186186e83e35SChris Wilson 		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
1862f796cf8fSJesse Barnes 
1863f796cf8fSJesse Barnes 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1864fbdedaeaSVille Syrjälä 	ilk_enable_display_irq(dev_priv, bit);
1865b1f14ad0SJesse Barnes 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1866b1f14ad0SJesse Barnes 
18672e8bf223SDhinakaran Pandiyan 	/* Even though there is no DMC, frame counter can get stuck when
18682e8bf223SDhinakaran Pandiyan 	 * PSR is active as no frames are generated.
18692e8bf223SDhinakaran Pandiyan 	 */
18702e8bf223SDhinakaran Pandiyan 	if (HAS_PSR(dev_priv))
187108fa8fd0SVille Syrjälä 		drm_crtc_vblank_restore(crtc);
18722e8bf223SDhinakaran Pandiyan 
1873b1f14ad0SJesse Barnes 	return 0;
1874b1f14ad0SJesse Barnes }
1875b1f14ad0SJesse Barnes 
18769c9e97c4SVandita Kulkarni static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
18779c9e97c4SVandita Kulkarni 				   bool enable)
18789c9e97c4SVandita Kulkarni {
18799c9e97c4SVandita Kulkarni 	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
18809c9e97c4SVandita Kulkarni 	enum port port;
18819c9e97c4SVandita Kulkarni 
18829c9e97c4SVandita Kulkarni 	if (!(intel_crtc->mode_flags &
18839c9e97c4SVandita Kulkarni 	    (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0)))
18849c9e97c4SVandita Kulkarni 		return false;
18859c9e97c4SVandita Kulkarni 
18869c9e97c4SVandita Kulkarni 	/* for dual link cases we consider TE from slave */
18879c9e97c4SVandita Kulkarni 	if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1)
18889c9e97c4SVandita Kulkarni 		port = PORT_B;
18899c9e97c4SVandita Kulkarni 	else
18909c9e97c4SVandita Kulkarni 		port = PORT_A;
18919c9e97c4SVandita Kulkarni 
18928cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT,
18938cee664dSAndrzej Hajda 			 enable ? 0 : DSI_TE_EVENT);
18949c9e97c4SVandita Kulkarni 
18958cee664dSAndrzej Hajda 	intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
18969c9e97c4SVandita Kulkarni 
18979c9e97c4SVandita Kulkarni 	return true;
18989c9e97c4SVandita Kulkarni }
18999c9e97c4SVandita Kulkarni 
1900f15f01a7SVille Syrjälä int bdw_enable_vblank(struct drm_crtc *_crtc)
1901abd58f01SBen Widawsky {
1902f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(_crtc);
1903f15f01a7SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1904f15f01a7SVille Syrjälä 	enum pipe pipe = crtc->pipe;
1905abd58f01SBen Widawsky 	unsigned long irqflags;
1906abd58f01SBen Widawsky 
1907f15f01a7SVille Syrjälä 	if (gen11_dsi_configure_te(crtc, true))
19089c9e97c4SVandita Kulkarni 		return 0;
19099c9e97c4SVandita Kulkarni 
1910abd58f01SBen Widawsky 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1911013d3752SVille Syrjälä 	bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
1912abd58f01SBen Widawsky 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1913013d3752SVille Syrjälä 
19142e8bf223SDhinakaran Pandiyan 	/* Even if there is no DMC, frame counter can get stuck when
19152e8bf223SDhinakaran Pandiyan 	 * PSR is active as no frames are generated, so check only for PSR.
19162e8bf223SDhinakaran Pandiyan 	 */
19172e8bf223SDhinakaran Pandiyan 	if (HAS_PSR(dev_priv))
1918f15f01a7SVille Syrjälä 		drm_crtc_vblank_restore(&crtc->base);
19192e8bf223SDhinakaran Pandiyan 
1920abd58f01SBen Widawsky 	return 0;
1921abd58f01SBen Widawsky }
1922abd58f01SBen Widawsky 
192342f52ef8SKeith Packard /* Called from drm generic code, passed 'crtc' which
192442f52ef8SKeith Packard  * we use as a pipe index
192542f52ef8SKeith Packard  */
192608fa8fd0SVille Syrjälä void i8xx_disable_vblank(struct drm_crtc *crtc)
192786e83e35SChris Wilson {
192808fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
192908fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
193086e83e35SChris Wilson 	unsigned long irqflags;
193186e83e35SChris Wilson 
193286e83e35SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
193386e83e35SChris Wilson 	i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
193486e83e35SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
193586e83e35SChris Wilson }
193686e83e35SChris Wilson 
19377d423af9SVille Syrjälä void i915gm_disable_vblank(struct drm_crtc *crtc)
1938d938da6bSVille Syrjälä {
193908fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
1940d938da6bSVille Syrjälä 
194108fa8fd0SVille Syrjälä 	i8xx_disable_vblank(crtc);
1942d938da6bSVille Syrjälä 
19437d423af9SVille Syrjälä 	if (--dev_priv->vblank_enabled == 0)
19442939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
1945d938da6bSVille Syrjälä }
1946d938da6bSVille Syrjälä 
194708fa8fd0SVille Syrjälä void i965_disable_vblank(struct drm_crtc *crtc)
19480a3e67a4SJesse Barnes {
194908fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
195008fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
1951e9d21d7fSKeith Packard 	unsigned long irqflags;
19520a3e67a4SJesse Barnes 
19531ec14ad3SChris Wilson 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
19547c463586SKeith Packard 	i915_disable_pipestat(dev_priv, pipe,
1955755e9019SImre Deak 			      PIPE_START_VBLANK_INTERRUPT_STATUS);
19561ec14ad3SChris Wilson 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
19570a3e67a4SJesse Barnes }
19580a3e67a4SJesse Barnes 
195908fa8fd0SVille Syrjälä void ilk_disable_vblank(struct drm_crtc *crtc)
1960f796cf8fSJesse Barnes {
196108fa8fd0SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
196208fa8fd0SVille Syrjälä 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
1963f796cf8fSJesse Barnes 	unsigned long irqflags;
1964373abf1aSMatt Roper 	u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
196586e83e35SChris Wilson 		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
1966f796cf8fSJesse Barnes 
1967f796cf8fSJesse Barnes 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1968fbdedaeaSVille Syrjälä 	ilk_disable_display_irq(dev_priv, bit);
1969b1f14ad0SJesse Barnes 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1970b1f14ad0SJesse Barnes }
1971b1f14ad0SJesse Barnes 
1972f15f01a7SVille Syrjälä void bdw_disable_vblank(struct drm_crtc *_crtc)
1973abd58f01SBen Widawsky {
1974f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(_crtc);
1975f15f01a7SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1976f15f01a7SVille Syrjälä 	enum pipe pipe = crtc->pipe;
1977abd58f01SBen Widawsky 	unsigned long irqflags;
1978abd58f01SBen Widawsky 
1979f15f01a7SVille Syrjälä 	if (gen11_dsi_configure_te(crtc, false))
19809c9e97c4SVandita Kulkarni 		return;
19819c9e97c4SVandita Kulkarni 
1982abd58f01SBen Widawsky 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
1983013d3752SVille Syrjälä 	bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
1984abd58f01SBen Widawsky 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
1985abd58f01SBen Widawsky }
1986abd58f01SBen Widawsky 
1987b243f530STvrtko Ursulin static void ibx_irq_reset(struct drm_i915_private *dev_priv)
198891738a95SPaulo Zanoni {
1989b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
1990b16b2a2fSPaulo Zanoni 
19916e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
199291738a95SPaulo Zanoni 		return;
199391738a95SPaulo Zanoni 
1994b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, SDE);
1995105b122eSPaulo Zanoni 
19966e266956STvrtko Ursulin 	if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
19972939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, SERR_INT, 0xffffffff);
1998622364b6SPaulo Zanoni }
1999105b122eSPaulo Zanoni 
200070591a41SVille Syrjälä static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
200170591a41SVille Syrjälä {
2002b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2003b16b2a2fSPaulo Zanoni 
200471b8b41dSVille Syrjälä 	if (IS_CHERRYVIEW(dev_priv))
2005f0818984STvrtko Ursulin 		intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
200671b8b41dSVille Syrjälä 	else
20077d938bc0SVille Syrjälä 		intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
200871b8b41dSVille Syrjälä 
2009ad22d106SVille Syrjälä 	i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
20108cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
201170591a41SVille Syrjälä 
201244d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
201370591a41SVille Syrjälä 
2014b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, VLV_);
20158bd099a7SChris Wilson 	dev_priv->irq_mask = ~0u;
201670591a41SVille Syrjälä }
201770591a41SVille Syrjälä 
20188bb61306SVille Syrjälä static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
20198bb61306SVille Syrjälä {
2020b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2021b16b2a2fSPaulo Zanoni 
20228bb61306SVille Syrjälä 	u32 pipestat_mask;
20239ab981f2SVille Syrjälä 	u32 enable_mask;
20248bb61306SVille Syrjälä 	enum pipe pipe;
20258bb61306SVille Syrjälä 
2026842ebf7aSVille Syrjälä 	pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
20278bb61306SVille Syrjälä 
20288bb61306SVille Syrjälä 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
20298bb61306SVille Syrjälä 	for_each_pipe(dev_priv, pipe)
20308bb61306SVille Syrjälä 		i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
20318bb61306SVille Syrjälä 
20329ab981f2SVille Syrjälä 	enable_mask = I915_DISPLAY_PORT_INTERRUPT |
20338bb61306SVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
2034ebf5f921SVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
2035ebf5f921SVille Syrjälä 		I915_LPE_PIPE_A_INTERRUPT |
2036ebf5f921SVille Syrjälä 		I915_LPE_PIPE_B_INTERRUPT;
2037ebf5f921SVille Syrjälä 
20388bb61306SVille Syrjälä 	if (IS_CHERRYVIEW(dev_priv))
2039ebf5f921SVille Syrjälä 		enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
2040ebf5f921SVille Syrjälä 			I915_LPE_PIPE_C_INTERRUPT;
20416b7eafc1SVille Syrjälä 
204248a1b8d4SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u);
20436b7eafc1SVille Syrjälä 
20449ab981f2SVille Syrjälä 	dev_priv->irq_mask = ~enable_mask;
20458bb61306SVille Syrjälä 
2046b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask);
20478bb61306SVille Syrjälä }
20488bb61306SVille Syrjälä 
20498bb61306SVille Syrjälä /* drm_dma.h hooks
20508bb61306SVille Syrjälä */
20519eae5e27SLucas De Marchi static void ilk_irq_reset(struct drm_i915_private *dev_priv)
20528bb61306SVille Syrjälä {
2053b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
20548bb61306SVille Syrjälä 
2055b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, DE);
2056e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
2057e44adb5dSChris Wilson 
2058651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) == 7)
2059f0818984STvrtko Ursulin 		intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff);
20608bb61306SVille Syrjälä 
2061fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
2062f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2063f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
2064fc340442SDaniel Vetter 	}
2065fc340442SDaniel Vetter 
20662cbc876dSMichał Winiarski 	gen5_gt_irq_reset(to_gt(dev_priv));
20678bb61306SVille Syrjälä 
2068b243f530STvrtko Ursulin 	ibx_irq_reset(dev_priv);
20698bb61306SVille Syrjälä }
20708bb61306SVille Syrjälä 
2071b318b824SVille Syrjälä static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
20727e231dbeSJesse Barnes {
20732939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0);
20742939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
207534c7b8a7SVille Syrjälä 
20762cbc876dSMichał Winiarski 	gen5_gt_irq_reset(to_gt(dev_priv));
20777e231dbeSJesse Barnes 
2078ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
20799918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
208070591a41SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2081ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
20827e231dbeSJesse Barnes }
20837e231dbeSJesse Barnes 
2084a844cfbeSJosé Roberto de Souza static void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
2085abd58f01SBen Widawsky {
2086b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2087d048a268SVille Syrjälä 	enum pipe pipe;
2088abd58f01SBen Widawsky 
2089a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2090a844cfbeSJosé Roberto de Souza 		return;
2091abd58f01SBen Widawsky 
2092f0818984STvrtko Ursulin 	intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2093f0818984STvrtko Ursulin 	intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
2094e04f7eceSVille Syrjälä 
2095055e393fSDamien Lespiau 	for_each_pipe(dev_priv, pipe)
2096f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
2097813bde43SPaulo Zanoni 						   POWER_DOMAIN_PIPE(pipe)))
2098b16b2a2fSPaulo Zanoni 			GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
2099abd58f01SBen Widawsky 
2100b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
2101b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
2102a844cfbeSJosé Roberto de Souza }
2103a844cfbeSJosé Roberto de Souza 
2104a844cfbeSJosé Roberto de Souza static void gen8_irq_reset(struct drm_i915_private *dev_priv)
2105a844cfbeSJosé Roberto de Souza {
2106a844cfbeSJosé Roberto de Souza 	struct intel_uncore *uncore = &dev_priv->uncore;
2107a844cfbeSJosé Roberto de Souza 
2108e58c2cacSAndrzej Hajda 	gen8_master_intr_disable(uncore->regs);
2109a844cfbeSJosé Roberto de Souza 
21102cbc876dSMichał Winiarski 	gen8_gt_irq_reset(to_gt(dev_priv));
2111a844cfbeSJosé Roberto de Souza 	gen8_display_irq_reset(dev_priv);
2112b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
2113abd58f01SBen Widawsky 
21146e266956STvrtko Ursulin 	if (HAS_PCH_SPLIT(dev_priv))
2115b243f530STvrtko Ursulin 		ibx_irq_reset(dev_priv);
211659b7cb44STejas Upadhyay 
2117abd58f01SBen Widawsky }
2118abd58f01SBen Widawsky 
2119a3265d85SMatt Roper static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
212051951ae7SMika Kuoppala {
2121b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2122d048a268SVille Syrjälä 	enum pipe pipe;
2123562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
2124562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
212551951ae7SMika Kuoppala 
2126a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2127a844cfbeSJosé Roberto de Souza 		return;
2128a844cfbeSJosé Roberto de Souza 
2129f0818984STvrtko Ursulin 	intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0);
213051951ae7SMika Kuoppala 
2131373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
21328241cfbeSJosé Roberto de Souza 		enum transcoder trans;
21338241cfbeSJosé Roberto de Souza 
2134562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
21358241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
21368241cfbeSJosé Roberto de Souza 
21378241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
21388241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
21398241cfbeSJosé Roberto de Souza 				continue;
21408241cfbeSJosé Roberto de Souza 
21418241cfbeSJosé Roberto de Souza 			intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff);
21428241cfbeSJosé Roberto de Souza 			intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff);
21438241cfbeSJosé Roberto de Souza 		}
21448241cfbeSJosé Roberto de Souza 	} else {
2145f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
2146f0818984STvrtko Ursulin 		intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
21478241cfbeSJosé Roberto de Souza 	}
214862819dfdSJosé Roberto de Souza 
214951951ae7SMika Kuoppala 	for_each_pipe(dev_priv, pipe)
215051951ae7SMika Kuoppala 		if (intel_display_power_is_enabled(dev_priv,
215151951ae7SMika Kuoppala 						   POWER_DOMAIN_PIPE(pipe)))
2152b16b2a2fSPaulo Zanoni 			GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
215351951ae7SMika Kuoppala 
2154b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
2155b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
2156babde06dSMika Kahola 
2157babde06dSMika Kahola 	if (DISPLAY_VER(dev_priv) >= 14)
2158babde06dSMika Kahola 		GEN3_IRQ_RESET(uncore, PICAINTERRUPT_);
2159babde06dSMika Kahola 	else
2160b16b2a2fSPaulo Zanoni 		GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_);
216131604222SAnusha Srivatsa 
216229b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
2163b16b2a2fSPaulo Zanoni 		GEN3_IRQ_RESET(uncore, SDE);
216451951ae7SMika Kuoppala }
216551951ae7SMika Kuoppala 
2166a3265d85SMatt Roper static void gen11_irq_reset(struct drm_i915_private *dev_priv)
2167a3265d85SMatt Roper {
21682cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2169fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
2170a3265d85SMatt Roper 
2171a3265d85SMatt Roper 	gen11_master_intr_disable(dev_priv->uncore.regs);
2172a3265d85SMatt Roper 
2173fd4d7904SPaulo Zanoni 	gen11_gt_irq_reset(gt);
2174a3265d85SMatt Roper 	gen11_display_irq_reset(dev_priv);
2175a3265d85SMatt Roper 
2176a3265d85SMatt Roper 	GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
2177a3265d85SMatt Roper 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
2178a3265d85SMatt Roper }
2179a3265d85SMatt Roper 
218022e26af7SPaulo Zanoni static void dg1_irq_reset(struct drm_i915_private *dev_priv)
218122e26af7SPaulo Zanoni {
21822cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2183fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
218422e26af7SPaulo Zanoni 
218522e26af7SPaulo Zanoni 	dg1_master_intr_disable(dev_priv->uncore.regs);
218622e26af7SPaulo Zanoni 
2187fd4d7904SPaulo Zanoni 	gen11_gt_irq_reset(gt);
218822e26af7SPaulo Zanoni 	gen11_display_irq_reset(dev_priv);
218922e26af7SPaulo Zanoni 
219022e26af7SPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_);
219122e26af7SPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
219222e26af7SPaulo Zanoni }
219322e26af7SPaulo Zanoni 
21944c6c03beSDamien Lespiau void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
2195001bd2cbSImre Deak 				     u8 pipe_mask)
2196d49bdb0eSPaulo Zanoni {
2197b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
21988bcc0840SMatt Roper 	u32 extra_ier = GEN8_PIPE_VBLANK |
21998bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
2200cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
22016831f3e3SVille Syrjälä 	enum pipe pipe;
2202d49bdb0eSPaulo Zanoni 
220313321786SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
22049dfe2e3aSImre Deak 
22059dfe2e3aSImre Deak 	if (!intel_irqs_enabled(dev_priv)) {
22069dfe2e3aSImre Deak 		spin_unlock_irq(&dev_priv->irq_lock);
22079dfe2e3aSImre Deak 		return;
22089dfe2e3aSImre Deak 	}
22099dfe2e3aSImre Deak 
22106831f3e3SVille Syrjälä 	for_each_pipe_masked(dev_priv, pipe, pipe_mask)
2211b16b2a2fSPaulo Zanoni 		GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
22126831f3e3SVille Syrjälä 				  dev_priv->de_irq_mask[pipe],
22136831f3e3SVille Syrjälä 				  ~dev_priv->de_irq_mask[pipe] | extra_ier);
22149dfe2e3aSImre Deak 
221513321786SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
2216d49bdb0eSPaulo Zanoni }
2217d49bdb0eSPaulo Zanoni 
2218aae8ba84SVille Syrjälä void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
2219001bd2cbSImre Deak 				     u8 pipe_mask)
2220aae8ba84SVille Syrjälä {
2221b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
22226831f3e3SVille Syrjälä 	enum pipe pipe;
22236831f3e3SVille Syrjälä 
2224aae8ba84SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
22259dfe2e3aSImre Deak 
22269dfe2e3aSImre Deak 	if (!intel_irqs_enabled(dev_priv)) {
22279dfe2e3aSImre Deak 		spin_unlock_irq(&dev_priv->irq_lock);
22289dfe2e3aSImre Deak 		return;
22299dfe2e3aSImre Deak 	}
22309dfe2e3aSImre Deak 
22316831f3e3SVille Syrjälä 	for_each_pipe_masked(dev_priv, pipe, pipe_mask)
2232b16b2a2fSPaulo Zanoni 		GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
22339dfe2e3aSImre Deak 
2234aae8ba84SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
2235aae8ba84SVille Syrjälä 
2236aae8ba84SVille Syrjälä 	/* make sure we're done processing display irqs */
2237315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
2238aae8ba84SVille Syrjälä }
2239aae8ba84SVille Syrjälä 
2240b318b824SVille Syrjälä static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
224143f328d7SVille Syrjälä {
2242b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
224343f328d7SVille Syrjälä 
2244e58c2cacSAndrzej Hajda 	intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0);
22452939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
224643f328d7SVille Syrjälä 
22472cbc876dSMichał Winiarski 	gen8_gt_irq_reset(to_gt(dev_priv));
224843f328d7SVille Syrjälä 
2249b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN8_PCU_);
225043f328d7SVille Syrjälä 
2251ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
22529918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
225370591a41SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2254ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
225543f328d7SVille Syrjälä }
225643f328d7SVille Syrjälä 
2257a0a6d8cbSVille Syrjälä /*
2258a0a6d8cbSVille Syrjälä  * SDEIER is also touched by the interrupt handler to work around missed PCH
2259a0a6d8cbSVille Syrjälä  * interrupts. Hence we can't update it after the interrupt handler is enabled -
2260a0a6d8cbSVille Syrjälä  * instead we unconditionally enable all PCH interrupt sources here, but then
2261a0a6d8cbSVille Syrjälä  * only unmask them as needed with SDEIMR.
2262a0a6d8cbSVille Syrjälä  *
2263a0a6d8cbSVille Syrjälä  * Note that we currently do this after installing the interrupt handler,
2264a0a6d8cbSVille Syrjälä  * but before we enable the master interrupt. That should be sufficient
2265a0a6d8cbSVille Syrjälä  * to avoid races with the irq handler, assuming we have MSI. Shared legacy
2266a0a6d8cbSVille Syrjälä  * interrupts could still race.
2267a0a6d8cbSVille Syrjälä  */
2268b318b824SVille Syrjälä static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
2269d46da437SPaulo Zanoni {
2270a0a6d8cbSVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
227182a28bcfSDaniel Vetter 	u32 mask;
2272d46da437SPaulo Zanoni 
22736e266956STvrtko Ursulin 	if (HAS_PCH_NOP(dev_priv))
2274692a04cfSDaniel Vetter 		return;
2275692a04cfSDaniel Vetter 
22766e266956STvrtko Ursulin 	if (HAS_PCH_IBX(dev_priv))
22775c673b60SDaniel Vetter 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
22784ebc6509SDhinakaran Pandiyan 	else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
22795c673b60SDaniel Vetter 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
22804ebc6509SDhinakaran Pandiyan 	else
22814ebc6509SDhinakaran Pandiyan 		mask = SDE_GMBUS_CPT;
22828664281bSPaulo Zanoni 
2283a0a6d8cbSVille Syrjälä 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
2284d46da437SPaulo Zanoni }
2285d46da437SPaulo Zanoni 
22869eae5e27SLucas De Marchi static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
2287036a4a7dSZhenyu Wang {
2288b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
22898e76f8dcSPaulo Zanoni 	u32 display_mask, extra_mask;
22908e76f8dcSPaulo Zanoni 
2291651e7d48SLucas De Marchi 	if (GRAPHICS_VER(dev_priv) >= 7) {
22928e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
2293842ebf7aSVille Syrjälä 				DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB);
22948e76f8dcSPaulo Zanoni 		extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
229523bb4cb5SVille Syrjälä 			      DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
22962a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_C) |
22972a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_B) |
22982a636e24SVille Syrjälä 			      DE_PLANE_FLIP_DONE_IVB(PLANE_A) |
229923bb4cb5SVille Syrjälä 			      DE_DP_A_HOTPLUG_IVB);
23008e76f8dcSPaulo Zanoni 	} else {
23018e76f8dcSPaulo Zanoni 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
2302842ebf7aSVille Syrjälä 				DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE |
2303842ebf7aSVille Syrjälä 				DE_PIPEA_CRC_DONE | DE_POISON);
2304c6073d4cSVille Syrjälä 		extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK |
2305e4ce95aaSVille Syrjälä 			      DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
23064bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_A) |
23074bb18054SVille Syrjälä 			      DE_PLANE_FLIP_DONE(PLANE_B) |
2308e4ce95aaSVille Syrjälä 			      DE_DP_A_HOTPLUG);
23098e76f8dcSPaulo Zanoni 	}
2310036a4a7dSZhenyu Wang 
2311fc340442SDaniel Vetter 	if (IS_HASWELL(dev_priv)) {
2312b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
2313fc340442SDaniel Vetter 		display_mask |= DE_EDP_PSR_INT_HSW;
2314fc340442SDaniel Vetter 	}
2315fc340442SDaniel Vetter 
2316c6073d4cSVille Syrjälä 	if (IS_IRONLAKE_M(dev_priv))
2317c6073d4cSVille Syrjälä 		extra_mask |= DE_PCU_EVENT;
2318c6073d4cSVille Syrjälä 
23191ec14ad3SChris Wilson 	dev_priv->irq_mask = ~display_mask;
2320036a4a7dSZhenyu Wang 
2321a0a6d8cbSVille Syrjälä 	ibx_irq_postinstall(dev_priv);
2322622364b6SPaulo Zanoni 
23232cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
2324a9922912SVille Syrjälä 
2325b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask,
2326b16b2a2fSPaulo Zanoni 		      display_mask | extra_mask);
2327036a4a7dSZhenyu Wang }
2328036a4a7dSZhenyu Wang 
2329f8b79e58SImre Deak void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
2330f8b79e58SImre Deak {
233167520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
2332f8b79e58SImre Deak 
2333f8b79e58SImre Deak 	if (dev_priv->display_irqs_enabled)
2334f8b79e58SImre Deak 		return;
2335f8b79e58SImre Deak 
2336f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = true;
2337f8b79e58SImre Deak 
2338d6c69803SVille Syrjälä 	if (intel_irqs_enabled(dev_priv)) {
2339d6c69803SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2340ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
2341f8b79e58SImre Deak 	}
2342d6c69803SVille Syrjälä }
2343f8b79e58SImre Deak 
2344f8b79e58SImre Deak void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
2345f8b79e58SImre Deak {
234667520415SChris Wilson 	lockdep_assert_held(&dev_priv->irq_lock);
2347f8b79e58SImre Deak 
2348f8b79e58SImre Deak 	if (!dev_priv->display_irqs_enabled)
2349f8b79e58SImre Deak 		return;
2350f8b79e58SImre Deak 
2351f8b79e58SImre Deak 	dev_priv->display_irqs_enabled = false;
2352f8b79e58SImre Deak 
2353950eabafSImre Deak 	if (intel_irqs_enabled(dev_priv))
2354ad22d106SVille Syrjälä 		vlv_display_irq_reset(dev_priv);
2355f8b79e58SImre Deak }
2356f8b79e58SImre Deak 
23570e6c9a9eSVille Syrjälä 
2358b318b824SVille Syrjälä static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
23590e6c9a9eSVille Syrjälä {
23602cbc876dSMichał Winiarski 	gen5_gt_irq_postinstall(to_gt(dev_priv));
23617e231dbeSJesse Barnes 
2362ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
23639918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
2364ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
2365ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
2366ad22d106SVille Syrjälä 
23672939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
23682939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER);
236920afbda2SDaniel Vetter }
237020afbda2SDaniel Vetter 
2371abd58f01SBen Widawsky static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
2372abd58f01SBen Widawsky {
2373b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2374b16b2a2fSPaulo Zanoni 
2375869129eeSMatt Roper 	u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
2376869129eeSMatt Roper 		GEN8_PIPE_CDCLK_CRC_DONE;
2377a9c287c9SJani Nikula 	u32 de_pipe_enables;
2378054318c7SImre Deak 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
23793a3b3c7dSVille Syrjälä 	u32 de_port_enables;
2380df0d28c1SDhinakaran Pandiyan 	u32 de_misc_masked = GEN8_DE_EDP_PSR;
2381562ddcb7SMatt Roper 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
2382562ddcb7SMatt Roper 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
23833a3b3c7dSVille Syrjälä 	enum pipe pipe;
2384770de83dSDamien Lespiau 
2385a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2386a844cfbeSJosé Roberto de Souza 		return;
2387a844cfbeSJosé Roberto de Souza 
2388373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) <= 10)
2389df0d28c1SDhinakaran Pandiyan 		de_misc_masked |= GEN8_DE_MISC_GSE;
2390df0d28c1SDhinakaran Pandiyan 
239170bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
23923a3b3c7dSVille Syrjälä 		de_port_masked |= BXT_DE_PORT_GMBUS;
2393a324fcacSRodrigo Vivi 
2394373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
23959c9e97c4SVandita Kulkarni 		enum port port;
23969c9e97c4SVandita Kulkarni 
23979c9e97c4SVandita Kulkarni 		if (intel_bios_is_dsi_present(dev_priv, &port))
23989c9e97c4SVandita Kulkarni 			de_port_masked |= DSI0_TE | DSI1_TE;
23999c9e97c4SVandita Kulkarni 	}
24009c9e97c4SVandita Kulkarni 
2401cda195f1SVille Syrjälä 	de_pipe_enables = de_pipe_masked |
24028bcc0840SMatt Roper 		GEN8_PIPE_VBLANK |
24038bcc0840SMatt Roper 		gen8_de_pipe_underrun_mask(dev_priv) |
2404cda195f1SVille Syrjälä 		gen8_de_pipe_flip_done_mask(dev_priv);
24051288f9b0SKarthik B S 
24063a3b3c7dSVille Syrjälä 	de_port_enables = de_port_masked;
240770bfb307SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
2408a52bb15bSVille Syrjälä 		de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
2409a52bb15bSVille Syrjälä 	else if (IS_BROADWELL(dev_priv))
2410e5abaab3SVille Syrjälä 		de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
24113a3b3c7dSVille Syrjälä 
2412373abf1aSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
24138241cfbeSJosé Roberto de Souza 		enum transcoder trans;
24148241cfbeSJosé Roberto de Souza 
2415562ddcb7SMatt Roper 		for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
24168241cfbeSJosé Roberto de Souza 			enum intel_display_power_domain domain;
24178241cfbeSJosé Roberto de Souza 
24188241cfbeSJosé Roberto de Souza 			domain = POWER_DOMAIN_TRANSCODER(trans);
24198241cfbeSJosé Roberto de Souza 			if (!intel_display_power_is_enabled(dev_priv, domain))
24208241cfbeSJosé Roberto de Souza 				continue;
24218241cfbeSJosé Roberto de Souza 
24228241cfbeSJosé Roberto de Souza 			gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
24238241cfbeSJosé Roberto de Souza 		}
24248241cfbeSJosé Roberto de Souza 	} else {
2425b16b2a2fSPaulo Zanoni 		gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
24268241cfbeSJosé Roberto de Souza 	}
2427e04f7eceSVille Syrjälä 
24280a195c02SMika Kahola 	for_each_pipe(dev_priv, pipe) {
24290a195c02SMika Kahola 		dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
2430abd58f01SBen Widawsky 
2431f458ebbcSDaniel Vetter 		if (intel_display_power_is_enabled(dev_priv,
2432813bde43SPaulo Zanoni 				POWER_DOMAIN_PIPE(pipe)))
2433b16b2a2fSPaulo Zanoni 			GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
2434813bde43SPaulo Zanoni 					  dev_priv->de_irq_mask[pipe],
243535079899SPaulo Zanoni 					  de_pipe_enables);
24360a195c02SMika Kahola 	}
2437abd58f01SBen Widawsky 
2438b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
2439b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
24402a57d9ccSImre Deak 
2441babde06dSMika Kahola 	if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
2442121e758eSDhinakaran Pandiyan 		u32 de_hpd_masked = 0;
2443b796b971SDhinakaran Pandiyan 		u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
2444b796b971SDhinakaran Pandiyan 				     GEN11_DE_TBT_HOTPLUG_MASK;
2445121e758eSDhinakaran Pandiyan 
2446b16b2a2fSPaulo Zanoni 		GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
2447b16b2a2fSPaulo Zanoni 			      de_hpd_enables);
2448abd58f01SBen Widawsky 	}
2449121e758eSDhinakaran Pandiyan }
2450abd58f01SBen Widawsky 
2451babde06dSMika Kahola static void mtp_irq_postinstall(struct drm_i915_private *i915)
2452babde06dSMika Kahola {
2453babde06dSMika Kahola 	struct intel_uncore *uncore = &i915->uncore;
2454babde06dSMika Kahola 	u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
2455babde06dSMika Kahola 	u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
2456babde06dSMika Kahola 	u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
2457babde06dSMika Kahola 			     XELPDP_TBT_HOTPLUG_MASK;
2458babde06dSMika Kahola 
2459babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
2460babde06dSMika Kahola 		      de_hpd_enables);
2461babde06dSMika Kahola 
2462babde06dSMika Kahola 	GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
2463babde06dSMika Kahola }
2464babde06dSMika Kahola 
246559b7cb44STejas Upadhyay static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
246659b7cb44STejas Upadhyay {
246759b7cb44STejas Upadhyay 	struct intel_uncore *uncore = &dev_priv->uncore;
246859b7cb44STejas Upadhyay 	u32 mask = SDE_GMBUS_ICP;
246959b7cb44STejas Upadhyay 
247059b7cb44STejas Upadhyay 	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
247159b7cb44STejas Upadhyay }
247259b7cb44STejas Upadhyay 
2473b318b824SVille Syrjälä static void gen8_irq_postinstall(struct drm_i915_private *dev_priv)
2474abd58f01SBen Widawsky {
247559b7cb44STejas Upadhyay 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
247659b7cb44STejas Upadhyay 		icp_irq_postinstall(dev_priv);
247759b7cb44STejas Upadhyay 	else if (HAS_PCH_SPLIT(dev_priv))
2478a0a6d8cbSVille Syrjälä 		ibx_irq_postinstall(dev_priv);
2479622364b6SPaulo Zanoni 
24802cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
2481abd58f01SBen Widawsky 	gen8_de_irq_postinstall(dev_priv);
2482abd58f01SBen Widawsky 
248325286aacSDaniele Ceraolo Spurio 	gen8_master_intr_enable(dev_priv->uncore.regs);
2484abd58f01SBen Widawsky }
2485abd58f01SBen Widawsky 
2486a844cfbeSJosé Roberto de Souza static void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
2487a844cfbeSJosé Roberto de Souza {
2488a844cfbeSJosé Roberto de Souza 	if (!HAS_DISPLAY(dev_priv))
2489a844cfbeSJosé Roberto de Souza 		return;
2490a844cfbeSJosé Roberto de Souza 
2491a844cfbeSJosé Roberto de Souza 	gen8_de_irq_postinstall(dev_priv);
2492a844cfbeSJosé Roberto de Souza 
2493a844cfbeSJosé Roberto de Souza 	intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
2494a844cfbeSJosé Roberto de Souza 			   GEN11_DISPLAY_IRQ_ENABLE);
2495a844cfbeSJosé Roberto de Souza }
249631604222SAnusha Srivatsa 
2497b318b824SVille Syrjälä static void gen11_irq_postinstall(struct drm_i915_private *dev_priv)
249851951ae7SMika Kuoppala {
24992cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2500fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
2501df0d28c1SDhinakaran Pandiyan 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
250251951ae7SMika Kuoppala 
250329b43ae2SRodrigo Vivi 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
2504b318b824SVille Syrjälä 		icp_irq_postinstall(dev_priv);
250531604222SAnusha Srivatsa 
2506fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
2507a844cfbeSJosé Roberto de Souza 	gen11_de_irq_postinstall(dev_priv);
250851951ae7SMika Kuoppala 
2509b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
2510df0d28c1SDhinakaran Pandiyan 
25119b77011eSTvrtko Ursulin 	gen11_master_intr_enable(uncore->regs);
25122939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ);
251351951ae7SMika Kuoppala }
251422e26af7SPaulo Zanoni 
251522e26af7SPaulo Zanoni static void dg1_irq_postinstall(struct drm_i915_private *dev_priv)
251622e26af7SPaulo Zanoni {
25172cbc876dSMichał Winiarski 	struct intel_gt *gt = to_gt(dev_priv);
2518fd4d7904SPaulo Zanoni 	struct intel_uncore *uncore = gt->uncore;
251922e26af7SPaulo Zanoni 	u32 gu_misc_masked = GEN11_GU_MISC_GSE;
252022e26af7SPaulo Zanoni 
2521fd4d7904SPaulo Zanoni 	gen11_gt_irq_postinstall(gt);
252222e26af7SPaulo Zanoni 
252322e26af7SPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked);
252422e26af7SPaulo Zanoni 
252522e26af7SPaulo Zanoni 	if (HAS_DISPLAY(dev_priv)) {
2526babde06dSMika Kahola 		if (DISPLAY_VER(dev_priv) >= 14)
2527babde06dSMika Kahola 			mtp_irq_postinstall(dev_priv);
2528babde06dSMika Kahola 		else
252922e26af7SPaulo Zanoni 			icp_irq_postinstall(dev_priv);
2530babde06dSMika Kahola 
253122e26af7SPaulo Zanoni 		gen8_de_irq_postinstall(dev_priv);
253222e26af7SPaulo Zanoni 		intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
253322e26af7SPaulo Zanoni 				   GEN11_DISPLAY_IRQ_ENABLE);
253422e26af7SPaulo Zanoni 	}
253522e26af7SPaulo Zanoni 
2536fd4d7904SPaulo Zanoni 	dg1_master_intr_enable(uncore->regs);
2537fd4d7904SPaulo Zanoni 	intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR);
253897b492f5SLucas De Marchi }
253951951ae7SMika Kuoppala 
2540b318b824SVille Syrjälä static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
254143f328d7SVille Syrjälä {
25422cbc876dSMichał Winiarski 	gen8_gt_irq_postinstall(to_gt(dev_priv));
254343f328d7SVille Syrjälä 
2544ad22d106SVille Syrjälä 	spin_lock_irq(&dev_priv->irq_lock);
25459918271eSVille Syrjälä 	if (dev_priv->display_irqs_enabled)
2546ad22d106SVille Syrjälä 		vlv_display_irq_postinstall(dev_priv);
2547ad22d106SVille Syrjälä 	spin_unlock_irq(&dev_priv->irq_lock);
2548ad22d106SVille Syrjälä 
25492939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
25502939eb06SJani Nikula 	intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
255143f328d7SVille Syrjälä }
255243f328d7SVille Syrjälä 
2553b318b824SVille Syrjälä static void i8xx_irq_reset(struct drm_i915_private *dev_priv)
2554c2798b19SChris Wilson {
2555b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2556c2798b19SChris Wilson 
255744d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
255844d9241eSVille Syrjälä 
2559ad7632ffSJani Nikula 	gen2_irq_reset(uncore);
2560e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
2561c2798b19SChris Wilson }
2562c2798b19SChris Wilson 
25633687ce75SVille Syrjälä static u32 i9xx_error_mask(struct drm_i915_private *i915)
25643687ce75SVille Syrjälä {
2565e7e12f6eSVille Syrjälä 	/*
2566e7e12f6eSVille Syrjälä 	 * On gen2/3 FBC generates (seemingly spurious)
2567e7e12f6eSVille Syrjälä 	 * display INVALID_GTT/INVALID_GTT_PTE table errors.
2568e7e12f6eSVille Syrjälä 	 *
2569e7e12f6eSVille Syrjälä 	 * Also gen3 bspec has this to say:
2570e7e12f6eSVille Syrjälä 	 * "DISPA_INVALID_GTT_PTE
2571e7e12f6eSVille Syrjälä 	 "  [DevNapa] : Reserved. This bit does not reflect the page
2572e7e12f6eSVille Syrjälä 	 "              table error for the display plane A."
2573e7e12f6eSVille Syrjälä 	 *
2574e7e12f6eSVille Syrjälä 	 * Unfortunately we can't mask off individual PGTBL_ER bits,
2575e7e12f6eSVille Syrjälä 	 * so we just have to mask off all page table errors via EMR.
2576e7e12f6eSVille Syrjälä 	 */
2577e7e12f6eSVille Syrjälä 	if (HAS_FBC(i915))
2578e7e12f6eSVille Syrjälä 		return ~I915_ERROR_MEMORY_REFRESH;
2579e7e12f6eSVille Syrjälä 	else
25803687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
25813687ce75SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
25823687ce75SVille Syrjälä }
25833687ce75SVille Syrjälä 
2584b318b824SVille Syrjälä static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv)
2585c2798b19SChris Wilson {
2586b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2587e9e9848aSVille Syrjälä 	u16 enable_mask;
2588c2798b19SChris Wilson 
25893687ce75SVille Syrjälä 	intel_uncore_write16(uncore, EMR, i9xx_error_mask(dev_priv));
2590c2798b19SChris Wilson 
2591c2798b19SChris Wilson 	/* Unmask the interrupts that we always want on. */
2592c2798b19SChris Wilson 	dev_priv->irq_mask =
2593c2798b19SChris Wilson 		~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
259416659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
259516659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
2596c2798b19SChris Wilson 
2597e9e9848aSVille Syrjälä 	enable_mask =
2598c2798b19SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
2599c2798b19SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
260016659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
2601e9e9848aSVille Syrjälä 		I915_USER_INTERRUPT;
2602e9e9848aSVille Syrjälä 
2603ad7632ffSJani Nikula 	gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask);
2604c2798b19SChris Wilson 
2605379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
2606379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
2607d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
2608755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
2609755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
2610d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
2611c2798b19SChris Wilson }
2612c2798b19SChris Wilson 
26134f5fd91fSTvrtko Ursulin static void i8xx_error_irq_ack(struct drm_i915_private *i915,
261478c357ddSVille Syrjälä 			       u16 *eir, u16 *eir_stuck)
261578c357ddSVille Syrjälä {
26164f5fd91fSTvrtko Ursulin 	struct intel_uncore *uncore = &i915->uncore;
261778c357ddSVille Syrjälä 	u16 emr;
261878c357ddSVille Syrjälä 
26194f5fd91fSTvrtko Ursulin 	*eir = intel_uncore_read16(uncore, EIR);
26204f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EIR, *eir);
262178c357ddSVille Syrjälä 
26224f5fd91fSTvrtko Ursulin 	*eir_stuck = intel_uncore_read16(uncore, EIR);
262378c357ddSVille Syrjälä 	if (*eir_stuck == 0)
262478c357ddSVille Syrjälä 		return;
262578c357ddSVille Syrjälä 
262678c357ddSVille Syrjälä 	/*
262778c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
262878c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
262978c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
263078c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
263178c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
263278c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
263378c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
263478c357ddSVille Syrjälä 	 * remains set.
263578c357ddSVille Syrjälä 	 */
26364f5fd91fSTvrtko Ursulin 	emr = intel_uncore_read16(uncore, EMR);
26374f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, 0xffff);
26384f5fd91fSTvrtko Ursulin 	intel_uncore_write16(uncore, EMR, emr | *eir_stuck);
263978c357ddSVille Syrjälä }
264078c357ddSVille Syrjälä 
264178c357ddSVille Syrjälä static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv,
264278c357ddSVille Syrjälä 				   u16 eir, u16 eir_stuck)
264378c357ddSVille Syrjälä {
2644a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir);
264578c357ddSVille Syrjälä 
264678c357ddSVille Syrjälä 	if (eir_stuck)
264700376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n",
264800376ccfSWambui Karuga 			eir_stuck);
2649d1e89592SVille Syrjälä 
2650d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
2651d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
265278c357ddSVille Syrjälä }
265378c357ddSVille Syrjälä 
265478c357ddSVille Syrjälä static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
265578c357ddSVille Syrjälä 			       u32 *eir, u32 *eir_stuck)
265678c357ddSVille Syrjälä {
265778c357ddSVille Syrjälä 	u32 emr;
265878c357ddSVille Syrjälä 
2659839259b8SVille Syrjälä 	*eir = intel_uncore_read(&dev_priv->uncore, EIR);
2660839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EIR, *eir);
266178c357ddSVille Syrjälä 
26622939eb06SJani Nikula 	*eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR);
266378c357ddSVille Syrjälä 	if (*eir_stuck == 0)
266478c357ddSVille Syrjälä 		return;
266578c357ddSVille Syrjälä 
266678c357ddSVille Syrjälä 	/*
266778c357ddSVille Syrjälä 	 * Toggle all EMR bits to make sure we get an edge
266878c357ddSVille Syrjälä 	 * in the ISR master error bit if we don't clear
266978c357ddSVille Syrjälä 	 * all the EIR bits. Otherwise the edge triggered
267078c357ddSVille Syrjälä 	 * IIR on i965/g4x wouldn't notice that an interrupt
267178c357ddSVille Syrjälä 	 * is still pending. Also some EIR bits can't be
267278c357ddSVille Syrjälä 	 * cleared except by handling the underlying error
267378c357ddSVille Syrjälä 	 * (or by a GPU reset) so we mask any bit that
267478c357ddSVille Syrjälä 	 * remains set.
267578c357ddSVille Syrjälä 	 */
2676839259b8SVille Syrjälä 	emr = intel_uncore_read(&dev_priv->uncore, EMR);
2677839259b8SVille Syrjälä 	intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff);
26782939eb06SJani Nikula 	intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck);
267978c357ddSVille Syrjälä }
268078c357ddSVille Syrjälä 
268178c357ddSVille Syrjälä static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv,
268278c357ddSVille Syrjälä 				   u32 eir, u32 eir_stuck)
268378c357ddSVille Syrjälä {
2684a10234fdSTvrtko Ursulin 	drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir);
268578c357ddSVille Syrjälä 
268678c357ddSVille Syrjälä 	if (eir_stuck)
268700376ccfSWambui Karuga 		drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n",
268800376ccfSWambui Karuga 			eir_stuck);
2689d1e89592SVille Syrjälä 
2690d1e89592SVille Syrjälä 	drm_dbg(&dev_priv->drm, "PGTBL_ER: 0x%08x\n",
2691d1e89592SVille Syrjälä 		intel_uncore_read(&dev_priv->uncore, PGTBL_ER));
269278c357ddSVille Syrjälä }
269378c357ddSVille Syrjälä 
2694ff1f525eSDaniel Vetter static irqreturn_t i8xx_irq_handler(int irq, void *arg)
2695c2798b19SChris Wilson {
2696b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
2697af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
2698c2798b19SChris Wilson 
26992dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
27002dd2a883SImre Deak 		return IRQ_NONE;
27012dd2a883SImre Deak 
27021f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
27039102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
27041f814dacSImre Deak 
2705af722d28SVille Syrjälä 	do {
2706af722d28SVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
270778c357ddSVille Syrjälä 		u16 eir = 0, eir_stuck = 0;
2708af722d28SVille Syrjälä 		u16 iir;
2709af722d28SVille Syrjälä 
27104f5fd91fSTvrtko Ursulin 		iir = intel_uncore_read16(&dev_priv->uncore, GEN2_IIR);
2711c2798b19SChris Wilson 		if (iir == 0)
2712af722d28SVille Syrjälä 			break;
2713c2798b19SChris Wilson 
2714af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
2715c2798b19SChris Wilson 
2716eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
2717eb64343cSVille Syrjälä 		 * signalled in iir */
2718eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
2719c2798b19SChris Wilson 
272078c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
272178c357ddSVille Syrjälä 			i8xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
272278c357ddSVille Syrjälä 
27234f5fd91fSTvrtko Ursulin 		intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir);
2724c2798b19SChris Wilson 
2725c2798b19SChris Wilson 		if (iir & I915_USER_INTERRUPT)
27262cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
2727c2798b19SChris Wilson 
272878c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
272978c357ddSVille Syrjälä 			i8xx_error_irq_handler(dev_priv, eir, eir_stuck);
2730af722d28SVille Syrjälä 
2731eb64343cSVille Syrjälä 		i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats);
2732af722d28SVille Syrjälä 	} while (0);
2733c2798b19SChris Wilson 
27349c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
27359c6508b9SThomas Gleixner 
27369102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
27371f814dacSImre Deak 
27381f814dacSImre Deak 	return ret;
2739c2798b19SChris Wilson }
2740c2798b19SChris Wilson 
2741b318b824SVille Syrjälä static void i915_irq_reset(struct drm_i915_private *dev_priv)
2742a266c7d5SChris Wilson {
2743b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2744a266c7d5SChris Wilson 
274556b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
27460706f17cSEgbert Eich 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
27478cee664dSAndrzej Hajda 		intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0);
2748a266c7d5SChris Wilson 	}
2749a266c7d5SChris Wilson 
275044d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
275144d9241eSVille Syrjälä 
2752b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
2753e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
2754a266c7d5SChris Wilson }
2755a266c7d5SChris Wilson 
2756b318b824SVille Syrjälä static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
2757a266c7d5SChris Wilson {
2758b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
275938bde180SChris Wilson 	u32 enable_mask;
2760a266c7d5SChris Wilson 
27613687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv));
276238bde180SChris Wilson 
276338bde180SChris Wilson 	/* Unmask the interrupts that we always want on. */
276438bde180SChris Wilson 	dev_priv->irq_mask =
276538bde180SChris Wilson 		~(I915_ASLE_INTERRUPT |
276638bde180SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
276716659bc5SVille Syrjälä 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
276816659bc5SVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
276938bde180SChris Wilson 
277038bde180SChris Wilson 	enable_mask =
277138bde180SChris Wilson 		I915_ASLE_INTERRUPT |
277238bde180SChris Wilson 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
277338bde180SChris Wilson 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
277416659bc5SVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
277538bde180SChris Wilson 		I915_USER_INTERRUPT;
277638bde180SChris Wilson 
277756b857a5STvrtko Ursulin 	if (I915_HAS_HOTPLUG(dev_priv)) {
2778a266c7d5SChris Wilson 		/* Enable in IER... */
2779a266c7d5SChris Wilson 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
2780a266c7d5SChris Wilson 		/* and unmask in IMR */
2781a266c7d5SChris Wilson 		dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
2782a266c7d5SChris Wilson 	}
2783a266c7d5SChris Wilson 
2784b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
2785a266c7d5SChris Wilson 
2786379ef82dSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
2787379ef82dSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
2788d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
2789755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
2790755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
2791d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
2792379ef82dSDaniel Vetter 
2793c30bb1fdSVille Syrjälä 	i915_enable_asle_pipestat(dev_priv);
279420afbda2SDaniel Vetter }
279520afbda2SDaniel Vetter 
2796ff1f525eSDaniel Vetter static irqreturn_t i915_irq_handler(int irq, void *arg)
2797a266c7d5SChris Wilson {
2798b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
2799af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
2800a266c7d5SChris Wilson 
28012dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
28022dd2a883SImre Deak 		return IRQ_NONE;
28032dd2a883SImre Deak 
28041f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
28059102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
28061f814dacSImre Deak 
280738bde180SChris Wilson 	do {
2808eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
280978c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
2810af722d28SVille Syrjälä 		u32 hotplug_status = 0;
2811af722d28SVille Syrjälä 		u32 iir;
2812a266c7d5SChris Wilson 
28132939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
2814af722d28SVille Syrjälä 		if (iir == 0)
2815af722d28SVille Syrjälä 			break;
2816af722d28SVille Syrjälä 
2817af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
2818af722d28SVille Syrjälä 
2819af722d28SVille Syrjälä 		if (I915_HAS_HOTPLUG(dev_priv) &&
2820af722d28SVille Syrjälä 		    iir & I915_DISPLAY_PORT_INTERRUPT)
2821af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
2822a266c7d5SChris Wilson 
2823eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
2824eb64343cSVille Syrjälä 		 * signalled in iir */
2825eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
2826a266c7d5SChris Wilson 
282778c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
282878c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
282978c357ddSVille Syrjälä 
28302939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
2831a266c7d5SChris Wilson 
2832a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
28332cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0], iir);
2834a266c7d5SChris Wilson 
283578c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
283678c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
2837a266c7d5SChris Wilson 
2838af722d28SVille Syrjälä 		if (hotplug_status)
2839af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
2840af722d28SVille Syrjälä 
2841af722d28SVille Syrjälä 		i915_pipestat_irq_handler(dev_priv, iir, pipe_stats);
2842af722d28SVille Syrjälä 	} while (0);
2843a266c7d5SChris Wilson 
28449c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, ret);
28459c6508b9SThomas Gleixner 
28469102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
28471f814dacSImre Deak 
2848a266c7d5SChris Wilson 	return ret;
2849a266c7d5SChris Wilson }
2850a266c7d5SChris Wilson 
2851b318b824SVille Syrjälä static void i965_irq_reset(struct drm_i915_private *dev_priv)
2852a266c7d5SChris Wilson {
2853b16b2a2fSPaulo Zanoni 	struct intel_uncore *uncore = &dev_priv->uncore;
2854a266c7d5SChris Wilson 
28550706f17cSEgbert Eich 	i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
28568cee664dSAndrzej Hajda 	intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
2857a266c7d5SChris Wilson 
285844d9241eSVille Syrjälä 	i9xx_pipestat_irq_reset(dev_priv);
285944d9241eSVille Syrjälä 
2860b16b2a2fSPaulo Zanoni 	GEN3_IRQ_RESET(uncore, GEN2_);
2861e44adb5dSChris Wilson 	dev_priv->irq_mask = ~0u;
2862a266c7d5SChris Wilson }
2863a266c7d5SChris Wilson 
28643687ce75SVille Syrjälä static u32 i965_error_mask(struct drm_i915_private *i915)
2865a266c7d5SChris Wilson {
2866045cebd2SVille Syrjälä 	/*
2867045cebd2SVille Syrjälä 	 * Enable some error detection, note the instruction error mask
2868045cebd2SVille Syrjälä 	 * bit is reserved, so we leave it masked.
2869e7e12f6eSVille Syrjälä 	 *
2870e7e12f6eSVille Syrjälä 	 * i965 FBC no longer generates spurious GTT errors,
2871e7e12f6eSVille Syrjälä 	 * so we can always enable the page table errors.
2872045cebd2SVille Syrjälä 	 */
28733687ce75SVille Syrjälä 	if (IS_G4X(i915))
28743687ce75SVille Syrjälä 		return ~(GM45_ERROR_PAGE_TABLE |
2875045cebd2SVille Syrjälä 			 GM45_ERROR_MEM_PRIV |
2876045cebd2SVille Syrjälä 			 GM45_ERROR_CP_PRIV |
2877045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
28783687ce75SVille Syrjälä 	else
28793687ce75SVille Syrjälä 		return ~(I915_ERROR_PAGE_TABLE |
2880045cebd2SVille Syrjälä 			 I915_ERROR_MEMORY_REFRESH);
2881045cebd2SVille Syrjälä }
28823687ce75SVille Syrjälä 
28833687ce75SVille Syrjälä static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
28843687ce75SVille Syrjälä {
28853687ce75SVille Syrjälä 	struct intel_uncore *uncore = &dev_priv->uncore;
28863687ce75SVille Syrjälä 	u32 enable_mask;
28873687ce75SVille Syrjälä 
28883687ce75SVille Syrjälä 	intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv));
2889045cebd2SVille Syrjälä 
2890a266c7d5SChris Wilson 	/* Unmask the interrupts that we always want on. */
2891c30bb1fdSVille Syrjälä 	dev_priv->irq_mask =
2892c30bb1fdSVille Syrjälä 		~(I915_ASLE_INTERRUPT |
2893adca4730SChris Wilson 		  I915_DISPLAY_PORT_INTERRUPT |
2894bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
2895bbba0a97SChris Wilson 		  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
289678c357ddSVille Syrjälä 		  I915_MASTER_ERROR_INTERRUPT);
2897bbba0a97SChris Wilson 
2898c30bb1fdSVille Syrjälä 	enable_mask =
2899c30bb1fdSVille Syrjälä 		I915_ASLE_INTERRUPT |
2900c30bb1fdSVille Syrjälä 		I915_DISPLAY_PORT_INTERRUPT |
2901c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
2902c30bb1fdSVille Syrjälä 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
290378c357ddSVille Syrjälä 		I915_MASTER_ERROR_INTERRUPT |
2904c30bb1fdSVille Syrjälä 		I915_USER_INTERRUPT;
2905bbba0a97SChris Wilson 
290691d14251STvrtko Ursulin 	if (IS_G4X(dev_priv))
2907bbba0a97SChris Wilson 		enable_mask |= I915_BSD_USER_INTERRUPT;
2908a266c7d5SChris Wilson 
2909b16b2a2fSPaulo Zanoni 	GEN3_IRQ_INIT(uncore, GEN2_, dev_priv->irq_mask, enable_mask);
2910c30bb1fdSVille Syrjälä 
2911b79480baSDaniel Vetter 	/* Interrupt setup is already guaranteed to be single-threaded, this is
2912b79480baSDaniel Vetter 	 * just to make the assert_spin_locked check happy. */
2913d6207435SDaniel Vetter 	spin_lock_irq(&dev_priv->irq_lock);
2914755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
2915755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
2916755e9019SImre Deak 	i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
2917d6207435SDaniel Vetter 	spin_unlock_irq(&dev_priv->irq_lock);
2918a266c7d5SChris Wilson 
291991d14251STvrtko Ursulin 	i915_enable_asle_pipestat(dev_priv);
292020afbda2SDaniel Vetter }
292120afbda2SDaniel Vetter 
2922ff1f525eSDaniel Vetter static irqreturn_t i965_irq_handler(int irq, void *arg)
2923a266c7d5SChris Wilson {
2924b318b824SVille Syrjälä 	struct drm_i915_private *dev_priv = arg;
2925af722d28SVille Syrjälä 	irqreturn_t ret = IRQ_NONE;
2926a266c7d5SChris Wilson 
29272dd2a883SImre Deak 	if (!intel_irqs_enabled(dev_priv))
29282dd2a883SImre Deak 		return IRQ_NONE;
29292dd2a883SImre Deak 
29301f814dacSImre Deak 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
29319102650fSDaniele Ceraolo Spurio 	disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
29321f814dacSImre Deak 
2933af722d28SVille Syrjälä 	do {
2934eb64343cSVille Syrjälä 		u32 pipe_stats[I915_MAX_PIPES] = {};
293578c357ddSVille Syrjälä 		u32 eir = 0, eir_stuck = 0;
2936af722d28SVille Syrjälä 		u32 hotplug_status = 0;
2937af722d28SVille Syrjälä 		u32 iir;
29382c8ba29fSChris Wilson 
29392939eb06SJani Nikula 		iir = intel_uncore_read(&dev_priv->uncore, GEN2_IIR);
2940af722d28SVille Syrjälä 		if (iir == 0)
2941af722d28SVille Syrjälä 			break;
2942af722d28SVille Syrjälä 
2943af722d28SVille Syrjälä 		ret = IRQ_HANDLED;
2944af722d28SVille Syrjälä 
2945af722d28SVille Syrjälä 		if (iir & I915_DISPLAY_PORT_INTERRUPT)
2946af722d28SVille Syrjälä 			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
2947a266c7d5SChris Wilson 
2948eb64343cSVille Syrjälä 		/* Call regardless, as some status bits might not be
2949eb64343cSVille Syrjälä 		 * signalled in iir */
2950eb64343cSVille Syrjälä 		i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
2951a266c7d5SChris Wilson 
295278c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
295378c357ddSVille Syrjälä 			i9xx_error_irq_ack(dev_priv, &eir, &eir_stuck);
295478c357ddSVille Syrjälä 
29552939eb06SJani Nikula 		intel_uncore_write(&dev_priv->uncore, GEN2_IIR, iir);
2956a266c7d5SChris Wilson 
2957a266c7d5SChris Wilson 		if (iir & I915_USER_INTERRUPT)
29582cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[RCS0],
29590669a6e1SChris Wilson 					    iir);
2960af722d28SVille Syrjälä 
2961a266c7d5SChris Wilson 		if (iir & I915_BSD_USER_INTERRUPT)
29622cbc876dSMichał Winiarski 			intel_engine_cs_irq(to_gt(dev_priv)->engine[VCS0],
29630669a6e1SChris Wilson 					    iir >> 25);
2964a266c7d5SChris Wilson 
296578c357ddSVille Syrjälä 		if (iir & I915_MASTER_ERROR_INTERRUPT)
296678c357ddSVille Syrjälä 			i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
2967515ac2bbSDaniel Vetter 
2968af722d28SVille Syrjälä 		if (hotplug_status)
2969af722d28SVille Syrjälä 			i9xx_hpd_irq_handler(dev_priv, hotplug_status);
2970af722d28SVille Syrjälä 
2971af722d28SVille Syrjälä 		i965_pipestat_irq_handler(dev_priv, iir, pipe_stats);
2972af722d28SVille Syrjälä 	} while (0);
2973a266c7d5SChris Wilson 
29749c6508b9SThomas Gleixner 	pmu_irq_stats(dev_priv, IRQ_HANDLED);
29759c6508b9SThomas Gleixner 
29769102650fSDaniele Ceraolo Spurio 	enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
29771f814dacSImre Deak 
2978a266c7d5SChris Wilson 	return ret;
2979a266c7d5SChris Wilson }
2980a266c7d5SChris Wilson 
2981fca52a55SDaniel Vetter /**
2982fca52a55SDaniel Vetter  * intel_irq_init - initializes irq support
2983fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
2984fca52a55SDaniel Vetter  *
2985fca52a55SDaniel Vetter  * This function initializes all the irq support including work items, timers
2986fca52a55SDaniel Vetter  * and all the vtables. It does not setup the interrupt itself though.
2987fca52a55SDaniel Vetter  */
2988b963291cSDaniel Vetter void intel_irq_init(struct drm_i915_private *dev_priv)
2989f71d4af4SJesse Barnes {
2990cefcff8fSJoonas Lahtinen 	int i;
29918b2e326dSChris Wilson 
299274bb98baSLucas De Marchi 	INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work);
2993cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
2994cefcff8fSJoonas Lahtinen 		dev_priv->l3_parity.remap_info[i] = NULL;
29958b2e326dSChris Wilson 
2996633023a4SDaniele Ceraolo Spurio 	/* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */
2997651e7d48SLucas De Marchi 	if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11)
29982cbc876dSMichał Winiarski 		to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16;
299926705e20SSagar Arun Kamble 
30009a450b68SLucas De Marchi 	if (!HAS_DISPLAY(dev_priv))
30019a450b68SLucas De Marchi 		return;
30029a450b68SLucas De Marchi 
30033703060dSAndrzej Hajda 	dev_priv->drm.vblank_disable_immediate = true;
300421da2700SVille Syrjälä 
3005262fd485SChris Wilson 	/* Most platforms treat the display irq block as an always-on
3006262fd485SChris Wilson 	 * power domain. vlv/chv can disable it at runtime and need
3007262fd485SChris Wilson 	 * special care to avoid writing any of the display block registers
3008262fd485SChris Wilson 	 * outside of the power domain. We defer setting up the display irqs
3009262fd485SChris Wilson 	 * in this case to the runtime pm.
3010262fd485SChris Wilson 	 */
3011262fd485SChris Wilson 	dev_priv->display_irqs_enabled = true;
3012262fd485SChris Wilson 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
3013262fd485SChris Wilson 		dev_priv->display_irqs_enabled = false;
3014262fd485SChris Wilson 
3015*da38ba98SJani Nikula 	intel_hotplug_irq_init(dev_priv);
30162ccf2e03SChris Wilson }
301720afbda2SDaniel Vetter 
3018fca52a55SDaniel Vetter /**
3019cefcff8fSJoonas Lahtinen  * intel_irq_fini - deinitializes IRQ support
3020cefcff8fSJoonas Lahtinen  * @i915: i915 device instance
3021cefcff8fSJoonas Lahtinen  *
3022cefcff8fSJoonas Lahtinen  * This function deinitializes all the IRQ support.
3023cefcff8fSJoonas Lahtinen  */
3024cefcff8fSJoonas Lahtinen void intel_irq_fini(struct drm_i915_private *i915)
3025cefcff8fSJoonas Lahtinen {
3026cefcff8fSJoonas Lahtinen 	int i;
3027cefcff8fSJoonas Lahtinen 
3028cefcff8fSJoonas Lahtinen 	for (i = 0; i < MAX_L3_SLICES; ++i)
3029cefcff8fSJoonas Lahtinen 		kfree(i915->l3_parity.remap_info[i]);
3030cefcff8fSJoonas Lahtinen }
3031cefcff8fSJoonas Lahtinen 
3032b318b824SVille Syrjälä static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv)
3033b318b824SVille Syrjälä {
3034b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
3035b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
3036b318b824SVille Syrjälä 			return cherryview_irq_handler;
3037b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
3038b318b824SVille Syrjälä 			return valleyview_irq_handler;
3039651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
3040b318b824SVille Syrjälä 			return i965_irq_handler;
3041651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
3042b318b824SVille Syrjälä 			return i915_irq_handler;
3043b318b824SVille Syrjälä 		else
3044b318b824SVille Syrjälä 			return i8xx_irq_handler;
3045b318b824SVille Syrjälä 	} else {
304622e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
304797b492f5SLucas De Marchi 			return dg1_irq_handler;
304822e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
3049b318b824SVille Syrjälä 			return gen11_irq_handler;
3050651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
3051b318b824SVille Syrjälä 			return gen8_irq_handler;
3052b318b824SVille Syrjälä 		else
30539eae5e27SLucas De Marchi 			return ilk_irq_handler;
3054b318b824SVille Syrjälä 	}
3055b318b824SVille Syrjälä }
3056b318b824SVille Syrjälä 
3057b318b824SVille Syrjälä static void intel_irq_reset(struct drm_i915_private *dev_priv)
3058b318b824SVille Syrjälä {
3059b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
3060b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
3061b318b824SVille Syrjälä 			cherryview_irq_reset(dev_priv);
3062b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
3063b318b824SVille Syrjälä 			valleyview_irq_reset(dev_priv);
3064651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
3065b318b824SVille Syrjälä 			i965_irq_reset(dev_priv);
3066651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
3067b318b824SVille Syrjälä 			i915_irq_reset(dev_priv);
3068b318b824SVille Syrjälä 		else
3069b318b824SVille Syrjälä 			i8xx_irq_reset(dev_priv);
3070b318b824SVille Syrjälä 	} else {
307122e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
307222e26af7SPaulo Zanoni 			dg1_irq_reset(dev_priv);
307322e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
3074b318b824SVille Syrjälä 			gen11_irq_reset(dev_priv);
3075651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
3076b318b824SVille Syrjälä 			gen8_irq_reset(dev_priv);
3077b318b824SVille Syrjälä 		else
30789eae5e27SLucas De Marchi 			ilk_irq_reset(dev_priv);
3079b318b824SVille Syrjälä 	}
3080b318b824SVille Syrjälä }
3081b318b824SVille Syrjälä 
3082b318b824SVille Syrjälä static void intel_irq_postinstall(struct drm_i915_private *dev_priv)
3083b318b824SVille Syrjälä {
3084b318b824SVille Syrjälä 	if (HAS_GMCH(dev_priv)) {
3085b318b824SVille Syrjälä 		if (IS_CHERRYVIEW(dev_priv))
3086b318b824SVille Syrjälä 			cherryview_irq_postinstall(dev_priv);
3087b318b824SVille Syrjälä 		else if (IS_VALLEYVIEW(dev_priv))
3088b318b824SVille Syrjälä 			valleyview_irq_postinstall(dev_priv);
3089651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 4)
3090b318b824SVille Syrjälä 			i965_irq_postinstall(dev_priv);
3091651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) == 3)
3092b318b824SVille Syrjälä 			i915_irq_postinstall(dev_priv);
3093b318b824SVille Syrjälä 		else
3094b318b824SVille Syrjälä 			i8xx_irq_postinstall(dev_priv);
3095b318b824SVille Syrjälä 	} else {
309622e26af7SPaulo Zanoni 		if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10))
309722e26af7SPaulo Zanoni 			dg1_irq_postinstall(dev_priv);
309822e26af7SPaulo Zanoni 		else if (GRAPHICS_VER(dev_priv) >= 11)
3099b318b824SVille Syrjälä 			gen11_irq_postinstall(dev_priv);
3100651e7d48SLucas De Marchi 		else if (GRAPHICS_VER(dev_priv) >= 8)
3101b318b824SVille Syrjälä 			gen8_irq_postinstall(dev_priv);
3102b318b824SVille Syrjälä 		else
31039eae5e27SLucas De Marchi 			ilk_irq_postinstall(dev_priv);
3104b318b824SVille Syrjälä 	}
3105b318b824SVille Syrjälä }
3106b318b824SVille Syrjälä 
3107cefcff8fSJoonas Lahtinen /**
3108fca52a55SDaniel Vetter  * intel_irq_install - enables the hardware interrupt
3109fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
3110fca52a55SDaniel Vetter  *
3111fca52a55SDaniel Vetter  * This function enables the hardware interrupt handling, but leaves the hotplug
3112fca52a55SDaniel Vetter  * handling still disabled. It is called after intel_irq_init().
3113fca52a55SDaniel Vetter  *
3114fca52a55SDaniel Vetter  * In the driver load and resume code we need working interrupts in a few places
3115fca52a55SDaniel Vetter  * but don't want to deal with the hassle of concurrent probe and hotplug
3116fca52a55SDaniel Vetter  * workers. Hence the split into this two-stage approach.
3117fca52a55SDaniel Vetter  */
31182aeb7d3aSDaniel Vetter int intel_irq_install(struct drm_i915_private *dev_priv)
31192aeb7d3aSDaniel Vetter {
31208ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
3121b318b824SVille Syrjälä 	int ret;
3122b318b824SVille Syrjälä 
31232aeb7d3aSDaniel Vetter 	/*
31242aeb7d3aSDaniel Vetter 	 * We enable some interrupt sources in our postinstall hooks, so mark
31252aeb7d3aSDaniel Vetter 	 * interrupts as enabled _before_ actually enabling them to avoid
31262aeb7d3aSDaniel Vetter 	 * special cases in our ordering checks.
31272aeb7d3aSDaniel Vetter 	 */
3128ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
31292aeb7d3aSDaniel Vetter 
3130ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = true;
3131b318b824SVille Syrjälä 
3132b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
3133b318b824SVille Syrjälä 
3134b318b824SVille Syrjälä 	ret = request_irq(irq, intel_irq_handler(dev_priv),
3135b318b824SVille Syrjälä 			  IRQF_SHARED, DRIVER_NAME, dev_priv);
3136b318b824SVille Syrjälä 	if (ret < 0) {
3137ac1723c1SThomas Zimmermann 		dev_priv->irq_enabled = false;
3138b318b824SVille Syrjälä 		return ret;
3139b318b824SVille Syrjälä 	}
3140b318b824SVille Syrjälä 
3141b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
3142b318b824SVille Syrjälä 
3143b318b824SVille Syrjälä 	return ret;
31442aeb7d3aSDaniel Vetter }
31452aeb7d3aSDaniel Vetter 
3146fca52a55SDaniel Vetter /**
3147fca52a55SDaniel Vetter  * intel_irq_uninstall - finilizes all irq handling
3148fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
3149fca52a55SDaniel Vetter  *
3150fca52a55SDaniel Vetter  * This stops interrupt and hotplug handling and unregisters and frees all
3151fca52a55SDaniel Vetter  * resources acquired in the init functions.
3152fca52a55SDaniel Vetter  */
31532aeb7d3aSDaniel Vetter void intel_irq_uninstall(struct drm_i915_private *dev_priv)
31542aeb7d3aSDaniel Vetter {
31558ff5446aSThomas Zimmermann 	int irq = to_pci_dev(dev_priv->drm.dev)->irq;
3156b318b824SVille Syrjälä 
3157b318b824SVille Syrjälä 	/*
3158789fa874SJanusz Krzysztofik 	 * FIXME we can get called twice during driver probe
3159789fa874SJanusz Krzysztofik 	 * error handling as well as during driver remove due to
316086a1758dSJani Nikula 	 * intel_display_driver_remove() calling us out of sequence.
3161789fa874SJanusz Krzysztofik 	 * Would be nice if it didn't do that...
3162b318b824SVille Syrjälä 	 */
3163ac1723c1SThomas Zimmermann 	if (!dev_priv->irq_enabled)
3164b318b824SVille Syrjälä 		return;
3165b318b824SVille Syrjälä 
3166ac1723c1SThomas Zimmermann 	dev_priv->irq_enabled = false;
3167b318b824SVille Syrjälä 
3168b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
3169b318b824SVille Syrjälä 
3170b318b824SVille Syrjälä 	free_irq(irq, dev_priv);
3171b318b824SVille Syrjälä 
31722aeb7d3aSDaniel Vetter 	intel_hpd_cancel_work(dev_priv);
3173ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
31742aeb7d3aSDaniel Vetter }
31752aeb7d3aSDaniel Vetter 
3176fca52a55SDaniel Vetter /**
3177fca52a55SDaniel Vetter  * intel_runtime_pm_disable_interrupts - runtime interrupt disabling
3178fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
3179fca52a55SDaniel Vetter  *
3180fca52a55SDaniel Vetter  * This function is used to disable interrupts at runtime, both in the runtime
3181fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
3182fca52a55SDaniel Vetter  */
3183b963291cSDaniel Vetter void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv)
3184c67a470bSPaulo Zanoni {
3185b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
3186ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = false;
3187315ca4c4SVille Syrjälä 	intel_synchronize_irq(dev_priv);
3188c67a470bSPaulo Zanoni }
3189c67a470bSPaulo Zanoni 
3190fca52a55SDaniel Vetter /**
3191fca52a55SDaniel Vetter  * intel_runtime_pm_enable_interrupts - runtime interrupt enabling
3192fca52a55SDaniel Vetter  * @dev_priv: i915 device instance
3193fca52a55SDaniel Vetter  *
3194fca52a55SDaniel Vetter  * This function is used to enable interrupts at runtime, both in the runtime
3195fca52a55SDaniel Vetter  * pm and the system suspend/resume code.
3196fca52a55SDaniel Vetter  */
3197b963291cSDaniel Vetter void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv)
3198c67a470bSPaulo Zanoni {
3199ad1443f0SSagar Arun Kamble 	dev_priv->runtime_pm.irqs_enabled = true;
3200b318b824SVille Syrjälä 	intel_irq_reset(dev_priv);
3201b318b824SVille Syrjälä 	intel_irq_postinstall(dev_priv);
3202c67a470bSPaulo Zanoni }
3203d64575eeSJani Nikula 
3204d64575eeSJani Nikula bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
3205d64575eeSJani Nikula {
3206d64575eeSJani Nikula 	return dev_priv->runtime_pm.irqs_enabled;
3207d64575eeSJani Nikula }
3208d64575eeSJani Nikula 
3209d64575eeSJani Nikula void intel_synchronize_irq(struct drm_i915_private *i915)
3210d64575eeSJani Nikula {
32118ff5446aSThomas Zimmermann 	synchronize_irq(to_pci_dev(i915->drm.dev)->irq);
3212d64575eeSJani Nikula }
3213320ad343SThomas Zimmermann 
3214320ad343SThomas Zimmermann void intel_synchronize_hardirq(struct drm_i915_private *i915)
3215320ad343SThomas Zimmermann {
3216320ad343SThomas Zimmermann 	synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq);
3217320ad343SThomas Zimmermann }
3218