Merge "asoc: codecs: bolero: suspend swr at VA use case switch"
diff --git a/asoc/bengal-port-config.h b/asoc/bengal-port-config.h
index 9989963..4ac7e10 100644
--- a/asoc/bengal-port-config.h
+++ b/asoc/bengal-port-config.h
@@ -37,7 +37,7 @@
 };
 
 static struct swr_mstr_port_map sm_port_map[] = {
-	{TX_MACRO, SWR_UC0, tx_frame_params_default},
+	{VA_MACRO, SWR_UC0, tx_frame_params_default},
 	{RX_MACRO, SWR_UC0, rx_frame_params_default},
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 };
diff --git a/asoc/codecs/bolero/bolero-cdc-registers.h b/asoc/codecs/bolero/bolero-cdc-registers.h
index 99890cc..c59bb86 100644
--- a/asoc/codecs/bolero/bolero-cdc-registers.h
+++ b/asoc/codecs/bolero/bolero-cdc-registers.h
@@ -696,6 +696,7 @@
 #define BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL	(VA_START_OFFSET + 0x0000)
 #define BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL \
 						(VA_START_OFFSET + 0x0004)
+#define BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL	(VA_START_OFFSET + 0x0008)
 #define BOLERO_CDC_VA_TOP_CSR_TOP_CFG0		(VA_START_OFFSET + 0x0080)
 #define BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL		(VA_START_OFFSET + 0x0084)
 #define BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL		(VA_START_OFFSET + 0x0088)
diff --git a/asoc/codecs/bolero/bolero-cdc-regmap.c b/asoc/codecs/bolero/bolero-cdc-regmap.c
index 037f9aa..9082966 100644
--- a/asoc/codecs/bolero/bolero-cdc-regmap.c
+++ b/asoc/codecs/bolero/bolero-cdc-regmap.c
@@ -609,6 +609,7 @@
 	/* VA macro */
 	{ BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
 	{ BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_TOP_CFG0, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL, 0x00},
diff --git a/asoc/codecs/bolero/bolero-cdc-tables.c b/asoc/codecs/bolero/bolero-cdc-tables.c
index 5298763..81639b3 100644
--- a/asoc/codecs/bolero/bolero-cdc-tables.c
+++ b/asoc/codecs/bolero/bolero-cdc-tables.c
@@ -442,6 +442,7 @@
 u8 bolero_va_reg_access[BOLERO_CDC_VA_MACRO_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
@@ -567,6 +568,7 @@
 u8 bolero_va_top_reg_access[BOLERO_CDC_VA_MACRO_TOP_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
diff --git a/asoc/codecs/bolero/bolero-cdc-utils.c b/asoc/codecs/bolero/bolero-cdc-utils.c
index b2fd153..f2e4ec4 100644
--- a/asoc/codecs/bolero/bolero-cdc-utils.c
+++ b/asoc/codecs/bolero/bolero-cdc-utils.c
@@ -68,12 +68,9 @@
 	reg_p = (u16 *)reg;
 	macro_id = bolero_get_macro_id(priv->va_without_decimation,
 					   reg_p[0]);
-	if (macro_id < 0 || !priv->macros_supported[macro_id]) {
-		dev_err_ratelimited(dev,
-			"%s: Unsupported macro %d or reg 0x%x is invalid\n",
-			__func__, macro_id, reg_p[0]);
-		return ret;
-	}
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
 	mutex_lock(&priv->io_lock);
 	for (i = 0; i < val_size; i++) {
 		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
@@ -121,12 +118,9 @@
 	reg_p = (u16 *)reg;
 	macro_id = bolero_get_macro_id(priv->va_without_decimation,
 					reg_p[0]);
-	if (macro_id < 0 || !priv->macros_supported[macro_id]) {
-		dev_err_ratelimited(dev,
-			"%s: Unsupported macro-id %d or reg 0x%x is invalid\n",
-			__func__, macro_id, reg_p[0]);
-		return ret;
-	}
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
 	mutex_lock(&priv->io_lock);
 	for (i = 0; i < val_size; i++) {
 		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index fdf0445..dde4719 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -20,9 +20,6 @@
 
 #define DRV_NAME "bolero_codec"
 
-#define BOLERO_VERSION_1_0 0x0001
-#define BOLERO_VERSION_1_1 0x0002
-#define BOLERO_VERSION_1_2 0x0003
 #define BOLERO_VERSION_ENTRY_SIZE 32
 #define BOLERO_CDC_STRING_LEN 80
 
@@ -214,6 +211,12 @@
 				priv->component,
 				BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST, data);
 		break;
+	case WCD_BOLERO_EVT_BCS_CLK_OFF:
+		if (priv->macro_params[TX_MACRO].event_handler)
+			priv->macro_params[TX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_BCS_CLK_OFF, data);
+		break;
 	default:
 		dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n",
 			__func__, event);
@@ -507,11 +510,17 @@
 		priv->macro_params[macro_id].reg_evt_listener =
 							ops->reg_evt_listener;
 	}
-
+	if (priv->version == BOLERO_VERSION_2_1) {
+		if (macro_id == VA_MACRO)
+			priv->macro_params[macro_id].reg_wake_irq =
+						ops->reg_wake_irq;
+	}
 	priv->num_dais += ops->num_dais;
 	priv->num_macros_registered++;
 	priv->macros_supported[macro_id] = true;
 
+	dev_dbg(dev, "%s: register macro successful:%d\n", macro_id);
+
 	if (priv->num_macros_registered == priv->num_macros) {
 		ret = bolero_copy_dais_from_macro(priv);
 		if (ret < 0) {
@@ -604,6 +613,28 @@
 }
 EXPORT_SYMBOL(bolero_wsa_pa_on);
 
+int bolero_get_version(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device for macro not added yet\n",
+			__func__);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return -EINVAL;
+	}
+	return priv->version;
+}
+EXPORT_SYMBOL(bolero_get_version);
+
 static ssize_t bolero_version_read(struct snd_info_entry *entry,
 				   void *file_private_data,
 				   struct file *file,
@@ -630,6 +661,9 @@
 	case BOLERO_VERSION_1_2:
 		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_2\n");
 		break;
+	case BOLERO_VERSION_2_1:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_2_1\n");
+		break;
 	default:
 		len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
 	}
@@ -794,9 +828,15 @@
 		return -EINVAL;
 	}
 
-	if (priv->macro_params[TX_MACRO].reg_wake_irq)
-		priv->macro_params[TX_MACRO].reg_wake_irq(
-				component, ipc_wakeup);
+	if (priv->version == BOLERO_VERSION_2_1) {
+		if (priv->macro_params[VA_MACRO].reg_wake_irq)
+			priv->macro_params[VA_MACRO].reg_wake_irq(
+					component, ipc_wakeup);
+	} else {
+		if (priv->macro_params[TX_MACRO].reg_wake_irq)
+			priv->macro_params[TX_MACRO].reg_wake_irq(
+					component, ipc_wakeup);
+	}
 
 	return 0;
 }
@@ -875,6 +915,29 @@
 
 	snd_soc_component_init_regmap(component, priv->regmap);
 
+	if (!priv->version) {
+		/*
+		 * In order for the ADIE RTC to differentiate between targets
+		 * version info is used.
+		 * Assign 1.0 for target with only one macro
+		 * Assign 1.1 for target with two macros
+		 * Assign 1.2 for target with more than two macros
+		 */
+		if (priv->num_macros_registered == 1)
+			priv->version = BOLERO_VERSION_1_0;
+		else if (priv->num_macros_registered == 2)
+			priv->version = BOLERO_VERSION_1_1;
+		else if (priv->num_macros_registered > 2)
+			priv->version = BOLERO_VERSION_1_2;
+	}
+
+	/* Assign bolero version 2.1 for bolero 2.1 */
+	if ((snd_soc_component_read32(component,
+		BOLERO_CDC_VA_TOP_CSR_CORE_ID_0) == 0x2) &&
+		(snd_soc_component_read32(component,
+			BOLERO_CDC_VA_TOP_CSR_CORE_ID_1) == 0xE))
+		priv->version = BOLERO_VERSION_2_1;
+
 	/* call init for supported macros */
 	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
 		if (priv->macro_params[macro_idx].init) {
@@ -888,19 +951,6 @@
 		}
 	}
 	priv->component = component;
-	/*
-	 * In order for the ADIE RTC to differentiate between targets
-	 * version info is used.
-	 * Assign 1.0 for target with only one macro
-	 * Assign 1.1 for target with two macros
-	 * Assign 1.2 for target with more than two macros
-	 */
-	if (priv->num_macros_registered == 1)
-		priv->version = BOLERO_VERSION_1_0;
-	else if (priv->num_macros_registered == 2)
-		priv->version = BOLERO_VERSION_1_1;
-	else if (priv->num_macros_registered > 2)
-		priv->version = BOLERO_VERSION_1_2;
 
 	ret = snd_event_client_register(priv->dev, &bolero_ssr_ops, priv);
 	if (!ret) {
@@ -1044,6 +1094,13 @@
 	if (priv->va_without_decimation)
 		bolero_reg_access[VA_MACRO] = bolero_va_top_reg_access;
 
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,bolero-version", &priv->version);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s:bolero version not specified\n",
+			__func__);
+		ret = 0;
+	}
 	priv->dev = &pdev->dev;
 	priv->dev_up = true;
 	priv->initial_boot = true;
diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h
index f104f88..2ec4617 100644
--- a/asoc/codecs/bolero/bolero-cdc.h
+++ b/asoc/codecs/bolero/bolero-cdc.h
@@ -8,6 +8,12 @@
 #include <sound/soc.h>
 #include <linux/regmap.h>
 
+#define BOLERO_VERSION_1_0 0x0001
+#define BOLERO_VERSION_1_1 0x0002
+#define BOLERO_VERSION_1_2 0x0003
+#define BOLERO_VERSION_2_0 0x0004
+#define BOLERO_VERSION_2_1 0x0005
+
 enum {
 	START_MACRO,
 	TX_MACRO = START_MACRO,
@@ -40,7 +46,8 @@
 	BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET,
 	BOLERO_MACRO_EVT_CLK_RESET,
 	BOLERO_MACRO_EVT_REG_WAKE_IRQ,
-	BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST
+	BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST,
+	BOLERO_MACRO_EVT_BCS_CLK_OFF
 };
 
 struct macro_ops {
@@ -85,6 +92,7 @@
 				   bool enable);
 void bolero_wsa_pa_on(struct device *dev);
 bool bolero_check_core_votes(struct device *dev);
+int bolero_get_version(struct device *dev);
 #else
 static inline int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb)
 {
@@ -164,5 +172,10 @@
 {
 	return false;
 }
+
+static int bolero_get_version(struct device *dev)
+{
+	return 0;
+}
 #endif /* CONFIG_SND_SOC_BOLERO */
 #endif /* BOLERO_CDC_H */
diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h
index d3f6894..ba89832 100644
--- a/asoc/codecs/bolero/internal.h
+++ b/asoc/codecs/bolero/internal.h
@@ -31,6 +31,7 @@
 	WCD_BOLERO_EVT_IMPED_TRUE,   /* for imped true */
 	WCD_BOLERO_EVT_IMPED_FALSE,  /* for imped false */
 	WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
+	WCD_BOLERO_EVT_BCS_CLK_OFF,
 };
 
 struct wcd_ctrl_platform_data {
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index ec71d4a..ffcd734 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -1350,10 +1350,8 @@
 			goto done;
 		reg = BOLERO_CDC_RX_COMPANDER0_CTL0 +
 				(rx_idx * RX_MACRO_COMP_OFFSET);
-		snd_soc_component_update_bits(component, reg,
-				0x20, 0x20);
-		snd_soc_component_update_bits(component, reg,
-				0x20, 0x00);
+		snd_soc_component_write(component, reg,
+				snd_soc_component_read32(component, reg));
 		break;
 	case BOLERO_MACRO_EVT_IMPED_TRUE:
 		rx_macro_wcd_clsh_imped_config(component, data, true);
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index ca88bfa..d27a5cf 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -160,6 +160,8 @@
 	s32 dmic_4_5_clk_cnt;
 	s32 dmic_6_7_clk_cnt;
 	u16 dmic_clk_div;
+	u32 version;
+	u32 is_used_tx_swr_gpio;
 	unsigned long active_ch_mask[TX_MACRO_MAX_DAIS];
 	unsigned long active_ch_cnt[TX_MACRO_MAX_DAIS];
 	char __iomem *tx_io_base;
@@ -172,6 +174,8 @@
 	int tx_clk_status;
 	bool bcs_enable;
 	int dec_mode[NUM_DECIMATORS];
+	bool bcs_clk_en;
+	bool hs_slow_insert_complete;
 };
 
 static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -387,6 +391,15 @@
 	case BOLERO_MACRO_EVT_CLK_RESET:
 		bolero_rsc_clk_reset(tx_dev, TX_CORE_CLK);
 		break;
