Merge "asoc: codecs: register notifier for all bolero codec variants"
diff --git a/asoc/bengal.c b/asoc/bengal.c
index 21287b4..c500a17 100644
--- a/asoc/bengal.c
+++ b/asoc/bengal.c
@@ -5833,6 +5833,8 @@
 	int rc = 0;
 	u32 mi2s_audio_intf = 0;
 	u32 auxpcm_audio_intf = 0;
+	u32 rxtx_bolero_codec = 0;
+	u32 va_bolero_codec = 0;
 	u32 val = 0;
 	u32 wcn_btfm_intf = 0;
 	const struct of_device_id *match;
@@ -5862,17 +5864,37 @@
 		       sizeof(msm_common_be_dai_links));
 		total_links += ARRAY_SIZE(msm_common_be_dai_links);
 
-		memcpy(msm_bengal_dai_links + total_links,
-		       msm_rx_tx_cdc_dma_be_dai_links,
-		       sizeof(msm_rx_tx_cdc_dma_be_dai_links));
-		total_links +=
-			ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links);
+		rc = of_property_read_u32(dev->of_node,
+					  "qcom,rxtx-bolero-codec",
+					  &rxtx_bolero_codec);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match RXTX Macro codec\n",
+				__func__);
+		} else {
+			if (rxtx_bolero_codec) {
+				memcpy(msm_bengal_dai_links + total_links,
+				       msm_rx_tx_cdc_dma_be_dai_links,
+				       sizeof(msm_rx_tx_cdc_dma_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(
+						msm_rx_tx_cdc_dma_be_dai_links);
+			}
+		}
 
-		memcpy(msm_bengal_dai_links + total_links,
-		       msm_va_cdc_dma_be_dai_links,
-		       sizeof(msm_va_cdc_dma_be_dai_links));
-		total_links +=
-			ARRAY_SIZE(msm_va_cdc_dma_be_dai_links);
+		rc = of_property_read_u32(dev->of_node, "qcom,va-bolero-codec",
+					  &va_bolero_codec);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match VA Macro codec\n",
+				__func__);
+		} else {
+			if (va_bolero_codec) {
+				memcpy(msm_bengal_dai_links + total_links,
+				       msm_va_cdc_dma_be_dai_links,
+				       sizeof(msm_va_cdc_dma_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_va_cdc_dma_be_dai_links);
+			}
+		}
 
 		rc = of_property_read_u32(dev->of_node, "qcom,mi2s-audio-intf",
 					  &mi2s_audio_intf);
diff --git a/asoc/codecs/Android.mk b/asoc/codecs/Android.mk
index da39e8c..5e3114e 100644
--- a/asoc/codecs/Android.mk
+++ b/asoc/codecs/Android.mk
@@ -111,7 +111,7 @@
 include $(DLKM_DIR)/AndroidKernelModule.mk
 endif
 ###########################################################
-ifneq ($(TARGET_PRODUCT), $(filter $(TARGET_PRODUCT), bengal))
+ifneq ($(call is-board-platform-in-list, bengal),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_wsa881x.ko
 LOCAL_MODULE_KBUILD_NAME  := wsa881x_dlkm.ko
@@ -148,7 +148,7 @@
 LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
 include $(DLKM_DIR)/AndroidKernelModule.mk
 ###########################################################
-ifneq ($(TARGET_PRODUCT), $(filter $(TARGET_PRODUCT), bengal))
+ifneq ($(call is-board-platform-in-list, bengal),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_hdmi.ko
 LOCAL_MODULE_KBUILD_NAME  := hdmi_dlkm.ko
diff --git a/asoc/codecs/bolero/bolero-cdc-registers.h b/asoc/codecs/bolero/bolero-cdc-registers.h
index c59bb86..e68e314 100644
--- a/asoc/codecs/bolero/bolero-cdc-registers.h
+++ b/asoc/codecs/bolero/bolero-cdc-registers.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _BOLERO_CDC_REGISTERS_H
@@ -716,6 +716,11 @@
 
 #define BOLERO_CDC_VA_MACRO_TOP_MAX 0x34 /* 0x0CC/4 = 0x33 + 1 = 0x34 */
 
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0	(VA_START_OFFSET + 0x00D0)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1	(VA_START_OFFSET + 0x00D4)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2	(VA_START_OFFSET + 0x00D8)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_CTRL		(VA_START_OFFSET + 0x00DC)
+
 #define BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0	(VA_START_OFFSET + 0x0100)
 #define BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1	(VA_START_OFFSET + 0x0104)
 #define BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0	(VA_START_OFFSET + 0x0108)
diff --git a/asoc/codecs/bolero/bolero-cdc-regmap.c b/asoc/codecs/bolero/bolero-cdc-regmap.c
index 9082966..77f5420 100644
--- a/asoc/codecs/bolero/bolero-cdc-regmap.c
+++ b/asoc/codecs/bolero/bolero-cdc-regmap.c
@@ -625,6 +625,10 @@
 	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_1, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_2, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_3, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0x06},
 
 	/* VA core */
 	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00},
diff --git a/asoc/codecs/bolero/bolero-cdc-tables.c b/asoc/codecs/bolero/bolero-cdc-tables.c
index 81639b3..5d0d353 100644
--- a/asoc/codecs/bolero/bolero-cdc-tables.c
+++ b/asoc/codecs/bolero/bolero-cdc-tables.c
@@ -149,6 +149,96 @@
 	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC6)] = RD_WR_REG,
 };
 
+u8 bolero_tx_reg_access_v2[BOLERO_CDC_TX_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_ANC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_CLK_RESET_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_A_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_B_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FB_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_SMLPF_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_DCFLT_SHIFT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_ADAPT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_A_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_B_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
 u8 bolero_rx_reg_access[BOLERO_CDC_RX_MACRO_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_RX_TOP_TOP_CFG0)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_RX_TOP_SWR_CTRL)] = RD_WR_REG,
@@ -581,6 +671,132 @@
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
 };
 
+u8 bolero_va_reg_access_v2[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,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 bolero_va_reg_access_v3[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,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
 u8 bolero_wsa_reg_access[BOLERO_CDC_WSA_MACRO_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 863ad59..fb182a2 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -104,21 +104,25 @@
 	if (priv->macro_params[VA_MACRO].dev)
 		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
 
-	/* Request Clk before register access */
-	ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0) {
+		/* Request Clk before register access */
+		ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				true);
-	if (ret < 0) {
-		dev_err_ratelimited(priv->dev,
-			"%s: Failed to enable clock, ret:%d\n", __func__, ret);
-		goto err;
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: Failed to enable clock, ret:%d\n",
+				__func__, ret);
+			goto err;
+		}
 	}
 
 	bolero_ahb_read_device(
 		priv->macro_params[macro_id].io_base, reg, val);
 
-	bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0)
+		bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				false);
@@ -148,21 +152,25 @@
 	if (priv->macro_params[VA_MACRO].dev)
 		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
 
-	/* Request Clk before register access */
-	ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0) {
+		/* Request Clk before register access */
+		ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				true);
-	if (ret < 0) {
-		dev_err_ratelimited(priv->dev,
-			"%s: Failed to enable clock, ret:%d\n", __func__, ret);
-		goto err;
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: Failed to enable clock, ret:%d\n",
+				__func__, ret);
+			goto err;
+		}
 	}
 
 	bolero_ahb_write_device(
 			priv->macro_params[macro_id].io_base, reg, val);
 
-	bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0)
+		bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				false);
@@ -717,6 +725,12 @@
 	struct bolero_priv *priv = data;
 	int macro_idx;
 
+	if (!priv->dev_up) {
+		dev_err_ratelimited(priv->dev,
+				    "%s: already disabled\n", __func__);
+		return;
+	}
+
 	bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_PA_OFF_PRE_SSR);
 	regcache_cache_only(priv->regmap, true);
 
@@ -1100,6 +1114,13 @@
 			__func__);
 		ret = 0;
 	}
+	if (priv->version == BOLERO_VERSION_2_1) {
+		bolero_reg_access[TX_MACRO] = bolero_tx_reg_access_v2;
+		bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v2;
+	} else if (priv->version == BOLERO_VERSION_2_0) {
+		bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v3;
+	}
+
 	priv->dev = &pdev->dev;
 	priv->dev_up = true;
 	priv->initial_boot = true;
diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h
index ba89832..d18568b 100644
--- a/asoc/codecs/bolero/internal.h
+++ b/asoc/codecs/bolero/internal.h
@@ -91,6 +91,9 @@
 extern const struct regmap_config bolero_regmap_config;
 extern u8 *bolero_reg_access[MAX_MACRO];
 extern u8 bolero_va_top_reg_access[BOLERO_CDC_VA_MACRO_TOP_MAX];
+extern u8 bolero_va_reg_access_v2[BOLERO_CDC_VA_MACRO_MAX];
+extern u8 bolero_va_reg_access_v3[BOLERO_CDC_VA_MACRO_MAX];
+extern u8 bolero_tx_reg_access_v2[BOLERO_CDC_TX_MACRO_MAX];
 extern const u16 macro_id_base_offset[MAX_MACRO];
 
 #endif
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index d27a5cf..31745d6 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -1475,10 +1475,6 @@
 	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[] = {
@@ -1528,6 +1524,10 @@
 			   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_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			tx_macro_tx_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | 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),
@@ -1921,6 +1921,15 @@
 	{"TX SMIC MUX7", "SWR_MIC9", "TX SWR_MIC9"},
 	{"TX SMIC MUX7", "SWR_MIC10", "TX SWR_MIC10"},
 	{"TX SMIC MUX7", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX SMIC MUX0", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX1", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX2", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX3", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX4", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX5", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX6", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX7", NULL, "TX_SWR_CLK"},
 };
 
 static const struct snd_soc_dapm_route tx_audio_map[] = {
@@ -2834,6 +2843,13 @@
 				tx_macro_reg_init[i].mask,
 				tx_macro_reg_init[i].val);
 
+	if (tx_priv->version == BOLERO_VERSION_2_1)
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0xF0, 0xA0);
+	else if (tx_priv->version == BOLERO_VERSION_2_0)
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0xF0, 0xA0);
+
 	return 0;
 }
 
diff --git a/asoc/codecs/msm-cdc-pinctrl.c b/asoc/codecs/msm-cdc-pinctrl.c
index cb7a52b..5c6ca49 100644
--- a/asoc/codecs/msm-cdc-pinctrl.c
+++ b/asoc/codecs/msm-cdc-pinctrl.c
@@ -196,7 +196,8 @@
 	struct msm_cdc_pinctrl_info *gpio_data;
 	u32 tlmm_gpio[MAX_GPIOS] = {0};
 	u32 chip_wakeup_reg[MAX_GPIOS] = {0};
-	u32 i = 0;
+	u32 chip_wakeup_default_val[MAX_GPIOS] = {0};
+	u32 i = 0, temp = 0;
 	int count = 0;
 
 	gpio_data = devm_kzalloc(&pdev->dev,
@@ -258,6 +259,20 @@
 			gpio_data->chip_wakeup_register[i] =
 				devm_ioremap(&pdev->dev, chip_wakeup_reg[i], 0x4);
 		}
+		if (of_property_read_u32_array(pdev->dev.of_node,
+					"qcom,chip-wakeup-default-val",
+					chip_wakeup_default_val, count)) {
+			for (i = 0; i < count; i++) {
+				temp = ioread32(gpio_data->chip_wakeup_register[i]);
+				if (chip_wakeup_default_val[i])
+					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]);
+			}
+		}
 		gpio_data->wakeup_reg_count = count;
 	}
 
diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c
index 9652d11..0635d54 100644
--- a/asoc/codecs/wcd-mbhc-adc.c
+++ b/asoc/codecs/wcd-mbhc-adc.c
@@ -694,7 +694,8 @@
 	 */
 	if (plug_type == MBHC_PLUG_TYPE_HEADSET ||
 	    plug_type == MBHC_PLUG_TYPE_HEADPHONE)
-		mbhc->mbhc_cb->bcs_enable(mbhc, false);
+		if (mbhc->mbhc_cb->bcs_enable)
+			mbhc->mbhc_cb->bcs_enable(mbhc, false);
 
 	timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
 	while (!time_after(jiffies, timeout)) {
@@ -842,7 +843,8 @@
 	}
 	if ((plug_type == MBHC_PLUG_TYPE_HEADSET ||
 	    plug_type == MBHC_PLUG_TYPE_HEADPHONE))
-		mbhc->mbhc_cb->bcs_enable(mbhc, true);
+		if (mbhc->mbhc_cb->bcs_enable)
+			mbhc->mbhc_cb->bcs_enable(mbhc, true);
 
 	if (!wrk_complete) {
 		/*
diff --git a/asoc/codecs/wcd937x/internal.h b/asoc/codecs/wcd937x/internal.h
index cd11c85..faf0118 100644
--- a/asoc/codecs/wcd937x/internal.h
+++ b/asoc/codecs/wcd937x/internal.h
@@ -133,6 +133,7 @@
 	WCD_BOLERO_EVT_RX_MUTE = 1,	/* for RX mute/unmute */
 	WCD_BOLERO_EVT_IMPED_TRUE,	/* for imped true */
 	WCD_BOLERO_EVT_IMPED_FALSE,	/* for imped false */
+	WCD_BOLERO_EVT_BCS_CLK_OFF,
 };
 
 enum {
@@ -164,6 +165,9 @@
 	WCD937X_NUM_IRQS,
 };
 
+extern void wcd937x_disable_bcs_before_slow_insert(
+				struct snd_soc_component *component,
+				bool bcs_disable);
 extern struct wcd937x_mbhc *wcd937x_soc_get_mbhc(
 				struct snd_soc_component *component);
 extern int wcd937x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
diff --git a/asoc/codecs/wcd937x/wcd937x-mbhc.c b/asoc/codecs/wcd937x/wcd937x-mbhc.c
index 2159cab..039f511 100644
--- a/asoc/codecs/wcd937x/wcd937x-mbhc.c
+++ b/asoc/codecs/wcd937x/wcd937x-mbhc.c
@@ -810,6 +810,15 @@
 			0x04, (enable << 2));
 }
 
+static void wcd937x_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
+						  bool bcs_enable)
+{
+	if (bcs_enable)
+		wcd937x_disable_bcs_before_slow_insert(mbhc->component, false);
+	else
+		wcd937x_disable_bcs_before_slow_insert(mbhc->component, true);
+}
+
 static const struct wcd_mbhc_cb mbhc_cb = {
 	.request_irq = wcd937x_mbhc_request_irq,
 	.irq_control = wcd937x_mbhc_irq_control,
@@ -834,6 +843,7 @@
 	.mbhc_get_moisture_status = wcd937x_mbhc_get_moisture_status,
 	.mbhc_moisture_polling_ctrl = wcd937x_mbhc_moisture_polling_ctrl,
 	.mbhc_moisture_detect_en = wcd937x_mbhc_moisture_detect_en,
+	.bcs_enable = wcd937x_mbhc_bcs_enable,
 };
 
 static int wcd937x_get_hph_type(struct snd_kcontrol *kcontrol,
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 94e59d9..21325ae 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -1517,6 +1517,21 @@
 }
 EXPORT_SYMBOL(wcd937x_micbias_control);
 
+void wcd937x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
+					    bool bcs_disable)
+{
+	struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
+
+	if (wcd937x->update_wcd_event) {
+		if (bcs_disable)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
+		else
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
+	}
+}
+
 static int wcd937x_get_logical_addr(struct swr_device *swr_dev)
 {
 	int ret = 0;
@@ -1642,6 +1657,51 @@
 	return __wcd937x_codec_enable_micbias(w, event);
 }
 
+static int __wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
+						 int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int micb_num;
+
+	dev_dbg(component->dev, "%s: wname: %s, event: %d\n",
+		__func__, w->name, event);
+
+	if (strnstr(w->name, "VA MIC BIAS1", sizeof("VA MIC BIAS1")))
+		micb_num = MIC_BIAS_1;
+	else if (strnstr(w->name, "VA MIC BIAS2", sizeof("VA MIC BIAS2")))
+		micb_num = MIC_BIAS_2;
+	else if (strnstr(w->name, "VA MIC BIAS3", sizeof("VA MIC BIAS3")))
+		micb_num = MIC_BIAS_3;
+	else
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd937x_micbias_control(component, micb_num,
+					MICB_PULLUP_ENABLE, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* 1 msec delay as per HW requirement */
+		usleep_range(1000, 1100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd937x_micbias_control(component, micb_num,
+					MICB_PULLUP_DISABLE, true);
+		break;
+	};
+
+	return 0;
+
+}
+
+static int wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
+					       struct snd_kcontrol *kcontrol,
+					       int event)
+{
+	return __wcd937x_codec_enable_micbias_pullup(w, event);
+}
+
 static int wcd937x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
@@ -2052,6 +2112,20 @@
 	SND_SOC_DAPM_OUTPUT("HPHL"),
 	SND_SOC_DAPM_OUTPUT("HPHR"),
 
+	/* micbias pull up widgets*/
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+				wcd937x_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS2", SND_SOC_NOPM, 0, 0,
+				wcd937x_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS3", SND_SOC_NOPM, 0, 0,
+				wcd937x_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
 };
 
 static const struct snd_soc_dapm_widget wcd9375_dapm_widgets[] = {
diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c
index 966fa8a..fc4f123 100644
--- a/asoc/codecs/wsa881x.c
+++ b/asoc/codecs/wsa881x.c
@@ -1395,6 +1395,7 @@
 			snd_soc_component_update_bits(wsa881x->component,
 					      WSA881X_SPKR_DRV_EN,
 					      0x80, 0x80);
+		break;
 	default:
 		break;
 	}
diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h
index 3f99f78..3f24712 100644
--- a/asoc/codecs/wsa883x/internal.h
+++ b/asoc/codecs/wsa883x/internal.h
@@ -63,12 +63,6 @@
 	u8 port_type;
 };
 
