Merge "asoc: msm: routing: remove WARN() log messages"
diff --git a/asoc/codecs/wcd934x/wcd934x.c b/asoc/codecs/wcd934x/wcd934x.c
index e268a73..44f741e 100644
--- a/asoc/codecs/wcd934x/wcd934x.c
+++ b/asoc/codecs/wcd934x/wcd934x.c
@@ -3174,8 +3174,6 @@
 		/* Undo reset for MAD */
 		snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
 				    0x02, 0x00);
-		snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
-					0x04, 0x04);
 	} else {
 		snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
 				    0x03, 0x00);
@@ -3185,8 +3183,6 @@
 		/* Turn off MAD clk */
 		snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
 				    0x01, 0x00);
-		snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
-					0x04, 0x00);
 	}
 done:
 	return rc;
@@ -9416,6 +9412,7 @@
 	{WCD934X_HPH_R_TEST, 0x01, 0x01},
 	{WCD934X_CPE_FLL_CONFIG_CTL_2, 0xFF, 0x20},
 	{WCD934X_MBHC_NEW_CTL_2, 0x0C, 0x00},
+	{WCD934X_CODEC_RPM_CLK_MCLK_CFG, 0x04, 0x04},
 };
 
 static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = {
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index e429a54..d35ed89 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -41,6 +41,7 @@
 #include <dsp/msm_audio_ion.h>
 #include <dsp/apr_audio-v2.h>
 #include <dsp/q6asm-v2.h>
+#include <dsp/q6core.h>
 #include <dsp/msm-audio-effects-q6-v2.h>
 #include "msm-pcm-routing-v2.h"
 #include "msm-qti-pp-config.h"
@@ -204,7 +205,7 @@
 
 struct msm_compr_ch_map {
 	bool set_ch_map;
-	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL];
+	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
 };
 
 static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
@@ -1012,16 +1013,32 @@
 			sample_word_size = 16;
 			break;
 		}
-		ret = q6asm_media_format_block_pcm_format_support_v4(
-							prtd->audio_client,
-							prtd->sample_rate,
-							prtd->num_channels,
-							bit_width, stream_id,
-							use_default_chmap,
-							chmap,
-							sample_word_size,
-							ASM_LITTLE_ENDIAN,
-							DEFAULT_QF);
+
+		if (q6core_get_avcs_api_version_per_service(
+					APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
+					ADSP_ASM_API_VERSION_V2) {
+			ret = q6asm_media_format_block_pcm_format_support_v5(
+					prtd->audio_client,
+					prtd->sample_rate,
+					prtd->num_channels,
+					bit_width, stream_id,
+					use_default_chmap,
+					chmap,
+					sample_word_size,
+					ASM_LITTLE_ENDIAN,
+					DEFAULT_QF);
+		} else {
+			ret = q6asm_media_format_block_pcm_format_support_v4(
+					prtd->audio_client,
+					prtd->sample_rate,
+					prtd->num_channels,
+					bit_width, stream_id,
+					use_default_chmap,
+					chmap,
+					sample_word_size,
+					ASM_LITTLE_ENDIAN,
+					DEFAULT_QF);
+		}
 		if (ret < 0)
 			pr_err("%s: CMD Format block failed\n", __func__);
 
@@ -1336,7 +1353,16 @@
 	} else {
 		pr_debug("%s: stream_id %d bits_per_sample %d\n",
 				__func__, ac->stream_id, bits_per_sample);
-		ret = q6asm_stream_open_write_v4(ac,
+
+		if (q6core_get_avcs_api_version_per_service(
+					APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
+					ADSP_ASM_API_VERSION_V2)
+			ret = q6asm_stream_open_write_v5(ac,
+				prtd->codec, bits_per_sample,
+				ac->stream_id,
+				prtd->gapless_state.use_dsp_gapless_mode);
+		else
+			ret = q6asm_stream_open_write_v4(ac,
 				prtd->codec, bits_per_sample,
 				ac->stream_id,
 				prtd->gapless_state.use_dsp_gapless_mode);
@@ -3640,7 +3666,7 @@
 
 	if (pdata->ch_map[fe_id]) {
 		pdata->ch_map[fe_id]->set_ch_map = true;
-		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
 			pdata->ch_map[fe_id]->channel_map[i] =
 				(char)(ucontrol->value.integer.value[i]);
 	} else {
@@ -3669,7 +3695,7 @@
 		goto end;
 	}
 	if (pdata->ch_map[fe_id]) {
-		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
 			ucontrol->value.integer.value[i] =
 				pdata->ch_map[fe_id]->channel_map[i];
 	}
@@ -3983,9 +4009,10 @@
 				      struct snd_ctl_elem_info *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 8;
+	uinfo->count = PCM_FORMAT_MAX_NUM_CHANNEL_V8;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 0xFFFFFFFF;
+	/* See PCM_CHANNEL_RSD=34 in apr_audio-v2.h */
+	uinfo->value.integer.max = 34;
 	return 0;
 }
 
diff --git a/asoc/msm-dai-fe.c b/asoc/msm-dai-fe.c
index 3dc4509..7654e56 100644
--- a/asoc/msm-dai-fe.c
+++ b/asoc/msm-dai-fe.c
@@ -99,7 +99,7 @@
 						SNDRV_PCM_FMTBIT_S24_3LE |
 						SNDRV_PCM_FMTBIT_S32_LE),
 			.channels_min = 1,
-			.channels_max = 8,
+			.channels_max = 16,
 			.rate_min =     8000,
 			.rate_max =	384000,
 		},
@@ -113,7 +113,7 @@
 				    SNDRV_PCM_FMTBIT_S24_3LE |
 				    SNDRV_PCM_FMTBIT_S32_LE),
 			.channels_min = 1,
-			.channels_max = 8,
+			.channels_max = 16,
 			.rate_min =     8000,
 			.rate_max =	48000,
 		},
@@ -311,7 +311,7 @@
 						SNDRV_PCM_FMTBIT_S24_3LE |
 						SNDRV_PCM_FMTBIT_S32_LE),
 			.channels_min = 1,
-			.channels_max = 8,
+			.channels_max = 16,
 			.rate_min =	8000,
 			.rate_max = 384000,
 		},
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 8b1dbd6..fccac28 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -40,6 +40,7 @@
 #define CHANNEL_STATUS_MASK_INIT 0x0
 #define CHANNEL_STATUS_MASK 0x4
 #define AFE_API_VERSION_CLOCK_SET 1
+#define MSM_DAI_SYSFS_ENTRY_MAX_LEN 64
 
 #define DAI_FORMATS_S16_S24_S32_LE (SNDRV_PCM_FMTBIT_S16_LE | \
 				    SNDRV_PCM_FMTBIT_S24_LE | \
@@ -218,6 +219,7 @@
 	u16 port_id;
 	struct afe_spdif_port_config spdif_port;
 	struct afe_event_fmt_update fmt_event;
+	struct kobject *kobj;
 };
 
 struct msm_dai_q6_spdif_event_msg {
@@ -1459,39 +1461,6 @@
 	return 0;
 }
 
-static int msm_dai_q6_spdif_ext_state_get(struct snd_kcontrol *kcontrol,
-		struct snd_ctl_elem_value *ucontrol)
-{
-
-	struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
-
-	ucontrol->value.integer.value[0] =
-		dai_data->fmt_event.status & 0x3;
-	return 0;
-}
-
-static int msm_dai_q6_spdif_ext_format_get(struct snd_kcontrol *kcontrol,
-		struct snd_ctl_elem_value *ucontrol)
-{
-
-	struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
-
-	ucontrol->value.integer.value[0] =
-		dai_data->fmt_event.data_format & 0x1;
-	return 0;
-}
-
-static int msm_dai_q6_spdif_ext_rate_get(struct snd_kcontrol *kcontrol,
-		struct snd_ctl_elem_value *ucontrol)
-{
-
-	struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
-
-	ucontrol->value.integer.value[0] =
-		dai_data->fmt_event.sample_rate;
-	return 0;
-}
-
 static const char * const spdif_format[] = {
 	"LPCM",
 	"Compr"
@@ -1501,10 +1470,6 @@
 	"Optical", "EXT-ARC", "Coaxial", "VT-ARC"
 };
 
-static const char * const spdif_state[] = {
-	"Inactive", "Active", "EOS"
-};
-
 static const struct soc_enum spdif_rx_config_enum[] = {
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_format), spdif_format),
 };
@@ -1514,11 +1479,6 @@
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_format), spdif_format),
 };
 
-static const struct soc_enum spdif_tx_status_enum[] = {
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_state), spdif_state),
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_format), spdif_format),
- };
-
 static int msm_dai_q6_spdif_chstatus_put(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
@@ -1609,21 +1569,6 @@
 			msm_dai_q6_spdif_format_put)
 };
 
-static const struct snd_kcontrol_new spdif_tx_status_controls[] = {
-	SOC_ENUM_EXT("PRI SPDIF TX EXT State", spdif_tx_status_enum[0],
-			msm_dai_q6_spdif_ext_state_get, NULL),
-	SOC_ENUM_EXT("PRI SPDIF TX EXT Format", spdif_tx_status_enum[1],
-			msm_dai_q6_spdif_ext_format_get, NULL),
-	SOC_SINGLE_EXT("PRI SPDIF TX EXT Rate", 0, 0, 192000, 0,
-			msm_dai_q6_spdif_ext_rate_get, NULL),
-	SOC_ENUM_EXT("SEC SPDIF TX EXT State", spdif_tx_status_enum[0],
-			msm_dai_q6_spdif_ext_state_get, NULL),
-	SOC_ENUM_EXT("SEC SPDIF TX EXT Format", spdif_tx_status_enum[1],
-			msm_dai_q6_spdif_ext_format_get, NULL),
-	SOC_SINGLE_EXT("SEC SPDIF TX EXT Rate", 0, 0, 192000, 0,
-			msm_dai_q6_spdif_ext_rate_get, NULL)
-};
-
 static void msm_dai_q6_spdif_process_event(uint32_t opcode, uint32_t token,
 		uint32_t *payload, void *private_data)
 {
@@ -1734,6 +1679,102 @@
 	return rc;
 }
 
+static ssize_t msm_dai_q6_spdif_sysfs_rda_audio_state(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dev);
+
+	if (!dai_data) {
+		pr_err("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, MSM_DAI_SYSFS_ENTRY_MAX_LEN, "%d\n",
+		dai_data->fmt_event.status);
+	pr_debug("%s: '%d'\n", __func__, dai_data->fmt_event.status);
+
+	return ret;
+}
+
+static ssize_t msm_dai_q6_spdif_sysfs_rda_audio_format(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dev);
+
+	if (!dai_data) {
+		pr_err("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, MSM_DAI_SYSFS_ENTRY_MAX_LEN, "%d\n",
+		dai_data->fmt_event.data_format);
+	pr_debug("%s: '%d'\n", __func__, dai_data->fmt_event.data_format);
+
+	return ret;
+}
+
+static ssize_t msm_dai_q6_spdif_sysfs_rda_audio_rate(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dev);
+
+	if (!dai_data) {
+		pr_err("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, MSM_DAI_SYSFS_ENTRY_MAX_LEN, "%d\n",
+		dai_data->fmt_event.sample_rate);
+	pr_debug("%s: '%d'\n", __func__, dai_data->fmt_event.sample_rate);
+
+	return ret;
+}
+
+static DEVICE_ATTR(audio_state, 0444, msm_dai_q6_spdif_sysfs_rda_audio_state,
+	NULL);
+static DEVICE_ATTR(audio_format, 0444, msm_dai_q6_spdif_sysfs_rda_audio_format,
+	NULL);
+static DEVICE_ATTR(audio_rate, 0444, msm_dai_q6_spdif_sysfs_rda_audio_rate,
+	NULL);
+
+static struct attribute *msm_dai_q6_spdif_fs_attrs[] = {
+	&dev_attr_audio_state.attr,
+	&dev_attr_audio_format.attr,
+	&dev_attr_audio_rate.attr,
+	NULL,
+};
+static struct attribute_group msm_dai_q6_spdif_fs_attrs_group = {
+	.attrs = msm_dai_q6_spdif_fs_attrs,
+};
+
+static int msm_dai_q6_spdif_sysfs_create(struct snd_soc_dai *dai,
+	struct msm_dai_q6_spdif_dai_data *dai_data)
+{
+	int rc;
+
+	rc = sysfs_create_group(&dai->dev->kobj,
+		&msm_dai_q6_spdif_fs_attrs_group);
+	if (rc) {
+		pr_err("%s: failed, rc=%d\n", __func__, rc);
+		return rc;
+	}
+	dai_data->kobj = &dai->dev->kobj;
+
+	return 0;
+}
+
+static void msm_dai_q6_spdif_sysfs_remove(struct snd_soc_dai *dai,
+	struct msm_dai_q6_spdif_dai_data *dai_data)
+{
+	if (dai_data->kobj)
+		sysfs_remove_group(dai_data->kobj,
+			&msm_dai_q6_spdif_fs_attrs_group);
+	dai_data->kobj = NULL;
+}
+
 static int msm_dai_q6_spdif_dai_probe(struct snd_soc_dai *dai)
 {
 	struct msm_dai_q6_spdif_dai_data *dai_data;
@@ -1773,40 +1814,24 @@
 				 dai_data));
 		break;
 	case AFE_PORT_ID_PRIMARY_SPDIF_TX:
+		rc = msm_dai_q6_spdif_sysfs_create(dai, dai_data);
+
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				snd_ctl_new1(&spdif_tx_config_controls[0],
 				dai_data));
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				snd_ctl_new1(&spdif_tx_config_controls[1],
 				dai_data));
-
-		rc = snd_ctl_add(dai->component->card->snd_card,
-				snd_ctl_new1(&spdif_tx_status_controls[0],
-				dai_data));
-		rc = snd_ctl_add(dai->component->card->snd_card,
-				snd_ctl_new1(&spdif_tx_status_controls[1],
-				dai_data));
-		rc = snd_ctl_add(dai->component->card->snd_card,
-				snd_ctl_new1(&spdif_tx_status_controls[2],
-				dai_data));
 		break;
 	case AFE_PORT_ID_SECONDARY_SPDIF_TX:
+		rc = msm_dai_q6_spdif_sysfs_create(dai, dai_data);
+
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				snd_ctl_new1(&spdif_tx_config_controls[2],
 				dai_data));
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				snd_ctl_new1(&spdif_tx_config_controls[3],
 				dai_data));
-
-		rc = snd_ctl_add(dai->component->card->snd_card,
-				snd_ctl_new1(&spdif_tx_status_controls[3],
-				dai_data));
-		rc = snd_ctl_add(dai->component->card->snd_card,
-				snd_ctl_new1(&spdif_tx_status_controls[4],
-				dai_data));
-		rc = snd_ctl_add(dai->component->card->snd_card,
-				snd_ctl_new1(&spdif_tx_status_controls[5],
-				dai_data));
 		break;
 	}
 	if (rc < 0)
@@ -1866,6 +1891,9 @@
 
 		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
 	}
+
+	msm_dai_q6_spdif_sysfs_remove(dai, dai_data);
+
 	kfree(dai_data);
 
 	return 0;
@@ -2095,7 +2123,7 @@
 	return 0;
 }
 