+	case BOLERO_MACRO_EVT_BCS_CLK_OFF:
+		if (tx_priv->bcs_clk_en)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, data << 6);
+		if (data)
+			tx_priv->hs_slow_insert_complete = true;
+		else
+			tx_priv->hs_slow_insert_complete = false;
+		break;
 	}
 	return 0;
 }
@@ -450,10 +463,10 @@
 	snd_soc_component_update_bits(component,
 			dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
 			hpf_cut_off_freq << 5);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x02);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x02);
 	/* Minimum 1 clk cycle delay is required as per HW spec */
 	usleep_range(1000, 1010);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x01);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x00);
 }
 
 static void tx_macro_mute_update_callback(struct work_struct *work)
@@ -865,6 +878,10 @@
 			tx_vol_ctl_reg, 0x20, 0x20);
 		snd_soc_component_update_bits(component,
 			hpf_gate_reg, 0x01, 0x00);
+		/*
+		 * Minimum 1 clk cycle delay is required as per HW spec
+		 */
+		usleep_range(1000, 1010);
 
 		hpf_cut_off_freq = (
 			snd_soc_component_read32(component, dec_cfg_reg) &
@@ -887,7 +904,7 @@
 					&tx_priv->tx_hpf_work[decimator].dwork,
 					msecs_to_jiffies(300));
 			snd_soc_component_update_bits(component,
-					hpf_gate_reg, 0x02, 0x02);
+					hpf_gate_reg, 0x03, 0x03);
 			/*
 			 * Minimum 1 clk cycle delay is required as per HW spec
 			 */
@@ -902,8 +919,11 @@
 		if (tx_priv->bcs_enable) {
 			snd_soc_component_update_bits(component, dec_cfg_reg,
 					0x01, 0x01);
-			snd_soc_component_update_bits(component,
-				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x40);
+			tx_priv->bcs_clk_en = true;
+			if (tx_priv->hs_slow_insert_complete)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40,
+					0x40);
 		}
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
@@ -946,6 +966,7 @@
 					0x01, 0x00);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x00);
+			tx_priv->bcs_clk_en = false;
 		}
 		break;
 	}
@@ -1210,6 +1231,44 @@
 			0, smic_mux_text, snd_soc_dapm_get_enum_double,
 			tx_macro_put_dec_enum);
 
+static const char * const smic_mux_text_v2[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic0_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic1_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic2_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic3_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic4_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic5_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic6_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic7_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
 static const char * const dec_mode_mux_text[] = {
 	"ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF",
 };
@@ -1275,6 +1334,205 @@
 			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
 };
 
+static const struct snd_kcontrol_new tx_aif1_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif2_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif3_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_common[] = {
+	SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0),
+
+	TX_MACRO_DAPM_MUX("TX DMIC MUX0", 0, tx_dmic0),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX1", 0, tx_dmic1),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX2", 0, tx_dmic2),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX3", 0, tx_dmic3),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3_v2),
+
+	SND_SOC_DAPM_MICBIAS_E("TX MIC BIAS1", SND_SOC_NOPM, 0, 0,
+			       tx_macro_enable_micbias,
+			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("TX SWR_MIC0"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC1"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC2"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC3"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC4"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC5"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC6"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC7"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC8"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC9"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC10"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC11"),
+
+	SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC0, 0,
+			   &tx_dec0_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC1 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC1, 0,
+			   &tx_dec1_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC2 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC2, 0,
+			   &tx_dec2_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC3 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC3, 0,
+			   &tx_dec3_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v2[] = {
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF1_CAP, 0,
+		tx_aif1_cap_mixer_v2, ARRAY_SIZE(tx_aif1_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF2_CAP, 0,
+		tx_aif2_cap_mixer_v2, ARRAY_SIZE(tx_aif2_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer_v2, ARRAY_SIZE(tx_aif3_cap_mixer_v2)),
+
+	SND_SOC_DAPM_SUPPLY_S("TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			tx_macro_tx_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v3[] = {
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF1_CAP, 0,
+		tx_aif1_cap_mixer, ARRAY_SIZE(tx_aif1_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF2_CAP, 0,
+		tx_aif2_cap_mixer, ARRAY_SIZE(tx_aif2_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)),
+
+	TX_MACRO_DAPM_MUX("TX DMIC MUX4", 0, tx_dmic4),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX5", 0, tx_dmic5),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX6", 0, tx_dmic6),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX7", 0, tx_dmic7),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX4", 0, tx_smic4_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX5", 0, tx_smic5_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX6", 0, tx_smic6_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX7", 0, tx_smic7_v3),
+
+	SND_SOC_DAPM_MUX_E("TX DEC4 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC4, 0,
+			   &tx_dec4_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC5 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC5, 0,
+			   &tx_dec5_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC6 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC6, 0,
+			   &tx_dec6_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC7 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC7, 0,
+			   &tx_dec7_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			tx_macro_va_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
 static const struct snd_soc_dapm_widget tx_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0,
 		SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0),
@@ -1421,6 +1679,250 @@
 			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
+static const struct snd_soc_dapm_route tx_audio_map_common[] = {
+	{"TX_AIF1 CAP", NULL, "TX_MCLK"},
+	{"TX_AIF2 CAP", NULL, "TX_MCLK"},
+	{"TX_AIF3 CAP", NULL, "TX_MCLK"},
+
+	{"TX_AIF1 CAP", NULL, "TX_AIF1_CAP Mixer"},
+	{"TX_AIF2 CAP", NULL, "TX_AIF2_CAP Mixer"},
+	{"TX_AIF3 CAP", NULL, "TX_AIF3_CAP Mixer"},
+
+	{"TX_AIF1_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+
+	{"TX_AIF2_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+
+	{"TX_AIF3_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+
+	{"TX DEC0 MUX", NULL, "TX_MCLK"},
+	{"TX DEC1 MUX", NULL, "TX_MCLK"},
+	{"TX DEC2 MUX", NULL, "TX_MCLK"},
+	{"TX DEC3 MUX", NULL, "TX_MCLK"},
+
+	{"TX DEC0 MUX", "MSM_DMIC", "TX DMIC MUX0"},
+	{"TX DMIC MUX0", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX0", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX0", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX0", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX0", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX0", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX0", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX0", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"},
+	{"TX SMIC MUX0", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX0", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX0", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX0", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX0", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX0", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX0", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX0", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX0", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX0", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX0", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX0", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC1 MUX", "MSM_DMIC", "TX DMIC MUX1"},
+	{"TX DMIC MUX1", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX1", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX1", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX1", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX1", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX1", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX1", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX1", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"},
+	{"TX SMIC MUX1", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX1", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX1", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX1", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX1", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX1", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX1", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX1", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX1", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX1", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX1", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX1", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC2 MUX", "MSM_DMIC", "TX DMIC MUX2"},
+	{"TX DMIC MUX2", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX2", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX2", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX2", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX2", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX2", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX2", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX2", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"},
+	{"TX SMIC MUX2", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX2", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX2", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX2", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX2", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX2", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX2", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX2", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX2", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX2", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX2", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX2", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC3 MUX", "MSM_DMIC", "TX DMIC MUX3"},
+	{"TX DMIC MUX3", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX3", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX3", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX3", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX3", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX3", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX3", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX3", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"},
+	{"TX SMIC MUX3", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX3", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX3", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX3", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX3", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX3", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX3", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX3", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX3", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX3", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX3", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX3", "SWR_MIC11", "TX SWR_MIC11"},
+};
+
+static const struct snd_soc_dapm_route tx_audio_map_v3[] = {
+	{"TX_AIF1_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX_AIF2_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX_AIF3_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX DEC4 MUX", NULL, "TX_MCLK"},
+	{"TX DEC5 MUX", NULL, "TX_MCLK"},
+	{"TX DEC6 MUX", NULL, "TX_MCLK"},
+	{"TX DEC7 MUX", NULL, "TX_MCLK"},
+
+	{"TX DEC4 MUX", "MSM_DMIC", "TX DMIC MUX4"},
+	{"TX DMIC MUX4", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX4", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX4", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX4", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX4", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX4", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX4", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX4", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"},
+	{"TX SMIC MUX4", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX4", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX4", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX4", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX4", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX4", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX4", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX4", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX4", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX4", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX4", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX4", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC5 MUX", "MSM_DMIC", "TX DMIC MUX5"},
+	{"TX DMIC MUX5", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX5", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX5", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX5", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX5", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX5", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX5", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX5", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"},
+	{"TX SMIC MUX5", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX5", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX5", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX5", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX5", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX5", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX5", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX5", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX5", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX5", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX5", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX5", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC6 MUX", "MSM_DMIC", "TX DMIC MUX6"},
+	{"TX DMIC MUX6", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX6", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX6", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX6", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX6", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX6", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX6", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX6", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"},
+	{"TX SMIC MUX6", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX6", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX6", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX6", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX6", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX6", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX6", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX6", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX6", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX6", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX6", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX6", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC7 MUX", "MSM_DMIC", "TX DMIC MUX7"},
+	{"TX DMIC MUX7", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX7", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX7", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX7", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX7", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX7", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX7", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX7", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"},
+	{"TX SMIC MUX7", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX7", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX7", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX7", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX7", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX7", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX7", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX7", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX7", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX7", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX7", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX7", "SWR_MIC11", "TX SWR_MIC11"},
+};
+
 static const struct snd_soc_dapm_route tx_audio_map[] = {
 	{"TX_AIF1 CAP", NULL, "TX_MCLK"},
 	{"TX_AIF2 CAP", NULL, "TX_MCLK"},
@@ -1667,6 +2169,63 @@
 	{"TX SMIC MUX7", "SWR_DMIC7", "TX SWR_DMIC7"},
 };
 
+static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = {
+	SOC_SINGLE_SX_TLV("TX_DEC0 Volume",
+			  BOLERO_CDC_TX0_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC1 Volume",
+			  BOLERO_CDC_TX1_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC2 Volume",
+			  BOLERO_CDC_TX2_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC3 Volume",
+			  BOLERO_CDC_TX3_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0,
+		       tx_macro_get_bcs, tx_macro_set_bcs),
+};
+
+static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = {
+	SOC_SINGLE_SX_TLV("TX_DEC4 Volume",
+			  BOLERO_CDC_TX4_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC5 Volume",
+			  BOLERO_CDC_TX5_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC6 Volume",
+			  BOLERO_CDC_TX6_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC7 Volume",
+			  BOLERO_CDC_TX7_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+};
+
 static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
 	SOC_SINGLE_SX_TLV("TX_DEC0 Volume",
 			  BOLERO_CDC_TX0_TX_VOL_CTL,
@@ -2126,18 +2685,65 @@
 			"%s: priv is null for macro!\n", __func__);
 		return -EINVAL;
 	}
-	ret = snd_soc_dapm_new_controls(dapm, tx_macro_dapm_widgets,
+	tx_priv->version = bolero_get_version(tx_dev);
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_common,
+				ARRAY_SIZE(tx_macro_dapm_widgets_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_1)
+			ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_v2,
+				ARRAY_SIZE(tx_macro_dapm_widgets_v2));
+		else if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_v3,
+				ARRAY_SIZE(tx_macro_dapm_widgets_v3));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_new_controls(dapm, tx_macro_dapm_widgets,
 					ARRAY_SIZE(tx_macro_dapm_widgets));
-	if (ret < 0) {
-		dev_err(tx_dev, "%s: Failed to add controls\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
 	}
 
-	ret = snd_soc_dapm_add_routes(dapm, tx_audio_map,
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_common,
+					ARRAY_SIZE(tx_audio_map_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_v3,
+					ARRAY_SIZE(tx_audio_map_v3));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_add_routes(dapm, tx_audio_map,
 					ARRAY_SIZE(tx_audio_map));
-	if (ret < 0) {
-		dev_err(tx_dev, "%s: Failed to add routes\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	ret = snd_soc_dapm_new_widgets(dapm->card);
@@ -2146,28 +2752,65 @@
 		return ret;
 	}
 
-	ret = snd_soc_add_component_controls(component, tx_macro_snd_controls,
-				   ARRAY_SIZE(tx_macro_snd_controls));
-	if (ret < 0) {
-		dev_err(tx_dev, "%s: Failed to add snd_ctls\n", __func__);
-		return ret;
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_add_component_controls(component,
+			tx_macro_snd_controls_common,
+			ARRAY_SIZE(tx_macro_snd_controls_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_add_component_controls(component,
+				tx_macro_snd_controls_v3,
+				ARRAY_SIZE(tx_macro_snd_controls_v3));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_add_component_controls(component,
+				tx_macro_snd_controls,
+				ARRAY_SIZE(tx_macro_snd_controls));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF1 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF2 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF3 Capture");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC0");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC1");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC2");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC3");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC0");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC1");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC2");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC3");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC4");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC5");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC6");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC7");
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC7");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC8");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC9");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC10");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC11");
+	} else {
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC7");
+	}
 	snd_soc_dapm_sync(dapm);
 
 	for (i = 0; i < NUM_DECIMATORS; i++) {
@@ -2423,19 +3066,21 @@
 		sample_rate, tx_priv) == TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED)
 			return -EINVAL;
 	}
-	tx_priv->reset_swr = true;
-	INIT_WORK(&tx_priv->tx_macro_add_child_devices_work,
-		  tx_macro_add_child_devices);
-	tx_priv->swr_plat_data.handle = (void *) tx_priv;
-	tx_priv->swr_plat_data.read = NULL;
-	tx_priv->swr_plat_data.write = NULL;
-	tx_priv->swr_plat_data.bulk_write = NULL;
-	tx_priv->swr_plat_data.clk = tx_macro_swrm_clock;
-	tx_priv->swr_plat_data.core_vote = tx_macro_core_vote;
-	tx_priv->swr_plat_data.handle_irq = NULL;
-
+	if (is_used_tx_swr_gpio) {
+		tx_priv->reset_swr = true;
+		INIT_WORK(&tx_priv->tx_macro_add_child_devices_work,
+			  tx_macro_add_child_devices);
+		tx_priv->swr_plat_data.handle = (void *) tx_priv;
+		tx_priv->swr_plat_data.read = NULL;
+		tx_priv->swr_plat_data.write = NULL;
+		tx_priv->swr_plat_data.bulk_write = NULL;
+		tx_priv->swr_plat_data.clk = tx_macro_swrm_clock;
+		tx_priv->swr_plat_data.core_vote = tx_macro_core_vote;
+		tx_priv->swr_plat_data.handle_irq = NULL;
+		mutex_init(&tx_priv->swr_clk_lock);
+	}
+	tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio;
 	mutex_init(&tx_priv->mclk_lock);
-	mutex_init(&tx_priv->swr_clk_lock);
 	tx_macro_init_ops(&ops, tx_io_base);
 	ops.clk_id_req = TX_CORE_CLK;
 	ops.default_clk_id = TX_CORE_CLK;
@@ -2445,8 +3090,8 @@
 			"%s: register macro failed\n", __func__);
 		goto err_reg_macro;
 	}
-
-	schedule_work(&tx_priv->tx_macro_add_child_devices_work);
+	if (is_used_tx_swr_gpio)
+		schedule_work(&tx_priv->tx_macro_add_child_devices_work);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
@@ -2456,7 +3101,8 @@
 	return 0;
 err_reg_macro:
 	mutex_destroy(&tx_priv->mclk_lock);
-	mutex_destroy(&tx_priv->swr_clk_lock);
+	if (is_used_tx_swr_gpio)
+		mutex_destroy(&tx_priv->swr_clk_lock);
 	return ret;
 }
 
@@ -2470,16 +3116,20 @@
 	if (!tx_priv)
 		return -EINVAL;
 
-	if (tx_priv->swr_ctrl_data)
-		kfree(tx_priv->swr_ctrl_data);
-	for (count = 0; count < tx_priv->child_count &&
-		count < TX_MACRO_CHILD_DEVICES_MAX; count++)
-		platform_device_unregister(tx_priv->pdev_child_devices[count]);
+	if (tx_priv->is_used_tx_swr_gpio) {
+		if (tx_priv->swr_ctrl_data)
+			kfree(tx_priv->swr_ctrl_data);
+		for (count = 0; count < tx_priv->child_count &&
+			count < TX_MACRO_CHILD_DEVICES_MAX; count++)
+			platform_device_unregister(
+				tx_priv->pdev_child_devices[count]);
+	}
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	mutex_destroy(&tx_priv->mclk_lock);
-	mutex_destroy(&tx_priv->swr_clk_lock);
+	if (tx_priv->is_used_tx_swr_gpio)
+		mutex_destroy(&tx_priv->swr_clk_lock);
 	bolero_unregister_macro(&pdev->dev, TX_MACRO);
 	return 0;
 }
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index 782c00e..c5f0ef9 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -13,6 +13,9 @@
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
 #include <linux/pm_runtime.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
 #include "bolero-cdc.h"
 #include "bolero-cdc-registers.h"
 #include "bolero-clk-rsc.h"
@@ -46,6 +49,9 @@
 #define BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS	40
 #define MAX_RETRY_ATTEMPTS 500
 
+#define VA_MACRO_SWR_STRING_LEN 80
+#define VA_MACRO_CHILD_DEVICES_MAX 3
+
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static int va_tx_unmute_delay = BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS;
 module_param(va_tx_unmute_delay, int, 0664);
@@ -85,6 +91,11 @@
 	SWR_MIC,
 };
 
+enum {
+	TX_MCLK,
+	VA_MCLK,
+};
+
 struct va_mute_work {
 	struct va_macro_priv *va_priv;
 	u32 decimator;
@@ -98,12 +109,31 @@
 	struct delayed_work dwork;
 };
 
+/* Hold instance to soundwire platform device */
+struct va_macro_swr_ctrl_data {
+	struct platform_device *va_swr_pdev;
+};
+
+struct va_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
 struct va_macro_priv {
 	struct device *dev;
 	bool dec_active[VA_MACRO_NUM_DECIMATORS];
 	bool va_without_decimation;
 	struct clk *lpass_audio_hw_vote;
 	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
 	struct snd_soc_component *component;
 	struct hpf_work va_hpf_work[VA_MACRO_NUM_DECIMATORS];
 	struct va_mute_work va_mute_dwork[VA_MACRO_NUM_DECIMATORS];
@@ -115,15 +145,29 @@
 	s32 dmic_6_7_clk_cnt;
 	u16 dmic_clk_div;
 	u16 va_mclk_users;
+	int swr_clk_users;
+	bool reset_swr;
+	struct device_node *va_swr_gpio_p;
+	struct va_macro_swr_ctrl_data *swr_ctrl_data;
+	struct va_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct va_macro_add_child_devices_work;
+	int child_count;
 	u16 mclk_mux_sel;
 	char __iomem *va_io_base;
 	char __iomem *va_island_mode_muxsel;
+	struct platform_device *pdev_child_devices
+			[VA_MACRO_CHILD_DEVICES_MAX];
 	struct regulator *micb_supply;
 	u32 micb_voltage;
 	u32 micb_current;
+	u32 version;
+	u32 is_used_va_swr_gpio;
 	int micb_users;
 	u16 default_clk_id;
 	u16 clk_id;
+	int tx_swr_clk_cnt;
+	int va_swr_clk_cnt;
+	int va_clk_status;
 	int tx_clk_status;
 };
 
@@ -249,10 +293,25 @@
 			bolero_clk_rsc_request_clock(va_priv->dev,
 						va_priv->default_clk_id,
 						VA_CORE_CLK, false);
+		/* reset swr after ssr/pdr */
+		va_priv->reset_swr = true;
+		if (va_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
 	case BOLERO_MACRO_EVT_CLK_RESET:
 		bolero_rsc_clk_reset(va_dev, VA_CORE_CLK);
 		break;
 	case BOLERO_MACRO_EVT_SSR_DOWN:
+		if (va_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_DOWN, NULL);
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
 		if ((!pm_runtime_enabled(va_dev) ||
 		     !pm_runtime_suspended(va_dev))) {
 			ret = bolero_runtime_suspend(va_dev);
@@ -269,6 +328,54 @@
 	return 0;
 }
 
+static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int ret = 0;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		va_priv->va_swr_clk_cnt++;
+		if (va_priv->swr_ctrl_data) {
+			ret = swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_REQ_CLK_SWITCH, NULL);
+			if (ret)
+				dev_dbg(va_dev, "%s: clock switch failed\n",
+					__func__);
+		}
+		msm_cdc_pinctrl_set_wakeup_capable(
+				va_priv->va_swr_gpio_p, false);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		msm_cdc_pinctrl_set_wakeup_capable(
+				va_priv->va_swr_gpio_p, true);
+		if (va_priv->swr_ctrl_data) {
+			ret = swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_REQ_CLK_SWITCH, NULL);
+			if (ret)
+				dev_dbg(va_dev, "%s: clock switch failed\n",
+					__func__);
+		}
+		va_priv->va_swr_clk_cnt--;
+		break;
+	default:
+		dev_err(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
 static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -312,6 +419,25 @@
 	return ret;
 }
 
+static int va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		++va_priv->tx_swr_clk_cnt;
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		--va_priv->tx_swr_clk_cnt;
+
+	return 0;
+}
+
 static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -355,6 +481,204 @@
 	return ret;
 }
 
