Blob Blame History Raw
From: Lyude <lyude@redhat.com>
Date: Fri, 19 May 2017 19:48:37 -0400
Subject: drm/radeon: Cleanup display interrupt handling for evergreen, si
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: 4cd096dde950c878e044211f1e7bac384b1588f5
Patch-mainline: v4.13-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

The current code here is really, really bad. A huge amount of it looks
to be copy pasted, it has some weird hatred of arrays and code sharing,
switch cases everywhere for things that really don't need them, and it
makes the file seem immensely more complex then it actually is. This is
a pain for maintanence, and is vulnerable to more weird irq handling
bugs.

So, let's start cleaning this up a bit. Modify all of the IRQ handlers
for evergreen/si so that they just use for loops. As well, we add a
helper function radeon_irq_kms_set_irq_n_enabled(), whose purpose is
just to update the state of registers that enable/disable interrupts
while printing any changes to the set of enabled interrupts to the
kernel log.

Note in this commit, since vblank/vline irq acking is intertwined with
page flip irq acking, we can't cut out all of the copy paste in
evergreen/si_irq_ack() just yet.

Changes since v1:
- Preserve order we write back all registers

Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Lyude <lyude@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/radeon/evergreen.c      |  729 ++++++--------------------------
 drivers/gpu/drm/radeon/radeon.h         |   13 
 drivers/gpu/drm/radeon/radeon_irq_kms.c |   35 +
 drivers/gpu/drm/radeon/si.c             |  596 +++++---------------------
 4 files changed, 314 insertions(+), 1059 deletions(-)

--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -35,6 +35,10 @@
 #include "evergreen_blit_shaders.h"
 #include "radeon_ucode.h"
 
+#define DC_HPDx_CONTROL(x)        (DC_HPD1_CONTROL     + (x * 0xc))
+#define DC_HPDx_INT_CONTROL(x)    (DC_HPD1_INT_CONTROL + (x * 0xc))
+#define DC_HPDx_INT_STATUS_REG(x) (DC_HPD1_INT_STATUS  + (x * 0xc))
+
 /*
  * Indirect registers accessor
  */
@@ -1714,38 +1718,10 @@ void evergreen_pm_finish(struct radeon_d
  */
 bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
 {
-	bool connected = false;
-
-	switch (hpd) {
-	case RADEON_HPD_1:
-		if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case RADEON_HPD_2:
-		if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case RADEON_HPD_3:
-		if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case RADEON_HPD_4:
-		if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case RADEON_HPD_5:
-		if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case RADEON_HPD_6:
-		if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	default:
-		break;
-	}
+	if (hpd == RADEON_HPD_NONE)
+		return false;
 
-	return connected;
+	return !!(RREG32(DC_HPDx_INT_STATUS_REG(hpd)) & DC_HPDx_SENSE);
 }
 
 /**
@@ -1759,61 +1735,15 @@ bool evergreen_hpd_sense(struct radeon_d
 void evergreen_hpd_set_polarity(struct radeon_device *rdev,
 				enum radeon_hpd_id hpd)
 {
-	u32 tmp;
 	bool connected = evergreen_hpd_sense(rdev, hpd);
 
-	switch (hpd) {
-	case RADEON_HPD_1:
-		tmp = RREG32(DC_HPD1_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD1_INT_CONTROL, tmp);
-		break;
-	case RADEON_HPD_2:
-		tmp = RREG32(DC_HPD2_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD2_INT_CONTROL, tmp);
-		break;
-	case RADEON_HPD_3:
-		tmp = RREG32(DC_HPD3_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD3_INT_CONTROL, tmp);
-		break;
-	case RADEON_HPD_4:
-		tmp = RREG32(DC_HPD4_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD4_INT_CONTROL, tmp);
-		break;
-	case RADEON_HPD_5:
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD5_INT_CONTROL, tmp);
-			break;
-	case RADEON_HPD_6:
-		tmp = RREG32(DC_HPD6_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD6_INT_CONTROL, tmp);
-		break;
-	default:
-		break;
-	}
+	if (hpd == RADEON_HPD_NONE)
+		return;
+
+	if (connected)
+		WREG32_AND(DC_HPDx_INT_CONTROL(hpd), ~DC_HPDx_INT_POLARITY);
+	else
+		WREG32_OR(DC_HPDx_INT_CONTROL(hpd), DC_HPDx_INT_POLARITY);
 }
 
 /**
@@ -1833,7 +1763,8 @@ void evergreen_hpd_init(struct radeon_de
 		DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		enum radeon_hpd_id hpd =
+			to_radeon_connector(connector)->hpd.hpd;
 
 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
 		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -1844,31 +1775,14 @@ void evergreen_hpd_init(struct radeon_de
 			 */
 			continue;
 		}
-		switch (radeon_connector->hpd.hpd) {
-		case RADEON_HPD_1:
-			WREG32(DC_HPD1_CONTROL, tmp);
-			break;
-		case RADEON_HPD_2:
-			WREG32(DC_HPD2_CONTROL, tmp);
-			break;
-		case RADEON_HPD_3:
-			WREG32(DC_HPD3_CONTROL, tmp);
-			break;
-		case RADEON_HPD_4:
-			WREG32(DC_HPD4_CONTROL, tmp);
-			break;
-		case RADEON_HPD_5:
-			WREG32(DC_HPD5_CONTROL, tmp);
-			break;
-		case RADEON_HPD_6:
-			WREG32(DC_HPD6_CONTROL, tmp);
-			break;
-		default:
-			break;
-		}
-		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
-		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
-			enabled |= 1 << radeon_connector->hpd.hpd;
+
+		if (hpd == RADEON_HPD_NONE)
+			continue;
+
+		WREG32(DC_HPDx_CONTROL(hpd), tmp);
+		enabled |= 1 << hpd;
+
+		radeon_hpd_set_polarity(rdev, hpd);
 	}
 	radeon_irq_kms_enable_hpd(rdev, enabled);
 }
