Browse Source

asoc: add A2DP sink support in dai-driver

Add decoder config support for split A2DP sink.

Change-Id: If71a2b2ae7f0f0500f196b0552ab185c9f37b778
Signed-off-by: Florian Pfister <[email protected]>
Signed-off-by: Surendar Karka <[email protected]>
Florian Pfister 6 years ago
parent
commit
522073c370
2 changed files with 207 additions and 43 deletions
  1. 205 41
      asoc/msm-dai-q6-v2.c
  2. 2 2
      asoc/msm-pcm-routing-v2.c

+ 205 - 41
asoc/msm-dai-q6-v2.c

@@ -52,12 +52,16 @@ enum {
 	ENC_FMT_NONE,
 	DEC_FMT_NONE = ENC_FMT_NONE,
 	ENC_FMT_SBC = ASM_MEDIA_FMT_SBC,
+	DEC_FMT_SBC = ASM_MEDIA_FMT_SBC,
 	ENC_FMT_AAC_V2 = ASM_MEDIA_FMT_AAC_V2,
+	DEC_FMT_AAC_V2 = ASM_MEDIA_FMT_AAC_V2,
 	ENC_FMT_APTX = ASM_MEDIA_FMT_APTX,
 	ENC_FMT_APTX_HD = ASM_MEDIA_FMT_APTX_HD,
 	ENC_FMT_CELT = ASM_MEDIA_FMT_CELT,
 	ENC_FMT_LDAC = ASM_MEDIA_FMT_LDAC,
 	ENC_FMT_APTX_ADAPTIVE = ASM_MEDIA_FMT_APTX_ADAPTIVE,
+	DEC_FMT_APTX_ADAPTIVE = ASM_MEDIA_FMT_APTX_ADAPTIVE,
+	DEC_FMT_MP3 = ASM_MEDIA_FMT_MP3,
 };
 
 enum {
@@ -203,8 +207,10 @@ struct msm_dai_q6_dai_data {
 	u32 channels;
 	u32 bitwidth;
 	u32 cal_mode;
-	u32 afe_in_channels;
-	u16 afe_in_bitformat;
+	u32 afe_rx_in_channels;
+	u16 afe_rx_in_bitformat;
+	u32 afe_tx_out_channels;
+	u16 afe_tx_out_bitformat;
 	struct afe_enc_config enc_config;
 	struct afe_dec_config dec_config;
 	union afe_port_config port_config;
@@ -2049,7 +2055,7 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
 		if (dai_data->enc_config.format != ENC_FMT_NONE) {
 			int bitwidth = 0;
 
-			switch (dai_data->afe_in_bitformat) {
+			switch (dai_data->afe_rx_in_bitformat) {
 			case SNDRV_PCM_FORMAT_S32_LE:
 				bitwidth = 32;
 				break;
@@ -2065,26 +2071,41 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
 				 __func__, dai_data->enc_config.format);
 			rc = afe_port_start_v2(dai->id, &dai_data->port_config,
 					       dai_data->rate,
-					       dai_data->afe_in_channels,
+					       dai_data->afe_rx_in_channels,
 					       bitwidth,
 					       &dai_data->enc_config, NULL);
 			if (rc < 0)
 				pr_err("%s: afe_port_start_v2 failed error: %d\n",
 					__func__, rc);
 		} else if (dai_data->dec_config.format != DEC_FMT_NONE) {
+			int bitwidth = 0;
+
 			/*
-			 * A dummy Tx session is established in LPASS to
-			 * get the link statistics from BTSoC.
-			 * Depacketizer extracts the bit rate levels and
-			 * transmits them to the encoder on the Rx path.
-			 * Since this is a dummy decoder - channels, bit
-			 * width are sent as 0 and encoder config is NULL.
-			 * This could be updated in the future if there is
-			 * a complete Tx path set up that uses this decoder.
+			 * If bitwidth is not configured set default value to
+			 * zero, so that decoder port config uses slim device
+			 * bit width value in afe decoder config.
 			 */
+			switch (dai_data->afe_tx_out_bitformat) {
+			case SNDRV_PCM_FORMAT_S32_LE:
+				bitwidth = 32;
+				break;
+			case SNDRV_PCM_FORMAT_S24_LE:
+				bitwidth = 24;
+				break;
+			case SNDRV_PCM_FORMAT_S16_LE:
+				bitwidth = 16;
+				break;
+			default:
+				bitwidth = 0;
+				break;
+			}
+			pr_debug("%s: calling AFE_PORT_START_V2 with dec format: %d\n",
+				 __func__, dai_data->dec_config.format);
 			rc = afe_port_start_v2(dai->id, &dai_data->port_config,
-					       dai_data->rate, 0, 0, NULL,
-					       &dai_data->dec_config);
+					       dai_data->rate,
+					       dai_data->afe_tx_out_channels,
+					       bitwidth,
+					       NULL, &dai_data->dec_config);
 			if (rc < 0) {
 				pr_err("%s: fail to open AFE port 0x%x\n",
 					__func__, dai->id);
@@ -2902,17 +2923,17 @@ static int msm_dai_q6_afe_enc_cfg_put(struct snd_kcontrol *kcontrol,
 	return ret;
 }
 
-static const char *const afe_input_chs_text[] = {"Zero", "One", "Two"};
+static const char *const afe_chs_text[] = {"Zero", "One", "Two"};
 
-static const struct soc_enum afe_input_chs_enum[] = {
-	SOC_ENUM_SINGLE_EXT(3, afe_input_chs_text),
+static const struct soc_enum afe_chs_enum[] = {
+	SOC_ENUM_SINGLE_EXT(3, afe_chs_text),
 };
 
-static const char *const afe_input_bit_format_text[] = {"S16_LE", "S24_LE",
+static const char *const afe_bit_format_text[] = {"S16_LE", "S24_LE",
 							"S32_LE"};
 
-static const struct soc_enum afe_input_bit_format_enum[] = {
-	SOC_ENUM_SINGLE_EXT(3, afe_input_bit_format_text),
+static const struct soc_enum afe_bit_format_enum[] = {
+	SOC_ENUM_SINGLE_EXT(3, afe_bit_format_text),
 };
 
 static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol,
@@ -2921,9 +2942,9 @@ static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol,
 	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
 
 	if (dai_data) {
-		ucontrol->value.integer.value[0] = dai_data->afe_in_channels;
+		ucontrol->value.integer.value[0] = dai_data->afe_rx_in_channels;
 		pr_debug("%s:afe input channel = %d\n",
-			  __func__, dai_data->afe_in_channels);
+			  __func__, dai_data->afe_rx_in_channels);
 	}
 
 	return 0;
@@ -2935,9 +2956,9 @@ static int msm_dai_q6_afe_input_channel_put(struct snd_kcontrol *kcontrol,
 	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
 
 	if (dai_data) {
-		dai_data->afe_in_channels = ucontrol->value.integer.value[0];
+		dai_data->afe_rx_in_channels = ucontrol->value.integer.value[0];
 		pr_debug("%s: updating afe input channel : %d\n",
-			__func__, dai_data->afe_in_channels);
+			__func__, dai_data->afe_rx_in_channels);
 	}
 
 	return 0;
@@ -2954,7 +2975,7 @@ static int msm_dai_q6_afe_input_bit_format_get(
 		return -EINVAL;
 	}
 
-	switch (dai_data->afe_in_bitformat) {
+	switch (dai_data->afe_rx_in_bitformat) {
 	case SNDRV_PCM_FORMAT_S32_LE:
 		ucontrol->value.integer.value[0] = 2;
 		break;
@@ -2984,22 +3005,107 @@ static int msm_dai_q6_afe_input_bit_format_put(
 	}
 	switch (ucontrol->value.integer.value[0]) {
 	case 2:
-		dai_data->afe_in_bitformat = SNDRV_PCM_FORMAT_S32_LE;
+		dai_data->afe_rx_in_bitformat = SNDRV_PCM_FORMAT_S32_LE;
 		break;
 	case 1:
-		dai_data->afe_in_bitformat = SNDRV_PCM_FORMAT_S24_LE;
+		dai_data->afe_rx_in_bitformat = SNDRV_PCM_FORMAT_S24_LE;
 		break;
 	case 0:
 	default:
-		dai_data->afe_in_bitformat = SNDRV_PCM_FORMAT_S16_LE;
+		dai_data->afe_rx_in_bitformat = SNDRV_PCM_FORMAT_S16_LE;
 		break;
 	}
 	pr_debug("%s: updating afe input bit format : %d\n",
-		__func__, dai_data->afe_in_bitformat);
+		__func__, dai_data->afe_rx_in_bitformat);
+
+	return 0;
+}
+
+static int msm_dai_q6_afe_output_bit_format_get(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+	if (!dai_data) {
+		pr_err("%s: Invalid dai data\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (dai_data->afe_tx_out_bitformat) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: afe output bit format : %ld\n",
+		  __func__, ucontrol->value.integer.value[0]);
 
 	return 0;
 }
 
+static int msm_dai_q6_afe_output_bit_format_put(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+	if (!dai_data) {
+		pr_err("%s: Invalid dai data\n", __func__);
+		return -EINVAL;
+	}
+	switch (ucontrol->value.integer.value[0]) {
+	case 2:
+		dai_data->afe_tx_out_bitformat = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 1:
+		dai_data->afe_tx_out_bitformat = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		dai_data->afe_tx_out_bitformat = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: updating afe output bit format : %d\n",
+		__func__, dai_data->afe_tx_out_bitformat);
+
+	return 0;
+}
+
+static int msm_dai_q6_afe_output_channel_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+	if (dai_data) {
+		ucontrol->value.integer.value[0] =
+			dai_data->afe_tx_out_channels;
+		pr_debug("%s:afe output channel = %d\n",
+			  __func__, dai_data->afe_tx_out_channels);
+	}
+	return 0;
+}
+
+static int msm_dai_q6_afe_output_channel_put(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+	if (dai_data) {
+		dai_data->afe_tx_out_channels =
+			ucontrol->value.integer.value[0];
+		pr_debug("%s: updating afe output channel : %d\n",
+			__func__, dai_data->afe_tx_out_channels);
+	}
+	return 0;
+}
+
 static int msm_dai_q6_afe_scrambler_mode_get(
 			struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
@@ -3041,10 +3147,10 @@ static const struct snd_kcontrol_new afe_enc_config_controls[] = {
 		.get = msm_dai_q6_afe_enc_cfg_get,
 		.put = msm_dai_q6_afe_enc_cfg_put,
 	},
-	SOC_ENUM_EXT("AFE Input Channels", afe_input_chs_enum[0],
+	SOC_ENUM_EXT("AFE Input Channels", afe_chs_enum[0],
 		     msm_dai_q6_afe_input_channel_get,
 		     msm_dai_q6_afe_input_channel_put),
-	SOC_ENUM_EXT("AFE Input Bit Format", afe_input_bit_format_enum[0],
+	SOC_ENUM_EXT("AFE Input Bit Format", afe_bit_format_enum[0],
 		     msm_dai_q6_afe_input_bit_format_get,
 		     msm_dai_q6_afe_input_bit_format_put),
 	SOC_SINGLE_EXT("AFE Scrambler Mode",
@@ -3066,7 +3172,7 @@ static int msm_dai_q6_afe_dec_cfg_get(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
 	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
-	int format_size = 0;
+	u32 format_size = 0;
 
 	if (!dai_data) {
 		pr_err("%s: Invalid dai data\n", __func__);
@@ -3077,10 +3183,25 @@ static int msm_dai_q6_afe_dec_cfg_get(struct snd_kcontrol *kcontrol,
 	memcpy(ucontrol->value.bytes.data,
 		&dai_data->dec_config.format,
 		format_size);
-	memcpy(ucontrol->value.bytes.data + format_size,
-		&dai_data->dec_config.abr_dec_cfg,
-		sizeof(struct afe_abr_dec_cfg_t));
+	switch (dai_data->dec_config.format) {
+	case DEC_FMT_AAC_V2:
+		memcpy(ucontrol->value.bytes.data + format_size,
+			&dai_data->dec_config.data,
+			sizeof(struct asm_aac_dec_cfg_v2_t));
+		break;
+	case DEC_FMT_SBC:
+	case DEC_FMT_MP3:
+		/* No decoder specific data available */
+		break;
+	default:
+		pr_debug("%s: Default decoder config for %d format: Expect abr_dec_cfg\n",
+				__func__, dai_data->dec_config.format);
+		memcpy(ucontrol->value.bytes.data + format_size,
+			&dai_data->dec_config.abr_dec_cfg,
+			sizeof(struct afe_abr_dec_cfg_t));
 
+		break;
+	}
 	return 0;
 }
 
@@ -3088,7 +3209,7 @@ static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
 	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
-	int format_size = 0;
+	u32 format_size = 0;
 
 	if (!dai_data) {
 		pr_err("%s: Invalid dai data\n", __func__);
@@ -3101,10 +3222,26 @@ static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol,
 	memcpy(&dai_data->dec_config.format,
 		ucontrol->value.bytes.data,
 		format_size);
-	memcpy(&dai_data->dec_config.abr_dec_cfg,
-		ucontrol->value.bytes.data + format_size,
-		sizeof(struct afe_abr_dec_cfg_t));
-
+	pr_debug("%s: Received decoder config for %d format\n",
+			__func__, dai_data->dec_config.format);
+	switch (dai_data->dec_config.format) {
+	case DEC_FMT_AAC_V2:
+		memcpy(&dai_data->dec_config.data,
+			ucontrol->value.bytes.data + format_size,
+			sizeof(struct asm_aac_dec_cfg_v2_t));
+		break;
+	case DEC_FMT_SBC:
+	case DEC_FMT_MP3:
+		/* No decoder specific data available */
+		break;
+	default:
+		pr_debug("%s: Default decoder config for %d format: Expect abr_dec_cfg\n",
+				__func__, dai_data->dec_config.format);
+		memcpy(&dai_data->dec_config.abr_dec_cfg,
+			ucontrol->value.bytes.data + format_size,
+			sizeof(struct afe_abr_dec_cfg_t));
+		break;
+	}
 	return 0;
 }
 
@@ -3118,6 +3255,21 @@ static const struct snd_kcontrol_new afe_dec_config_controls[] = {
 		.get = msm_dai_q6_afe_dec_cfg_get,
 		.put = msm_dai_q6_afe_dec_cfg_put,
 	},
+	{
+		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			   SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+		.name = "SLIM_9_TX Decoder Config",
+		.info = msm_dai_q6_afe_dec_cfg_info,
+		.get = msm_dai_q6_afe_dec_cfg_get,
+		.put = msm_dai_q6_afe_dec_cfg_put,
+	},
+	SOC_ENUM_EXT("AFE Output Channels", afe_chs_enum[0],
+		     msm_dai_q6_afe_output_channel_get,
+		     msm_dai_q6_afe_output_channel_put),
+	SOC_ENUM_EXT("AFE Output Bit Format", afe_bit_format_enum[0],
+		     msm_dai_q6_afe_output_bit_format_get,
+		     msm_dai_q6_afe_output_bit_format_put),
 };
 
 static int msm_dai_q6_slim_rx_drift_info(struct snd_kcontrol *kcontrol,
@@ -3296,6 +3448,17 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
 				 snd_ctl_new1(&afe_dec_config_controls[0],
 				 dai_data));
 		break;
+	case SLIMBUS_9_TX:
+		rc = snd_ctl_add(dai->component->card->snd_card,
+				 snd_ctl_new1(&afe_dec_config_controls[1],
+				 dai_data));
+		rc = snd_ctl_add(dai->component->card->snd_card,
+				 snd_ctl_new1(&afe_dec_config_controls[2],
+				 dai_data));
+		rc = snd_ctl_add(dai->component->card->snd_card,
+				 snd_ctl_new1(&afe_dec_config_controls[3],
+				 dai_data));
+		break;
 	case RT_PROXY_DAI_001_RX:
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				 snd_ctl_new1(&rt_proxy_config_controls[0],
@@ -4284,7 +4447,8 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai[] = {
 			.stream_name = "Slimbus9 Capture",
 			.aif_name = "SLIMBUS_9_TX",
 			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+			SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
 			SNDRV_PCM_RATE_192000,
 			.formats = SNDRV_PCM_FMTBIT_S16_LE |
 				   SNDRV_PCM_FMTBIT_S24_LE |

+ 2 - 2
asoc/msm-pcm-routing-v2.c

@@ -794,7 +794,7 @@ static struct msm_pcm_stream_app_type_cfg
 
 static int last_be_id_configured[MSM_FRONTEND_DAI_MAX][MAX_SESSION_TYPES];
 
-/* The caller of this should aqcuire routing lock */
+/* The caller of this should acquire routing lock */
 void msm_pcm_routing_get_bedai_info(int be_idx,
 				    struct msm_pcm_routing_bdai_data *be_dai)
 {
@@ -803,7 +803,7 @@ void msm_pcm_routing_get_bedai_info(int be_idx,
 		       sizeof(struct msm_pcm_routing_bdai_data));
 }
 
-/* The caller of this should aqcuire routing lock */
+/* The caller of this should acquire routing lock */
 void msm_pcm_routing_get_fedai_info(int fe_idx, int sess_type,
 				    struct msm_pcm_routing_fdai_data *fe_dai)
 {