[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