-static u8 num_of_bits_set(u8 sd_line_mask)
+static u16 num_of_bits_set(u16 sd_line_mask)
 {
 	u8 num_bits_set = 0;
 
@@ -4644,11 +4672,68 @@
 
 	dai_data->channels = params_channels(params);
 	switch (dai_data->channels) {
+	case 15:
+	case 16:
+		switch (mi2s_dai_config->pdata_mi2s_lines) {
+		case AFE_PORT_I2S_16CHS:
+			dai_data->port_config.i2s.channel_mode
+				= AFE_PORT_I2S_16CHS;
+			break;
+		default:
+			goto error_invalid_data;
+		};
+		break;
+	case 13:
+	case 14:
+		switch (mi2s_dai_config->pdata_mi2s_lines) {
+		case AFE_PORT_I2S_14CHS:
+		case AFE_PORT_I2S_16CHS:
+			dai_data->port_config.i2s.channel_mode
+				= AFE_PORT_I2S_14CHS;
+			break;
+		default:
+			goto error_invalid_data;
+		};
+		break;
+	case 11:
+	case 12:
+		switch (mi2s_dai_config->pdata_mi2s_lines) {
+		case AFE_PORT_I2S_12CHS:
+		case AFE_PORT_I2S_14CHS:
+		case AFE_PORT_I2S_16CHS:
+			dai_data->port_config.i2s.channel_mode
+				= AFE_PORT_I2S_12CHS;
+			break;
+		default:
+			goto error_invalid_data;
+		};
+		break;
+	case 9:
+	case 10:
+		switch (mi2s_dai_config->pdata_mi2s_lines) {
+		case AFE_PORT_I2S_10CHS:
+		case AFE_PORT_I2S_12CHS:
+		case AFE_PORT_I2S_14CHS:
+		case AFE_PORT_I2S_16CHS:
+			dai_data->port_config.i2s.channel_mode
+				= AFE_PORT_I2S_10CHS;
+			break;
+		default:
+			goto error_invalid_data;
+		};
+		break;
 	case 8:
 	case 7:
 		if (mi2s_dai_config->pdata_mi2s_lines < AFE_PORT_I2S_8CHS)
 			goto error_invalid_data;
-		dai_data->port_config.i2s.channel_mode = AFE_PORT_I2S_8CHS;
+		else
+			if (mi2s_dai_config->pdata_mi2s_lines
+					== AFE_PORT_I2S_8CHS_2)
+				dai_data->port_config.i2s.channel_mode =
+						AFE_PORT_I2S_8CHS_2;
+			else
+				dai_data->port_config.i2s.channel_mode =
+						AFE_PORT_I2S_8CHS;
 		break;
 	case 6:
 	case 5:
@@ -4658,14 +4743,33 @@
 		break;
 	case 4:
 	case 3:
-		if (mi2s_dai_config->pdata_mi2s_lines < AFE_PORT_I2S_QUAD01)
+		switch (mi2s_dai_config->pdata_mi2s_lines) {
+		case AFE_PORT_I2S_SD0:
+		case AFE_PORT_I2S_SD1:
+		case AFE_PORT_I2S_SD2:
+		case AFE_PORT_I2S_SD3:
+		case AFE_PORT_I2S_SD4:
+		case AFE_PORT_I2S_SD5:
+		case AFE_PORT_I2S_SD6:
+		case AFE_PORT_I2S_SD7:
 			goto error_invalid_data;
-		if (mi2s_dai_config->pdata_mi2s_lines == AFE_PORT_I2S_QUAD23)
+			break;
+		case AFE_PORT_I2S_QUAD01:
+		case AFE_PORT_I2S_QUAD23:
+		case AFE_PORT_I2S_QUAD45:
+		case AFE_PORT_I2S_QUAD67:
 			dai_data->port_config.i2s.channel_mode =
 				mi2s_dai_config->pdata_mi2s_lines;
-		else
+			break;
+		case AFE_PORT_I2S_8CHS_2:
+			dai_data->port_config.i2s.channel_mode =
+					AFE_PORT_I2S_QUAD45;
+			break;
+		default:
 			dai_data->port_config.i2s.channel_mode =
 					AFE_PORT_I2S_QUAD01;
+			break;
+		};
 		break;
 	case 2:
 	case 1:
@@ -4676,12 +4780,20 @@
 		case AFE_PORT_I2S_SD1:
 		case AFE_PORT_I2S_SD2:
 		case AFE_PORT_I2S_SD3:
+		case AFE_PORT_I2S_SD4:
+		case AFE_PORT_I2S_SD5:
+		case AFE_PORT_I2S_SD6:
+		case AFE_PORT_I2S_SD7:
 			dai_data->port_config.i2s.channel_mode =
 				mi2s_dai_config->pdata_mi2s_lines;
 			break;
 		case AFE_PORT_I2S_QUAD01:
 		case AFE_PORT_I2S_6CHS:
 		case AFE_PORT_I2S_8CHS:
+		case AFE_PORT_I2S_10CHS:
+		case AFE_PORT_I2S_12CHS:
+		case AFE_PORT_I2S_14CHS:
+		case AFE_PORT_I2S_16CHS:
 			if (dai_data->vi_feed_mono == SPKR_1)
 				dai_data->port_config.i2s.channel_mode =
 							AFE_PORT_I2S_SD0;
@@ -4693,6 +4805,14 @@
 			dai_data->port_config.i2s.channel_mode =
 						AFE_PORT_I2S_SD2;
 			break;
+		case AFE_PORT_I2S_QUAD45:
+			dai_data->port_config.i2s.channel_mode =
+						AFE_PORT_I2S_SD4;
+			break;
+		case AFE_PORT_I2S_QUAD67:
+			dai_data->port_config.i2s.channel_mode =
+						AFE_PORT_I2S_SD6;
+			break;
 		}
 		if (dai_data->channels == 2)
 			dai_data->port_config.i2s.mono_stereo =
@@ -4864,15 +4984,17 @@
 			.stream_name = "Primary MI2S Playback",
 			.aif_name = "PRI_MI2S_RX",
 			.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
-				 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
-				 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
-				 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
-				 SNDRV_PCM_RATE_192000,
+				SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
+				SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+				SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+				SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+				SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_352800 |
+				SNDRV_PCM_RATE_384000,
 			.formats = SNDRV_PCM_FMTBIT_S16_LE |
 				SNDRV_PCM_FMTBIT_S24_LE |
 				SNDRV_PCM_FMTBIT_S24_3LE,
 			.rate_min =     8000,
-			.rate_max =     192000,
+			.rate_max =     384000,
 		},
 		.capture = {
 			.stream_name = "Primary MI2S Capture",
@@ -5257,6 +5379,18 @@
 		case MSM_MI2S_SD3:
 			*config_ptr = AFE_PORT_I2S_SD3;
 			break;
+		case MSM_MI2S_SD4:
+			*config_ptr = AFE_PORT_I2S_SD4;
+			break;
+		case MSM_MI2S_SD5:
+			*config_ptr = AFE_PORT_I2S_SD5;
+			break;
+		case MSM_MI2S_SD6:
+			*config_ptr = AFE_PORT_I2S_SD6;
+			break;
+		case MSM_MI2S_SD7:
+			*config_ptr = AFE_PORT_I2S_SD7;
+			break;
 		default:
 			pr_err("%s: invalid SD lines %d\n",
 				   __func__, sd_lines);
@@ -5271,6 +5405,12 @@
 		case MSM_MI2S_SD2 | MSM_MI2S_SD3:
 			*config_ptr = AFE_PORT_I2S_QUAD23;
 			break;
+		case MSM_MI2S_SD4 | MSM_MI2S_SD5:
+			*config_ptr = AFE_PORT_I2S_QUAD45;
+			break;
+		case MSM_MI2S_SD6 | MSM_MI2S_SD7:
+			*config_ptr = AFE_PORT_I2S_QUAD67;
+			break;
 		default:
 			pr_err("%s: invalid SD lines %d\n",
 				   __func__, sd_lines);
@@ -5293,6 +5433,57 @@
 		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3:
 			*config_ptr = AFE_PORT_I2S_8CHS;
 			break;
+		case MSM_MI2S_SD4 | MSM_MI2S_SD5 | MSM_MI2S_SD6 | MSM_MI2S_SD7:
+			*config_ptr = AFE_PORT_I2S_8CHS_2;
+			break;
+		default:
+			pr_err("%s: invalid SD lines %d\n",
+				   __func__, sd_lines);
+			goto error_invalid_data;
+		}
+		break;
+	case 5:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2
+		   | MSM_MI2S_SD3 | MSM_MI2S_SD4:
+			*config_ptr = AFE_PORT_I2S_10CHS;
+			break;
+		default:
+			pr_err("%s: invalid SD lines %d\n",
+				   __func__, sd_lines);
+			goto error_invalid_data;
+		}
+		break;
+	case 6:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2
+		   | MSM_MI2S_SD3 | MSM_MI2S_SD4 | MSM_MI2S_SD5:
+			*config_ptr = AFE_PORT_I2S_12CHS;
+			break;
+		default:
+			pr_err("%s: invalid SD lines %d\n",
+				   __func__, sd_lines);
+			goto error_invalid_data;
+		}
+		break;
+	case 7:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3
+		   | MSM_MI2S_SD4 | MSM_MI2S_SD5 | MSM_MI2S_SD6:
+			*config_ptr = AFE_PORT_I2S_14CHS;
+			break;
+		default:
+			pr_err("%s: invalid SD lines %d\n",
+				   __func__, sd_lines);
+			goto error_invalid_data;
+		}
+		break;
+	case 8:
+		switch (sd_lines) {
+		case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3
+		   | MSM_MI2S_SD4 | MSM_MI2S_SD5 | MSM_MI2S_SD6 | MSM_MI2S_SD7:
+			*config_ptr = AFE_PORT_I2S_16CHS;
+			break;
 		default:
 			pr_err("%s: invalid SD lines %d\n",
 				   __func__, sd_lines);
diff --git a/asoc/msm-dai-q6-v2.h b/asoc/msm-dai-q6-v2.h
index b3f457e..2327cfd 100644
--- a/asoc/msm-dai-q6-v2.h
+++ b/asoc/msm-dai-q6-v2.h
@@ -18,6 +18,11 @@
 #define MSM_MI2S_SD1 (1 << 1)
 #define MSM_MI2S_SD2 (1 << 2)
 #define MSM_MI2S_SD3 (1 << 3)
+#define MSM_MI2S_SD4 (1 << 4)
+#define MSM_MI2S_SD5 (1 << 5)
+#define MSM_MI2S_SD6 (1 << 6)
+#define MSM_MI2S_SD7 (1 << 7)
+
 #define MSM_MI2S_CAP_RX 0
 #define MSM_MI2S_CAP_TX 1
 
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index 0b312fe..1dccecd 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -35,6 +35,8 @@
 #include <sound/pcm_params.h>
 #include <dsp/msm_audio_ion.h>
 #include <dsp/q6audio-v2.h>
+#include <dsp/q6core.h>
+#include <dsp/q6asm-v2.h>
 
 #include "msm-pcm-q6-v2.h"
 #include "msm-pcm-routing-v2.h"
@@ -384,11 +386,18 @@
 			return -ENOMEM;
 		}
 	} else {
-		ret = q6asm_open_write_v4(prtd->audio_client,
-			fmt_type, bits_per_sample);
+		if ((q6core_get_avcs_api_version_per_service(
+				APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
+				ADSP_ASM_API_VERSION_V2) &&
+					q6core_use_Q6_32ch_support())
+			ret = q6asm_open_write_v5(prtd->audio_client,
+				fmt_type, bits_per_sample);
+		else
+			ret = q6asm_open_write_v4(prtd->audio_client,
+				fmt_type, bits_per_sample);
 
 		if (ret < 0) {
-			pr_err("%s: q6asm_open_write_v4 failed (%d)\n",
+			pr_err("%s: q6asm_open_write failed (%d)\n",
 			__func__, ret);
 			q6asm_audio_client_free(prtd->audio_client);
 			prtd->audio_client = NULL;
@@ -425,12 +434,26 @@
 			runtime->channels, !prtd->set_channel_map,
 			prtd->channel_map, bits_per_sample);
 	} else {
-		ret = q6asm_media_format_block_multi_ch_pcm_v4(
+
+		if ((q6core_get_avcs_api_version_per_service(
+				APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
+				ADSP_ASM_API_VERSION_V2) &&
+					q6core_use_Q6_32ch_support()) {
+
+			ret = q6asm_media_format_block_multi_ch_pcm_v5(
 				prtd->audio_client, runtime->rate,
 				runtime->channels, !prtd->set_channel_map,
 				prtd->channel_map, bits_per_sample,
 				sample_word_size, ASM_LITTLE_ENDIAN,
 				DEFAULT_QF);
+		} else {
+			ret = q6asm_media_format_block_multi_ch_pcm_v4(
+				prtd->audio_client, runtime->rate,
+				runtime->channels, !prtd->set_channel_map,
+				prtd->channel_map, bits_per_sample,
+				sample_word_size, ASM_LITTLE_ENDIAN,
+				DEFAULT_QF);
+		}
 	}
 	if (ret < 0)
 		pr_info("%s: CMD Format block failed\n", __func__);
@@ -489,7 +512,16 @@
 				__func__, params_channels(params),
 				prtd->audio_client->perf_mode);
 
-		ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
+		if ((q6core_get_avcs_api_version_per_service(
+				APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
+				ADSP_ASM_API_VERSION_V2) &&
+					q6core_use_Q6_32ch_support())
+			ret = q6asm_open_read_v5(prtd->audio_client,
+				FORMAT_LINEAR_PCM,
+				bits_per_sample, false, ENC_CFG_ID_NONE);
+		else
+			ret = q6asm_open_read_v4(prtd->audio_client,
+				FORMAT_LINEAR_PCM,
 				bits_per_sample, false, ENC_CFG_ID_NONE);
 		if (ret < 0) {
 			pr_err("%s: q6asm_open_read failed\n", __func__);
@@ -557,13 +589,29 @@
 	pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n",
 			__func__, prtd->samp_rate, prtd->channel_mode,
 			bits_per_sample, sample_word_size);
-	ret = q6asm_enc_cfg_blk_pcm_format_support_v4(prtd->audio_client,
-						      prtd->samp_rate,
-						      prtd->channel_mode,
-						      bits_per_sample,
-						      sample_word_size,
-						      ASM_LITTLE_ENDIAN,
-						      DEFAULT_QF);
+
+	if ((q6core_get_avcs_api_version_per_service(
+			APRV2_IDS_SERVICE_ID_ADSP_ASM_V) >=
+			ADSP_ASM_API_VERSION_V2) &&
+			q6core_use_Q6_32ch_support())
+		ret = q6asm_enc_cfg_blk_pcm_format_support_v5(
+						prtd->audio_client,
+						prtd->samp_rate,
+						prtd->channel_mode,
+						bits_per_sample,
+						sample_word_size,
+						ASM_LITTLE_ENDIAN,
+						DEFAULT_QF);
+	else
+		ret = q6asm_enc_cfg_blk_pcm_format_support_v4(
+						prtd->audio_client,
+						prtd->samp_rate,
+						prtd->channel_mode,
+						bits_per_sample,
+						sample_word_size,
+						ASM_LITTLE_ENDIAN,
+						DEFAULT_QF);
+
 	if (ret < 0)
 		pr_debug("%s: cmd cfg pcm was block failed", __func__);
 
@@ -1508,7 +1556,7 @@
 	prtd = substream->runtime->private_data;
 	if (prtd) {
 		prtd->set_channel_map = true;
-			for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+			for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
 				prtd->channel_map[i] =
 				(char)(ucontrol->value.integer.value[i]);
 	}
@@ -1536,11 +1584,11 @@
 	prtd = substream->runtime->private_data;
 
 	if (prtd && prtd->set_channel_map == true) {
-		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
 			ucontrol->value.integer.value[i] =
 					(int)prtd->channel_map[i];
 	} else {
-		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
 			ucontrol->value.integer.value[i] = 0;
 	}
 
@@ -1558,7 +1606,7 @@
 	pr_debug("%s, Channel map cntrl add\n", __func__);
 	ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				     snd_pcm_std_chmaps,
-				     PCM_FORMAT_MAX_NUM_CHANNEL, 0,
+				     PCM_FORMAT_MAX_NUM_CHANNEL_V8, 0,
 				     &chmap_info);
 	if (ret < 0) {
 		pr_err("%s, channel map cntrl add failed\n", __func__);
diff --git a/asoc/msm-pcm-q6-v2.h b/asoc/msm-pcm-q6-v2.h
index 21d09cd..201c7e5 100644
--- a/asoc/msm-pcm-q6-v2.h
+++ b/asoc/msm-pcm-q6-v2.h
@@ -105,7 +105,7 @@
 	int mmap_flag;
 	atomic_t pending_buffer;
 	bool set_channel_map;
-	char channel_map[8];
+	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
 	int cmd_interrupt;
 	bool meta_data_mode;
 	uint32_t volume;
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 6776f56..83bba1c 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -591,6 +591,12 @@
 	  LPASS_BE_INT6_MI2S_RX},
 	{ AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT6_MI2S_TX},
+	{ AFE_PORT_ID_SENARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0,
+	  LPASS_BE_SEN_AUXPCM_RX},
+	{ AFE_PORT_ID_SENARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0,
+	  LPASS_BE_SEN_AUXPCM_TX},
+	{ AFE_PORT_ID_SENARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
+	  LPASS_BE_SENARY_MI2S_RX},
 	{ AFE_PORT_ID_WSA_CODEC_DMA_RX_0, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_WSA_CDC_DMA_RX_0},
 	{ AFE_PORT_ID_WSA_CODEC_DMA_TX_0, 0, {0}, {0}, 0, 0, 0, 0,
@@ -14989,6 +14995,14 @@
 		msm_routing_put_port_mixer),
 };
 
+static const struct snd_kcontrol_new sec_tdm_rx_7_port_mixer_controls[] = {
+	SOC_DOUBLE_EXT("TERT_TDM_TX_7", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_SEC_TDM_RX_7,
+		MSM_BACKEND_DAI_TERT_TDM_TX_7, 1, 0,
+		msm_routing_get_port_mixer,
+		msm_routing_put_port_mixer),
+};
+
 static const struct snd_kcontrol_new tert_tdm_rx_0_port_mixer_controls[] = {
 	SOC_DOUBLE_EXT("PRI_MI2S_TX", SND_SOC_NOPM,
 		MSM_BACKEND_DAI_TERT_TDM_RX_0,
@@ -19308,6 +19322,9 @@
 	SND_SOC_DAPM_MIXER("SEC_TDM_RX_3 Port Mixer", SND_SOC_NOPM, 0, 0,
 	sec_tdm_rx_3_port_mixer_controls,
 	ARRAY_SIZE(sec_tdm_rx_3_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_TDM_RX_7 Port Mixer", SND_SOC_NOPM, 0, 0,
+	sec_tdm_rx_7_port_mixer_controls,
+	ARRAY_SIZE(sec_tdm_rx_7_port_mixer_controls)),
 	SND_SOC_DAPM_MIXER("TERT_TDM_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0,
 	tert_tdm_rx_0_port_mixer_controls,
 	ARRAY_SIZE(tert_tdm_rx_0_port_mixer_controls)),
@@ -21922,10 +21939,12 @@
 	{"SEC_TDM_RX_1", NULL, "SEC_TDM_RX_1_DL_HL"},
 	{"SEC_TDM_RX_2", NULL, "SEC_TDM_RX_2_DL_HL"},
 	{"SEC_TDM_RX_3", NULL, "SEC_TDM_RX_3_DL_HL"},
+	{"SEC_TDM_RX_7", NULL, "SEC_TDM_RX_7_DL_HL"},
 	{"TERT_TDM_TX_0_UL_HL", NULL, "TERT_TDM_TX_0"},
 	{"TERT_TDM_TX_1_UL_HL", NULL, "TERT_TDM_TX_1"},
 	{"TERT_TDM_TX_2_UL_HL", NULL, "TERT_TDM_TX_2"},
 	{"TERT_TDM_TX_3_UL_HL", NULL, "TERT_TDM_TX_3"},
+	{"TERT_TDM_TX_7_UL_HL", NULL, "TERT_TDM_TX_7"},
 	{"TERT_TDM_RX_0", NULL, "TERT_TDM_RX_0_DL_HL"},
 	{"TERT_TDM_RX_1", NULL, "TERT_TDM_RX_1_DL_HL"},
 	{"TERT_TDM_RX_2", NULL, "TERT_TDM_RX_2_DL_HL"},
@@ -22123,6 +22142,9 @@
 	{"SEC_TDM_RX_3 Port Mixer", "QUIN_TDM_TX_3", "QUIN_TDM_TX_3"},
 	{"SEC_TDM_RX_3", NULL, "SEC_TDM_RX_3 Port Mixer"},
 
+	{"SEC_TDM_RX_7 Port Mixer", "TERT_TDM_TX_7", "TERT_TDM_TX_7"},
+	{"SEC_TDM_RX_7", NULL, "SEC_TDM_RX_7 Port Mixer"},
+
 	{"TERT_TDM_RX_0 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"TERT_TDM_RX_0 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
 	{"TERT_TDM_RX_0 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
@@ -22704,6 +22726,7 @@
 	{"BE_OUT", NULL, "SEC_TDM_RX_1"},
 	{"BE_OUT", NULL, "SEC_TDM_RX_2"},
 	{"BE_OUT", NULL, "SEC_TDM_RX_3"},
+	{"BE_OUT", NULL, "SEC_TDM_RX_7"},
 	{"BE_OUT", NULL, "TERT_TDM_RX_0"},
 	{"BE_OUT", NULL, "TERT_TDM_RX_1"},
 	{"BE_OUT", NULL, "TERT_TDM_RX_2"},
@@ -22792,6 +22815,7 @@
 	{"TERT_TDM_TX_1", NULL, "BE_IN"},
 	{"TERT_TDM_TX_2", NULL, "BE_IN"},
 	{"TERT_TDM_TX_3", NULL, "BE_IN"},
+	{"TERT_TDM_TX_7", NULL, "BE_IN"},
 	{"QUAT_TDM_TX_0", NULL, "BE_IN"},
 	{"QUAT_TDM_TX_1", NULL, "BE_IN"},
 	{"QUAT_TDM_TX_2", NULL, "BE_IN"},
diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h
index e9a08eb..f06dfc0 100644
--- a/asoc/msm-pcm-routing-v2.h
+++ b/asoc/msm-pcm-routing-v2.h
@@ -43,6 +43,8 @@
 #define LPASS_BE_QUAT_AUXPCM_TX "QUAT_AUX_PCM_TX"
 #define LPASS_BE_QUIN_AUXPCM_RX "QUIN_AUX_PCM_RX"
 #define LPASS_BE_QUIN_AUXPCM_TX "QUIN_AUX_PCM_TX"
+#define LPASS_BE_SEN_AUXPCM_RX "SEN_AUX_PCM_RX"
+#define LPASS_BE_SEN_AUXPCM_TX "SEN_AUX_PCM_TX"
 #define LPASS_BE_VOICE_PLAYBACK_TX "VOICE_PLAYBACK_TX"
 #define LPASS_BE_VOICE2_PLAYBACK_TX "VOICE2_PLAYBACK_TX"
 #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_RX"
@@ -84,6 +86,7 @@
 #define LPASS_BE_QUIN_MI2S_RX "QUIN_MI2S_RX"
 #define LPASS_BE_QUIN_MI2S_TX "QUIN_MI2S_TX"
 #define LPASS_BE_SENARY_MI2S_TX "SENARY_MI2S_TX"
+#define LPASS_BE_SENARY_MI2S_RX "SENARY_MI2S_RX"
 
 #define LPASS_BE_PRI_TDM_RX_0 "PRI_TDM_RX_0"
 #define LPASS_BE_PRI_TDM_TX_0 "PRI_TDM_TX_0"
@@ -431,6 +434,9 @@
 	MSM_BACKEND_DAI_INT5_MI2S_TX,
 	MSM_BACKEND_DAI_INT6_MI2S_RX,
 	MSM_BACKEND_DAI_INT6_MI2S_TX,
+	MSM_BACKEND_DAI_SEN_AUXPCM_RX,
+	MSM_BACKEND_DAI_SEN_AUXPCM_TX,
+	MSM_BACKEND_DAI_SENARY_MI2S_RX,
 	MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0,
 	MSM_BACKEND_DAI_WSA_CDC_DMA_TX_0,
 	MSM_BACKEND_DAI_WSA_CDC_DMA_RX_1,
diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c
index 0923d0a..1a3bd9c 100644
--- a/asoc/msm-qti-pp-config.c
+++ b/asoc/msm-qti-pp-config.c
@@ -809,11 +809,11 @@
 static int msm_qti_pp_get_channel_map_mixer(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_value *ucontrol)
 {
-	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL] = {0};
+	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8] = {0};
 	int i;
 
 	adm_get_multi_ch_map(channel_map, ADM_PATH_PLAYBACK);
-	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
 		ucontrol->value.integer.value[i] =
 			(unsigned int) channel_map[i];
 	return 0;
@@ -822,10 +822,10 @@
 static int msm_qti_pp_put_channel_map_mixer(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_value *ucontrol)
 {
-	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL];
+	char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
 	int i;
 
-	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
 		channel_map[i] = (char)(ucontrol->value.integer.value[i]);
 	adm_set_multi_ch_map(channel_map, ADM_PATH_PLAYBACK);
 
@@ -1414,8 +1414,8 @@
 };
 
 static const struct snd_kcontrol_new multi_ch_channel_map_mixer_controls[] = {
-	SOC_SINGLE_MULTI_EXT("Playback Device Channel Map", SND_SOC_NOPM, 0, 16,
-	0, 8, msm_qti_pp_get_channel_map_mixer,
+	SOC_SINGLE_MULTI_EXT("Playback Device Channel Map", SND_SOC_NOPM, 0, 34,
+	0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, msm_qti_pp_get_channel_map_mixer,
 	msm_qti_pp_put_channel_map_mixer),
 };
 
diff --git a/asoc/qcs405.c b/asoc/qcs405.c
index c819bb8..b5e6c0e 100644
--- a/asoc/qcs405.c
+++ b/asoc/qcs405.c
@@ -9,7 +9,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
@@ -64,7 +63,7 @@
 #define SAMPLING_RATE_352P8KHZ  352800
 #define SAMPLING_RATE_384KHZ    384000
 
-#define SPDIF_TX_CORE_CLK_204_P8_MHZ  204800000
+#define SPDIF_TX_CORE_CLK_163_P84_MHZ  163840000
 #define TLMM_EAST_SPARE 0x07BA0000
 #define TLMM_SPDIF_HDMI_ARC_CTL 0x07BA2000
 
@@ -108,6 +107,7 @@
 	TERT_MI2S,
 	QUAT_MI2S,
 	QUIN_MI2S,
+	SEN_MI2S,
 	MI2S_MAX,
 };
 
@@ -117,6 +117,7 @@
 	TERT_AUX_PCM,
 	QUAT_AUX_PCM,
 	QUIN_AUX_PCM,
+	SEN_AUX_PCM,
 	AUX_PCM_MAX,
 };
 
@@ -158,7 +159,8 @@
 	Q6AFE_LPASS_CLK_ID_SEC_MI2S_EBIT,
 	Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT,
 	Q6AFE_LPASS_CLK_ID_QUAD_MI2S_EBIT,
-	Q6AFE_LPASS_CLK_ID_QUI_MI2S_EBIT
+	Q6AFE_LPASS_CLK_ID_QUI_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_SEN_MI2S_EBIT
 };
 
 struct dev_config {
@@ -191,6 +193,7 @@
 	struct regulator *tdm_micb_supply;
 	u32 tdm_micb_voltage;
 	u32 tdm_micb_current;
+	bool codec_is_csra;
 };
 
 struct msm_asoc_wcd93xx_codec {
@@ -279,7 +282,6 @@
 		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
 		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
 	}
-
 };
 
 /* TDM default config */
@@ -401,6 +403,7 @@
 	[TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
 	[QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
 	[QUIN_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[SEN_MI2S]  = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
 };
 
 /* Default configuration of SPDIF channels */
@@ -420,6 +423,7 @@
 	[TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 	[QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 	[QUIN_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEN_MI2S]  = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 };
 
 static struct dev_config aux_pcm_rx_cfg[] = {
@@ -428,6 +432,7 @@
 	[TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 	[QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 	[QUIN_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEN_AUX_PCM]  = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 };
 
 static struct dev_config aux_pcm_tx_cfg[] = {
@@ -436,6 +441,7 @@
 	[TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 	[QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 	[QUIN_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEN_AUX_PCM]  = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 };
 
 static int msm_vi_feed_tx_ch = 2;
@@ -472,10 +478,12 @@
 static const char *const auxpcm_rate_text[] = {"KHZ_8", "KHZ_16"};
 static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_11P025", "KHZ_16",
 				      "KHZ_22P05", "KHZ_32", "KHZ_44P1",
-				      "KHZ_48", "KHZ_96", "KHZ_192"};
-static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
-					   "Five", "Six", "Seven",
-					   "Eight"};
+				      "KHZ_48", "KHZ_96", "KHZ_192", "KHZ_384"};
+static const char *const mi2s_ch_text[] = {
+		"One", "Two", "Three", "Four", "Five", "Six", "Seven",
+		"Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+		"Fourteen", "Fifteen", "Sixteen"
+};
 static const char *const qos_text[] = {"Disable", "Enable"};
 
 static const char *const cdc_dma_rx_ch_text[] = {"One", "Two"};
@@ -529,21 +537,25 @@
 static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_rx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_rx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quin_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sen_aux_pcm_rx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_tx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_tx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_tx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_tx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quin_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sen_aux_pcm_tx_sample_rate, auxpcm_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quin_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sen_mi2s_rx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quin_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sen_mi2s_tx_sample_rate, mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_chs, mi2s_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_chs, mi2s_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_chs, mi2s_ch_text);
@@ -554,6 +566,8 @@
 static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quin_mi2s_rx_chs, mi2s_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(quin_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sen_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sen_mi2s_tx_chs, mi2s_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text);
 static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text);
 static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text);
@@ -653,6 +667,14 @@
 		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
 		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
 		0,
+	},
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
 	}
 
 };
