Merge "asoc: qcs405: fix pop at end of DSD playback"
diff --git a/Android.mk b/Android.mk
index f5b8931..e0d3f0f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -60,3 +60,8 @@
 $(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/wcd937x/Module.symvers)
 include $(MY_LOCAL_PATH)/asoc/codecs/wcd937x/Android.mk
 endif
+
+ifeq ($(call is-board-platform-in-list, lito),true)
+$(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/wsa883x/Module.symvers)
+include $(MY_LOCAL_PATH)/asoc/codecs/wsa883x/Android.mk
+endif
\ No newline at end of file
diff --git a/asoc/bengal.c b/asoc/bengal.c
index 1ab7f99..ec73cc9 100644
--- a/asoc/bengal.c
+++ b/asoc/bengal.c
@@ -5030,6 +5030,33 @@
 		.ignore_suspend = 1,
 		.ignore_pmdown_time = 1,
 	},
+	/* Proxy Tx BACK END DAI Link */
+	{
+		.name = LPASS_BE_PROXY_TX,
+		.stream_name = "Proxy Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.8195",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_PROXY_TX,
+		.ignore_suspend = 1,
+	},
+	/* Proxy Rx BACK END DAI Link */
+	{
+		.name = LPASS_BE_PROXY_RX,
+		.stream_name = "Proxy Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.8194",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_PROXY_RX,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
 	{
 		.name = LPASS_BE_USB_AUDIO_RX,
 		.stream_name = "USB Audio Playback",
diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild
index 7a2cfcd..5ab7c3b 100644
--- a/asoc/codecs/Kbuild
+++ b/asoc/codecs/Kbuild
@@ -227,6 +227,7 @@
 	obj-y	+= wcd938x/
 	obj-y	+= bolero/
 	obj-y	+= rouleur/
+	obj-y	+= wsa883x/
 endif
 # Module information used by KBuild framework
 obj-$(CONFIG_WCD9XXX_CODEC_CORE) += wcd_core_dlkm.o
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 2db0c5b..417b34d 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -14,6 +14,7 @@
 #include <soc/snd_event.h>
 #include <linux/pm_runtime.h>
 #include <soc/swr-common.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
 #include "bolero-cdc.h"
 #include "internal.h"
 #include "bolero-clk-rsc.h"
@@ -1367,6 +1368,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
 int bolero_runtime_resume(struct device *dev)
 {
 	struct bolero_priv *priv = dev_get_drvdata(dev->parent);
@@ -1379,7 +1381,7 @@
 	}
 
 	if (priv->core_hw_vote_count == 0) {
-		ret = clk_prepare_enable(priv->lpass_core_hw_vote);
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote);
 		if (ret < 0) {
 			dev_err(dev, "%s:lpass core hw enable failed\n",
 				__func__);
@@ -1397,7 +1399,7 @@
 	}
 
 	if (priv->core_audio_vote_count == 0) {
-		ret = clk_prepare_enable(priv->lpass_audio_hw_vote);
+		ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote);
 		if (ret < 0) {
 			dev_err(dev, "%s:lpass audio hw enable failed\n",
 				__func__);
@@ -1422,7 +1424,8 @@
 	mutex_lock(&priv->vote_lock);
 	if (priv->lpass_core_hw_vote != NULL) {
 		if (--priv->core_hw_vote_count == 0)
-			clk_disable_unprepare(priv->lpass_core_hw_vote);
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_core_hw_vote);
 		if (priv->core_hw_vote_count < 0)
 			priv->core_hw_vote_count = 0;
 	} else {
@@ -1434,7 +1437,8 @@
 
 	if (priv->lpass_audio_hw_vote != NULL) {
 		if (--priv->core_audio_vote_count == 0)
-			clk_disable_unprepare(priv->lpass_audio_hw_vote);
+			digital_cdc_rsc_mgr_hw_vote_disable(
+					priv->lpass_audio_hw_vote);
 		if (priv->core_audio_vote_count < 0)
 			priv->core_audio_vote_count = 0;
 	} else {
@@ -1448,6 +1452,7 @@
 	return 0;
 }
 EXPORT_SYMBOL(bolero_runtime_suspend);
+#endif /* CONFIG_PM */
 
 bool bolero_check_core_votes(struct device *dev)
 {
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index ea1a374..70b0126 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -1908,7 +1908,12 @@
 				0x40, 0x40);
 		break;
 	case INTERP_HPHR:
-		snd_soc_component_update_bits(component,
+		if (rx_priv->is_ear_mode_on)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_CLSH_HPH_V_PA,
+				0x3F, 0x39);
+		else
+			snd_soc_component_update_bits(component,
 				BOLERO_CDC_RX_CLSH_HPH_V_PA,
 				0x3F, 0x1C);
 		snd_soc_component_update_bits(component,
@@ -4135,6 +4140,10 @@
 };
 
 static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
 	SET_RUNTIME_PM_OPS(
 		bolero_runtime_suspend,
 		bolero_runtime_resume,
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index 9fe19c1..121f56d 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -496,8 +496,6 @@
 				hpf_cut_off_freq << 5);
 		snd_soc_component_update_bits(component, hpf_gate_reg,
 						0x03, 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);
 	} else {
@@ -980,11 +978,12 @@
 		if (tx_unmute_delay < unmute_delay)
 			tx_unmute_delay = unmute_delay;
 		/* schedule work queue to Remove Mute */
-		schedule_delayed_work(&tx_priv->tx_mute_dwork[decimator].dwork,
-				      msecs_to_jiffies(tx_unmute_delay));
+		queue_delayed_work(system_freezable_wq,
+				   &tx_priv->tx_mute_dwork[decimator].dwork,
+				   msecs_to_jiffies(tx_unmute_delay));
 		if (tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq !=
 							CF_MIN_3DB_150HZ) {
-			schedule_delayed_work(
+			queue_delayed_work(system_freezable_wq,
 				&tx_priv->tx_hpf_work[decimator].dwork,
 				msecs_to_jiffies(hpf_delay));
 			snd_soc_component_update_bits(component,
@@ -992,10 +991,6 @@
 			if (!is_amic_enabled(component, decimator))
 				snd_soc_component_update_bits(component,
 					hpf_gate_reg, 0x03, 0x00);
-			/*
-			 * 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);
 			/*
@@ -3297,6 +3292,10 @@
 };
 
 static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
 	SET_RUNTIME_PM_OPS(
 		bolero_runtime_suspend,
 		bolero_runtime_resume,
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index 85d4ae3..a947a28 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -16,6 +16,7 @@
 #include <asoc/msm-cdc-pinctrl.h>
 #include <soc/swr-common.h>
 #include <soc/swr-wcd.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
 #include "bolero-cdc.h"
 #include "bolero-cdc-registers.h"
 #include "bolero-clk-rsc.h"
@@ -444,7 +445,8 @@
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		if (va_priv->lpass_audio_hw_vote) {
-			ret = clk_prepare_enable(va_priv->lpass_audio_hw_vote);
+			ret = digital_cdc_rsc_mgr_hw_vote_enable(
+					va_priv->lpass_audio_hw_vote);
 			if (ret)
 				dev_err(va_dev,
 					"%s: lpass audio hw enable failed\n",
@@ -467,7 +469,8 @@
 		if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG))
 			dev_dbg(va_dev, "%s: clock switch failed\n",__func__);
 		if (va_priv->lpass_audio_hw_vote)
-			clk_disable_unprepare(va_priv->lpass_audio_hw_vote);
+			digital_cdc_rsc_mgr_hw_vote_disable(
+				va_priv->lpass_audio_hw_vote);
 		break;
 	default:
 		dev_err(va_priv->dev,
@@ -1183,11 +1186,12 @@
 		 */
 		usleep_range(6000, 6010);
 		/* schedule work queue to Remove Mute */
-		schedule_delayed_work(&va_priv->va_mute_dwork[decimator].dwork,
-				      msecs_to_jiffies(va_tx_unmute_delay));
+		queue_delayed_work(system_freezable_wq,
+				   &va_priv->va_mute_dwork[decimator].dwork,
+				   msecs_to_jiffies(va_tx_unmute_delay));
 		if (va_priv->va_hpf_work[decimator].hpf_cut_off_freq !=
 							CF_MIN_3DB_150HZ)
-			schedule_delayed_work(
+			queue_delayed_work(system_freezable_wq,
 					&va_priv->va_hpf_work[decimator].dwork,
 					msecs_to_jiffies(hpf_delay));
 		/* apply gain after decimator is enabled */
@@ -3208,6 +3212,10 @@
 };
 
 static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
 	SET_RUNTIME_PM_OPS(
 		bolero_runtime_suspend,
 		bolero_runtime_resume,
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index e97d746..2ab2e8a 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -3244,6 +3244,10 @@
 };
 
 static const struct dev_pm_ops bolero_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(
+		pm_runtime_force_suspend,
+		pm_runtime_force_resume
+	)
 	SET_RUNTIME_PM_OPS(
 		bolero_runtime_suspend,
 		bolero_runtime_resume,
diff --git a/asoc/codecs/msm-cdc-supply.c b/asoc/codecs/msm-cdc-supply.c
index 220da9d..831562f 100644
--- a/asoc/codecs/msm-cdc-supply.c
+++ b/asoc/codecs/msm-cdc-supply.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/kernel.h>
@@ -119,6 +119,47 @@
 }
 
 /*
+ * msm_cdc_is_ondemand_supply:
+ *	return if ondemand supply true or not
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: supply name to be checked
+ *
+ * Return true/false
+ */
+bool msm_cdc_is_ondemand_supply(struct device *dev,
+				struct regulator_bulk_data *supplies,
+				struct cdc_regulator *cdc_vreg,
+				int num_supplies,
+				char *supply_name)
+{
+	bool rc = false;
+	int ret, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return rc;
+	}
+	/* input parameter validation */
+	ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (ret)
+		return rc;
+
+	for (i = 0; i < num_supplies; i++) {
+		if (cdc_vreg[i].ondemand &&
+			!strcmp(cdc_vreg[i].name, supply_name))
+			return true;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
+
+/*
  * msm_cdc_disable_ondemand_supply:
  *	Disable codec ondemand supply
  *
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 5c3f14f..30ad7e3 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -37,6 +37,8 @@
 #define WCD937X_VERSION_ENTRY_SIZE 32
 #define EAR_RX_PATH_AUX 1
 
+#define NUM_ATTEMPTS 5
+
 enum {
 	CODEC_TX = 0,
 	CODEC_RX,
@@ -568,7 +570,8 @@
 			snd_soc_component_update_bits(component,
 				WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L,
 				0x0F, 0x06);
-		snd_soc_component_update_bits(component,
+		if (wcd937x->comp1_enable)
+			snd_soc_component_update_bits(component,
 				WCD937X_DIGITAL_CDC_COMP_CTL_0,
 				0x02, 0x02);
 		usleep_range(5000, 5010);
@@ -586,6 +589,10 @@
 			snd_soc_component_update_bits(component,
 				WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L,
 				0x0F, 0x01);
+		if (wcd937x->comp1_enable)
+			snd_soc_component_update_bits(component,
+				WCD937X_DIGITAL_CDC_COMP_CTL_0,
+				0x02, 0x00);
 		break;
 	};
 	return 0;
@@ -1447,7 +1454,7 @@
 		mutex_unlock(&wcd937x->ana_tx_clk_lock);
 		if (wcd937x->micb_ref[micb_index] == 1) {
 			snd_soc_component_update_bits(component,
-				WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0xE0, 0xE0);
+				WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0xF0, 0xF0);
 			snd_soc_component_update_bits(component,
 				WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
 			snd_soc_component_update_bits(component,
@@ -1535,14 +1542,18 @@
 {
 	int ret = 0;
 	uint8_t devnum = 0;
+	int num_retry = NUM_ATTEMPTS;
 
-	ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
-	if (ret) {
-		dev_err(&swr_dev->dev,
-			"%s get devnum %d for dev addr %lx failed\n",
-			__func__, devnum, swr_dev->addr);
-		return ret;
-	}
+	do {
+		ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
+		if (ret) {
+			dev_err(&swr_dev->dev,
+				"%s get devnum %d for dev addr %lx failed\n",
+				__func__, devnum, swr_dev->addr);
+			/* retry after 1ms */
+			usleep_range(1000, 1010);
+		}
+	} while (ret && --num_retry);
 	swr_dev->dev_num = devnum;
 	return 0;
 }
diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h
index c59d5b8..f8a47fd 100644
--- a/asoc/codecs/wcd938x/internal.h
+++ b/asoc/codecs/wcd938x/internal.h
@@ -155,8 +155,8 @@
 
 enum {
 	/* INTR_CTRL_INT_MASK_0 */
-	WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET = 0,
-	WCD938X_IRQ_MBHC_BUTTON_PRESS_DET,
+	WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0,
+	WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET,
 	WCD938X_IRQ_MBHC_ELECT_INS_REM_DET,
 	WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
 	WCD938X_IRQ_MBHC_SW_DET,
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 8ade1d9..abd3106 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -657,8 +657,10 @@
 				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x04);
 			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x01);
-			snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x02);
+			if (wcd938x->comp1_enable)
+				snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_CDC_COMP_CTL_0,
+					0x02, 0x02);
 		}
 		/* 5 msec delay as per HW requirement */
 		usleep_range(5000, 5010);
@@ -683,8 +685,10 @@
 				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x04, 0x00);
 			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x01, 0x00);
-			snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x00);
+			if (wcd938x->comp1_enable)
+				snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_CDC_COMP_CTL_0,
+					0x02, 0x00);
 		}
 		snd_soc_component_update_bits(component,
 				WCD938X_ANA_EAR_COMPANDER_CTL, 0x80, 0x00);
@@ -777,7 +781,7 @@
 		usleep_range(100, 110);
 		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x13);
+				WCD938X_DIGITAL_PDM_WD_CTL1, 0x07, 0x03);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/*
@@ -857,7 +861,7 @@
 		snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
 						0x10, 0x00);
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x00);
+				WCD938X_DIGITAL_PDM_WD_CTL1, 0x07, 0x00);
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_POST_PA,
 			     WCD_CLSH_STATE_HPHR,
@@ -913,7 +917,7 @@
 		usleep_range(100, 110);
 		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x13);
+				WCD938X_DIGITAL_PDM_WD_CTL0, 0x07, 0x03);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/*
@@ -993,7 +997,7 @@
 		snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
 						0x20, 0x00);
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x00);
+				WCD938X_DIGITAL_PDM_WD_CTL0, 0x07, 0x00);
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_POST_PA,
 			     WCD_CLSH_STATE_HPHL,
@@ -1026,7 +1030,7 @@
 			    wcd938x->rx_swr_dev->dev_num,
 			    true);
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_PDM_WD_CTL2, 0x05, 0x05);
+				WCD938X_DIGITAL_PDM_WD_CTL2, 0x01, 0x01);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/* 1 msec delay as per HW requirement */
@@ -1054,7 +1058,7 @@
 		/* 1 msec delay as per HW requirement */
 		usleep_range(1000, 1010);
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_PDM_WD_CTL2, 0x05, 0x00);
+				WCD938X_DIGITAL_PDM_WD_CTL2, 0x01, 0x00);
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_POST_PA,
 			     WCD_CLSH_STATE_AUX,
@@ -1098,11 +1102,11 @@
 		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
 			snd_soc_component_update_bits(component,
 					WCD938X_DIGITAL_PDM_WD_CTL2,
-					0x05, 0x05);
+					0x01, 0x01);
 		else
 			snd_soc_component_update_bits(component,
 					WCD938X_DIGITAL_PDM_WD_CTL0,
-					0x17, 0x13);
+					0x07, 0x03);
 		if (!wcd938x->comp1_enable)
 			snd_soc_component_update_bits(component,
 				WCD938X_ANA_EAR_COMPANDER_CTL, 0x80, 0x80);
@@ -1157,11 +1161,11 @@
 		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
 			snd_soc_component_update_bits(component,
 					WCD938X_DIGITAL_PDM_WD_CTL2,
-					0x05, 0x00);
+					0x01, 0x00);
 		else
 			snd_soc_component_update_bits(component,
 					WCD938X_DIGITAL_PDM_WD_CTL0,
-					0x17, 0x00);
+					0x07, 0x00);
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_POST_PA,
 			     WCD_CLSH_STATE_EAR,
@@ -1878,7 +1882,7 @@
 		wcd938x->micb_ref[micb_index]++;
 		if (wcd938x->micb_ref[micb_index] == 1) {
 			snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0xE0, 0xE0);
+				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0xF0, 0xF0);
 			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
 			snd_soc_component_update_bits(component,
@@ -2360,6 +2364,67 @@
 	return 0;
 }
 
+static int wcd938x_codec_enable_vdd_buck(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 wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	struct wcd938x_pdata *pdata = NULL;
+	int ret = 0;
+
+	pdata = dev_get_platdata(wcd938x->dev);
+
+	if (!pdata) {
+		dev_err(component->dev, "%s: pdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!msm_cdc_is_ondemand_supply(wcd938x->dev,
+					wcd938x->supplies,
+					pdata->regulator,
+					pdata->num_supplies,
+					"cdc-vdd-buck"))
+		return 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (test_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask)) {
+			dev_dbg(component->dev,
+				"%s: buck already in enabled state\n",
+				__func__);
+			clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+			return 0;
+		}
+		ret = msm_cdc_enable_ondemand_supply(wcd938x->dev,
+						wcd938x->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-vdd-buck");
+		if (ret == -EINVAL) {
+			dev_err(component->dev, "%s: vdd buck is not enabled\n",
+				__func__);
+			return ret;
+		}
+		clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+		/*
+		 * 200us sleep is required after LDO is enabled as per
+		 * HW requirement
+		 */
+		usleep_range(200, 250);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		set_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+		break;
+	}
+	return 0;
+}
+
+
 static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
@@ -2779,6 +2844,10 @@
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 				SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0,
+			     wcd938x_codec_enable_vdd_buck,
+			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0,
 			     wcd938x_enable_clsh,
 			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
@@ -2936,6 +3005,7 @@
 	{"DMIC8_OUTPUT", NULL, "DMIC8_MIXER"},
 	{"DMIC8_MIXER", "Switch", "DMIC8"},
 
+	{"IN1_HPHL", NULL, "VDD_BUCK"},
 	{"IN1_HPHL", NULL, "CLS_H_PORT"},
 	{"RX1", NULL, "IN1_HPHL"},
 	{"RDAC1", NULL, "RX1"},
