Bladeren bron

Merge "q6afe: add support for lc3 codec playback"

qctecmdr 4 jaren geleden
bovenliggende
commit
e2c4330a48
4 gewijzigde bestanden met toevoegingen van 368 en 33 verwijderingen
  1. 102 2
      asoc/msm-dai-q6-v2.c
  2. 166 31
      dsp/q6afe.c
  3. 93 0
      include/dsp/apr_audio-v2.h
  4. 7 0
      include/dsp/q6afe-v2.h

+ 102 - 2
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));

+ 166 - 31
dsp/q6afe.c

@@ -401,6 +401,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 =
@@ -416,6 +420,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;
@@ -4898,6 +4907,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;
 
@@ -4907,6 +4917,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(&param_hdr, 0, sizeof(param_hdr));
 
 	param_hdr.module_id = AFE_MODULE_ID_DECODER;
@@ -4921,6 +4932,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,
@@ -5028,6 +5045,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;
@@ -5055,18 +5075,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;
@@ -5085,6 +5102,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;
@@ -5168,6 +5211,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;
@@ -5185,13 +5230,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(&param_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;
@@ -5229,23 +5277,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) {
@@ -5353,21 +5404,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;
@@ -5404,8 +5493,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;
@@ -5436,6 +5527,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;
@@ -5464,6 +5558,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;
@@ -5489,7 +5586,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;
@@ -5550,6 +5648,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(&param_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,
@@ -5914,7 +6048,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

+ 93 - 0
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 {

+ 7 - 0
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,