linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Cleanup evergreen/si IRQ handling code
@ 2017-05-16 21:11 Lyude
  2017-05-16 21:11 ` [PATCH 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Lyude @ 2017-05-16 21:11 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

This is the first part of me going through and cleaning up the IRQ handling
code for radeon, since after taking a look at it the other day while trying to
debug something I realized basically all of the code was copy pasted
everywhere, and quite difficult to actually read through.

Will come up with something for r600 and cik once I've got the chipsets on hand
to test with.

Lyude (3):
  drm/radeon: Cleanup display interrupt handling for evergreen, si
  drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
  drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si

 drivers/gpu/drm/radeon/evergreen.c      | 915 +++++---------------------------
 drivers/gpu/drm/radeon/evergreend.h     |  74 +--
 drivers/gpu/drm/radeon/radeon.h         |  27 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c |  35 ++
 drivers/gpu/drm/radeon/si.c             | 627 ++++------------------
 drivers/gpu/drm/radeon/sid.h            |  72 +--
 6 files changed, 328 insertions(+), 1422 deletions(-)

-- 
2.9.4

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si
  2017-05-16 21:11 [PATCH 0/3] Cleanup evergreen/si IRQ handling code Lyude
@ 2017-05-16 21:11 ` Lyude
  2017-05-16 21:11 ` [PATCH 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen Lyude
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Lyude @ 2017-05-16 21:11 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

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.

There is one change here that doesn't look very important (testing
hasn't shown that it changes anyything afaict), but should be noted in
case this patch breaks something. The way the code originally handled
enabling or acking IRQs went like this:

 - Check enable/interrupt status of all IRQs
 - Write back any acknowledgements, enablements, or disablements to
   IRQs, all at the same time

But now with the helpers we've implemented, it goes a little more like
this
 - For each IRQ:
   - Check enable/interrupt status
   - Write back ack/new status

Signed-off-by: Lyude <lyude@redhat.com>
---
 drivers/gpu/drm/radeon/evergreen.c      | 699 ++++++--------------------------
 drivers/gpu/drm/radeon/evergreend.h     |  74 +---
 drivers/gpu/drm/radeon/radeon.h         |  13 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c |  35 ++
 drivers/gpu/drm/radeon/si.c             | 565 +++++---------------------
 drivers/gpu/drm/radeon/sid.h            |  72 +---
 6 files changed, 290 insertions(+), 1168 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 0bf1035..35baf0a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1714,38 +1714,10 @@ void evergreen_pm_finish(struct radeon_device *rdev)
  */
 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(hpd)) & DC_HPDx_SENSE);
 }
 
 /**
@@ -1759,61 +1731,15 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
 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 +1759,8 @@ void evergreen_hpd_init(struct radeon_device *rdev)
 		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 +1771,14 @@ void evergreen_hpd_init(struct radeon_device *rdev)
 			 */
 			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 +1798,14 @@ void evergreen_hpd_fini(struct radeon_device *rdev)
 	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);
 }
@@ -4543,6 +4436,7 @@ u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc)
 
 void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 {
+	int i;
 	u32 tmp;
 
 	if (rdev->family >= CHIP_CAYMAN) {
@@ -4558,16 +4452,8 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 	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);
@@ -4585,27 +4471,15 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 		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 < EVERGREEN_MAX_DISP_REGISTERS; i++)
+		WREG32_AND(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_POLARITY);
 }
 
 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;
@@ -4623,12 +4497,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		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);
@@ -4685,60 +4553,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		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;
@@ -4778,17 +4592,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 
 	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);
-	}
-
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
 	       GRPH_PFLIP_INT_MASK);
 	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
@@ -4806,12 +4609,21 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		       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 < EVERGREEN_MAX_DISP_REGISTERS; 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 (i < rdev->num_crtc) {
+			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->family == CHIP_ARUBA)
 		WREG32(TN_CG_THERMAL_INT_CTRL, thermal_int);
 	else
@@ -4832,14 +4644,28 @@ int evergreen_irq_set(struct radeon_device *rdev)
 
 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 < EVERGREEN_MAX_DISP_REGISTERS; i++) {
+		disp_int[i] = RREG32(DISP_INTERRUPT_STATUS(i));
+
+		if (disp_int[i] & DC_HPDx_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_ACK);
+		if (disp_int[i] & DC_HPDx_RX_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
+
+		if (i < rdev->num_crtc) {
+			if (disp_int[i] & LB_Dx_VBLANK_INTERRUPT)
+				WREG32(VBLANK_STATUS + crtc_offsets[i],
+				       VBLANK_ACK);
+			if (disp_int[i] & LB_Dx_VLINE_INTERRUPT)
+				WREG32(VLINE_STATUS + crtc_offsets[i],
+				       VLINE_ACK);
+		}
+	}
+
 	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) {
@@ -4862,28 +4688,12 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		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 (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 (rdev->num_crtc >= 6) {
@@ -4891,76 +4701,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 			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 (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
@@ -5037,6 +4777,9 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
 
 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;
@@ -5046,6 +4789,7 @@ int evergreen_irq_process(struct radeon_device *rdev)
 	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
+	const char *event_name;
 
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
@@ -5074,184 +4818,44 @@ int evergreen_irq_process(struct radeon_device *rdev)
 
 		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 (rdev->irq.crtc_vblank_int[4]) {
-					drm_handle_vblank(rdev->ddev, 4);
+			if (src_data == 0) { /* vblank */
+				mask = LB_Dx_VBLANK_INTERRUPT;
+				event_name = "vblank";
+
+				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_Dx_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 */
@@ -5264,107 +4868,30 @@ int evergreen_irq_process(struct radeon_device *rdev)
 				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;
-				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;
+			if (src_data <= 5) {
+				hpd_idx = src_data;
+				mask = DC_HPDx_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");
+				event_name = "HPD";
 
-				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_HPDx_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) {
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index f3d88ca..56d1e7e 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -36,6 +36,7 @@
 #define EVERGREEN_MAX_PIPES             8
 #define EVERGREEN_MAX_PIPES_MASK        0xFF
 #define EVERGREEN_MAX_LDS_NUM           0xFFFF
+#define EVERGREEN_MAX_DISP_REGISTERS    6
 
 #define CYPRESS_GB_ADDR_CONFIG_GOLDEN        0x02011003
 #define BARTS_GB_ADDR_CONFIG_GOLDEN          0x02011003
@@ -1285,85 +1286,52 @@
 #       define VBLANK_INT_MASK                          (1 << 0)
 #       define VLINE_INT_MASK                           (1 << 4)
 
-#define DISP_INTERRUPT_STATUS                           0x60f4
-#       define LB_D1_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D1_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD1_INTERRUPT                        (1 << 17)
-#       define DC_HPD1_RX_INTERRUPT                     (1 << 18)
+/* 0x60f4, 0x60f8, 0x60fc, 0x6100, 0x614c, 0x6150 */
+#define DISP_INTERRUPT_STATUS(i) \
+	((i < 4) ? 0x60f4 + (0x4 * i) : 0x614c + (0x4 * (i - 4)))
+#       define LB_Dx_VLINE_INTERRUPT                    (1 << 2)
+#       define LB_Dx_VBLANK_INTERRUPT                   (1 << 3)
+#       define DC_HPDx_INTERRUPT                        (1 << 17)
+#       define DC_HPDx_RX_INTERRUPT                     (1 << 18)
+/* First reg only */
 #       define DACA_AUTODETECT_INTERRUPT                (1 << 22)
 #       define DACB_AUTODETECT_INTERRUPT                (1 << 23)
 #       define DC_I2C_SW_DONE_INTERRUPT                 (1 << 24)
 #       define DC_I2C_HW_DONE_INTERRUPT                 (1 << 25)
-#define DISP_INTERRUPT_STATUS_CONTINUE                  0x60f8
-#       define LB_D2_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D2_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD2_INTERRUPT                        (1 << 17)
-#       define DC_HPD2_RX_INTERRUPT                     (1 << 18)
+/* Second reg only */
 #       define DISP_TIMER_INTERRUPT                     (1 << 24)
-#define DISP_INTERRUPT_STATUS_CONTINUE2                 0x60fc
-#       define LB_D3_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D3_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD3_INTERRUPT                        (1 << 17)
-#       define DC_HPD3_RX_INTERRUPT                     (1 << 18)
-#define DISP_INTERRUPT_STATUS_CONTINUE3                 0x6100
-#       define LB_D4_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D4_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD4_INTERRUPT                        (1 << 17)
-#       define DC_HPD4_RX_INTERRUPT                     (1 << 18)
-#define DISP_INTERRUPT_STATUS_CONTINUE4                 0x614c
-#       define LB_D5_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D5_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD5_INTERRUPT                        (1 << 17)
-#       define DC_HPD5_RX_INTERRUPT                     (1 << 18)
-#define DISP_INTERRUPT_STATUS_CONTINUE5                 0x6150
-#       define LB_D6_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D6_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD6_INTERRUPT                        (1 << 17)
-#       define DC_HPD6_RX_INTERRUPT                     (1 << 18)
 
 /* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */
 #define GRPH_INT_STATUS                                 0x6858
 #       define GRPH_PFLIP_INT_OCCURRED                  (1 << 0)
 #       define GRPH_PFLIP_INT_CLEAR                     (1 << 8)
 /* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */
-#define	GRPH_INT_CONTROL			        0x685c
+#define	GRPH_INT_CONTROL                                0x685c
 #       define GRPH_PFLIP_INT_MASK                      (1 << 0)
 #       define GRPH_PFLIP_INT_TYPE                      (1 << 8)
 
 #define	DACA_AUTODETECT_INT_CONTROL			0x66c8
 #define	DACB_AUTODETECT_INT_CONTROL			0x67c8
 
-#define DC_HPD1_INT_STATUS                              0x601c
-#define DC_HPD2_INT_STATUS                              0x6028
-#define DC_HPD3_INT_STATUS                              0x6034
-#define DC_HPD4_INT_STATUS                              0x6040
-#define DC_HPD5_INT_STATUS                              0x604c
-#define DC_HPD6_INT_STATUS                              0x6058
-#       define DC_HPDx_INT_STATUS                       (1 << 0)
+/* 0x601c, 0x6028, 0x6034, 0x6040, 0x604c, 0x6058 */
+#define DC_HPDx_INT_STATUS(x)                           (0x601c + (0xc * x))
+#       define DC_HPDx_INT_STATUS_MASK                  (1 << 0)
 #       define DC_HPDx_SENSE                            (1 << 1)
 #       define DC_HPDx_RX_INT_STATUS                    (1 << 8)
 
-#define DC_HPD1_INT_CONTROL                             0x6020
-#define DC_HPD2_INT_CONTROL                             0x602c
-#define DC_HPD3_INT_CONTROL                             0x6038
-#define DC_HPD4_INT_CONTROL                             0x6044
-#define DC_HPD5_INT_CONTROL                             0x6050
-#define DC_HPD6_INT_CONTROL                             0x605c
+/* 0x6020, 0x602c, 0x6038, 0x6044, 0x6050, 0x605c */
+#define DC_HPDx_INT_CONTROL(x)                          (0x6020 + (0xc * x))
 #       define DC_HPDx_INT_ACK                          (1 << 0)
 #       define DC_HPDx_INT_POLARITY                     (1 << 8)
 #       define DC_HPDx_INT_EN                           (1 << 16)
 #       define DC_HPDx_RX_INT_ACK                       (1 << 20)
 #       define DC_HPDx_RX_INT_EN                        (1 << 24)
 
-#define DC_HPD1_CONTROL                                   0x6024
-#define DC_HPD2_CONTROL                                   0x6030
-#define DC_HPD3_CONTROL                                   0x603c
-#define DC_HPD4_CONTROL                                   0x6048
-#define DC_HPD5_CONTROL                                   0x6054
-#define DC_HPD6_CONTROL                                   0x6060
-#       define DC_HPDx_CONNECTION_TIMER(x)                ((x) << 0)
-#       define DC_HPDx_RX_INT_TIMER(x)                    ((x) << 16)
-#       define DC_HPDx_EN                                 (1 << 28)
+/* 0x6024, 0x6030, 0x603c, 0x6048, 0x6054, 0x6060 */
+#define DC_HPDx_CONTROL(x)                              (0x6024 + (0xc * x))
+#       define DC_HPDx_CONNECTION_TIMER(x)              ((x) << 0)
+#       define DC_HPDx_RX_INT_TIMER(x)                  ((x) << 16)
+#       define DC_HPDx_EN                               (1 << 28)
 
 /* DCE4/5/6 FMT blocks */
 #define FMT_DYNAMIC_EXP_CNTL                 0x6fb4
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c1c8e22..b6086ee 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -767,12 +767,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;
@@ -2976,6 +2971,12 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
 			       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
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 1b7528d..7aacb44 100644
--- 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 radeon_device *rdev, unsigned hpd_mask)
 	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);
+	}
+}
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 76d1888..bb745e1 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -139,6 +139,16 @@ static void si_fini_pg(struct radeon_device *rdev);
 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 verde_rlc_save_restore_register_list[] =
 {
 	(0x8000 << 16) | (0x98f4 >> 2),
@@ -5916,6 +5926,7 @@ static void si_disable_interrupts(struct radeon_device *rdev)
 
 static void si_disable_interrupt_state(struct radeon_device *rdev)
 {
+	int i;
 	u32 tmp;
 
 	tmp = RREG32(CP_INT_CNTL_RING0) &
@@ -5929,18 +5940,8 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 	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);
@@ -5958,18 +5959,9 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 	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 < SI_MAX_DISP_REGISTERS; i++)
+			WREG32_AND(DC_HPDx_INT_CONTROL(i),
+				   DC_HPDx_INT_POLARITY);
 	}
 }
 
@@ -6046,10 +6038,9 @@ static int si_irq_init(struct radeon_device *rdev)
 
 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;
@@ -6069,15 +6060,6 @@ int si_irq_set(struct radeon_device *rdev)
 	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;
 
@@ -6106,60 +6088,6 @@ int si_irq_set(struct radeon_device *rdev)
 		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);
@@ -6176,19 +6104,6 @@ int si_irq_set(struct radeon_device *rdev)
 	}
 
 	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);
-	}
-
-	if (rdev->num_crtc >= 2) {
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
 		       GRPH_PFLIP_INT_MASK);
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
@@ -6208,12 +6123,19 @@ int si_irq_set(struct radeon_device *rdev)
 	}
 
 	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 < SI_MAX_DISP_REGISTERS; 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);
+		}
+	}
+
+	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(CG_THERMAL_INT, thermal_int);
@@ -6226,17 +6148,12 @@ int si_irq_set(struct radeon_device *rdev)
 
 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);
 	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) {
@@ -6248,32 +6165,34 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 	}
 
+	for (i = 0; i < SI_MAX_DISP_REGISTERS; i++) {
+		disp_int[i] = RREG32(DISP_INTERRUPT_STATUS(i));
+
+		if (disp_int[i] & DC_HPDx_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_ACK);
+		if (disp_int[i] & DC_HPDx_RX_INTERRUPT)
+			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
+
+		if (i < rdev->num_crtc) {
+			if (disp_int[i] & LB_Dx_VBLANK_INTERRUPT)
+				WREG32(VBLANK_STATUS + crtc_offsets[i],
+				       VBLANK_ACK);
+			if (disp_int[i] & LB_Dx_VLINE_INTERRUPT)
+				WREG32(VLINE_STATUS + crtc_offsets[i],
+				       VLINE_ACK);
+		}
+	}
+
 	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
 		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 (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 (rdev->num_crtc >= 6) {
@@ -6281,76 +6200,6 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 			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);
 	}
 }
 
@@ -6412,6 +6261,9 @@ static inline u32 si_get_ih_wptr(struct radeon_device *rdev)
  */
 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;
@@ -6420,6 +6272,7 @@ int si_irq_process(struct radeon_device *rdev)
 	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
+	const char *event_name;
 
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
@@ -6449,184 +6302,44 @@ int si_irq_process(struct radeon_device *rdev)
 
 		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_Dx_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_Dx_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 */
@@ -6639,119 +6352,29 @@ int si_irq_process(struct radeon_device *rdev)
 				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_HPDx_INTERRUPT;
 				queue_hotplug = true;
-				DRM_DEBUG("IH: HPD2\n");
+				event_name = "HPD";
 
-				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;
-				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_HPDx_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");
-
-				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));
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 65a911d..0ef68f0 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -47,6 +47,7 @@
 #define SI_MAX_LDS_NUM           0xFFFF
 #define SI_MAX_TCC               16
 #define SI_MAX_TCC_MASK          0xFFFF
+#define SI_MAX_DISP_REGISTERS    6
 
 /* SMC IND accessor regs */
 #define SMC_IND_INDEX_0                              0x200
@@ -820,41 +821,20 @@
 #       define VBLANK_INT_MASK                          (1 << 0)
 #       define VLINE_INT_MASK                           (1 << 4)
 
-#define DISP_INTERRUPT_STATUS                           0x60f4
-#       define LB_D1_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D1_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD1_INTERRUPT                        (1 << 17)
-#       define DC_HPD1_RX_INTERRUPT                     (1 << 18)
+/* 0x60f4, 0x60f8, 0x60fc, 0x6100, 0x614c, 0x6150 */
+#define DISP_INTERRUPT_STATUS(i) \
+	((i < 4) ? 0x60f4 + (0x4 * i) : 0x614c + (0x4 * (i - 4)))
+#       define LB_Dx_VLINE_INTERRUPT                    (1 << 2)
+#       define LB_Dx_VBLANK_INTERRUPT                   (1 << 3)
+#       define DC_HPDx_INTERRUPT                        (1 << 17)
+#       define DC_HPDx_RX_INTERRUPT                     (1 << 18)
+/* First reg only */
 #       define DACA_AUTODETECT_INTERRUPT                (1 << 22)
 #       define DACB_AUTODETECT_INTERRUPT                (1 << 23)
 #       define DC_I2C_SW_DONE_INTERRUPT                 (1 << 24)
 #       define DC_I2C_HW_DONE_INTERRUPT                 (1 << 25)
-#define DISP_INTERRUPT_STATUS_CONTINUE                  0x60f8
-#       define LB_D2_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D2_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD2_INTERRUPT                        (1 << 17)
-#       define DC_HPD2_RX_INTERRUPT                     (1 << 18)
+/* Second reg only */
 #       define DISP_TIMER_INTERRUPT                     (1 << 24)
-#define DISP_INTERRUPT_STATUS_CONTINUE2                 0x60fc
-#       define LB_D3_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D3_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD3_INTERRUPT                        (1 << 17)
-#       define DC_HPD3_RX_INTERRUPT                     (1 << 18)
-#define DISP_INTERRUPT_STATUS_CONTINUE3                 0x6100
-#       define LB_D4_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D4_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD4_INTERRUPT                        (1 << 17)
-#       define DC_HPD4_RX_INTERRUPT                     (1 << 18)
-#define DISP_INTERRUPT_STATUS_CONTINUE4                 0x614c
-#       define LB_D5_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D5_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD5_INTERRUPT                        (1 << 17)
-#       define DC_HPD5_RX_INTERRUPT                     (1 << 18)
-#define DISP_INTERRUPT_STATUS_CONTINUE5                 0x6150
-#       define LB_D6_VLINE_INTERRUPT                    (1 << 2)
-#       define LB_D6_VBLANK_INTERRUPT                   (1 << 3)
-#       define DC_HPD6_INTERRUPT                        (1 << 17)
-#       define DC_HPD6_RX_INTERRUPT                     (1 << 18)
 
 /* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */
 #define GRPH_INT_STATUS                                 0x6858
@@ -867,37 +847,25 @@
 
 #define	DAC_AUTODETECT_INT_CONTROL			0x67c8
 
-#define DC_HPD1_INT_STATUS                              0x601c
-#define DC_HPD2_INT_STATUS                              0x6028
-#define DC_HPD3_INT_STATUS                              0x6034
-#define DC_HPD4_INT_STATUS                              0x6040
-#define DC_HPD5_INT_STATUS                              0x604c
-#define DC_HPD6_INT_STATUS                              0x6058
-#       define DC_HPDx_INT_STATUS                       (1 << 0)
+/* 0x601c, 0x6028, 0x6034, 0x6040, 0x604c, 0x6058 */
+#define DC_HPDx_INT_STATUS(x)                           (0x601c + (0xc * x))
+#       define DC_HPDx_INT_STATUS_MASK                  (1 << 0)
 #       define DC_HPDx_SENSE                            (1 << 1)
 #       define DC_HPDx_RX_INT_STATUS                    (1 << 8)
 
-#define DC_HPD1_INT_CONTROL                             0x6020
-#define DC_HPD2_INT_CONTROL                             0x602c
-#define DC_HPD3_INT_CONTROL                             0x6038
-#define DC_HPD4_INT_CONTROL                             0x6044
-#define DC_HPD5_INT_CONTROL                             0x6050
-#define DC_HPD6_INT_CONTROL                             0x605c
+/* 0x6020, 0x602c, 0x6038, 0x6044, 0x6050, 0x605c */
+#define DC_HPDx_INT_CONTROL(x)                          (0x6020 + (0xc * x))
 #       define DC_HPDx_INT_ACK                          (1 << 0)
 #       define DC_HPDx_INT_POLARITY                     (1 << 8)
 #       define DC_HPDx_INT_EN                           (1 << 16)
 #       define DC_HPDx_RX_INT_ACK                       (1 << 20)
 #       define DC_HPDx_RX_INT_EN                        (1 << 24)
 
-#define DC_HPD1_CONTROL                                   0x6024
-#define DC_HPD2_CONTROL                                   0x6030
-#define DC_HPD3_CONTROL                                   0x603c
-#define DC_HPD4_CONTROL                                   0x6048
-#define DC_HPD5_CONTROL                                   0x6054
-#define DC_HPD6_CONTROL                                   0x6060
-#       define DC_HPDx_CONNECTION_TIMER(x)                ((x) << 0)
-#       define DC_HPDx_RX_INT_TIMER(x)                    ((x) << 16)
-#       define DC_HPDx_EN                                 (1 << 28)
+/* 0x6024, 0x6030, 0x603c, 0x6048, 0x6054, 0x6060 */
+#define DC_HPDx_CONTROL(x)                              (0x6024 + (0xc * x))
+#       define DC_HPDx_CONNECTION_TIMER(x)              ((x) << 0)
+#       define DC_HPDx_RX_INT_TIMER(x)                  ((x) << 16)
+#       define DC_HPDx_EN                               (1 << 28)
 
 #define DPG_PIPE_STUTTER_CONTROL                          0x6cd4
 #       define STUTTER_ENABLE                             (1 << 0)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
  2017-05-16 21:11 [PATCH 0/3] Cleanup evergreen/si IRQ handling code Lyude
  2017-05-16 21:11 ` [PATCH 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
@ 2017-05-16 21:11 ` Lyude
  2017-05-16 21:12 ` [PATCH 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si Lyude
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Lyude @ 2017-05-16 21:11 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

Same as the previous patch, but now for handling HDMI audio interrupts.

Signed-off-by: Lyude <lyude@redhat.com>
---
 drivers/gpu/drm/radeon/evergreen.c | 152 ++++++-------------------------------
 drivers/gpu/drm/radeon/radeon.h    |   7 +-
 2 files changed, 24 insertions(+), 135 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 35baf0a..76a2f20 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4481,7 +4481,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
 	u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;
 	u32 grbm_int_cntl = 0;
-	u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0;
 	u32 dma_cntl, dma_cntl1 = 0;
 	u32 thermal_int = 0;
 
@@ -4504,13 +4503,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		thermal_int = RREG32(CG_THERMAL_INT) &
 			~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
 
-	afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt3 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt4 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt5 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt6 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-
 	dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE;
 
 	if (rdev->family >= CHIP_CAYMAN) {
@@ -4553,31 +4545,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
 	}
 
-	if (rdev->irq.afmt[0]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 0\n");
-		afmt1 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[1]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 1\n");
-		afmt2 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[2]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 2\n");
-		afmt3 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[3]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 3\n");
-		afmt4 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[4]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 4\n");
-		afmt5 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[5]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 5\n");
-		afmt6 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-
 	if (rdev->family >= CHIP_CAYMAN) {
 		cayman_cp_int_cntl_setup(rdev, 0, cp_int_cntl);
 		cayman_cp_int_cntl_setup(rdev, 1, cp_int_cntl1);
@@ -4616,6 +4583,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
 						 DC_HPDx_RX_INT_EN,
 						 rdev->irq.hpd[i], "HPD", i);
 
+		radeon_irq_kms_set_irq_n_enabled(rdev,
+						 AFMT_AUDIO_PACKET_CONTROL +
+						 crtc_offsets[i],
+						 AFMT_AZ_FORMAT_WTRIG_MASK,
+						 rdev->irq.afmt[i], "hdmi", i);
+
 		if (i < rdev->num_crtc) {
 			radeon_irq_kms_set_irq_n_enabled(
 			    rdev, INT_MASK + crtc_offsets[i], VBLANK_INT_MASK,
@@ -4629,13 +4602,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	else
 		WREG32(CG_THERMAL_INT, thermal_int);
 
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, afmt3);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, afmt4);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6);
-
 	/* posting read */
 	RREG32(SRBM_STATUS);
 
@@ -4646,15 +4612,19 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 {
 	int i;
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
-	u32 tmp;
+	u32 *afmt_status = rdev->irq.stat_regs.evergreen.afmt_status;
 
 	for (i = 0; i < EVERGREEN_MAX_DISP_REGISTERS; i++) {
 		disp_int[i] = RREG32(DISP_INTERRUPT_STATUS(i));
+		afmt_status[i] = RREG32(AFMT_STATUS + crtc_offsets[i]);
 
 		if (disp_int[i] & DC_HPDx_INTERRUPT)
 			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_ACK);
 		if (disp_int[i] & DC_HPDx_RX_INTERRUPT)
 			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
+		if (afmt_status[i] & AFMT_AZ_FORMAT_WTRIG)
+			WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + crtc_offsets[i],
+				  AFMT_AZ_FORMAT_WTRIG_ACK);
 
 		if (i < rdev->num_crtc) {
 			if (disp_int[i] & LB_Dx_VBLANK_INTERRUPT)
@@ -4677,12 +4647,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 	}
 
-	rdev->irq.stat_regs.evergreen.afmt_status1 = RREG32(AFMT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status2 = RREG32(AFMT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status3 = RREG32(AFMT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status4 = RREG32(AFMT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 
 	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
 		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
@@ -4702,37 +4666,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		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.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, tmp);
-	}
 }
 
 static void evergreen_irq_disable(struct radeon_device *rdev)
@@ -4778,7 +4711,8 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
 int evergreen_irq_process(struct radeon_device *rdev)
 {
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
-	u32 crtc_idx, hpd_idx;
+	u32 *afmt_status = rdev->irq.stat_regs.evergreen.afmt_status;
+	u32 crtc_idx, hpd_idx, afmt_idx;
 	u32 mask;
 	u32 wptr;
 	u32 rptr;
@@ -4894,59 +4828,19 @@ int evergreen_irq_process(struct radeon_device *rdev)
 
 			break;
 		case 44: /* hdmi */
-			switch (src_data) {
-			case 0:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI0\n");
-				break;
-			case 1:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI1\n");
-				break;
-			case 2:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI2\n");
-				break;
-			case 3:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI3\n");
-				break;
-			case 4:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI4\n");
-				break;
-			case 5:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+			afmt_idx = src_data;
+			if (!(afmt_status[afmt_idx] & AFMT_AZ_FORMAT_WTRIG))
+				DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
 
-				rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI5\n");
-				break;
-			default:
-				DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
+			if (afmt_idx > 5) {
+				DRM_ERROR("Unhandled interrupt: %d %d\n",
+					  src_id, src_data);
 				break;
 			}
+			afmt_status[afmt_idx] &= ~AFMT_AZ_FORMAT_WTRIG;
+			queue_hdmi = true;
+			DRM_DEBUG("IH: HDMI%d\n", afmt_idx + 1);
+			break;
 		case 96:
 			DRM_ERROR("SRBM_READ_ERROR: 0x%x\n", RREG32(SRBM_READ_ERROR));
 			WREG32(SRBM_INT_ACK, 0x1);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index b6086ee..e961a8a 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -774,12 +774,7 @@ struct evergreen_irq_stat_regs {
 	u32 d4grph_int;
 	u32 d5grph_int;
 	u32 d6grph_int;
-	u32 afmt_status1;
-	u32 afmt_status2;
-	u32 afmt_status3;
-	u32 afmt_status4;
-	u32 afmt_status5;
-	u32 afmt_status6;
+	u32 afmt_status[6];
 };
 
 struct cik_irq_stat_regs {
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si
  2017-05-16 21:11 [PATCH 0/3] Cleanup evergreen/si IRQ handling code Lyude
  2017-05-16 21:11 ` [PATCH 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
  2017-05-16 21:11 ` [PATCH 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen Lyude
@ 2017-05-16 21:12 ` Lyude
  2017-05-17  8:32 ` [PATCH 0/3] Cleanup evergreen/si IRQ handling code Christian König
  2017-05-19 23:48 ` [PATCH v2 " Lyude
  4 siblings, 0 replies; 12+ messages in thread
From: Lyude @ 2017-05-16 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

Same as the previous patch, but for pageflipping now.

Signed-off-by: Lyude <lyude@redhat.com>
---
 drivers/gpu/drm/radeon/evergreen.c | 70 ++++++------------------------------
 drivers/gpu/drm/radeon/radeon.h    |  7 +---
 drivers/gpu/drm/radeon/si.c        | 72 ++++++--------------------------------
 3 files changed, 22 insertions(+), 127 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 76a2f20..3bfc951 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4452,18 +4452,9 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 	WREG32(DMA_CNTL, tmp);
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(SRBM_INT_CNTL, 0);
-	for (i = 0; i < rdev->num_crtc; i++)
+	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);
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], 0);
 	}
 
 	/* only one DAC on DCE5 */
@@ -4559,23 +4550,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 
 	WREG32(GRBM_INT_CNTL, grbm_int_cntl);
 
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	for (i = 0; i < EVERGREEN_MAX_DISP_REGISTERS; i++) {
 		radeon_irq_kms_set_irq_n_enabled(rdev,
 						 DC_HPDx_INT_CONTROL(i),
@@ -4594,6 +4568,9 @@ int evergreen_irq_set(struct radeon_device *rdev)
 			    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 + crtc_offsets[i],
+			       GRPH_PFLIP_INT_MASK);
 		}
 	}
 
@@ -4611,6 +4588,7 @@ int evergreen_irq_set(struct radeon_device *rdev)
 static void evergreen_irq_ack(struct radeon_device *rdev)
 {
 	int i;
+	u32 *grph_int = rdev->irq.stat_regs.evergreen.grph_int;
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
 	u32 *afmt_status = rdev->irq.stat_regs.evergreen.afmt_status;
 
@@ -4627,45 +4605,19 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 				  AFMT_AZ_FORMAT_WTRIG_ACK);
 
 		if (i < rdev->num_crtc) {
+			grph_int[i] = RREG32(GRPH_INT_STATUS + crtc_offsets[i]);
+
 			if (disp_int[i] & LB_Dx_VBLANK_INTERRUPT)
 				WREG32(VBLANK_STATUS + crtc_offsets[i],
 				       VBLANK_ACK);
 			if (disp_int[i] & LB_Dx_VLINE_INTERRUPT)
 				WREG32(VLINE_STATUS + crtc_offsets[i],
 				       VLINE_ACK);
+			if (grph_int[i] & GRPH_PFLIP_INT_OCCURRED)
+				WREG32(GRPH_INT_STATUS + crtc_offsets[i],
+				       GRPH_PFLIP_INT_CLEAR);
 		}
 	}
-
-	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) {
-		rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
-	}
-	if (rdev->num_crtc >= 6) {
-		rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
-	}
-
-
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		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->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->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			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);
-	}
 }
 
 static void evergreen_irq_disable(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index e961a8a..edb9686 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -768,12 +768,7 @@ struct r600_irq_stat_regs {
 
 struct evergreen_irq_stat_regs {
 	u32 disp_int[6];
-	u32 d1grph_int;
-	u32 d2grph_int;
-	u32 d3grph_int;
-	u32 d4grph_int;
-	u32 d5grph_int;
-	u32 d6grph_int;
+	u32 grph_int[6];
 	u32 afmt_status[6];
 };
 
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index bb745e1..7c28689 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5940,20 +5940,9 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 	WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, tmp);
 	WREG32(GRBM_INT_CNTL, 0);
 	WREG32(SRBM_INT_CNTL, 0);
-	for (i = 0; i < rdev->num_crtc; i++)
+	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);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], 0);
 	}
 
 	if (!ASIC_IS_NODCE(rdev)) {
@@ -6103,25 +6092,6 @@ int si_irq_set(struct radeon_device *rdev)
 		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
 	}
 
-	if (rdev->num_crtc >= 2) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-
 	if (!ASIC_IS_NODCE(rdev)) {
 		for (i = 0; i < SI_MAX_DISP_REGISTERS; i++) {
 			radeon_irq_kms_set_irq_n_enabled(
@@ -6136,6 +6106,8 @@ int si_irq_set(struct radeon_device *rdev)
 		    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 + crtc_offsets[i], GRPH_PFLIP_INT_MASK);
 	}
 
 	WREG32(CG_THERMAL_INT, thermal_int);
@@ -6150,21 +6122,11 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 {
 	int i;
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
+	u32 *grph_int = rdev->irq.stat_regs.evergreen.grph_int;
 
 	if (ASIC_IS_NODCE(rdev))
 		return;
 
-	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) {
-		rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
-	}
-	if (rdev->num_crtc >= 6) {
-		rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
-	}
-
 	for (i = 0; i < SI_MAX_DISP_REGISTERS; i++) {
 		disp_int[i] = RREG32(DISP_INTERRUPT_STATUS(i));
 
@@ -6174,33 +6136,19 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
 
 		if (i < rdev->num_crtc) {
+			grph_int[i] = RREG32(GRPH_INT_STATUS + crtc_offsets[i]);
+
 			if (disp_int[i] & LB_Dx_VBLANK_INTERRUPT)
 				WREG32(VBLANK_STATUS + crtc_offsets[i],
 				       VBLANK_ACK);
 			if (disp_int[i] & LB_Dx_VLINE_INTERRUPT)
 				WREG32(VLINE_STATUS + crtc_offsets[i],
 				       VLINE_ACK);
+			if (grph_int[i] & GRPH_PFLIP_INT_OCCURRED)
+				WREG32(GRPH_INT_STATUS + crtc_offsets[i],
+				       GRPH_PFLIP_INT_CLEAR);
 		}
 	}
-
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		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->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->num_crtc >= 6) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			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);
-	}
 }
 
 static void si_irq_disable(struct radeon_device *rdev)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] Cleanup evergreen/si IRQ handling code
  2017-05-16 21:11 [PATCH 0/3] Cleanup evergreen/si IRQ handling code Lyude
                   ` (2 preceding siblings ...)
  2017-05-16 21:12 ` [PATCH 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si Lyude
@ 2017-05-17  8:32 ` Christian König
  2017-05-19 23:48 ` [PATCH v2 " Lyude
  4 siblings, 0 replies; 12+ messages in thread
From: Christian König @ 2017-05-17  8:32 UTC (permalink / raw)
  To: Lyude, amd-gfx; +Cc: Alex Deucher, David Airlie, dri-devel, linux-kernel

Am 16.05.2017 um 23:11 schrieb Lyude:
> This is the first part of me going through and cleaning up the IRQ handling
> code for radeon, since after taking a look at it the other day while trying to
> debug something I realized basically all of the code was copy pasted
> everywhere, and quite difficult to actually read through.
>
> Will come up with something for r600 and cik once I've got the chipsets on hand
> to test with.

Oh, yes please. This always annoyed me as well, but never had the time 
to clean it up globally.

Just two general comments:
1. Don't modify the register headers.

They are more or less from a database and we don't want manual code like 
this in there:
> +#define DISP_INTERRUPT_STATUS(i) \
> +	((i < 4) ? 0x60f4 + (0x4 * i) : 0x614c + (0x4 * (i - 4)))

Instead use a static constant array, e.g. like this:
static const uint32_t disp_interrupt_status[4] {
     DISP_INTERRUPT_STATUS,
     DISP_INTERRUPT_STATUS_CONTINUE,
...
};

2. Keep the order in which stuff is written to the regs exactly the same.

In other words, don't replace this:

> -	rdev->irq.stat_regs.evergreen.afmt_status1 = RREG32(AFMT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
> -	rdev->irq.stat_regs.evergreen.afmt_status2 = RREG32(AFMT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
> -	rdev->irq.stat_regs.evergreen.afmt_status3 = RREG32(AFMT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
> -	rdev->irq.stat_regs.evergreen.afmt_status4 = RREG32(AFMT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
> -	rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
> -	rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);

With:

>   	for (i = 0; i < EVERGREEN_MAX_DISP_REGISTERS; i++) {
>   		disp_int[i] = RREG32(DISP_INTERRUPT_STATUS(i));
> +		afmt_status[i] = RREG32(AFMT_STATUS + crtc_offsets[i]);
>   
>   		if (disp_int[i] & DC_HPDx_INTERRUPT)
>   			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_ACK);
>   		if (disp_int[i] & DC_HPDx_RX_INTERRUPT)
>   			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
> +		if (afmt_status[i] & AFMT_AZ_FORMAT_WTRIG)
> +			WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + crtc_offsets[i],
> +				  AFMT_AZ_FORMAT_WTRIG_ACK);

Regards,
Christian.

>
> Lyude (3):
>    drm/radeon: Cleanup display interrupt handling for evergreen, si
>    drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
>    drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si
>
>   drivers/gpu/drm/radeon/evergreen.c      | 915 +++++---------------------------
>   drivers/gpu/drm/radeon/evergreend.h     |  74 +--
>   drivers/gpu/drm/radeon/radeon.h         |  27 +-
>   drivers/gpu/drm/radeon/radeon_irq_kms.c |  35 ++
>   drivers/gpu/drm/radeon/si.c             | 627 ++++------------------
>   drivers/gpu/drm/radeon/sid.h            |  72 +--
>   6 files changed, 328 insertions(+), 1422 deletions(-)
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code
  2017-05-16 21:11 [PATCH 0/3] Cleanup evergreen/si IRQ handling code Lyude
                   ` (3 preceding siblings ...)
  2017-05-17  8:32 ` [PATCH 0/3] Cleanup evergreen/si IRQ handling code Christian König
@ 2017-05-19 23:48 ` Lyude
  2017-05-19 23:48   ` [PATCH v2 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
                     ` (3 more replies)
  4 siblings, 4 replies; 12+ messages in thread
From: Lyude @ 2017-05-19 23:48 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

This is the first part of me going through and cleaning up the IRQ handling
code for radeon, since after taking a look at it the other day while trying to
debug something I realized basically all of the code was copy pasted
everywhere, and quite difficult to actually read through.

Will come up with something for r600 and cik once I've got the chipsets on hand
to test with.

Lyude (3):
  drm/radeon: Cleanup display interrupt handling for evergreen, si
  drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
  drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si

 drivers/gpu/drm/radeon/evergreen.c      | 943 ++++++--------------------------
 drivers/gpu/drm/radeon/radeon.h         |  27 +-
 drivers/gpu/drm/radeon/radeon_irq_kms.c |  35 ++
 drivers/gpu/drm/radeon/si.c             | 655 +++++-----------------
 4 files changed, 344 insertions(+), 1316 deletions(-)

-- 
2.9.4

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si
  2017-05-19 23:48 ` [PATCH v2 " Lyude
@ 2017-05-19 23:48   ` Lyude
  2017-05-19 23:48   ` [PATCH v2 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen Lyude
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 12+ messages in thread
From: Lyude @ 2017-05-19 23:48 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

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

Signed-off-by: Lyude <lyude@redhat.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(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 0bf1035..44ac6d3 100644
--- 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_device *rdev)
  */
 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_device *rdev, enum radeon_hpd_id hpd)
 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_device *rdev)
 		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_device *rdev)
 			 */
 			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_device *rdev)
 	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);
 }
@@ -2637,6 +2534,15 @@ static const unsigned evergreen_dp_offsets[] =
 	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
@@ -4543,6 +4449,7 @@ u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc)
 
 void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 {
+	int i;
 	u32 tmp;
 
 	if (rdev->family >= CHIP_CAYMAN) {
@@ -4558,16 +4465,8 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 	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);
@@ -4585,27 +4484,16 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 		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;
@@ -4623,12 +4511,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		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);
@@ -4685,60 +4567,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		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;
@@ -4778,15 +4606,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
 
 	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,
@@ -4806,12 +4631,13 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		       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
@@ -4830,16 +4656,16 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	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) {
@@ -4862,28 +4688,28 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		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) {
@@ -4891,76 +4717,24 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 			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) {
@@ -5037,6 +4811,9 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
 
 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;
@@ -5046,6 +4823,7 @@ int evergreen_irq_process(struct radeon_device *rdev)
 	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
+	const char *event_name;
 
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
@@ -5074,184 +4852,44 @@ int evergreen_irq_process(struct radeon_device *rdev)
 
 		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 */
@@ -5264,107 +4902,30 @@ int evergreen_irq_process(struct radeon_device *rdev)
 				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;
-				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;
+			if (src_data <= 5) {
+				hpd_idx = src_data;
+				mask = DC_HPD1_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");
+				event_name = "HPD";
 
-				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");
+				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) {
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c1c8e22..b6086ee 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -767,12 +767,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;
@@ -2976,6 +2971,12 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
 			       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
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 1b7528d..7aacb44 100644
--- 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 radeon_device *rdev, unsigned hpd_mask)
 	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);
+	}
+}
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 76d1888..8351f06 100644
--- 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_device *rdev);
 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),
@@ -5916,6 +5940,7 @@ static void si_disable_interrupts(struct radeon_device *rdev)
 
 static void si_disable_interrupt_state(struct radeon_device *rdev)
 {
+	int i;
 	u32 tmp;
 
 	tmp = RREG32(CP_INT_CNTL_RING0) &
@@ -5929,18 +5954,8 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 	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);
@@ -5958,18 +5973,9 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 	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);
 	}
 }
 
@@ -6044,12 +6050,12 @@ static int si_irq_init(struct radeon_device *rdev)
 	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;
@@ -6069,15 +6075,6 @@ int si_irq_set(struct radeon_device *rdev)
 	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;
 
@@ -6106,60 +6103,6 @@ int si_irq_set(struct radeon_device *rdev)
 		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);
@@ -6175,17 +6118,11 @@ int si_irq_set(struct radeon_device *rdev)
 		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) {
@@ -6208,12 +6145,12 @@ int si_irq_set(struct radeon_device *rdev)
 	}
 
 	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);
@@ -6224,19 +6161,18 @@ int si_irq_set(struct radeon_device *rdev)
 	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) {
@@ -6252,28 +6188,28 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 		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) {
@@ -6281,76 +6217,24 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 			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);
 	}
 }
 
@@ -6412,6 +6296,9 @@ static inline u32 si_get_ih_wptr(struct radeon_device *rdev)
  */
 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;
@@ -6420,6 +6307,7 @@ int si_irq_process(struct radeon_device *rdev)
 	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
+	const char *event_name;
 
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
@@ -6449,184 +6337,44 @@ int si_irq_process(struct radeon_device *rdev)
 
 		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 */
@@ -6639,119 +6387,29 @@ int si_irq_process(struct radeon_device *rdev)
 				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");
+				event_name = "HPD";
 
-				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;
-				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");
-
-				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));
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
  2017-05-19 23:48 ` [PATCH v2 " Lyude
  2017-05-19 23:48   ` [PATCH v2 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
@ 2017-05-19 23:48   ` Lyude
  2017-05-19 23:48   ` [PATCH v2 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si Lyude
  2017-05-20 11:39   ` [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code Christian König
  3 siblings, 0 replies; 12+ messages in thread
From: Lyude @ 2017-05-19 23:48 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

Same as the previous patch, but now for handling HDMI audio interrupts.

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

Signed-off-by: Lyude <lyude@redhat.com>
---
 drivers/gpu/drm/radeon/evergreen.c | 153 +++++++------------------------------
 drivers/gpu/drm/radeon/radeon.h    |   7 +-
 2 files changed, 27 insertions(+), 133 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 44ac6d3..507a773 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4495,7 +4495,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
 	u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;
 	u32 grbm_int_cntl = 0;
-	u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0;
 	u32 dma_cntl, dma_cntl1 = 0;
 	u32 thermal_int = 0;
 
@@ -4518,13 +4517,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		thermal_int = RREG32(CG_THERMAL_INT) &
 			~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
 
-	afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt3 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt4 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt5 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-	afmt6 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
-
 	dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE;
 
 	if (rdev->family >= CHIP_CAYMAN) {
@@ -4567,31 +4559,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
 	}
 
-	if (rdev->irq.afmt[0]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 0\n");
-		afmt1 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[1]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 1\n");
-		afmt2 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[2]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 2\n");
-		afmt3 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[3]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 3\n");
-		afmt4 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[4]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 4\n");
-		afmt5 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-	if (rdev->irq.afmt[5]) {
-		DRM_DEBUG("evergreen_irq_set: hdmi 5\n");
-		afmt6 |= AFMT_AZ_FORMAT_WTRIG_MASK;
-	}
-
 	if (rdev->family >= CHIP_CAYMAN) {
 		cayman_cp_int_cntl_setup(rdev, 0, cp_int_cntl);
 		cayman_cp_int_cntl_setup(rdev, 1, cp_int_cntl1);
@@ -4643,12 +4610,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	else
 		WREG32(CG_THERMAL_INT, thermal_int);
 
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, afmt3);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, afmt4);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5);
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6);
+	for (i = 0; i < 6; i++) {
+		radeon_irq_kms_set_irq_n_enabled(
+		    rdev, AFMT_AUDIO_PACKET_CONTROL + crtc_offsets[i],
+		    AFMT_AZ_FORMAT_WTRIG_MASK,
+		    rdev->irq.afmt[i], "HDMI", i);
+	}
 
 	/* posting read */
 	RREG32(SRBM_STATUS);
@@ -4661,10 +4628,12 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 {
 	int i;
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
-	u32 tmp;
+	u32 *afmt_status = rdev->irq.stat_regs.evergreen.afmt_status;
 
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++) {
 		disp_int[i] = RREG32(evergreen_disp_int_status[i]);
+		afmt_status[i] = RREG32(AFMT_STATUS + crtc_offsets[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);
@@ -4677,12 +4646,6 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 	}
 
-	rdev->irq.stat_regs.evergreen.afmt_status1 = RREG32(AFMT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status2 = RREG32(AFMT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status3 = RREG32(AFMT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status4 = RREG32(AFMT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
-	rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
 
 	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
 		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
@@ -4737,35 +4700,10 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
 	}
 
-	if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, tmp);
-	}
-	if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) {
-		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
-		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, tmp);
+	for (i = 0; i < 6; i++) {
+		if (afmt_status[i] & AFMT_AZ_FORMAT_WTRIG)
+			WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + crtc_offsets[i],
+				  AFMT_AZ_FORMAT_WTRIG_ACK);
 	}
 }
 
@@ -4812,7 +4750,8 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
 int evergreen_irq_process(struct radeon_device *rdev)
 {
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
-	u32 crtc_idx, hpd_idx;
+	u32 *afmt_status = rdev->irq.stat_regs.evergreen.afmt_status;
+	u32 crtc_idx, hpd_idx, afmt_idx;
 	u32 mask;
 	u32 wptr;
 	u32 rptr;
@@ -4928,59 +4867,19 @@ int evergreen_irq_process(struct radeon_device *rdev)
 
 			break;
 		case 44: /* hdmi */
-			switch (src_data) {
-			case 0:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI0\n");
-				break;
-			case 1:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI1\n");
-				break;
-			case 2:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI2\n");
-				break;
-			case 3:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI3\n");
-				break;
-			case 4:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
-				rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI4\n");
-				break;
-			case 5:
-				if (!(rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG))
-					DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+			afmt_idx = src_data;
+			if (!(afmt_status[afmt_idx] & AFMT_AZ_FORMAT_WTRIG))
+				DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
 
-				rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG;
-				queue_hdmi = true;
-				DRM_DEBUG("IH: HDMI5\n");
-				break;
-			default:
-				DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
+			if (afmt_idx > 5) {
+				DRM_ERROR("Unhandled interrupt: %d %d\n",
+					  src_id, src_data);
 				break;
 			}
+			afmt_status[afmt_idx] &= ~AFMT_AZ_FORMAT_WTRIG;
+			queue_hdmi = true;
+			DRM_DEBUG("IH: HDMI%d\n", afmt_idx + 1);
+			break;
 		case 96:
 			DRM_ERROR("SRBM_READ_ERROR: 0x%x\n", RREG32(SRBM_READ_ERROR));
 			WREG32(SRBM_INT_ACK, 0x1);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index b6086ee..e961a8a 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -774,12 +774,7 @@ struct evergreen_irq_stat_regs {
 	u32 d4grph_int;
 	u32 d5grph_int;
 	u32 d6grph_int;
-	u32 afmt_status1;
-	u32 afmt_status2;
-	u32 afmt_status3;
-	u32 afmt_status4;
-	u32 afmt_status5;
-	u32 afmt_status6;
+	u32 afmt_status[6];
 };
 
 struct cik_irq_stat_regs {
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si
  2017-05-19 23:48 ` [PATCH v2 " Lyude
  2017-05-19 23:48   ` [PATCH v2 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
  2017-05-19 23:48   ` [PATCH v2 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen Lyude
@ 2017-05-19 23:48   ` Lyude
  2017-05-20 11:39   ` [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code Christian König
  3 siblings, 0 replies; 12+ messages in thread
From: Lyude @ 2017-05-19 23:48 UTC (permalink / raw)
  To: amd-gfx
  Cc: Lyude, Alex Deucher, Christian König, David Airlie,
	dri-devel, linux-kernel

Same as the previous patch, but for pageflipping now. This also lets us
clear up the copy paste for vblank/vline IRQs.

Changes since v1:
- Preserve the order all registers are written back

Signed-off-by: Lyude <lyude@redhat.com>
---
 drivers/gpu/drm/radeon/evergreen.c | 105 ++++++++---------------------------
 drivers/gpu/drm/radeon/radeon.h    |   7 +--
 drivers/gpu/drm/radeon/si.c        | 111 +++++++++----------------------------
 3 files changed, 51 insertions(+), 172 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 507a773..44527e6 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4467,17 +4467,8 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 	WREG32(SRBM_INT_CNTL, 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);
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
-	}
+	for (i = 0; i < rdev->num_crtc; i++)
+		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], 0);
 
 	/* only one DAC on DCE5 */
 	if (!ASIC_IS_DCE5(rdev))
@@ -4581,22 +4572,8 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		    atomic_read(&rdev->irq.pflip[i]), "vblank", i);
 	}
 
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-	       GRPH_PFLIP_INT_MASK);
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
+	for (i = 0; i < rdev->num_crtc; i++)
+		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], GRPH_PFLIP_INT_MASK);
 
 	for (i = 0; i < 6; i++) {
 		radeon_irq_kms_set_irq_n_enabled(
@@ -4626,68 +4603,34 @@ int evergreen_irq_set(struct radeon_device *rdev)
 /* Note that the order we write back regs here is important */
 static void evergreen_irq_ack(struct radeon_device *rdev)
 {
-	int i;
+	int i, j;
+	u32 *grph_int = rdev->irq.stat_regs.evergreen.grph_int;
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
 	u32 *afmt_status = rdev->irq.stat_regs.evergreen.afmt_status;
 
 	for (i = 0; i < 6; i++) {
 		disp_int[i] = RREG32(evergreen_disp_int_status[i]);
 		afmt_status[i] = RREG32(AFMT_STATUS + crtc_offsets[i]);
+		if (i < rdev->num_crtc)
+			grph_int[i] = RREG32(GRPH_INT_STATUS + crtc_offsets[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) {
-		rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
-	}
-	if (rdev->num_crtc >= 6) {
-		rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
-	}
-
-
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		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 (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 (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) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			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 (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);
+	/* We write back each interrupt register in pairs of two */
+	for (i = 0; i < rdev->num_crtc; i += 2) {
+		for (j = i; j < (i + 2); j++) {
+			if (grph_int[j] & GRPH_PFLIP_INT_OCCURRED)
+				WREG32(GRPH_INT_STATUS + crtc_offsets[j],
+				       GRPH_PFLIP_INT_CLEAR);
+		}
+
+		for (j = i; j < (i + 2); j++) {
+			if (disp_int[j] & LB_D1_VBLANK_INTERRUPT)
+				WREG32(VBLANK_STATUS + crtc_offsets[j],
+				       VBLANK_ACK);
+			if (disp_int[j] & LB_D1_VLINE_INTERRUPT)
+				WREG32(VLINE_STATUS + crtc_offsets[j],
+				       VLINE_ACK);
+		}
 	}
 
 	for (i = 0; i < 6; i++) {
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index e961a8a..edb9686 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -768,12 +768,7 @@ struct r600_irq_stat_regs {
 
 struct evergreen_irq_stat_regs {
 	u32 disp_int[6];
-	u32 d1grph_int;
-	u32 d2grph_int;
-	u32 d3grph_int;
-	u32 d4grph_int;
-	u32 d5grph_int;
-	u32 d6grph_int;
+	u32 grph_int[6];
 	u32 afmt_status[6];
 };
 
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 8351f06..c88a80e 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5956,19 +5956,8 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 	WREG32(SRBM_INT_CNTL, 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);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
-	}
+	for (i = 0; i < rdev->num_crtc; i++)
+		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], 0);
 
 	if (!ASIC_IS_NODCE(rdev)) {
 		WREG32(DAC_AUTODETECT_INT_CONTROL, 0);
@@ -6125,24 +6114,8 @@ int si_irq_set(struct radeon_device *rdev)
 		    atomic_read(&rdev->irq.pflip[i]), "vblank", i);
 	}
 
-	if (rdev->num_crtc >= 2) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 4) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
-	if (rdev->num_crtc >= 6) {
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
-		       GRPH_PFLIP_INT_MASK);
-	}
+	for (i = 0; i < rdev->num_crtc; i++)
+		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], GRPH_PFLIP_INT_MASK);
 
 	if (!ASIC_IS_NODCE(rdev)) {
 		for (i = 0; i < 6; i++) {
@@ -6164,67 +6137,35 @@ int si_irq_set(struct radeon_device *rdev)
 /* The order we write back each register here is important */
 static inline void si_irq_ack(struct radeon_device *rdev)
 {
-	int i;
+	int i, j;
 	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
+	u32 *grph_int = rdev->irq.stat_regs.evergreen.grph_int;
 
 	if (ASIC_IS_NODCE(rdev))
 		return;
 
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++) {
 		disp_int[i] = RREG32(si_disp_int_status[i]);
+		if (i < rdev->num_crtc)
+			grph_int[i] = RREG32(GRPH_INT_STATUS + crtc_offsets[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) {
-		rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
-	}
-	if (rdev->num_crtc >= 6) {
-		rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
-		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
-	}
-
-	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
-		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 (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 (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) {
-		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
-			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 (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);
+	/* We write back each interrupt register in pairs of two */
+	for (i = 0; i < rdev->num_crtc; i += 2) {
+		for (j = i; j < (i + 2); j++) {
+			if (grph_int[j] & GRPH_PFLIP_INT_OCCURRED)
+				WREG32(GRPH_INT_STATUS + crtc_offsets[j],
+				       GRPH_PFLIP_INT_CLEAR);
+		}
+
+		for (j = i; j < (i + 2); j++) {
+			if (disp_int[j] & LB_D1_VBLANK_INTERRUPT)
+				WREG32(VBLANK_STATUS + crtc_offsets[j],
+				       VBLANK_ACK);
+			if (disp_int[j] & LB_D1_VLINE_INTERRUPT)
+				WREG32(VLINE_STATUS + crtc_offsets[j],
+				       VLINE_ACK);
+		}
 	}
 
 	for (i = 0; i < 6; i++) {
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code
  2017-05-19 23:48 ` [PATCH v2 " Lyude
                     ` (2 preceding siblings ...)
  2017-05-19 23:48   ` [PATCH v2 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si Lyude
@ 2017-05-20 11:39   ` Christian König
  2017-05-22 13:52     ` Lyude Paul
  2017-05-24 18:31     ` Alex Deucher
  3 siblings, 2 replies; 12+ messages in thread
From: Christian König @ 2017-05-20 11:39 UTC (permalink / raw)
  To: Lyude, amd-gfx
  Cc: David Airlie, linux-kernel, dri-devel, Alex Deucher,
	Christian König

Am 20.05.2017 um 01:48 schrieb Lyude:
> This is the first part of me going through and cleaning up the IRQ handling
> code for radeon, since after taking a look at it the other day while trying to
> debug something I realized basically all of the code was copy pasted
> everywhere, and quite difficult to actually read through.
>
> Will come up with something for r600 and cik once I've got the chipsets on hand
> to test with.
>
> Lyude (3):
>    drm/radeon: Cleanup display interrupt handling for evergreen, si
>    drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
>    drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si

I don't have time to do a line by line review, but what I saw looked 
very good to me.

So the whole seres is Acked-by: Christian König <christian.koenig@amd.com>.

BTW: You don't want to take a look at the other hw generations as well?

Regards,
Christian.

>
>   drivers/gpu/drm/radeon/evergreen.c      | 943 ++++++--------------------------
>   drivers/gpu/drm/radeon/radeon.h         |  27 +-
>   drivers/gpu/drm/radeon/radeon_irq_kms.c |  35 ++
>   drivers/gpu/drm/radeon/si.c             | 655 +++++-----------------
>   4 files changed, 344 insertions(+), 1316 deletions(-)
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code
  2017-05-20 11:39   ` [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code Christian König
@ 2017-05-22 13:52     ` Lyude Paul
  2017-05-24 18:31     ` Alex Deucher
  1 sibling, 0 replies; 12+ messages in thread
From: Lyude Paul @ 2017-05-22 13:52 UTC (permalink / raw)
  To: Christian König, amd-gfx
  Cc: David Airlie, linux-kernel, dri-devel, Alex Deucher,
	Christian König

On Sat, 2017-05-20 at 13:39 +0200, Christian König wrote:
> Am 20.05.2017 um 01:48 schrieb Lyude:
> > This is the first part of me going through and cleaning up the IRQ
> > handling
> > code for radeon, since after taking a look at it the other day
> > while trying to
> > debug something I realized basically all of the code was copy
> > pasted
> > everywhere, and quite difficult to actually read through.
> > 
> > Will come up with something for r600 and cik once I've got the
> > chipsets on hand
> > to test with.
> > 
> > Lyude (3):
> >    drm/radeon: Cleanup display interrupt handling for evergreen, si
> >    drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
> >    drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si
> 
> I don't have time to do a line by line review, but what I saw looked 
> very good to me.
> 
> So the whole seres is Acked-by: Christian König <christian.koenig@amd
> .com>.
> 
> BTW: You don't want to take a look at the other hw generations as
> well?
Oh don't worry, I'm already planning on that! The next chance I have
available I'll be going my coworker's GPUs so I can get the hardware I
need to test refactors I write of the rest of the hw gen's IRQ handling
code. :)
> 
> Regards,
> Christian.
> 
> > 
> >   drivers/gpu/drm/radeon/evergreen.c      | 943 ++++++-------------
> > -------------
> >   drivers/gpu/drm/radeon/radeon.h         |  27 +-
> >   drivers/gpu/drm/radeon/radeon_irq_kms.c |  35 ++
> >   drivers/gpu/drm/radeon/si.c             | 655 +++++------------
> > -----
> >   4 files changed, 344 insertions(+), 1316 deletions(-)
> > 
> 
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code
  2017-05-20 11:39   ` [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code Christian König
  2017-05-22 13:52     ` Lyude Paul
@ 2017-05-24 18:31     ` Alex Deucher
  1 sibling, 0 replies; 12+ messages in thread
From: Alex Deucher @ 2017-05-24 18:31 UTC (permalink / raw)
  To: Christian König
  Cc: Lyude, amd-gfx list, Alex Deucher, LKML,
	Maling list - DRI developers, Christian König

On Sat, May 20, 2017 at 7:39 AM, Christian König
<deathsimple@vodafone.de> wrote:
> Am 20.05.2017 um 01:48 schrieb Lyude:
>>
>> This is the first part of me going through and cleaning up the IRQ
>> handling
>> code for radeon, since after taking a look at it the other day while
>> trying to
>> debug something I realized basically all of the code was copy pasted
>> everywhere, and quite difficult to actually read through.
>>
>> Will come up with something for r600 and cik once I've got the chipsets on
>> hand
>> to test with.
>>
>> Lyude (3):
>>    drm/radeon: Cleanup display interrupt handling for evergreen, si
>>    drm/radeon: Cleanup HDMI audio interrupt handling for evergreen
>>    drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si
>
>
> I don't have time to do a line by line review, but what I saw looked very
> good to me.
>
> So the whole seres is Acked-by: Christian König <christian.koenig@amd.com>.

Applied.  thanks!

Alex


>
> BTW: You don't want to take a look at the other hw generations as well?
>
> Regards,
> Christian.
>
>>
>>   drivers/gpu/drm/radeon/evergreen.c      | 943
>> ++++++--------------------------
>>   drivers/gpu/drm/radeon/radeon.h         |  27 +-
>>   drivers/gpu/drm/radeon/radeon_irq_kms.c |  35 ++
>>   drivers/gpu/drm/radeon/si.c             | 655 +++++-----------------
>>   4 files changed, 344 insertions(+), 1316 deletions(-)
>>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-05-24 18:31 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-16 21:11 [PATCH 0/3] Cleanup evergreen/si IRQ handling code Lyude
2017-05-16 21:11 ` [PATCH 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
2017-05-16 21:11 ` [PATCH 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen Lyude
2017-05-16 21:12 ` [PATCH 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si Lyude
2017-05-17  8:32 ` [PATCH 0/3] Cleanup evergreen/si IRQ handling code Christian König
2017-05-19 23:48 ` [PATCH v2 " Lyude
2017-05-19 23:48   ` [PATCH v2 1/3] drm/radeon: Cleanup display interrupt handling for evergreen, si Lyude
2017-05-19 23:48   ` [PATCH v2 2/3] drm/radeon: Cleanup HDMI audio interrupt handling for evergreen Lyude
2017-05-19 23:48   ` [PATCH v2 3/3] drm/radeon: Cleanup pageflipping IRQ handling for evergreen, si Lyude
2017-05-20 11:39   ` [PATCH v2 0/3] Cleanup evergreen/si IRQ handling code Christian König
2017-05-22 13:52     ` Lyude Paul
2017-05-24 18:31     ` Alex Deucher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).