@@ -2943,6 +3013,7 @@
 	{"HPHL PGA", NULL, "HPHL_RDAC"},
 	{"HPHL", NULL, "HPHL PGA"},
 
+	{"IN2_HPHR", NULL, "VDD_BUCK"},
 	{"IN2_HPHR", NULL, "CLS_H_PORT"},
 	{"RX2", NULL, "IN2_HPHR"},
 	{"RDAC2", NULL, "RX2"},
@@ -2950,6 +3021,7 @@
 	{"HPHR PGA", NULL, "HPHR_RDAC"},
 	{"HPHR", NULL, "HPHR PGA"},
 
+	{"IN3_AUX", NULL, "VDD_BUCK"},
 	{"IN3_AUX", NULL, "CLS_H_PORT"},
 	{"RX3", NULL, "IN3_AUX"},
 	{"RDAC4", NULL, "RX3"},
@@ -3792,6 +3864,37 @@
 #ifdef CONFIG_PM_SLEEP
 static int wcd938x_suspend(struct device *dev)
 {
+	struct wcd938x_priv *wcd938x = NULL;
+	int ret = 0;
+	struct wcd938x_pdata *pdata = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd938x = dev_get_drvdata(dev);
+	if (!wcd938x)
+		return -EINVAL;
+
+	pdata = dev_get_platdata(wcd938x->dev);
+
+	if (!pdata) {
+		dev_err(dev, "%s: pdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (test_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask)) {
+		ret = msm_cdc_disable_ondemand_supply(wcd938x->dev,
+						wcd938x->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-vdd-buck");
+		if (ret == -EINVAL) {
+			dev_err(dev, "%s: vdd buck is not disabled\n",
+				__func__);
+			return 0;
+		}
+		clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask);
+	}
 	return 0;
 }
 
diff --git a/asoc/codecs/wsa881x-analog.c b/asoc/codecs/wsa881x-analog.c
index 038e338..fe8a5b9 100644
--- a/asoc/codecs/wsa881x-analog.c
+++ b/asoc/codecs/wsa881x-analog.c
@@ -398,9 +398,14 @@
 			snd_soc_component_update_bits(component,
 					WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
 					0x03, 0x00);
-			snd_soc_component_update_bits(component,
-						WSA881X_BOOST_PRESET_OUT1,
-						0xF0, 0x70);
+			if (snd_soc_component_read32(component, WSA881X_OTP_REG_0))
+				snd_soc_component_update_bits(component,
+					WSA881X_BOOST_PRESET_OUT1,
+					0xF0, 0x70);
+			else
+				snd_soc_component_update_bits(component,
+					WSA881X_BOOST_PRESET_OUT1,
+					0xF0, 0xB0);
 			snd_soc_component_update_bits(component,
 						WSA881X_ANA_CTL, 0x03, 0x01);
 			snd_soc_component_update_bits(component,
diff --git a/asoc/codecs/wsa883x/Android.mk b/asoc/codecs/wsa883x/Android.mk
index 66056e8..42ad517 100644
--- a/asoc/codecs/wsa883x/Android.mk
+++ b/asoc/codecs/wsa883x/Android.mk
@@ -9,7 +9,7 @@
 
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
-ifeq ($(call is-board-platform-in-list,lahaina),true)
+ifeq ($(call is-board-platform-in-list,lahaina lito),true)
 
 LOCAL_PATH := $(call my-dir)
 
diff --git a/asoc/codecs/wsa883x/Kbuild b/asoc/codecs/wsa883x/Kbuild
index 4eb844a..ac608b4 100644
--- a/asoc/codecs/wsa883x/Kbuild
+++ b/asoc/codecs/wsa883x/Kbuild
@@ -18,6 +18,10 @@
 		include $(AUDIO_ROOT)/config/lahainaauto.conf
 		INCS    +=  -include $(AUDIO_ROOT)/config/lahainaautoconf.h
 	endif
+	ifeq ($(CONFIG_ARCH_LITO), y)
+		include $(AUDIO_ROOT)/config/litoauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+	endif
 endif
 
 # As per target team, build is done as follows:
diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h
index 2384043..1863aac 100644
--- a/asoc/codecs/wsa883x/internal.h
+++ b/asoc/codecs/wsa883x/internal.h
@@ -1,11 +1,12 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef WSA883X_INTERNAL_H
 #define WSA883X_INTERNAL_H
 
+#include <asoc/wcd-irq.h>
 #include "wsa883x.h"
 #include "wsa883x-registers.h"
 
@@ -25,7 +26,11 @@
 #define WSA883X_DRV_NAME "wsa883x-codec"
 #define WSA883X_NUM_RETRY	5
 
-#define WSA883X_VERSION_ENTRY_SIZE 27
+#define WSA883X_VERSION_ENTRY_SIZE 32
+#define WSA883X_VARIANT_ENTRY_SIZE 32
+
+#define WSA883X_VERSION_1_0 0
+#define WSA883X_VERSION_1_1 1
 
 enum {
 	G_18DB = 0,
@@ -60,12 +65,13 @@
 	BOLERO_WSA_EVT_PA_OFF_PRE_SSR,
 	BOLERO_WSA_EVT_SSR_DOWN,
 	BOLERO_WSA_EVT_SSR_UP,
+	BOLERO_WSA_EVT_PA_ON_POST_FSCLK,
 };
 
 struct wsa_ctrl_platform_data {
-	void *handle,
+	void *handle;
 	int (*update_wsa_event)(void *handle, u16 event, u32 data);
-	int (*register_notifier)(void *handle, struct notifer_block *nblock,
+	int (*register_notifier)(void *handle, struct notifier_block *nblock,
 				bool enable);
 };
 
@@ -97,10 +103,13 @@
 	struct mutex res_lock;
 	struct snd_info_entry *entry;
 	struct snd_info_entry *version_entry;
+	struct snd_info_entry *variant_entry;
 	struct device_node *wsa_rst_np;
 	int pa_mute;
 	int curr_temp;
 	int variant;
+	int version;
+	u8 pa_gain;
 	struct irq_domain *virq;
 	struct wcd_irq_info irq_info;
 #ifdef CONFIG_DEBUG_FS
@@ -116,8 +125,11 @@
 	void *handle;
 	int (*register_notifier)(void *handle,
 				struct notifier_block *nblock, bool enable);
+	struct delayed_work vbat_work;
+	struct cdc_regulator *regulator;
+	int num_supplies;
+	struct regulator_bulk_data *supplies;
+	unsigned long status_mask;
 };
 
-static int32_t wsa883x_resource_acquire(struct snd_soc_component *component,
-						bool enable);
 #endif /* WSA883X_INTERNAL_H */
diff --git a/asoc/codecs/wsa883x/wsa883x-registers.h b/asoc/codecs/wsa883x/wsa883x-registers.h
index 7e518d2..6450a45 100644
--- a/asoc/codecs/wsa883x/wsa883x-registers.h
+++ b/asoc/codecs/wsa883x/wsa883x-registers.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2019-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef WSA883X_REGISTERS_H
@@ -15,7 +15,7 @@
 	RD_WR_REG,
 };
 
-#define WSA883X_ANA_BG_TSADC_BASE       (WSA883X_BASE+0x00000000)
+#define WSA883X_ANA_BG_TSADC_BASE       (WSA883X_BASE+0x00000001)
 #define WSA883X_REF_CTRL                (WSA883X_ANA_BG_TSADC_BASE+0x0000)
 #define WSA883X_TEST_CTL_0              (WSA883X_ANA_BG_TSADC_BASE+0x0001)
 #define WSA883X_BIAS_0                  (WSA883X_ANA_BG_TSADC_BASE+0x0002)
@@ -69,8 +69,8 @@
 #define WSA883X_SPKR_DRV_LF_MASK_DCC_CTL (WSA883X_ANA_SPK_TOP_BASE+0x000F)
 #define WSA883X_SPKR_DRV_LF_MISC_CTL    (WSA883X_ANA_SPK_TOP_BASE+0x0010)
 #define WSA883X_SPKR_DRV_LF_REG_GAIN    (WSA883X_ANA_SPK_TOP_BASE+0x0011)
-#define WSA883X_SPKR_DRV_LF_OS_CAL_CTL1 (WSA883X_ANA_SPK_TOP_BASE+0x0012)
-#define WSA883X_SPKR_DRV_LF_OS_CAL_CTL  (WSA883X_ANA_SPK_TOP_BASE+0x0013)
+#define WSA883X_SPKR_DRV_OS_CAL_CTL     (WSA883X_ANA_SPK_TOP_BASE+0x0012)
+#define WSA883X_SPKR_DRV_OS_CAL_CTL1     (WSA883X_ANA_SPK_TOP_BASE+0x0013)
 #define WSA883X_SPKR_PWM_CLK_CTL        (WSA883X_ANA_SPK_TOP_BASE+0x0014)
 #define WSA883X_SPKR_PDRV_HS_CTL        (WSA883X_ANA_SPK_TOP_BASE+0x0015)
 #define WSA883X_SPKR_PDRV_LS_CTL        (WSA883X_ANA_SPK_TOP_BASE+0x0016)
@@ -81,7 +81,7 @@
 #define WSA883X_PA_STATUS1              (WSA883X_ANA_SPK_TOP_BASE+0x001B)
 #define WSA883X_PA_STATUS2              (WSA883X_ANA_SPK_TOP_BASE+0x001C)
 
-#define WSA883X_ANA_BOOST_BASE          (WSA883X_BASE+0x00000045)
+#define WSA883X_ANA_BOOST_BASE          (WSA883X_BASE+0x00000043)
 #define WSA883X_EN_CTRL                 (WSA883X_ANA_BOOST_BASE+0x0000)
 #define WSA883X_CURRENT_LIMIT           (WSA883X_ANA_BOOST_BASE+0x0001)
 #define WSA883X_IBIAS1                  (WSA883X_ANA_BOOST_BASE+0x0002)
@@ -92,34 +92,35 @@
 #define WSA883X_STABILITY_CTRL2         (WSA883X_ANA_BOOST_BASE+0x0007)
 #define WSA883X_PWRSTAGE_CTRL1          (WSA883X_ANA_BOOST_BASE+0x0008)
 #define WSA883X_PWRSTAGE_CTRL2          (WSA883X_ANA_BOOST_BASE+0x0009)
-#define WSA883X_UVLO                    (WSA883X_ANA_BOOST_BASE+0x000A)
-#define WSA883X_SEQUENCE_CTRL           (WSA883X_ANA_BOOST_BASE+0x000B)
+#define WSA883X_BYPASS_1                (WSA883X_ANA_BOOST_BASE+0x000A)
+#define WSA883X_BYPASS_2                (WSA883X_ANA_BOOST_BASE+0x000B)
 #define WSA883X_ZX_CTRL_1               (WSA883X_ANA_BOOST_BASE+0x000C)
 #define WSA883X_ZX_CTRL_2               (WSA883X_ANA_BOOST_BASE+0x000D)
 #define WSA883X_MISC1                   (WSA883X_ANA_BOOST_BASE+0x000E)
 #define WSA883X_MISC2                   (WSA883X_ANA_BOOST_BASE+0x000F)
 #define WSA883X_GMAMP_SUP1              (WSA883X_ANA_BOOST_BASE+0x0010)
 #define WSA883X_PWRSTAGE_CTRL3          (WSA883X_ANA_BOOST_BASE+0x0011)
-#define WSA883X_PRSTAGE_CTRL4           (WSA883X_ANA_BOOST_BASE+0x0012)
-#define WSA883X_SPARE1                  (WSA883X_ANA_BOOST_BASE+0x0013)
+#define WSA883X_PWRSTAGE_CTRL4          (WSA883X_ANA_BOOST_BASE+0x0012)
+#define WSA883X_TEST1                   (WSA883X_ANA_BOOST_BASE+0x0013)
+#define WSA883X_SPARE1                  (WSA883X_ANA_BOOST_BASE+0x0014)
+#define WSA883X_SPARE2                  (WSA883X_ANA_BOOST_BASE+0x0015)
 
 #define WSA883X_ANA_PON_LDOL_BASE       (WSA883X_BASE+0x00000059)
 #define WSA883X_PON_CTL_0               (WSA883X_ANA_PON_LDOL_BASE+0x0000)
 #define WSA883X_PON_CLT_1               (WSA883X_ANA_PON_LDOL_BASE+0x0001)
 #define WSA883X_PON_CTL_2               (WSA883X_ANA_PON_LDOL_BASE+0x0002)
 #define WSA883X_PON_CTL_3               (WSA883X_ANA_PON_LDOL_BASE+0x0003)
-#define WSA883X_PON_CTL_4               (WSA883X_ANA_PON_LDOL_BASE+0x0004)
-#define WSA883X_CKWD_CTL_0              (WSA883X_ANA_PON_LDOL_BASE+0x0005)
-#define WSA883X_CKWD_CTL_1              (WSA883X_ANA_PON_LDOL_BASE+0x0006)
-#define WSA883X_CKWD_CTL_2              (WSA883X_ANA_PON_LDOL_BASE+0x0007)
-#define WSA883X_CKSK_CTL_0              (WSA883X_ANA_PON_LDOL_BASE+0x0008)
+#define WSA883X_CKWD_CTL_0              (WSA883X_ANA_PON_LDOL_BASE+0x0004)
+#define WSA883X_CKWD_CTL_1              (WSA883X_ANA_PON_LDOL_BASE+0x0005)
+#define WSA883X_CKWD_CTL_2              (WSA883X_ANA_PON_LDOL_BASE+0x0006)
+#define WSA883X_CKSK_CTL_0              (WSA883X_ANA_PON_LDOL_BASE+0x0007)
+#define WSA883X_PADSW_CTL_0             (WSA883X_ANA_PON_LDOL_BASE+0x0008)
 #define WSA883X_TEST_0                  (WSA883X_ANA_PON_LDOL_BASE+0x0009)
 #define WSA883X_TEST_1                  (WSA883X_ANA_PON_LDOL_BASE+0x000A)
 #define WSA883X_STATUS_0                (WSA883X_ANA_PON_LDOL_BASE+0x000B)
 #define WSA883X_STATUS_1                (WSA883X_ANA_PON_LDOL_BASE+0x000C)
 
 #define WSA883X_DIG_CTRL_BASE           (WSA883X_BASE+0x00000400)
-#define WSA883X_PAGE_REGISTER           (WSA883X_DIG_CTRL_BASE+0x0000)
 #define WSA883X_CHIP_ID0                (WSA883X_DIG_CTRL_BASE+0x0001)
 #define WSA883X_CHIP_ID1                (WSA883X_DIG_CTRL_BASE+0x0002)
 #define WSA883X_CHIP_ID2                (WSA883X_DIG_CTRL_BASE+0x0003)
@@ -130,6 +131,7 @@
 #define WSA883X_CDC_PATH_MODE           (WSA883X_DIG_CTRL_BASE+0x0008)
 #define WSA883X_CDC_CLK_CTL             (WSA883X_DIG_CTRL_BASE+0x0009)
 #define WSA883X_SWR_RESET_EN            (WSA883X_DIG_CTRL_BASE+0x000A)
+#define WSA883X_RESET_CTL               (WSA883X_DIG_CTRL_BASE+0x000B)
 #define WSA883X_PA_FSM_CTL              (WSA883X_DIG_CTRL_BASE+0x0010)
 #define WSA883X_PA_FSM_TIMER0           (WSA883X_DIG_CTRL_BASE+0x0011)
 #define WSA883X_PA_FSM_TIMER1           (WSA883X_DIG_CTRL_BASE+0x0012)
@@ -137,6 +139,7 @@
 #define WSA883X_PA_FSM_ERR_COND         (WSA883X_DIG_CTRL_BASE+0x0014)
 #define WSA883X_PA_FSM_MSK              (WSA883X_DIG_CTRL_BASE+0x0015)
 #define WSA883X_PA_FSM_BYP              (WSA883X_DIG_CTRL_BASE+0x0016)
+#define WSA883X_PA_FSM_DBG              (WSA883X_DIG_CTRL_BASE+0x0017)
 #define WSA883X_TADC_VALUE_CTL          (WSA883X_DIG_CTRL_BASE+0x0020)
 #define WSA883X_TEMP_DETECT_CTL         (WSA883X_DIG_CTRL_BASE+0x0021)
 #define WSA883X_TEMP_MSB                (WSA883X_DIG_CTRL_BASE+0x0022)
@@ -208,8 +211,10 @@
 #define WSA883X_WAVG_PER_2_3            (WSA883X_DIG_CTRL_BASE+0x0068)
 #define WSA883X_WAVG_PER_4_5            (WSA883X_DIG_CTRL_BASE+0x0069)
 #define WSA883X_WAVG_PER_6_7            (WSA883X_DIG_CTRL_BASE+0x006A)
+#define WSA883X_WAVG_STA                (WSA883X_DIG_CTRL_BASE+0x006B)
 #define WSA883X_DRE_CTL_0               (WSA883X_DIG_CTRL_BASE+0x006C)
 #define WSA883X_DRE_CTL_1               (WSA883X_DIG_CTRL_BASE+0x006D)
+#define WSA883X_DRE_IDLE_DET_CTL        (WSA883X_DIG_CTRL_BASE+0x006E)
 #define WSA883X_CLSH_CTL_0              (WSA883X_DIG_CTRL_BASE+0x0070)
 #define WSA883X_CLSH_CTL_1              (WSA883X_DIG_CTRL_BASE+0x0071)
 #define WSA883X_CLSH_V_HD_PA            (WSA883X_DIG_CTRL_BASE+0x0072)
@@ -249,26 +254,28 @@
 #define WSA883X_I2C_SLAVE_CTL           (WSA883X_DIG_CTRL_BASE+0x0097)
 #define WSA883X_PDM_TEST_MODE           (WSA883X_DIG_CTRL_BASE+0x00A0)
 #define WSA883X_ATE_TEST_MODE           (WSA883X_DIG_CTRL_BASE+0x00A1)
-#define WSA883X_DRE_TEST                (WSA883X_DIG_CTRL_BASE+0x00A2)
 #define WSA883X_DIG_DEBUG_MODE          (WSA883X_DIG_CTRL_BASE+0x00A3)
 #define WSA883X_DIG_DEBUG_SEL           (WSA883X_DIG_CTRL_BASE+0x00A4)
 #define WSA883X_DIG_DEBUG_EN            (WSA883X_DIG_CTRL_BASE+0x00A5)
 #define WSA883X_SWR_HM_TEST0            (WSA883X_DIG_CTRL_BASE+0x00A6)
 #define WSA883X_SWR_HM_TEST1            (WSA883X_DIG_CTRL_BASE+0x00A7)
 #define WSA883X_SWR_PAD_CTL             (WSA883X_DIG_CTRL_BASE+0x00A8)
-#define WSA883X_TEMP_DETECT_DBG_CTL     (WSA883X_DIG_CTRL_BASE+0x00A9)
-#define WSA883X_TEMP_DEBUG_MSB          (WSA883X_DIG_CTRL_BASE+0x00AA)
-#define WSA883X_TEMP_DEBUG_LSB          (WSA883X_DIG_CTRL_BASE+0x00AB)
+#define WSA883X_TADC_DETECT_DBG_CTL     (WSA883X_DIG_CTRL_BASE+0x00A9)
+#define WSA883X_TADC_DEBUG_MSB          (WSA883X_DIG_CTRL_BASE+0x00AA)
+#define WSA883X_TADC_DEBUG_LSB          (WSA883X_DIG_CTRL_BASE+0x00AB)
 #define WSA883X_SAMPLE_EDGE_SEL         (WSA883X_DIG_CTRL_BASE+0x00AC)
-#define WSA883X_TEST_MODE_CTL           (WSA883X_DIG_CTRL_BASE+0x00AD)
-#define WSA883X_IOPAD_CTL               (WSA883X_DIG_CTRL_BASE+0x00AE)
-#define WSA883X_SPARE_0                 (WSA883X_DIG_CTRL_BASE+0x00B0)
-#define WSA883X_SPARE_1                 (WSA883X_DIG_CTRL_BASE+0x00B1)
-#define WSA883X_SPARE_2                 (WSA883X_DIG_CTRL_BASE+0x00B2)
+#define WSA883X_SWR_EDGE_SEL            (WSA883X_DIG_CTRL_BASE+0x00AD)
+#define WSA883X_TEST_MODE_CTL           (WSA883X_DIG_CTRL_BASE+0x00AE)
+#define WSA883X_IOPAD_CTL               (WSA883X_DIG_CTRL_BASE+0x00AF)
+#define WSA883X_ANA_CSR_DBG_ADD         (WSA883X_DIG_CTRL_BASE+0x00B0)
+#define WSA883X_ANA_CSR_DBG_CTL         (WSA883X_DIG_CTRL_BASE+0x00B1)
+#define WSA883X_SPARE_R                 (WSA883X_DIG_CTRL_BASE+0x00BC)
+#define WSA883X_SPARE_0                 (WSA883X_DIG_CTRL_BASE+0x00BD)
+#define WSA883X_SPARE_1                 (WSA883X_DIG_CTRL_BASE+0x00BE)
+#define WSA883X_SPARE_2                 (WSA883X_DIG_CTRL_BASE+0x00BF)
 #define WSA883X_SCODE                   (WSA883X_DIG_CTRL_BASE+0x00C0)
 
 #define WSA883X_DIG_TRIM_BASE           (WSA883X_BASE+0x00000500)
-#define WSA883X_PAGE_REGISTER           (WSA883X_DIG_TRIM_BASE+0x0000)
 #define WSA883X_OTP_REG_0               (WSA883X_DIG_TRIM_BASE+0x0080)
 #define WSA883X_OTP_REG_1               (WSA883X_DIG_TRIM_BASE+0x0081)
 #define WSA883X_OTP_REG_2               (WSA883X_DIG_TRIM_BASE+0x0082)
@@ -301,7 +308,10 @@
 #define WSA883X_OTP_REG_29              (WSA883X_DIG_TRIM_BASE+0x009D)
 #define WSA883X_OTP_REG_30              (WSA883X_DIG_TRIM_BASE+0x009E)
 #define WSA883X_OTP_REG_31              (WSA883X_DIG_TRIM_BASE+0x009F)
-#define WSA883X_OTP_REG_SCODE           (WSA883X_DIG_TRIM_BASE+0x00A0)
+#define WSA883X_OTP_REG_32              (WSA883X_DIG_TRIM_BASE+0x00A0)
+#define WSA883X_OTP_REG_33              (WSA883X_DIG_TRIM_BASE+0x00A1)
+#define WSA883X_OTP_REG_34              (WSA883X_DIG_TRIM_BASE+0x00A2)
+#define WSA883X_OTP_REG_35              (WSA883X_DIG_TRIM_BASE+0x00A3)
 #define WSA883X_OTP_REG_63              (WSA883X_DIG_TRIM_BASE+0x00BF)
 
 #define WSA883X_DIG_EMEM_BASE           (WSA883X_BASE+0x000005C0)
diff --git a/asoc/codecs/wsa883x/wsa883x-regmap.c b/asoc/codecs/wsa883x/wsa883x-regmap.c
index 8394e9c..b55fbad 100644
--- a/asoc/codecs/wsa883x/wsa883x-regmap.c
+++ b/asoc/codecs/wsa883x/wsa883x-regmap.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 2019-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/regmap.h>
@@ -11,100 +11,101 @@
 extern const u8 wsa883x_reg_access[WSA883X_NUM_REGISTERS];
 
 static struct reg_default wsa883x_defaults[] = {
-	{WSA883X_REF_CTRL,                   0x6C},
+	{WSA883X_REF_CTRL,                   0xD5},
 	{WSA883X_TEST_CTL_0,                 0x06},
 	{WSA883X_BIAS_0,                     0xD2},
 	{WSA883X_OP_CTL,                     0xE0},
-	{WSA883X_IREF_CTL,                   0x58},
+	{WSA883X_IREF_CTL,                   0x57},
 	{WSA883X_ISENS_CTL,                  0x47},
 	{WSA883X_CLK_CTL,                    0x87},
 	{WSA883X_TEST_CTL_1,                 0x00},
 	{WSA883X_BIAS_1,                     0x51},
-	{WSA883X_ADC_CTL,                    0x03},
+	{WSA883X_ADC_CTL,                    0x01},
 	{WSA883X_DOUT_MSB,                   0x00},
 	{WSA883X_DOUT_LSB,                   0x00},
-	{WSA883X_VBAT_SNS,                   0x00},
-	{WSA883X_ITRIM_CODE,                 0x1F},
-	{WSA883X_EN,                         0x00},
+	{WSA883X_VBAT_SNS,                   0x40},
+	{WSA883X_ITRIM_CODE,                 0x9F},
+	{WSA883X_EN,                         0x20},
 	{WSA883X_OVERRIDE1,                  0x00},
 	{WSA883X_OVERRIDE2,                  0x08},
 	{WSA883X_VSENSE1,                    0xD3},
 	{WSA883X_ISENSE1,                    0xD4},
 	{WSA883X_ISENSE2,                    0x20},
 	{WSA883X_ISENSE_CAL,                 0x00},
-	{WSA883X_MISC,                       0x00},
+	{WSA883X_MISC,                       0x08},
 	{WSA883X_ADC_0,                      0x00},
 	{WSA883X_ADC_1,                      0x00},
-	{WSA883X_ADC_2,                      0x00},
-	{WSA883X_ADC_3,                      0x00},
-	{WSA883X_ADC_4,                      0x45},
-	{WSA883X_ADC_5,                      0x20},
-	{WSA883X_ADC_6,                      0x10},
-	{WSA883X_ADC_7,                      0x00},
+	{WSA883X_ADC_2,                      0x40},
+	{WSA883X_ADC_3,                      0x80},
+	{WSA883X_ADC_4,                      0x25},
+	{WSA883X_ADC_5,                      0x25},
+	{WSA883X_ADC_6,                      0x08},
+	{WSA883X_ADC_7,                      0x81},
 	{WSA883X_STATUS,                     0x00},
-	{WSA883X_DAC_CTRL_REG,               0x41},
+	{WSA883X_DAC_CTRL_REG,               0x53},
 	{WSA883X_DAC_EN_DEBUG_REG,           0x00},
 	{WSA883X_DAC_OPAMP_BIAS1_REG,        0x48},
 	{WSA883X_DAC_OPAMP_BIAS2_REG,        0x48},
-	{WSA883X_DAC_VCM_CTRL_REG,           0x0B},
-	{WSA883X_DAC_VOLTAGE_CTRL_REG,       0x05},
+	{WSA883X_DAC_VCM_CTRL_REG,           0x88},
+	{WSA883X_DAC_VOLTAGE_CTRL_REG,       0xA5},
 	{WSA883X_ATEST1_REG,                 0x00},
 	{WSA883X_ATEST2_REG,                 0x00},
-	{WSA883X_SPKR_TOP_BIAS_REG1,         0x4A},
+	{WSA883X_SPKR_TOP_BIAS_REG1,         0x6A},
 	{WSA883X_SPKR_TOP_BIAS_REG2,         0x65},
 	{WSA883X_SPKR_TOP_BIAS_REG3,         0x55},
 	{WSA883X_SPKR_TOP_BIAS_REG4,         0xA9},
-	{WSA883X_SPKR_CLIP_DET_REG,          0x00},
+	{WSA883X_SPKR_CLIP_DET_REG,          0x9C},
 	{WSA883X_SPKR_DRV_LF_BLK_EN,         0x0F},
 	{WSA883X_SPKR_DRV_LF_EN,             0x0A},
 	{WSA883X_SPKR_DRV_LF_MASK_DCC_CTL,   0x00},
-	{WSA883X_SPKR_DRV_LF_MISC_CTL,       0x32},
+	{WSA883X_SPKR_DRV_LF_MISC_CTL,       0x3A},
 	{WSA883X_SPKR_DRV_LF_REG_GAIN,       0x00},
-	{WSA883X_SPKR_DRV_LF_OS_CAL_CTL1,    0x90},
-	{WSA883X_SPKR_DRV_LF_OS_CAL_CTL,     0x00},
+	{WSA883X_SPKR_DRV_OS_CAL_CTL,        0x00},
+	{WSA883X_SPKR_DRV_OS_CAL_CTL1,       0x90},
 	{WSA883X_SPKR_PWM_CLK_CTL,           0x00},
-	{WSA883X_SPKR_PDRV_HS_CTL,           0x50},
+	{WSA883X_SPKR_PDRV_HS_CTL,           0x52},
 	{WSA883X_SPKR_PDRV_LS_CTL,           0x48},
-	{WSA883X_SPKR_PWRSTG_DBG,            0x00},
-	{WSA883X_SPKR_OCP_CTL,               0x00},
-	{WSA883X_SPKR_BBM_CTL,               0x90},
+	{WSA883X_SPKR_PWRSTG_DBG,            0x08},
+	{WSA883X_SPKR_OCP_CTL,               0xE2},
+	{WSA883X_SPKR_BBM_CTL,               0x92},
 	{WSA883X_PA_STATUS0,                 0x00},
 	{WSA883X_PA_STATUS1,                 0x00},
-	{WSA883X_PA_STATUS2,                 0x00},
-	{WSA883X_EN_CTRL,                    0x54},
-	{WSA883X_CURRENT_LIMIT,              0x90},
+	{WSA883X_PA_STATUS2,                 0x80},
+	{WSA883X_EN_CTRL,                    0x44},
+	{WSA883X_CURRENT_LIMIT,              0xCC},
 	{WSA883X_IBIAS1,                     0x00},
 	{WSA883X_IBIAS2,                     0x00},
 	{WSA883X_IBIAS3,                     0x00},
-	{WSA883X_LDO_PROG,                   0x2A},
+	{WSA883X_LDO_PROG,                   0x02},
 	{WSA883X_STABILITY_CTRL1,            0x8E},
-	{WSA883X_STABILITY_CTRL2,            0x00},
-	{WSA883X_PWRSTAGE_CTRL1,             0x00},
-	{WSA883X_PWRSTAGE_CTRL2,             0x40},
-	{WSA883X_UVLO,                       0xE9},
-	{WSA883X_SEQUENCE_CTRL,              0x11},
+	{WSA883X_STABILITY_CTRL2,            0x10},
+	{WSA883X_PWRSTAGE_CTRL1,             0x06},
+	{WSA883X_PWRSTAGE_CTRL2,             0x00},
+	{WSA883X_BYPASS_1,                   0x19},
+	{WSA883X_BYPASS_2,                   0x13},
 	{WSA883X_ZX_CTRL_1,                  0xF0},
-	{WSA883X_ZX_CTRL_2,                  0x06},
-	{WSA883X_MISC1,                      0x02},
-	{WSA883X_MISC2,                      0x81},
-	{WSA883X_GMAMP_SUP1,                 0x84},
-	{WSA883X_PWRSTAGE_CTRL3,             0x14},
-	{WSA883X_PRSTAGE_CTRL4,              0x5F},
+	{WSA883X_ZX_CTRL_2,                  0x04},
+	{WSA883X_MISC1,                      0x06},
+	{WSA883X_MISC2,                      0xA0},
+	{WSA883X_GMAMP_SUP1,                 0x82},
+	{WSA883X_PWRSTAGE_CTRL3,             0x39},
+	{WSA883X_PWRSTAGE_CTRL4,             0x5F},
+	{WSA883X_TEST1,                      0x00},
 	{WSA883X_SPARE1,                     0x00},
-	{WSA883X_PON_CTL_0,                  0xE3},
-	{WSA883X_PON_CLT_1,                  0x70},
-	{WSA883X_PON_CTL_2,                  0x00},
-	{WSA883X_PON_CTL_3,                  0x00},
-	{WSA883X_PON_CTL_4,                  0x00},
+	{WSA883X_SPARE2,                     0x00},
+	{WSA883X_PON_CTL_0,                  0x10},
+	{WSA883X_PON_CLT_1,                  0xE0},
+	{WSA883X_PON_CTL_2,                  0x90},
+	{WSA883X_PON_CTL_3,                  0x70},
 	{WSA883X_CKWD_CTL_0,                 0x34},
-	{WSA883X_CKWD_CTL_1,                 0x80},
+	{WSA883X_CKWD_CTL_1,                 0x0F},
 	{WSA883X_CKWD_CTL_2,                 0x00},
-	{WSA883X_CKSK_CTL_0,                 0x0A},
+	{WSA883X_CKSK_CTL_0,                 0x00},
+	{WSA883X_PADSW_CTL_0,                0x00},
 	{WSA883X_TEST_0,                     0x00},
 	{WSA883X_TEST_1,                     0x00},
 	{WSA883X_STATUS_0,                   0x00},
 	{WSA883X_STATUS_1,                   0x00},
-	{WSA883X_PAGE_REGISTER,              0x00},
 	{WSA883X_CHIP_ID0,                   0x00},
 	{WSA883X_CHIP_ID1,                   0x00},
 	{WSA883X_CHIP_ID2,                   0x02},
@@ -115,13 +116,15 @@
 	{WSA883X_CDC_PATH_MODE,              0x00},
 	{WSA883X_CDC_CLK_CTL,                0xFF},
 	{WSA883X_SWR_RESET_EN,               0x00},
+	{WSA883X_RESET_CTL,                  0x00},
 	{WSA883X_PA_FSM_CTL,                 0x00},
 	{WSA883X_PA_FSM_TIMER0,              0x80},
 	{WSA883X_PA_FSM_TIMER1,              0x80},
 	{WSA883X_PA_FSM_STA,                 0x00},
 	{WSA883X_PA_FSM_ERR_COND,            0x00},
 	{WSA883X_PA_FSM_MSK,                 0x00},
-	{WSA883X_PA_FSM_BYP,                 0x00},
+	{WSA883X_PA_FSM_BYP,                 0x01},
+	{WSA883X_PA_FSM_DBG,                 0x00},
 	{WSA883X_TADC_VALUE_CTL,             0x03},
 	{WSA883X_TEMP_DETECT_CTL,            0x01},
 	{WSA883X_TEMP_MSB,                   0x00},
@@ -193,15 +196,17 @@
 	{WSA883X_WAVG_PER_2_3,               0x88},
 	{WSA883X_WAVG_PER_4_5,               0x88},
 	{WSA883X_WAVG_PER_6_7,               0x88},
-	{WSA883X_DRE_CTL_0,                  0x30},
-	{WSA883X_DRE_CTL_1,                  0x20},
+	{WSA883X_WAVG_STA,                   0x00},
+	{WSA883X_DRE_CTL_0,                  0x70},
+	{WSA883X_DRE_CTL_1,                  0x08},
+	{WSA883X_DRE_IDLE_DET_CTL,           0x1F},
 	{WSA883X_CLSH_CTL_0,                 0x37},
 	{WSA883X_CLSH_CTL_1,                 0x81},
 	{WSA883X_CLSH_V_HD_PA,               0x0F},
 	{WSA883X_CLSH_V_PA_MIN,              0x00},
 	{WSA883X_CLSH_OVRD_VAL,              0x00},
 	{WSA883X_CLSH_HARD_MAX,              0xFF},
-	{WSA883X_CLSH_SOFT_MAX,              0xFF},
+	{WSA883X_CLSH_SOFT_MAX,              0xF5},
 	{WSA883X_CLSH_SIG_DP,                0x00},
 	{WSA883X_TAGC_CTL,                   0x10},
 	{WSA883X_TAGC_TIME,                  0x20},
@@ -212,18 +217,18 @@
 	{WSA883X_VAGC_ATTN_LVL_1_2,          0x21},
 	{WSA883X_VAGC_ATTN_LVL_3,            0x03},
 	{WSA883X_INTR_MODE,                  0x00},
-	{WSA883X_INTR_MASK0,                 0x1B},
-	{WSA883X_INTR_MASK1,                 0x03},
+	{WSA883X_INTR_MASK0,                 0x90},
+	{WSA883X_INTR_MASK1,                 0x00},
 	{WSA883X_INTR_STATUS0,               0x00},
 	{WSA883X_INTR_STATUS1,               0x00},
 	{WSA883X_INTR_CLEAR0,                0x00},
-	{WSA883X_INTR_CLEAR1,                0x03},
+	{WSA883X_INTR_CLEAR1,                0x00},
 	{WSA883X_INTR_LEVEL0,                0x00},
-	{WSA883X_INTR_LEVEL1,                0x03},
+	{WSA883X_INTR_LEVEL1,                0x00},
 	{WSA883X_INTR_SET0,                  0x00},
-	{WSA883X_INTR_SET1,                  0x03},
+	{WSA883X_INTR_SET1,                  0x00},
 	{WSA883X_INTR_TEST0,                 0x00},
-	{WSA883X_INTR_TEST1,                 0x03},
+	{WSA883X_INTR_TEST1,                 0x00},
 	{WSA883X_OTP_CTRL0,                  0x00},
 	{WSA883X_OTP_CTRL1,                  0x00},
 	{WSA883X_HDRIVE_CTL_GROUP1,          0x00},
@@ -234,25 +239,27 @@
 	{WSA883X_I2C_SLAVE_CTL,              0x00},
 	{WSA883X_PDM_TEST_MODE,              0x00},
 	{WSA883X_ATE_TEST_MODE,              0x00},
-	{WSA883X_DRE_TEST,                   0x00},
 	{WSA883X_DIG_DEBUG_MODE,             0x00},
 	{WSA883X_DIG_DEBUG_SEL,              0x00},
 	{WSA883X_DIG_DEBUG_EN,               0x00},
 	{WSA883X_SWR_HM_TEST0,               0x08},
 	{WSA883X_SWR_HM_TEST1,               0x00},
-	{WSA883X_SWR_PAD_CTL,                0x45},
-	{WSA883X_TEMP_DETECT_DBG_CTL,        0x00},
-	{WSA883X_TEMP_DEBUG_MSB,             0x00},
-	{WSA883X_TEMP_DEBUG_LSB,             0x00},
+	{WSA883X_SWR_PAD_CTL,                0x37},
+	{WSA883X_TADC_DETECT_DBG_CTL,        0x00},
+	{WSA883X_TADC_DEBUG_MSB,             0x00},
+	{WSA883X_TADC_DEBUG_LSB,             0x00},
 	{WSA883X_SAMPLE_EDGE_SEL,            0x7F},
-	{WSA883X_TEST_MODE_CTL,              0x00},
+	{WSA883X_SWR_EDGE_SEL,               0x00},
+	{WSA883X_TEST_MODE_CTL,              0x04},
 	{WSA883X_IOPAD_CTL,                  0x00},
+	{WSA883X_ANA_CSR_DBG_ADD,            0x00},
+	{WSA883X_ANA_CSR_DBG_CTL,            0x12},
+	{WSA883X_SPARE_R,                    0x00},
 	{WSA883X_SPARE_0,                    0x00},
 	{WSA883X_SPARE_1,                    0x00},
 	{WSA883X_SPARE_2,                    0x00},
 	{WSA883X_SCODE,                      0x00},
-	{WSA883X_PAGE_REGISTER,              0x00},
-	{WSA883X_OTP_REG_0,                  0x01},
+	{WSA883X_OTP_REG_0,                  0x05},
 	{WSA883X_OTP_REG_1,                  0xFF},
 	{WSA883X_OTP_REG_2,                  0xC0},
 	{WSA883X_OTP_REG_3,                  0xFF},
@@ -276,15 +283,18 @@
 	{WSA883X_OTP_REG_21,                 0xFF},
 	{WSA883X_OTP_REG_22,                 0xFF},
 	{WSA883X_OTP_REG_23,                 0xFF},
-	{WSA883X_OTP_REG_24,                 0x03},
-	{WSA883X_OTP_REG_25,                 0x01},
+	{WSA883X_OTP_REG_24,                 0x37},
+	{WSA883X_OTP_REG_25,                 0x3F},
 	{WSA883X_OTP_REG_26,                 0x03},
-	{WSA883X_OTP_REG_27,                 0x11},
-	{WSA883X_OTP_REG_28,                 0x3F},
-	{WSA883X_OTP_REG_29,                 0x3F},
-	{WSA883X_OTP_REG_30,                 0x01},
-	{WSA883X_OTP_REG_31,                 0x01},
-	{WSA883X_OTP_REG_SCODE,              0x00},
+	{WSA883X_OTP_REG_27,                 0x00},
+	{WSA883X_OTP_REG_28,                 0x00},
+	{WSA883X_OTP_REG_29,                 0x00},
+	{WSA883X_OTP_REG_30,                 0x00},
+	{WSA883X_OTP_REG_31,                 0x03},
+	{WSA883X_OTP_REG_32,                 0x00},
+	{WSA883X_OTP_REG_33,                 0xFF},
+	{WSA883X_OTP_REG_34,                 0x00},
+	{WSA883X_OTP_REG_35,                 0x00},
 	{WSA883X_OTP_REG_63,                 0x40},
 	{WSA883X_EMEM_0,                     0x00},
 	{WSA883X_EMEM_1,                     0x00},
@@ -377,7 +387,7 @@
 		!(wsa883x_reg_access[WSA883X_REG(reg)] & WR_REG));
 }
 