@@ -2420,6 +2442,9 @@
 	else if (strnstr(kcontrol->id.name, "QUIN_AUX_PCM",
 			 sizeof("QUIN_AUX_PCM")))
 		idx = QUIN_AUX_PCM;
+	else if (strnstr(kcontrol->id.name, "SEN_AUX_PCM",
+			 sizeof("SENN_AUX_PCM")))
+		idx = SEN_AUX_PCM;
 	else {
 		pr_err("%s: unsupported port: %s",
 			__func__, kcontrol->id.name);
@@ -2520,6 +2545,9 @@
 	else if (strnstr(kcontrol->id.name, "QUIN_MI2S_RX",
 		 sizeof("QUIN_MI2S_RX")))
 		idx = QUIN_MI2S;
+	else if (strnstr(kcontrol->id.name, "SEN_MI2S_RX",
+		 sizeof("SEN_MI2S_RX")))
+		idx = SEN_MI2S;
 	else if (strnstr(kcontrol->id.name, "PRIM_MI2S_TX",
 		 sizeof("PRIM_MI2S_TX")))
 		idx = PRIM_MI2S;
@@ -2535,6 +2563,9 @@
 	else if (strnstr(kcontrol->id.name, "QUIN_MI2S_TX",
 		 sizeof("QUIN_MI2S_TX")))
 		idx = QUIN_MI2S;
+	else if (strnstr(kcontrol->id.name, "SEN_MI2S_TX",
+		 sizeof("SEN_MI2S_TX")))
+		idx = SEN_MI2S;
 	else {
 		pr_err("%s: unsupported channel: %s",
 			__func__, kcontrol->id.name);
@@ -2576,6 +2607,9 @@
 	case SAMPLING_RATE_192KHZ:
 		sample_rate_val = 8;
 		break;
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 9;
+		break;
 	default:
 		sample_rate_val = 6;
 		break;
@@ -2615,6 +2649,9 @@
 	case 8:
 		sample_rate = SAMPLING_RATE_192KHZ;
 		break;
+	case 9:
+		sample_rate = SAMPLING_RATE_384KHZ;
+		break;
 	default:
 		sample_rate = SAMPLING_RATE_48KHZ;
 		break;
@@ -2823,17 +2860,34 @@
 static int msm_mi2s_rx_format_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
+
+	struct msm_asoc_mach_data *pdata = NULL;
+	struct snd_soc_component *component =  NULL;
+	struct snd_soc_card *card = NULL;
 	int idx = mi2s_get_port_idx(kcontrol);
 
+	component = snd_soc_kcontrol_component(kcontrol);
+	card = kcontrol->private_data;
+	pdata = snd_soc_card_get_drvdata(card);
+
 	if (idx < 0)
 		return idx;
 
-	mi2s_rx_cfg[idx].bit_format =
-		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+	/* check for PRIM_MI2S and CSRAx config to allow 24bit BE config only */
+	if ((PRIM_MI2S == idx) && (true==pdata->codec_is_csra))
+	{
+		mi2s_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		pr_debug("%s: Keeping default format idx[%d]_rx_format = %d, item = %d\n",
+			__func__, idx, mi2s_rx_cfg[idx].bit_format,
+				ucontrol->value.enumerated.item[0]);
+	} else {
+		mi2s_rx_cfg[idx].bit_format =
+			mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
 
-	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
-		  idx, mi2s_rx_cfg[idx].bit_format,
-		  ucontrol->value.enumerated.item[0]);
+		pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+			idx, mi2s_rx_cfg[idx].bit_format,
+			ucontrol->value.enumerated.item[0]);
+	}
 
 	return 0;
 }
