[PATCH] drm/amdgpu: add DP audio support for si dce6
Alex Deucher
alexdeucher at gmail.com
Tue Feb 21 15:23:32 UTC 2017
On Tue, Feb 21, 2017 at 10:21 AM, Deucher, Alexander
<Alexander.Deucher at amd.com> wrote:
>> -----Original Message-----
>> From: amd-gfx [mailto:amd-gfx-bounces at lists.freedesktop.org] On Behalf
>> Of Xiaojie Yuan
>> Sent: Monday, February 20, 2017 5:16 AM
>> To: amd-gfx at lists.freedesktop.org
>> Cc: Yuan, Xiaojie
>> Subject: [PATCH] drm/amdgpu: add DP audio support for si dce6
>>
>> Signed-off-by: Xiaojie Yuan <Xiaojie.Yuan at amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 457
>> +++++++++++++++++++--
>> .../drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h | 2 +
>> 2 files changed, 425 insertions(+), 34 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
>> b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
>> index 94877cb..ec2f122 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
>> @@ -118,14 +118,31 @@ static const struct {
>> static u32 dce_v6_0_audio_endpt_rreg(struct amdgpu_device *adev,
>> u32 block_offset, u32 reg)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_audio_endpt_rreg ----no impl!!!!\n");
>> - return 0;
>> + unsigned long flags;
>> + u32 r;
>> +
>> + spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags);
>> + WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset,
>> reg);
>> + r = RREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA +
>> block_offset);
>> + spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags);
>> +
>> + return r;
>> }
>>
>> static void dce_v6_0_audio_endpt_wreg(struct amdgpu_device *adev,
>> u32 block_offset, u32 reg, u32 v)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_audio_endpt_wreg ----no impl!!!!\n");
>> + unsigned long flags;
>> + u32 tmp;
>> +
>> + spin_lock_irqsave(&adev->audio_endpt_idx_lock, flags);
>> + tmp = REG_SET_FIELD(0, AZALIA_F0_CODEC_ENDPOINT_INDEX,
>> + AZALIA_ENDPOINT_REG_INDEX, reg);
>> + tmp = REG_SET_FIELD(tmp, AZALIA_F0_CODEC_ENDPOINT_INDEX,
>> + AZALIA_ENDPOINT_REG_WRITE_EN, 1);
>> + WREG32(mmAZALIA_F0_CODEC_ENDPOINT_INDEX + block_offset,
>> tmp);
>> + WREG32(mmAZALIA_F0_CODEC_ENDPOINT_DATA + block_offset,
>> v);
>> + spin_unlock_irqrestore(&adev->audio_endpt_idx_lock, flags);
>> }
>>
>> static bool dce_v6_0_is_in_vblank(struct amdgpu_device *adev, int crtc)
>> @@ -1231,17 +1248,17 @@ static void dce_v6_0_bandwidth_update(struct
>> amdgpu_device *adev)
>> dce_v6_0_program_watermarks(adev, adev-
>> >mode_info.crtcs[i+1], lb_size, num_heads);
>> }
>> }
>> -/*
>> +
>> static void dce_v6_0_audio_get_connected_pins(struct amdgpu_device
>> *adev)
>> {
>> int i;
>> - u32 offset, tmp;
>> + u32 tmp;
>>
>> for (i = 0; i < adev->mode_info.audio.num_pins; i++) {
>> - offset = adev->mode_info.audio.pin[i].offset;
>> - tmp = RREG32_AUDIO_ENDPT(offset,
>> -
>> AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT);
>> - if (((tmp & PORT_CONNECTIVITY_MASK) >>
>> PORT_CONNECTIVITY_SHIFT) == 1)
>> + tmp = RREG32_AUDIO_ENDPT(adev-
>> >mode_info.audio.pin[i].offset,
>> +
>> ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_
>> DEFAULT);
>> + if (REG_GET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT,
>> + PORT_CONNECTIVITY))
>> adev->mode_info.audio.pin[i].connected = false;
>> else
>> adev->mode_info.audio.pin[i].connected = true;
>> @@ -1268,40 +1285,201 @@ static void
>> dce_v6_0_afmt_audio_select_pin(struct drm_encoder *encoder)
>> struct amdgpu_device *adev = encoder->dev->dev_private;
>> struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> - u32 offset;
>>
>> if (!dig || !dig->afmt || !dig->afmt->pin)
>> return;
>>
>> - offset = dig->afmt->offset;
>> -
>> - WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
>> - AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
>> -
>> + WREG32(mmAFMT_AUDIO_SRC_CONTROL + dig->afmt->offset,
>> + REG_SET_FIELD(0, AFMT_AUDIO_SRC_CONTROL,
>> AFMT_AUDIO_SRC_SELECT,
>> + dig->afmt->pin->id));
>> }
>>
>> static void dce_v6_0_audio_write_latency_fields(struct drm_encoder
>> *encoder,
>> struct drm_display_mode
>> *mode)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_audio_write_latency_fields---no
>> imp!!!!!\n");
>> + struct amdgpu_device *adev = encoder->dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + struct drm_connector *connector;
>> + struct amdgpu_connector *amdgpu_connector = NULL;
>> + int interlace = 0;
>> + u32 tmp;
>> +
>> + list_for_each_entry(connector, &encoder->dev-
>> >mode_config.connector_list, head) {
>> + if (connector->encoder == encoder) {
>> + amdgpu_connector =
>> to_amdgpu_connector(connector);
>> + break;
>> + }
>> + }
>> +
>> + if (!amdgpu_connector) {
>> + DRM_ERROR("Couldn't find encoder's connector\n");
>> + return;
>> + }
>> +
>> + if (mode->flags & DRM_MODE_FLAG_INTERLACE)
>> + interlace = 1;
>> +
>> + if (connector->latency_present[interlace]) {
>> + tmp = REG_SET_FIELD(0,
>> AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
>> + VIDEO_LIPSYNC, connector-
>> >video_latency[interlace]);
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
>> + AUDIO_LIPSYNC, connector-
>> >audio_latency[interlace]);
>> + } else {
>> + tmp = REG_SET_FIELD(0,
>> AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
>> + VIDEO_LIPSYNC, 0);
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
>> + AUDIO_LIPSYNC, 0);
>> + }
>> + WREG32_AUDIO_ENDPT(dig->afmt->pin->offset,
>> +
>> ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
>> }
>>
>> static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder
>> *encoder)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_audio_write_speaker_allocation---no
>> imp!!!!!\n");
>> + struct amdgpu_device *adev = encoder->dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + struct drm_connector *connector;
>> + struct amdgpu_connector *amdgpu_connector = NULL;
>> + u8 *sadb = NULL;
>> + int sad_count;
>> + u32 tmp;
>> +
>> + list_for_each_entry(connector, &encoder->dev-
>> >mode_config.connector_list, head) {
>> + if (connector->encoder == encoder) {
>> + amdgpu_connector =
>> to_amdgpu_connector(connector);
>> + break;
>> + }
>> + }
>> +
>> + if (!amdgpu_connector) {
>> + DRM_ERROR("Couldn't find encoder's connector\n");
>> + return;
>> + }
>> +
>> + sad_count =
>> drm_edid_to_speaker_allocation(amdgpu_connector_edid(connector),
>> &sadb);
>> + if (sad_count < 0) {
>> + DRM_ERROR("Couldn't read Speaker Allocation Data Block:
>> %d\n", sad_count);
>> + sad_count = 0;
>> + }
>> +
>> + /* program the speaker allocation */
>> + tmp = RREG32_AUDIO_ENDPT(dig->afmt->pin->offset,
>> +
>> ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
>> + HDMI_CONNECTION, 0);
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
>> + DP_CONNECTION, 0);
>> +
>> + if (connector->connector_type ==
>> DRM_MODE_CONNECTOR_DisplayPort)
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
>> + DP_CONNECTION, 1);
>> + else
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
>> + HDMI_CONNECTION, 1);
>> +
>> + if (sad_count)
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
>> + SPEAKER_ALLOCATION, sadb[0]);
>> + else
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
>> + SPEAKER_ALLOCATION, 5); /* stereo */
>> +
>> + WREG32_AUDIO_ENDPT(dig->afmt->pin->offset,
>> +
>> ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
>> +
>> + kfree(sadb);
>> }
>>
>> static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_audio_write_sad_regs---no
>> imp!!!!!\n");
>> + struct amdgpu_device *adev = encoder->dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + struct drm_connector *connector;
>> + struct amdgpu_connector *amdgpu_connector = NULL;
>> + struct cea_sad *sads;
>> + int i, sad_count;
>> +
>> + static const u16 eld_reg_to_type[][2] = {
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
>> HDMI_AUDIO_CODING_TYPE_PCM },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1,
>> HDMI_AUDIO_CODING_TYPE_AC3 },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2,
>> HDMI_AUDIO_CODING_TYPE_MPEG1 },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3,
>> HDMI_AUDIO_CODING_TYPE_MP3 },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4,
>> HDMI_AUDIO_CODING_TYPE_MPEG2 },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5,
>> HDMI_AUDIO_CODING_TYPE_AAC_LC },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6,
>> HDMI_AUDIO_CODING_TYPE_DTS },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7,
>> HDMI_AUDIO_CODING_TYPE_ATRAC },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9,
>> HDMI_AUDIO_CODING_TYPE_EAC3 },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10,
>> HDMI_AUDIO_CODING_TYPE_DTS_HD },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11,
>> HDMI_AUDIO_CODING_TYPE_MLP },
>> + {
>> ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13,
>> HDMI_AUDIO_CODING_TYPE_WMA_PRO },
>> + };
>> +
>> + list_for_each_entry(connector, &encoder->dev-
>> >mode_config.connector_list, head) {
>> + if (connector->encoder == encoder) {
>> + amdgpu_connector =
>> to_amdgpu_connector(connector);
>> + break;
>> + }
>> + }
>> +
>> + if (!amdgpu_connector) {
>> + DRM_ERROR("Couldn't find encoder's connector\n");
>> + return;
>> + }
>> +
>> + sad_count =
>> drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
>> + if (sad_count <= 0) {
>> + DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
>> + return;
>> + }
>> +
>> + for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
>> + u32 tmp = 0;
>> + u8 stereo_freqs = 0;
>> + int max_channels = -1;
>> + int j;
>> +
>> + for (j = 0; j < sad_count; j++) {
>> + struct cea_sad *sad = &sads[j];
>> +
>> + if (sad->format == eld_reg_to_type[i][1]) {
>> + if (sad->channels > max_channels) {
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
>> + MAX_CHANNELS,
>> sad->channels);
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
>> + DESCRIPTOR_BYTE_2,
>> sad->byte2);
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
>> +
>> SUPPORTED_FREQUENCIES, sad->freq);
>> + max_channels = sad->channels;
>> + }
>> +
>> + if (sad->format ==
>> HDMI_AUDIO_CODING_TYPE_PCM)
>> + stereo_freqs |= sad->freq;
>> + else
>> + break;
>> + }
>> + }
>> +
>> + tmp = REG_SET_FIELD(tmp,
>> AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
>> + SUPPORTED_FREQUENCIES_STEREO,
>> stereo_freqs);
>> + WREG32_AUDIO_ENDPT(dig->afmt->pin->offset,
>> eld_reg_to_type[i][0], tmp);
>> + }
>> +
>> + kfree(sads);
>>
>> }
>> -*/
>> +
>> static void dce_v6_0_audio_enable(struct amdgpu_device *adev,
>> struct amdgpu_audio_pin *pin,
>> bool enable)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_audio_enable---no imp!!!!!\n");
>> + if (!pin)
>> + return;
>> +
>> + WREG32_AUDIO_ENDPT(pin->offset,
>> ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
>> + enable ?
>> AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLE
>> D_MASK : 0);
>> }
>>
>> static const u32 pin_offsets[7] =
>> @@ -1317,12 +1495,44 @@ static const u32 pin_offsets[7] =
>>
>> static int dce_v6_0_audio_init(struct amdgpu_device *adev)
>> {
>> + int i;
>> +
>> + if (!amdgpu_audio)
>> + return 0;
>> +
>> + adev->mode_info.audio.enabled = true;
>> +
>> + adev->mode_info.audio.num_pins = 7;
>
>
> num_pins should be 6 on SI. With that fixed:
Actually should be 6 for verde, tahiti, pitcairn, and 2 for oland.
Alex
>
> Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
>
>> +
>> + for (i = 0; i < adev->mode_info.audio.num_pins; i++) {
>> + adev->mode_info.audio.pin[i].channels = -1;
>> + adev->mode_info.audio.pin[i].rate = -1;
>> + adev->mode_info.audio.pin[i].bits_per_sample = -1;
>> + adev->mode_info.audio.pin[i].status_bits = 0;
>> + adev->mode_info.audio.pin[i].category_code = 0;
>> + adev->mode_info.audio.pin[i].connected = false;
>> + adev->mode_info.audio.pin[i].offset = pin_offsets[i];
>> + adev->mode_info.audio.pin[i].id = i;
>> + dce_v6_0_audio_enable(adev, &adev-
>> >mode_info.audio.pin[i], false);
>> + }
>> +
>> return 0;
>> }
>>
>> static void dce_v6_0_audio_fini(struct amdgpu_device *adev)
>> {
>> + int i;
>> +
>> + if (!amdgpu_audio)
>> + return;
>> +
>> + if (!adev->mode_info.audio.enabled)
>> + return;
>>
>> + for (i = 0; i < adev->mode_info.audio.num_pins; i++)
>> + dce_v6_0_audio_enable(adev, &adev-
>> >mode_info.audio.pin[i], false);
>> +
>> + adev->mode_info.audio.enabled = false;
>> }
>>
>> /*
>> @@ -1331,28 +1541,204 @@ static void dce_v6_0_afmt_update_ACR(struct
>> drm_encoder *encoder, uint32_t clock
>> DRM_INFO("xxxx: dce_v6_0_afmt_update_ACR---no imp!!!!!\n");
>> }
>> */
>> -/*
>> - * build a HDMI Video Info Frame
>> - */
>> -/*
>> +
>> static void dce_v6_0_afmt_update_avi_infoframe(struct drm_encoder
>> *encoder,
>> - void *buffer, size_t size)
>> + struct drm_display_mode *mode)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_afmt_update_avi_infoframe---no
>> imp!!!!!\n");
>> + struct drm_device *dev = encoder->dev;
>> + struct amdgpu_device *adev = dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + struct hdmi_avi_infoframe frame;
>> + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE +
>> HDMI_AVI_INFOFRAME_SIZE];
>> + uint8_t *payload = buffer + 3;
>> + uint8_t *header = buffer;
>> + ssize_t err;
>> + u32 tmp;
>> +
>> + err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
>> mode);
>> + if (err < 0) {
>> + DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>> + return;
>> + }
>> +
>> + err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
>> + if (err < 0) {
>> + DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
>> + return;
>> + }
>> +
>> + WREG32(mmAFMT_AVI_INFO0 + dig->afmt->offset,
>> + payload[0x0] | (payload[0x1] << 8) | (payload[0x2] << 16) |
>> (payload[0x3] << 24));
>> + WREG32(mmAFMT_AVI_INFO1 + dig->afmt->offset,
>> + payload[0x4] | (payload[0x5] << 8) | (payload[0x6] << 16) |
>> (payload[0x7] << 24));
>> + WREG32(mmAFMT_AVI_INFO2 + dig->afmt->offset,
>> + payload[0x8] | (payload[0x9] << 8) | (payload[0xA] << 16) |
>> (payload[0xB] << 24));
>> + WREG32(mmAFMT_AVI_INFO3 + dig->afmt->offset,
>> + payload[0xC] | (payload[0xD] << 8) | (header[1] << 24));
>> +
>> + tmp = RREG32(mmHDMI_INFOFRAME_CONTROL1 + dig->afmt-
>> >offset);
>> + /* anything other than 0 */
>> + tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL1,
>> + HDMI_AUDIO_INFO_LINE, 2);
>> + WREG32(mmHDMI_INFOFRAME_CONTROL1 + dig->afmt->offset,
>> tmp);
>> }
>>
>> static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32
>> clock)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_audio_set_dto---no imp!!!!!\n");
>> + struct drm_device *dev = encoder->dev;
>> + struct amdgpu_device *adev = dev->dev_private;
>> + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder-
>> >crtc);
>> + u32 tmp;
>> +
>> + /*
>> + * Two dtos: generally use dto0 for hdmi, dto1 for dp.
>> + * 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
>> + */
>> + tmp = RREG32(mmDCCG_AUDIO_DTO_SOURCE);
>> + tmp = REG_SET_FIELD(tmp, DCCG_AUDIO_DTO_SOURCE,
>> + DCCG_AUDIO_DTO0_SOURCE_SEL, amdgpu_crtc-
>> >crtc_id);
>> + tmp = REG_SET_FIELD(tmp, DCCG_AUDIO_DTO_SOURCE,
>> DCCG_AUDIO_DTO_SEL, 1);
>> + WREG32(mmDCCG_AUDIO_DTO_SOURCE, tmp);
>> + WREG32(mmDCCG_AUDIO_DTO1_PHASE, 24000);
>> + WREG32(mmDCCG_AUDIO_DTO1_MODULE, clock);
>> +}
>> +
>> +static void dce_v6_0_set_audio_packet(struct drm_encoder *encoder)
>> +{
>> + struct drm_device *dev = encoder->dev;
>> + struct amdgpu_device *adev = dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + u32 tmp;
>> +
>> + tmp = RREG32(mmAFMT_INFOFRAME_CONTROL0 + dig->afmt-
>> >offset);
>> + tmp = REG_SET_FIELD(tmp, AFMT_INFOFRAME_CONTROL0,
>> AFMT_AUDIO_INFO_UPDATE, 1);
>> + WREG32(mmAFMT_INFOFRAME_CONTROL0 + dig->afmt->offset,
>> tmp);
>> +
>> + tmp = RREG32(mmAFMT_60958_0 + dig->afmt->offset);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_0,
>> AFMT_60958_CS_CHANNEL_NUMBER_L, 1);
>> + WREG32(mmAFMT_60958_0 + dig->afmt->offset, tmp);
>> +
>> + tmp = RREG32(mmAFMT_60958_1 + dig->afmt->offset);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_1,
>> AFMT_60958_CS_CHANNEL_NUMBER_R, 2);
>> + WREG32(mmAFMT_60958_1 + dig->afmt->offset, tmp);
>> +
>> + tmp = RREG32(mmAFMT_60958_2 + dig->afmt->offset);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_2,
>> AFMT_60958_CS_CHANNEL_NUMBER_2, 3);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_2,
>> AFMT_60958_CS_CHANNEL_NUMBER_3, 4);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_2,
>> AFMT_60958_CS_CHANNEL_NUMBER_4, 5);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_2,
>> AFMT_60958_CS_CHANNEL_NUMBER_5, 6);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_2,
>> AFMT_60958_CS_CHANNEL_NUMBER_6, 7);
>> + tmp = REG_SET_FIELD(tmp, AFMT_60958_2,
>> AFMT_60958_CS_CHANNEL_NUMBER_7, 8);
>> + WREG32(mmAFMT_60958_2 + dig->afmt->offset, tmp);
>> +
>> + tmp = RREG32(mmAFMT_AUDIO_PACKET_CONTROL2 + dig->afmt-
>> >offset);
>> + tmp = REG_SET_FIELD(tmp, AFMT_AUDIO_PACKET_CONTROL2,
>> AFMT_AUDIO_CHANNEL_ENABLE, 0xff);
>> + WREG32(mmAFMT_AUDIO_PACKET_CONTROL2 + dig->afmt-
>> >offset, tmp);
>> +
>> + tmp = RREG32(mmHDMI_AUDIO_PACKET_CONTROL + dig->afmt-
>> >offset);
>> + tmp = REG_SET_FIELD(tmp, HDMI_AUDIO_PACKET_CONTROL,
>> HDMI_AUDIO_DELAY_EN, 1);
>> + tmp = REG_SET_FIELD(tmp, HDMI_AUDIO_PACKET_CONTROL,
>> HDMI_AUDIO_PACKETS_PER_LINE, 3);
>> + WREG32(mmHDMI_AUDIO_PACKET_CONTROL + dig->afmt->offset,
>> tmp);
>> +
>> + tmp = RREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt-
>> >offset);
>> + tmp = REG_SET_FIELD(tmp, AFMT_AUDIO_PACKET_CONTROL,
>> AFMT_RESET_FIFO_WHEN_AUDIO_DIS, 1);
>> + tmp = REG_SET_FIELD(tmp, AFMT_AUDIO_PACKET_CONTROL,
>> AFMT_60958_CS_UPDATE, 1);
>> + WREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
>> tmp);
>> }
>> -*/
>> -/*
>> - * update the info frames with the data from the current display mode
>> - */
>> +
>> +static void dce_v6_0_audio_set_mute(struct drm_encoder *encoder, bool
>> mute)
>> +{
>> + struct drm_device *dev = encoder->dev;
>> + struct amdgpu_device *adev = dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + u32 tmp;
>> +
>> + tmp = RREG32(mmHDMI_GC + dig->afmt->offset);
>> + tmp = REG_SET_FIELD(tmp, HDMI_GC, HDMI_GC_AVMUTE, mute ?
>> 1 : 0);
>> + WREG32(mmHDMI_GC + dig->afmt->offset, tmp);
>> +}
>> +
>> +static void dce_v6_0_audio_dp_enable(struct drm_encoder *encoder, bool
>> enable)
>> +{
>> + struct drm_device *dev = encoder->dev;
>> + struct amdgpu_device *adev = dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + u32 tmp;
>> +
>> + if (enable) {
>> + tmp = RREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig-
>> >afmt->offset);
>> + tmp = REG_SET_FIELD(tmp,
>> AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, 1);
>> + WREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt-
>> >offset, tmp);
>> +
>> + tmp = RREG32(mmDP_SEC_TIMESTAMP + dig->afmt-
>> >offset);
>> + tmp = REG_SET_FIELD(tmp, DP_SEC_TIMESTAMP,
>> DP_SEC_TIMESTAMP_MODE, 1);
>> + WREG32(mmDP_SEC_TIMESTAMP + dig->afmt->offset,
>> tmp);
>> +
>> + tmp = RREG32(mmDP_SEC_CNTL + dig->afmt->offset);
>> + tmp = REG_SET_FIELD(tmp, DP_SEC_CNTL,
>> DP_SEC_ASP_ENABLE, 1);
>> + tmp = REG_SET_FIELD(tmp, DP_SEC_CNTL,
>> DP_SEC_ATP_ENABLE, 1);
>> + tmp = REG_SET_FIELD(tmp, DP_SEC_CNTL,
>> DP_SEC_AIP_ENABLE, 1);
>> + tmp = REG_SET_FIELD(tmp, DP_SEC_CNTL,
>> DP_SEC_STREAM_ENABLE, 1);
>> + WREG32(mmDP_SEC_CNTL + dig->afmt->offset, tmp);
>> + } else {
>> + WREG32(mmDP_SEC_CNTL + dig->afmt->offset, 0);
>> + }
>> +}
>> +
>> static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder,
>> struct drm_display_mode *mode)
>> {
>> - DRM_INFO("xxxx: dce_v6_0_afmt_setmode ----no impl !!!!!!!!\n");
>> + struct drm_device *dev = encoder->dev;
>> + struct amdgpu_device *adev = dev->dev_private;
>> + struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder-
>> >enc_priv;
>> + struct drm_connector *connector;
>> + struct amdgpu_connector *amdgpu_connector = NULL;
>> +
>> + if (!dig || !dig->afmt)
>> + return;
>> +
>> + list_for_each_entry(connector, &encoder->dev-
>> >mode_config.connector_list, head) {
>> + if (connector->encoder == encoder) {
>> + amdgpu_connector =
>> to_amdgpu_connector(connector);
>> + break;
>> + }
>> + }
>> +
>> + if (!amdgpu_connector) {
>> + DRM_ERROR("Couldn't find encoder's connector\n");
>> + return;
>> + }
>> +
>> + if (!dig->afmt->enabled)
>> + return;
>> +
>> + dig->afmt->pin = dce_v6_0_audio_get_pin(adev);
>> + if (!dig->afmt->pin)
>> + return;
>> +
>> + /* disable audio before setting up hw */
>> + dce_v6_0_audio_enable(adev, dig->afmt->pin, false);
>> +
>> + dce_v6_0_audio_set_mute(encoder, true);
>> + dce_v6_0_audio_write_speaker_allocation(encoder);
>> + dce_v6_0_audio_write_sad_regs(encoder);
>> + dce_v6_0_audio_write_latency_fields(encoder, mode);
>> + dce_v6_0_audio_set_dto(encoder, adev->clock.default_dispclk *
>> 10);
>> + dce_v6_0_set_audio_packet(encoder);
>> + dce_v6_0_afmt_audio_select_pin(encoder);
>> + dce_v6_0_afmt_update_avi_infoframe(encoder, mode);
>> + dce_v6_0_audio_set_mute(encoder, false);
>> + dce_v6_0_audio_dp_enable(encoder, 1);
>> +
>> + /* enable audio after setting up hw */
>> + dce_v6_0_audio_enable(adev, dig->afmt->pin, true);
>> }
>>
>> static void dce_v6_0_afmt_enable(struct drm_encoder *encoder, bool
>> enable)
>> @@ -1368,6 +1754,7 @@ static void dce_v6_0_afmt_enable(struct
>> drm_encoder *encoder, bool enable)
>> /* Silent, r600_hdmi_enable will raise WARN for us */
>> if (enable && dig->afmt->enabled)
>> return;
>> +
>> if (!enable && !dig->afmt->enabled)
>> return;
>>
>> @@ -2781,6 +3168,7 @@ dce_v6_0_encoder_mode_set(struct
>> drm_encoder *encoder,
>> {
>>
>> struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> + int em =
>> amdgpu_atombios_encoder_get_encoder_mode(encoder);
>>
>> amdgpu_encoder->pixel_clock = adjusted_mode->clock;
>>
>> @@ -2790,7 +3178,7 @@ dce_v6_0_encoder_mode_set(struct
>> drm_encoder *encoder,
>> /* set scaler clears this on some chips */
>> dce_v6_0_set_interleave(encoder->crtc, mode);
>>
>> - if (amdgpu_atombios_encoder_get_encoder_mode(encoder) ==
>> ATOM_ENCODER_MODE_HDMI) {
>> + if (em == ATOM_ENCODER_MODE_HDMI ||
>> ENCODER_MODE_IS_DP(em)) {
>> dce_v6_0_afmt_enable(encoder, true);
>> dce_v6_0_afmt_setmode(encoder, adjusted_mode);
>> }
>> @@ -2852,11 +3240,12 @@ static void dce_v6_0_encoder_disable(struct
>> drm_encoder *encoder)
>>
>> struct amdgpu_encoder *amdgpu_encoder =
>> to_amdgpu_encoder(encoder);
>> struct amdgpu_encoder_atom_dig *dig;
>> + int em =
>> amdgpu_atombios_encoder_get_encoder_mode(encoder);
>>
>> amdgpu_atombios_encoder_dpms(encoder,
>> DRM_MODE_DPMS_OFF);
>>
>> if (amdgpu_atombios_encoder_is_digital(encoder)) {
>> - if
>> (amdgpu_atombios_encoder_get_encoder_mode(encoder) ==
>> ATOM_ENCODER_MODE_HDMI)
>> + if (em == ATOM_ENCODER_MODE_HDMI ||
>> ENCODER_MODE_IS_DP(em))
>> dce_v6_0_afmt_enable(encoder, false);
>> dig = amdgpu_encoder->enc_priv;
>> dig->dig_encoder = -1;
>> diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h
>> b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h
>> index 9a4d4c2..abe05bc 100644
>> --- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h
>> +++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h
>> @@ -906,6 +906,8 @@
>> #define
>> AZALIA_F0_CODEC_ENDPOINT_DATA__AZALIA_ENDPOINT_REG_DATA__S
>> HIFT 0x00000000
>> #define
>> AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX_M
>> ASK 0x000000ffL
>> #define
>> AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX__S
>> HIFT 0x00000000
>> +#define
>> AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_WRITE_E
>> N_MASK 0x00000100L
>> +#define
>> AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_WRITE_E
>> N__SHIFT 0x00000008
>> #define
>> AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION
>> __CONVERTER_SYNCHRONIZATION_MASK 0x0000003fL
>> #define
>> AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION
>> __CONVERTER_SYNCHRONIZATION__SHIFT 0x00000000
>> #define
>> AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK_M
>> ASK 0x00000200L
>> --
>> 2.7.4
>>
>> _______________________________________________
>> amd-gfx mailing list
>> amd-gfx at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list