@@ -1888,31 +1802,14 @@ void evergreen_hpd_fini(struct radeon_de
 	unsigned disabled = 0;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		switch (radeon_connector->hpd.hpd) {
-		case RADEON_HPD_1:
-			WREG32(DC_HPD1_CONTROL, 0);
-			break;
-		case RADEON_HPD_2:
-			WREG32(DC_HPD2_CONTROL, 0);
-			break;
-		case RADEON_HPD_3:
-			WREG32(DC_HPD3_CONTROL, 0);
-			break;
-		case RADEON_HPD_4:
-			WREG32(DC_HPD4_CONTROL, 0);
-			break;
-		case RADEON_HPD_5:
-			WREG32(DC_HPD5_CONTROL, 0);
-			break;
-		case RADEON_HPD_6:
-			WREG32(DC_HPD6_CONTROL, 0);
-			break;
-		default:
-			break;
-		}
-		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
-			disabled |= 1 << radeon_connector->hpd.hpd;
+		enum radeon_hpd_id hpd =
+			to_radeon_connector(connector)->hpd.hpd;
+
+		if (hpd == RADEON_HPD_NONE)
+			continue;
+
+		WREG32(DC_HPDx_CONTROL(hpd), 0);
+		disabled |= 1 << hpd;
 	}
 	radeon_irq_kms_disable_hpd(rdev, disabled);
 }
@@ -2640,6 +2537,15 @@ static const unsigned evergreen_dp_offse
 	EVERGREEN_DP5_REGISTER_OFFSET
 };
 
+static const unsigned evergreen_disp_int_status[] =
+{
+	DISP_INTERRUPT_STATUS,
+	DISP_INTERRUPT_STATUS_CONTINUE,
+	DISP_INTERRUPT_STATUS_CONTINUE2,
+	DISP_INTERRUPT_STATUS_CONTINUE3,
+	DISP_INTERRUPT_STATUS_CONTINUE4,
+	DISP_INTERRUPT_STATUS_CONTINUE5
+};
 
 /*
  * Assumption is that EVERGREEN_CRTC_MASTER_EN enable for requested crtc
@@ -4546,6 +4452,7 @@ u32 evergreen_get_vblank_counter(struct
 
 void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 {
+	int i;
 	u32 tmp;
 
 	if (rdev->family >= CHIP_CAYMAN) {
@@ -4561,16 +4468,8 @@ void evergreen_disable_interrupt_state(s
 	WREG32(DMA_CNTL, tmp);
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(SRBM_INT_CNTL, 0);
-	WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
-	WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	if (rdev->num_crtc >= 4) {
-		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
-	}
+	for (i = 0; i < rdev->num_crtc; i++)
+		WREG32(INT_MASK + crtc_offsets[i], 0);
 
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
@@ -4588,27 +4487,16 @@ void evergreen_disable_interrupt_state(s
 		WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
 	WREG32(DACB_AUTODETECT_INT_CONTROL, 0);
 
-	tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-	WREG32(DC_HPD1_INT_CONTROL, tmp);
-	tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-	WREG32(DC_HPD2_INT_CONTROL, tmp);
-	tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-	WREG32(DC_HPD3_INT_CONTROL, tmp);
-	tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-	WREG32(DC_HPD4_INT_CONTROL, tmp);
-	tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-	WREG32(DC_HPD5_INT_CONTROL, tmp);
-	tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-	WREG32(DC_HPD6_INT_CONTROL, tmp);
-
+	for (i = 0; i < 6; i++)
+		WREG32_AND(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_POLARITY);
 }
 
+/* Note that the order we write back regs here is important */
 int evergreen_irq_set(struct radeon_device *rdev)
 {
+	int i;
 	u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
 	u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;
-	u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
-	u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
 	u32 grbm_int_cntl = 0;
 	u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0;
 	u32 dma_cntl, dma_cntl1 = 0;
@@ -4626,12 +4514,6 @@ int evergreen_irq_set(struct radeon_devi
 		return 0;
 	}
 
-	hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-	hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-	hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-	hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-	hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-	hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
 	if (rdev->family == CHIP_ARUBA)
 		thermal_int = RREG32(TN_CG_THERMAL_INT_CTRL) &
 			~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
@@ -4688,60 +4570,6 @@ int evergreen_irq_set(struct radeon_devi
 		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
 	}
 
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
-		DRM_DEBUG("evergreen_irq_set: vblank 0\n");
-		crtc1 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
-		DRM_DEBUG("evergreen_irq_set: vblank 1\n");
-		crtc2 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[2] ||
-	    atomic_read(&rdev->irq.pflip[2])) {
-		DRM_DEBUG("evergreen_irq_set: vblank 2\n");
-		crtc3 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[3] ||
-	    atomic_read(&rdev->irq.pflip[3])) {
-		DRM_DEBUG("evergreen_irq_set: vblank 3\n");
-		crtc4 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[4] ||
-	    atomic_read(&rdev->irq.pflip[4])) {
-		DRM_DEBUG("evergreen_irq_set: vblank 4\n");
-		crtc5 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[5] ||
-	    atomic_read(&rdev->irq.pflip[5])) {
-		DRM_DEBUG("evergreen_irq_set: vblank 5\n");
-		crtc6 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.hpd[0]) {
-		DRM_DEBUG("evergreen_irq_set: hpd 1\n");
-		hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[1]) {
-		DRM_DEBUG("evergreen_irq_set: hpd 2\n");
-		hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[2]) {
-		DRM_DEBUG("evergreen_irq_set: hpd 3\n");
-		hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[3]) {
-		DRM_DEBUG("evergreen_irq_set: hpd 4\n");
-		hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[4]) {
-		DRM_DEBUG("evergreen_irq_set: hpd 5\n");
-		hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[5]) {
-		DRM_DEBUG("evergreen_irq_set: hpd 6\n");
-		hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
 	if (rdev->irq.afmt[0]) {
 		DRM_DEBUG("evergreen_irq_set: hdmi 0\n");
 		afmt1 |= AFMT_AZ_FORMAT_WTRIG_MASK;
@@ -4781,15 +4609,12 @@ int evergreen_irq_set(struct radeon_devi
 
 	WREG32(GRBM_INT_CNTL, grbm_int_cntl);
 
-	WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1);
-	WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2);
-	if (rdev->num_crtc >= 4) {
-		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3);
-		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5);
-		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
+	for (i = 0; i < rdev->num_crtc; i++) {
+		radeon_irq_kms_set_irq_n_enabled(
+		    rdev, INT_MASK + crtc_offsets[i],
+		    VBLANK_INT_MASK,
+		    rdev->irq.crtc_vblank_int[i] ||
+		    atomic_read(&rdev->irq.pflip[i]), "vblank", i);
 	}
 
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
@@ -4809,12 +4634,13 @@ int evergreen_irq_set(struct radeon_devi
 		       GRPH_PFLIP_INT_MASK);
 	}
 
