From da866c30a683b383cf7b1ea6843f0a5220815a08 Mon Sep 17 00:00:00 2001 From: Manisha Agarwal Date: Thu, 17 Oct 2019 18:19:25 +0800 Subject: [PATCH] q6afe: add support for lc3 codec playback Add support for lc3 codec playback. Change-Id: I96ee7bb869c89c71bf8ee986529bf8575efd4b5b Signed-off-by: Manisha Agarwal --- asoc/msm-dai-q6-v2.c | 104 +++++++++++++++++++- dsp/q6afe.c | 197 +++++++++++++++++++++++++++++++------ include/dsp/apr_audio-v2.h | 93 +++++++++++++++++ include/dsp/q6afe-v2.h | 7 ++ 4 files changed, 368 insertions(+), 33 deletions(-) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index 8b589a77877c..dcd538b48035 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -31,6 +31,9 @@ #define MSM_DAI_TWS_CHANNEL_MODE_ONE 1 #define MSM_DAI_TWS_CHANNEL_MODE_TWO 2 +#define MSM_DAI_LC3_CHANNEL_MODE_ONE 1 +#define MSM_DAI_LC3_CHANNEL_MODE_TWO 2 + #define spdif_clock_value(rate) (2*rate*32*2) #define CHANNEL_STATUS_SIZE 24 #define CHANNEL_STATUS_MASK_INIT 0x0 @@ -63,6 +66,7 @@ enum { DEC_FMT_MP3 = ASM_MEDIA_FMT_MP3, ENC_FMT_APTX_AD_SPEECH = ASM_MEDIA_FMT_APTX_AD_SPEECH, DEC_FMT_APTX_AD_SPEECH = ASM_MEDIA_FMT_APTX_AD_SPEECH, + ENC_FMT_LC3 = ASM_MEDIA_FMT_LC3, }; enum { @@ -3234,7 +3238,11 @@ static int msm_dai_q6_afe_enc_cfg_get(struct snd_kcontrol *kcontrol, &dai_data->enc_config.data, sizeof(struct asm_aptx_ad_speech_enc_cfg_t)); break; - + case ENC_FMT_LC3: + memcpy(ucontrol->value.bytes.data + format_size, + &dai_data->enc_config.data, + sizeof(struct asm_enc_lc3_cfg_t)); + break; default: pr_debug("%s: unknown format = %d\n", __func__, dai_data->enc_config.format); @@ -3303,6 +3311,11 @@ static int msm_dai_q6_afe_enc_cfg_put(struct snd_kcontrol *kcontrol, ucontrol->value.bytes.data + format_size, sizeof(struct asm_aptx_ad_speech_enc_cfg_t)); break; + case ENC_FMT_LC3: + memcpy(&dai_data->enc_config.data, + ucontrol->value.bytes.data + format_size, + sizeof(struct asm_enc_lc3_cfg_t)); + break; default: pr_debug("%s: Ignore enc config for unknown format = %d\n", @@ -3335,6 +3348,12 @@ static const struct soc_enum tws_chs_mode_enum[] = { SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tws_chs_mode_text), tws_chs_mode_text), }; +static const char *const lc3_chs_mode_text[] = {"Zero", "One", "Two"}; + +static const struct soc_enum lc3_chs_mode_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lc3_chs_mode_text), lc3_chs_mode_text), +}; + static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3424,6 +3443,67 @@ exit: return ret; } +static int msm_dai_q6_lc3_channel_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = kcontrol->private_data; + struct msm_dai_q6_dai_data *dai_data = NULL; + + if (dai) + dai_data = dev_get_drvdata(dai->dev); + + if (dai_data) { + ucontrol->value.integer.value[0] = + dai_data->enc_config.lc3_mono_mode; + pr_debug("%s:lc3 channel mode = %d\n", + __func__, dai_data->enc_config.lc3_mono_mode); + } + + return 0; +} + +static int msm_dai_q6_lc3_channel_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = kcontrol->private_data; + struct msm_dai_q6_dai_data *dai_data = NULL; + int ret = 0; + u32 format = 0; + + if (dai) + dai_data = dev_get_drvdata(dai->dev); + + if (dai_data) + format = dai_data->enc_config.format; + else + goto exit; + + if (format == ENC_FMT_LC3) { + if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { + ret = afe_set_lc3_channel_mode(format, + dai->id, ucontrol->value.integer.value[0]); + if (ret < 0) { + pr_err("%s: channel mode setting failed for LC3\n", + __func__); + goto exit; + } else { + pr_debug("%s: updating lc3 channel mode : %d\n", + __func__, dai_data->enc_config.lc3_mono_mode); + } + } + if (ucontrol->value.integer.value[0] == + MSM_DAI_LC3_CHANNEL_MODE_ONE || + ucontrol->value.integer.value[0] == + MSM_DAI_LC3_CHANNEL_MODE_TWO) + dai_data->enc_config.lc3_mono_mode = + ucontrol->value.integer.value[0]; + else + return -EINVAL; + } +exit: + return ret; +} + static int msm_dai_q6_afe_input_bit_format_get( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -3628,7 +3708,10 @@ static const struct snd_kcontrol_new afe_enc_config_controls[] = { .info = msm_dai_q6_afe_enc_cfg_info, .get = msm_dai_q6_afe_enc_cfg_get, .put = msm_dai_q6_afe_enc_cfg_put, - } + }, + SOC_ENUM_EXT("LC3 Channel Mode", lc3_chs_mode_enum[0], + msm_dai_q6_lc3_channel_mode_get, + msm_dai_q6_lc3_channel_mode_put) }; static int msm_dai_q6_afe_dec_cfg_info(struct snd_kcontrol *kcontrol, @@ -3672,6 +3755,13 @@ static int msm_dai_q6_afe_feedback_dec_cfg_get(struct snd_kcontrol *kcontrol, &dai_data->dec_config.data, sizeof(struct asm_aptx_ad_speech_dec_cfg_t)); break; + case ASM_MEDIA_FMT_LC3: + pr_debug("%s: afe_dec_cfg for %d format\n", + __func__, dai_data->dec_config.format); + memcpy(ucontrol->value.bytes.data + format_size + abr_size, + &dai_data->dec_config.data, + sizeof(struct asm_lc3_dec_cfg_t)); + break; default: pr_debug("%s: no afe_dec_cfg for format %d\n", __func__, dai_data->dec_config.format); @@ -3716,6 +3806,13 @@ static int msm_dai_q6_afe_feedback_dec_cfg_put(struct snd_kcontrol *kcontrol, ucontrol->value.bytes.data + format_size + abr_size, sizeof(struct asm_aptx_ad_speech_dec_cfg_t)); break; + case ASM_MEDIA_FMT_LC3: + pr_debug("%s: afe_dec_cfg for %d format\n", + __func__, dai_data->dec_config.format); + memcpy(&dai_data->dec_config.data, + ucontrol->value.bytes.data + format_size + abr_size, + sizeof(struct asm_lc3_dec_cfg_t)); + break; default: pr_debug("%s: no afe_dec_cfg for format %d\n", __func__, dai_data->dec_config.format); @@ -4148,6 +4245,9 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) rc = snd_ctl_add(dai->component->card->snd_card, snd_ctl_new1(&afe_enc_config_controls[5], dai_data)); + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(&afe_enc_config_controls[6], + dai)); rc = snd_ctl_add(dai->component->card->snd_card, snd_ctl_new1(&avd_drift_config_controls[2], dai)); diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 5a944a6a9d73..af36ca2fd36c 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -400,6 +400,10 @@ static int q6afe_load_avcs_modules(int num_modules, u16 port_id, AMDB_MODULE_TYPE_PACKETIZER; pm[i]->payload->load_unload_info[0].id1 = AVS_MODULE_ID_PACKETIZER_COP; + if (format_id == ASM_MEDIA_FMT_LC3) + pm[i]->payload->load_unload_info[0].id1 = + AVS_MODULE_ID_PACKETIZER_COP_V2; + pm[i]->payload->load_unload_info[1].module_type = AMDB_MODULE_TYPE_ENCODER; pm[i]->payload->load_unload_info[1].id1 = @@ -415,6 +419,11 @@ static int q6afe_load_avcs_modules(int num_modules, u16 port_id, AVS_MODULE_ID_DEPACKETIZER_COP; goto load_unload; } + if (format_id == ASM_MEDIA_FMT_LC3) { + pm[i]->payload->load_unload_info[0].id1 = + AVS_MODULE_ID_DEPACKETIZER_COP_V2; + goto load_unload; + } pm[i]->payload->load_unload_info[1].module_type = AMDB_MODULE_TYPE_DECODER; @@ -4897,6 +4906,7 @@ static int q6afe_send_dec_config(u16 port_id, struct afe_matched_port_t matched_port_param; struct asm_aptx_ad_speech_mode_cfg_t speech_codec_init_param; struct param_hdr_v3 param_hdr; + struct avs_cop_v2_param_id_stream_info_t lc3_enc_stream_info; int ret; u32 dec_fmt; @@ -4906,6 +4916,7 @@ static int q6afe_send_dec_config(u16 port_id, memset(&media_type, 0, sizeof(media_type)); memset(&matched_port_param, 0, sizeof(matched_port_param)); memset(&speech_codec_init_param, 0, sizeof(speech_codec_init_param)); + memset(&lc3_enc_stream_info, 0, sizeof(lc3_enc_stream_info)); memset(¶m_hdr, 0, sizeof(param_hdr)); param_hdr.module_id = AFE_MODULE_ID_DECODER; @@ -4920,6 +4931,12 @@ static int q6afe_send_dec_config(u16 port_id, if (cfg->format == ENC_CODEC_TYPE_LDAC) dec_depkt_id_param.dec_depacketizer_id = AFE_MODULE_ID_DEPACKETIZER_COP; + if (format == ASM_MEDIA_FMT_LC3) { + pr_debug("%s: sending AFE_MODULE_ID_DEPACKETIZER_COP_V2 to DSP payload\n", + __func__); + dec_depkt_id_param.dec_depacketizer_id = + AFE_MODULE_ID_DEPACKETIZER_COP_V2; + } ret = q6afe_pack_and_set_param_in_band(port_id, q6audio_get_port_index(port_id), param_hdr, @@ -5027,6 +5044,9 @@ static int q6afe_send_dec_config(u16 port_id, case ASM_MEDIA_FMT_APTX_AD_SPEECH: media_type.sample_rate = AFE_PORT_SAMPLE_RATE_32K; break; + case ASM_MEDIA_FMT_LC3: + media_type.sample_rate = AFE_PORT_SAMPLE_RATE_48K; + break; default: media_type.sample_rate = afe_config.slim_sch.sample_rate; @@ -5054,18 +5074,15 @@ static int q6afe_send_dec_config(u16 port_id, if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 && format != ASM_MEDIA_FMT_APTX_ADAPTIVE && - format != ASM_MEDIA_FMT_APTX_AD_SPEECH) { + format != ASM_MEDIA_FMT_APTX_AD_SPEECH && + format != ASM_MEDIA_FMT_LC3) { pr_debug("%s:Unsuppported dec format. Ignore AFE config %u\n", __func__, format); goto exit; } - if (format == ASM_MEDIA_FMT_APTX_ADAPTIVE && - cfg->abr_dec_cfg.is_abr_enabled) { - pr_debug("%s: Ignore AFE config for abr case\n", __func__); - goto exit; - } - if (format == ASM_MEDIA_FMT_APTX_AD_SPEECH) { + if (format == ASM_MEDIA_FMT_APTX_AD_SPEECH || + format == ASM_MEDIA_FMT_LC3) { pr_debug("%s: sending AFE_PARAM_ID_RATE_MATCHED_PORT to DSP payload\n", __func__); param_hdr.param_id = AFE_PARAM_ID_RATE_MATCHED_PORT; @@ -5084,6 +5101,32 @@ static int q6afe_send_dec_config(u16 port_id, } } + if (format == ASM_MEDIA_FMT_LC3) { + pr_debug("%s: sending AVS_COP_V2_PARAM_ID_STREAM_INFO to DSP\n", + __func__); + param_hdr.module_id = AFE_MODULE_ID_DECODER; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = AVS_COP_V2_PARAM_ID_STREAM_INFO; + param_hdr.param_size = + sizeof(struct avs_cop_v2_param_id_stream_info_t); + lc3_enc_stream_info = cfg->data.lc3_dec_config.dec_codec.streamMapToAir; + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &lc3_enc_stream_info); + if (ret) { + pr_err("%s: AVS_COP_V2_PARAM_ID_STREAM_INFO for port 0x%x failed %d\n", + __func__, port_id, ret); + goto exit; + } + } + + if ((format == ASM_MEDIA_FMT_APTX_ADAPTIVE || format == ASM_MEDIA_FMT_LC3) && + cfg->abr_dec_cfg.is_abr_enabled) { + pr_debug("%s: Ignore AFE config for abr case\n", __func__); + goto exit; + } + pr_debug("%s: sending AFE_DECODER_PARAM_ID_DEC_MEDIA_FMT to DSP payload\n", __func__); param_hdr.module_id = AFE_MODULE_ID_DECODER; @@ -5167,6 +5210,8 @@ static int q6afe_send_enc_config(u16 port_id, struct aptx_channel_mode_param_t channel_mode_param; struct afe_matched_port_t matched_port_param; struct asm_aptx_ad_speech_mode_cfg_t speech_codec_init_param; + struct avs_cop_v2_param_id_stream_info_t lc3_enc_stream_info; + struct afe_lc3_enc_cfg_t lc3_enc_config_init; struct param_hdr_v3 param_hdr; int ret; uint32_t frame_size_ctl_value_v2; @@ -5184,13 +5229,16 @@ static int q6afe_send_enc_config(u16 port_id, memset(&media_type, 0, sizeof(media_type)); memset(&matched_port_param, 0, sizeof(matched_port_param)); memset(&speech_codec_init_param, 0, sizeof(speech_codec_init_param)); + memset(&lc3_enc_stream_info, 0, sizeof(lc3_enc_stream_info)); + memset(&lc3_enc_config_init, 0, sizeof(lc3_enc_config_init)); memset(¶m_hdr, 0, sizeof(param_hdr)); if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 && format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD && format != ASM_MEDIA_FMT_CELT && format != ASM_MEDIA_FMT_LDAC && format != ASM_MEDIA_FMT_APTX_ADAPTIVE && - format != ASM_MEDIA_FMT_APTX_AD_SPEECH) { + format != ASM_MEDIA_FMT_APTX_AD_SPEECH && + format != ASM_MEDIA_FMT_LC3) { pr_err("%s:Unsuppported enc format. Ignore AFE config\n", __func__); return 0; @@ -5228,23 +5276,26 @@ static int q6afe_send_enc_config(u16 port_id, } else if (format == ASM_MEDIA_FMT_APTX_AD_SPEECH) { param_hdr.param_size = sizeof(struct afe_enc_aptx_ad_speech_cfg_blk_param_t); enc_blk_param.enc_cfg_blk_size = sizeof(struct asm_custom_enc_cfg_t); - } else { + } else if (format != ASM_MEDIA_FMT_LC3) { param_hdr.param_size = sizeof(struct afe_enc_cfg_blk_param_t); enc_blk_param.enc_cfg_blk_size = sizeof(union afe_enc_config_data); } - pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload\n", - __func__); - param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK; - enc_blk_param.enc_blk_config = *cfg; - ret = q6afe_pack_and_set_param_in_band(port_id, - q6audio_get_port_index(port_id), - param_hdr, - (u8 *) &enc_blk_param); - if (ret) { - pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n", - __func__, port_id, ret); - goto exit; + + if (format != ASM_MEDIA_FMT_LC3) { + pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload\n", + __func__); + param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK; + enc_blk_param.enc_blk_config = *cfg; + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &enc_blk_param); + if (ret) { + pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n", + __func__, port_id, ret); + goto exit; + } } if (format == ASM_MEDIA_FMT_AAC_V2) { @@ -5352,21 +5403,59 @@ static int q6afe_send_enc_config(u16 port_id, } pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP\n", - __func__); + __func__); param_hdr.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID; param_hdr.param_size = sizeof(struct avs_enc_packetizer_id_param_t); enc_pkt_id_param.enc_packetizer_id = AFE_MODULE_ID_PACKETIZER_COP; + if (format == ASM_MEDIA_FMT_LC3) + enc_pkt_id_param.enc_packetizer_id = AFE_MODULE_ID_PACKETIZER_COP_V2; ret = q6afe_pack_and_set_param_in_band(port_id, - q6audio_get_port_index(port_id), - param_hdr, - (u8 *) &enc_pkt_id_param); + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &enc_pkt_id_param); if (ret) { pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER for port 0x%x failed %d\n", - __func__, port_id, ret); + __func__, port_id, ret); goto exit; } - if (format != ASM_MEDIA_FMT_APTX_AD_SPEECH) { + if (format == ASM_MEDIA_FMT_LC3) { + pr_debug("%s: sending CAPI_V2_PARAM_LC3_ENC_INIT to DSP\n", + __func__); + param_hdr.param_id = CAPI_V2_PARAM_LC3_ENC_INIT; + param_hdr.param_size = + sizeof(struct afe_lc3_enc_cfg_t); + lc3_enc_config_init = cfg->lc3_enc_config.enc_codec.to_Air_cfg; + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &lc3_enc_config_init); + if (ret) { + pr_err("%s: CAPI_V2_PARAM_LC3_ENC_INIT for port 0x%x failed %d\n", + __func__, port_id, ret); + goto exit; + } + + pr_debug("%s: sending AVS_COP_V2_PARAM_ID_STREAM_INFO to DSP\n", + __func__); + param_hdr.param_id = AVS_COP_V2_PARAM_ID_STREAM_INFO; + param_hdr.param_size = + sizeof(struct avs_cop_v2_param_id_stream_info_t); + lc3_enc_stream_info = cfg->lc3_enc_config.enc_codec.streamMapToAir; + + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &lc3_enc_stream_info); + if (ret) { + pr_err("%s: AVS_COP_V2_PARAM_ID_STREAM_INFO for port 0x%x failed %d\n", + __func__, port_id, ret); + goto exit; + } + } + + if (format != ASM_MEDIA_FMT_APTX_AD_SPEECH && + format != ASM_MEDIA_FMT_LC3) { pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING mode= %d to DSP payload\n", __func__, scrambler_mode); param_hdr.param_id = AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING; @@ -5403,8 +5492,10 @@ static int q6afe_send_enc_config(u16 port_id, if ((format == ASM_MEDIA_FMT_LDAC && cfg->ldac_config.abr_config.is_abr_enabled) || format == ASM_MEDIA_FMT_APTX_ADAPTIVE || - format == ASM_MEDIA_FMT_APTX_AD_SPEECH) { - if (format != ASM_MEDIA_FMT_APTX_AD_SPEECH) { + format == ASM_MEDIA_FMT_APTX_AD_SPEECH || + format == ASM_MEDIA_FMT_LC3) { + if (format != ASM_MEDIA_FMT_APTX_AD_SPEECH && + format != ASM_MEDIA_FMT_LC3) { pr_debug("%s:sending AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP to DSP payload", __func__); param_hdr.param_id = AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP; @@ -5435,6 +5526,9 @@ static int q6afe_send_enc_config(u16 port_id, else if (format == ASM_MEDIA_FMT_APTX_AD_SPEECH) imc_info_param.imc_info = cfg->aptx_ad_speech_config.imc_info; + else if (format == ASM_MEDIA_FMT_LC3) + imc_info_param.imc_info = + cfg->lc3_enc_config.imc_info; else imc_info_param.imc_info = cfg->ldac_config.abr_config.imc_info; @@ -5463,6 +5557,9 @@ static int q6afe_send_enc_config(u16 port_id, else if (format == ASM_MEDIA_FMT_APTX_AD_SPEECH) media_type.sample_rate = cfg->aptx_ad_speech_config.custom_cfg.sample_rate; + else if (format == ASM_MEDIA_FMT_LC3) + media_type.sample_rate = + cfg->lc3_enc_config.enc_codec.to_Air_cfg.toAirConfig.sampling_freq; else media_type.sample_rate = afe_config.slim_sch.sample_rate; @@ -5488,7 +5585,8 @@ static int q6afe_send_enc_config(u16 port_id, goto exit; } - if (format == ASM_MEDIA_FMT_APTX_AD_SPEECH) { + if (format == ASM_MEDIA_FMT_APTX_AD_SPEECH || + format == ASM_MEDIA_FMT_LC3) { pr_debug("%s: sending AFE_PARAM_ID_RATE_MATCHED_PORT to DSP payload", __func__); param_hdr.param_id = AFE_PARAM_ID_RATE_MATCHED_PORT; @@ -5549,6 +5647,42 @@ int afe_set_tws_channel_mode(u32 format, u16 port_id, u32 channel_mode) } EXPORT_SYMBOL(afe_set_tws_channel_mode); +int afe_set_lc3_channel_mode(u32 format, u16 port_id, u32 channel_mode) +{ + struct lc3_channel_mode_param_t channel_mode_param; + struct param_hdr_v3 param_info; + int ret = 0; + u32 param_id = 0; + + if (format == ASM_MEDIA_FMT_LC3) { + param_id = CAPI_V2_PARAM_SET_LC3_ENC_DOWNMIX_2_MONO; + } else { + pr_err("%s: Not supported format 0x%x\n", __func__, format); + return -EINVAL; + } + + memset(¶m_info, 0, sizeof(param_info)); + memset(&channel_mode_param, 0, sizeof(channel_mode_param)); + + param_info.module_id = AFE_MODULE_ID_ENCODER; + param_info.instance_id = INSTANCE_ID_0; + param_info.param_id = param_id; + param_info.param_size = sizeof(channel_mode_param); + + channel_mode_param.channel_mode = channel_mode; + + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_info, + (u8 *) &channel_mode_param); + if (ret) + pr_err("%s: AFE set channel mode cfg for port 0x%x failed %d\n", + __func__, port_id, ret); + + return ret; +} +EXPORT_SYMBOL(afe_set_lc3_channel_mode); + static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, u32 rate, u16 afe_in_channels, u16 afe_in_bit_width, union afe_enc_config_data *enc_cfg, @@ -5913,7 +6047,8 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, * Only loading de-packetizer module. */ if (codec_format == ENC_CODEC_TYPE_LDAC || - codec_format == ASM_MEDIA_FMT_APTX_ADAPTIVE) + codec_format == ASM_MEDIA_FMT_APTX_ADAPTIVE || + codec_format == ASM_MEDIA_FMT_LC3) ret = q6afe_load_avcs_modules(1, port_id, DECODER_CASE, codec_format); else diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 1d6d3debcc18..87173c79da61 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -4103,6 +4103,9 @@ struct afe_id_aptx_adaptive_enc_init /* Macro for defining the packetizer ID: COP. */ #define AFE_MODULE_ID_PACKETIZER_COP 0x0001322A +/* Macro for defining the packetizer ID: COP V2 */ +#define AFE_MODULE_ID_PACKETIZER_COP_V2 0x000132F9 + /* * Packetizer type parameter for the #AVS_MODULE_ID_ENCODER module. * This parameter cannot be set runtime. @@ -4168,6 +4171,7 @@ struct afe_id_aptx_adaptive_enc_init */ #define AFE_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AFE_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 +#define AFE_MODULE_ID_DEPACKETIZER_COP_V2 0x000132FC /* Macros for dynamic loading of modules by AVCS */ @@ -4175,10 +4179,22 @@ struct afe_id_aptx_adaptive_enc_init #define AVS_MODULE_ID_PACKETIZER_COP_V1 0x000132E8 +#define AVS_MODULE_ID_PACKETIZER_COP_V2 0x000132F9 + #define AVS_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AVS_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 +#define AVS_MODULE_ID_DEPACKETIZER_COP_V2 0x000132FC + +/* + * Depacketizer and packetizer type parameter for the + * #AVS_MODULE_ID_DEPACKETIZER_COP_V2 module and + * #AVS_MODULE_ID_PACKETIZER_COP_V2 module. + */ + +#define AVS_COP_V2_PARAM_ID_STREAM_INFO 0x000132FD + /* * Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module. * This parameter cannot be set runtime. @@ -4192,6 +4208,12 @@ struct afe_id_aptx_adaptive_enc_init struct aptx_channel_mode_param_t { u32 channel_mode; } __packed; + +#define CAPI_V2_PARAM_SET_LC3_ENC_DOWNMIX_2_MONO 0x00013384 +struct lc3_channel_mode_param_t { + u32 channel_mode; +} __packed; + /* * Decoder buffer ID parameter for the #AVS_MODULE_ID_DECODER module. * This parameter cannot be set runtime. @@ -4410,6 +4432,10 @@ struct asm_aac_enc_cfg_t { /* FMT ID for apt-X Adaptive speech */ #define ASM_MEDIA_FMT_APTX_AD_SPEECH 0x00013208 +/* FMT ID for lc3 codec */ +#define ASM_MEDIA_FMT_LC3 0x0001337E +#define ENC_CODEC_TYPE_LC3 0x2B000000 + #define PCM_CHANNEL_L 1 #define PCM_CHANNEL_R 2 #define PCM_CHANNEL_C 3 @@ -4470,6 +4496,70 @@ struct asm_aptx_ad_speech_enc_cfg_t struct asm_aptx_ad_speech_mode_cfg_t speech_mode; } __attribute__ ((packed)); + +#define CAPI_V2_PARAM_LC3_ENC_INIT 0x00013381 +#define CAPI_V2_PARAM_LC3_DEC_MODULE_INIT 0x00013391 +struct afe_lc3_stream_map_t { + uint32_t stream_id; + uint32_t direction; + uint32_t channel_mask_lsw; + uint32_t channel_mask_msw; +} __packed; + +struct afe_stream_map_t { + uint32_t audio_location; + uint8_t stream_id; + uint8_t direction; +} __packed; + +struct afe_lc3_cfg_t { + uint32_t api_version; + uint32_t sampling_freq; + uint32_t max_octets_per_frame; + uint32_t frame_duration; + uint32_t bit_depth; + uint32_t num_blocks; + uint8_t default_q_level; + uint8_t vendor_specific[16]; + uint32_t mode; +} __packed; + +struct afe_lc3_enc_cfg_t { + struct afe_lc3_cfg_t toAirConfig; + uint32_t stream_map_size; + struct afe_stream_map_t streamMapOut[16]; +} __packed; + +struct afe_lc3_dec_cfg_t { + struct afe_lc3_cfg_t FromAir; + uint32_t decoder_output_channel; + uint32_t stream_map_size; + struct afe_stream_map_t streamMapIn[16]; +} __packed; + +struct avs_cop_v2_param_id_stream_info_t { + uint32_t stream_map_size; + struct afe_lc3_stream_map_t streamMap[16]; +} __packed; + +struct afe_lc3_dec_config_t { + struct avs_cop_v2_param_id_stream_info_t streamMapToAir; +} __packed; + +struct afe_lc3_enc_config_t { + struct afe_lc3_enc_cfg_t to_Air_cfg; + struct avs_cop_v2_param_id_stream_info_t streamMapToAir; +} __packed; + +struct asm_enc_lc3_cfg_t { + struct afe_imc_dec_enc_info imc_info; + struct afe_lc3_enc_config_t enc_codec; +} __packed; + +struct asm_lc3_dec_cfg_t { + struct afe_lc3_dec_config_t dec_codec; +} __packed; + struct afe_matched_port_t { uint32_t minor_version; @@ -4765,12 +4855,14 @@ union afe_enc_config_data { struct asm_ldac_enc_cfg_t ldac_config; struct asm_aptx_ad_enc_cfg_t aptx_ad_config; struct asm_aptx_ad_speech_enc_cfg_t aptx_ad_speech_config; + struct asm_enc_lc3_cfg_t lc3_enc_config; }; struct afe_enc_config { u32 format; u32 scrambler_mode; u32 mono_mode; + u32 lc3_mono_mode; union afe_enc_config_data data; }; @@ -4830,6 +4922,7 @@ union afe_dec_config_data { struct asm_mp3_dec_cfg_t mp3_config; struct asm_aptx_ad_dec_cfg_t aptx_ad_config; struct asm_aptx_ad_speech_dec_cfg_t aptx_ad_speech_config; + struct asm_lc3_dec_cfg_t lc3_dec_config; }; struct afe_dec_config { diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index 09afc2e2aa47..5c66b4b5ca64 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -54,6 +54,12 @@ #define AFE_API_VERSION_V8 8 +/* the different modes for data*/ +#define BAP_UNICAST 1 +#define BAP_BROADCAST 2 +#define BAP_BA_SIMULCAST 3 + + typedef int (*routing_cb)(int port); enum { @@ -426,6 +432,7 @@ int afe_get_power_mode_cfg(u16 port_id, u32 *enable_flag); int afe_port_start(u16 port_id, union afe_port_config *afe_config, u32 rate); int afe_set_tws_channel_mode(u32 foramt, u16 port_id, u32 channel_mode); +int afe_set_lc3_channel_mode(u32 foramt, u16 port_id, u32 channel_mode); int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config, u32 rate, u16 afe_in_channels, u16 afe_in_bit_width, struct afe_enc_config *enc_config,