Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42a69eda authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "asoc: qcs405: add A2DP sink support in machine driver"

parents 17c1ef34 cc99c351
Loading
Loading
Loading
Loading
+205 −41
Original line number Diff line number Diff line
@@ -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);
	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);
	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
Original line number Diff line number Diff line
@@ -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)
{
+87 −7
Original line number Diff line number Diff line
@@ -70,8 +70,9 @@
#define WSA8810_NAME_1 "wsa881x.20170211"
#define WSA8810_NAME_2 "wsa881x.20170212"
#define WCN_CDC_SLIM_RX_CH_MAX 2
#define WCN_CDC_SLIM_TX_CH_MAX 3
#define WCN_CDC_SLIM_TX_CH_MAX 4
#define TDM_CHANNEL_MAX 8
#define BT_SLIM_TX SLIM_TX_9

#define ADSP_STATE_READY_TIMEOUT_MS 3000
#define MSM_LL_QOS_VALUE 300 /* time in us to ensure LPM doesn't go in C3/C4 */
@@ -98,6 +99,7 @@ enum {
	SLIM_TX_6,
	SLIM_TX_7,
	SLIM_TX_8,
	SLIM_TX_9,
	SLIM_TX_MAX,
};

@@ -361,6 +363,7 @@ static struct dev_config slim_tx_cfg[] = {
	[SLIM_TX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
	[SLIM_TX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
	[SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
	[SLIM_TX_9] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
};

/* Default configuration of Codec DMA Interface Tx */
@@ -524,6 +527,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_sink, bt_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_chs, tdm_ch_text);
@@ -1149,6 +1153,68 @@ static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
	return 0;
}

static int msm_bt_sample_rate_sink_get(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	switch (slim_tx_cfg[BT_SLIM_TX].sample_rate) {
	case SAMPLING_RATE_96KHZ:
		ucontrol->value.integer.value[0] = 5;
		break;
	case SAMPLING_RATE_88P2KHZ:
		ucontrol->value.integer.value[0] = 4;
		break;
	case SAMPLING_RATE_48KHZ:
		ucontrol->value.integer.value[0] = 3;
		break;
	case SAMPLING_RATE_44P1KHZ:
		ucontrol->value.integer.value[0] = 2;
		break;
	case SAMPLING_RATE_16KHZ:
		ucontrol->value.integer.value[0] = 1;
		break;
	case SAMPLING_RATE_8KHZ:
	default:
		ucontrol->value.integer.value[0] = 0;
		break;
	}
	pr_debug("%s: sample rate = %d", __func__,
		 slim_tx_cfg[BT_SLIM_TX].sample_rate);

	return 0;
}

static int msm_bt_sample_rate_sink_put(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	switch (ucontrol->value.integer.value[0]) {
	case 1:
		slim_tx_cfg[BT_SLIM_TX].sample_rate = SAMPLING_RATE_16KHZ;
		break;
	case 2:
		slim_tx_cfg[BT_SLIM_TX].sample_rate = SAMPLING_RATE_44P1KHZ;
		break;
	case 3:
		slim_tx_cfg[BT_SLIM_TX].sample_rate = SAMPLING_RATE_48KHZ;
		break;
	case 4:
		slim_tx_cfg[BT_SLIM_TX].sample_rate = SAMPLING_RATE_88P2KHZ;
		break;
	case 5:
		slim_tx_cfg[BT_SLIM_TX].sample_rate = SAMPLING_RATE_96KHZ;
		break;
	case 0:
	default:
		slim_tx_cfg[BT_SLIM_TX].sample_rate = SAMPLING_RATE_8KHZ;
		break;
	}
	pr_debug("%s: sample rate = %d, value = %d\n",
		 __func__,
		 slim_tx_cfg[BT_SLIM_TX].sample_rate,
		 ucontrol->value.enumerated.item[0]);

	return 0;
}

static int cdc_dma_get_port_idx(struct snd_kcontrol *kcontrol)
{
	int idx = 0;
@@ -3427,19 +3493,25 @@ static const struct snd_kcontrol_new msm_snd_wsa_controls[] = {
};

static const struct snd_kcontrol_new msm_snd_controls[] = {
	SOC_ENUM_EXT("BT_TX SampleRate", bt_sample_rate_sink,
			msm_bt_sample_rate_sink_get,
			msm_bt_sample_rate_sink_put),
	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
			msm_bt_sample_rate_get,
			msm_bt_sample_rate_put),
	SOC_ENUM_EXT("BT_RX SampleRate", bt_sample_rate,
			msm_bt_sample_rate_get,
			msm_bt_sample_rate_put),
	SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
			proxy_rx_ch_get, proxy_rx_ch_put),
	SOC_ENUM_EXT("USB_AUDIO_RX Channels", usb_rx_chs,
			usb_audio_rx_ch_get, usb_audio_rx_ch_put),
	SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs,
			usb_audio_tx_ch_get, usb_audio_tx_ch_put),
	SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
			proxy_rx_ch_get, proxy_rx_ch_put),
	SOC_ENUM_EXT("USB_AUDIO_RX Format", usb_rx_format,
			usb_audio_rx_format_get, usb_audio_rx_format_put),
	SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format,
			usb_audio_tx_format_get, usb_audio_tx_format_put),
	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
			msm_bt_sample_rate_get,
			msm_bt_sample_rate_put),
	SOC_ENUM_EXT("USB_AUDIO_RX SampleRate", usb_rx_sample_rate,
			usb_audio_rx_sample_rate_get,
			usb_audio_rx_sample_rate_put),
@@ -4108,6 +4180,14 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
			slim_tx_cfg[SLIM_TX_8].channels;
		break;

	case MSM_BACKEND_DAI_SLIMBUS_9_TX:
		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
				slim_tx_cfg[SLIM_TX_9].bit_format);
		rate->min = rate->max = slim_tx_cfg[SLIM_TX_9].sample_rate;
		channels->min = channels->max =
			slim_tx_cfg[SLIM_TX_9].channels;
		break;

	case MSM_BACKEND_DAI_USB_RX:
		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
				usb_rx_cfg.bit_format);
@@ -4853,7 +4933,7 @@ static int msm_wsa_cdc_dma_init(struct snd_soc_pcm_runtime *rtd)
static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
{
	unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
	unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX]  = {159, 160, 161};
	unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX]  = {159, 160, 161, 162};
	struct snd_soc_dai *codec_dai = rtd->codec_dai;

	return snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),