--- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel