Merge "asoc: dsp: Add support for adaptive bitrate"
diff --git a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
index c0aa424..77981dd 100644
--- a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -87,6 +87,9 @@
 
 static char on_demand_supply_name[][MAX_ON_DEMAND_SUPPLY_NAME_LENGTH] = {
 	"cdc-vdd-mic-bias",
+	"",
+	"cdc-vdda18-l10",
+	"cdc-vdd-l1",
 };
 
 static struct wcd_mbhc_register
@@ -3448,6 +3451,16 @@
 		msm_anlg_cdc_codec_enable_on_demand_supply,
 		SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("VDDA18_L10_REGULATOR", SND_SOC_NOPM,
+		ON_DEMAND_VDDA18_L10, 0,
+		msm_anlg_cdc_codec_enable_on_demand_supply,
+		SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("VDD_L1_REGULATOR", SND_SOC_NOPM,
+		ON_DEMAND_VDD_L1, 0,
+		msm_anlg_cdc_codec_enable_on_demand_supply,
+		SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS Internal1",
 		MSM89XX_PMIC_ANALOG_MICB_1_EN, 7, 0,
@@ -4137,6 +4150,20 @@
 	atomic_set(&sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS].ref,
 		   0);
 
+	msm_anlg_cdc_update_micbias_regulator(
+				sdm660_cdc,
+				on_demand_supply_name[ON_DEMAND_VDD_L1],
+				&sdm660_cdc->on_demand_list[ON_DEMAND_VDD_L1]);
+	atomic_set(&sdm660_cdc->on_demand_list[ON_DEMAND_VDD_L1].ref,
+		   0);
+
+	msm_anlg_cdc_update_micbias_regulator(
+			sdm660_cdc,
+			on_demand_supply_name[ON_DEMAND_VDDA18_L10],
+			&sdm660_cdc->on_demand_list[ON_DEMAND_VDDA18_L10]);
+	atomic_set(&sdm660_cdc->on_demand_list[ON_DEMAND_VDDA18_L10].ref,
+		   0);
+
 	sdm660_cdc->fw_data = devm_kzalloc(codec->dev,
 					sizeof(*(sdm660_cdc->fw_data)),
 					GFP_KERNEL);
@@ -4183,6 +4210,13 @@
 	sdm660_cdc_priv->on_demand_list[ON_DEMAND_MICBIAS].supply = NULL;
 	atomic_set(&sdm660_cdc_priv->on_demand_list[ON_DEMAND_MICBIAS].ref,
 		   0);
+	sdm660_cdc_priv->on_demand_list[ON_DEMAND_VDD_L1].supply = NULL;
+	atomic_set(&sdm660_cdc_priv->on_demand_list[ON_DEMAND_VDD_L1].ref,
+		   0);
+	sdm660_cdc_priv->on_demand_list[ON_DEMAND_VDDA18_L10].supply = NULL;
+	atomic_set(&sdm660_cdc_priv->on_demand_list[ON_DEMAND_VDDA18_L10].ref,
+		   0);
+
 	wcd_mbhc_deinit(&sdm660_cdc_priv->mbhc);
 
 	return 0;
diff --git a/asoc/codecs/sdm660_cdc/msm-analog-cdc.h b/asoc/codecs/sdm660_cdc/msm-analog-cdc.h
index bf69cd0..a44b48e 100644
--- a/asoc/codecs/sdm660_cdc/msm-analog-cdc.h
+++ b/asoc/codecs/sdm660_cdc/msm-analog-cdc.h
@@ -121,6 +121,8 @@
 enum {
 	ON_DEMAND_MICBIAS = 0,
 	ON_DEMAND_SPKDRV,
+	ON_DEMAND_VDDA18_L10,
+	ON_DEMAND_VDD_L1,
 	ON_DEMAND_SUPPLIES_MAX,
 };
 
diff --git a/asoc/codecs/sdm660_cdc/msm-digital-cdc.c b/asoc/codecs/sdm660_cdc/msm-digital-cdc.c
index f1f1ed4..8519e67 100644
--- a/asoc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/asoc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -1391,7 +1391,21 @@
 	atomic_set(&msm_dig_cdc->on_demand_list[ON_DEMAND_DIGITAL].ref, 0);
 
 	registered_digcodec = codec;
+	if (msm_dig_cdc->no_analog_codec) {
+		msm_dig_cdc->fw_data = devm_kzalloc(codec->dev,
+					    sizeof(*(msm_dig_cdc->fw_data)),
+					    GFP_KERNEL);
+		if (!msm_dig_cdc->fw_data)
+			return -ENOMEM;
 
+		ret = wcd_cal_create_hwdep(msm_dig_cdc->fw_data,
+			WCD9XXX_CODEC_HWDEP_NODE, codec);
+		if (ret < 0) {
+			dev_err(codec->dev, "%s hwdep failed %d\n", __func__,
+				ret);
+			return ret;
+		}
+	}
 	snd_soc_dapm_ignore_suspend(dapm, "AIF1 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "AIF1 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "ADC1_IN");
@@ -2469,7 +2483,6 @@
 	u32 dig_cdc_addr;
 	struct msm_dig_priv *msm_dig_cdc;
 	struct dig_ctrl_platform_data *pdata = NULL;
-	bool no_analog_codec = false;
 	int adsp_state;
 
 	adsp_state = apr_get_subsys_state();
@@ -2491,10 +2504,11 @@
 		return -EINVAL;
 
 	if (pdev->dev.of_node)
-		no_analog_codec = of_property_read_bool(pdev->dev.of_node,
+		msm_dig_cdc->no_analog_codec = of_property_read_bool(
+					pdev->dev.of_node,
 					"qcom,no-analog-codec");
 
-	if (no_analog_codec) {
+	if (msm_dig_cdc->no_analog_codec) {
 		dev_dbg(&pdev->dev, "%s:Platform data from device tree\n",
 				__func__);
 		if (msm_digital_cdc_populate_dt_pdata(&pdev->dev,
@@ -2549,7 +2563,7 @@
 			__func__, dig_cdc_addr);
 	return ret;
 err_supplies:
-	if (no_analog_codec)
+	if (msm_dig_cdc->no_analog_codec)
 		msm_digital_cdc_disable_supplies(msm_dig_cdc);
 rtn:
 	return ret;
diff --git a/asoc/codecs/sdm660_cdc/msm-digital-cdc.h b/asoc/codecs/sdm660_cdc/msm-digital-cdc.h
index a841a09..f230cac 100644
--- a/asoc/codecs/sdm660_cdc/msm-digital-cdc.h
+++ b/asoc/codecs/sdm660_cdc/msm-digital-cdc.h
@@ -73,6 +73,9 @@
 	s32 dmic_3_4_clk_cnt;
 	bool dec_active[NUM_DECIMATORS];
 	int version;
+	/* cal info for codec */
+	struct fw_info *fw_data;
+	bool no_analog_codec;
 	/* Entry for version info */
 	struct snd_info_entry *entry;
 	struct snd_info_entry *version_entry;
diff --git a/asoc/codecs/wcd-dsp-mgr.c b/asoc/codecs/wcd-dsp-mgr.c
index cde9851..b0e5315 100644
--- a/asoc/codecs/wcd-dsp-mgr.c
+++ b/asoc/codecs/wcd-dsp-mgr.c
@@ -802,6 +802,7 @@
 		__wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_WDSP_READY);
 		wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_PRE_SHUTDOWN,
 					     NULL);
+		reinit_completion(&wdsp->ready_compl);
 		schedule_work(&wdsp->ssr_work);
 		break;
 
@@ -818,7 +819,7 @@
 						     WDSP_EVENT_PRE_SHUTDOWN,
 						     NULL);
 		}
-
+		reinit_completion(&wdsp->ready_compl);
 		schedule_work(&wdsp->ssr_work);
 		break;
 
diff --git a/asoc/codecs/wcd9335.c b/asoc/codecs/wcd9335.c
index ffe52e5..d8c4ca0 100644
--- a/asoc/codecs/wcd9335.c
+++ b/asoc/codecs/wcd9335.c
@@ -2372,9 +2372,9 @@
 	mutex_lock(&tasha_p->codec_mutex);
 
 	if (tasha_p->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
-		if (dai_id != AIF1_CAP) {
-			dev_err(codec->dev, "%s: invalid AIF for Slimbus mode\n",
-				__func__);
+		if (dai_id >= ARRAY_SIZE(vport_slim_check_table)) {
+			dev_err(codec->dev, "%s: dai_id: %d, out of bounds\n",
+				__func__, dai_id);
 			mutex_unlock(&tasha_p->codec_mutex);
 			return -EINVAL;
 		}
diff --git a/asoc/codecs/wcd934x/wcd934x-dsp-cntl.c b/asoc/codecs/wcd934x/wcd934x-dsp-cntl.c
index 662f484..de4f399 100644
--- a/asoc/codecs/wcd934x/wcd934x-dsp-cntl.c
+++ b/asoc/codecs/wcd934x/wcd934x-dsp-cntl.c
@@ -1011,10 +1011,12 @@
 {
 	struct wcd_dsp_cntl *cntl = container_of(filep->private_data,
 						 struct wcd_dsp_cntl, miscdev);
-	char val[WCD_MISCDEV_CMD_MAX_LEN];
+	char val[WCD_MISCDEV_CMD_MAX_LEN + 1];
 	bool vote;
 	int ret = 0;
 
+	memset(val, 0, WCD_MISCDEV_CMD_MAX_LEN + 1);
+
 	if (count == 0 || count > WCD_MISCDEV_CMD_MAX_LEN) {
 		pr_err("%s: Invalid count = %zd\n", __func__, count);
 		ret = -EINVAL;
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 0d076bd..6d9ba11 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -82,6 +82,7 @@
 static bool is_custom_stereo_on;
 static bool is_ds2_on;
 static bool swap_ch;
+static int msm_ec_ref_port_id;
 
 #define WEIGHT_0_DB 0x4000
 /* all the FEs which can support channel mixer */
@@ -774,6 +775,11 @@
 	return 0;
 }
 
+static int get_port_id(int port_id)
+{
+	return (port_id == AFE_LOOPBACK_TX ? msm_ec_ref_port_id : port_id);
+}
+
 static bool is_mm_lsm_fe_id(int fe_id)
 {
 	bool rc = true;
@@ -1028,12 +1034,12 @@
 		   (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		   (msm_bedais[i].active) &&
 		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) {
+			int port_id = get_port_id(msm_bedais[i].port_id);
 			for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
 				unsigned long copp =
 				      session_copp_map[fedai_id][sess_type][i];
 				if (test_bit(j, &copp)) {
-					payload.port_id[num_copps] =
-							msm_bedais[i].port_id;
+					payload.port_id[num_copps] = port_id;
 					payload.copp_idx[num_copps] = j;
 					payload.app_type[num_copps] =
 						fe_dai_app_type_cfg
@@ -1180,6 +1186,7 @@
 			(msm_bedais[i].active) &&
 			(test_bit(fe_id, &msm_bedais[i].fe_sessions[0]))) {
 			int app_type, app_type_idx, copp_idx, acdb_dev_id;
+			int port_id = get_port_id(msm_bedais[i].port_id);
 
 			/*
 			 * check if ADM needs to be configured with different
@@ -1226,10 +1233,10 @@
 				topology);
 
 			copp_idx =
-				adm_open(msm_bedais[i].port_id,
-					 path_type, sample_rate, channels,
-					 topology, perf_mode, bit_width,
-					 app_type, acdb_dev_id);
+				adm_open(port_id, path_type, sample_rate,
+					 channels, topology, perf_mode,
+					 bit_width, app_type, acdb_dev_id,
+					 session_type);
 			if ((copp_idx < 0) ||
 				(copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s:adm open failed coppid:%d\n",
@@ -1245,16 +1252,14 @@
 			if (msm_is_resample_needed(
 				sample_rate,
 				msm_bedais[i].sample_rate))
-				adm_copp_mfc_cfg(
-					msm_bedais[i].port_id, copp_idx,
+				adm_copp_mfc_cfg(port_id, copp_idx,
 					msm_bedais[i].sample_rate);
 
 			for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
 				unsigned long copp =
 				session_copp_map[fe_id][session_type][i];
 				if (test_bit(j, &copp)) {
-					payload.port_id[num_copps] =
-					msm_bedais[i].port_id;
+					payload.port_id[num_copps] = port_id;
 					payload.copp_idx[num_copps] = j;
 					payload.app_type[num_copps] =
 						fe_dai_app_type_cfg
@@ -1274,8 +1279,7 @@
 			if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD
 			    && passthr_mode !=
 			    COMPRESSED_PASSTHROUGH_GEN) {
-				msm_routing_send_device_pp_params(
-				msm_bedais[i].port_id,
+				msm_routing_send_device_pp_params(port_id,
 				copp_idx, fe_id);
 			}
 		}
@@ -1411,6 +1415,8 @@
 		   (msm_bedais[i].active) &&
 		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) {
 			int app_type, app_type_idx, copp_idx, acdb_dev_id;
+			int port_id = get_port_id(msm_bedais[i].port_id);
+
 			/*
 			 * check if ADM needs to be configured with different
 			 * channel mapping than backend
@@ -1444,10 +1450,11 @@
 			topology = msm_routing_get_adm_topology(fedai_id,
 								session_type,
 								i);
-			copp_idx = adm_open(msm_bedais[i].port_id, path_type,
+			copp_idx = adm_open(port_id, path_type,
 					    sample_rate, channels, topology,
 					    perf_mode, bits_per_sample,
-					    app_type, acdb_dev_id);
+					    app_type, acdb_dev_id,
+					    session_type);
 			if ((copp_idx < 0) ||
 				(copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s: adm open failed copp_idx:%d\n",
@@ -1463,16 +1470,14 @@
 			if (msm_is_resample_needed(
 				sample_rate,
 				msm_bedais[i].sample_rate))
-				adm_copp_mfc_cfg(
-					msm_bedais[i].port_id, copp_idx,
+				adm_copp_mfc_cfg(port_id, copp_idx,
 					msm_bedais[i].sample_rate);
 
 			for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
 				unsigned long copp =
 				    session_copp_map[fedai_id][session_type][i];
 				if (test_bit(j, &copp)) {
-					payload.port_id[num_copps] =
-							msm_bedais[i].port_id;
+					payload.port_id[num_copps] = port_id;
 					payload.copp_idx[num_copps] = j;
 					payload.app_type[num_copps] =
 						fe_dai_app_type_cfg
@@ -1492,9 +1497,8 @@
 			if ((perf_mode == LEGACY_PCM_MODE) &&
 				(msm_bedais[i].passthr_mode[fedai_id] ==
 				LEGACY_PCM))
-				msm_pcm_routing_cfg_pp(msm_bedais[i].port_id,
-						       copp_idx, topology,
-						       channels);
+				msm_pcm_routing_cfg_pp(port_id, copp_idx,
+						       topology, channels);
 		}
 	}
 	if (num_copps) {
@@ -1529,7 +1533,7 @@
 
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
 {
-	int i, port_type, session_type, path_type, topology;
+	int i, port_type, session_type, path_type, topology, port_id;
 	struct msm_pcm_routing_fdai_data *fdai;
 
 	if (!is_mm_lsm_fe_id(fedai_id)) {
@@ -1568,9 +1572,10 @@
 								__func__);
 				continue;
 			}
+			port_id = get_port_id(msm_bedais[i].port_id);
 			topology = adm_get_topology_for_port_copp_idx(
-					msm_bedais[i].port_id, idx);
-			adm_close(msm_bedais[i].port_id, fdai->perf_mode, idx);
+					port_id, idx);
+			adm_close(port_id, fdai->perf_mode, idx);
 			pr_debug("%s:copp:%ld,idx bit fe:%d,type:%d,be:%d\n",
 				 __func__, copp, fedai_id, session_type, i);
 			clear_bit(idx,
@@ -1580,8 +1585,7 @@
 			    (fdai->perf_mode == LEGACY_PCM_MODE) &&
 			    (msm_bedais[i].passthr_mode[fedai_id] ==
 					LEGACY_PCM))
-				msm_pcm_routing_deinit_pp(msm_bedais[i].port_id,
-							  topology);
+				msm_pcm_routing_deinit_pp(port_id, topology);
 		}
 	}
 
@@ -1660,6 +1664,7 @@
 		if (msm_bedais[reg].active && fdai->strm_id !=
 			INVALID_SESSION) {
 			int app_type, app_type_idx, copp_idx, acdb_dev_id;
+			int port_id = get_port_id(msm_bedais[reg].port_id);
 			/*
 			 * check if ADM needs to be configured with different
 			 * channel mapping than backend
@@ -1710,10 +1715,11 @@
 								reg);
 			acdb_dev_id =
 			fe_dai_app_type_cfg[val][session_type][reg].acdb_dev_id;
-			copp_idx = adm_open(msm_bedais[reg].port_id, path_type,
+			copp_idx = adm_open(port_id, path_type,
 					    sample_rate, channels, topology,
 					    fdai->perf_mode, bits_per_sample,
-					    app_type, acdb_dev_id);
+					    app_type, acdb_dev_id,
+					    session_type);
 			if ((copp_idx < 0) ||
 			    (copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s: adm open failed\n", __func__);
@@ -1728,8 +1734,7 @@
 			if (msm_is_resample_needed(
 				sample_rate,
 				msm_bedais[reg].sample_rate))
-				adm_copp_mfc_cfg(
-					msm_bedais[reg].port_id, copp_idx,
+				adm_copp_mfc_cfg(port_id, copp_idx,
 					msm_bedais[reg].sample_rate);
 
 			if (session_type == SESSION_TYPE_RX &&
@@ -1744,9 +1749,8 @@
 						     passthr_mode);
 			if ((fdai->perf_mode == LEGACY_PCM_MODE) &&
 				(passthr_mode == LEGACY_PCM))
-				msm_pcm_routing_cfg_pp(msm_bedais[reg].port_id,
-						       copp_idx, topology,
-						       channels);
+				msm_pcm_routing_cfg_pp(port_id, copp_idx,
+						       topology, channels);
 		}
 	} else {
 		if (test_bit(val, &msm_bedais[reg].fe_sessions[0]) &&
@@ -1765,11 +1769,10 @@
 				if (test_bit(idx, &copp))
 					break;
 
-			port_id = msm_bedais[reg].port_id;
+			port_id = get_port_id(msm_bedais[reg].port_id);
 			topology = adm_get_topology_for_port_copp_idx(port_id,
 								      idx);
-			adm_close(msm_bedais[reg].port_id, fdai->perf_mode,
-				  idx);
+			adm_close(port_id, fdai->perf_mode, idx);
 			pr_debug("%s: copp: %ld, reset idx bit fe:%d, type: %d, be:%d topology=0x%x\n",
 				 __func__, copp, val, session_type, reg,
 				 topology);
@@ -1779,9 +1782,7 @@
 				topology == DS2_ADM_COPP_TOPOLOGY_ID) &&
 			    (fdai->perf_mode == LEGACY_PCM_MODE) &&
 			    (passthr_mode == LEGACY_PCM))
-				msm_pcm_routing_deinit_pp(
-						msm_bedais[reg].port_id,
-						topology);
+				msm_pcm_routing_deinit_pp(port_id, topology);
 			msm_pcm_routing_build_matrix(val, session_type,
 						     path_type,
 						     fdai->perf_mode,
@@ -3699,6 +3700,7 @@
 		ec_ref_port_id = AFE_PORT_INVALID;
 		break;
 	}
+	msm_ec_ref_port_id = ec_ref_port_id;
 	adm_ec_ref_rx_id(ec_ref_port_id);
 	pr_debug("%s: msm_route_ec_ref_rx = %d\n",
 	    __func__, msm_route_ec_ref_rx);
@@ -7933,6 +7935,9 @@
 	SOC_SINGLE_EXT("QUIN_TDM_TX_3", MSM_BACKEND_DAI_QUIN_TDM_TX_3,
 	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("AFE_LOOPBACK_TX", MSM_BACKEND_DAI_AFE_LOOPBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mmul10_mixer_controls[] = {
@@ -12346,6 +12351,9 @@
 	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
 					"INT3_MI2S")) {
 		*port_id = AFE_PORT_ID_INT3_MI2S_TX;
+	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
+					"PRIMARY_TDM")) {
+		*port_id = AFE_PORT_ID_PRIMARY_TDM_TX;
 	} else {
 		pr_err("%s: mixer ctl name=%s, could not derive valid port id\n",
 			__func__, kcontrol->id.name);
@@ -12580,6 +12588,21 @@
 		.info	= msm_source_tracking_info,
 		.get	= msm_audio_source_tracking_get,
 	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name   = "Sound Focus Audio Tx PRIMARY_TDM",
+		.info   = msm_sound_focus_info,
+		.get    = msm_audio_sound_focus_get,
+		.put    = msm_audio_sound_focus_put,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name   = "Source Tracking Audio Tx PRIMARY_TDM",
+		.info   = msm_source_tracking_info,
+		.get    = msm_audio_source_tracking_get,
+	},
 };
 
 static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol,
@@ -14379,6 +14402,7 @@
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"PRI_MI2S_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia10", "MM_DL10"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia11", "MM_DL11"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia12", "MM_DL12"},
@@ -16917,10 +16941,10 @@
 				if (test_bit(idx, &copp))
 					break;
 			fdai->be_srate = bedai->sample_rate;
-			port_id = bedai->port_id;
+			port_id = get_port_id(msm_bedais[i].port_id);
 			topology = adm_get_topology_for_port_copp_idx(port_id,
 								     idx);
-			adm_close(bedai->port_id, fdai->perf_mode, idx);
+			adm_close(port_id, fdai->perf_mode, idx);
 			pr_debug("%s: copp:%ld,idx bit fe:%d, type:%d,be:%d topology=0x%x\n",
 				 __func__, copp, i, session_type, be_id,
 				 topology);
@@ -16928,7 +16952,7 @@
 				  &session_copp_map[i][session_type][be_id]);
 			if ((fdai->perf_mode == LEGACY_PCM_MODE) &&
 				(bedai->passthr_mode[i] == LEGACY_PCM))
-				msm_pcm_routing_deinit_pp(bedai->port_id,
+				msm_pcm_routing_deinit_pp(port_id,
 							  topology);
 		}
 	}
@@ -17001,6 +17025,7 @@
 		fdai = &fe_dai_map[i][session_type];
 		if (fdai->strm_id != INVALID_SESSION) {
 			int app_type, app_type_idx, copp_idx, acdb_dev_id;
+			int port_id = get_port_id(bedai->port_id);
 
 			if (session_type == SESSION_TYPE_TX &&
 			    fdai->be_srate &&
@@ -17050,10 +17075,11 @@
 			fe_dai_app_type_cfg[i][session_type][be_id].acdb_dev_id;
 			topology = msm_routing_get_adm_topology(i, session_type,
 								be_id);
-			copp_idx = adm_open(bedai->port_id, path_type,
+			copp_idx = adm_open(port_id, path_type,
 					    sample_rate, channels, topology,
 					    fdai->perf_mode, bits_per_sample,
-					    app_type, acdb_dev_id);
+					    app_type, acdb_dev_id,
+					    session_type);
 			if ((copp_idx < 0) ||
 				(copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s: adm open failed\n", __func__);
@@ -17068,8 +17094,7 @@
 			if (msm_is_resample_needed(
 				sample_rate,
 				bedai->sample_rate))
-				adm_copp_mfc_cfg(
-					bedai->port_id, copp_idx,
+				adm_copp_mfc_cfg(port_id, copp_idx,
 					bedai->sample_rate);
 
 			msm_pcm_routing_build_matrix(i, session_type, path_type,
@@ -17077,7 +17102,7 @@
 						     bedai->passthr_mode[i]);
 			if ((fdai->perf_mode == LEGACY_PCM_MODE) &&
 				(bedai->passthr_mode[i] == LEGACY_PCM))
-				msm_pcm_routing_cfg_pp(bedai->port_id, copp_idx,
+				msm_pcm_routing_cfg_pp(port_id, copp_idx,
 						       topology, channels);
 		}
 	}
diff --git a/asoc/sdm660-internal.c b/asoc/sdm660-internal.c
index c656713..ebcea54 100644
--- a/asoc/sdm660-internal.c
+++ b/asoc/sdm660-internal.c
@@ -45,7 +45,8 @@
 };
 
 enum {
-	BT_SLIM7,
+	BT_SLIM7_RX,
+	BT_SLIM7_TX,
 	FM_SLIM8,
 	SLIM_MAX,
 };
@@ -139,7 +140,8 @@
 };
 
 static struct dev_config bt_fm_cfg[] = {
-	[BT_SLIM7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[BT_SLIM7_RX] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[BT_SLIM7_TX] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
 	[FM_SLIM8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
 };
 
@@ -154,6 +156,12 @@
 static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16",
 					"KHZ_44P1", "KHZ_48",
 					"KHZ_88P2", "KHZ_96"};
+static char const *bt_sample_rate_rx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static char const *bt_sample_rate_tx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
 
 static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_sample_rate, int_mi2s_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_chs, int_mi2s_ch_text);
@@ -170,6 +178,8 @@
 static SOC_ENUM_SINGLE_EXT_DECL(int5_mi2s_tx_chs, int_mi2s_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(loopback_mclk_en, loopback_mclk_text);
 static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_rx, bt_sample_rate_rx_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_tx, bt_sample_rate_tx_text);
 
 static int msm_dmic_event(struct snd_soc_dapm_widget *w,
 			  struct snd_kcontrol *kcontrol, int event);
@@ -639,12 +649,18 @@
 
 	switch (dai_link->id) {
 	case MSM_BACKEND_DAI_SLIMBUS_7_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				bt_fm_cfg[BT_SLIM7_RX].bit_format);
+		rate->min = rate->max = bt_fm_cfg[BT_SLIM7_RX].sample_rate;
+		channels->min = channels->max =
+			bt_fm_cfg[BT_SLIM7_RX].channels;
+		break;
 	case MSM_BACKEND_DAI_SLIMBUS_7_TX:
 		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
-				bt_fm_cfg[BT_SLIM7].bit_format);
-		rate->min = rate->max = bt_fm_cfg[BT_SLIM7].sample_rate;
+				bt_fm_cfg[BT_SLIM7_TX].bit_format);
+		rate->min = rate->max = bt_fm_cfg[BT_SLIM7_TX].sample_rate;
 		channels->min = channels->max =
-			bt_fm_cfg[BT_SLIM7].channels;
+			bt_fm_cfg[BT_SLIM7_TX].channels;
 		break;
 
 	case MSM_BACKEND_DAI_SLIMBUS_8_TX:
@@ -849,7 +865,7 @@
 	 * when used for BT_SCO use case. Return either Rx or Tx sample rate
 	 * value.
 	 */
-	switch (bt_fm_cfg[BT_SLIM7].sample_rate) {
+	switch (bt_fm_cfg[BT_SLIM7_RX].sample_rate) {
 	case SAMPLING_RATE_96KHZ:
 		ucontrol->value.integer.value[0] = 5;
 		break;
@@ -871,7 +887,7 @@
 		break;
 	}
 	pr_debug("%s: sample rate = %d", __func__,
-		 bt_fm_cfg[BT_SLIM7].sample_rate);
+		 bt_fm_cfg[BT_SLIM7_RX].sample_rate);
 
 	return 0;
 }
@@ -881,33 +897,163 @@
 {
 	switch (ucontrol->value.integer.value[0]) {
 	case 1:
-		bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_16KHZ;
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_16KHZ;
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_16KHZ;
 		break;
 	case 2:
-		bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_44P1KHZ;
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_44P1KHZ;
 		break;
 	case 3:
-		bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_48KHZ;
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_48KHZ;
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_48KHZ;
 		break;
 	case 4:
-		bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_88P2KHZ;
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_88P2KHZ;
 		break;
 	case 5:
-		bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_96KHZ;
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_96KHZ;
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_96KHZ;
 		break;
 	case 0:
 	default:
-		bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_8KHZ;
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_8KHZ;
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_8KHZ;
 		break;
 	}
 	pr_debug("%s: sample rates: slim7_rx = %d, value = %d\n",
 		 __func__,
-		 bt_fm_cfg[BT_SLIM7].sample_rate,
+		 bt_fm_cfg[BT_SLIM7_RX].sample_rate,
 		 ucontrol->value.enumerated.item[0]);
 
 	return 0;
 }
 
+static int msm_bt_sample_rate_rx_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (bt_fm_cfg[BT_SLIM7_RX].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate = %d", __func__,
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_rx_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rates: slim7_rx = %d, value = %d\n",
+		__func__,
+		bt_fm_cfg[BT_SLIM7_RX].sample_rate,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (bt_fm_cfg[BT_SLIM7_TX].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate = %d", __func__,
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rates: slim7_tx = %d, value = %d\n",
+		__func__,
+		bt_fm_cfg[BT_SLIM7_TX].sample_rate,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new msm_snd_controls[] = {
 	SOC_ENUM_EXT("INT0_MI2S_RX Format", int0_mi2s_rx_format,
 		     int_mi2s_bit_format_get, int_mi2s_bit_format_put),
@@ -933,6 +1079,12 @@
 	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
 			msm_bt_sample_rate_get,
 			msm_bt_sample_rate_put),
+	SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
+			msm_bt_sample_rate_rx_get,
+			msm_bt_sample_rate_rx_put),
+	SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
+			msm_bt_sample_rate_tx_get,
+			msm_bt_sample_rate_tx_put),
 };
 
 static const struct snd_kcontrol_new msm_loopback_snd_controls[] = {
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index 48e4b16..74a9244 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -66,6 +66,7 @@
 	atomic_t channels[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 	atomic_t app_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 	atomic_t acdb_id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
+	atomic_t session_type[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 	wait_queue_head_t wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 	wait_queue_head_t adm_delay_wait[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 	atomic_t adm_delay_stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
@@ -267,7 +268,8 @@
 }
 
 static int adm_get_idx_if_copp_exists(int port_idx, int topology, int mode,
-				 int rate, int bit_width, int app_type)
+				 int rate, int bit_width, int app_type,
+				 int session_type)
 {
 	int idx;
 
@@ -281,6 +283,9 @@
 		    (rate == atomic_read(&this_adm.copp.rate[port_idx][idx])) &&
 		    (bit_width ==
 			atomic_read(&this_adm.copp.bit_width[port_idx][idx])) &&
+		    (session_type ==
+			atomic_read(
+				&this_adm.copp.session_type[port_idx][idx])) &&
 		    (app_type ==
 			atomic_read(&this_adm.copp.app_type[port_idx][idx])))
 			return idx;
@@ -1468,6 +1473,8 @@
 			    &this_adm.copp.app_type[i][j], 0);
 			atomic_set(
 			   &this_adm.copp.acdb_id[i][j], 0);
+			atomic_set(
+			   &this_adm.copp.session_type[i][j], 0);
 			this_adm.copp.adm_status[i][j] =
 				ADM_STATUS_CALIBRATION_REQUIRED;
 		}
@@ -2560,7 +2567,8 @@
  * Returns 0 on success or error on failure
  */
 int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
-	     int perf_mode, uint16_t bit_width, int app_type, int acdb_id)
+	     int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
+	     int session_type)
 {
 	struct adm_cmd_device_open_v5	open;
 	struct adm_cmd_device_open_v6	open_v6;
@@ -2629,7 +2637,7 @@
 		copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
 						      perf_mode,
 						      rate, bit_width,
-						      app_type);
+						      app_type, session_type);
 
 	if (copp_idx < 0) {
 		copp_idx = adm_get_next_available_copp(port_idx);
@@ -2653,6 +2661,8 @@
 			   app_type);
 		atomic_set(&this_adm.copp.acdb_id[port_idx][copp_idx],
 			   acdb_id);
+		atomic_set(&this_adm.copp.session_type[port_idx][copp_idx],
+			   session_type);
 		set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
 		(void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
 		if ((path != ADM_PATH_COMPRESSED_RX) &&
@@ -2703,7 +2713,8 @@
 		open.endpoint_id_1 = tmp_port;
 		open.endpoint_id_2 = 0xFFFF;
 
-		if (this_adm.ec_ref_rx && (path != 1)) {
+		if (this_adm.ec_ref_rx && (path != 1) &&
+		    (afe_get_port_type(tmp_port) == MSM_AFE_PORT_TYPE_TX)) {
 			open.endpoint_id_2 = this_adm.ec_ref_rx;
 			this_adm.ec_ref_rx = -1;
 		}
@@ -3252,6 +3263,7 @@
 		atomic_set(&this_adm.copp.channels[port_idx][copp_idx], 0);
 		atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
 		atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
+		atomic_set(&this_adm.copp.session_type[port_idx][copp_idx], 0);
 
 		clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
 			(void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
@@ -5243,6 +5255,7 @@
 			atomic_set(&this_adm.copp.bit_width[i][j], 0);
 			atomic_set(&this_adm.copp.app_type[i][j], 0);
 			atomic_set(&this_adm.copp.acdb_id[i][j], 0);
+			atomic_set(&this_adm.copp.session_type[i][j], 0);
 			init_waitqueue_head(&this_adm.copp.wait[i][j]);
 			atomic_set(&this_adm.copp.adm_delay_stat[i][j], 0);
 			init_waitqueue_head(
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 2539564..ce12374 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -95,6 +95,7 @@
 struct audio_session {
 	struct audio_client *ac;
 	spinlock_t session_lock;
+	struct mutex mutex_lock_per_session;
 };
 /* session id: 0 reserved */
 static struct audio_session session[ASM_ACTIVE_STREAMS_ALLOWED + 1];
@@ -562,6 +563,8 @@
 		if (session[n].ac == ac)
 			return n;
 	}
+	pr_debug("%s: cannot find matching audio client. ac = %pK\n",
+		__func__, ac);
 	return 0;
 }
 
@@ -573,10 +576,11 @@
 static void q6asm_session_free(struct audio_client *ac)
 {
 	int session_id;
-	unsigned long flags;
+	unsigned long flags = 0;
 
 	pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
 	session_id = ac->session;
+	mutex_lock(&session[session_id].mutex_lock_per_session);
 	rtac_remove_popp_from_adm_devices(ac->session);
 	spin_lock_irqsave(&(session[session_id].session_lock), flags);
 	session[ac->session].ac = NULL;
@@ -588,6 +592,7 @@
 	kfree(ac);
 	ac = NULL;
 	spin_unlock_irqrestore(&(session[session_id].session_lock), flags);
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
 }
 
 static uint32_t q6asm_get_next_buf(struct audio_client *ac,
@@ -1193,7 +1198,7 @@
 {
 	char *asm_params = NULL;
 	struct apr_hdr hdr;
-	int rc;
+	int rc, session_id = 0;
 	uint32_t sz = 0;
 	uint64_t actual_sz = 0;
 
@@ -1204,6 +1209,12 @@
 		goto done;
 	}
 
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
+		rc = -EINVAL;
+		goto done;
+	}
+
 	if (data->event_type >= ARRAY_SIZE(adsp_reg_event_opcode)) {
 		pr_err("%s: event %u out of boundary of array size of (%lu)\n",
 		       __func__, data->event_type,
@@ -1227,6 +1238,12 @@
 		goto done;
 	}
 
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
+		goto fail_send_param;
+	}
+
 	q6asm_add_hdr_async(ac, &hdr, sz, TRUE);
 	atomic_set(&ac->cmd_state_pp, -1);
 	hdr.opcode = adsp_reg_event_opcode[data->event_type];
@@ -1259,6 +1276,7 @@
 
 	rc = 0;
 fail_send_param:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
 	kfree(asm_params);
 done:
 	return rc;
@@ -1621,7 +1639,7 @@
 	uint32_t dir = 0;
 	uint32_t i = IN;
 	uint32_t *payload;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 	unsigned long flags = 0;
 	struct asm_buffer_node *buf_node = NULL;
 	struct list_head *ptr, *next;
@@ -1838,7 +1856,7 @@
 {
 	int i = 0;
 	struct audio_client *ac = (struct audio_client *)priv;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 	uint32_t *payload;
 	uint32_t wakeup_flag = 1;
 	int32_t  ret = 0;
@@ -1846,7 +1864,7 @@
 	uint8_t buf_index;
 	struct msm_adsp_event_data *pp_event_package = NULL;
 	uint32_t payload_size = 0;
-	unsigned long flags;
+	unsigned long flags = 0;
 	int session_id;
 
 	if (ac == NULL) {
@@ -2531,7 +2549,7 @@
 static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
 			uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id)
 {
-	unsigned long flags;
+	unsigned long flags = 0;
 
 	dev_vdbg(ac->dev, "%s: pkt_size=%d cmd_flg=%d session=%d stream_id=%d\n",
 			__func__, pkt_size, cmd_flg, ac->session, stream_id);
@@ -7397,12 +7415,26 @@
 	struct asm_volume_ctrl_multichannel_gain multi_ch_gain;
 	int sz = 0;
 	int rc  = 0;
+	int session_id = 0;
 
 	if (ac == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
 		rc = -EINVAL;
+		goto done;
+	}
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
 		goto fail_cmd;
 	}
+
 	if (ac->apr == NULL) {
 		pr_err("%s: AC APR handle NULL\n", __func__);
 		rc = -EINVAL;
@@ -7456,6 +7488,8 @@
 	}
 	rc = 0;
 fail_cmd:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
+done:
 	return rc;
 }
 
@@ -7473,7 +7507,7 @@
 	struct asm_volume_ctrl_multichannel_gain multich_gain;
 	int sz = 0;
 	int rc  = 0;
-	int i;
+	int i, session_id = 0;
 	u8 default_chmap[VOLUME_CONTROL_MAX_CHANNELS];
 
 	if (ac == NULL) {
@@ -7481,30 +7515,44 @@
 		rc = -EINVAL;
 		goto done;
 	}
-	if (ac->apr == NULL) {
-		dev_err(ac->dev, "%s: AC APR handle NULL\n", __func__);
-		rc = -EINVAL;
-		goto done;
-	}
-	if (gains == NULL) {
-		dev_err(ac->dev, "%s: gain_list is NULL\n", __func__);
-		rc = -EINVAL;
-		goto done;
-	}
-	if (channels > VOLUME_CONTROL_MAX_CHANNELS) {
-		dev_err(ac->dev, "%s: Invalid channel count %d\n",
-			__func__, channels);
-		rc = -EINVAL;
-		goto done;
-	}
-	if (!use_default && ch_map == NULL) {
-		dev_err(ac->dev, "%s: NULL channel map\n", __func__);
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
 		rc = -EINVAL;
 		goto done;
 	}
 
 	memset(&multich_gain, 0, sizeof(multich_gain));
 	sz = sizeof(struct asm_volume_ctrl_multichannel_gain);
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
+	if (ac->apr == NULL) {
+		dev_err(ac->dev, "%s: AC APR handle NULL\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
+	if (gains == NULL) {
+		dev_err(ac->dev, "%s: gain_list is NULL\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	if (channels > VOLUME_CONTROL_MAX_CHANNELS) {
+		dev_err(ac->dev, "%s: Invalid channel count %d\n",
+			__func__, channels);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	if (!use_default && ch_map == NULL) {
+		dev_err(ac->dev, "%s: NULL channel map\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
 	q6asm_add_hdr_async(ac, &multich_gain.hdr, sz, TRUE);
 	atomic_set(&ac->cmd_state_pp, -1);
 	multich_gain.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
@@ -7522,7 +7570,7 @@
 	if (use_default) {
 		rc = q6asm_map_channels(default_chmap, channels, false);
 		if (rc < 0)
-			goto done;
+			goto fail_cmd;
 		for (i = 0; i < channels; i++) {
 			multich_gain.gain_data[i].channeltype =
 				default_chmap[i];
@@ -7540,7 +7588,7 @@
 	if (rc < 0) {
 		pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
 				__func__, multich_gain.data.param_id, rc);
-		goto done;
+		goto fail_cmd;
 	}
 
 	rc = wait_event_timeout(ac->cmd_wait,
@@ -7549,16 +7597,18 @@
 		pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
 				multich_gain.data.param_id);
 		rc = -EINVAL;
-		goto done;
+		goto fail_cmd;
 	}
 	if (atomic_read(&ac->cmd_state_pp) > 0) {
 		pr_err("%s: DSP returned error[%d] , set-params paramid[0x%x]\n",
 		       __func__, atomic_read(&ac->cmd_state_pp),
 		       multich_gain.data.param_id);
 		rc = -EINVAL;
-		goto done;
+		goto fail_cmd;
 	}
 	rc = 0;
+fail_cmd:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
 done:
 	return rc;
 }
@@ -7578,12 +7628,26 @@
 	struct asm_volume_ctrl_mute_config mute;
 	int sz = 0;
 	int rc  = 0;
+	int session_id = 0;
 
 	if (ac == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
 		rc = -EINVAL;
+		goto done;
+	}
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
 		goto fail_cmd;
 	}
+
 	if (ac->apr == NULL) {
 		pr_err("%s: AC APR handle NULL\n", __func__);
 		rc = -EINVAL;
@@ -7632,6 +7696,8 @@
 	}
 	rc = 0;
 fail_cmd:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
+done:
 	return rc;
 }
 EXPORT_SYMBOL(q6asm_set_mute);
@@ -7641,17 +7707,18 @@
 	struct asm_volume_ctrl_master_gain vol;
 	int sz = 0;
 	int rc  = 0;
-	int module_id;
+	int module_id, session_id = 0;
 
 	if (ac == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
 		rc = -EINVAL;
-		goto fail_cmd;
+		goto done;
 	}
-	if (ac->apr == NULL) {
-		pr_err("%s: AC APR handle NULL\n", __func__);
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
 		rc = -EINVAL;
-		goto fail_cmd;
+		goto done;
 	}
 
 	switch (instance) {
@@ -7665,6 +7732,18 @@
 	}
 
 	sz = sizeof(struct asm_volume_ctrl_master_gain);
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
+	if (ac->apr == NULL) {
+		pr_err("%s: AC APR handle NULL\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
 	q6asm_add_hdr_async(ac, &vol.hdr, sz, TRUE);
 	atomic_set(&ac->cmd_state_pp, -1);
 	vol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
@@ -7707,6 +7786,8 @@
 
 	rc = 0;
 fail_cmd:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
+done:
 	return rc;
 }
 
@@ -7989,12 +8070,26 @@
 	struct asm_soft_pause_params softpause;
 	int sz = 0;
 	int rc  = 0;
+	int session_id = 0;
 
 	if (ac == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
 		rc = -EINVAL;
+		goto done;
+	}
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
 		goto fail_cmd;
 	}
+
 	if (ac->apr == NULL) {
 		pr_err("%s: AC APR handle NULL\n", __func__);
 		rc = -EINVAL;
@@ -8048,6 +8143,8 @@
 	}
 	rc = 0;
 fail_cmd:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
+done:
 	return rc;
 }
 EXPORT_SYMBOL(q6asm_set_softpause);
@@ -8059,17 +8156,18 @@
 	struct asm_soft_step_volume_params softvol;
 	int sz = 0;
 	int rc  = 0;
-	int module_id;
+	int module_id, session_id;
 
 	if (ac == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
 		rc = -EINVAL;
-		goto fail_cmd;
+		goto done;
 	}
-	if (ac->apr == NULL) {
-		pr_err("%s: AC APR handle NULL\n", __func__);
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
 		rc = -EINVAL;
-		goto fail_cmd;
+		goto done;
 	}
 
 	switch (instance) {
@@ -8083,6 +8181,18 @@
 	}
 
 	sz = sizeof(struct asm_soft_step_volume_params);
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
+	if (ac->apr == NULL) {
+		pr_err("%s: AC APR handle NULL\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+
 	q6asm_add_hdr_async(ac, &softvol.hdr, sz, TRUE);
 	atomic_set(&ac->cmd_state_pp, -1);
 	softvol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
@@ -8127,6 +8237,8 @@
 	}
 	rc = 0;
 fail_cmd:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
+done:
 	return rc;
 }
 
@@ -8181,12 +8293,26 @@
 	int i  = 0;
 	int sz = 0;
 	int rc  = 0;
+	int session_id = 0;
 
 	if (ac == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
 		rc = -EINVAL;
+		goto done;
+	}
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id) {
+		rc = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
 		goto fail_cmd;
 	}
+
 	if (ac->apr == NULL) {
 		pr_err("%s: AC APR handle NULL\n", __func__);
 		rc = -EINVAL;
@@ -8264,6 +8390,8 @@
 	}
 	rc = 0;
 fail_cmd:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
+done:
 	return rc;
 }
 EXPORT_SYMBOL(q6asm_equalizer);
@@ -8961,17 +9089,18 @@
 	char *asm_params = NULL;
 	struct apr_hdr hdr;
 	struct asm_stream_cmd_set_pp_params_v2 payload_params;
-	int sz, rc;
+	int sz, rc, session_id = 0;
 
 	pr_debug("%s:\n", __func__);
 	if (!ac) {
 		pr_err("%s: APR handle NULL\n", __func__);
 		return -EINVAL;
 	}
-	if (ac->apr == NULL) {
-		pr_err("%s: AC APR handle NULL\n", __func__);
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id)
 		return -EINVAL;
-	}
+
 	if (params == NULL) {
 		pr_err("%s: params NULL\n", __func__);
 		return -EINVAL;
@@ -8984,6 +9113,18 @@
 		pr_err("%s, asm params memory alloc failed", __func__);
 		return -ENOMEM;
 	}
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
+		goto fail_send_param;
+	}
+
+	if (ac->apr == NULL) {
+		pr_err("%s: AC APR handle NULL\n", __func__);
+		rc = -EINVAL;
+		goto fail_send_param;
+	}
+
 	q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
 				sizeof(struct asm_stream_cmd_set_pp_params_v2) +
 				params_length), TRUE);
@@ -9023,6 +9164,7 @@
 
 	rc = 0;
 fail_send_param:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
 	kfree(asm_params);
 	return rc;
 }