@@ -3512,6 +3566,9 @@
 	SOC_ENUM_EXT("QUIN_AUX_PCM_TX SampleRate", quin_aux_pcm_tx_sample_rate,
 			aux_pcm_tx_sample_rate_get,
 			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEN_AUX_PCM_TX SampleRate", sen_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
 	SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate,
 			mi2s_rx_sample_rate_get,
 			mi2s_rx_sample_rate_put),
@@ -3527,6 +3584,9 @@
 	SOC_ENUM_EXT("QUIN_MI2S_RX SampleRate", quin_mi2s_rx_sample_rate,
 			mi2s_rx_sample_rate_get,
 			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEN_MI2S_RX SampleRate",  sen_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
 	SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate,
 			mi2s_tx_sample_rate_get,
 			mi2s_tx_sample_rate_put),
@@ -3542,6 +3602,9 @@
 	SOC_ENUM_EXT("QUIN_MI2S_TX SampleRate", quin_mi2s_tx_sample_rate,
 			mi2s_tx_sample_rate_get,
 			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEN_MI2S_TX SampleRate", sen_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
 	SOC_ENUM_EXT("PRIM_MI2S_RX Channels", prim_mi2s_rx_chs,
 			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
 	SOC_ENUM_EXT("PRIM_MI2S_TX Channels", prim_mi2s_tx_chs,
@@ -3562,6 +3625,10 @@
 			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
 	SOC_ENUM_EXT("QUIN_MI2S_TX Channels", quin_mi2s_tx_chs,
 			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("SEN_MI2S_RX Channels", sen_mi2s_rx_chs,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("SEN_MI2S_TX Channels", sen_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
 	SOC_ENUM_EXT("PRIM_MI2S_RX Format", mi2s_rx_format,
 			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
 	SOC_ENUM_EXT("PRIM_MI2S_TX Format", mi2s_tx_format,
@@ -3582,6 +3649,10 @@
 			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
 	SOC_ENUM_EXT("QUIN_MI2S_TX Format", mi2s_tx_format,
 			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("SEN_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("SEN_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
 	SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
 			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
 	SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
@@ -3602,6 +3673,10 @@
 			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
 	SOC_ENUM_EXT("QUIN_AUX_PCM_TX Format", aux_pcm_tx_format,
 			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("SEN_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("SEN_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
 	SOC_SINGLE_MULTI_EXT("VAD CFG", SND_SOC_NOPM, 0, 1000, 0, 3, NULL,
 				msm_snd_vad_cfg_put),
 	SOC_ENUM_EXT("PRIM_SPDIF_RX SampleRate", spdif_rx_sample_rate,
@@ -4132,7 +4207,6 @@
 		rate->min = rate->max = tdm_tx_cfg[TDM_QUIN][TDM_0].sample_rate;
 		break;
 
-
 	case MSM_BACKEND_DAI_AUXPCM_RX:
 		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
 			aux_pcm_rx_cfg[PRIM_AUX_PCM].bit_format);
@@ -4223,6 +4297,24 @@
 			aux_pcm_tx_cfg[QUIN_AUX_PCM].channels;
 		break;
 
+	case MSM_BACKEND_DAI_SEN_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[SEN_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[SEN_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[SEN_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SEN_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[SEN_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[SEN_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[SEN_AUX_PCM].channels;
+		break;
+
 	case MSM_BACKEND_DAI_PRI_MI2S_RX:
 		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
 			mi2s_rx_cfg[PRIM_MI2S].bit_format);
@@ -4303,6 +4395,21 @@
 			mi2s_tx_cfg[QUIN_MI2S].channels;
 		break;
 
+	case MSM_BACKEND_DAI_SENARY_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[SEN_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[SEN_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[SEN_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SENARY_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[SEN_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[SEN_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[SEN_MI2S].channels;
+		break;
 	case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0:
 	case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_1:
 		idx = msm_cdc_dma_get_idx_from_beid(dai_link->id);
@@ -4984,6 +5091,12 @@
 	case MSM_BACKEND_DAI_QUINARY_MI2S_TX:
 		afe_port_id = AFE_PORT_ID_QUINARY_MI2S_TX;
 		break;
+	case MSM_BACKEND_DAI_SENARY_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_SENARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_SENARY_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_SENARY_MI2S_TX;
+		break;
 	default:
 		pr_err("%s: Invalid BE id: %d\n", __func__, be_id);
 		afe_port_id = -EINVAL;
@@ -5150,7 +5263,6 @@
 	case AFE_PORT_ID_QUINARY_TDM_TX:
 		channels = tdm_tx_cfg[TDM_QUIN][TDM_0].channels;
 		break;
-
 	default:
 		pr_err("%s: dai id 0x%x not supported\n",
 			__func__, cpu_dai->id);
@@ -5365,11 +5477,13 @@
 	.prepare = msm_fe_qos_prepare,
 };
 
+
 static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
 {
 	int ret = 0;
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+
 	int index = cpu_dai->id;
 	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
 	struct snd_soc_card *card = rtd->card;
@@ -5485,11 +5599,11 @@
 		break;
 	case AFE_PORT_ID_PRIMARY_SPDIF_TX:
 		clk_cfg.clk_id = AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE;
-		clk_cfg.clk_freq_in_hz = SPDIF_TX_CORE_CLK_204_P8_MHZ;
+		clk_cfg.clk_freq_in_hz = SPDIF_TX_CORE_CLK_163_P84_MHZ;
 		break;
 	case AFE_PORT_ID_SECONDARY_SPDIF_TX:
 		clk_cfg.clk_id = AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE;
-		clk_cfg.clk_freq_in_hz = SPDIF_TX_CORE_CLK_204_P8_MHZ;
+		clk_cfg.clk_freq_in_hz = SPDIF_TX_CORE_CLK_163_P84_MHZ;
 		break;
 	}
 
@@ -8323,10 +8437,13 @@
 		val = 0;
 	}
 	if (val) {
+		pdata->codec_is_csra = true;
+		mi2s_rx_cfg[PRIM_MI2S].bit_format = SNDRV_PCM_FORMAT_S24_LE;
 		ret = msm_init_csra_dev(pdev, card);
 		if (ret)
 			goto err;
 	} else {
+		pdata->codec_is_csra = false;
 		ret = msm_init_wsa_dev(pdev, card);
 		if (ret)
 			goto err;
diff --git a/asoc/sa8155.c b/asoc/sa8155.c
index 5e51f09..a477a85 100644
--- a/asoc/sa8155.c
+++ b/asoc/sa8155.c
@@ -397,7 +397,7 @@
 		{0xFFFF}, /* not used */
 		{0xFFFF}, /* not used */
 		{0xFFFF}, /* not used */
-		{0xFFFF}, /* not used */
+		{28, 0xFFFF},
 	},
 	{/* TERT TDM */
 		{0, 4, 8, 12, 16, 20, 0xFFFF},
@@ -461,7 +461,7 @@
 		{0xFFFF}, /* not used */
 		{0xFFFF}, /* not used */
 		{0xFFFF}, /* not used */
-		{0xFFFF}, /* not used */
+		{28, 0xFFFF},
 	},
 	{/* QUAT TDM */
 		{0xFFFF}, /* not used */
@@ -512,7 +512,7 @@
 		{10, 0xFFFF},
 		{12, 14, 16, 18, 20, 22, 24, 26, 0xFFFF},
 		{28, 30, 0xFFFF},
-		{0xFFFF}, /* not used */
+		{30, 0xFFFF},
 	},
 	{/* TERT TDM */
 		{0, 2, 0xFFFF},
@@ -576,7 +576,7 @@
 		{0xFFFF}, /* not used */
 		{0xFFFF}, /* not used */
 		{0xFFFF}, /* not used */
-		{0xFFFF}, /* not used */
+		{30, 0xFFFF},
 	},
 	{/* QUAT TDM */
 		{0xFFFF}, /* not used */
@@ -4018,6 +4018,14 @@
 		rate->min = rate->max =
 				tdm_rx_cfg[TDM_SEC][TDM_3].sample_rate;
 		break;
+	case AFE_PORT_ID_SECONDARY_TDM_RX_7:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_SEC][TDM_7].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				tdm_rx_cfg[TDM_SEC][TDM_7].bit_format);
+		rate->min = rate->max =
+				tdm_rx_cfg[TDM_SEC][TDM_7].sample_rate;
+		break;
 	case AFE_PORT_ID_SECONDARY_TDM_TX:
 		channels->min = channels->max =
 				tdm_tx_cfg[TDM_SEC][TDM_0].channels;
@@ -4122,6 +4130,14 @@
 		rate->min = rate->max =
 				tdm_tx_cfg[TDM_TERT][TDM_3].sample_rate;
 		break;
+	case AFE_PORT_ID_TERTIARY_TDM_TX_7:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_TERT][TDM_7].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				tdm_tx_cfg[TDM_TERT][TDM_7].bit_format);
+		rate->min = rate->max =
+				tdm_tx_cfg[TDM_TERT][TDM_7].sample_rate;
+		break;
 	case AFE_PORT_ID_QUATERNARY_TDM_RX:
 		channels->min = channels->max =
 				tdm_rx_cfg[TDM_QUAT][TDM_0].channels;
@@ -4375,6 +4391,11 @@
 		slot_width = tdm_slot[TDM_SEC].width;
 		slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_3];
 		break;
+	case AFE_PORT_ID_SECONDARY_TDM_RX_7:
+		slots = tdm_slot[TDM_SEC].num;
+		slot_width = tdm_slot[TDM_SEC].width;
+		slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_7];
+		break;
 	case AFE_PORT_ID_SECONDARY_TDM_TX:
 		slots = tdm_slot[TDM_SEC].num;
 		slot_width = tdm_slot[TDM_SEC].width;
@@ -4440,6 +4461,11 @@
 		slot_width = tdm_slot[TDM_TERT].width;
 		slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_3];
 		break;
+	case AFE_PORT_ID_TERTIARY_TDM_TX_7:
+		slots = tdm_slot[TDM_TERT].num;
+		slot_width = tdm_slot[TDM_TERT].width;
+		slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_7];
+		break;
 	case AFE_PORT_ID_QUATERNARY_TDM_RX:
 		slots = tdm_slot[TDM_QUAT].num;
 		slot_width = tdm_slot[TDM_QUAT].width;
@@ -5565,7 +5591,37 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.id = MSM_FRONTEND_DAI_DTMF_RX,
-	}
+	},
+	{
+		.name = "Secondary TDM RX 7 Hostless",
+		.stream_name = "Secondary TDM RX 7 Hostless",
+		.cpu_dai_name = "SEC_TDM_RX_7_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{
+		.name = "Tertiary TDM TX 7 Hostless",
+		.stream_name = "Tertiary TDM TX 7 Hostless",
+		.cpu_dai_name = "TERT_TDM_TX_7_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
 };
 
 static struct snd_soc_dai_link msm_custom_fe_dai_links[] = {
@@ -6119,6 +6175,20 @@
 		.ignore_suspend = 1,
 	},
 	{
+		.name = LPASS_BE_SEC_TDM_RX_7,
+		.stream_name = "Secondary TDM7 Playback",
+		.cpu_dai_name = "msm-dai-q6-tdm.36894",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SEC_TDM_RX_7,
+		.be_hw_params_fixup = msm_tdm_be_hw_params_fixup,
+		.ops = &sa8155_tdm_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
 		.name = LPASS_BE_SEC_TDM_TX_1,
 		.stream_name = "Secondary TDM1 Capture",
 		.cpu_dai_name = "msm-dai-q6-tdm.36883",
@@ -6259,6 +6329,20 @@
 		.ignore_suspend = 1,
 	},
 	{
+		.name = LPASS_BE_TERT_TDM_TX_7,
+		.stream_name = "Tertiary TDM7 Capture",
+		.cpu_dai_name = "msm-dai-q6-tdm.36911",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TERT_TDM_TX_7,
+		.be_hw_params_fixup = msm_tdm_be_hw_params_fixup,
+		.ops = &sa8155_tdm_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
 		.name = LPASS_BE_QUAT_TDM_RX_1,
 		.stream_name = "Quaternary TDM1 Playback",
 		.cpu_dai_name = "msm-dai-q6-tdm.36914",
diff --git a/asoc/sm6150.c b/asoc/sm6150.c
index a3c455b..8bd1d6f 100644
--- a/asoc/sm6150.c
+++ b/asoc/sm6150.c
@@ -22,6 +22,7 @@
 #include <linux/input.h>
 #include <linux/of_device.h>
 #include <linux/pm_qos.h>
+#include <linux/soc/qcom/fsa4480-i2c.h>
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -202,6 +203,7 @@
 	struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
 	struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
 	bool is_afe_config_done;
+	struct device_node *fsa_handle;
 };
 
 struct msm_asoc_wcd93xx_codec {
@@ -4601,88 +4603,14 @@
 
 static bool msm_usbc_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
 {
-	int value = 0;
-	bool ret = 0;
 	struct snd_soc_card *card = codec->component.card;
-	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct pinctrl_state *en2_pinctrl_active;
-	struct pinctrl_state *en2_pinctrl_sleep;
+	struct msm_asoc_mach_data *pdata =
+				snd_soc_card_get_drvdata(card);
 
-	if (!pdata->usbc_en2_gpio_p) {
-		if (active) {
-			/* if active and usbc_en2_gpio undefined, get pin */
-			pdata->usbc_en2_gpio_p = devm_pinctrl_get(card->dev);
-			if (IS_ERR_OR_NULL(pdata->usbc_en2_gpio_p)) {
-				dev_err(card->dev,
-					"%s: Can't get EN2 gpio pinctrl:%ld\n",
-					__func__,
-					PTR_ERR(pdata->usbc_en2_gpio_p));
-				pdata->usbc_en2_gpio_p = NULL;
-				return false;
-			}
-		} else {
-			/* if not active and usbc_en2_gpio undefined, return */
-			return false;
-		}
-	}
-
-	pdata->usbc_en2_gpio = of_get_named_gpio(card->dev->of_node,
-				    "qcom,usbc-analog-en2-gpio", 0);
-	if (!gpio_is_valid(pdata->usbc_en2_gpio)) {
-		dev_err(card->dev, "%s, property %s not in node %s",
-			__func__, "qcom,usbc-analog-en2-gpio",
-			card->dev->of_node->full_name);
+	if (!pdata->fsa_handle)
 		return false;
-	}
 
-	en2_pinctrl_active = pinctrl_lookup_state(
-					pdata->usbc_en2_gpio_p, "aud_active");
-	if (IS_ERR_OR_NULL(en2_pinctrl_active)) {
-		dev_err(card->dev,
-			"%s: Cannot get aud_active pinctrl state:%ld\n",
-			__func__, PTR_ERR(en2_pinctrl_active));
-		ret = false;
-		goto err_lookup_state;
-	}
-
-	en2_pinctrl_sleep = pinctrl_lookup_state(
-					pdata->usbc_en2_gpio_p, "aud_sleep");
-	if (IS_ERR_OR_NULL(en2_pinctrl_sleep)) {
-		dev_err(card->dev,
-			"%s: Cannot get aud_sleep pinctrl state:%ld\n",
-			__func__, PTR_ERR(en2_pinctrl_sleep));
-		ret = false;
-		goto err_lookup_state;
-	}
-
-	/* if active and usbc_en2_gpio_p defined, swap using usbc_en2_gpio_p */
-	if (active) {
-		dev_dbg(codec->dev, "%s: enter\n", __func__);
-		if (pdata->usbc_en2_gpio_p) {
-			value = gpio_get_value_cansleep(pdata->usbc_en2_gpio);
-			if (value)
-				pinctrl_select_state(pdata->usbc_en2_gpio_p,
-							en2_pinctrl_sleep);
-			else
-				pinctrl_select_state(pdata->usbc_en2_gpio_p,
-							en2_pinctrl_active);
-		} else if (pdata->usbc_en2_gpio >= 0) {
-			value = gpio_get_value_cansleep(pdata->usbc_en2_gpio);
-			gpio_set_value_cansleep(pdata->usbc_en2_gpio, !value);
-		}
-		pr_debug("%s: swap select switch %d to %d\n", __func__,
-			value, !value);
-		ret = true;
-	} else {
-		/* if not active, release usbc_en2_gpio_p pin */
-		pinctrl_select_state(pdata->usbc_en2_gpio_p,
-					en2_pinctrl_sleep);
-	}
-
-err_lookup_state:
-	devm_pinctrl_put(pdata->usbc_en2_gpio_p);
-	pdata->usbc_en2_gpio_p = NULL;
-	return ret;
+	return fsa4480_switch_event(pdata->fsa_handle, FSA_MIC_GND_SWAP);
 }
 
 static bool msm_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
@@ -8595,6 +8523,18 @@
 			"qcom,us-euro-gpios");
 		wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
 	}
+
+	if (wcd_mbhc_cfg.enable_usbc_analog) {
+		wcd_mbhc_cfg.swap_gnd_mic = msm_usbc_swap_gnd_mic;
+
+		pdata->fsa_handle = of_parse_phandle(pdev->dev.of_node,
+						"fsa4480-i2c-handle", 0);
+		if (!pdata->fsa_handle)
+			dev_err(&pdev->dev,
+				"property %s not detected in node %s\n",
+				"fsa4480-i2c-handle",
+				pdev->dev.of_node->full_name);
+	}
 	/* Parse pinctrl info from devicetree */
 	ret = msm_get_pinctrl(pdev);
 	if (!ret) {
diff --git a/config/qcs405auto.conf b/config/qcs405auto.conf
index 61620eb..afa8140 100644
--- a/config/qcs405auto.conf
+++ b/config/qcs405auto.conf
@@ -36,3 +36,4 @@
 CONFIG_MSM_AVTIMER=m
 CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=m
 CONFIG_SND_SOC_EP92=m
+CONFIG_USE_Q6_32CH_SUPPORT=m
diff --git a/config/qcs405autoconf.h b/config/qcs405autoconf.h
index 98cd166..fd9407b 100644
--- a/config/qcs405autoconf.h
+++ b/config/qcs405autoconf.h
@@ -48,3 +48,4 @@
 #define CONFIG_MSM_AVTIMER 1
 #define CONFIG_SND_SOC_MSM_HDMI_CODEC_RX 1
 #define CONFIG_SND_SOC_EP92 1
+#define CONFIG_USE_Q6_32CH_SUPPORT 1
diff --git a/dsp/adsp-loader.c b/dsp/adsp-loader.c
index cc995db..5afd48c 100644
--- a/dsp/adsp-loader.c
+++ b/dsp/adsp-loader.c
@@ -26,12 +26,17 @@
 
 #define Q6_PIL_GET_DELAY_MS 100
 #define BOOT_CMD 1
+#define SSR_RESET_CMD 1
 #define IMAGE_UNLOAD_CMD 0
 
 static ssize_t adsp_boot_store(struct kobject *kobj,
 	struct kobj_attribute *attr,
 	const char *buf, size_t count);
 
+static ssize_t adsp_ssr_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf, size_t count);
+
 struct adsp_loader_private {
 	void *pil_h;
 	struct kobject *boot_adsp_obj;
@@ -41,8 +46,12 @@
 static struct kobj_attribute adsp_boot_attribute =
 	__ATTR(boot, 0220, NULL, adsp_boot_store);
 
+static struct kobj_attribute adsp_ssr_attribute =
+	__ATTR(ssr, 0220, NULL, adsp_ssr_store);
+
 static struct attribute *attrs[] = {
 	&adsp_boot_attribute.attr,
+	&adsp_ssr_attribute.attr,
 	NULL,
 };
 
@@ -151,6 +160,46 @@
 	schedule_work(&adsp_ldr_work);
 }
 
+static ssize_t adsp_ssr_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf,
+	size_t count)
+{
+	int ssr_command = 0;
+	struct subsys_device *adsp_dev = NULL;
+	struct platform_device *pdev = adsp_private;
+	struct adsp_loader_private *priv = NULL;
+	int rc;
+
+	dev_dbg(&pdev->dev, "%s: going to call adsp ssr\n ", __func__);
+
+	if (kstrtoint(buf, 10, &ssr_command) < 0)
+		return -EINVAL;
+
+	if (ssr_command != SSR_RESET_CMD)
+		return -EINVAL;
+
+	priv = platform_get_drvdata(pdev);
+	if (!priv)
+		return -EINVAL;
+
+	adsp_dev = (struct subsys_device *)priv->pil_h;
+	if (!adsp_dev)
+		return -EINVAL;
+
+	dev_err(&pdev->dev, "requesting for ADSP restart\n");
+
+	/* subsystem_restart_dev has worker queue to handle */
+	rc = subsystem_restart_dev(adsp_dev);
+	if (rc) {
+		dev_err(&pdev->dev, "subsystem_restart_dev failed\n");
+		return rc;
+	}
+
+	dev_dbg(&pdev->dev, "ADSP restarted\n");
+	return count;
+}
+
 static ssize_t adsp_boot_store(struct kobject *kobj,
 	struct kobj_attribute *attr,
 	const char *buf,
diff --git a/dsp/codecs/audio_utils_aio.c b/dsp/codecs/audio_utils_aio.c
index 298a77d..445bd3f 100644
--- a/dsp/codecs/audio_utils_aio.c
+++ b/dsp/codecs/audio_utils_aio.c
@@ -1181,7 +1181,13 @@
 			kfree(buf_node);
 			return -EINVAL;
 		}
-		extract_meta_out_info(audio, buf_node, 1);
+		ret = extract_meta_out_info(audio, buf_node, 1);
+		if (ret) {
+			pr_debug("%s: extract meta failed with %d\n",
+				  __func__, ret);
+			kfree(buf_node);
+			return ret;
+		}
 		/* Not a EOS buffer */
 		if (!(buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOS_SET)) {
 			spin_lock_irqsave(&audio->dsp_lock, flags);
@@ -1683,7 +1689,7 @@
 	case AUDIO_SET_CONFIG: {
 		struct msm_audio_config config;
 
-		pr_err("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
+		pr_debug("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
 		mutex_lock(&audio->lock);
 		if (copy_from_user(&config, (void *)arg, sizeof(config))) {
 			pr_err(
@@ -2010,7 +2016,7 @@
 			mutex_unlock(&audio->lock);
 			break;
 		}
-		pr_err("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
+		pr_debug("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
 		if (copy_from_user(&config_32, (void *)arg,
 					sizeof(config_32))) {
 			pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n",
diff --git a/dsp/codecs/audio_utils_aio.h b/dsp/codecs/audio_utils_aio.h
index 1993f60..bd99c36 100644
--- a/dsp/codecs/audio_utils_aio.h
+++ b/dsp/codecs/audio_utils_aio.h
@@ -210,7 +210,7 @@
 int insert_eos_buf(struct q6audio_aio *audio,
 		struct audio_aio_buffer_node *buf_node);
 
-void extract_meta_out_info(struct q6audio_aio *audio,
+int extract_meta_out_info(struct q6audio_aio *audio,
 		struct audio_aio_buffer_node *buf_node, int dir);
 
 int audio_aio_open(struct q6audio_aio *audio, struct file *file);
diff --git a/dsp/codecs/q6audio_v2_aio.c b/dsp/codecs/q6audio_v2_aio.c
index 9f76458..973108d 100644
--- a/dsp/codecs/q6audio_v2_aio.c
+++ b/dsp/codecs/q6audio_v2_aio.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -118,19 +118,26 @@
 	}
 }
 
-void extract_meta_out_info(struct q6audio_aio *audio,
+int extract_meta_out_info(struct q6audio_aio *audio,
 		struct audio_aio_buffer_node *buf_node, int dir)
 {
 	struct dec_meta_out *meta_data = buf_node->kvaddr;
 	uint32_t temp;
 
 	if (dir) { /* input buffer - Write */
-		if (audio->buf_cfg.meta_info_enable)
+		if (audio->buf_cfg.meta_info_enable) {
+			if (buf_node->buf.buf_len <
+				sizeof(struct dec_meta_in)) {
+				pr_debug("%s: invalid buf len %d\n",
+					 __func__, buf_node->buf.buf_len);
+				return -EINVAL;
+			}
 			memcpy(&buf_node->meta_info.meta_in,
 			(char *)buf_node->kvaddr, sizeof(struct dec_meta_in));
-		else
+		} else {
 			memset(&buf_node->meta_info.meta_in,
 			0, sizeof(struct dec_meta_in));
+		}
 		pr_debug("%s[%pK]:i/p: msw_ts %d lsw_ts %d nflags 0x%8x\n",
 			__func__, audio,
 			buf_node->meta_info.meta_in.ntimestamp.highpart,
@@ -156,6 +163,7 @@
 			meta_out_dsp[0].nflags,
 		((struct dec_meta_out *)buf_node->kvaddr)->num_of_frames);
 	}
+	return 0;
 }
 
 /* Read buffer from DSP / Handle Ack from DSP */
@@ -165,6 +173,7 @@
 	unsigned long flags;
 	union msm_audio_event_payload event_payload;
 	struct audio_aio_buffer_node *filled_buf;
+	int ret;
 
 	pr_debug("%s\n", __func__);
 
@@ -208,7 +217,7 @@
 				__func__, audio,
 				filled_buf->meta_info.meta_out.num_of_frames,
 				event_payload.aio_buf.data_len);
-			extract_meta_out_info(audio, filled_buf, 0);
+			ret = extract_meta_out_info(audio, filled_buf, 0);
 			audio->eos_rsp = 0;
 		}
 		pr_debug("%s, posting read done to the app here\n", __func__);
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index 191e668..4e621a9 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -23,6 +23,7 @@
 #include <dsp/q6adm-v2.h>
 #include <dsp/q6audio-v2.h>
 #include <dsp/q6afe-v2.h>
+#include <dsp/q6core.h>
 #include <dsp/audio_cal_utils.h>
 #include <dsp/q6common.h>
 #include <ipc/apr.h>
@@ -104,24 +105,32 @@
 	int num_ec_ref_rx_chans;
 	int ec_ref_rx_bit_width;
 	int ec_ref_rx_sampling_rate;
+
+	int native_mode;
 };
 
 static struct adm_ctl			this_adm;
 
 struct adm_multi_ch_map {
 	bool set_channel_map;
-	char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+	char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
 };
 
 #define ADM_MCH_MAP_IDX_PLAYBACK 0
 #define ADM_MCH_MAP_IDX_REC 1
 static struct adm_multi_ch_map multi_ch_maps[2] = {
-							{ false,
-							{0, 0, 0, 0, 0, 0, 0, 0}
-							},
-							{ false,
-							{0, 0, 0, 0, 0, 0, 0, 0}
-							}
+			{ false,
+			{0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0, 0, 0, 0}
+			},
+			{ false,
+			{0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0, 0, 0, 0}
+			}
 };
 
 static int adm_get_parameters[MAX_COPPS_PER_PORT * ADM_GET_PARAMETER_LENGTH];
@@ -1303,7 +1312,7 @@
 	}
 
 	memcpy(multi_ch_maps[idx].channel_mapping, channel_map,
-		PCM_FORMAT_MAX_NUM_CHANNEL);
+			PCM_FORMAT_MAX_NUM_CHANNEL_V8);
 	multi_ch_maps[idx].set_channel_map = true;
 
 	return 0;
@@ -1334,7 +1343,7 @@
 
 	if (multi_ch_maps[idx].set_channel_map) {
 		memcpy(channel_map, multi_ch_maps[idx].channel_mapping,
-		       PCM_FORMAT_MAX_NUM_CHANNEL);
+				PCM_FORMAT_MAX_NUM_CHANNEL_V8);
 	}
 
 	return 0;
@@ -1581,6 +1590,7 @@
 			case ADM_CMD_DEVICE_OPEN_V5:
 			case ADM_CMD_DEVICE_CLOSE_V5:
 			case ADM_CMD_DEVICE_OPEN_V6:
+			case ADM_CMD_DEVICE_OPEN_V8:
 				pr_debug("%s: Basic callback received, wake up.\n",
 					__func__);
 				atomic_set(&this_adm.copp.stat[port_idx]
@@ -1680,7 +1690,8 @@
 
 		switch (data->opcode) {
 		case ADM_CMDRSP_DEVICE_OPEN_V5:
-		case ADM_CMDRSP_DEVICE_OPEN_V6: {
+		case ADM_CMDRSP_DEVICE_OPEN_V6:
+		case ADM_CMDRSP_DEVICE_OPEN_V8: {
 			struct adm_cmd_rsp_device_open_v5 *open =
 			(struct adm_cmd_rsp_device_open_v5 *)data->payload;
 
@@ -2514,6 +2525,225 @@
 	return rc;
 }
 
+static int adm_arrange_mch_map_v8(
+		struct adm_device_endpoint_payload *ep_payload,
+		int path,
+		int channel_mode)
+{
+	int rc = 0, idx;
+
+	memset(ep_payload->dev_channel_mapping,
+			0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+	switch (path) {
+	case ADM_PATH_PLAYBACK:
+		idx = ADM_MCH_MAP_IDX_PLAYBACK;
+		break;
+	case ADM_PATH_LIVE_REC:
+	case ADM_PATH_NONLIVE_REC:
+		idx = ADM_MCH_MAP_IDX_REC;
+		break;
+	default:
+		goto non_mch_path;
+	};
+
+	if ((ep_payload->dev_num_channel > 2) &&
+			multi_ch_maps[idx].set_channel_map) {
+		memcpy(ep_payload->dev_channel_mapping,
+			multi_ch_maps[idx].channel_mapping,
+			PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+	} else {
+		if (channel_mode == 1) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
+		} else if (channel_mode == 2) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		} else if (channel_mode == 3) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+		} else if (channel_mode == 4) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
+		} else if (channel_mode == 5) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
+			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
+		} else if (channel_mode == 6) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+		} else if (channel_mode == 7) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
+			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
+			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
+			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
+		} else if (channel_mode == 8) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+		} else if (channel_mode == 10) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
+			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
+			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
+			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
+			ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
+			ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
+		} else if (channel_mode == 12) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
+			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
+			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
+			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
+			ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
+			ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
+			ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
+			ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
+		} else if (channel_mode == 16) {
+			ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
+			ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
+			ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LS;
+			ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RS;
+			ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
+			ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
+			ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
+			ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
+			ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
+			ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
+			ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
+			ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
+		} else {
+			pr_err("%s: invalid num_chan %d\n", __func__,
+				channel_mode);
+			rc = -EINVAL;
+			goto inval_ch_mod;
+		}
+	}
+
+non_mch_path:
+inval_ch_mod:
+	return rc;
+}
+
+static int adm_arrange_mch_ep2_map_v8(
+		struct adm_device_endpoint_payload *ep_payload,
+		int channel_mode)
+{
+	int rc = 0;
+
+	memset(ep_payload->dev_channel_mapping, 0,
+	       PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+
+	if (channel_mode == 1) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
+	} else if (channel_mode == 2) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+	} else if (channel_mode == 3) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+	} else if (channel_mode == 4) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
+		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
+	} else if (channel_mode == 5) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
+		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
+	} else if (channel_mode == 6) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+	} else if (channel_mode == 8) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+	}  else if (channel_mode == 10) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+		ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+		ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+	} else if (channel_mode == 12) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+		ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_TFL;
+		ep_payload->dev_channel_mapping[9] = PCM_CHANNEL_TFR;
+		ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_TSL;
+		ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_TSR;
+	} else if (channel_mode == 16) {
+		ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+		ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+		ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+		ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+		ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+		ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+		ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+		ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+		ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+		ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
+		ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
+		ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
+		ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
+		ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
+		ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
+	} else {
+		pr_err("%s: invalid num_chan %d\n", __func__,
+			channel_mode);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
 /**
  * adm_open -
  *        command to send ADM open
@@ -2535,10 +2765,17 @@
 {
 	struct adm_cmd_device_open_v5	open;
 	struct adm_cmd_device_open_v6	open_v6;
+	struct adm_cmd_device_open_v8	open_v8;
+	struct adm_device_endpoint_payload ep1_payload;
+	struct adm_device_endpoint_payload ep2_payload;
+	int ep1_payload_size = 0;
+	int ep2_payload_size = 0;
 	int ret = 0;
 	int port_idx, flags;
 	int copp_idx = -1;
 	int tmp_port = q6audio_get_port_id(port_id);
+	void *adm_params = NULL;
+	int param_size;
 
 	pr_debug("%s:port %#x path:%d rate:%d mode:%d perf_mode:%d,topo_id %d\n",
 		 __func__, port_id, path, rate, channel_mode, perf_mode,
@@ -2550,6 +2787,11 @@
 		pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
 		return -EINVAL;
 	}
+	if (channel_mode < 0 || channel_mode > 32) {
+		pr_err("%s: Invalid channel number 0x%x\n",
+				__func__, channel_mode);
+		return -EINVAL;
+	}
 
 	if (this_adm.apr == NULL) {
 		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
@@ -2643,109 +2885,246 @@
 	if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
 		pr_debug("%s: open ADM: port_idx: %d, copp_idx: %d\n", __func__,
 			 port_idx, copp_idx);
-	if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
-	     perf_mode == LEGACY_PCM_MODE) {
-		int res;
+		if ((topology == SRS_TRUMEDIA_TOPOLOGY_ID) &&
+		      perf_mode == LEGACY_PCM_MODE) {
+			int res;
 
-		atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
-		msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
-		res = adm_memory_map_regions(&this_adm.outband_memmap.paddr, 0,
-		(uint32_t *)&this_adm.outband_memmap.size, 1);
-		if (res < 0) {
-			pr_err("%s: SRS adm_memory_map_regions failed ! addr = 0x%pK, size = %d\n",
-			 __func__, (void *)this_adm.outband_memmap.paddr,
-		(uint32_t)this_adm.outband_memmap.size);
-		}
-	}
-		open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-						   APR_HDR_LEN(APR_HDR_SIZE),
-						   APR_PKT_VER);
-		open.hdr.pkt_size = sizeof(open);
-		open.hdr.src_svc = APR_SVC_ADM;
-		open.hdr.src_domain = APR_DOMAIN_APPS;
-		open.hdr.src_port = tmp_port;
-		open.hdr.dest_svc = APR_SVC_ADM;
-		open.hdr.dest_domain = APR_DOMAIN_ADSP;
-		open.hdr.dest_port = tmp_port;
-		open.hdr.token = port_idx << 16 | copp_idx;
-		open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
-		open.flags = flags;
-		open.mode_of_operation = path;
-		open.endpoint_id_1 = tmp_port;
-		open.endpoint_id_2 = 0xFFFF;
-
-		if (this_adm.ec_ref_rx && (path != 1)) {
-			open.endpoint_id_2 = this_adm.ec_ref_rx;
-			this_adm.ec_ref_rx = -1;
-		}
-
-		open.topology_id = topology;
-
-		open.dev_num_channel = channel_mode & 0x00FF;
-		open.bit_width = bit_width;
-		WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
-			(rate != ULL_SUPPORTED_SAMPLE_RATE));
-		open.sample_rate  = rate;
-
-		ret = adm_arrange_mch_map(&open, path, channel_mode);
-
-		if (ret)
-			return ret;
-
-		pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
-			__func__, open.endpoint_id_1, open.sample_rate,
-			open.topology_id);
-
-		atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
-
-		if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1) &&
-			(open.endpoint_id_2 != 0xFFFF)) {
-			memset(&open_v6, 0,
-				sizeof(struct adm_cmd_device_open_v6));
-			memcpy(&open_v6, &open,
-				sizeof(struct adm_cmd_device_open_v5));
-			open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
-			open_v6.hdr.pkt_size = sizeof(open_v6);
-			open_v6.dev_num_channel_eid2 =
-				this_adm.num_ec_ref_rx_chans;
-			this_adm.num_ec_ref_rx_chans = 0;
-
-			if (this_adm.ec_ref_rx_bit_width != 0) {
-				open_v6.bit_width_eid2 =
-					this_adm.ec_ref_rx_bit_width;
-				this_adm.ec_ref_rx_bit_width = 0;
-			} else {
-				open_v6.bit_width_eid2 = bit_width;
+			atomic_set(&this_adm.mem_map_index, ADM_SRS_TRUMEDIA);
+			msm_dts_srs_tm_ion_memmap(&this_adm.outband_memmap);
+			res = adm_memory_map_regions(
+					&this_adm.outband_memmap.paddr, 0,
+			(uint32_t *)&this_adm.outband_memmap.size, 1);
+			if (res < 0) {
+				pr_err("%s: SRS adm_memory_map_regions failed! addr = 0x%pK, size = %d\n",
+					__func__,
+					(void *)this_adm.outband_memmap.paddr,
+					(uint32_t)this_adm.outband_memmap.size);
 			}
+		}
 
-			if (this_adm.ec_ref_rx_sampling_rate != 0) {
-				open_v6.sample_rate_eid2 =
+
+		if ((q6core_get_avcs_api_version_per_service(
+				APRV2_IDS_SERVICE_ID_ADSP_ADM_V) >=
+					ADSP_ADM_API_VERSION_V3) &&
+					q6core_use_Q6_32ch_support()) {
+			memset(&open_v8, 0, sizeof(open_v8));
+			memset(&ep1_payload, 0, sizeof(ep1_payload));
+			memset(&ep2_payload, 0, sizeof(ep2_payload));
+
+			open_v8.hdr.hdr_field = APR_HDR_FIELD(
+					APR_MSG_TYPE_SEQ_CMD,
+					APR_HDR_LEN(APR_HDR_SIZE),
+					APR_PKT_VER);
+			open_v8.hdr.src_svc = APR_SVC_ADM;
+			open_v8.hdr.src_domain = APR_DOMAIN_APPS;
+			open_v8.hdr.src_port = tmp_port;
+			open_v8.hdr.dest_svc = APR_SVC_ADM;
+			open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
+			open_v8.hdr.dest_port = tmp_port;
+			open_v8.hdr.token = port_idx << 16 | copp_idx;
+			open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;
+
+			if (this_adm.native_mode != 0) {
+				open_v8.flags = flags |
+					(this_adm.native_mode << 11);
+				this_adm.native_mode = 0;
+			} else {
+				open_v8.flags = flags;
+			}
+			open_v8.mode_of_operation = path;
+			open_v8.endpoint_id_1 = tmp_port;
+			open_v8.endpoint_id_2 = 0xFFFF;
+			open_v8.endpoint_id_3 = 0xFFFF;
+
+
+			open_v8.topology_id = topology;
+			open_v8.reserved = 0;
+
+			/* variable endpoint payload */
+			ep1_payload.dev_num_channel = channel_mode & 0x00FF;
+			ep1_payload.bit_width = bit_width;
+			ep1_payload.sample_rate  = rate;
+			ret = adm_arrange_mch_map_v8(&ep1_payload, path,
+					channel_mode);
+			if (ret)
+				return ret;
+
+			pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
+				__func__, open_v8.endpoint_id_1,
+				open_v8.endpoint_id_2,
+				open_v8.endpoint_id_3,
+				open_v8.topology_id,
+				open_v8.flags,
+				this_adm.num_ec_ref_rx_chans);
+
+			ep1_payload_size = 8 +
+				roundup(ep1_payload.dev_num_channel, 4);
+			param_size = sizeof(struct adm_cmd_device_open_v8)
+				+ ep1_payload_size;
+			atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
+
+			if ((this_adm.num_ec_ref_rx_chans != 0)
+				&& (path != ADM_PATH_PLAYBACK)
+				&& (open_v8.endpoint_id_2 != 0xFFFF)) {
+				open_v8.endpoint_id_2 = this_adm.ec_ref_rx;
+				this_adm.ec_ref_rx = -1;
+				ep2_payload.dev_num_channel =
+					this_adm.num_ec_ref_rx_chans;
+				this_adm.num_ec_ref_rx_chans = 0;
+
+				if (this_adm.ec_ref_rx_bit_width != 0) {
+					ep2_payload.bit_width =
+						this_adm.ec_ref_rx_bit_width;
+					this_adm.ec_ref_rx_bit_width = 0;
+				} else {
+					ep2_payload.bit_width = bit_width;
+				}
+
+				if (this_adm.ec_ref_rx_sampling_rate != 0) {
+					ep2_payload.sample_rate =
 					this_adm.ec_ref_rx_sampling_rate;
-				this_adm.ec_ref_rx_sampling_rate = 0;
-			} else {
-				open_v6.sample_rate_eid2 = rate;
+					this_adm.ec_ref_rx_sampling_rate = 0;
+				} else {
+					ep2_payload.sample_rate = rate;
+				}
+
+				pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
+					__func__,
+					ep2_payload.dev_num_channel,
+					ep2_payload.bit_width,
+					ep2_payload.sample_rate);
+
+				ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
+					ep2_payload.dev_num_channel);
+
+				if (ret)
+					return ret;
+				ep2_payload_size = 8 +
+					roundup(ep2_payload.dev_num_channel, 4);
+				param_size += ep2_payload_size;
 			}
 
