All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Deucher <alexdeucher-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: "Deucher, Alexander" <Alexander.Deucher-5C7GfCeVMHo@public.gmane.org>
Cc: "amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org"
	<amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>,
	"Yuan, Xiaojie" <Xiaojie.Yuan-5C7GfCeVMHo@public.gmane.org>
Subject: Re: [PATCH] drm/amdgpu: add DP audio support for si dce6
Date: Tue, 21 Feb 2017 10:23:32 -0500	[thread overview]
Message-ID: <CADnq5_OhCKkhoycUq0WQ3qWdWnzakGQwSvmPWLeUjjb=w+d=VA@mail.gmail.com> (raw)
In-Reply-To: <BN6PR12MB1652D60F7F854DCC3002B870F7510-/b2+HYfkarQqUD6E6FAiowdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>

On Tue, Feb 21, 2017 at 10:21 AM, Deucher, Alexander
<Alexander.Deucher@amd.com> wrote:
>> -----Original Message-----
>> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On Behalf
>> Of Xiaojie Yuan
>> Sent: Monday, February 20, 2017 5:16 AM
>> To: amd-gfx@lists.freedesktop.org
>> Cc: Yuan, Xiaojie
>> Subject: [PATCH] drm/amdgpu: add DP audio support for si dce6
>>
>> Signed-off-by: Xiaojie Yuan <Xiaojie.Yuan@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@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@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

      parent reply	other threads:[~2017-02-21 15:23 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-20 10:16 [PATCH] drm/amdgpu: add DP audio support for si dce6 Xiaojie Yuan
     [not found] ` <1487585786-29676-1-git-send-email-Xiaojie.Yuan-5C7GfCeVMHo@public.gmane.org>
2017-02-21  3:29   ` Zhang, Jerry
2017-02-21 15:21   ` Deucher, Alexander
     [not found]     ` <BN6PR12MB1652D60F7F854DCC3002B870F7510-/b2+HYfkarQqUD6E6FAiowdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-02-21 15:23       ` Alex Deucher [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CADnq5_OhCKkhoycUq0WQ3qWdWnzakGQwSvmPWLeUjjb=w+d=VA@mail.gmail.com' \
    --to=alexdeucher-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
    --cc=Alexander.Deucher-5C7GfCeVMHo@public.gmane.org \
    --cc=Xiaojie.Yuan-5C7GfCeVMHo@public.gmane.org \
    --cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.