[PATCH][RFC] drm/radeon/kms: use HDMI IRQ on Evergreen

Rafał Miłecki zajec5 at gmail.com
Sun Mar 25 08:20:40 PDT 2012


---
 drivers/gpu/drm/radeon/evergreen.c |   45 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/r600_hdmi.c |    7 ++++-
 drivers/gpu/drm/radeon/radeon.h    |    2 +-
 3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index f58254a..8779a75 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2527,12 +2527,22 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 
 int evergreen_irq_set(struct radeon_device *rdev)
 {
+	u8 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 hdmi[6];
 	u32 grbm_int_cntl = 0;
 	u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
+	u16 eg_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,
+	};
 
 	if (!rdev->irq.installed) {
 		WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@@ -2553,6 +2563,10 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
 	hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
 
+	for (i = 0; i < ARRAY_SIZE(eg_offsets) && i < rdev->num_crtc; i++)
+		hdmi[i] = RREG32(EVERGREEN_HDMI_BASE + eg_offsets[i] + 0xfc)
+			& ~0x10000000;
+
 	if (rdev->family >= CHIP_CAYMAN) {
 		/* enable CP interrupts on all rings */
 		if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) {
@@ -2629,6 +2643,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
 		DRM_DEBUG("evergreen_irq_set: hpd 6\n");
 		hpd6 |= DC_HPDx_INT_EN;
 	}
+	for (i = 0; i < ARRAY_SIZE(eg_offsets) && i < rdev->num_crtc; i++) {
+		if (rdev->irq.hdmi[i]) {
+			DRM_DEBUG("evergreen_irq_set: hdmi %d\n", i);
+			hdmi[i] |= 0x10000000;
+		}
+	}
 	if (rdev->irq.gui_idle) {
 		DRM_DEBUG("gui idle\n");
 		grbm_int_cntl |= GUI_IDLE_INT_ENABLE;
@@ -2671,12 +2691,24 @@ int evergreen_irq_set(struct radeon_device *rdev)
 	WREG32(DC_HPD5_INT_CONTROL, hpd5);
 	WREG32(DC_HPD6_INT_CONTROL, hpd6);
 
+	for (i = 0; i < ARRAY_SIZE(eg_offsets) && i < rdev->num_crtc; i++)
+		WREG32(EVERGREEN_HDMI_BASE + eg_offsets[i] + 0xfc, hdmi[i]);
+
 	return 0;
 }
 
 static void evergreen_irq_ack(struct radeon_device *rdev)
 {
+	u8 i;
 	u32 tmp;
+	u16 eg_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,
+	};
 
 	rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS);
 	rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
@@ -2768,6 +2800,15 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
+
+	for (i = 0; i < ARRAY_SIZE(eg_offsets) && i < rdev->num_crtc; i++) {
+		tmp = RREG32(EVERGREEN_HDMI_BASE + eg_offsets[i] + 0xf8);
+		if (tmp & 0x20000000) {
+			pr_info("zajec reg 0x%X is: 0x%X\n", EVERGREEN_HDMI_BASE + eg_offsets[i] + 0xf8, tmp);
+			WREG32_P(EVERGREEN_HDMI_BASE + eg_offsets[i] + 0xfc, 0x20000000, ~0x20000000);
+			pr_info("zajec ACKed, now: 0x%X\n", RREG32(EVERGREEN_HDMI_BASE + eg_offsets[i] + 0xf8));
+		}
+	}
 }
 
 void evergreen_irq_disable(struct radeon_device *rdev)
@@ -3050,6 +3091,10 @@ restart_ih:
 				break;
 			}
 			break;
+		case 44: /* HDMI */
+			pr_info("IH: HDMI: 0x%x\n", src_data);
+			r600_audio_schedule_polling(rdev);
+			break;
 		case 176: /* CP_INT in ring buffer */
 		case 177: /* CP_INT in IB1 */
 		case 178: /* CP_INT in IB2 */
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 0b59206..cd00853 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -507,6 +507,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	uint32_t offset;
 
 	if (ASIC_IS_DCE5(rdev))
@@ -548,7 +549,11 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
 		}
 	}
 
-	if (rdev->irq.installed
+	if (rdev->irq.installed && ASIC_IS_DCE4(rdev)) {
+		rdev->irq.hdmi[dig->dig_encoder] = true;
+		radeon_irq_set(rdev);
+		r600_audio_disable_polling(encoder);
+	} else if (rdev->irq.installed
 	    && rdev->family != CHIP_RS600
 	    && rdev->family != CHIP_RS690
 	    && rdev->family != CHIP_RS740
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index d98c55f..88e6d04 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -593,7 +593,7 @@ union radeon_irq_stat_regs {
 
 #define RADEON_MAX_HPD_PINS 6
 #define RADEON_MAX_CRTCS 6
-#define RADEON_MAX_HDMI_BLOCKS 2
+#define RADEON_MAX_HDMI_BLOCKS 6
 
 struct radeon_irq {
 	bool		installed;
-- 
1.7.7



More information about the dri-devel mailing list