-			pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
-				__func__, open_v6.dev_num_channel_eid2,
-				open_v6.bit_width_eid2,
-				open_v6.sample_rate_eid2);
+			open_v8.hdr.pkt_size = param_size;
+			adm_params = kzalloc(param_size, GFP_KERNEL);
+			if (!adm_params)
+				return -ENOMEM;
+			memcpy(adm_params, &open_v8, sizeof(open_v8));
+			memcpy(adm_params + sizeof(open_v8),
+					(void *)&ep1_payload,
+					ep1_payload_size);
 
-			ret = adm_arrange_mch_ep2_map(&open_v6,
-				open_v6.dev_num_channel_eid2);
+			if ((this_adm.num_ec_ref_rx_chans != 0)
+				&& (path != ADM_PATH_PLAYBACK)
+				&& (open_v8.endpoint_id_2 != 0xFFFF)) {
+				memcpy(adm_params + sizeof(open_v8)
+						+ ep1_payload_size,
+						(void *)&ep2_payload,
+						ep2_payload_size);
+			}
+
+			ret = apr_send_pkt(this_adm.apr,
+					(uint32_t *)adm_params);
+			if (ret < 0) {
+				pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
+					__func__, tmp_port, port_id, ret);
+				return -EINVAL;
+			}
+			kfree(adm_params);
+		} else {
+
+			open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE),
+				APR_PKT_VER);
+			open.hdr.pkt_size = sizeof(open);
+			open.hdr.src_svc = APR_SVC_ADM;
+			open.hdr.src_domain = APR_DOMAIN_APPS;
+			open.hdr.src_port = tmp_port;
+			open.hdr.dest_svc = APR_SVC_ADM;
+			open.hdr.dest_domain = APR_DOMAIN_ADSP;
+			open.hdr.dest_port = tmp_port;
+			open.hdr.token = port_idx << 16 | copp_idx;
+			open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
+			open.flags = flags;
+			open.mode_of_operation = path;
+			open.endpoint_id_1 = tmp_port;
+			open.endpoint_id_2 = 0xFFFF;
+
+			if (this_adm.ec_ref_rx && (path != 1)) {
+				open.endpoint_id_2 = this_adm.ec_ref_rx;
+				this_adm.ec_ref_rx = -1;
+			}
+
+			open.topology_id = topology;
+
+			open.dev_num_channel = channel_mode & 0x00FF;
+			open.bit_width = bit_width;
+			WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
+				(rate != ULL_SUPPORTED_SAMPLE_RATE));
+			open.sample_rate  = rate;
+
+			ret = adm_arrange_mch_map(&open, path, channel_mode);
 
 			if (ret)
 				return ret;
 
