@ -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 ) ;
@ -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 ) ;
}
}
@ -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 ) {
@ -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 ;
@ -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 ] ) {
@ -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 " ) ;
@ -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 ) ;
@ -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 ;
@ -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 ) ;
@ -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 ( 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 ( 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 ) ;
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 ( 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 ) ;
}
} 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 ) ;
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 {
tmp = RREG32 ( HDMI1_AUDIO_PACKET_CONTROL ) ;
tmp | = HDMI0_AZ_FORMAT_WTRIG_ACK ;
WREG32 ( HDMI1_AUDIO_PACKET_CONTROL , tmp ) ;
}
}
}
}
@ -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 ;
@ -3483,9 +3529,26 @@ restart_ih:
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 */
@ -3517,6 +3580,8 @@ restart_ih:
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 ) ;