aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600.c
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-03-30 08:59:57 -0400
committerDave Airlie <airlied@redhat.com>2012-04-24 04:50:14 -0400
commitf122c6109b1a79153cfb1e188c665ce3f312a886 (patch)
tree9b8d9211c0be59a0a96a906373bd85d187d23ab4 /drivers/gpu/drm/radeon/r600.c
parent3a2a67aa28725bb500505087067e7830cfa9c137 (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/r600.c')
-rw-r--r--drivers/gpu/drm/radeon/r600.c115
1 files changed, 90 insertions, 25 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 4added1c7ee9..ba637d95965b 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2968,6 +2968,15 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev)
2968 WREG32(DC_HPD5_INT_CONTROL, tmp); 2968 WREG32(DC_HPD5_INT_CONTROL, tmp);
2969 tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; 2969 tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
2970 WREG32(DC_HPD6_INT_CONTROL, tmp); 2970 WREG32(DC_HPD6_INT_CONTROL, tmp);
2971 tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
2972 WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp);
2973 tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
2974 WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp);
2975 } else {
2976 tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
2977 WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp);
2978 tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
2979 WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp);
2971 } 2980 }
2972 } else { 2981 } else {
2973 WREG32(DACA_AUTODETECT_INT_CONTROL, 0); 2982 WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
@@ -2978,6 +2987,10 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev)
2978 WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); 2987 WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
2979 tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; 2988 tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
2980 WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); 2989 WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
2990 tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
2991 WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp);
2992 tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
2993 WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp);
2981 } 2994 }
2982} 2995}
2983 2996
@@ -3074,7 +3087,7 @@ int r600_irq_set(struct radeon_device *rdev)
3074 u32 mode_int = 0; 3087 u32 mode_int = 0;
3075 u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; 3088 u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
3076 u32 grbm_int_cntl = 0; 3089 u32 grbm_int_cntl = 0;
3077 u32 hdmi1, hdmi2; 3090 u32 hdmi0, hdmi1;
3078 u32 d1grph = 0, d2grph = 0; 3091 u32 d1grph = 0, d2grph = 0;
3079 3092
3080 if (!rdev->irq.installed) { 3093 if (!rdev->irq.installed) {
@@ -3089,9 +3102,7 @@ int r600_irq_set(struct radeon_device *rdev)
3089 return 0; 3102 return 0;
3090 } 3103 }
3091 3104
3092 hdmi1 = RREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
3093 if (ASIC_IS_DCE3(rdev)) { 3105 if (ASIC_IS_DCE3(rdev)) {
3094 hdmi2 = RREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
3095 hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; 3106 hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
3096 hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; 3107 hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
3097 hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; 3108 hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
@@ -3099,12 +3110,18 @@ int r600_irq_set(struct radeon_device *rdev)
3099 if (ASIC_IS_DCE32(rdev)) { 3110 if (ASIC_IS_DCE32(rdev)) {
3100 hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; 3111 hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
3101 hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; 3112 hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
3113 hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
3114 hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
3115 } else {
3116 hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
3117 hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
3102 } 3118 }
3103 } else { 3119 } else {
3104 hdmi2 = RREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
3105 hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; 3120 hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN;
3106 hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; 3121 hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN;
3107 hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; 3122 hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN;
3123 hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
3124 hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
3108 } 3125 }
3109 3126
3110 if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { 3127 if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) {
@@ -3146,13 +3163,13 @@ int r600_irq_set(struct radeon_device *rdev)
3146 DRM_DEBUG("r600_irq_set: hpd 6\n"); 3163 DRM_DEBUG("r600_irq_set: hpd 6\n");
3147 hpd6 |= DC_HPDx_INT_EN; 3164 hpd6 |= DC_HPDx_INT_EN;
3148 } 3165 }
3149 if (rdev->irq.hdmi[0]) { 3166 if (rdev->irq.afmt[0]) {
3150 DRM_DEBUG("r600_irq_set: hdmi 1\n"); 3167 DRM_DEBUG("r600_irq_set: hdmi 0\n");
3151 hdmi1 |= R600_HDMI_INT_EN; 3168 hdmi0 |= HDMI0_AZ_FORMAT_WTRIG_MASK;
3152 } 3169 }
3153 if (rdev->irq.hdmi[1]) { 3170 if (rdev->irq.afmt[1]) {
3154 DRM_DEBUG("r600_irq_set: hdmi 2\n"); 3171 DRM_DEBUG("r600_irq_set: hdmi 0\n");
3155 hdmi2 |= R600_HDMI_INT_EN; 3172 hdmi1 |= HDMI0_AZ_FORMAT_WTRIG_MASK;
3156 } 3173 }
3157 if (rdev->irq.gui_idle) { 3174 if (rdev->irq.gui_idle) {
3158 DRM_DEBUG("gui idle\n"); 3175 DRM_DEBUG("gui idle\n");
@@ -3164,9 +3181,7 @@ int r600_irq_set(struct radeon_device *rdev)
3164 WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); 3181 WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph);
3165 WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); 3182 WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph);
3166 WREG32(GRBM_INT_CNTL, grbm_int_cntl); 3183 WREG32(GRBM_INT_CNTL, grbm_int_cntl);
3167 WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1);
3168 if (ASIC_IS_DCE3(rdev)) { 3184 if (ASIC_IS_DCE3(rdev)) {
3169 WREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, hdmi2);
3170 WREG32(DC_HPD1_INT_CONTROL, hpd1); 3185 WREG32(DC_HPD1_INT_CONTROL, hpd1);
3171 WREG32(DC_HPD2_INT_CONTROL, hpd2); 3186 WREG32(DC_HPD2_INT_CONTROL, hpd2);
3172 WREG32(DC_HPD3_INT_CONTROL, hpd3); 3187 WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -3174,12 +3189,18 @@ int r600_irq_set(struct radeon_device *rdev)
3174 if (ASIC_IS_DCE32(rdev)) { 3189 if (ASIC_IS_DCE32(rdev)) {
3175 WREG32(DC_HPD5_INT_CONTROL, hpd5); 3190 WREG32(DC_HPD5_INT_CONTROL, hpd5);
3176 WREG32(DC_HPD6_INT_CONTROL, hpd6); 3191 WREG32(DC_HPD6_INT_CONTROL, hpd6);
3192 WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, hdmi0);
3193 WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, hdmi1);
3194 } else {
3195 WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
3196 WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1);
3177 } 3197 }
3178 } else { 3198 } else {
3179 WREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, hdmi2);
3180 WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); 3199 WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
3181 WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); 3200 WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
3182 WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); 3201 WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3);
3202 WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
3203 WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1);
3183 } 3204 }
3184 3205
3185 return 0; 3206 return 0;
@@ -3193,10 +3214,19 @@ static void r600_irq_ack(struct radeon_device *rdev)
3193 rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); 3214 rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
3194 rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); 3215 rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
3195 rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); 3216 rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
3217 if (ASIC_IS_DCE32(rdev)) {
3218 rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + HDMI_OFFSET0);
3219 rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + HDMI_OFFSET1);
3220 } else {
3221 rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS);
3222 rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS);
3223 }
3196 } else { 3224 } else {
3197 rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); 3225 rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS);
3198 rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); 3226 rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
3199 rdev->irq.stat_regs.r600.disp_int_cont2 = 0; 3227 rdev->irq.stat_regs.r600.disp_int_cont2 = 0;
3228 rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS);
3229 rdev->irq.stat_regs.r600.hdmi1_status = RREG32(HDMI1_STATUS);
3200 } 3230 }
3201 rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); 3231 rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
3202 rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); 3232 rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
@@ -3262,17 +3292,32 @@ static void r600_irq_ack(struct radeon_device *rdev)
3262 tmp |= DC_HPDx_INT_ACK; 3292 tmp |= DC_HPDx_INT_ACK;
3263 WREG32(DC_HPD6_INT_CONTROL, tmp); 3293 WREG32(DC_HPD6_INT_CONTROL, tmp);
3264 } 3294 }
3265 } 3295 if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) {
3266 if (RREG32(R600_HDMI_BLOCK1 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { 3296 tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0);
3267 WREG32_P(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); 3297 tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
3268 } 3298 WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET0, tmp);
3269 if (ASIC_IS_DCE3(rdev)) { 3299 }
3270 if (RREG32(R600_HDMI_BLOCK3 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { 3300 if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) {
3271 WREG32_P(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); 3301 tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1);
3302 tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
3303 WREG32(AFMT_AUDIO_PACKET_CONTROL + HDMI_OFFSET1, tmp);
3272 } 3304 }
3273 } else { 3305 } else {
3274 if (RREG32(R600_HDMI_BLOCK2 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) { 3306 if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) {
3275 WREG32_P(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK); 3307 tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL);
3308 tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK;
3309 WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp);
3310 }
3311 if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) {
3312 if (ASIC_IS_DCE3(rdev)) {
3313 tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL);
3314 tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK;
3315 WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp);
3316 } else {
3317 tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL);
3318 tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK;
3319 WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp);
3320 }
3276 } 3321 }
3277 } 3322 }
3278} 3323}
@@ -3348,6 +3393,7 @@ int r600_irq_process(struct radeon_device *rdev)
3348 u32 ring_index; 3393 u32 ring_index;
3349 unsigned long flags; 3394 unsigned long flags;
3350 bool queue_hotplug = false; 3395 bool queue_hotplug = false;
3396 bool queue_hdmi = false;
3351 3397
3352 if (!rdev->ih.enabled || rdev->shutdown) 3398 if (!rdev->ih.enabled || rdev->shutdown)
3353 return IRQ_NONE; 3399 return IRQ_NONE;
@@ -3483,9 +3529,26 @@ restart_ih:
3483 break; 3529 break;
3484 } 3530 }
3485 break; 3531 break;
3486 case 21: /* HDMI */ 3532 case 21: /* hdmi */
3487 DRM_DEBUG("IH: HDMI: 0x%x\n", src_data); 3533 switch (src_data) {
3488 r600_audio_schedule_polling(rdev); 3534 case 4:
3535 if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) {
3536 rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG;
3537 queue_hdmi = true;
3538 DRM_DEBUG("IH: HDMI0\n");
3539 }
3540 break;
3541 case 5:
3542 if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) {
3543 rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG;
3544 queue_hdmi = true;
3545 DRM_DEBUG("IH: HDMI1\n");
3546 }
3547 break;
3548 default:
3549 DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
3550 break;
3551 }
3489 break; 3552 break;
3490 case 176: /* CP_INT in ring buffer */ 3553 case 176: /* CP_INT in ring buffer */
3491 case 177: /* CP_INT in IB1 */ 3554 case 177: /* CP_INT in IB1 */
@@ -3517,6 +3580,8 @@ restart_ih:
3517 goto restart_ih; 3580 goto restart_ih;
3518 if (queue_hotplug) 3581 if (queue_hotplug)
3519 schedule_work(&rdev->hotplug_work); 3582 schedule_work(&rdev->hotplug_work);
3583 if (queue_hdmi)
3584 schedule_work(&rdev->audio_work);
3520 rdev->ih.rptr = rptr; 3585 rdev->ih.rptr = rptr;
3521 WREG32(IH_RB_RPTR, rdev->ih.rptr); 3586 WREG32(IH_RB_RPTR, rdev->ih.rptr);
3522 spin_unlock_irqrestore(&rdev->ih.lock, flags); 3587 spin_unlock_irqrestore(&rdev->ih.lock, flags);