diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 285d32e249b8..9df3e77da05b 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -114,6 +114,7 @@ enum { PCM_MEDIA_FORMAT_V2 = 0, PCM_MEDIA_FORMAT_V3, PCM_MEDIA_FORMAT_V4, + PCM_MEDIA_FORMAT_V5, }; /* PCM format modes in DSP */ @@ -288,6 +289,9 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format, int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, bool ts_mode); +int q6asm_open_read_v5(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample, bool ts_mode); + int q6asm_open_write(struct audio_client *ac, uint32_t format /*, uint16_t bits_per_sample*/); @@ -303,6 +307,8 @@ int q6asm_open_write_v3(struct audio_client *ac, uint32_t format, int q6asm_open_write_v4(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample); +int q6asm_open_write_v5(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample); int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode); @@ -450,6 +456,13 @@ int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac, uint16_t endianness, uint16_t mode); +int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode); + int q6asm_set_encdec_chan_map(struct audio_client *ac, uint32_t num_channels); @@ -545,6 +558,15 @@ int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac, uint16_t endianness, uint16_t mode); +int q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac, + uint32_t rate, uint32_t channels, + bool use_default_chmap, + char *channel_map, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode); + int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg); @@ -704,4 +726,5 @@ uint8_t q6asm_get_stream_id_from_token(uint32_t token); int q6asm_adjust_session_clock(struct audio_client *ac, uint32_t adjust_time_lsw, uint32_t adjust_time_msw); +int q6asm_get_svc_version(uint32_t service_id); #endif /* __Q6_ASM_H__ */ diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 3326c993e129..c9178fb3b8a3 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -99,7 +99,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -113,7 +113,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -132,7 +132,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -146,7 +146,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -217,7 +217,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 6, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -231,7 +231,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -250,7 +250,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -270,7 +270,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -284,7 +284,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -303,7 +303,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -317,7 +317,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -336,7 +336,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -356,7 +356,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -370,7 +370,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -2155,7 +2155,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2166,7 +2166,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -2372,7 +2372,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2392,7 +2392,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2412,7 +2412,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2432,7 +2432,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2452,7 +2452,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2472,7 +2472,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2492,7 +2492,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2506,7 +2506,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -2574,7 +2574,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 192000, }, @@ -2593,7 +2593,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 192000, }, @@ -2612,7 +2612,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 192000, }, @@ -2632,7 +2632,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2646,7 +2646,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -2665,7 +2665,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2679,7 +2679,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 48000, }, @@ -2698,7 +2698,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2717,7 +2717,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2736,7 +2736,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2755,7 +2755,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2774,7 +2774,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 384000, }, @@ -2793,7 +2793,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 192000, }, @@ -2812,7 +2812,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 192000, }, @@ -2831,7 +2831,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE), .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, .rate_max = 192000, }, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index d54c357247f8..a0364bbdfeb9 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "msm-pcm-q6-v2.h" #include "msm-pcm-routing-v2.h" @@ -384,8 +385,13 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) return -ENOMEM; } } else { - ret = q6asm_open_write_v4(prtd->audio_client, - fmt_type, bits_per_sample); + if (q6asm_get_svc_version(APR_SVC_ASM) >= + ADSP_ASM_API_VERSION_V2) + ret = q6asm_open_write_v5(prtd->audio_client, + fmt_type, bits_per_sample); + else + ret = q6asm_open_write_v4(prtd->audio_client, + fmt_type, bits_per_sample); if (ret < 0) { pr_err("%s: q6asm_open_write_v4 failed (%d)\n", @@ -425,7 +431,16 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) runtime->channels, !prtd->set_channel_map, prtd->channel_map, bits_per_sample); } else { - ret = q6asm_media_format_block_multi_ch_pcm_v4( + if (q6asm_get_svc_version(APR_SVC_ASM) >= + ADSP_ASM_API_VERSION_V2) + ret = q6asm_media_format_block_multi_ch_pcm_v5( + prtd->audio_client, runtime->rate, + runtime->channels, !prtd->set_channel_map, + prtd->channel_map, bits_per_sample, + sample_word_size, ASM_LITTLE_ENDIAN, + DEFAULT_QF); + else + ret = q6asm_media_format_block_multi_ch_pcm_v4( prtd->audio_client, runtime->rate, runtime->channels, !prtd->set_channel_map, prtd->channel_map, bits_per_sample, @@ -489,8 +504,15 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) __func__, params_channels(params), prtd->audio_client->perf_mode); - ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM, - bits_per_sample, false); + if (q6asm_get_svc_version(APR_SVC_ASM) >= + ADSP_ASM_API_VERSION_V2) + ret = q6asm_open_read_v5(prtd->audio_client, + FORMAT_LINEAR_PCM, + bits_per_sample, false); + else + ret = q6asm_open_read_v4(prtd->audio_client, + FORMAT_LINEAR_PCM, + bits_per_sample, false); if (ret < 0) { pr_err("%s: q6asm_open_read failed\n", __func__); q6asm_audio_client_free(prtd->audio_client); @@ -557,13 +579,25 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n", __func__, prtd->samp_rate, prtd->channel_mode, bits_per_sample, sample_word_size); - ret = q6asm_enc_cfg_blk_pcm_format_support_v4(prtd->audio_client, - prtd->samp_rate, - prtd->channel_mode, - bits_per_sample, - sample_word_size, - ASM_LITTLE_ENDIAN, - DEFAULT_QF); + if (q6asm_get_svc_version(APR_SVC_ASM) >= + ADSP_ASM_API_VERSION_V2) + ret = q6asm_enc_cfg_blk_pcm_format_support_v5( + prtd->audio_client, + prtd->samp_rate, + prtd->channel_mode, + bits_per_sample, + sample_word_size, + ASM_LITTLE_ENDIAN, + DEFAULT_QF); + else + ret = q6asm_enc_cfg_blk_pcm_format_support_v4( + prtd->audio_client, + prtd->samp_rate, + prtd->channel_mode, + bits_per_sample, + sample_word_size, + ASM_LITTLE_ENDIAN, + DEFAULT_QF); if (ret < 0) pr_debug("%s: cmd cfg pcm was block failed", __func__); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h index f9c0c03492e1..afe314455fbf 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h @@ -104,7 +104,7 @@ struct msm_audio { int mmap_flag; atomic_t pending_buffer; bool set_channel_map; - char channel_map[8]; + char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V2]; int cmd_interrupt; bool meta_data_mode; uint32_t volume; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 9e14b341448a..e9592cf1eb5a 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -195,6 +195,39 @@ static int is_adsp_raise_event(uint32_t cmd) return -EINVAL; } +int q6asm_get_svc_version(uint32_t service_id) +{ + int ret = 0; + static int asm_cached_version; + size_t ver_size; + struct avcs_fwk_ver_info *ver_info = NULL; + + if (service_id == AVCS_SERVICE_ID_ALL) { + pr_err("%s: Invalid service id: %d", __func__, + AVCS_SERVICE_ID_ALL); + return -EINVAL; + } + + if (asm_cached_version != 0) + return asm_cached_version; + + ver_size = sizeof(struct avcs_get_fwk_version) + + sizeof(struct avs_svc_api_info); + ver_info = kzalloc(ver_size, GFP_KERNEL); + if (ver_info == NULL) + return -ENOMEM; + + ret = q6core_get_service_version(service_id, ver_info, ver_size); + if (ret < 0) + goto done; + + ret = ver_info->services[0].api_version; + asm_cached_version = ret; +done: + kfree(ver_info); + return ret; +} + static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token, int flag, int flag_offset) { @@ -228,6 +261,9 @@ static inline uint32_t q6asm_get_pcm_format_id(uint32_t media_format_block_ver) uint32_t pcm_format_id; switch (media_format_block_ver) { + case PCM_MEDIA_FORMAT_V5: + pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V5; + break; case PCM_MEDIA_FORMAT_V4: pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4; break; @@ -2869,6 +2905,23 @@ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, } EXPORT_SYMBOL(q6asm_open_read_v4); +/* + * asm_open_read_v5 - Opens audio capture session + * + * @ac: Client session handle + * @format: encoder format + * @bits_per_sample: bit width of capture session + * @ts_mode: timestamp mode + */ +int q6asm_open_read_v5(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample, bool ts_mode) +{ + return __q6asm_open_read(ac, format, bits_per_sample, + PCM_MEDIA_FORMAT_V5 /*media fmt block ver*/, + ts_mode); +} +EXPORT_SYMBOL(q6asm_open_read_v5); + int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format, uint32_t passthrough_flag) { @@ -3172,6 +3225,22 @@ int q6asm_open_write_v4(struct audio_client *ac, uint32_t format, } EXPORT_SYMBOL(q6asm_open_write_v4); +/* + * q6asm_open_write_v5 - Opens audio playback session + * + * @ac: Client session handle + * @format: decoder format + * @bits_per_sample: bit width of playback session + */ +int q6asm_open_write_v5(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample) +{ + return __q6asm_open_write(ac, format, bits_per_sample, + ac->stream_id, false /*gapless*/, + PCM_MEDIA_FORMAT_V5 /*pcm_format_block_ver*/); +} +EXPORT_SYMBOL(q6asm_open_write_v5); + int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode) @@ -4238,6 +4307,108 @@ fail_cmd: return rc; } +/* + * q6asm_enc_cfg_blk_pcm_v5 - sends encoder configuration parameters + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @bits_per_sample: bit width of encoder session + * @use_default_chmap: true if default channel map to be used + * @use_back_flavor: to configure back left and right channel + * @channel_map: input channel map + * @sample_word_size: Size in bits of the word that holds a sample of a channel + * @endianness: endianness of the pcm data + * @mode: Mode to provide additional info about the pcm input data + */ +static int q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, bool use_default_chmap, + bool use_back_flavor, u8 *channel_map, + uint16_t sample_word_size, uint16_t endianness, + uint16_t mode) +{ + struct asm_multi_channel_pcm_enc_cfg_v5 enc_cfg; + struct asm_enc_cfg_blk_param_v2 enc_fg_blk; + u8 *channel_mapping; + u32 frames_per_buf = 0; + int rc; + + if (!use_default_chmap && (channel_map == NULL)) { + pr_err("%s: No valid chan map and can't use default\n", + __func__); + rc = -EINVAL; + goto fail_cmd; + } + + pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, + ac->session, rate, channels, + bits_per_sample, sample_word_size); + + memset(&enc_cfg, 0, sizeof(enc_cfg)); + q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE); + atomic_set(&ac->cmd_state, -1); + enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM; + enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2; + enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) - + sizeof(enc_cfg.encdec); + enc_cfg.encblk.frames_per_buf = frames_per_buf; + enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size - + sizeof(enc_fg_blk); + enc_cfg.num_channels = channels; + enc_cfg.bits_per_sample = bits_per_sample; + enc_cfg.sample_rate = rate; + enc_cfg.is_signed = 1; + enc_cfg.sample_word_size = sample_word_size; + enc_cfg.endianness = endianness; + enc_cfg.mode = mode; + channel_mapping = enc_cfg.channel_mapping; + + memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V2); + + if (use_default_chmap) { + pr_debug("%s: setting default channel map for %d channels", + __func__, channels); + if (q6asm_map_channels(channel_mapping, channels, + use_back_flavor)) { + pr_err("%s: map channels failed %d\n", + __func__, channels); + rc = -EINVAL; + goto fail_cmd; + } + } else { + pr_debug("%s: Using pre-defined channel map", __func__); + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL_V2); + } + + rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg); + if (rc < 0) { + pr_err("%s: Command open failed %d\n", __func__, rc); + goto fail_cmd; + } + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout opcode[0x%x]\n", + __func__, enc_cfg.hdr.opcode); + rc = -ETIMEDOUT; + goto fail_cmd; + } + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state)); + goto fail_cmd; + } + return 0; +fail_cmd: + return rc; +} +EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v5); + /* * q6asm_enc_cfg_blk_pcm_v4 - sends encoder configuration parameters * @@ -4516,6 +4687,18 @@ fail_cmd: return rc; } +static int __q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + return q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels, + bits_per_sample, true, false, NULL, + sample_word_size, endianness, mode); +} + static int __q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac, uint32_t rate, uint32_t channels, uint16_t bits_per_sample, @@ -4602,6 +4785,31 @@ int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac, } EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4); +/* + * q6asm_enc_cfg_blk_pcm_format_support_v5 - sends encoder configuration + * parameters + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @bits_per_sample: bit width of encoder session + * @sample_word_size: Size in bits of the word that holds a sample of a channel + * @endianness: endianness of the pcm data + * @mode: Mode to provide additional info about the pcm input data + */ +int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + return __q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels, + bits_per_sample, sample_word_size, + endianness, mode); +} +EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v5); + int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac, uint32_t rate, uint32_t channels) { @@ -4727,6 +4935,67 @@ static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels, lchannel_mapping[5] = PCM_CHANNEL_RB; lchannel_mapping[6] = PCM_CHANNEL_LS; lchannel_mapping[7] = PCM_CHANNEL_RS; + } else if (channels == 10) { + lchannel_mapping[0] = PCM_CHANNEL_FL; + lchannel_mapping[1] = PCM_CHANNEL_FR; + lchannel_mapping[2] = PCM_CHANNEL_LFE; + lchannel_mapping[3] = PCM_CHANNEL_FC; + lchannel_mapping[4] = PCM_CHANNEL_LS; + lchannel_mapping[5] = PCM_CHANNEL_RS; + lchannel_mapping[6] = PCM_CHANNEL_LB; + lchannel_mapping[7] = PCM_CHANNEL_RB; + lchannel_mapping[8] = PCM_CHANNEL_CS; + lchannel_mapping[9] = PCM_CHANNELS; + } else if (channels == 16) { + lchannel_mapping[0] = PCM_CHANNEL_FL; + lchannel_mapping[1] = PCM_CHANNEL_FR; + lchannel_mapping[2] = PCM_CHANNEL_LFE; + lchannel_mapping[3] = PCM_CHANNEL_FC; + lchannel_mapping[4] = PCM_CHANNEL_LS; + lchannel_mapping[5] = PCM_CHANNEL_RS; + lchannel_mapping[6] = PCM_CHANNEL_LB; + lchannel_mapping[7] = PCM_CHANNEL_RB; + lchannel_mapping[8] = PCM_CHANNEL_CS; + lchannel_mapping[9] = PCM_CHANNELS; + lchannel_mapping[10] = PCM_CHANNEL_CVH; + lchannel_mapping[11] = PCM_CHANNEL_MS; + lchannel_mapping[12] = PCM_CHANNEL_FLC; + lchannel_mapping[13] = PCM_CHANNEL_FRC; + lchannel_mapping[14] = PCM_CHANNEL_RLC; + lchannel_mapping[15] = PCM_CHANNEL_RRC; + } else if (channels == 32) { + lchannel_mapping[0] = PCM_CHANNEL_FL; + lchannel_mapping[1] = PCM_CHANNEL_FR; + lchannel_mapping[2] = PCM_CHANNEL_LFE; + lchannel_mapping[3] = PCM_CHANNEL_FC; + lchannel_mapping[4] = PCM_CHANNEL_LS; + lchannel_mapping[5] = PCM_CHANNEL_RS; + lchannel_mapping[6] = PCM_CHANNEL_LB; + lchannel_mapping[7] = PCM_CHANNEL_RB; + lchannel_mapping[8] = PCM_CHANNEL_CS; + lchannel_mapping[9] = PCM_CHANNELS; + lchannel_mapping[10] = PCM_CHANNEL_CVH; + lchannel_mapping[11] = PCM_CHANNEL_MS; + lchannel_mapping[12] = PCM_CHANNEL_FLC; + lchannel_mapping[13] = PCM_CHANNEL_FRC; + lchannel_mapping[14] = PCM_CHANNEL_RLC; + lchannel_mapping[15] = PCM_CHANNEL_RRC; + lchannel_mapping[16] = PCM_CHANNEL_LFE2; + lchannel_mapping[17] = PCM_CHANNEL_SL; + lchannel_mapping[18] = PCM_CHANNEL_SR; + lchannel_mapping[19] = PCM_CHANNEL_TFL; + lchannel_mapping[20] = PCM_CHANNEL_TFR; + lchannel_mapping[21] = PCM_CHANNEL_TC; + lchannel_mapping[22] = PCM_CHANNEL_TBL; + lchannel_mapping[23] = PCM_CHANNEL_TBR; + lchannel_mapping[24] = PCM_CHANNEL_TSL; + lchannel_mapping[25] = PCM_CHANNEL_TSR; + lchannel_mapping[26] = PCM_CHANNEL_TBC; + lchannel_mapping[27] = PCM_CHANNEL_BFC; + lchannel_mapping[28] = PCM_CHANNEL_BFL; + lchannel_mapping[29] = PCM_CHANNEL_BFR; + lchannel_mapping[30] = PCM_CHANNEL_LW; + lchannel_mapping[31] = PCM_CHANNEL_RW; } else { pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__, channels); @@ -5647,6 +5916,79 @@ fail_cmd: return rc; } +static int __q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac, + uint32_t rate, + uint32_t channels, + bool use_default_chmap, + char *channel_map, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + struct asm_multi_channel_pcm_fmt_blk_param_v5 fmt; + u8 *channel_mapping; + int rc; + + pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, + ac->session, rate, channels, + bits_per_sample, sample_word_size); + + memset(&fmt, 0, sizeof(fmt)); + q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE); + atomic_set(&ac->cmd_state, -1); + + fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; + fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - + sizeof(fmt.fmt_blk); + fmt.param.num_channels = channels; + fmt.param.bits_per_sample = bits_per_sample; + fmt.param.sample_rate = rate; + fmt.param.is_signed = 1; + fmt.param.sample_word_size = sample_word_size; + fmt.param.endianness = endianness; + fmt.param.mode = mode; + channel_mapping = fmt.param.channel_mapping; + + memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V2); + + if (use_default_chmap) { + if (q6asm_map_channels(channel_mapping, channels, false)) { + pr_err("%s: map channels failed %d\n", + __func__, channels); + rc = -EINVAL; + goto fail_cmd; + } + } else { + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL_V2); + } + + rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt); + if (rc < 0) { + pr_err("%s: Comamnd open failed %d\n", __func__, rc); + goto fail_cmd; + } + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout. waited for format update\n", __func__); + rc = -ETIMEDOUT; + goto fail_cmd; + } + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state)); + goto fail_cmd; + } + return 0; +fail_cmd: + return rc; +} + int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, uint32_t rate, uint32_t channels, bool use_default_chmap, char *channel_map) @@ -5726,6 +6068,40 @@ int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac, } EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4); +/* + * q6asm_media_format_block_multi_ch_pcm_v5 - sends pcm decoder configuration + * parameters + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @bits_per_sample: bit width of encoder session + * @use_default_chmap: true if default channel map to be used + * @channel_map: input channel map + * @sample_word_size: Size in bits of the word that holds a sample of a channel + * @endianness: endianness of the pcm data + * @mode: Mode to provide additional info about the pcm input data + */ +int q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac, + uint32_t rate, uint32_t channels, + bool use_default_chmap, + char *channel_map, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + return __q6asm_media_format_block_multi_ch_pcm_v5(ac, rate, channels, + use_default_chmap, + channel_map, + bits_per_sample, + sample_word_size, + endianness, + mode); +} +EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v5); + + /* * q6asm_media_format_block_gen_compr - set up generic compress format params *