-	WREG32(DC_HPD1_INT_CONTROL, hpd1);
-	WREG32(DC_HPD2_INT_CONTROL, hpd2);
-	WREG32(DC_HPD3_INT_CONTROL, hpd3);
-	WREG32(DC_HPD4_INT_CONTROL, hpd4);
-	WREG32(DC_HPD5_INT_CONTROL, hpd5);
-	WREG32(DC_HPD6_INT_CONTROL, hpd6);
+	for (i = 0; i < 6; i++) {
+		radeon_irq_kms_set_irq_n_enabled(
+		    rdev, DC_HPDx_INT_CONTROL(i),
+		    DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN,
+		    rdev->irq.hpd[i], "HPD", i);
+	}
+
 	if (rdev->family == CHIP_ARUBA)
 		WREG32(TN_CG_THERMAL_INT_CTRL, thermal_int);
 	else
@@ -4833,16 +4659,16 @@ int evergreen_irq_set(struct radeon_devi
 	return 0;
 }
 
+/* Note that the order we write back regs here is important */
 static void evergreen_irq_ack(struct radeon_device *rdev)
 {
+	int i;
+	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
 	u32 tmp;
 
-	rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS);
-	rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
-	rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2);
-	rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3);
-	rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4);
-	rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
+	for (i = 0; i < 6; i++)
+		disp_int[i] = RREG32(evergreen_disp_int_status[i]);
+
 	rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
 	rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
 	if (rdev->num_crtc >= 4) {
@@ -4865,28 +4691,28 @@ static void evergreen_irq_ack(struct rad
 		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
 		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
-		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
-	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
-		WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK);
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)
-		WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK);
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)
-		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
+	if (disp_int[0] & LB_D1_VBLANK_INTERRUPT)
+		WREG32(VBLANK_STATUS + crtc_offsets[0], VBLANK_ACK);
+	if (disp_int[0] & LB_D1_VLINE_INTERRUPT)
+		WREG32(VLINE_STATUS + crtc_offsets[0], VLINE_ACK);
+	if (disp_int[1] & LB_D1_VBLANK_INTERRUPT)
+		WREG32(VBLANK_STATUS + crtc_offsets[1], VBLANK_ACK);
+	if (disp_int[1] & LB_D1_VLINE_INTERRUPT)
+		WREG32(VLINE_STATUS + crtc_offsets[1], VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
 		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK);
