12b874a02SJani Nikula // SPDX-License-Identifier: MIT
22b874a02SJani Nikula /*
32b874a02SJani Nikula * Copyright © 2023 Intel Corporation
42b874a02SJani Nikula */
52b874a02SJani Nikula
6d705a8c7SJani Nikula #include "gt/intel_rps.h"
72b874a02SJani Nikula #include "i915_drv.h"
82b874a02SJani Nikula #include "i915_irq.h"
92b874a02SJani Nikula #include "i915_reg.h"
102b874a02SJani Nikula #include "icl_dsi_regs.h"
112b874a02SJani Nikula #include "intel_crtc.h"
122b874a02SJani Nikula #include "intel_de.h"
13d705a8c7SJani Nikula #include "intel_display_irq.h"
14d705a8c7SJani Nikula #include "intel_display_trace.h"
15d705a8c7SJani Nikula #include "intel_display_types.h"
16d705a8c7SJani Nikula #include "intel_dp_aux.h"
17d705a8c7SJani Nikula #include "intel_fdi_regs.h"
18d705a8c7SJani Nikula #include "intel_fifo_underrun.h"
19d705a8c7SJani Nikula #include "intel_gmbus.h"
20d705a8c7SJani Nikula #include "intel_hotplug_irq.h"
214c4cc7acSMika Kahola #include "intel_pmdemand.h"
22d705a8c7SJani Nikula #include "intel_psr.h"
23d705a8c7SJani Nikula #include "intel_psr_regs.h"
242b874a02SJani Nikula
252b874a02SJani Nikula static void
intel_handle_vblank(struct drm_i915_private * dev_priv,enum pipe pipe)262b874a02SJani Nikula intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
272b874a02SJani Nikula {
282b874a02SJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
292b874a02SJani Nikula
302b874a02SJani Nikula drm_crtc_handle_vblank(&crtc->base);
312b874a02SJani Nikula }
322b874a02SJani Nikula
332b874a02SJani Nikula /**
342b874a02SJani Nikula * ilk_update_display_irq - update DEIMR
352b874a02SJani Nikula * @dev_priv: driver private
362b874a02SJani Nikula * @interrupt_mask: mask of interrupt bits to update
372b874a02SJani Nikula * @enabled_irq_mask: mask of interrupt bits to enable
382b874a02SJani Nikula */
ilk_update_display_irq(struct drm_i915_private * dev_priv,u32 interrupt_mask,u32 enabled_irq_mask)392b874a02SJani Nikula void ilk_update_display_irq(struct drm_i915_private *dev_priv,
402b874a02SJani Nikula u32 interrupt_mask, u32 enabled_irq_mask)
412b874a02SJani Nikula {
422b874a02SJani Nikula u32 new_val;
432b874a02SJani Nikula
442b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
452b874a02SJani Nikula drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
462b874a02SJani Nikula
472b874a02SJani Nikula new_val = dev_priv->irq_mask;
482b874a02SJani Nikula new_val &= ~interrupt_mask;
492b874a02SJani Nikula new_val |= (~enabled_irq_mask & interrupt_mask);
502b874a02SJani Nikula
512b874a02SJani Nikula if (new_val != dev_priv->irq_mask &&
522b874a02SJani Nikula !drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) {
532b874a02SJani Nikula dev_priv->irq_mask = new_val;
542b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, DEIMR, dev_priv->irq_mask);
552b874a02SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, DEIMR);
562b874a02SJani Nikula }
572b874a02SJani Nikula }
582b874a02SJani Nikula
ilk_enable_display_irq(struct drm_i915_private * i915,u32 bits)592b874a02SJani Nikula void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits)
602b874a02SJani Nikula {
612b874a02SJani Nikula ilk_update_display_irq(i915, bits, bits);
622b874a02SJani Nikula }
632b874a02SJani Nikula
ilk_disable_display_irq(struct drm_i915_private * i915,u32 bits)642b874a02SJani Nikula void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits)
652b874a02SJani Nikula {
662b874a02SJani Nikula ilk_update_display_irq(i915, bits, 0);
672b874a02SJani Nikula }
682b874a02SJani Nikula
692b874a02SJani Nikula /**
702b874a02SJani Nikula * bdw_update_port_irq - update DE port interrupt
712b874a02SJani Nikula * @dev_priv: driver private
722b874a02SJani Nikula * @interrupt_mask: mask of interrupt bits to update
732b874a02SJani Nikula * @enabled_irq_mask: mask of interrupt bits to enable
742b874a02SJani Nikula */
bdw_update_port_irq(struct drm_i915_private * dev_priv,u32 interrupt_mask,u32 enabled_irq_mask)752b874a02SJani Nikula void bdw_update_port_irq(struct drm_i915_private *dev_priv,
762b874a02SJani Nikula u32 interrupt_mask, u32 enabled_irq_mask)
772b874a02SJani Nikula {
782b874a02SJani Nikula u32 new_val;
792b874a02SJani Nikula u32 old_val;
802b874a02SJani Nikula
812b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
822b874a02SJani Nikula
832b874a02SJani Nikula drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
842b874a02SJani Nikula
852b874a02SJani Nikula if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
862b874a02SJani Nikula return;
872b874a02SJani Nikula
882b874a02SJani Nikula old_val = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
892b874a02SJani Nikula
902b874a02SJani Nikula new_val = old_val;
912b874a02SJani Nikula new_val &= ~interrupt_mask;
922b874a02SJani Nikula new_val |= (~enabled_irq_mask & interrupt_mask);
932b874a02SJani Nikula
942b874a02SJani Nikula if (new_val != old_val) {
952b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IMR, new_val);
962b874a02SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PORT_IMR);
972b874a02SJani Nikula }
982b874a02SJani Nikula }
992b874a02SJani Nikula
1002b874a02SJani Nikula /**
1012b874a02SJani Nikula * bdw_update_pipe_irq - update DE pipe interrupt
1022b874a02SJani Nikula * @dev_priv: driver private
1032b874a02SJani Nikula * @pipe: pipe whose interrupt to update
1042b874a02SJani Nikula * @interrupt_mask: mask of interrupt bits to update
1052b874a02SJani Nikula * @enabled_irq_mask: mask of interrupt bits to enable
1062b874a02SJani Nikula */
bdw_update_pipe_irq(struct drm_i915_private * dev_priv,enum pipe pipe,u32 interrupt_mask,u32 enabled_irq_mask)1072b874a02SJani Nikula static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
1082b874a02SJani Nikula enum pipe pipe, u32 interrupt_mask,
1092b874a02SJani Nikula u32 enabled_irq_mask)
1102b874a02SJani Nikula {
1112b874a02SJani Nikula u32 new_val;
1122b874a02SJani Nikula
1132b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
1142b874a02SJani Nikula
1152b874a02SJani Nikula drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
1162b874a02SJani Nikula
1172b874a02SJani Nikula if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
1182b874a02SJani Nikula return;
1192b874a02SJani Nikula
1202b874a02SJani Nikula new_val = dev_priv->de_irq_mask[pipe];
1212b874a02SJani Nikula new_val &= ~interrupt_mask;
1222b874a02SJani Nikula new_val |= (~enabled_irq_mask & interrupt_mask);
1232b874a02SJani Nikula
1242b874a02SJani Nikula if (new_val != dev_priv->de_irq_mask[pipe]) {
1252b874a02SJani Nikula dev_priv->de_irq_mask[pipe] = new_val;
1262b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
1272b874a02SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe));
1282b874a02SJani Nikula }
1292b874a02SJani Nikula }
1302b874a02SJani Nikula
bdw_enable_pipe_irq(struct drm_i915_private * i915,enum pipe pipe,u32 bits)1312b874a02SJani Nikula void bdw_enable_pipe_irq(struct drm_i915_private *i915,
1322b874a02SJani Nikula enum pipe pipe, u32 bits)
1332b874a02SJani Nikula {
1342b874a02SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, bits);
1352b874a02SJani Nikula }
1362b874a02SJani Nikula
bdw_disable_pipe_irq(struct drm_i915_private * i915,enum pipe pipe,u32 bits)1372b874a02SJani Nikula void bdw_disable_pipe_irq(struct drm_i915_private *i915,
1382b874a02SJani Nikula enum pipe pipe, u32 bits)
1392b874a02SJani Nikula {
1402b874a02SJani Nikula bdw_update_pipe_irq(i915, pipe, bits, 0);
1412b874a02SJani Nikula }
1422b874a02SJani Nikula
1432b874a02SJani Nikula /**
1442b874a02SJani Nikula * ibx_display_interrupt_update - update SDEIMR
1452b874a02SJani Nikula * @dev_priv: driver private
1462b874a02SJani Nikula * @interrupt_mask: mask of interrupt bits to update
1472b874a02SJani Nikula * @enabled_irq_mask: mask of interrupt bits to enable
1482b874a02SJani Nikula */
ibx_display_interrupt_update(struct drm_i915_private * dev_priv,u32 interrupt_mask,u32 enabled_irq_mask)1492b874a02SJani Nikula void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
1502b874a02SJani Nikula u32 interrupt_mask,
1512b874a02SJani Nikula u32 enabled_irq_mask)
1522b874a02SJani Nikula {
1532b874a02SJani Nikula u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR);
1542b874a02SJani Nikula
1552b874a02SJani Nikula sdeimr &= ~interrupt_mask;
1562b874a02SJani Nikula sdeimr |= (~enabled_irq_mask & interrupt_mask);
1572b874a02SJani Nikula
1582b874a02SJani Nikula drm_WARN_ON(&dev_priv->drm, enabled_irq_mask & ~interrupt_mask);
1592b874a02SJani Nikula
1602b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
1612b874a02SJani Nikula
1622b874a02SJani Nikula if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)))
1632b874a02SJani Nikula return;
1642b874a02SJani Nikula
1652b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIMR, sdeimr);
1662b874a02SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, SDEIMR);
1672b874a02SJani Nikula }
1682b874a02SJani Nikula
ibx_enable_display_interrupt(struct drm_i915_private * i915,u32 bits)1692b874a02SJani Nikula void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits)
1702b874a02SJani Nikula {
1712b874a02SJani Nikula ibx_display_interrupt_update(i915, bits, bits);
1722b874a02SJani Nikula }
1732b874a02SJani Nikula
ibx_disable_display_interrupt(struct drm_i915_private * i915,u32 bits)1742b874a02SJani Nikula void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits)
1752b874a02SJani Nikula {
1762b874a02SJani Nikula ibx_display_interrupt_update(i915, bits, 0);
1772b874a02SJani Nikula }
1782b874a02SJani Nikula
i915_pipestat_enable_mask(struct drm_i915_private * dev_priv,enum pipe pipe)1792b874a02SJani Nikula u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv,
1802b874a02SJani Nikula enum pipe pipe)
1812b874a02SJani Nikula {
1822b874a02SJani Nikula u32 status_mask = dev_priv->pipestat_irq_mask[pipe];
1832b874a02SJani Nikula u32 enable_mask = status_mask << 16;
1842b874a02SJani Nikula
1852b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
1862b874a02SJani Nikula
1872b874a02SJani Nikula if (DISPLAY_VER(dev_priv) < 5)
1882b874a02SJani Nikula goto out;
1892b874a02SJani Nikula
1902b874a02SJani Nikula /*
1912b874a02SJani Nikula * On pipe A we don't support the PSR interrupt yet,
1922b874a02SJani Nikula * on pipe B and C the same bit MBZ.
1932b874a02SJani Nikula */
1942b874a02SJani Nikula if (drm_WARN_ON_ONCE(&dev_priv->drm,
1952b874a02SJani Nikula status_mask & PIPE_A_PSR_STATUS_VLV))
1962b874a02SJani Nikula return 0;
1972b874a02SJani Nikula /*
1982b874a02SJani Nikula * On pipe B and C we don't support the PSR interrupt yet, on pipe
1992b874a02SJani Nikula * A the same bit is for perf counters which we don't use either.
2002b874a02SJani Nikula */
2012b874a02SJani Nikula if (drm_WARN_ON_ONCE(&dev_priv->drm,
2022b874a02SJani Nikula status_mask & PIPE_B_PSR_STATUS_VLV))
2032b874a02SJani Nikula return 0;
2042b874a02SJani Nikula
2052b874a02SJani Nikula enable_mask &= ~(PIPE_FIFO_UNDERRUN_STATUS |
2062b874a02SJani Nikula SPRITE0_FLIP_DONE_INT_EN_VLV |
2072b874a02SJani Nikula SPRITE1_FLIP_DONE_INT_EN_VLV);
2082b874a02SJani Nikula if (status_mask & SPRITE0_FLIP_DONE_INT_STATUS_VLV)
2092b874a02SJani Nikula enable_mask |= SPRITE0_FLIP_DONE_INT_EN_VLV;
2102b874a02SJani Nikula if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV)
2112b874a02SJani Nikula enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV;
2122b874a02SJani Nikula
2132b874a02SJani Nikula out:
2142b874a02SJani Nikula drm_WARN_ONCE(&dev_priv->drm,
2152b874a02SJani Nikula enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
2162b874a02SJani Nikula status_mask & ~PIPESTAT_INT_STATUS_MASK,
2172b874a02SJani Nikula "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
2182b874a02SJani Nikula pipe_name(pipe), enable_mask, status_mask);
2192b874a02SJani Nikula
2202b874a02SJani Nikula return enable_mask;
2212b874a02SJani Nikula }
2222b874a02SJani Nikula
i915_enable_pipestat(struct drm_i915_private * dev_priv,enum pipe pipe,u32 status_mask)2232b874a02SJani Nikula void i915_enable_pipestat(struct drm_i915_private *dev_priv,
2242b874a02SJani Nikula enum pipe pipe, u32 status_mask)
2252b874a02SJani Nikula {
2262b874a02SJani Nikula i915_reg_t reg = PIPESTAT(pipe);
2272b874a02SJani Nikula u32 enable_mask;
2282b874a02SJani Nikula
2292b874a02SJani Nikula drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
2302b874a02SJani Nikula "pipe %c: status_mask=0x%x\n",
2312b874a02SJani Nikula pipe_name(pipe), status_mask);
2322b874a02SJani Nikula
2332b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
2342b874a02SJani Nikula drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
2352b874a02SJani Nikula
2362b874a02SJani Nikula if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask)
2372b874a02SJani Nikula return;
2382b874a02SJani Nikula
2392b874a02SJani Nikula dev_priv->pipestat_irq_mask[pipe] |= status_mask;
2402b874a02SJani Nikula enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
2412b874a02SJani Nikula
2422b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
2432b874a02SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg);
2442b874a02SJani Nikula }
2452b874a02SJani Nikula
i915_disable_pipestat(struct drm_i915_private * dev_priv,enum pipe pipe,u32 status_mask)2462b874a02SJani Nikula void i915_disable_pipestat(struct drm_i915_private *dev_priv,
2472b874a02SJani Nikula enum pipe pipe, u32 status_mask)
2482b874a02SJani Nikula {
2492b874a02SJani Nikula i915_reg_t reg = PIPESTAT(pipe);
2502b874a02SJani Nikula u32 enable_mask;
2512b874a02SJani Nikula
2522b874a02SJani Nikula drm_WARN_ONCE(&dev_priv->drm, status_mask & ~PIPESTAT_INT_STATUS_MASK,
2532b874a02SJani Nikula "pipe %c: status_mask=0x%x\n",
2542b874a02SJani Nikula pipe_name(pipe), status_mask);
2552b874a02SJani Nikula
2562b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
2572b874a02SJani Nikula drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv));
2582b874a02SJani Nikula
2592b874a02SJani Nikula if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0)
2602b874a02SJani Nikula return;
2612b874a02SJani Nikula
2622b874a02SJani Nikula dev_priv->pipestat_irq_mask[pipe] &= ~status_mask;
2632b874a02SJani Nikula enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
2642b874a02SJani Nikula
2652b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask);
2662b874a02SJani Nikula intel_uncore_posting_read(&dev_priv->uncore, reg);
2672b874a02SJani Nikula }
2682b874a02SJani Nikula
i915_has_asle(struct drm_i915_private * dev_priv)2692b874a02SJani Nikula static bool i915_has_asle(struct drm_i915_private *dev_priv)
2702b874a02SJani Nikula {
2712b874a02SJani Nikula if (!dev_priv->display.opregion.asle)
2722b874a02SJani Nikula return false;
2732b874a02SJani Nikula
2742b874a02SJani Nikula return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
2752b874a02SJani Nikula }
2762b874a02SJani Nikula
2772b874a02SJani Nikula /**
2782b874a02SJani Nikula * i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
2792b874a02SJani Nikula * @dev_priv: i915 device private
2802b874a02SJani Nikula */
i915_enable_asle_pipestat(struct drm_i915_private * dev_priv)2812b874a02SJani Nikula void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
2822b874a02SJani Nikula {
2832b874a02SJani Nikula if (!i915_has_asle(dev_priv))
2842b874a02SJani Nikula return;
2852b874a02SJani Nikula
2862b874a02SJani Nikula spin_lock_irq(&dev_priv->irq_lock);
2872b874a02SJani Nikula
2882b874a02SJani Nikula i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
2892b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 4)
2902b874a02SJani Nikula i915_enable_pipestat(dev_priv, PIPE_A,
2912b874a02SJani Nikula PIPE_LEGACY_BLC_EVENT_STATUS);
2922b874a02SJani Nikula
2932b874a02SJani Nikula spin_unlock_irq(&dev_priv->irq_lock);
2942b874a02SJani Nikula }
2952b874a02SJani Nikula
2962b874a02SJani Nikula #if defined(CONFIG_DEBUG_FS)
display_pipe_crc_irq_handler(struct drm_i915_private * dev_priv,enum pipe pipe,u32 crc0,u32 crc1,u32 crc2,u32 crc3,u32 crc4)2972b874a02SJani Nikula static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
2982b874a02SJani Nikula enum pipe pipe,
2992b874a02SJani Nikula u32 crc0, u32 crc1,
3002b874a02SJani Nikula u32 crc2, u32 crc3,
3012b874a02SJani Nikula u32 crc4)
3022b874a02SJani Nikula {
3032b874a02SJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
3042b874a02SJani Nikula struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
3052b874a02SJani Nikula u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 };
3062b874a02SJani Nikula
3072b874a02SJani Nikula trace_intel_pipe_crc(crtc, crcs);
3082b874a02SJani Nikula
3092b874a02SJani Nikula spin_lock(&pipe_crc->lock);
3102b874a02SJani Nikula /*
3112b874a02SJani Nikula * For some not yet identified reason, the first CRC is
3122b874a02SJani Nikula * bonkers. So let's just wait for the next vblank and read
3132b874a02SJani Nikula * out the buggy result.
3142b874a02SJani Nikula *
3152b874a02SJani Nikula * On GEN8+ sometimes the second CRC is bonkers as well, so
3162b874a02SJani Nikula * don't trust that one either.
3172b874a02SJani Nikula */
3182b874a02SJani Nikula if (pipe_crc->skipped <= 0 ||
3192b874a02SJani Nikula (DISPLAY_VER(dev_priv) >= 8 && pipe_crc->skipped == 1)) {
3202b874a02SJani Nikula pipe_crc->skipped++;
3212b874a02SJani Nikula spin_unlock(&pipe_crc->lock);
3222b874a02SJani Nikula return;
3232b874a02SJani Nikula }
3242b874a02SJani Nikula spin_unlock(&pipe_crc->lock);
3252b874a02SJani Nikula
3262b874a02SJani Nikula drm_crtc_add_crc_entry(&crtc->base, true,
3272b874a02SJani Nikula drm_crtc_accurate_vblank_count(&crtc->base),
3282b874a02SJani Nikula crcs);
3292b874a02SJani Nikula }
3302b874a02SJani Nikula #else
3312b874a02SJani Nikula static inline void
display_pipe_crc_irq_handler(struct drm_i915_private * dev_priv,enum pipe pipe,u32 crc0,u32 crc1,u32 crc2,u32 crc3,u32 crc4)3322b874a02SJani Nikula display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
3332b874a02SJani Nikula enum pipe pipe,
3342b874a02SJani Nikula u32 crc0, u32 crc1,
3352b874a02SJani Nikula u32 crc2, u32 crc3,
3362b874a02SJani Nikula u32 crc4) {}
3372b874a02SJani Nikula #endif
3382b874a02SJani Nikula
flip_done_handler(struct drm_i915_private * i915,enum pipe pipe)3392b874a02SJani Nikula static void flip_done_handler(struct drm_i915_private *i915,
3402b874a02SJani Nikula enum pipe pipe)
3412b874a02SJani Nikula {
3422b874a02SJani Nikula struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
3432b874a02SJani Nikula struct drm_crtc_state *crtc_state = crtc->base.state;
3442b874a02SJani Nikula struct drm_pending_vblank_event *e = crtc_state->event;
3452b874a02SJani Nikula struct drm_device *dev = &i915->drm;
3462b874a02SJani Nikula unsigned long irqflags;
3472b874a02SJani Nikula
3482b874a02SJani Nikula spin_lock_irqsave(&dev->event_lock, irqflags);
3492b874a02SJani Nikula
3502b874a02SJani Nikula crtc_state->event = NULL;
3512b874a02SJani Nikula
3522b874a02SJani Nikula drm_crtc_send_vblank_event(&crtc->base, e);
3532b874a02SJani Nikula
3542b874a02SJani Nikula spin_unlock_irqrestore(&dev->event_lock, irqflags);
3552b874a02SJani Nikula }
3562b874a02SJani Nikula
hsw_pipe_crc_irq_handler(struct drm_i915_private * dev_priv,enum pipe pipe)3572b874a02SJani Nikula static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
3582b874a02SJani Nikula enum pipe pipe)
3592b874a02SJani Nikula {
3602b874a02SJani Nikula display_pipe_crc_irq_handler(dev_priv, pipe,
3612b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
3622b874a02SJani Nikula 0, 0, 0, 0);
3632b874a02SJani Nikula }
3642b874a02SJani Nikula
ivb_pipe_crc_irq_handler(struct drm_i915_private * dev_priv,enum pipe pipe)3652b874a02SJani Nikula static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
3662b874a02SJani Nikula enum pipe pipe)
3672b874a02SJani Nikula {
3682b874a02SJani Nikula display_pipe_crc_irq_handler(dev_priv, pipe,
3692b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_1_IVB(pipe)),
3702b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_2_IVB(pipe)),
3712b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_3_IVB(pipe)),
3722b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_4_IVB(pipe)),
3732b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_5_IVB(pipe)));
3742b874a02SJani Nikula }
3752b874a02SJani Nikula
i9xx_pipe_crc_irq_handler(struct drm_i915_private * dev_priv,enum pipe pipe)3762b874a02SJani Nikula static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
3772b874a02SJani Nikula enum pipe pipe)
3782b874a02SJani Nikula {
3792b874a02SJani Nikula u32 res1, res2;
3802b874a02SJani Nikula
3812b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 3)
3822b874a02SJani Nikula res1 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES1_I915(pipe));
3832b874a02SJani Nikula else
3842b874a02SJani Nikula res1 = 0;
3852b874a02SJani Nikula
3862b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
3872b874a02SJani Nikula res2 = intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RES2_G4X(pipe));
3882b874a02SJani Nikula else
3892b874a02SJani Nikula res2 = 0;
3902b874a02SJani Nikula
3912b874a02SJani Nikula display_pipe_crc_irq_handler(dev_priv, pipe,
3922b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_RED(pipe)),
3932b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_GREEN(pipe)),
3942b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, PIPE_CRC_RES_BLUE(pipe)),
3952b874a02SJani Nikula res1, res2);
3962b874a02SJani Nikula }
3972b874a02SJani Nikula
i9xx_pipestat_irq_reset(struct drm_i915_private * dev_priv)3982b874a02SJani Nikula void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
3992b874a02SJani Nikula {
4002b874a02SJani Nikula enum pipe pipe;
4012b874a02SJani Nikula
4022b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
4032b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, PIPESTAT(pipe),
4042b874a02SJani Nikula PIPESTAT_INT_STATUS_MASK |
4052b874a02SJani Nikula PIPE_FIFO_UNDERRUN_STATUS);
4062b874a02SJani Nikula
4072b874a02SJani Nikula dev_priv->pipestat_irq_mask[pipe] = 0;
4082b874a02SJani Nikula }
4092b874a02SJani Nikula }
4102b874a02SJani Nikula
i9xx_pipestat_irq_ack(struct drm_i915_private * dev_priv,u32 iir,u32 pipe_stats[I915_MAX_PIPES])4112b874a02SJani Nikula void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
4122b874a02SJani Nikula u32 iir, u32 pipe_stats[I915_MAX_PIPES])
4132b874a02SJani Nikula {
4142b874a02SJani Nikula enum pipe pipe;
4152b874a02SJani Nikula
4162b874a02SJani Nikula spin_lock(&dev_priv->irq_lock);
4172b874a02SJani Nikula
4182b874a02SJani Nikula if (!dev_priv->display_irqs_enabled) {
4192b874a02SJani Nikula spin_unlock(&dev_priv->irq_lock);
4202b874a02SJani Nikula return;
4212b874a02SJani Nikula }
4222b874a02SJani Nikula
4232b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
4242b874a02SJani Nikula i915_reg_t reg;
4252b874a02SJani Nikula u32 status_mask, enable_mask, iir_bit = 0;
4262b874a02SJani Nikula
4272b874a02SJani Nikula /*
4282b874a02SJani Nikula * PIPESTAT bits get signalled even when the interrupt is
4292b874a02SJani Nikula * disabled with the mask bits, and some of the status bits do
4302b874a02SJani Nikula * not generate interrupts at all (like the underrun bit). Hence
4312b874a02SJani Nikula * we need to be careful that we only handle what we want to
4322b874a02SJani Nikula * handle.
4332b874a02SJani Nikula */
4342b874a02SJani Nikula
4352b874a02SJani Nikula /* fifo underruns are filterered in the underrun handler. */
4362b874a02SJani Nikula status_mask = PIPE_FIFO_UNDERRUN_STATUS;
4372b874a02SJani Nikula
4382b874a02SJani Nikula switch (pipe) {
4392b874a02SJani Nikula default:
4402b874a02SJani Nikula case PIPE_A:
4412b874a02SJani Nikula iir_bit = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
4422b874a02SJani Nikula break;
4432b874a02SJani Nikula case PIPE_B:
4442b874a02SJani Nikula iir_bit = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
4452b874a02SJani Nikula break;
4462b874a02SJani Nikula case PIPE_C:
4472b874a02SJani Nikula iir_bit = I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
4482b874a02SJani Nikula break;
4492b874a02SJani Nikula }
4502b874a02SJani Nikula if (iir & iir_bit)
4512b874a02SJani Nikula status_mask |= dev_priv->pipestat_irq_mask[pipe];
4522b874a02SJani Nikula
4532b874a02SJani Nikula if (!status_mask)
4542b874a02SJani Nikula continue;
4552b874a02SJani Nikula
4562b874a02SJani Nikula reg = PIPESTAT(pipe);
4572b874a02SJani Nikula pipe_stats[pipe] = intel_uncore_read(&dev_priv->uncore, reg) & status_mask;
4582b874a02SJani Nikula enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
4592b874a02SJani Nikula
4602b874a02SJani Nikula /*
4612b874a02SJani Nikula * Clear the PIPE*STAT regs before the IIR
4622b874a02SJani Nikula *
4632b874a02SJani Nikula * Toggle the enable bits to make sure we get an
4642b874a02SJani Nikula * edge in the ISR pipe event bit if we don't clear
4652b874a02SJani Nikula * all the enabled status bits. Otherwise the edge
4662b874a02SJani Nikula * triggered IIR on i965/g4x wouldn't notice that
4672b874a02SJani Nikula * an interrupt is still pending.
4682b874a02SJani Nikula */
4692b874a02SJani Nikula if (pipe_stats[pipe]) {
4702b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, pipe_stats[pipe]);
4712b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, reg, enable_mask);
4722b874a02SJani Nikula }
4732b874a02SJani Nikula }
4742b874a02SJani Nikula spin_unlock(&dev_priv->irq_lock);
4752b874a02SJani Nikula }
4762b874a02SJani Nikula
i8xx_pipestat_irq_handler(struct drm_i915_private * dev_priv,u16 iir,u32 pipe_stats[I915_MAX_PIPES])4772b874a02SJani Nikula void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv,
4782b874a02SJani Nikula u16 iir, u32 pipe_stats[I915_MAX_PIPES])
4792b874a02SJani Nikula {
4802b874a02SJani Nikula enum pipe pipe;
4812b874a02SJani Nikula
4822b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
4832b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
4842b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
4852b874a02SJani Nikula
4862b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
4872b874a02SJani Nikula i9xx_pipe_crc_irq_handler(dev_priv, pipe);
4882b874a02SJani Nikula
4892b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
4902b874a02SJani Nikula intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
4912b874a02SJani Nikula }
4922b874a02SJani Nikula }
4932b874a02SJani Nikula
i915_pipestat_irq_handler(struct drm_i915_private * dev_priv,u32 iir,u32 pipe_stats[I915_MAX_PIPES])4942b874a02SJani Nikula void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv,
4952b874a02SJani Nikula u32 iir, u32 pipe_stats[I915_MAX_PIPES])
4962b874a02SJani Nikula {
4972b874a02SJani Nikula bool blc_event = false;
4982b874a02SJani Nikula enum pipe pipe;
4992b874a02SJani Nikula
5002b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
5012b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
5022b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
5032b874a02SJani Nikula
5042b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
5052b874a02SJani Nikula blc_event = true;
5062b874a02SJani Nikula
5072b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
5082b874a02SJani Nikula i9xx_pipe_crc_irq_handler(dev_priv, pipe);
5092b874a02SJani Nikula
5102b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
5112b874a02SJani Nikula intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
5122b874a02SJani Nikula }
5132b874a02SJani Nikula
5142b874a02SJani Nikula if (blc_event || (iir & I915_ASLE_INTERRUPT))
5152b874a02SJani Nikula intel_opregion_asle_intr(dev_priv);
5162b874a02SJani Nikula }
5172b874a02SJani Nikula
i965_pipestat_irq_handler(struct drm_i915_private * dev_priv,u32 iir,u32 pipe_stats[I915_MAX_PIPES])5182b874a02SJani Nikula void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv,
5192b874a02SJani Nikula u32 iir, u32 pipe_stats[I915_MAX_PIPES])
5202b874a02SJani Nikula {
5212b874a02SJani Nikula bool blc_event = false;
5222b874a02SJani Nikula enum pipe pipe;
5232b874a02SJani Nikula
5242b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
5252b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
5262b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
5272b874a02SJani Nikula
5282b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
5292b874a02SJani Nikula blc_event = true;
5302b874a02SJani Nikula
5312b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
5322b874a02SJani Nikula i9xx_pipe_crc_irq_handler(dev_priv, pipe);
5332b874a02SJani Nikula
5342b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
5352b874a02SJani Nikula intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
5362b874a02SJani Nikula }
5372b874a02SJani Nikula
5382b874a02SJani Nikula if (blc_event || (iir & I915_ASLE_INTERRUPT))
5392b874a02SJani Nikula intel_opregion_asle_intr(dev_priv);
5402b874a02SJani Nikula
5412b874a02SJani Nikula if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
5422b874a02SJani Nikula intel_gmbus_irq_handler(dev_priv);
5432b874a02SJani Nikula }
5442b874a02SJani Nikula
valleyview_pipestat_irq_handler(struct drm_i915_private * dev_priv,u32 pipe_stats[I915_MAX_PIPES])5452b874a02SJani Nikula void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
5462b874a02SJani Nikula u32 pipe_stats[I915_MAX_PIPES])
5472b874a02SJani Nikula {
5482b874a02SJani Nikula enum pipe pipe;
5492b874a02SJani Nikula
5502b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
5512b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
5522b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
5532b874a02SJani Nikula
5542b874a02SJani Nikula if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
5552b874a02SJani Nikula flip_done_handler(dev_priv, pipe);
5562b874a02SJani Nikula
5572b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
5582b874a02SJani Nikula i9xx_pipe_crc_irq_handler(dev_priv, pipe);
5592b874a02SJani Nikula
5602b874a02SJani Nikula if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
5612b874a02SJani Nikula intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
5622b874a02SJani Nikula }
5632b874a02SJani Nikula
5642b874a02SJani Nikula if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
5652b874a02SJani Nikula intel_gmbus_irq_handler(dev_priv);
5662b874a02SJani Nikula }
5672b874a02SJani Nikula
ibx_irq_handler(struct drm_i915_private * dev_priv,u32 pch_iir)5682b874a02SJani Nikula static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
5692b874a02SJani Nikula {
5702b874a02SJani Nikula enum pipe pipe;
5712b874a02SJani Nikula u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
5722b874a02SJani Nikula
5732b874a02SJani Nikula ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
5742b874a02SJani Nikula
5752b874a02SJani Nikula if (pch_iir & SDE_AUDIO_POWER_MASK) {
5762b874a02SJani Nikula int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
5772b874a02SJani Nikula SDE_AUDIO_POWER_SHIFT);
5782b874a02SJani Nikula drm_dbg(&dev_priv->drm, "PCH audio power change on port %d\n",
5792b874a02SJani Nikula port_name(port));
5802b874a02SJani Nikula }
5812b874a02SJani Nikula
5822b874a02SJani Nikula if (pch_iir & SDE_AUX_MASK)
5832b874a02SJani Nikula intel_dp_aux_irq_handler(dev_priv);
5842b874a02SJani Nikula
5852b874a02SJani Nikula if (pch_iir & SDE_GMBUS)
5862b874a02SJani Nikula intel_gmbus_irq_handler(dev_priv);
5872b874a02SJani Nikula
5882b874a02SJani Nikula if (pch_iir & SDE_AUDIO_HDCP_MASK)
5892b874a02SJani Nikula drm_dbg(&dev_priv->drm, "PCH HDCP audio interrupt\n");
5902b874a02SJani Nikula
5912b874a02SJani Nikula if (pch_iir & SDE_AUDIO_TRANS_MASK)
5922b874a02SJani Nikula drm_dbg(&dev_priv->drm, "PCH transcoder audio interrupt\n");
5932b874a02SJani Nikula
5942b874a02SJani Nikula if (pch_iir & SDE_POISON)
5952b874a02SJani Nikula drm_err(&dev_priv->drm, "PCH poison interrupt\n");
5962b874a02SJani Nikula
5972b874a02SJani Nikula if (pch_iir & SDE_FDI_MASK) {
5982b874a02SJani Nikula for_each_pipe(dev_priv, pipe)
5992b874a02SJani Nikula drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n",
6002b874a02SJani Nikula pipe_name(pipe),
6012b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
6022b874a02SJani Nikula }
6032b874a02SJani Nikula
6042b874a02SJani Nikula if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
6052b874a02SJani Nikula drm_dbg(&dev_priv->drm, "PCH transcoder CRC done interrupt\n");
6062b874a02SJani Nikula
6072b874a02SJani Nikula if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
6082b874a02SJani Nikula drm_dbg(&dev_priv->drm,
6092b874a02SJani Nikula "PCH transcoder CRC error interrupt\n");
6102b874a02SJani Nikula
6112b874a02SJani Nikula if (pch_iir & SDE_TRANSA_FIFO_UNDER)
6122b874a02SJani Nikula intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A);
6132b874a02SJani Nikula
6142b874a02SJani Nikula if (pch_iir & SDE_TRANSB_FIFO_UNDER)
6152b874a02SJani Nikula intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B);
6162b874a02SJani Nikula }
6172b874a02SJani Nikula
ivb_err_int_handler(struct drm_i915_private * dev_priv)6182b874a02SJani Nikula static void ivb_err_int_handler(struct drm_i915_private *dev_priv)
6192b874a02SJani Nikula {
6202b874a02SJani Nikula u32 err_int = intel_uncore_read(&dev_priv->uncore, GEN7_ERR_INT);
6212b874a02SJani Nikula enum pipe pipe;
6222b874a02SJani Nikula
6232b874a02SJani Nikula if (err_int & ERR_INT_POISON)
6242b874a02SJani Nikula drm_err(&dev_priv->drm, "Poison interrupt\n");
6252b874a02SJani Nikula
6262b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
6272b874a02SJani Nikula if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
6282b874a02SJani Nikula intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
6292b874a02SJani Nikula
6302b874a02SJani Nikula if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
6312b874a02SJani Nikula if (IS_IVYBRIDGE(dev_priv))
6322b874a02SJani Nikula ivb_pipe_crc_irq_handler(dev_priv, pipe);
6332b874a02SJani Nikula else
6342b874a02SJani Nikula hsw_pipe_crc_irq_handler(dev_priv, pipe);
6352b874a02SJani Nikula }
6362b874a02SJani Nikula }
6372b874a02SJani Nikula
6382b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN7_ERR_INT, err_int);
6392b874a02SJani Nikula }
6402b874a02SJani Nikula
cpt_serr_int_handler(struct drm_i915_private * dev_priv)6412b874a02SJani Nikula static void cpt_serr_int_handler(struct drm_i915_private *dev_priv)
6422b874a02SJani Nikula {
6432b874a02SJani Nikula u32 serr_int = intel_uncore_read(&dev_priv->uncore, SERR_INT);
6442b874a02SJani Nikula enum pipe pipe;
6452b874a02SJani Nikula
6462b874a02SJani Nikula if (serr_int & SERR_INT_POISON)
6472b874a02SJani Nikula drm_err(&dev_priv->drm, "PCH poison interrupt\n");
6482b874a02SJani Nikula
6492b874a02SJani Nikula for_each_pipe(dev_priv, pipe)
6502b874a02SJani Nikula if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe))
6512b874a02SJani Nikula intel_pch_fifo_underrun_irq_handler(dev_priv, pipe);
6522b874a02SJani Nikula
6532b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, SERR_INT, serr_int);
6542b874a02SJani Nikula }
6552b874a02SJani Nikula
cpt_irq_handler(struct drm_i915_private * dev_priv,u32 pch_iir)6562b874a02SJani Nikula static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
6572b874a02SJani Nikula {
6582b874a02SJani Nikula enum pipe pipe;
6592b874a02SJani Nikula u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
6602b874a02SJani Nikula
6612b874a02SJani Nikula ibx_hpd_irq_handler(dev_priv, hotplug_trigger);
6622b874a02SJani Nikula
6632b874a02SJani Nikula if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
6642b874a02SJani Nikula int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
6652b874a02SJani Nikula SDE_AUDIO_POWER_SHIFT_CPT);
6662b874a02SJani Nikula drm_dbg(&dev_priv->drm, "PCH audio power change on port %c\n",
6672b874a02SJani Nikula port_name(port));
6682b874a02SJani Nikula }
6692b874a02SJani Nikula
6702b874a02SJani Nikula if (pch_iir & SDE_AUX_MASK_CPT)
6712b874a02SJani Nikula intel_dp_aux_irq_handler(dev_priv);
6722b874a02SJani Nikula
6732b874a02SJani Nikula if (pch_iir & SDE_GMBUS_CPT)
6742b874a02SJani Nikula intel_gmbus_irq_handler(dev_priv);
6752b874a02SJani Nikula
6762b874a02SJani Nikula if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
6772b874a02SJani Nikula drm_dbg(&dev_priv->drm, "Audio CP request interrupt\n");
6782b874a02SJani Nikula
6792b874a02SJani Nikula if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
6802b874a02SJani Nikula drm_dbg(&dev_priv->drm, "Audio CP change interrupt\n");
6812b874a02SJani Nikula
6822b874a02SJani Nikula if (pch_iir & SDE_FDI_MASK_CPT) {
6832b874a02SJani Nikula for_each_pipe(dev_priv, pipe)
6842b874a02SJani Nikula drm_dbg(&dev_priv->drm, " pipe %c FDI IIR: 0x%08x\n",
6852b874a02SJani Nikula pipe_name(pipe),
6862b874a02SJani Nikula intel_uncore_read(&dev_priv->uncore, FDI_RX_IIR(pipe)));
6872b874a02SJani Nikula }
6882b874a02SJani Nikula
6892b874a02SJani Nikula if (pch_iir & SDE_ERROR_CPT)
6902b874a02SJani Nikula cpt_serr_int_handler(dev_priv);
6912b874a02SJani Nikula }
6922b874a02SJani Nikula
ilk_display_irq_handler(struct drm_i915_private * dev_priv,u32 de_iir)6932b874a02SJani Nikula void ilk_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir)
6942b874a02SJani Nikula {
6952b874a02SJani Nikula enum pipe pipe;
6962b874a02SJani Nikula u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
6972b874a02SJani Nikula
6982b874a02SJani Nikula if (hotplug_trigger)
6992b874a02SJani Nikula ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
7002b874a02SJani Nikula
7012b874a02SJani Nikula if (de_iir & DE_AUX_CHANNEL_A)
7022b874a02SJani Nikula intel_dp_aux_irq_handler(dev_priv);
7032b874a02SJani Nikula
7042b874a02SJani Nikula if (de_iir & DE_GSE)
7052b874a02SJani Nikula intel_opregion_asle_intr(dev_priv);
7062b874a02SJani Nikula
7072b874a02SJani Nikula if (de_iir & DE_POISON)
7082b874a02SJani Nikula drm_err(&dev_priv->drm, "Poison interrupt\n");
7092b874a02SJani Nikula
7102b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
7112b874a02SJani Nikula if (de_iir & DE_PIPE_VBLANK(pipe))
7122b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
7132b874a02SJani Nikula
7142b874a02SJani Nikula if (de_iir & DE_PLANE_FLIP_DONE(pipe))
7152b874a02SJani Nikula flip_done_handler(dev_priv, pipe);
7162b874a02SJani Nikula
7172b874a02SJani Nikula if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
7182b874a02SJani Nikula intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
7192b874a02SJani Nikula
7202b874a02SJani Nikula if (de_iir & DE_PIPE_CRC_DONE(pipe))
7212b874a02SJani Nikula i9xx_pipe_crc_irq_handler(dev_priv, pipe);
7222b874a02SJani Nikula }
7232b874a02SJani Nikula
7242b874a02SJani Nikula /* check event from PCH */
7252b874a02SJani Nikula if (de_iir & DE_PCH_EVENT) {
7262b874a02SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
7272b874a02SJani Nikula
7282b874a02SJani Nikula if (HAS_PCH_CPT(dev_priv))
7292b874a02SJani Nikula cpt_irq_handler(dev_priv, pch_iir);
7302b874a02SJani Nikula else
7312b874a02SJani Nikula ibx_irq_handler(dev_priv, pch_iir);
7322b874a02SJani Nikula
7332b874a02SJani Nikula /* should clear PCH hotplug event before clear CPU irq */
7342b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
7352b874a02SJani Nikula }
7362b874a02SJani Nikula
7372b874a02SJani Nikula if (DISPLAY_VER(dev_priv) == 5 && de_iir & DE_PCU_EVENT)
7382b874a02SJani Nikula gen5_rps_irq_handler(&to_gt(dev_priv)->rps);
7392b874a02SJani Nikula }
7402b874a02SJani Nikula
ivb_display_irq_handler(struct drm_i915_private * dev_priv,u32 de_iir)7412b874a02SJani Nikula void ivb_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir)
7422b874a02SJani Nikula {
7432b874a02SJani Nikula enum pipe pipe;
7442b874a02SJani Nikula u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
7452b874a02SJani Nikula
7462b874a02SJani Nikula if (hotplug_trigger)
7472b874a02SJani Nikula ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
7482b874a02SJani Nikula
7492b874a02SJani Nikula if (de_iir & DE_ERR_INT_IVB)
7502b874a02SJani Nikula ivb_err_int_handler(dev_priv);
7512b874a02SJani Nikula
752e8b883c1SVille Syrjälä if (de_iir & DE_EDP_PSR_INT_HSW) {
753e8b883c1SVille Syrjälä struct intel_encoder *encoder;
754e8b883c1SVille Syrjälä
755e8b883c1SVille Syrjälä for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
756e8b883c1SVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
757e8b883c1SVille Syrjälä u32 psr_iir;
758e8b883c1SVille Syrjälä
759e8b883c1SVille Syrjälä psr_iir = intel_uncore_rmw(&dev_priv->uncore,
760e8b883c1SVille Syrjälä EDP_PSR_IIR, 0, 0);
761e8b883c1SVille Syrjälä intel_psr_irq_handler(intel_dp, psr_iir);
762e8b883c1SVille Syrjälä break;
763e8b883c1SVille Syrjälä }
764e8b883c1SVille Syrjälä }
765e8b883c1SVille Syrjälä
7662b874a02SJani Nikula if (de_iir & DE_AUX_CHANNEL_A_IVB)
7672b874a02SJani Nikula intel_dp_aux_irq_handler(dev_priv);
7682b874a02SJani Nikula
7692b874a02SJani Nikula if (de_iir & DE_GSE_IVB)
7702b874a02SJani Nikula intel_opregion_asle_intr(dev_priv);
7712b874a02SJani Nikula
7722b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
7732b874a02SJani Nikula if (de_iir & DE_PIPE_VBLANK_IVB(pipe))
7742b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
7752b874a02SJani Nikula
7762b874a02SJani Nikula if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
7772b874a02SJani Nikula flip_done_handler(dev_priv, pipe);
7782b874a02SJani Nikula }
7792b874a02SJani Nikula
7802b874a02SJani Nikula /* check event from PCH */
7812b874a02SJani Nikula if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
7822b874a02SJani Nikula u32 pch_iir = intel_uncore_read(&dev_priv->uncore, SDEIIR);
7832b874a02SJani Nikula
7842b874a02SJani Nikula cpt_irq_handler(dev_priv, pch_iir);
7852b874a02SJani Nikula
7862b874a02SJani Nikula /* clear PCH hotplug event before clear CPU irq */
7872b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, SDEIIR, pch_iir);
7882b874a02SJani Nikula }
7892b874a02SJani Nikula }
7902b874a02SJani Nikula
gen8_de_port_aux_mask(struct drm_i915_private * dev_priv)7912b874a02SJani Nikula static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
7922b874a02SJani Nikula {
7932b874a02SJani Nikula u32 mask;
7942b874a02SJani Nikula
7952b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 14)
7962b874a02SJani Nikula return TGL_DE_PORT_AUX_DDIA |
7972b874a02SJani Nikula TGL_DE_PORT_AUX_DDIB;
7982b874a02SJani Nikula else if (DISPLAY_VER(dev_priv) >= 13)
7992b874a02SJani Nikula return TGL_DE_PORT_AUX_DDIA |
8002b874a02SJani Nikula TGL_DE_PORT_AUX_DDIB |
8012b874a02SJani Nikula TGL_DE_PORT_AUX_DDIC |
8022b874a02SJani Nikula XELPD_DE_PORT_AUX_DDID |
8032b874a02SJani Nikula XELPD_DE_PORT_AUX_DDIE |
8042b874a02SJani Nikula TGL_DE_PORT_AUX_USBC1 |
8052b874a02SJani Nikula TGL_DE_PORT_AUX_USBC2 |
8062b874a02SJani Nikula TGL_DE_PORT_AUX_USBC3 |
8072b874a02SJani Nikula TGL_DE_PORT_AUX_USBC4;
8082b874a02SJani Nikula else if (DISPLAY_VER(dev_priv) >= 12)
8092b874a02SJani Nikula return TGL_DE_PORT_AUX_DDIA |
8102b874a02SJani Nikula TGL_DE_PORT_AUX_DDIB |
8112b874a02SJani Nikula TGL_DE_PORT_AUX_DDIC |
8122b874a02SJani Nikula TGL_DE_PORT_AUX_USBC1 |
8132b874a02SJani Nikula TGL_DE_PORT_AUX_USBC2 |
8142b874a02SJani Nikula TGL_DE_PORT_AUX_USBC3 |
8152b874a02SJani Nikula TGL_DE_PORT_AUX_USBC4 |
8162b874a02SJani Nikula TGL_DE_PORT_AUX_USBC5 |
8172b874a02SJani Nikula TGL_DE_PORT_AUX_USBC6;
8182b874a02SJani Nikula
8192b874a02SJani Nikula mask = GEN8_AUX_CHANNEL_A;
8202b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 9)
8212b874a02SJani Nikula mask |= GEN9_AUX_CHANNEL_B |
8222b874a02SJani Nikula GEN9_AUX_CHANNEL_C |
8232b874a02SJani Nikula GEN9_AUX_CHANNEL_D;
8242b874a02SJani Nikula
8252b874a02SJani Nikula if (DISPLAY_VER(dev_priv) == 11) {
8262b874a02SJani Nikula mask |= ICL_AUX_CHANNEL_F;
8272b874a02SJani Nikula mask |= ICL_AUX_CHANNEL_E;
8282b874a02SJani Nikula }
8292b874a02SJani Nikula
8302b874a02SJani Nikula return mask;
8312b874a02SJani Nikula }
8322b874a02SJani Nikula
gen8_de_pipe_fault_mask(struct drm_i915_private * dev_priv)8332b874a02SJani Nikula static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
8342b874a02SJani Nikula {
8352b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
8362b874a02SJani Nikula return RKL_DE_PIPE_IRQ_FAULT_ERRORS;
8372b874a02SJani Nikula else if (DISPLAY_VER(dev_priv) >= 11)
8382b874a02SJani Nikula return GEN11_DE_PIPE_IRQ_FAULT_ERRORS;
8392b874a02SJani Nikula else if (DISPLAY_VER(dev_priv) >= 9)
8402b874a02SJani Nikula return GEN9_DE_PIPE_IRQ_FAULT_ERRORS;
8412b874a02SJani Nikula else
8422b874a02SJani Nikula return GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
8432b874a02SJani Nikula }
8442b874a02SJani Nikula
intel_pmdemand_irq_handler(struct drm_i915_private * dev_priv)8454c4cc7acSMika Kahola static void intel_pmdemand_irq_handler(struct drm_i915_private *dev_priv)
8464c4cc7acSMika Kahola {
8474c4cc7acSMika Kahola wake_up_all(&dev_priv->display.pmdemand.waitqueue);
8484c4cc7acSMika Kahola }
8494c4cc7acSMika Kahola
8502b874a02SJani Nikula static void
gen8_de_misc_irq_handler(struct drm_i915_private * dev_priv,u32 iir)8512b874a02SJani Nikula gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
8522b874a02SJani Nikula {
8532b874a02SJani Nikula bool found = false;
8542b874a02SJani Nikula
8554c4cc7acSMika Kahola if (DISPLAY_VER(dev_priv) >= 14) {
8564c4cc7acSMika Kahola if (iir & (XELPDP_PMDEMAND_RSP |
8574c4cc7acSMika Kahola XELPDP_PMDEMAND_RSPTOUT_ERR)) {
8584c4cc7acSMika Kahola if (iir & XELPDP_PMDEMAND_RSPTOUT_ERR)
8594c4cc7acSMika Kahola drm_dbg(&dev_priv->drm,
8604c4cc7acSMika Kahola "Error waiting for Punit PM Demand Response\n");
8614c4cc7acSMika Kahola
8624c4cc7acSMika Kahola intel_pmdemand_irq_handler(dev_priv);
8634c4cc7acSMika Kahola found = true;
8644c4cc7acSMika Kahola }
8654c4cc7acSMika Kahola } else if (iir & GEN8_DE_MISC_GSE) {
8662b874a02SJani Nikula intel_opregion_asle_intr(dev_priv);
8672b874a02SJani Nikula found = true;
8682b874a02SJani Nikula }
8692b874a02SJani Nikula
8702b874a02SJani Nikula if (iir & GEN8_DE_EDP_PSR) {
8712b874a02SJani Nikula struct intel_encoder *encoder;
8722b874a02SJani Nikula u32 psr_iir;
8732b874a02SJani Nikula i915_reg_t iir_reg;
8742b874a02SJani Nikula
8752b874a02SJani Nikula for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
8762b874a02SJani Nikula struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
8772b874a02SJani Nikula
8782b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 12)
8792b874a02SJani Nikula iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder);
8802b874a02SJani Nikula else
8812b874a02SJani Nikula iir_reg = EDP_PSR_IIR;
8822b874a02SJani Nikula
8832b874a02SJani Nikula psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0);
8842b874a02SJani Nikula
8852b874a02SJani Nikula if (psr_iir)
8862b874a02SJani Nikula found = true;
8872b874a02SJani Nikula
8882b874a02SJani Nikula intel_psr_irq_handler(intel_dp, psr_iir);
8892b874a02SJani Nikula
8902b874a02SJani Nikula /* prior GEN12 only have one EDP PSR */
8912b874a02SJani Nikula if (DISPLAY_VER(dev_priv) < 12)
8922b874a02SJani Nikula break;
8932b874a02SJani Nikula }
8942b874a02SJani Nikula }
8952b874a02SJani Nikula
8962b874a02SJani Nikula if (!found)
8972b874a02SJani Nikula drm_err(&dev_priv->drm, "Unexpected DE Misc interrupt\n");
8982b874a02SJani Nikula }
8992b874a02SJani Nikula
gen11_dsi_te_interrupt_handler(struct drm_i915_private * dev_priv,u32 te_trigger)9002b874a02SJani Nikula static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv,
9012b874a02SJani Nikula u32 te_trigger)
9022b874a02SJani Nikula {
9032b874a02SJani Nikula enum pipe pipe = INVALID_PIPE;
9042b874a02SJani Nikula enum transcoder dsi_trans;
9052b874a02SJani Nikula enum port port;
90641b611dbSJani Nikula u32 val;
9072b874a02SJani Nikula
9082b874a02SJani Nikula /*
9092b874a02SJani Nikula * Incase of dual link, TE comes from DSI_1
9102b874a02SJani Nikula * this is to check if dual link is enabled
9112b874a02SJani Nikula */
9122b874a02SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL2(TRANSCODER_DSI_0));
9132b874a02SJani Nikula val &= PORT_SYNC_MODE_ENABLE;
9142b874a02SJani Nikula
9152b874a02SJani Nikula /*
9162b874a02SJani Nikula * if dual link is enabled, then read DSI_0
9172b874a02SJani Nikula * transcoder registers
9182b874a02SJani Nikula */
9192b874a02SJani Nikula port = ((te_trigger & DSI1_TE && val) || (te_trigger & DSI0_TE)) ?
9202b874a02SJani Nikula PORT_A : PORT_B;
9212b874a02SJani Nikula dsi_trans = (port == PORT_A) ? TRANSCODER_DSI_0 : TRANSCODER_DSI_1;
9222b874a02SJani Nikula
9232b874a02SJani Nikula /* Check if DSI configured in command mode */
9242b874a02SJani Nikula val = intel_uncore_read(&dev_priv->uncore, DSI_TRANS_FUNC_CONF(dsi_trans));
9252b874a02SJani Nikula val = val & OP_MODE_MASK;
9262b874a02SJani Nikula
9272b874a02SJani Nikula if (val != CMD_MODE_NO_GATE && val != CMD_MODE_TE_GATE) {
9282b874a02SJani Nikula drm_err(&dev_priv->drm, "DSI trancoder not configured in command mode\n");
9292b874a02SJani Nikula return;
9302b874a02SJani Nikula }
9312b874a02SJani Nikula
9322b874a02SJani Nikula /* Get PIPE for handling VBLANK event */
9332b874a02SJani Nikula val = intel_uncore_read(&dev_priv->uncore, TRANS_DDI_FUNC_CTL(dsi_trans));
9342b874a02SJani Nikula switch (val & TRANS_DDI_EDP_INPUT_MASK) {
9352b874a02SJani Nikula case TRANS_DDI_EDP_INPUT_A_ON:
9362b874a02SJani Nikula pipe = PIPE_A;
9372b874a02SJani Nikula break;
9382b874a02SJani Nikula case TRANS_DDI_EDP_INPUT_B_ONOFF:
9392b874a02SJani Nikula pipe = PIPE_B;
9402b874a02SJani Nikula break;
9412b874a02SJani Nikula case TRANS_DDI_EDP_INPUT_C_ONOFF:
9422b874a02SJani Nikula pipe = PIPE_C;
9432b874a02SJani Nikula break;
9442b874a02SJani Nikula default:
9452b874a02SJani Nikula drm_err(&dev_priv->drm, "Invalid PIPE\n");
9462b874a02SJani Nikula return;
9472b874a02SJani Nikula }
9482b874a02SJani Nikula
9492b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
9502b874a02SJani Nikula
9512b874a02SJani Nikula /* clear TE in dsi IIR */
9522b874a02SJani Nikula port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A;
95341b611dbSJani Nikula intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
9542b874a02SJani Nikula }
9552b874a02SJani Nikula
gen8_de_pipe_flip_done_mask(struct drm_i915_private * i915)9562b874a02SJani Nikula static u32 gen8_de_pipe_flip_done_mask(struct drm_i915_private *i915)
9572b874a02SJani Nikula {
9582b874a02SJani Nikula if (DISPLAY_VER(i915) >= 9)
9592b874a02SJani Nikula return GEN9_PIPE_PLANE1_FLIP_DONE;
9602b874a02SJani Nikula else
9612b874a02SJani Nikula return GEN8_PIPE_PRIMARY_FLIP_DONE;
9622b874a02SJani Nikula }
9632b874a02SJani Nikula
gen8_de_pipe_underrun_mask(struct drm_i915_private * dev_priv)9642b874a02SJani Nikula u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv)
9652b874a02SJani Nikula {
9662b874a02SJani Nikula u32 mask = GEN8_PIPE_FIFO_UNDERRUN;
9672b874a02SJani Nikula
9682b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 13)
9692b874a02SJani Nikula mask |= XELPD_PIPE_SOFT_UNDERRUN |
9702b874a02SJani Nikula XELPD_PIPE_HARD_UNDERRUN;
9712b874a02SJani Nikula
9722b874a02SJani Nikula return mask;
9732b874a02SJani Nikula }
9742b874a02SJani Nikula
gen8_read_and_ack_pch_irqs(struct drm_i915_private * i915,u32 * pch_iir,u32 * pica_iir)9752b874a02SJani Nikula static void gen8_read_and_ack_pch_irqs(struct drm_i915_private *i915, u32 *pch_iir, u32 *pica_iir)
9762b874a02SJani Nikula {
9772b874a02SJani Nikula u32 pica_ier = 0;
9782b874a02SJani Nikula
9792b874a02SJani Nikula *pica_iir = 0;
9802b874a02SJani Nikula *pch_iir = intel_de_read(i915, SDEIIR);
9812b874a02SJani Nikula if (!*pch_iir)
9822b874a02SJani Nikula return;
9832b874a02SJani Nikula
9842b874a02SJani Nikula /**
9852b874a02SJani Nikula * PICA IER must be disabled/re-enabled around clearing PICA IIR and
9862b874a02SJani Nikula * SDEIIR, to avoid losing PICA IRQs and to ensure that such IRQs set
9872b874a02SJani Nikula * their flags both in the PICA and SDE IIR.
9882b874a02SJani Nikula */
9892b874a02SJani Nikula if (*pch_iir & SDE_PICAINTERRUPT) {
9902b874a02SJani Nikula drm_WARN_ON(&i915->drm, INTEL_PCH_TYPE(i915) < PCH_MTP);
9912b874a02SJani Nikula
9922b874a02SJani Nikula pica_ier = intel_de_rmw(i915, PICAINTERRUPT_IER, ~0, 0);
9932b874a02SJani Nikula *pica_iir = intel_de_read(i915, PICAINTERRUPT_IIR);
9942b874a02SJani Nikula intel_de_write(i915, PICAINTERRUPT_IIR, *pica_iir);
9952b874a02SJani Nikula }
9962b874a02SJani Nikula
9972b874a02SJani Nikula intel_de_write(i915, SDEIIR, *pch_iir);
9982b874a02SJani Nikula
9992b874a02SJani Nikula if (pica_ier)
10002b874a02SJani Nikula intel_de_write(i915, PICAINTERRUPT_IER, pica_ier);
10012b874a02SJani Nikula }
10022b874a02SJani Nikula
gen8_de_irq_handler(struct drm_i915_private * dev_priv,u32 master_ctl)10032b874a02SJani Nikula void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
10042b874a02SJani Nikula {
10052b874a02SJani Nikula u32 iir;
10062b874a02SJani Nikula enum pipe pipe;
10072b874a02SJani Nikula
10082b874a02SJani Nikula drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DISPLAY(dev_priv));
10092b874a02SJani Nikula
10102b874a02SJani Nikula if (master_ctl & GEN8_DE_MISC_IRQ) {
10112b874a02SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_MISC_IIR);
10122b874a02SJani Nikula if (iir) {
10132b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_MISC_IIR, iir);
10142b874a02SJani Nikula gen8_de_misc_irq_handler(dev_priv, iir);
10152b874a02SJani Nikula } else {
10162b874a02SJani Nikula drm_err_ratelimited(&dev_priv->drm,
10172b874a02SJani Nikula "The master control interrupt lied (DE MISC)!\n");
10182b874a02SJani Nikula }
10192b874a02SJani Nikula }
10202b874a02SJani Nikula
10212b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 11 && (master_ctl & GEN11_DE_HPD_IRQ)) {
10222b874a02SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IIR);
10232b874a02SJani Nikula if (iir) {
10242b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IIR, iir);
10252b874a02SJani Nikula gen11_hpd_irq_handler(dev_priv, iir);
10262b874a02SJani Nikula } else {
10272b874a02SJani Nikula drm_err_ratelimited(&dev_priv->drm,
10282b874a02SJani Nikula "The master control interrupt lied, (DE HPD)!\n");
10292b874a02SJani Nikula }
10302b874a02SJani Nikula }
10312b874a02SJani Nikula
10322b874a02SJani Nikula if (master_ctl & GEN8_DE_PORT_IRQ) {
10332b874a02SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PORT_IIR);
10342b874a02SJani Nikula if (iir) {
10352b874a02SJani Nikula bool found = false;
10362b874a02SJani Nikula
10372b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PORT_IIR, iir);
10382b874a02SJani Nikula
10392b874a02SJani Nikula if (iir & gen8_de_port_aux_mask(dev_priv)) {
10402b874a02SJani Nikula intel_dp_aux_irq_handler(dev_priv);
10412b874a02SJani Nikula found = true;
10422b874a02SJani Nikula }
10432b874a02SJani Nikula
10442b874a02SJani Nikula if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
10452b874a02SJani Nikula u32 hotplug_trigger = iir & BXT_DE_PORT_HOTPLUG_MASK;
10462b874a02SJani Nikula
10472b874a02SJani Nikula if (hotplug_trigger) {
10482b874a02SJani Nikula bxt_hpd_irq_handler(dev_priv, hotplug_trigger);
10492b874a02SJani Nikula found = true;
10502b874a02SJani Nikula }
10512b874a02SJani Nikula } else if (IS_BROADWELL(dev_priv)) {
10522b874a02SJani Nikula u32 hotplug_trigger = iir & BDW_DE_PORT_HOTPLUG_MASK;
10532b874a02SJani Nikula
10542b874a02SJani Nikula if (hotplug_trigger) {
10552b874a02SJani Nikula ilk_hpd_irq_handler(dev_priv, hotplug_trigger);
10562b874a02SJani Nikula found = true;
10572b874a02SJani Nikula }
10582b874a02SJani Nikula }
10592b874a02SJani Nikula
10602b874a02SJani Nikula if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
10612b874a02SJani Nikula (iir & BXT_DE_PORT_GMBUS)) {
10622b874a02SJani Nikula intel_gmbus_irq_handler(dev_priv);
10632b874a02SJani Nikula found = true;
10642b874a02SJani Nikula }
10652b874a02SJani Nikula
10662b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 11) {
10672b874a02SJani Nikula u32 te_trigger = iir & (DSI0_TE | DSI1_TE);
10682b874a02SJani Nikula
10692b874a02SJani Nikula if (te_trigger) {
10702b874a02SJani Nikula gen11_dsi_te_interrupt_handler(dev_priv, te_trigger);
10712b874a02SJani Nikula found = true;
10722b874a02SJani Nikula }
10732b874a02SJani Nikula }
10742b874a02SJani Nikula
10752b874a02SJani Nikula if (!found)
10762b874a02SJani Nikula drm_err_ratelimited(&dev_priv->drm,
10772b874a02SJani Nikula "Unexpected DE Port interrupt\n");
10782b874a02SJani Nikula } else {
10792b874a02SJani Nikula drm_err_ratelimited(&dev_priv->drm,
10802b874a02SJani Nikula "The master control interrupt lied (DE PORT)!\n");
10812b874a02SJani Nikula }
10822b874a02SJani Nikula }
10832b874a02SJani Nikula
10842b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
10852b874a02SJani Nikula u32 fault_errors;
10862b874a02SJani Nikula
10872b874a02SJani Nikula if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
10882b874a02SJani Nikula continue;
10892b874a02SJani Nikula
10902b874a02SJani Nikula iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe));
10912b874a02SJani Nikula if (!iir) {
10922b874a02SJani Nikula drm_err_ratelimited(&dev_priv->drm,
10932b874a02SJani Nikula "The master control interrupt lied (DE PIPE)!\n");
10942b874a02SJani Nikula continue;
10952b874a02SJani Nikula }
10962b874a02SJani Nikula
10972b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), iir);
10982b874a02SJani Nikula
10992b874a02SJani Nikula if (iir & GEN8_PIPE_VBLANK)
11002b874a02SJani Nikula intel_handle_vblank(dev_priv, pipe);
11012b874a02SJani Nikula
11022b874a02SJani Nikula if (iir & gen8_de_pipe_flip_done_mask(dev_priv))
11032b874a02SJani Nikula flip_done_handler(dev_priv, pipe);
11042b874a02SJani Nikula
11052b874a02SJani Nikula if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
11062b874a02SJani Nikula hsw_pipe_crc_irq_handler(dev_priv, pipe);
11072b874a02SJani Nikula
11082b874a02SJani Nikula if (iir & gen8_de_pipe_underrun_mask(dev_priv))
11092b874a02SJani Nikula intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
11102b874a02SJani Nikula
11112b874a02SJani Nikula fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
11122b874a02SJani Nikula if (fault_errors)
11132b874a02SJani Nikula drm_err_ratelimited(&dev_priv->drm,
11142b874a02SJani Nikula "Fault errors on pipe %c: 0x%08x\n",
11152b874a02SJani Nikula pipe_name(pipe),
11162b874a02SJani Nikula fault_errors);
11172b874a02SJani Nikula }
11182b874a02SJani Nikula
11192b874a02SJani Nikula if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
11202b874a02SJani Nikula master_ctl & GEN8_DE_PCH_IRQ) {
11212b874a02SJani Nikula u32 pica_iir;
11222b874a02SJani Nikula
11232b874a02SJani Nikula /*
11242b874a02SJani Nikula * FIXME(BDW): Assume for now that the new interrupt handling
11252b874a02SJani Nikula * scheme also closed the SDE interrupt handling race we've seen
11262b874a02SJani Nikula * on older pch-split platforms. But this needs testing.
11272b874a02SJani Nikula */
11282b874a02SJani Nikula gen8_read_and_ack_pch_irqs(dev_priv, &iir, &pica_iir);
11292b874a02SJani Nikula if (iir) {
11302b874a02SJani Nikula if (pica_iir)
11312b874a02SJani Nikula xelpdp_pica_irq_handler(dev_priv, pica_iir);
11322b874a02SJani Nikula
11332b874a02SJani Nikula if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
11342b874a02SJani Nikula icp_irq_handler(dev_priv, iir);
11352b874a02SJani Nikula else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
11362b874a02SJani Nikula spt_irq_handler(dev_priv, iir);
11372b874a02SJani Nikula else
11382b874a02SJani Nikula cpt_irq_handler(dev_priv, iir);
11392b874a02SJani Nikula } else {
11402b874a02SJani Nikula /*
11412b874a02SJani Nikula * Like on previous PCH there seems to be something
11422b874a02SJani Nikula * fishy going on with forwarding PCH interrupts.
11432b874a02SJani Nikula */
11442b874a02SJani Nikula drm_dbg(&dev_priv->drm,
11452b874a02SJani Nikula "The master control interrupt lied (SDE)!\n");
11462b874a02SJani Nikula }
11472b874a02SJani Nikula }
11482b874a02SJani Nikula }
11492b874a02SJani Nikula
gen11_gu_misc_irq_ack(struct drm_i915_private * i915,const u32 master_ctl)11502b874a02SJani Nikula u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl)
11512b874a02SJani Nikula {
115272e9abc3SJani Nikula void __iomem * const regs = intel_uncore_regs(&i915->uncore);
11532b874a02SJani Nikula u32 iir;
11542b874a02SJani Nikula
11552b874a02SJani Nikula if (!(master_ctl & GEN11_GU_MISC_IRQ))
11562b874a02SJani Nikula return 0;
11572b874a02SJani Nikula
11582b874a02SJani Nikula iir = raw_reg_read(regs, GEN11_GU_MISC_IIR);
11592b874a02SJani Nikula if (likely(iir))
11602b874a02SJani Nikula raw_reg_write(regs, GEN11_GU_MISC_IIR, iir);
11612b874a02SJani Nikula
11622b874a02SJani Nikula return iir;
11632b874a02SJani Nikula }
11642b874a02SJani Nikula
gen11_gu_misc_irq_handler(struct drm_i915_private * i915,const u32 iir)11652b874a02SJani Nikula void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir)
11662b874a02SJani Nikula {
11672b874a02SJani Nikula if (iir & GEN11_GU_MISC_GSE)
11682b874a02SJani Nikula intel_opregion_asle_intr(i915);
11692b874a02SJani Nikula }
11702b874a02SJani Nikula
gen11_display_irq_handler(struct drm_i915_private * i915)11712b874a02SJani Nikula void gen11_display_irq_handler(struct drm_i915_private *i915)
11722b874a02SJani Nikula {
117372e9abc3SJani Nikula void __iomem * const regs = intel_uncore_regs(&i915->uncore);
11742b874a02SJani Nikula const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
11752b874a02SJani Nikula
11762b874a02SJani Nikula disable_rpm_wakeref_asserts(&i915->runtime_pm);
11772b874a02SJani Nikula /*
11782b874a02SJani Nikula * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
11792b874a02SJani Nikula * for the display related bits.
11802b874a02SJani Nikula */
11812b874a02SJani Nikula raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0);
11822b874a02SJani Nikula gen8_de_irq_handler(i915, disp_ctl);
11832b874a02SJani Nikula raw_reg_write(regs, GEN11_DISPLAY_INT_CTL,
11842b874a02SJani Nikula GEN11_DISPLAY_IRQ_ENABLE);
11852b874a02SJani Nikula
11862b874a02SJani Nikula enable_rpm_wakeref_asserts(&i915->runtime_pm);
11872b874a02SJani Nikula }
11882b874a02SJani Nikula
11892b874a02SJani Nikula /* Called from drm generic code, passed 'crtc' which
11902b874a02SJani Nikula * we use as a pipe index
11912b874a02SJani Nikula */
i8xx_enable_vblank(struct drm_crtc * crtc)11922b874a02SJani Nikula int i8xx_enable_vblank(struct drm_crtc *crtc)
11932b874a02SJani Nikula {
11942b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
11952b874a02SJani Nikula enum pipe pipe = to_intel_crtc(crtc)->pipe;
11962b874a02SJani Nikula unsigned long irqflags;
11972b874a02SJani Nikula
11982b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
11992b874a02SJani Nikula i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
12002b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
12012b874a02SJani Nikula
12022b874a02SJani Nikula return 0;
12032b874a02SJani Nikula }
12042b874a02SJani Nikula
i915gm_enable_vblank(struct drm_crtc * crtc)12052b874a02SJani Nikula int i915gm_enable_vblank(struct drm_crtc *crtc)
12062b874a02SJani Nikula {
12072b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
12082b874a02SJani Nikula
12092b874a02SJani Nikula /*
12102b874a02SJani Nikula * Vblank interrupts fail to wake the device up from C2+.
12112b874a02SJani Nikula * Disabling render clock gating during C-states avoids
12122b874a02SJani Nikula * the problem. There is a small power cost so we do this
12132b874a02SJani Nikula * only when vblank interrupts are actually enabled.
12142b874a02SJani Nikula */
12152b874a02SJani Nikula if (dev_priv->vblank_enabled++ == 0)
12162b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
12172b874a02SJani Nikula
12182b874a02SJani Nikula return i8xx_enable_vblank(crtc);
12192b874a02SJani Nikula }
12202b874a02SJani Nikula
i965_enable_vblank(struct drm_crtc * crtc)12212b874a02SJani Nikula int i965_enable_vblank(struct drm_crtc *crtc)
12222b874a02SJani Nikula {
12232b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
12242b874a02SJani Nikula enum pipe pipe = to_intel_crtc(crtc)->pipe;
12252b874a02SJani Nikula unsigned long irqflags;
12262b874a02SJani Nikula
12272b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
12282b874a02SJani Nikula i915_enable_pipestat(dev_priv, pipe,
12292b874a02SJani Nikula PIPE_START_VBLANK_INTERRUPT_STATUS);
12302b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
12312b874a02SJani Nikula
12322b874a02SJani Nikula return 0;
12332b874a02SJani Nikula }
12342b874a02SJani Nikula
ilk_enable_vblank(struct drm_crtc * crtc)12352b874a02SJani Nikula int ilk_enable_vblank(struct drm_crtc *crtc)
12362b874a02SJani Nikula {
12372b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
12382b874a02SJani Nikula enum pipe pipe = to_intel_crtc(crtc)->pipe;
12392b874a02SJani Nikula unsigned long irqflags;
12402b874a02SJani Nikula u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
12412b874a02SJani Nikula DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
12422b874a02SJani Nikula
12432b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
12442b874a02SJani Nikula ilk_enable_display_irq(dev_priv, bit);
12452b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
12462b874a02SJani Nikula
12472b874a02SJani Nikula /* Even though there is no DMC, frame counter can get stuck when
12482b874a02SJani Nikula * PSR is active as no frames are generated.
12492b874a02SJani Nikula */
12502b874a02SJani Nikula if (HAS_PSR(dev_priv))
12512b874a02SJani Nikula drm_crtc_vblank_restore(crtc);
12522b874a02SJani Nikula
12532b874a02SJani Nikula return 0;
12542b874a02SJani Nikula }
12552b874a02SJani Nikula
gen11_dsi_configure_te(struct intel_crtc * intel_crtc,bool enable)12562b874a02SJani Nikula static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
12572b874a02SJani Nikula bool enable)
12582b874a02SJani Nikula {
12592b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
12602b874a02SJani Nikula enum port port;
12612b874a02SJani Nikula
12622b874a02SJani Nikula if (!(intel_crtc->mode_flags &
12632b874a02SJani Nikula (I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0)))
12642b874a02SJani Nikula return false;
12652b874a02SJani Nikula
12662b874a02SJani Nikula /* for dual link cases we consider TE from slave */
12672b874a02SJani Nikula if (intel_crtc->mode_flags & I915_MODE_FLAG_DSI_USE_TE1)
12682b874a02SJani Nikula port = PORT_B;
12692b874a02SJani Nikula else
12702b874a02SJani Nikula port = PORT_A;
12712b874a02SJani Nikula
12722b874a02SJani Nikula intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT,
12732b874a02SJani Nikula enable ? 0 : DSI_TE_EVENT);
12742b874a02SJani Nikula
12752b874a02SJani Nikula intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
12762b874a02SJani Nikula
12772b874a02SJani Nikula return true;
12782b874a02SJani Nikula }
12792b874a02SJani Nikula
bdw_enable_vblank(struct drm_crtc * _crtc)12802b874a02SJani Nikula int bdw_enable_vblank(struct drm_crtc *_crtc)
12812b874a02SJani Nikula {
12822b874a02SJani Nikula struct intel_crtc *crtc = to_intel_crtc(_crtc);
12832b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
12842b874a02SJani Nikula enum pipe pipe = crtc->pipe;
12852b874a02SJani Nikula unsigned long irqflags;
12862b874a02SJani Nikula
12872b874a02SJani Nikula if (gen11_dsi_configure_te(crtc, true))
12882b874a02SJani Nikula return 0;
12892b874a02SJani Nikula
12902b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
12912b874a02SJani Nikula bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
12922b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
12932b874a02SJani Nikula
12942b874a02SJani Nikula /* Even if there is no DMC, frame counter can get stuck when
12952b874a02SJani Nikula * PSR is active as no frames are generated, so check only for PSR.
12962b874a02SJani Nikula */
12972b874a02SJani Nikula if (HAS_PSR(dev_priv))
12982b874a02SJani Nikula drm_crtc_vblank_restore(&crtc->base);
12992b874a02SJani Nikula
13002b874a02SJani Nikula return 0;
13012b874a02SJani Nikula }
13022b874a02SJani Nikula
13032b874a02SJani Nikula /* Called from drm generic code, passed 'crtc' which
13042b874a02SJani Nikula * we use as a pipe index
13052b874a02SJani Nikula */
i8xx_disable_vblank(struct drm_crtc * crtc)13062b874a02SJani Nikula void i8xx_disable_vblank(struct drm_crtc *crtc)
13072b874a02SJani Nikula {
13082b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
13092b874a02SJani Nikula enum pipe pipe = to_intel_crtc(crtc)->pipe;
13102b874a02SJani Nikula unsigned long irqflags;
13112b874a02SJani Nikula
13122b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
13132b874a02SJani Nikula i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
13142b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
13152b874a02SJani Nikula }
13162b874a02SJani Nikula
i915gm_disable_vblank(struct drm_crtc * crtc)13172b874a02SJani Nikula void i915gm_disable_vblank(struct drm_crtc *crtc)
13182b874a02SJani Nikula {
13192b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
13202b874a02SJani Nikula
13212b874a02SJani Nikula i8xx_disable_vblank(crtc);
13222b874a02SJani Nikula
13232b874a02SJani Nikula if (--dev_priv->vblank_enabled == 0)
13242b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
13252b874a02SJani Nikula }
13262b874a02SJani Nikula
i965_disable_vblank(struct drm_crtc * crtc)13272b874a02SJani Nikula void i965_disable_vblank(struct drm_crtc *crtc)
13282b874a02SJani Nikula {
13292b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
13302b874a02SJani Nikula enum pipe pipe = to_intel_crtc(crtc)->pipe;
13312b874a02SJani Nikula unsigned long irqflags;
13322b874a02SJani Nikula
13332b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
13342b874a02SJani Nikula i915_disable_pipestat(dev_priv, pipe,
13352b874a02SJani Nikula PIPE_START_VBLANK_INTERRUPT_STATUS);
13362b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
13372b874a02SJani Nikula }
13382b874a02SJani Nikula
ilk_disable_vblank(struct drm_crtc * crtc)13392b874a02SJani Nikula void ilk_disable_vblank(struct drm_crtc *crtc)
13402b874a02SJani Nikula {
13412b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->dev);
13422b874a02SJani Nikula enum pipe pipe = to_intel_crtc(crtc)->pipe;
13432b874a02SJani Nikula unsigned long irqflags;
13442b874a02SJani Nikula u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
13452b874a02SJani Nikula DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
13462b874a02SJani Nikula
13472b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
13482b874a02SJani Nikula ilk_disable_display_irq(dev_priv, bit);
13492b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
13502b874a02SJani Nikula }
13512b874a02SJani Nikula
bdw_disable_vblank(struct drm_crtc * _crtc)13522b874a02SJani Nikula void bdw_disable_vblank(struct drm_crtc *_crtc)
13532b874a02SJani Nikula {
13542b874a02SJani Nikula struct intel_crtc *crtc = to_intel_crtc(_crtc);
13552b874a02SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
13562b874a02SJani Nikula enum pipe pipe = crtc->pipe;
13572b874a02SJani Nikula unsigned long irqflags;
13582b874a02SJani Nikula
13592b874a02SJani Nikula if (gen11_dsi_configure_te(crtc, false))
13602b874a02SJani Nikula return;
13612b874a02SJani Nikula
13622b874a02SJani Nikula spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
13632b874a02SJani Nikula bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
13642b874a02SJani Nikula spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
13652b874a02SJani Nikula }
13662b874a02SJani Nikula
vlv_display_irq_reset(struct drm_i915_private * dev_priv)13672b874a02SJani Nikula void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
13682b874a02SJani Nikula {
13692b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
13702b874a02SJani Nikula
13712b874a02SJani Nikula if (IS_CHERRYVIEW(dev_priv))
13722b874a02SJani Nikula intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
13732b874a02SJani Nikula else
13742b874a02SJani Nikula intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
13752b874a02SJani Nikula
13762b874a02SJani Nikula i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
13772b874a02SJani Nikula intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
13782b874a02SJani Nikula
13792b874a02SJani Nikula i9xx_pipestat_irq_reset(dev_priv);
13802b874a02SJani Nikula
13812b874a02SJani Nikula GEN3_IRQ_RESET(uncore, VLV_);
13822b874a02SJani Nikula dev_priv->irq_mask = ~0u;
13832b874a02SJani Nikula }
13842b874a02SJani Nikula
vlv_display_irq_postinstall(struct drm_i915_private * dev_priv)13852b874a02SJani Nikula void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
13862b874a02SJani Nikula {
13872b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
13882b874a02SJani Nikula
13892b874a02SJani Nikula u32 pipestat_mask;
13902b874a02SJani Nikula u32 enable_mask;
13912b874a02SJani Nikula enum pipe pipe;
13922b874a02SJani Nikula
13932b874a02SJani Nikula pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
13942b874a02SJani Nikula
13952b874a02SJani Nikula i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
13962b874a02SJani Nikula for_each_pipe(dev_priv, pipe)
13972b874a02SJani Nikula i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
13982b874a02SJani Nikula
13992b874a02SJani Nikula enable_mask = I915_DISPLAY_PORT_INTERRUPT |
14002b874a02SJani Nikula I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
14012b874a02SJani Nikula I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
14022b874a02SJani Nikula I915_LPE_PIPE_A_INTERRUPT |
14032b874a02SJani Nikula I915_LPE_PIPE_B_INTERRUPT;
14042b874a02SJani Nikula
14052b874a02SJani Nikula if (IS_CHERRYVIEW(dev_priv))
14062b874a02SJani Nikula enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
14072b874a02SJani Nikula I915_LPE_PIPE_C_INTERRUPT;
14082b874a02SJani Nikula
14092b874a02SJani Nikula drm_WARN_ON(&dev_priv->drm, dev_priv->irq_mask != ~0u);
14102b874a02SJani Nikula
14112b874a02SJani Nikula dev_priv->irq_mask = ~enable_mask;
14122b874a02SJani Nikula
14132b874a02SJani Nikula GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask);
14142b874a02SJani Nikula }
14152b874a02SJani Nikula
gen8_display_irq_reset(struct drm_i915_private * dev_priv)14162b874a02SJani Nikula void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
14172b874a02SJani Nikula {
14182b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
14192b874a02SJani Nikula enum pipe pipe;
14202b874a02SJani Nikula
14212b874a02SJani Nikula if (!HAS_DISPLAY(dev_priv))
14222b874a02SJani Nikula return;
14232b874a02SJani Nikula
14242b874a02SJani Nikula intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
14252b874a02SJani Nikula intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
14262b874a02SJani Nikula
14272b874a02SJani Nikula for_each_pipe(dev_priv, pipe)
14282b874a02SJani Nikula if (intel_display_power_is_enabled(dev_priv,
14292b874a02SJani Nikula POWER_DOMAIN_PIPE(pipe)))
14302b874a02SJani Nikula GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
14312b874a02SJani Nikula
14322b874a02SJani Nikula GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
14332b874a02SJani Nikula GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
14342b874a02SJani Nikula }
14352b874a02SJani Nikula
gen11_display_irq_reset(struct drm_i915_private * dev_priv)14362b874a02SJani Nikula void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
14372b874a02SJani Nikula {
14382b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
14392b874a02SJani Nikula enum pipe pipe;
14402b874a02SJani Nikula u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
14412b874a02SJani Nikula BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
14422b874a02SJani Nikula
14432b874a02SJani Nikula if (!HAS_DISPLAY(dev_priv))
14442b874a02SJani Nikula return;
14452b874a02SJani Nikula
14462b874a02SJani Nikula intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0);
14472b874a02SJani Nikula
14482b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 12) {
14492b874a02SJani Nikula enum transcoder trans;
14502b874a02SJani Nikula
14512b874a02SJani Nikula for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
14522b874a02SJani Nikula enum intel_display_power_domain domain;
14532b874a02SJani Nikula
14542b874a02SJani Nikula domain = POWER_DOMAIN_TRANSCODER(trans);
14552b874a02SJani Nikula if (!intel_display_power_is_enabled(dev_priv, domain))
14562b874a02SJani Nikula continue;
14572b874a02SJani Nikula
14582b874a02SJani Nikula intel_uncore_write(uncore, TRANS_PSR_IMR(trans), 0xffffffff);
14592b874a02SJani Nikula intel_uncore_write(uncore, TRANS_PSR_IIR(trans), 0xffffffff);
14602b874a02SJani Nikula }
14612b874a02SJani Nikula } else {
14622b874a02SJani Nikula intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff);
14632b874a02SJani Nikula intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff);
14642b874a02SJani Nikula }
14652b874a02SJani Nikula
14662b874a02SJani Nikula for_each_pipe(dev_priv, pipe)
14672b874a02SJani Nikula if (intel_display_power_is_enabled(dev_priv,
14682b874a02SJani Nikula POWER_DOMAIN_PIPE(pipe)))
14692b874a02SJani Nikula GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
14702b874a02SJani Nikula
14712b874a02SJani Nikula GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
14722b874a02SJani Nikula GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
14732b874a02SJani Nikula
14742b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 14)
14752b874a02SJani Nikula GEN3_IRQ_RESET(uncore, PICAINTERRUPT_);
14762b874a02SJani Nikula else
14772b874a02SJani Nikula GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_);
14782b874a02SJani Nikula
14792b874a02SJani Nikula if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
14802b874a02SJani Nikula GEN3_IRQ_RESET(uncore, SDE);
14812b874a02SJani Nikula }
14822b874a02SJani Nikula
gen8_irq_power_well_post_enable(struct drm_i915_private * dev_priv,u8 pipe_mask)14832b874a02SJani Nikula void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
14842b874a02SJani Nikula u8 pipe_mask)
14852b874a02SJani Nikula {
14862b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
14872b874a02SJani Nikula u32 extra_ier = GEN8_PIPE_VBLANK |
14882b874a02SJani Nikula gen8_de_pipe_underrun_mask(dev_priv) |
14892b874a02SJani Nikula gen8_de_pipe_flip_done_mask(dev_priv);
14902b874a02SJani Nikula enum pipe pipe;
14912b874a02SJani Nikula
14922b874a02SJani Nikula spin_lock_irq(&dev_priv->irq_lock);
14932b874a02SJani Nikula
14942b874a02SJani Nikula if (!intel_irqs_enabled(dev_priv)) {
14952b874a02SJani Nikula spin_unlock_irq(&dev_priv->irq_lock);
14962b874a02SJani Nikula return;
14972b874a02SJani Nikula }
14982b874a02SJani Nikula
14992b874a02SJani Nikula for_each_pipe_masked(dev_priv, pipe, pipe_mask)
15002b874a02SJani Nikula GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
15012b874a02SJani Nikula dev_priv->de_irq_mask[pipe],
15022b874a02SJani Nikula ~dev_priv->de_irq_mask[pipe] | extra_ier);
15032b874a02SJani Nikula
15042b874a02SJani Nikula spin_unlock_irq(&dev_priv->irq_lock);
15052b874a02SJani Nikula }
15062b874a02SJani Nikula
gen8_irq_power_well_pre_disable(struct drm_i915_private * dev_priv,u8 pipe_mask)15072b874a02SJani Nikula void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
15082b874a02SJani Nikula u8 pipe_mask)
15092b874a02SJani Nikula {
15102b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
15112b874a02SJani Nikula enum pipe pipe;
15122b874a02SJani Nikula
15132b874a02SJani Nikula spin_lock_irq(&dev_priv->irq_lock);
15142b874a02SJani Nikula
15152b874a02SJani Nikula if (!intel_irqs_enabled(dev_priv)) {
15162b874a02SJani Nikula spin_unlock_irq(&dev_priv->irq_lock);
15172b874a02SJani Nikula return;
15182b874a02SJani Nikula }
15192b874a02SJani Nikula
15202b874a02SJani Nikula for_each_pipe_masked(dev_priv, pipe, pipe_mask)
15212b874a02SJani Nikula GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
15222b874a02SJani Nikula
15232b874a02SJani Nikula spin_unlock_irq(&dev_priv->irq_lock);
15242b874a02SJani Nikula
15252b874a02SJani Nikula /* make sure we're done processing display irqs */
15262b874a02SJani Nikula intel_synchronize_irq(dev_priv);
15272b874a02SJani Nikula }
15282b874a02SJani Nikula
15292b874a02SJani Nikula /*
15302b874a02SJani Nikula * SDEIER is also touched by the interrupt handler to work around missed PCH
15312b874a02SJani Nikula * interrupts. Hence we can't update it after the interrupt handler is enabled -
15322b874a02SJani Nikula * instead we unconditionally enable all PCH interrupt sources here, but then
15332b874a02SJani Nikula * only unmask them as needed with SDEIMR.
15342b874a02SJani Nikula *
15352b874a02SJani Nikula * Note that we currently do this after installing the interrupt handler,
15362b874a02SJani Nikula * but before we enable the master interrupt. That should be sufficient
15372b874a02SJani Nikula * to avoid races with the irq handler, assuming we have MSI. Shared legacy
15382b874a02SJani Nikula * interrupts could still race.
15392b874a02SJani Nikula */
ibx_irq_postinstall(struct drm_i915_private * dev_priv)1540*129ebb54SJani Nikula static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
15412b874a02SJani Nikula {
15422b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
15432b874a02SJani Nikula u32 mask;
15442b874a02SJani Nikula
15452b874a02SJani Nikula if (HAS_PCH_NOP(dev_priv))
15462b874a02SJani Nikula return;
15472b874a02SJani Nikula
15482b874a02SJani Nikula if (HAS_PCH_IBX(dev_priv))
15492b874a02SJani Nikula mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
15502b874a02SJani Nikula else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
15512b874a02SJani Nikula mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
15522b874a02SJani Nikula else
15532b874a02SJani Nikula mask = SDE_GMBUS_CPT;
15542b874a02SJani Nikula
15552b874a02SJani Nikula GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
15562b874a02SJani Nikula }
15572b874a02SJani Nikula
valleyview_enable_display_irqs(struct drm_i915_private * dev_priv)15582b874a02SJani Nikula void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
15592b874a02SJani Nikula {
15602b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
15612b874a02SJani Nikula
15622b874a02SJani Nikula if (dev_priv->display_irqs_enabled)
15632b874a02SJani Nikula return;
15642b874a02SJani Nikula
15652b874a02SJani Nikula dev_priv->display_irqs_enabled = true;
15662b874a02SJani Nikula
15672b874a02SJani Nikula if (intel_irqs_enabled(dev_priv)) {
15682b874a02SJani Nikula vlv_display_irq_reset(dev_priv);
15692b874a02SJani Nikula vlv_display_irq_postinstall(dev_priv);
15702b874a02SJani Nikula }
15712b874a02SJani Nikula }
15722b874a02SJani Nikula
valleyview_disable_display_irqs(struct drm_i915_private * dev_priv)15732b874a02SJani Nikula void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
15742b874a02SJani Nikula {
15752b874a02SJani Nikula lockdep_assert_held(&dev_priv->irq_lock);
15762b874a02SJani Nikula
15772b874a02SJani Nikula if (!dev_priv->display_irqs_enabled)
15782b874a02SJani Nikula return;
15792b874a02SJani Nikula
15802b874a02SJani Nikula dev_priv->display_irqs_enabled = false;
15812b874a02SJani Nikula
15822b874a02SJani Nikula if (intel_irqs_enabled(dev_priv))
15832b874a02SJani Nikula vlv_display_irq_reset(dev_priv);
15842b874a02SJani Nikula }
15852b874a02SJani Nikula
ilk_de_irq_postinstall(struct drm_i915_private * i915)1586fcc02c75SJani Nikula void ilk_de_irq_postinstall(struct drm_i915_private *i915)
1587fcc02c75SJani Nikula {
1588fcc02c75SJani Nikula struct intel_uncore *uncore = &i915->uncore;
1589fcc02c75SJani Nikula u32 display_mask, extra_mask;
1590fcc02c75SJani Nikula
1591fcc02c75SJani Nikula if (GRAPHICS_VER(i915) >= 7) {
1592fcc02c75SJani Nikula display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
1593fcc02c75SJani Nikula DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB);
1594fcc02c75SJani Nikula extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
1595fcc02c75SJani Nikula DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB |
1596fcc02c75SJani Nikula DE_PLANE_FLIP_DONE_IVB(PLANE_C) |
1597fcc02c75SJani Nikula DE_PLANE_FLIP_DONE_IVB(PLANE_B) |
1598fcc02c75SJani Nikula DE_PLANE_FLIP_DONE_IVB(PLANE_A) |
1599fcc02c75SJani Nikula DE_DP_A_HOTPLUG_IVB);
1600fcc02c75SJani Nikula } else {
1601fcc02c75SJani Nikula display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
1602fcc02c75SJani Nikula DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE |
1603fcc02c75SJani Nikula DE_PIPEA_CRC_DONE | DE_POISON);
1604fcc02c75SJani Nikula extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK |
1605fcc02c75SJani Nikula DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
1606fcc02c75SJani Nikula DE_PLANE_FLIP_DONE(PLANE_A) |
1607fcc02c75SJani Nikula DE_PLANE_FLIP_DONE(PLANE_B) |
1608fcc02c75SJani Nikula DE_DP_A_HOTPLUG);
1609fcc02c75SJani Nikula }
1610fcc02c75SJani Nikula
1611fcc02c75SJani Nikula if (IS_HASWELL(i915)) {
1612fcc02c75SJani Nikula gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
1613fcc02c75SJani Nikula display_mask |= DE_EDP_PSR_INT_HSW;
1614fcc02c75SJani Nikula }
1615fcc02c75SJani Nikula
1616fcc02c75SJani Nikula if (IS_IRONLAKE_M(i915))
1617fcc02c75SJani Nikula extra_mask |= DE_PCU_EVENT;
1618fcc02c75SJani Nikula
1619fcc02c75SJani Nikula i915->irq_mask = ~display_mask;
1620fcc02c75SJani Nikula
1621fcc02c75SJani Nikula ibx_irq_postinstall(i915);
1622fcc02c75SJani Nikula
1623fcc02c75SJani Nikula GEN3_IRQ_INIT(uncore, DE, i915->irq_mask,
1624fcc02c75SJani Nikula display_mask | extra_mask);
1625fcc02c75SJani Nikula }
1626fcc02c75SJani Nikula
1627*129ebb54SJani Nikula static void mtp_irq_postinstall(struct drm_i915_private *i915);
1628*129ebb54SJani Nikula static void icp_irq_postinstall(struct drm_i915_private *i915);
1629*129ebb54SJani Nikula
gen8_de_irq_postinstall(struct drm_i915_private * dev_priv)16302b874a02SJani Nikula void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
16312b874a02SJani Nikula {
16322b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
16332b874a02SJani Nikula
16342b874a02SJani Nikula u32 de_pipe_masked = gen8_de_pipe_fault_mask(dev_priv) |
16352b874a02SJani Nikula GEN8_PIPE_CDCLK_CRC_DONE;
16362b874a02SJani Nikula u32 de_pipe_enables;
16372b874a02SJani Nikula u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
16382b874a02SJani Nikula u32 de_port_enables;
16392b874a02SJani Nikula u32 de_misc_masked = GEN8_DE_EDP_PSR;
16402b874a02SJani Nikula u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
16412b874a02SJani Nikula BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
16422b874a02SJani Nikula enum pipe pipe;
16432b874a02SJani Nikula
16442b874a02SJani Nikula if (!HAS_DISPLAY(dev_priv))
16452b874a02SJani Nikula return;
16462b874a02SJani Nikula
1647*129ebb54SJani Nikula if (DISPLAY_VER(dev_priv) >= 14)
1648*129ebb54SJani Nikula mtp_irq_postinstall(dev_priv);
1649*129ebb54SJani Nikula else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
1650*129ebb54SJani Nikula icp_irq_postinstall(dev_priv);
1651*129ebb54SJani Nikula else if (HAS_PCH_SPLIT(dev_priv))
1652*129ebb54SJani Nikula ibx_irq_postinstall(dev_priv);
1653*129ebb54SJani Nikula
16542b874a02SJani Nikula if (DISPLAY_VER(dev_priv) <= 10)
16552b874a02SJani Nikula de_misc_masked |= GEN8_DE_MISC_GSE;
16562b874a02SJani Nikula
16572b874a02SJani Nikula if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
16582b874a02SJani Nikula de_port_masked |= BXT_DE_PORT_GMBUS;
16592b874a02SJani Nikula
16604c4cc7acSMika Kahola if (DISPLAY_VER(dev_priv) >= 14) {
16614c4cc7acSMika Kahola de_misc_masked |= XELPDP_PMDEMAND_RSPTOUT_ERR |
16624c4cc7acSMika Kahola XELPDP_PMDEMAND_RSP;
16634c4cc7acSMika Kahola } else if (DISPLAY_VER(dev_priv) >= 11) {
16642b874a02SJani Nikula enum port port;
16652b874a02SJani Nikula
16662b874a02SJani Nikula if (intel_bios_is_dsi_present(dev_priv, &port))
16672b874a02SJani Nikula de_port_masked |= DSI0_TE | DSI1_TE;
16682b874a02SJani Nikula }
16692b874a02SJani Nikula
16702b874a02SJani Nikula de_pipe_enables = de_pipe_masked |
16712b874a02SJani Nikula GEN8_PIPE_VBLANK |
16722b874a02SJani Nikula gen8_de_pipe_underrun_mask(dev_priv) |
16732b874a02SJani Nikula gen8_de_pipe_flip_done_mask(dev_priv);
16742b874a02SJani Nikula
16752b874a02SJani Nikula de_port_enables = de_port_masked;
16762b874a02SJani Nikula if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
16772b874a02SJani Nikula de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
16782b874a02SJani Nikula else if (IS_BROADWELL(dev_priv))
16792b874a02SJani Nikula de_port_enables |= BDW_DE_PORT_HOTPLUG_MASK;
16802b874a02SJani Nikula
16812b874a02SJani Nikula if (DISPLAY_VER(dev_priv) >= 12) {
16822b874a02SJani Nikula enum transcoder trans;
16832b874a02SJani Nikula
16842b874a02SJani Nikula for_each_cpu_transcoder_masked(dev_priv, trans, trans_mask) {
16852b874a02SJani Nikula enum intel_display_power_domain domain;
16862b874a02SJani Nikula
16872b874a02SJani Nikula domain = POWER_DOMAIN_TRANSCODER(trans);
16882b874a02SJani Nikula if (!intel_display_power_is_enabled(dev_priv, domain))
16892b874a02SJani Nikula continue;
16902b874a02SJani Nikula
16912b874a02SJani Nikula gen3_assert_iir_is_zero(uncore, TRANS_PSR_IIR(trans));
16922b874a02SJani Nikula }
16932b874a02SJani Nikula } else {
16942b874a02SJani Nikula gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR);
16952b874a02SJani Nikula }
16962b874a02SJani Nikula
16972b874a02SJani Nikula for_each_pipe(dev_priv, pipe) {
16982b874a02SJani Nikula dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
16992b874a02SJani Nikula
17002b874a02SJani Nikula if (intel_display_power_is_enabled(dev_priv,
17012b874a02SJani Nikula POWER_DOMAIN_PIPE(pipe)))
17022b874a02SJani Nikula GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
17032b874a02SJani Nikula dev_priv->de_irq_mask[pipe],
17042b874a02SJani Nikula de_pipe_enables);
17052b874a02SJani Nikula }
17062b874a02SJani Nikula
17072b874a02SJani Nikula GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
17082b874a02SJani Nikula GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
17092b874a02SJani Nikula
17102b874a02SJani Nikula if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
17112b874a02SJani Nikula u32 de_hpd_masked = 0;
17122b874a02SJani Nikula u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
17132b874a02SJani Nikula GEN11_DE_TBT_HOTPLUG_MASK;
17142b874a02SJani Nikula
17152b874a02SJani Nikula GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
17162b874a02SJani Nikula de_hpd_enables);
17172b874a02SJani Nikula }
17182b874a02SJani Nikula }
17192b874a02SJani Nikula
mtp_irq_postinstall(struct drm_i915_private * i915)17201007337fSJani Nikula static void mtp_irq_postinstall(struct drm_i915_private *i915)
17212b874a02SJani Nikula {
17222b874a02SJani Nikula struct intel_uncore *uncore = &i915->uncore;
17232b874a02SJani Nikula u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT;
17242b874a02SJani Nikula u32 de_hpd_mask = XELPDP_AUX_TC_MASK;
17252b874a02SJani Nikula u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
17262b874a02SJani Nikula XELPDP_TBT_HOTPLUG_MASK;
17272b874a02SJani Nikula
17282b874a02SJani Nikula GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
17292b874a02SJani Nikula de_hpd_enables);
17302b874a02SJani Nikula
17312b874a02SJani Nikula GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
17322b874a02SJani Nikula }
17332b874a02SJani Nikula
icp_irq_postinstall(struct drm_i915_private * dev_priv)1734*129ebb54SJani Nikula static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
17352b874a02SJani Nikula {
17362b874a02SJani Nikula struct intel_uncore *uncore = &dev_priv->uncore;
17372b874a02SJani Nikula u32 mask = SDE_GMBUS_ICP;
17382b874a02SJani Nikula
17392b874a02SJani Nikula GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
17402b874a02SJani Nikula }
17412b874a02SJani Nikula
gen11_de_irq_postinstall(struct drm_i915_private * dev_priv)17422b874a02SJani Nikula void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
17432b874a02SJani Nikula {
17442b874a02SJani Nikula if (!HAS_DISPLAY(dev_priv))
17452b874a02SJani Nikula return;
17462b874a02SJani Nikula
17472b874a02SJani Nikula gen8_de_irq_postinstall(dev_priv);
17482b874a02SJani Nikula
17492b874a02SJani Nikula intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL,
17502b874a02SJani Nikula GEN11_DISPLAY_IRQ_ENABLE);
17512b874a02SJani Nikula }
17522b874a02SJani Nikula
dg1_de_irq_postinstall(struct drm_i915_private * i915)17531007337fSJani Nikula void dg1_de_irq_postinstall(struct drm_i915_private *i915)
17541007337fSJani Nikula {
17551007337fSJani Nikula if (!HAS_DISPLAY(i915))
17561007337fSJani Nikula return;
17571007337fSJani Nikula
17581007337fSJani Nikula gen8_de_irq_postinstall(i915);
17591007337fSJani Nikula intel_uncore_write(&i915->uncore, GEN11_DISPLAY_INT_CTL,
17601007337fSJani Nikula GEN11_DISPLAY_IRQ_ENABLE);
17611007337fSJani Nikula }
17621007337fSJani Nikula
intel_display_irq_init(struct drm_i915_private * i915)17631486d040SJani Nikula void intel_display_irq_init(struct drm_i915_private *i915)
17641486d040SJani Nikula {
17651486d040SJani Nikula i915->drm.vblank_disable_immediate = true;
17661486d040SJani Nikula
17671486d040SJani Nikula /*
17681486d040SJani Nikula * Most platforms treat the display irq block as an always-on power
17691486d040SJani Nikula * domain. vlv/chv can disable it at runtime and need special care to
17701486d040SJani Nikula * avoid writing any of the display block registers outside of the power
17711486d040SJani Nikula * domain. We defer setting up the display irqs in this case to the
17721486d040SJani Nikula * runtime pm.
17731486d040SJani Nikula */
17741486d040SJani Nikula i915->display_irqs_enabled = true;
17751486d040SJani Nikula if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
17761486d040SJani Nikula i915->display_irqs_enabled = false;
17771486d040SJani Nikula
17781486d040SJani Nikula intel_hotplug_irq_init(i915);
17791486d040SJani Nikula }
1780