-struct regmap_config wsa881x_regmap_config = {
+struct regmap_config wsa883x_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
 	.cache_type = REGCACHE_RBTREE,
diff --git a/asoc/codecs/wsa883x/wsa883x-tables.c b/asoc/codecs/wsa883x/wsa883x-tables.c
index 16b0a88..c693097 100644
--- a/asoc/codecs/wsa883x/wsa883x-tables.c
+++ b/asoc/codecs/wsa883x/wsa883x-tables.c
@@ -1,13 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
  */
 
 #include <linux/regmap.h>
 #include <linux/device.h>
 #include "wsa883x-registers.h"
 
-const u8 wsa883x_reg_readable[WSA883X_NUM_REGISTERS] = {
+const u8 wsa883x_reg_access[WSA883X_NUM_REGISTERS] = {
 	[WSA883X_REG(WSA883X_REF_CTRL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_TEST_CTL_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_BIAS_0)] = RD_WR_REG,
@@ -57,14 +57,14 @@
 	[WSA883X_REG(WSA883X_SPKR_DRV_LF_MASK_DCC_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPKR_DRV_LF_MISC_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPKR_DRV_LF_REG_GAIN)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_SPKR_DRV_LF_OS_CAL_CTL1)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_SPKR_DRV_LF_OS_CAL_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_DRV_OS_CAL_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_DRV_OS_CAL_CTL1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPKR_PWM_CLK_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPKR_PDRV_HS_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPKR_PDRV_LS_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPKR_PWRSTG_DBG)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPKR_OCP_CTL)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_SPKR_BBM_CTL)] = RD_REG,