+		if (disp_int[2] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[2], VBLANK_ACK);
+		if (disp_int[2] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[2], VLINE_ACK);
+		if (disp_int[3] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[3], VBLANK_ACK);
+		if (disp_int[3] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[3], VLINE_ACK);
 	}
 
 	if (rdev->num_crtc >= 6) {
@@ -4894,76 +4720,24 @@ static void evergreen_irq_ack(struct rad
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK);
-	}
-
-	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) {
-		tmp = RREG32(DC_HPD1_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD1_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) {
-		tmp = RREG32(DC_HPD2_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD2_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) {
-		tmp = RREG32(DC_HPD3_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD3_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) {
-		tmp = RREG32(DC_HPD4_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD4_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD5_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-		tmp = RREG32(DC_HPD6_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD6_INT_CONTROL, tmp);
-	}
-
-	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD1_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD1_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD2_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD2_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD3_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD3_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD4_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD4_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD5_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD6_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD6_INT_CONTROL, tmp);
+		if (disp_int[4] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[4], VBLANK_ACK);
+		if (disp_int[4] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[4], VLINE_ACK);
+		if (disp_int[5] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[5], VBLANK_ACK);
+		if (disp_int[5] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[5], VLINE_ACK);
+	}
+
+	for (i = 0; i < 6; i++) {
+		if (disp_int[i] & DC_HPD1_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_ACK);
+	}
+
+	for (i = 0; i < 6; i++) {
+		if (disp_int[i] & DC_HPD1_RX_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
 	}
 
 	if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
@@ -5040,6 +4814,9 @@ static u32 evergreen_get_ih_wptr(struct
 
 int evergreen_irq_process(struct radeon_device *rdev)
 {
+	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
+	u32 crtc_idx, hpd_idx;
+	u32 mask;
 	u32 wptr;
 	u32 rptr;
 	u32 src_id, src_data;
@@ -5049,6 +4826,7 @@ int evergreen_irq_process(struct radeon_
 	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
+	const char *event_name;
 
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
@@ -5077,184 +4855,44 @@ restart_ih:
 
 		switch (src_id) {
 		case 1: /* D1 vblank/vline */
-			switch (src_data) {
-			case 0: /* D1 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[0]) {
-					drm_handle_vblank(rdev->ddev, 0);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[0]))
-					radeon_crtc_handle_vblank(rdev, 0);
-				rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D1 vblank\n");
-
-				break;
-			case 1: /* D1 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D1 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 2: /* D2 vblank/vline */
-			switch (src_data) {
-			case 0: /* D2 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[1]) {
-					drm_handle_vblank(rdev->ddev, 1);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[1]))
-					radeon_crtc_handle_vblank(rdev, 1);
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D2 vblank\n");
-
-				break;
-			case 1: /* D2 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D2 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 3: /* D3 vblank/vline */
-			switch (src_data) {
-			case 0: /* D3 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: D3 vblank - IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[2]) {
-					drm_handle_vblank(rdev->ddev, 2);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[2]))
-					radeon_crtc_handle_vblank(rdev, 2);
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D3 vblank\n");
-
-				break;
-			case 1: /* D3 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: D3 vline - IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D3 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 4: /* D4 vblank/vline */
-			switch (src_data) {
-			case 0: /* D4 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: D4 vblank - IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[3]) {
-					drm_handle_vblank(rdev->ddev, 3);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[3]))
-					radeon_crtc_handle_vblank(rdev, 3);
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D4 vblank\n");
-
-				break;
-			case 1: /* D4 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: D4 vline - IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D4 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 5: /* D5 vblank/vline */
-			switch (src_data) {
-			case 0: /* D5 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: D5 vblank - IH event w/o asserted irq bit?\n");
+		case 6: /* D6 vblank/vline */
+			crtc_idx = src_id - 1;
+
+			if (src_data == 0) { /* vblank */
+				mask = LB_D1_VBLANK_INTERRUPT;
+				event_name = "vblank";
 
-				if (rdev->irq.crtc_vblank_int[4]) {
-					drm_handle_vblank(rdev->ddev, 4);
+				if (rdev->irq.crtc_vblank_int[crtc_idx]) {
+					drm_handle_vblank(rdev->ddev, crtc_idx);
 					rdev->pm.vblank_sync = true;
 					wake_up(&rdev->irq.vblank_queue);
 				}
-				if (atomic_read(&rdev->irq.pflip[4]))
-					radeon_crtc_handle_vblank(rdev, 4);
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D5 vblank\n");
-
-				break;
-			case 1: /* D5 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: D5 vline - IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D5 vline\n");
+				if (atomic_read(&rdev->irq.pflip[crtc_idx])) {
+					radeon_crtc_handle_vblank(rdev,
+								  crtc_idx);
+				}
 
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
+			} else if (src_data == 1) { /* vline */
+				mask = LB_D1_VLINE_INTERRUPT;
+				event_name = "vline";
+			} else {
+				DRM_DEBUG("Unhandled interrupt: %d %d\n",
+					  src_id, src_data);
 				break;
 			}
-			break;
-		case 6: /* D6 vblank/vline */
-			switch (src_data) {
-			case 0: /* D6 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: D6 vblank - IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[5]) {
-					drm_handle_vblank(rdev->ddev, 5);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[5]))
-					radeon_crtc_handle_vblank(rdev, 5);
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D6 vblank\n");
 
-				break;
-			case 1: /* D6 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: D6 vline - IH event w/o asserted irq bit?\n");
+			if (!(disp_int[crtc_idx] & mask)) {
+				DRM_DEBUG("IH: D%d %s - IH event w/o asserted irq bit?\n",
+					  crtc_idx + 1, event_name);
+			}
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D6 vline\n");
+			disp_int[crtc_idx] &= ~mask;
+			DRM_DEBUG("IH: D%d %s\n", crtc_idx + 1, event_name);
 
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
 			break;
 		case 8: /* D1 page flip */
 		case 10: /* D2 page flip */
@@ -5267,107 +4905,30 @@ restart_ih:
 				radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
 			break;
 		case 42: /* HPD hotplug */
-			switch (src_data) {
-			case 0:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD1\n");
-				break;
-			case 1:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT;
+			if (src_data <= 5) {
+				hpd_idx = src_data;
+				mask = DC_HPD1_INTERRUPT;
 				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD2\n");
-				break;
-			case 2:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+				event_name = "HPD";
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD3\n");
-				break;
-			case 3:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD4\n");
-				break;
-			case 4:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD5\n");
-				break;
-			case 5:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD6\n");
-				break;
-			case 6:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT;
+			} else if (src_data <= 11) {
+				hpd_idx = src_data - 6;
+				mask = DC_HPD1_RX_INTERRUPT;
 				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 1\n");
-				break;
-			case 7:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 2\n");
-				break;
-			case 8:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+				event_name = "HPD_RX";
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 3\n");
+			} else {
+				DRM_DEBUG("Unhandled interrupt: %d %d\n",
+					  src_id, src_data);
 				break;
-			case 9:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+			}
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 4\n");
-				break;
-			case 10:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+			if (!(disp_int[hpd_idx] & mask))
+				DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 5\n");
-				break;
-			case 11:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+			disp_int[hpd_idx] &= ~mask;
+			DRM_DEBUG("IH: %s%d\n", event_name, hpd_idx + 1);
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 6\n");
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
 			break;
 		case 44: /* hdmi */
 			switch (src_data) {
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -771,12 +771,7 @@ struct r600_irq_stat_regs {
 };
 
 struct evergreen_irq_stat_regs {
-	u32 disp_int;
-	u32 disp_int_cont;
-	u32 disp_int_cont2;
-	u32 disp_int_cont3;
-	u32 disp_int_cont4;
-	u32 disp_int_cont5;
+	u32 disp_int[6];
 	u32 d1grph_int;
 	u32 d2grph_int;
 	u32 d3grph_int;
@@ -2980,6 +2975,12 @@ int r600_cs_common_vline_parse(struct ra
 			       uint32_t *vline_start_end,
 			       uint32_t *vline_status);
 
+/* interrupt control register helpers */
+void radeon_irq_kms_set_irq_n_enabled(struct radeon_device *rdev,
+				      u32 reg, u32 mask,
+				      bool enable, const char *name,
+				      unsigned n);
+
 #include "radeon_object.h"
 
 #endif
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -538,3 +538,38 @@ void radeon_irq_kms_disable_hpd(struct r
 	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 }
 
+/**
+ * radeon_irq_kms_update_int_n - helper for updating interrupt enable registers
+ *
+ * @rdev: radeon device pointer
+ * @reg: the register to write to enable/disable interrupts
+ * @mask: the mask that enables the interrupts
+ * @enable: whether to enable or disable the interrupt register
+ * @name: the name of the interrupt register to print to the kernel log
+ * @num: the number of the interrupt register to print to the kernel log
+ *
+ * Helper for updating the enable state of interrupt registers. Checks whether
+ * or not the interrupt matches the enable state we want. If it doesn't, then
+ * we update it and print a debugging message to the kernel log indicating the
+ * new state of the interrupt register.
+ *
+ * Used for updating sequences of interrupts registers like HPD1, HPD2, etc.
+ */
+void radeon_irq_kms_set_irq_n_enabled(struct radeon_device *rdev,
+				      u32 reg, u32 mask,
+				      bool enable, const char *name, unsigned n)
+{
+	u32 tmp = RREG32(reg);
+
+	/* Interrupt state didn't change */
+	if (!!(tmp & mask) == enable)
+		return;
+
+	if (enable) {
+		DRM_DEBUG("%s%d interrupts enabled\n", name, n);
+		WREG32(reg, tmp |= mask);
+	} else {
+		DRM_DEBUG("%s%d interrupts disabled\n", name, n);
+		WREG32(reg, tmp & ~mask);
+	}
+}
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -139,6 +139,30 @@ static void si_fini_pg(struct radeon_dev
 static void si_fini_cg(struct radeon_device *rdev);
 static void si_rlc_stop(struct radeon_device *rdev);
 
+static const u32 crtc_offsets[] =
+{
+	EVERGREEN_CRTC0_REGISTER_OFFSET,
+	EVERGREEN_CRTC1_REGISTER_OFFSET,
+	EVERGREEN_CRTC2_REGISTER_OFFSET,
+	EVERGREEN_CRTC3_REGISTER_OFFSET,
+	EVERGREEN_CRTC4_REGISTER_OFFSET,
+	EVERGREEN_CRTC5_REGISTER_OFFSET
+};
+
+static const u32 si_disp_int_status[] =
+{
+	DISP_INTERRUPT_STATUS,
+	DISP_INTERRUPT_STATUS_CONTINUE,
+	DISP_INTERRUPT_STATUS_CONTINUE2,
+	DISP_INTERRUPT_STATUS_CONTINUE3,
+	DISP_INTERRUPT_STATUS_CONTINUE4,
+	DISP_INTERRUPT_STATUS_CONTINUE5
+};
+
+#define DC_HPDx_CONTROL(x)        (DC_HPD1_CONTROL     + (x * 0xc))
+#define DC_HPDx_INT_CONTROL(x)    (DC_HPD1_INT_CONTROL + (x * 0xc))
+#define DC_HPDx_INT_STATUS_REG(x) (DC_HPD1_INT_STATUS  + (x * 0xc))
+
 static const u32 verde_rlc_save_restore_register_list[] =
 {
 	(0x8000 << 16) | (0x98f4 >> 2),
@@ -5919,6 +5943,7 @@ static void si_disable_interrupts(struct
 
 static void si_disable_interrupt_state(struct radeon_device *rdev)
 {
+	int i;
 	u32 tmp;
 
 	tmp = RREG32(CP_INT_CNTL_RING0) &
@@ -5932,18 +5957,8 @@ static void si_disable_interrupt_state(s
 	WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, tmp);
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(SRBM_INT_CNTL, 0);
-	if (rdev->num_crtc >= 2) {
-		WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
-		WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
-	}
+	for (i = 0; i < rdev->num_crtc; i++)
+		WREG32(INT_MASK + crtc_offsets[i], 0);
 
 	if (rdev->num_crtc >= 2) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
@@ -5961,18 +5976,9 @@ static void si_disable_interrupt_state(s
 	if (!ASIC_IS_NODCE(rdev)) {
 		WREG32(DAC_AUTODETECT_INT_CONTROL, 0);
 
-		tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD1_INT_CONTROL, tmp);
-		tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD2_INT_CONTROL, tmp);
-		tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD3_INT_CONTROL, tmp);
-		tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD4_INT_CONTROL, tmp);
-		tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD5_INT_CONTROL, tmp);
-		tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD6_INT_CONTROL, tmp);
+		for (i = 0; i < 6; i++)
+			WREG32_AND(DC_HPDx_INT_CONTROL(i),
+				   DC_HPDx_INT_POLARITY);
 	}
 }
 
@@ -6047,12 +6053,12 @@ static int si_irq_init(struct radeon_dev
 	return ret;
 }
 
+/* The order we write back each register here is important */
 int si_irq_set(struct radeon_device *rdev)
 {
+	int i;
 	u32 cp_int_cntl;
 	u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;
-	u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
-	u32 hpd1 = 0, hpd2 = 0, hpd3 = 0, hpd4 = 0, hpd5 = 0, hpd6 = 0;
 	u32 grbm_int_cntl = 0;
 	u32 dma_cntl, dma_cntl1;
 	u32 thermal_int = 0;
@@ -6072,15 +6078,6 @@ int si_irq_set(struct radeon_device *rde
 	cp_int_cntl = RREG32(CP_INT_CNTL_RING0) &
 		(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
 
-	if (!ASIC_IS_NODCE(rdev)) {
-		hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-		hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-		hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-		hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-		hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-		hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-	}
-
 	dma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
 	dma_cntl1 = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET) & ~TRAP_ENABLE;
 
@@ -6109,60 +6106,6 @@ int si_irq_set(struct radeon_device *rde
 		DRM_DEBUG("si_irq_set: sw int dma1\n");
 		dma_cntl1 |= TRAP_ENABLE;
 	}
-	if (rdev->irq.crtc_vblank_int[0] ||
-	    atomic_read(&rdev->irq.pflip[0])) {
-		DRM_DEBUG("si_irq_set: vblank 0\n");
-		crtc1 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[1] ||
-	    atomic_read(&rdev->irq.pflip[1])) {
-		DRM_DEBUG("si_irq_set: vblank 1\n");
-		crtc2 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[2] ||
-	    atomic_read(&rdev->irq.pflip[2])) {
-		DRM_DEBUG("si_irq_set: vblank 2\n");
-		crtc3 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[3] ||
-	    atomic_read(&rdev->irq.pflip[3])) {
-		DRM_DEBUG("si_irq_set: vblank 3\n");
-		crtc4 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[4] ||
-	    atomic_read(&rdev->irq.pflip[4])) {
-		DRM_DEBUG("si_irq_set: vblank 4\n");
-		crtc5 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.crtc_vblank_int[5] ||
-	    atomic_read(&rdev->irq.pflip[5])) {
-		DRM_DEBUG("si_irq_set: vblank 5\n");
-		crtc6 |= VBLANK_INT_MASK;
-	}
-	if (rdev->irq.hpd[0]) {
-		DRM_DEBUG("si_irq_set: hpd 1\n");
-		hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[1]) {
-		DRM_DEBUG("si_irq_set: hpd 2\n");
-		hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[2]) {
-		DRM_DEBUG("si_irq_set: hpd 3\n");
-		hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[3]) {
-		DRM_DEBUG("si_irq_set: hpd 4\n");
-		hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[4]) {
-		DRM_DEBUG("si_irq_set: hpd 5\n");
-		hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
-	if (rdev->irq.hpd[5]) {
-		DRM_DEBUG("si_irq_set: hpd 6\n");
-		hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
-	}
 
 	WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
 	WREG32(CP_INT_CNTL_RING1, cp_int_cntl1);
@@ -6178,17 +6121,11 @@ int si_irq_set(struct radeon_device *rde
 		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
 	}
 
-	if (rdev->num_crtc >= 2) {
-		WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1);
-		WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3);
-		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5);
-		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
+	for (i = 0; i < rdev->num_crtc; i++) {
+		radeon_irq_kms_set_irq_n_enabled(
+		    rdev, INT_MASK + crtc_offsets[i], VBLANK_INT_MASK,
+		    rdev->irq.crtc_vblank_int[i] ||
+		    atomic_read(&rdev->irq.pflip[i]), "vblank", i);
 	}
 
 	if (rdev->num_crtc >= 2) {
@@ -6211,12 +6148,12 @@ int si_irq_set(struct radeon_device *rde
 	}
 
 	if (!ASIC_IS_NODCE(rdev)) {
-		WREG32(DC_HPD1_INT_CONTROL, hpd1);
-		WREG32(DC_HPD2_INT_CONTROL, hpd2);
-		WREG32(DC_HPD3_INT_CONTROL, hpd3);
-		WREG32(DC_HPD4_INT_CONTROL, hpd4);
-		WREG32(DC_HPD5_INT_CONTROL, hpd5);
-		WREG32(DC_HPD6_INT_CONTROL, hpd6);
+		for (i = 0; i < 6; i++) {
+			radeon_irq_kms_set_irq_n_enabled(
+			    rdev, DC_HPDx_INT_CONTROL(i),
+			    DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN,
+			    rdev->irq.hpd[i], "HPD", i);
+		}
 	}
 
 	WREG32(CG_THERMAL_INT, thermal_int);
@@ -6227,19 +6164,18 @@ int si_irq_set(struct radeon_device *rde
 	return 0;
 }
 
+/* The order we write back each register here is important */
 static inline void si_irq_ack(struct radeon_device *rdev)
 {
-	u32 tmp;
+	int i;
+	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
 
 	if (ASIC_IS_NODCE(rdev))
 		return;
 
-	rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS);
-	rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
-	rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2);
-	rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3);
-	rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4);
-	rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
+	for (i = 0; i < 6; i++)
+		disp_int[i] = RREG32(si_disp_int_status[i]);
+
 	rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
 	rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
 	if (rdev->num_crtc >= 4) {
@@ -6255,28 +6191,28 @@ static inline void si_irq_ack(struct rad
 		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
 		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
-		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
-	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
-		WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK);
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)
-		WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK);
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)
-		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
+	if (disp_int[0] & LB_D1_VBLANK_INTERRUPT)
+		WREG32(VBLANK_STATUS + crtc_offsets[0], VBLANK_ACK);
+	if (disp_int[0] & LB_D1_VLINE_INTERRUPT)
+		WREG32(VLINE_STATUS + crtc_offsets[0], VLINE_ACK);
+	if (disp_int[1] & LB_D1_VBLANK_INTERRUPT)
+		WREG32(VBLANK_STATUS + crtc_offsets[1], VBLANK_ACK);
+	if (disp_int[1] & LB_D1_VLINE_INTERRUPT)
+		WREG32(VLINE_STATUS + crtc_offsets[1], VLINE_ACK);
 
 	if (rdev->num_crtc >= 4) {
 		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK);
+		if (disp_int[2] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[2], VBLANK_ACK);
+		if (disp_int[2] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[2], VLINE_ACK);
+		if (disp_int[3] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[3], VBLANK_ACK);
+		if (disp_int[3] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[3], VLINE_ACK);
 	}
 
 	if (rdev->num_crtc >= 6) {
@@ -6284,76 +6220,24 @@ static inline void si_irq_ack(struct rad
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
 		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
 			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)
-			WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK);
-		if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)
-			WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK);
-	}
-
-	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) {
-		tmp = RREG32(DC_HPD1_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD1_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) {
-		tmp = RREG32(DC_HPD2_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD2_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) {
-		tmp = RREG32(DC_HPD3_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD3_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) {
-		tmp = RREG32(DC_HPD4_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD4_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD5_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-		tmp = RREG32(DC_HPD6_INT_CONTROL);
-		tmp |= DC_HPDx_INT_ACK;
-		WREG32(DC_HPD6_INT_CONTROL, tmp);
-	}
-
-	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD1_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD1_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD2_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD2_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD3_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD3_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD4_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD4_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD5_INT_CONTROL, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-		tmp = RREG32(DC_HPD6_INT_CONTROL);
-		tmp |= DC_HPDx_RX_INT_ACK;
-		WREG32(DC_HPD6_INT_CONTROL, tmp);
+		if (disp_int[4] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[4], VBLANK_ACK);
+		if (disp_int[4] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[4], VLINE_ACK);
+		if (disp_int[5] & LB_D1_VBLANK_INTERRUPT)
+			WREG32(VBLANK_STATUS + crtc_offsets[5], VBLANK_ACK);
+		if (disp_int[5] & LB_D1_VLINE_INTERRUPT)
+			WREG32(VLINE_STATUS + crtc_offsets[5], VLINE_ACK);
+	}
+
+	for (i = 0; i < 6; i++) {
+		if (disp_int[i] & DC_HPD1_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_ACK);
+	}
+
+	for (i = 0; i < 6; i++) {
+		if (disp_int[i] & DC_HPD1_RX_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
 	}
 }
 
@@ -6415,6 +6299,9 @@ static inline u32 si_get_ih_wptr(struct
  */
 int si_irq_process(struct radeon_device *rdev)
 {
+	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
+	u32 crtc_idx, hpd_idx;
+	u32 mask;
 	u32 wptr;
 	u32 rptr;
 	u32 src_id, src_data, ring_id;
@@ -6423,6 +6310,7 @@ int si_irq_process(struct radeon_device
 	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
+	const char *event_name;
 
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
@@ -6452,184 +6340,44 @@ restart_ih:
 
 		switch (src_id) {
 		case 1: /* D1 vblank/vline */
-			switch (src_data) {
-			case 0: /* D1 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[0]) {
-					drm_handle_vblank(rdev->ddev, 0);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[0]))
-					radeon_crtc_handle_vblank(rdev, 0);
-				rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D1 vblank\n");
-
-				break;
-			case 1: /* D1 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D1 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 2: /* D2 vblank/vline */
-			switch (src_data) {
-			case 0: /* D2 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[1]) {
-					drm_handle_vblank(rdev->ddev, 1);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[1]))
-					radeon_crtc_handle_vblank(rdev, 1);
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D2 vblank\n");
-
-				break;
-			case 1: /* D2 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D2 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 3: /* D3 vblank/vline */
-			switch (src_data) {
-			case 0: /* D3 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[2]) {
-					drm_handle_vblank(rdev->ddev, 2);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[2]))
-					radeon_crtc_handle_vblank(rdev, 2);
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D3 vblank\n");
-
-				break;
-			case 1: /* D3 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D3 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 4: /* D4 vblank/vline */
-			switch (src_data) {
-			case 0: /* D4 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[3]) {
-					drm_handle_vblank(rdev->ddev, 3);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[3]))
-					radeon_crtc_handle_vblank(rdev, 3);
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D4 vblank\n");
-
-				break;
-			case 1: /* D4 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D4 vline\n");
-
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
-			break;
 		case 5: /* D5 vblank/vline */
-			switch (src_data) {
-			case 0: /* D5 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+		case 6: /* D6 vblank/vline */
+			crtc_idx = src_id - 1;
+
+			if (src_data == 0) { /* vblank */
+				mask = LB_D1_VBLANK_INTERRUPT;
+				event_name = "vblank";
 
-				if (rdev->irq.crtc_vblank_int[4]) {
-					drm_handle_vblank(rdev->ddev, 4);
+				if (rdev->irq.crtc_vblank_int[crtc_idx]) {
+					drm_handle_vblank(rdev->ddev, crtc_idx);
 					rdev->pm.vblank_sync = true;
 					wake_up(&rdev->irq.vblank_queue);
 				}
-				if (atomic_read(&rdev->irq.pflip[4]))
-					radeon_crtc_handle_vblank(rdev, 4);
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D5 vblank\n");
-
-				break;
-			case 1: /* D5 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D5 vline\n");
+				if (atomic_read(&rdev->irq.pflip[crtc_idx])) {
+					radeon_crtc_handle_vblank(rdev,
+								  crtc_idx);
+				}
 
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
+			} else if (src_data == 1) { /* vline */
+				mask = LB_D1_VLINE_INTERRUPT;
+				event_name = "vline";
+			} else {
+				DRM_DEBUG("Unhandled interrupt: %d %d\n",
+					  src_id, src_data);
 				break;
 			}
-			break;
-		case 6: /* D6 vblank/vline */
-			switch (src_data) {
-			case 0: /* D6 vblank */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				if (rdev->irq.crtc_vblank_int[5]) {
-					drm_handle_vblank(rdev->ddev, 5);
-					rdev->pm.vblank_sync = true;
-					wake_up(&rdev->irq.vblank_queue);
-				}
-				if (atomic_read(&rdev->irq.pflip[5]))
-					radeon_crtc_handle_vblank(rdev, 5);
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
-				DRM_DEBUG("IH: D6 vblank\n");
 
-				break;
-			case 1: /* D6 vline */
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+			if (!(disp_int[crtc_idx] & mask)) {
+				DRM_DEBUG("IH: D%d %s - IH event w/o asserted irq bit?\n",
+					  crtc_idx + 1, event_name);
+			}
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT;
-				DRM_DEBUG("IH: D6 vline\n");
+			disp_int[crtc_idx] &= ~mask;
+			DRM_DEBUG("IH: D%d %s\n", crtc_idx + 1, event_name);
 
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
 			break;
 		case 8: /* D1 page flip */
 		case 10: /* D2 page flip */
@@ -6642,119 +6390,29 @@ restart_ih:
 				radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
 			break;
 		case 42: /* HPD hotplug */
-			switch (src_data) {
-			case 0:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD1\n");
-
-				break;
-			case 1:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD2\n");
-
-				break;
-			case 2:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT;
+			if (src_data <= 5) {
+				hpd_idx = src_data;
+				mask = DC_HPD1_INTERRUPT;
 				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD3\n");
+				event_name = "HPD";
 
-				break;
-			case 3:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD4\n");
-
-				break;
-			case 4:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD5\n");
-
-				break;
-			case 5:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT;
-				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD6\n");
-
-				break;
-			case 6:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 1\n");
-
-				break;
-			case 7:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
+			} else if (src_data <= 11) {
+				hpd_idx = src_data - 6;
+				mask = DC_HPD1_RX_INTERRUPT;
 				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 2\n");
-
-				break;
-			case 8:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 3\n");
-
-				break;
-			case 9:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 4\n");
-
-				break;
-			case 10:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 5\n");
+				event_name = "HPD_RX";
 
+			} else {
+				DRM_DEBUG("Unhandled interrupt: %d %d\n",
+					  src_id, src_data);
 				break;
-			case 11:
-				if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+			}
 
-				rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
-				queue_dp = true;
-				DRM_DEBUG("IH: HPD_RX 6\n");
+			if (!(disp_int[hpd_idx] & mask))
+				DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
 
-				break;
-			default:
-				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
-				break;
-			}
+			disp_int[hpd_idx] &= ~mask;
+			DRM_DEBUG("IH: %s%d\n", event_name, hpd_idx + 1);
 			break;
 		case 96:
 			DRM_ERROR("SRBM_READ_ERROR: 0x%x\n", RREG32(SRBM_READ_ERROR));