@@ -10077,7 +10219,7 @@
 	struct apr_hdr	hdr;
 	char *asm_params = NULL;
 	struct asm_stream_cmd_set_pp_params_v2 payload_params;
-	int sz, rc = -EINVAL;
+	int sz, rc = -EINVAL, session_id = 0;
 
 	pr_debug("%s:\n", __func__);
 
@@ -10085,23 +10227,14 @@
 		pr_err("%s: APR handle NULL\n", __func__);
 		goto done;
 	}
-	if (ac->apr == NULL) {
-		pr_err("%s: AC APR handle NULL\n", __func__);
+
+	session_id = q6asm_get_session_id_from_audio_client(ac);
+	if (!session_id)
 		goto done;
-	}
-	if (ac->io_mode & NT_MODE) {
-		pr_debug("%s: called for NT MODE, exiting\n", __func__);
-		goto done;
-	}
 
 	if (cal_data[ASM_AUDSTRM_CAL] == NULL)
 		goto done;
 
-	if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
-		rc = 0; /* no cal is required, not error case */
-		goto done;
-	}
-
 	mutex_lock(&cal_data[ASM_AUDSTRM_CAL]->lock);
 	cal_block = cal_utils_get_only_cal_block(cal_data[ASM_AUDSTRM_CAL]);
 	if (cal_block == NULL) {
@@ -10133,6 +10266,26 @@
 		goto unlock;
 	}
 