-enum {
-	WSA883X_DEV_DOWN,
-	WSA883X_DEV_UP,
-	WSA883X_DEV_READY,
-};
-
 extern struct regmap_config wsa883x_regmap_config;
 
 /*
@@ -81,24 +75,18 @@
 	struct swr_device *swr_slave;
 	struct snd_soc_component *component;
 	bool comp_enable;
-	bool boost_enable;
 	bool visense_enable;
-	u8 pa_gain;
+	bool ext_vdd_spk;
 	struct swr_port port[WSA883X_MAX_SWR_PORTS];
 	int pd_gpio;
-	struct wsa883x_tz_priv tz_pdata;
-	int bg_cnt;
-	int clk_cnt;
-	int version;
-	struct mutex bg_lock;
+	int global_pa_cnt;
+	int dev_mode;
 	struct mutex res_lock;
-	struct mutex temp_lock;
 	struct snd_info_entry *entry;
 	struct snd_info_entry *version_entry;
-	int state;
-	struct delayed_work ocp_ctl_work;
 	struct device_node *wsa_rst_np;
 	int pa_mute;
+	int curr_temp;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_dent;
 	struct dentry *debugfs_peek;
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c
index 988196e..cbf9559 100644
--- a/asoc/codecs/wsa883x/wsa883x.c
+++ b/asoc/codecs/wsa883x/wsa883x.c
@@ -26,9 +26,33 @@
 #include <sound/tlv.h>
 #include <asoc/msm-cdc-pinctrl.h>
 #include "wsa883x.h"
-#include "wsa883x-temp-sensor.h"
 #include "internal.h"
 
+#define T1_TEMP -10
+#define T2_TEMP 150
+#define LOW_TEMP_THRESHOLD 5
+#define HIGH_TEMP_THRESHOLD 45
+#define TEMP_INVALID	0xFFFF
+#define WSA883X_TEMP_RETRY 3
+
+enum {
+	WSA_4OHMS =4,
+	WSA_8OHMS = 8,
+	WSA_16OHMS = 16,
+	WSA_32OHMS = 32,
+};
+
+struct wsa_temp_register {
+	u8 d1_msb;
+	u8 d1_lsb;
+	u8 d2_msb;
+	u8 d2_lsb;
+	u8 dmeas_msb;
+	u8 dmeas_lsb;
+};
+
+static int wsa883x_get_temperature(struct snd_soc_component *component,
+				   int *temp);
 #ifdef CONFIG_DEBUG_FS
 static int codec_debug_open(struct inode *inode, struct file *file)
 {
@@ -265,6 +289,43 @@
 };
 #endif
 
+static const char * const wsa_dev_mode_text[] = {
+	"speaker", "receiver", "ultrasound"
+};
+
+static const struct soc_enum wsa_dev_mode_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_dev_mode_text), wsa_dev_mode_text);
+
+static int wsa_dev_mode_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->dev_mode;
+
+	dev_dbg(component->dev, "%s: mode = 0x%x\n", __func__,
+			wsa883x->dev_mode);
+
+	return 0;
+}
+
+static int wsa_dev_mode_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	wsa883x->dev_mode =  ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
 static const char * const wsa_pa_gain_text[] = {
 	"G_18_DB", "G_16P5_DB", "G_15_DB", "G_13P5_DB", "G_12_DB", "G_10P5_DB",
 	"G_9_DB", "G_7P5_DB", "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB",
@@ -332,43 +393,19 @@
 	return 0;
 }
 
-static int wsa883x_get_t0_init(struct snd_kcontrol *kcontrol,
+static int wsa_get_temp(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component =
 			snd_soc_kcontrol_component(kcontrol);
-	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-	struct wsa883x_tz_priv *pdata = &wsa883x->tz_pdata;
+	int temp = 0;
 
-	ucontrol->value.integer.value[0] = pdata->t0_init;
-	dev_dbg(component->dev, "%s: t0 init %d\n", __func__, pdata->t0_init);
+	wsa883x_get_temperature(component, &temp);
+	ucontrol->value.integer.value[0] = temp;
 
 	return 0;
 }
 
-static int wsa883x_set_t0_init(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component =
-			snd_soc_kcontrol_component(kcontrol);
-	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-	struct wsa883x_tz_priv *pdata = &wsa883x->tz_pdata;
-
-	pdata->t0_init = ucontrol->value.integer.value[0];
-	dev_dbg(component->dev, "%s: t0 init %d\n", __func__, pdata->t0_init);
-
-	return 0;
-}
-
-static const struct snd_kcontrol_new wsa_snd_controls[] = {
-	SOC_ENUM_EXT("WSA PA Gain", wsa_pa_gain_enum,
-		     wsa_pa_gain_get, wsa_pa_gain_put),
-	SOC_SINGLE_EXT("WSA PA Mute", SND_SOC_NOPM, 0, 1, 0,
-		wsa883x_get_mute, wsa883x_set_mute),
-	SOC_SINGLE_EXT("WSA T0 Init", SND_SOC_NOPM, 0, 1, 0,
-		wsa883x_get_t0_init, wsa883x_set_t0_init),
-};
-
 static ssize_t wsa883x_codec_version_read(struct snd_info_entry *entry,
 			       void *file_private_data, struct file *file,
 			       char __user *buf, size_t count, loff_t pos)
@@ -454,89 +491,8 @@
 static void wsa883x_regcache_sync(struct wsa883x_priv *wsa883x)
 {
 	mutex_lock(&wsa883x->res_lock);
-	if (wsa883x->state != WSA883X_DEV_READY) {
-		regcache_mark_dirty(wsa883x->regmap);
-		regcache_sync(wsa883x->regmap);
-		wsa883x->state = WSA883X_DEV_READY;
-	}
-	mutex_unlock(&wsa883x->res_lock);
-}
-
-static int wsa883x_visense_txfe_ctrl(struct snd_soc_component *component,
-				     bool enable, u8 isense1_gain,
-				     u8 isense2_gain, u8 vsense_gain)
-{
-	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-
-	dev_dbg(component->dev,
-		"%s: enable:%d, isense1 gain: %d, isense2 gain: %d, vsense_gain %d\n",
-		__func__, enable, isense1_gain, isense2_gain, vsense_gain);
-
-	return 0;
-}
-
-static int wsa883x_visense_adc_ctrl(struct snd_soc_component *component,
-				    bool enable)
-{
-
-	dev_dbg(component->dev, "%s: enable:%d\n", __func__, enable);
-
-	return 0;
-}
-
-static void wsa883x_bandgap_ctrl(struct snd_soc_component *component,
-				 bool enable)
-{
-	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-
-	dev_dbg(component->dev, "%s: enable:%d, bg_count:%d\n", __func__,
-		enable, wsa883x->bg_cnt);
-	mutex_lock(&wsa883x->bg_lock);
-	if (enable) {
-		++wsa883x->bg_cnt;
-		if (wsa883x->bg_cnt == 1) {
-			snd_soc_component_update_bits(component,
-					WSA883X_OP_CTL,
-					0x08, 0x08);
-		}
-	} else {
-		--wsa883x->bg_cnt;
-		if (wsa883x->bg_cnt <= 0) {
-			WARN_ON(wsa883x->bg_cnt < 0);
-			wsa883x->bg_cnt = 0;
-			snd_soc_component_update_bits(component,
-					WSA883X_OP_CTL, 0x08, 0x00);
-		}
-	}
-	mutex_unlock(&wsa883x->bg_lock);
-}
-
-static void wsa883x_clk_ctrl(struct snd_soc_component *component, bool enable)
-{
-	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-
-	dev_dbg(component->dev, "%s: enable:%d, clk_count:%d\n", __func__,
-		enable, wsa883x->clk_cnt);
-	mutex_lock(&wsa883x->res_lock);
-	if (enable) {
-		++wsa883x->clk_cnt;
-		if (wsa883x->clk_cnt == 1) {
-			snd_soc_component_write(component,
-					WSA883X_CDC_CLK_CTL, 0x01);
-			snd_soc_component_write(component,
-					WSA883X_CLK_CTL, 0x01);
-		}
-	} else {
-		--wsa883x->clk_cnt;
-		if (wsa883x->clk_cnt <= 0) {
-			WARN_ON(wsa883x->clk_cnt < 0);
-			wsa883x->clk_cnt = 0;
-			snd_soc_component_write(component,
-					WSA883X_CDC_CLK_CTL, 0x00);
-			snd_soc_component_write(component,
-					WSA883X_CLK_CTL, 0x00);
-		}
-	}
+	regcache_mark_dirty(wsa883x->regmap);
+	regcache_sync(wsa883x->regmap);
 	mutex_unlock(&wsa883x->res_lock);
 }
 
@@ -590,12 +546,54 @@
 	return 0;
 }
 
+static int wsa883x_get_ext_vdd_spk(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->ext_vdd_spk;
+
+	return 0;
+}
+
+static int wsa883x_put_ext_vdd_spk(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: Ext VDD SPK enable current %d, new %d\n",
+		 __func__, wsa883x->ext_vdd_spk, value);
+	wsa883x->ext_vdd_spk = value;
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new wsa883x_snd_controls[] = {
+	SOC_ENUM_EXT("WSA PA Gain", wsa_pa_gain_enum,
+		     wsa_pa_gain_get, wsa_pa_gain_put),
+
+	SOC_SINGLE_EXT("WSA PA Mute", SND_SOC_NOPM, 0, 1, 0,
+		wsa883x_get_mute, wsa883x_set_mute),
+
+	SOC_SINGLE_EXT("WSA Temp", SND_SOC_NOPM, 0, 1, 0,
+			wsa_get_temp, NULL),
+
+	SOC_ENUM_EXT("WSA MODE", wsa_dev_mode_enum,
+		     wsa_dev_mode_get, wsa_dev_mode_put),
+
 	SOC_SINGLE_EXT("COMP Switch", SND_SOC_NOPM, 0, 1, 0,
 		wsa883x_get_compander, wsa883x_set_compander),
 
 	SOC_SINGLE_EXT("VISENSE Switch", SND_SOC_NOPM, 0, 1, 0,
 		wsa883x_get_visense, wsa883x_set_visense),
+
+	SOC_SINGLE_EXT("External VDD_SPK", SND_SOC_NOPM, 0, 1, 0,
+		wsa883x_get_ext_vdd_spk, wsa883x_put_ext_vdd_spk),
 };
 
 static const struct snd_kcontrol_new swr_dac_port[] = {
@@ -661,8 +659,14 @@
 					&port_type[0]);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
+		swr_slvdev_datapath_control(wsa883x->swr_slave,
+					    wsa883x->swr_slave->dev_num,
+					    true);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
+		swr_slvdev_datapath_control(wsa883x->swr_slave,
+					    wsa883x->swr_slave->dev_num,
+					    false);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		wsa883x_set_port(component, SWR_DAC_PORT,
@@ -694,52 +698,7 @@
 	return 0;
 }
 
-static int wsa883x_rdac_event(struct snd_soc_dapm_widget *w,
-			struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_component *component =
-			snd_soc_dapm_to_component(w->dapm);
-	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-
-	dev_dbg(component->dev, "%s: %s event: %d visense %d\n", __func__,
-		w->name, event, wsa883x->visense_enable);
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		mutex_lock(&wsa883x->temp_lock);
-		wsa883x_resource_acquire(component, ENABLE);
-		mutex_unlock(&wsa883x->temp_lock);
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		swr_slvdev_datapath_control(wsa883x->swr_slave,
-					    wsa883x->swr_slave->dev_num,
-					    false);
-		mutex_lock(&wsa883x->temp_lock);
-		wsa883x_resource_acquire(component, DISABLE);
-		mutex_unlock(&wsa883x->temp_lock);
-		break;
-	}
-	return 0;
-}
-
-static int wsa883x_ramp_pa_gain(struct snd_soc_component *component,
-				int min_gain, int max_gain, int udelay)
-{
-	int val;
-
-	for (val = min_gain; max_gain <= val; val--) {
-		snd_soc_component_update_bits(component, WSA883X_SPKR_DRV_GAIN,
-				    0xF0, val << 4);
-		/*
-		 * 1ms delay is needed for every step change in gain as per
-		 * HW requirement.
-		 */
-		usleep_range(udelay, udelay + 10);
-	}
-	return 0;
-}
-
-static int wsa883x_spkr_pa_event(struct snd_soc_dapm_widget *w,
+static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
 			struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_component *component =
@@ -750,54 +709,16 @@
 	dev_dbg(component->dev, "%s: %s %d\n", __func__, w->name, event);
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		swr_slvdev_datapath_control(wsa883x->swr_slave,
-					    wsa883x->swr_slave->dev_num,
-					    true);
-		/* Set register mode if compander is not enabled */
-		if (!wsa883x->comp_enable)
-			snd_soc_component_update_bits(component,
-					WSA883X_SPKR_DRV_GAIN,
-					0x08, 0x08);
-		else
-			snd_soc_component_update_bits(component,
-					WSA883X_SPKR_DRV_GAIN,
-					0x08, 0x00);
-
+		/* TODO Vote for Global PA */
 		break;
+
 	case SND_SOC_DAPM_POST_PMU:
-		if (!wsa883x->comp_enable) {
-			max_gain = wsa883x->pa_gain;
-			/*
-			 * Gain has to set incrementally in 4 steps
-			 * as per HW sequence
-			 */
-			if (max_gain > G_4P5DB)
-				min_gain = G_0DB;
-			else
-				min_gain = max_gain + 3;
-			/*
-			 * 1ms delay is needed before change in gain
-			 * as per HW requirement.
-			 */
-			usleep_range(1000, 1010);
-			wsa883x_ramp_pa_gain(component, min_gain, max_gain,
-					1000);
-		}
-		if (wsa883x->visense_enable) {
-			wsa883x_visense_txfe_ctrl(component, ENABLE,
-						0x00, 0x03, 0x01);
-			wsa883x_visense_adc_ctrl(component, ENABLE);
-		}
 		/* Force remove group */
 		swr_remove_from_group(wsa883x->swr_slave,
 				      wsa883x->swr_slave->dev_num);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (wsa883x->visense_enable) {
-			wsa883x_visense_adc_ctrl(component, DISABLE);
-			wsa883x_visense_txfe_ctrl(component, DISABLE,
-						0x00, 0x01, 0x01);
-		}
+		/* TODO Unvote for Global PA */
 		break;
 	}
 	return 0;