+	[WSA883X_REG(WSA883X_SPKR_BBM_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PA_STATUS0)] = RD_REG,
 	[WSA883X_REG(WSA883X_PA_STATUS1)] = RD_REG,
 	[WSA883X_REG(WSA883X_PA_STATUS2)] = RD_REG,
@@ -78,30 +78,31 @@
 	[WSA883X_REG(WSA883X_STABILITY_CTRL2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PWRSTAGE_CTRL1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PWRSTAGE_CTRL2)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_UVLO)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_SEQUENCE_CTRL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_BYPASS_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_BYPASS_2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_ZX_CTRL_1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_ZX_CTRL_2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_MISC1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_MISC2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_GMAMP_SUP1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PWRSTAGE_CTRL3)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_PRSTAGE_CTRL4)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PWRSTAGE_CTRL4)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TEST1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPARE1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPARE2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PON_CTL_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PON_CLT_1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PON_CTL_2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PON_CTL_3)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_PON_CTL_4)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CKWD_CTL_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CKWD_CTL_1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CKWD_CTL_2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CKSK_CTL_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PADSW_CTL_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_TEST_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_TEST_1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_STATUS_0)] = RD_REG,
 	[WSA883X_REG(WSA883X_STATUS_1)] = RD_REG,
-	[WSA883X_REG(WSA883X_PAGE_REGISTER)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CHIP_ID0)] = RD_REG,
 	[WSA883X_REG(WSA883X_CHIP_ID1)] = RD_REG,
 	[WSA883X_REG(WSA883X_CHIP_ID2)] = RD_REG,
@@ -112,6 +113,7 @@
 	[WSA883X_REG(WSA883X_CDC_PATH_MODE)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CDC_CLK_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SWR_RESET_EN)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_RESET_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PA_FSM_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PA_FSM_TIMER0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PA_FSM_TIMER1)] = RD_WR_REG,
@@ -119,6 +121,7 @@
 	[WSA883X_REG(WSA883X_PA_FSM_ERR_COND)] = RD_REG,
 	[WSA883X_REG(WSA883X_PA_FSM_MSK)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PA_FSM_BYP)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PA_FSM_DBG)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_TADC_VALUE_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_TEMP_DETECT_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_TEMP_MSB)] = RD_REG,
@@ -190,8 +193,10 @@
 	[WSA883X_REG(WSA883X_WAVG_PER_2_3)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_WAVG_PER_4_5)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_WAVG_PER_6_7)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_STA)] = RD_REG,
 	[WSA883X_REG(WSA883X_DRE_CTL_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_DRE_CTL_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DRE_IDLE_DET_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CLSH_CTL_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CLSH_CTL_1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_CLSH_V_HD_PA)] = RD_WR_REG,
@@ -231,24 +236,26 @@
 	[WSA883X_REG(WSA883X_I2C_SLAVE_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_PDM_TEST_MODE)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_ATE_TEST_MODE)] = RD_REG,
-	[WSA883X_REG(WSA883X_DRE_TEST)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_DIG_DEBUG_MODE)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_DIG_DEBUG_SEL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_DIG_DEBUG_EN)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SWR_HM_TEST0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SWR_HM_TEST1)] = RD_REG,
 	[WSA883X_REG(WSA883X_SWR_PAD_CTL)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_TEMP_DETECT_DBG_CTL)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_TEMP_DEBUG_MSB)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_TEMP_DEBUG_LSB)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TADC_DETECT_DBG_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TADC_DEBUG_MSB)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TADC_DEBUG_LSB)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SAMPLE_EDGE_SEL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SWR_EDGE_SEL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_TEST_MODE_CTL)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_IOPAD_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ANA_CSR_DBG_ADD)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ANA_CSR_DBG_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPARE_R)] = RD_REG,
 	[WSA883X_REG(WSA883X_SPARE_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPARE_1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SPARE_2)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_SCODE)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_PAGE_REGISTER)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_OTP_REG_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_OTP_REG_1)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_OTP_REG_2)] = RD_WR_REG,
@@ -280,8 +287,11 @@
 	[WSA883X_REG(WSA883X_OTP_REG_28)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_OTP_REG_29)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_OTP_REG_30)] = RD_WR_REG,
-	[WSA883X_REG(WSA883X_OTP_REG_31)] = RD_REG,
-	[WSA883X_REG(WSA883X_OTP_REG_SCODE)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_31)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_32)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_33)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_34)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_35)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_OTP_REG_63)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_EMEM_0)] = RD_WR_REG,
 	[WSA883X_REG(WSA883X_EMEM_1)] = RD_WR_REG,
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c
index 08f6858..9e25e53 100644
--- a/asoc/codecs/wsa883x/wsa883x.c
+++ b/asoc/codecs/wsa883x/wsa883x.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/of_platform.h>
 #include <linux/regmap.h>
 #include <linux/debugfs.h>
 #include <soc/soundwire.h>
@@ -25,6 +26,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
 #include <asoc/msm-cdc-pinctrl.h>
+#include <asoc/msm-cdc-supply.h>
 #include "wsa883x.h"
 #include "internal.h"
 
@@ -34,6 +36,13 @@
 #define HIGH_TEMP_THRESHOLD 45
 #define TEMP_INVALID	0xFFFF
 #define WSA883X_TEMP_RETRY 3
+#define WSA883X_VBAT_TIMER_SEC    2
+
+static int wsa883x_vbat_timer_sec = WSA883X_VBAT_TIMER_SEC;
+module_param(wsa883x_vbat_timer_sec, int, 0664);
+MODULE_PARM_DESC(wsa883x_vbat_timer_sec, "timer for VBAT monitor polling");
+
+#define DRV_NAME "wsa-codec"
 
 enum {
 	WSA_4OHMS =4,
@@ -51,6 +60,56 @@
 	u8 dmeas_lsb;
 };
 
+struct wsa_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+static const struct wsa_reg_mask_val reg_init[] = {
+	{WSA883X_PA_FSM_BYP, 0x01, 0x00},
+	{WSA883X_CDC_SPK_DSM_A2_0, 0xFF, 0x0A},
+	{WSA883X_CDC_SPK_DSM_A2_1, 0x0F, 0x08},
+	{WSA883X_CDC_SPK_DSM_A3_0, 0xFF, 0xF3},
+	{WSA883X_CDC_SPK_DSM_A3_1, 0x07, 0x07},
+	{WSA883X_CDC_SPK_DSM_A4_0, 0xFF, 0x79},
+	{WSA883X_CDC_SPK_DSM_A4_1, 0x03, 0x02},
+	{WSA883X_CDC_SPK_DSM_A5_0, 0xFF, 0x0B},
+	{WSA883X_CDC_SPK_DSM_A5_1, 0x03, 0x02},
+	{WSA883X_CDC_SPK_DSM_A6_0, 0xFF, 0x8A},
+	{WSA883X_CDC_SPK_DSM_A7_0, 0xFF, 0x9B},
+	{WSA883X_CDC_SPK_DSM_C_0, 0xFF, 0x68},
+	{WSA883X_CDC_SPK_DSM_C_1, 0xFF, 0x54},
+	{WSA883X_CDC_SPK_DSM_C_2, 0xFF, 0xF2},
+	{WSA883X_CDC_SPK_DSM_C_3, 0x3F, 0x20},
+	{WSA883X_CDC_SPK_DSM_R1, 0xFF, 0x83},
+	{WSA883X_CDC_SPK_DSM_R2, 0xFF, 0x7F},
+	{WSA883X_CDC_SPK_DSM_R3, 0xFF, 0x9D},
+	{WSA883X_CDC_SPK_DSM_R4, 0xFF, 0x82},
+	{WSA883X_CDC_SPK_DSM_R5, 0xFF, 0x8B},
+	{WSA883X_CDC_SPK_DSM_R6, 0xFF, 0x9B},
+	{WSA883X_CDC_SPK_DSM_R7, 0xFF, 0x3F},
+	{WSA883X_DRE_CTL_0, 0xF0, 0x90},
+	{WSA883X_DRE_IDLE_DET_CTL, 0x10, 0x00},
+	{WSA883X_PDM_WD_CTL, 0x01, 0x01},
+	{WSA883X_CURRENT_LIMIT, 0x78, 0x40},
+	{WSA883X_DRE_CTL_0, 0x07, 0x02},
+	{WSA883X_VAGC_TIME, 0x03, 0x02},
+	{WSA883X_VAGC_CTL, 0x01, 0x01},
+	{WSA883X_TAGC_CTL, 0x0E, 0x0A},
+	{WSA883X_TAGC_TIME, 0x0C, 0x0C},
+	{WSA883X_TAGC_E2E_GAIN, 0x1F, 0x02},
+	{WSA883X_TEMP_CONFIG0, 0x07, 0x02},
+	{WSA883X_TEMP_CONFIG1, 0x07, 0x02},
+	{WSA883X_OTP_REG_1, 0xFF, 0x49},
+	{WSA883X_OTP_REG_2, 0xC0, 0x80},
+	{WSA883X_OTP_REG_3, 0xFF, 0xC9},
+	{WSA883X_OTP_REG_4, 0xC0, 0x40},
+	{WSA883X_TAGC_CTL, 0x01, 0x01},
+	{WSA883X_CKWD_CTL_0, 0x60, 0x00},
+	{WSA883X_CKWD_CTL_1, 0x1F, 0x1B},
+};
+
 static int wsa883x_get_temperature(struct snd_soc_component *component,
 				   int *temp);
 enum {
@@ -59,6 +118,10 @@
 };
 
 enum {
+	SPKR_STATUS = 0,
+};
+
+enum {
 	WSA883X_IRQ_INT_SAF2WAR = 0,
 	WSA883X_IRQ_INT_WAR2SAF,
 	WSA883X_IRQ_INT_DISABLE,
@@ -69,6 +132,7 @@
 	WSA883X_IRQ_INT_INTR_PIN,
 	WSA883X_IRQ_INT_UVLO,
 	WSA883X_IRQ_INT_PA_ON_ERR,
+	WSA883X_NUM_IRQS,
 };
 
 static const struct regmap_irq wsa883x_irqs[WSA883X_NUM_IRQS] = {
@@ -174,8 +238,13 @@
 		if (!is_swr_slave_reg_readable(i))
 			continue;
 		swr_read(pdev, pdev->dev_num, i, &reg_val, 1);
-		len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i,
+		len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i,
 			       (reg_val & 0xFF));
+		if (len < 0) {
+			pr_err("%s: fail to fill the buffer\n", __func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
 		if ((total + len) >= count - 1)
 			break;
 		if (copy_to_user((ubuf + total), tmp_buf, len)) {
@@ -334,6 +403,14 @@
 };
 #endif
 
+static void wsa883x_regcache_sync(struct wsa883x_priv *wsa883x)
+{
+	mutex_lock(&wsa883x->res_lock);
+	regcache_mark_dirty(wsa883x->regmap);
+	regcache_sync(wsa883x->regmap);
+	mutex_unlock(&wsa883x->res_lock);
+}
+
 static irqreturn_t wsa883x_saf2war_handle_irq(int irq, void *data)
 {
 	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
@@ -535,7 +612,17 @@
 		return -EINVAL;
 	}
 
-	len = snprintf(buffer, sizeof(buffer), "WSA883X-SOUNDWIRE_1_0\n");
+	switch (wsa883x->version) {
+	case WSA883X_VERSION_1_0:
+		len = snprintf(buffer, sizeof(buffer), "WSA883X_1_0\n");
+		break;
+	case WSA883X_VERSION_1_1:
+		len = snprintf(buffer, sizeof(buffer), "WSA883X_1_1\n");
+		break;
+	default:
+		len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
+		break;
+	}
 
 	return simple_read_from_buffer(buf, count, &pos, buffer, len);
 }
@@ -544,6 +631,41 @@
 	.read = wsa883x_codec_version_read,
 };
 