+static int va_macro_tx_va_mclk_enable(struct va_macro_priv *va_priv,
+				      struct regmap *regmap, int clk_type,
+				      bool enable)
+{
+	int ret = 0, clk_tx_ret = 0;
+
+	dev_dbg(va_priv->dev,
+		"%s: clock type %s, enable: %s tx_mclk_users: %d\n",
+		__func__, (clk_type ? "VA_MCLK" : "TX_MCLK"),
+		(enable ? "enable" : "disable"), va_priv->va_mclk_users);
+
+	if (enable) {
+		if (va_priv->swr_clk_users == 0)
+			msm_cdc_pinctrl_select_active_state(
+						va_priv->va_swr_gpio_p);
+		clk_tx_ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		if (clk_type == TX_MCLK) {
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+			bolero_clk_rsc_fs_gen_request(va_priv->dev,
+						  true);
+		}
+		if (clk_type == VA_MCLK) {
+			ret = va_macro_mclk_enable(va_priv, 1, true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: request clock enable failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (va_priv->swr_clk_users == 0) {
+			dev_dbg(va_priv->dev, "%s: reset_swr: %d\n",
+				__func__, va_priv->reset_swr);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			va_priv->reset_swr = false;
+		}
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		va_priv->swr_clk_users++;
+	} else {
+		if (va_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"va swrm clock users already 0\n");
+			va_priv->swr_clk_users = 0;
+			return 0;
+		}
+		clk_tx_ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		va_priv->swr_clk_users--;
+		if (va_priv->swr_clk_users == 0)
+			regmap_update_bits(regmap,
+				BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+		if (clk_type == VA_MCLK)
+			va_macro_mclk_enable(va_priv, 0, true);
+		if (clk_type == TX_MCLK) {
+			bolero_clk_rsc_fs_gen_request(va_priv->dev,
+						  false);
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   false);
+			if (ret < 0) {
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		if (va_priv->swr_clk_users == 0)
+			msm_cdc_pinctrl_select_sleep_state(
+						va_priv->va_swr_gpio_p);
+	}
+	return 0;
+
+done:
+	if (!clk_tx_ret)
+		bolero_clk_rsc_request_clock(va_priv->dev,
+				TX_CORE_CLK,
+				TX_CORE_CLK,
+				false);
+	return ret;
+}
+
+static int va_macro_swrm_clock(void *handle, bool enable)
+{
+	struct va_macro_priv *va_priv = (struct va_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(va_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&va_priv->swr_clk_lock);
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n",
+		__func__, (enable ? "enable" : "disable"),
+		va_priv->tx_swr_clk_cnt, va_priv->va_swr_clk_cnt);
+
+	if (enable) {
+		pm_runtime_get_sync(va_priv->dev);
+		if (va_priv->va_swr_clk_cnt && !va_priv->tx_swr_clk_cnt) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			va_priv->va_clk_status++;
+		} else {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			va_priv->tx_clk_status++;
+		}
+		pm_runtime_mark_last_busy(va_priv->dev);
+		pm_runtime_put_autosuspend(va_priv->dev);
+	} else {
+		if (va_priv->va_clk_status && !va_priv->tx_clk_status) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->va_clk_status;
+		} else if (!va_priv->va_clk_status && va_priv->tx_clk_status) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->tx_clk_status;
+		} else if (va_priv->va_clk_status && va_priv->tx_clk_status) {
+			if (!va_priv->va_swr_clk_cnt && va_priv->tx_swr_clk_cnt) {
+				ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+								VA_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->va_clk_status;
+			} else {
+				ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+								TX_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->tx_clk_status;
+			}
+
+		} else {
+			dev_dbg(va_priv->dev,
+				"%s: Both clocks are disabled\n", __func__);
+		}
+	}
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock users %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n",
+		__func__, va_priv->swr_clk_users, va_priv->tx_clk_status,
+		va_priv->va_clk_status);
+done:
+	mutex_unlock(&va_priv->swr_clk_lock);
+	return ret;
+}
+
 static void va_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
 {
 	struct delayed_work *hpf_delayed_work;
@@ -395,10 +719,10 @@
 	snd_soc_component_update_bits(component,
 			dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
 			hpf_cut_off_freq << 5);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x02);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x02);
 	/* Minimum 1 clk cycle delay is required as per HW spec */
 	usleep_range(1000, 1010);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x01);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x00);
 }
 
 static void va_macro_mute_update_callback(struct work_struct *work)
@@ -690,6 +1014,10 @@
 				tx_vol_ctl_reg, 0x20, 0x20);
 		snd_soc_component_update_bits(component,
 				hpf_gate_reg, 0x01, 0x00);
+		/*
+		 * Minimum 1 clk cycle delay is required as per HW spec
+		 */
+		usleep_range(1000, 1010);
 
 		hpf_cut_off_freq = (snd_soc_component_read32(
 					component, dec_cfg_reg) &
@@ -702,7 +1030,7 @@
 					    TX_HPF_CUT_OFF_FREQ_MASK,
 					    CF_MIN_3DB_150HZ << 5);
 			snd_soc_component_update_bits(component,
-					hpf_gate_reg, 0x02, 0x02);
+					hpf_gate_reg, 0x03, 0x03);
 			/*
 			 * Minimum 1 clk cycle delay is required as per HW spec
 			 */
@@ -1122,6 +1450,28 @@
 			0, smic_mux_text, snd_soc_dapm_get_enum_double,
 			va_macro_put_dec_enum);
 
