2012-05-06 19:29:44 +04:00
/*
* Copyright 2008 Advanced Micro Devices , Inc .
* Copyright 2008 Red Hat Inc .
* Copyright 2009 Christian König .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDER ( S ) OR AUTHOR ( S ) BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*
* Authors : Christian König
* Rafał Miłecki
*/
2013-01-14 16:36:30 +04:00
# include <linux/hdmi.h>
2012-10-02 21:01:07 +04:00
# include <drm/drmP.h>
# include <drm/radeon_drm.h>
2012-05-06 19:29:44 +04:00
# include "radeon.h"
# include "radeon_asic.h"
2015-01-22 18:41:55 +03:00
# include "radeon_audio.h"
2012-05-06 19:29:44 +04:00
# include "evergreend.h"
# include "atom.h"
2014-09-19 01:26:39 +04:00
/* enable the audio stream */
2014-12-03 23:29:53 +03:00
void dce4_audio_enable ( struct radeon_device * rdev ,
2014-09-19 01:26:39 +04:00
struct r600_audio_pin * pin ,
u8 enable_mask )
{
u32 tmp = RREG32 ( AZ_HOT_PLUG_CONTROL ) ;
if ( ! pin )
return ;
if ( enable_mask ) {
tmp | = AUDIO_ENABLED ;
if ( enable_mask & 1 )
tmp | = PIN0_AUDIO_ENABLED ;
if ( enable_mask & 2 )
tmp | = PIN1_AUDIO_ENABLED ;
if ( enable_mask & 4 )
tmp | = PIN2_AUDIO_ENABLED ;
if ( enable_mask & 8 )
tmp | = PIN3_AUDIO_ENABLED ;
} else {
tmp & = ~ ( AUDIO_ENABLED |
PIN0_AUDIO_ENABLED |
PIN1_AUDIO_ENABLED |
PIN2_AUDIO_ENABLED |
PIN3_AUDIO_ENABLED ) ;
}
WREG32 ( AZ_HOT_PLUG_CONTROL , tmp ) ;
}
2014-12-07 04:19:16 +03:00
void evergreen_hdmi_update_acr ( struct drm_encoder * encoder , long offset ,
const struct radeon_hdmi_acr * acr )
2012-05-06 19:29:44 +04:00
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
2014-12-07 04:19:16 +03:00
int bpc = 8 ;
if ( encoder - > crtc ) {
struct radeon_crtc * radeon_crtc = to_radeon_crtc ( encoder - > crtc ) ;
bpc = radeon_crtc - > bpc ;
}
2012-05-06 19:29:44 +04:00
2014-12-07 04:19:16 +03:00
if ( bpc > 8 )
WREG32 ( HDMI_ACR_PACKET_CONTROL + offset ,
HDMI_ACR_AUTO_SEND ) ; /* allow hw to sent ACR packets when required */
else
WREG32 ( HDMI_ACR_PACKET_CONTROL + offset ,
HDMI_ACR_SOURCE | /* select SW CTS value */
HDMI_ACR_AUTO_SEND ) ; /* allow hw to sent ACR packets when required */
WREG32 ( HDMI_ACR_32_0 + offset , HDMI_ACR_CTS_32 ( acr - > cts_32khz ) ) ;
WREG32 ( HDMI_ACR_32_1 + offset , acr - > n_32khz ) ;
2012-05-06 19:29:44 +04:00
2014-12-07 04:19:16 +03:00
WREG32 ( HDMI_ACR_44_0 + offset , HDMI_ACR_CTS_44 ( acr - > cts_44_1khz ) ) ;
WREG32 ( HDMI_ACR_44_1 + offset , acr - > n_44_1khz ) ;
2012-05-06 19:29:44 +04:00
2014-12-07 04:19:16 +03:00
WREG32 ( HDMI_ACR_48_0 + offset , HDMI_ACR_CTS_48 ( acr - > cts_48khz ) ) ;
WREG32 ( HDMI_ACR_48_1 + offset , acr - > n_48khz ) ;
2012-05-06 19:29:44 +04:00
}
2014-12-02 19:20:48 +03:00
void dce4_afmt_write_latency_fields ( struct drm_encoder * encoder ,
struct drm_connector * connector , struct drm_display_mode * mode )
2013-10-11 01:54:51 +04:00
{
struct radeon_device * rdev = encoder - > dev - > dev_private ;
u32 tmp = 0 ;
if ( mode - > flags & DRM_MODE_FLAG_INTERLACE ) {
if ( connector - > latency_present [ 1 ] )
tmp = VIDEO_LIPSYNC ( connector - > video_latency [ 1 ] ) |
AUDIO_LIPSYNC ( connector - > audio_latency [ 1 ] ) ;
else
tmp = VIDEO_LIPSYNC ( 255 ) | AUDIO_LIPSYNC ( 255 ) ;
} else {
if ( connector - > latency_present [ 0 ] )
tmp = VIDEO_LIPSYNC ( connector - > video_latency [ 0 ] ) |
AUDIO_LIPSYNC ( connector - > audio_latency [ 0 ] ) ;
else
tmp = VIDEO_LIPSYNC ( 255 ) | AUDIO_LIPSYNC ( 255 ) ;
}
2014-12-02 19:20:48 +03:00
WREG32_ENDPOINT ( 0 , AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC , tmp ) ;
2013-10-11 01:54:51 +04:00
}
2014-12-02 02:02:57 +03:00
void dce4_afmt_hdmi_write_speaker_allocation ( struct drm_encoder * encoder ,
u8 * sadb , int sad_count )
2013-08-15 17:34:07 +04:00
{
struct radeon_device * rdev = encoder - > dev - > dev_private ;
u32 tmp ;
/* program the speaker allocation */
2014-12-02 02:02:57 +03:00
tmp = RREG32_ENDPOINT ( 0 , AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER ) ;
2013-08-15 17:34:07 +04:00
tmp & = ~ ( DP_CONNECTION | SPEAKER_ALLOCATION_MASK ) ;
/* set HDMI mode */
tmp | = HDMI_CONNECTION ;
if ( sad_count )
tmp | = SPEAKER_ALLOCATION ( sadb [ 0 ] ) ;
else
tmp | = SPEAKER_ALLOCATION ( 5 ) ; /* stereo */
2014-12-02 02:02:57 +03:00
WREG32_ENDPOINT ( 0 , AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER , tmp ) ;
}
2013-08-15 17:34:07 +04:00
2014-12-02 02:02:57 +03:00
void dce4_afmt_dp_write_speaker_allocation ( struct drm_encoder * encoder ,
u8 * sadb , int sad_count )
{
struct radeon_device * rdev = encoder - > dev - > dev_private ;
u32 tmp ;
/* program the speaker allocation */
tmp = RREG32_ENDPOINT ( 0 , AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER ) ;
tmp & = ~ ( HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK ) ;
/* set DP mode */
tmp | = DP_CONNECTION ;
if ( sad_count )
tmp | = SPEAKER_ALLOCATION ( sadb [ 0 ] ) ;
else
tmp | = SPEAKER_ALLOCATION ( 5 ) ; /* stereo */
WREG32_ENDPOINT ( 0 , AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER , tmp ) ;
2013-08-15 17:34:07 +04:00
}
2015-01-22 18:41:55 +03:00
void evergreen_hdmi_write_sad_regs ( struct drm_encoder * encoder ,
struct cea_sad * sads , int sad_count )
2013-04-19 21:01:26 +04:00
{
2015-01-22 18:41:55 +03:00
int i ;
2013-04-19 21:01:26 +04:00
struct radeon_device * rdev = encoder - > dev - > dev_private ;
static const u16 eld_reg_to_type [ ] [ 2 ] = {
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0 , HDMI_AUDIO_CODING_TYPE_PCM } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1 , HDMI_AUDIO_CODING_TYPE_AC3 } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2 , HDMI_AUDIO_CODING_TYPE_MPEG1 } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3 , HDMI_AUDIO_CODING_TYPE_MP3 } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4 , HDMI_AUDIO_CODING_TYPE_MPEG2 } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5 , HDMI_AUDIO_CODING_TYPE_AAC_LC } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6 , HDMI_AUDIO_CODING_TYPE_DTS } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7 , HDMI_AUDIO_CODING_TYPE_ATRAC } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9 , HDMI_AUDIO_CODING_TYPE_EAC3 } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10 , HDMI_AUDIO_CODING_TYPE_DTS_HD } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11 , HDMI_AUDIO_CODING_TYPE_MLP } ,
{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13 , HDMI_AUDIO_CODING_TYPE_WMA_PRO } ,
} ;
for ( i = 0 ; i < ARRAY_SIZE ( eld_reg_to_type ) ; i + + ) {
u32 value = 0 ;
2013-10-29 03:19:16 +04:00
u8 stereo_freqs = 0 ;
int max_channels = - 1 ;
2013-04-19 21:01:26 +04:00
int j ;
for ( j = 0 ; j < sad_count ; j + + ) {
struct cea_sad * sad = & sads [ j ] ;
if ( sad - > format = = eld_reg_to_type [ i ] [ 1 ] ) {
2013-10-29 03:19:16 +04:00
if ( sad - > channels > max_channels ) {
value = MAX_CHANNELS ( sad - > channels ) |
DESCRIPTOR_BYTE_2 ( sad - > byte2 ) |
SUPPORTED_FREQUENCIES ( sad - > freq ) ;
max_channels = sad - > channels ;
}
2013-04-19 21:01:26 +04:00
if ( sad - > format = = HDMI_AUDIO_CODING_TYPE_PCM )
2013-10-29 03:19:16 +04:00
stereo_freqs | = sad - > freq ;
else
break ;
2013-04-19 21:01:26 +04:00
}
}
2013-10-29 03:19:16 +04:00
value | = SUPPORTED_FREQUENCIES_STEREO ( stereo_freqs ) ;
2015-01-22 18:41:55 +03:00
WREG32_ENDPOINT ( 0 , eld_reg_to_type [ i ] [ 0 ] , value ) ;
2013-04-19 21:01:26 +04:00
}
}
2012-05-06 19:29:44 +04:00
/*
2014-12-06 01:59:56 +03:00
* build a AVI Info Frame
2012-05-06 19:29:44 +04:00
*/
2014-12-09 02:28:33 +03:00
void evergreen_set_avi_packet ( struct radeon_device * rdev , u32 offset ,
2014-12-06 01:59:56 +03:00
unsigned char * buffer , size_t size )
2012-05-06 19:29:44 +04:00
{
2013-01-14 16:36:30 +04:00
uint8_t * frame = buffer + 3 ;
2012-05-06 19:29:44 +04:00
WREG32 ( AFMT_AVI_INFO0 + offset ,
frame [ 0x0 ] | ( frame [ 0x1 ] < < 8 ) | ( frame [ 0x2 ] < < 16 ) | ( frame [ 0x3 ] < < 24 ) ) ;
WREG32 ( AFMT_AVI_INFO1 + offset ,
frame [ 0x4 ] | ( frame [ 0x5 ] < < 8 ) | ( frame [ 0x6 ] < < 16 ) | ( frame [ 0x7 ] < < 24 ) ) ;
WREG32 ( AFMT_AVI_INFO2 + offset ,
frame [ 0x8 ] | ( frame [ 0x9 ] < < 8 ) | ( frame [ 0xA ] < < 16 ) | ( frame [ 0xB ] < < 24 ) ) ;
WREG32 ( AFMT_AVI_INFO3 + offset ,
2014-12-06 01:59:56 +03:00
frame [ 0xC ] | ( frame [ 0xD ] < < 8 ) | ( buffer [ 1 ] < < 24 ) ) ;
2014-12-09 02:28:33 +03:00
WREG32_P ( HDMI_INFOFRAME_CONTROL1 + offset ,
2015-03-31 17:33:05 +03:00
HDMI_AVI_INFO_LINE ( 2 ) , /* anything other than 0 */
~ HDMI_AVI_INFO_LINE_MASK ) ;
2012-05-06 19:29:44 +04:00
}
2014-12-05 21:38:31 +03:00
void dce4_hdmi_audio_set_dto ( struct radeon_device * rdev ,
struct radeon_crtc * crtc , unsigned int clock )
2013-04-18 18:50:55 +04:00
{
2014-12-05 21:38:31 +03:00
unsigned int max_ratio = clock / 24000 ;
2013-07-31 01:31:07 +04:00
u32 dto_phase ;
u32 wallclock_ratio ;
2014-12-05 21:38:31 +03:00
u32 value ;
if ( max_ratio > = 8 ) {
dto_phase = 192 * 1000 ;
wallclock_ratio = 3 ;
} else if ( max_ratio > = 4 ) {
dto_phase = 96 * 1000 ;
wallclock_ratio = 2 ;
} else if ( max_ratio > = 2 ) {
dto_phase = 48 * 1000 ;
wallclock_ratio = 1 ;
2013-08-01 00:51:33 +04:00
} else {
2014-12-05 21:38:31 +03:00
dto_phase = 24 * 1000 ;
wallclock_ratio = 0 ;
2013-07-31 01:31:07 +04:00
}
2014-12-05 21:38:31 +03:00
value = RREG32 ( DCCG_AUDIO_DTO0_CNTL ) & ~ DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK ;
value | = DCCG_AUDIO_DTO_WALLCLOCK_RATIO ( wallclock_ratio ) ;
value & = ~ DCCG_AUDIO_DTO1_USE_512FBR_DTO ;
WREG32 ( DCCG_AUDIO_DTO0_CNTL , value ) ;
/* Two dtos; generally use dto0 for HDMI */
value = 0 ;
if ( crtc )
value | = DCCG_AUDIO_DTO0_SOURCE_SEL ( crtc - > crtc_id ) ;
WREG32 ( DCCG_AUDIO_DTO_SOURCE , value ) ;
2013-04-18 18:50:55 +04:00
/* Express [24MHz / target pixel clock] as an exact rational
* number ( coefficient of two integer numbers . DCCG_AUDIO_DTOx_PHASE
* is the numerator , DCCG_AUDIO_DTOx_MODULE is the denominator
*/
2013-07-31 01:31:07 +04:00
WREG32 ( DCCG_AUDIO_DTO0_PHASE , dto_phase ) ;
2014-12-05 21:38:31 +03:00
WREG32 ( DCCG_AUDIO_DTO0_MODULE , clock ) ;
2013-04-18 18:50:55 +04:00
}
2014-12-05 21:38:31 +03:00
void dce4_dp_audio_set_dto ( struct radeon_device * rdev ,
2015-02-27 22:43:47 +03:00
struct radeon_crtc * crtc , unsigned int clock )
2014-12-05 21:38:31 +03:00
{
u32 value ;
value = RREG32 ( DCCG_AUDIO_DTO1_CNTL ) & ~ DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK ;
value | = DCCG_AUDIO_DTO1_USE_512FBR_DTO ;
WREG32 ( DCCG_AUDIO_DTO1_CNTL , value ) ;
/* Two dtos; generally use dto1 for DP */
value = 0 ;
value | = DCCG_AUDIO_DTO_SEL ;
if ( crtc )
value | = DCCG_AUDIO_DTO0_SOURCE_SEL ( crtc - > crtc_id ) ;
WREG32 ( DCCG_AUDIO_DTO_SOURCE , value ) ;
/* Express [24MHz / target pixel clock] as an exact rational
* number ( coefficient of two integer numbers . DCCG_AUDIO_DTOx_PHASE
* is the numerator , DCCG_AUDIO_DTOx_MODULE is the denominator
*/
WREG32 ( DCCG_AUDIO_DTO1_PHASE , 24000 ) ;
2015-02-27 22:43:47 +03:00
WREG32 ( DCCG_AUDIO_DTO1_MODULE , clock ) ;
2014-12-05 21:38:31 +03:00
}
2013-04-18 18:50:55 +04:00
2015-01-21 03:20:52 +03:00
void dce4_set_vbi_packet ( struct drm_encoder * encoder , u32 offset )
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
WREG32 ( HDMI_VBI_PACKET_CONTROL + offset ,
HDMI_NULL_SEND | /* send null packets when required */
HDMI_GC_SEND | /* send general control packets */
HDMI_GC_CONT ) ; /* send general control packets every frame */
}
2014-12-09 00:25:37 +03:00
void dce4_hdmi_set_color_depth ( struct drm_encoder * encoder , u32 offset , int bpc )
2012-05-06 19:29:44 +04:00
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
2014-05-29 03:02:31 +04:00
struct drm_connector * connector = radeon_get_connector_for_encoder ( encoder ) ;
2014-05-29 03:14:36 +04:00
uint32_t val ;
2012-05-06 19:29:44 +04:00
2014-05-29 03:14:36 +04:00
val = RREG32 ( HDMI_CONTROL + offset ) ;
val & = ~ HDMI_DEEP_COLOR_ENABLE ;
val & = ~ HDMI_DEEP_COLOR_DEPTH_MASK ;
switch ( bpc ) {
case 0 :
case 6 :
case 8 :
case 16 :
default :
DRM_DEBUG ( " %s: Disabling hdmi deep color for %d bpc. \n " ,
2014-06-03 15:56:19 +04:00
connector - > name , bpc ) ;
2014-05-29 03:14:36 +04:00
break ;
case 10 :
val | = HDMI_DEEP_COLOR_ENABLE ;
val | = HDMI_DEEP_COLOR_DEPTH ( HDMI_30BIT_DEEP_COLOR ) ;
DRM_DEBUG ( " %s: Enabling hdmi deep color 30 for 10 bpc. \n " ,
2014-06-03 15:56:19 +04:00
connector - > name ) ;
2014-05-29 03:14:36 +04:00
break ;
case 12 :
val | = HDMI_DEEP_COLOR_ENABLE ;
val | = HDMI_DEEP_COLOR_DEPTH ( HDMI_36BIT_DEEP_COLOR ) ;
DRM_DEBUG ( " %s: Enabling hdmi deep color 36 for 12 bpc. \n " ,
2014-06-03 15:56:19 +04:00
connector - > name ) ;
2014-05-29 03:14:36 +04:00
break ;
}
WREG32 ( HDMI_CONTROL + offset , val ) ;
2014-12-09 00:25:37 +03:00
}
2014-12-10 00:44:18 +03:00
void dce4_set_audio_packet ( struct drm_encoder * encoder , u32 offset )
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
WREG32 ( AFMT_INFOFRAME_CONTROL0 + offset ,
AFMT_AUDIO_INFO_UPDATE ) ; /* required for audio info values to be updated */
WREG32 ( AFMT_60958_0 + offset ,
AFMT_60958_CS_CHANNEL_NUMBER_L ( 1 ) ) ;
WREG32 ( AFMT_60958_1 + offset ,
AFMT_60958_CS_CHANNEL_NUMBER_R ( 2 ) ) ;
WREG32 ( AFMT_60958_2 + offset ,
AFMT_60958_CS_CHANNEL_NUMBER_2 ( 3 ) |
AFMT_60958_CS_CHANNEL_NUMBER_3 ( 4 ) |
AFMT_60958_CS_CHANNEL_NUMBER_4 ( 5 ) |
AFMT_60958_CS_CHANNEL_NUMBER_5 ( 6 ) |
AFMT_60958_CS_CHANNEL_NUMBER_6 ( 7 ) |
AFMT_60958_CS_CHANNEL_NUMBER_7 ( 8 ) ) ;
WREG32 ( AFMT_AUDIO_PACKET_CONTROL2 + offset ,
AFMT_AUDIO_CHANNEL_ENABLE ( 0xff ) ) ;
2015-03-31 18:43:12 +03:00
WREG32 ( HDMI_AUDIO_PACKET_CONTROL + offset ,
HDMI_AUDIO_DELAY_EN ( 1 ) | /* set the default audio delay */
HDMI_AUDIO_PACKETS_PER_LINE ( 3 ) ) ; /* should be suffient for all audio modes and small enough for all hblanks */
2014-12-10 00:44:18 +03:00
/* allow 60958 channel status and send audio packets fields to be updated */
2015-03-31 18:43:12 +03:00
WREG32_OR ( AFMT_AUDIO_PACKET_CONTROL + offset ,
AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE ) ;
2014-12-10 00:44:18 +03:00
}
2014-12-10 01:17:35 +03:00
void dce4_set_mute ( struct drm_encoder * encoder , u32 offset , bool mute )
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
if ( mute )
WREG32_OR ( HDMI_GC + offset , HDMI_GC_AVMUTE ) ;
else
WREG32_AND ( HDMI_GC + offset , ~ HDMI_GC_AVMUTE ) ;
}
2013-04-18 19:32:16 +04:00
void evergreen_hdmi_enable ( struct drm_encoder * encoder , bool enable )
{
2014-09-19 02:07:08 +04:00
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
2013-04-18 19:32:16 +04:00
struct radeon_encoder * radeon_encoder = to_radeon_encoder ( encoder ) ;
struct radeon_encoder_atom_dig * dig = radeon_encoder - > enc_priv ;
2013-07-09 02:16:56 +04:00
if ( ! dig | | ! dig - > afmt )
return ;
2015-02-27 18:04:11 +03:00
if ( enable ) {
2015-04-07 17:20:49 +03:00
struct drm_connector * connector = radeon_get_connector_for_encoder ( encoder ) ;
2015-05-27 18:33:26 +03:00
if ( connector & & drm_detect_monitor_audio ( radeon_connector_edid ( connector ) ) ) {
2015-04-07 17:20:49 +03:00
WREG32 ( HDMI_INFOFRAME_CONTROL0 + dig - > afmt - > offset ,
HDMI_AVI_INFO_SEND | /* enable AVI info frames */
HDMI_AVI_INFO_CONT | /* required for audio info values to be updated */
HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
HDMI_AUDIO_INFO_CONT ) ; /* required for audio info values to be updated */
WREG32_OR ( AFMT_AUDIO_PACKET_CONTROL + dig - > afmt - > offset ,
AFMT_AUDIO_SAMPLE_SEND ) ;
} else {
WREG32 ( HDMI_INFOFRAME_CONTROL0 + dig - > afmt - > offset ,
HDMI_AVI_INFO_SEND | /* enable AVI info frames */
HDMI_AVI_INFO_CONT ) ; /* required for audio info values to be updated */
WREG32_AND ( AFMT_AUDIO_PACKET_CONTROL + dig - > afmt - > offset ,
~ AFMT_AUDIO_SAMPLE_SEND ) ;
}
2015-02-27 18:04:11 +03:00
} else {
2015-03-31 18:43:12 +03:00
WREG32_AND ( AFMT_AUDIO_PACKET_CONTROL + dig - > afmt - > offset ,
~ AFMT_AUDIO_SAMPLE_SEND ) ;
2015-02-27 18:04:11 +03:00
WREG32 ( HDMI_INFOFRAME_CONTROL0 + dig - > afmt - > offset , 0 ) ;
2014-09-19 02:07:08 +04:00
}
2013-04-18 19:32:16 +04:00
dig - > afmt - > enabled = enable ;
DRM_DEBUG ( " %sabling HDMI interface @ 0x%04X for encoder 0x%x \n " ,
enable ? " En " : " Dis " , dig - > afmt - > offset , radeon_encoder - > encoder_id ) ;
}
2014-12-13 01:01:42 +03:00
2015-02-27 18:04:11 +03:00
void evergreen_dp_enable ( struct drm_encoder * encoder , bool enable )
2014-12-13 01:01:42 +03:00
{
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 ;
2015-04-07 17:20:49 +03:00
struct drm_connector * connector = radeon_get_connector_for_encoder ( encoder ) ;
2014-12-13 01:01:42 +03:00
if ( ! dig | | ! dig - > afmt )
return ;
2015-05-27 18:33:26 +03:00
if ( enable & & connector & &
drm_detect_monitor_audio ( radeon_connector_edid ( connector ) ) ) {
2014-12-13 01:01:42 +03:00
struct drm_connector * connector = radeon_get_connector_for_encoder ( encoder ) ;
struct radeon_connector * radeon_connector = to_radeon_connector ( connector ) ;
struct radeon_connector_atom_dig * dig_connector ;
uint32_t val ;
2015-03-31 18:43:12 +03:00
WREG32_OR ( AFMT_AUDIO_PACKET_CONTROL + dig - > afmt - > offset ,
AFMT_AUDIO_SAMPLE_SEND ) ;
2015-02-27 18:04:11 +03:00
WREG32 ( EVERGREEN_DP_SEC_TIMESTAMP + dig - > afmt - > offset ,
EVERGREEN_DP_SEC_TIMESTAMP_MODE ( 1 ) ) ;
2014-12-13 01:01:42 +03:00
2015-03-31 18:38:48 +03:00
if ( ! ASIC_IS_DCE6 ( rdev ) & & radeon_connector - > con_priv ) {
2014-12-13 01:01:42 +03:00
dig_connector = radeon_connector - > con_priv ;
2015-02-27 18:04:11 +03:00
val = RREG32 ( EVERGREEN_DP_SEC_AUD_N + dig - > afmt - > offset ) ;
2014-12-13 01:01:42 +03:00
val & = ~ EVERGREEN_DP_SEC_N_BASE_MULTIPLE ( 0xf ) ;
if ( dig_connector - > dp_clock = = 162000 )
val | = EVERGREEN_DP_SEC_N_BASE_MULTIPLE ( 3 ) ;
else
val | = EVERGREEN_DP_SEC_N_BASE_MULTIPLE ( 5 ) ;
2015-02-27 18:04:11 +03:00
WREG32 ( EVERGREEN_DP_SEC_AUD_N + dig - > afmt - > offset , val ) ;
2014-12-13 01:01:42 +03:00
}
2015-02-27 18:04:11 +03:00
WREG32 ( EVERGREEN_DP_SEC_CNTL + dig - > afmt - > offset ,
2014-12-13 01:01:42 +03:00
EVERGREEN_DP_SEC_ASP_ENABLE | /* Audio packet transmission */
EVERGREEN_DP_SEC_ATP_ENABLE | /* Audio timestamp packet transmission */
EVERGREEN_DP_SEC_AIP_ENABLE | /* Audio infoframe packet transmission */
EVERGREEN_DP_SEC_STREAM_ENABLE ) ; /* Master enable for secondary stream engine */
} else {
2015-02-27 18:04:11 +03:00
WREG32 ( EVERGREEN_DP_SEC_CNTL + dig - > afmt - > offset , 0 ) ;
2015-03-31 18:43:12 +03:00
WREG32_AND ( AFMT_AUDIO_PACKET_CONTROL + dig - > afmt - > offset ,
~ AFMT_AUDIO_SAMPLE_SEND ) ;
2014-12-13 01:01:42 +03:00
}
dig - > afmt - > enabled = enable ;
}