diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-03-30 08:59:57 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-04-24 04:50:14 -0400 |
commit | f122c6109b1a79153cfb1e188c665ce3f312a886 (patch) | |
tree | 9b8d9211c0be59a0a96a906373bd85d187d23ab4 /drivers/gpu/drm/radeon/evergreen.c | |
parent | 3a2a67aa28725bb500505087067e7830cfa9c137 (diff) |
drm/radeon/kms: fix up audio interrupt handling
- add support for rs6xx
- add support for DCE4/5
- fixup 6xx/7xx
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index cfa372cb1cb..eed7acefb49 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -2594,6 +2594,7 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
2594 | u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; | 2594 | u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; |
2595 | u32 grbm_int_cntl = 0; | 2595 | u32 grbm_int_cntl = 0; |
2596 | u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; | 2596 | u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; |
2597 | u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; | ||
2597 | 2598 | ||
2598 | if (!rdev->irq.installed) { | 2599 | if (!rdev->irq.installed) { |
2599 | WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); | 2600 | WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); |
@@ -2614,6 +2615,13 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
2614 | hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; | 2615 | hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; |
2615 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; | 2616 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; |
2616 | 2617 | ||
2618 | afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2619 | afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2620 | afmt3 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2621 | afmt4 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2622 | afmt5 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2623 | afmt6 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2624 | |||
2617 | if (rdev->family >= CHIP_CAYMAN) { | 2625 | if (rdev->family >= CHIP_CAYMAN) { |
2618 | /* enable CP interrupts on all rings */ | 2626 | /* enable CP interrupts on all rings */ |
2619 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 2627 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { |
@@ -2690,6 +2698,30 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
2690 | DRM_DEBUG("evergreen_irq_set: hpd 6\n"); | 2698 | DRM_DEBUG("evergreen_irq_set: hpd 6\n"); |
2691 | hpd6 |= DC_HPDx_INT_EN; | 2699 | hpd6 |= DC_HPDx_INT_EN; |
2692 | } | 2700 | } |
2701 | if (rdev->irq.afmt[0]) { | ||
2702 | DRM_DEBUG("evergreen_irq_set: hdmi 0\n"); | ||
2703 | afmt1 |= AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2704 | } | ||
2705 | if (rdev->irq.afmt[1]) { | ||
2706 | DRM_DEBUG("evergreen_irq_set: hdmi 1\n"); | ||
2707 | afmt2 |= AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2708 | } | ||
2709 | if (rdev->irq.afmt[2]) { | ||
2710 | DRM_DEBUG("evergreen_irq_set: hdmi 2\n"); | ||
2711 | afmt3 |= AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2712 | } | ||
2713 | if (rdev->irq.afmt[3]) { | ||
2714 | DRM_DEBUG("evergreen_irq_set: hdmi 3\n"); | ||
2715 | afmt4 |= AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2716 | } | ||
2717 | if (rdev->irq.afmt[4]) { | ||
2718 | DRM_DEBUG("evergreen_irq_set: hdmi 4\n"); | ||
2719 | afmt5 |= AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2720 | } | ||
2721 | if (rdev->irq.afmt[5]) { | ||
2722 | DRM_DEBUG("evergreen_irq_set: hdmi 5\n"); | ||
2723 | afmt6 |= AFMT_AZ_FORMAT_WTRIG_MASK; | ||
2724 | } | ||
2693 | if (rdev->irq.gui_idle) { | 2725 | if (rdev->irq.gui_idle) { |
2694 | DRM_DEBUG("gui idle\n"); | 2726 | DRM_DEBUG("gui idle\n"); |
2695 | grbm_int_cntl |= GUI_IDLE_INT_ENABLE; | 2727 | grbm_int_cntl |= GUI_IDLE_INT_ENABLE; |
@@ -2732,6 +2764,13 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
2732 | WREG32(DC_HPD5_INT_CONTROL, hpd5); | 2764 | WREG32(DC_HPD5_INT_CONTROL, hpd5); |
2733 | WREG32(DC_HPD6_INT_CONTROL, hpd6); | 2765 | WREG32(DC_HPD6_INT_CONTROL, hpd6); |
2734 | 2766 | ||
2767 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1); | ||
2768 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2); | ||
2769 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, afmt3); | ||
2770 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, afmt4); | ||
2771 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5); | ||
2772 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6); | ||
2773 | |||
2735 | return 0; | 2774 | return 0; |
2736 | } | 2775 | } |
2737 | 2776 | ||
@@ -2756,6 +2795,13 @@ static void evergreen_irq_ack(struct radeon_device *rdev) | |||
2756 | rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); | 2795 | rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); |
2757 | } | 2796 | } |
2758 | 2797 | ||
2798 | rdev->irq.stat_regs.evergreen.afmt_status1 = RREG32(AFMT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); | ||
2799 | rdev->irq.stat_regs.evergreen.afmt_status2 = RREG32(AFMT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); | ||
2800 | rdev->irq.stat_regs.evergreen.afmt_status3 = RREG32(AFMT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); | ||
2801 | rdev->irq.stat_regs.evergreen.afmt_status4 = RREG32(AFMT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); | ||
2802 | rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); | ||
2803 | rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); | ||
2804 | |||
2759 | if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) | 2805 | if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) |
2760 | WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); | 2806 | WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); |
2761 | if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) | 2807 | if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) |
@@ -2829,6 +2875,36 @@ static void evergreen_irq_ack(struct radeon_device *rdev) | |||
2829 | tmp |= DC_HPDx_INT_ACK; | 2875 | tmp |= DC_HPDx_INT_ACK; |
2830 | WREG32(DC_HPD6_INT_CONTROL, tmp); | 2876 | WREG32(DC_HPD6_INT_CONTROL, tmp); |
2831 | } | 2877 | } |
2878 | if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { | ||
2879 | tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); | ||
2880 | tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; | ||
2881 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, tmp); | ||
2882 | } | ||
2883 | if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { | ||
2884 | tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); | ||
2885 | tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; | ||
2886 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, tmp); | ||
2887 | } | ||
2888 | if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { | ||
2889 | tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); | ||
2890 | tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; | ||
2891 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, tmp); | ||
2892 | } | ||
2893 | if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { | ||
2894 | tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); | ||
2895 | tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; | ||
2896 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, tmp); | ||
2897 | } | ||
2898 | if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { | ||
2899 | tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); | ||
2900 | tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; | ||
2901 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, tmp); | ||
2902 | } | ||
2903 | if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { | ||
2904 | tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); | ||
2905 | tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; | ||
2906 | WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, tmp); | ||
2907 | } | ||
2832 | } | 2908 | } |
2833 | 2909 | ||
2834 | void evergreen_irq_disable(struct radeon_device *rdev) | 2910 | void evergreen_irq_disable(struct radeon_device *rdev) |
@@ -2878,6 +2954,7 @@ int evergreen_irq_process(struct radeon_device *rdev) | |||
2878 | u32 ring_index; | 2954 | u32 ring_index; |
2879 | unsigned long flags; | 2955 | unsigned long flags; |
2880 | bool queue_hotplug = false; | 2956 | bool queue_hotplug = false; |
2957 | bool queue_hdmi = false; | ||
2881 | 2958 | ||
2882 | if (!rdev->ih.enabled || rdev->shutdown) | 2959 | if (!rdev->ih.enabled || rdev->shutdown) |
2883 | return IRQ_NONE; | 2960 | return IRQ_NONE; |
@@ -3111,6 +3188,55 @@ restart_ih: | |||
3111 | break; | 3188 | break; |
3112 | } | 3189 | } |
3113 | break; | 3190 | break; |
3191 | case 44: /* hdmi */ | ||
3192 | switch (src_data) { | ||
3193 | case 0: | ||
3194 | if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { | ||
3195 | rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; | ||
3196 | queue_hdmi = true; | ||
3197 | DRM_DEBUG("IH: HDMI0\n"); | ||
3198 | } | ||
3199 | break; | ||
3200 | case 1: | ||
3201 | if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { | ||
3202 | rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; | ||
3203 | queue_hdmi = true; | ||
3204 | DRM_DEBUG("IH: HDMI1\n"); | ||
3205 | } | ||
3206 | break; | ||
3207 | case 2: | ||
3208 | if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { | ||
3209 | rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; | ||
3210 | queue_hdmi = true; | ||
3211 | DRM_DEBUG("IH: HDMI2\n"); | ||
3212 | } | ||
3213 | break; | ||
3214 | case 3: | ||
3215 | if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { | ||
3216 | rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; | ||
3217 | queue_hdmi = true; | ||
3218 | DRM_DEBUG("IH: HDMI3\n"); | ||
3219 | } | ||
3220 | break; | ||
3221 | case 4: | ||
3222 | if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { | ||
3223 | rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; | ||
3224 | queue_hdmi = true; | ||
3225 | DRM_DEBUG("IH: HDMI4\n"); | ||
3226 | } | ||
3227 | break; | ||
3228 | case 5: | ||
3229 | if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { | ||
3230 | rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; | ||
3231 | queue_hdmi = true; | ||
3232 | DRM_DEBUG("IH: HDMI5\n"); | ||
3233 | } | ||
3234 | break; | ||
3235 | default: | ||
3236 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | ||
3237 | break; | ||
3238 | } | ||
3239 | break; | ||
3114 | case 176: /* CP_INT in ring buffer */ | 3240 | case 176: /* CP_INT in ring buffer */ |
3115 | case 177: /* CP_INT in IB1 */ | 3241 | case 177: /* CP_INT in IB1 */ |
3116 | case 178: /* CP_INT in IB2 */ | 3242 | case 178: /* CP_INT in IB2 */ |
@@ -3154,6 +3280,8 @@ restart_ih: | |||
3154 | goto restart_ih; | 3280 | goto restart_ih; |
3155 | if (queue_hotplug) | 3281 | if (queue_hotplug) |
3156 | schedule_work(&rdev->hotplug_work); | 3282 | schedule_work(&rdev->hotplug_work); |
3283 | if (queue_hdmi) | ||
3284 | schedule_work(&rdev->audio_work); | ||
3157 | rdev->ih.rptr = rptr; | 3285 | rdev->ih.rptr = rptr; |
3158 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | 3286 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |
3159 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3287 | spin_unlock_irqrestore(&rdev->ih.lock, flags); |