-			ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open_v6);
-		} else {
-			ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+			pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
+				__func__, open.endpoint_id_1, open.sample_rate,
+				open.topology_id);
+
+			atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
+
+			if ((this_adm.num_ec_ref_rx_chans != 0) &&
+				(path != 1) && (open.endpoint_id_2 != 0xFFFF)) {
+				memset(&open_v6, 0,
+					sizeof(struct adm_cmd_device_open_v6));
+				memcpy(&open_v6, &open,
+					sizeof(struct adm_cmd_device_open_v5));
+				open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
+				open_v6.hdr.pkt_size = sizeof(open_v6);
+				open_v6.dev_num_channel_eid2 =
+					this_adm.num_ec_ref_rx_chans;
+				this_adm.num_ec_ref_rx_chans = 0;
+
+				if (this_adm.ec_ref_rx_bit_width != 0) {
+					open_v6.bit_width_eid2 =
+						this_adm.ec_ref_rx_bit_width;
+					this_adm.ec_ref_rx_bit_width = 0;
+				} else {
+					open_v6.bit_width_eid2 = bit_width;
+				}
+
+				if (this_adm.ec_ref_rx_sampling_rate != 0) {
+					open_v6.sample_rate_eid2 =
+					       this_adm.ec_ref_rx_sampling_rate;
+					this_adm.ec_ref_rx_sampling_rate = 0;
+				} else {
+					open_v6.sample_rate_eid2 = rate;
+				}
+
+				pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
+					__func__, open_v6.dev_num_channel_eid2,
+					open_v6.bit_width_eid2,
+					open_v6.sample_rate_eid2);
+
+				ret = adm_arrange_mch_ep2_map(&open_v6,
+					open_v6.dev_num_channel_eid2);
+
+				if (ret)
+					return ret;
+
+				ret = apr_send_pkt(this_adm.apr,
+					(uint32_t *)&open_v6);
+			} else {
+				ret = apr_send_pkt(this_adm.apr,
+					(uint32_t *)&open);
+			}
+			if (ret < 0) {
+				pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
+					__func__, tmp_port, port_id, ret);
+				return -EINVAL;
+			}
 		}