@@ -805,28 +726,17 @@
 
 static const struct snd_soc_dapm_widget wsa883x_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("IN"),
-
 	SND_SOC_DAPM_MIXER_E("SWR DAC_Port", SND_SOC_NOPM, 0, 0, swr_dac_port,
 		ARRAY_SIZE(swr_dac_port), wsa883x_enable_swr_dac_port,
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_DAC_E("RDAC", NULL, WSA883X_SPKR_DAC_CTL, 7, 0,
-		wsa883x_rdac_event,
-		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_PGA_E("SPKR PGA", WSA883X_SPKR_DRV_EN, 7, 0, NULL, 0,
-			wsa883x_spkr_pa_event, SND_SOC_DAPM_PRE_PMU |
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_OUTPUT("SPKR"),
+	SND_SOC_DAPM_SPK("SPKR", wsa883x_spkr_event),
 };
 
 static const struct snd_soc_dapm_route wsa883x_audio_map[] = {
 	{"SWR DAC_Port", "Switch", "IN"},
-	{"RDAC", NULL, "SWR DAC_Port"},
-	{"SPKR PGA", NULL, "RDAC"},
-	{"SPKR", NULL, "SPKR PGA"},
+	{"SPKR", NULL, "SWR DAC_Port"},
 };
 
 int wsa883x_set_channel_map(struct snd_soc_component *component, u8 *port,
@@ -856,7 +766,7 @@
 }
 EXPORT_SYMBOL(wsa883x_set_channel_map);
 
-static void wsa883x_init(struct snd_soc_component *component)
+static void wsa883x_codec_init(struct snd_soc_component *component)
 {
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
 
@@ -865,44 +775,19 @@
 
 }
 
-static int32_t wsa883x_resource_acquire(struct snd_soc_component *component,
-						bool enable)
-{
-	wsa883x_clk_ctrl(component, enable);
-	wsa883x_bandgap_ctrl(component, enable);
-	return 0;
-}
-
 static int32_t wsa883x_temp_reg_read(struct snd_soc_component *component,
 				     struct wsa_temp_register *wsa_temp_reg)
 {
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-	struct swr_device *dev;
-	u8 retry = WSA883X_NUM_RETRY;
-	u8 devnum = 0;
 
 	if (!wsa883x) {
 		dev_err(component->dev, "%s: wsa883x is NULL\n", __func__);
 		return -EINVAL;
 	}
-	dev = wsa883x->swr_slave;
-	if (dev && (wsa883x->state == WSA883X_DEV_DOWN)) {
-		while (swr_get_logical_dev_num(dev, dev->addr, &devnum) &&
-		       retry--) {
-			/* Retry after 1 msec delay */
-			usleep_range(1000, 1100);
-		}
-		if (retry == 0) {
-			dev_err(component->dev,
-				"%s get devnum %d for dev addr %lx failed\n",
-				__func__, devnum, dev->addr);
-			return -EINVAL;
-		}
-	}
-	wsa883x_regcache_sync(wsa883x);
-	mutex_lock(&wsa883x->temp_lock);
-	wsa883x_resource_acquire(component, ENABLE);
 
+	mutex_lock(&wsa883x->res_lock);
+
+	/* TODO Vote for global PA */
 	snd_soc_component_update_bits(component, WSA883X_TADC_VALUE_CTL,
 				0x01, 0x00);
 	wsa_temp_reg->dmeas_msb = snd_soc_component_read32(
@@ -920,12 +805,82 @@
 	wsa_temp_reg->d2_lsb = snd_soc_component_read32(
 					component, WSA883X_OTP_REG_4);
 
-	wsa883x_resource_acquire(component, DISABLE);
-	mutex_unlock(&wsa883x->temp_lock);
+	/* TODO Unvote for global PA */
+	mutex_unlock(&wsa883x->res_lock);
 
 	return 0;
 }
 
+static int wsa883x_get_temperature(struct snd_soc_component *component,
+				   int *temp)
+{
+	struct snd_soc_component *component;
+	struct wsa_temp_register reg;
+	int dmeas, d1, d2;
+	int ret = 0;
+	int temp_val = 0;
+	int t1 = T1_TEMP;
+	int t2 = T2_TEMP;
+	u8 retry = WSA883X_TEMP_RETRY;
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	if (!wsa883x)
+		return -EINVAL;
+
+	do {
+		ret = wsa883x_temp_reg_read(component, &reg)
+		if (ret) {
+			pr_err("%s: temp read failed: %d, current temp: %d\n",
+				__func__, ret, wsa883x->curr_temp);
+			if (temp)
+				*temp = wsa883x->curr_temp;
+			return 0;
+		}
+		/*
+		 * Temperature register values are expected to be in the
+		 * following range.
+		 * d1_msb  = 68 - 92 and d1_lsb  = 0, 64, 128, 192
+		 * d2_msb  = 185 -218 and  d2_lsb  = 0, 64, 128, 192
+		 */
+		if ((reg.d1_msb < 68 || reg.d1_msb > 92) ||
+		    (!(reg.d1_lsb == 0 || reg.d1_lsb == 64 || reg.d1_lsb == 128 ||
+			reg.d1_lsb == 192)) ||
+		    (reg.d2_msb < 185 || reg.d2_msb > 218) ||
+		    (!(reg.d2_lsb == 0 || reg.d2_lsb == 64 || reg.d2_lsb == 128 ||
+			reg.d2_lsb == 192))) {
+			printk_ratelimited("%s: Temperature registers[%d %d %d %d] are out of range\n",
+					   __func__, reg.d1_msb, reg.d1_lsb, reg.d2_msb,
+					   reg.d2_lsb);
+		}
+		dmeas = ((reg.dmeas_msb << 0x8) | reg.dmeas_lsb) >> 0x6;
+		d1 = ((reg.d1_msb << 0x8) | reg.d1_lsb) >> 0x6;
+		d2 = ((reg.d2_msb << 0x8) | reg.d2_lsb) >> 0x6;
+
+		if (d1 == d2)
+			temp_val = TEMP_INVALID;
+		else
+			temp_val = t1 + (((dmeas - d1) * (t2 - t1))/(d2 - d1));
+
+		if (temp_val <= LOW_TEMP_THRESHOLD ||
+			temp_val >= HIGH_TEMP_THRESHOLD) {
+			pr_debug("%s: T0: %d is out of range[%d, %d]\n", __func__,
+				 temp_val, LOW_TEMP_THRESHOLD, HIGH_TEMP_THRESHOLD);
+			if (retry--)
+				msleep(10);
+		} else {
+			break;
+		}
+	} while (retry);
+
+	wsa883x->curr_temp = temp_val;
+	if (temp)
+		*temp = temp_val;
+	pr_debug("%s: t0 measured: %d dmeas = %d, d1 = %d, d2 = %d\n",
+		  __func__, temp_val, dmeas, d1, d2);
+
+	return ret;
+}
+
 static int wsa883x_codec_probe(struct snd_soc_component *component)
 {
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
@@ -937,17 +892,9 @@
 
 	dev = wsa883x->swr_slave;
 	wsa883x->component = component;
-	mutex_init(&wsa883x->bg_lock);
-	wsa883x_init(component);
-	snprintf(wsa883x->tz_pdata.name, sizeof(wsa883x->tz_pdata.name),
-		"%s.%x", "wsatz", (u8)dev->addr);
-	wsa883x->bg_cnt = 0;
-	wsa883x->clk_cnt = 0;
-	wsa883x->tz_pdata.component = component;
-	wsa883x->tz_pdata.wsa_temp_reg_read = wsa883x_temp_reg_read;
-	wsa883x_init_thermal(&wsa883x->tz_pdata);
-	snd_soc_add_component_controls(component, wsa_snd_controls,
-				   ARRAY_SIZE(wsa_snd_controls));
+	wsa883x_codec_init(component);
+	wsa883x->global_pa_cnt = 0;
+
 	return 0;
 }
 
@@ -955,9 +902,10 @@
 {
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
 
-	if (wsa883x->tz_pdata.tz_dev)
-		wsa883x_deinit_thermal(wsa883x->tz_pdata.tz_dev);
-	mutex_destroy(&wsa883x->bg_lock);
+	if (!wsa883x)
+		return;
+
+	snd_soc_component_exit_regmap(component);
 
 	return;
 }
@@ -1046,8 +994,6 @@
 		goto dev_err;
 	}
 	mutex_init(&wsa883x->res_lock);
-	mutex_init(&wsa883x->temp_lock);
-	wsa883x->state = WSA883X_DEV_UP;
 
 #ifdef CONFIG_DEBUG_FS
 	if (!wcd938x->debugfs_dent) {
@@ -1103,10 +1049,7 @@
 	wsa883x->debugfs_dent = NULL;
 #endif
 	mutex_destroy(&wsa883x->res_lock);
-	mutex_destroy(&wsa883x->temp_lock);
 	snd_soc_unregister_component(&pdev->dev);
-	if (wsa883x->pd_gpio)
-		gpio_free(wsa883x->pd_gpio);
 	swr_set_dev_data(pdev, NULL);
 	return 0;
 }
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index 4347bec..4560299 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -408,8 +408,8 @@
 		gain_list[0] = volume_l;
 		gain_list[1] = volume_r;
 		gain_list[2] = volume_l;
-		num_channels = 3;
-		use_default = true;
+		if (use_default)
+			num_channels = 3;
 		rc = q6asm_set_multich_gain(prtd->audio_client, num_channels,
 					gain_list, chmap, use_default);
 	}
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index ae86f7a..9cddca0 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -5463,6 +5463,10 @@
 		*index = 37;
 		port_id = AFE_PORT_ID_HDMI_OVER_DP_RX;
 		break;
+	case 38:
+		*index = 38;
+		port_id = AFE_PORT_ID_SENARY_MI2S_RX;
+		break;
 	default:
 		*index = 0; /* NONE */
 		pr_err("%s: Invalid value %d\n", __func__, value);
@@ -5520,7 +5524,7 @@
 	"WSA_CDC_DMA_TX_0", "WSA_CDC_DMA_TX_1", "WSA_CDC_DMA_TX_2",
 	"SLIM_7_RX", "RX_CDC_DMA_RX_0", "RX_CDC_DMA_RX_1", "RX_CDC_DMA_RX_2",
 	"RX_CDC_DMA_RX_3", "TX_CDC_DMA_TX_0", "TERT_TDM_RX_2", "SEC_TDM_TX_0",
-	"DISPLAY_PORT1",
+	"DISPLAY_PORT1", "SEN_MI2S_RX",
 };
 
 static const struct soc_enum msm_route_ec_ref_rx_enum[] = {
@@ -17347,6 +17351,25 @@
 
 };
 