+static ssize_t wsa883x_variant_read(struct snd_info_entry *entry,
+				    void *file_private_data,
+				    struct file *file,
+				    char __user *buf, size_t count,
+				    loff_t pos)
+{
+	struct wsa883x_priv *wsa883x;
+	char buffer[WSA883X_VARIANT_ENTRY_SIZE];
+	int len = 0;
+
+	wsa883x = (struct wsa883x_priv *) entry->private_data;
+	if (!wsa883x) {
+		pr_err("%s: wsa883x priv is null\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (wsa883x->variant) {
+	case WSA8830:
+		len = snprintf(buffer, sizeof(buffer), "WSA8830\n");
+		break;
+	case WSA8835:
+		len = snprintf(buffer, sizeof(buffer), "WSA8835\n");
+		break;
+	default:
+		len = snprintf(buffer, sizeof(buffer), "UNDEFINED\n");
+		break;
+	}
+
+	return simple_read_from_buffer(buf, count, &pos, buffer, len);
+}
+
+static struct snd_info_entry_ops wsa883x_variant_ops = {
+	.read = wsa883x_variant_read,
+};
+
 /*
  * wsa883x_codec_info_create_codec_entry - creates wsa883x module
  * @codec_root: The parent directory
@@ -558,6 +680,7 @@
 					  struct snd_soc_component *component)
 {
 	struct snd_info_entry *version_entry;
+	struct snd_info_entry *variant_entry;
 	struct wsa883x_priv *wsa883x;
 	struct snd_soc_card *card;
 	char name[80];
@@ -566,11 +689,17 @@
 		return -EINVAL;
 
 	wsa883x = snd_soc_component_get_drvdata(component);
+	if (wsa883x->entry) {
+		dev_dbg(wsa883x->dev,
+			"%s:wsa883x module already created\n", __func__);
+		return 0;
+	}
 	card = component->card;
-	snprintf(name, sizeof(name), "%s.%x", "wsa883x",
-		 (u32)wsa883x->swr_slave->addr);
 
-	wsa883x->entry = snd_info_create_subdir(codec_root->module,
+	snprintf(name, sizeof(name), "%s.%llx", "wsa883x",
+		 wsa883x->swr_slave->addr);
+
+	wsa883x->entry = snd_info_create_module_entry(codec_root->module,
 						(const char *)name,
 						codec_root);
 	if (!wsa883x->entry) {
@@ -579,12 +708,19 @@
 		return -ENOMEM;
 	}
 
+	wsa883x->entry->mode = S_IFDIR | 0555;
+	if (snd_info_register(wsa883x->entry) < 0) {
+		snd_info_free_entry(wsa883x->entry);
+		return -ENOMEM;
+	}
+
 	version_entry = snd_info_create_card_entry(card->snd_card,
 						   "version",
 						   wsa883x->entry);
 	if (!version_entry) {
 		dev_dbg(component->dev, "%s: failed to create wsa883x version entry\n",
 			__func__);
+		snd_info_free_entry(wsa883x->entry);
 		return -ENOMEM;
 	}
 
@@ -595,22 +731,40 @@
 
 	if (snd_info_register(version_entry) < 0) {
 		snd_info_free_entry(version_entry);
+		snd_info_free_entry(wsa883x->entry);
 		return -ENOMEM;
 	}
 	wsa883x->version_entry = version_entry;
 
+	variant_entry = snd_info_create_card_entry(card->snd_card,
+						   "variant",
+						   wsa883x->entry);
+	if (!variant_entry) {
+		dev_dbg(component->dev,
+			"%s: failed to create wsa883x variant entry\n",
+			__func__);
+		snd_info_free_entry(version_entry);
+		snd_info_free_entry(wsa883x->entry);
+		return -ENOMEM;
+	}
+
+	variant_entry->private_data = wsa883x;
+	variant_entry->size = WSA883X_VARIANT_ENTRY_SIZE;
+	variant_entry->content = SNDRV_INFO_CONTENT_DATA;
+	variant_entry->c.ops = &wsa883x_variant_ops;
+
+	if (snd_info_register(variant_entry) < 0) {
+		snd_info_free_entry(variant_entry);
+		snd_info_free_entry(version_entry);
+		snd_info_free_entry(wsa883x->entry);
+		return -ENOMEM;
+	}
+	wsa883x->variant_entry = variant_entry;
+
 	return 0;
 }
 EXPORT_SYMBOL(wsa883x_codec_info_create_codec_entry);
 
-static void wsa883x_regcache_sync(struct wsa883x_priv *wsa883x)
-{
-	mutex_lock(&wsa883x->res_lock);
-	regcache_mark_dirty(wsa883x->regmap);
-	regcache_sync(wsa883x->regmap);
-	mutex_unlock(&wsa883x->res_lock);
-}
-
 static int wsa883x_get_compander(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
@@ -774,16 +928,8 @@
 					&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,
 				&port_id[num_port], &num_ch[num_port],
 				&ch_mask[num_port], &ch_rate[num_port],
@@ -807,6 +953,15 @@
 		swr_disconnect_port(wsa883x->swr_slave, &port_id[0], num_port,
 				&ch_mask[0], &port_type[0]);
 		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (swr_set_device_group(wsa883x->swr_slave, SWR_GROUP_NONE))
+			dev_err(component->dev,
+				"%s: set num ch failed\n", __func__);
+
+		swr_slvdev_datapath_control(wsa883x->swr_slave,
+					    wsa883x->swr_slave->dev_num,
+					    false);
+		break;
 	default:
 		break;
 	}
@@ -819,21 +974,39 @@
 	struct snd_soc_component *component =
 			snd_soc_dapm_to_component(w->dapm);
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
-	int min_gain, max_gain;
 
 	dev_dbg(component->dev, "%s: %s %d\n", __func__, w->name, event);
 	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		/* TODO Vote for Global PA */
-		break;
-
 	case SND_SOC_DAPM_POST_PMU:
+		swr_slvdev_datapath_control(wsa883x->swr_slave,
+					    wsa883x->swr_slave->dev_num,
+					    true);
+		wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
 		/* Force remove group */
 		swr_remove_from_group(wsa883x->swr_slave,
 				      wsa883x->swr_slave->dev_num);
+		snd_soc_component_update_bits(component,
+				WSA883X_VBAT_ADC_FLT_CTL,
+				0x0E, 0x06);
+		snd_soc_component_update_bits(component,
+				WSA883X_VBAT_ADC_FLT_CTL,
+				0x01, 0x01);
+		schedule_delayed_work(&wsa883x->vbat_work,
+			msecs_to_jiffies(wsa883x_vbat_timer_sec * 1000));
+		set_bit(SPKR_STATUS, &wsa883x->status_mask);
 		break;
-	case SND_SOC_DAPM_POST_PMD:
-		/* TODO Unvote for Global PA */
+	case SND_SOC_DAPM_PRE_PMD:
+		cancel_delayed_work_sync(&wsa883x->vbat_work);
+		snd_soc_component_update_bits(component,
+				WSA883X_VBAT_ADC_FLT_CTL,
+				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				WSA883X_VBAT_ADC_FLT_CTL,
+				0x0E, 0x00);
+		snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
+				0x01, 0x00);
+		wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
+		clear_bit(SPKR_STATUS, &wsa883x->status_mask);
 		break;
 	}
 	return 0;
@@ -884,10 +1057,14 @@
 static void wsa883x_codec_init(struct snd_soc_component *component)
 {
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	int i;
 
 	if (!wsa883x)
 		return;
 
+	for (i = 0; i < ARRAY_SIZE(reg_init); i++)
+		snd_soc_component_update_bits(component, reg_init[i].reg,
+					reg_init[i].mask, reg_init[i].val);
 }
 
 static int32_t wsa883x_temp_reg_read(struct snd_soc_component *component,
@@ -929,7 +1106,6 @@
 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;
@@ -943,7 +1119,7 @@
 		return -EINVAL;
 
 	do {
-		ret = wsa883x_temp_reg_read(component, &reg)
+		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);
@@ -996,10 +1172,42 @@
 	return ret;
 }
 
+static void wsa883x_vbat_monitor_work(struct work_struct *work)
+{
+	struct wsa883x_priv *wsa883x;
+	struct delayed_work *dwork;
+	struct snd_soc_component *component;
+	u16 val = 0, vbat_code = 0;
+	int vbat_val = 0;
+
+	dwork = to_delayed_work(work);
+	wsa883x = container_of(dwork, struct wsa883x_priv, vbat_work);
+	component = wsa883x->component;
+
+	val = snd_soc_component_read32(component, WSA883X_VBAT_DIN_MSB);
+	vbat_code = (val << 2);
+	val = (snd_soc_component_read32(component, WSA883X_VBAT_DIN_LSB)
+		& 0xC0);
+	vbat_code |= (val >> 6);
+	vbat_val = ((vbat_code * 5) / 1023);
+	dev_dbg(component->dev, "%s: instant vbat code = %d val = %d\n",
+		__func__, vbat_code, vbat_val);
+
+	val = snd_soc_component_read32(component, WSA883X_VBAT_DOUT);
+	vbat_val = ((val * 5) / 255);
+
+	dev_dbg(component->dev, "%s: low pass vbat code = %d val = %d\n",
+		__func__, val, vbat_val);
+
+	schedule_delayed_work(&wsa883x->vbat_work,
+			msecs_to_jiffies(wsa883x_vbat_timer_sec * 1000));
+}
+
 static int wsa883x_codec_probe(struct snd_soc_component *component)
 {
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
 	struct swr_device *dev;
+	int variant = 0, version = 0;
 
 	if (!wsa883x)
 		return -EINVAL;
@@ -1007,8 +1215,18 @@
 
 	dev = wsa883x->swr_slave;
 	wsa883x->component = component;
+
+	variant = (snd_soc_component_read32(component, WSA883X_OTP_REG_0)
+					    & 0x0F);
+	wsa883x->variant = variant;
+
+	version = (snd_soc_component_read32(component, WSA883X_CHIP_ID0)
+					    & 0xFF);
+	wsa883x->version = version;
+
 	wsa883x_codec_init(component);
 	wsa883x->global_pa_cnt = 0;
+	INIT_DELAYED_WORK(&wsa883x->vbat_work, wsa883x_vbat_monitor_work);
 
 	return 0;
 }
@@ -1055,6 +1273,45 @@
 	return ret;
 }
 
+static int wsa883x_swr_up(struct wsa883x_priv *wsa883x)
+{
+	int ret;
+
+	ret = wsa883x_gpio_ctrl(wsa883x, true);
+	if (ret)
+		dev_err(wsa883x->dev, "%s: Failed to enable gpio\n", __func__);
+
+	return ret;
+}
+
+static int wsa883x_swr_down(struct wsa883x_priv *wsa883x)
+{
+	int ret;
+
+	ret = wsa883x_gpio_ctrl(wsa883x, false);
+	if (ret)
+		dev_err(wsa883x->dev, "%s: Failed to disable gpio\n", __func__);
+
+	return ret;
+}
+
+static int wsa883x_swr_reset(struct wsa883x_priv *wsa883x)
+{
+	u8 retry = WSA883X_NUM_RETRY;
+	u8 devnum = 0;
+	struct swr_device *pdev;
+
+	pdev = wsa883x->swr_slave;
+	while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
+		/* Retry after 1 msec delay */
+		usleep_range(1000, 1100);
+	}
+	pdev->dev_num = devnum;
+	wsa883x_regcache_sync(wsa883x);
+
+	return 0;
+}
+
 static int wsa883x_event_notify(struct notifier_block *nb,
 				unsigned long val, void *ptr)
 {
@@ -1067,23 +1324,70 @@
 
 	switch (event) {
 	case BOLERO_WSA_EVT_PA_OFF_PRE_SSR:
+		if (delayed_work_pending(&wsa883x->vbat_work))
+			cancel_delayed_work_sync(&wsa883x->vbat_work);
 		snd_soc_component_update_bits(wsa883x->component,
-					      WSA883X_SPKR_DRV_GAIN,
-					      0xF0, 0xC0);
-		snd_soc_component_update_bits(wsa883x->component,
-					      WSA883X_SPKR_DRV_EN,
-					      0x80, 0x00);
+					WSA883X_PA_FSM_CTL,
+					0x01, 0x00);
+		wsa883x_swr_down(wsa883x);
+		break;
+
+	case BOLERO_WSA_EVT_SSR_UP:
+		wsa883x_swr_up(wsa883x);
+		/* Add delay to allow enumerate */
+		usleep_range(20000, 20010);
+		wsa883x_swr_reset(wsa883x);
+		break;
+
+	case BOLERO_WSA_EVT_PA_ON_POST_FSCLK:
+		if (test_bit(SPKR_STATUS, &wsa883x->status_mask))
+			snd_soc_component_update_bits(wsa883x->component,
+						WSA883X_PA_FSM_CTL,
+						0x01, 0x01);
 		break;
 	default:
+		dev_dbg(wsa883x->dev, "%s: unknown event %d\n",
+			__func__, event);
 		break;
 	}
 
 	return 0;
 }
 
-static int wsa883x_swr_probe(struct swr_device *pdev)
+static int wsa883x_enable_supplies(struct device * dev,
+				   struct wsa883x_priv *priv)
 {
 	int ret = 0;
+
+	/* Parse power supplies */
+	msm_cdc_get_power_supplies(dev, &priv->regulator,
+				   &priv->num_supplies);
+	if (!priv->regulator || (priv->num_supplies <= 0)) {
+		dev_err(dev, "%s: no power supplies defined\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = msm_cdc_init_supplies(dev, &priv->supplies,
+				    priv->regulator, priv->num_supplies);
+	if (!priv->supplies) {
+		dev_err(dev, "%s: Cannot init wsa supplies\n",
+			__func__);
+		return ret;
+	}
+
+	ret = msm_cdc_enable_static_supplies(dev, priv->supplies,
+					     priv->regulator,
+					     priv->num_supplies);
+	if (ret)
+		dev_err(dev, "%s: wsa static supply enable failed!\n",
+			__func__);
+
+	return ret;
+}
+
+static int wsa883x_swr_probe(struct swr_device *pdev)
+{
+	int ret = 0, i = 0;
 	struct wsa883x_priv *wsa883x;
 	u8 devnum = 0;
 	bool pin_state_current = false;
@@ -1094,6 +1398,10 @@
 	if (!wsa883x)
 		return -ENOMEM;
 
+	ret = wsa883x_enable_supplies(&pdev->dev, wsa883x);
+	if (ret)
+		return -EINVAL;
+
 	wsa883x->wsa_rst_np = of_parse_phandle(pdev->dev.of_node,
 					     "qcom,spkr-sd-n-node", 0);
 	if (!wsa883x->wsa_rst_np) {
@@ -1109,10 +1417,10 @@
 	 * soundwire auto enumeration of slave devices as
 	 * as per HW requirement.
 	 */
-	usleep_range(5000, 5010);
+	usleep_range(20000, 20010);
 	ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
 	if (ret) {
-		dev_dbg(&pdev->dev,
+		dev_err(&pdev->dev,
 			"%s get devnum %d for dev addr %lx failed\n",
 			__func__, devnum, pdev->addr);
 		goto dev_err;
@@ -1136,7 +1444,7 @@
 	wsa883x->irq_info.wcd_regmap_irq_chip = &wsa883x_regmap_irq_chip;
 	wsa883x->irq_info.codec_name = "WSA883X";
 	wsa883x->irq_info.regmap = wsa883x->regmap;
-	wsa883x->irq_info.dev = dev;
+	wsa883x->irq_info.dev = &pdev->dev;
 	ret = wcd_irq_init(&wsa883x->irq_info, &wsa883x->virq);
 
 	if (ret) {
@@ -1157,15 +1465,23 @@
 	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP,
 			"WSA OCP", wsa883x_ocp_handle_irq, NULL);
 
+	wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP);
+
 	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLIP,
 			"WSA CLIP", wsa883x_clip_handle_irq, NULL);
 
+	wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLIP);
+
 	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD,
 			"WSA PDM WD", wsa883x_pdm_wd_handle_irq, NULL);
 
+	wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
+
 	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLK_WD,
 			"WSA CLK WD", wsa883x_clk_wd_handle_irq, NULL);
 
+	wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLK_WD);
+
 	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN,
 			"WSA EXT INT", wsa883x_ext_int_handle_irq, NULL);
 
@@ -1176,6 +1492,8 @@
 	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR,
 			"WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL);
 