-		if (ret < 0) {
-			pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
-			__func__, tmp_port, port_id, ret);
-			return -EINVAL;
-		}
+
 		/* Wait for the callback with copp id */
 		ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
 			atomic_read(&this_adm.copp.stat
@@ -3081,6 +3460,22 @@
 EXPORT_SYMBOL(adm_ec_ref_rx_sampling_rate);
 
 /**
+ * adm_set_native_mode -
+ *      Set adm channel native mode.
+ *      If enabled matrix mixer will be
+ *      running in native mode for channel
+ *      configuration for this device session.
+ *
+ */
+void adm_set_native_mode(int mode)
+{
+	this_adm.native_mode = mode;
+	pr_debug("%s: enable native_mode :%d\n",
+		__func__, this_adm.native_mode);
+}
+EXPORT_SYMBOL(adm_set_native_mode);
+
+/**
  * adm_close -
  *        command to close ADM copp
  *
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 6697208..6f46a23 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -110,12 +110,9 @@
 		uint32_t token, uint32_t *payload, void *priv);
 	void *pri_spdif_tx_private_data;
 	void *sec_spdif_tx_private_data;
-	struct afe_port_mod_evt_rsp_hdr pri_spdif_evt_pl;
-	struct afe_event_fmt_update pri_spdif_fmt_event;
-	struct afe_port_mod_evt_rsp_hdr sec_spdif_evt_pl;
-	struct afe_event_fmt_update sec_spdif_fmt_event;
-	struct work_struct afe_pri_spdif_work;
-	struct work_struct afe_sec_spdif_work;
+	int pri_spdif_config_change;
+	int sec_spdif_config_change;
+	struct work_struct afe_spdif_work;
 
 	int	topology[AFE_MAX_PORTS];
 	struct cal_type_data *cal_data[MAX_AFE_CAL_TYPES];
@@ -387,107 +384,26 @@
 	return 0;
 }
 
-static const char *const afe_event_port_text[] = {
-	"PORT=Primary",
-	"PORT=Secondary",
-};
-
-static const char * const afe_event_state_text[] = {
-	"STATE=Inactive",
-	"STATE=Active",
-	"STATE=EOS",
-};
-
-static const char *const afe_event_rate_text[] = {
-	"RATE=32000",
-	"RATE=44100",
-	"RATE=48000",
-	"RATE=88200",
-	"RATE=96000",
-	"RATE=176400",
-	"RATE=192000",
-};
-
-static const char *const afe_event_format_text[] = {
-	"FORMAT=LPCM",
-	"FORMAT=Compr",
-};
-
-static void afe_notify_spdif_fmt_update_common(void *payload)
+static void afe_notify_spdif_fmt_update_work_fn(struct work_struct *work)
 {
 	int ret = 0;
-	char *env[6];
-	struct afe_port_mod_evt_rsp_hdr *evt_pl;
-	struct afe_event_fmt_update *fmt_event;
+	char event_pri[] = "PRI_SPDIF_TX=MEDIA_CONFIG_CHANGE";
+	char event_sec[] = "SEC_SPDIF_TX=MEDIA_CONFIG_CHANGE";
 
-	evt_pl = (struct afe_port_mod_evt_rsp_hdr *)payload;
-	fmt_event = (struct afe_event_fmt_update *)
-			(payload + sizeof(struct afe_port_mod_evt_rsp_hdr));
-
-	env[0] = "SPDIF_FMT_UPDATE=TRUE";
-	if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX)
-		env[1] = (char *)afe_event_port_text[0];
-	else
-		env[1] = (char *)afe_event_port_text[1];
-
-	switch (fmt_event->status) {
-	case AFE_PORT_STATUS_AUDIO_ACTIVE:
-		env[2] = (char *)afe_event_state_text[1];
-		break;
-	case AFE_PORT_STATUS_AUDIO_EOS:
-		env[2] = (char *)afe_event_state_text[2];
-		break;
-	default:
-		env[2] = (char *)afe_event_state_text[0];
+	if (this_afe.pri_spdif_config_change) {
+		this_afe.pri_spdif_config_change = 0;
+		ret = q6core_send_uevent(this_afe.uevent_data, event_pri);
+		if (ret)
+			pr_err("%s: Send UEvent %s failed :%d\n",
+			       __func__, event_pri, ret);
 	}
-
-	switch (fmt_event->sample_rate) {
-	case 32000:
-		env[3] = (char *)afe_event_rate_text[0];
-		break;
-	case 44100:
-		env[3] = (char *)afe_event_rate_text[1];
-		break;
-	case 48000:
-		env[3] = (char *)afe_event_rate_text[2];
-		break;
-	case 88200:
-		env[3] = (char *)afe_event_rate_text[3];
-		break;
-	case 96000:
-		env[3] = (char *)afe_event_rate_text[4];
-		break;
-	case 176400:
-		env[3] = (char *)afe_event_rate_text[5];
-		break;
-	case 192000:
-		env[3] = (char *)afe_event_rate_text[6];
-		break;
-	default:
-		env[3] = (char *)afe_event_rate_text[2];
+	if (this_afe.sec_spdif_config_change) {
+		this_afe.sec_spdif_config_change = 0;
+		ret = q6core_send_uevent(this_afe.uevent_data, event_sec);
+		if (ret)
+			pr_err("%s: Send UEvent %s failed :%d\n",
+			       __func__, event_sec, ret);
 	}
-
-	if (fmt_event->data_format == AFE_NON_LINEAR_DATA)
-		env[4] = (char *)afe_event_format_text[1];
-	else
-		env[4] = (char *)afe_event_format_text[0];
-
-	env[5] = NULL;
-
-	ret = q6core_send_uevent_env(this_afe.uevent_data, env);
-	if (ret)
-		pr_err("%s: Send UEvent %s failed: %d\n", __func__,
-			env[0], ret);
-}
-
-static void afe_notify_pri_spdif_fmt_update_work_fn(struct work_struct *work)
-{
-	afe_notify_spdif_fmt_update_common(&this_afe.pri_spdif_evt_pl);
-}
-
-static void afe_notify_sec_spdif_fmt_update_work_fn(struct work_struct *work)
-{
-	afe_notify_spdif_fmt_update_common(&this_afe.sec_spdif_evt_pl);
 }
 
 static void afe_notify_spdif_fmt_update(void *payload)
@@ -495,17 +411,12 @@
 	struct afe_port_mod_evt_rsp_hdr *evt_pl;
 
 	evt_pl = (struct afe_port_mod_evt_rsp_hdr *)payload;
-	if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) {
-		memcpy(&this_afe.pri_spdif_evt_pl, payload,
-			sizeof(struct afe_port_mod_evt_rsp_hdr) +
-			sizeof(struct afe_event_fmt_update));
-		schedule_work(&this_afe.afe_pri_spdif_work);
-	} else {
-		memcpy(&this_afe.sec_spdif_evt_pl, payload,
-			sizeof(struct afe_port_mod_evt_rsp_hdr) +
-			sizeof(struct afe_event_fmt_update));
-		schedule_work(&this_afe.afe_sec_spdif_work);
-	}
+	if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX)
+		this_afe.pri_spdif_config_change = 1;
+	else
+		this_afe.sec_spdif_config_change = 1;
+
+	schedule_work(&this_afe.afe_spdif_work);
 }
 
 static int32_t afe_callback(struct apr_client_data *data, void *priv)
@@ -3274,8 +3185,22 @@
 			this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
 	}
 
-	/* Also send the topology id here: */
 	port_index = afe_get_port_index(port_id);
+
+	if (q6core_get_avcs_api_version_per_service(
+		APRV2_IDS_SERVICE_ID_ADSP_AFE_V) >= AFE_API_VERSION_V4) {
+		/* send VAD configuration if enabled */
+		if (this_afe.vad_cfg[port_index].is_enable) {
+			ret = afe_send_port_vad_cfg_params(port_id);
+			if (ret) {
+				pr_err("%s: afe send VAD config failed %d\n",
+					__func__, ret);
+				goto fail_cmd;
+			}
+		}
+	}
+
+	/* Also send the topology id here: */
 	if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
 		/* One time call: only for first time */
 		afe_send_custom_topology();
@@ -8163,10 +8088,8 @@
 	q6core_init_uevent_data(this_afe.uevent_data, "q6afe_uevent");
 
 	INIT_WORK(&this_afe.afe_dc_work, afe_notify_dc_presence_work_fn);
-	INIT_WORK(&this_afe.afe_pri_spdif_work,
-		  afe_notify_pri_spdif_fmt_update_work_fn);
-	INIT_WORK(&this_afe.afe_sec_spdif_work,
-		  afe_notify_sec_spdif_fmt_update_work_fn);
+	INIT_WORK(&this_afe.afe_spdif_work,
+		  afe_notify_spdif_fmt_update_work_fn);
 
 	this_afe.event_notifier.notifier_call  = afe_aud_event_notify;
 	msm_aud_evt_blocking_register_client(&this_afe.event_notifier);
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 74fd1cf..7a8b941 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -40,6 +40,7 @@
 #include <dsp/q6asm-v2.h>
 #include <dsp/q6audio-v2.h>
 #include <dsp/q6common.h>
+#include <dsp/q6core.h>
 #include "adsp_err.h"
 
 #define TRUE        0x01
@@ -228,6 +229,9 @@
 	uint32_t pcm_format_id;
 
 	switch (media_format_block_ver) {
+	case PCM_MEDIA_FORMAT_V5:
+		pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V5;
+		break;
 	case PCM_MEDIA_FORMAT_V4:
 		pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4;
 		break;
@@ -3144,6 +3148,25 @@
 }
 EXPORT_SYMBOL(q6asm_open_read_v4);
 
+
+/*
+ * asm_open_read_v5 - Opens audio capture session
+ *
+ * @ac: Client session handle
+ * @format: encoder format
+ * @bits_per_sample: bit width of capture session
+ * @ts_mode: timestamp mode
+ */
+int q6asm_open_read_v5(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample, bool ts_mode, uint32_t enc_cfg_id)
+{
+	return __q6asm_open_read(ac, format, bits_per_sample,
+				 PCM_MEDIA_FORMAT_V5 /*media fmt block ver*/,
+				 ts_mode, enc_cfg_id);
+}
+EXPORT_SYMBOL(q6asm_open_read_v5);
+
+
 /**
  * q6asm_open_write_compressed -
  *       command to open ASM in compressed write mode
@@ -3492,6 +3515,23 @@
 EXPORT_SYMBOL(q6asm_stream_open_write_v3);
 
 /*
+ * q6asm_open_write_v5 - Opens audio playback session
+ *
+ * @ac: Client session handle
+ * @format: decoder format
+ * @bits_per_sample: bit width of playback session
+ */
+int q6asm_open_write_v5(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample)
+{
+	return __q6asm_open_write(ac, format, bits_per_sample,
+				  ac->stream_id, false /*gapless*/,
+				  PCM_MEDIA_FORMAT_V5 /*pcm_format_block_ver*/);
+}
+EXPORT_SYMBOL(q6asm_open_write_v5);
+
+
+/*
  * q6asm_stream_open_write_v4 - Creates audio stream for playback
  *
  * @ac: Client session handle
@@ -3510,6 +3550,26 @@
 }
 EXPORT_SYMBOL(q6asm_stream_open_write_v4);
 
+/*
+ * q6asm_stream_open_write_v5 - Creates audio stream for playback
+ *
+ * @ac: Client session handle
+ * @format: asm playback format
+ * @bits_per_sample: bit width of requested stream
+ * @stream_id: stream id of stream to be associated with this session
+ * @is_gapless_mode: true if gapless mode needs to be enabled
+ */
+int q6asm_stream_open_write_v5(struct audio_client *ac, uint32_t format,
+			       uint16_t bits_per_sample, int32_t stream_id,
+			       bool is_gapless_mode)
+{
+	return __q6asm_open_write(ac, format, bits_per_sample,
+				  stream_id, is_gapless_mode,
+				  PCM_MEDIA_FORMAT_V5 /*pcm_format_block_ver*/);
+}
+EXPORT_SYMBOL(q6asm_stream_open_write_v5);
+
+
 static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
 				   uint32_t wr_format, bool is_meta_data_mode,
 				   uint32_t bits_per_sample,
@@ -4748,6 +4808,108 @@
 EXPORT_SYMBOL(q6asm_set_encdec_chan_map);
 
 /*
+ * q6asm_enc_cfg_blk_pcm_v5 - sends encoder configuration parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @use_default_chmap: true if default channel map  to be used
+ * @use_back_flavor: to configure back left and right channel
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ * @endianness: endianness of the pcm data
+ * @mode: Mode to provide additional info about the pcm input data
+ */
+static int q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac,
+			     uint32_t rate, uint32_t channels,
+			     uint16_t bits_per_sample, bool use_default_chmap,
+			     bool use_back_flavor, u8 *channel_map,
+			     uint16_t sample_word_size, uint16_t endianness,
+			     uint16_t mode)
+{
+	struct asm_multi_channel_pcm_enc_cfg_v5 enc_cfg;
+	struct asm_enc_cfg_blk_param_v2 enc_fg_blk;
+	u8 *channel_mapping;
+	u32 frames_per_buf = 0;
+	int rc;
+
+	if (!use_default_chmap && (channel_map == NULL)) {
+		pr_err("%s: No valid chan map and can't use default\n",
+				__func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
+	pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+		 ac->session, rate, channels,
+		 bits_per_sample, sample_word_size);
+
+	memset(&enc_cfg, 0, sizeof(enc_cfg));
+	q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+	atomic_set(&ac->cmd_state, -1);
+	enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+	enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
+	enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
+				    sizeof(enc_cfg.encdec);
+	enc_cfg.encblk.frames_per_buf = frames_per_buf;
+	enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
+					  sizeof(enc_fg_blk);
+	enc_cfg.num_channels = channels;
+	enc_cfg.bits_per_sample = bits_per_sample;
+	enc_cfg.sample_rate = rate;
+	enc_cfg.is_signed = 1;
+	enc_cfg.sample_word_size = sample_word_size;
+	enc_cfg.endianness = endianness;
+	enc_cfg.mode = mode;
+	channel_mapping = enc_cfg.channel_mapping;
+
+	memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+
+	if (use_default_chmap) {
+		pr_debug("%s: setting default channel map for %d channels",
+			 __func__, channels);
+		if (q6asm_map_channels(channel_mapping, channels,
+					use_back_flavor)) {
+			pr_err("%s: map channels failed %d\n",
+			       __func__, channels);
+			rc = -EINVAL;
+			goto fail_cmd;
+		}
+	} else {
+		pr_debug("%s: Using pre-defined channel map", __func__);
+		memcpy(channel_mapping, channel_map,
+			PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+	}
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+	if (rc < 0) {
+		pr_err("%s: Command open failed %d\n", __func__, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s: timeout opcode[0x%x]\n",
+		       __func__, enc_cfg.hdr.opcode);
+		rc = -ETIMEDOUT;
+		goto fail_cmd;
+	}
+	if (atomic_read(&ac->cmd_state) > 0) {
+		pr_err("%s: DSP returned error[%s]\n",
+		       __func__, adsp_err_get_err_str(
+		       atomic_read(&ac->cmd_state)));
+		rc = adsp_err_get_lnx_err_code(
+				atomic_read(&ac->cmd_state));
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return rc;
+}
+EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v5);
+
+/*
  * q6asm_enc_cfg_blk_pcm_v4 - sends encoder configuration parameters
  *
  * @ac: Client session handle
@@ -5040,6 +5202,18 @@
 }
 EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v2);
 
+static int __q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac,
+				      uint32_t rate, uint32_t channels,
+				      uint16_t bits_per_sample,
+				      uint16_t sample_word_size,
+				      uint16_t endianness,
+				      uint16_t mode)
+{
+	return q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
+					bits_per_sample, true, false, NULL,
+					sample_word_size, endianness, mode);
+}
+
 static int __q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac,
 				      uint32_t rate, uint32_t channels,
 				      uint16_t bits_per_sample,
@@ -5137,6 +5311,31 @@
 }
 EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4);
 
+/*
+ * q6asm_enc_cfg_blk_pcm_format_support_v5 - sends encoder configuration
+ *                                           parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ * @endianness: endianness of the pcm data
+ * @mode: Mode to provide additional info about the pcm input data
+ */
+int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
+					    uint32_t rate, uint32_t channels,
+					    uint16_t bits_per_sample,
+					    uint16_t sample_word_size,
+					    uint16_t endianness,
+					    uint16_t mode)
+{
+	 return __q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
+					   bits_per_sample, sample_word_size,
+					   endianness, mode);
+}
+
+EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v5);
 /**
  * q6asm_enc_cfg_blk_pcm_native -
  *       command to set encode config block for pcm_native
@@ -5274,6 +5473,44 @@
 		lchannel_mapping[5] = PCM_CHANNEL_RB;
 		lchannel_mapping[6] = PCM_CHANNEL_LS;
 		lchannel_mapping[7] = PCM_CHANNEL_RS;
+	} else if (channels == 12) {
+		/*
+		 * Configured for 7.1.4 channel mapping
+		 * Todo: Needs to be checked
+		 */
+		lchannel_mapping[0] = PCM_CHANNEL_FL;
+		lchannel_mapping[1] = PCM_CHANNEL_FR;
+		lchannel_mapping[2] = PCM_CHANNEL_FC;
+		lchannel_mapping[3] = PCM_CHANNEL_LFE;
+		lchannel_mapping[4] = PCM_CHANNEL_LB;
+		lchannel_mapping[5] = PCM_CHANNEL_RB;
+		lchannel_mapping[6] = PCM_CHANNEL_LS;
+		lchannel_mapping[7] = PCM_CHANNEL_RS;
+		lchannel_mapping[8] = PCM_CHANNEL_TFL;
+		lchannel_mapping[9] = PCM_CHANNEL_TFR;
+		lchannel_mapping[10] = PCM_CHANNEL_TSL;
+		lchannel_mapping[11] = PCM_CHANNEL_TSR;
+	} else if (channels == 16) {
+		/*
+		 * Configured for 7.1.8 channel mapping
+		 * Todo: Needs to be checked
+		 */
+		lchannel_mapping[0] = PCM_CHANNEL_FL;
+		lchannel_mapping[1] = PCM_CHANNEL_FR;
+		lchannel_mapping[2] = PCM_CHANNEL_FC;
+		lchannel_mapping[3] = PCM_CHANNEL_LFE;
+		lchannel_mapping[4] = PCM_CHANNEL_LB;
+		lchannel_mapping[5] = PCM_CHANNEL_RB;
+		lchannel_mapping[6] = PCM_CHANNEL_LS;
+		lchannel_mapping[7] = PCM_CHANNEL_RS;
+		lchannel_mapping[8] = PCM_CHANNEL_TFL;
+		lchannel_mapping[9] = PCM_CHANNEL_TFR;
+		lchannel_mapping[10] = PCM_CHANNEL_TSL;
+		lchannel_mapping[11] = PCM_CHANNEL_TSR;
+		lchannel_mapping[12] = PCM_CHANNEL_FLC;
+		lchannel_mapping[13] = PCM_CHANNEL_FRC;
+		lchannel_mapping[14] = PCM_CHANNEL_RLC;
+		lchannel_mapping[15] = PCM_CHANNEL_RRC;
 	} else {
 		pr_err("%s: ERROR.unsupported num_ch = %u\n",
 		 __func__, channels);
@@ -5953,6 +6190,92 @@
 	return rc;
 }
 