+static const struct snd_kcontrol_new rx_cdc_dma_rx_1_port_mixer_controls[] = {
+	SOC_DOUBLE_EXT("VA_CDC_DMA_TX_0", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_VA_CDC_DMA_TX_0, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_DOUBLE_EXT("TX_CDC_DMA_TX_3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_TX_CDC_DMA_TX_3, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_DOUBLE_EXT("SLIM_8_TX", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_SLIMBUS_8_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_DOUBLE_EXT("TERT_MI2S_TX", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
 static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
 	SOC_DOUBLE_EXT("INTERNAL_FM_TX", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_SLIMBUS_0_RX,
@@ -24223,6 +24246,10 @@
 			   SND_SOC_NOPM, 0, 0,
 			   rx_cdc_dma_rx_0_voice_mixer_controls,
 			   ARRAY_SIZE(rx_cdc_dma_rx_0_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX_CDC_DMA_RX_1_Voice Mixer",
+			   SND_SOC_NOPM, 0, 0,
+			   rx_cdc_dma_rx_1_voice_mixer_controls,
+			   ARRAY_SIZE(rx_cdc_dma_rx_1_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
 				ARRAY_SIZE(tx_voip_mixer_controls)),
@@ -24426,6 +24453,9 @@
 	SND_SOC_DAPM_MIXER("RX_CDC_DMA_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0,
 	rx_cdc_dma_rx_0_port_mixer_controls,
 	ARRAY_SIZE(rx_cdc_dma_rx_0_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX_CDC_DMA_RX_1 Port Mixer", SND_SOC_NOPM, 0, 0,
+	rx_cdc_dma_rx_1_port_mixer_controls,
+	ARRAY_SIZE(rx_cdc_dma_rx_1_port_mixer_controls)),
 	SND_SOC_DAPM_MIXER("QCHAT_Tx Mixer",
 	SND_SOC_NOPM, 0, 0, tx_qchat_mixer_controls,
 	ARRAY_SIZE(tx_qchat_mixer_controls)),
@@ -24989,9 +25019,11 @@
 	{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia4 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia8 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
+	{"MultiMedia9 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia4 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia8 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
+	{"MultiMedia9 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
 	{"MultiMedia1 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"},
 	{"MultiMedia1 Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"},
@@ -27008,6 +27040,11 @@
 	{"RX_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
 	{"RX_CDC_DMA_RX_0", NULL, "RX_CDC_DMA_RX_0_Voice Mixer"},
 
+	{"RX_CDC_DMA_RX_1_Voice Mixer", "Voip", "VOIP_DL"},
+	{"RX_CDC_DMA_RX_1_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
+	{"RX_CDC_DMA_RX_1_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
+	{"RX_CDC_DMA_RX_1", NULL, "RX_CDC_DMA_RX_1_Voice Mixer"},
+
 	{"VOC_EXT_EC MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"VOC_EXT_EC MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
 	{"VOC_EXT_EC MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
@@ -28157,6 +28194,12 @@
 	{"RX_CDC_DMA_RX_0 Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
 	{"RX_CDC_DMA_RX_0", NULL, "RX_CDC_DMA_RX_0 Port Mixer"},
 
+	{"RX_CDC_DMA_RX_1 Port Mixer", "VA_CDC_DMA_TX_0", "VA_CDC_DMA_TX_0"},
+	{"RX_CDC_DMA_RX_1 Port Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
+	{"RX_CDC_DMA_RX_1 Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
+	{"RX_CDC_DMA_RX_1 Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+	{"RX_CDC_DMA_RX_1", NULL, "RX_CDC_DMA_RX_1 Port Mixer"},
+
 	{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 6111832..7297a1e 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -110,7 +110,7 @@
 	wait_queue_head_t wait_wakeup;
 	struct task_struct *task;
 	wait_queue_head_t lpass_core_hw_wait;
-	uint32_t lpass_hw_core_client_hdl;
+	uint32_t lpass_hw_core_client_hdl[AFE_LPASS_CORE_HW_VOTE_MAX];
 	void (*tx_cb)(uint32_t opcode,
 		uint32_t token, uint32_t *payload, void *priv);
 	void (*rx_cb)(uint32_t opcode,
@@ -571,6 +571,8 @@
 
 static int32_t afe_callback(struct apr_client_data *data, void *priv)
 {
+	uint16_t i = 0;
+
 	if (!data) {
 		pr_err("%s: Invalid param data\n", __func__);
 		return -EINVAL;
@@ -598,7 +600,8 @@
 
 		/* Reset the core client handle in SSR/PDR use cases */
 		mutex_lock(&this_afe.afe_cmd_lock);
-		this_afe.lpass_hw_core_client_hdl = 0;
+		for (i = 0; i < AFE_LPASS_CORE_HW_VOTE_MAX; i++)
+			this_afe.lpass_hw_core_client_hdl[i] = 0;
 		mutex_unlock(&this_afe.afe_cmd_lock);
 
 		/*
@@ -673,7 +676,9 @@
 
 		pr_debug("%s: AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST handle %d\n",
 			__func__, payload[0]);
-		this_afe.lpass_hw_core_client_hdl = payload[0];
+		if (data->token < AFE_LPASS_CORE_HW_VOTE_MAX)
+			this_afe.lpass_hw_core_client_hdl[data->token] =
+								payload[0];
 		atomic_set(&this_afe.state, 0);
 		atomic_set(&this_afe.status, 0);
 		wake_up(&this_afe.lpass_core_hw_wait);
@@ -9086,7 +9091,8 @@
 	this_afe.mmap_handle = 0;
 	this_afe.vi_tx_port = -1;
 	this_afe.vi_rx_port = -1;
-	this_afe.lpass_hw_core_client_hdl = 0;
+	for (i = 0; i < AFE_LPASS_CORE_HW_VOTE_MAX; i++)
+		this_afe.lpass_hw_core_client_hdl[i] = 0;
 	this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
 	this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
 	this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
@@ -9218,7 +9224,7 @@
 	cmd_ptr->hdr.pkt_size = sizeof(hw_vote_cfg);
 	cmd_ptr->hdr.src_port = 0;
 	cmd_ptr->hdr.dest_port = 0;
-	cmd_ptr->hdr.token = 0;
+	cmd_ptr->hdr.token = hw_block_id;
 	cmd_ptr->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST;
 	cmd_ptr->hw_block_id = hw_block_id;
 	strlcpy(cmd_ptr->client_name, client_name,
@@ -9259,9 +9265,9 @@
 		goto done;
 	}
 
-	*client_handle = this_afe.lpass_hw_core_client_hdl;
+	*client_handle = this_afe.lpass_hw_core_client_hdl[hw_block_id];
 	pr_debug("%s: lpass_hw_core_client_hdl %d\n", __func__,
-		this_afe.lpass_hw_core_client_hdl);
+		this_afe.lpass_hw_core_client_hdl[hw_block_id]);
 done:
 	mutex_unlock(&this_afe.afe_cmd_lock);
 	return ret;
@@ -9291,7 +9297,7 @@
 
 	mutex_lock(&this_afe.afe_cmd_lock);
 
-	if (!this_afe.lpass_hw_core_client_hdl) {
+	if (!this_afe.lpass_hw_core_client_hdl[hw_block_id]) {
 		pr_debug("%s: SSR in progress, return\n", __func__);
 		goto done;
 	}
diff --git a/dsp/q6voice.c b/dsp/q6voice.c
index 77a08ee..e0491f1 100644
--- a/dsp/q6voice.c
+++ b/dsp/q6voice.c
@@ -4297,6 +4297,7 @@
 	struct cvp_set_mfc_config_cmd_v2 cvp_set_mfc_config_cmd;
 	void *apr_cvp;
 	u16 cvp_handle;
+	uint8_t ch_idx;
 	struct vss_icommon_param_data_mfc_config_v2_t *cvp_config_param_data =
 		&cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.param_data;
 	struct vss_param_mfc_config_info_t *mfc_config_info =
@@ -4345,9 +4346,15 @@
 	mfc_config_info->num_channels = v->dev_rx.no_of_channels;
 	mfc_config_info->bits_per_sample = 16;
 	mfc_config_info->sample_rate = v->dev_rx.sample_rate;
-	memcpy(&mfc_config_info->channel_type,
-	       v->dev_rx.channel_mapping,
-	       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
+
+	/*
+	 * Do not use memcpy here as channel_type in mfc_config structure is a
+	 * uint16_t array while channel_mapping array of device is of uint8_t
+	 */
+	for (ch_idx = 0; ch_idx < VSS_NUM_CHANNELS_MAX; ch_idx++) {
+		mfc_config_info->channel_type[ch_idx] =
+					v->dev_rx.channel_mapping[ch_idx];
+	}
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	v->async_err = 0;
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index d1b4f3c..9e1a0b2 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -483,10 +483,14 @@
 int afe_get_doa_tracking_mon(u16 port_id,
 	struct doa_tracking_mon_param *doa_tracking_data);
 
-#define AFE_LPASS_CORE_HW_BLOCK_ID_NONE                        0
-#define AFE_LPASS_CORE_HW_BLOCK_ID_AVTIMER                     2
-#define AFE_LPASS_CORE_HW_MACRO_BLOCK                          3
-#define AFE_LPASS_CORE_HW_DCODEC_BLOCK                         4
+enum {
+	AFE_LPASS_CORE_HW_BLOCK_ID_NONE,
+	AFE_LPASS_CORE_HW_RSVD,
+	AFE_LPASS_CORE_HW_BLOCK_ID_AVTIMER,
+	AFE_LPASS_CORE_HW_MACRO_BLOCK,
+	AFE_LPASS_CORE_HW_DCODEC_BLOCK,
+	AFE_LPASS_CORE_HW_VOTE_MAX
+};
 
 /* Handles audio-video timer (avtimer) and BTSC vote requests from clients.
  */
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index 008801f..2682c45 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -44,6 +44,7 @@
 #define ERR_AUTO_SUSPEND_TIMER_VAL 0x1
 
 #define SWRM_INTERRUPT_STATUS_MASK 0x1FDFD
+#define SWRM_LINK_STATUS_RETRY_CNT 0x5
 
 #define SWRM_ROW_48    48
 #define SWRM_ROW_50    50
@@ -314,6 +315,11 @@
 			func, reg[i], val[i]);
 }
 
+static bool is_swr_clk_needed(struct swr_mstr_ctrl *swrm)
+{
+	return ((swrm->version <= SWRM_VERSION_1_5_1) ? true : false);
+}
+
 static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm,
 				int core_type, bool enable)
 {
@@ -359,6 +365,30 @@
 	return ((swrm->bus_clk * 2) / ((row * col) * frame_sync));
 }
 
+static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm)
+{
+	int ret = 0;
+
+	if (!swrm->handle)
+		return -EINVAL;
+
+	mutex_lock(&swrm->clklock);
+	if (!swrm->dev_up) {
+		ret = -ENODEV;
+		goto exit;
+	}
+	if (swrm->core_vote) {
+		ret = swrm->core_vote(swrm->handle, true);
+		if (ret)
+			dev_err_ratelimited(swrm->dev,
+				"%s: core vote request failed\n", __func__);
+	}
+exit:
+	mutex_unlock(&swrm->clklock);
+
+	return ret;
+}
+
 static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
 {
 	int ret = 0;
@@ -372,13 +402,15 @@
 			ret = -ENODEV;
 			goto exit;
 		}
-		if (swrm->core_vote) {
-			ret = swrm->core_vote(swrm->handle, true);
-			if (ret) {
-				dev_err_ratelimited(swrm->dev,
-					"%s: clock enable req failed",
-					__func__);
-				goto exit;
+		if (is_swr_clk_needed(swrm)) {
+			if (swrm->core_vote) {
+				ret = swrm->core_vote(swrm->handle, true);
+				if (ret) {
+					dev_err_ratelimited(swrm->dev,
+						"%s: core vote request failed\n",
+						__func__);
+					goto exit;
+				}
 			}
 		}
 		swrm->clk_ref_count++;
@@ -415,14 +447,21 @@
 	if (!swrm->dev_up)
 		goto err;
 
-	ret = swrm_clk_request(swrm, TRUE);
-	if (ret) {
-		dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
-				    __func__);
+	if (is_swr_clk_needed(swrm)) {
+		ret = swrm_clk_request(swrm, TRUE);
+		if (ret) {
+			dev_err_ratelimited(swrm->dev,
+					    "%s: clock request failed\n",
+					    __func__);
+			goto err;
+		}
+	} else if (swrm_core_vote_request(swrm)) {
 		goto err;
 	}
+
 	iowrite32(temp, swrm->swrm_dig_base + reg);
-	swrm_clk_request(swrm, FALSE);
+	if (is_swr_clk_needed(swrm))
+		swrm_clk_request(swrm, FALSE);
 err:
 	mutex_unlock(&swrm->devlock);
 	return ret;
@@ -438,15 +477,21 @@
 	if (!swrm->dev_up)
 		goto err;
 
-	ret = swrm_clk_request(swrm, TRUE);
-	if (ret) {
-		dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
-				    __func__);
+	if (is_swr_clk_needed(swrm)) {
+		ret = swrm_clk_request(swrm, TRUE);
+		if (ret) {
+			dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
+					    __func__);
+			goto err;
+		}
+	} else if (swrm_core_vote_request(swrm)) {
 		goto err;
 	}
+
 	temp = ioread32(swrm->swrm_dig_base + reg);
 	*value = temp;
-	swrm_clk_request(swrm, FALSE);
+	if (is_swr_clk_needed(swrm))
+		swrm_clk_request(swrm, FALSE);
 err:
 	mutex_unlock(&swrm->devlock);
 	return ret;
@@ -494,6 +539,34 @@
 	return 0;
 }
 
+static bool swrm_check_link_status(struct swr_mstr_ctrl *swrm, bool active)
+{
+	int retry = SWRM_LINK_STATUS_RETRY_CNT;
+	int ret = false;
+	int status = active ? 0x1 : 0x0;
+	int comp_sts = 0x0;
+
+	if ((swrm->version <= SWRM_VERSION_1_5_1))
+		return true;
+
+	do {
+		comp_sts = swr_master_read(swrm, SWRM_COMP_STATUS) & 0x01;
+		/* check comp status and status requested met */
+		if ((comp_sts && status) || (!comp_sts && !status)) {
+			ret = true;
+			break;
+		}
+		retry--;
+		usleep_range(500, 510);
+	} while (retry);
+
+	if (retry == 0)
+		dev_err(swrm->dev, "%s: link status not %s\n", __func__,
+			active ? "connected" : "disconnected");
+
+	return ret;
+}
+
 static bool swrm_is_port_en(struct swr_master *mstr)
 {
 	return !!(mstr->num_port);
@@ -1795,6 +1868,7 @@
 		case SWRM_INTERRUPT_STATUS_AUTO_ENUM_TABLE_IS_FULL_V2:
 			break;
 		case SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2:
+			swrm_check_link_status(swrm, 0x1);
 			break;
 		case SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED_V2:
 			break;
@@ -2615,6 +2689,8 @@
 			swrm_master_init(swrm);
 			/* wait for hw enumeration to complete */
 			usleep_range(100, 105);
+			if (!swrm_check_link_status(swrm, 0x1))
+				goto exit;
 			swrm_cmd_fifo_wr_cmd(swrm, 0x4, 0xF, 0x0,
 						SWRS_SCP_INT_STATUS_MASK_1);
 			if (swrm->state == SWR_MSTR_SSR) {
@@ -2626,6 +2702,8 @@
 			/*wake up from clock stop*/
 			swr_master_write(swrm, SWRM_MCP_BUS_CTRL_ADDR, 0x2);
 			usleep_range(100, 105);
+			if (!swrm_check_link_status(swrm, 0x1))
+				goto exit;
 		}
 		swrm->state = SWR_MSTR_UP;
 	}
@@ -2726,6 +2804,8 @@
 					SWR_WAKE_IRQ_REGISTER, (void *)swrm);
 				swrm->ipc_wakeup_triggered = false;
 			}
+			if (!swrm_check_link_status(swrm, 0x0))
+				goto exit;
 		}
 
 	}
diff --git a/soc/swrm_registers.h b/soc/swrm_registers.h
index 6f2544b..63fe4ca 100644
--- a/soc/swrm_registers.h
+++ b/soc/swrm_registers.h
@@ -17,6 +17,7 @@
 #define SWRM_COMP_CFG_ENABLE_SHFT			0x0
 
 #define SWRM_COMP_SW_RESET		(SWRM_BASE_ADDRESS+0x00000008)
+#define SWRM_COMP_STATUS		(SWRM_BASE_ADDRESS+0x00000014)
 
 #define SWRM_COMP_PARAMS		(SWRM_BASE_ADDRESS+0x100)
 #define SWRM_COMP_PARAMS_DOUT_PORTS_MASK	0x0000001F