Browse Source

Merge "asoc: Add support for Aptx Adaptive decoder"

Linux Build Service Account 6 years ago
parent
commit
16470427d0
3 changed files with 140 additions and 17 deletions
  1. 74 13
      asoc/msm-dai-q6-v2.c
  2. 50 4
      dsp/q6afe.c
  3. 16 0
      include/dsp/apr_audio-v2.h

+ 74 - 13
asoc/msm-dai-q6-v2.c

@@ -3226,11 +3226,64 @@ static int  msm_dai_q6_afe_dec_cfg_info(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int msm_dai_q6_afe_feedback_dec_cfg_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+	u32 format_size = 0;
+
+	if (!dai_data) {
+		pr_err("%s: Invalid dai data\n", __func__);
+		return -EINVAL;
+	}
+
+	format_size = sizeof(dai_data->dec_config.format);
+	memcpy(ucontrol->value.bytes.data,
+		&dai_data->dec_config.format,
+		format_size);
+
+	pr_debug("%s: abr_dec_cfg for %d format\n",
+			__func__, dai_data->dec_config.format);
+	memcpy(ucontrol->value.bytes.data + format_size,
+		&dai_data->dec_config.abr_dec_cfg,
+		sizeof(struct afe_imc_dec_enc_info));
+
+	return 0;
+}
+
+static int msm_dai_q6_afe_feedback_dec_cfg_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+	u32 format_size = 0;
+
+	if (!dai_data) {
+		pr_err("%s: Invalid dai data\n", __func__);
+		return -EINVAL;
+	}
+
+	memset(&dai_data->dec_config, 0x0,
+		sizeof(struct afe_dec_config));
+	format_size = sizeof(dai_data->dec_config.format);
+	memcpy(&dai_data->dec_config.format,
+		ucontrol->value.bytes.data,
+		format_size);
+
+	pr_debug("%s: abr_dec_cfg for %d format\n",
+			__func__, dai_data->dec_config.format);
+	memcpy(&dai_data->dec_config.abr_dec_cfg,
+		ucontrol->value.bytes.data + format_size,
+		sizeof(struct afe_imc_dec_enc_info));
+	dai_data->dec_config.abr_dec_cfg.is_abr_enabled = true;
+	return 0;
+}
+
 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;
 	u32 format_size = 0;
