Loading include/sound/q6asm-v2.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,11 @@ /* bit 4 represents META enable of encoded data buffer */ /* bit 4 represents META enable of encoded data buffer */ #define BUFFER_META_ENABLE 0x0010 #define BUFFER_META_ENABLE 0x0010 /* bit 5 represents timestamp */ /* bit 5 - 0 -- ASM_DATA_EVENT_READ_DONE will have relative time-stamp*/ /* bit 5 - 1 -- ASM_DATA_EVENT_READ_DONE will have absolute time-stamp*/ #define ABSOLUTE_TIMESTAMP_ENABLE 0x0020 /* Enable Sample_Rate/Channel_Mode notification event from Decoder */ /* Enable Sample_Rate/Channel_Mode notification event from Decoder */ #define SR_CM_NOTIFY_ENABLE 0x0004 #define SR_CM_NOTIFY_ENABLE 0x0004 Loading Loading @@ -175,6 +180,7 @@ struct audio_aio_read_param { phys_addr_t paddr; phys_addr_t paddr; uint32_t len; uint32_t len; uint32_t uid; uint32_t uid; uint32_t flags;/*meta data flags*/ }; }; struct audio_port_data { struct audio_port_data { Loading include/uapi/sound/compress_params.h +23 −1 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,11 @@ #define Q6_DTS 0x00010D88 #define Q6_DTS 0x00010D88 #define Q6_DTS_LBR 0x00010DBB #define Q6_DTS_LBR 0x00010DBB /* Timestamp flsg */ /* Bit-0 - 1 : Enable Timestamp mode */ /* Bit-0 - 0 : Disable Timestamp mode */ #define COMPRESSED_TIMESTAMP_FLAG 0x0001 /* Codecs are listed linearly to allow for extensibility */ /* Codecs are listed linearly to allow for extensibility */ #define SND_AUDIOCODEC_PCM ((__u32) 0x00000001) #define SND_AUDIOCODEC_PCM ((__u32) 0x00000001) #define SND_AUDIOCODEC_MP3 ((__u32) 0x00000002) #define SND_AUDIOCODEC_MP3 ((__u32) 0x00000002) Loading Loading @@ -480,7 +485,24 @@ struct snd_codec { __u32 align; __u32 align; __u32 compr_passthr; __u32 compr_passthr; union snd_codec_options options; union snd_codec_options options; __u32 reserved[3]; __u32 flags; __u32 reserved[2]; } __attribute__((packed, aligned(4))); } __attribute__((packed, aligned(4))); /** struct snd_codec_metadata * @length: Length of the encoded buffer. * @offset: Offset from the buffer address to the first byte of the first * encoded frame. All encoded frames are consecutive starting * from this offset. * @timestamp: Session time in microseconds of the first sample in the buffer. * @reserved: Reserved for future use. */ struct snd_codec_metadata { __u32 length; __u32 offset; __u64 timestamp; __u32 reserved[4]; }; #endif #endif sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +135 −18 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,10 @@ #define DSP_NUM_OUTPUT_FRAME_BUFFERED 2 #define DSP_NUM_OUTPUT_FRAME_BUFFERED 2 #define FLAC_BLK_SIZE_LIMIT 65535 #define FLAC_BLK_SIZE_LIMIT 65535 /* Timestamp mode payload offsets */ #define TS_LSW_OFFSET 6 #define TS_MSW_OFFSET 7 /* decoder parameter length */ /* decoder parameter length */ #define DDP_DEC_MAX_NUM_PARAM 18 #define DDP_DEC_MAX_NUM_PARAM 18 Loading Loading @@ -132,6 +136,8 @@ struct msm_compr_audio { uint64_t bytes_read; /* from DSP */ uint64_t bytes_read; /* from DSP */ uint32_t bytes_read_offset; /* bytes read offset */ uint32_t bytes_read_offset; /* bytes read offset */ uint32_t ts_header_offset; /* holds the timestamp header offset */ int32_t first_buffer; int32_t first_buffer; int32_t last_buffer; int32_t last_buffer; int32_t partial_drain_delay; int32_t partial_drain_delay; Loading Loading @@ -380,19 +386,23 @@ static int msm_compr_read_buffer(struct msm_compr_audio *prtd) return -EINVAL; return -EINVAL; } } buffer_length = prtd->codec_param.buffer.fragment_size; buffer_length = prtd->codec_param.buffer.fragment_size - prtd->ts_header_offset; bytes_available = prtd->received_total - prtd->bytes_copied; bytes_available = prtd->received_total - prtd->bytes_copied; buffer_sent = prtd->bytes_read - prtd->bytes_copied; buffer_sent = prtd->bytes_read - prtd->bytes_copied; if (buffer_sent + buffer_length > prtd->buffer_size) { if (buffer_sent + buffer_length + prtd->ts_header_offset > prtd->buffer_size) { pr_debug(" %s : Buffer is Full bytes_available: %llu\n", pr_debug(" %s : Buffer is Full bytes_available: %llu\n", __func__, bytes_available); __func__, bytes_available); return 0; return 0; } } memset(¶m, 0x0, sizeof(struct audio_aio_read_param)); memset(¶m, 0x0, sizeof(struct audio_aio_read_param)); param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset; param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset + prtd->ts_header_offset; param.len = buffer_length; param.len = buffer_length; param.uid = buffer_length; param.uid = buffer_length; param.flags = prtd->codec_param.codec.flags; pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n", pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n", __func__, buffer_length, prtd->bytes_read); __func__, buffer_length, prtd->bytes_read); Loading Loading @@ -423,6 +433,7 @@ static void compr_event_handler(uint32_t opcode, uint32_t stream_index; uint32_t stream_index; unsigned long flags; unsigned long flags; uint64_t read_size; uint64_t read_size; uint32_t *buff_addr; if (!prtd) { if (!prtd) { pr_err("%s: prtd is NULL\n", __func__); pr_err("%s: prtd is NULL\n", __func__); Loading Loading @@ -514,6 +525,23 @@ static void compr_event_handler(uint32_t opcode, pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n", pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n", prtd->byte_offset, payload[4]); prtd->byte_offset, payload[4]); if (prtd->ts_header_offset) { /* Update the header for received buffer */ buff_addr = prtd->buffer + prtd->byte_offset; /* Write the length of the buffer */ *buff_addr = prtd->codec_param.buffer.fragment_size - prtd->ts_header_offset; buff_addr++; /* Write the offset */ *buff_addr = prtd->ts_header_offset; buff_addr++; /* Write the TS LSW */ *buff_addr = payload[TS_LSW_OFFSET]; buff_addr++; /* Write the TS MSW */ *buff_addr = payload[TS_MSW_OFFSET]; } /* Always assume read_size is same as fragment_size */ /* Always assume read_size is same as fragment_size */ read_size = prtd->codec_param.buffer.fragment_size; read_size = prtd->codec_param.buffer.fragment_size; prtd->byte_offset += read_size; prtd->byte_offset += read_size; Loading Loading @@ -1214,7 +1242,7 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream) pr_debug("%s: stream_id %d bits_per_sample %d\n", pr_debug("%s: stream_id %d bits_per_sample %d\n", __func__, ac->stream_id, bits_per_sample); __func__, ac->stream_id, bits_per_sample); ret = q6asm_open_read_v3(prtd->audio_client, FORMAT_LINEAR_PCM, ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM, bits_per_sample); bits_per_sample); if (ret < 0) { if (ret < 0) { pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret); pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret); Loading Loading @@ -1265,6 +1293,11 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream) prtd->buffer_paddr = ac->port[dir].buf[0].phys; prtd->buffer_paddr = ac->port[dir].buf[0].phys; prtd->buffer_size = runtime->fragments * runtime->fragment_size; prtd->buffer_size = runtime->fragments * runtime->fragment_size; /* Bit-0 of flags represent timestamp mode */ if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG) prtd->ts_header_offset = sizeof(struct snd_codec_metadata); else prtd->ts_header_offset = 0; pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n", pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n", __func__, prtd->sample_rate, prtd->num_channels, __func__, prtd->sample_rate, prtd->num_channels, Loading Loading @@ -3146,7 +3179,7 @@ static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol, return 0; return 0; } } static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol, static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol) { { u64 fe_id = kcontrol->private_value; u64 fe_id = kcontrol->private_value; Loading @@ -3173,7 +3206,7 @@ static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol, return 0; return 0; } } static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol, static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol) { { u64 fe_id = kcontrol->private_value; u64 fe_id = kcontrol->private_value; Loading Loading @@ -3208,6 +3241,68 @@ done: return ret; return ret; } } static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; int app_type; int acdb_dev_id; int sample_rate = 48000; pr_debug("%s: fe_id- %llu\n", __func__, fe_id); if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received out of bounds fe_id %llu\n", __func__, fe_id); return -EINVAL; } app_type = ucontrol->value.integer.value[0]; acdb_dev_id = ucontrol->value.integer.value[1]; if (ucontrol->value.integer.value[2] != 0) sample_rate = ucontrol->value.integer.value[2]; pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); return 0; } static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; int ret = 0; int app_type; int acdb_dev_id; int sample_rate; pr_debug("%s: fe_id- %llu\n", __func__, fe_id); if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received out of bounds fe_id %llu\n", __func__, fe_id); ret = -EINVAL; goto done; } ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX, &app_type, &acdb_dev_id, &sample_rate); if (ret < 0) { pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", __func__, ret); goto done; } ucontrol->value.integer.value[0] = app_type; ucontrol->value.integer.value[1] = acdb_dev_id; ucontrol->value.integer.value[2] = sample_rate; pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", __func__, fe_id, SESSION_TYPE_TX, app_type, acdb_dev_id, sample_rate); done: return ret; } static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol, static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol) { { Loading Loading @@ -3595,7 +3690,8 @@ static int msm_compr_add_dec_runtime_params_control( static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) { { const char *mixer_ctl_name = "Audio Stream"; const char *playback_mixer_ctl_name = "Audio Stream"; const char *capture_mixer_ctl_name = "Audio Stream Capture"; const char *deviceNo = "NN"; const char *deviceNo = "NN"; const char *suffix = "App Type Cfg"; const char *suffix = "App Type Cfg"; char *mixer_str = NULL; char *mixer_str = NULL; Loading @@ -3606,8 +3702,8 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) .name = "?", .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_compr_app_type_cfg_info, .info = msm_compr_app_type_cfg_info, .put = msm_compr_app_type_cfg_put, .put = msm_compr_playback_app_type_cfg_put, .get = msm_compr_app_type_cfg_get, .get = msm_compr_playback_app_type_cfg_get, .private_value = 0, .private_value = 0, } } }; }; Loading @@ -3620,9 +3716,13 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n", pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n", __func__, rtd->dai_link->name, rtd->dai_link->be_id, __func__, rtd->dai_link->name, rtd->dai_link->be_id, rtd->dai_link->cpu_dai_name, rtd->pcm->device); rtd->dai_link->cpu_dai_name, rtd->pcm->device); if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; else ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { if (!mixer_str) { Loading @@ -3630,10 +3730,27 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) return 0; return 0; } } snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name, if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) rtd->pcm->device, suffix); snprintf(mixer_str, ctl_len, "%s %d %s", playback_mixer_ctl_name, rtd->pcm->device, suffix); else snprintf(mixer_str, ctl_len, "%s %d %s", capture_mixer_ctl_name, rtd->pcm->device, suffix); fe_app_type_cfg_control[0].name = mixer_str; fe_app_type_cfg_control[0].name = mixer_str; fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id; fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id; if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) { fe_app_type_cfg_control[0].put = msm_compr_playback_app_type_cfg_put; fe_app_type_cfg_control[0].get = msm_compr_playback_app_type_cfg_get; } else { fe_app_type_cfg_control[0].put = msm_compr_capture_app_type_cfg_put; fe_app_type_cfg_control[0].get = msm_compr_capture_app_type_cfg_get; } pr_debug("Registering new mixer ctl %s", mixer_str); pr_debug("Registering new mixer ctl %s", mixer_str); snd_soc_add_platform_controls(rtd->platform, snd_soc_add_platform_controls(rtd->platform, fe_app_type_cfg_control, fe_app_type_cfg_control, Loading sound/soc/msm/qdsp6v2/q6asm.c +17 −6 Original line number Original line Diff line number Diff line Loading @@ -2285,7 +2285,8 @@ static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr, static int __q6asm_open_read(struct audio_client *ac, static int __q6asm_open_read(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, uint32_t format, uint16_t bits_per_sample, uint32_t pcm_format_block_ver) uint32_t pcm_format_block_ver, bool ts_mode) { { int rc = 0x00; int rc = 0x00; struct asm_stream_cmd_open_read_v3 open; struct asm_stream_cmd_open_read_v3 open; Loading Loading @@ -2329,6 +2330,8 @@ static int __q6asm_open_read(struct audio_client *ac, case FORMAT_LINEAR_PCM: case FORMAT_LINEAR_PCM: open.mode_flags |= 0x00; open.mode_flags |= 0x00; open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver); open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver); if (ts_mode) open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE; break; break; case FORMAT_MPEG4_AAC: case FORMAT_MPEG4_AAC: open.mode_flags |= BUFFER_META_ENABLE; open.mode_flags |= BUFFER_META_ENABLE; Loading Loading @@ -2391,14 +2394,16 @@ int q6asm_open_read(struct audio_client *ac, uint32_t format) uint32_t format) { { return __q6asm_open_read(ac, format, 16, return __q6asm_open_read(ac, format, 16, PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/); PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/, false/*ts_mode*/); } } int q6asm_open_read_v2(struct audio_client *ac, uint32_t format, int q6asm_open_read_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample) { { return __q6asm_open_read(ac, format, bits_per_sample, return __q6asm_open_read(ac, format, bits_per_sample, PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/); PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/, false/*ts_mode*/); } } /* /* Loading @@ -2412,7 +2417,8 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample) { { return __q6asm_open_read(ac, format, bits_per_sample, return __q6asm_open_read(ac, format, bits_per_sample, PCM_MEDIA_FORMAT_V3/*media fmt block ver*/); PCM_MEDIA_FORMAT_V3/*media fmt block ver*/, false/*ts_mode*/); } } EXPORT_SYMBOL(q6asm_open_read_v3); EXPORT_SYMBOL(q6asm_open_read_v3); Loading @@ -2427,7 +2433,8 @@ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample) { { return __q6asm_open_read(ac, format, bits_per_sample, return __q6asm_open_read(ac, format, bits_per_sample, PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/); PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/, true/*ts_mode*/); } } EXPORT_SYMBOL(q6asm_open_read_v4); EXPORT_SYMBOL(q6asm_open_read_v4); Loading Loading @@ -7150,6 +7157,10 @@ int q6asm_async_read(struct audio_client *ac, lbuf_phys_addr = (param->paddr - 64); lbuf_phys_addr = (param->paddr - 64); dir = OUT; dir = OUT; } else { } else { if (param->flags & COMPRESSED_TIMESTAMP_FLAG) lbuf_phys_addr = param->paddr - sizeof(struct snd_codec_metadata); else lbuf_phys_addr = param->paddr; lbuf_phys_addr = param->paddr; dir = OUT; dir = OUT; } } Loading Loading
include/sound/q6asm-v2.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,11 @@ /* bit 4 represents META enable of encoded data buffer */ /* bit 4 represents META enable of encoded data buffer */ #define BUFFER_META_ENABLE 0x0010 #define BUFFER_META_ENABLE 0x0010 /* bit 5 represents timestamp */ /* bit 5 - 0 -- ASM_DATA_EVENT_READ_DONE will have relative time-stamp*/ /* bit 5 - 1 -- ASM_DATA_EVENT_READ_DONE will have absolute time-stamp*/ #define ABSOLUTE_TIMESTAMP_ENABLE 0x0020 /* Enable Sample_Rate/Channel_Mode notification event from Decoder */ /* Enable Sample_Rate/Channel_Mode notification event from Decoder */ #define SR_CM_NOTIFY_ENABLE 0x0004 #define SR_CM_NOTIFY_ENABLE 0x0004 Loading Loading @@ -175,6 +180,7 @@ struct audio_aio_read_param { phys_addr_t paddr; phys_addr_t paddr; uint32_t len; uint32_t len; uint32_t uid; uint32_t uid; uint32_t flags;/*meta data flags*/ }; }; struct audio_port_data { struct audio_port_data { Loading
include/uapi/sound/compress_params.h +23 −1 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,11 @@ #define Q6_DTS 0x00010D88 #define Q6_DTS 0x00010D88 #define Q6_DTS_LBR 0x00010DBB #define Q6_DTS_LBR 0x00010DBB /* Timestamp flsg */ /* Bit-0 - 1 : Enable Timestamp mode */ /* Bit-0 - 0 : Disable Timestamp mode */ #define COMPRESSED_TIMESTAMP_FLAG 0x0001 /* Codecs are listed linearly to allow for extensibility */ /* Codecs are listed linearly to allow for extensibility */ #define SND_AUDIOCODEC_PCM ((__u32) 0x00000001) #define SND_AUDIOCODEC_PCM ((__u32) 0x00000001) #define SND_AUDIOCODEC_MP3 ((__u32) 0x00000002) #define SND_AUDIOCODEC_MP3 ((__u32) 0x00000002) Loading Loading @@ -480,7 +485,24 @@ struct snd_codec { __u32 align; __u32 align; __u32 compr_passthr; __u32 compr_passthr; union snd_codec_options options; union snd_codec_options options; __u32 reserved[3]; __u32 flags; __u32 reserved[2]; } __attribute__((packed, aligned(4))); } __attribute__((packed, aligned(4))); /** struct snd_codec_metadata * @length: Length of the encoded buffer. * @offset: Offset from the buffer address to the first byte of the first * encoded frame. All encoded frames are consecutive starting * from this offset. * @timestamp: Session time in microseconds of the first sample in the buffer. * @reserved: Reserved for future use. */ struct snd_codec_metadata { __u32 length; __u32 offset; __u64 timestamp; __u32 reserved[4]; }; #endif #endif
sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +135 −18 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,10 @@ #define DSP_NUM_OUTPUT_FRAME_BUFFERED 2 #define DSP_NUM_OUTPUT_FRAME_BUFFERED 2 #define FLAC_BLK_SIZE_LIMIT 65535 #define FLAC_BLK_SIZE_LIMIT 65535 /* Timestamp mode payload offsets */ #define TS_LSW_OFFSET 6 #define TS_MSW_OFFSET 7 /* decoder parameter length */ /* decoder parameter length */ #define DDP_DEC_MAX_NUM_PARAM 18 #define DDP_DEC_MAX_NUM_PARAM 18 Loading Loading @@ -132,6 +136,8 @@ struct msm_compr_audio { uint64_t bytes_read; /* from DSP */ uint64_t bytes_read; /* from DSP */ uint32_t bytes_read_offset; /* bytes read offset */ uint32_t bytes_read_offset; /* bytes read offset */ uint32_t ts_header_offset; /* holds the timestamp header offset */ int32_t first_buffer; int32_t first_buffer; int32_t last_buffer; int32_t last_buffer; int32_t partial_drain_delay; int32_t partial_drain_delay; Loading Loading @@ -380,19 +386,23 @@ static int msm_compr_read_buffer(struct msm_compr_audio *prtd) return -EINVAL; return -EINVAL; } } buffer_length = prtd->codec_param.buffer.fragment_size; buffer_length = prtd->codec_param.buffer.fragment_size - prtd->ts_header_offset; bytes_available = prtd->received_total - prtd->bytes_copied; bytes_available = prtd->received_total - prtd->bytes_copied; buffer_sent = prtd->bytes_read - prtd->bytes_copied; buffer_sent = prtd->bytes_read - prtd->bytes_copied; if (buffer_sent + buffer_length > prtd->buffer_size) { if (buffer_sent + buffer_length + prtd->ts_header_offset > prtd->buffer_size) { pr_debug(" %s : Buffer is Full bytes_available: %llu\n", pr_debug(" %s : Buffer is Full bytes_available: %llu\n", __func__, bytes_available); __func__, bytes_available); return 0; return 0; } } memset(¶m, 0x0, sizeof(struct audio_aio_read_param)); memset(¶m, 0x0, sizeof(struct audio_aio_read_param)); param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset; param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset + prtd->ts_header_offset; param.len = buffer_length; param.len = buffer_length; param.uid = buffer_length; param.uid = buffer_length; param.flags = prtd->codec_param.codec.flags; pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n", pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n", __func__, buffer_length, prtd->bytes_read); __func__, buffer_length, prtd->bytes_read); Loading Loading @@ -423,6 +433,7 @@ static void compr_event_handler(uint32_t opcode, uint32_t stream_index; uint32_t stream_index; unsigned long flags; unsigned long flags; uint64_t read_size; uint64_t read_size; uint32_t *buff_addr; if (!prtd) { if (!prtd) { pr_err("%s: prtd is NULL\n", __func__); pr_err("%s: prtd is NULL\n", __func__); Loading Loading @@ -514,6 +525,23 @@ static void compr_event_handler(uint32_t opcode, pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n", pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n", prtd->byte_offset, payload[4]); prtd->byte_offset, payload[4]); if (prtd->ts_header_offset) { /* Update the header for received buffer */ buff_addr = prtd->buffer + prtd->byte_offset; /* Write the length of the buffer */ *buff_addr = prtd->codec_param.buffer.fragment_size - prtd->ts_header_offset; buff_addr++; /* Write the offset */ *buff_addr = prtd->ts_header_offset; buff_addr++; /* Write the TS LSW */ *buff_addr = payload[TS_LSW_OFFSET]; buff_addr++; /* Write the TS MSW */ *buff_addr = payload[TS_MSW_OFFSET]; } /* Always assume read_size is same as fragment_size */ /* Always assume read_size is same as fragment_size */ read_size = prtd->codec_param.buffer.fragment_size; read_size = prtd->codec_param.buffer.fragment_size; prtd->byte_offset += read_size; prtd->byte_offset += read_size; Loading Loading @@ -1214,7 +1242,7 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream) pr_debug("%s: stream_id %d bits_per_sample %d\n", pr_debug("%s: stream_id %d bits_per_sample %d\n", __func__, ac->stream_id, bits_per_sample); __func__, ac->stream_id, bits_per_sample); ret = q6asm_open_read_v3(prtd->audio_client, FORMAT_LINEAR_PCM, ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM, bits_per_sample); bits_per_sample); if (ret < 0) { if (ret < 0) { pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret); pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret); Loading Loading @@ -1265,6 +1293,11 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream) prtd->buffer_paddr = ac->port[dir].buf[0].phys; prtd->buffer_paddr = ac->port[dir].buf[0].phys; prtd->buffer_size = runtime->fragments * runtime->fragment_size; prtd->buffer_size = runtime->fragments * runtime->fragment_size; /* Bit-0 of flags represent timestamp mode */ if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG) prtd->ts_header_offset = sizeof(struct snd_codec_metadata); else prtd->ts_header_offset = 0; pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n", pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n", __func__, prtd->sample_rate, prtd->num_channels, __func__, prtd->sample_rate, prtd->num_channels, Loading Loading @@ -3146,7 +3179,7 @@ static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol, return 0; return 0; } } static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol, static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol) { { u64 fe_id = kcontrol->private_value; u64 fe_id = kcontrol->private_value; Loading @@ -3173,7 +3206,7 @@ static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol, return 0; return 0; } } static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol, static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol) { { u64 fe_id = kcontrol->private_value; u64 fe_id = kcontrol->private_value; Loading Loading @@ -3208,6 +3241,68 @@ done: return ret; return ret; } } static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; int app_type; int acdb_dev_id; int sample_rate = 48000; pr_debug("%s: fe_id- %llu\n", __func__, fe_id); if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received out of bounds fe_id %llu\n", __func__, fe_id); return -EINVAL; } app_type = ucontrol->value.integer.value[0]; acdb_dev_id = ucontrol->value.integer.value[1]; if (ucontrol->value.integer.value[2] != 0) sample_rate = ucontrol->value.integer.value[2]; pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); return 0; } static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u64 fe_id = kcontrol->private_value; int ret = 0; int app_type; int acdb_dev_id; int sample_rate; pr_debug("%s: fe_id- %llu\n", __func__, fe_id); if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received out of bounds fe_id %llu\n", __func__, fe_id); ret = -EINVAL; goto done; } ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX, &app_type, &acdb_dev_id, &sample_rate); if (ret < 0) { pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", __func__, ret); goto done; } ucontrol->value.integer.value[0] = app_type; ucontrol->value.integer.value[1] = acdb_dev_id; ucontrol->value.integer.value[2] = sample_rate; pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", __func__, fe_id, SESSION_TYPE_TX, app_type, acdb_dev_id, sample_rate); done: return ret; } static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol, static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol) { { Loading Loading @@ -3595,7 +3690,8 @@ static int msm_compr_add_dec_runtime_params_control( static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) { { const char *mixer_ctl_name = "Audio Stream"; const char *playback_mixer_ctl_name = "Audio Stream"; const char *capture_mixer_ctl_name = "Audio Stream Capture"; const char *deviceNo = "NN"; const char *deviceNo = "NN"; const char *suffix = "App Type Cfg"; const char *suffix = "App Type Cfg"; char *mixer_str = NULL; char *mixer_str = NULL; Loading @@ -3606,8 +3702,8 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) .name = "?", .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_compr_app_type_cfg_info, .info = msm_compr_app_type_cfg_info, .put = msm_compr_app_type_cfg_put, .put = msm_compr_playback_app_type_cfg_put, .get = msm_compr_app_type_cfg_get, .get = msm_compr_playback_app_type_cfg_get, .private_value = 0, .private_value = 0, } } }; }; Loading @@ -3620,9 +3716,13 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n", pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n", __func__, rtd->dai_link->name, rtd->dai_link->be_id, __func__, rtd->dai_link->name, rtd->dai_link->be_id, rtd->dai_link->cpu_dai_name, rtd->pcm->device); rtd->dai_link->cpu_dai_name, rtd->pcm->device); if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; else ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + strlen(suffix) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { if (!mixer_str) { Loading @@ -3630,10 +3730,27 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) return 0; return 0; } } snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name, if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) rtd->pcm->device, suffix); snprintf(mixer_str, ctl_len, "%s %d %s", playback_mixer_ctl_name, rtd->pcm->device, suffix); else snprintf(mixer_str, ctl_len, "%s %d %s", capture_mixer_ctl_name, rtd->pcm->device, suffix); fe_app_type_cfg_control[0].name = mixer_str; fe_app_type_cfg_control[0].name = mixer_str; fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id; fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id; if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) { fe_app_type_cfg_control[0].put = msm_compr_playback_app_type_cfg_put; fe_app_type_cfg_control[0].get = msm_compr_playback_app_type_cfg_get; } else { fe_app_type_cfg_control[0].put = msm_compr_capture_app_type_cfg_put; fe_app_type_cfg_control[0].get = msm_compr_capture_app_type_cfg_get; } pr_debug("Registering new mixer ctl %s", mixer_str); pr_debug("Registering new mixer ctl %s", mixer_str); snd_soc_add_platform_controls(rtd->platform, snd_soc_add_platform_controls(rtd->platform, fe_app_type_cfg_control, fe_app_type_cfg_control, Loading
sound/soc/msm/qdsp6v2/q6asm.c +17 −6 Original line number Original line Diff line number Diff line Loading @@ -2285,7 +2285,8 @@ static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr, static int __q6asm_open_read(struct audio_client *ac, static int __q6asm_open_read(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, uint32_t format, uint16_t bits_per_sample, uint32_t pcm_format_block_ver) uint32_t pcm_format_block_ver, bool ts_mode) { { int rc = 0x00; int rc = 0x00; struct asm_stream_cmd_open_read_v3 open; struct asm_stream_cmd_open_read_v3 open; Loading Loading @@ -2329,6 +2330,8 @@ static int __q6asm_open_read(struct audio_client *ac, case FORMAT_LINEAR_PCM: case FORMAT_LINEAR_PCM: open.mode_flags |= 0x00; open.mode_flags |= 0x00; open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver); open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver); if (ts_mode) open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE; break; break; case FORMAT_MPEG4_AAC: case FORMAT_MPEG4_AAC: open.mode_flags |= BUFFER_META_ENABLE; open.mode_flags |= BUFFER_META_ENABLE; Loading Loading @@ -2391,14 +2394,16 @@ int q6asm_open_read(struct audio_client *ac, uint32_t format) uint32_t format) { { return __q6asm_open_read(ac, format, 16, return __q6asm_open_read(ac, format, 16, PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/); PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/, false/*ts_mode*/); } } int q6asm_open_read_v2(struct audio_client *ac, uint32_t format, int q6asm_open_read_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample) { { return __q6asm_open_read(ac, format, bits_per_sample, return __q6asm_open_read(ac, format, bits_per_sample, PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/); PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/, false/*ts_mode*/); } } /* /* Loading @@ -2412,7 +2417,8 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample) { { return __q6asm_open_read(ac, format, bits_per_sample, return __q6asm_open_read(ac, format, bits_per_sample, PCM_MEDIA_FORMAT_V3/*media fmt block ver*/); PCM_MEDIA_FORMAT_V3/*media fmt block ver*/, false/*ts_mode*/); } } EXPORT_SYMBOL(q6asm_open_read_v3); EXPORT_SYMBOL(q6asm_open_read_v3); Loading @@ -2427,7 +2433,8 @@ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample) { { return __q6asm_open_read(ac, format, bits_per_sample, return __q6asm_open_read(ac, format, bits_per_sample, PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/); PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/, true/*ts_mode*/); } } EXPORT_SYMBOL(q6asm_open_read_v4); EXPORT_SYMBOL(q6asm_open_read_v4); Loading Loading @@ -7150,6 +7157,10 @@ int q6asm_async_read(struct audio_client *ac, lbuf_phys_addr = (param->paddr - 64); lbuf_phys_addr = (param->paddr - 64); dir = OUT; dir = OUT; } else { } else { if (param->flags & COMPRESSED_TIMESTAMP_FLAG) lbuf_phys_addr = param->paddr - sizeof(struct snd_codec_metadata); else lbuf_phys_addr = param->paddr; lbuf_phys_addr = param->paddr; dir = OUT; dir = OUT; } } Loading