+	wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR);
+
 	ret = snd_soc_register_component(&pdev->dev, &soc_codec_dev_wsa883x,
 				     NULL, 0);
 	if (ret) {
diff --git a/asoc/kona.c b/asoc/kona.c
index a97590f..7560fa9 100644
--- a/asoc/kona.c
+++ b/asoc/kona.c
@@ -31,6 +31,7 @@
 #include "asoc/wcd-mbhc-v2.h"
 #include "codecs/wcd938x/wcd938x-mbhc.h"
 #include "codecs/wsa881x.h"
+#include "codecs/wsa883x/wsa883x.h"
 #include "codecs/wcd938x/wcd938x.h"
 #include "codecs/bolero/bolero-cdc.h"
 #include <dt-bindings/sound/audio-codec-port-types.h>
@@ -3691,6 +3692,46 @@
 	SOC_ENUM_EXT("USB_AUDIO_TX SampleRate", usb_tx_sample_rate,
 			usb_audio_tx_sample_rate_get,
 			usb_audio_tx_sample_rate_put),
+	SOC_ENUM_EXT("USB_AUDIO_RX Format", usb_rx_format,
+			usb_audio_rx_format_get, usb_audio_rx_format_put),
+	SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format,
+			usb_audio_tx_format_get, usb_audio_tx_format_put),
+	SOC_ENUM_EXT("USB_AUDIO_RX Channels", usb_rx_chs,
+			usb_audio_rx_ch_get, usb_audio_rx_ch_put),
+	SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs,
+			usb_audio_tx_ch_get, usb_audio_tx_ch_put),
+	SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
+			proxy_rx_ch_get, proxy_rx_ch_put),
+	SOC_ENUM_EXT("Display Port RX Channels", ext_disp_rx_chs,
+			ext_disp_rx_ch_get, ext_disp_rx_ch_put),
+	SOC_ENUM_EXT("Display Port RX Bit Format", ext_disp_rx_format,
+			ext_disp_rx_format_get, ext_disp_rx_format_put),
+	SOC_ENUM_EXT("Display Port RX SampleRate", ext_disp_rx_sample_rate,
+			ext_disp_rx_sample_rate_get,
+			ext_disp_rx_sample_rate_put),
+	SOC_ENUM_EXT("Display Port1 RX Channels", ext_disp_rx_chs,
+			ext_disp_rx_ch_get, ext_disp_rx_ch_put),
+	SOC_ENUM_EXT("Display Port1 RX Bit Format", ext_disp_rx_format,
+			ext_disp_rx_format_get, ext_disp_rx_format_put),
+	SOC_ENUM_EXT("Display Port1 RX SampleRate", ext_disp_rx_sample_rate,
+			ext_disp_rx_sample_rate_get,
+			ext_disp_rx_sample_rate_put),
+	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
+			msm_bt_sample_rate_get,
+			msm_bt_sample_rate_put),
+	SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
+			msm_bt_sample_rate_rx_get,
+			msm_bt_sample_rate_rx_put),
+	SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
+			msm_bt_sample_rate_tx_get,
+			msm_bt_sample_rate_tx_put),
+	SOC_ENUM_EXT("AFE_LOOPBACK_TX Channels", afe_loopback_tx_chs,
+			afe_loopback_tx_ch_get, afe_loopback_tx_ch_put),
+	SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
+			msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
+};
+
+static const struct snd_kcontrol_new msm_tdm_snd_controls[] = {
 	SOC_ENUM_EXT("PRI_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
 			tdm_rx_sample_rate_get,
 			tdm_rx_sample_rate_put),
@@ -3727,82 +3768,6 @@
 	SOC_ENUM_EXT("SEN_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
 			tdm_tx_sample_rate_get,
 			tdm_tx_sample_rate_put),
-	SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
-			aux_pcm_rx_sample_rate_get,
-			aux_pcm_rx_sample_rate_put),
-	SOC_ENUM_EXT("SEC_AUX_PCM_RX SampleRate", sec_aux_pcm_rx_sample_rate,
-			aux_pcm_rx_sample_rate_get,
-			aux_pcm_rx_sample_rate_put),
-	SOC_ENUM_EXT("TERT_AUX_PCM_RX SampleRate", tert_aux_pcm_rx_sample_rate,
-			aux_pcm_rx_sample_rate_get,
-			aux_pcm_rx_sample_rate_put),
-	SOC_ENUM_EXT("QUAT_AUX_PCM_RX SampleRate", quat_aux_pcm_rx_sample_rate,
-			aux_pcm_rx_sample_rate_get,
-			aux_pcm_rx_sample_rate_put),
-	SOC_ENUM_EXT("QUIN_AUX_PCM_RX SampleRate", quin_aux_pcm_rx_sample_rate,
-			aux_pcm_rx_sample_rate_get,
-			aux_pcm_rx_sample_rate_put),
-	SOC_ENUM_EXT("SEN_AUX_PCM_RX SampleRate", sen_aux_pcm_rx_sample_rate,
-			aux_pcm_rx_sample_rate_get,
-			aux_pcm_rx_sample_rate_put),
-	SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
-			aux_pcm_tx_sample_rate_get,
-			aux_pcm_tx_sample_rate_put),
-	SOC_ENUM_EXT("SEC_AUX_PCM_TX SampleRate", sec_aux_pcm_tx_sample_rate,
-			aux_pcm_tx_sample_rate_get,
-			aux_pcm_tx_sample_rate_put),
-	SOC_ENUM_EXT("TERT_AUX_PCM_TX SampleRate", tert_aux_pcm_tx_sample_rate,
-			aux_pcm_tx_sample_rate_get,
-			aux_pcm_tx_sample_rate_put),
-	SOC_ENUM_EXT("QUAT_AUX_PCM_TX SampleRate", quat_aux_pcm_tx_sample_rate,
-			aux_pcm_tx_sample_rate_get,
-			aux_pcm_tx_sample_rate_put),
-	SOC_ENUM_EXT("QUIN_AUX_PCM_TX SampleRate", quin_aux_pcm_tx_sample_rate,
-			aux_pcm_tx_sample_rate_get,
-			aux_pcm_tx_sample_rate_put),
-	SOC_ENUM_EXT("SEN_AUX_PCM_TX SampleRate", sen_aux_pcm_tx_sample_rate,
-			aux_pcm_tx_sample_rate_get,
-			aux_pcm_tx_sample_rate_put),
-	SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate,
-			mi2s_rx_sample_rate_get,
-			mi2s_rx_sample_rate_put),
-	SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate,
-			mi2s_rx_sample_rate_get,
-			mi2s_rx_sample_rate_put),
-	SOC_ENUM_EXT("TERT_MI2S_RX SampleRate", tert_mi2s_rx_sample_rate,
-			mi2s_rx_sample_rate_get,
-			mi2s_rx_sample_rate_put),
-	SOC_ENUM_EXT("QUAT_MI2S_RX SampleRate", quat_mi2s_rx_sample_rate,
-			mi2s_rx_sample_rate_get,
-			mi2s_rx_sample_rate_put),
-	SOC_ENUM_EXT("QUIN_MI2S_RX SampleRate", quin_mi2s_rx_sample_rate,
-			mi2s_rx_sample_rate_get,
-			mi2s_rx_sample_rate_put),
-	SOC_ENUM_EXT("SEN_MI2S_RX SampleRate", sen_mi2s_rx_sample_rate,
-			mi2s_rx_sample_rate_get,
-			mi2s_rx_sample_rate_put),
-	SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate,
-			mi2s_tx_sample_rate_get,
-			mi2s_tx_sample_rate_put),
-	SOC_ENUM_EXT("SEC_MI2S_TX SampleRate", sec_mi2s_tx_sample_rate,
-			mi2s_tx_sample_rate_get,
-			mi2s_tx_sample_rate_put),
-	SOC_ENUM_EXT("TERT_MI2S_TX SampleRate", tert_mi2s_tx_sample_rate,
-			mi2s_tx_sample_rate_get,
-			mi2s_tx_sample_rate_put),
-	SOC_ENUM_EXT("QUAT_MI2S_TX SampleRate", quat_mi2s_tx_sample_rate,
-			mi2s_tx_sample_rate_get,
-			mi2s_tx_sample_rate_put),
-	SOC_ENUM_EXT("QUIN_MI2S_TX SampleRate", quin_mi2s_tx_sample_rate,
-			mi2s_tx_sample_rate_get,
-			mi2s_tx_sample_rate_put),
-	SOC_ENUM_EXT("SEN_MI2S_TX SampleRate", sen_mi2s_tx_sample_rate,
-			mi2s_tx_sample_rate_get,
-			mi2s_tx_sample_rate_put),
-	SOC_ENUM_EXT("USB_AUDIO_RX Format", usb_rx_format,
-			usb_audio_rx_format_get, usb_audio_rx_format_put),
-	SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format,
-			usb_audio_tx_format_get, usb_audio_tx_format_put),
 	SOC_ENUM_EXT("PRI_TDM_RX_0 Format", tdm_rx_format,
 			tdm_rx_format_get,
 			tdm_rx_format_put),
@@ -3839,60 +3804,6 @@
 	SOC_ENUM_EXT("SEN_TDM_TX_0 Format", tdm_tx_format,
 			tdm_tx_format_get,
 			tdm_tx_format_put),