+static const char * const smic_mux_text_v2[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic0_v2, BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic1_v2, BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic2_v3, BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic3_v3, BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
 static const struct snd_kcontrol_new va_aif1_cap_mixer[] = {
 	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
 			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
@@ -1179,6 +1529,202 @@
 			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
 };
 
+static const struct snd_kcontrol_new va_aif1_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif1_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_common[] = {
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF2 CAP", "VA_AIF2 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF2_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF3 CAP", "VA_AIF3 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF3_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	VA_MACRO_DAPM_MUX("VA DMIC MUX0", 0, va_dmic0),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX1", 0, va_dmic1),
+
+	VA_MACRO_DAPM_MUX("VA SMIC MUX0", 0, va_smic0_v2),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX1", 0, va_smic1_v2),
+
+	SND_SOC_DAPM_INPUT("VA SWR_MIC0"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC1"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC2"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC3"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC4"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC5"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC6"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC7"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC8"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC9"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC10"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC11"),
+
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+			       va_macro_enable_micbias,
+			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, VA_MACRO_DEC0, 0,
+			   &va_dec0_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("VA DEC1 MUX", SND_SOC_NOPM, VA_MACRO_DEC1, 0,
+			   &va_dec1_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_mclk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v2[] = {
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer_v2, ARRAY_SIZE(va_aif1_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer_v2, ARRAY_SIZE(va_aif2_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer_v2, ARRAY_SIZE(va_aif3_cap_mixer_v2)),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_pwr_event_v2,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			      va_macro_tx_swr_clk_event_v2,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = {
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer_v3, ARRAY_SIZE(va_aif1_cap_mixer_v3)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer_v3, ARRAY_SIZE(va_aif2_cap_mixer_v3)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer_v3, ARRAY_SIZE(va_aif3_cap_mixer_v3)),
+
+	VA_MACRO_DAPM_MUX("VA DMIC MUX2", 0, va_dmic2),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX3", 0, va_dmic3),
+
+	VA_MACRO_DAPM_MUX("VA SMIC MUX2", 0, va_smic2_v3),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX3", 0, va_smic3_v3),
+
+	SND_SOC_DAPM_MUX_E("VA DEC2 MUX", SND_SOC_NOPM, VA_MACRO_DEC2, 0,
+			   &va_dec2_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("VA DEC3 MUX", SND_SOC_NOPM, VA_MACRO_DEC3, 0,
+			   &va_dec3_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_pwr_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
 static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0,
 		SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0,
@@ -1329,6 +1875,146 @@
 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
+static const struct snd_soc_dapm_route va_audio_map_common[] = {
+	{"VA_AIF1 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF2 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF3 CAP", NULL, "VA_MCLK"},
+
+	{"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"},
+	{"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"},
+	{"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"},
+
+	{"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA DEC0 MUX", "MSM_DMIC", "VA DMIC MUX0"},
+	{"VA DMIC MUX0", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX0", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX0", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX0", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX0", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX0", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX0", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX0", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"},
+	{"VA SMIC MUX0", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX0", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX0", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX0", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX0", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX0", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX0", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX0", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX0", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX0", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX0", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX0", "SWR_MIC11", "VA SWR_MIC11"},
+
+	{"VA DEC1 MUX", "MSM_DMIC", "VA DMIC MUX1"},
+	{"VA DMIC MUX1", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX1", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX1", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX1", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX1", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX1", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX1", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX1", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"},
+	{"VA SMIC MUX1", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX1", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX1", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX1", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX1", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX1", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX1", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX1", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX1", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX1", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX1", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX1", "SWR_MIC11", "VA SWR_MIC11"},
+
+	{"VA SWR_MIC0", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC1", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC2", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC3", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC4", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC5", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC6", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC7", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC8", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC9", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC10", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC11", NULL, "VA_SWR_PWR"},
+
+};
+
+static const struct snd_soc_dapm_route va_audio_map_v3[] = {
+	{"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA DEC2 MUX", "MSM_DMIC", "VA DMIC MUX2"},
+	{"VA DMIC MUX2", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX2", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX2", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX2", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX2", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX2", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX2", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX2", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"},
+	{"VA SMIC MUX2", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX2", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX2", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX2", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX2", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX2", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX2", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX2", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX2", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX2", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX2", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX2", "SWR_MIC11", "VA SWR_MIC11"},
+
+	{"VA DEC3 MUX", "MSM_DMIC", "VA DMIC MUX3"},
+	{"VA DMIC MUX3", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX3", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX3", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX3", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX3", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX3", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX3", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX3", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"},
+	{"VA SMIC MUX3", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX3", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX3", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX3", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX3", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX3", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX3", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX3", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX3", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX3", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX3", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX3", "SWR_MIC11", "VA SWR_MIC11"},
+};
+
 static const struct snd_soc_dapm_route va_audio_map[] = {
 	{"VA_AIF1 CAP", NULL, "VA_MCLK"},
 	{"VA_AIF2 CAP", NULL, "VA_MCLK"},
@@ -1590,6 +2276,24 @@
 			  0, -84, 40, digital_gain),
 };
 
+static const struct snd_kcontrol_new va_macro_snd_controls_common[] = {
+	SOC_SINGLE_SX_TLV("VA_DEC0 Volume",
+			  BOLERO_CDC_VA_TX0_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("VA_DEC1 Volume",
+			  BOLERO_CDC_VA_TX1_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+};
+
+static const struct snd_kcontrol_new va_macro_snd_controls_v3[] = {
+	SOC_SINGLE_SX_TLV("VA_DEC2 Volume",
+			  BOLERO_CDC_VA_TX2_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("VA_DEC3 Volume",
+			  BOLERO_CDC_VA_TX3_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+};
+
 static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
 				      struct va_macro_priv *va_priv)
 {
@@ -1674,18 +2378,65 @@
 		return 0;
 	}
 
-	ret = snd_soc_dapm_new_controls(dapm, va_macro_dapm_widgets,
+	va_priv->version = bolero_get_version(va_dev);
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_common,
+				ARRAY_SIZE(va_macro_dapm_widgets_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_1)
+			ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_v2,
+				ARRAY_SIZE(va_macro_dapm_widgets_v2));
+		else if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_v3,
+				ARRAY_SIZE(va_macro_dapm_widgets_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_new_controls(dapm, va_macro_dapm_widgets,
 					ARRAY_SIZE(va_macro_dapm_widgets));
-	if (ret < 0) {
-		dev_err(va_dev, "%s: Failed to add controls\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
 	}
 
-	ret = snd_soc_dapm_add_routes(dapm, va_audio_map,
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_add_routes(dapm,
+					va_audio_map_common,
+					ARRAY_SIZE(va_audio_map_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_add_routes(dapm,
+					va_audio_map_v3,
+					ARRAY_SIZE(va_audio_map_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_add_routes(dapm, va_audio_map,
 					ARRAY_SIZE(va_audio_map));
-	if (ret < 0) {
-		dev_err(va_dev, "%s: Failed to add routes\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	ret = snd_soc_dapm_new_widgets(dapm->card);
@@ -1693,28 +2444,65 @@
 		dev_err(va_dev, "%s: Failed to add widgets\n", __func__);
 		return ret;
 	}
-	ret = snd_soc_add_component_controls(component, va_macro_snd_controls,
-				   ARRAY_SIZE(va_macro_snd_controls));
-	if (ret < 0) {
-		dev_err(va_dev, "%s: Failed to add snd_ctls\n", __func__);
-		return ret;
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_add_component_controls(component,
+				va_macro_snd_controls_common,
+				ARRAY_SIZE(va_macro_snd_controls_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_add_component_controls(component,
+					va_macro_snd_controls_v3,
+					ARRAY_SIZE(va_macro_snd_controls_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_add_component_controls(component,
+				va_macro_snd_controls,
+				ARRAY_SIZE(va_macro_snd_controls));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF1 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF2 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF3 Capture");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC0");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC1");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC2");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC3");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7");
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC8");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC9");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC10");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC11");
+	} else {
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7");
+	}
 	snd_soc_dapm_sync(dapm);
 
 	for (i = 0; i < VA_MACRO_NUM_DECIMATORS; i++) {
@@ -1747,6 +2535,156 @@
 	return 0;
 }
 
+static void va_macro_add_child_devices(struct work_struct *work)
+{
+	struct va_macro_priv *va_priv = NULL;
+	struct platform_device *pdev = NULL;
+	struct device_node *node = NULL;
+	struct va_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL;
+	int ret = 0;
+	u16 count = 0, ctrl_num = 0;
+	struct va_macro_swr_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[VA_MACRO_SWR_STRING_LEN] = "";
+	bool va_swr_master_node = false;
+
+	va_priv = container_of(work, struct va_macro_priv,
+			     va_macro_add_child_devices_work);
+	if (!va_priv) {
+		pr_err("%s: Memory for va_priv does not exist\n",
+			__func__);
+		return;
+	}
+
+	if (!va_priv->dev) {
+		pr_err("%s: VA dev does not exist\n", __func__);
+		return;
+	}
+
+	if (!va_priv->dev->of_node) {
+		dev_err(va_priv->dev,
+			"%s: DT node for va_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &va_priv->swr_plat_data;
+	va_priv->child_count = 0;
+
+	for_each_available_child_of_node(va_priv->dev->of_node, node) {
+		va_swr_master_node = false;
+		if (strnstr(node->name, "va_swr_master",
+                                strlen("va_swr_master")) != NULL)
+			va_swr_master_node = true;
+
+		if (va_swr_master_node)
+			strlcpy(plat_dev_name, "va_swr_ctrl",
+				(VA_MACRO_SWR_STRING_LEN - 1));
+		else
+			strlcpy(plat_dev_name, node->name,
+				(VA_MACRO_SWR_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(va_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = va_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (va_swr_master_node) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (va_swr_master_node) {
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct va_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].va_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Added soundwire ctrl device(s)\n",
+				__func__);
+			va_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+		if (va_priv->child_count < VA_MACRO_CHILD_DEVICES_MAX)
+			va_priv->pdev_child_devices[
+					va_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < va_priv->child_count; count++)
+		platform_device_put(va_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static int va_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static int va_macro_reg_wake_irq(struct snd_soc_component *component,
+				 u32 data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	u32 ipc_wakeup = data;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_REGISTER_WAKE_IRQ, &ipc_wakeup);
+
+	return ret;
+}
+
 static void va_macro_init_ops(struct macro_ops *ops,
 			      char __iomem *va_io_base,
 			      bool va_without_decimation)
@@ -1763,6 +2701,8 @@
 	ops->exit = va_macro_deinit;
 	ops->io_base = va_io_base;
 	ops->event_handler = va_macro_event_handler;
+	ops->set_port_map = va_macro_set_port_map;
+	ops->reg_wake_irq = va_macro_reg_wake_irq;
 }
 
 static int va_macro_probe(struct platform_device *pdev)
@@ -1780,6 +2720,8 @@
 	const char *dmic_sample_rate = "qcom,va-dmic-sample-rate";
 	u32 default_clk_id = 0;
 	struct clk *lpass_audio_hw_vote = NULL;
+	u32 is_used_va_swr_gpio = 0;
+	const char *is_used_va_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
 	va_priv = devm_kzalloc(&pdev->dev, sizeof(struct va_macro_priv),
 			    GFP_KERNEL);
@@ -1810,6 +2752,31 @@
 			return -EINVAL;
 	}
 
+	if (of_find_property(pdev->dev.of_node, is_used_va_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_va_swr_gpio_dt,
+					   &is_used_va_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_va_swr_gpio_dt);
+			is_used_va_swr_gpio = 0;
+		}
+	}
+	va_priv->va_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,va-swr-gpios", 0);
+	if (!va_priv->va_swr_gpio_p && is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if ((msm_cdc_pinctrl_get_state(va_priv->va_swr_gpio_p) < 0) &&
+		is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
 	va_io_base = devm_ioremap(&pdev->dev, va_base_addr,
 				  VA_MACRO_MAX_OFFSET);
 	if (!va_io_base) {
@@ -1869,6 +2836,20 @@
 	va_priv->clk_id = VA_CORE_CLK;
 	va_priv->default_clk_id = default_clk_id;
 
+	if (is_used_va_swr_gpio) {
+		va_priv->reset_swr = true;
+		INIT_WORK(&va_priv->va_macro_add_child_devices_work,
+			  va_macro_add_child_devices);
+		va_priv->swr_plat_data.handle = (void *) va_priv;
+		va_priv->swr_plat_data.read = NULL;
+		va_priv->swr_plat_data.write = NULL;
+		va_priv->swr_plat_data.bulk_write = NULL;
+		va_priv->swr_plat_data.clk = va_macro_swrm_clock;
+		va_priv->swr_plat_data.handle_irq = NULL;
+		mutex_init(&va_priv->swr_clk_lock);
+	}
+	va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio;
+
 	mutex_init(&va_priv->mclk_lock);
 	dev_set_drvdata(&pdev->dev, va_priv);
 	va_macro_init_ops(&ops, va_io_base, va_without_decimation);
@@ -1879,29 +2860,46 @@
 		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
 		goto reg_macro_fail;
 	}
+	if (is_used_va_swr_gpio)
+		schedule_work(&va_priv->va_macro_add_child_devices_work);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, VA_AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
 	pm_runtime_enable(&pdev->dev);
 	return ret;
 
 reg_macro_fail:
 	mutex_destroy(&va_priv->mclk_lock);
+	if (is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
 	return ret;
 }
 
 static int va_macro_remove(struct platform_device *pdev)
 {
 	struct va_macro_priv *va_priv;
+	int count = 0;
 
 	va_priv = dev_get_drvdata(&pdev->dev);
 
 	if (!va_priv)
 		return -EINVAL;
+	if (va_priv->is_used_va_swr_gpio) {
+		if (va_priv->swr_ctrl_data)
+			kfree(va_priv->swr_ctrl_data);
+		for (count = 0; count < va_priv->child_count &&
+			count < VA_MACRO_CHILD_DEVICES_MAX; count++)
+			platform_device_unregister(
+				va_priv->pdev_child_devices[count]);
+	}
+
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	bolero_unregister_macro(&pdev->dev, VA_MACRO);
 	mutex_destroy(&va_priv->mclk_lock);
+	if (va_priv->is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
 	return 0;
 }
 
diff --git a/asoc/codecs/msm-cdc-pinctrl.c b/asoc/codecs/msm-cdc-pinctrl.c
index a10a681..cb7a52b 100644
--- a/asoc/codecs/msm-cdc-pinctrl.c
+++ b/asoc/codecs/msm-cdc-pinctrl.c
@@ -4,6 +4,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -23,8 +24,12 @@
 	int gpio;
 	bool state;
 	u32 tlmm_gpio[MAX_GPIOS];
+	char __iomem *chip_wakeup_register[MAX_GPIOS];
+	u32 chip_wakeup_maskbit[MAX_GPIOS];
 	u32 count;
+	u32 wakeup_reg_count;
 	bool wakeup_capable;
+	bool chip_wakeup_reg;
 };
 
 static struct msm_cdc_pinctrl_info *msm_cdc_pinctrl_get_gpiodata(
@@ -154,7 +159,7 @@
 {
 	struct msm_cdc_pinctrl_info *gpio_data;
 	int ret = 0;
-	u32 i = 0;
+	u32 i = 0, temp = 0;
 
 	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
 	if (!gpio_data)
@@ -168,6 +173,18 @@
 				goto exit;
 		}
 	}
+	if (gpio_data->chip_wakeup_reg) {
+		for (i = 0; i < gpio_data->wakeup_reg_count; i++) {
+			temp = ioread32(gpio_data->chip_wakeup_register[i]);
+			if (enable)
+				temp |= (1 <<
+					 gpio_data->chip_wakeup_maskbit[i]);
+			else
+				temp &= ~(1 <<
+					  gpio_data->chip_wakeup_maskbit[i]);
+			iowrite32(temp, gpio_data->chip_wakeup_register[i]);
+		}
+	}
 exit:
 	return ret;
 }
@@ -178,6 +195,7 @@
 	int ret = 0;
 	struct msm_cdc_pinctrl_info *gpio_data;
 	u32 tlmm_gpio[MAX_GPIOS] = {0};
+	u32 chip_wakeup_reg[MAX_GPIOS] = {0};
 	u32 i = 0;
 	int count = 0;
 
@@ -223,6 +241,27 @@
 	}
 
 
+	count = of_property_count_u32_elems(pdev->dev.of_node, "qcom,chip-wakeup-reg");
+	if (count <= 0)
+		goto cdc_tlmm_gpio;
+	if (!of_property_read_u32_array(pdev->dev.of_node, "qcom,chip-wakeup-reg",
+				chip_wakeup_reg, count)) {
+		if (of_property_read_u32_array(pdev->dev.of_node,
+					   "qcom,chip-wakeup-maskbit",
+					   gpio_data->chip_wakeup_maskbit, count)) {
+			dev_err(&pdev->dev,
+				"chip-wakeup-maskbit needed if chip-wakeup-reg is defined!\n");
+			goto cdc_tlmm_gpio;
+		}
+		gpio_data->chip_wakeup_reg = true;
+		for (i = 0; i < count; i++) {
+			gpio_data->chip_wakeup_register[i] =
+				devm_ioremap(&pdev->dev, chip_wakeup_reg[i], 0x4);
+		}
+		gpio_data->wakeup_reg_count = count;
+	}
+
+cdc_tlmm_gpio:
 	count = of_property_count_u32_elems(pdev->dev.of_node, "qcom,tlmm-gpio");
 	if (count <= 0)
 		goto cdc_rst;
diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c
index 4de19de..9652d11 100644
--- a/asoc/codecs/wcd-mbhc-adc.c
+++ b/asoc/codecs/wcd-mbhc-adc.c
@@ -689,6 +689,13 @@
 	}
 
 correct_plug_type:
+	/*
+	 * Callback to disable BCS slow insertion detection
+	 */
+	if (plug_type == MBHC_PLUG_TYPE_HEADSET ||
+	    plug_type == MBHC_PLUG_TYPE_HEADPHONE)
+		mbhc->mbhc_cb->bcs_enable(mbhc, false);
+
 	timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
 	while (!time_after(jiffies, timeout)) {
 		if (mbhc->hs_detect_work_stop) {
@@ -833,6 +840,10 @@
 			wrk_complete = false;
 		}
 	}
+	if ((plug_type == MBHC_PLUG_TYPE_HEADSET ||
+	    plug_type == MBHC_PLUG_TYPE_HEADPHONE))
+		mbhc->mbhc_cb->bcs_enable(mbhc, true);
+
 	if (!wrk_complete) {
 		/*
 		 * If plug_tye is headset, we might have already reported either
diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c
index 01544aa..ed98deb 100644
--- a/asoc/codecs/wcd-mbhc-v2.c
+++ b/asoc/codecs/wcd-mbhc-v2.c
@@ -1055,6 +1055,10 @@
 	struct wcd_mbhc *mbhc = data;
 
 	pr_debug("%s: enter\n", __func__);
+	if (mbhc == NULL) {
+		pr_err("%s: NULL irq data\n", __func__);
+		return IRQ_NONE;
+	}
 	if (unlikely((mbhc->mbhc_cb->lock_sleep(mbhc, true)) == false)) {
 		pr_warn("%s: failed to hold suspend\n", __func__);
 		r = IRQ_NONE;
diff --git a/asoc/codecs/wcd-spi.c b/asoc/codecs/wcd-spi.c
index 0173e15..4c7a853 100644
--- a/asoc/codecs/wcd-spi.c
+++ b/asoc/codecs/wcd-spi.c
@@ -815,6 +815,15 @@
 		return -EINVAL;
 	}
 
+	WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex);
+	if (wcd_spi_is_suspended(wcd_spi)) {
+		dev_dbg(&spi->dev,
+			"%s: SPI suspended, cannot perform transfer\n",
+			__func__);
+		ret = -EIO;
+		goto done;
+	}
+
 	WCD_SPI_MUTEX_LOCK(spi, wcd_spi->xfer_mutex);
 	if (msg->len == WCD_SPI_WORD_BYTE_CNT) {
 		if (xfer_req == WCD_SPI_XFER_WRITE)
@@ -827,7 +836,8 @@
 		ret = wcd_spi_transfer_split(spi, msg, xfer_req);
 	}
 	WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->xfer_mutex);
-
+done:
+	WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex);
 	return ret;
 }
 
diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h
index 098a60d..46d61a0 100644
--- a/asoc/codecs/wcd938x/internal.h
+++ b/asoc/codecs/wcd938x/internal.h
@@ -149,6 +149,7 @@
 	WCD_BOLERO_EVT_IMPED_TRUE,	/* for imped true */
 	WCD_BOLERO_EVT_IMPED_FALSE,	/* for imped false */
 	WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
+	WCD_BOLERO_EVT_BCS_CLK_OFF,
 };
 
 enum {
@@ -182,6 +183,9 @@
 
 extern struct wcd938x_mbhc *wcd938x_soc_get_mbhc(
 				struct snd_soc_component *component);
+extern void wcd938x_disable_bcs_before_slow_insert(
+				struct snd_soc_component *component,
+				bool bcs_disable);
 extern int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
 					int volt, int micb_num);
 extern int wcd938x_get_micb_vout_ctl_val(u32 micb_mv);
diff --git a/asoc/codecs/wcd938x/wcd938x-mbhc.c b/asoc/codecs/wcd938x/wcd938x-mbhc.c
index 27566ee..0687de6 100644
--- a/asoc/codecs/wcd938x/wcd938x-mbhc.c
+++ b/asoc/codecs/wcd938x/wcd938x-mbhc.c
@@ -803,6 +803,15 @@
 			0x04, (enable << 2));
 }
 
+static void wcd938x_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
+						  bool bcs_enable)
+{
+	if (bcs_enable)
+		wcd938x_disable_bcs_before_slow_insert(mbhc->component, false);
+	else
+		wcd938x_disable_bcs_before_slow_insert(mbhc->component, true);
+}
+
 static const struct wcd_mbhc_cb mbhc_cb = {
 	.request_irq = wcd938x_mbhc_request_irq,
 	.irq_control = wcd938x_mbhc_irq_control,
@@ -827,6 +836,7 @@
 	.mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,
 	.mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,
 	.mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,
+	.bcs_enable = wcd938x_mbhc_bcs_enable,
 };
 
 static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 04954d9..ae88d7c 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -1523,6 +1523,21 @@
 	return 0;
 }
 
+void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
+					    bool bcs_disable)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	if (wcd938x->update_wcd_event) {
+		if (bcs_disable)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
+		else
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
+	}
+}
+
 int wcd938x_tx_channel_config(struct snd_soc_component *component,
 			      int channel, int mode)
 {
@@ -1627,18 +1642,30 @@
 		switch (w->shift) {
 		case 0:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0x0F,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x10, 0x00);
 			break;
 		case 1:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0xF0,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x20, 0x00);
 			break;
 		case 2:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0x0F,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x40, 0x00);
 			break;
 		case 3:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0xF0,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x00);
 			break;
 		default:
diff --git a/asoc/codecs/wcd_cpe_core.c b/asoc/codecs/wcd_cpe_core.c
index 4c776d1..5b5291f 100644
--- a/asoc/codecs/wcd_cpe_core.c
+++ b/asoc/codecs/wcd_cpe_core.c
@@ -2896,6 +2896,7 @@
 	struct cmi_obm_msg obm_msg;
 	struct cpe_param_data *param_d;
 
+	memset(&obm_msg, 0, sizeof(obm_msg));
 
 	ret = fill_cmi_header(&obm_msg.hdr, session->id,
 			CMI_CPE_LSM_SERVICE_ID, 0, 20,
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 12fbf35..b35a1e8 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -5510,6 +5510,10 @@
 		dai_data->port_config.i2s.bit_width = 24;
 		dai_data->bitwidth = 24;
 		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		dai_data->port_config.i2s.bit_width = 32;
+		dai_data->bitwidth = 32;
+		break;
 	default:
 		pr_err("%s: format %d\n",
 			__func__, params_format(params));
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 79ddd89..ae86f7a 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -123,6 +123,7 @@
 #define VA_CDC_DMA_TX_2_TEXT "VA_CDC_DMA_TX_2"
 #define TX_CDC_DMA_TX_3_TEXT "TX_CDC_DMA_TX_3"
 #define QUIN_TDM_TX_TEXT "QUIN_TDM_TX_0"
+#define TERT_TDM_TX_TEXT "TERT_TDM_TX_0"
 
 #define LSM_FUNCTION_TEXT "LSM Function"
 static const char * const lsm_port_text[] = {
@@ -131,7 +132,8 @@
 	SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT,
 	TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT,
 	INT3_MI2S_TX_TEXT, VA_CDC_DMA_TX_0_TEXT, VA_CDC_DMA_TX_1_TEXT,
-	VA_CDC_DMA_TX_2_TEXT, TX_CDC_DMA_TX_3_TEXT, QUIN_TDM_TX_TEXT
+	VA_CDC_DMA_TX_2_TEXT, TX_CDC_DMA_TX_3_TEXT, QUIN_TDM_TX_TEXT,
+	TERT_TDM_TX_TEXT
 };
 
 struct msm_pcm_route_bdai_pp_params {
@@ -2056,7 +2058,13 @@
 
 	pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
 
-	if (!is_mm_lsm_fe_id(val)) {
+	if (val == MSM_FRONTEND_DAI_DTMF_RX &&
+		afe_get_port_type(msm_bedais[reg].port_id) ==
+			MSM_AFE_PORT_TYPE_RX) {
+		pr_debug("%s(): set=%d port id=0x%x for dtmf generation\n",
+			__func__, set, msm_bedais[reg].port_id);
+		afe_set_dtmf_gen_rx_portid(msm_bedais[reg].port_id, set);
+	} else if (!is_mm_lsm_fe_id(val)) {
 		/* recheck FE ID in the mixer control defined in this file */
 		pr_err("%s: bad MM ID\n", __func__);
 		return;
@@ -3026,6 +3034,9 @@
 	case 15:
 		lsm_port = AFE_PORT_ID_QUINARY_TDM_TX;
 		break;
+	case 16:
+		lsm_port = AFE_PORT_ID_TERTIARY_TDM_TX;
+		break;
 	default:
 		pr_err("Default lsm port");
 		break;
@@ -3043,7 +3054,7 @@
 	u16 port_id;
 	enum afe_mad_type mad_type;
 
-	pr_debug("%s: enter\n", __func__);
+	pr_debug("%s: id name %s\n", __func__, kcontrol->id.name);
 	for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++)
 		if (!strnstr(kcontrol->id.name, lsm_port_text[i],
 			    strlen(lsm_port_text[i])))
@@ -3070,14 +3081,18 @@
 			strlen(lsm_port_text[10])))
 		port_id = AFE_PORT_ID_INT3_MI2S_TX;
 
-	if (strnstr(kcontrol->id.name, lsm_port_text[13],
-			strlen(lsm_port_text[13])))
-		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
-
 	if (strnstr(kcontrol->id.name, lsm_port_text[14],
 			strlen(lsm_port_text[14])))
+		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
+
+	if (strnstr(kcontrol->id.name, lsm_port_text[15],
+			strlen(lsm_port_text[15])))
 		port_id = AFE_PORT_ID_QUINARY_TDM_TX;
 
+	if (strnstr(kcontrol->id.name, lsm_port_text[16],
+			strlen(lsm_port_text[16])))
+		port_id = AFE_PORT_ID_TERTIARY_TDM_TX;
+
 	mad_type = afe_port_get_mad_type(port_id);
 	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
 		 mad_type);
@@ -3111,7 +3126,7 @@
 	u16 port_id;
 	enum afe_mad_type mad_type;
 
-	pr_debug("%s: enter\n", __func__);
+	pr_debug("%s: id name %s\n", __func__, kcontrol->id.name);
 	for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++)
 		if (strnstr(kcontrol->id.name, lsm_port_text[i],
 			    strlen(lsm_port_text[i])))
@@ -3158,14 +3173,18 @@
 			strlen(lsm_port_text[10])))
 		port_id = AFE_PORT_ID_INT3_MI2S_TX;
 
-	if (strnstr(kcontrol->id.name, lsm_port_text[13],
-			strlen(lsm_port_text[13])))
-		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
-
 	if (strnstr(kcontrol->id.name, lsm_port_text[14],
 			strlen(lsm_port_text[14])))
+		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
+
+	if (strnstr(kcontrol->id.name, lsm_port_text[15],
+			strlen(lsm_port_text[15])))
 		port_id = AFE_PORT_ID_QUINARY_TDM_TX;
 
+	if (strnstr(kcontrol->id.name, lsm_port_text[16],
+			strlen(lsm_port_text[16])))
+		port_id = AFE_PORT_ID_TERTIARY_TDM_TX;
+
 	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
 		 mad_type);
 	return afe_port_set_mad_type(port_id, mad_type);
@@ -7040,7 +7059,10 @@
 	MSM_BACKEND_DAI_PRI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA30, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
-
+	SOC_DOUBLE_EXT("DTMF", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int0_mi2s_rx_mixer_controls[] = {
@@ -7607,6 +7629,10 @@
 	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
@@ -11191,6 +11217,73 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_tx_1_mixer_controls[] = {
+	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia2", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia6", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia7", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia8", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia9", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia10", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia11", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia12", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia13", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia14", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia15", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia16", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new quin_tdm_rx_1_mixer_controls[] = {
 	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_QUIN_TDM_RX_1,
@@ -11270,6 +11363,73 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_tx_2_mixer_controls[] = {
+	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia2", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia6", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia7", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia8", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia9", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia10", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia11", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia12", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia13", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia14", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia15", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia16", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new quin_tdm_rx_2_mixer_controls[] = {
 	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_QUIN_TDM_RX_2,
@@ -11349,6 +11509,73 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_tx_3_mixer_controls[] = {
+	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia2", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia6", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia7", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia8", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia9", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia10", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia11", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia12", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia13", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia14", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia15", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia16", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new quin_tdm_rx_3_mixer_controls[] = {
 	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_QUIN_TDM_RX_3,
@@ -15843,6 +16070,13 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_rx_2_voice_mixer_controls[] = {
+	SOC_DOUBLE_EXT("VoiceMMode1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_RX_2,
+	MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new wsa_cdc_dma_rx_0_voice_mixer_controls[] = {
 	SOC_DOUBLE_EXT("Voip", SND_SOC_NOPM,
 			MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0,
@@ -20786,6 +21020,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm2_mixer_controls[] = {
@@ -20842,6 +21080,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm3_mixer_controls[] = {
@@ -20897,6 +21139,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm4_mixer_controls[] = {
@@ -20952,6 +21198,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm5_mixer_controls[] = {
@@ -21007,6 +21257,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm6_mixer_controls[] = {
@@ -21062,6 +21316,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm7_mixer_controls[] = {
@@ -21117,6 +21375,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm8_mixer_controls[] = {
@@ -21172,6 +21434,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new slim_fm_switch_mixer_controls =
@@ -21322,6 +21588,8 @@
 		    msm_routing_lsm_func_get, msm_routing_lsm_func_put),
 	SOC_ENUM_EXT(QUIN_TDM_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
 		    msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+	SOC_ENUM_EXT(TERT_TDM_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		    msm_routing_lsm_func_get, msm_routing_lsm_func_put),
 	/* kcontrol of lsm_port */
 	SOC_ENUM_EXT("LSM1 Port", lsm_port_enum,
 			  msm_routing_lsm_port_get,
@@ -23701,12 +23969,21 @@
 	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				quin_tdm_rx_1_mixer_controls,
 				ARRAY_SIZE(quin_tdm_rx_1_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_TX_1 Audio Mixer", SND_SOC_NOPM, 0, 0,
+				quin_tdm_tx_1_mixer_controls,
+				ARRAY_SIZE(quin_tdm_tx_1_mixer_controls)),
 	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				quin_tdm_rx_2_mixer_controls,
 				ARRAY_SIZE(quin_tdm_rx_2_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_TX_2 Audio Mixer", SND_SOC_NOPM, 0, 0,
+				quin_tdm_tx_2_mixer_controls,
+				ARRAY_SIZE(quin_tdm_tx_2_mixer_controls)),
 	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				quin_tdm_rx_3_mixer_controls,
 				ARRAY_SIZE(quin_tdm_rx_3_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_TX_3 Audio Mixer", SND_SOC_NOPM, 0, 0,
+				quin_tdm_tx_3_mixer_controls,
+				ARRAY_SIZE(quin_tdm_tx_3_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SEN_TDM_TX_0 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				sen_tdm_tx_0_mixer_controls,
 				ARRAY_SIZE(sen_tdm_tx_0_mixer_controls)),
@@ -23934,6 +24211,10 @@
 				SND_SOC_NOPM, 0, 0,
 				quat_tdm_rx_2_voice_mixer_controls,
 				ARRAY_SIZE(quat_tdm_rx_2_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_2_Voice Mixer",
+				SND_SOC_NOPM, 0, 0,
+				quin_tdm_rx_2_voice_mixer_controls,
+				ARRAY_SIZE(quin_tdm_rx_2_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("WSA_CDC_DMA_RX_0_Voice Mixer",
 			   SND_SOC_NOPM, 0, 0,
 			   wsa_cdc_dma_rx_0_voice_mixer_controls,
@@ -24614,6 +24895,7 @@
 	/* incall */
 	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"Incall_Music Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"Incall_Music Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
@@ -24880,6 +25162,7 @@
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia26", "MM_DL26"},
 	{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Audio Mixer"},
+	{"PRI_MI2S_RX Audio Mixer", "DTMF", "DTMF_DL_HL"},
 
 	{"INT0_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"INT0_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -26712,6 +26995,9 @@
 	{"QUAT_TDM_RX_2_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
 	{"QUAT_TDM_RX_2", NULL, "QUAT_TDM_RX_2_Voice Mixer"},
 
+	{"QUIN_TDM_RX_2_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
+	{"QUIN_TDM_RX_2", NULL, "QUIN_TDM_RX_2_Voice Mixer"},
+
 	{"WSA_CDC_DMA_RX_0_Voice Mixer", "Voip", "VOIP_DL"},
 	{"WSA_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
 	{"WSA_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
@@ -26974,6 +27260,7 @@
 	{"LSM1 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM1 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM1 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM1 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM1_UL_HL", NULL, "LSM1 Mixer"},
 
 	{"LSM2 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -26989,6 +27276,7 @@
 	{"LSM2 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM2 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM2 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM2 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM2_UL_HL", NULL, "LSM2 Mixer"},
 
 
@@ -27005,6 +27293,7 @@
 	{"LSM3 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM3 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM3 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM3 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM3_UL_HL", NULL, "LSM3 Mixer"},
 
 
@@ -27021,6 +27310,7 @@
 	{"LSM4 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM4 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM4 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM4 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM4_UL_HL", NULL, "LSM4 Mixer"},
 
 	{"LSM5 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27036,6 +27326,7 @@
 	{"LSM5 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM5 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM5 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM5 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM5_UL_HL", NULL, "LSM5 Mixer"},
 
 	{"LSM6 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27049,6 +27340,7 @@
 	{"LSM6 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM6 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM6 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM6 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM6_UL_HL", NULL, "LSM6 Mixer"},
 
 	{"LSM7 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27062,6 +27354,7 @@
 	{"LSM7 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM7 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM7 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM7 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM7_UL_HL", NULL, "LSM7 Mixer"},
 
 	{"LSM8 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27075,6 +27368,7 @@
 	{"LSM8 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM8 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM8 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM8 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM8_UL_HL", NULL, "LSM8 Mixer"},
 
 
@@ -28871,6 +29165,11 @@
 	uint32_t be_idx = ucontrol->value.integer.value[0];
 	int i;
 
+	if (be_idx >= MSM_BACKEND_DAI_MAX) {
+		pr_err("%s: Invalid Backend index %d\n",  __func__, be_idx);
+		return -EINVAL;
+	}
+
 	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++) {
 		channel_map[i] = (char)(ucontrol->value.integer.value[i + 1]);
 		if (channel_map[i] > PCM_MAX_CHMAP_ID) {
diff --git a/asoc/msm-pcm-voice-v2.c b/asoc/msm-pcm-voice-v2.c
index f8acc30..5a25b3e 100644
--- a/asoc/msm-pcm-voice-v2.c
+++ b/asoc/msm-pcm-voice-v2.c
@@ -582,6 +582,20 @@
 	return 0;
 }
 
+static int msm_voice_ecns_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	uint32_t enable = ucontrol->value.integer.value[0];
+	uint32_t session_id = ucontrol->value.integer.value[1];
+	uint32_t module_id = ucontrol->value.integer.value[2];
+
+	pr_debug("%s: ecns enable=%d session_id=%#x\n", __func__, enable,
+		 session_id);
+	voc_set_ecns_enable(session_id, module_id, enable);
+
+	return 0;
+}
+
 static int msm_voice_hd_voice_put(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
@@ -695,6 +709,8 @@
 				msm_voice_tty_mode_put),
 	SOC_SINGLE_MULTI_EXT("Slowtalk Enable", SND_SOC_NOPM, 0, VSID_MAX, 0, 2,
 				NULL, msm_voice_slowtalk_put),
+	SOC_SINGLE_MULTI_EXT("Voice ECNS Enable", SND_SOC_NOPM, 0, VSID_MAX, 0, 3,
+				NULL, msm_voice_ecns_put),
 	SOC_SINGLE_MULTI_EXT("Voice Topology Disable", SND_SOC_NOPM, 0,
 			     VSID_MAX, 0, 2, NULL,
 			     msm_voice_topology_disable_put),
diff --git a/dsp/avtimer.c b/dsp/avtimer.c
index ad5e13a..e1d032d 100644
--- a/dsp/avtimer.c
+++ b/dsp/avtimer.c
@@ -271,6 +271,7 @@
 				rc = avcs_core_disable_avtimer(
 				avtimer.timer_handle);
 				avtimer.timer_handle = 0;
+				atomic_set(&avtimer.adsp_ready, 0);
 			}
 		}
 	}
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index ccc91cf..6111832 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -2897,7 +2897,8 @@
 
 	if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
 		port_id == AFE_PORT_ID_INT3_MI2S_TX ||
-		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3) {
+		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3 ||
+		port_id == AFE_PORT_ID_TERTIARY_TDM_TX) {
 		mad_type = MAD_SW_AUDIO;
 		return 0;
 	}
@@ -2926,7 +2927,8 @@
 
 	if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
 		port_id == AFE_PORT_ID_INT3_MI2S_TX ||
-		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3)
+		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3 ||
+		port_id == AFE_PORT_ID_TERTIARY_TDM_TX)
 		return MAD_SW_AUDIO;
 
 	i = port_id - SLIMBUS_0_RX;
diff --git a/dsp/q6voice.c b/dsp/q6voice.c
index 3db75d0..77a08ee 100644
--- a/dsp/q6voice.c
+++ b/dsp/q6voice.c
@@ -110,6 +110,10 @@
 static int voice_send_set_pp_enable_cmd(
 	struct voice_data *v, struct module_instance_info mod_inst_info,
 	int enable);
+
+static int voice_send_cvp_ecns_enable_cmd(struct voice_data *v,
+	uint32_t module_id, int enable);
+
 static int is_cal_memory_allocated(void);
 static bool is_cvd_version_queried(void);
 static int is_voip_memory_allocated(void);
@@ -1544,6 +1548,124 @@
 	return ret;
 }
 
+static int voice_send_cvp_ecns_enable_cmd(struct voice_data *v,
+	uint32_t module_id, int enable)
+{
+	int ret;
+	struct cvp_set_channel_ecns_cmd_v2 cvp_set_ch_ecns_cmd;
+	void *apr_cvp;
+	u16 cvp_handle;
+	struct vss_icommon_param_data_ecns_t *cvp_config_param_data =
+				&cvp_set_ch_ecns_cmd.
+				cvp_set_ecns.param_data;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	apr_cvp = common.apr_q6_cvp;
+
+	if (!apr_cvp) {
+		pr_err("%s: apr_cvp is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cvp_handle = voice_get_cvp_handle(v);
+	memset(&cvp_set_ch_ecns_cmd, 0,
+		sizeof(cvp_set_ch_ecns_cmd));
+
+	cvp_set_ch_ecns_cmd.hdr.hdr_field =
+			APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE),
+			APR_PKT_VER);
+	cvp_set_ch_ecns_cmd.hdr.pkt_size =
+			APR_PKT_SIZE(APR_HDR_SIZE,
+			sizeof(cvp_set_ch_ecns_cmd) - APR_HDR_SIZE);
+	cvp_set_ch_ecns_cmd.hdr.src_svc = 0;
+	cvp_set_ch_ecns_cmd.hdr.src_domain = APR_DOMAIN_APPS;
+	cvp_set_ch_ecns_cmd.hdr.src_port =
+			voice_get_idx_for_session(v->session_id);
+	cvp_set_ch_ecns_cmd.hdr.dest_svc = 0;
+	cvp_set_ch_ecns_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+	cvp_set_ch_ecns_cmd.hdr.dest_port = cvp_handle;
+	cvp_set_ch_ecns_cmd.hdr.token = 0;
+	cvp_set_ch_ecns_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
+	cvp_set_ch_ecns_cmd.cvp_set_ecns.mem_size =
+			sizeof(struct vss_icommon_param_data_ecns_t);
+
+	cvp_config_param_data->module_id = module_id;
+	cvp_config_param_data->param_id = VOICE_PARAM_MOD_ENABLE;
+	cvp_config_param_data->param_size = MOD_ENABLE_PARAM_LEN;
+	cvp_config_param_data->reserved = 0;
+	cvp_config_param_data->enable = enable;
+
+	v->cvp_state = CMD_STATUS_FAIL;
+	v->async_err = 0;
+	ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_ch_ecns_cmd);
+
+	if (ret < 0) {
+		pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2 %d\n",
+		       __func__, ret);
+		goto done;
+	}
+	ret = wait_event_timeout(v->cvp_wait,
+				(v->cvp_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -ETIMEDOUT;
+		goto done;
+	}
+
+	if (v->async_err > 0) {
+		pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
+		       adsp_err_get_err_str(v->async_err), cvp_handle);
+		ret = adsp_err_get_lnx_err_code(v->async_err);
+		goto done;
+	}
+	ret = 0;
+done:
+	return ret;
+}
+
+/**
+ * voc_set_ecns_enable -
+ *       Command to set ECNS for voice module
+ *
+ * @session_id: voice session ID to send this command
+ * @module_id: voice module id
+ * @enable: enable/disable flag
+ *
+ * Returns 0 on success or error on failure
+ */
+int voc_set_ecns_enable(uint32_t session_id, uint32_t module_id,
+	 uint32_t enable)
+{
+	struct voice_data *v = voice_get_session(session_id);
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+		return -EINVAL;
+	}
+	mutex_lock(&v->lock);
+	v->ecns_enable = enable;
+	v->ecns_module_id = module_id;
+
+	if (is_voc_state_active(v->voc_state))
+		ret = voice_send_cvp_ecns_enable_cmd(v,
+				v->ecns_module_id, v->ecns_enable);
+
+	mutex_unlock(&v->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(voc_set_ecns_enable);
+
 static int voice_send_set_pp_enable_cmd(
 	struct voice_data *v, struct module_instance_info mod_inst_info,
 	int enable)
@@ -4420,6 +4542,10 @@
 	if (v->dtmf_rx_detect_en)
 		voice_send_dtmf_rx_detection_cmd(v, v->dtmf_rx_detect_en);
 
+	if (v->ecns_enable)
+		voice_send_cvp_ecns_enable_cmd(v, v->ecns_module_id,
+			v->ecns_enable);
+
 	if (v->hd_enable)
 		voice_send_hd_cmd(v, v->hd_enable);
 
@@ -5076,6 +5202,9 @@
 	if (v->dtmf_rx_detect_en)
 		voice_send_dtmf_rx_detection_cmd(v, 0);
 
+	if (v->ecns_enable)
+		voice_send_cvp_ecns_enable_cmd(v, v->ecns_module_id, 0);
+
 	/* detach VOCPROC and wait for response from mvm */
 	mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h
index 1f9d64e..f3ee728 100644
--- a/include/asoc/wcd-mbhc-v2.h
+++ b/include/asoc/wcd-mbhc-v2.h
@@ -451,6 +451,8 @@
 };
 
 struct wcd_mbhc_cb {
+	void (*bcs_enable)
+		(struct wcd_mbhc *mbhc, bool bcs_enable);
 	int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on);
 	void (*trim_btn_reg)(struct snd_soc_component *component);
 	void (*compute_impedance)(struct wcd_mbhc *mbhc,
diff --git a/include/dsp/q6voice.h b/include/dsp/q6voice.h
index 2edfbe2..35ace4e 100644
--- a/include/dsp/q6voice.h
+++ b/include/dsp/q6voice.h
@@ -312,6 +312,21 @@
 	struct vss_param_channel_mixer_info_t ch_mixer_info;
 } __packed;
 
+struct vss_icommon_param_data_ecns_t {
+	/* Valid ID of the module. */
+	uint32_t module_id;
+	/* Valid ID of the parameter. */
+	uint32_t param_id;
+	/*
+	 * Data size of the structure relating to the param_id/module_id
+	 * combination in uint8_t bytes.
+	 */
+	uint16_t param_size;
+	/* This field must be set to zero. */
+	uint16_t reserved;
+	uint32_t enable;
+} __packed;
+
 struct vss_icommon_cmd_set_param_ch_mixer_v2_t {
 	/*
 	 * Pointer to the unique identifier for an address (physical/virtual).
@@ -338,6 +353,33 @@
 	struct vss_icommon_param_data_ch_mixer_v2_t param_data;
 } __packed;
 
+
+struct vss_icommon_cmd_set_ecns_enable_t {
+	/*
+	 * Pointer to the unique identifier for an address (physical/virtual).
+	 *
+	 * If the parameter data payload is within the message payload
+	 * (in-band), set this field to 0. The parameter data begins at the
+	 * specified data payload address.
+	 *
+	 * If the parameter data is out-of-band, this field is the handle to
+	 * the physical address in the shared memory that holds the parameter
+	 * data.
+	 */
+	uint32_t mem_handle;
+	/*
+	 * Location of the parameter data payload.
+	 *
+	 * The payload is an array of vss_icommon_param_data_t. If the
+	 * mem_handle is 0, this field is ignored.
+	 */
+	uint64_t mem_address;
+	/* Size of the parameter data payload in bytes. */
+	uint32_t mem_size;
+
+	struct vss_icommon_param_data_ecns_t param_data;
+} __packed;
+
 struct vss_icommon_param_data_mfc_config_v2_t {
 	/* Valid ID of the module. */
 	uint32_t module_id;
@@ -809,6 +851,7 @@
 
 #define MODULE_ID_VOICE_MODULE_ST			0x00010EE3
 #define VOICE_PARAM_MOD_ENABLE				0x00010E00
+#define MOD_ENABLE_PARAM_LEN				4
 
 #define VSS_IPLAYBACK_CMD_START				0x000112BD
 /* Start in-call music delivery on the Tx voice path. */
@@ -1679,6 +1722,11 @@
 	struct apr_hdr hdr;
 } __packed;
 
+struct cvp_set_channel_ecns_cmd_v2 {
+	struct apr_hdr hdr;
+	struct vss_icommon_cmd_set_ecns_enable_t cvp_set_ecns;
+} __packed;
+
 struct cvp_set_rx_volume_index_cmd {
 	struct apr_hdr hdr;
 	struct vss_ivocproc_cmd_set_volume_index_t cvp_set_vol_idx;
@@ -1894,6 +1942,10 @@
 
 	bool mic_break_status;
 	struct work_struct voice_mic_break_work;
+
+	uint32_t ecns_enable;
+	uint32_t ecns_module_id;
+
 };
 
 #define MAX_VOC_SESSIONS 8
@@ -2042,6 +2094,8 @@
 int voc_set_route_flag(uint32_t session_id, uint8_t path_dir, uint8_t set);
 uint8_t voc_get_route_flag(uint32_t session_id, uint8_t path_dir);
 bool voc_get_mbd_enable(void);
+int voc_set_ecns_enable(uint32_t session_id, uint32_t module_id,
+			uint32_t enable);
 uint8_t voc_set_mbd_enable(bool enable);
 int voc_enable_dtmf_rx_detection(uint32_t session_id, uint32_t enable);
 void voc_disable_dtmf_det_on_active_sessions(void);
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index a3934a5..008801f 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -25,6 +25,7 @@
 #include "swrm_registers.h"
 #include "swr-mstr-ctrl.h"
 
+#define SWRM_FRAME_SYNC_SEL    4000 /* 4KHz */
 #define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700
 #define SWRM_SYS_SUSPEND_WAIT 1
 
@@ -43,6 +44,13 @@
 #define ERR_AUTO_SUSPEND_TIMER_VAL 0x1
 
 #define SWRM_INTERRUPT_STATUS_MASK 0x1FDFD
+
+#define SWRM_ROW_48    48
+#define SWRM_ROW_50    50
+#define SWRM_ROW_64    64
+#define SWRM_COL_02    02
+#define SWRM_COL_16    16
+
 /* pm runtime auto suspend timer in msecs */
 static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000;
 module_param(auto_suspend_timer, int, 0664);
@@ -341,6 +349,16 @@
 	return ret;
 }
 
+static int swrm_get_ssp_period(struct swr_mstr_ctrl *swrm,
+				int row, int col,
+				int frame_sync)
+{
+	if (!swrm || !row || !col || !frame_sync)
+		return 1;
+
+	return ((swrm->bus_clk * 2) / ((row * col) * frame_sync));
+}
+
 static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
 {
 	int ret = 0;
@@ -591,6 +609,10 @@
 		if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) {
 			/* wait 500 us before retry on fifo read failure */
 			usleep_range(500, 505);
+			if (retry_attempt == (MAX_FIFO_RD_FAIL_RETRY - 1)) {
+				swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
+				swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
+			}
 			retry_attempt++;
 			goto retry_read;
 		} else {
@@ -1093,7 +1115,9 @@
 {
 	u8 bank;
 	u32 value, n_row, n_col;
+	u32 row = 0, col = 0;
 	int ret;
+	u8 ssp_period = 0;
 	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
 	int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK |
 		    SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK |
@@ -1162,30 +1186,39 @@
 	if (enable) {
 		/* set col = 16 */
 		n_col = SWR_MAX_COL;
+		col = SWRM_COL_16;
 	} else {
 		/*
 		 * Do not change to col = 2 if there are still active ports
 		 */
-		if (!master->num_port)
+		if (!master->num_port) {
 			n_col = SWR_MIN_COL;
-		else
+			col = SWRM_COL_02;
+		} else {
 			n_col = SWR_MAX_COL;
+			col = SWRM_COL_16;
+		}
 	}
 	/* Use default 50 * x, frame shape. Change based on mclk */
 	if (swrm->mclk_freq == MCLK_FREQ_NATIVE) {
 		dev_dbg(swrm->dev, "setting 64 x %d frameshape\n",
 			n_col ? 16 : 2);
 		n_row = SWR_ROW_64;
+		row = SWRM_ROW_64;
 	} else {
 		dev_dbg(swrm->dev, "setting 50 x %d frameshape\n",
 			n_col ? 16 : 2);
 		n_row = SWR_ROW_50;
+		row = SWRM_ROW_50;
 	}
+	ssp_period = swrm_get_ssp_period(swrm, row, col, SWRM_FRAME_SYNC_SEL);
+	dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
+
 	value = swr_master_read(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank));
 	value &= (~mask);
 	value |= ((n_row << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
 		  (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
-		  (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
+		  ((ssp_period - 1) << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
 	swr_master_write(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value);
 
 	dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__,
@@ -1726,6 +1759,7 @@
 		case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
 			dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n",
 				__func__);
+			swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
 			break;
 		case SWRM_INTERRUPT_STATUS_CMD_ERROR:
 			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
@@ -2019,10 +2053,14 @@
 	u32 temp = 0;
 	int len = 0;
 
+	ssp_period = swrm_get_ssp_period(swrm, SWRM_ROW_50,
+					SWRM_COL_02, SWRM_FRAME_SYNC_SEL);
+	dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
+
 	/* Clear Rows and Cols */
 	val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
 		(col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
-		(ssp_period << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
+		((ssp_period - 1) << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
 
 	reg[len] = SWRM_MCP_FRAME_CTRL_BANK_ADDR(0);
 	value[len++] = val;
@@ -2303,6 +2341,7 @@
 	swrm->clk_ref_count = 0;
 	swrm->swr_irq_wakeup_capable = 0;
 	swrm->mclk_freq = MCLK_FREQ;
+	swrm->bus_clk = MCLK_FREQ;
 	swrm->dev_up = true;
 	swrm->state = SWR_MSTR_UP;
 	swrm->ipc_wakeup = false;
@@ -2882,6 +2921,7 @@
 				usleep_range(10000, 10500);
 			}
 			swrm->mclk_freq = *(int *)data;
+			swrm->bus_clk = swrm->mclk_freq;
 			mutex_unlock(&swrm->mlock);
 		}
 		break;
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index 43bf227..b07a80d 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -142,6 +142,7 @@
 	int wake_irq;
 	int version;
 	int mclk_freq;
+	int bus_clk;
 	u32 num_dev;
 	int slave_status;
 	struct swrm_mports mport_cfg[SWR_MAX_MSTR_PORT_NUM];