Loading drivers/gpu/drm/radeon/evergreen.c +128 −0 Original line number Diff line number Diff line Loading @@ -2594,6 +2594,7 @@ int evergreen_irq_set(struct radeon_device *rdev) u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; u32 grbm_int_cntl = 0; u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; if (!rdev->irq.installed) { WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); Loading @@ -2614,6 +2615,13 @@ 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; 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; if (rdev->family >= CHIP_CAYMAN) { /* enable CP interrupts on all rings */ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { Loading Loading @@ -2690,6 +2698,30 @@ int evergreen_irq_set(struct radeon_device *rdev) DRM_DEBUG("evergreen_irq_set: hpd 6\n"); hpd6 |= DC_HPDx_INT_EN; } 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->irq.gui_idle) { DRM_DEBUG("gui idle\n"); grbm_int_cntl |= GUI_IDLE_INT_ENABLE; Loading Loading @@ -2732,6 +2764,13 @@ int evergreen_irq_set(struct radeon_device *rdev) WREG32(DC_HPD5_INT_CONTROL, hpd5); WREG32(DC_HPD6_INT_CONTROL, hpd6); 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); return 0; } Loading @@ -2756,6 +2795,13 @@ 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); if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) Loading Loading @@ -2829,6 +2875,36 @@ static void evergreen_irq_ack(struct radeon_device *rdev) tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD6_INT_CONTROL, tmp); } 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); } } void evergreen_irq_disable(struct radeon_device *rdev) Loading Loading @@ -2878,6 +2954,7 @@ int evergreen_irq_process(struct radeon_device *rdev) u32 ring_index; unsigned long flags; bool queue_hotplug = false; bool queue_hdmi = false; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; Loading Loading @@ -3111,6 +3188,55 @@ int evergreen_irq_process(struct radeon_device *rdev) break; } break; case 44: /* hdmi */ switch (src_data) { case 0: if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { 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) { 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) { 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) { 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) { 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) { 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); break; } break; case 176: /* CP_INT in ring buffer */ case 177: /* CP_INT in IB1 */ case 178: /* CP_INT in IB2 */ Loading Loading @@ -3154,6 +3280,8 @@ int evergreen_irq_process(struct radeon_device *rdev) goto restart_ih; if (queue_hotplug) schedule_work(&rdev->hotplug_work); if (queue_hdmi) schedule_work(&rdev->audio_work); rdev->ih.rptr = rptr; WREG32(IH_RB_RPTR, rdev->ih.rptr); spin_unlock_irqrestore(&rdev->ih.lock, flags); Loading drivers/gpu/drm/radeon/r600.c +90 −25 Original line number Diff line number Diff line Loading @@ -2968,6 +2968,15 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) WREG32(DC_HPD5_INT_CONTROL, tmp); tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; WREG32(DC_HPD6_INT_CONTROL, tmp); tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp); tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp); } else { tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); } } else { WREG32(DACA_AUTODETECT_INT_CONTROL, 0); Loading @@ -2978,6 +2987,10 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); } } Loading Loading @@ -3074,7 +3087,7 @@ int r600_irq_set(struct radeon_device *rdev) u32 mode_int = 0; u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; u32 hdmi1, hdmi2; u32 hdmi0, hdmi1; u32 d1grph = 0, d2grph = 0; if (!rdev->irq.installed) { Loading @@ -3089,9 +3102,7 @@ int r600_irq_set(struct radeon_device *rdev) return 0; } hdmi1 = RREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; if (ASIC_IS_DCE3(rdev)) { hdmi2 = RREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; Loading @@ -3099,12 +3110,18 @@ int r600_irq_set(struct radeon_device *rdev) if (ASIC_IS_DCE32(rdev)) { hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK; hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK; } else { hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; } } else { hdmi2 = RREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; } if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { Loading Loading @@ -3146,13 +3163,13 @@ int r600_irq_set(struct radeon_device *rdev) DRM_DEBUG("r600_irq_set: hpd 6\n"); hpd6 |= DC_HPDx_INT_EN; } if (rdev->irq.hdmi[0]) { DRM_DEBUG("r600_irq_set: hdmi 1\n"); hdmi1 |= R600_HDMI_INT_EN; if (rdev->irq.afmt[0]) { DRM_DEBUG("r600_irq_set: hdmi 0\n"); hdmi0 |= HDMI0_AZ_FORMAT_WTRIG_MASK; } if (rdev->irq.hdmi[1]) { DRM_DEBUG("r600_irq_set: hdmi 2\n"); hdmi2 |= R600_HDMI_INT_EN; if (rdev->irq.afmt[1]) { DRM_DEBUG("r600_irq_set: hdmi 0\n"); hdmi1 |= HDMI0_AZ_FORMAT_WTRIG_MASK; } if (rdev->irq.gui_idle) { DRM_DEBUG("gui idle\n"); Loading @@ -3164,9 +3181,7 @@ int r600_irq_set(struct radeon_device *rdev) WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); WREG32(GRBM_INT_CNTL, grbm_int_cntl); WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1); if (ASIC_IS_DCE3(rdev)) { WREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, hdmi2); WREG32(DC_HPD1_INT_CONTROL, hpd1); WREG32(DC_HPD2_INT_CONTROL, hpd2); WREG32(DC_HPD3_INT_CONTROL, hpd3); Loading @@ -3174,12 +3189,18 @@ int r600_irq_set(struct radeon_device *rdev) if (ASIC_IS_DCE32(rdev)) { WREG32(DC_HPD5_INT_CONTROL, hpd5); WREG32(DC_HPD6_INT_CONTROL, hpd6); WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, hdmi0); WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, hdmi1); } else { WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1); } } else { WREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, hdmi2); WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1); } return 0; Loading @@ -3193,10 +3214,19 @@ static void r600_irq_ack(struct radeon_device *rdev) rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); if (ASIC_IS_DCE32(rdev)) { rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + HDMI_OFFSET0); rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + HDMI_OFFSET1); } else { rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS); } } else { rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); rdev->irq.stat_regs.r600.disp_int_cont2 = 0; rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); rdev->irq.stat_regs.r600.hdmi1_status = RREG32(HDMI1_STATUS); } rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); Loading Loading @@ -3262,17 +3292,32 @@ static void r600_irq_ack(struct radeon_device *rdev) tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD6_INT_CONTROL, tmp); } if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) { tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0); tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp); } if (RREG32(R600_HDMI_BLOCK1 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { WREG32_P(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) { tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1); tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp); } if (ASIC_IS_DCE3(rdev)) { if (RREG32(R600_HDMI_BLOCK3 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { WREG32_P(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); } else { if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL); tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); } if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { if (ASIC_IS_DCE3(rdev)) { tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL); tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); } else { if (RREG32(R600_HDMI_BLOCK2 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { WREG32_P(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL); tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); } } } } Loading Loading @@ -3348,6 +3393,7 @@ int r600_irq_process(struct radeon_device *rdev) u32 ring_index; unsigned long flags; bool queue_hotplug = false; bool queue_hdmi = false; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; Loading Loading @@ -3483,9 +3529,26 @@ int r600_irq_process(struct radeon_device *rdev) break; } break; case 21: /* HDMI */ DRM_DEBUG("IH: HDMI: 0x%x\n", src_data); r600_audio_schedule_polling(rdev); case 21: /* hdmi */ switch (src_data) { case 4: if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; queue_hdmi = true; DRM_DEBUG("IH: HDMI0\n"); } break; case 5: if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; queue_hdmi = true; DRM_DEBUG("IH: HDMI1\n"); } break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; case 176: /* CP_INT in ring buffer */ case 177: /* CP_INT in IB1 */ Loading Loading @@ -3517,6 +3580,8 @@ int r600_irq_process(struct radeon_device *rdev) goto restart_ih; if (queue_hotplug) schedule_work(&rdev->hotplug_work); if (queue_hdmi) schedule_work(&rdev->audio_work); rdev->ih.rptr = rptr; WREG32(IH_RB_RPTR, rdev->ih.rptr); spin_unlock_irqrestore(&rdev->ih.lock, flags); Loading drivers/gpu/drm/radeon/r600_audio.c +5 −58 Original line number Diff line number Diff line Loading @@ -29,8 +29,6 @@ #include "radeon_asic.h" #include "atom.h" #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ /* * check if the chipset is supported */ Loading Loading @@ -105,21 +103,13 @@ uint8_t r600_audio_category_code(struct radeon_device *rdev) return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; } /* * schedule next audio update event */ void r600_audio_schedule_polling(struct radeon_device *rdev) { mod_timer(&rdev->audio_timer, jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); } /* * update all hdmi interfaces with current audio parameters */ static void r600_audio_update_hdmi(unsigned long param) void r600_audio_update_hdmi(struct work_struct *work) { struct radeon_device *rdev = (struct radeon_device *)param; struct radeon_device *rdev = container_of(work, struct radeon_device, audio_work); struct drm_device *dev = rdev->ddev; int channels = r600_audio_channels(rdev); Loading @@ -127,9 +117,8 @@ static void r600_audio_update_hdmi(unsigned long param) int bps = r600_audio_bits_per_sample(rdev); uint8_t status_bits = r600_audio_status_bits(rdev); uint8_t category_code = r600_audio_category_code(rdev); struct drm_encoder *encoder; int changes = 0, still_going = 0; int changes = 0; changes |= channels != rdev->audio_channels; changes |= rate != rdev->audio_rate; Loading @@ -146,14 +135,9 @@ static void r600_audio_update_hdmi(unsigned long param) } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); still_going |= radeon_encoder->audio_polling_active; if (changes || r600_hdmi_buffer_status_changed(encoder)) r600_hdmi_update_audio_settings(encoder); } if (still_going) r600_audio_schedule_polling(rdev); } /* Loading @@ -177,7 +161,7 @@ static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) } /* * initialize the audio vars and register the update timer * initialize the audio vars */ int r600_audio_init(struct radeon_device *rdev) { Loading @@ -192,44 +176,9 @@ int r600_audio_init(struct radeon_device *rdev) rdev->audio_status_bits = 0; rdev->audio_category_code = 0; setup_timer( &rdev->audio_timer, r600_audio_update_hdmi, (unsigned long)rdev); return 0; } /* * enable the polling timer, to check for status changes */ void r600_audio_enable_polling(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); DRM_DEBUG("r600_audio_enable_polling: %d\n", radeon_encoder->audio_polling_active); if (radeon_encoder->audio_polling_active) return; radeon_encoder->audio_polling_active = 1; if (rdev->audio_enabled) mod_timer(&rdev->audio_timer, jiffies + 1); } /* * disable the polling timer, so we get no more status updates */ void r600_audio_disable_polling(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); DRM_DEBUG("r600_audio_disable_polling: %d\n", radeon_encoder->audio_polling_active); radeon_encoder->audio_polling_active = 0; } /* * atach the audio codec to the clock source of the encoder */ Loading Loading @@ -297,7 +246,5 @@ void r600_audio_fini(struct radeon_device *rdev) if (!rdev->audio_enabled) return; del_timer(&rdev->audio_timer); r600_audio_engine_enable(rdev, false); } drivers/gpu/drm/radeon/r600_hdmi.c +3 −14 Original line number Diff line number Diff line Loading @@ -548,19 +548,10 @@ void r600_hdmi_enable(struct drm_encoder *encoder) } } if (rdev->irq.installed && rdev->family != CHIP_RS600 && rdev->family != CHIP_RS690 && rdev->family != CHIP_RS740 && !ASIC_IS_DCE4(rdev)) { if (rdev->irq.installed) { /* if irq is available use it */ rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true; rdev->irq.afmt[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true; radeon_irq_set(rdev); r600_audio_disable_polling(encoder); } else { /* if not fallback to polling */ r600_audio_enable_polling(encoder); } DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", Loading Loading @@ -590,11 +581,9 @@ void r600_hdmi_disable(struct drm_encoder *encoder) offset, radeon_encoder->encoder_id); /* disable irq */ rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = false; rdev->irq.afmt[offset == R600_HDMI_BLOCK1 ? 0 : 1] = false; radeon_irq_set(rdev); /* disable polling */ r600_audio_disable_polling(encoder); if (ASIC_IS_DCE5(rdev)) { /* TODO */ Loading drivers/gpu/drm/radeon/radeon.h +14 −3 Original line number Diff line number Diff line Loading @@ -560,6 +560,7 @@ struct radeon_unpin_work { struct r500_irq_stat_regs { u32 disp_int; u32 hdmi0_status; }; struct r600_irq_stat_regs { Loading @@ -568,6 +569,8 @@ struct r600_irq_stat_regs { u32 disp_int_cont2; u32 d1grph_int; u32 d2grph_int; u32 hdmi0_status; u32 hdmi1_status; }; struct evergreen_irq_stat_regs { Loading @@ -583,6 +586,12 @@ 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; }; union radeon_irq_stat_regs { Loading @@ -593,7 +602,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_AFMT_BLOCKS 6 struct radeon_irq { bool installed; Loading @@ -605,7 +614,7 @@ struct radeon_irq { bool gui_idle; bool gui_idle_acked; wait_queue_head_t idle_queue; bool hdmi[RADEON_MAX_HDMI_BLOCKS]; bool afmt[RADEON_MAX_AFMT_BLOCKS]; spinlock_t sw_lock; int sw_refcount[RADEON_NUM_RINGS]; union radeon_irq_stat_regs stat_regs; Loading Loading @@ -1546,13 +1555,13 @@ struct radeon_device { struct r600_ih ih; /* r6/700 interrupt ring */ struct si_rlc rlc; struct work_struct hotplug_work; struct work_struct audio_work; int num_crtc; /* number of crtcs */ struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ struct mutex vram_mutex; /* audio stuff */ bool audio_enabled; struct timer_list audio_timer; int audio_channels; int audio_rate; int audio_bits_per_sample; Loading Loading @@ -1828,6 +1837,8 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, struct radeon_vm *vm, struct radeon_bo *bo); /* audio */ void r600_audio_update_hdmi(struct work_struct *work); /* * R600 vram scratch functions Loading Loading
drivers/gpu/drm/radeon/evergreen.c +128 −0 Original line number Diff line number Diff line Loading @@ -2594,6 +2594,7 @@ int evergreen_irq_set(struct radeon_device *rdev) u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; u32 grbm_int_cntl = 0; u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; if (!rdev->irq.installed) { WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); Loading @@ -2614,6 +2615,13 @@ 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; 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; if (rdev->family >= CHIP_CAYMAN) { /* enable CP interrupts on all rings */ if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { Loading Loading @@ -2690,6 +2698,30 @@ int evergreen_irq_set(struct radeon_device *rdev) DRM_DEBUG("evergreen_irq_set: hpd 6\n"); hpd6 |= DC_HPDx_INT_EN; } 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->irq.gui_idle) { DRM_DEBUG("gui idle\n"); grbm_int_cntl |= GUI_IDLE_INT_ENABLE; Loading Loading @@ -2732,6 +2764,13 @@ int evergreen_irq_set(struct radeon_device *rdev) WREG32(DC_HPD5_INT_CONTROL, hpd5); WREG32(DC_HPD6_INT_CONTROL, hpd6); 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); return 0; } Loading @@ -2756,6 +2795,13 @@ 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); if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) Loading Loading @@ -2829,6 +2875,36 @@ static void evergreen_irq_ack(struct radeon_device *rdev) tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD6_INT_CONTROL, tmp); } 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); } } void evergreen_irq_disable(struct radeon_device *rdev) Loading Loading @@ -2878,6 +2954,7 @@ int evergreen_irq_process(struct radeon_device *rdev) u32 ring_index; unsigned long flags; bool queue_hotplug = false; bool queue_hdmi = false; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; Loading Loading @@ -3111,6 +3188,55 @@ int evergreen_irq_process(struct radeon_device *rdev) break; } break; case 44: /* hdmi */ switch (src_data) { case 0: if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { 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) { 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) { 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) { 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) { 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) { 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); break; } break; case 176: /* CP_INT in ring buffer */ case 177: /* CP_INT in IB1 */ case 178: /* CP_INT in IB2 */ Loading Loading @@ -3154,6 +3280,8 @@ int evergreen_irq_process(struct radeon_device *rdev) goto restart_ih; if (queue_hotplug) schedule_work(&rdev->hotplug_work); if (queue_hdmi) schedule_work(&rdev->audio_work); rdev->ih.rptr = rptr; WREG32(IH_RB_RPTR, rdev->ih.rptr); spin_unlock_irqrestore(&rdev->ih.lock, flags); Loading
drivers/gpu/drm/radeon/r600.c +90 −25 Original line number Diff line number Diff line Loading @@ -2968,6 +2968,15 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) WREG32(DC_HPD5_INT_CONTROL, tmp); tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; WREG32(DC_HPD6_INT_CONTROL, tmp); tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp); tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp); } else { tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); } } else { WREG32(DACA_AUTODETECT_INT_CONTROL, 0); Loading @@ -2978,6 +2987,10 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); } } Loading Loading @@ -3074,7 +3087,7 @@ int r600_irq_set(struct radeon_device *rdev) u32 mode_int = 0; u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; u32 hdmi1, hdmi2; u32 hdmi0, hdmi1; u32 d1grph = 0, d2grph = 0; if (!rdev->irq.installed) { Loading @@ -3089,9 +3102,7 @@ int r600_irq_set(struct radeon_device *rdev) return 0; } hdmi1 = RREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; if (ASIC_IS_DCE3(rdev)) { hdmi2 = RREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; Loading @@ -3099,12 +3110,18 @@ int r600_irq_set(struct radeon_device *rdev) if (ASIC_IS_DCE32(rdev)) { hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK; hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK; } else { hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; } } else { hdmi2 = RREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN; hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; } if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { Loading Loading @@ -3146,13 +3163,13 @@ int r600_irq_set(struct radeon_device *rdev) DRM_DEBUG("r600_irq_set: hpd 6\n"); hpd6 |= DC_HPDx_INT_EN; } if (rdev->irq.hdmi[0]) { DRM_DEBUG("r600_irq_set: hdmi 1\n"); hdmi1 |= R600_HDMI_INT_EN; if (rdev->irq.afmt[0]) { DRM_DEBUG("r600_irq_set: hdmi 0\n"); hdmi0 |= HDMI0_AZ_FORMAT_WTRIG_MASK; } if (rdev->irq.hdmi[1]) { DRM_DEBUG("r600_irq_set: hdmi 2\n"); hdmi2 |= R600_HDMI_INT_EN; if (rdev->irq.afmt[1]) { DRM_DEBUG("r600_irq_set: hdmi 0\n"); hdmi1 |= HDMI0_AZ_FORMAT_WTRIG_MASK; } if (rdev->irq.gui_idle) { DRM_DEBUG("gui idle\n"); Loading @@ -3164,9 +3181,7 @@ int r600_irq_set(struct radeon_device *rdev) WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); WREG32(GRBM_INT_CNTL, grbm_int_cntl); WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1); if (ASIC_IS_DCE3(rdev)) { WREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, hdmi2); WREG32(DC_HPD1_INT_CONTROL, hpd1); WREG32(DC_HPD2_INT_CONTROL, hpd2); WREG32(DC_HPD3_INT_CONTROL, hpd3); Loading @@ -3174,12 +3189,18 @@ int r600_irq_set(struct radeon_device *rdev) if (ASIC_IS_DCE32(rdev)) { WREG32(DC_HPD5_INT_CONTROL, hpd5); WREG32(DC_HPD6_INT_CONTROL, hpd6); WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, hdmi0); WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, hdmi1); } else { WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1); } } else { WREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, hdmi2); WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1); } return 0; Loading @@ -3193,10 +3214,19 @@ static void r600_irq_ack(struct radeon_device *rdev) rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); if (ASIC_IS_DCE32(rdev)) { rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + HDMI_OFFSET0); rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + HDMI_OFFSET1); } else { rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS); } } else { rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); rdev->irq.stat_regs.r600.disp_int_cont2 = 0; rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); rdev->irq.stat_regs.r600.hdmi1_status = RREG32(HDMI1_STATUS); } rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); Loading Loading @@ -3262,17 +3292,32 @@ static void r600_irq_ack(struct radeon_device *rdev) tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD6_INT_CONTROL, tmp); } if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) { tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0); tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp); } if (RREG32(R600_HDMI_BLOCK1 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { WREG32_P(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) { tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1); tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp); } if (ASIC_IS_DCE3(rdev)) { if (RREG32(R600_HDMI_BLOCK3 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { WREG32_P(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); } else { if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL); tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); } if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { if (ASIC_IS_DCE3(rdev)) { tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL); tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); } else { if (RREG32(R600_HDMI_BLOCK2 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { WREG32_P(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL); tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); } } } } Loading Loading @@ -3348,6 +3393,7 @@ int r600_irq_process(struct radeon_device *rdev) u32 ring_index; unsigned long flags; bool queue_hotplug = false; bool queue_hdmi = false; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; Loading Loading @@ -3483,9 +3529,26 @@ int r600_irq_process(struct radeon_device *rdev) break; } break; case 21: /* HDMI */ DRM_DEBUG("IH: HDMI: 0x%x\n", src_data); r600_audio_schedule_polling(rdev); case 21: /* hdmi */ switch (src_data) { case 4: if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; queue_hdmi = true; DRM_DEBUG("IH: HDMI0\n"); } break; case 5: if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; queue_hdmi = true; DRM_DEBUG("IH: HDMI1\n"); } break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; case 176: /* CP_INT in ring buffer */ case 177: /* CP_INT in IB1 */ Loading Loading @@ -3517,6 +3580,8 @@ int r600_irq_process(struct radeon_device *rdev) goto restart_ih; if (queue_hotplug) schedule_work(&rdev->hotplug_work); if (queue_hdmi) schedule_work(&rdev->audio_work); rdev->ih.rptr = rptr; WREG32(IH_RB_RPTR, rdev->ih.rptr); spin_unlock_irqrestore(&rdev->ih.lock, flags); Loading
drivers/gpu/drm/radeon/r600_audio.c +5 −58 Original line number Diff line number Diff line Loading @@ -29,8 +29,6 @@ #include "radeon_asic.h" #include "atom.h" #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ /* * check if the chipset is supported */ Loading Loading @@ -105,21 +103,13 @@ uint8_t r600_audio_category_code(struct radeon_device *rdev) return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; } /* * schedule next audio update event */ void r600_audio_schedule_polling(struct radeon_device *rdev) { mod_timer(&rdev->audio_timer, jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); } /* * update all hdmi interfaces with current audio parameters */ static void r600_audio_update_hdmi(unsigned long param) void r600_audio_update_hdmi(struct work_struct *work) { struct radeon_device *rdev = (struct radeon_device *)param; struct radeon_device *rdev = container_of(work, struct radeon_device, audio_work); struct drm_device *dev = rdev->ddev; int channels = r600_audio_channels(rdev); Loading @@ -127,9 +117,8 @@ static void r600_audio_update_hdmi(unsigned long param) int bps = r600_audio_bits_per_sample(rdev); uint8_t status_bits = r600_audio_status_bits(rdev); uint8_t category_code = r600_audio_category_code(rdev); struct drm_encoder *encoder; int changes = 0, still_going = 0; int changes = 0; changes |= channels != rdev->audio_channels; changes |= rate != rdev->audio_rate; Loading @@ -146,14 +135,9 @@ static void r600_audio_update_hdmi(unsigned long param) } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); still_going |= radeon_encoder->audio_polling_active; if (changes || r600_hdmi_buffer_status_changed(encoder)) r600_hdmi_update_audio_settings(encoder); } if (still_going) r600_audio_schedule_polling(rdev); } /* Loading @@ -177,7 +161,7 @@ static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) } /* * initialize the audio vars and register the update timer * initialize the audio vars */ int r600_audio_init(struct radeon_device *rdev) { Loading @@ -192,44 +176,9 @@ int r600_audio_init(struct radeon_device *rdev) rdev->audio_status_bits = 0; rdev->audio_category_code = 0; setup_timer( &rdev->audio_timer, r600_audio_update_hdmi, (unsigned long)rdev); return 0; } /* * enable the polling timer, to check for status changes */ void r600_audio_enable_polling(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); DRM_DEBUG("r600_audio_enable_polling: %d\n", radeon_encoder->audio_polling_active); if (radeon_encoder->audio_polling_active) return; radeon_encoder->audio_polling_active = 1; if (rdev->audio_enabled) mod_timer(&rdev->audio_timer, jiffies + 1); } /* * disable the polling timer, so we get no more status updates */ void r600_audio_disable_polling(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); DRM_DEBUG("r600_audio_disable_polling: %d\n", radeon_encoder->audio_polling_active); radeon_encoder->audio_polling_active = 0; } /* * atach the audio codec to the clock source of the encoder */ Loading Loading @@ -297,7 +246,5 @@ void r600_audio_fini(struct radeon_device *rdev) if (!rdev->audio_enabled) return; del_timer(&rdev->audio_timer); r600_audio_engine_enable(rdev, false); }
drivers/gpu/drm/radeon/r600_hdmi.c +3 −14 Original line number Diff line number Diff line Loading @@ -548,19 +548,10 @@ void r600_hdmi_enable(struct drm_encoder *encoder) } } if (rdev->irq.installed && rdev->family != CHIP_RS600 && rdev->family != CHIP_RS690 && rdev->family != CHIP_RS740 && !ASIC_IS_DCE4(rdev)) { if (rdev->irq.installed) { /* if irq is available use it */ rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true; rdev->irq.afmt[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true; radeon_irq_set(rdev); r600_audio_disable_polling(encoder); } else { /* if not fallback to polling */ r600_audio_enable_polling(encoder); } DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", Loading Loading @@ -590,11 +581,9 @@ void r600_hdmi_disable(struct drm_encoder *encoder) offset, radeon_encoder->encoder_id); /* disable irq */ rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = false; rdev->irq.afmt[offset == R600_HDMI_BLOCK1 ? 0 : 1] = false; radeon_irq_set(rdev); /* disable polling */ r600_audio_disable_polling(encoder); if (ASIC_IS_DCE5(rdev)) { /* TODO */ Loading
drivers/gpu/drm/radeon/radeon.h +14 −3 Original line number Diff line number Diff line Loading @@ -560,6 +560,7 @@ struct radeon_unpin_work { struct r500_irq_stat_regs { u32 disp_int; u32 hdmi0_status; }; struct r600_irq_stat_regs { Loading @@ -568,6 +569,8 @@ struct r600_irq_stat_regs { u32 disp_int_cont2; u32 d1grph_int; u32 d2grph_int; u32 hdmi0_status; u32 hdmi1_status; }; struct evergreen_irq_stat_regs { Loading @@ -583,6 +586,12 @@ 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; }; union radeon_irq_stat_regs { Loading @@ -593,7 +602,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_AFMT_BLOCKS 6 struct radeon_irq { bool installed; Loading @@ -605,7 +614,7 @@ struct radeon_irq { bool gui_idle; bool gui_idle_acked; wait_queue_head_t idle_queue; bool hdmi[RADEON_MAX_HDMI_BLOCKS]; bool afmt[RADEON_MAX_AFMT_BLOCKS]; spinlock_t sw_lock; int sw_refcount[RADEON_NUM_RINGS]; union radeon_irq_stat_regs stat_regs; Loading Loading @@ -1546,13 +1555,13 @@ struct radeon_device { struct r600_ih ih; /* r6/700 interrupt ring */ struct si_rlc rlc; struct work_struct hotplug_work; struct work_struct audio_work; int num_crtc; /* number of crtcs */ struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ struct mutex vram_mutex; /* audio stuff */ bool audio_enabled; struct timer_list audio_timer; int audio_channels; int audio_rate; int audio_bits_per_sample; Loading Loading @@ -1828,6 +1837,8 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, struct radeon_vm *vm, struct radeon_bo *bo); /* audio */ void r600_audio_update_hdmi(struct work_struct *work); /* * R600 vram scratch functions Loading