-	SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
-			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
-	SOC_ENUM_EXT("SEC_AUX_PCM_RX Format", aux_pcm_rx_format,
-			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
-	SOC_ENUM_EXT("TERT_AUX_PCM_RX Format", aux_pcm_rx_format,
-			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
-	SOC_ENUM_EXT("QUAT_AUX_PCM_RX Format", aux_pcm_rx_format,
-			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
-	SOC_ENUM_EXT("QUIN_AUX_PCM_RX Format", aux_pcm_rx_format,
-			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
-	SOC_ENUM_EXT("SEN_AUX_PCM_RX Format", aux_pcm_rx_format,
-			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
-	SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
-			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
-	SOC_ENUM_EXT("SEC_AUX_PCM_TX Format", aux_pcm_tx_format,
-			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
-	SOC_ENUM_EXT("TERT_AUX_PCM_TX Format", aux_pcm_tx_format,
-			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
-	SOC_ENUM_EXT("QUAT_AUX_PCM_TX Format", aux_pcm_tx_format,
-			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
-	SOC_ENUM_EXT("QUIN_AUX_PCM_TX Format", aux_pcm_tx_format,
-			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
-	SOC_ENUM_EXT("SEN_AUX_PCM_TX Format", aux_pcm_tx_format,
-			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
-	SOC_ENUM_EXT("PRIM_MI2S_RX Format", mi2s_rx_format,
-			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
-	SOC_ENUM_EXT("SEC_MI2S_RX Format", mi2s_rx_format,
-			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
-	SOC_ENUM_EXT("TERT_MI2S_RX Format", mi2s_rx_format,
-			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
-	SOC_ENUM_EXT("QUAT_MI2S_RX Format", mi2s_rx_format,
-			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
-	SOC_ENUM_EXT("QUIN_MI2S_RX Format", mi2s_rx_format,
-			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
-	SOC_ENUM_EXT("SEN_MI2S_RX Format", mi2s_rx_format,
-			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
-	SOC_ENUM_EXT("PRIM_MI2S_TX Format", mi2s_tx_format,
-			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
-	SOC_ENUM_EXT("SEC_MI2S_TX Format", mi2s_tx_format,
-			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
-	SOC_ENUM_EXT("TERT_MI2S_TX Format", mi2s_tx_format,
-			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
-	SOC_ENUM_EXT("QUAT_MI2S_TX Format", mi2s_tx_format,
-			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
-	SOC_ENUM_EXT("QUIN_MI2S_TX Format", mi2s_tx_format,
-			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
-	SOC_ENUM_EXT("SEN_MI2S_TX Format", mi2s_tx_format,
-			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
-	SOC_ENUM_EXT("USB_AUDIO_RX Channels", usb_rx_chs,
-			usb_audio_rx_ch_get, usb_audio_rx_ch_put),
-	SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs,
-			usb_audio_tx_ch_get, usb_audio_tx_ch_put),
-	SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
-			proxy_rx_ch_get, proxy_rx_ch_put),
 	SOC_ENUM_EXT("PRI_TDM_RX_0 Channels", tdm_rx_chs,
 			tdm_rx_ch_get,
 			tdm_rx_ch_put),
@@ -3929,6 +3840,134 @@
 	SOC_ENUM_EXT("SEN_TDM_TX_0 Channels", tdm_tx_chs,
 			tdm_tx_ch_get,
 			tdm_tx_ch_put),
+	SOC_SINGLE_MULTI_EXT("TDM Slot Map", SND_SOC_NOPM, 0, 255, 0,
+			TDM_MAX_SLOTS + MAX_PATH, NULL, tdm_slot_map_put),
+};
+
+static const struct snd_kcontrol_new msm_auxpcm_snd_controls[] = {
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_RX SampleRate", sec_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_RX SampleRate", tert_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_RX SampleRate", quat_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUIN_AUX_PCM_RX SampleRate", quin_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEN_AUX_PCM_RX SampleRate", sen_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_TX SampleRate", sec_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_TX SampleRate", tert_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_TX SampleRate", quat_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUIN_AUX_PCM_TX SampleRate", quin_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEN_AUX_PCM_TX SampleRate", sen_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("QUIN_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("SEN_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("QUIN_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("SEN_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+};
+
+static const struct snd_kcontrol_new msm_mi2s_snd_controls[] = {
+	SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_MI2S_RX SampleRate", tert_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_MI2S_RX SampleRate", quat_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUIN_MI2S_RX SampleRate", quin_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEN_MI2S_RX SampleRate", sen_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_MI2S_TX SampleRate", sec_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_MI2S_TX SampleRate", tert_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_MI2S_TX SampleRate", quat_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUIN_MI2S_TX SampleRate", quin_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEN_MI2S_TX SampleRate", sen_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("SEC_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("TERT_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("QUAT_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("QUIN_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("SEN_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("PRIM_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("SEC_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("TERT_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("QUAT_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("QUIN_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("SEN_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
 	SOC_ENUM_EXT("PRIM_MI2S_RX Channels", prim_mi2s_rx_chs,
 			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
 	SOC_ENUM_EXT("SEC_MI2S_RX Channels", sec_mi2s_rx_chs,
@@ -3953,35 +3992,6 @@
 			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
 	SOC_ENUM_EXT("SEN_MI2S_TX Channels", sen_mi2s_tx_chs,
 			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
-	SOC_ENUM_EXT("Display Port RX Channels", ext_disp_rx_chs,
-			ext_disp_rx_ch_get, ext_disp_rx_ch_put),
-	SOC_ENUM_EXT("Display Port RX Bit Format", ext_disp_rx_format,
-			ext_disp_rx_format_get, ext_disp_rx_format_put),
-	SOC_ENUM_EXT("Display Port RX SampleRate", ext_disp_rx_sample_rate,
-			ext_disp_rx_sample_rate_get,
-			ext_disp_rx_sample_rate_put),
-	SOC_ENUM_EXT("Display Port1 RX Channels", ext_disp_rx_chs,
-			ext_disp_rx_ch_get, ext_disp_rx_ch_put),
-	SOC_ENUM_EXT("Display Port1 RX Bit Format", ext_disp_rx_format,
-			ext_disp_rx_format_get, ext_disp_rx_format_put),
-	SOC_ENUM_EXT("Display Port1 RX SampleRate", ext_disp_rx_sample_rate,
-			ext_disp_rx_sample_rate_get,
-			ext_disp_rx_sample_rate_put),
-	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
-			msm_bt_sample_rate_get,
-			msm_bt_sample_rate_put),
-	SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
-			msm_bt_sample_rate_rx_get,
-			msm_bt_sample_rate_rx_put),
-	SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
-			msm_bt_sample_rate_tx_get,
-			msm_bt_sample_rate_tx_put),
-	SOC_ENUM_EXT("AFE_LOOPBACK_TX Channels", afe_loopback_tx_chs,
-			afe_loopback_tx_ch_get, afe_loopback_tx_ch_put),
-	SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
-			msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
-	SOC_SINGLE_MULTI_EXT("TDM Slot Map", SND_SOC_NOPM, 0, 255, 0,
-			TDM_MAX_SLOTS + MAX_PATH, NULL, tdm_slot_map_put),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -5313,6 +5323,45 @@
 					   tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
 }
 
+#ifndef CONFIG_TDM_DISABLE
+static void msm_add_tdm_snd_controls(struct snd_soc_component *component)
+{
+	snd_soc_add_component_controls(component, msm_tdm_snd_controls,
+				ARRAY_SIZE(msm_tdm_snd_controls));
+}
+#else
+static void msm_add_tdm_snd_controls(struct snd_soc_component *component)
+{
+	return;
+}
+#endif
+
+#ifndef CONFIG_MI2S_DISABLE
+static void msm_add_mi2s_snd_controls(struct snd_soc_component *component)
+{
+	snd_soc_add_component_controls(component, msm_mi2s_snd_controls,
+				ARRAY_SIZE(msm_mi2s_snd_controls));
+}
+#else
+static void msm_add_mi2s_snd_controls(struct snd_soc_component *component)
+{
+	return;
+}
+#endif
+
+#ifndef CONFIG_AUXPCM_DISABLE
+static void msm_add_auxpcm_snd_controls(struct snd_soc_component *component)
+{
+	snd_soc_add_component_controls(component, msm_auxpcm_snd_controls,
+				ARRAY_SIZE(msm_auxpcm_snd_controls));
+}
+#else
+static void msm_add_auxpcm_snd_controls(struct snd_soc_component *component)
+{
+	return;
+}
+#endif
+
 static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int ret = -EINVAL;
@@ -5348,6 +5397,10 @@
 		return ret;
 	}
 
+	msm_add_tdm_snd_controls(component);
+	msm_add_mi2s_snd_controls(component);
+	msm_add_auxpcm_snd_controls(component);
+
 	snd_soc_dapm_new_controls(dapm, msm_int_dapm_widgets,
 				ARRAY_SIZE(msm_int_dapm_widgets));
 
@@ -6244,6 +6297,10 @@
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
+};
+
+
+static struct snd_soc_dai_link msm_tdm_be_dai_links[] = {
 	{
 		.name = LPASS_BE_PRI_TDM_RX_0,
 		.stream_name = "Primary TDM0 Playback",
@@ -7120,7 +7177,8 @@
 			ARRAY_SIZE(ext_disp_be_dai_link) +
 			ARRAY_SIZE(msm_wcn_be_dai_links) +
 			ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) +
-			ARRAY_SIZE(msm_wcn_btfm_be_dai_links)];
+			ARRAY_SIZE(msm_wcn_btfm_be_dai_links) +
+			ARRAY_SIZE(msm_tdm_be_dai_links)];
 
 static int msm_populate_dai_link_component_of_node(
 					struct snd_soc_card *card)
@@ -7437,6 +7495,16 @@
 				ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
 		}
 
+		rc = of_property_read_u32(dev->of_node, "qcom,tdm-audio-intf",
+				&val);
+		if (!rc && val) {
+			memcpy(msm_kona_dai_links + total_links,
+				msm_tdm_be_dai_links,
+				sizeof(msm_tdm_be_dai_links));
+			total_links +=
+				ARRAY_SIZE(msm_tdm_be_dai_links);
+		}
+
 		rc = of_property_read_u32(dev->of_node, "qcom,wcn-btfm",
 					  &wcn_btfm_intf);
 		if (rc) {
@@ -7503,9 +7571,14 @@
 	if (!strcmp(component->name_prefix, "SpkrLeft")) {
 		dev_dbg(component->dev, "%s: setting left ch map to codec %s\n",
 			__func__, component->name);
-		wsa881x_set_channel_map(component, &spkleft_ports[0],
-				WSA881X_MAX_SWR_PORTS, &ch_mask[0],
-				&ch_rate[0], &spkleft_port_types[0]);
+		if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+			wsa883x_set_channel_map(component, &spkleft_ports[0],
+					WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+					&ch_rate[0], &spkleft_port_types[0]);
+		else
+			wsa881x_set_channel_map(component, &spkleft_ports[0],
+					WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+					&ch_rate[0], &spkleft_port_types[0]);
 		if (dapm->component) {
 			snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
 			snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
@@ -7513,9 +7586,14 @@
 	} else if (!strcmp(component->name_prefix, "SpkrRight")) {
 		dev_dbg(component->dev, "%s: setting right ch map to codec %s\n",
 			__func__, component->name);
-		wsa881x_set_channel_map(component, &spkright_ports[0],
-				WSA881X_MAX_SWR_PORTS, &ch_mask[0],
-				&ch_rate[0], &spkright_port_types[0]);
+		if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+			wsa883x_set_channel_map(component, &spkright_ports[0],
+					WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+					&ch_rate[0], &spkright_port_types[0]);
+		else
+			wsa881x_set_channel_map(component, &spkright_ports[0],
+					WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+					&ch_rate[0], &spkright_port_types[0]);
 		if (dapm->component) {
 			snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
 			snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
@@ -7538,8 +7616,12 @@
 		}
 		pdata->codec_root = entry;
 	}
-	wsa881x_codec_info_create_codec_entry(pdata->codec_root,
-					      component);
+	if (strnstr(component->name, "wsa883x", sizeof(component->name)))
+		wsa883x_codec_info_create_codec_entry(pdata->codec_root,
+						      component);
+	else
+		wsa881x_codec_info_create_codec_entry(pdata->codec_root,
+						      component);
 err:
 	return ret;
 }
diff --git a/asoc/msm-pcm-loopback-v2.c b/asoc/msm-pcm-loopback-v2.c
index 86e8c81..4c00c72 100644
--- a/asoc/msm-pcm-loopback-v2.c
+++ b/asoc/msm-pcm-loopback-v2.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -568,11 +568,15 @@
 {
 	int rc = 0;
 	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
-	struct snd_pcm_substream *substream =
-		vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct snd_pcm_substream *substream = NULL;
 	struct msm_pcm_loopback *prtd;
 
 	pr_debug("%s\n", __func__);
+	if (!vol) {
+		pr_err("%s: vol is NULL\n", __func__);
+		return -ENODEV;
+	}
+	substream = vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
 	if ((!substream) || (!substream->runtime)) {
 		pr_debug("%s substream or runtime not found\n", __func__);
 		rc = -ENODEV;
diff --git a/asoc/msm-pcm-q6-noirq.c b/asoc/msm-pcm-q6-noirq.c
index 12a1f12..8fb6f7c 100644
--- a/asoc/msm-pcm-q6-noirq.c
+++ b/asoc/msm-pcm-q6-noirq.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -720,13 +720,17 @@
 {
 	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
 	struct msm_plat_data *pdata = NULL;
-	struct snd_pcm_substream *substream =
-		vol->pcm->streams[vol->stream].substream;
+	struct snd_pcm_substream *substream = NULL;
 	struct snd_soc_pcm_runtime *soc_prtd = NULL;
 	struct snd_soc_component *component = NULL;
 	struct msm_audio *prtd;
 
 	pr_debug("%s\n", __func__);
+	if (!vol) {
+		pr_err("%s: vol is NULL\n", __func__);
+		return -ENODEV;
+	}
+	substream = vol->pcm->streams[vol->stream].substream;
 	if (!substream) {
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index 60e84cb..c22c39b 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
  */
 
 
@@ -1514,13 +1514,17 @@
 {
 	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
 	struct msm_plat_data *pdata = NULL;
-	struct snd_pcm_substream *substream =
-		vol->pcm->streams[vol->stream].substream;
+	struct snd_pcm_substream *substream = NULL;
 	struct snd_soc_pcm_runtime *soc_prtd = NULL;
 	struct snd_soc_component *component = NULL;
 	struct msm_audio *prtd;
 
 	pr_debug("%s\n", __func__);
+	if (!vol) {
+		pr_err("%s: vol is NULL\n", __func__);
+		return -ENODEV;
+	}
+	substream = vol->pcm->streams[vol->stream].substream;
 	if (!substream) {
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 70e2ebf..d4fbe39 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -30222,6 +30222,50 @@
 	msm_aptx_dec_license_control_put),
 };
 
+static int msm_routing_get_pll_clk_drift(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	return 0;
+}
+
+static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	u16 port_id = 0;
+	int32_t clk_drift = 0;
+	uint32_t clk_reset = 0;
+	int be_idx, ret = -EINVAL;
+
+	be_idx = ucontrol->value.integer.value[0];
+	clk_drift = ucontrol->value.integer.value[1];
+	clk_reset = ucontrol->value.integer.value[2];
+
+	if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) {
+		pr_err("%s: Invalid be id %d\n", __func__, be_idx);
+		return -EINVAL;
+	}
+
+	if (!msm_bedais[be_idx].active && !clk_reset) {
+		pr_err("%s:BE is not active %d, cannot set clock drift\n",
+			__func__, be_idx);
+		return -EINVAL;
+	}
+
+	port_id = msm_bedais[be_idx].port_id;
+	pr_debug("%s: clk drift %d be idx %d clk reset %d port id 0x%x\n",
+		  __func__, clk_drift, be_idx, clk_reset, port_id);
+	ret = afe_set_pll_clk_drift(port_id, clk_drift, clk_reset);
+	if (ret < 0)
+		pr_err("%s: failed to set pll clk drift\n", __func__);
+
+	return ret;
+}
+
+static const struct snd_kcontrol_new pll_clk_drift_controls[] = {
+	SOC_SINGLE_MULTI_EXT("PLL config data", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+	0, 128, msm_routing_get_pll_clk_drift, msm_routing_put_pll_clk_drift),
+};
+
 static int msm_routing_put_port_chmap_mixer(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_value *ucontrol)
 {
@@ -30522,6 +30566,9 @@
 			port_multi_channel_map_mixer_controls,
 			ARRAY_SIZE(port_multi_channel_map_mixer_controls));
 
+	snd_soc_add_component_controls(component, pll_clk_drift_controls,
+				      ARRAY_SIZE(pll_clk_drift_controls));
+
 	return 0;
 }
 
diff --git a/config/bengalauto.conf b/config/bengalauto.conf
index 0478eca..cd614f6 100644
--- a/config/bengalauto.conf
+++ b/config/bengalauto.conf
@@ -27,6 +27,7 @@
 CONFIG_VA_MACRO=m
 CONFIG_RX_MACRO=m
 CONFIG_TX_MACRO=m
+CONFIG_DIGITAL_CDC_RSC_MGR=m
 CONFIG_SND_SOC_WCD_IRQ=m
 CONFIG_SND_SOC_WCD937X=m
 CONFIG_SND_SOC_WCD937X_SLAVE=m
diff --git a/config/bengalautoconf.h b/config/bengalautoconf.h
index 3e72903..83cca08 100644
--- a/config/bengalautoconf.h
+++ b/config/bengalautoconf.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
  */
 
 #define CONFIG_PINCTRL_LPI 1
@@ -31,6 +31,7 @@
 #define CONFIG_VA_MACRO 1
 #define CONFIG_RX_MACRO 1
 #define CONFIG_TX_MACRO 1
+#define CONFIG_DIGITAL_CDC_RSC_MGR 1
 #define CONFIG_SND_SOC_WCD_IRQ 1
 #define CONFIG_SND_SOC_WCD937X 1
 #define CONFIG_SND_SOC_WCD937X_SLAVE 1
diff --git a/config/konaauto.conf b/config/konaauto.conf
index 03e0541..74ca2d4 100644
--- a/config/konaauto.conf
+++ b/config/konaauto.conf
@@ -36,3 +36,4 @@
 export CONFIG_SND_SOC_KONA=m
 export CONFIG_SND_EVENT=m
 export CONFIG_VOICE_MHI=m
+export CONFIG_DIGITAL_CDC_RSC_MGR=m
diff --git a/config/konaautoconf.h b/config/konaautoconf.h
index f932236..e489b41 100644
--- a/config/konaautoconf.h
+++ b/config/konaautoconf.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  */
 
 #define CONFIG_PINCTRL_LPI 1
@@ -40,3 +40,4 @@
 #define CONFIG_SND_SOC_KONA 1
 #define CONFIG_SND_EVENT 1
 #define CONFIG_VOICE_MHI 1
+#define CONFIG_DIGITAL_CDC_RSC_MGR 1
diff --git a/config/litoauto.conf b/config/litoauto.conf
index 12bb1df..d0030bb 100644
--- a/config/litoauto.conf
+++ b/config/litoauto.conf
@@ -3,6 +3,7 @@
 CONFIG_SND_SOC_WCD9XXX_V2=m
 CONFIG_SND_SOC_WCD_MBHC=m
 CONFIG_SND_SOC_WSA881X=m
+CONFIG_SND_SOC_WSA883X=m
 CONFIG_WCD9XXX_CODEC_CORE_V2=m
 CONFIG_MSM_CDC_PINCTRL=m
 CONFIG_MSM_QDSP6V2_CODECS=m
@@ -29,6 +30,7 @@
 CONFIG_VA_MACRO=m
 CONFIG_RX_MACRO=m
 CONFIG_TX_MACRO=m
+CONFIG_DIGITAL_CDC_RSC_MGR=m
 CONFIG_SND_SOC_WCD_IRQ=m
 CONFIG_SND_SOC_WCD938X=m
 CONFIG_SND_SOC_WCD938X_SLAVE=m
diff --git a/config/litoautoconf.h b/config/litoautoconf.h
index 0cfdab2..322ac73 100644
--- a/config/litoautoconf.h
+++ b/config/litoautoconf.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
  */
 
 #define CONFIG_PINCTRL_LPI 1
@@ -7,6 +7,7 @@
 #define CONFIG_SND_SOC_WCD9XXX_V2 1
 #define CONFIG_SND_SOC_WCD_MBHC 1
 #define CONFIG_SND_SOC_WSA881X 1
+#define CONFIG_SND_SOC_WSA883X 1
 #define CONFIG_WCD9XXX_CODEC_CORE_V2 1
 #define CONFIG_MSM_CDC_PINCTRL 1
 #define CONFIG_MSM_QDSP6V2_CODECS 1
@@ -33,6 +34,7 @@
 #define CONFIG_VA_MACRO 1
 #define CONFIG_RX_MACRO 1
 #define CONFIG_TX_MACRO 1
+#define CONFIG_DIGITAL_CDC_RSC_MGR 1
 #define CONFIG_SND_SOC_WCD_IRQ 1
 #define CONFIG_SND_SOC_WCD938X 1
 #define CONFIG_SND_SOC_WCD938X_SLAVE 1
diff --git a/dsp/Kbuild b/dsp/Kbuild
index 006de44..43180e7 100644
--- a/dsp/Kbuild
+++ b/dsp/Kbuild
@@ -184,6 +184,10 @@
 	Q6_OBJS += voice_mhi.o
 endif
 
+ifdef CONFIG_DIGITAL_CDC_RSC_MGR
+	Q6_OBJS += digital-cdc-rsc-mgr.o
+endif
+
 LINUX_INC +=	-Iinclude/linux
 
 INCS +=		$(COMMON_INC) \
diff --git a/dsp/digital-cdc-rsc-mgr.c b/dsp/digital-cdc-rsc-mgr.c
new file mode 100644
index 0000000..4206523
--- /dev/null
+++ b/dsp/digital-cdc-rsc-mgr.c
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/ratelimit.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
+
+struct mutex hw_vote_lock;
+static bool is_init_done;
+
+/**
+ * digital_cdc_rsc_mgr_hw_vote_enable - Enables hw vote in DSP
+ *
+ * @vote_handle: vote handle for which voting needs to be done
+ *
+ * Returns 0 on success or -EINVAL/error code on failure
+ */
+int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle)
+{
+	int ret = 0;
+
+	if (!is_init_done || vote_handle == NULL) {
+		pr_err_ratelimited("%s: init failed or vote handle NULL\n",
+				   __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_vote_lock);
+	ret = clk_prepare_enable(vote_handle);
+	mutex_unlock(&hw_vote_lock);
+
+	pr_debug("%s: return %d\n", __func__, ret);
+	trace_printk("%s: return %d\n", __func__, ret);
+	return ret;
+}
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_enable);
+
+/**
+ * digital_cdc_rsc_mgr_hw_vote_disable - Disables hw vote in DSP
+ *
+ * @vote_handle: vote handle for which voting needs to be disabled
+ *
+ */
+void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle)
+{
+	if (!is_init_done || vote_handle == NULL) {
+		pr_err_ratelimited("%s: init failed or vote handle NULL\n",
+				   __func__);
+		return;
+	}
+
+	mutex_lock(&hw_vote_lock);
+	clk_disable_unprepare(vote_handle);
+	mutex_unlock(&hw_vote_lock);
+	trace_printk("%s\n", __func__);
+}
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable);
+
+/**
+ * digital_cdc_rsc_mgr_hw_vote_reset - Resets hw vote count
+ *
+ */
+void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
+{
+	int count = 0;
+
+	if (!is_init_done || vote_handle == NULL) {
+		pr_err_ratelimited("%s: init failed or vote handle NULL\n",
+				   __func__);
+		return;
+	}
+
+	mutex_lock(&hw_vote_lock);
+	while (__clk_is_enabled(vote_handle)) {
+		clk_disable_unprepare(vote_handle);
+		count++;
+	}
+	pr_debug("%s: Vote count after SSR: %d\n", __func__, count);
+	trace_printk("%s: Vote count after SSR: %d\n", __func__, count);
+
+	while (count--)
+		clk_prepare_enable(vote_handle);
+	mutex_unlock(&hw_vote_lock);
+}
+EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset);
+
+void digital_cdc_rsc_mgr_init()
+{
+	mutex_init(&hw_vote_lock);
+	is_init_done = true;
+}
+
+void digital_cdc_rsc_mgr_exit()
+{
+	mutex_destroy(&hw_vote_lock);
+	is_init_done = false;
+}
diff --git a/dsp/q6_init.c b/dsp/q6_init.c
index fb18741..e990f2a 100644
--- a/dsp/q6_init.c
+++ b/dsp/q6_init.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019-2020 The Linux Foundation. All rights reserved.
  */
 
 #include <linux/kernel.h>
@@ -24,11 +24,13 @@
 	avtimer_init();
 	msm_mdf_init();
 	voice_mhi_init();
+	digital_cdc_rsc_mgr_init();
 	return 0;
 }
 
 static void __exit audio_q6_exit(void)
 {
+	digital_cdc_rsc_mgr_exit();
 	msm_mdf_exit();
 	avtimer_exit();
 	audio_slimslave_exit();
diff --git a/dsp/q6_init.h b/dsp/q6_init.h
index 4df2e03..77ba743 100644
--- a/dsp/q6_init.h
+++ b/dsp/q6_init.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef __Q6_INIT_H__
@@ -80,5 +80,19 @@
 	return;
 }
 #endif
+
+#ifdef CONFIG_DIGITAL_CDC_RSC_MGR
+void digital_cdc_rsc_mgr_init(void);
+void digital_cdc_rsc_mgr_exit(void);
+#else
+static inline void digital_cdc_rsc_mgr_init(void)
+{
+}
+
+static inline void digital_cdc_rsc_mgr_exit(void)
+{
+}
+#endif /* CONFIG_DIGITAL_CDC_RSC_MGR */
+
 #endif
 
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 3b26c0c..2586bd5 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -174,6 +174,43 @@
 	uint32_t v_vali_flag;
 };
 
+struct afe_clkinfo_per_port {
+	u16 port_id; /* AFE port ID */
+	uint32_t clk_id; /* Clock ID */
+};
+
+struct afe_clkinfo_per_port clkinfo_per_port[] = {
+	{ AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+	{ AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT},
+	{ AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT},
+	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT},
+	{ AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT},
+	{ AFE_PORT_ID_SENARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT},
+	{ AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT},
+	{ AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT},
+	{ AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT},
+	{ AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT},
+	{ AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT},
+	{ AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT},
+	{ AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT},
+	{ AFE_PORT_ID_PRIMARY_SPDIF_RX,
+		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE},
+	{ AFE_PORT_ID_PRIMARY_SPDIF_TX,
+		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE},
+	{ AFE_PORT_ID_SECONDARY_SPDIF_RX,
+		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE},
+	{ AFE_PORT_ID_SECONDARY_SPDIF_TX,
+		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE},
+	{ AFE_PORT_ID_PRIMARY_META_MI2S_RX,
+		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+	{ AFE_PORT_ID_SECONDARY_META_MI2S_RX,
+		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+};
+
 static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
 static unsigned long afe_configured_cmd;
 
@@ -7843,6 +7880,156 @@
 }
 EXPORT_SYMBOL(afe_set_lpass_clock);
 
+static int afe_get_port_idx(u16 port_id)
+{
+	u16 afe_port = 0;
+	int i = -EINVAL;
+
+	pr_debug("%s: port id 0x%x\n", __func__, port_id);
+
+	if ((port_id >= AFE_PORT_ID_TDM_PORT_RANGE_START) &&
+		(port_id <= AFE_PORT_ID_TDM_PORT_RANGE_END))
+		afe_port = port_id & 0xFFF0;
+	else if ((port_id == AFE_PORT_ID_PRIMARY_SPDIF_RX) ||
+		 (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) ||
+		 (port_id == AFE_PORT_ID_SECONDARY_SPDIF_RX) ||
+		 (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX))
+		afe_port = port_id;
+	else
+		afe_port = port_id & 0xFFFE;
+
+	for (i = 0; i < ARRAY_SIZE(clkinfo_per_port); i++) {
+		if (afe_port == clkinfo_per_port[i].port_id) {
+			pr_debug("%s: idx 0x%x port id 0x%x\n", __func__,
+				  i, afe_port);
+			return i;
+		}
+	}
+
+	pr_debug("%s: cannot get idx for port id 0x%x\n", __func__,
+		afe_port);
+
+	return -EINVAL;
+}
+
+static int afe_get_clk_id(u16 port_id)
+{
+	u16 afe_port = 0;
+	uint32_t clk_id = -EINVAL;
+	int idx = 0;
+
+	idx = afe_get_port_idx(port_id);
+	if (idx < 0) {
+		pr_err("%s: cannot get clock id for port id 0x%x\n", __func__,
+			afe_port);
+		return -EINVAL;
+	}
+
+	clk_id = clkinfo_per_port[idx].clk_id;
+	pr_debug("%s: clk id 0x%x port id 0x%x\n", __func__, clk_id,
+		  afe_port);
+
+	return clk_id;
+}
+
+/**
+ * afe_set_clk_id - Update clock id for AFE port
+ *
+ * @port_id: AFE port id
+ * @clk_id: CLock ID
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int afe_set_clk_id(u16 port_id, uint32_t clk_id)
+{
+	u16 afe_port = 0;
+	int idx = 0;
+
+	idx = afe_get_port_idx(port_id);
+	if (idx < 0) {
+		pr_debug("%s: cannot set clock id for port id 0x%x\n", __func__,
+			afe_port);
+		return -EINVAL;
+	}
+
+	clkinfo_per_port[idx].clk_id = clk_id;
+	pr_debug("%s: updated clk id 0x%x port id 0x%x\n", __func__,
+		  clkinfo_per_port[idx].clk_id, afe_port);
+
+	return 0;
+}
+EXPORT_SYMBOL(afe_set_clk_id);
+
+/**
+ * afe_set_pll_clk_drift - Set audio interface PLL clock drift
+ *
+ * @port_id: AFE port id
+ * @set_clk_drift: clk drift to adjust PLL
+ * @clk_reset: reset Interface clock to original value
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
+			  uint32_t clk_reset)
+{
+	struct afe_set_clk_drift clk_drift;
+	struct param_hdr_v3 param_hdr;
+	uint32_t clk_id;
+	int index = 0, ret = 0;
+
+	memset(&param_hdr, 0, sizeof(param_hdr));
+	memset(&clk_drift, 0, sizeof(clk_drift));
+
+	index = q6audio_get_port_index(port_id);
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: index[%d] invalid!\n", __func__, index);
+		return -EINVAL;
+	}
+
+	ret = afe_q6_interface_prepare();
+	if (ret != 0) {
+		pr_err_ratelimited("%s: Q6 interface prepare failed %d\n",
+				    __func__, ret);
+		return ret;
+	}
+
+	clk_id = afe_get_clk_id(port_id);
+	if (clk_id < 0) {
+		pr_err("%s: cannot get clk id for port id 0x%x\n",
+			__func__, port_id);
+		return -EINVAL;
+	}
+
+	if (clk_id & 0x01) {
+		pr_err("%s: cannot adjust clock drift for external clock id 0x%x\n",
+			__func__, clk_id);
+		return -EINVAL;
+	}
+
+	clk_drift.clk_drift = set_clk_drift;
+	clk_drift.clk_reset = clk_reset;
+	clk_drift.clk_id = clk_id;
+	pr_debug("%s: clk id = 0x%x clk drift  = %d clk reset = %d port id 0x%x\n",
+		  __func__, clk_drift.clk_id, clk_drift.clk_drift,
+		 clk_drift.clk_reset, port_id);
+
+	mutex_lock(&this_afe.afe_clk_lock);
+	param_hdr.module_id = AFE_MODULE_CLOCK_SET;
+	param_hdr.instance_id = INSTANCE_ID_0;
+	param_hdr.param_id = AFE_PARAM_ID_CLOCK_ADJUST;
+	param_hdr.param_size = sizeof(struct afe_set_clk_drift);
+
+	ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
+						   (u8 *) &clk_drift);
+	if (ret < 0)
+		pr_err_ratelimited("%s: AFE PLL clk drift failed with ret %d\n",
+				    __func__, ret);
+
+	mutex_unlock(&this_afe.afe_clk_lock);
+	return ret;
+}
+EXPORT_SYMBOL(afe_set_pll_clk_drift);
+
 /**
  * afe_set_lpass_clk_cfg - Set AFE clk config
  *
@@ -7929,6 +8116,10 @@
 		return -EINVAL;
 	}
 
+	ret = afe_set_clk_id(port_id, cfg->clk_id);
+	if (ret < 0)
+		pr_debug("%s: afe_set_clk_id fail %d\n", __func__, ret);
+
 	ret = afe_set_lpass_clk_cfg(index, cfg);
 	if (ret)
 		pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index 66883ba..a77ffd3 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -2393,7 +2393,7 @@
 	lab_config_hdr.param_id = LSM_PARAM_ID_LAB_CONFIG;
 	lab_config_hdr.param_size = sizeof(lab_config);
 	lab_config.minor_version = 1;
-	lab_config.wake_up_latency_ms = 250;
+	lab_config.wake_up_latency_ms = 40;
 	rc = q6lsm_pack_and_set_params(client, &lab_config_hdr,
 				       (uint8_t *) &lab_config,
 				       LSM_SESSION_CMD_SET_PARAMS);
diff --git a/include/asoc/msm-cdc-supply.h b/include/asoc/msm-cdc-supply.h
index c6aacf6..cff1a4a 100644
--- a/include/asoc/msm-cdc-supply.h
+++ b/include/asoc/msm-cdc-supply.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2016, 2018-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016, 2018-2020 The Linux Foundation. All rights reserved.
  */
 
 #ifndef __CODEC_POWER_SUPPLY_H__
@@ -21,6 +21,10 @@
 extern int msm_cdc_get_power_supplies(struct device *dev,
 				      struct cdc_regulator **cdc_vreg,
 				      int *total_num_supplies);
+extern bool msm_cdc_is_ondemand_supply(struct device *dev,
+				struct regulator_bulk_data *supplies,
+				struct cdc_regulator *cdc_vreg,
+				int num_supplies, char *supply_name);
 extern int msm_cdc_disable_ondemand_supply(struct device *dev,
 					struct regulator_bulk_data *supplies,
 					struct cdc_regulator *cdc_vreg,
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 7d56a4d..5ac7751 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -11766,6 +11766,35 @@
 #define AFE_MODULE_CLOCK_SET		0x0001028F
 #define AFE_PARAM_ID_CLOCK_SET		0x00010290
 
+struct afe_set_clk_drift {
+	/*
+	 * Clock ID
+	 *	@values
+	 *	- 0x100 to 0x10E
+	 *	- 0x200 to 0x20C
+	 *	- 0x500 to 0x505
+	 */
+	uint32_t clk_id;
+
+	/*
+	 * Clock drift  (in PPB) to be set.
+	 *	@values
+	 *	- need to get values from DSP team
+	 */
+	int32_t clk_drift;
+
+	/*
+	 * Clock rest.
+	 *	@values
+	 *	- 1 -- Reset PLL with the original frequency
+	 *	- 0 -- Adjust the clock with the clk drift value
+	 */
+	uint32_t clk_reset;
+} __packed;
+
+/* This param id is used to adjust audio interface PLL*/
+#define AFE_PARAM_ID_CLOCK_ADJUST       0x000102C6
+
 enum afe_lpass_digital_clk_src {
 	Q6AFE_LPASS_DIGITAL_ROOT_INVALID,
 	Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR,
diff --git a/include/dsp/digital-cdc-rsc-mgr.h b/include/dsp/digital-cdc-rsc-mgr.h
new file mode 100644
index 0000000..685cd5c
--- /dev/null
+++ b/include/dsp/digital-cdc-rsc-mgr.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef DIGITAL_CDC_RSC_MGR_H
+#define DIGITAL_CDC_RSC_MGR_H
+
+#ifdef CONFIG_DIGITAL_CDC_RSC_MGR
+
+int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle);
+void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle);
+void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle);
+
+#else
+
+static inline int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle)
+{
+	return 0;
+}
+
+static inline void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle)
+{
+}
+
+static inline void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
+{
+}
+
+#endif /* CONFIG_DIGITAL_CDC_RSC_MGR */
+
+#endif /* DIGITAL_CDC_RSC_MGR_H */
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 76617a9..3ff3028 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -487,6 +487,9 @@
 	void (*afe_cb_wakeup_irq)(void *handle));
 int afe_get_doa_tracking_mon(u16 port_id,
 	struct doa_tracking_mon_param *doa_tracking_data);
+int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
+			  uint32_t clk_reset);
+int afe_set_clk_id(u16 port_id, uint32_t clk_id);
 
 enum {
 	AFE_LPASS_CORE_HW_BLOCK_ID_NONE,
diff --git a/include/uapi/linux/msm_audio_calibration.h b/include/uapi/linux/msm_audio_calibration.h
index 35b5960..e8ba1b3 100644
--- a/include/uapi/linux/msm_audio_calibration.h
+++ b/include/uapi/linux/msm_audio_calibration.h
@@ -104,6 +104,7 @@
 	ADM_LSM_TOPOLOGY_CAL_TYPE,
 	ADM_LSM_AUDPROC_CAL_TYPE,
 	ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
+	ADM_AUDPROC_PERSISTENT_CAL_TYPE,
 	MAX_CAL_TYPES,
 };
 
@@ -117,6 +118,7 @@
 #define ADM_LSM_TOPOLOGY_CAL_TYPE ADM_LSM_TOPOLOGY_CAL_TYPE
 #define ADM_LSM_AUDPROC_CAL_TYPE ADM_LSM_AUDPROC_CAL_TYPE
 #define ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE
+#define ADM_AUDPROC_PERSISTENT_CAL_TYPE ADM_AUDPROC_PERSISTENT_CAL_TYPE
 #define LSM_CAL_TYPES
 
 #define TOPOLOGY_SPECIFIC_CHANNEL_INFO
diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c
index c3d2326..0b0eef5 100644
--- a/soc/pinctrl-lpi.c
+++ b/soc/pinctrl-lpi.c
@@ -16,6 +16,7 @@
 #include <linux/clk.h>
 #include <linux/bitops.h>
 #include <soc/snd_event.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
 #include <linux/pm_runtime.h>
 #include <dsp/audio_notifier.h>
 
@@ -469,6 +470,7 @@
 				   unsigned long opcode, void *ptr)
 {
 	static bool initial_boot = true;
+	struct lpi_gpio_state *state = dev_get_drvdata(lpi_dev);
 
 	pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
 
@@ -484,6 +486,17 @@
 	case AUDIO_NOTIFIER_SERVICE_UP:
 		if (initial_boot)
 			initial_boot = false;
+
+		/* Reset HW votes after SSR */
+		if (!lpi_dev_up) {
+			if (state->lpass_core_hw_vote)
+				digital_cdc_rsc_mgr_hw_vote_reset(
+					state->lpass_core_hw_vote);
+			if (state->lpass_audio_hw_vote)
+				digital_cdc_rsc_mgr_hw_vote_reset(
+					state->lpass_audio_hw_vote);
+		}
+
 		lpi_dev_up = true;
 		snd_event_notify(lpi_dev, SND_EVENT_UP);
 		break;
@@ -870,7 +883,7 @@
 	}
 
 	mutex_lock(&state->core_hw_vote_lock);
-	ret = clk_prepare_enable(hw_vote);
+	ret = digital_cdc_rsc_mgr_hw_vote_enable(hw_vote);
 	if (ret < 0) {
 		pm_runtime_set_autosuspend_delay(dev,
 						 LPI_AUTO_SUSPEND_DELAY_ERROR);
@@ -906,7 +919,7 @@
 
 	mutex_lock(&state->core_hw_vote_lock);
 	if (state->core_hw_vote_status) {
-		clk_disable_unprepare(hw_vote);
+		digital_cdc_rsc_mgr_hw_vote_disable(hw_vote);
 		state->core_hw_vote_status = false;
 	}
 	mutex_unlock(&state->core_hw_vote_lock);
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index 4aa5c0c..6358437 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -22,6 +22,7 @@
 #include <soc/swr-common.h>
 #include <linux/regmap.h>
 #include <dsp/msm-audio-event-notify.h>
+#include <dsp/digital-cdc-rsc-mgr.h>
 #include "swrm_registers.h"
 #include "swr-mstr-ctrl.h"
 
@@ -378,8 +379,8 @@
 				}
 				if (++swrm->hw_core_clk_en == 1) {
 					ret =
-					   clk_prepare_enable(
-						swrm->lpass_core_hw_vote);
+					   digital_cdc_rsc_mgr_hw_vote_enable(
+							swrm->lpass_core_hw_vote);
 					if (ret < 0) {
 						dev_err(swrm->dev,
 							"%s:lpass core hw enable failed\n",
@@ -392,8 +393,8 @@
 				if (swrm->hw_core_clk_en < 0)
 					swrm->hw_core_clk_en = 0;
 				else if (swrm->hw_core_clk_en == 0)
-					clk_disable_unprepare(
-						swrm->lpass_core_hw_vote);
+					digital_cdc_rsc_mgr_hw_vote_disable(
+							swrm->lpass_core_hw_vote);
 			}
 		}
 	}
@@ -410,8 +411,8 @@
 				}
 				if (++swrm->aud_core_clk_en == 1) {
 					ret =
-					   clk_prepare_enable(
-						swrm->lpass_core_audio);
+					   digital_cdc_rsc_mgr_hw_vote_enable(
+							swrm->lpass_core_audio);
 					if (ret < 0) {
 						dev_err(swrm->dev,
 							"%s:lpass audio hw enable failed\n",
@@ -424,8 +425,8 @@
 				if (swrm->aud_core_clk_en < 0)
 					swrm->aud_core_clk_en = 0;
 				else if (swrm->aud_core_clk_en == 0)
-					clk_disable_unprepare(
-						swrm->lpass_core_audio);
+					digital_cdc_rsc_mgr_hw_vote_disable(
+							swrm->lpass_core_audio);
 			}
 		}
 	}
@@ -615,10 +616,10 @@
 		for (i = 0; i < length; i++) {
 		/* wait for FIFO WR command to complete to avoid overflow */
 		/*
-		 * Reduce sleep from 100us to 10us to meet KPIs
+		 * Reduce sleep from 100us to 50us to meet KPIs
 		 * This still meets the hardware spec
 		 */
-			usleep_range(10, 12);
+			usleep_range(50, 55);
 			swr_master_write(swrm, reg_addr[i], val[i]);
 		}
 		mutex_unlock(&swrm->iolock);
@@ -1340,9 +1341,9 @@
 	dev_dbg(swrm->dev, "%s: enter bank: %d master_ports: %d\n",
 		__func__, bank, master->num_port);
 
-
-	swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00,
-			SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank));
+	if (!swrm->disable_div2_clk_switch)
+		swrm_cmd_fifo_wr_cmd(swrm, 0x01, 0xF, 0x00,
+				SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(bank));
 
 	swrm_copy_data_port_config(master, bank);
 }
@@ -1908,7 +1909,6 @@
 		return IRQ_NONE;
 	}
 
-	mutex_lock(&swrm->ssr_lock);
 	mutex_lock(&swrm->reslock);
 	if (swrm_request_hw_vote(swrm, LPASS_HW_CORE, true)) {
 		ret = IRQ_NONE;
@@ -2025,6 +2025,11 @@
 			dev_err_ratelimited(swrm->dev,
 					"%s: SWR bus clsh detected\n",
 					__func__);
+			swrm->intr_mask &=
+				~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
+			swr_master_write(swrm,
+				SWR_MSTR_RX_SWRM_CPU_INTERRUPT_EN,
+				swrm->intr_mask);
 			break;
 		case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
 			dev_dbg(swrm->dev, "%s: SWR read FIFO overflow\n",
@@ -2122,7 +2127,6 @@
 	swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
 exit:
 	mutex_unlock(&swrm->reslock);
-	mutex_unlock(&swrm->ssr_lock);
 	swrm_unlock_sleep(swrm);
 	trace_printk("%s exit\n", __func__);
 	return ret;
@@ -2644,6 +2648,7 @@
 	swrm->state = SWR_MSTR_UP;
 	swrm->ipc_wakeup = false;
 	swrm->ipc_wakeup_triggered = false;
+	swrm->disable_div2_clk_switch = FALSE;
 	init_completion(&swrm->reset);
 	init_completion(&swrm->broadcast);
 	init_completion(&swrm->clk_off_complete);
@@ -2655,7 +2660,6 @@
 	mutex_init(&swrm->clklock);
 	mutex_init(&swrm->devlock);
 	mutex_init(&swrm->pm_lock);
-	mutex_init(&swrm->ssr_lock);
 	swrm->wlock_holders = 0;
 	swrm->pm_state = SWRM_PM_SLEEPABLE;
 	init_waitqueue_head(&swrm->pm_wq);
@@ -2666,6 +2670,12 @@
 	for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
 		INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
 
+	if (of_property_read_u32(pdev->dev.of_node,
+			"qcom,disable-div2-clk-switch",
+			&swrm->disable_div2_clk_switch)) {
+		swrm->disable_div2_clk_switch = FALSE;
+	}
+
 	/* Register LPASS core hw vote */
 	lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote");
 	if (IS_ERR(lpass_core_hw_vote)) {
@@ -2804,7 +2814,6 @@
 	mutex_destroy(&swrm->iolock);
 	mutex_destroy(&swrm->clklock);
 	mutex_destroy(&swrm->pm_lock);
-	mutex_destroy(&swrm->ssr_lock);
 	pm_qos_remove_request(&swrm->pm_qos_req);
 
 err_pdata_fail:
@@ -2838,7 +2847,6 @@
 	mutex_destroy(&swrm->clklock);
 	mutex_destroy(&swrm->force_down_lock);
 	mutex_destroy(&swrm->pm_lock);
-	mutex_destroy(&swrm->ssr_lock);
 	pm_qos_remove_request(&swrm->pm_qos_req);
 	devm_kfree(&pdev->dev, swrm);
 	return 0;
@@ -3325,7 +3333,6 @@
 		break;
 	case SWR_DEVICE_SSR_DOWN:
 		trace_printk("%s: swr device down called\n", __func__);
-		mutex_lock(&swrm->ssr_lock);
 		mutex_lock(&swrm->mlock);
 		if (swrm->state == SWR_MSTR_DOWN)
 			dev_dbg(swrm->dev, "%s:SWR master is already Down:%d\n",
@@ -3334,12 +3341,13 @@
 			swrm_device_down(&pdev->dev);
 		mutex_lock(&swrm->devlock);
 		swrm->dev_up = false;
+		swrm->hw_core_clk_en = 0;
+		swrm->aud_core_clk_en = 0;
 		mutex_unlock(&swrm->devlock);
 		mutex_lock(&swrm->reslock);
 		swrm->state = SWR_MSTR_SSR;
 		mutex_unlock(&swrm->reslock);
 		mutex_unlock(&swrm->mlock);
-		mutex_unlock(&swrm->ssr_lock);
 		break;
 	case SWR_DEVICE_SSR_UP:
 		/* wait for clk voting to be zero */
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index 0fac80e..ec5bbd2 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -126,7 +126,6 @@
 	struct mutex reslock;
 	struct mutex pm_lock;
 	struct mutex irq_lock;
-	struct mutex ssr_lock;
 	u32 swrm_base_reg;
 	char __iomem *swrm_dig_base;
 	char __iomem *swrm_hctl_reg;
@@ -181,6 +180,7 @@
 	int hw_core_clk_en;
 	int aud_core_clk_en;
 	int clk_src;
+	u32 disable_div2_clk_switch;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_swrm_dent;
 	struct dentry *debugfs_peek;