+
+static int __q6asm_media_format_block_pcm_v5(struct audio_client *ac,
+					     uint32_t rate, uint32_t channels,
+					     uint16_t bits_per_sample,
+					     int stream_id,
+					     bool use_default_chmap,
+					     char *channel_map,
+					     uint16_t sample_word_size,
+					     uint16_t endianness,
+					     uint16_t mode)
+{
+	struct asm_multi_channel_pcm_fmt_blk_param_v5 fmt;
+	u8 *channel_mapping;
+	int rc;
+
+	pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+		 ac->session, rate, channels,
+		 bits_per_sample, sample_word_size);
+
+	memset(&fmt, 0, sizeof(fmt));
+	q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
+	atomic_set(&ac->cmd_state, -1);
+	/*
+	 * Updated the token field with stream/session for compressed playback
+	 * Platform driver must know the the stream with which the command is
+	 * associated
+	 */
+	if (ac->io_mode & COMPRESSED_STREAM_IO)
+		fmt.hdr.token = ((ac->session << 8) & 0xFFFF00) |
+				(stream_id & 0xFF);
+
+	pr_debug("%s: token = 0x%x, stream_id  %d, session 0x%x\n",
+		 __func__, fmt.hdr.token, stream_id, ac->session);
+
+	fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+	fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+					sizeof(fmt.fmt_blk);
+	fmt.param.num_channels = (uint16_t) channels & 0xFFFF;
+	fmt.param.bits_per_sample = bits_per_sample;
+	fmt.param.sample_rate = rate;
+	fmt.param.is_signed = 1;
+	fmt.param.sample_word_size = sample_word_size;
+	fmt.param.endianness = endianness;
+	fmt.param.mode = mode;
+	channel_mapping = fmt.param.channel_mapping;
+
+	memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+
+	if (use_default_chmap) {
+		if (q6asm_map_channels(channel_mapping, fmt.param.num_channels, false)) {
+			pr_err("%s: map channels failed %d\n",
+			       __func__, channels);
+			rc = -EINVAL;
+			goto fail_cmd;
+		}
+	} else {
+		memcpy(channel_mapping, channel_map,
+			 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+	}
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+	if (rc < 0) {
+		pr_err("%s: Comamnd open failed %d\n", __func__, rc);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s: timeout. waited for format update\n", __func__);
+		rc = -ETIMEDOUT;
+		goto fail_cmd;
+	}
+	if (atomic_read(&ac->cmd_state) > 0) {
+		pr_err("%s: DSP returned error[%s]\n",
+			__func__, adsp_err_get_err_str(
+			atomic_read(&ac->cmd_state)));
+		rc = adsp_err_get_lnx_err_code(
+				atomic_read(&ac->cmd_state));
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return rc;
+}
+
 /**
  * q6asm_media_format_block_pcm -
  *       command to set mediafmt block for PCM on ASM stream
@@ -6084,6 +6407,47 @@
 EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v4);
 
 
+/*
+ * q6asm_media_format_block_pcm_format_support_v5- sends pcm decoder
+ *						    configuration parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @stream_id: stream id of stream to be associated with this session
+ * @use_default_chmap: true if default channel map  to be used
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ * @endianness: endianness of the pcm data
+ * @mode: Mode to provide additional info about the pcm input data
+ */
+int q6asm_media_format_block_pcm_format_support_v5(struct audio_client *ac,
+						   uint32_t rate,
+						   uint32_t channels,
+						   uint16_t bits_per_sample,
+						   int stream_id,
+						   bool use_default_chmap,
+						   char *channel_map,
+						   uint16_t sample_word_size,
+						   uint16_t endianness,
+						   uint16_t mode)
+{
+	if (!use_default_chmap && (channel_map == NULL)) {
+		pr_err("%s: No valid chan map and can't use default\n",
+			__func__);
+		return -EINVAL;
+	}
+	return __q6asm_media_format_block_pcm_v5(ac, rate,
+				channels, bits_per_sample, stream_id,
+				use_default_chmap, channel_map,
+				sample_word_size, endianness,
+				mode);
+
+}
+EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v5);
+
+
 static int __q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
 				uint32_t rate, uint32_t channels,
 				bool use_default_chmap, char *channel_map,
@@ -6290,6 +6654,79 @@
 	return rc;
 }
 
+static int __q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac,
+						      uint32_t rate,
+						      uint32_t channels,
+						      bool use_default_chmap,
+						      char *channel_map,
+						      uint16_t bits_per_sample,
+						      uint16_t sample_word_size,
+						      uint16_t endianness,
+						      uint16_t mode)
+{
+	struct asm_multi_channel_pcm_fmt_blk_param_v5 fmt;
+	u8 *channel_mapping;
+	int rc;
+
+	pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+		 ac->session, rate, channels,
+		 bits_per_sample, sample_word_size);
+
+	memset(&fmt, 0, sizeof(fmt));
+	q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+	atomic_set(&ac->cmd_state, -1);
+
+	fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+	fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+					sizeof(fmt.fmt_blk);
+	fmt.param.num_channels = channels;
+	fmt.param.bits_per_sample = bits_per_sample;
+	fmt.param.sample_rate = rate;
+	fmt.param.is_signed = 1;
+	fmt.param.sample_word_size = sample_word_size;
+	fmt.param.endianness = endianness;
+	fmt.param.mode = mode;
+	channel_mapping = fmt.param.channel_mapping;
+
+	memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+
+	if (use_default_chmap) {
+		if (q6asm_map_channels(channel_mapping, channels, false)) {
+			pr_err("%s: map channels failed %d\n",
+			       __func__, channels);
+			rc = -EINVAL;
+			goto fail_cmd;
+		}
+	} else {
+		memcpy(channel_mapping, channel_map,
+			 PCM_FORMAT_MAX_NUM_CHANNEL_V8);
+	}
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+	if (rc < 0) {
+		pr_err("%s: Comamnd open failed %d\n", __func__, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s: timeout. waited for format update\n", __func__);
+		rc = -ETIMEDOUT;
+		goto fail_cmd;
+	}
+	if (atomic_read(&ac->cmd_state) > 0) {
+		pr_err("%s: DSP returned error[%s]\n",
+		       __func__, adsp_err_get_err_str(
+		       atomic_read(&ac->cmd_state)));
+		rc = adsp_err_get_lnx_err_code(
+				atomic_read(&ac->cmd_state));
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return rc;
+}
+
 int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
 		uint32_t rate, uint32_t channels,
 		bool use_default_chmap, char *channel_map)
@@ -6369,6 +6806,41 @@
 }
 EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4);
 
+
+/*
+ * q6asm_media_format_block_multi_ch_pcm_v5 - sends pcm decoder configuration
+ *                                            parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @use_default_chmap: true if default channel map  to be used
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ * @endianness: endianness of the pcm data
+ * @mode: Mode to provide additional info about the pcm input data
+ */
+int q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac,
+					     uint32_t rate, uint32_t channels,
+					     bool use_default_chmap,
+					     char *channel_map,
+					     uint16_t bits_per_sample,
+					     uint16_t sample_word_size,
+					     uint16_t endianness,
+					     uint16_t mode)
+{
+	return __q6asm_media_format_block_multi_ch_pcm_v5(ac, rate, channels,
+							  use_default_chmap,
+							  channel_map,
+							  bits_per_sample,
+							  sample_word_size,
+							  endianness,
+							  mode);
+}
+EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v5);
+
+
 /*
  * q6asm_media_format_block_gen_compr - set up generic compress format params
  *
diff --git a/dsp/q6core.c b/dsp/q6core.c
index 5160c3d..cf84193 100644
--- a/dsp/q6core.c
+++ b/dsp/q6core.c
@@ -193,23 +193,6 @@
 }
 EXPORT_SYMBOL(q6core_send_uevent);
 
-/**
- * q6core_send_uevent_env - send uevent with list of keys to userspace.
- *
- * @uevent_data: uevent data.
- * @event: array of event keys to send.
- *
- * Returns 0 on success or error otherwise.
- */
-int q6core_send_uevent_env(struct audio_uevent_data *uevent_data, char *env[])
-{
-	if (!env || !uevent_data)
-		return -EINVAL;
-
-	return kobject_uevent_env(&uevent_data->kobj, KOBJ_CHANGE, env);
-}
-EXPORT_SYMBOL(q6core_send_uevent_env);
-
 static int parse_fwk_version_info(uint32_t *payload)
 {
 	size_t ver_size;
diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h
index eafd2ad..bf3d0f0 100644
--- a/include/dsp/q6adm-v2.h
+++ b/include/dsp/q6adm-v2.h
@@ -57,7 +57,9 @@
 };
 
 #define MAX_COPPS_PER_PORT 0x8
-#define ADM_MAX_CHANNELS 8
+#define ADM_MAX_CHANNELS 32
+
+#define ADSP_ADM_API_VERSION_V3 3
 
 /* multiple copp per stream. */
 struct route_payload {
@@ -208,4 +210,5 @@
 			int channel_index);
 void msm_dts_srs_acquire_lock(void);
 void msm_dts_srs_release_lock(void);
+void adm_set_native_mode(int mode);
 #endif /* __Q6_ADM_V2_H__ */
diff --git a/include/dsp/q6asm-v2.h b/include/dsp/q6asm-v2.h
index 5fa03be..2d738d6 100644
--- a/include/dsp/q6asm-v2.h
+++ b/include/dsp/q6asm-v2.h
@@ -112,11 +112,14 @@
 #define ASM_LITTLE_ENDIAN 0
 #define ASM_BIG_ENDIAN 1
 
+#define ADSP_ASM_API_VERSION_V2   2
+
 /* PCM_MEDIA_FORMAT_Version */
 enum {
 	PCM_MEDIA_FORMAT_V2 = 0,
 	PCM_MEDIA_FORMAT_V3,
 	PCM_MEDIA_FORMAT_V4,
+	PCM_MEDIA_FORMAT_V5,
 };
 
 /* PCM format modes in DSP */
@@ -296,6 +299,10 @@
 		       uint16_t bits_per_sample, bool ts_mode,
 			   uint32_t enc_cfg_id);
 
+int q6asm_open_read_v5(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample, bool ts_mode,
+			uint32_t enc_cfg_id);
+
 int q6asm_open_write(struct audio_client *ac, uint32_t format
 		/*, uint16_t bits_per_sample*/);
 
@@ -312,6 +319,9 @@
 int q6asm_open_write_v4(struct audio_client *ac, uint32_t format,
 			uint16_t bits_per_sample);
 
+int q6asm_open_write_v5(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample);
+
 int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
 			       uint16_t bits_per_sample, int32_t stream_id,
 			       bool is_gapless_mode);
@@ -324,6 +334,10 @@
 			       uint16_t bits_per_sample, int32_t stream_id,
 			       bool is_gapless_mode);
 
+int q6asm_stream_open_write_v5(struct audio_client *ac, uint32_t format,
+			       uint16_t bits_per_sample, int32_t stream_id,
+			       bool is_gapless_mode);
+
 int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format,
 				uint32_t passthrough_flag);
 
@@ -462,6 +476,13 @@
 					    uint16_t endianness,
 					    uint16_t mode);
 
+int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
+					uint32_t rate, uint32_t channels,
+					uint16_t bits_per_sample,
+					uint16_t sample_word_size,
+					uint16_t endianness,
+					uint16_t mode);
+
 int q6asm_enc_cfg_blk_custom(struct audio_client *ac,
 			uint32_t sample_rate, uint32_t channels,
 			uint32_t format, void *cfg);
@@ -526,6 +547,17 @@
 						   uint16_t endianness,
 						   uint16_t mode);
 
+int q6asm_media_format_block_pcm_format_support_v5(struct audio_client *ac,
+		   uint32_t rate,
+		   uint32_t channels,
+		   uint16_t bits_per_sample,
+		   int stream_id,
+		   bool use_default_chmap,
+		   char *channel_map,
+		   uint16_t sample_word_size,
+		   uint16_t endianness,
+		   uint16_t mode);
+
 int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
 			uint32_t rate, uint32_t channels,
 			bool use_default_chmap, char *channel_map);
@@ -561,6 +593,15 @@
 					     uint16_t endianness,
 					     uint16_t mode);
 
+int q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac,
+					     uint32_t rate, uint32_t channels,
+					     bool use_default_chmap,
+					     char *channel_map,
+					     uint16_t bits_per_sample,
+					     uint16_t sample_word_size,
+					     uint16_t endianness,
+					     uint16_t mode);
+
 int q6asm_media_format_block_aac(struct audio_client *ac,
 			struct asm_aac_cfg *cfg);
 
diff --git a/include/dsp/q6core.h b/include/dsp/q6core.h
index 4d5a973..55d7dbc 100644
--- a/include/dsp/q6core.h
+++ b/include/dsp/q6core.h
@@ -35,7 +35,6 @@
 int q6core_init_uevent_data(struct audio_uevent_data *uevent_data, char *name);
 void q6core_destroy_uevent_data(struct audio_uevent_data *uevent_data);
 int q6core_send_uevent(struct audio_uevent_data *uevent_data, char *name);
-int q6core_send_uevent_env(struct audio_uevent_data *uevent_data, char *env[]);
 int q6core_get_avcs_api_version_per_service(uint32_t service_id);
 
 #define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919
@@ -208,4 +207,17 @@
 
 int32_t q6core_load_unload_topo_modules(uint32_t topology_id,
 			bool preload_type);
+
+#if IS_ENABLED(CONFIG_USE_Q6_32CH_SUPPORT)
+static inline bool q6core_use_Q6_32ch_support(void)
+{
+	return true;
+}
+#else
+static inline bool q6core_use_Q6_32ch_support(void)
+{
+	return false;
+}
+#endif
+
 #endif /* __Q6CORE_H__ */