+	int ret = 0;
 
 	if (!dai_data) {
 		pr_err("%s: Invalid dai data\n", __func__);
@@ -3247,20 +3300,23 @@ static int msm_dai_q6_afe_dec_cfg_get(struct snd_kcontrol *kcontrol,
 			&dai_data->dec_config.data,
 			sizeof(struct asm_aac_dec_cfg_v2_t));
 		break;
+	case DEC_FMT_APTX_ADAPTIVE:
+		memcpy(ucontrol->value.bytes.data + format_size,
+			&dai_data->dec_config.data,
+			sizeof(struct asm_aptx_ad_dec_cfg_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",
+		pr_err("%s: Invalid format %d\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));
-
+		ret = -EINVAL;
 		break;
 	}
-	return 0;
+
+	return ret;
 }
 
 static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol,
@@ -3268,6 +3324,7 @@ static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol,
 {
 	struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
 	u32 format_size = 0;
+	int ret = 0;
 
 	if (!dai_data) {
 		pr_err("%s: Invalid dai data\n", __func__);
@@ -3293,15 +3350,19 @@ static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol,
 			ucontrol->value.bytes.data + format_size,
 			sizeof(struct asm_sbc_dec_cfg_t));
 		break;
+	case DEC_FMT_APTX_ADAPTIVE:
+		memcpy(&dai_data->dec_config.data,
+			ucontrol->value.bytes.data + format_size,
+			sizeof(struct asm_aptx_ad_dec_cfg_t));
+		break;
 	default:
-		pr_debug("%s: Default decoder config for %d format: Expect abr_dec_cfg\n",
+		pr_err("%s: Invalid format %d\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));
+		ret = -EINVAL;
 		break;
 	}
-	return 0;
+
+	return ret;
 }
 
 static const struct snd_kcontrol_new afe_dec_config_controls[] = {
@@ -3311,8 +3372,8 @@ static const struct snd_kcontrol_new afe_dec_config_controls[] = {
 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
 		.name = "SLIM_7_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,
+		.get = msm_dai_q6_afe_feedback_dec_cfg_get,
+		.put = msm_dai_q6_afe_feedback_dec_cfg_put,
 	},
 	{
 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |

+ 50 - 4
dsp/q6afe.c

@@ -75,6 +75,11 @@ enum {
 	Q6AFE_MSM_SPKR_FTM_MODE
 };
 
+enum {
+	APTX_AD_48 = 0,
+	APTX_AD_44_1 = 1
+};
+
 struct wlock {
 	struct wakeup_source ws;
 };
@@ -3564,6 +3569,29 @@ static int q6afe_send_dec_config(u16 port_id,
 			goto exit;
 		}
 		break;
+	case ASM_MEDIA_FMT_APTX_ADAPTIVE:
+		if (!cfg->abr_dec_cfg.is_abr_enabled) {
+			pr_debug("%s: sending aptx adaptive congestion buffer size to dsp\n",
+				__func__);
+			param_hdr.param_id =
+				AFE_DECODER_PARAM_ID_CONGESTION_BUFFER_SIZE;
+			param_hdr.param_size =
+			   sizeof(struct avs_dec_congestion_buffer_param_t);
+			dec_buffer_id_param.version = 0;
+			dec_buffer_id_param.max_nr_buffers  = 226;
+			dec_buffer_id_param.pre_buffer_size = 226;
+			ret = q6afe_pack_and_set_param_in_band(port_id,
+						q6audio_get_port_index(port_id),
+						param_hdr,
+						(u8 *) &dec_buffer_id_param);
+			if (ret) {
+				pr_err("%s: aptx adaptive congestion buffer size for port 0x%x failed %d\n",
+					__func__, port_id, ret);
+				goto exit;
+			}
+			break;
+		}
+		/* fall through for abr enabled case */
 	default:
 		pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload\n",
 			  __func__);
@@ -3584,7 +3612,7 @@ static int q6afe_send_dec_config(u16 port_id,
 		break;
 	}
 
-	pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
+	pr_debug("%s: Send AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n", __func__);
 	param_hdr.module_id = AFE_MODULE_PORT;
 	param_hdr.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
 	param_hdr.param_size = sizeof(struct afe_port_media_type_t);
@@ -3598,6 +3626,15 @@ static int q6afe_send_dec_config(u16 port_id,
 		media_type.sample_rate =
 			cfg->data.sbc_config.sample_rate;
 		break;
+	case ASM_MEDIA_FMT_APTX_ADAPTIVE:
+		if (!cfg->abr_dec_cfg.is_abr_enabled) {
+			media_type.sample_rate =
+			(cfg->data.aptx_ad_config.sample_rate == APTX_AD_44_1) ?
+				AFE_PORT_SAMPLE_RATE_44_1K :
+				AFE_PORT_SAMPLE_RATE_48K;
+			break;
+		}
+		/* fall through for abr enabled case */
 	default:
 		media_type.sample_rate =
 			afe_config.slim_sch.sample_rate;
@@ -3623,11 +3660,19 @@ static int q6afe_send_dec_config(u16 port_id,
 		goto exit;
 	}
 
-	if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2) {
+	if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 &&
+		format != ASM_MEDIA_FMT_APTX_ADAPTIVE) {
 		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;
+	}
+
 	pr_debug("%s: sending AFE_DECODER_PARAM_ID_DEC_MEDIA_FMT to DSP payload\n",
 		  __func__);
 	param_hdr.module_id = AFE_MODULE_ID_DECODER;
@@ -3646,9 +3691,10 @@ static int q6afe_send_dec_config(u16 port_id,
 
 	switch (cfg->format) {
 	case ASM_MEDIA_FMT_AAC_V2:
+	case ASM_MEDIA_FMT_APTX_ADAPTIVE:
 		param_hdr.param_size = sizeof(struct afe_dec_media_fmt_t);
 
-		pr_debug("%s:send AFE_DECODER_PARAM_ID DEC_MEDIA_FMT to DSP payload\n",
+		pr_debug("%s:send AVS_DECODER_PARAM_ID DEC_MEDIA_FMT to DSP payload\n",
 			 __func__);
 		param_hdr.param_id = AVS_DECODER_PARAM_ID_DEC_MEDIA_FMT;
 		dec_media_fmt.dec_media_config = cfg->data;
@@ -3657,7 +3703,7 @@ static int q6afe_send_dec_config(u16 port_id,
 						param_hdr,
 						(u8 *) &dec_media_fmt);
 		if (ret) {
-			pr_err("%s: AFE_DECODER_PARAM_ID DEC_MEDIA_FMT for port 0x%x failed %d\n",
+			pr_err("%s: AVS_DECODER_PARAM_ID DEC_MEDIA_FMT for port 0x%x failed %d\n",
 				__func__, port_id, ret);
 			goto exit;
 		}

+ 16 - 0
include/dsp/apr_audio-v2.h

@@ -2480,6 +2480,7 @@ struct afe_port_data_cmd_rt_proxy_port_read_v2 {
 #define AFE_MODULE_AUDIO_DEV_INTERFACE    0x0001020C
 #define AFE_PORT_SAMPLE_RATE_8K           8000
 #define AFE_PORT_SAMPLE_RATE_16K          16000
+#define AFE_PORT_SAMPLE_RATE_44_1K        44100
 #define AFE_PORT_SAMPLE_RATE_48K          48000
 #define AFE_PORT_SAMPLE_RATE_96K          96000
 #define AFE_PORT_SAMPLE_RATE_176P4K       176400
@@ -3798,6 +3799,7 @@ struct afe_imc_dec_enc_info {
 
 struct afe_abr_dec_cfg_t {
 	struct afe_imc_dec_enc_info imc_info;
+	bool is_abr_enabled;
 } __packed;
 
 struct afe_abr_enc_cfg_t {
@@ -4440,6 +4442,19 @@ struct asm_aac_dec_cfg_v2_t {
 	 */
 } __packed;
 
+/*
+ * Payload of the APTX AD decoder configuration parameters in the
+ * #ASM_MEDIA_FMT_APTX_ADAPTIVE media format.
+ */
+struct asm_aptx_ad_dec_cfg_t {
+	uint32_t          sample_rate;
+	/*
+	 * Number of samples per second.
+	 *
+	 * @values 0x0(48000Hz), 0x1(44100Hz)
+	 */
+} __packed;
+
 union afe_enc_config_data {
 	struct asm_sbc_enc_cfg_t sbc_config;
 	struct asm_aac_enc_cfg_t aac_config;
@@ -4461,6 +4476,7 @@ union afe_dec_config_data {
 	struct asm_sbc_dec_cfg_t sbc_config;
 	struct asm_aac_dec_cfg_v2_t aac_config;
 	struct asm_mp3_dec_cfg_t mp3_config;
+	struct asm_aptx_ad_dec_cfg_t aptx_ad_config;
 };
 
 struct afe_dec_config {