[Intel-gfx] [PATCH 2/3] drm/i915/irq: split out hotplug irq handling

Rodrigo Vivi rodrigo.vivi at kernel.org
Fri May 5 14:35:37 UTC 2023


On Thu, May 04, 2023 at 07:57:30PM +0300, Jani Nikula wrote:
> Split hotplug irq handling out of i915_irq.[ch] into
> display/intel_hotplug_irq.[ch].
> 
> The line between the new intel_hotplug_irq.[ch] and the existing
> intel_hotplug.[ch] needs further clarification, but the first step is to
> move the stuff out of i915_irq.[ch].
> 
> Signed-off-by: Jani Nikula <jani.nikula at intel.com>

\o/ - special celebration after having had to deal with
hpd irq changes on the recent rebase of Xe...

Reviewed-by: Rodrigo Vivi <rodrigo.vivi at intel.com>


> ---
>  drivers/gpu/drm/i915/Makefile                 |    1 +
>  drivers/gpu/drm/i915/display/intel_crt.c      |    1 +
>  drivers/gpu/drm/i915/display/intel_dp.c       |    1 +
>  drivers/gpu/drm/i915/display/intel_hotplug.c  |    1 +
>  .../gpu/drm/i915/display/intel_hotplug_irq.c  | 1442 ++++++++++++++++
>  .../gpu/drm/i915/display/intel_hotplug_irq.h  |   35 +
>  drivers/gpu/drm/i915/i915_irq.c               | 1504 +----------------
>  drivers/gpu/drm/i915/i915_irq.h               |   12 +-
>  8 files changed, 1525 insertions(+), 1472 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_hotplug_irq.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_hotplug_irq.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index f2ac803e35b4..b8520aea6068 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -261,6 +261,7 @@ i915-y += \
>  	display/intel_hdcp.o \
>  	display/intel_hdcp_gsc.o \
>  	display/intel_hotplug.o \
> +	display/intel_hotplug_irq.o \
>  	display/intel_hti.o \
>  	display/intel_load_detect.o \
>  	display/intel_lpe_audio.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
> index 13519f78cf9f..ab57bc0873f1 100644
> --- a/drivers/gpu/drm/i915/display/intel_crt.c
> +++ b/drivers/gpu/drm/i915/display/intel_crt.c
> @@ -48,6 +48,7 @@
>  #include "intel_fifo_underrun.h"
>  #include "intel_gmbus.h"
>  #include "intel_hotplug.h"
> +#include "intel_hotplug_irq.h"
>  #include "intel_load_detect.h"
>  #include "intel_pch_display.h"
>  #include "intel_pch_refclk.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 4361c1ac65c3..9019071abcbf 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -68,6 +68,7 @@
>  #include "intel_hdcp.h"
>  #include "intel_hdmi.h"
>  #include "intel_hotplug.h"
> +#include "intel_hotplug_irq.h"
>  #include "intel_lspcon.h"
>  #include "intel_lvds.h"
>  #include "intel_panel.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
> index b12900446828..23a5e1a875f1 100644
> --- a/drivers/gpu/drm/i915/display/intel_hotplug.c
> +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
> @@ -27,6 +27,7 @@
>  #include "i915_irq.h"
>  #include "intel_display_types.h"
>  #include "intel_hotplug.h"
> +#include "intel_hotplug_irq.h"
>  
>  /**
>   * DOC: Hotplug
> diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
> new file mode 100644
> index 000000000000..1d7ae49e073e
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
> @@ -0,0 +1,1442 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include "i915_drv.h"
> +#include "i915_irq.h"
> +#include "i915_reg.h"
> +#include "intel_de.h"
> +#include "intel_display_types.h"
> +#include "intel_dp_aux.h"
> +#include "intel_gmbus.h"
> +#include "intel_hotplug.h"
> +#include "intel_hotplug_irq.h"
> +
> +typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val);
> +typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder);
> +typedef u32 (*hotplug_mask_func)(enum hpd_pin pin);
> +
> +static const u32 hpd_ilk[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = DE_DP_A_HOTPLUG,
> +};
> +
> +static const u32 hpd_ivb[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB,
> +};
> +
> +static const u32 hpd_bdw[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
> +};
> +
> +static const u32 hpd_ibx[HPD_NUM_PINS] = {
> +	[HPD_CRT] = SDE_CRT_HOTPLUG,
> +	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
> +	[HPD_PORT_B] = SDE_PORTB_HOTPLUG,
> +	[HPD_PORT_C] = SDE_PORTC_HOTPLUG,
> +	[HPD_PORT_D] = SDE_PORTD_HOTPLUG,
> +};
> +
> +static const u32 hpd_cpt[HPD_NUM_PINS] = {
> +	[HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
> +	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
> +	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
> +	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
> +	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
> +};
> +
> +static const u32 hpd_spt[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT,
> +	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
> +	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
> +	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
> +	[HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT,
> +};
> +
> +static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
> +	[HPD_CRT] = CRT_HOTPLUG_INT_EN,
> +	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
> +	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
> +	[HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
> +	[HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
> +	[HPD_PORT_D] = PORTD_HOTPLUG_INT_EN,
> +};
> +
> +static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
> +	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
> +	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
> +	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
> +	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
> +	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
> +	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
> +};
> +
> +static const u32 hpd_status_i915[HPD_NUM_PINS] = {
> +	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
> +	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
> +	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
> +	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
> +	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
> +	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
> +};
> +
> +static const u32 hpd_bxt[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
> +	[HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B),
> +	[HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C),
> +};
> +
> +static const u32 hpd_gen11[HPD_NUM_PINS] = {
> +	[HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1),
> +	[HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2),
> +	[HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3),
> +	[HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4),
> +	[HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5),
> +	[HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
> +};
> +
> +static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
> +	[HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
> +	[HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
> +	[HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
> +	[HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
> +};
> +
> +static const u32 hpd_icp[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
> +	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
> +	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
> +	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
> +	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
> +	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
> +	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
> +	[HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5),
> +	[HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6),
> +};
> +
> +static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
> +	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
> +	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
> +	[HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D),
> +	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
> +};
> +
> +static const u32 hpd_mtp[HPD_NUM_PINS] = {
> +	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
> +	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
> +	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
> +	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
> +	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
> +	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
> +};
> +
> +static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_hotplug *hpd = &dev_priv->display.hotplug;
> +
> +	if (HAS_GMCH(dev_priv)) {
> +		if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
> +		    IS_CHERRYVIEW(dev_priv))
> +			hpd->hpd = hpd_status_g4x;
> +		else
> +			hpd->hpd = hpd_status_i915;
> +		return;
> +	}
> +
> +	if (DISPLAY_VER(dev_priv) >= 14)
> +		hpd->hpd = hpd_xelpdp;
> +	else if (DISPLAY_VER(dev_priv) >= 11)
> +		hpd->hpd = hpd_gen11;
> +	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
> +		hpd->hpd = hpd_bxt;
> +	else if (DISPLAY_VER(dev_priv) == 9)
> +		hpd->hpd = NULL; /* no north HPD on SKL */
> +	else if (DISPLAY_VER(dev_priv) >= 8)
> +		hpd->hpd = hpd_bdw;
> +	else if (DISPLAY_VER(dev_priv) >= 7)
> +		hpd->hpd = hpd_ivb;
> +	else
> +		hpd->hpd = hpd_ilk;
> +
> +	if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) &&
> +	    (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
> +		return;
> +
> +	if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
> +		hpd->pch_hpd = hpd_sde_dg1;
> +	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
> +		hpd->pch_hpd = hpd_mtp;
> +	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
> +		hpd->pch_hpd = hpd_icp;
> +	else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
> +		hpd->pch_hpd = hpd_spt;
> +	else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv))
> +		hpd->pch_hpd = hpd_cpt;
> +	else if (HAS_PCH_IBX(dev_priv))
> +		hpd->pch_hpd = hpd_ibx;
> +	else
> +		MISSING_CASE(INTEL_PCH_TYPE(dev_priv));
> +}
> +
> +/* For display hotplug interrupt */
> +void i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
> +					  u32 mask, u32 bits)
> +{
> +	lockdep_assert_held(&dev_priv->irq_lock);
> +	drm_WARN_ON(&dev_priv->drm, bits & ~mask);
> +
> +	intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits);
> +}
> +
> +/**
> + * i915_hotplug_interrupt_update - update hotplug interrupt enable
> + * @dev_priv: driver private
> + * @mask: bits to update
> + * @bits: bits to enable
> + * NOTE: the HPD enable bits are modified both inside and outside
> + * of an interrupt context. To avoid that read-modify-write cycles
> + * interfer, these bits are protected by a spinlock. Since this
> + * function is usually not called from a context where the lock is
> + * held already, this function acquires the lock itself. A non-locking
> + * version is also available.
> + */
> +void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
> +				   u32 mask,
> +				   u32 bits)
> +{
> +	spin_lock_irq(&dev_priv->irq_lock);
> +	i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
> +	spin_unlock_irq(&dev_priv->irq_lock);
> +}
> +
> +static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_TC1:
> +	case HPD_PORT_TC2:
> +	case HPD_PORT_TC3:
> +	case HPD_PORT_TC4:
> +	case HPD_PORT_TC5:
> +	case HPD_PORT_TC6:
> +		return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin);
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_A:
> +		return val & PORTA_HOTPLUG_LONG_DETECT;
> +	case HPD_PORT_B:
> +		return val & PORTB_HOTPLUG_LONG_DETECT;
> +	case HPD_PORT_C:
> +		return val & PORTC_HOTPLUG_LONG_DETECT;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_A:
> +	case HPD_PORT_B:
> +	case HPD_PORT_C:
> +	case HPD_PORT_D:
> +		return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin);
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_TC1:
> +	case HPD_PORT_TC2:
> +	case HPD_PORT_TC3:
> +	case HPD_PORT_TC4:
> +	case HPD_PORT_TC5:
> +	case HPD_PORT_TC6:
> +		return val & ICP_TC_HPD_LONG_DETECT(pin);
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_E:
> +		return val & PORTE_HOTPLUG_LONG_DETECT;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_A:
> +		return val & PORTA_HOTPLUG_LONG_DETECT;
> +	case HPD_PORT_B:
> +		return val & PORTB_HOTPLUG_LONG_DETECT;
> +	case HPD_PORT_C:
> +		return val & PORTC_HOTPLUG_LONG_DETECT;
> +	case HPD_PORT_D:
> +		return val & PORTD_HOTPLUG_LONG_DETECT;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_A:
> +		return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_B:
> +		return val & PORTB_HOTPLUG_LONG_DETECT;
> +	case HPD_PORT_C:
> +		return val & PORTC_HOTPLUG_LONG_DETECT;
> +	case HPD_PORT_D:
> +		return val & PORTD_HOTPLUG_LONG_DETECT;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> +{
> +	switch (pin) {
> +	case HPD_PORT_B:
> +		return val & PORTB_HOTPLUG_INT_LONG_PULSE;
> +	case HPD_PORT_C:
> +		return val & PORTC_HOTPLUG_INT_LONG_PULSE;
> +	case HPD_PORT_D:
> +		return val & PORTD_HOTPLUG_INT_LONG_PULSE;
> +	default:
> +		return false;
> +	}
> +}
> +
> +/*
> + * Get a bit mask of pins that have triggered, and which ones may be long.
> + * This can be called multiple times with the same masks to accumulate
> + * hotplug detection results from several registers.
> + *
> + * Note that the caller is expected to zero out the masks initially.
> + */
> +static void intel_get_hpd_pins(struct drm_i915_private *dev_priv,
> +			       u32 *pin_mask, u32 *long_mask,
> +			       u32 hotplug_trigger, u32 dig_hotplug_reg,
> +			       const u32 hpd[HPD_NUM_PINS],
> +			       bool long_pulse_detect(enum hpd_pin pin, u32 val))
> +{
> +	enum hpd_pin pin;
> +
> +	BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS);
> +
> +	for_each_hpd_pin(pin) {
> +		if ((hpd[pin] & hotplug_trigger) == 0)
> +			continue;
> +
> +		*pin_mask |= BIT(pin);
> +
> +		if (long_pulse_detect(pin, dig_hotplug_reg))
> +			*long_mask |= BIT(pin);
> +	}
> +
> +	drm_dbg(&dev_priv->drm,
> +		"hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n",
> +		hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask);
> +}
> +
> +static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
> +				  const u32 hpd[HPD_NUM_PINS])
> +{
> +	struct intel_encoder *encoder;
> +	u32 enabled_irqs = 0;
> +
> +	for_each_intel_encoder(&dev_priv->drm, encoder)
> +		if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
> +			enabled_irqs |= hpd[encoder->hpd_pin];
> +
> +	return enabled_irqs;
> +}
> +
> +static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv,
> +				  const u32 hpd[HPD_NUM_PINS])
> +{
> +	struct intel_encoder *encoder;
> +	u32 hotplug_irqs = 0;
> +
> +	for_each_intel_encoder(&dev_priv->drm, encoder)
> +		hotplug_irqs |= hpd[encoder->hpd_pin];
> +
> +	return hotplug_irqs;
> +}
> +
> +static u32 intel_hpd_hotplug_mask(struct drm_i915_private *i915,
> +				  hotplug_mask_func hotplug_mask)
> +{
> +	enum hpd_pin pin;
> +	u32 hotplug = 0;
> +
> +	for_each_hpd_pin(pin)
> +		hotplug |= hotplug_mask(pin);
> +
> +	return hotplug;
> +}
> +
> +static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915,
> +				     hotplug_enables_func hotplug_enables)
> +{
> +	struct intel_encoder *encoder;
> +	u32 hotplug = 0;
> +
> +	for_each_intel_encoder(&i915->drm, encoder)
> +		hotplug |= hotplug_enables(encoder);
> +
> +	return hotplug;
> +}
> +
> +u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_status = 0, hotplug_status_mask;
> +	int i;
> +
> +	if (IS_G4X(dev_priv) ||
> +	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		hotplug_status_mask = HOTPLUG_INT_STATUS_G4X |
> +			DP_AUX_CHANNEL_MASK_INT_STATUS_G4X;
> +	else
> +		hotplug_status_mask = HOTPLUG_INT_STATUS_I915;
> +
> +	/*
> +	 * We absolutely have to clear all the pending interrupt
> +	 * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port
> +	 * interrupt bit won't have an edge, and the i965/g4x
> +	 * edge triggered IIR will not notice that an interrupt
> +	 * is still pending. We can't use PORT_HOTPLUG_EN to
> +	 * guarantee the edge as the act of toggling the enable
> +	 * bits can itself generate a new hotplug interrupt :(
> +	 */
> +	for (i = 0; i < 10; i++) {
> +		u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask;
> +
> +		if (tmp == 0)
> +			return hotplug_status;
> +
> +		hotplug_status |= tmp;
> +		intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status);
> +	}
> +
> +	drm_WARN_ONCE(&dev_priv->drm, 1,
> +		      "PORT_HOTPLUG_STAT did not clear (0x%08x)\n",
> +		      intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
> +
> +	return hotplug_status;
> +}
> +
> +void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_status)
> +{
> +	u32 pin_mask = 0, long_mask = 0;
> +	u32 hotplug_trigger;
> +
> +	if (IS_G4X(dev_priv) ||
> +	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
> +	else
> +		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
> +
> +	if (hotplug_trigger) {
> +		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +				   hotplug_trigger, hotplug_trigger,
> +				   dev_priv->display.hotplug.hpd,
> +				   i9xx_port_hotplug_long_detect);
> +
> +		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> +	}
> +
> +	if ((IS_G4X(dev_priv) ||
> +	     IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> +	    hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
> +		intel_dp_aux_irq_handler(dev_priv);
> +}
> +
> +void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger)
> +{
> +	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
> +
> +	/*
> +	 * Somehow the PCH doesn't seem to really ack the interrupt to the CPU
> +	 * unless we touch the hotplug register, even if hotplug_trigger is
> +	 * zero. Not acking leads to "The master control interrupt lied (SDE)!"
> +	 * errors.
> +	 */
> +	dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
> +	if (!hotplug_trigger) {
> +		u32 mask = PORTA_HOTPLUG_STATUS_MASK |
> +			PORTD_HOTPLUG_STATUS_MASK |
> +			PORTC_HOTPLUG_STATUS_MASK |
> +			PORTB_HOTPLUG_STATUS_MASK;
> +		dig_hotplug_reg &= ~mask;
> +	}
> +
> +	intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg);
> +	if (!hotplug_trigger)
> +		return;
> +
> +	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +			   hotplug_trigger, dig_hotplug_reg,
> +			   dev_priv->display.hotplug.pch_hpd,
> +			   pch_port_hotplug_long_detect);
> +
> +	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> +}
> +
> +void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
> +{
> +	enum hpd_pin pin;
> +	u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK);
> +	u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
> +	u32 pin_mask = 0, long_mask = 0;
> +
> +	for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
> +		u32 val;
> +
> +		if (!(i915->display.hotplug.hpd[pin] & hotplug_trigger))
> +			continue;
> +
> +		pin_mask |= BIT(pin);
> +
> +		val = intel_de_read(i915, XELPDP_PORT_HOTPLUG_CTL(pin));
> +		intel_de_write(i915, XELPDP_PORT_HOTPLUG_CTL(pin), val);
> +
> +		if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | XELPDP_TBT_HPD_LONG_DETECT))
> +			long_mask |= BIT(pin);
> +	}
> +
> +	if (pin_mask) {
> +		drm_dbg(&i915->drm,
> +			"pica hotplug event received, stat 0x%08x, pins 0x%08x, long 0x%08x\n",
> +			hotplug_trigger, pin_mask, long_mask);
> +
> +		intel_hpd_irq_handler(i915, pin_mask, long_mask);
> +	}
> +
> +	if (trigger_aux)
> +		intel_dp_aux_irq_handler(i915);
> +
> +	if (!pin_mask && !trigger_aux)
> +		drm_err(&i915->drm,
> +			"Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
> +}
> +
> +void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
> +{
> +	u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
> +	u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
> +	u32 pin_mask = 0, long_mask = 0;
> +
> +	if (ddi_hotplug_trigger) {
> +		u32 dig_hotplug_reg;
> +
> +		/* Locking due to DSI native GPIO sequences */
> +		spin_lock(&dev_priv->irq_lock);
> +		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
> +		spin_unlock(&dev_priv->irq_lock);
> +
> +		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +				   ddi_hotplug_trigger, dig_hotplug_reg,
> +				   dev_priv->display.hotplug.pch_hpd,
> +				   icp_ddi_port_hotplug_long_detect);
> +	}
> +
> +	if (tc_hotplug_trigger) {
> +		u32 dig_hotplug_reg;
> +
> +		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0);
> +
> +		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +				   tc_hotplug_trigger, dig_hotplug_reg,
> +				   dev_priv->display.hotplug.pch_hpd,
> +				   icp_tc_port_hotplug_long_detect);
> +	}
> +
> +	if (pin_mask)
> +		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> +
> +	if (pch_iir & SDE_GMBUS_ICP)
> +		intel_gmbus_irq_handler(dev_priv);
> +}
> +
> +void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
> +{
> +	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
> +		~SDE_PORTE_HOTPLUG_SPT;
> +	u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
> +	u32 pin_mask = 0, long_mask = 0;
> +
> +	if (hotplug_trigger) {
> +		u32 dig_hotplug_reg;
> +
> +		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
> +
> +		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +				   hotplug_trigger, dig_hotplug_reg,
> +				   dev_priv->display.hotplug.pch_hpd,
> +				   spt_port_hotplug_long_detect);
> +	}
> +
> +	if (hotplug2_trigger) {
> +		u32 dig_hotplug_reg;
> +
> +		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0);
> +
> +		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +				   hotplug2_trigger, dig_hotplug_reg,
> +				   dev_priv->display.hotplug.pch_hpd,
> +				   spt_port_hotplug2_long_detect);
> +	}
> +
> +	if (pin_mask)
> +		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> +
> +	if (pch_iir & SDE_GMBUS_CPT)
> +		intel_gmbus_irq_handler(dev_priv);
> +}
> +
> +void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger)
> +{
> +	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
> +
> +	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0);
> +
> +	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +			   hotplug_trigger, dig_hotplug_reg,
> +			   dev_priv->display.hotplug.hpd,
> +			   ilk_port_hotplug_long_detect);
> +
> +	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> +}
> +
> +void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger)
> +{
> +	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
> +
> +	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
> +
> +	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +			   hotplug_trigger, dig_hotplug_reg,
> +			   dev_priv->display.hotplug.hpd,
> +			   bxt_port_hotplug_long_detect);
> +
> +	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> +}
> +
> +void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
> +{
> +	u32 pin_mask = 0, long_mask = 0;
> +	u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK;
> +	u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK;
> +
> +	if (trigger_tc) {
> +		u32 dig_hotplug_reg;
> +
> +		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0);
> +
> +		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +				   trigger_tc, dig_hotplug_reg,
> +				   dev_priv->display.hotplug.hpd,
> +				   gen11_port_hotplug_long_detect);
> +	}
> +
> +	if (trigger_tbt) {
> +		u32 dig_hotplug_reg;
> +
> +		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0);
> +
> +		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> +				   trigger_tbt, dig_hotplug_reg,
> +				   dev_priv->display.hotplug.hpd,
> +				   gen11_port_hotplug_long_detect);
> +	}
> +
> +	if (pin_mask)
> +		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> +	else
> +		drm_err(&dev_priv->drm,
> +			"Unexpected DE HPD interrupt 0x%08x\n", iir);
> +}
> +
> +static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_A:
> +		return PORTA_HOTPLUG_ENABLE;
> +	case HPD_PORT_B:
> +		return PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_MASK;
> +	case HPD_PORT_C:
> +		return PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_MASK;
> +	case HPD_PORT_D:
> +		return PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_MASK;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	switch (encoder->hpd_pin) {
> +	case HPD_PORT_A:
> +		/*
> +		 * When CPU and PCH are on the same package, port A
> +		 * HPD must be enabled in both north and south.
> +		 */
> +		return HAS_PCH_LPT_LP(i915) ?
> +			PORTA_HOTPLUG_ENABLE : 0;
> +	case HPD_PORT_B:
> +		return PORTB_HOTPLUG_ENABLE |
> +			PORTB_PULSE_DURATION_2ms;
> +	case HPD_PORT_C:
> +		return PORTC_HOTPLUG_ENABLE |
> +			PORTC_PULSE_DURATION_2ms;
> +	case HPD_PORT_D:
> +		return PORTD_HOTPLUG_ENABLE |
> +			PORTD_PULSE_DURATION_2ms;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	/*
> +	 * Enable digital hotplug on the PCH, and configure the DP short pulse
> +	 * duration to 2ms (which is the minimum in the Display Port spec).
> +	 * The pulse duration bits are reserved on LPT+.
> +	 */
> +	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
> +			 intel_hpd_hotplug_mask(dev_priv, ibx_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
> +}
> +
> +static void ibx_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
> +			 ibx_hotplug_mask(encoder->hpd_pin),
> +			 ibx_hotplug_enables(encoder));
> +}
> +
> +static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> +
> +	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
> +
> +	ibx_hpd_detection_setup(dev_priv);
> +}
> +
> +static u32 icp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_A:
> +	case HPD_PORT_B:
> +	case HPD_PORT_C:
> +	case HPD_PORT_D:
> +		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	return icp_ddi_hotplug_mask(encoder->hpd_pin);
> +}
> +
> +static u32 icp_tc_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_TC1:
> +	case HPD_PORT_TC2:
> +	case HPD_PORT_TC3:
> +	case HPD_PORT_TC4:
> +	case HPD_PORT_TC5:
> +	case HPD_PORT_TC6:
> +		return ICP_TC_HPD_ENABLE(hpd_pin);
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	return icp_tc_hotplug_mask(encoder->hpd_pin);
> +}
> +
> +static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
> +			 intel_hpd_hotplug_mask(dev_priv, icp_ddi_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
> +}
> +
> +static void icp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_DDI,
> +			 icp_ddi_hotplug_mask(encoder->hpd_pin),
> +			 icp_ddi_hotplug_enables(encoder));
> +}
> +
> +static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
> +			 intel_hpd_hotplug_mask(dev_priv, icp_tc_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
> +}
> +
> +static void icp_tc_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_TC,
> +			 icp_tc_hotplug_mask(encoder->hpd_pin),
> +			 icp_tc_hotplug_enables(encoder));
> +}
> +
> +static void icp_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	icp_ddi_hpd_enable_detection(encoder);
> +	icp_tc_hpd_enable_detection(encoder);
> +}
> +
> +static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> +
> +	if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
> +		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
> +
> +	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
> +
> +	icp_ddi_hpd_detection_setup(dev_priv);
> +	icp_tc_hpd_detection_setup(dev_priv);
> +}
> +
> +static u32 gen11_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_TC1:
> +	case HPD_PORT_TC2:
> +	case HPD_PORT_TC3:
> +	case HPD_PORT_TC4:
> +	case HPD_PORT_TC5:
> +	case HPD_PORT_TC6:
> +		return GEN11_HOTPLUG_CTL_ENABLE(hpd_pin);
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	return gen11_hotplug_mask(encoder->hpd_pin);
> +}
> +
> +static void dg1_hpd_invert(struct drm_i915_private *i915)
> +{
> +	u32 val = (INVERT_DDIA_HPD |
> +		   INVERT_DDIB_HPD |
> +		   INVERT_DDIC_HPD |
> +		   INVERT_DDID_HPD);
> +	intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
> +}
> +
> +static void dg1_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	dg1_hpd_invert(i915);
> +	icp_hpd_enable_detection(encoder);
> +}
> +
> +static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	dg1_hpd_invert(dev_priv);
> +	icp_hpd_irq_setup(dev_priv);
> +}
> +
> +static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
> +			 intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
> +}
> +
> +static void gen11_tc_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_uncore_rmw(&i915->uncore, GEN11_TC_HOTPLUG_CTL,
> +			 gen11_hotplug_mask(encoder->hpd_pin),
> +			 gen11_hotplug_enables(encoder));
> +}
> +
> +static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
> +			 intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
> +}
> +
> +static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_uncore_rmw(&i915->uncore, GEN11_TBT_HOTPLUG_CTL,
> +			 gen11_hotplug_mask(encoder->hpd_pin),
> +			 gen11_hotplug_enables(encoder));
> +}
> +
> +static void gen11_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	gen11_tc_hpd_enable_detection(encoder);
> +	gen11_tbt_hpd_enable_detection(encoder);
> +
> +	if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
> +		icp_hpd_enable_detection(encoder);
> +}
> +
> +static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> +
> +	intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
> +			 ~enabled_irqs & hotplug_irqs);
> +	intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
> +
> +	gen11_tc_hpd_detection_setup(dev_priv);
> +	gen11_tbt_hpd_detection_setup(dev_priv);
> +
> +	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
> +		icp_hpd_irq_setup(dev_priv);
> +}
> +
> +static u32 mtp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_A:
> +	case HPD_PORT_B:
> +		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	return mtp_ddi_hotplug_mask(encoder->hpd_pin);
> +}
> +
> +static u32 mtp_tc_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_TC1:
> +	case HPD_PORT_TC2:
> +	case HPD_PORT_TC3:
> +	case HPD_PORT_TC4:
> +		return ICP_TC_HPD_ENABLE(hpd_pin);
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	return mtp_tc_hotplug_mask(encoder->hpd_pin);
> +}
> +
> +static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
> +{
> +	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
> +		     intel_hpd_hotplug_mask(i915, mtp_ddi_hotplug_mask),
> +		     intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
> +}
> +
> +static void mtp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
> +		     mtp_ddi_hotplug_mask(encoder->hpd_pin),
> +		     mtp_ddi_hotplug_enables(encoder));
> +}
> +
> +static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
> +{
> +	intel_de_rmw(i915, SHOTPLUG_CTL_TC,
> +		     intel_hpd_hotplug_mask(i915, mtp_tc_hotplug_mask),
> +		     intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
> +}
> +
> +static void mtp_tc_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
> +		     mtp_tc_hotplug_mask(encoder->hpd_pin),
> +		     mtp_tc_hotplug_enables(encoder));
> +}
> +
> +static void mtp_hpd_invert(struct drm_i915_private *i915)
> +{
> +	u32 val = (INVERT_DDIA_HPD |
> +		   INVERT_DDIB_HPD |
> +		   INVERT_DDIC_HPD |
> +		   INVERT_TC1_HPD |
> +		   INVERT_TC2_HPD |
> +		   INVERT_TC3_HPD |
> +		   INVERT_TC4_HPD |
> +		   INVERT_DDID_HPD_MTP |
> +		   INVERT_DDIE_HPD);
> +	intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
> +}
> +
> +static void mtp_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	mtp_hpd_invert(i915);
> +	mtp_ddi_hpd_enable_detection(encoder);
> +	mtp_tc_hpd_enable_detection(encoder);
> +}
> +
> +static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
> +
> +	intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
> +
> +	mtp_hpd_invert(i915);
> +	ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
> +
> +	mtp_ddi_hpd_detection_setup(i915);
> +	mtp_tc_hpd_detection_setup(i915);
> +}
> +
> +static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
> +{
> +	return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
> +}
> +
> +static void _xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915,
> +					     enum hpd_pin hpd_pin, bool enable)
> +{
> +	u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
> +		XELPDP_DP_ALT_HOTPLUG_ENABLE;
> +
> +	if (!is_xelpdp_pica_hpd_pin(hpd_pin))
> +		return;
> +
> +	intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(hpd_pin),
> +		     mask, enable ? mask : 0);
> +}
> +
> +static void xelpdp_pica_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	_xelpdp_pica_hpd_detection_setup(i915, encoder->hpd_pin, true);
> +}
> +
> +static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
> +{
> +	struct intel_encoder *encoder;
> +	u32 available_pins = 0;
> +	enum hpd_pin pin;
> +
> +	BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
> +
> +	for_each_intel_encoder(&i915->drm, encoder)
> +		available_pins |= BIT(encoder->hpd_pin);
> +
> +	for_each_hpd_pin(pin)
> +		_xelpdp_pica_hpd_detection_setup(i915, pin, available_pins & BIT(pin));
> +}
> +
> +static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	xelpdp_pica_hpd_enable_detection(encoder);
> +	mtp_hpd_enable_detection(encoder);
> +}
> +
> +static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.hpd);
> +
> +	intel_de_rmw(i915, PICAINTERRUPT_IMR, hotplug_irqs,
> +		     ~enabled_irqs & hotplug_irqs);
> +	intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR);
> +
> +	xelpdp_pica_hpd_detection_setup(i915);
> +
> +	if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
> +		mtp_hpd_irq_setup(i915);
> +}
> +
> +static u32 spt_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_A:
> +		return PORTA_HOTPLUG_ENABLE;
> +	case HPD_PORT_B:
> +		return PORTB_HOTPLUG_ENABLE;
> +	case HPD_PORT_C:
> +		return PORTC_HOTPLUG_ENABLE;
> +	case HPD_PORT_D:
> +		return PORTD_HOTPLUG_ENABLE;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 spt_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	return spt_hotplug_mask(encoder->hpd_pin);
> +}
> +
> +static u32 spt_hotplug2_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_E:
> +		return PORTE_HOTPLUG_ENABLE;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
> +{
> +	return spt_hotplug2_mask(encoder->hpd_pin);
> +}
> +
> +static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	/* Display WA #1179 WaHardHangonHotPlug: cnp */
> +	if (HAS_PCH_CNP(dev_priv)) {
> +		intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
> +				 CHASSIS_CLK_REQ_DURATION(0xf));
> +	}
> +
> +	/* Enable digital hotplug on the PCH */
> +	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
> +			 intel_hpd_hotplug_mask(dev_priv, spt_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
> +
> +	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2,
> +			 intel_hpd_hotplug_mask(dev_priv, spt_hotplug2_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
> +}
> +
> +static void spt_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	/* Display WA #1179 WaHardHangonHotPlug: cnp */
> +	if (HAS_PCH_CNP(i915)) {
> +		intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1,
> +				 CHASSIS_CLK_REQ_DURATION_MASK,
> +				 CHASSIS_CLK_REQ_DURATION(0xf));
> +	}
> +
> +	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
> +			 spt_hotplug_mask(encoder->hpd_pin),
> +			 spt_hotplug_enables(encoder));
> +
> +	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG2,
> +			 spt_hotplug2_mask(encoder->hpd_pin),
> +			 spt_hotplug2_enables(encoder));
> +}
> +
> +static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
> +		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> +
> +	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
> +
> +	spt_hpd_detection_setup(dev_priv);
> +}
> +
> +static u32 ilk_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_A:
> +		return DIGITAL_PORTA_HOTPLUG_ENABLE |
> +			DIGITAL_PORTA_PULSE_DURATION_MASK;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	switch (encoder->hpd_pin) {
> +	case HPD_PORT_A:
> +		return DIGITAL_PORTA_HOTPLUG_ENABLE |
> +			DIGITAL_PORTA_PULSE_DURATION_2ms;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	/*
> +	 * Enable digital hotplug on the CPU, and configure the DP short pulse
> +	 * duration to 2ms (which is the minimum in the Display Port spec)
> +	 * The pulse duration bits are reserved on HSW+.
> +	 */
> +	intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
> +			 intel_hpd_hotplug_mask(dev_priv, ilk_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
> +}
> +
> +static void ilk_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_uncore_rmw(&i915->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
> +			 ilk_hotplug_mask(encoder->hpd_pin),
> +			 ilk_hotplug_enables(encoder));
> +
> +	ibx_hpd_enable_detection(encoder);
> +}
> +
> +static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> +
> +	if (DISPLAY_VER(dev_priv) >= 8)
> +		bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
> +	else
> +		ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
> +
> +	ilk_hpd_detection_setup(dev_priv);
> +
> +	ibx_hpd_irq_setup(dev_priv);
> +}
> +
> +static u32 bxt_hotplug_mask(enum hpd_pin hpd_pin)
> +{
> +	switch (hpd_pin) {
> +	case HPD_PORT_A:
> +		return PORTA_HOTPLUG_ENABLE | BXT_DDIA_HPD_INVERT;
> +	case HPD_PORT_B:
> +		return PORTB_HOTPLUG_ENABLE | BXT_DDIB_HPD_INVERT;
> +	case HPD_PORT_C:
> +		return PORTC_HOTPLUG_ENABLE | BXT_DDIC_HPD_INVERT;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
> +{
> +	u32 hotplug;
> +
> +	switch (encoder->hpd_pin) {
> +	case HPD_PORT_A:
> +		hotplug = PORTA_HOTPLUG_ENABLE;
> +		if (intel_bios_encoder_hpd_invert(encoder->devdata))
> +			hotplug |= BXT_DDIA_HPD_INVERT;
> +		return hotplug;
> +	case HPD_PORT_B:
> +		hotplug = PORTB_HOTPLUG_ENABLE;
> +		if (intel_bios_encoder_hpd_invert(encoder->devdata))
> +			hotplug |= BXT_DDIB_HPD_INVERT;
> +		return hotplug;
> +	case HPD_PORT_C:
> +		hotplug = PORTC_HOTPLUG_ENABLE;
> +		if (intel_bios_encoder_hpd_invert(encoder->devdata))
> +			hotplug |= BXT_DDIC_HPD_INVERT;
> +		return hotplug;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
> +{
> +	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
> +			 intel_hpd_hotplug_mask(dev_priv, bxt_hotplug_mask),
> +			 intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
> +}
> +
> +static void bxt_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
> +			 bxt_hotplug_mask(encoder->hpd_pin),
> +			 bxt_hotplug_enables(encoder));
> +}
> +
> +static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_irqs, enabled_irqs;
> +
> +	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> +	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> +
> +	bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
> +
> +	bxt_hpd_detection_setup(dev_priv);
> +}
> +
> +static void i915_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	u32 hotplug_en = hpd_mask_i915[encoder->hpd_pin];
> +
> +	/* HPD sense and interrupt enable are one and the same */
> +	i915_hotplug_interrupt_update(i915, hotplug_en, hotplug_en);
> +}
> +
> +static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
> +{
> +	u32 hotplug_en;
> +
> +	lockdep_assert_held(&dev_priv->irq_lock);
> +
> +	/*
> +	 * Note HDMI and DP share hotplug bits. Enable bits are the same for all
> +	 * generations.
> +	 */
> +	hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
> +	/*
> +	 * Programming the CRT detection parameters tends to generate a spurious
> +	 * hotplug event about three seconds later. So just do it once.
> +	 */
> +	if (IS_G4X(dev_priv))
> +		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
> +	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
> +
> +	/* Ignore TV since it's buggy */
> +	i915_hotplug_interrupt_update_locked(dev_priv,
> +					     HOTPLUG_INT_EN_MASK |
> +					     CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
> +					     CRT_HOTPLUG_ACTIVATION_PERIOD_64,
> +					     hotplug_en);
> +}
> +
> +struct intel_hotplug_funcs {
> +	/* Enable HPD sense and interrupts for all present encoders */
> +	void (*hpd_irq_setup)(struct drm_i915_private *i915);
> +	/* Enable HPD sense for a single encoder */
> +	void (*hpd_enable_detection)(struct intel_encoder *encoder);
> +};
> +
> +#define HPD_FUNCS(platform)					 \
> +static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
> +	.hpd_irq_setup = platform##_hpd_irq_setup,		 \
> +	.hpd_enable_detection = platform##_hpd_enable_detection, \
> +}
> +
> +HPD_FUNCS(i915);
> +HPD_FUNCS(xelpdp);
> +HPD_FUNCS(dg1);
> +HPD_FUNCS(gen11);
> +HPD_FUNCS(bxt);
> +HPD_FUNCS(icp);
> +HPD_FUNCS(spt);
> +HPD_FUNCS(ilk);
> +#undef HPD_FUNCS
> +
> +void intel_hpd_enable_detection(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	if (i915->display.funcs.hotplug)
> +		i915->display.funcs.hotplug->hpd_enable_detection(encoder);
> +}
> +
> +void intel_hpd_irq_setup(struct drm_i915_private *i915)
> +{
> +	if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
> +		i915->display.funcs.hotplug->hpd_irq_setup(i915);
> +}
> +
> +void intel_hotplug_irq_init(struct drm_i915_private *i915)
> +{
> +	intel_hpd_init_pins(i915);
> +
> +	intel_hpd_init_early(i915);
> +
> +	if (HAS_GMCH(i915)) {
> +		if (I915_HAS_HOTPLUG(i915))
> +			i915->display.funcs.hotplug = &i915_hpd_funcs;
> +	} else {
> +		if (HAS_PCH_DG2(i915))
> +			i915->display.funcs.hotplug = &icp_hpd_funcs;
> +		else if (HAS_PCH_DG1(i915))
> +			i915->display.funcs.hotplug = &dg1_hpd_funcs;
> +		else if (DISPLAY_VER(i915) >= 14)
> +			i915->display.funcs.hotplug = &xelpdp_hpd_funcs;
> +		else if (DISPLAY_VER(i915) >= 11)
> +			i915->display.funcs.hotplug = &gen11_hpd_funcs;
> +		else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
> +			i915->display.funcs.hotplug = &bxt_hpd_funcs;
> +		else if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
> +			i915->display.funcs.hotplug = &icp_hpd_funcs;
> +		else if (INTEL_PCH_TYPE(i915) >= PCH_SPT)
> +			i915->display.funcs.hotplug = &spt_hpd_funcs;
> +		else
> +			i915->display.funcs.hotplug = &ilk_hpd_funcs;
> +	}
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.h b/drivers/gpu/drm/i915/display/intel_hotplug_irq.h
> new file mode 100644
> index 000000000000..e4db752df096
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef __INTEL_HOTPLUG_IRQ_H__
> +#define __INTEL_HOTPLUG_IRQ_H__
> +
> +#include <linux/types.h>
> +
> +struct drm_i915_private;
> +struct intel_encoder;
> +
> +u32 i9xx_hpd_irq_ack(struct drm_i915_private *i915);
> +
> +void i9xx_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_status);
> +void ibx_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_trigger);
> +void ilk_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_trigger);
> +void gen11_hpd_irq_handler(struct drm_i915_private *i915, u32 iir);
> +void bxt_hpd_irq_handler(struct drm_i915_private *i915, u32 hotplug_trigger);
> +void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir);
> +void icp_irq_handler(struct drm_i915_private *i915, u32 pch_iir);
> +void spt_irq_handler(struct drm_i915_private *i915, u32 pch_iir);
> +
> +void i915_hotplug_interrupt_update_locked(struct drm_i915_private *i915,
> +					  u32 mask, u32 bits);
> +void i915_hotplug_interrupt_update(struct drm_i915_private *i915,
> +				   u32 mask, u32 bits);
> +
> +void intel_hpd_enable_detection(struct intel_encoder *encoder);
> +void intel_hpd_irq_setup(struct drm_i915_private *i915);
> +
> +void intel_hotplug_irq_init(struct drm_i915_private *i915);
> +
> +#endif /* __INTEL_HOTPLUG_IRQ_H__ */
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 02b6cbb832e9..0ead32154f81 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -42,6 +42,7 @@
>  #include "display/intel_fifo_underrun.h"
>  #include "display/intel_gmbus.h"
>  #include "display/intel_hotplug.h"
> +#include "display/intel_hotplug_irq.h"
>  #include "display/intel_lpe_audio.h"
>  #include "display/intel_psr.h"
>  #include "display/intel_psr_regs.h"
> @@ -84,172 +85,6 @@ static inline void pmu_irq_stats(struct drm_i915_private *i915,
>  	WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1);
>  }
>  
> -typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val);
> -typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder);
> -typedef u32 (*hotplug_mask_func)(enum hpd_pin pin);
> -
> -static const u32 hpd_ilk[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = DE_DP_A_HOTPLUG,
> -};
> -
> -static const u32 hpd_ivb[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB,
> -};
> -
> -static const u32 hpd_bdw[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
> -};
> -
> -static const u32 hpd_ibx[HPD_NUM_PINS] = {
> -	[HPD_CRT] = SDE_CRT_HOTPLUG,
> -	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
> -	[HPD_PORT_B] = SDE_PORTB_HOTPLUG,
> -	[HPD_PORT_C] = SDE_PORTC_HOTPLUG,
> -	[HPD_PORT_D] = SDE_PORTD_HOTPLUG,
> -};
> -
> -static const u32 hpd_cpt[HPD_NUM_PINS] = {
> -	[HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
> -	[HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
> -	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
> -	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
> -	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
> -};
> -
> -static const u32 hpd_spt[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT,
> -	[HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
> -	[HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT,
> -	[HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT,
> -	[HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT,
> -};
> -
> -static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
> -	[HPD_CRT] = CRT_HOTPLUG_INT_EN,
> -	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
> -	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
> -	[HPD_PORT_B] = PORTB_HOTPLUG_INT_EN,
> -	[HPD_PORT_C] = PORTC_HOTPLUG_INT_EN,
> -	[HPD_PORT_D] = PORTD_HOTPLUG_INT_EN,
> -};
> -
> -static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
> -	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
> -	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
> -	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
> -	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
> -	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
> -	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
> -};
> -
> -static const u32 hpd_status_i915[HPD_NUM_PINS] = {
> -	[HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
> -	[HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
> -	[HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
> -	[HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
> -	[HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
> -	[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS,
> -};
> -
> -static const u32 hpd_bxt[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A),
> -	[HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B),
> -	[HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C),
> -};
> -
> -static const u32 hpd_gen11[HPD_NUM_PINS] = {
> -	[HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1),
> -	[HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2),
> -	[HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3),
> -	[HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4),
> -	[HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5),
> -	[HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
> -};
> -
> -static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
> -	[HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
> -	[HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
> -	[HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
> -	[HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
> -};
> -
> -static const u32 hpd_icp[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
> -	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
> -	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
> -	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
> -	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
> -	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
> -	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
> -	[HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5),
> -	[HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6),
> -};
> -
> -static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
> -	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
> -	[HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C),
> -	[HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D),
> -	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
> -};
> -
> -static const u32 hpd_mtp[HPD_NUM_PINS] = {
> -	[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
> -	[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
> -	[HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
> -	[HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
> -	[HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
> -	[HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
> -};
> -
> -static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_hotplug *hpd = &dev_priv->display.hotplug;
> -
> -	if (HAS_GMCH(dev_priv)) {
> -		if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
> -		    IS_CHERRYVIEW(dev_priv))
> -			hpd->hpd = hpd_status_g4x;
> -		else
> -			hpd->hpd = hpd_status_i915;
> -		return;
> -	}
> -
> -	if (DISPLAY_VER(dev_priv) >= 14)
> -		hpd->hpd = hpd_xelpdp;
> -	else if (DISPLAY_VER(dev_priv) >= 11)
> -		hpd->hpd = hpd_gen11;
> -	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
> -		hpd->hpd = hpd_bxt;
> -	else if (DISPLAY_VER(dev_priv) == 9)
> -		hpd->hpd = NULL; /* no north HPD on SKL */
> -	else if (DISPLAY_VER(dev_priv) >= 8)
> -		hpd->hpd = hpd_bdw;
> -	else if (DISPLAY_VER(dev_priv) >= 7)
> -		hpd->hpd = hpd_ivb;
> -	else
> -		hpd->hpd = hpd_ilk;
> -
> -	if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) &&
> -	    (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
> -		return;
> -
> -	if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
> -		hpd->pch_hpd = hpd_sde_dg1;
> -	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
> -		hpd->pch_hpd = hpd_mtp;
> -	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
> -		hpd->pch_hpd = hpd_icp;
> -	else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
> -		hpd->pch_hpd = hpd_spt;
> -	else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv))
> -		hpd->pch_hpd = hpd_cpt;
> -	else if (HAS_PCH_IBX(dev_priv))
> -		hpd->pch_hpd = hpd_ibx;
> -	else
> -		MISSING_CASE(INTEL_PCH_TYPE(dev_priv));
> -}
> -
>  static void
>  intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
>  {
> @@ -344,47 +179,14 @@ static void gen2_irq_init(struct intel_uncore *uncore,
>  	intel_uncore_posting_read16(uncore, GEN2_IMR);
>  }
>  
> -/* For display hotplug interrupt */
> -static inline void
> -i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
> -				     u32 mask,
> -				     u32 bits)
> -{
> -	lockdep_assert_held(&dev_priv->irq_lock);
> -	drm_WARN_ON(&dev_priv->drm, bits & ~mask);
> -
> -	intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits);
> -}
> -
> -/**
> - * i915_hotplug_interrupt_update - update hotplug interrupt enable
> - * @dev_priv: driver private
> - * @mask: bits to update
> - * @bits: bits to enable
> - * NOTE: the HPD enable bits are modified both inside and outside
> - * of an interrupt context. To avoid that read-modify-write cycles
> - * interfer, these bits are protected by a spinlock. Since this
> - * function is usually not called from a context where the lock is
> - * held already, this function acquires the lock itself. A non-locking
> - * version is also available.
> - */
> -void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
> -				   u32 mask,
> -				   u32 bits)
> -{
> -	spin_lock_irq(&dev_priv->irq_lock);
> -	i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
> -	spin_unlock_irq(&dev_priv->irq_lock);
> -}
> -
>  /**
>   * ilk_update_display_irq - update DEIMR
>   * @dev_priv: driver private
>   * @interrupt_mask: mask of interrupt bits to update
>   * @enabled_irq_mask: mask of interrupt bits to enable
>   */
> -static void ilk_update_display_irq(struct drm_i915_private *dev_priv,
> -				   u32 interrupt_mask, u32 enabled_irq_mask)
> +void ilk_update_display_irq(struct drm_i915_private *dev_priv,
> +			    u32 interrupt_mask, u32 enabled_irq_mask)
>  {
>  	u32 new_val;
>  
> @@ -419,9 +221,8 @@ void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits)
>   * @interrupt_mask: mask of interrupt bits to update
>   * @enabled_irq_mask: mask of interrupt bits to enable
>   */
> -static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
> -				u32 interrupt_mask,
> -				u32 enabled_irq_mask)
> +void bdw_update_port_irq(struct drm_i915_private *dev_priv,
> +			 u32 interrupt_mask, u32 enabled_irq_mask)
>  {
>  	u32 new_val;
>  	u32 old_val;
> @@ -494,9 +295,9 @@ void bdw_disable_pipe_irq(struct drm_i915_private *i915,
>   * @interrupt_mask: mask of interrupt bits to update
>   * @enabled_irq_mask: mask of interrupt bits to enable
>   */
> -static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
> -					 u32 interrupt_mask,
> -					 u32 enabled_irq_mask)
> +void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
> +				  u32 interrupt_mask,
> +				  u32 enabled_irq_mask)
>  {
>  	u32 sdeimr = intel_uncore_read(&dev_priv->uncore, SDEIMR);
>  	sdeimr &= ~interrupt_mask;
> @@ -724,209 +525,6 @@ static void ivb_parity_work(struct work_struct *work)
>  	mutex_unlock(&dev_priv->drm.struct_mutex);
>  }
>  
> -static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_TC1:
> -	case HPD_PORT_TC2:
> -	case HPD_PORT_TC3:
> -	case HPD_PORT_TC4:
> -	case HPD_PORT_TC5:
> -	case HPD_PORT_TC6:
> -		return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin);
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_A:
> -		return val & PORTA_HOTPLUG_LONG_DETECT;
> -	case HPD_PORT_B:
> -		return val & PORTB_HOTPLUG_LONG_DETECT;
> -	case HPD_PORT_C:
> -		return val & PORTC_HOTPLUG_LONG_DETECT;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_A:
> -	case HPD_PORT_B:
> -	case HPD_PORT_C:
> -	case HPD_PORT_D:
> -		return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin);
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_TC1:
> -	case HPD_PORT_TC2:
> -	case HPD_PORT_TC3:
> -	case HPD_PORT_TC4:
> -	case HPD_PORT_TC5:
> -	case HPD_PORT_TC6:
> -		return val & ICP_TC_HPD_LONG_DETECT(pin);
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_E:
> -		return val & PORTE_HOTPLUG_LONG_DETECT;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_A:
> -		return val & PORTA_HOTPLUG_LONG_DETECT;
> -	case HPD_PORT_B:
> -		return val & PORTB_HOTPLUG_LONG_DETECT;
> -	case HPD_PORT_C:
> -		return val & PORTC_HOTPLUG_LONG_DETECT;
> -	case HPD_PORT_D:
> -		return val & PORTD_HOTPLUG_LONG_DETECT;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_A:
> -		return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_B:
> -		return val & PORTB_HOTPLUG_LONG_DETECT;
> -	case HPD_PORT_C:
> -		return val & PORTC_HOTPLUG_LONG_DETECT;
> -	case HPD_PORT_D:
> -		return val & PORTD_HOTPLUG_LONG_DETECT;
> -	default:
> -		return false;
> -	}
> -}
> -
> -static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
> -{
> -	switch (pin) {
> -	case HPD_PORT_B:
> -		return val & PORTB_HOTPLUG_INT_LONG_PULSE;
> -	case HPD_PORT_C:
> -		return val & PORTC_HOTPLUG_INT_LONG_PULSE;
> -	case HPD_PORT_D:
> -		return val & PORTD_HOTPLUG_INT_LONG_PULSE;
> -	default:
> -		return false;
> -	}
> -}
> -
> -/*
> - * Get a bit mask of pins that have triggered, and which ones may be long.
> - * This can be called multiple times with the same masks to accumulate
> - * hotplug detection results from several registers.
> - *
> - * Note that the caller is expected to zero out the masks initially.
> - */
> -static void intel_get_hpd_pins(struct drm_i915_private *dev_priv,
> -			       u32 *pin_mask, u32 *long_mask,
> -			       u32 hotplug_trigger, u32 dig_hotplug_reg,
> -			       const u32 hpd[HPD_NUM_PINS],
> -			       bool long_pulse_detect(enum hpd_pin pin, u32 val))
> -{
> -	enum hpd_pin pin;
> -
> -	BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS);
> -
> -	for_each_hpd_pin(pin) {
> -		if ((hpd[pin] & hotplug_trigger) == 0)
> -			continue;
> -
> -		*pin_mask |= BIT(pin);
> -
> -		if (long_pulse_detect(pin, dig_hotplug_reg))
> -			*long_mask |= BIT(pin);
> -	}
> -
> -	drm_dbg(&dev_priv->drm,
> -		"hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n",
> -		hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask);
> -
> -}
> -
> -static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv,
> -				  const u32 hpd[HPD_NUM_PINS])
> -{
> -	struct intel_encoder *encoder;
> -	u32 enabled_irqs = 0;
> -
> -	for_each_intel_encoder(&dev_priv->drm, encoder)
> -		if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED)
> -			enabled_irqs |= hpd[encoder->hpd_pin];
> -
> -	return enabled_irqs;
> -}
> -
> -static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv,
> -				  const u32 hpd[HPD_NUM_PINS])
> -{
> -	struct intel_encoder *encoder;
> -	u32 hotplug_irqs = 0;
> -
> -	for_each_intel_encoder(&dev_priv->drm, encoder)
> -		hotplug_irqs |= hpd[encoder->hpd_pin];
> -
> -	return hotplug_irqs;
> -}
> -
> -static u32 intel_hpd_hotplug_mask(struct drm_i915_private *i915,
> -				  hotplug_mask_func hotplug_mask)
> -{
> -	enum hpd_pin pin;
> -	u32 hotplug = 0;
> -
> -	for_each_hpd_pin(pin)
> -		hotplug |= hotplug_mask(pin);
> -
> -	return hotplug;
> -}
> -
> -static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915,
> -				     hotplug_enables_func hotplug_enables)
> -{
> -	struct intel_encoder *encoder;
> -	u32 hotplug = 0;
> -
> -	for_each_intel_encoder(&i915->drm, encoder)
> -		hotplug |= hotplug_enables(encoder);
> -
> -	return hotplug;
> -}
> -
>  #if defined(CONFIG_DEBUG_FS)
>  static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
>  					 enum pipe pipe,
> @@ -1199,71 +797,6 @@ static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
>  		intel_gmbus_irq_handler(dev_priv);
>  }
>  
> -static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_status = 0, hotplug_status_mask;
> -	int i;
> -
> -	if (IS_G4X(dev_priv) ||
> -	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		hotplug_status_mask = HOTPLUG_INT_STATUS_G4X |
> -			DP_AUX_CHANNEL_MASK_INT_STATUS_G4X;
> -	else
> -		hotplug_status_mask = HOTPLUG_INT_STATUS_I915;
> -
> -	/*
> -	 * We absolutely have to clear all the pending interrupt
> -	 * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port
> -	 * interrupt bit won't have an edge, and the i965/g4x
> -	 * edge triggered IIR will not notice that an interrupt
> -	 * is still pending. We can't use PORT_HOTPLUG_EN to
> -	 * guarantee the edge as the act of toggling the enable
> -	 * bits can itself generate a new hotplug interrupt :(
> -	 */
> -	for (i = 0; i < 10; i++) {
> -		u32 tmp = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask;
> -
> -		if (tmp == 0)
> -			return hotplug_status;
> -
> -		hotplug_status |= tmp;
> -		intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, hotplug_status);
> -	}
> -
> -	drm_WARN_ONCE(&dev_priv->drm, 1,
> -		      "PORT_HOTPLUG_STAT did not clear (0x%08x)\n",
> -		      intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
> -
> -	return hotplug_status;
> -}
> -
> -static void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv,
> -				 u32 hotplug_status)
> -{
> -	u32 pin_mask = 0, long_mask = 0;
> -	u32 hotplug_trigger;
> -
> -	if (IS_G4X(dev_priv) ||
> -	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
> -	else
> -		hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
> -
> -	if (hotplug_trigger) {
> -		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -				   hotplug_trigger, hotplug_trigger,
> -				   dev_priv->display.hotplug.hpd,
> -				   i9xx_port_hotplug_long_detect);
> -
> -		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> -	}
> -
> -	if ((IS_G4X(dev_priv) ||
> -	     IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> -	    hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
> -		intel_dp_aux_irq_handler(dev_priv);
> -}
> -
>  static irqreturn_t valleyview_irq_handler(int irq, void *arg)
>  {
>  	struct drm_i915_private *dev_priv = arg;
> @@ -1428,38 +961,6 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
>  	return ret;
>  }
>  
> -static void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv,
> -				u32 hotplug_trigger)
> -{
> -	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
> -
> -	/*
> -	 * Somehow the PCH doesn't seem to really ack the interrupt to the CPU
> -	 * unless we touch the hotplug register, even if hotplug_trigger is
> -	 * zero. Not acking leads to "The master control interrupt lied (SDE)!"
> -	 * errors.
> -	 */
> -	dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
> -	if (!hotplug_trigger) {
> -		u32 mask = PORTA_HOTPLUG_STATUS_MASK |
> -			PORTD_HOTPLUG_STATUS_MASK |
> -			PORTC_HOTPLUG_STATUS_MASK |
> -			PORTB_HOTPLUG_STATUS_MASK;
> -		dig_hotplug_reg &= ~mask;
> -	}
> -
> -	intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, dig_hotplug_reg);
> -	if (!hotplug_trigger)
> -		return;
> -
> -	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -			   hotplug_trigger, dig_hotplug_reg,
> -			   dev_priv->display.hotplug.pch_hpd,
> -			   pch_port_hotplug_long_detect);
> -
> -	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> -}
> -
>  static void ibx_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
>  {
>  	enum pipe pipe;
> @@ -1585,133 +1086,6 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
>  		cpt_serr_int_handler(dev_priv);
>  }
>  
> -static void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
> -{
> -	enum hpd_pin pin;
> -	u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK);
> -	u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
> -	u32 pin_mask = 0, long_mask = 0;
> -
> -	for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
> -		u32 val;
> -
> -		if (!(i915->display.hotplug.hpd[pin] & hotplug_trigger))
> -			continue;
> -
> -		pin_mask |= BIT(pin);
> -
> -		val = intel_de_read(i915, XELPDP_PORT_HOTPLUG_CTL(pin));
> -		intel_de_write(i915, XELPDP_PORT_HOTPLUG_CTL(pin), val);
> -
> -		if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | XELPDP_TBT_HPD_LONG_DETECT))
> -			long_mask |= BIT(pin);
> -	}
> -
> -	if (pin_mask) {
> -		drm_dbg(&i915->drm,
> -			"pica hotplug event received, stat 0x%08x, pins 0x%08x, long 0x%08x\n",
> -			hotplug_trigger, pin_mask, long_mask);
> -
> -		intel_hpd_irq_handler(i915, pin_mask, long_mask);
> -	}
> -
> -	if (trigger_aux)
> -		intel_dp_aux_irq_handler(i915);
> -
> -	if (!pin_mask && !trigger_aux)
> -		drm_err(&i915->drm,
> -			"Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
> -}
> -
> -static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
> -{
> -	u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
> -	u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
> -	u32 pin_mask = 0, long_mask = 0;
> -
> -	if (ddi_hotplug_trigger) {
> -		u32 dig_hotplug_reg;
> -
> -		/* Locking due to DSI native GPIO sequences */
> -		spin_lock(&dev_priv->irq_lock);
> -		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
> -		spin_unlock(&dev_priv->irq_lock);
> -
> -		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -				   ddi_hotplug_trigger, dig_hotplug_reg,
> -				   dev_priv->display.hotplug.pch_hpd,
> -				   icp_ddi_port_hotplug_long_detect);
> -	}
> -
> -	if (tc_hotplug_trigger) {
> -		u32 dig_hotplug_reg;
> -
> -		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC, 0, 0);
> -
> -		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -				   tc_hotplug_trigger, dig_hotplug_reg,
> -				   dev_priv->display.hotplug.pch_hpd,
> -				   icp_tc_port_hotplug_long_detect);
> -	}
> -
> -	if (pin_mask)
> -		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> -
> -	if (pch_iir & SDE_GMBUS_ICP)
> -		intel_gmbus_irq_handler(dev_priv);
> -}
> -
> -static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
> -{
> -	u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT &
> -		~SDE_PORTE_HOTPLUG_SPT;
> -	u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT;
> -	u32 pin_mask = 0, long_mask = 0;
> -
> -	if (hotplug_trigger) {
> -		u32 dig_hotplug_reg;
> -
> -		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
> -
> -		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -				   hotplug_trigger, dig_hotplug_reg,
> -				   dev_priv->display.hotplug.pch_hpd,
> -				   spt_port_hotplug_long_detect);
> -	}
> -
> -	if (hotplug2_trigger) {
> -		u32 dig_hotplug_reg;
> -
> -		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 0, 0);
> -
> -		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -				   hotplug2_trigger, dig_hotplug_reg,
> -				   dev_priv->display.hotplug.pch_hpd,
> -				   spt_port_hotplug2_long_detect);
> -	}
> -
> -	if (pin_mask)
> -		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> -
> -	if (pch_iir & SDE_GMBUS_CPT)
> -		intel_gmbus_irq_handler(dev_priv);
> -}
> -
> -static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv,
> -				u32 hotplug_trigger)
> -{
> -	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
> -
> -	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, 0, 0);
> -
> -	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -			   hotplug_trigger, dig_hotplug_reg,
> -			   dev_priv->display.hotplug.hpd,
> -			   ilk_port_hotplug_long_detect);
> -
> -	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> -}
> -
>  static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
>  				    u32 de_iir)
>  {
> @@ -1876,56 +1250,6 @@ static irqreturn_t ilk_irq_handler(int irq, void *arg)
>  	return ret;
>  }
>  
> -static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv,
> -				u32 hotplug_trigger)
> -{
> -	u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
> -
> -	dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG, 0, 0);
> -
> -	intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -			   hotplug_trigger, dig_hotplug_reg,
> -			   dev_priv->display.hotplug.hpd,
> -			   bxt_port_hotplug_long_detect);
> -
> -	intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> -}
> -
> -static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
> -{
> -	u32 pin_mask = 0, long_mask = 0;
> -	u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK;
> -	u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK;
> -
> -	if (trigger_tc) {
> -		u32 dig_hotplug_reg;
> -
> -		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 0, 0);
> -
> -		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -				   trigger_tc, dig_hotplug_reg,
> -				   dev_priv->display.hotplug.hpd,
> -				   gen11_port_hotplug_long_detect);
> -	}
> -
> -	if (trigger_tbt) {
> -		u32 dig_hotplug_reg;
> -
> -		dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 0, 0);
> -
> -		intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
> -				   trigger_tbt, dig_hotplug_reg,
> -				   dev_priv->display.hotplug.hpd,
> -				   gen11_port_hotplug_long_detect);
> -	}
> -
> -	if (pin_mask)
> -		intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
> -	else
> -		drm_err(&dev_priv->drm,
> -			"Unexpected DE HPD interrupt 0x%08x\n", iir);
> -}
> -
>  static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
>  {
>  	u32 mask;
> @@ -2943,696 +2267,39 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  }
>  
> -static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin)
> +/*
> + * SDEIER is also touched by the interrupt handler to work around missed PCH
> + * interrupts. Hence we can't update it after the interrupt handler is enabled -
> + * instead we unconditionally enable all PCH interrupt sources here, but then
> + * only unmask them as needed with SDEIMR.
> + *
> + * Note that we currently do this after installing the interrupt handler,
> + * but before we enable the master interrupt. That should be sufficient
> + * to avoid races with the irq handler, assuming we have MSI. Shared legacy
> + * interrupts could still race.
> + */
> +static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
>  {
> -	switch (hpd_pin) {
> -	case HPD_PORT_A:
> -		return PORTA_HOTPLUG_ENABLE;
> -	case HPD_PORT_B:
> -		return PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_MASK;
> -	case HPD_PORT_C:
> -		return PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_MASK;
> -	case HPD_PORT_D:
> -		return PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_MASK;
> -	default:
> -		return 0;
> -	}
> +	struct intel_uncore *uncore = &dev_priv->uncore;
> +	u32 mask;
> +
> +	if (HAS_PCH_NOP(dev_priv))
> +		return;
> +
> +	if (HAS_PCH_IBX(dev_priv))
> +		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
> +	else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
> +		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
> +	else
> +		mask = SDE_GMBUS_CPT;
> +
> +	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
>  }
>  
> -static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
> +static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	switch (encoder->hpd_pin) {
> -	case HPD_PORT_A:
> -		/*
> -		 * When CPU and PCH are on the same package, port A
> -		 * HPD must be enabled in both north and south.
> -		 */
> -		return HAS_PCH_LPT_LP(i915) ?
> -			PORTA_HOTPLUG_ENABLE : 0;
> -	case HPD_PORT_B:
> -		return PORTB_HOTPLUG_ENABLE |
> -			PORTB_PULSE_DURATION_2ms;
> -	case HPD_PORT_C:
> -		return PORTC_HOTPLUG_ENABLE |
> -			PORTC_PULSE_DURATION_2ms;
> -	case HPD_PORT_D:
> -		return PORTD_HOTPLUG_ENABLE |
> -			PORTD_PULSE_DURATION_2ms;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	/*
> -	 * Enable digital hotplug on the PCH, and configure the DP short pulse
> -	 * duration to 2ms (which is the minimum in the Display Port spec).
> -	 * The pulse duration bits are reserved on LPT+.
> -	 */
> -	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
> -			 intel_hpd_hotplug_mask(dev_priv, ibx_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables));
> -}
> -
> -static void ibx_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
> -			 ibx_hotplug_mask(encoder->hpd_pin),
> -			 ibx_hotplug_enables(encoder));
> -}
> -
> -static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> -
> -	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
> -
> -	ibx_hpd_detection_setup(dev_priv);
> -}
> -
> -static u32 icp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_A:
> -	case HPD_PORT_B:
> -	case HPD_PORT_C:
> -	case HPD_PORT_D:
> -		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	return icp_ddi_hotplug_mask(encoder->hpd_pin);
> -}
> -
> -static u32 icp_tc_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_TC1:
> -	case HPD_PORT_TC2:
> -	case HPD_PORT_TC3:
> -	case HPD_PORT_TC4:
> -	case HPD_PORT_TC5:
> -	case HPD_PORT_TC6:
> -		return ICP_TC_HPD_ENABLE(hpd_pin);
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	return icp_tc_hotplug_mask(encoder->hpd_pin);
> -}
> -
> -static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI,
> -			 intel_hpd_hotplug_mask(dev_priv, icp_ddi_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables));
> -}
> -
> -static void icp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_DDI,
> -			 icp_ddi_hotplug_mask(encoder->hpd_pin),
> -			 icp_ddi_hotplug_enables(encoder));
> -}
> -
> -static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_TC,
> -			 intel_hpd_hotplug_mask(dev_priv, icp_tc_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables));
> -}
> -
> -static void icp_tc_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_uncore_rmw(&i915->uncore, SHOTPLUG_CTL_TC,
> -			 icp_tc_hotplug_mask(encoder->hpd_pin),
> -			 icp_tc_hotplug_enables(encoder));
> -}
> -
> -static void icp_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	icp_ddi_hpd_enable_detection(encoder);
> -	icp_tc_hpd_enable_detection(encoder);
> -}
> -
> -static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> -
> -	if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
> -		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
> -
> -	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
> -
> -	icp_ddi_hpd_detection_setup(dev_priv);
> -	icp_tc_hpd_detection_setup(dev_priv);
> -}
> -
> -static u32 gen11_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_TC1:
> -	case HPD_PORT_TC2:
> -	case HPD_PORT_TC3:
> -	case HPD_PORT_TC4:
> -	case HPD_PORT_TC5:
> -	case HPD_PORT_TC6:
> -		return GEN11_HOTPLUG_CTL_ENABLE(hpd_pin);
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 gen11_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	return gen11_hotplug_mask(encoder->hpd_pin);
> -}
> -
> -static void dg1_hpd_invert(struct drm_i915_private *i915)
> -{
> -	u32 val = (INVERT_DDIA_HPD |
> -		   INVERT_DDIB_HPD |
> -		   INVERT_DDIC_HPD |
> -		   INVERT_DDID_HPD);
> -	intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1, 0, val);
> -}
> -
> -static void dg1_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	dg1_hpd_invert(i915);
> -	icp_hpd_enable_detection(encoder);
> -}
> -
> -static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	dg1_hpd_invert(dev_priv);
> -	icp_hpd_irq_setup(dev_priv);
> -}
> -
> -static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	intel_uncore_rmw(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL,
> -			 intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
> -}
> -
> -static void gen11_tc_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_uncore_rmw(&i915->uncore, GEN11_TC_HOTPLUG_CTL,
> -			 gen11_hotplug_mask(encoder->hpd_pin),
> -			 gen11_hotplug_enables(encoder));
> -}
> -
> -static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	intel_uncore_rmw(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL,
> -			 intel_hpd_hotplug_mask(dev_priv, gen11_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables));
> -}
> -
> -static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_uncore_rmw(&i915->uncore, GEN11_TBT_HOTPLUG_CTL,
> -			 gen11_hotplug_mask(encoder->hpd_pin),
> -			 gen11_hotplug_enables(encoder));
> -}
> -
> -static void gen11_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	gen11_tc_hpd_enable_detection(encoder);
> -	gen11_tbt_hpd_enable_detection(encoder);
> -
> -	if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
> -		icp_hpd_enable_detection(encoder);
> -}
> -
> -static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> -
> -	intel_uncore_rmw(&dev_priv->uncore, GEN11_DE_HPD_IMR, hotplug_irqs,
> -			 ~enabled_irqs & hotplug_irqs);
> -	intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
> -
> -	gen11_tc_hpd_detection_setup(dev_priv);
> -	gen11_tbt_hpd_detection_setup(dev_priv);
> -
> -	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
> -		icp_hpd_irq_setup(dev_priv);
> -}
> -
> -static u32 mtp_ddi_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_A:
> -	case HPD_PORT_B:
> -		return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin);
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	return mtp_ddi_hotplug_mask(encoder->hpd_pin);
> -}
> -
> -static u32 mtp_tc_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_TC1:
> -	case HPD_PORT_TC2:
> -	case HPD_PORT_TC3:
> -	case HPD_PORT_TC4:
> -		return ICP_TC_HPD_ENABLE(hpd_pin);
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	return mtp_tc_hotplug_mask(encoder->hpd_pin);
> -}
> -
> -static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915)
> -{
> -	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
> -		     intel_hpd_hotplug_mask(i915, mtp_ddi_hotplug_mask),
> -		     intel_hpd_hotplug_enables(i915, mtp_ddi_hotplug_enables));
> -}
> -
> -static void mtp_ddi_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
> -		     mtp_ddi_hotplug_mask(encoder->hpd_pin),
> -		     mtp_ddi_hotplug_enables(encoder));
> -}
> -
> -static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915)
> -{
> -	intel_de_rmw(i915, SHOTPLUG_CTL_TC,
> -		     intel_hpd_hotplug_mask(i915, mtp_tc_hotplug_mask),
> -		     intel_hpd_hotplug_enables(i915, mtp_tc_hotplug_enables));
> -}
> -
> -static void mtp_tc_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_de_rmw(i915, SHOTPLUG_CTL_DDI,
> -		     mtp_tc_hotplug_mask(encoder->hpd_pin),
> -		     mtp_tc_hotplug_enables(encoder));
> -}
> -
> -static void mtp_hpd_invert(struct drm_i915_private *i915)
> -{
> -	u32 val = (INVERT_DDIA_HPD |
> -		   INVERT_DDIB_HPD |
> -		   INVERT_DDIC_HPD |
> -		   INVERT_TC1_HPD |
> -		   INVERT_TC2_HPD |
> -		   INVERT_TC3_HPD |
> -		   INVERT_TC4_HPD |
> -		   INVERT_DDID_HPD_MTP |
> -		   INVERT_DDIE_HPD);
> -	intel_de_rmw(i915, SOUTH_CHICKEN1, 0, val);
> -}
> -
> -static void mtp_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	mtp_hpd_invert(i915);
> -	mtp_ddi_hpd_enable_detection(encoder);
> -	mtp_tc_hpd_enable_detection(encoder);
> -}
> -
> -static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
> -
> -	intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
> -
> -	mtp_hpd_invert(i915);
> -	ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
> -
> -	mtp_ddi_hpd_detection_setup(i915);
> -	mtp_tc_hpd_detection_setup(i915);
> -}
> -
> -static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
> -{
> -	return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
> -}
> -
> -static void _xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915,
> -					     enum hpd_pin hpd_pin, bool enable)
> -{
> -	u32 mask = XELPDP_TBT_HOTPLUG_ENABLE |
> -		XELPDP_DP_ALT_HOTPLUG_ENABLE;
> -
> -	if (!is_xelpdp_pica_hpd_pin(hpd_pin))
> -		return;
> -
> -	intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(hpd_pin),
> -		     mask, enable ? mask : 0);
> -}
> -
> -static void xelpdp_pica_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	_xelpdp_pica_hpd_detection_setup(i915, encoder->hpd_pin, true);
> -}
> -
> -static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915)
> -{
> -	struct intel_encoder *encoder;
> -	u32 available_pins = 0;
> -	enum hpd_pin pin;
> -
> -	BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS);
> -
> -	for_each_intel_encoder(&i915->drm, encoder)
> -		available_pins |= BIT(encoder->hpd_pin);
> -
> -	for_each_hpd_pin(pin)
> -		_xelpdp_pica_hpd_detection_setup(i915, pin, available_pins & BIT(pin));
> -}
> -
> -static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	xelpdp_pica_hpd_enable_detection(encoder);
> -	mtp_hpd_enable_detection(encoder);
> -}
> -
> -static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.hpd);
> -
> -	intel_de_rmw(i915, PICAINTERRUPT_IMR, hotplug_irqs,
> -		     ~enabled_irqs & hotplug_irqs);
> -	intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR);
> -
> -	xelpdp_pica_hpd_detection_setup(i915);
> -
> -	if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
> -		mtp_hpd_irq_setup(i915);
> -}
> -
> -static u32 spt_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_A:
> -		return PORTA_HOTPLUG_ENABLE;
> -	case HPD_PORT_B:
> -		return PORTB_HOTPLUG_ENABLE;
> -	case HPD_PORT_C:
> -		return PORTC_HOTPLUG_ENABLE;
> -	case HPD_PORT_D:
> -		return PORTD_HOTPLUG_ENABLE;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 spt_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	return spt_hotplug_mask(encoder->hpd_pin);
> -}
> -
> -static u32 spt_hotplug2_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_E:
> -		return PORTE_HOTPLUG_ENABLE;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
> -{
> -	return spt_hotplug2_mask(encoder->hpd_pin);
> -}
> -
> -static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	/* Display WA #1179 WaHardHangonHotPlug: cnp */
> -	if (HAS_PCH_CNP(dev_priv)) {
> -		intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
> -				 CHASSIS_CLK_REQ_DURATION(0xf));
> -	}
> -
> -	/* Enable digital hotplug on the PCH */
> -	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
> -			 intel_hpd_hotplug_mask(dev_priv, spt_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables));
> -
> -	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG2,
> -			 intel_hpd_hotplug_mask(dev_priv, spt_hotplug2_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables));
> -}
> -
> -static void spt_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	/* Display WA #1179 WaHardHangonHotPlug: cnp */
> -	if (HAS_PCH_CNP(i915)) {
> -		intel_uncore_rmw(&i915->uncore, SOUTH_CHICKEN1,
> -				 CHASSIS_CLK_REQ_DURATION_MASK,
> -				 CHASSIS_CLK_REQ_DURATION(0xf));
> -	}
> -
> -	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
> -			 spt_hotplug_mask(encoder->hpd_pin),
> -			 spt_hotplug_enables(encoder));
> -
> -	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG2,
> -			 spt_hotplug2_mask(encoder->hpd_pin),
> -			 spt_hotplug2_enables(encoder));
> -}
> -
> -static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
> -		intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
> -
> -	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
> -
> -	spt_hpd_detection_setup(dev_priv);
> -}
> -
> -static u32 ilk_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_A:
> -		return DIGITAL_PORTA_HOTPLUG_ENABLE |
> -			DIGITAL_PORTA_PULSE_DURATION_MASK;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 ilk_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	switch (encoder->hpd_pin) {
> -	case HPD_PORT_A:
> -		return DIGITAL_PORTA_HOTPLUG_ENABLE |
> -			DIGITAL_PORTA_PULSE_DURATION_2ms;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	/*
> -	 * Enable digital hotplug on the CPU, and configure the DP short pulse
> -	 * duration to 2ms (which is the minimum in the Display Port spec)
> -	 * The pulse duration bits are reserved on HSW+.
> -	 */
> -	intel_uncore_rmw(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
> -			 intel_hpd_hotplug_mask(dev_priv, ilk_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables));
> -}
> -
> -static void ilk_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_uncore_rmw(&i915->uncore, DIGITAL_PORT_HOTPLUG_CNTRL,
> -			 ilk_hotplug_mask(encoder->hpd_pin),
> -			 ilk_hotplug_enables(encoder));
> -
> -	ibx_hpd_enable_detection(encoder);
> -}
> -
> -static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> -
> -	if (DISPLAY_VER(dev_priv) >= 8)
> -		bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
> -	else
> -		ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs);
> -
> -	ilk_hpd_detection_setup(dev_priv);
> -
> -	ibx_hpd_irq_setup(dev_priv);
> -}
> -
> -static u32 bxt_hotplug_mask(enum hpd_pin hpd_pin)
> -{
> -	switch (hpd_pin) {
> -	case HPD_PORT_A:
> -		return PORTA_HOTPLUG_ENABLE | BXT_DDIA_HPD_INVERT;
> -	case HPD_PORT_B:
> -		return PORTB_HOTPLUG_ENABLE | BXT_DDIB_HPD_INVERT;
> -	case HPD_PORT_C:
> -		return PORTC_HOTPLUG_ENABLE | BXT_DDIC_HPD_INVERT;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static u32 bxt_hotplug_enables(struct intel_encoder *encoder)
> -{
> -	u32 hotplug;
> -
> -	switch (encoder->hpd_pin) {
> -	case HPD_PORT_A:
> -		hotplug = PORTA_HOTPLUG_ENABLE;
> -		if (intel_bios_encoder_hpd_invert(encoder->devdata))
> -			hotplug |= BXT_DDIA_HPD_INVERT;
> -		return hotplug;
> -	case HPD_PORT_B:
> -		hotplug = PORTB_HOTPLUG_ENABLE;
> -		if (intel_bios_encoder_hpd_invert(encoder->devdata))
> -			hotplug |= BXT_DDIB_HPD_INVERT;
> -		return hotplug;
> -	case HPD_PORT_C:
> -		hotplug = PORTC_HOTPLUG_ENABLE;
> -		if (intel_bios_encoder_hpd_invert(encoder->devdata))
> -			hotplug |= BXT_DDIC_HPD_INVERT;
> -		return hotplug;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
> -{
> -	intel_uncore_rmw(&dev_priv->uncore, PCH_PORT_HOTPLUG,
> -			 intel_hpd_hotplug_mask(dev_priv, bxt_hotplug_mask),
> -			 intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables));
> -}
> -
> -static void bxt_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	intel_uncore_rmw(&i915->uncore, PCH_PORT_HOTPLUG,
> -			 bxt_hotplug_mask(encoder->hpd_pin),
> -			 bxt_hotplug_enables(encoder));
> -}
> -
> -static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_irqs, enabled_irqs;
> -
> -	enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> -	hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.hpd);
> -
> -	bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs);
> -
> -	bxt_hpd_detection_setup(dev_priv);
> -}
> -
> -/*
> - * SDEIER is also touched by the interrupt handler to work around missed PCH
> - * interrupts. Hence we can't update it after the interrupt handler is enabled -
> - * instead we unconditionally enable all PCH interrupt sources here, but then
> - * only unmask them as needed with SDEIMR.
> - *
> - * Note that we currently do this after installing the interrupt handler,
> - * but before we enable the master interrupt. That should be sufficient
> - * to avoid races with the irq handler, assuming we have MSI. Shared legacy
> - * interrupts could still race.
> - */
> -static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_uncore *uncore = &dev_priv->uncore;
> -	u32 mask;
> -
> -	if (HAS_PCH_NOP(dev_priv))
> -		return;
> -
> -	if (HAS_PCH_IBX(dev_priv))
> -		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
> -	else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
> -		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
> -	else
> -		mask = SDE_GMBUS_CPT;
> -
> -	GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
> -}
> -
> -static void ilk_irq_postinstall(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_uncore *uncore = &dev_priv->uncore;
> -	u32 display_mask, extra_mask;
> +	struct intel_uncore *uncore = &dev_priv->uncore;
> +	u32 display_mask, extra_mask;
>  
>  	if (GRAPHICS_VER(dev_priv) >= 7) {
>  		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
> @@ -4267,40 +2934,6 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
>  	i915_enable_asle_pipestat(dev_priv);
>  }
>  
> -static void i915_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -	u32 hotplug_en = hpd_mask_i915[encoder->hpd_pin];
> -
> -	/* HPD sense and interrupt enable are one and the same */
> -	i915_hotplug_interrupt_update(i915, hotplug_en, hotplug_en);
> -}
> -
> -static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv)
> -{
> -	u32 hotplug_en;
> -
> -	lockdep_assert_held(&dev_priv->irq_lock);
> -
> -	/* Note HDMI and DP share hotplug bits */
> -	/* enable bits are the same for all generations */
> -	hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd_mask_i915);
> -	/* Programming the CRT detection parameters tends
> -	   to generate a spurious hotplug event about three
> -	   seconds later.  So just do it once.
> -	*/
> -	if (IS_G4X(dev_priv))
> -		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
> -	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
> -
> -	/* Ignore TV since it's buggy */
> -	i915_hotplug_interrupt_update_locked(dev_priv,
> -					     HOTPLUG_INT_EN_MASK |
> -					     CRT_HOTPLUG_VOLTAGE_COMPARE_MASK |
> -					     CRT_HOTPLUG_ACTIVATION_PERIOD_64,
> -					     hotplug_en);
> -}
> -
>  static irqreturn_t i965_irq_handler(int irq, void *arg)
>  {
>  	struct drm_i915_private *dev_priv = arg;
> @@ -4360,43 +2993,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
>  	return ret;
>  }
>  
> -struct intel_hotplug_funcs {
> -	/* Enable HPD sense and interrupts for all present encoders */
> -	void (*hpd_irq_setup)(struct drm_i915_private *i915);
> -	/* Enable HPD sense for a single encoder */
> -	void (*hpd_enable_detection)(struct intel_encoder *encoder);
> -};
> -
> -#define HPD_FUNCS(platform)					 \
> -static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
> -	.hpd_irq_setup = platform##_hpd_irq_setup,		 \
> -	.hpd_enable_detection = platform##_hpd_enable_detection, \
> -}
> -
> -HPD_FUNCS(i915);
> -HPD_FUNCS(xelpdp);
> -HPD_FUNCS(dg1);
> -HPD_FUNCS(gen11);
> -HPD_FUNCS(bxt);
> -HPD_FUNCS(icp);
> -HPD_FUNCS(spt);
> -HPD_FUNCS(ilk);
> -#undef HPD_FUNCS
> -
> -void intel_hpd_enable_detection(struct intel_encoder *encoder)
> -{
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> -
> -	if (i915->display.funcs.hotplug)
> -		i915->display.funcs.hotplug->hpd_enable_detection(encoder);
> -}
> -
> -void intel_hpd_irq_setup(struct drm_i915_private *i915)
> -{
> -	if (i915->display_irqs_enabled && i915->display.funcs.hotplug)
> -		i915->display.funcs.hotplug->hpd_irq_setup(i915);
> -}
> -
>  /**
>   * intel_irq_init - initializes irq support
>   * @dev_priv: i915 device instance
> @@ -4419,10 +3015,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
>  	if (!HAS_DISPLAY(dev_priv))
>  		return;
>  
> -	intel_hpd_init_pins(dev_priv);
> -
> -	intel_hpd_init_early(dev_priv);
> -
>  	dev_priv->drm.vblank_disable_immediate = true;
>  
>  	/* Most platforms treat the display irq block as an always-on
> @@ -4435,27 +3027,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
>  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>  		dev_priv->display_irqs_enabled = false;
>  
> -	if (HAS_GMCH(dev_priv)) {
> -		if (I915_HAS_HOTPLUG(dev_priv))
> -			dev_priv->display.funcs.hotplug = &i915_hpd_funcs;
> -	} else {
> -		if (HAS_PCH_DG2(dev_priv))
> -			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
> -		else if (HAS_PCH_DG1(dev_priv))
> -			dev_priv->display.funcs.hotplug = &dg1_hpd_funcs;
> -		else if (DISPLAY_VER(dev_priv) >= 14)
> -			dev_priv->display.funcs.hotplug = &xelpdp_hpd_funcs;
> -		else if (DISPLAY_VER(dev_priv) >= 11)
> -			dev_priv->display.funcs.hotplug = &gen11_hpd_funcs;
> -		else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
> -			dev_priv->display.funcs.hotplug = &bxt_hpd_funcs;
> -		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
> -			dev_priv->display.funcs.hotplug = &icp_hpd_funcs;
> -		else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
> -			dev_priv->display.funcs.hotplug = &spt_hpd_funcs;
> -		else
> -			dev_priv->display.funcs.hotplug = &ilk_hpd_funcs;
> -	}
> +	intel_hotplug_irq_init(dev_priv);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h
> index dd47e473ba4f..913c854f873d 100644
> --- a/drivers/gpu/drm/i915/i915_irq.h
> +++ b/drivers/gpu/drm/i915/i915_irq.h
> @@ -38,18 +38,18 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
>  void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
>  void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
>  
> -void intel_hpd_enable_detection(struct intel_encoder *encoder);
> -void intel_hpd_irq_setup(struct drm_i915_private *i915);
> -void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
> -				   u32 mask,
> -				   u32 bits);
> -
> +void ilk_update_display_irq(struct drm_i915_private *i915,
> +			    u32 interrupt_mask, u32 enabled_irq_mask);
>  void ilk_enable_display_irq(struct drm_i915_private *i915, u32 bits);
>  void ilk_disable_display_irq(struct drm_i915_private *i915, u32 bits);
>  
> +void bdw_update_port_irq(struct drm_i915_private *i915,
> +			 u32 interrupt_mask, u32 enabled_irq_mask);
>  void bdw_enable_pipe_irq(struct drm_i915_private *i915, enum pipe pipe, u32 bits);
>  void bdw_disable_pipe_irq(struct drm_i915_private *i915, enum pipe pipe, u32 bits);
>  
> +void ibx_display_interrupt_update(struct drm_i915_private *i915,
> +				  u32 interrupt_mask, u32 enabled_irq_mask);
>  void ibx_enable_display_interrupt(struct drm_i915_private *i915, u32 bits);
>  void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits);
>  
> -- 
> 2.39.2
> 


More information about the Intel-gfx mailing list