+	mutex_lock(&session[session_id].mutex_lock_per_session);
+	if (!q6asm_is_valid_audio_client(ac)) {
+		rc = -EINVAL;
+		goto free;
+	}
+
+	if (ac->apr == NULL) {
+		pr_err("%s: AC APR handle NULL\n", __func__);
+		goto free;
+	}
+	if (ac->io_mode & NT_MODE) {
+		pr_debug("%s: called for NT MODE, exiting\n", __func__);
+		goto free;
+	}
+
+	if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
+		rc = 0; /* no cal is required, not error case */
+		goto free;
+	}
+
 	/* asm_stream_cmd_set_pp_params_v2 has no APR header in it */
 	q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
 		sizeof(struct asm_stream_cmd_set_pp_params_v2)), TRUE);
@@ -10179,6 +10332,7 @@
 	rc = 0;
 
 free:
+	mutex_unlock(&session[session_id].mutex_lock_per_session);
 	kfree(asm_params);
 unlock:
 	mutex_unlock(&cal_data[ASM_AUDSTRM_CAL]->lock);
@@ -10368,8 +10522,10 @@
 
 	memset(session, 0, sizeof(struct audio_session) *
 		(ASM_ACTIVE_STREAMS_ALLOWED + 1));
-	for (lcnt = 0; lcnt <= ASM_ACTIVE_STREAMS_ALLOWED; lcnt++)
+	for (lcnt = 0; lcnt <= ASM_ACTIVE_STREAMS_ALLOWED; lcnt++) {
 		spin_lock_init(&(session[lcnt].session_lock));
+		mutex_init(&(session[lcnt].mutex_lock_per_session));
+	}
 	set_custom_topology = 1;
 
 	/*setup common client used for cal mem map */
diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h
index 881943b..e8000ab 100644
--- a/include/dsp/q6adm-v2.h
+++ b/include/dsp/q6adm-v2.h
@@ -102,7 +102,7 @@
 
 int adm_open(int port, int path, int rate, int mode, int topology,
 			   int perf_mode, uint16_t bits_per_sample,
-			   int app_type, int acdbdev_id);
+			   int app_type, int acdbdev_id, int session_type);
 
 int adm_map_rtac_block(struct rtac_cal_block_data *cal_block);