Merge "ASoC: rx-macro: Update rx droop based on sampling rate" into audio-drivers.lnx.4.0
diff --git a/Android.mk b/Android.mk
index feead01..cac7388 100644
--- a/Android.mk
+++ b/Android.mk
@@ -38,7 +38,7 @@
 endif
 endif
 
-ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET)),true)
+ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET) bengal),true)
 ifneq ($(TARGET_BOARD_AUTO),true)
 $(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/bolero/Module.symvers)
 include $(MY_LOCAL_PATH)/asoc/codecs/bolero/Android.mk
@@ -47,7 +47,7 @@
 endif
 endif
 
-ifeq ($(call is-board-platform-in-list, kona lito bengal),true)
+ifeq ($(call is-board-platform-in-list, kona lito),true)
 $(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/bolero/Module.symvers)
 include $(MY_LOCAL_PATH)/asoc/codecs/bolero/Android.mk
 $(shell rm -rf $(PRODUCT_OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/wcd938x/Module.symvers)
diff --git a/asoc/Android.mk b/asoc/Android.mk
index 4431f88..4ce1fa7 100644
--- a/asoc/Android.mk
+++ b/asoc/Android.mk
@@ -36,6 +36,11 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_LITO=m
 endif
 
+ifeq ($(call is-board-platform,bengal),true)
+TARGET := bengal
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
 ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) $(TRINKET) kona lito bengal sdmshrike),true)
diff --git a/asoc/Kbuild b/asoc/Kbuild
index 9e455a9..137fd60 100644
--- a/asoc/Kbuild
+++ b/asoc/Kbuild
@@ -51,9 +51,9 @@
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
+		include $(AUDIO_ROOT)/config/bengalauto.conf
 		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_SDMSHRIKE), y)
 		ifdef CONFIG_SND_SOC_SA8155
@@ -135,6 +135,11 @@
 	MACHINE_OBJS += kona.o
 endif
 
+# for BENGAL sound card driver
+ifdef CONFIG_SND_SOC_BENGAL
+	MACHINE_OBJS += bengal.o
+endif
+
 # for sa8155 sound card driver
 ifdef CONFIG_SND_SOC_SA8155
 	MACHINE_OBJS += sa8155.o
@@ -244,6 +249,9 @@
 obj-$(CONFIG_SND_SOC_LITO) += machine_dlkm.o
 machine_dlkm-y := $(MACHINE_OBJS)
 
+obj-$(CONFIG_SND_SOC_BENGAL) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
 obj-$(CONFIG_SND_SOC_SA8155) += machine_dlkm.o
 machine_dlkm-y := $(MACHINE_OBJS)
 
diff --git a/asoc/bengal-port-config.h b/asoc/bengal-port-config.h
new file mode 100644
index 0000000..4ac7e10
--- /dev/null
+++ b/asoc/bengal-port-config.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _BENGAL_PORT_CONFIG
+#define _BENGAL_PORT_CONFIG
+
+#include <soc/swr-common.h>
+
+/*
+ * Add port configuration in the format
+ *{ si, off1, off2, hstart, hstop, wd_len, bp_mode, bgp_ctrl, lane_ctrl}
+ */
+
+static struct port_params rx_frame_params_default[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1},
+	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0},
+	{31, 11, 11, 0xFF, 0xFF, 4,    1,    0xFF, 0},
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},
+	{0,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0,    0},
+};
+
+static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1},
+	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0},
+	{31, 11, 11, 0xFF, 0xFF, 4,    1,    0xFF, 0},
+	{7,  9,  0,  0xFF, 0xFF, 0xFF, 0xFF, 1,    0},
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 3,    0},
+};
+
+/* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */
+static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = {
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX1 */
+	{1,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1},  /* TX2 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0},  /* TX3 */
+};
+
+static struct swr_mstr_port_map sm_port_map[] = {
+	{VA_MACRO, SWR_UC0, tx_frame_params_default},
+	{RX_MACRO, SWR_UC0, rx_frame_params_default},
+	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
+};
+
+#endif /* _BENGAL_PORT_CONFIG */
diff --git a/asoc/bengal.c b/asoc/bengal.c
new file mode 100644
index 0000000..c500a17
--- /dev/null
+++ b/asoc/bengal.c
@@ -0,0 +1,6629 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/of_device.h>
+#include <linux/soc/qcom/fsa4480-i2c.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <soc/snd_event.h>
+#include <dsp/audio_notifier.h>
+#include <soc/swr-common.h>
+#include <dsp/q6afe-v2.h>
+#include <dsp/q6core.h>
+#include "device_event.h"
+#include "msm-pcm-routing-v2.h"
+#include "asoc/msm-cdc-pinctrl.h"
+#include "asoc/wcd-mbhc-v2.h"
+#include "codecs/wcd937x/wcd937x-mbhc.h"
+#include "codecs/wsa881x-analog.h"
+#include "codecs/wcd937x/wcd937x.h"
+#include "codecs/bolero/bolero-cdc.h"
+#include <dt-bindings/sound/audio-codec-port-types.h>
+#include "bengal-port-config.h"
+
+#define DRV_NAME "bengal-asoc-snd"
+#define __CHIPSET__ "BENGAL "
+#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
+
+#define SAMPLING_RATE_8KHZ      8000
+#define SAMPLING_RATE_11P025KHZ 11025
+#define SAMPLING_RATE_16KHZ     16000
+#define SAMPLING_RATE_22P05KHZ  22050
+#define SAMPLING_RATE_32KHZ     32000
+#define SAMPLING_RATE_44P1KHZ   44100
+#define SAMPLING_RATE_48KHZ     48000
+#define SAMPLING_RATE_88P2KHZ   88200
+#define SAMPLING_RATE_96KHZ     96000
+#define SAMPLING_RATE_176P4KHZ  176400
+#define SAMPLING_RATE_192KHZ    192000
+#define SAMPLING_RATE_352P8KHZ  352800
+#define SAMPLING_RATE_384KHZ    384000
+
+#define WCD9XXX_MBHC_DEF_RLOADS     5
+#define WCD9XXX_MBHC_DEF_BUTTONS    8
+#define CODEC_EXT_CLK_RATE          9600000
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+#define DEV_NAME_STR_LEN            32
+#define WCD_MBHC_HS_V_MAX           1600
+
+#define TDM_CHANNEL_MAX		8
+#define DEV_NAME_STR_LEN	32
+
+/* time in us to ensure LPM doesn't go in C3/C4 */
+#define MSM_LL_QOS_VALUE	300
+
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+
+#define WCN_CDC_SLIM_RX_CH_MAX 2
+#define WCN_CDC_SLIM_TX_CH_MAX 3
+
+enum {
+	TDM_0 = 0,
+	TDM_1,
+	TDM_2,
+	TDM_3,
+	TDM_4,
+	TDM_5,
+	TDM_6,
+	TDM_7,
+	TDM_PORT_MAX,
+};
+
+enum {
+	TDM_PRI = 0,
+	TDM_SEC,
+	TDM_TERT,
+	TDM_QUAT,
+	TDM_INTERFACE_MAX,
+};
+
+enum {
+	PRIM_AUX_PCM = 0,
+	SEC_AUX_PCM,
+	TERT_AUX_PCM,
+	QUAT_AUX_PCM,
+	AUX_PCM_MAX,
+};
+
+enum {
+	PRIM_MI2S = 0,
+	SEC_MI2S,
+	TERT_MI2S,
+	QUAT_MI2S,
+	MI2S_MAX,
+};
+
+enum {
+	RX_CDC_DMA_RX_0 = 0,
+	RX_CDC_DMA_RX_1,
+	RX_CDC_DMA_RX_2,
+	RX_CDC_DMA_RX_3,
+	RX_CDC_DMA_RX_5,
+	CDC_DMA_RX_MAX,
+};
+
+enum {
+	TX_CDC_DMA_TX_0 = 0,
+	TX_CDC_DMA_TX_3,
+	TX_CDC_DMA_TX_4,
+	VA_CDC_DMA_TX_0,
+	VA_CDC_DMA_TX_1,
+	VA_CDC_DMA_TX_2,
+	CDC_DMA_TX_MAX,
+};
+
+enum {
+	SLIM_RX_7 = 0,
+	SLIM_RX_MAX,
+};
+
+enum {
+	SLIM_TX_7 = 0,
+	SLIM_TX_8,
+	SLIM_TX_MAX,
+};
+
+enum {
+	AFE_LOOPBACK_TX_IDX = 0,
+	AFE_LOOPBACK_TX_IDX_MAX,
+};
+struct msm_asoc_mach_data {
+	struct snd_info_entry *codec_root;
+	int usbc_en2_gpio; /* used by gpio driver API */
+	struct device_node *dmic01_gpio_p; /* used by pinctrl API */
+	struct device_node *dmic23_gpio_p; /* used by pinctrl API */
+	struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
+	atomic_t mi2s_gpio_ref_count[MI2S_MAX]; /* used by pinctrl API */
+	struct device_node *us_euro_gpio_p; /* used by pinctrl API */
+	struct pinctrl *usbc_en2_gpio_p; /* used by pinctrl API */
+	struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
+	struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
+	bool is_afe_config_done;
+	struct device_node *fsa_handle;
+};
+
+struct tdm_port {
+	u32 mode;
+	u32 channel;
+};
+
+enum {
+	EXT_DISP_RX_IDX_DP = 0,
+	EXT_DISP_RX_IDX_DP1,
+	EXT_DISP_RX_IDX_MAX,
+};
+
+struct msm_wsa881x_dev_info {
+	struct device_node *of_node;
+	u32 index;
+};
+
+struct aux_codec_dev_info {
+	struct device_node *of_node;
+	u32 index;
+};
+
+struct dev_config {
+	u32 sample_rate;
+	u32 bit_format;
+	u32 channels;
+};
+
+/* Default configuration of slimbus channels */
+static struct dev_config slim_rx_cfg[] = {
+	[SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct dev_config slim_tx_cfg[] = {
+	[SLIM_TX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+static struct dev_config usb_rx_cfg = {
+	.sample_rate = SAMPLING_RATE_48KHZ,
+	.bit_format = SNDRV_PCM_FORMAT_S16_LE,
+	.channels = 2,
+};
+
+static struct dev_config usb_tx_cfg = {
+	.sample_rate = SAMPLING_RATE_48KHZ,
+	.bit_format = SNDRV_PCM_FORMAT_S16_LE,
+	.channels = 1,
+};
+
+static struct dev_config proxy_rx_cfg = {
+	.sample_rate = SAMPLING_RATE_48KHZ,
+	.bit_format = SNDRV_PCM_FORMAT_S16_LE,
+	.channels = 2,
+};
+
+static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+};
+
+struct mi2s_conf {
+	struct mutex lock;
+	u32 ref_cnt;
+	u32 msm_is_mi2s_master;
+};
+
+static u32 mi2s_ebit_clk[MI2S_MAX] = {
+	Q6AFE_LPASS_CLK_ID_PRI_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_SEC_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT,
+};
+
+static struct mi2s_conf mi2s_intf_conf[MI2S_MAX];
+
+/* Default configuration of TDM channels */
+static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
+	{ /* PRI TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+	{ /* SEC TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+	{ /* TERT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+	{ /* QUAT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+};
+
+static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
+	{ /* PRI TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+	{ /* SEC TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+	{ /* TERT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+	{ /* QUAT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+};
+
+/* Default configuration of AUX PCM channels */
+static struct dev_config aux_pcm_rx_cfg[] = {
+	[PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEC_AUX_PCM]  = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct dev_config aux_pcm_tx_cfg[] = {
+	[PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEC_AUX_PCM]  = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+/* Default configuration of MI2S channels */
+static struct dev_config mi2s_rx_cfg[] = {
+	[PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[SEC_MI2S]  = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+static struct dev_config mi2s_tx_cfg[] = {
+	[PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEC_MI2S]  = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+/* Default configuration of Codec DMA Interface RX */
+static struct dev_config cdc_dma_rx_cfg[] = {
+	[RX_CDC_DMA_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+/* Default configuration of Codec DMA Interface TX */
+static struct dev_config cdc_dma_tx_cfg[] = {
+	[TX_CDC_DMA_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[TX_CDC_DMA_TX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[TX_CDC_DMA_TX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[VA_CDC_DMA_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 8},
+	[VA_CDC_DMA_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 8},
+	[VA_CDC_DMA_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 8},
+};
+
+static struct dev_config afe_loopback_tx_cfg[] = {
+	[AFE_LOOPBACK_TX_IDX] = {
+			SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static int msm_vi_feed_tx_ch = 2;
+static const char *const vi_feed_ch_text[] = {"One", "Two"};
+static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
+					  "S32_LE"};
+static char const *ch_text[] = {"Two", "Three", "Four", "Five",
+					"Six", "Seven", "Eight"};
+static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
+					"KHZ_16", "KHZ_22P05",
+					"KHZ_32", "KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96", "KHZ_176P4",
+					"KHZ_192", "KHZ_352P8", "KHZ_384"};
+static const char *const usb_ch_text[] = {"One", "Two", "Three", "Four",
+					   "Five", "Six", "Seven",
+					   "Eight"};
+static char const *tdm_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32",
+					     "KHZ_48", "KHZ_176P4",
+					     "KHZ_352P8"};
+static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
+static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
+				    "Five", "Six", "Seven", "Eight"};
+static const char *const auxpcm_rate_text[] = {"KHZ_8", "KHZ_16"};
+static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_11P025", "KHZ_16",
+				      "KHZ_22P05", "KHZ_32", "KHZ_44P1",
+				      "KHZ_48", "KHZ_96", "KHZ_192"};
+static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
+					   "Five", "Six", "Seven",
+					   "Eight"};
+
+static const char *const cdc_dma_rx_ch_text[] = {"One", "Two"};
+static const char *const cdc_dma_tx_ch_text[] = {"One", "Two", "Three", "Four",
+						"Five", "Six", "Seven",
+						"Eight"};
+static char const *cdc_dma_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
+						 "KHZ_16", "KHZ_22P05",
+						 "KHZ_32", "KHZ_44P1", "KHZ_48",
+						 "KHZ_88P2", "KHZ_96",
+						 "KHZ_176P4", "KHZ_192",
+						 "KHZ_352P8", "KHZ_384"};
+static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static char const *bt_sample_rate_rx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static char const *bt_sample_rate_tx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static const char *const afe_loopback_tx_ch_text[] = {"One", "Two"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_sample_rate, tdm_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_sample_rate, tdm_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_format, tdm_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_format, tdm_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_chs, tdm_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_chs, tdm_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_0_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_1_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_2_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_3_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_5_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_0_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_3_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_0_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_1_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_2_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_0_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_1_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_2_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_3_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_5_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_0_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_3_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_0_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_1_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_2_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_0_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_1_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_2_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_3_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_5_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_0_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_3_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_0_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_1_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_2_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_rx, bt_sample_rate_rx_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_tx, bt_sample_rate_tx_text);
+static SOC_ENUM_SINGLE_EXT_DECL(afe_loopback_tx_chs, afe_loopback_tx_ch_text);
+
+static bool is_initial_boot;
+static bool codec_reg_done;
+static struct snd_soc_aux_dev *msm_aux_dev;
+static struct snd_soc_codec_conf *msm_codec_conf;
+static struct snd_soc_card snd_soc_card_bengal_msm;
+static int dmic_0_1_gpio_cnt;
+static int dmic_2_3_gpio_cnt;
+
+static void *def_wcd_mbhc_cal(void);
+
+/*
+ * Need to report LINEIN
+ * if R/L channel impedance is larger than 5K ohm
+ */
+static struct wcd_mbhc_config wcd_mbhc_cfg = {
+	.read_fw_bin = false,
+	.calibration = NULL,
+	.detect_extn_cable = true,
+	.mono_stero_detection = false,
+	.swap_gnd_mic = NULL,
+	.hs_ext_micbias = true,
+	.key_code[0] = KEY_MEDIA,
+	.key_code[1] = KEY_VOICECOMMAND,
+	.key_code[2] = KEY_VOLUMEUP,
+	.key_code[3] = KEY_VOLUMEDOWN,
+	.key_code[4] = 0,
+	.key_code[5] = 0,
+	.key_code[6] = 0,
+	.key_code[7] = 0,
+	.linein_th = 5000,
+	.moisture_en = false,
+	.mbhc_micbias = MIC_BIAS_2,
+	.anc_micbias = MIC_BIAS_2,
+	.enable_anc_mic_detect = false,
+	.moisture_duty_cycle_en = true,
+};
+
+static inline int param_is_mask(int p)
+{
+	return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+			(p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p,
+					     int n)
+{
+	return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n,
+			   unsigned int bit)
+{
+	if (bit >= SNDRV_MASK_MAX)
+		return;
+	if (param_is_mask(n)) {
+		struct snd_mask *m = param_to_mask(p, n);
+
+		m->bits[0] = 0;
+		m->bits[1] = 0;
+		m->bits[bit >> 5] |= (1 << (bit & 31));
+	}
+}
+
+static int usb_audio_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val = 0;
+
+	switch (usb_rx_cfg.sample_rate) {
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		sample_rate_val = 0;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: usb_audio_rx_sample_rate = %d\n", __func__,
+		 usb_rx_cfg.sample_rate);
+	return 0;
+}
+
+static int usb_audio_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 12:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	case 11:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 10:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 9:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 8:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 7:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 6:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 5:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 4:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 2:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 1:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 0:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	default:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	pr_debug("%s: control value = %ld, usb_audio_rx_sample_rate = %d\n",
+		__func__, ucontrol->value.integer.value[0],
+		usb_rx_cfg.sample_rate);
+	return 0;
+}
+
+static int usb_audio_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val = 0;
+
+	switch (usb_tx_cfg.sample_rate) {
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: usb_audio_tx_sample_rate = %d\n", __func__,
+		 usb_tx_cfg.sample_rate);
+	return 0;
+}
+
+static int usb_audio_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 12:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	case 11:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 10:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 9:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 8:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 7:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 6:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 5:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 4:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 2:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 1:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 0:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	default:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	pr_debug("%s: control value = %ld, usb_audio_tx_sample_rate = %d\n",
+		__func__, ucontrol->value.integer.value[0],
+		usb_tx_cfg.sample_rate);
+	return 0;
+}
+static int afe_loopback_tx_ch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: afe_loopback_tx_ch  = %d\n", __func__,
+		afe_loopback_tx_cfg[0].channels);
+	ucontrol->value.enumerated.item[0] =
+		afe_loopback_tx_cfg[0].channels - 1;
+
+	return 0;
+}
+
+static int afe_loopback_tx_ch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	afe_loopback_tx_cfg[0].channels =
+			ucontrol->value.enumerated.item[0] + 1;
+	pr_debug("%s: afe_loopback_tx_ch  = %d\n", __func__,
+			afe_loopback_tx_cfg[0].channels);
+
+	return 1;
+}
+
+static int usb_audio_rx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	switch (usb_rx_cfg.bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: usb_audio_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_rx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int usb_audio_rx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: usb_audio_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_rx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+static int usb_audio_tx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	switch (usb_tx_cfg.bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: usb_audio_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_tx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: usb_audio_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_tx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+static int usb_audio_rx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: usb_audio_rx_ch  = %d\n", __func__,
+		 usb_rx_cfg.channels);
+	ucontrol->value.integer.value[0] = usb_rx_cfg.channels - 1;
+	return 0;
+}
+
+static int usb_audio_rx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	usb_rx_cfg.channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: usb_audio_rx_ch = %d\n", __func__, usb_rx_cfg.channels);
+	return 1;
+}
+
+static int usb_audio_tx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: usb_audio_tx_ch  = %d\n", __func__,
+		 usb_tx_cfg.channels);
+	ucontrol->value.integer.value[0] = usb_tx_cfg.channels - 1;
+	return 0;
+}
+
+static int usb_audio_tx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	usb_tx_cfg.channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: usb_audio_tx_ch = %d\n", __func__, usb_tx_cfg.channels);
+	return 1;
+}
+
+static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
+	pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
+	pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
+	return 1;
+}
+
+static int proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: proxy_rx channels = %d\n",
+		 __func__, proxy_rx_cfg.channels);
+	ucontrol->value.integer.value[0] = proxy_rx_cfg.channels - 2;
+
+	return 0;
+}
+
+static int proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	proxy_rx_cfg.channels = ucontrol->value.integer.value[0] + 2;
+	pr_debug("%s: proxy_rx channels = %d\n",
+		 __func__, proxy_rx_cfg.channels);
+
+	return 1;
+}
+
+static int tdm_get_port_idx(struct snd_kcontrol *kcontrol,
+			    struct tdm_port *port)
+{
+	if (port) {
+		if (strnstr(kcontrol->id.name, "PRI",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_PRI;
+		} else if (strnstr(kcontrol->id.name, "SEC",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_SEC;
+		} else if (strnstr(kcontrol->id.name, "TERT",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_TERT;
+		} else if (strnstr(kcontrol->id.name, "QUAT",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_QUAT;
+		} else {
+			pr_err("%s: unsupported mode in: %s\n",
+				__func__, kcontrol->id.name);
+			return -EINVAL;
+		}
+
+		if (strnstr(kcontrol->id.name, "RX_0",
+		    sizeof(kcontrol->id.name)) ||
+		    strnstr(kcontrol->id.name, "TX_0",
+		    sizeof(kcontrol->id.name))) {
+			port->channel = TDM_0;
+		} else if (strnstr(kcontrol->id.name, "RX_1",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_1",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_1;
+		} else if (strnstr(kcontrol->id.name, "RX_2",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_2",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_2;
+		} else if (strnstr(kcontrol->id.name, "RX_3",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_3",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_3;
+		} else if (strnstr(kcontrol->id.name, "RX_4",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_4",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_4;
+		} else if (strnstr(kcontrol->id.name, "RX_5",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_5",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_5;
+		} else if (strnstr(kcontrol->id.name, "RX_6",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_6",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_6;
+		} else if (strnstr(kcontrol->id.name, "RX_7",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_7",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_7;
+		} else {
+			pr_err("%s: unsupported channel in: %s\n",
+				__func__, kcontrol->id.name);
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tdm_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 0:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	case 1:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 5:
+		sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	default:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int tdm_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 5;
+		break;
+	default:
+		sample_rate_val = 3;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int tdm_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_sample_rate_val(
+			tdm_rx_cfg[port.mode][port.channel].sample_rate);
+
+		pr_debug("%s: tdm_rx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_rx_cfg[port.mode][port.channel].sample_rate =
+			tdm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_rx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_sample_rate_val(
+			tdm_tx_cfg[port.mode][port.channel].sample_rate);
+
+		pr_debug("%s: tdm_tx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_tx_cfg[port.mode][port.channel].sample_rate =
+			tdm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_tx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_get_format(int value)
+{
+	int format = 0;
+
+	switch (value) {
+	case 0:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	case 1:
+		format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 2:
+		format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	default:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	return format;
+}
+
+static int tdm_get_format_val(int format)
+{
+	int value = 0;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		value = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		value = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		value = 2;
+		break;
+	default:
+		value = 0;
+		break;
+	}
+	return value;
+}
+
+static int tdm_rx_format_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_format_val(
+				tdm_rx_cfg[port.mode][port.channel].bit_format);
+
+		pr_debug("%s: tdm_rx_bit_format = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_format_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_rx_cfg[port.mode][port.channel].bit_format =
+			tdm_get_format(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_rx_bit_format = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_format_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_format_val(
+				tdm_tx_cfg[port.mode][port.channel].bit_format);
+
+		pr_debug("%s: tdm_tx_bit_format = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_format_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_tx_cfg[port.mode][port.channel].bit_format =
+			tdm_get_format(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_tx_bit_format = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_ch_get(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+
+		ucontrol->value.enumerated.item[0] =
+			tdm_rx_cfg[port.mode][port.channel].channels - 1;
+
+		pr_debug("%s: tdm_rx_ch = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].channels - 1,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_ch_put(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_rx_cfg[port.mode][port.channel].channels =
+			ucontrol->value.enumerated.item[0] + 1;
+
+		pr_debug("%s: tdm_rx_ch = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].channels,
+			 ucontrol->value.enumerated.item[0] + 1);
+	}
+	return ret;
+}
+
+static int tdm_tx_ch_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] =
+			tdm_tx_cfg[port.mode][port.channel].channels - 1;
+
+		pr_debug("%s: tdm_tx_ch = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].channels - 1,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_tx_cfg[port.mode][port.channel].channels =
+			ucontrol->value.enumerated.item[0] + 1;
+
+		pr_debug("%s: tdm_tx_ch = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].channels,
+			 ucontrol->value.enumerated.item[0] + 1);
+	}
+	return ret;
+}
+
+static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+	int idx = 0;
+
+	if (strnstr(kcontrol->id.name, "PRIM_AUX_PCM",
+		    sizeof("PRIM_AUX_PCM"))) {
+		idx = PRIM_AUX_PCM;
+	} else if (strnstr(kcontrol->id.name, "SEC_AUX_PCM",
+			 sizeof("SEC_AUX_PCM"))) {
+		idx = SEC_AUX_PCM;
+	} else if (strnstr(kcontrol->id.name, "TERT_AUX_PCM",
+			 sizeof("TERT_AUX_PCM"))) {
+		idx = TERT_AUX_PCM;
+	} else if (strnstr(kcontrol->id.name, "QUAT_AUX_PCM",
+			 sizeof("QUAT_AUX_PCM"))) {
+		idx = QUAT_AUX_PCM;
+	} else {
+		pr_err("%s: unsupported port: %s\n",
+			__func__, kcontrol->id.name);
+		idx = -EINVAL;
+	}
+
+	return idx;
+}
+
+static int aux_pcm_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 1:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 0:
+	default:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int aux_pcm_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		sample_rate_val = 0;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int mi2s_auxpcm_get_format(int value)
+{
+	int format = 0;
+
+	switch (value) {
+	case 0:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	case 1:
+		format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 2:
+		format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 3:
+		format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	default:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	return format;
+}
+
+static int mi2s_auxpcm_get_format_value(int format)
+{
+	int value = 0;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		value = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		value = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		value = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		value = 3;
+		break;
+	default:
+		value = 0;
+		break;
+	}
+	return value;
+}
+
+static int aux_pcm_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+	     aux_pcm_get_sample_rate_val(aux_pcm_rx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int aux_pcm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_rx_cfg[idx].sample_rate =
+		aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int aux_pcm_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+	     aux_pcm_get_sample_rate_val(aux_pcm_tx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int aux_pcm_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_tx_cfg[idx].sample_rate =
+		aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_rx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(aux_pcm_rx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		idx, aux_pcm_rx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_rx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_rx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		  idx, aux_pcm_rx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_tx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(aux_pcm_tx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		idx, aux_pcm_tx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_tx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_tx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		  idx, aux_pcm_tx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+	int idx = 0;
+
+	if (strnstr(kcontrol->id.name, "PRIM_MI2S_RX",
+	    sizeof("PRIM_MI2S_RX"))) {
+		idx = PRIM_MI2S;
+	} else if (strnstr(kcontrol->id.name, "SEC_MI2S_RX",
+		 sizeof("SEC_MI2S_RX"))) {
+		idx = SEC_MI2S;
+	} else if (strnstr(kcontrol->id.name, "TERT_MI2S_RX",
+		 sizeof("TERT_MI2S_RX"))) {
+		idx = TERT_MI2S;
+	} else if (strnstr(kcontrol->id.name, "QUAT_MI2S_RX",
+		 sizeof("QUAT_MI2S_RX"))) {
+		idx = QUAT_MI2S;
+	} else if (strnstr(kcontrol->id.name, "PRIM_MI2S_TX",
+		 sizeof("PRIM_MI2S_TX"))) {
+		idx = PRIM_MI2S;
+	} else if (strnstr(kcontrol->id.name, "SEC_MI2S_TX",
+		 sizeof("SEC_MI2S_TX"))) {
+		idx = SEC_MI2S;
+	} else if (strnstr(kcontrol->id.name, "TERT_MI2S_TX",
+		 sizeof("TERT_MI2S_TX"))) {
+		idx = TERT_MI2S;
+	} else if (strnstr(kcontrol->id.name, "QUAT_MI2S_TX",
+		 sizeof("QUAT_MI2S_TX"))) {
+		idx = QUAT_MI2S;
+	} else {
+		pr_err("%s: unsupported channel: %s\n",
+			__func__, kcontrol->id.name);
+		idx = -EINVAL;
+	}
+
+	return idx;
+}
+
+static int mi2s_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 0:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	case 1:
+		sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 2:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 3:
+		sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 4:
+		sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 5:
+		sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 6:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 7:
+		sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 8:
+		sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	default:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int mi2s_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 8;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int mi2s_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_get_sample_rate_val(mi2s_rx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_rx_cfg[idx].sample_rate =
+		mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_get_sample_rate_val(mi2s_tx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_tx_cfg[idx].sample_rate =
+		mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_rx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(mi2s_rx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		idx, mi2s_rx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_rx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_rx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		  idx, mi2s_rx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_tx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(mi2s_tx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		idx, mi2s_tx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_tx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_tx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		  idx, mi2s_tx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+static int msm_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	pr_debug("%s: msm_mi2s_[%d]_rx_ch  = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].channels);
+	ucontrol->value.enumerated.item[0] = mi2s_rx_cfg[idx].channels - 1;
+
+	return 0;
+}
+
+static int msm_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_rx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1;
+	pr_debug("%s: msm_mi2s_[%d]_rx_ch  = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].channels);
+
+	return 1;
+}
+
+static int msm_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	pr_debug("%s: msm_mi2s_[%d]_tx_ch  = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].channels);
+	ucontrol->value.enumerated.item[0] = mi2s_tx_cfg[idx].channels - 1;
+
+	return 0;
+}
+
+static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_tx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1;
+	pr_debug("%s: msm_mi2s_[%d]_tx_ch  = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].channels);
+
+	return 1;
+}
+
+static int msm_get_port_id(int be_id)
+{
+	int afe_port_id = 0;
+
+	switch (be_id) {
+	case MSM_BACKEND_DAI_PRI_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_PRI_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+		afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_0;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+		afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_1;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_2;
+		break;
+	default:
+		pr_err("%s: Invalid BE id: %d\n", __func__, be_id);
+		afe_port_id = -EINVAL;
+	}
+
+	return afe_port_id;
+}
+
+static u32 get_mi2s_bits_per_sample(u32 bit_format)
+{
+	u32 bit_per_sample = 0;
+
+	switch (bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+	case SNDRV_PCM_FORMAT_S24_3LE:
+	case SNDRV_PCM_FORMAT_S24_LE:
+		bit_per_sample = 32;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		bit_per_sample = 16;
+		break;
+	}
+
+	return bit_per_sample;
+}
+
+static void update_mi2s_clk_val(int dai_id, int stream)
+{
+	u32 bit_per_sample = 0;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		bit_per_sample =
+		    get_mi2s_bits_per_sample(mi2s_rx_cfg[dai_id].bit_format);
+		mi2s_clk[dai_id].clk_freq_in_hz =
+		    mi2s_rx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
+	} else {
+		bit_per_sample =
+		    get_mi2s_bits_per_sample(mi2s_tx_cfg[dai_id].bit_format);
+		mi2s_clk[dai_id].clk_freq_in_hz =
+		    mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
+	}
+}
+
+static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int port_id = 0;
+	int index = cpu_dai->id;
+
+	port_id = msm_get_port_id(rtd->dai_link->id);
+	if (port_id < 0) {
+		dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
+		ret = port_id;
+		goto err;
+	}
+
+	if (enable) {
+		update_mi2s_clk_val(index, substream->stream);
+		dev_dbg(rtd->card->dev, "%s: clock rate %ul\n", __func__,
+			mi2s_clk[index].clk_freq_in_hz);
+	}
+
+	mi2s_clk[index].enable = enable;
+	ret = afe_set_lpass_clock_v2(port_id,
+				     &mi2s_clk[index]);
+	if (ret < 0) {
+		dev_err(rtd->card->dev,
+			"%s: afe lpass clock failed for port 0x%x , err:%d\n",
+			__func__, port_id, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int cdc_dma_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+	int idx = 0;
+
+	if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_0",
+		sizeof("RX_CDC_DMA_RX_0")))
+		idx = RX_CDC_DMA_RX_0;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_1",
+		sizeof("RX_CDC_DMA_RX_1")))
+		idx = RX_CDC_DMA_RX_1;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_2",
+		sizeof("RX_CDC_DMA_RX_2")))
+		idx = RX_CDC_DMA_RX_2;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_3",
+		sizeof("RX_CDC_DMA_RX_3")))
+		idx = RX_CDC_DMA_RX_3;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_5",
+		sizeof("RX_CDC_DMA_RX_5")))
+		idx = RX_CDC_DMA_RX_5;
+	else if (strnstr(kcontrol->id.name, "TX_CDC_DMA_TX_0",
+		sizeof("TX_CDC_DMA_TX_0")))
+		idx = TX_CDC_DMA_TX_0;
+	else if (strnstr(kcontrol->id.name, "TX_CDC_DMA_TX_3",
+		sizeof("TX_CDC_DMA_TX_3")))
+		idx = TX_CDC_DMA_TX_3;
+	else if (strnstr(kcontrol->id.name, "TX_CDC_DMA_TX_4",
+		sizeof("TX_CDC_DMA_TX_4")))
+		idx = TX_CDC_DMA_TX_4;
+	else if (strnstr(kcontrol->id.name, "VA_CDC_DMA_TX_0",
+		sizeof("VA_CDC_DMA_TX_0")))
+		idx = VA_CDC_DMA_TX_0;
+	else if (strnstr(kcontrol->id.name, "VA_CDC_DMA_TX_1",
+		sizeof("VA_CDC_DMA_TX_1")))
+		idx = VA_CDC_DMA_TX_1;
+	else if (strnstr(kcontrol->id.name, "VA_CDC_DMA_TX_2",
+		sizeof("VA_CDC_DMA_TX_2")))
+		idx = VA_CDC_DMA_TX_2;
+	else {
+		pr_err("%s: unsupported channel: %s\n",
+			__func__, kcontrol->id.name);
+		return -EINVAL;
+	}
+
+	return idx;
+}
+
+static int cdc_dma_rx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	pr_debug("%s: cdc_dma_rx_ch  = %d\n", __func__,
+		 cdc_dma_rx_cfg[ch_num].channels - 1);
+	ucontrol->value.integer.value[0] = cdc_dma_rx_cfg[ch_num].channels - 1;
+	return 0;
+}
+
+static int cdc_dma_rx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	cdc_dma_rx_cfg[ch_num].channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: cdc_dma_rx_ch = %d\n", __func__,
+		cdc_dma_rx_cfg[ch_num].channels);
+	return 1;
+}
+
+static int cdc_dma_rx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (cdc_dma_rx_cfg[ch_num].bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: cdc_dma_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_rx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int cdc_dma_rx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: cdc_dma_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_rx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+
+static int cdc_dma_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int cdc_dma_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 0:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	case 1:
+		sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 2:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 3:
+		sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 4:
+		sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 5:
+		sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 6:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 7:
+		sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 8:
+		sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 9:
+		sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 10:
+		sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 11:
+		sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 12:
+		sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	default:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int cdc_dma_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	ucontrol->value.enumerated.item[0] =
+		cdc_dma_get_sample_rate_val(cdc_dma_rx_cfg[ch_num].sample_rate);
+
+	pr_debug("%s: cdc_dma_rx_sample_rate = %d\n", __func__,
+		 cdc_dma_rx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	cdc_dma_rx_cfg[ch_num].sample_rate =
+		cdc_dma_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+
+	pr_debug("%s: control value = %d, cdc_dma_rx_sample_rate = %d\n",
+		__func__, ucontrol->value.enumerated.item[0],
+		cdc_dma_rx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_tx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	pr_debug("%s: cdc_dma_tx_ch  = %d\n", __func__,
+		 cdc_dma_tx_cfg[ch_num].channels);
+	ucontrol->value.integer.value[0] = cdc_dma_tx_cfg[ch_num].channels - 1;
+	return 0;
+}
+
+static int cdc_dma_tx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	cdc_dma_tx_cfg[ch_num].channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: cdc_dma_tx_ch = %d\n", __func__,
+		cdc_dma_tx_cfg[ch_num].channels);
+	return 1;
+}
+
+static int cdc_dma_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val;
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (cdc_dma_tx_cfg[ch_num].sample_rate) {
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: cdc_dma_tx_sample_rate = %d\n", __func__,
+		 cdc_dma_tx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 12:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	case 11:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 10:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 9:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 8:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 7:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 6:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 5:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 4:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 2:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 1:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 0:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	default:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	pr_debug("%s: control value = %ld, cdc_dma_tx_sample_rate = %d\n",
+		__func__, ucontrol->value.integer.value[0],
+		cdc_dma_tx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_tx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (cdc_dma_tx_cfg[ch_num].bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: cdc_dma_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_tx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int cdc_dma_tx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: cdc_dma_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_tx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+static int msm_cdc_dma_get_idx_from_beid(int32_t be_id)
+{
+	int idx = 0;
+
+	switch (be_id) {
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0:
+		idx = RX_CDC_DMA_RX_0;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1:
+		idx = RX_CDC_DMA_RX_1;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2:
+		idx = RX_CDC_DMA_RX_2;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3:
+		idx = RX_CDC_DMA_RX_3;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5:
+		idx = RX_CDC_DMA_RX_5;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0:
+		idx = TX_CDC_DMA_TX_0;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3:
+		idx = TX_CDC_DMA_TX_3;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4:
+		idx = TX_CDC_DMA_TX_4;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+		idx = VA_CDC_DMA_TX_0;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+		idx = VA_CDC_DMA_TX_1;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		idx = VA_CDC_DMA_TX_2;
+		break;
+	default:
+		idx = RX_CDC_DMA_RX_0;
+		break;
+	}
+
+	return idx;
+}
+
+static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	/*
+	 * Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
+	 * when used for BT_SCO use case. Return either Rx or Tx sample rate
+	 * value.
+	 */
+	switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate = %d\n", __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rates: slim7_rx = %d, slim7_tx = %d, value = %d\n",
+		 __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_rx_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate rx = %d\n", __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_rx_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rate: slim7_rx = %d, value = %d\n",
+		 __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (slim_tx_cfg[SLIM_TX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate tx = %d\n", __func__,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rate: slim7_tx = %d, value = %d\n",
+		 __func__,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new msm_int_snd_controls[] = {
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 Channels", rx_cdc_dma_rx_0_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 Channels", rx_cdc_dma_rx_1_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 Channels", rx_cdc_dma_rx_2_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 Channels", rx_cdc_dma_rx_3_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 Channels", rx_cdc_dma_rx_5_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_0 Channels", tx_cdc_dma_tx_0_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_3 Channels", tx_cdc_dma_tx_3_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_4 Channels", tx_cdc_dma_tx_4_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_0 Channels", va_cdc_dma_tx_0_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_1 Channels", va_cdc_dma_tx_1_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_2 Channels", va_cdc_dma_tx_2_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 Format", rx_cdc_dma_rx_0_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 Format", rx_cdc_dma_rx_1_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 Format", rx_cdc_dma_rx_2_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 Format", rx_cdc_dma_rx_3_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 Format", rx_cdc_dma_rx_5_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_0 Format", tx_cdc_dma_tx_0_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_3 Format", tx_cdc_dma_tx_3_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_4 Format", tx_cdc_dma_tx_4_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_0 Format", va_cdc_dma_tx_0_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_1 Format", va_cdc_dma_tx_1_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_2 Format", va_cdc_dma_tx_2_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 SampleRate",
+			rx_cdc_dma_rx_0_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 SampleRate",
+			rx_cdc_dma_rx_1_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 SampleRate",
+			rx_cdc_dma_rx_2_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 SampleRate",
+			rx_cdc_dma_rx_3_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 SampleRate",
+			rx_cdc_dma_rx_5_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_0 SampleRate",
+			tx_cdc_dma_tx_0_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_3 SampleRate",
+			tx_cdc_dma_tx_3_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_4 SampleRate",
+			tx_cdc_dma_tx_4_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_0 SampleRate",
+			va_cdc_dma_tx_0_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_1 SampleRate",
+			va_cdc_dma_tx_1_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_2 SampleRate",
+			va_cdc_dma_tx_2_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+};
+
+static const struct snd_kcontrol_new msm_common_snd_controls[] = {
+	SOC_ENUM_EXT("USB_AUDIO_RX SampleRate", usb_rx_sample_rate,
+			usb_audio_rx_sample_rate_get,
+			usb_audio_rx_sample_rate_put),
+	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("PRI_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("PRI_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+			tdm_tx_sample_rate_get,
+			tdm_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+			tdm_tx_sample_rate_get,
+			tdm_tx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+			tdm_tx_sample_rate_get,
+			tdm_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_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("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("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("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("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),
+	SOC_ENUM_EXT("SEC_TDM_RX_0 Format", tdm_rx_format,
+			tdm_rx_format_get,
+			tdm_rx_format_put),
+	SOC_ENUM_EXT("TERT_TDM_RX_0 Format", tdm_rx_format,
+			tdm_rx_format_get,
+			tdm_rx_format_put),
+	SOC_ENUM_EXT("QUAT_TDM_RX_0 Format", tdm_rx_format,
+			tdm_rx_format_get,
+			tdm_rx_format_put),
+	SOC_ENUM_EXT("PRI_TDM_TX_0 Format", tdm_tx_format,
+			tdm_tx_format_get,
+			tdm_tx_format_put),
+	SOC_ENUM_EXT("SEC_TDM_TX_0 Format", tdm_tx_format,
+			tdm_tx_format_get,
+			tdm_tx_format_put),
+	SOC_ENUM_EXT("TERT_TDM_TX_0 Format", tdm_tx_format,
+			tdm_tx_format_get,
+			tdm_tx_format_put),
+	SOC_ENUM_EXT("QUAT_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("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("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("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("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),
+	SOC_ENUM_EXT("SEC_TDM_RX_0 Channels", tdm_rx_chs,
+			tdm_rx_ch_get,
+			tdm_rx_ch_put),
+	SOC_ENUM_EXT("TERT_TDM_RX_0 Channels", tdm_rx_chs,
+			tdm_rx_ch_get,
+			tdm_rx_ch_put),
+	SOC_ENUM_EXT("QUAT_TDM_RX_0 Channels", tdm_rx_chs,
+			tdm_rx_ch_get,
+			tdm_rx_ch_put),
+	SOC_ENUM_EXT("PRI_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_put),
+	SOC_ENUM_EXT("SEC_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_put),
+	SOC_ENUM_EXT("TERT_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_put),
+	SOC_ENUM_EXT("QUAT_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_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,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("TERT_MI2S_RX Channels", tert_mi2s_rx_chs,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("QUAT_MI2S_RX Channels", quat_mi2s_rx_chs,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("PRIM_MI2S_TX Channels", prim_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("SEC_MI2S_TX Channels", sec_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("TERT_MI2S_TX Channels", tert_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("QUAT_MI2S_TX Channels", quat_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_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_snd_controls[] = {
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_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("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+};
+
+static int bengal_send_island_va_config(int32_t be_id)
+{
+	int rc = 0;
+	int port_id = 0xFFFF;
+
+	port_id = msm_get_port_id(be_id);
+	if (port_id < 0) {
+		pr_err("%s: Invalid island interface, be_id: %d\n",
+		       __func__, be_id);
+		rc = -EINVAL;
+	} else {
+		/*
+		 * send island mode config
+		 * This should be the first configuration
+		 */
+		rc = afe_send_port_island_mode(port_id);
+		if (rc)
+			pr_err("%s: afe send island mode failed %d\n",
+				__func__, rc);
+	}
+
+	return rc;
+}
+
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+	int idx = 0;
+
+	pr_debug("%s: format = %d, rate = %d\n",
+		  __func__, params_format(params), params_rate(params));
+
+	switch (dai_link->id) {
+	case MSM_BACKEND_DAI_USB_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				usb_rx_cfg.bit_format);
+		rate->min = rate->max = usb_rx_cfg.sample_rate;
+		channels->min = channels->max = usb_rx_cfg.channels;
+		break;
+
+	case MSM_BACKEND_DAI_USB_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				usb_tx_cfg.bit_format);
+		rate->min = rate->max = usb_tx_cfg.sample_rate;
+		channels->min = channels->max = usb_tx_cfg.channels;
+		break;
+
+	case MSM_BACKEND_DAI_AFE_PCM_RX:
+		channels->min = channels->max = proxy_rx_cfg.channels;
+		rate->min = rate->max = SAMPLING_RATE_48KHZ;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_PRI][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_PRI][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_PRI][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_PRI][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_PRI][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_PRI][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_SEC][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_SEC][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_SEC][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_SEC][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_SEC][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_SEC][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_TERT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_TERT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_TERT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_TERT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_TERT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_TERT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_QUAT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_QUAT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_QUAT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_QUAT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_QUAT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_QUAT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[PRIM_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[PRIM_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[PRIM_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[PRIM_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[PRIM_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[PRIM_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[SEC_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[SEC_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[SEC_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[SEC_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[SEC_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[SEC_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[TERT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[TERT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[TERT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[TERT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[TERT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[TERT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[QUAT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[QUAT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[QUAT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[QUAT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[QUAT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[QUAT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[PRIM_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[PRIM_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[PRIM_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[PRIM_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[PRIM_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[PRIM_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[SEC_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[SEC_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[SEC_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[SEC_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[SEC_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[SEC_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[TERT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[TERT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[TERT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[TERT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[TERT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[TERT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[QUAT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[QUAT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[QUAT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[QUAT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[QUAT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[QUAT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0:
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1:
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2:
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3:
+		idx = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				cdc_dma_rx_cfg[idx].bit_format);
+		rate->min = rate->max = cdc_dma_rx_cfg[idx].sample_rate;
+		channels->min = channels->max = cdc_dma_rx_cfg[idx].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0:
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3:
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		idx = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				cdc_dma_tx_cfg[idx].bit_format);
+		rate->min = rate->max = cdc_dma_tx_cfg[idx].sample_rate;
+		channels->min = channels->max = cdc_dma_tx_cfg[idx].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SLIMBUS_7_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				slim_rx_cfg[SLIM_RX_7].bit_format);
+		rate->min = rate->max = slim_rx_cfg[SLIM_RX_7].sample_rate;
+		channels->min = channels->max =
+			slim_rx_cfg[SLIM_RX_7].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SLIMBUS_7_TX:
+		rate->min = rate->max = slim_tx_cfg[SLIM_TX_7].sample_rate;
+		channels->min = channels->max =
+			slim_tx_cfg[SLIM_TX_7].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SLIMBUS_8_TX:
+		rate->min = rate->max = slim_tx_cfg[SLIM_TX_8].sample_rate;
+		channels->min = channels->max =
+			slim_tx_cfg[SLIM_TX_8].channels;
+		break;
+
+	case MSM_BACKEND_DAI_AFE_LOOPBACK_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				afe_loopback_tx_cfg[idx].bit_format);
+		rate->min = rate->max = afe_loopback_tx_cfg[idx].sample_rate;
+		channels->min = channels->max =
+				afe_loopback_tx_cfg[idx].channels;
+		break;
+
+	default:
+		rate->min = rate->max = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	return 0;
+}
+
+static bool msm_usbc_swap_gnd_mic(struct snd_soc_component *component,
+				  bool active)
+{
+	struct snd_soc_card *card = component->card;
+	struct msm_asoc_mach_data *pdata =
+				snd_soc_card_get_drvdata(card);
+
+	if (!pdata->fsa_handle)
+		return false;
+
+	return fsa4480_switch_event(pdata->fsa_handle, FSA_MIC_GND_SWAP);
+}
+
+static bool msm_swap_gnd_mic(struct snd_soc_component *component, bool active)
+{
+	int value = 0;
+	bool ret = false;
+	struct snd_soc_card *card;
+	struct msm_asoc_mach_data *pdata;
+
+	if (!component) {
+		pr_err("%s component is NULL\n", __func__);
+		return false;
+	}
+	card = component->card;
+	pdata = snd_soc_card_get_drvdata(card);
+
+	if (!pdata)
+		return false;
+
+	if (wcd_mbhc_cfg.enable_usbc_analog)
+		return msm_usbc_swap_gnd_mic(component, active);
+
+	/* if usbc is not defined, swap using us_euro_gpio_p */
+	if (pdata->us_euro_gpio_p) {
+		value = msm_cdc_pinctrl_get_state(
+				pdata->us_euro_gpio_p);
+		if (value)
+			msm_cdc_pinctrl_select_sleep_state(
+					pdata->us_euro_gpio_p);
+		else
+			msm_cdc_pinctrl_select_active_state(
+					pdata->us_euro_gpio_p);
+		dev_dbg(component->dev, "%s: swap select switch %d to %d\n",
+			__func__, value, !value);
+		ret = true;
+	}
+
+	return ret;
+}
+
+static int bengal_tdm_snd_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	int slot_width = 32;
+	int channels, slots;
+	unsigned int slot_mask, rate, clk_freq;
+	unsigned int slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
+
+	pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);
+
+	/* currently only supporting TDM_RX_0 and TDM_TX_0 */
+	switch (cpu_dai->id) {
+	case AFE_PORT_ID_PRIMARY_TDM_RX:
+		slots = tdm_rx_cfg[TDM_PRI][TDM_0].channels;
+		break;
+	case AFE_PORT_ID_SECONDARY_TDM_RX:
+		slots = tdm_rx_cfg[TDM_SEC][TDM_0].channels;
+		break;
+	case AFE_PORT_ID_TERTIARY_TDM_RX:
+		slots = tdm_rx_cfg[TDM_TERT][TDM_0].channels;
+		break;
+	case AFE_PORT_ID_QUATERNARY_TDM_RX:
+		slots = tdm_rx_cfg[TDM_QUAT][TDM_0].channels;
+		break;
+	case AFE_PORT_ID_PRIMARY_TDM_TX:
+		slots = tdm_tx_cfg[TDM_PRI][TDM_0].channels;
+		break;
+	case AFE_PORT_ID_SECONDARY_TDM_TX:
+		slots = tdm_tx_cfg[TDM_SEC][TDM_0].channels;
+		break;
+	case AFE_PORT_ID_TERTIARY_TDM_TX:
+		slots = tdm_tx_cfg[TDM_TERT][TDM_0].channels;
+		break;
+	case AFE_PORT_ID_QUATERNARY_TDM_TX:
+		slots = tdm_tx_cfg[TDM_QUAT][TDM_0].channels;
+		break;
+
+	default:
+		pr_err("%s: dai id 0x%x not supported\n",
+			__func__, cpu_dai->id);
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/*2 slot config - bits 0 and 1 set for the first two slots */
+		slot_mask = 0x0000FFFF >> (16 - slots);
+		channels = slots;
+
+		pr_debug("%s: tdm rx slot_width %d slots %d\n",
+			__func__, slot_width, slots);
+
+		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask,
+			slots, slot_width);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm rx slot, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+			0, NULL, channels, slot_offset);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm rx channel map, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		/*2 slot config - bits 0 and 1 set for the first two slots */
+		slot_mask = 0x0000FFFF >> (16 - slots);
+		channels = slots;
+
+		pr_debug("%s: tdm tx slot_width %d slots %d\n",
+			__func__, slot_width, slots);
+
+		ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0,
+			slots, slot_width);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm tx slot, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+			channels, slot_offset, 0, NULL);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm tx channel map, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+	} else {
+		ret = -EINVAL;
+		pr_err("%s: invalid use case, err:%d\n",
+			__func__, ret);
+		goto end;
+	}
+
+	rate = params_rate(params);
+	clk_freq = rate * slot_width * slots;
+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, clk_freq, SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		pr_err("%s: failed to set tdm clk, err:%d\n",
+			__func__, ret);
+
+end:
+	return ret;
+}
+
+static int msm_get_tdm_mode(u32 port_id)
+{
+	int tdm_mode;
+
+	switch (port_id) {
+	case AFE_PORT_ID_PRIMARY_TDM_RX:
+	case AFE_PORT_ID_PRIMARY_TDM_TX:
+		tdm_mode = TDM_PRI;
+		break;
+	case AFE_PORT_ID_SECONDARY_TDM_RX:
+	case AFE_PORT_ID_SECONDARY_TDM_TX:
+		tdm_mode = TDM_SEC;
+		break;
+	case AFE_PORT_ID_TERTIARY_TDM_RX:
+	case AFE_PORT_ID_TERTIARY_TDM_TX:
+		tdm_mode = TDM_TERT;
+		break;
+	case AFE_PORT_ID_QUATERNARY_TDM_RX:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX:
+		tdm_mode = TDM_QUAT;
+		break;
+	default:
+		pr_err("%s: Invalid port id: %d\n", __func__, port_id);
+		tdm_mode = -EINVAL;
+	}
+	return tdm_mode;
+}
+
+static int bengal_tdm_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int tdm_mode = msm_get_tdm_mode(cpu_dai->id);
+
+	if (tdm_mode >= TDM_INTERFACE_MAX || tdm_mode < 0) {
+		ret = -EINVAL;
+		pr_err("%s: Invalid TDM interface %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (pdata->mi2s_gpio_p[tdm_mode]) {
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[tdm_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+				pdata->mi2s_gpio_p[tdm_mode]);
+			if (ret) {
+				pr_err("%s: TDM GPIO pinctrl set active failed with %d\n",
+					__func__, ret);
+				goto done;
+			}
+		}
+		atomic_inc(&(pdata->mi2s_gpio_ref_count[tdm_mode]));
+	}
+
+done:
+	return ret;
+}
+
+static void bengal_tdm_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int tdm_mode = msm_get_tdm_mode(cpu_dai->id);
+
+	if (tdm_mode >= TDM_INTERFACE_MAX || tdm_mode < 0) {
+		ret = -EINVAL;
+		pr_err("%s: Invalid TDM interface %d\n",
+			__func__, ret);
+		return;
+	}
+
+	if (pdata->mi2s_gpio_p[tdm_mode]) {
+		atomic_dec(&(pdata->mi2s_gpio_ref_count[tdm_mode]));
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[tdm_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_sleep_state(
+				pdata->mi2s_gpio_p[tdm_mode]);
+			if (ret)
+				pr_err("%s: TDM GPIO pinctrl set sleep failed with %d\n",
+					__func__, ret);
+		}
+	}
+}
+
+static int bengal_aux_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	u32 aux_mode = cpu_dai->id - 1;
+
+	if (aux_mode >= AUX_PCM_MAX) {
+		ret = -EINVAL;
+		pr_err("%s: Invalid AUX interface %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (pdata->mi2s_gpio_p[aux_mode]) {
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[aux_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+				pdata->mi2s_gpio_p[aux_mode]);
+			if (ret) {
+				pr_err("%s: AUX GPIO pinctrl set active failed with %d\n",
+					__func__, ret);
+				goto done;
+			}
+		}
+		atomic_inc(&(pdata->mi2s_gpio_ref_count[aux_mode]));
+	}
+
+done:
+	return ret;
+}
+
+static void bengal_aux_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	u32 aux_mode = cpu_dai->id - 1;
+
+	if (aux_mode >= AUX_PCM_MAX) {
+		pr_err("%s: Invalid AUX interface %d\n",
+			__func__, ret);
+		return;
+	}
+
+	if (pdata->mi2s_gpio_p[aux_mode]) {
+		atomic_dec(&(pdata->mi2s_gpio_ref_count[aux_mode]));
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[aux_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_sleep_state(
+				pdata->mi2s_gpio_p[aux_mode]);
+			if (ret)
+				pr_err("%s: AUX GPIO pinctrl set sleep failed with %d\n",
+					__func__, ret);
+		}
+	}
+}
+
+static int msm_snd_cdc_dma_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+	switch (dai_link->id) {
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		ret = bengal_send_island_va_config(dai_link->id);
+		if (ret)
+			pr_err("%s: send island va cfg failed, err: %d\n",
+			       __func__, ret);
+		break;
+	}
+
+	return ret;
+}
+
+static int msm_snd_cdc_dma_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+	int ret = 0;
+	u32 rx_ch_cdc_dma, tx_ch_cdc_dma;
+	u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+	u32 user_set_tx_ch = 0;
+	u32 user_set_rx_ch = 0;
+	u32 ch_id;
+
+	ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, &tx_ch_cdc_dma, &rx_ch_cnt,
+				&rx_ch_cdc_dma);
+	if (ret < 0) {
+		pr_err("%s: failed to get codec chan map, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (dai_link->id) {
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0:
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1:
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2:
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3:
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_4:
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5:
+		{
+			ch_id = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+			pr_debug("%s: id %d rx_ch=%d\n", __func__,
+				ch_id, cdc_dma_rx_cfg[ch_id].channels);
+			user_set_rx_ch = cdc_dma_rx_cfg[ch_id].channels;
+			ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+					  user_set_rx_ch, &rx_ch_cdc_dma);
+			if (ret < 0) {
+				pr_err("%s: failed to set cpu chan map, err:%d\n",
+				__func__, ret);
+				goto err;
+			}
+
+		}
+		break;
+		}
+	} else {
+		switch (dai_link->id) {
+		case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0:
+		case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3:
+		case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4:
+		case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+		case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+		case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		{
+			ch_id = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+			pr_debug("%s: id %d tx_ch=%d\n", __func__,
+				ch_id, cdc_dma_tx_cfg[ch_id].channels);
+			user_set_tx_ch = cdc_dma_tx_cfg[ch_id].channels;
+		}
+		break;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, user_set_tx_ch,
+					&tx_ch_cdc_dma, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map, err:%d\n",
+			__func__, ret);
+			goto err;
+		}
+	}
+
+err:
+	return ret;
+}
+
+static int msm_fe_qos_prepare(struct snd_pcm_substream *substream)
+{
+	cpumask_t mask;
+
+	if (pm_qos_request_active(&substream->latency_pm_qos_req))
+		pm_qos_remove_request(&substream->latency_pm_qos_req);
+
+	cpumask_clear(&mask);
+	cpumask_set_cpu(1, &mask); /* affine to core 1 */
+	cpumask_set_cpu(2, &mask); /* affine to core 2 */
+	cpumask_copy(&substream->latency_pm_qos_req.cpus_affine, &mask);
+
+	substream->latency_pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES;
+
+	pm_qos_add_request(&substream->latency_pm_qos_req,
+			  PM_QOS_CPU_DMA_LATENCY,
+			  MSM_LL_QOS_VALUE);
+	return 0;
+}
+
+static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int index = cpu_dai->id;
+	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	dev_dbg(rtd->card->dev,
+		"%s: substream = %s  stream = %d, dai name %s, dai ID %d\n",
+		__func__, substream->name, substream->stream,
+		cpu_dai->name, cpu_dai->id);
+
+	if (index < PRIM_MI2S || index >= MI2S_MAX) {
+		ret = -EINVAL;
+		dev_err(rtd->card->dev,
+			"%s: CPU DAI id (%d) out of range\n",
+			__func__, cpu_dai->id);
+		goto err;
+	}
+	/*
+	 * Mutex protection in case the same MI2S
+	 * interface using for both TX and RX so
+	 * that the same clock won't be enable twice.
+	 */
+	mutex_lock(&mi2s_intf_conf[index].lock);
+	if (++mi2s_intf_conf[index].ref_cnt == 1) {
+		/* Check if msm needs to provide the clock to the interface */
+		if (!mi2s_intf_conf[index].msm_is_mi2s_master) {
+			mi2s_clk[index].clk_id = mi2s_ebit_clk[index];
+			fmt = SND_SOC_DAIFMT_CBM_CFM;
+		}
+		ret = msm_mi2s_set_sclk(substream, true);
+		if (ret < 0) {
+			dev_err(rtd->card->dev,
+				"%s: afe lpass clock failed to enable MI2S clock, err:%d\n",
+				__func__, ret);
+			goto clean_up;
+		}
+
+		ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+		if (ret < 0) {
+			pr_err("%s: set fmt cpu dai failed for MI2S (%d), err:%d\n",
+				__func__, index, ret);
+			goto clk_off;
+		}
+		if (pdata->mi2s_gpio_p[index]) {
+			if (atomic_read(&(pdata->mi2s_gpio_ref_count[index]))
+									== 0) {
+				ret = msm_cdc_pinctrl_select_active_state(
+						pdata->mi2s_gpio_p[index]);
+				if (ret) {
+					pr_err("%s: MI2S GPIO pinctrl set active failed with %d\n",
+						__func__, ret);
+					goto clk_off;
+				}
+			}
+			atomic_inc(&(pdata->mi2s_gpio_ref_count[index]));
+		}
+	}
+clk_off:
+	if (ret < 0)
+		msm_mi2s_set_sclk(substream, false);
+clean_up:
+	if (ret < 0)
+		mi2s_intf_conf[index].ref_cnt--;
+	mutex_unlock(&mi2s_intf_conf[index].lock);
+err:
+	return ret;
+}
+
+static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	int index = rtd->cpu_dai->id;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	if (index < PRIM_MI2S || index >= MI2S_MAX) {
+		pr_err("%s:invalid MI2S DAI(%d)\n", __func__, index);
+		return;
+	}
+
+	mutex_lock(&mi2s_intf_conf[index].lock);
+	if (--mi2s_intf_conf[index].ref_cnt == 0) {
+		if (pdata->mi2s_gpio_p[index]) {
+			atomic_dec(&(pdata->mi2s_gpio_ref_count[index]));
+			if (atomic_read(&(pdata->mi2s_gpio_ref_count[index]))
+									== 0) {
+				ret = msm_cdc_pinctrl_select_sleep_state(
+						pdata->mi2s_gpio_p[index]);
+				if (ret)
+					pr_err("%s: MI2S GPIO pinctrl set sleep failed with %d\n",
+						__func__, ret);
+			}
+		}
+
+		ret = msm_mi2s_set_sclk(substream, false);
+		if (ret < 0)
+			pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
+				__func__, index, ret);
+	}
+	mutex_unlock(&mi2s_intf_conf[index].lock);
+}
+
+static int msm_wcn_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	u32 rx_ch[WCN_CDC_SLIM_RX_CH_MAX], tx_ch[WCN_CDC_SLIM_TX_CH_MAX];
+	u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+	int ret = 0;
+
+	dev_dbg(rtd->dev, "%s: %s_tx_dai_id_%d\n", __func__,
+		 codec_dai->name, codec_dai->id);
+	ret = snd_soc_dai_get_channel_map(codec_dai,
+				 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+	if (ret) {
+		dev_err(rtd->dev,
+			"%s: failed to get BTFM codec chan map\n, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) BE id %d\n",
+		__func__, tx_ch_cnt, dai_link->id);
+
+	ret = snd_soc_dai_set_channel_map(cpu_dai,
+					  tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
+	if (ret)
+		dev_err(rtd->dev, "%s: failed to set cpu chan map, err:%d\n",
+			__func__, ret);
+
+err:
+	return ret;
+}
+
+static struct snd_soc_ops bengal_aux_be_ops = {
+	.startup = bengal_aux_snd_startup,
+	.shutdown = bengal_aux_snd_shutdown
+};
+
+static struct snd_soc_ops bengal_tdm_be_ops = {
+	.hw_params = bengal_tdm_snd_hw_params,
+	.startup = bengal_tdm_snd_startup,
+	.shutdown = bengal_tdm_snd_shutdown
+};
+
+static struct snd_soc_ops msm_mi2s_be_ops = {
+	.startup = msm_mi2s_snd_startup,
+	.shutdown = msm_mi2s_snd_shutdown,
+};
+
+static struct snd_soc_ops msm_fe_qos_ops = {
+	.prepare = msm_fe_qos_prepare,
+};
+
+static struct snd_soc_ops msm_cdc_dma_be_ops = {
+	.startup = msm_snd_cdc_dma_startup,
+	.hw_params = msm_snd_cdc_dma_hw_params,
+};
+
+static struct snd_soc_ops msm_wcn_ops = {
+	.hw_params = msm_wcn_hw_params,
+};
+
+static int msm_dmic_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol, int event)
+{
+	struct msm_asoc_mach_data *pdata = NULL;
+	struct snd_soc_component *component =
+					snd_soc_dapm_to_component(w->dapm);
+	int ret = 0;
+	u32 dmic_idx;
+	int *dmic_gpio_cnt;
+	struct device_node *dmic_gpio;
+	char  *wname;
+
+	wname = strpbrk(w->name, "0123");
+	if (!wname) {
+		dev_err(component->dev, "%s: widget not found\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = kstrtouint(wname, 10, &dmic_idx);
+	if (ret < 0) {
+		dev_err(component->dev, "%s: Invalid DMIC line on the codec\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	pdata = snd_soc_card_get_drvdata(component->card);
+
+	switch (dmic_idx) {
+	case 0:
+	case 1:
+		dmic_gpio_cnt = &dmic_0_1_gpio_cnt;
+		dmic_gpio = pdata->dmic01_gpio_p;
+		break;
+	case 2:
+	case 3:
+		dmic_gpio_cnt = &dmic_2_3_gpio_cnt;
+		dmic_gpio = pdata->dmic23_gpio_p;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid DMIC Selection\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: event %d DMIC%d dmic_gpio_cnt %d\n",
+			__func__, event, dmic_idx, *dmic_gpio_cnt);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		(*dmic_gpio_cnt)++;
+		if (*dmic_gpio_cnt == 1) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						dmic_gpio);
+			if (ret < 0) {
+				pr_err("%s: gpio set cannot be activated %sd",
+					__func__, "dmic_gpio");
+				return ret;
+			}
+		}
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		(*dmic_gpio_cnt)--;
+		if (*dmic_gpio_cnt == 0) {
+			ret = msm_cdc_pinctrl_select_sleep_state(
+					dmic_gpio);
+			if (ret < 0) {
+				pr_err("%s: gpio set cannot be de-activated %sd",
+					__func__, "dmic_gpio");
+				return ret;
+			}
+		}
+		break;
+	default:
+		pr_err("%s: invalid DAPM event %d\n", __func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget msm_int_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Analog Mic1", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic2", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic3", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic4", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic0", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic1", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic2", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic3", msm_dmic_event),
+};
+
+static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
+{
+	unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
+	unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX]  = {159, 160, 161};
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	return snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+					   tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+}
+
+static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = -EINVAL;
+	struct snd_soc_component *component;
+	struct snd_soc_dapm_context *dapm;
+	struct snd_card *card;
+	struct snd_info_entry *entry;
+	struct msm_asoc_mach_data *pdata =
+				snd_soc_card_get_drvdata(rtd->card);
+
+	component = snd_soc_rtdcom_lookup(rtd, "bolero_codec");
+	if (!component) {
+		pr_err("%s: could not find component for bolero_codec\n",
+			__func__);
+		return ret;
+	}
+
+	dapm = snd_soc_component_get_dapm(component);
+
+	ret = snd_soc_add_component_controls(component, msm_int_snd_controls,
+				ARRAY_SIZE(msm_int_snd_controls));
+	if (ret < 0) {
+		pr_err("%s: add_component_controls failed: %d\n",
+			__func__, ret);
+		return ret;
+	}
+	ret = snd_soc_add_component_controls(component, msm_common_snd_controls,
+				ARRAY_SIZE(msm_common_snd_controls));
+	if (ret < 0) {
+		pr_err("%s: add common snd controls failed: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	snd_soc_dapm_new_controls(dapm, msm_int_dapm_widgets,
+				ARRAY_SIZE(msm_int_dapm_widgets));
+
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
+
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic1");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic2");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic3");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
+
+	snd_soc_dapm_sync(dapm);
+
+		bolero_set_port_map(component, ARRAY_SIZE(sm_port_map),
+				    sm_port_map);
+	card = rtd->card->snd_card;
+	if (!pdata->codec_root) {
+		entry = snd_info_create_subdir(card->module, "codecs",
+						 card->proc_root);
+		if (!entry) {
+			pr_debug("%s: Cannot create codecs module entry\n",
+				 __func__);
+			ret = 0;
+			goto err;
+		}
+		pdata->codec_root = entry;
+	}
+	bolero_info_create_codec_entry(pdata->codec_root, component);
+	bolero_register_wake_irq(component, false);
+	codec_reg_done = true;
+	return 0;
+err:
+	return ret;
+}
+
+static void *def_wcd_mbhc_cal(void)
+{
+	void *wcd_mbhc_cal;
+	struct wcd_mbhc_btn_detect_cfg *btn_cfg;
+	u16 *btn_high;
+
+	wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
+				WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
+	if (!wcd_mbhc_cal)
+		return NULL;
+
+	WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->v_hs_max = WCD_MBHC_HS_V_MAX;
+	WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->num_btn = WCD_MBHC_DEF_BUTTONS;
+	btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal);
+	btn_high = ((void *)&btn_cfg->_v_btn_low) +
+		(sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
+
+	btn_high[0] = 75;
+	btn_high[1] = 150;
+	btn_high[2] = 237;
+	btn_high[3] = 500;
+	btn_high[4] = 500;
+	btn_high[5] = 500;
+	btn_high[6] = 500;
+	btn_high[7] = 500;
+
+	return wcd_mbhc_cal;
+}
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm_common_dai_links[] = {
+	/* FrontEnd DAI Links */
+	{/* hw:x,0 */
+		.name = MSM_DAILINK_NAME(Media1),
+		.stream_name = "MultiMedia1",
+		.cpu_dai_name = "MultiMedia1",
+		.platform_name = "msm-pcm-dsp.0",
+		.dynamic = 1,
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA1
+	},
+	{/* hw:x,1 */
+		.name = MSM_DAILINK_NAME(Media2),
+		.stream_name = "MultiMedia2",
+		.cpu_dai_name = "MultiMedia2",
+		.platform_name = "msm-pcm-dsp.0",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+	},
+	{/* hw:x,2 */
+		.name = "VoiceMMode1",
+		.stream_name = "VoiceMMode1",
+		.cpu_dai_name = "VoiceMMode1",
+		.platform_name = "msm-pcm-voice",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_VOICEMMODE1,
+	},
+	{/* hw:x,3 */
+		.name = "MSM VoIP",
+		.stream_name = "VoIP",
+		.cpu_dai_name = "VoIP",
+		.platform_name = "msm-voip-dsp",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_VOIP,
+	},
+	{/* hw:x,4 */
+		.name = MSM_DAILINK_NAME(ULL),
+		.stream_name = "MultiMedia3",
+		.cpu_dai_name = "MultiMedia3",
+		.platform_name = "msm-pcm-dsp.2",
+		.dynamic = 1,
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+	},
+	{/* hw:x,5 */
+		.name = "MSM AFE-PCM RX",
+		.stream_name = "AFE-PROXY RX",
+		.cpu_dai_name = "msm-dai-q6-dev.241",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.platform_name = "msm-pcm-afe",
+		.dpcm_playback = 1,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{/* hw:x,6 */
+		.name = "MSM AFE-PCM TX",
+		.stream_name = "AFE-PROXY TX",
+		.cpu_dai_name = "msm-dai-q6-dev.240",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.platform_name  = "msm-pcm-afe",
+		.dpcm_capture = 1,
+		.ignore_suspend = 1,
+	},
+	{/* hw:x,7 */
+		.name = MSM_DAILINK_NAME(Compress1),
+		.stream_name = "Compress1",
+		.cpu_dai_name = "MultiMedia4",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.async_ops = ASYNC_DPCM_SND_SOC_HW_PARAMS,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+	},
+	/* Hostless PCM purpose */
+	{/* hw:x,8 */
+		.name = "AUXPCM Hostless",
+		.stream_name = "AUXPCM Hostless",
+		.cpu_dai_name = "AUXPCM_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,9 */
+		.name = MSM_DAILINK_NAME(LowLatency),
+		.stream_name = "MultiMedia5",
+		.cpu_dai_name = "MultiMedia5",
+		.platform_name = "msm-pcm-dsp.1",
+		.dynamic = 1,
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+		.ops = &msm_fe_qos_ops,
+	},
+	{/* hw:x,10 */
+		.name = "Listen 1 Audio Service",
+		.stream_name = "Listen 1 Audio Service",
+		.cpu_dai_name = "LSM1",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+			     SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM1,
+	},
+	/* Multiple Tunnel instances */
+	{/* hw:x,11 */
+		.name = MSM_DAILINK_NAME(Compress2),
+		.stream_name = "Compress2",
+		.cpu_dai_name = "MultiMedia7",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+	},
+	{/* hw:x,12 */
+		.name = MSM_DAILINK_NAME(MultiMedia10),
+		.stream_name = "MultiMedia10",
+		.cpu_dai_name = "MultiMedia10",
+		.platform_name = "msm-pcm-dsp.1",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA10,
+	},
+	{/* hw:x,13 */
+		.name = MSM_DAILINK_NAME(ULL_NOIRQ),
+		.stream_name = "MM_NOIRQ",
+		.cpu_dai_name = "MultiMedia8",
+		.platform_name = "msm-pcm-dsp-noirq",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+		.ops = &msm_fe_qos_ops,
+	},
+	/* HDMI Hostless */
+	{/* hw:x,14 */
+		.name = "HDMI_RX_HOSTLESS",
+		.stream_name = "HDMI_RX_HOSTLESS",
+		.cpu_dai_name = "HDMI_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,15 */
+		.name = "VoiceMMode2",
+		.stream_name = "VoiceMMode2",
+		.cpu_dai_name = "VoiceMMode2",
+		.platform_name = "msm-pcm-voice",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_VOICEMMODE2,
+	},
+	/* LSM FE */
+	{/* hw:x,16 */
+		.name = "Listen 2 Audio Service",
+		.stream_name = "Listen 2 Audio Service",
+		.cpu_dai_name = "LSM2",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM2,
+	},
+	{/* hw:x,17 */
+		.name = "Listen 3 Audio Service",
+		.stream_name = "Listen 3 Audio Service",
+		.cpu_dai_name = "LSM3",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM3,
+	},
+	{/* hw:x,18 */
+		.name = "Listen 4 Audio Service",
+		.stream_name = "Listen 4 Audio Service",
+		.cpu_dai_name = "LSM4",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM4,
+	},
+	{/* hw:x,19 */
+		.name = "Listen 5 Audio Service",
+		.stream_name = "Listen 5 Audio Service",
+		.cpu_dai_name = "LSM5",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM5,
+	},
+	{/* hw:x,20 */
+		.name = "Listen 6 Audio Service",
+		.stream_name = "Listen 6 Audio Service",
+		.cpu_dai_name = "LSM6",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM6,
+	},
+	{/* hw:x,21 */
+		.name = "Listen 7 Audio Service",
+		.stream_name = "Listen 7 Audio Service",
+		.cpu_dai_name = "LSM7",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM7,
+	},
+	{/* hw:x,22 */
+		.name = "Listen 8 Audio Service",
+		.stream_name = "Listen 8 Audio Service",
+		.cpu_dai_name = "LSM8",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.id = MSM_FRONTEND_DAI_LSM8,
+	},
+	{/* hw:x,23 */
+		.name = MSM_DAILINK_NAME(Media9),
+		.stream_name = "MultiMedia9",
+		.cpu_dai_name = "MultiMedia9",
+		.platform_name = "msm-pcm-dsp.0",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+	},
+	{/* hw:x,24 */
+		.name = MSM_DAILINK_NAME(Compress4),
+		.stream_name = "Compress4",
+		.cpu_dai_name = "MultiMedia11",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA11,
+	},
+	{/* hw:x,25 */
+		.name = MSM_DAILINK_NAME(Compress5),
+		.stream_name = "Compress5",
+		.cpu_dai_name = "MultiMedia12",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA12,
+	},
+	{/* hw:x,26 */
+		.name = MSM_DAILINK_NAME(Compress6),
+		.stream_name = "Compress6",
+		.cpu_dai_name = "MultiMedia13",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA13,
+	},
+	{/* hw:x,27 */
+		.name = MSM_DAILINK_NAME(Compress7),
+		.stream_name = "Compress7",
+		.cpu_dai_name = "MultiMedia14",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA14,
+	},
+	{/* hw:x,28 */
+		.name = MSM_DAILINK_NAME(Compress8),
+		.stream_name = "Compress8",
+		.cpu_dai_name = "MultiMedia15",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA15,
+	},
+	{/* hw:x,29 */
+		.name = MSM_DAILINK_NAME(ULL_NOIRQ_2),
+		.stream_name = "MM_NOIRQ_2",
+		.cpu_dai_name = "MultiMedia16",
+		.platform_name = "msm-pcm-dsp-noirq",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA16,
+		.ops = &msm_fe_qos_ops,
+	},
+	{/* hw:x,30 */
+		.name = "CDC_DMA Hostless",
+		.stream_name = "CDC_DMA Hostless",
+		.cpu_dai_name = "CDC_DMA_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		 /* this dailink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,31 */
+		.name = "TX3_CDC_DMA Hostless",
+		.stream_name = "TX3_CDC_DMA Hostless",
+		.cpu_dai_name = "TX3_CDC_DMA_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,32 */
+		.name = "Tertiary MI2S TX_Hostless",
+		.stream_name = "Tertiary MI2S_TX Hostless Capture",
+		.cpu_dai_name = "TERT_MI2S_TX_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+};
+
+static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
+	{/* hw:x,34 */
+		.name = MSM_DAILINK_NAME(ASM Loopback),
+		.stream_name = "MultiMedia6",
+		.cpu_dai_name = "MultiMedia6",
+		.platform_name = "msm-pcm-loopback",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+	},
+	{/* hw:x,35 */
+		.name = "USB Audio Hostless",
+		.stream_name = "USB Audio Hostless",
+		.cpu_dai_name = "USBAUDIO_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,36 */
+		.name = "SLIMBUS_7 Hostless",
+		.stream_name = "SLIMBUS_7 Hostless",
+		.cpu_dai_name = "SLIMBUS7_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,37 */
+		.name = "Compress Capture",
+		.stream_name = "Compress9",
+		.cpu_dai_name = "MultiMedia17",
+		.platform_name = "msm-compress-dsp",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA17,
+	},
+	{/* hw:x,38 */
+		.name = "SLIMBUS_8 Hostless",
+		.stream_name = "SLIMBUS_8 Hostless",
+		.cpu_dai_name = "SLIMBUS8_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{/* hw:x,39 */
+		.name = LPASS_BE_TX_CDC_DMA_TX_5,
+		.stream_name = "TX CDC DMA5 Capture",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45115",
+		.platform_name = "msm-pcm-hostless",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "tx_macro_tx3",
+		.id = MSM_BACKEND_DAI_TX_CDC_DMA_TX_5,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+};
+
+static struct snd_soc_dai_link msm_common_be_dai_links[] = {
+	/* Backend AFE DAI Links */
+	{
+		.name = LPASS_BE_AFE_PCM_RX,
+		.stream_name = "AFE Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.224",
+		.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_AFE_PCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_TX,
+		.stream_name = "AFE Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.225",
+		.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_AFE_PCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Record Uplink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_TX,
+		.stream_name = "Voice Uplink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32772",
+		.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_INCALL_RECORD_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Record Downlink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_RX,
+		.stream_name = "Voice Downlink Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.32771",
+		.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_INCALL_RECORD_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	/* Incall Music BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE_PLAYBACK_TX,
+		.stream_name = "Voice Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32773",
+		.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_VOICE_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	/* Incall Music 2 BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE2_PLAYBACK_TX,
+		.stream_name = "Voice2 Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32770",
+		.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_VOICE2_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_USB_AUDIO_RX,
+		.stream_name = "USB Audio Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.28672",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.dynamic_be = 1,
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_USB_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_USB_AUDIO_TX,
+		.stream_name = "USB Audio Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.28673",
+		.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_USB_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_PRI_TDM_RX_0,
+		.stream_name = "Primary TDM0 Playback",
+		.cpu_dai_name = "msm-dai-q6-tdm.36864",
+		.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_PRI_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_PRI_TDM_TX_0,
+		.stream_name = "Primary TDM0 Capture",
+		.cpu_dai_name = "msm-dai-q6-tdm.36865",
+		.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_PRI_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_SEC_TDM_RX_0,
+		.stream_name = "Secondary TDM0 Playback",
+		.cpu_dai_name = "msm-dai-q6-tdm.36880",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_SEC_TDM_TX_0,
+		.stream_name = "Secondary TDM0 Capture",
+		.cpu_dai_name = "msm-dai-q6-tdm.36881",
+		.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_SEC_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_TERT_TDM_RX_0,
+		.stream_name = "Tertiary TDM0 Playback",
+		.cpu_dai_name = "msm-dai-q6-tdm.36896",
+		.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_TERT_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_TERT_TDM_TX_0,
+		.stream_name = "Tertiary TDM0 Capture",
+		.cpu_dai_name = "msm-dai-q6-tdm.36897",
+		.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_TERT_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_QUAT_TDM_RX_0,
+		.stream_name = "Quaternary TDM0 Playback",
+		.cpu_dai_name = "msm-dai-q6-tdm.36912",
+		.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_QUAT_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_QUAT_TDM_TX_0,
+		.stream_name = "Quaternary TDM0 Capture",
+		.cpu_dai_name = "msm-dai-q6-tdm.36913",
+		.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_QUAT_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_tdm_be_ops,
+		.ignore_suspend = 1,
+	},
+};
+
+static struct snd_soc_dai_link msm_wcn_btfm_be_dai_links[] = {
+	{
+		.name = LPASS_BE_SLIMBUS_7_RX,
+		.stream_name = "Slimbus7 Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.16398",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "btfmslim_slave",
+		/* BT codec driver determines capabilities based on
+		 * dai name, bt codecdai name should always contains
+		 * supported usecase information
+		 */
+		.codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.init = &msm_wcn_init,
+		.ops = &msm_wcn_ops,
+		/* dai link has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_7_TX,
+		.stream_name = "Slimbus7 Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16399",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "btfmslim_slave",
+		.codec_dai_name = "btfm_bt_sco_slim_tx",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_wcn_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_8_TX,
+		.stream_name = "Slimbus8 Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16401",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "btfmslim_slave",
+		.codec_dai_name = "btfm_fm_slim_tx",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_wcn_ops,
+		.ignore_suspend = 1,
+	},
+};
+
+static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
+	{
+		.name = LPASS_BE_PRI_MI2S_RX,
+		.stream_name = "Primary MI2S Playback",
+		.cpu_dai_name = "msm-dai-q6-mi2s.0",
+		.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_PRI_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_PRI_MI2S_TX,
+		.stream_name = "Primary MI2S Capture",
+		.cpu_dai_name = "msm-dai-q6-mi2s.0",
+		.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_PRI_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_SEC_MI2S_RX,
+		.stream_name = "Secondary MI2S Playback",
+		.cpu_dai_name = "msm-dai-q6-mi2s.1",
+		.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_SECONDARY_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_SEC_MI2S_TX,
+		.stream_name = "Secondary MI2S Capture",
+		.cpu_dai_name = "msm-dai-q6-mi2s.1",
+		.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_SECONDARY_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_TERT_MI2S_RX,
+		.stream_name = "Tertiary MI2S Playback",
+		.cpu_dai_name = "msm-dai-q6-mi2s.2",
+		.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_TERTIARY_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_TERT_MI2S_TX,
+		.stream_name = "Tertiary MI2S Capture",
+		.cpu_dai_name = "msm-dai-q6-mi2s.2",
+		.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_TERTIARY_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_QUAT_MI2S_RX,
+		.stream_name = "Quaternary MI2S Playback",
+		.cpu_dai_name = "msm-dai-q6-mi2s.3",
+		.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_QUATERNARY_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_QUAT_MI2S_TX,
+		.stream_name = "Quaternary MI2S Capture",
+		.cpu_dai_name = "msm-dai-q6-mi2s.3",
+		.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_QUATERNARY_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+	},
+};
+
+static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
+	/* Primary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_AUXPCM_RX,
+		.stream_name = "AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
+		.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_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_AUXPCM_TX,
+		.stream_name = "AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
+		.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_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_suspend = 1,
+	},
+	/* Secondary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_SEC_AUXPCM_RX,
+		.stream_name = "Sec AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.2",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_SEC_AUXPCM_TX,
+		.stream_name = "Sec AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.2",
+		.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_SEC_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_suspend = 1,
+	},
+	/* Tertiary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_TERT_AUXPCM_RX,
+		.stream_name = "Tert AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.3",
+		.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_TERT_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_TERT_AUXPCM_TX,
+		.stream_name = "Tert AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.3",
+		.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_TERT_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_suspend = 1,
+	},
+	/* Quaternary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_QUAT_AUXPCM_RX,
+		.stream_name = "Quat AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.4",
+		.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_QUAT_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = LPASS_BE_QUAT_AUXPCM_TX,
+		.stream_name = "Quat AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.4",
+		.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_QUAT_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &bengal_aux_be_ops,
+		.ignore_suspend = 1,
+	},
+};
+
+static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
+	/* RX CDC DMA Backend DAI Links */
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_0,
+		.stream_name = "RX CDC DMA0 Playback",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45104",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "rx_macro_rx1",
+		.dynamic_be = 1,
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_RX_CDC_DMA_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_1,
+		.stream_name = "RX CDC DMA1 Playback",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45106",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "rx_macro_rx2",
+		.dynamic_be = 1,
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_2,
+		.stream_name = "RX CDC DMA2 Playback",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45108",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "rx_macro_rx3",
+		.dynamic_be = 1,
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_RX_CDC_DMA_RX_2,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_3,
+		.stream_name = "RX CDC DMA3 Playback",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45110",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "rx_macro_rx4",
+		.dynamic_be = 1,
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_RX_CDC_DMA_RX_3,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+	/* TX CDC DMA Backend DAI Links */
+	{
+		.name = LPASS_BE_TX_CDC_DMA_TX_3,
+		.stream_name = "TX CDC DMA3 Capture",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45111",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "tx_macro_tx1",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TX_CDC_DMA_TX_3,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+	{
+		.name = LPASS_BE_TX_CDC_DMA_TX_4,
+		.stream_name = "TX CDC DMA4 Capture",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45113",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "tx_macro_tx2",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TX_CDC_DMA_TX_4,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+};
+
+static struct snd_soc_dai_link msm_va_cdc_dma_be_dai_links[] = {
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_0,
+		.stream_name = "VA CDC DMA0 Capture",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45089",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "va_macro_tx1",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.init = &msm_int_audrx_init,
+		.id = MSM_BACKEND_DAI_VA_CDC_DMA_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_1,
+		.stream_name = "VA CDC DMA1 Capture",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45091",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "va_macro_tx2",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_VA_CDC_DMA_TX_1,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_2,
+		.stream_name = "VA CDC DMA2 Capture",
+		.cpu_dai_name = "msm-dai-cdc-dma-dev.45093",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "bolero_codec",
+		.codec_dai_name = "va_macro_tx3",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_VA_CDC_DMA_TX_2,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+	},
+};
+
+static struct snd_soc_dai_link msm_afe_rxtx_lb_be_dai_link[] = {
+	{
+		.name = LPASS_BE_AFE_LOOPBACK_TX,
+		.stream_name = "AFE Loopback Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.24577",
+		.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_AFE_LOOPBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+	},
+};
+
+static struct snd_soc_dai_link msm_bengal_dai_links[
+			ARRAY_SIZE(msm_common_dai_links) +
+			ARRAY_SIZE(msm_common_misc_fe_dai_links) +
+			ARRAY_SIZE(msm_common_be_dai_links) +
+			ARRAY_SIZE(msm_mi2s_be_dai_links) +
+			ARRAY_SIZE(msm_auxpcm_be_dai_links) +
+			ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links) +
+			ARRAY_SIZE(msm_va_cdc_dma_be_dai_links) +
+			ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) +
+			ARRAY_SIZE(msm_wcn_btfm_be_dai_links)];
+
+static int msm_populate_dai_link_component_of_node(
+					struct snd_soc_card *card)
+{
+	int i, index, ret = 0;
+	struct device *cdev = card->dev;
+	struct snd_soc_dai_link *dai_link = card->dai_link;
+	struct device_node *np;
+
+	if (!cdev) {
+		dev_err(cdev, "%s: Sound card device memory NULL\n", __func__);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < card->num_links; i++) {
+		if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
+			continue;
+
+		/* populate platform_of_node for snd card dai links */
+		if (dai_link[i].platform_name &&
+		    !dai_link[i].platform_of_node) {
+			index = of_property_match_string(cdev->of_node,
+						"asoc-platform-names",
+						dai_link[i].platform_name);
+			if (index < 0) {
+				dev_err(cdev,
+				"%s: No match found for platform name: %s\n",
+				__func__, dai_link[i].platform_name);
+				ret = index;
+				goto err;
+			}
+			np = of_parse_phandle(cdev->of_node, "asoc-platform",
+					      index);
+			if (!np) {
+				dev_err(cdev,
+				"%s: retrieving phandle for platform %s, index %d failed\n",
+				__func__, dai_link[i].platform_name,
+				index);
+				ret = -ENODEV;
+				goto err;
+			}
+			dai_link[i].platform_of_node = np;
+			dai_link[i].platform_name = NULL;
+		}
+
+		/* populate cpu_of_node for snd card dai links */
+		if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
+			index = of_property_match_string(cdev->of_node,
+						 "asoc-cpu-names",
+						 dai_link[i].cpu_dai_name);
+			if (index >= 0) {
+				np = of_parse_phandle(cdev->of_node, "asoc-cpu",
+						index);
+				if (!np) {
+					dev_err(cdev,
+					"%s: retrieving phandle for cpu dai %s failed\n",
+					__func__,
+					dai_link[i].cpu_dai_name);
+					ret = -ENODEV;
+					goto err;
+				}
+				dai_link[i].cpu_of_node = np;
+				dai_link[i].cpu_dai_name = NULL;
+			}
+		}
+
+		/* populate codec_of_node for snd card dai links */
+		if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
+			index = of_property_match_string(cdev->of_node,
+						 "asoc-codec-names",
+						 dai_link[i].codec_name);
+			if (index < 0)
+				continue;
+			np = of_parse_phandle(cdev->of_node, "asoc-codec",
+					      index);
+			if (!np) {
+				dev_err(cdev,
+				"%s: retrieving phandle for codec %s failed\n",
+				__func__, dai_link[i].codec_name);
+				ret = -ENODEV;
+				goto err;
+			}
+			dai_link[i].codec_of_node = np;
+			dai_link[i].codec_name = NULL;
+		}
+	}
+
+err:
+	return ret;
+}
+
+static int msm_audrx_stub_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = -EINVAL;
+	struct snd_soc_component *component =
+			snd_soc_rtdcom_lookup(rtd, "msm-stub-codec");
+
+	if (!component) {
+		pr_err("* %s: No match for msm-stub-codec component\n",
+			__func__);
+		return ret;
+	}
+
+	ret = snd_soc_add_component_controls(component, msm_snd_controls,
+			ARRAY_SIZE(msm_snd_controls));
+	if (ret < 0) {
+		dev_err(component->dev,
+			"%s: add_codec_controls failed, err = %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int msm_snd_stub_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	return 0;
+}
+
+static struct snd_soc_ops msm_stub_be_ops = {
+	.hw_params = msm_snd_stub_hw_params,
+};
+
+struct snd_soc_card snd_soc_card_stub_msm = {
+	.name		= "bengal-stub-snd-card",
+};
+
+static struct snd_soc_dai_link msm_stub_fe_dai_links[] = {
+	/* FrontEnd DAI Links */
+	{
+		.name = "MSMSTUB Media1",
+		.stream_name = "MultiMedia1",
+		.cpu_dai_name = "MultiMedia1",
+		.platform_name = "msm-pcm-dsp.0",
+		.dynamic = 1,
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA1
+	},
+};
+
+static struct snd_soc_dai_link msm_stub_be_dai_links[] = {
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_AUXPCM_RX,
+		.stream_name = "AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
+		.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_AUXPCM_RX,
+		.init = &msm_audrx_stub_init,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_stub_be_ops,
+	},
+	{
+		.name = LPASS_BE_AUXPCM_TX,
+		.stream_name = "AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6-auxpcm.1",
+		.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_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_stub_be_ops,
+	},
+};
+
+static struct snd_soc_dai_link msm_stub_dai_links[
+			 ARRAY_SIZE(msm_stub_fe_dai_links) +
+			 ARRAY_SIZE(msm_stub_be_dai_links)];
+
+static const struct of_device_id bengal_asoc_machine_of_match[]  = {
+	{ .compatible = "qcom,bengal-asoc-snd",
+	  .data = "codec"},
+	{ .compatible = "qcom,bengal-asoc-snd-stub",
+	  .data = "stub_codec"},
+	{},
+};
+
+static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+{
+	struct snd_soc_card *card = NULL;
+	struct snd_soc_dai_link *dailink = NULL;
+	int len_1 = 0;
+	int len_2 = 0;
+	int total_links = 0;
+	int rc = 0;
+	u32 mi2s_audio_intf = 0;
+	u32 auxpcm_audio_intf = 0;
+	u32 rxtx_bolero_codec = 0;
+	u32 va_bolero_codec = 0;
+	u32 val = 0;
+	u32 wcn_btfm_intf = 0;
+	const struct of_device_id *match;
+
+	match = of_match_node(bengal_asoc_machine_of_match, dev->of_node);
+	if (!match) {
+		dev_err(dev, "%s: No DT match found for sound card\n",
+			__func__);
+		return NULL;
+	}
+
+	if (!strcmp(match->data, "codec")) {
+		card = &snd_soc_card_bengal_msm;
+
+		memcpy(msm_bengal_dai_links + total_links,
+		       msm_common_dai_links,
+		       sizeof(msm_common_dai_links));
+		total_links += ARRAY_SIZE(msm_common_dai_links);
+
+		memcpy(msm_bengal_dai_links + total_links,
+		       msm_common_misc_fe_dai_links,
+		       sizeof(msm_common_misc_fe_dai_links));
+		total_links += ARRAY_SIZE(msm_common_misc_fe_dai_links);
+
+		memcpy(msm_bengal_dai_links + total_links,
+		       msm_common_be_dai_links,
+		       sizeof(msm_common_be_dai_links));
+		total_links += ARRAY_SIZE(msm_common_be_dai_links);
+
+		rc = of_property_read_u32(dev->of_node,
+					  "qcom,rxtx-bolero-codec",
+					  &rxtx_bolero_codec);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match RXTX Macro codec\n",
+				__func__);
+		} else {
+			if (rxtx_bolero_codec) {
+				memcpy(msm_bengal_dai_links + total_links,
+				       msm_rx_tx_cdc_dma_be_dai_links,
+				       sizeof(msm_rx_tx_cdc_dma_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(
+						msm_rx_tx_cdc_dma_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,va-bolero-codec",
+					  &va_bolero_codec);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match VA Macro codec\n",
+				__func__);
+		} else {
+			if (va_bolero_codec) {
+				memcpy(msm_bengal_dai_links + total_links,
+				       msm_va_cdc_dma_be_dai_links,
+				       sizeof(msm_va_cdc_dma_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_va_cdc_dma_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,mi2s-audio-intf",
+					  &mi2s_audio_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match MI2S audio interface\n",
+				__func__);
+		} else {
+			if (mi2s_audio_intf) {
+				memcpy(msm_bengal_dai_links + total_links,
+					msm_mi2s_be_dai_links,
+					sizeof(msm_mi2s_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_mi2s_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node,
+					  "qcom,auxpcm-audio-intf",
+					  &auxpcm_audio_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match Aux PCM interface\n",
+				__func__);
+		} else {
+			if (auxpcm_audio_intf) {
+				memcpy(msm_bengal_dai_links + total_links,
+					msm_auxpcm_be_dai_links,
+					sizeof(msm_auxpcm_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_auxpcm_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,afe-rxtx-lb",
+				&val);
+		if (!rc && val) {
+			memcpy(msm_bengal_dai_links + total_links,
+				msm_afe_rxtx_lb_be_dai_link,
+				sizeof(msm_afe_rxtx_lb_be_dai_link));
+			total_links +=
+				ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,wcn-btfm",
+					  &wcn_btfm_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match wcn btfm interface\n",
+				__func__);
+		} else {
+			if (wcn_btfm_intf) {
+				memcpy(msm_bengal_dai_links + total_links,
+					msm_wcn_btfm_be_dai_links,
+					sizeof(msm_wcn_btfm_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_wcn_btfm_be_dai_links);
+			}
+		}
+		dailink = msm_bengal_dai_links;
+	} else if (!strcmp(match->data, "stub_codec")) {
+		card = &snd_soc_card_stub_msm;
+		len_1 = ARRAY_SIZE(msm_stub_fe_dai_links);
+		len_2 = len_1 + ARRAY_SIZE(msm_stub_be_dai_links);
+
+		memcpy(msm_stub_dai_links,
+		       msm_stub_fe_dai_links,
+		       sizeof(msm_stub_fe_dai_links));
+		memcpy(msm_stub_dai_links + len_1,
+		       msm_stub_be_dai_links,
+		       sizeof(msm_stub_be_dai_links));
+
+		dailink = msm_stub_dai_links;
+		total_links = len_2;
+	}
+
+	if (card) {
+		card->dai_link = dailink;
+		card->num_links = total_links;
+	}
+
+	return card;
+}
+
+static int msm_aux_codec_init(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm =
+				snd_soc_component_get_dapm(component);
+	int ret = 0;
+	void *mbhc_calibration;
+	struct snd_info_entry *entry;
+	struct snd_card *card = component->card->snd_card;
+	struct msm_asoc_mach_data *pdata;
+
+	snd_soc_dapm_ignore_suspend(dapm, "EAR");
+	snd_soc_dapm_ignore_suspend(dapm, "AUX");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHL");
+	snd_soc_dapm_ignore_suspend(dapm, "HPHR");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
+	snd_soc_dapm_sync(dapm);
+
+	pdata = snd_soc_card_get_drvdata(component->card);
+	if (!pdata->codec_root) {
+		entry = snd_info_create_subdir(card->module, "codecs",
+						 card->proc_root);
+		if (!entry) {
+			dev_dbg(component->dev, "%s: Cannot create codecs module entry\n",
+				 __func__);
+			ret = 0;
+			goto mbhc_cfg_cal;
+		}
+		pdata->codec_root = entry;
+	}
+	wcd937x_info_create_codec_entry(pdata->codec_root, component);
+
+mbhc_cfg_cal:
+	mbhc_calibration = def_wcd_mbhc_cal();
+	if (!mbhc_calibration)
+		return -ENOMEM;
+	wcd_mbhc_cfg.calibration = mbhc_calibration;
+	ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
+			__func__, ret);
+		goto err_hs_detect;
+	}
+	return 0;
+
+err_hs_detect:
+	kfree(mbhc_calibration);
+	return ret;
+}
+
+static int msm_init_aux_dev(struct platform_device *pdev,
+				struct snd_soc_card *card)
+{
+	struct device_node *wsa_of_node;
+	struct device_node *aux_codec_of_node;
+	u32 wsa_max_devs;
+	u32 wsa_dev_cnt;
+	u32 codec_max_aux_devs = 0;
+	u32 codec_aux_dev_cnt = 0;
+	int i;
+	struct msm_wsa881x_dev_info *wsa881x_dev_info;
+	struct aux_codec_dev_info *aux_cdc_dev_info;
+	const char *auxdev_name_prefix[1];
+	char *dev_name_str = NULL;
+	int found = 0;
+	int codecs_found = 0;
+	int ret = 0;
+
+	/* Get maximum WSA device count for this platform */
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "qcom,wsa-max-devs", &wsa_max_devs);
+	if (ret) {
+		dev_info(&pdev->dev,
+			 "%s: wsa-max-devs property missing in DT %s, ret = %d\n",
+			 __func__, pdev->dev.of_node->full_name, ret);
+		wsa_max_devs = 0;
+		goto codec_aux_dev;
+	}
+	if (wsa_max_devs == 0) {
+		dev_warn(&pdev->dev,
+			 "%s: Max WSA devices is 0 for this target?\n",
+			 __func__);
+		goto codec_aux_dev;
+	}
+
+	/* Get count of WSA device phandles for this platform */
+	wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node,
+						 "qcom,wsa-devs", NULL);
+	if (wsa_dev_cnt == -ENOENT) {
+		dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n",
+			 __func__);
+		goto err;
+	} else if (wsa_dev_cnt <= 0) {
+		dev_err(&pdev->dev,
+			"%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n",
+			__func__, wsa_dev_cnt);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/*
+	 * Expect total phandles count to be NOT less than maximum possible
+	 * WSA count. However, if it is less, then assign same value to
+	 * max count as well.
+	 */
+	if (wsa_dev_cnt < wsa_max_devs) {
+		dev_dbg(&pdev->dev,
+			"%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n",
+			__func__, wsa_max_devs, wsa_dev_cnt);
+		wsa_max_devs = wsa_dev_cnt;
+	}
+
+	/* Make sure prefix string passed for each WSA device */
+	ret = of_property_count_strings(pdev->dev.of_node,
+					"qcom,wsa-aux-dev-prefix");
+	if (ret != wsa_dev_cnt) {
+		dev_err(&pdev->dev,
+			"%s: expecting %d wsa prefix. Defined only %d in DT\n",
+			__func__, wsa_dev_cnt, ret);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/*
+	 * Alloc mem to store phandle and index info of WSA device, if already
+	 * registered with ALSA core
+	 */
+	wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs,
+					sizeof(struct msm_wsa881x_dev_info),
+					GFP_KERNEL);
+	if (!wsa881x_dev_info) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * search and check whether all WSA devices are already
+	 * registered with ALSA core or not. If found a node, store
+	 * the node and the index in a local array of struct for later
+	 * use.
+	 */
+	for (i = 0; i < wsa_dev_cnt; i++) {
+		wsa_of_node = of_parse_phandle(pdev->dev.of_node,
+					    "qcom,wsa-devs", i);
+		if (unlikely(!wsa_of_node)) {
+			/* we should not be here */
+			dev_err(&pdev->dev,
+				"%s: wsa dev node is not present\n",
+				__func__);
+			ret = -EINVAL;
+			goto err;
+		}
+		if (soc_find_component(wsa_of_node, NULL)) {
+			/* WSA device registered with ALSA core */
+			wsa881x_dev_info[found].of_node = wsa_of_node;
+			wsa881x_dev_info[found].index = i;
+			found++;
+			if (found == wsa_max_devs)
+				break;
+		}
+	}
+
+	if (found < wsa_max_devs) {
+		dev_dbg(&pdev->dev,
+			"%s: failed to find %d components. Found only %d\n",
+			__func__, wsa_max_devs, found);
+		return -EPROBE_DEFER;
+	}
+	dev_info(&pdev->dev,
+		"%s: found %d wsa881x devices registered with ALSA core\n",
+		__func__, found);
+
+codec_aux_dev:
+	/* Get maximum aux codec device count for this platform */
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "qcom,codec-max-aux-devs",
+				   &codec_max_aux_devs);
+	if (ret) {
+		dev_err(&pdev->dev,
+			 "%s: codec-max-aux-devs property missing in DT %s, ret = %d\n",
+			 __func__, pdev->dev.of_node->full_name, ret);
+		codec_max_aux_devs = 0;
+		goto aux_dev_register;
+	}
+	if (codec_max_aux_devs == 0) {
+		dev_dbg(&pdev->dev,
+			 "%s: Max aux codec devices is 0 for this target?\n",
+			 __func__);
+		goto aux_dev_register;
+	}
+
+	/* Get count of aux codec device phandles for this platform */
+	codec_aux_dev_cnt = of_count_phandle_with_args(
+				pdev->dev.of_node,
+				"qcom,codec-aux-devs", NULL);
+	if (codec_aux_dev_cnt == -ENOENT) {
+		dev_warn(&pdev->dev, "%s: No aux codec defined in DT.\n",
+			 __func__);
+		goto err;
+	} else if (codec_aux_dev_cnt <= 0) {
+		dev_err(&pdev->dev,
+			"%s: Error reading aux codec device from DT, dev_cnt=%d\n",
+			__func__, codec_aux_dev_cnt);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/*
+	 * Expect total phandles count to be NOT less than maximum possible
+	 * AUX device count. However, if it is less, then assign same value to
+	 * max count as well.
+	 */
+	if (codec_aux_dev_cnt < codec_max_aux_devs) {
+		dev_dbg(&pdev->dev,
+			"%s: codec_max_aux_devs = %d cannot exceed codec_aux_dev_cnt = %d\n",
+			__func__, codec_max_aux_devs,
+			codec_aux_dev_cnt);
+		codec_max_aux_devs = codec_aux_dev_cnt;
+	}
+
+	/*
+	 * Alloc mem to store phandle and index info of aux codec
+	 * if already registered with ALSA core
+	 */
+	aux_cdc_dev_info = devm_kcalloc(&pdev->dev, codec_aux_dev_cnt,
+				sizeof(struct aux_codec_dev_info),
+				GFP_KERNEL);
+	if (!aux_cdc_dev_info) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * search and check whether all aux codecs are already
+	 * registered with ALSA core or not. If found a node, store
+	 * the node and the index in a local array of struct for later
+	 * use.
+	 */
+	for (i = 0; i < codec_aux_dev_cnt; i++) {
+		aux_codec_of_node = of_parse_phandle(pdev->dev.of_node,
+					    "qcom,codec-aux-devs", i);
+		if (unlikely(!aux_codec_of_node)) {
+			/* we should not be here */
+			dev_err(&pdev->dev,
+				"%s: aux codec dev node is not present\n",
+				__func__);
+			ret = -EINVAL;
+			goto err;
+		}
+		if (soc_find_component(aux_codec_of_node, NULL)) {
+			/* AUX codec registered with ALSA core */
+			aux_cdc_dev_info[codecs_found].of_node =
+						aux_codec_of_node;
+			aux_cdc_dev_info[codecs_found].index = i;
+			codecs_found++;
+		}
+	}
+
+	if (codecs_found < codec_aux_dev_cnt) {
+		dev_dbg(&pdev->dev,
+			"%s: failed to find %d components. Found only %d\n",
+			__func__, codec_aux_dev_cnt, codecs_found);
+		return -EPROBE_DEFER;
+	}
+	dev_info(&pdev->dev,
+		"%s: found %d AUX codecs registered with ALSA core\n",
+		__func__, codecs_found);
+
+aux_dev_register:
+	card->num_aux_devs = wsa_max_devs + codec_aux_dev_cnt;
+	card->num_configs = wsa_max_devs + codec_aux_dev_cnt;
+
+	/* Alloc array of AUX devs struct */
+	msm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs,
+				       sizeof(struct snd_soc_aux_dev),
+				       GFP_KERNEL);
+	if (!msm_aux_dev) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Alloc array of codec conf struct */
+	msm_codec_conf = devm_kcalloc(&pdev->dev, card->num_configs,
+					  sizeof(struct snd_soc_codec_conf),
+					  GFP_KERNEL);
+	if (!msm_codec_conf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < wsa_max_devs; i++) {
+		dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN,
+					    GFP_KERNEL);
+		if (!dev_name_str) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		ret = of_property_read_string_index(pdev->dev.of_node,
+						    "qcom,wsa-aux-dev-prefix",
+						    wsa881x_dev_info[i].index,
+						    auxdev_name_prefix);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: failed to read wsa aux dev prefix, ret = %d\n",
+				__func__, ret);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i);
+		msm_aux_dev[i].name = dev_name_str;
+		msm_aux_dev[i].codec_name = NULL;
+		msm_aux_dev[i].codec_of_node =
+					wsa881x_dev_info[i].of_node;
+		msm_aux_dev[i].init = NULL;
+		msm_codec_conf[i].dev_name = NULL;
+		msm_codec_conf[i].name_prefix = auxdev_name_prefix[0];
+		msm_codec_conf[i].of_node =
+				wsa881x_dev_info[i].of_node;
+	}
+
+	for (i = 0; i < codec_aux_dev_cnt; i++) {
+		msm_aux_dev[wsa_max_devs + i].name = NULL;
+		msm_aux_dev[wsa_max_devs + i].codec_name = NULL;
+		msm_aux_dev[wsa_max_devs + i].codec_of_node =
+					aux_cdc_dev_info[i].of_node;
+		msm_aux_dev[wsa_max_devs + i].init =  msm_aux_codec_init;
+		msm_codec_conf[wsa_max_devs + i].dev_name = NULL;
+		msm_codec_conf[wsa_max_devs + i].name_prefix =
+						NULL;
+		msm_codec_conf[wsa_max_devs + i].of_node =
+				aux_cdc_dev_info[i].of_node;
+	}
+
+	card->codec_conf = msm_codec_conf;
+	card->aux_dev = msm_aux_dev;
+err:
+	return ret;
+}
+
+static void msm_i2s_auxpcm_init(struct platform_device *pdev)
+{
+	int count = 0;
+	u32 mi2s_master_slave[MI2S_MAX];
+	int ret = 0;
+
+	for (count = 0; count < MI2S_MAX; count++) {
+		mutex_init(&mi2s_intf_conf[count].lock);
+		mi2s_intf_conf[count].ref_cnt = 0;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,msm-mi2s-master",
+			mi2s_master_slave, MI2S_MAX);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: no qcom,msm-mi2s-master in DT node\n",
+			__func__);
+	} else {
+		for (count = 0; count < MI2S_MAX; count++) {
+			mi2s_intf_conf[count].msm_is_mi2s_master =
+				mi2s_master_slave[count];
+		}
+	}
+}
+
+static void msm_i2s_auxpcm_deinit(void)
+{
+	int count = 0;
+
+	for (count = 0; count < MI2S_MAX; count++) {
+		mutex_destroy(&mi2s_intf_conf[count].lock);
+		mi2s_intf_conf[count].ref_cnt = 0;
+		mi2s_intf_conf[count].msm_is_mi2s_master = 0;
+	}
+}
+
+static int bengal_ssr_enable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!strcmp(card->name, "bengal-stub-snd-card")) {
+		/* TODO */
+		dev_dbg(dev, "%s: TODO\n", __func__);
+	}
+
+	snd_soc_card_change_online_state(card, 1);
+	dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
+
+err:
+	return ret;
+}
+
+static void bengal_ssr_disable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		return;
+	}
+
+	dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
+	snd_soc_card_change_online_state(card, 0);
+
+	if (!strcmp(card->name, "bengal-stub-snd-card")) {
+		/* TODO */
+		dev_dbg(dev, "%s: TODO\n", __func__);
+	}
+}
+
+static const struct snd_event_ops bengal_ssr_ops = {
+	.enable = bengal_ssr_enable,
+	.disable = bengal_ssr_disable,
+};
+
+static int msm_audio_ssr_compare(struct device *dev, void *data)
+{
+	struct device_node *node = data;
+
+	dev_dbg(dev, "%s: dev->of_node = 0x%p, node = 0x%p\n",
+		__func__, dev->of_node, node);
+	return (dev->of_node && dev->of_node == node);
+}
+
+static int msm_audio_ssr_register(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct snd_event_clients *ssr_clients = NULL;
+	struct device_node *node = NULL;
+	int ret = 0;
+	int i = 0;
+
+	for (i = 0; ; i++) {
+		node = of_parse_phandle(np, "qcom,msm_audio_ssr_devs", i);
+		if (!node)
+			break;
+		snd_event_mstr_add_client(&ssr_clients,
+					msm_audio_ssr_compare, node);
+	}
+
+	ret = snd_event_master_register(dev, &bengal_ssr_ops,
+					ssr_clients, NULL);
+	if (!ret)
+		snd_event_notify(dev, SND_EVENT_UP);
+
+	return ret;
+}
+
+static int msm_asoc_machine_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct msm_asoc_mach_data *pdata = NULL;
+	const char *mbhc_audio_jack_type = NULL;
+	int ret = 0;
+	uint index = 0;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev,
+			"%s: No platform supplied from device tree\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct msm_asoc_mach_data), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	card = populate_snd_card_dailinks(&pdev->dev);
+	if (!card) {
+		dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, pdata);
+
+	ret = snd_soc_of_parse_card_name(card, "qcom,model");
+	if (ret) {
+		dev_err(&pdev->dev, "%s: parse card name failed, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
+	if (ret) {
+		dev_err(&pdev->dev, "%s: parse audio routing failed, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = msm_populate_dai_link_component_of_node(card);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
+
+	ret = msm_init_aux_dev(pdev, card);
+	if (ret)
+		goto err;
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret == -EPROBE_DEFER) {
+		if (codec_reg_done)
+			ret = -EINVAL;
+		goto err;
+	} else if (ret) {
+		dev_err(&pdev->dev, "%s: snd_soc_register_card failed (%d)\n",
+			__func__, ret);
+		goto err;
+	}
+	dev_info(&pdev->dev, "%s: Sound card %s registered\n",
+		 __func__, card->name);
+
+	pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
+						"qcom,hph-en1-gpio", 0);
+	if (!pdata->hph_en1_gpio_p) {
+		dev_dbg(&pdev->dev, "%s: property %s not detected in node %s\n",
+			__func__, "qcom,hph-en1-gpio",
+			pdev->dev.of_node->full_name);
+	}
+
+	pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
+						"qcom,hph-en0-gpio", 0);
+	if (!pdata->hph_en0_gpio_p) {
+		dev_dbg(&pdev->dev, "%s: property %s not detected in node %s\n",
+			__func__, "qcom,hph-en0-gpio",
+			pdev->dev.of_node->full_name);
+	}
+
+	ret = of_property_read_string(pdev->dev.of_node,
+		"qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, "qcom,mbhc-audio-jack-type",
+			pdev->dev.of_node->full_name);
+		dev_dbg(&pdev->dev, "Jack type properties set to default\n");
+	} else {
+		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
+			dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
+		} else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
+			dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
+		} else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
+			dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
+		} else {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
+			dev_dbg(&pdev->dev, "Unknown value, set to default\n");
+		}
+	}
+	/*
+	 * Parse US-Euro gpio info from DT. Report no error if us-euro
+	 * entry is not found in DT file as some targets do not support
+	 * US-Euro detection
+	 */
+	pdata->us_euro_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,us-euro-gpios", 0);
+	if (!pdata->us_euro_gpio_p) {
+		dev_dbg(&pdev->dev, "property %s not detected in node %s",
+			"qcom,us-euro-gpios", pdev->dev.of_node->full_name);
+	} else {
+		dev_dbg(&pdev->dev, "%s detected\n",
+			"qcom,us-euro-gpios");
+		wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
+	}
+
+	if (wcd_mbhc_cfg.enable_usbc_analog)
+		wcd_mbhc_cfg.swap_gnd_mic = msm_usbc_swap_gnd_mic;
+
+	pdata->fsa_handle = of_parse_phandle(pdev->dev.of_node,
+					"fsa4480-i2c-handle", 0);
+	if (!pdata->fsa_handle)
+		dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
+			"fsa4480-i2c-handle", pdev->dev.of_node->full_name);
+
+	msm_i2s_auxpcm_init(pdev);
+	pdata->dmic01_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					      "qcom,cdc-dmic01-gpios",
+					       0);
+	pdata->dmic23_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					      "qcom,cdc-dmic23-gpios",
+					       0);
+
+	pdata->mi2s_gpio_p[PRIM_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,pri-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[SEC_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,sec-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[TERT_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,tert-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[QUAT_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,quat-mi2s-gpios", 0);
+	for (index = PRIM_MI2S; index < MI2S_MAX; index++)
+		atomic_set(&(pdata->mi2s_gpio_ref_count[index]), 0);
+
+	ret = msm_audio_ssr_register(&pdev->dev);
+	if (ret)
+		pr_err("%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+
+	is_initial_boot = true;
+
+	return 0;
+err:
+	devm_kfree(&pdev->dev, pdata);
+	return ret;
+}
+
+static int msm_asoc_machine_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_event_master_deregister(&pdev->dev);
+	snd_soc_unregister_card(card);
+	msm_i2s_auxpcm_deinit();
+
+	return 0;
+}
+
+static struct platform_driver bengal_asoc_machine_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = bengal_asoc_machine_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = msm_asoc_machine_probe,
+	.remove = msm_asoc_machine_remove,
+};
+module_platform_driver(bengal_asoc_machine_driver);
+
+MODULE_DESCRIPTION("ALSA SoC msm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, bengal_asoc_machine_of_match);
diff --git a/asoc/codecs/Android.mk b/asoc/codecs/Android.mk
index fb00efb..5e3114e 100644
--- a/asoc/codecs/Android.mk
+++ b/asoc/codecs/Android.mk
@@ -31,6 +31,10 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_LITO=m
 endif
 
+ifeq ($(call is-board-platform,bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
 ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) $(TRINKET) kona lito bengal sdmshrike),true)
@@ -107,6 +111,7 @@
 include $(DLKM_DIR)/AndroidKernelModule.mk
 endif
 ###########################################################
+ifneq ($(call is-board-platform-in-list, bengal),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_wsa881x.ko
 LOCAL_MODULE_KBUILD_NAME  := wsa881x_dlkm.ko
@@ -114,6 +119,17 @@
 LOCAL_MODULE_DEBUG_ENABLE := true
 LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
 include $(DLKM_DIR)/AndroidKernelModule.mk
+endif
+###########################################################
+ifeq ($(call is-board-platform-in-list, bengal),true)
+include $(CLEAR_VARS)
+LOCAL_MODULE              := $(AUDIO_CHIPSET)_wsa881x_analog.ko
+LOCAL_MODULE_KBUILD_NAME  := wsa881x_analog_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/AndroidKernelModule.mk
+endif
 ###########################################################
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_mbhc.ko
@@ -132,6 +148,7 @@
 LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
 include $(DLKM_DIR)/AndroidKernelModule.mk
 ###########################################################
+ifneq ($(call is-board-platform-in-list, bengal),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_hdmi.ko
 LOCAL_MODULE_KBUILD_NAME  := hdmi_dlkm.ko
@@ -139,6 +156,7 @@
 LOCAL_MODULE_DEBUG_ENABLE := true
 LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
 include $(DLKM_DIR)/AndroidKernelModule.mk
+endif
 ###########################################################
 
 endif # DLKM check
diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild
index b8abfc4..1ce059e 100644
--- a/asoc/codecs/Kbuild
+++ b/asoc/codecs/Kbuild
@@ -51,9 +51,9 @@
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
+		include $(AUDIO_ROOT)/config/bengalauto.conf
 		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_SDMSHRIKE), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
@@ -143,6 +143,12 @@
 	WSA881X_OBJS += wsa881x-temp-sensor.o
 endif
 
+ifdef CONFIG_SND_SOC_WSA881X_ANALOG
+	WSA881X_ANALOG_OBJS += wsa881x-analog.o
+	WSA881X_ANALOG_OBJS += wsa881x-tables-analog.o
+	WSA881X_ANALOG_OBJS += wsa881x-regmap-analog.o
+	WSA881X_ANALOG_OBJS += wsa881x-temp-sensor.o
+endif
 ifdef CONFIG_SND_SOC_MSM_STUB
 	STUB_OBJS += msm_stub.o
 endif
@@ -235,6 +241,9 @@
 obj-$(CONFIG_SND_SOC_WSA881X) += wsa881x_dlkm.o
 wsa881x_dlkm-y := $(WSA881X_OBJS)
 
+obj-$(CONFIG_SND_SOC_WSA881X_ANALOG) += wsa881x_analog_dlkm.o
+wsa881x_analog_dlkm-y := $(WSA881X_ANALOG_OBJS)
+
 obj-$(CONFIG_SND_SOC_MSM_STUB) += stub_dlkm.o
 stub_dlkm-y := $(STUB_OBJS)
 
diff --git a/asoc/codecs/bolero/Android.mk b/asoc/codecs/bolero/Android.mk
index 9d1274f..5764412 100644
--- a/asoc/codecs/bolero/Android.mk
+++ b/asoc/codecs/bolero/Android.mk
@@ -15,6 +15,10 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_LITO=m
 endif
 
+ifeq ($(call is-board-platform,bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
 ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET) kona lito bengal),true)
@@ -52,6 +56,7 @@
 LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
 include $(DLKM_DIR)/AndroidKernelModule.mk
 ###########################################################
+ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET) kona lito),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_wsa_macro.ko
 LOCAL_MODULE_KBUILD_NAME  := wsa_macro_dlkm.ko
@@ -59,6 +64,7 @@
 LOCAL_MODULE_DEBUG_ENABLE := true
 LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
 include $(DLKM_DIR)/AndroidKernelModule.mk
+endif
 ###########################################################
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_va_macro.ko
diff --git a/asoc/codecs/bolero/Kbuild b/asoc/codecs/bolero/Kbuild
index e6517f8..15e5dc5 100644
--- a/asoc/codecs/bolero/Kbuild
+++ b/asoc/codecs/bolero/Kbuild
@@ -36,9 +36,9 @@
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
+		include $(AUDIO_ROOT)/config/bengalauto.conf
 		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_QCS405), y)
 		include $(AUDIO_ROOT)/config/qcs405auto.conf
diff --git a/asoc/codecs/bolero/bolero-cdc-registers.h b/asoc/codecs/bolero/bolero-cdc-registers.h
index 99890cc..e68e314 100644
--- a/asoc/codecs/bolero/bolero-cdc-registers.h
+++ b/asoc/codecs/bolero/bolero-cdc-registers.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _BOLERO_CDC_REGISTERS_H
@@ -696,6 +696,7 @@
 #define BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL	(VA_START_OFFSET + 0x0000)
 #define BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL \
 						(VA_START_OFFSET + 0x0004)
+#define BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL	(VA_START_OFFSET + 0x0008)
 #define BOLERO_CDC_VA_TOP_CSR_TOP_CFG0		(VA_START_OFFSET + 0x0080)
 #define BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL		(VA_START_OFFSET + 0x0084)
 #define BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL		(VA_START_OFFSET + 0x0088)
@@ -715,6 +716,11 @@
 
 #define BOLERO_CDC_VA_MACRO_TOP_MAX 0x34 /* 0x0CC/4 = 0x33 + 1 = 0x34 */
 
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0	(VA_START_OFFSET + 0x00D0)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1	(VA_START_OFFSET + 0x00D4)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2	(VA_START_OFFSET + 0x00D8)
+#define BOLERO_CDC_VA_TOP_CSR_SWR_CTRL		(VA_START_OFFSET + 0x00DC)
+
 #define BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0	(VA_START_OFFSET + 0x0100)
 #define BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1	(VA_START_OFFSET + 0x0104)
 #define BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0	(VA_START_OFFSET + 0x0108)
diff --git a/asoc/codecs/bolero/bolero-cdc-regmap.c b/asoc/codecs/bolero/bolero-cdc-regmap.c
index a0ecd83..77f5420 100644
--- a/asoc/codecs/bolero/bolero-cdc-regmap.c
+++ b/asoc/codecs/bolero/bolero-cdc-regmap.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/regmap.h>
@@ -609,6 +609,7 @@
 	/* VA macro */
 	{ BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00},
 	{ BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00},
+	{ BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_TOP_CFG0, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL, 0x00},
@@ -624,6 +625,10 @@
 	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_1, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_2, 0x00},
 	{ BOLERO_CDC_VA_TOP_CSR_CORE_ID_3, 0x00},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE},
+	{ BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0x06},
 
 	/* VA core */
 	{ BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00},
@@ -809,9 +814,13 @@
 	case BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FMAX_CNTR_MSB:
 	case BOLERO_CDC_WSA_SPLINE_ASRC1_STATUS_FIFO:
 	case BOLERO_CDC_RX_TOP_HPHL_COMP_RD_LSB:
+	case BOLERO_CDC_RX_TOP_HPHL_COMP_WR_LSB:
 	case BOLERO_CDC_RX_TOP_HPHL_COMP_RD_MSB:
+	case BOLERO_CDC_RX_TOP_HPHL_COMP_WR_MSB:
 	case BOLERO_CDC_RX_TOP_HPHR_COMP_RD_LSB:
+	case BOLERO_CDC_RX_TOP_HPHR_COMP_WR_LSB:
 	case BOLERO_CDC_RX_TOP_HPHR_COMP_RD_MSB:
+	case BOLERO_CDC_RX_TOP_HPHR_COMP_WR_MSB:
 	case BOLERO_CDC_RX_TOP_DSD0_DEBUG_CFG2:
 	case BOLERO_CDC_RX_TOP_DSD1_DEBUG_CFG2:
 	case BOLERO_CDC_RX_BCL_VBAT_GAIN_MON_VAL:
diff --git a/asoc/codecs/bolero/bolero-cdc-tables.c b/asoc/codecs/bolero/bolero-cdc-tables.c
index 5298763..5d0d353 100644
--- a/asoc/codecs/bolero/bolero-cdc-tables.c
+++ b/asoc/codecs/bolero/bolero-cdc-tables.c
@@ -149,6 +149,96 @@
 	[BOLERO_REG(BOLERO_CDC_TX7_TX_PATH_SEC6)] = RD_WR_REG,
 };
 
+u8 bolero_tx_reg_access_v2[BOLERO_CDC_TX_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_ANC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_CLK_RESET_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_MODE_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_SHIFT)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_A_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FF_B_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_LPF_FB_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_SMLPF_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_DCFLT_SHIFT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_ADAPT_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_IIR_COEFF_2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_A_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FF_B_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_ANC0_FB_GAIN_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
 u8 bolero_rx_reg_access[BOLERO_CDC_RX_MACRO_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_RX_TOP_TOP_CFG0)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_RX_TOP_SWR_CTRL)] = RD_WR_REG,
@@ -442,6 +532,7 @@
 u8 bolero_va_reg_access[BOLERO_CDC_VA_MACRO_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
@@ -567,6 +658,7 @@
 u8 bolero_va_top_reg_access[BOLERO_CDC_VA_MACRO_TOP_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
@@ -579,6 +671,132 @@
 	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
 };
 
+u8 bolero_va_reg_access_v2[BOLERO_CDC_VA_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
+u8 bolero_va_reg_access_v3[BOLERO_CDC_VA_MACRO_MAX] = {
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TOP_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DMIC_CFG)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_BUS)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_DEBUG_EN)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_TX_I2S_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_CLK)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_I2S_RESET)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_0)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_1)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_2)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_CORE_ID_3)] = RD_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_MIC_CTL2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TOP_CSR_SWR_CTRL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX0_TX_PATH_SEC7)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX1_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX2_TX_PATH_SEC6)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_CFG1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_VOL_CTL)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC0)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC1)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC2)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC3)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC4)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC5)] = RD_WR_REG,
+	[BOLERO_REG(BOLERO_CDC_VA_TX3_TX_PATH_SEC6)] = RD_WR_REG,
+};
+
 u8 bolero_wsa_reg_access[BOLERO_CDC_WSA_MACRO_MAX] = {
 	[BOLERO_REG(BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL)] = RD_WR_REG,
 	[BOLERO_REG(BOLERO_CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL)] = RD_WR_REG,
diff --git a/asoc/codecs/bolero/bolero-cdc-utils.c b/asoc/codecs/bolero/bolero-cdc-utils.c
index b2fd153..f2e4ec4 100644
--- a/asoc/codecs/bolero/bolero-cdc-utils.c
+++ b/asoc/codecs/bolero/bolero-cdc-utils.c
@@ -68,12 +68,9 @@
 	reg_p = (u16 *)reg;
 	macro_id = bolero_get_macro_id(priv->va_without_decimation,
 					   reg_p[0]);
-	if (macro_id < 0 || !priv->macros_supported[macro_id]) {
-		dev_err_ratelimited(dev,
-			"%s: Unsupported macro %d or reg 0x%x is invalid\n",
-			__func__, macro_id, reg_p[0]);
-		return ret;
-	}
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
 	mutex_lock(&priv->io_lock);
 	for (i = 0; i < val_size; i++) {
 		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
@@ -121,12 +118,9 @@
 	reg_p = (u16 *)reg;
 	macro_id = bolero_get_macro_id(priv->va_without_decimation,
 					reg_p[0]);
-	if (macro_id < 0 || !priv->macros_supported[macro_id]) {
-		dev_err_ratelimited(dev,
-			"%s: Unsupported macro-id %d or reg 0x%x is invalid\n",
-			__func__, macro_id, reg_p[0]);
-		return ret;
-	}
+	if (macro_id < 0 || !priv->macros_supported[macro_id])
+		return 0;
+
 	mutex_lock(&priv->io_lock);
 	for (i = 0; i < val_size; i++) {
 		__reg = (reg_p[0] + i * 4) - macro_id_base_offset[macro_id];
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 76c9d40..fb182a2 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -20,9 +20,6 @@
 
 #define DRV_NAME "bolero_codec"
 
-#define BOLERO_VERSION_1_0 0x0001
-#define BOLERO_VERSION_1_1 0x0002
-#define BOLERO_VERSION_1_2 0x0003
 #define BOLERO_VERSION_ENTRY_SIZE 32
 #define BOLERO_CDC_STRING_LEN 80
 
@@ -107,21 +104,25 @@
 	if (priv->macro_params[VA_MACRO].dev)
 		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
 
-	/* Request Clk before register access */
-	ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0) {
+		/* Request Clk before register access */
+		ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				true);
-	if (ret < 0) {
-		dev_err_ratelimited(priv->dev,
-			"%s: Failed to enable clock, ret:%d\n", __func__, ret);
-		goto err;
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: Failed to enable clock, ret:%d\n",
+				__func__, ret);
+			goto err;
+		}
 	}
 
 	bolero_ahb_read_device(
 		priv->macro_params[macro_id].io_base, reg, val);
 
-	bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0)
+		bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				false);
@@ -151,21 +152,25 @@
 	if (priv->macro_params[VA_MACRO].dev)
 		pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev);
 
-	/* Request Clk before register access */
-	ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0) {
+		/* Request Clk before register access */
+		ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				true);
-	if (ret < 0) {
-		dev_err_ratelimited(priv->dev,
-			"%s: Failed to enable clock, ret:%d\n", __func__, ret);
-		goto err;
+		if (ret < 0) {
+			dev_err_ratelimited(priv->dev,
+				"%s: Failed to enable clock, ret:%d\n",
+				__func__, ret);
+			goto err;
+		}
 	}
 
 	bolero_ahb_write_device(
 			priv->macro_params[macro_id].io_base, reg, val);
 
-	bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
+	if (priv->version < BOLERO_VERSION_2_0)
+		bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev,
 				priv->macro_params[macro_id].default_clk_id,
 				priv->macro_params[macro_id].clk_id_req,
 				false);
@@ -214,6 +219,12 @@
 				priv->component,
 				BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST, data);
 		break;
+	case WCD_BOLERO_EVT_BCS_CLK_OFF:
+		if (priv->macro_params[TX_MACRO].event_handler)
+			priv->macro_params[TX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_BCS_CLK_OFF, data);
+		break;
 	default:
 		dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n",
 			__func__, event);
@@ -507,11 +518,17 @@
 		priv->macro_params[macro_id].reg_evt_listener =
 							ops->reg_evt_listener;
 	}
-
+	if (priv->version == BOLERO_VERSION_2_1) {
+		if (macro_id == VA_MACRO)
+			priv->macro_params[macro_id].reg_wake_irq =
+						ops->reg_wake_irq;
+	}
 	priv->num_dais += ops->num_dais;
 	priv->num_macros_registered++;
 	priv->macros_supported[macro_id] = true;
 
+	dev_dbg(dev, "%s: register macro successful:%d\n", macro_id);
+
 	if (priv->num_macros_registered == priv->num_macros) {
 		ret = bolero_copy_dais_from_macro(priv);
 		if (ret < 0) {
@@ -604,6 +621,28 @@
 }
 EXPORT_SYMBOL(bolero_wsa_pa_on);
 
+int bolero_get_version(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return -EINVAL;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device for macro not added yet\n",
+			__func__);
+		return -EINVAL;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return -EINVAL;
+	}
+	return priv->version;
+}
+EXPORT_SYMBOL(bolero_get_version);
+
 static ssize_t bolero_version_read(struct snd_info_entry *entry,
 				   void *file_private_data,
 				   struct file *file,
@@ -630,6 +669,9 @@
 	case BOLERO_VERSION_1_2:
 		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_2\n");
 		break;
+	case BOLERO_VERSION_2_1:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_2_1\n");
+		break;
 	default:
 		len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
 	}
@@ -661,7 +703,11 @@
 	priv->dev_up = true;
 	mutex_unlock(&priv->clk_lock);
 	regcache_mark_dirty(priv->regmap);
+	bolero_clk_rsc_enable_all_clocks(priv->clk_dev, true);
 	regcache_sync(priv->regmap);
+	/* Add a 100usec sleep to ensure last register write is done */
+	usleep_range(100,110);
+	bolero_clk_rsc_enable_all_clocks(priv->clk_dev, false);
 	/* call ssr event for supported macros */
 	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
 		if (!priv->macro_params[macro_idx].event_handler)
@@ -679,6 +725,12 @@
 	struct bolero_priv *priv = data;
 	int macro_idx;
 
+	if (!priv->dev_up) {
+		dev_err_ratelimited(priv->dev,
+				    "%s: already disabled\n", __func__);
+		return;
+	}
+
 	bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_PA_OFF_PRE_SSR);
 	regcache_cache_only(priv->regmap, true);
 
@@ -790,9 +842,15 @@
 		return -EINVAL;
 	}
 
-	if (priv->macro_params[TX_MACRO].reg_wake_irq)
-		priv->macro_params[TX_MACRO].reg_wake_irq(
-				component, ipc_wakeup);
+	if (priv->version == BOLERO_VERSION_2_1) {
+		if (priv->macro_params[VA_MACRO].reg_wake_irq)
+			priv->macro_params[VA_MACRO].reg_wake_irq(
+					component, ipc_wakeup);
+	} else {
+		if (priv->macro_params[TX_MACRO].reg_wake_irq)
+			priv->macro_params[TX_MACRO].reg_wake_irq(
+					component, ipc_wakeup);
+	}
 
 	return 0;
 }
@@ -871,6 +929,29 @@
 
 	snd_soc_component_init_regmap(component, priv->regmap);
 
+	if (!priv->version) {
+		/*
+		 * In order for the ADIE RTC to differentiate between targets
+		 * version info is used.
+		 * Assign 1.0 for target with only one macro
+		 * Assign 1.1 for target with two macros
+		 * Assign 1.2 for target with more than two macros
+		 */
+		if (priv->num_macros_registered == 1)
+			priv->version = BOLERO_VERSION_1_0;
+		else if (priv->num_macros_registered == 2)
+			priv->version = BOLERO_VERSION_1_1;
+		else if (priv->num_macros_registered > 2)
+			priv->version = BOLERO_VERSION_1_2;
+	}
+
+	/* Assign bolero version 2.1 for bolero 2.1 */
+	if ((snd_soc_component_read32(component,
+		BOLERO_CDC_VA_TOP_CSR_CORE_ID_0) == 0x2) &&
+		(snd_soc_component_read32(component,
+			BOLERO_CDC_VA_TOP_CSR_CORE_ID_1) == 0xE))
+		priv->version = BOLERO_VERSION_2_1;
+
 	/* call init for supported macros */
 	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
 		if (priv->macro_params[macro_idx].init) {
@@ -884,19 +965,6 @@
 		}
 	}
 	priv->component = component;
-	/*
-	 * In order for the ADIE RTC to differentiate between targets
-	 * version info is used.
-	 * Assign 1.0 for target with only one macro
-	 * Assign 1.1 for target with two macros
-	 * Assign 1.2 for target with more than two macros
-	 */
-	if (priv->num_macros_registered == 1)
-		priv->version = BOLERO_VERSION_1_0;
-	else if (priv->num_macros_registered == 2)
-		priv->version = BOLERO_VERSION_1_1;
-	else if (priv->num_macros_registered > 2)
-		priv->version = BOLERO_VERSION_1_2;
 
 	ret = snd_event_client_register(priv->dev, &bolero_ssr_ops, priv);
 	if (!ret) {
@@ -981,10 +1049,9 @@
 		pdev->dev.parent = priv->dev;
 		pdev->dev.of_node = node;
 
-		if (split_codec) {
-			priv->dev->platform_data = platdata;
+		priv->dev->platform_data = platdata;
+		if (split_codec)
 			priv->wcd_dev = &pdev->dev;
-		}
 
 		ret = platform_device_add(pdev);
 		if (ret) {
@@ -1040,6 +1107,20 @@
 	if (priv->va_without_decimation)
 		bolero_reg_access[VA_MACRO] = bolero_va_top_reg_access;
 
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,bolero-version", &priv->version);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s:bolero version not specified\n",
+			__func__);
+		ret = 0;
+	}
+	if (priv->version == BOLERO_VERSION_2_1) {
+		bolero_reg_access[TX_MACRO] = bolero_tx_reg_access_v2;
+		bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v2;
+	} else if (priv->version == BOLERO_VERSION_2_0) {
+		bolero_reg_access[VA_MACRO] = bolero_va_reg_access_v3;
+	}
+
 	priv->dev = &pdev->dev;
 	priv->dev_up = true;
 	priv->initial_boot = true;
@@ -1111,12 +1192,12 @@
 	struct bolero_priv *priv = dev_get_drvdata(dev->parent);
 	int ret = 0;
 
+	mutex_lock(&priv->vote_lock);
 	if (priv->lpass_core_hw_vote == NULL) {
 		dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__);
-		return 0;
+		goto audio_vote;
 	}
 
-	mutex_lock(&priv->vote_lock);
 	if (priv->core_hw_vote_count == 0) {
 		ret = clk_prepare_enable(priv->lpass_core_hw_vote);
 		if (ret < 0) {
@@ -1180,6 +1261,21 @@
 }
 EXPORT_SYMBOL(bolero_runtime_suspend);
 
+bool bolero_check_core_votes(struct device *dev)
+{
+	struct bolero_priv *priv = dev_get_drvdata(dev->parent);
+	bool ret = true;
+
+	mutex_lock(&priv->vote_lock);
+	if ((priv->lpass_core_hw_vote && !priv->core_hw_vote_count) ||
+		(priv->lpass_audio_hw_vote && !priv->core_audio_vote_count))
+		ret = false;
+	mutex_unlock(&priv->vote_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(bolero_check_core_votes);
+
 static const struct of_device_id bolero_dt_match[] = {
 	{.compatible = "qcom,bolero-codec"},
 	{}
diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h
index 957389c..2ec4617 100644
--- a/asoc/codecs/bolero/bolero-cdc.h
+++ b/asoc/codecs/bolero/bolero-cdc.h
@@ -8,6 +8,12 @@
 #include <sound/soc.h>
 #include <linux/regmap.h>
 
+#define BOLERO_VERSION_1_0 0x0001
+#define BOLERO_VERSION_1_1 0x0002
+#define BOLERO_VERSION_1_2 0x0003
+#define BOLERO_VERSION_2_0 0x0004
+#define BOLERO_VERSION_2_1 0x0005
+
 enum {
 	START_MACRO,
 	TX_MACRO = START_MACRO,
@@ -40,7 +46,8 @@
 	BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET,
 	BOLERO_MACRO_EVT_CLK_RESET,
 	BOLERO_MACRO_EVT_REG_WAKE_IRQ,
-	BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST
+	BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST,
+	BOLERO_MACRO_EVT_BCS_CLK_OFF
 };
 
 struct macro_ops {
@@ -84,6 +91,8 @@
 int bolero_register_event_listener(struct snd_soc_component *component,
 				   bool enable);
 void bolero_wsa_pa_on(struct device *dev);
+bool bolero_check_core_votes(struct device *dev);
+int bolero_get_version(struct device *dev);
 #else
 static inline int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb)
 {
@@ -158,5 +167,15 @@
 static void bolero_wsa_pa_on(struct device *dev)
 {
 }
+
+static inline bool bolero_check_core_votes(struct device *dev)
+{
+	return false;
+}
+
+static int bolero_get_version(struct device *dev)
+{
+	return 0;
+}
 #endif /* CONFIG_SND_SOC_BOLERO */
 #endif /* BOLERO_CDC_H */
diff --git a/asoc/codecs/bolero/bolero-clk-rsc.c b/asoc/codecs/bolero/bolero-clk-rsc.c
index 4940f67..b80a267 100644
--- a/asoc/codecs/bolero/bolero-clk-rsc.c
+++ b/asoc/codecs/bolero/bolero-clk-rsc.c
@@ -137,6 +137,49 @@
 }
 EXPORT_SYMBOL(bolero_rsc_clk_reset);
 
+void bolero_clk_rsc_enable_all_clocks(struct device *dev, bool enable)
+{
+	struct device *clk_dev = NULL;
+	struct bolero_clk_rsc *priv = NULL;
+	int i = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null %d\n", __func__);
+		return;
+	}
+
+	clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return;
+	}
+
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk private data\n", __func__);
+		return;
+	}
+	mutex_lock(&priv->rsc_clk_lock);
+	for (i = 0; i < MAX_CLK - NPL_CLK_OFFSET; i++) {
+		if (enable) {
+			if (priv->clk[i])
+				clk_prepare_enable(priv->clk[i]);
+			if (priv->clk[i + NPL_CLK_OFFSET])
+				clk_prepare_enable(
+					priv->clk[i + NPL_CLK_OFFSET]);
+		} else {
+			if (priv->clk[i + NPL_CLK_OFFSET])
+				clk_disable_unprepare(
+					priv->clk[i + NPL_CLK_OFFSET]);
+			if (priv->clk[i])
+				clk_disable_unprepare(priv->clk[i]);
+		}
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+	return;
+}
+EXPORT_SYMBOL(bolero_clk_rsc_enable_all_clocks);
+
 static int bolero_clk_rsc_mux0_clk_request(struct bolero_clk_rsc *priv,
 					   int clk_id,
 					   bool enable)
diff --git a/asoc/codecs/bolero/bolero-clk-rsc.h b/asoc/codecs/bolero/bolero-clk-rsc.h
index fc3c02f..cc8ee39 100644
--- a/asoc/codecs/bolero/bolero-clk-rsc.h
+++ b/asoc/codecs/bolero/bolero-clk-rsc.h
@@ -19,6 +19,7 @@
 				int clk_id_req,
 				bool enable);
 int bolero_rsc_clk_reset(struct device *dev, int clk_id);
+void bolero_clk_rsc_enable_all_clocks(struct device *dev, bool enable);
 #else
 static inline void bolero_clk_rsc_fs_gen_request(struct device *dev,
 						bool enable)
@@ -42,5 +43,10 @@
 {
 	return 0;
 }
+static inline void bolero_clk_rsc_enable_all_clocks(struct device *dev,
+						    bool enable)
+{
+	return;
+}
 #endif /* CONFIG_SND_SOC_BOLERO */
 #endif /* BOLERO_CLK_RSC_H */
diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h
index d3f6894..d18568b 100644
--- a/asoc/codecs/bolero/internal.h
+++ b/asoc/codecs/bolero/internal.h
@@ -31,6 +31,7 @@
 	WCD_BOLERO_EVT_IMPED_TRUE,   /* for imped true */
 	WCD_BOLERO_EVT_IMPED_FALSE,  /* for imped false */
 	WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
+	WCD_BOLERO_EVT_BCS_CLK_OFF,
 };
 
 struct wcd_ctrl_platform_data {
@@ -90,6 +91,9 @@
 extern const struct regmap_config bolero_regmap_config;
 extern u8 *bolero_reg_access[MAX_MACRO];
 extern u8 bolero_va_top_reg_access[BOLERO_CDC_VA_MACRO_TOP_MAX];
+extern u8 bolero_va_reg_access_v2[BOLERO_CDC_VA_MACRO_MAX];
+extern u8 bolero_va_reg_access_v3[BOLERO_CDC_VA_MACRO_MAX];
+extern u8 bolero_tx_reg_access_v2[BOLERO_CDC_TX_MACRO_MAX];
 extern const u16 macro_id_base_offset[MAX_MACRO];
 
 #endif
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index 07b7b30..a9ec81a 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -1350,10 +1350,8 @@
 			goto done;
 		reg = BOLERO_CDC_RX_COMPANDER0_CTL0 +
 				(rx_idx * RX_MACRO_COMP_OFFSET);
-		snd_soc_component_update_bits(component, reg,
-				0x20, 0x20);
-		snd_soc_component_update_bits(component, reg,
-				0x20, 0x00);
+		snd_soc_component_write(component, reg,
+				snd_soc_component_read32(component, reg));
 		break;
 	case BOLERO_MACRO_EVT_IMPED_TRUE:
 		rx_macro_wcd_clsh_imped_config(component, data, true);
@@ -3592,7 +3590,10 @@
 		pm_runtime_mark_last_busy(rx_priv->dev);
 	}
 
-	return 0;
+	if (bolero_check_core_votes(rx_priv->dev))
+		return 0;
+	else
+		return -EINVAL;
 }
 
 static int rx_swrm_clock(void *handle, bool enable)
@@ -4062,6 +4063,7 @@
 	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
 	pm_runtime_enable(&pdev->dev);
 
 	return 0;
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index 97d9f7e..31745d6 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -160,6 +160,8 @@
 	s32 dmic_4_5_clk_cnt;
 	s32 dmic_6_7_clk_cnt;
 	u16 dmic_clk_div;
+	u32 version;
+	u32 is_used_tx_swr_gpio;
 	unsigned long active_ch_mask[TX_MACRO_MAX_DAIS];
 	unsigned long active_ch_cnt[TX_MACRO_MAX_DAIS];
 	char __iomem *tx_io_base;
@@ -172,6 +174,8 @@
 	int tx_clk_status;
 	bool bcs_enable;
 	int dec_mode[NUM_DECIMATORS];
+	bool bcs_clk_en;
+	bool hs_slow_insert_complete;
 };
 
 static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -387,6 +391,15 @@
 	case BOLERO_MACRO_EVT_CLK_RESET:
 		bolero_rsc_clk_reset(tx_dev, TX_CORE_CLK);
 		break;
+	case BOLERO_MACRO_EVT_BCS_CLK_OFF:
+		if (tx_priv->bcs_clk_en)
+			snd_soc_component_update_bits(component,
+				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, data << 6);
+		if (data)
+			tx_priv->hs_slow_insert_complete = true;
+		else
+			tx_priv->hs_slow_insert_complete = false;
+		break;
 	}
 	return 0;
 }
@@ -450,10 +463,10 @@
 	snd_soc_component_update_bits(component,
 			dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
 			hpf_cut_off_freq << 5);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x02);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x02);
 	/* Minimum 1 clk cycle delay is required as per HW spec */
 	usleep_range(1000, 1010);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x01);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x00);
 }
 
 static void tx_macro_mute_update_callback(struct work_struct *work)
@@ -865,6 +878,10 @@
 			tx_vol_ctl_reg, 0x20, 0x20);
 		snd_soc_component_update_bits(component,
 			hpf_gate_reg, 0x01, 0x00);
+		/*
+		 * Minimum 1 clk cycle delay is required as per HW spec
+		 */
+		usleep_range(1000, 1010);
 
 		hpf_cut_off_freq = (
 			snd_soc_component_read32(component, dec_cfg_reg) &
@@ -887,7 +904,7 @@
 					&tx_priv->tx_hpf_work[decimator].dwork,
 					msecs_to_jiffies(300));
 			snd_soc_component_update_bits(component,
-					hpf_gate_reg, 0x02, 0x02);
+					hpf_gate_reg, 0x03, 0x03);
 			/*
 			 * Minimum 1 clk cycle delay is required as per HW spec
 			 */
@@ -902,8 +919,11 @@
 		if (tx_priv->bcs_enable) {
 			snd_soc_component_update_bits(component, dec_cfg_reg,
 					0x01, 0x01);
-			snd_soc_component_update_bits(component,
-				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x40);
+			tx_priv->bcs_clk_en = true;
+			if (tx_priv->hs_slow_insert_complete)
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40,
+					0x40);
 		}
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
@@ -946,6 +966,7 @@
 					0x01, 0x00);
 			snd_soc_component_update_bits(component,
 				BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x00);
+			tx_priv->bcs_clk_en = false;
 		}
 		break;
 	}
@@ -1210,6 +1231,44 @@
 			0, smic_mux_text, snd_soc_dapm_get_enum_double,
 			tx_macro_put_dec_enum);
 
+static const char * const smic_mux_text_v2[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic0_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic1_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic2_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic3_v2, BOLERO_CDC_TX_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic4_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX4_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic5_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX5_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic6_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX6_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
+TX_MACRO_DAPM_ENUM_EXT(tx_smic7_v3, BOLERO_CDC_TX_INP_MUX_ADC_MUX7_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			tx_macro_put_dec_enum);
+
 static const char * const dec_mode_mux_text[] = {
 	"ADC_DEFAULT", "ADC_LOW_PWR", "ADC_HIGH_PERF",
 };
@@ -1275,6 +1334,205 @@
 			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
 };
 
+static const struct snd_kcontrol_new tx_aif1_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif2_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new tx_aif3_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, TX_MACRO_DEC0, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, TX_MACRO_DEC1, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, TX_MACRO_DEC2, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, TX_MACRO_DEC3, 1, 0,
+			tx_macro_tx_mixer_get, tx_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_common[] = {
+	SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF2 CAP", "TX_AIF2 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF2_CAP, 0),
+
+	SND_SOC_DAPM_AIF_OUT("TX_AIF3 CAP", "TX_AIF3 Capture", 0,
+		SND_SOC_NOPM, TX_MACRO_AIF3_CAP, 0),
+
+	TX_MACRO_DAPM_MUX("TX DMIC MUX0", 0, tx_dmic0),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX1", 0, tx_dmic1),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX2", 0, tx_dmic2),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX3", 0, tx_dmic3),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX0", 0, tx_smic0_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX1", 0, tx_smic1_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX2", 0, tx_smic2_v2),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX3", 0, tx_smic3_v2),
+
+	SND_SOC_DAPM_MICBIAS_E("TX MIC BIAS1", SND_SOC_NOPM, 0, 0,
+			       tx_macro_enable_micbias,
+			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("TX DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("TX DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		tx_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("TX SWR_MIC0"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC1"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC2"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC3"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC4"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC5"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC6"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC7"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC8"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC9"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC10"),
+	SND_SOC_DAPM_INPUT("TX SWR_MIC11"),
+
+	SND_SOC_DAPM_MUX_E("TX DEC0 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC0, 0,
+			   &tx_dec0_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC1 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC1, 0,
+			   &tx_dec1_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC2 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC2, 0,
+			   &tx_dec2_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC3 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC3, 0,
+			   &tx_dec3_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v2[] = {
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF1_CAP, 0,
+		tx_aif1_cap_mixer_v2, ARRAY_SIZE(tx_aif1_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF2_CAP, 0,
+		tx_aif2_cap_mixer_v2, ARRAY_SIZE(tx_aif2_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer_v2, ARRAY_SIZE(tx_aif3_cap_mixer_v2)),
+};
+
+static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v3[] = {
+	SND_SOC_DAPM_MIXER("TX_AIF1_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF1_CAP, 0,
+		tx_aif1_cap_mixer, ARRAY_SIZE(tx_aif1_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF2_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF2_CAP, 0,
+		tx_aif2_cap_mixer, ARRAY_SIZE(tx_aif2_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("TX_AIF3_CAP Mixer", SND_SOC_NOPM,
+		TX_MACRO_AIF3_CAP, 0,
+		tx_aif3_cap_mixer, ARRAY_SIZE(tx_aif3_cap_mixer)),
+
+	TX_MACRO_DAPM_MUX("TX DMIC MUX4", 0, tx_dmic4),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX5", 0, tx_dmic5),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX6", 0, tx_dmic6),
+	TX_MACRO_DAPM_MUX("TX DMIC MUX7", 0, tx_dmic7),
+
+	TX_MACRO_DAPM_MUX("TX SMIC MUX4", 0, tx_smic4_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX5", 0, tx_smic5_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX6", 0, tx_smic6_v3),
+	TX_MACRO_DAPM_MUX("TX SMIC MUX7", 0, tx_smic7_v3),
+
+	SND_SOC_DAPM_MUX_E("TX DEC4 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC4, 0,
+			   &tx_dec4_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC5 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC5, 0,
+			   &tx_dec5_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC6 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC6, 0,
+			   &tx_dec6_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("TX DEC7 MUX", SND_SOC_NOPM,
+			   TX_MACRO_DEC7, 0,
+			   &tx_dec7_mux, tx_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			tx_macro_tx_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			tx_macro_va_swr_clk_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
 static const struct snd_soc_dapm_widget tx_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT("TX_AIF1 CAP", "TX_AIF1 Capture", 0,
 		SND_SOC_NOPM, TX_MACRO_AIF1_CAP, 0),
@@ -1421,6 +1679,259 @@
 			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
+static const struct snd_soc_dapm_route tx_audio_map_common[] = {
+	{"TX_AIF1 CAP", NULL, "TX_MCLK"},
+	{"TX_AIF2 CAP", NULL, "TX_MCLK"},
+	{"TX_AIF3 CAP", NULL, "TX_MCLK"},
+
+	{"TX_AIF1 CAP", NULL, "TX_AIF1_CAP Mixer"},
+	{"TX_AIF2 CAP", NULL, "TX_AIF2_CAP Mixer"},
+	{"TX_AIF3 CAP", NULL, "TX_AIF3_CAP Mixer"},
+
+	{"TX_AIF1_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+
+	{"TX_AIF2_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+
+	{"TX_AIF3_CAP Mixer", "DEC0", "TX DEC0 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC1", "TX DEC1 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC2", "TX DEC2 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC3", "TX DEC3 MUX"},
+
+	{"TX DEC0 MUX", NULL, "TX_MCLK"},
+	{"TX DEC1 MUX", NULL, "TX_MCLK"},
+	{"TX DEC2 MUX", NULL, "TX_MCLK"},
+	{"TX DEC3 MUX", NULL, "TX_MCLK"},
+
+	{"TX DEC0 MUX", "MSM_DMIC", "TX DMIC MUX0"},
+	{"TX DMIC MUX0", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX0", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX0", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX0", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX0", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX0", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX0", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX0", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"},
+	{"TX SMIC MUX0", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX0", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX0", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX0", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX0", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX0", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX0", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX0", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX0", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX0", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX0", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX0", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC1 MUX", "MSM_DMIC", "TX DMIC MUX1"},
+	{"TX DMIC MUX1", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX1", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX1", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX1", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX1", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX1", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX1", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX1", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"},
+	{"TX SMIC MUX1", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX1", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX1", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX1", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX1", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX1", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX1", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX1", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX1", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX1", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX1", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX1", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC2 MUX", "MSM_DMIC", "TX DMIC MUX2"},
+	{"TX DMIC MUX2", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX2", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX2", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX2", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX2", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX2", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX2", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX2", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"},
+	{"TX SMIC MUX2", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX2", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX2", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX2", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX2", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX2", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX2", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX2", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX2", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX2", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX2", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX2", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC3 MUX", "MSM_DMIC", "TX DMIC MUX3"},
+	{"TX DMIC MUX3", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX3", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX3", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX3", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX3", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX3", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX3", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX3", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"},
+	{"TX SMIC MUX3", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX3", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX3", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX3", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX3", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX3", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX3", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX3", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX3", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX3", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX3", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX3", "SWR_MIC11", "TX SWR_MIC11"},
+};
+
+static const struct snd_soc_dapm_route tx_audio_map_v3[] = {
+	{"TX_AIF1_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF1_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX_AIF2_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF2_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX_AIF3_CAP Mixer", "DEC4", "TX DEC4 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC5", "TX DEC5 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC6", "TX DEC6 MUX"},
+	{"TX_AIF3_CAP Mixer", "DEC7", "TX DEC7 MUX"},
+
+	{"TX DEC4 MUX", NULL, "TX_MCLK"},
+	{"TX DEC5 MUX", NULL, "TX_MCLK"},
+	{"TX DEC6 MUX", NULL, "TX_MCLK"},
+	{"TX DEC7 MUX", NULL, "TX_MCLK"},
+
+	{"TX DEC4 MUX", "MSM_DMIC", "TX DMIC MUX4"},
+	{"TX DMIC MUX4", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX4", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX4", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX4", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX4", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX4", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX4", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX4", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"},
+	{"TX SMIC MUX4", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX4", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX4", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX4", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX4", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX4", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX4", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX4", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX4", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX4", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX4", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX4", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC5 MUX", "MSM_DMIC", "TX DMIC MUX5"},
+	{"TX DMIC MUX5", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX5", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX5", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX5", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX5", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX5", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX5", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX5", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"},
+	{"TX SMIC MUX5", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX5", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX5", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX5", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX5", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX5", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX5", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX5", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX5", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX5", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX5", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX5", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC6 MUX", "MSM_DMIC", "TX DMIC MUX6"},
+	{"TX DMIC MUX6", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX6", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX6", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX6", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX6", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX6", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX6", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX6", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"},
+	{"TX SMIC MUX6", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX6", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX6", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX6", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX6", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX6", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX6", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX6", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX6", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX6", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX6", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX6", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX DEC7 MUX", "MSM_DMIC", "TX DMIC MUX7"},
+	{"TX DMIC MUX7", "DMIC0", "TX DMIC0"},
+	{"TX DMIC MUX7", "DMIC1", "TX DMIC1"},
+	{"TX DMIC MUX7", "DMIC2", "TX DMIC2"},
+	{"TX DMIC MUX7", "DMIC3", "TX DMIC3"},
+	{"TX DMIC MUX7", "DMIC4", "TX DMIC4"},
+	{"TX DMIC MUX7", "DMIC5", "TX DMIC5"},
+	{"TX DMIC MUX7", "DMIC6", "TX DMIC6"},
+	{"TX DMIC MUX7", "DMIC7", "TX DMIC7"},
+
+	{"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"},
+	{"TX SMIC MUX7", "SWR_MIC0", "TX SWR_MIC0"},
+	{"TX SMIC MUX7", "SWR_MIC1", "TX SWR_MIC1"},
+	{"TX SMIC MUX7", "SWR_MIC2", "TX SWR_MIC2"},
+	{"TX SMIC MUX7", "SWR_MIC3", "TX SWR_MIC3"},
+	{"TX SMIC MUX7", "SWR_MIC4", "TX SWR_MIC4"},
+	{"TX SMIC MUX7", "SWR_MIC5", "TX SWR_MIC5"},
+	{"TX SMIC MUX7", "SWR_MIC6", "TX SWR_MIC6"},
+	{"TX SMIC MUX7", "SWR_MIC7", "TX SWR_MIC7"},
+	{"TX SMIC MUX7", "SWR_MIC8", "TX SWR_MIC8"},
+	{"TX SMIC MUX7", "SWR_MIC9", "TX SWR_MIC9"},
+	{"TX SMIC MUX7", "SWR_MIC10", "TX SWR_MIC10"},
+	{"TX SMIC MUX7", "SWR_MIC11", "TX SWR_MIC11"},
+
+	{"TX SMIC MUX0", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX1", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX2", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX3", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX4", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX5", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX6", NULL, "TX_SWR_CLK"},
+	{"TX SMIC MUX7", NULL, "TX_SWR_CLK"},
+};
+
 static const struct snd_soc_dapm_route tx_audio_map[] = {
 	{"TX_AIF1 CAP", NULL, "TX_MCLK"},
 	{"TX_AIF2 CAP", NULL, "TX_MCLK"},
@@ -1667,6 +2178,63 @@
 	{"TX SMIC MUX7", "SWR_DMIC7", "TX SWR_DMIC7"},
 };
 
+static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = {
+	SOC_SINGLE_SX_TLV("TX_DEC0 Volume",
+			  BOLERO_CDC_TX0_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC1 Volume",
+			  BOLERO_CDC_TX1_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC2 Volume",
+			  BOLERO_CDC_TX2_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC3 Volume",
+			  BOLERO_CDC_TX3_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC1 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC2 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC3 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_SINGLE_EXT("DEC0_BCS Switch", SND_SOC_NOPM, 0, 1, 0,
+		       tx_macro_get_bcs, tx_macro_set_bcs),
+};
+
+static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = {
+	SOC_SINGLE_SX_TLV("TX_DEC4 Volume",
+			  BOLERO_CDC_TX4_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC5 Volume",
+			  BOLERO_CDC_TX5_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC6 Volume",
+			  BOLERO_CDC_TX6_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("TX_DEC7 Volume",
+			  BOLERO_CDC_TX7_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+
+	SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC5 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC6 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+
+	SOC_ENUM_EXT("DEC7 MODE", dec_mode_mux_enum,
+			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
+};
+
 static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
 	SOC_SINGLE_SX_TLV("TX_DEC0 Volume",
 			  BOLERO_CDC_TX0_TX_VOL_CTL,
@@ -1952,7 +2520,6 @@
 static int tx_macro_core_vote(void *handle, bool enable)
 {
 	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
-	int ret = 0;
 
 	if (tx_priv == NULL) {
 		pr_err("%s: tx priv data is NULL\n", __func__);
@@ -1964,7 +2531,10 @@
 		pm_runtime_mark_last_busy(tx_priv->dev);
 	}
 
-	return ret;
+	if (bolero_check_core_votes(tx_priv->dev))
+		return 0;
+	else
+		return -EINVAL;
 }
 
 static int tx_macro_swrm_clock(void *handle, bool enable)
@@ -2124,18 +2694,65 @@
 			"%s: priv is null for macro!\n", __func__);
 		return -EINVAL;
 	}
-	ret = snd_soc_dapm_new_controls(dapm, tx_macro_dapm_widgets,
+	tx_priv->version = bolero_get_version(tx_dev);
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_common,
+				ARRAY_SIZE(tx_macro_dapm_widgets_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_1)
+			ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_v2,
+				ARRAY_SIZE(tx_macro_dapm_widgets_v2));
+		else if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_new_controls(dapm,
+				tx_macro_dapm_widgets_v3,
+				ARRAY_SIZE(tx_macro_dapm_widgets_v3));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_new_controls(dapm, tx_macro_dapm_widgets,
 					ARRAY_SIZE(tx_macro_dapm_widgets));
-	if (ret < 0) {
-		dev_err(tx_dev, "%s: Failed to add controls\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
 	}
 
-	ret = snd_soc_dapm_add_routes(dapm, tx_audio_map,
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_common,
+					ARRAY_SIZE(tx_audio_map_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_add_routes(dapm,
+					tx_audio_map_v3,
+					ARRAY_SIZE(tx_audio_map_v3));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_add_routes(dapm, tx_audio_map,
 					ARRAY_SIZE(tx_audio_map));
-	if (ret < 0) {
-		dev_err(tx_dev, "%s: Failed to add routes\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	ret = snd_soc_dapm_new_widgets(dapm->card);
@@ -2144,28 +2761,65 @@
 		return ret;
 	}
 
-	ret = snd_soc_add_component_controls(component, tx_macro_snd_controls,
-				   ARRAY_SIZE(tx_macro_snd_controls));
-	if (ret < 0) {
-		dev_err(tx_dev, "%s: Failed to add snd_ctls\n", __func__);
-		return ret;
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_add_component_controls(component,
+			tx_macro_snd_controls_common,
+			ARRAY_SIZE(tx_macro_snd_controls_common));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+		if (tx_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_add_component_controls(component,
+				tx_macro_snd_controls_v3,
+				ARRAY_SIZE(tx_macro_snd_controls_v3));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_add_component_controls(component,
+				tx_macro_snd_controls,
+				ARRAY_SIZE(tx_macro_snd_controls));
+		if (ret < 0) {
+			dev_err(tx_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF1 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF2 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "TX_AIF3 Capture");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC0");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC1");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC2");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC3");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC0");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC1");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC2");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC3");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC4");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC5");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC6");
-	snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC7");
+	if (tx_priv->version >= BOLERO_VERSION_2_0) {
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC7");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC8");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC9");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC10");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_MIC11");
+	} else {
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_ADC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "TX SWR_DMIC7");
+	}
 	snd_soc_dapm_sync(dapm);
 
 	for (i = 0; i < NUM_DECIMATORS; i++) {
@@ -2189,6 +2843,13 @@
 				tx_macro_reg_init[i].mask,
 				tx_macro_reg_init[i].val);
 
+	if (tx_priv->version == BOLERO_VERSION_2_1)
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_VA_TOP_CSR_SWR_CTRL, 0xF0, 0xA0);
+	else if (tx_priv->version == BOLERO_VERSION_2_0)
+		snd_soc_component_update_bits(component,
+			BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0xF0, 0xA0);
+
 	return 0;
 }
 
@@ -2421,19 +3082,21 @@
 		sample_rate, tx_priv) == TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED)
 			return -EINVAL;
 	}
-	tx_priv->reset_swr = true;
-	INIT_WORK(&tx_priv->tx_macro_add_child_devices_work,
-		  tx_macro_add_child_devices);
-	tx_priv->swr_plat_data.handle = (void *) tx_priv;
-	tx_priv->swr_plat_data.read = NULL;
-	tx_priv->swr_plat_data.write = NULL;
-	tx_priv->swr_plat_data.bulk_write = NULL;
-	tx_priv->swr_plat_data.clk = tx_macro_swrm_clock;
-	tx_priv->swr_plat_data.core_vote = tx_macro_core_vote;
-	tx_priv->swr_plat_data.handle_irq = NULL;
-
+	if (is_used_tx_swr_gpio) {
+		tx_priv->reset_swr = true;
+		INIT_WORK(&tx_priv->tx_macro_add_child_devices_work,
+			  tx_macro_add_child_devices);
+		tx_priv->swr_plat_data.handle = (void *) tx_priv;
+		tx_priv->swr_plat_data.read = NULL;
+		tx_priv->swr_plat_data.write = NULL;
+		tx_priv->swr_plat_data.bulk_write = NULL;
+		tx_priv->swr_plat_data.clk = tx_macro_swrm_clock;
+		tx_priv->swr_plat_data.core_vote = tx_macro_core_vote;
+		tx_priv->swr_plat_data.handle_irq = NULL;
+		mutex_init(&tx_priv->swr_clk_lock);
+	}
+	tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio;
 	mutex_init(&tx_priv->mclk_lock);
-	mutex_init(&tx_priv->swr_clk_lock);
 	tx_macro_init_ops(&ops, tx_io_base);
 	ops.clk_id_req = TX_CORE_CLK;
 	ops.default_clk_id = TX_CORE_CLK;
@@ -2443,8 +3106,8 @@
 			"%s: register macro failed\n", __func__);
 		goto err_reg_macro;
 	}
-
-	schedule_work(&tx_priv->tx_macro_add_child_devices_work);
+	if (is_used_tx_swr_gpio)
+		schedule_work(&tx_priv->tx_macro_add_child_devices_work);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
@@ -2454,7 +3117,8 @@
 	return 0;
 err_reg_macro:
 	mutex_destroy(&tx_priv->mclk_lock);
-	mutex_destroy(&tx_priv->swr_clk_lock);
+	if (is_used_tx_swr_gpio)
+		mutex_destroy(&tx_priv->swr_clk_lock);
 	return ret;
 }
 
@@ -2468,16 +3132,20 @@
 	if (!tx_priv)
 		return -EINVAL;
 
-	if (tx_priv->swr_ctrl_data)
-		kfree(tx_priv->swr_ctrl_data);
-	for (count = 0; count < tx_priv->child_count &&
-		count < TX_MACRO_CHILD_DEVICES_MAX; count++)
-		platform_device_unregister(tx_priv->pdev_child_devices[count]);
+	if (tx_priv->is_used_tx_swr_gpio) {
+		if (tx_priv->swr_ctrl_data)
+			kfree(tx_priv->swr_ctrl_data);
+		for (count = 0; count < tx_priv->child_count &&
+			count < TX_MACRO_CHILD_DEVICES_MAX; count++)
+			platform_device_unregister(
+				tx_priv->pdev_child_devices[count]);
+	}
 
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	mutex_destroy(&tx_priv->mclk_lock);
-	mutex_destroy(&tx_priv->swr_clk_lock);
+	if (tx_priv->is_used_tx_swr_gpio)
+		mutex_destroy(&tx_priv->swr_clk_lock);
 	bolero_unregister_macro(&pdev->dev, TX_MACRO);
 	return 0;
 }
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index b7d6fe0..c5f0ef9 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -13,6 +13,9 @@
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
 #include <linux/pm_runtime.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include <soc/swr-common.h>
+#include <soc/swr-wcd.h>
 #include "bolero-cdc.h"
 #include "bolero-cdc-registers.h"
 #include "bolero-clk-rsc.h"
@@ -46,6 +49,9 @@
 #define BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS	40
 #define MAX_RETRY_ATTEMPTS 500
 
+#define VA_MACRO_SWR_STRING_LEN 80
+#define VA_MACRO_CHILD_DEVICES_MAX 3
+
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static int va_tx_unmute_delay = BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS;
 module_param(va_tx_unmute_delay, int, 0664);
@@ -85,6 +91,11 @@
 	SWR_MIC,
 };
 
+enum {
+	TX_MCLK,
+	VA_MCLK,
+};
+
 struct va_mute_work {
 	struct va_macro_priv *va_priv;
 	u32 decimator;
@@ -98,12 +109,31 @@
 	struct delayed_work dwork;
 };
 
+/* Hold instance to soundwire platform device */
+struct va_macro_swr_ctrl_data {
+	struct platform_device *va_swr_pdev;
+};
+
+struct va_macro_swr_ctrl_platform_data {
+	void *handle; /* holds codec private data */
+	int (*read)(void *handle, int reg);
+	int (*write)(void *handle, int reg, int val);
+	int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
+	int (*clk)(void *handle, bool enable);
+	int (*handle_irq)(void *handle,
+			  irqreturn_t (*swrm_irq_handler)(int irq,
+							  void *data),
+			  void *swrm_handle,
+			  int action);
+};
+
 struct va_macro_priv {
 	struct device *dev;
 	bool dec_active[VA_MACRO_NUM_DECIMATORS];
 	bool va_without_decimation;
 	struct clk *lpass_audio_hw_vote;
 	struct mutex mclk_lock;
+	struct mutex swr_clk_lock;
 	struct snd_soc_component *component;
 	struct hpf_work va_hpf_work[VA_MACRO_NUM_DECIMATORS];
 	struct va_mute_work va_mute_dwork[VA_MACRO_NUM_DECIMATORS];
@@ -115,15 +145,29 @@
 	s32 dmic_6_7_clk_cnt;
 	u16 dmic_clk_div;
 	u16 va_mclk_users;
+	int swr_clk_users;
+	bool reset_swr;
+	struct device_node *va_swr_gpio_p;
+	struct va_macro_swr_ctrl_data *swr_ctrl_data;
+	struct va_macro_swr_ctrl_platform_data swr_plat_data;
+	struct work_struct va_macro_add_child_devices_work;
+	int child_count;
 	u16 mclk_mux_sel;
 	char __iomem *va_io_base;
 	char __iomem *va_island_mode_muxsel;
+	struct platform_device *pdev_child_devices
+			[VA_MACRO_CHILD_DEVICES_MAX];
 	struct regulator *micb_supply;
 	u32 micb_voltage;
 	u32 micb_current;
+	u32 version;
+	u32 is_used_va_swr_gpio;
 	int micb_users;
 	u16 default_clk_id;
 	u16 clk_id;
+	int tx_swr_clk_cnt;
+	int va_swr_clk_cnt;
+	int va_clk_status;
 	int tx_clk_status;
 };
 
@@ -249,10 +293,25 @@
 			bolero_clk_rsc_request_clock(va_priv->dev,
 						va_priv->default_clk_id,
 						VA_CORE_CLK, false);
+		/* reset swr after ssr/pdr */
+		va_priv->reset_swr = true;
+		if (va_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
+		break;
 	case BOLERO_MACRO_EVT_CLK_RESET:
 		bolero_rsc_clk_reset(va_dev, VA_CORE_CLK);
 		break;
 	case BOLERO_MACRO_EVT_SSR_DOWN:
+		if (va_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_DOWN, NULL);
+			swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
 		if ((!pm_runtime_enabled(va_dev) ||
 		     !pm_runtime_suspended(va_dev))) {
 			ret = bolero_runtime_suspend(va_dev);
@@ -269,6 +328,54 @@
 	return 0;
 }
 
+static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int ret = 0;
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(va_dev, "%s: event = %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		va_priv->va_swr_clk_cnt++;
+		if (va_priv->swr_ctrl_data) {
+			ret = swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_REQ_CLK_SWITCH, NULL);
+			if (ret)
+				dev_dbg(va_dev, "%s: clock switch failed\n",
+					__func__);
+		}
+		msm_cdc_pinctrl_set_wakeup_capable(
+				va_priv->va_swr_gpio_p, false);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		msm_cdc_pinctrl_set_wakeup_capable(
+				va_priv->va_swr_gpio_p, true);
+		if (va_priv->swr_ctrl_data) {
+			ret = swrm_wcd_notify(
+				va_priv->swr_ctrl_data[0].va_swr_pdev,
+				SWR_REQ_CLK_SWITCH, NULL);
+			if (ret)
+				dev_dbg(va_dev, "%s: clock switch failed\n",
+					__func__);
+		}
+		va_priv->va_swr_clk_cnt--;
+		break;
+	default:
+		dev_err(va_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
 static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -312,6 +419,25 @@
 	return ret;
 }
 
+static int va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w,
+			       struct snd_kcontrol *kcontrol, int event)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(w->dapm);
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		++va_priv->tx_swr_clk_cnt;
+	if (SND_SOC_DAPM_EVENT_OFF(event))
+		--va_priv->tx_swr_clk_cnt;
+
+	return 0;
+}
+
 static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -336,6 +462,8 @@
 		ret = va_macro_mclk_enable(va_priv, 1, true);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		if (bolero_tx_clk_switch(component))
+			dev_dbg(va_dev, "%s: clock switch failed\n",__func__);
 		va_macro_mclk_enable(va_priv, 0, true);
 		if (va_priv->tx_clk_status > 0) {
 			bolero_clk_rsc_request_clock(va_priv->dev,
@@ -353,6 +481,204 @@
 	return ret;
 }
 
+static int va_macro_tx_va_mclk_enable(struct va_macro_priv *va_priv,
+				      struct regmap *regmap, int clk_type,
+				      bool enable)
+{
+	int ret = 0, clk_tx_ret = 0;
+
+	dev_dbg(va_priv->dev,
+		"%s: clock type %s, enable: %s tx_mclk_users: %d\n",
+		__func__, (clk_type ? "VA_MCLK" : "TX_MCLK"),
+		(enable ? "enable" : "disable"), va_priv->va_mclk_users);
+
+	if (enable) {
+		if (va_priv->swr_clk_users == 0)
+			msm_cdc_pinctrl_select_active_state(
+						va_priv->va_swr_gpio_p);
+		clk_tx_ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		if (clk_type == TX_MCLK) {
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+			bolero_clk_rsc_fs_gen_request(va_priv->dev,
+						  true);
+		}
+		if (clk_type == VA_MCLK) {
+			ret = va_macro_mclk_enable(va_priv, 1, true);
+			if (ret < 0) {
+				if (va_priv->swr_clk_users == 0)
+					msm_cdc_pinctrl_select_sleep_state(
+							va_priv->va_swr_gpio_p);
+				dev_err_ratelimited(va_priv->dev,
+					"%s: request clock enable failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (va_priv->swr_clk_users == 0) {
+			dev_dbg(va_priv->dev, "%s: reset_swr: %d\n",
+				__func__, va_priv->reset_swr);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x02);
+			regmap_update_bits(regmap,
+				BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x01);
+			if (va_priv->reset_swr)
+				regmap_update_bits(regmap,
+					BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+					0x02, 0x00);
+			va_priv->reset_swr = false;
+		}
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		va_priv->swr_clk_users++;
+	} else {
+		if (va_priv->swr_clk_users <= 0) {
+			dev_err_ratelimited(va_priv->dev,
+				"va swrm clock users already 0\n");
+			va_priv->swr_clk_users = 0;
+			return 0;
+		}
+		clk_tx_ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
+		va_priv->swr_clk_users--;
+		if (va_priv->swr_clk_users == 0)
+			regmap_update_bits(regmap,
+				BOLERO_CDC_VA_CLK_RST_CTRL_SWR_CONTROL,
+				0x01, 0x00);
+		if (clk_type == VA_MCLK)
+			va_macro_mclk_enable(va_priv, 0, true);
+		if (clk_type == TX_MCLK) {
+			bolero_clk_rsc_fs_gen_request(va_priv->dev,
+						  false);
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   false);
+			if (ret < 0) {
+				dev_err_ratelimited(va_priv->dev,
+					"%s: swr request clk failed\n",
+					__func__);
+				goto done;
+			}
+		}
+		if (!clk_tx_ret)
+			ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
+		if (va_priv->swr_clk_users == 0)
+			msm_cdc_pinctrl_select_sleep_state(
+						va_priv->va_swr_gpio_p);
+	}
+	return 0;
+
+done:
+	if (!clk_tx_ret)
+		bolero_clk_rsc_request_clock(va_priv->dev,
+				TX_CORE_CLK,
+				TX_CORE_CLK,
+				false);
+	return ret;
+}
+
+static int va_macro_swrm_clock(void *handle, bool enable)
+{
+	struct va_macro_priv *va_priv = (struct va_macro_priv *) handle;
+	struct regmap *regmap = dev_get_regmap(va_priv->dev->parent, NULL);
+	int ret = 0;
+
+	if (regmap == NULL) {
+		dev_err(va_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&va_priv->swr_clk_lock);
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n",
+		__func__, (enable ? "enable" : "disable"),
+		va_priv->tx_swr_clk_cnt, va_priv->va_swr_clk_cnt);
+
+	if (enable) {
+		pm_runtime_get_sync(va_priv->dev);
+		if (va_priv->va_swr_clk_cnt && !va_priv->tx_swr_clk_cnt) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			va_priv->va_clk_status++;
+		} else {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			va_priv->tx_clk_status++;
+		}
+		pm_runtime_mark_last_busy(va_priv->dev);
+		pm_runtime_put_autosuspend(va_priv->dev);
+	} else {
+		if (va_priv->va_clk_status && !va_priv->tx_clk_status) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->va_clk_status;
+		} else if (!va_priv->va_clk_status && va_priv->tx_clk_status) {
+			ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			--va_priv->tx_clk_status;
+		} else if (va_priv->va_clk_status && va_priv->tx_clk_status) {
+			if (!va_priv->va_swr_clk_cnt && va_priv->tx_swr_clk_cnt) {
+				ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+								VA_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->va_clk_status;
+			} else {
+				ret = va_macro_tx_va_mclk_enable(va_priv, regmap,
+								TX_MCLK, enable);
+				if (ret)
+					goto done;
+				--va_priv->tx_clk_status;
+			}
+
+		} else {
+			dev_dbg(va_priv->dev,
+				"%s: Both clocks are disabled\n", __func__);
+		}
+	}
+	dev_dbg(va_priv->dev,
+		"%s: swrm clock users %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n",
+		__func__, va_priv->swr_clk_users, va_priv->tx_clk_status,
+		va_priv->va_clk_status);
+done:
+	mutex_unlock(&va_priv->swr_clk_lock);
+	return ret;
+}
+
 static void va_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
 {
 	struct delayed_work *hpf_delayed_work;
@@ -393,10 +719,10 @@
 	snd_soc_component_update_bits(component,
 			dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
 			hpf_cut_off_freq << 5);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x02);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x02);
 	/* Minimum 1 clk cycle delay is required as per HW spec */
 	usleep_range(1000, 1010);
-	snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x01);
+	snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x00);
 }
 
 static void va_macro_mute_update_callback(struct work_struct *work)
@@ -688,6 +1014,10 @@
 				tx_vol_ctl_reg, 0x20, 0x20);
 		snd_soc_component_update_bits(component,
 				hpf_gate_reg, 0x01, 0x00);
+		/*
+		 * Minimum 1 clk cycle delay is required as per HW spec
+		 */
+		usleep_range(1000, 1010);
 
 		hpf_cut_off_freq = (snd_soc_component_read32(
 					component, dec_cfg_reg) &
@@ -700,7 +1030,7 @@
 					    TX_HPF_CUT_OFF_FREQ_MASK,
 					    CF_MIN_3DB_150HZ << 5);
 			snd_soc_component_update_bits(component,
-					hpf_gate_reg, 0x02, 0x02);
+					hpf_gate_reg, 0x03, 0x03);
 			/*
 			 * Minimum 1 clk cycle delay is required as per HW spec
 			 */
@@ -775,6 +1105,8 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
+		if (bolero_tx_clk_switch(component))
+			dev_dbg(va_dev, "%s: clock switch failed\n",__func__);
 		if (va_priv->tx_clk_status > 0) {
 			ret = bolero_clk_rsc_request_clock(va_priv->dev,
 						   va_priv->default_clk_id,
@@ -1118,6 +1450,28 @@
 			0, smic_mux_text, snd_soc_dapm_get_enum_double,
 			va_macro_put_dec_enum);
 
+static const char * const smic_mux_text_v2[] = {
+	"ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3",
+	"SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7",
+	"SWR_MIC8", "SWR_MIC9", "SWR_MIC10", "SWR_MIC11"
+};
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic0_v2, BOLERO_CDC_VA_INP_MUX_ADC_MUX0_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic1_v2, BOLERO_CDC_VA_INP_MUX_ADC_MUX1_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic2_v3, BOLERO_CDC_VA_INP_MUX_ADC_MUX2_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
+VA_MACRO_DAPM_ENUM_EXT(va_smic3_v3, BOLERO_CDC_VA_INP_MUX_ADC_MUX3_CFG0,
+			0, smic_mux_text_v2, snd_soc_dapm_get_enum_double,
+			va_macro_put_dec_enum);
+
 static const struct snd_kcontrol_new va_aif1_cap_mixer[] = {
 	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
 			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
@@ -1175,6 +1529,202 @@
 			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
 };
 
+static const struct snd_kcontrol_new va_aif1_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer_v2[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif1_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif2_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new va_aif3_cap_mixer_v3[] = {
+	SOC_SINGLE_EXT("DEC0", SND_SOC_NOPM, VA_MACRO_DEC0, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC1", SND_SOC_NOPM, VA_MACRO_DEC1, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC2", SND_SOC_NOPM, VA_MACRO_DEC2, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+	SOC_SINGLE_EXT("DEC3", SND_SOC_NOPM, VA_MACRO_DEC3, 1, 0,
+			va_macro_tx_mixer_get, va_macro_tx_mixer_put),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_common[] = {
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF2 CAP", "VA_AIF2 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF2_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("VA_AIF3 CAP", "VA_AIF3 Capture", 0,
+		SND_SOC_NOPM, VA_MACRO_AIF3_CAP, 0,
+		va_macro_enable_tx, SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	VA_MACRO_DAPM_MUX("VA DMIC MUX0", 0, va_dmic0),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX1", 0, va_dmic1),
+
+	VA_MACRO_DAPM_MUX("VA SMIC MUX0", 0, va_smic0_v2),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX1", 0, va_smic1_v2),
+
+	SND_SOC_DAPM_INPUT("VA SWR_MIC0"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC1"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC2"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC3"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC4"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC5"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC6"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC7"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC8"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC9"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC10"),
+	SND_SOC_DAPM_INPUT("VA SWR_MIC11"),
+
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+			       va_macro_enable_micbias,
+			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("VA DMIC7", NULL, SND_SOC_NOPM, 0, 0,
+		va_macro_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("VA DEC0 MUX", SND_SOC_NOPM, VA_MACRO_DEC0, 0,
+			   &va_dec0_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("VA DEC1 MUX", SND_SOC_NOPM, VA_MACRO_DEC1, 0,
+			   &va_dec1_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_mclk_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v2[] = {
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer_v2, ARRAY_SIZE(va_aif1_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer_v2, ARRAY_SIZE(va_aif2_cap_mixer_v2)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer_v2, ARRAY_SIZE(va_aif3_cap_mixer_v2)),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_pwr_event_v2,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_TX_SWR_CLK", 0, SND_SOC_NOPM, 0, 0,
+			      va_macro_tx_swr_clk_event_v2,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = {
+	SND_SOC_DAPM_MIXER("VA_AIF1_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF1_CAP, 0,
+		va_aif1_cap_mixer_v3, ARRAY_SIZE(va_aif1_cap_mixer_v3)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF2_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF2_CAP, 0,
+		va_aif2_cap_mixer_v3, ARRAY_SIZE(va_aif2_cap_mixer_v3)),
+
+	SND_SOC_DAPM_MIXER("VA_AIF3_CAP Mixer", SND_SOC_NOPM,
+		VA_MACRO_AIF3_CAP, 0,
+		va_aif3_cap_mixer_v3, ARRAY_SIZE(va_aif3_cap_mixer_v3)),
+
+	VA_MACRO_DAPM_MUX("VA DMIC MUX2", 0, va_dmic2),
+	VA_MACRO_DAPM_MUX("VA DMIC MUX3", 0, va_dmic3),
+
+	VA_MACRO_DAPM_MUX("VA SMIC MUX2", 0, va_smic2_v3),
+	VA_MACRO_DAPM_MUX("VA SMIC MUX3", 0, va_smic3_v3),
+
+	SND_SOC_DAPM_MUX_E("VA DEC2 MUX", SND_SOC_NOPM, VA_MACRO_DEC2, 0,
+			   &va_dec2_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("VA DEC3 MUX", SND_SOC_NOPM, VA_MACRO_DEC3, 0,
+			   &va_dec3_mux, va_macro_enable_dec,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0,
+			      va_macro_swr_pwr_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
 static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT_E("VA_AIF1 CAP", "VA_AIF1 Capture", 0,
 		SND_SOC_NOPM, VA_MACRO_AIF1_CAP, 0,
@@ -1325,6 +1875,146 @@
 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
+static const struct snd_soc_dapm_route va_audio_map_common[] = {
+	{"VA_AIF1 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF2 CAP", NULL, "VA_MCLK"},
+	{"VA_AIF3 CAP", NULL, "VA_MCLK"},
+
+	{"VA_AIF1 CAP", NULL, "VA_AIF1_CAP Mixer"},
+	{"VA_AIF2 CAP", NULL, "VA_AIF2_CAP Mixer"},
+	{"VA_AIF3 CAP", NULL, "VA_AIF3_CAP Mixer"},
+
+	{"VA_AIF1_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC0", "VA DEC0 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC1", "VA DEC1 MUX"},
+
+	{"VA DEC0 MUX", "MSM_DMIC", "VA DMIC MUX0"},
+	{"VA DMIC MUX0", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX0", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX0", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX0", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX0", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX0", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX0", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX0", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"},
+	{"VA SMIC MUX0", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX0", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX0", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX0", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX0", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX0", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX0", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX0", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX0", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX0", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX0", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX0", "SWR_MIC11", "VA SWR_MIC11"},
+
+	{"VA DEC1 MUX", "MSM_DMIC", "VA DMIC MUX1"},
+	{"VA DMIC MUX1", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX1", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX1", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX1", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX1", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX1", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX1", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX1", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"},
+	{"VA SMIC MUX1", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX1", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX1", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX1", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX1", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX1", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX1", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX1", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX1", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX1", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX1", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX1", "SWR_MIC11", "VA SWR_MIC11"},
+
+	{"VA SWR_MIC0", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC1", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC2", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC3", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC4", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC5", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC6", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC7", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC8", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC9", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC10", NULL, "VA_SWR_PWR"},
+	{"VA SWR_MIC11", NULL, "VA_SWR_PWR"},
+
+};
+
+static const struct snd_soc_dapm_route va_audio_map_v3[] = {
+	{"VA_AIF1_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF1_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF2_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF2_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA_AIF3_CAP Mixer", "DEC2", "VA DEC2 MUX"},
+	{"VA_AIF3_CAP Mixer", "DEC3", "VA DEC3 MUX"},
+
+	{"VA DEC2 MUX", "MSM_DMIC", "VA DMIC MUX2"},
+	{"VA DMIC MUX2", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX2", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX2", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX2", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX2", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX2", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX2", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX2", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"},
+	{"VA SMIC MUX2", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX2", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX2", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX2", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX2", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX2", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX2", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX2", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX2", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX2", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX2", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX2", "SWR_MIC11", "VA SWR_MIC11"},
+
+	{"VA DEC3 MUX", "MSM_DMIC", "VA DMIC MUX3"},
+	{"VA DMIC MUX3", "DMIC0", "VA DMIC0"},
+	{"VA DMIC MUX3", "DMIC1", "VA DMIC1"},
+	{"VA DMIC MUX3", "DMIC2", "VA DMIC2"},
+	{"VA DMIC MUX3", "DMIC3", "VA DMIC3"},
+	{"VA DMIC MUX3", "DMIC4", "VA DMIC4"},
+	{"VA DMIC MUX3", "DMIC5", "VA DMIC5"},
+	{"VA DMIC MUX3", "DMIC6", "VA DMIC6"},
+	{"VA DMIC MUX3", "DMIC7", "VA DMIC7"},
+
+	{"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"},
+	{"VA SMIC MUX3", "SWR_MIC0", "VA SWR_MIC0"},
+	{"VA SMIC MUX3", "SWR_MIC1", "VA SWR_MIC1"},
+	{"VA SMIC MUX3", "SWR_MIC2", "VA SWR_MIC2"},
+	{"VA SMIC MUX3", "SWR_MIC3", "VA SWR_MIC3"},
+	{"VA SMIC MUX3", "SWR_MIC4", "VA SWR_MIC4"},
+	{"VA SMIC MUX3", "SWR_MIC5", "VA SWR_MIC5"},
+	{"VA SMIC MUX3", "SWR_MIC6", "VA SWR_MIC6"},
+	{"VA SMIC MUX3", "SWR_MIC7", "VA SWR_MIC7"},
+	{"VA SMIC MUX3", "SWR_MIC8", "VA SWR_MIC8"},
+	{"VA SMIC MUX3", "SWR_MIC9", "VA SWR_MIC9"},
+	{"VA SMIC MUX3", "SWR_MIC10", "VA SWR_MIC10"},
+	{"VA SMIC MUX3", "SWR_MIC11", "VA SWR_MIC11"},
+};
+
 static const struct snd_soc_dapm_route va_audio_map[] = {
 	{"VA_AIF1 CAP", NULL, "VA_MCLK"},
 	{"VA_AIF2 CAP", NULL, "VA_MCLK"},
@@ -1586,6 +2276,24 @@
 			  0, -84, 40, digital_gain),
 };
 
+static const struct snd_kcontrol_new va_macro_snd_controls_common[] = {
+	SOC_SINGLE_SX_TLV("VA_DEC0 Volume",
+			  BOLERO_CDC_VA_TX0_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("VA_DEC1 Volume",
+			  BOLERO_CDC_VA_TX1_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+};
+
+static const struct snd_kcontrol_new va_macro_snd_controls_v3[] = {
+	SOC_SINGLE_SX_TLV("VA_DEC2 Volume",
+			  BOLERO_CDC_VA_TX2_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+	SOC_SINGLE_SX_TLV("VA_DEC3 Volume",
+			  BOLERO_CDC_VA_TX3_TX_VOL_CTL,
+			  0, -84, 40, digital_gain),
+};
+
 static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate,
 				      struct va_macro_priv *va_priv)
 {
@@ -1670,18 +2378,65 @@
 		return 0;
 	}
 
-	ret = snd_soc_dapm_new_controls(dapm, va_macro_dapm_widgets,
+	va_priv->version = bolero_get_version(va_dev);
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_common,
+				ARRAY_SIZE(va_macro_dapm_widgets_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_1)
+			ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_v2,
+				ARRAY_SIZE(va_macro_dapm_widgets_v2));
+		else if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_new_controls(dapm,
+				va_macro_dapm_widgets_v3,
+				ARRAY_SIZE(va_macro_dapm_widgets_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_new_controls(dapm, va_macro_dapm_widgets,
 					ARRAY_SIZE(va_macro_dapm_widgets));
-	if (ret < 0) {
-		dev_err(va_dev, "%s: Failed to add controls\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add controls\n",
+				__func__);
+			return ret;
+		}
 	}
 
-	ret = snd_soc_dapm_add_routes(dapm, va_audio_map,
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_dapm_add_routes(dapm,
+					va_audio_map_common,
+					ARRAY_SIZE(va_audio_map_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_dapm_add_routes(dapm,
+					va_audio_map_v3,
+					ARRAY_SIZE(va_audio_map_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_dapm_add_routes(dapm, va_audio_map,
 					ARRAY_SIZE(va_audio_map));
-	if (ret < 0) {
-		dev_err(va_dev, "%s: Failed to add routes\n", __func__);
-		return ret;
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add routes\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	ret = snd_soc_dapm_new_widgets(dapm->card);
@@ -1689,28 +2444,65 @@
 		dev_err(va_dev, "%s: Failed to add widgets\n", __func__);
 		return ret;
 	}
-	ret = snd_soc_add_component_controls(component, va_macro_snd_controls,
-				   ARRAY_SIZE(va_macro_snd_controls));
-	if (ret < 0) {
-		dev_err(va_dev, "%s: Failed to add snd_ctls\n", __func__);
-		return ret;
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		ret = snd_soc_add_component_controls(component,
+				va_macro_snd_controls_common,
+				ARRAY_SIZE(va_macro_snd_controls_common));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+		if (va_priv->version == BOLERO_VERSION_2_0)
+			ret = snd_soc_add_component_controls(component,
+					va_macro_snd_controls_v3,
+					ARRAY_SIZE(va_macro_snd_controls_v3));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
+	} else {
+		ret = snd_soc_add_component_controls(component,
+				va_macro_snd_controls,
+				ARRAY_SIZE(va_macro_snd_controls));
+		if (ret < 0) {
+			dev_err(va_dev, "%s: Failed to add snd_ctls\n",
+				__func__);
+			return ret;
+		}
 	}
 
 	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF1 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF2 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "VA_AIF3 Capture");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC0");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC1");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC2");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC3");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6");
-	snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7");
+	if (va_priv->version >= BOLERO_VERSION_2_0) {
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC8");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC9");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC10");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC11");
+	} else {
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_ADC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC0");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC1");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC2");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC3");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC4");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC5");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC6");
+		snd_soc_dapm_ignore_suspend(dapm, "VA SWR_MIC7");
+	}
 	snd_soc_dapm_sync(dapm);
 
 	for (i = 0; i < VA_MACRO_NUM_DECIMATORS; i++) {
@@ -1743,6 +2535,156 @@
 	return 0;
 }
 
+static void va_macro_add_child_devices(struct work_struct *work)
+{
+	struct va_macro_priv *va_priv = NULL;
+	struct platform_device *pdev = NULL;
+	struct device_node *node = NULL;
+	struct va_macro_swr_ctrl_data *swr_ctrl_data = NULL, *temp = NULL;
+	int ret = 0;
+	u16 count = 0, ctrl_num = 0;
+	struct va_macro_swr_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[VA_MACRO_SWR_STRING_LEN] = "";
+	bool va_swr_master_node = false;
+
+	va_priv = container_of(work, struct va_macro_priv,
+			     va_macro_add_child_devices_work);
+	if (!va_priv) {
+		pr_err("%s: Memory for va_priv does not exist\n",
+			__func__);
+		return;
+	}
+
+	if (!va_priv->dev) {
+		pr_err("%s: VA dev does not exist\n", __func__);
+		return;
+	}
+
+	if (!va_priv->dev->of_node) {
+		dev_err(va_priv->dev,
+			"%s: DT node for va_priv does not exist\n", __func__);
+		return;
+	}
+
+	platdata = &va_priv->swr_plat_data;
+	va_priv->child_count = 0;
+
+	for_each_available_child_of_node(va_priv->dev->of_node, node) {
+		va_swr_master_node = false;
+		if (strnstr(node->name, "va_swr_master",
+                                strlen("va_swr_master")) != NULL)
+			va_swr_master_node = true;
+
+		if (va_swr_master_node)
+			strlcpy(plat_dev_name, "va_swr_ctrl",
+				(VA_MACRO_SWR_STRING_LEN - 1));
+		else
+			strlcpy(plat_dev_name, node->name,
+				(VA_MACRO_SWR_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(va_priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = va_priv->dev;
+		pdev->dev.of_node = node;
+
+		if (va_swr_master_node) {
+			ret = platform_device_add_data(pdev, platdata,
+						       sizeof(*platdata));
+			if (ret) {
+				dev_err(&pdev->dev,
+					"%s: cannot add plat data ctrl:%d\n",
+					__func__, ctrl_num);
+				goto fail_pdev_add;
+			}
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			goto fail_pdev_add;
+		}
+
+		if (va_swr_master_node) {
+			temp = krealloc(swr_ctrl_data,
+					(ctrl_num + 1) * sizeof(
+					struct va_macro_swr_ctrl_data),
+					GFP_KERNEL);
+			if (!temp) {
+				ret = -ENOMEM;
+				goto fail_pdev_add;
+			}
+			swr_ctrl_data = temp;
+			swr_ctrl_data[ctrl_num].va_swr_pdev = pdev;
+			ctrl_num++;
+			dev_dbg(&pdev->dev,
+				"%s: Added soundwire ctrl device(s)\n",
+				__func__);
+			va_priv->swr_ctrl_data = swr_ctrl_data;
+		}
+		if (va_priv->child_count < VA_MACRO_CHILD_DEVICES_MAX)
+			va_priv->pdev_child_devices[
+					va_priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < va_priv->child_count; count++)
+		platform_device_put(va_priv->pdev_child_devices[count]);
+err:
+	return;
+}
+
+static int va_macro_set_port_map(struct snd_soc_component *component,
+				u32 usecase, u32 size, void *data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	struct swrm_port_config port_cfg;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	memset(&port_cfg, 0, sizeof(port_cfg));
+	port_cfg.uc = usecase;
+	port_cfg.size = size;
+	port_cfg.params = data;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
+
+	return ret;
+}
+
+static int va_macro_reg_wake_irq(struct snd_soc_component *component,
+				 u32 data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	u32 ipc_wakeup = data;
+	int ret = 0;
+
+	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	if (va_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			va_priv->swr_ctrl_data[0].va_swr_pdev,
+			SWR_REGISTER_WAKE_IRQ, &ipc_wakeup);
+
+	return ret;
+}
+
 static void va_macro_init_ops(struct macro_ops *ops,
 			      char __iomem *va_io_base,
 			      bool va_without_decimation)
@@ -1759,6 +2701,8 @@
 	ops->exit = va_macro_deinit;
 	ops->io_base = va_io_base;
 	ops->event_handler = va_macro_event_handler;
+	ops->set_port_map = va_macro_set_port_map;
+	ops->reg_wake_irq = va_macro_reg_wake_irq;
 }
 
 static int va_macro_probe(struct platform_device *pdev)
@@ -1776,6 +2720,8 @@
 	const char *dmic_sample_rate = "qcom,va-dmic-sample-rate";
 	u32 default_clk_id = 0;
 	struct clk *lpass_audio_hw_vote = NULL;
+	u32 is_used_va_swr_gpio = 0;
+	const char *is_used_va_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
 	va_priv = devm_kzalloc(&pdev->dev, sizeof(struct va_macro_priv),
 			    GFP_KERNEL);
@@ -1806,6 +2752,31 @@
 			return -EINVAL;
 	}
 
+	if (of_find_property(pdev->dev.of_node, is_used_va_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_va_swr_gpio_dt,
+					   &is_used_va_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_va_swr_gpio_dt);
+			is_used_va_swr_gpio = 0;
+		}
+	}
+	va_priv->va_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,va-swr-gpios", 0);
+	if (!va_priv->va_swr_gpio_p && is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
+			__func__);
+		return -EINVAL;
+	}
+	if ((msm_cdc_pinctrl_get_state(va_priv->va_swr_gpio_p) < 0) &&
+		is_used_va_swr_gpio) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
 	va_io_base = devm_ioremap(&pdev->dev, va_base_addr,
 				  VA_MACRO_MAX_OFFSET);
 	if (!va_io_base) {
@@ -1865,6 +2836,20 @@
 	va_priv->clk_id = VA_CORE_CLK;
 	va_priv->default_clk_id = default_clk_id;
 
+	if (is_used_va_swr_gpio) {
+		va_priv->reset_swr = true;
+		INIT_WORK(&va_priv->va_macro_add_child_devices_work,
+			  va_macro_add_child_devices);
+		va_priv->swr_plat_data.handle = (void *) va_priv;
+		va_priv->swr_plat_data.read = NULL;
+		va_priv->swr_plat_data.write = NULL;
+		va_priv->swr_plat_data.bulk_write = NULL;
+		va_priv->swr_plat_data.clk = va_macro_swrm_clock;
+		va_priv->swr_plat_data.handle_irq = NULL;
+		mutex_init(&va_priv->swr_clk_lock);
+	}
+	va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio;
+
 	mutex_init(&va_priv->mclk_lock);
 	dev_set_drvdata(&pdev->dev, va_priv);
 	va_macro_init_ops(&ops, va_io_base, va_without_decimation);
@@ -1875,29 +2860,46 @@
 		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
 		goto reg_macro_fail;
 	}
+	if (is_used_va_swr_gpio)
+		schedule_work(&va_priv->va_macro_add_child_devices_work);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, VA_AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
 	pm_runtime_enable(&pdev->dev);
 	return ret;
 
 reg_macro_fail:
 	mutex_destroy(&va_priv->mclk_lock);
+	if (is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
 	return ret;
 }
 
 static int va_macro_remove(struct platform_device *pdev)
 {
 	struct va_macro_priv *va_priv;
+	int count = 0;
 
 	va_priv = dev_get_drvdata(&pdev->dev);
 
 	if (!va_priv)
 		return -EINVAL;
+	if (va_priv->is_used_va_swr_gpio) {
+		if (va_priv->swr_ctrl_data)
+			kfree(va_priv->swr_ctrl_data);
+		for (count = 0; count < va_priv->child_count &&
+			count < VA_MACRO_CHILD_DEVICES_MAX; count++)
+			platform_device_unregister(
+				va_priv->pdev_child_devices[count]);
+	}
+
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	bolero_unregister_macro(&pdev->dev, VA_MACRO);
 	mutex_destroy(&va_priv->mclk_lock);
+	if (va_priv->is_used_va_swr_gpio)
+		mutex_destroy(&va_priv->swr_clk_lock);
 	return 0;
 }
 
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index 623af37..03bea4e 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -2802,7 +2802,6 @@
 static int wsa_macro_core_vote(void *handle, bool enable)
 {
 	struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
-	int ret = 0;
 
 	if (wsa_priv == NULL) {
 		pr_err("%s: wsa priv data is NULL\n", __func__);
@@ -2814,7 +2813,10 @@
 		pm_runtime_mark_last_busy(wsa_priv->dev);
 	}
 
-	return ret;
+	if (bolero_check_core_votes(wsa_priv->dev))
+		return 0;
+	else
+		return -EINVAL;
 }
 
 static int wsa_swrm_clock(void *handle, bool enable)
@@ -3199,6 +3201,7 @@
 	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
+	pm_suspend_ignore_children(&pdev->dev, true);
 	pm_runtime_enable(&pdev->dev);
 
 	return ret;
diff --git a/asoc/codecs/msm-cdc-pinctrl.c b/asoc/codecs/msm-cdc-pinctrl.c
index a10a681..5c6ca49 100644
--- a/asoc/codecs/msm-cdc-pinctrl.c
+++ b/asoc/codecs/msm-cdc-pinctrl.c
@@ -4,6 +4,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -23,8 +24,12 @@
 	int gpio;
 	bool state;
 	u32 tlmm_gpio[MAX_GPIOS];
+	char __iomem *chip_wakeup_register[MAX_GPIOS];
+	u32 chip_wakeup_maskbit[MAX_GPIOS];
 	u32 count;
+	u32 wakeup_reg_count;
 	bool wakeup_capable;
+	bool chip_wakeup_reg;
 };
 
 static struct msm_cdc_pinctrl_info *msm_cdc_pinctrl_get_gpiodata(
@@ -154,7 +159,7 @@
 {
 	struct msm_cdc_pinctrl_info *gpio_data;
 	int ret = 0;
-	u32 i = 0;
+	u32 i = 0, temp = 0;
 
 	gpio_data = msm_cdc_pinctrl_get_gpiodata(np);
 	if (!gpio_data)
@@ -168,6 +173,18 @@
 				goto exit;
 		}
 	}
+	if (gpio_data->chip_wakeup_reg) {
+		for (i = 0; i < gpio_data->wakeup_reg_count; i++) {
+			temp = ioread32(gpio_data->chip_wakeup_register[i]);
+			if (enable)
+				temp |= (1 <<
+					 gpio_data->chip_wakeup_maskbit[i]);
+			else
+				temp &= ~(1 <<
+					  gpio_data->chip_wakeup_maskbit[i]);
+			iowrite32(temp, gpio_data->chip_wakeup_register[i]);
+		}
+	}
 exit:
 	return ret;
 }
@@ -178,7 +195,9 @@
 	int ret = 0;
 	struct msm_cdc_pinctrl_info *gpio_data;
 	u32 tlmm_gpio[MAX_GPIOS] = {0};
-	u32 i = 0;
+	u32 chip_wakeup_reg[MAX_GPIOS] = {0};
+	u32 chip_wakeup_default_val[MAX_GPIOS] = {0};
+	u32 i = 0, temp = 0;
 	int count = 0;
 
 	gpio_data = devm_kzalloc(&pdev->dev,
@@ -223,6 +242,41 @@
 	}
 
 
+	count = of_property_count_u32_elems(pdev->dev.of_node, "qcom,chip-wakeup-reg");
+	if (count <= 0)
+		goto cdc_tlmm_gpio;
+	if (!of_property_read_u32_array(pdev->dev.of_node, "qcom,chip-wakeup-reg",
+				chip_wakeup_reg, count)) {
+		if (of_property_read_u32_array(pdev->dev.of_node,
+					   "qcom,chip-wakeup-maskbit",
+					   gpio_data->chip_wakeup_maskbit, count)) {
+			dev_err(&pdev->dev,
+				"chip-wakeup-maskbit needed if chip-wakeup-reg is defined!\n");
+			goto cdc_tlmm_gpio;
+		}
+		gpio_data->chip_wakeup_reg = true;
+		for (i = 0; i < count; i++) {
+			gpio_data->chip_wakeup_register[i] =
+				devm_ioremap(&pdev->dev, chip_wakeup_reg[i], 0x4);
+		}
+		if (of_property_read_u32_array(pdev->dev.of_node,
+					"qcom,chip-wakeup-default-val",
+					chip_wakeup_default_val, count)) {
+			for (i = 0; i < count; i++) {
+				temp = ioread32(gpio_data->chip_wakeup_register[i]);
+				if (chip_wakeup_default_val[i])
+					temp |= (1 <<
+						 gpio_data->chip_wakeup_maskbit[i]);
+				else
+					temp &= ~(1 <<
+						  gpio_data->chip_wakeup_maskbit[i]);
+				iowrite32(temp, gpio_data->chip_wakeup_register[i]);
+			}
+		}
+		gpio_data->wakeup_reg_count = count;
+	}
+
+cdc_tlmm_gpio:
 	count = of_property_count_u32_elems(pdev->dev.of_node, "qcom,tlmm-gpio");
 	if (count <= 0)
 		goto cdc_rst;
diff --git a/asoc/codecs/msm_hdmi_codec_rx.c b/asoc/codecs/msm_hdmi_codec_rx.c
index 5144b92..1588c56 100644
--- a/asoc/codecs/msm_hdmi_codec_rx.c
+++ b/asoc/codecs/msm_hdmi_codec_rx.c
@@ -29,8 +29,6 @@
 	codec_info.type = EXT_DISPLAY_TYPE_DP; \
 	codec_info.ctrl_id = codec_data->ctl[dai_id]; \
 	codec_info.stream_id = codec_data->stream[dai_id]; \
-	msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, \
-				&codec_info)
 
 enum {
         DP_CONTROLLER0 = 0,
@@ -94,7 +92,9 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
-	if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
 		dev_dbg(component->dev, "%s: get_audio_edid_blk() is NULL\n",
 			__func__);
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
@@ -139,7 +139,9 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
-	if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
 		dev_err(component->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);
@@ -199,9 +201,11 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
 	if (!codec_data->ext_disp_ops.get_audio_edid_blk ||
-	    !codec_data->ext_disp_ops.get_intf_id) {
+	    !codec_data->ext_disp_ops.get_intf_id || rc) {
 		dev_err(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
 			__func__);
 		rc = -EINVAL;
@@ -284,8 +288,10 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
-	if (!codec_data->ext_disp_ops.acknowledge) {
+	if (!codec_data->ext_disp_ops.acknowledge || rc) {
 		dev_err(component->dev,
 			"%s: codec_data ops acknowledge() is NULL\n",
 			__func__);
@@ -460,7 +466,7 @@
 		struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
-	int ret = 0;
+	int ret = 0, rc = 0;
 	struct msm_ext_disp_codec_id codec_info;
 	struct msm_ext_disp_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->component->dev);
@@ -477,8 +483,10 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
-	if (!codec_data->ext_disp_ops.cable_status) {
+	if (!codec_data->ext_disp_ops.cable_status || rc) {
 		dev_err(dai->dev, "%s() cable_status is null\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);
@@ -532,8 +540,10 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
-	if (!codec_data->ext_disp_ops.audio_info_setup) {
+	if (!codec_data->ext_disp_ops.audio_info_setup || rc) {
 		dev_err(dai->dev, "%s: audio_info_setup is null\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);
@@ -600,8 +610,13 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (rc)
+		goto end;
 	rc = codec_data->ext_disp_ops.audio_info_setup(
 			codec_data->ext_disp_core_pdev, &audio_setup_params);
+end:
 	mutex_unlock(&codec_data->dp_ops_lock);
 	if (rc < 0) {
 		dev_err_ratelimited(dai->dev,
@@ -634,9 +649,11 @@
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
 	if (!codec_data->ext_disp_ops.teardown_done ||
-	    !codec_data->ext_disp_ops.cable_status) {
+	    !codec_data->ext_disp_ops.cable_status || rc) {
 		dev_err(dai->dev, "%s: teardown_done or cable_status is null\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);
diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c
index 4de19de..0635d54 100644
--- a/asoc/codecs/wcd-mbhc-adc.c
+++ b/asoc/codecs/wcd-mbhc-adc.c
@@ -689,6 +689,14 @@
 	}
 
 correct_plug_type:
+	/*
+	 * Callback to disable BCS slow insertion detection
+	 */
+	if (plug_type == MBHC_PLUG_TYPE_HEADSET ||
+	    plug_type == MBHC_PLUG_TYPE_HEADPHONE)
+		if (mbhc->mbhc_cb->bcs_enable)
+			mbhc->mbhc_cb->bcs_enable(mbhc, false);
+
 	timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
 	while (!time_after(jiffies, timeout)) {
 		if (mbhc->hs_detect_work_stop) {
@@ -833,6 +841,11 @@
 			wrk_complete = false;
 		}
 	}
+	if ((plug_type == MBHC_PLUG_TYPE_HEADSET ||
+	    plug_type == MBHC_PLUG_TYPE_HEADPHONE))
+		if (mbhc->mbhc_cb->bcs_enable)
+			mbhc->mbhc_cb->bcs_enable(mbhc, true);
+
 	if (!wrk_complete) {
 		/*
 		 * If plug_tye is headset, we might have already reported either
diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c
index 01544aa..fd55715 100644
--- a/asoc/codecs/wcd-mbhc-v2.c
+++ b/asoc/codecs/wcd-mbhc-v2.c
@@ -883,7 +883,8 @@
 					detection_type);
 		ret = true;
 		WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
-		WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_DET_EN, 1);
+		if (mbhc->mbhc_cfg->gnd_det_en)
+			WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_DET_EN, 1);
 	} else {
 		mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc, false);
 		mbhc->mbhc_cb->mbhc_moisture_detect_en(mbhc, false);
@@ -1023,7 +1024,7 @@
 					mbhc->component, false);
 		}
 
-		if (mbhc->mbhc_cfg->moisture_en &&
+		if (mbhc->mbhc_cfg->moisture_en ||
 		    mbhc->mbhc_cfg->moisture_duty_cycle_en) {
 			if (mbhc->mbhc_cb->mbhc_moisture_polling_ctrl)
 				mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc,
@@ -1055,6 +1056,10 @@
 	struct wcd_mbhc *mbhc = data;
 
 	pr_debug("%s: enter\n", __func__);
+	if (mbhc == NULL) {
+		pr_err("%s: NULL irq data\n", __func__);
+		return IRQ_NONE;
+	}
 	if (unlikely((mbhc->mbhc_cb->lock_sleep(mbhc, true)) == false)) {
 		pr_warn("%s: failed to hold suspend\n", __func__);
 		r = IRQ_NONE;
diff --git a/asoc/codecs/wcd-spi.c b/asoc/codecs/wcd-spi.c
index 0173e15..4c7a853 100644
--- a/asoc/codecs/wcd-spi.c
+++ b/asoc/codecs/wcd-spi.c
@@ -815,6 +815,15 @@
 		return -EINVAL;
 	}
 
+	WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex);
+	if (wcd_spi_is_suspended(wcd_spi)) {
+		dev_dbg(&spi->dev,
+			"%s: SPI suspended, cannot perform transfer\n",
+			__func__);
+		ret = -EIO;
+		goto done;
+	}
+
 	WCD_SPI_MUTEX_LOCK(spi, wcd_spi->xfer_mutex);
 	if (msg->len == WCD_SPI_WORD_BYTE_CNT) {
 		if (xfer_req == WCD_SPI_XFER_WRITE)
@@ -827,7 +836,8 @@
 		ret = wcd_spi_transfer_split(spi, msg, xfer_req);
 	}
 	WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->xfer_mutex);
-
+done:
+	WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex);
 	return ret;
 }
 
diff --git a/asoc/codecs/wcd937x/Android.mk b/asoc/codecs/wcd937x/Android.mk
index cbd0877..4168dd1 100644
--- a/asoc/codecs/wcd937x/Android.mk
+++ b/asoc/codecs/wcd937x/Android.mk
@@ -7,9 +7,13 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_SM6150=m
 endif
 
+ifeq ($(call is-board-platform,bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
-ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET)),true)
+ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET) bengal),true)
 
 LOCAL_PATH := $(call my-dir)
 
diff --git a/asoc/codecs/wcd937x/Kbuild b/asoc/codecs/wcd937x/Kbuild
index b8db202..e353e8a 100644
--- a/asoc/codecs/wcd937x/Kbuild
+++ b/asoc/codecs/wcd937x/Kbuild
@@ -26,6 +26,11 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm6150autoconf.h
 	endif
+	ifeq ($(CONFIG_ARCH_BENGAL), y)
+		include $(AUDIO_ROOT)/config/bengalauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
+	endif
 endif
 
 # As per target team, build is done as follows:
diff --git a/asoc/codecs/wcd937x/internal.h b/asoc/codecs/wcd937x/internal.h
index cd11c85..faf0118 100644
--- a/asoc/codecs/wcd937x/internal.h
+++ b/asoc/codecs/wcd937x/internal.h
@@ -133,6 +133,7 @@
 	WCD_BOLERO_EVT_RX_MUTE = 1,	/* for RX mute/unmute */
 	WCD_BOLERO_EVT_IMPED_TRUE,	/* for imped true */
 	WCD_BOLERO_EVT_IMPED_FALSE,	/* for imped false */
+	WCD_BOLERO_EVT_BCS_CLK_OFF,
 };
 
 enum {
@@ -164,6 +165,9 @@
 	WCD937X_NUM_IRQS,
 };
 
+extern void wcd937x_disable_bcs_before_slow_insert(
+				struct snd_soc_component *component,
+				bool bcs_disable);
 extern struct wcd937x_mbhc *wcd937x_soc_get_mbhc(
 				struct snd_soc_component *component);
 extern int wcd937x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
diff --git a/asoc/codecs/wcd937x/wcd937x-mbhc.c b/asoc/codecs/wcd937x/wcd937x-mbhc.c
index 2159cab..039f511 100644
--- a/asoc/codecs/wcd937x/wcd937x-mbhc.c
+++ b/asoc/codecs/wcd937x/wcd937x-mbhc.c
@@ -810,6 +810,15 @@
 			0x04, (enable << 2));
 }
 
+static void wcd937x_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
+						  bool bcs_enable)
+{
+	if (bcs_enable)
+		wcd937x_disable_bcs_before_slow_insert(mbhc->component, false);
+	else
+		wcd937x_disable_bcs_before_slow_insert(mbhc->component, true);
+}
+
 static const struct wcd_mbhc_cb mbhc_cb = {
 	.request_irq = wcd937x_mbhc_request_irq,
 	.irq_control = wcd937x_mbhc_irq_control,
@@ -834,6 +843,7 @@
 	.mbhc_get_moisture_status = wcd937x_mbhc_get_moisture_status,
 	.mbhc_moisture_polling_ctrl = wcd937x_mbhc_moisture_polling_ctrl,
 	.mbhc_moisture_detect_en = wcd937x_mbhc_moisture_detect_en,
+	.bcs_enable = wcd937x_mbhc_bcs_enable,
 };
 
 static int wcd937x_get_hph_type(struct snd_kcontrol *kcontrol,
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 1799599..21325ae 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -1310,7 +1310,7 @@
 		/* Enable BCS for Headset mic */
 		if (w->shift == 1 && !(snd_soc_component_read32(component,
 				WCD937X_TX_NEW_TX_CH2_SEL) & 0x80)) {
-			wcd937x_tx_connect_port(codec, MBHC, true);
+			wcd937x_tx_connect_port(component, MBHC, true);
 			set_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask);
 		}
 		wcd937x_tx_connect_port(component, ADC1 + (w->shift), true);
@@ -1319,7 +1319,7 @@
 		wcd937x_tx_connect_port(component, ADC1 + (w->shift), false);
 		if (w->shift == 1 &&
 			test_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask)) {
-			wcd937x_tx_connect_port(codec, MBHC, false);
+			wcd937x_tx_connect_port(component, MBHC, false);
 			clear_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask);
 		}
 		snd_soc_component_update_bits(component,
@@ -1517,6 +1517,21 @@
 }
 EXPORT_SYMBOL(wcd937x_micbias_control);
 
+void wcd937x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
+					    bool bcs_disable)
+{
+	struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
+
+	if (wcd937x->update_wcd_event) {
+		if (bcs_disable)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
+		else
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
+	}
+}
+
 static int wcd937x_get_logical_addr(struct swr_device *swr_dev)
 {
 	int ret = 0;
@@ -1642,6 +1657,51 @@
 	return __wcd937x_codec_enable_micbias(w, event);
 }
 
+static int __wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
+						 int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int micb_num;
+
+	dev_dbg(component->dev, "%s: wname: %s, event: %d\n",
+		__func__, w->name, event);
+
+	if (strnstr(w->name, "VA MIC BIAS1", sizeof("VA MIC BIAS1")))
+		micb_num = MIC_BIAS_1;
+	else if (strnstr(w->name, "VA MIC BIAS2", sizeof("VA MIC BIAS2")))
+		micb_num = MIC_BIAS_2;
+	else if (strnstr(w->name, "VA MIC BIAS3", sizeof("VA MIC BIAS3")))
+		micb_num = MIC_BIAS_3;
+	else
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd937x_micbias_control(component, micb_num,
+					MICB_PULLUP_ENABLE, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* 1 msec delay as per HW requirement */
+		usleep_range(1000, 1100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd937x_micbias_control(component, micb_num,
+					MICB_PULLUP_DISABLE, true);
+		break;
+	};
+
+	return 0;
+
+}
+
+static int wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
+					       struct snd_kcontrol *kcontrol,
+					       int event)
+{
+	return __wcd937x_codec_enable_micbias_pullup(w, event);
+}
+
 static int wcd937x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
@@ -2052,6 +2112,20 @@
 	SND_SOC_DAPM_OUTPUT("HPHL"),
 	SND_SOC_DAPM_OUTPUT("HPHR"),
 
+	/* micbias pull up widgets*/
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+				wcd937x_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS2", SND_SOC_NOPM, 0, 0,
+				wcd937x_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS3", SND_SOC_NOPM, 0, 0,
+				wcd937x_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
 };
 
 static const struct snd_soc_dapm_widget wcd9375_dapm_widgets[] = {
diff --git a/asoc/codecs/wcd938x/Android.mk b/asoc/codecs/wcd938x/Android.mk
index 49aa2d4..96fb6f5 100644
--- a/asoc/codecs/wcd938x/Android.mk
+++ b/asoc/codecs/wcd938x/Android.mk
@@ -13,7 +13,7 @@
 
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
-ifeq ($(call is-board-platform-in-list,kona lito bengal),true)
+ifeq ($(call is-board-platform-in-list,kona lito),true)
 
 LOCAL_PATH := $(call my-dir)
 
diff --git a/asoc/codecs/wcd938x/Kbuild b/asoc/codecs/wcd938x/Kbuild
index 99d7195..3dfe142 100644
--- a/asoc/codecs/wcd938x/Kbuild
+++ b/asoc/codecs/wcd938x/Kbuild
@@ -23,11 +23,6 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
-		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
-	endif
 
 endif
 
diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h
index 098a60d..46d61a0 100644
--- a/asoc/codecs/wcd938x/internal.h
+++ b/asoc/codecs/wcd938x/internal.h
@@ -149,6 +149,7 @@
 	WCD_BOLERO_EVT_IMPED_TRUE,	/* for imped true */
 	WCD_BOLERO_EVT_IMPED_FALSE,	/* for imped false */
 	WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
+	WCD_BOLERO_EVT_BCS_CLK_OFF,
 };
 
 enum {
@@ -182,6 +183,9 @@
 
 extern struct wcd938x_mbhc *wcd938x_soc_get_mbhc(
 				struct snd_soc_component *component);
+extern void wcd938x_disable_bcs_before_slow_insert(
+				struct snd_soc_component *component,
+				bool bcs_disable);
 extern int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
 					int volt, int micb_num);
 extern int wcd938x_get_micb_vout_ctl_val(u32 micb_mv);
diff --git a/asoc/codecs/wcd938x/wcd938x-mbhc.c b/asoc/codecs/wcd938x/wcd938x-mbhc.c
index 27566ee..0687de6 100644
--- a/asoc/codecs/wcd938x/wcd938x-mbhc.c
+++ b/asoc/codecs/wcd938x/wcd938x-mbhc.c
@@ -803,6 +803,15 @@
 			0x04, (enable << 2));
 }
 
+static void wcd938x_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
+						  bool bcs_enable)
+{
+	if (bcs_enable)
+		wcd938x_disable_bcs_before_slow_insert(mbhc->component, false);
+	else
+		wcd938x_disable_bcs_before_slow_insert(mbhc->component, true);
+}
+
 static const struct wcd_mbhc_cb mbhc_cb = {
 	.request_irq = wcd938x_mbhc_request_irq,
 	.irq_control = wcd938x_mbhc_irq_control,
@@ -827,6 +836,7 @@
 	.mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,
 	.mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,
 	.mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,
+	.bcs_enable = wcd938x_mbhc_bcs_enable,
 };
 
 static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 9bc75a0..3db8fc5 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -41,6 +41,8 @@
 #define ADC_MODE_VAL_ULP1     0x09
 #define ADC_MODE_VAL_ULP2     0x0B
 
+#define NUM_ATTEMPTS 5
+
 enum {
 	CODEC_TX = 0,
 	CODEC_RX,
@@ -1022,6 +1024,9 @@
 			snd_soc_component_update_bits(component,
 					WCD938X_DIGITAL_PDM_WD_CTL0,
 					0x17, 0x13);
+		if (!wcd938x->comp1_enable)
+			snd_soc_component_update_bits(component,
+				WCD938X_ANA_EAR_COMPANDER_CTL, 0x80, 0x80);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/* 6 msec delay as per HW requirement */
@@ -1065,6 +1070,9 @@
 		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		if (!wcd938x->comp1_enable)
+			snd_soc_component_update_bits(component,
+				WCD938X_ANA_EAR_COMPANDER_CTL, 0x80, 0x00);
 		/* 7 msec delay as per HW requirement */
 		usleep_range(7000, 7010);
 		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
@@ -1517,6 +1525,21 @@
 	return 0;
 }
 
+void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
+					    bool bcs_disable)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	if (wcd938x->update_wcd_event) {
+		if (bcs_disable)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
+		else
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
+	}
+}
+
 int wcd938x_tx_channel_config(struct snd_soc_component *component,
 			      int channel, int mode)
 {
@@ -1621,18 +1644,30 @@
 		switch (w->shift) {
 		case 0:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0x0F,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x10, 0x00);
 			break;
 		case 1:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0xF0,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x20, 0x00);
 			break;
 		case 2:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0x0F,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x40, 0x00);
 			break;
 		case 3:
 			snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0xF0,
+				0x00);
+			snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x00);
 			break;
 		default:
@@ -1809,15 +1844,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);
-		swr_remove_device(swr_dev);
-		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;
 }
@@ -1871,8 +1909,12 @@
 		break;
 	case BOLERO_WCD_EVT_SSR_UP:
 		wcd938x_reset(wcd938x->dev);
+		/* allow reset to take effect */
+		usleep_range(10000, 10010);
+
 		wcd938x_get_logical_addr(wcd938x->tx_swr_dev);
 		wcd938x_get_logical_addr(wcd938x->rx_swr_dev);
+
 		wcd938x_init_reg(component);
 		regcache_mark_dirty(wcd938x->regmap);
 		regcache_sync(wcd938x->regmap);
@@ -2126,6 +2168,48 @@
 	return 0;
 }
 
+static int wcd938x_ear_pa_gain_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 ear_pa_gain = 0;
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+
+	ear_pa_gain = snd_soc_component_read32(component,
+				WCD938X_ANA_EAR_COMPANDER_CTL);
+
+	ear_pa_gain = (ear_pa_gain & 0x7C) >> 2;
+
+	ucontrol->value.integer.value[0] = ear_pa_gain;
+
+	dev_dbg(component->dev, "%s: ear_pa_gain = 0x%x\n", __func__,
+		ear_pa_gain);
+
+	return 0;
+}
+
+static int wcd938x_ear_pa_gain_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 ear_pa_gain = 0;
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+			__func__, ucontrol->value.integer.value[0]);
+
+	ear_pa_gain =  ucontrol->value.integer.value[0] << 2;
+
+	if (!wcd938x->comp1_enable) {
+		snd_soc_component_update_bits(component,
+				WCD938X_ANA_EAR_COMPANDER_CTL,
+				0x7C, ear_pa_gain);
+	}
+
+	return 0;
+}
+
 static int wcd938x_get_compander(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
@@ -2211,10 +2295,21 @@
 	"CLS_AB_LOHIFI",
 };
 
+static const char * const wcd938x_ear_pa_gain_text[] = {
+	"G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB", "G_0_DB",
+	"G_M1P5_DB", "G_M3_DB", "G_M4P5_DB",
+	"G_M6_DB", "G_7P5_DB", "G_M9_DB",
+	"G_M10P5_DB", "G_M12_DB", "G_M13P5_DB",
+	"G_M15_DB", "G_M16P5_DB", "G_M18_DB",
+};
+
 static const struct soc_enum rx_hph_mode_mux_enum_wcd9380 =
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text_wcd9380),
 			    rx_hph_mode_mux_text_wcd9380);
 
+static SOC_ENUM_SINGLE_EXT_DECL(wcd938x_ear_pa_gain_enum,
+				wcd938x_ear_pa_gain_text);
+
 static const char * const rx_hph_mode_mux_text[] = {
 	"CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
 	"CLS_H_ULP", "CLS_AB_HIFI", "CLS_AB_LP", "CLS_AB_LOHIFI",
@@ -2225,6 +2320,9 @@
 			    rx_hph_mode_mux_text);
 
 static const struct snd_kcontrol_new wcd9380_snd_controls[] = {
+	SOC_ENUM_EXT("EAR PA GAIN", wcd938x_ear_pa_gain_enum,
+		wcd938x_ear_pa_gain_get, wcd938x_ear_pa_gain_put),
+
 	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum_wcd9380,
 		wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),
 
diff --git a/asoc/codecs/wcd_cpe_core.c b/asoc/codecs/wcd_cpe_core.c
index 4c776d1..5b5291f 100644
--- a/asoc/codecs/wcd_cpe_core.c
+++ b/asoc/codecs/wcd_cpe_core.c
@@ -2896,6 +2896,7 @@
 	struct cmi_obm_msg obm_msg;
 	struct cpe_param_data *param_d;
 
+	memset(&obm_msg, 0, sizeof(obm_msg));
 
 	ret = fill_cmi_header(&obm_msg.hdr, session->id,
 			CMI_CPE_LSM_SERVICE_ID, 0, 20,
diff --git a/asoc/codecs/wsa881x-analog.c b/asoc/codecs/wsa881x-analog.c
new file mode 100644
index 0000000..c6b4066
--- /dev/null
+++ b/asoc/codecs/wsa881x-analog.c
@@ -0,0 +1,1543 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015-2016, 2018-2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/bitops.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <soc/soundwire.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <dsp/q6afe-v2.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <soc/internal.h>
+#include <linux/regmap.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include "wsa881x-analog.h"
+#include "wsa881x-temp-sensor.h"
+
+#define SPK_GAIN_12DB 4
+#define WIDGET_NAME_MAX_SIZE 80
+
+/*
+ * Private data Structure for wsa881x. All parameters related to
+ * WSA881X codec needs to be defined here.
+ */
+struct wsa881x_pdata {
+	struct regmap *regmap[2];
+	struct i2c_client *client[2];
+	struct snd_soc_component *component;
+
+	/* track wsa881x status during probe */
+	int status;
+	bool boost_enable;
+	bool visense_enable;
+	int spk_pa_gain;
+	struct i2c_msg xfer_msg[2];
+	struct mutex xfer_lock;
+	bool regmap_flag;
+	bool wsa_active;
+	int index;
+	struct wsa881x_tz_priv tz_pdata;
+	struct clk *wsa_mclk;
+	int bg_cnt;
+	int clk_cnt;
+	int enable_cnt;
+	int version;
+	struct mutex bg_lock;
+	struct mutex res_lock;
+	struct delayed_work ocp_ctl_work;
+	struct device_node *wsa_vi_gpio_p;
+	struct device_node *wsa_clk_gpio_p;
+	struct device_node *wsa_reset_gpio_p;
+};
+
+enum {
+	WSA881X_STATUS_PROBING,
+	WSA881X_STATUS_I2C,
+};
+
+#define WSA881X_OCP_CTL_TIMER_SEC 2
+#define WSA881X_OCP_CTL_TEMP_CELSIUS 25
+#define WSA881X_OCP_CTL_POLL_TIMER_SEC 60
+
+static int wsa881x_ocp_poll_timer_sec = WSA881X_OCP_CTL_POLL_TIMER_SEC;
+module_param(wsa881x_ocp_poll_timer_sec, int, 0664);
+MODULE_PARM_DESC(wsa881x_ocp_poll_timer_sec, "timer for ocp ctl polling");
+
+static int32_t wsa881x_resource_acquire(struct snd_soc_component *component,
+						bool enable);
+
+const char *wsa_tz_names[] = {"wsa881x.0e", "wsa881x.0f"};
+
+struct wsa881x_pdata wsa_pdata[MAX_WSA881X_DEVICE];
+
+static bool pinctrl_init;
+
+static int wsa881x_populate_dt_pdata(struct device *dev, int wsa881x_index);
+static int wsa881x_reset(struct wsa881x_pdata *pdata, bool enable);
+static int wsa881x_startup(struct wsa881x_pdata *pdata);
+static int wsa881x_shutdown(struct wsa881x_pdata *pdata);
+
+static int delay_array_msec[] = {10, 20, 30, 40, 50};
+
+static int wsa881x_i2c_addr = -1;
+static int wsa881x_probing_count;
+static int wsa881x_presence_count;
+
+static const char * const wsa881x_spk_pa_gain_text[] = {
+"POS_13P5_DB", "POS_12_DB", "POS_10P5_DB", "POS_9_DB", "POS_7P5_DB",
+"POS_6_DB", "POS_4P5_DB", "POS_3_DB", "POS_1P5_DB", "POS_0_DB"};
+
+static const struct soc_enum wsa881x_spk_pa_gain_enum[] = {
+		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa881x_spk_pa_gain_text),
+				    wsa881x_spk_pa_gain_text),
+};
+
+static int wsa881x_spk_pa_gain_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa881x_pdata *wsa881x =
+			snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa881x->spk_pa_gain;
+
+	dev_dbg(component->dev, "%s: spk_pa_gain = %ld\n", __func__,
+				ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa881x_spk_pa_gain_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa881x_pdata *wsa881x =
+			snd_soc_component_get_drvdata(component);
+
+	if (ucontrol->value.integer.value[0] < 0 ||
+		ucontrol->value.integer.value[0] > 0xC) {
+		dev_err(component->dev, "%s: Unsupported gain val %ld\n",
+			 __func__, ucontrol->value.integer.value[0]);
+		return -EINVAL;
+	}
+	wsa881x->spk_pa_gain = ucontrol->value.integer.value[0];
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+			 __func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int get_i2c_wsa881x_device_index(u16 reg)
+{
+	u16 mask = 0x0f00;
+	int value = 0;
+
+	value = ((reg & mask) >> 8) & 0x000f;
+
+	switch (value) {
+	case 0:
+		return 0;
+	case 1:
+		return 1;
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int wsa881x_i2c_write_device(struct wsa881x_pdata *wsa881x,
+			unsigned int reg, unsigned int val)
+{
+	int i = 0, rc = 0;
+	int wsa881x_index;
+	struct i2c_msg *msg;
+	int ret = 0;
+	int bytes = 1;
+	u8 reg_addr = 0;
+	u8 data[2];
+
+	wsa881x_index = get_i2c_wsa881x_device_index(reg);
+	if (wsa881x_index < 0) {
+		pr_err_ratelimited("%s:invalid register to write\n", __func__);
+		return -EINVAL;
+	}
+	if (wsa881x->regmap_flag) {
+		rc = regmap_write(wsa881x->regmap[wsa881x_index], reg, val);
+		for (i = 0; rc && i < ARRAY_SIZE(delay_array_msec); i++) {
+			pr_err_ratelimited("Failed writing reg=%u-retry(%d)\n",
+							reg, i);
+			/* retry after delay of increasing order */
+			msleep(delay_array_msec[i]);
+			rc = regmap_write(wsa881x->regmap[wsa881x_index],
+								reg, val);
+		}
+		if (rc)
+			pr_err_ratelimited("Failed writing reg=%u rc=%d\n",
+							reg, rc);
+		else
+			pr_debug("write success register = %x val = %x\n",
+							reg, val);
+	} else {
+		reg_addr = (u8)reg;
+		msg = &wsa881x->xfer_msg[0];
+		msg->addr = wsa881x->client[wsa881x_index]->addr;
+		msg->len = bytes + 1;
+		msg->flags = 0;
+		data[0] = reg;
+		data[1] = (u8)val;
+		msg->buf = data;
+		ret = i2c_transfer(wsa881x->client[wsa881x_index]->adapter,
+						wsa881x->xfer_msg, 1);
+		/* Try again if the write fails */
+		if (ret != 1) {
+			ret = i2c_transfer(
+					wsa881x->client[wsa881x_index]->adapter,
+							wsa881x->xfer_msg, 1);
+			if (ret != 1) {
+				pr_err_ratelimited("failed to write the device\n");
+				return ret;
+			}
+		}
+		pr_debug("write success reg = %x val = %x\n", reg, data[1]);
+	}
+	return rc;
+}
+
+static int wsa881x_i2c_read_device(struct wsa881x_pdata *wsa881x,
+				unsigned int reg)
+{
+	int wsa881x_index;
+	int i = 0, rc = 0;
+	unsigned int val;
+	struct i2c_msg *msg;
+	int ret = 0;
+	u8 reg_addr = 0;
+	u8 dest[5] = {0};
+
+	wsa881x_index = get_i2c_wsa881x_device_index(reg);
+	if (wsa881x_index < 0) {
+		pr_err_ratelimited("%s:invalid register to read\n", __func__);
+		return -EINVAL;
+	}
+	if (wsa881x->regmap_flag) {
+		rc = regmap_read(wsa881x->regmap[wsa881x_index], reg, &val);
+		for (i = 0; rc && i < ARRAY_SIZE(delay_array_msec); i++) {
+			pr_err_ratelimited("Failed reading reg=%u - retry(%d)\n",
+								reg, i);
+			/* retry after delay of increasing order */
+			msleep(delay_array_msec[i]);
+			rc = regmap_read(wsa881x->regmap[wsa881x_index],
+						reg, &val);
+		}
+		if (rc) {
+			pr_err_ratelimited("Failed reading reg=%u rc=%d\n",
+								 reg, rc);
+			return rc;
+		}
+		pr_debug("read success reg = %x val = %x\n",
+						reg, val);
+	} else {
+		reg_addr = (u8)reg;
+		msg = &wsa881x->xfer_msg[0];
+		msg->addr = wsa881x->client[wsa881x_index]->addr;
+		msg->len = 1;
+		msg->flags = 0;
+		msg->buf = &reg_addr;
+
+		msg = &wsa881x->xfer_msg[1];
+		msg->addr = wsa881x->client[wsa881x_index]->addr;
+		msg->len = 1;
+		msg->flags = I2C_M_RD;
+		msg->buf = dest;
+		ret = i2c_transfer(wsa881x->client[wsa881x_index]->adapter,
+					wsa881x->xfer_msg, 2);
+
+		/* Try again if read fails first time */
+		if (ret != 2) {
+			ret = i2c_transfer(
+				wsa881x->client[wsa881x_index]->adapter,
+						wsa881x->xfer_msg, 2);
+			if (ret != 2) {
+				pr_err_ratelimited("failed to read wsa register:%d\n",
+								reg);
+				return ret;
+			}
+		}
+		val = dest[0];
+	}
+	return val;
+}
+
+static unsigned int wsa881x_i2c_read(struct snd_soc_component *component,
+				unsigned int reg)
+{
+	struct wsa881x_pdata *wsa881x;
+	int wsa881x_index;
+
+	if (component == NULL) {
+		pr_err_ratelimited("%s: invalid component\n", __func__);
+		return -EINVAL;
+	}
+	wsa881x = snd_soc_component_get_drvdata(component);
+	if (!wsa881x->wsa_active)
+		return 0;
+
+	wsa881x_index = get_i2c_wsa881x_device_index(reg);
+	if (wsa881x_index < 0) {
+		pr_err_ratelimited("%s:invalid register to read\n", __func__);
+		return -EINVAL;
+	}
+	return wsa881x_i2c_read_device(wsa881x, reg);
+}
+
+static int wsa881x_i2c_write(struct snd_soc_component *component,
+			unsigned int reg,
+			unsigned int val)
+{
+	struct wsa881x_pdata *wsa881x;
+	int wsa881x_index;
+
+	if (component == NULL) {
+		pr_err_ratelimited("%s: invalid component\n", __func__);
+		return -EINVAL;
+	}
+	wsa881x = snd_soc_component_get_drvdata(component);
+	if (!wsa881x->wsa_active)
+		return 0;
+
+	wsa881x_index = get_i2c_wsa881x_device_index(reg);
+	if (wsa881x_index < 0) {
+		pr_err_ratelimited("%s:invalid register to read\n", __func__);
+		return -EINVAL;
+	}
+	return wsa881x_i2c_write_device(wsa881x, reg, val);
+}
+
+static int wsa881x_i2c_get_client_index(struct i2c_client *client,
+					int *wsa881x_index)
+{
+	int ret = 0;
+
+	switch (client->addr) {
+	case WSA881X_I2C_SPK0_SLAVE0_ADDR:
+	case WSA881X_I2C_SPK0_SLAVE1_ADDR:
+		*wsa881x_index = WSA881X_I2C_SPK0_SLAVE0;
+	break;
+	case WSA881X_I2C_SPK1_SLAVE0_ADDR:
+	case WSA881X_I2C_SPK1_SLAVE1_ADDR:
+		*wsa881x_index = WSA881X_I2C_SPK1_SLAVE0;
+	break;
+	default:
+		ret = -EINVAL;
+	break;
+	}
+	return ret;
+}
+
+static int wsa881x_boost_ctrl(struct snd_soc_component *component, bool enable)
+{
+	struct wsa881x_pdata *wsa881x =
+			snd_soc_component_get_drvdata(component);
+
+
+	pr_debug("%s: enable:%d\n", __func__, enable);
+	if (enable) {
+		if (!WSA881X_IS_2_0(wsa881x->version)) {
+			snd_soc_component_update_bits(component,
+						WSA881X_ANA_CTL, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+						WSA881X_ANA_CTL, 0x04, 0x04);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_PS_CTL,
+						0x40, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_PRESET_OUT1,
+						0xF0, 0xB0);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_ZX_CTL,
+						0x20, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_EN_CTL,
+						0x80, 0x80);
+		} else {
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_LOOP_STABILITY,
+						0x03, 0x03);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_MISC2_CTL,
+						0xFF, 0x14);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_START_CTL,
+						0x80, 0x80);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_START_CTL,
+						0x03, 0x00);
+			snd_soc_component_update_bits(component,
+					WSA881X_BOOST_SLOPE_COMP_ISENSE_FB,
+					0x0C, 0x04);
+			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);
+			snd_soc_component_update_bits(component,
+						WSA881X_ANA_CTL, 0x03, 0x01);
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_DRV_EN,
+						0x08, 0x08);
+			snd_soc_component_update_bits(component,
+						WSA881X_ANA_CTL, 0x04, 0x04);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_CURRENT_LIMIT,
+						0x0F, 0x08);
+			snd_soc_component_update_bits(component,
+						WSA881X_BOOST_EN_CTL,
+						0x80, 0x80);
+		}
+		/* For WSA8810, start-up time is 1500us as per qcrg sequence */
+		usleep_range(1500, 1510);
+	} else {
+		/* ENSURE: Class-D amp is shutdown. CLK is still on */
+		snd_soc_component_update_bits(component,
+					WSA881X_BOOST_EN_CTL, 0x80, 0x00);
+		/* boost settle time is 1500us as per qcrg sequence */
+		usleep_range(1500, 1510);
+	}
+	return 0;
+}
+
+static int wsa881x_visense_txfe_ctrl(struct snd_soc_component *component,
+				     bool enable,
+				     u8 isense1_gain, u8 isense2_gain,
+				     u8 vsense_gain)
+{
+	u8 value = 0;
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	pr_debug("%s: enable:%d\n", __func__, enable);
+
+	if (enable) {
+		if (WSA881X_IS_2_0(wsa881x->version)) {
+			snd_soc_component_update_bits(component,
+						WSA881X_OTP_REG_28,
+						0x3F, 0x3A);
+			snd_soc_component_update_bits(component,
+						WSA881X_BONGO_RESRV_REG1,
+						0xFF, 0xB2);
+			snd_soc_component_update_bits(component,
+						WSA881X_BONGO_RESRV_REG2,
+						0xFF, 0x05);
+		}
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PROT_FE_VSENSE_VCM,
+					0x08, 0x00);
+		if (WSA881X_IS_2_0(wsa881x->version)) {
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PROT_ATEST2,
+					0x1C, 0x04);
+		} else {
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PROT_ATEST2,
+					0x08, 0x08);
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PROT_ATEST2,
+					0x02, 0x02);
+		}
+		value = ((isense2_gain << 6) | (isense1_gain << 4) |
+			(vsense_gain << 3));
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PROT_FE_GAIN,
+					0xF8, value);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PROT_FE_GAIN,
+					0x01, 0x01);
+	} else {
+		if (WSA881X_IS_2_0(wsa881x->version))
+			snd_soc_component_update_bits(component,
+				WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x10, 0x10);
+		else
+			snd_soc_component_update_bits(component,
+				WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x08, 0x08);
+		/*
+		 * 200us sleep is needed after visense txfe disable as per
+		 * HW requirement.
+		 */
+		usleep_range(200, 210);
+
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PROT_FE_GAIN,
+					0x01, 0x00);
+	}
+	return 0;
+}
+
+static int wsa881x_visense_adc_ctrl(struct snd_soc_component *component,
+				    bool enable)
+{
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	pr_debug("%s: enable:%d\n", __func__, enable);
+	if (enable) {
+		if (!WSA881X_IS_2_0(wsa881x->version))
+			snd_soc_component_update_bits(component,
+					WSA881X_ADC_SEL_IBIAS,
+					0x70, 0x40);
+			snd_soc_component_update_bits(component,
+					WSA881X_ADC_EN_SEL_IBIAS,
+					0x07, 0x04);
+			snd_soc_component_update_bits(component,
+					WSA881X_ADC_EN_MODU_V, 0x80, 0x80);
+			snd_soc_component_update_bits(component,
+					WSA881X_ADC_EN_MODU_I, 0x80, 0x80);
+	} else {
+		/* Ensure: Speaker Protection has been stopped */
+		snd_soc_component_update_bits(component,
+					WSA881X_ADC_EN_MODU_V, 0x80, 0x00);
+		snd_soc_component_update_bits(component,
+					WSA881X_ADC_EN_MODU_I, 0x80, 0x00);
+	}
+
+	return 0;
+}
+
+static void wsa881x_bandgap_ctrl(struct snd_soc_component *component,
+				 bool enable)
+{
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s: enable:%d, bg_count:%d\n", __func__,
+		enable, wsa881x->bg_cnt);
+	mutex_lock(&wsa881x->bg_lock);
+	if (enable) {
+		++wsa881x->bg_cnt;
+		if (wsa881x->bg_cnt == 1) {
+			snd_soc_component_update_bits(component,
+						WSA881X_TEMP_OP, 0x08, 0x08);
+			/* 400usec sleep is needed as per HW requirement */
+			usleep_range(400, 410);
+			snd_soc_component_update_bits(component,
+						WSA881X_TEMP_OP, 0x04, 0x04);
+		}
+	} else {
+		--wsa881x->bg_cnt;
+		if (wsa881x->bg_cnt <= 0) {
+			WARN_ON(wsa881x->bg_cnt < 0);
+			wsa881x->bg_cnt = 0;
+			snd_soc_component_update_bits(component,
+						WSA881X_TEMP_OP, 0x04, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA881X_TEMP_OP, 0x08, 0x00);
+		}
+	}
+	mutex_unlock(&wsa881x->bg_lock);
+}
+
+static void wsa881x_clk_ctrl(struct snd_soc_component *component, bool enable)
+{
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s:ss enable:%d, clk_count:%d\n", __func__,
+		enable, wsa881x->clk_cnt);
+	mutex_lock(&wsa881x->res_lock);
+	if (enable) {
+		++wsa881x->clk_cnt;
+		if (wsa881x->clk_cnt == 1) {
+			snd_soc_component_write(component,
+					WSA881X_CDC_RST_CTL, 0x02);
+			snd_soc_component_write(component,
+					WSA881X_CDC_RST_CTL, 0x03);
+			snd_soc_component_write(component,
+					WSA881X_CLOCK_CONFIG, 0x01);
+
+			snd_soc_component_write(component,
+					WSA881X_CDC_DIG_CLK_CTL, 0x01);
+			snd_soc_component_write(component,
+					WSA881X_CDC_ANA_CLK_CTL, 0x01);
+
+		}
+	} else {
+		--wsa881x->clk_cnt;
+		if (wsa881x->clk_cnt <= 0) {
+			WARN_ON(wsa881x->clk_cnt < 0);
+			wsa881x->clk_cnt = 0;
+			snd_soc_component_write(component,
+					WSA881X_CDC_ANA_CLK_CTL, 0x00);
+			snd_soc_component_write(component,
+					WSA881X_CDC_DIG_CLK_CTL, 0x00);
+			if (WSA881X_IS_2_0(wsa881x->version))
+				snd_soc_component_update_bits(component,
+					WSA881X_CDC_TOP_CLK_CTL, 0x01, 0x00);
+		}
+	}
+	mutex_unlock(&wsa881x->res_lock);
+}
+
+static int wsa881x_rdac_ctrl(struct snd_soc_component *component, bool enable)
+{
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	pr_debug("%s: enable:%d\n", __func__, enable);
+	if (enable) {
+		snd_soc_component_update_bits(component,
+					WSA881X_ANA_CTL, 0x08, 0x00);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DRV_GAIN, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DAC_CTL, 0x20, 0x20);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DAC_CTL, 0x20, 0x00);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DAC_CTL, 0x40, 0x40);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DAC_CTL, 0x80, 0x80);
+		if (WSA881X_IS_2_0(wsa881x->version)) {
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_BIAS_CAL, 0x01, 0x01);
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_OCP_CTL, 0x30, 0x30);
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_OCP_CTL, 0x0C, 0x00);
+		}
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DRV_GAIN, 0xF0, 0x40);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_MISC_CTL1, 0x01, 0x01);
+	} else {
+		/* Ensure class-D amp is off */
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DAC_CTL, 0x80, 0x00);
+	}
+	return 0;
+}
+
+static int wsa881x_spkr_pa_ctrl(struct snd_soc_component *component,
+				bool enable)
+{
+	int ret = 0;
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	pr_debug("%s: enable:%d\n", __func__, enable);
+	if (enable) {
+		/*
+		 * Ensure: Boost is enabled and stable, Analog input is up
+		 * and outputting silence
+		 */
+		if (!WSA881X_IS_2_0(wsa881x->version)) {
+			snd_soc_component_update_bits(component,
+						WSA881X_ADC_EN_DET_TEST_I,
+						0xFF, 0x01);
+			snd_soc_component_update_bits(component,
+						WSA881X_ADC_EN_MODU_V,
+						0x02, 0x02);
+			snd_soc_component_update_bits(component,
+						WSA881X_ADC_EN_DET_TEST_V,
+						0xFF, 0x10);
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_PWRSTG_DBG,
+						0xA0, 0xA0);
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_DRV_EN,
+						0x80, 0x80);
+			usleep_range(700, 710);
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_PWRSTG_DBG,
+						0x00, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA881X_ADC_EN_DET_TEST_V,
+						0xFF, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA881X_ADC_EN_MODU_V,
+						0x02, 0x00);
+			snd_soc_component_update_bits(component,
+						WSA881X_ADC_EN_DET_TEST_I,
+						0xFF, 0x00);
+		} else
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DRV_EN, 0x80, 0x80);
+		/* add 1000us delay as per qcrg */
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DRV_EN, 0x01, 0x01);
+		if (WSA881X_IS_2_0(wsa881x->version))
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_BIAS_CAL,
+						0x01, 0x00);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DRV_GAIN,
+					0xF0, (wsa881x->spk_pa_gain << 4));
+		if (wsa881x->visense_enable) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						wsa881x->wsa_vi_gpio_p);
+			if (ret) {
+				pr_err("%s: gpio set cannot be activated %s\n",
+					__func__, "wsa_vi");
+				return ret;
+			}
+			wsa881x_visense_txfe_ctrl(component, true,
+						0x00, 0x01, 0x00);
+			wsa881x_visense_adc_ctrl(component, true);
+		}
+	} else {
+		/*
+		 * Ensure: Boost is still on, Stream from Analog input and
+		 * Speaker Protection has been stopped and input is at 0V
+		 */
+		if (WSA881X_IS_2_0(wsa881x->version)) {
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_BIAS_CAL,
+						0x01, 0x01);
+			usleep_range(1000, 1010);
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_BIAS_CAL,
+						0x01, 0x00);
+			msleep(20);
+			snd_soc_component_update_bits(component,
+						WSA881X_ANA_CTL, 0x03, 0x00);
+			usleep_range(200, 210);
+		}
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DRV_EN, 0x80, 0x00);
+	}
+	return 0;
+}
+
+static int wsa881x_get_boost(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa881x->boost_enable;
+	return 0;
+}
+
+static int wsa881x_set_boost(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: Boost enable current %d, new %d\n",
+		 __func__, wsa881x->boost_enable, value);
+	wsa881x->boost_enable = value;
+	return 0;
+}
+
+static int wsa881x_get_visense(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa881x->visense_enable;
+	return 0;
+}
+
+static int wsa881x_set_visense(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: VIsense enable current %d, new %d\n",
+		 __func__, wsa881x->visense_enable, value);
+	wsa881x->visense_enable = value;
+	return 0;
+}
+
+static const struct snd_kcontrol_new wsa881x_snd_controls[] = {
+	SOC_SINGLE_EXT("BOOST Switch", SND_SOC_NOPM, 0, 1, 0,
+		wsa881x_get_boost, wsa881x_set_boost),
+
+	SOC_SINGLE_EXT("VISENSE Switch", SND_SOC_NOPM, 0, 1, 0,
+		wsa881x_get_visense, wsa881x_set_visense),
+
+	SOC_ENUM_EXT("WSA_SPK PA Gain", wsa881x_spk_pa_gain_enum[0],
+		wsa881x_spk_pa_gain_get, wsa881x_spk_pa_gain_put),
+};
+
+static const char * const rdac_text[] = {
+	"ZERO", "Switch",
+};
+
+static const struct soc_enum rdac_enum =
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(rdac_text), rdac_text);
+
+static const struct snd_kcontrol_new rdac_mux[] = {
+	SOC_DAPM_ENUM("RDAC", rdac_enum)
+};
+
+static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+					snd_soc_dapm_to_component(w->dapm);
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	dev_dbg(component->dev, "%s: %s %d boost %d visense %d\n",
+		 __func__, w->name, event,
+		wsa881x->boost_enable, wsa881x->visense_enable);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = wsa881x_startup(wsa881x);
+		if (ret) {
+			pr_err("%s: wsa startup failed ret: %d", __func__, ret);
+			return ret;
+		}
+		wsa881x_clk_ctrl(component, true);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_DAC_CTL, 0x02, 0x02);
+		if (!WSA881X_IS_2_0(wsa881x->version))
+			snd_soc_component_update_bits(component,
+						WSA881X_BIAS_REF_CTRL,
+						0x0F, 0x08);
+		wsa881x_bandgap_ctrl(component, true);
+		if (!WSA881X_IS_2_0(wsa881x->version))
+			snd_soc_component_update_bits(component,
+						WSA881X_SPKR_BBM_CTL,
+						0x02, 0x02);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_MISC_CTL1, 0xC0, 0x80);
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_MISC_CTL1, 0x06, 0x06);
+		if (!WSA881X_IS_2_0(wsa881x->version)) {
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_MISC_CTL2,
+					0x04, 0x04);
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_BIAS_INT,
+					0x09, 0x09);
+		}
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PA_INT, 0xF0, 0x20);
+		if (WSA881X_IS_2_0(wsa881x->version))
+			snd_soc_component_update_bits(component,
+					WSA881X_SPKR_PA_INT,
+					0x0E, 0x0E);
+		if (wsa881x->boost_enable)
+			wsa881x_boost_ctrl(component, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		wsa881x_rdac_ctrl(component, true);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		wsa881x_rdac_ctrl(component, false);
+		if (wsa881x->visense_enable) {
+			wsa881x_visense_adc_ctrl(component, false);
+			wsa881x_visense_txfe_ctrl(component, false,
+						0x00, 0x01, 0x00);
+			ret = msm_cdc_pinctrl_select_sleep_state(
+						wsa881x->wsa_vi_gpio_p);
+			if (ret) {
+				pr_err("%s: gpio set cannot be suspended %s\n",
+					__func__, "wsa_vi");
+				return ret;
+			}
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (wsa881x->boost_enable)
+			wsa881x_boost_ctrl(component, false);
+		wsa881x_clk_ctrl(component, false);
+		wsa881x_bandgap_ctrl(component, false);
+		ret = wsa881x_shutdown(wsa881x);
+		if (ret < 0) {
+			pr_err("%s: wsa shutdown failed ret: %d",
+					__func__, ret);
+			return ret;
+		}
+		break;
+	default:
+		pr_err("%s: invalid event:%d\n", __func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void wsa881x_ocp_ctl_work(struct work_struct *work)
+{
+	struct wsa881x_pdata *wsa881x;
+	struct delayed_work *dwork;
+	struct snd_soc_component *component;
+	int temp_val;
+
+	dwork = to_delayed_work(work);
+	wsa881x = container_of(dwork, struct wsa881x_pdata, ocp_ctl_work);
+
+	if (!wsa881x)
+		return;
+
+	component = wsa881x->component;
+	wsa881x_get_temp(wsa881x->tz_pdata.tz_dev, &temp_val);
+	dev_dbg(component->dev, " temp = %d\n", temp_val);
+
+	if (temp_val <= WSA881X_OCP_CTL_TEMP_CELSIUS)
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_OCP_CTL, 0xC0, 0x00);
+	else
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_OCP_CTL, 0xC0, 0xC0);
+
+	schedule_delayed_work(&wsa881x->ocp_ctl_work,
+			msecs_to_jiffies(wsa881x_ocp_poll_timer_sec * 1000));
+}
+
+static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+					snd_soc_dapm_to_component(w->dapm);
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	pr_debug("%s: %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+					WSA881X_SPKR_OCP_CTL, 0xC0, 0x80);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		wsa881x_spkr_pa_ctrl(component, true);
+		schedule_delayed_work(&wsa881x->ocp_ctl_work,
+			msecs_to_jiffies(WSA881X_OCP_CTL_TIMER_SEC * 1000));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		wsa881x_spkr_pa_ctrl(component, false);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		cancel_delayed_work_sync(&wsa881x->ocp_ctl_work);
+		snd_soc_component_update_bits(component,
+				WSA881X_SPKR_OCP_CTL, 0xC0, 0xC0);
+		break;
+	default:
+		pr_err("%s: invalid event:%d\n", __func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget wsa881x_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("WSA_IN"),
+
+	SND_SOC_DAPM_DAC_E("RDAC Analog", NULL, SND_SOC_NOPM, 0, 0,
+		wsa881x_rdac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("WSA_RDAC", SND_SOC_NOPM, 0, 0,
+		rdac_mux),
+
+	SND_SOC_DAPM_PGA_S("WSA_SPKR PGA", 1, SND_SOC_NOPM, 0, 0,
+			wsa881x_spkr_pa_event,
+			SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
+			SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_OUTPUT("WSA_SPKR"),
+};
+
+static const struct snd_soc_dapm_route wsa881x_audio_map[] = {
+	{"WSA_RDAC", "Switch", "WSA_IN"},
+	{"RDAC Analog", NULL, "WSA_RDAC"},
+	{"WSA_SPKR PGA", NULL, "RDAC Analog"},
+	{"WSA_SPKR", NULL, "WSA_SPKR PGA"},
+};
+
+
+static int wsa881x_startup(struct wsa881x_pdata *pdata)
+{
+	int ret = 0;
+
+	pr_debug("%s(): wsa startup, enable_cnt:%d\n", __func__,
+					pdata->enable_cnt);
+
+	if (pdata->enable_cnt++ > 0)
+		return 0;
+	ret = msm_cdc_pinctrl_select_active_state(pdata->wsa_clk_gpio_p);
+	if (ret) {
+		pr_err("%s: gpio set cannot be activated %s\n",
+			__func__, "wsa_clk");
+		return ret;
+	}
+	ret = clk_prepare_enable(pdata->wsa_mclk);
+	if (ret) {
+		pr_err("%s: WSA MCLK enable failed\n",
+			__func__);
+		return ret;
+	}
+	ret = wsa881x_reset(pdata, true);
+	return ret;
+}
+
+static int wsa881x_shutdown(struct wsa881x_pdata *pdata)
+{
+	int ret = 0;
+
+	pr_debug("%s(): wsa shutdown, enable_cnt:%d\n", __func__,
+					pdata->enable_cnt);
+	if (--pdata->enable_cnt > 0)
+		return 0;
+	ret = wsa881x_reset(pdata, false);
+	if (ret) {
+		pr_err("%s: wsa reset failed suspend %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	clk_disable_unprepare(pdata->wsa_mclk);
+
+	ret = msm_cdc_pinctrl_select_sleep_state(pdata->wsa_clk_gpio_p);
+	if (ret) {
+		pr_err("%s: gpio set cannot be suspended %s\n",
+			__func__, "wsa_clk");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int32_t wsa881x_resource_acquire(struct snd_soc_component *component,
+						bool enable)
+{
+	int ret = 0;
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	if (enable) {
+		ret = wsa881x_startup(wsa881x);
+		if (ret < 0) {
+			dev_err_ratelimited(component->dev,
+				"%s: failed to startup\n", __func__);
+			return ret;
+		}
+	}
+	wsa881x_clk_ctrl(component, enable);
+	wsa881x_bandgap_ctrl(component, enable);
+	if (!enable) {
+		ret = wsa881x_shutdown(wsa881x);
+		if (ret < 0)
+			dev_err_ratelimited(component->dev,
+				"%s: failed to shutdown\n", __func__);
+	}
+	return ret;
+}
+
+static int32_t wsa881x_temp_reg_read(struct snd_soc_component *component,
+				     struct wsa_temp_register *wsa_temp_reg)
+{
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+	int ret = 0;
+
+	if (!wsa881x) {
+		dev_err(component->dev, "%s: wsa881x is NULL\n", __func__);
+		return -EINVAL;
+	}
+	ret = wsa881x_resource_acquire(component, true);
+	if (ret) {
+		dev_err_ratelimited(component->dev,
+			"%s: resource acquire fail\n", __func__);
+		return ret;
+	}
+
+	if (WSA881X_IS_2_0(wsa881x->version)) {
+		snd_soc_component_update_bits(component,
+					WSA881X_TADC_VALUE_CTL, 0x01, 0x00);
+		wsa_temp_reg->dmeas_msb =
+				snd_soc_component_read32(component,
+							 WSA881X_TEMP_MSB);
+		wsa_temp_reg->dmeas_lsb =
+				snd_soc_component_read32(component,
+							 WSA881X_TEMP_LSB);
+		snd_soc_component_update_bits(component,
+					WSA881X_TADC_VALUE_CTL, 0x01, 0x01);
+	} else {
+		wsa_temp_reg->dmeas_msb = snd_soc_component_read32(component,
+						   WSA881X_TEMP_DOUT_MSB);
+		wsa_temp_reg->dmeas_lsb = snd_soc_component_read32(component,
+						   WSA881X_TEMP_DOUT_LSB);
+	}
+	wsa_temp_reg->d1_msb = snd_soc_component_read32(component,
+							WSA881X_OTP_REG_1);
+	wsa_temp_reg->d1_lsb = snd_soc_component_read32(component,
+							WSA881X_OTP_REG_2);
+	wsa_temp_reg->d2_msb = snd_soc_component_read32(component,
+							WSA881X_OTP_REG_3);
+	wsa_temp_reg->d2_lsb = snd_soc_component_read32(component,
+							WSA881X_OTP_REG_4);
+
+	ret = wsa881x_resource_acquire(component, false);
+	if (ret)
+		dev_err_ratelimited(component->dev,
+			"%s: resource release fail\n", __func__);
+
+	return ret;
+}
+
+static int wsa881x_probe(struct snd_soc_component *component)
+{
+	struct i2c_client *client;
+	int ret = 0;
+	int wsa881x_index = 0;
+	struct snd_soc_dapm_context *dapm =
+					snd_soc_component_get_dapm(component);
+	char *widget_name = NULL;
+	struct snd_soc_card *card = component->card;
+	struct snd_soc_codec_conf *codec_conf = card->codec_conf;
+
+	client = dev_get_drvdata(component->dev);
+	ret = wsa881x_i2c_get_client_index(client, &wsa881x_index);
+	if (ret != 0) {
+		dev_err(&client->dev, "%s: I2C get codec I2C\n"
+			"client failed\n", __func__);
+		return ret;
+	}
+	mutex_init(&wsa_pdata[wsa881x_index].bg_lock);
+	mutex_init(&wsa_pdata[wsa881x_index].res_lock);
+	snprintf(wsa_pdata[wsa881x_index].tz_pdata.name, 100, "%s",
+		wsa_tz_names[wsa881x_index]);
+	wsa_pdata[wsa881x_index].component = component;
+	wsa_pdata[wsa881x_index].spk_pa_gain = SPK_GAIN_12DB;
+	wsa_pdata[wsa881x_index].component = component;
+	wsa_pdata[wsa881x_index].tz_pdata.component = component;
+	wsa_pdata[wsa881x_index].tz_pdata.wsa_temp_reg_read =
+						wsa881x_temp_reg_read;
+	snd_soc_component_set_drvdata(component, &wsa_pdata[wsa881x_index]);
+	wsa881x_init_thermal(&wsa_pdata[wsa881x_index].tz_pdata);
+	INIT_DELAYED_WORK(&wsa_pdata[wsa881x_index].ocp_ctl_work,
+				wsa881x_ocp_ctl_work);
+
+	if (codec_conf->name_prefix) {
+		widget_name = kcalloc(WIDGET_NAME_MAX_SIZE, sizeof(char),
+					GFP_KERNEL);
+		if (!widget_name)
+			return -ENOMEM;
+
+		snprintf(widget_name, WIDGET_NAME_MAX_SIZE,
+			"%s WSA_SPKR", codec_conf->name_prefix);
+		snd_soc_dapm_ignore_suspend(dapm, widget_name);
+		snprintf(widget_name, WIDGET_NAME_MAX_SIZE,
+			"%s WSA_IN", codec_conf->name_prefix);
+		snd_soc_dapm_ignore_suspend(dapm, widget_name);
+		kfree(widget_name);
+	} else {
+		snd_soc_dapm_ignore_suspend(dapm, "WSA_SPKR");
+		snd_soc_dapm_ignore_suspend(dapm, "WSA_IN");
+	}
+
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static void wsa881x_remove(struct snd_soc_component *component)
+{
+	struct wsa881x_pdata *wsa881x =
+				snd_soc_component_get_drvdata(component);
+
+	if (wsa881x->tz_pdata.tz_dev)
+		wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev);
+
+	mutex_destroy(&wsa881x->bg_lock);
+	mutex_destroy(&wsa881x->res_lock);
+}
+
+static const struct snd_soc_component_driver soc_component_dev_wsa881x = {
+	.probe	= wsa881x_probe,
+	.remove	= wsa881x_remove,
+
+	.read = wsa881x_i2c_read,
+	.write = wsa881x_i2c_write,
+
+	.controls = wsa881x_snd_controls,
+	.num_controls = ARRAY_SIZE(wsa881x_snd_controls),
+	.dapm_widgets = wsa881x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wsa881x_dapm_widgets),
+	.dapm_routes = wsa881x_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(wsa881x_audio_map),
+};
+
+static int wsa881x_reset(struct wsa881x_pdata *pdata, bool enable)
+{
+	int ret = 0;
+
+	/*
+	 * shutdown the GPIOs WSA_EN, WSA_MCLK, regulators
+	 * and restore defaults in soc cache when shutdown.
+	 * Enable regulators, GPIOs WSA_MCLK, WSA_EN when powerup.
+	 */
+	if (enable) {
+		if (pdata->wsa_active)
+			return 0;
+		ret = msm_cdc_pinctrl_select_active_state(
+					pdata->wsa_reset_gpio_p);
+		if (ret) {
+			pr_err("%s: gpio set cannot be activated %s\n",
+				__func__, "wsa_reset");
+			return ret;
+		}
+		ret = msm_cdc_pinctrl_select_sleep_state(
+					pdata->wsa_reset_gpio_p);
+		if (ret) {
+			pr_err("%s: gpio set cannot be suspended(powerup) %s\n",
+				__func__, "wsa_reset");
+			return ret;
+		}
+		ret = msm_cdc_pinctrl_select_active_state(
+					pdata->wsa_reset_gpio_p);
+		if (ret) {
+			pr_err("%s: gpio set cannot be activated %s\n",
+				__func__, "wsa_reset");
+			return ret;
+		}
+		pdata->wsa_active = true;
+	} else {
+		if (!pdata->wsa_active)
+			return 0;
+		ret = msm_cdc_pinctrl_select_sleep_state(
+					pdata->wsa_reset_gpio_p);
+		if (ret) {
+			pr_err("%s: gpio set cannot be suspended %s\n",
+				__func__, "wsa_reset");
+			return ret;
+		}
+		pdata->wsa_active = false;
+	}
+	return ret;
+}
+
+int wsa881x_get_client_index(void)
+{
+	return wsa881x_i2c_addr;
+}
+EXPORT_SYMBOL(wsa881x_get_client_index);
+
+int wsa881x_get_probing_count(void)
+{
+	return wsa881x_probing_count;
+}
+EXPORT_SYMBOL(wsa881x_get_probing_count);
+
+int wsa881x_get_presence_count(void)
+{
+	return wsa881x_presence_count;
+}
+EXPORT_SYMBOL(wsa881x_get_presence_count);
+
+static int check_wsa881x_presence(struct i2c_client *client)
+{
+	int ret = 0;
+	int wsa881x_index = 0;
+
+	ret = wsa881x_i2c_get_client_index(client, &wsa881x_index);
+	if (ret != 0) {
+		dev_err(&client->dev, "%s: I2C get codec I2C\n"
+			"client failed\n", __func__);
+		return ret;
+	}
+	ret = wsa881x_i2c_read_device(&wsa_pdata[wsa881x_index],
+					WSA881X_CDC_RST_CTL);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to read wsa881x with addr %x\n",
+				client->addr);
+		return ret;
+	}
+	ret = wsa881x_i2c_write_device(&wsa_pdata[wsa881x_index],
+					WSA881X_CDC_RST_CTL, 0x01);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed write addr %x reg:0x5 val:0x1\n",
+					client->addr);
+		return ret;
+	}
+	/* allow 20ms before trigger next write to verify wsa881x presence */
+	msleep(20);
+	ret = wsa881x_i2c_write_device(&wsa_pdata[wsa881x_index],
+					WSA881X_CDC_RST_CTL, 0x00);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed write addr %x reg:0x5 val:0x0\n",
+					client->addr);
+		return ret;
+	}
+	return ret;
+}
+
+static int wsa881x_populate_dt_pdata(struct device *dev, int wsa881x_index)
+{
+	int ret = 0;
+	struct wsa881x_pdata *pdata = &wsa_pdata[wsa881x_index];
+
+	/* reading the gpio configurations from dtsi file */
+	pdata->wsa_vi_gpio_p = of_parse_phandle(dev->of_node,
+				"qcom,wsa-analog-vi-gpio", 0);
+	pdata->wsa_clk_gpio_p = of_parse_phandle(dev->of_node,
+				"qcom,wsa-analog-clk-gpio", 0);
+	pdata->wsa_reset_gpio_p = of_parse_phandle(dev->of_node,
+				"qcom,wsa-analog-reset-gpio", 0);
+	pinctrl_init = true;
+	return ret;
+}
+
+static int wsa881x_i2c_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret = 0;
+	int wsa881x_index = 0;
+	struct wsa881x_pdata *pdata = NULL;
+	struct clk *wsa_mclk = NULL;
+
+	ret = wsa881x_i2c_get_client_index(client, &wsa881x_index);
+	if (ret != 0) {
+		dev_err(&client->dev, "%s: I2C get codec I2C\n"
+			"client failed\n", __func__);
+		return ret;
+	}
+
+	pdata = &wsa_pdata[wsa881x_index];
+	if ((client->addr == WSA881X_I2C_SPK0_SLAVE1_ADDR ||
+		client->addr == WSA881X_I2C_SPK1_SLAVE1_ADDR) &&
+		(pdata->status == WSA881X_STATUS_PROBING)) {
+		wsa881x_probing_count++;
+		return -EPROBE_DEFER;
+	}
+
+	if (pdata->status == WSA881X_STATUS_I2C) {
+		dev_dbg(&client->dev, "%s:probe for other slaves\n"
+			"devices of codec I2C slave Addr = %x\n",
+			__func__, client->addr);
+		dev_dbg(&client->dev, "%s:wsa_idx = %d SLAVE = %d\n",
+				__func__, wsa881x_index, WSA881X_ANALOG_SLAVE);
+		pdata->regmap[WSA881X_ANALOG_SLAVE] =
+			devm_regmap_init_i2c(
+				client,
+			&wsa881x_ana_regmap_config[WSA881X_ANALOG_SLAVE]);
+		regcache_cache_bypass(pdata->regmap[WSA881X_ANALOG_SLAVE],
+					true);
+		if (IS_ERR(pdata->regmap[WSA881X_ANALOG_SLAVE])) {
+			ret = PTR_ERR(pdata->regmap[WSA881X_ANALOG_SLAVE]);
+			dev_err(&client->dev,
+				"%s: regmap_init failed %d\n",
+					__func__, ret);
+		}
+		client->dev.platform_data = pdata;
+		i2c_set_clientdata(client, pdata);
+		pdata->client[WSA881X_ANALOG_SLAVE] = client;
+		if (pdata->version == WSA881X_2_0)
+			wsa881x_update_regmap_2_0(
+					pdata->regmap[WSA881X_ANALOG_SLAVE],
+					WSA881X_ANALOG_SLAVE);
+
+		wsa881x_probing_count++;
+		return ret;
+	} else if (pdata->status == WSA881X_STATUS_PROBING) {
+		pdata->index = wsa881x_index;
+		if (client->dev.of_node) {
+			dev_dbg(&client->dev, "%s:Platform data\n"
+				"from device tree\n", __func__);
+			ret = wsa881x_populate_dt_pdata(
+					&client->dev, wsa881x_index);
+			if (ret < 0) {
+				dev_err(&client->dev,
+				"%s: Fail to obtain pdata from device tree\n",
+					 __func__);
+				ret = -EINVAL;
+				goto err;
+			}
+			client->dev.platform_data = pdata;
+		} else {
+			dev_dbg(&client->dev, "%s:Platform data from\n"
+				"board file\n", __func__);
+			pdata = client->dev.platform_data;
+		}
+		if (!pdata) {
+			dev_dbg(&client->dev, "no platform data?\n");
+			ret = -EINVAL;
+			goto err;
+		}
+		wsa_mclk = devm_clk_get(&client->dev, "wsa_mclk");
+		if (IS_ERR(wsa_mclk)) {
+			ret = PTR_ERR(wsa_mclk);
+			dev_dbg(&client->dev, "%s: clk get %s failed %d\n",
+				__func__, "wsa_mclk", ret);
+			wsa_mclk = NULL;
+			goto err;
+		}
+		pdata->wsa_mclk = wsa_mclk;
+		dev_set_drvdata(&client->dev, client);
+
+		pdata->regmap[WSA881X_DIGITAL_SLAVE] =
+			devm_regmap_init_i2c(
+				client,
+			&wsa881x_ana_regmap_config[WSA881X_DIGITAL_SLAVE]);
+		regcache_cache_bypass(pdata->regmap[WSA881X_DIGITAL_SLAVE],
+					true);
+		if (IS_ERR(pdata->regmap[WSA881X_DIGITAL_SLAVE])) {
+			ret = PTR_ERR(pdata->regmap[WSA881X_DIGITAL_SLAVE]);
+			dev_err(&client->dev, "%s: regmap_init failed %d\n",
+				__func__, ret);
+			goto err;
+		}
+
+		/* bus reset sequence */
+		ret = wsa881x_reset(pdata, true);
+		if (ret < 0) {
+			wsa881x_probing_count++;
+			dev_err(&client->dev, "%s: WSA enable Failed %d\n",
+				__func__, ret);
+			goto err;
+		}
+		pdata->client[WSA881X_DIGITAL_SLAVE] = client;
+		pdata->regmap_flag = true;
+		ret = check_wsa881x_presence(client);
+		if (ret < 0) {
+			dev_err(&client->dev,
+				"failed to ping wsa with addr:%x, ret = %d\n",
+						client->addr, ret);
+			wsa881x_probing_count++;
+			goto err1;
+		}
+		pdata->version = wsa881x_i2c_read_device(pdata,
+					WSA881X_CHIP_ID1);
+		pr_debug("%s: wsa881x version: %d\n", __func__, pdata->version);
+		if (pdata->version == WSA881X_2_0) {
+			wsa881x_update_reg_defaults_2_0();
+			wsa881x_update_regmap_2_0(
+					pdata->regmap[WSA881X_DIGITAL_SLAVE],
+					WSA881X_DIGITAL_SLAVE);
+		}
+		wsa881x_presence_count++;
+		wsa881x_probing_count++;
+		ret = snd_soc_register_component(&client->dev,
+					&soc_component_dev_wsa881x,
+					NULL, 0);
+		if (ret < 0)
+			goto err1;
+		pdata->status = WSA881X_STATUS_I2C;
+	}
+err1:
+	wsa881x_reset(pdata, false);
+err:
+	return ret;
+}
+
+static int wsa881x_i2c_remove(struct i2c_client *client)
+{
+	struct wsa881x_pdata *wsa881x = client->dev.platform_data;
+
+	snd_soc_unregister_component(&client->dev);
+	i2c_set_clientdata(client, NULL);
+	kfree(wsa881x);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int wsa881x_i2c_suspend(struct device *dev)
+{
+	pr_debug("%s: system suspend\n", __func__);
+	return 0;
+}
+
+static int wsa881x_i2c_resume(struct device *dev)
+{
+	pr_debug("%s: system resume\n", __func__);
+	return 0;
+}
+
+static const struct dev_pm_ops wsa881x_i2c_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(wsa881x_i2c_suspend, wsa881x_i2c_resume)
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct i2c_device_id wsa881x_i2c_id[] = {
+	{"wsa881x-i2c-dev", WSA881X_I2C_SPK0_SLAVE0_ADDR},
+	{"wsa881x-i2c-dev", WSA881X_I2C_SPK0_SLAVE1_ADDR},
+	{"wsa881x-i2c-dev", WSA881X_I2C_SPK1_SLAVE0_ADDR},
+	{"wsa881x-i2c-dev", WSA881X_I2C_SPK1_SLAVE1_ADDR},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, wsa881x_i2c_id);
+
+
+static const struct of_device_id msm_match_table[] = {
+	{.compatible = "qcom,wsa881x-i2c-codec"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_match_table);
+
+static struct i2c_driver wsa881x_codec_driver = {
+	.driver = {
+		.name = "wsa881x-i2c-codec",
+		.owner = THIS_MODULE,
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+#ifdef CONFIG_PM_SLEEP
+		.pm = &wsa881x_i2c_pm_ops,
+#endif
+		.of_match_table = msm_match_table,
+	},
+	.id_table = wsa881x_i2c_id,
+	.probe = wsa881x_i2c_probe,
+	.remove = wsa881x_i2c_remove,
+};
+
+static int __init wsa881x_codec_init(void)
+{
+	int i = 0;
+
+	for (i = 0; i < MAX_WSA881X_DEVICE; i++)
+		wsa_pdata[i].status = WSA881X_STATUS_PROBING;
+	return i2c_add_driver(&wsa881x_codec_driver);
+}
+module_init(wsa881x_codec_init);
+
+static void __exit wsa881x_codec_exit(void)
+{
+	i2c_del_driver(&wsa881x_codec_driver);
+}
+
+module_exit(wsa881x_codec_exit);
+
+MODULE_DESCRIPTION("WSA881x Codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/asoc/codecs/wsa881x-analog.h b/asoc/codecs/wsa881x-analog.h
new file mode 100644
index 0000000..0aa86a9
--- /dev/null
+++ b/asoc/codecs/wsa881x-analog.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2015, 2018-2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _WSA881X_H
+#define _WSA881X_H
+
+#include <linux/regmap.h>
+#include "wsa881x-registers-analog.h"
+#include <sound/soc.h>
+
+#define WSA881X_I2C_SPK0_SLAVE0_ADDR	0x0E
+#define WSA881X_I2C_SPK0_SLAVE1_ADDR	0x44
+#define WSA881X_I2C_SPK1_SLAVE0_ADDR	0x0F
+#define WSA881X_I2C_SPK1_SLAVE1_ADDR	0x45
+
+#define WSA881X_I2C_SPK0_SLAVE0	0
+#define WSA881X_I2C_SPK1_SLAVE0	1
+#define MAX_WSA881X_DEVICE 2
+#define WSA881X_DIGITAL_SLAVE 0
+#define WSA881X_ANALOG_SLAVE 1
+
+enum {
+	WSA881X_1_X = 0,
+	WSA881X_2_0,
+};
+
+#define WSA881X_IS_2_0(ver) \
+	((ver == WSA881X_2_0) ? 1 : 0)
+
+extern const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE];
+extern struct reg_default wsa881x_ana_reg_defaults[WSA881X_CACHE_SIZE];
+extern struct regmap_config wsa881x_ana_regmap_config[2];
+int wsa881x_get_client_index(void);
+int wsa881x_get_probing_count(void);
+int wsa881x_get_presence_count(void);
+int wsa881x_set_mclk_callback(
+	int (*enable_mclk_callback)(struct snd_soc_card *, bool));
+void wsa881x_update_reg_defaults_2_0(void);
+void wsa881x_update_regmap_2_0(struct regmap *regmap, int flag);
+
+#endif /* _WSA881X_H */
diff --git a/asoc/codecs/wsa881x-registers-analog.h b/asoc/codecs/wsa881x-registers-analog.h
new file mode 100644
index 0000000..2f24023
--- /dev/null
+++ b/asoc/codecs/wsa881x-registers-analog.h
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2015, 2018-2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef WSA881X_REGISTERS_H
+#define WSA881X_REGISTERS_H
+
+#define WSA881X_DIGITAL_BASE	0x0000
+#define WSA881X_ANALOG_BASE	0x0100
+
+#define WSA881X_CHIP_ID0                        (WSA881X_DIGITAL_BASE+0x0000)
+#define WSA881X_CHIP_ID1			(WSA881X_DIGITAL_BASE+0x0001)
+#define WSA881X_CHIP_ID2			(WSA881X_DIGITAL_BASE+0x0002)
+#define WSA881X_CHIP_ID3			(WSA881X_DIGITAL_BASE+0x0003)
+#define WSA881X_BUS_ID				(WSA881X_DIGITAL_BASE+0x0004)
+#define WSA881X_CDC_RST_CTL			(WSA881X_DIGITAL_BASE+0x0005)
+#define WSA881X_CDC_TOP_CLK_CTL			(WSA881X_DIGITAL_BASE+0x0006)
+#define WSA881X_CDC_ANA_CLK_CTL			(WSA881X_DIGITAL_BASE+0x0007)
+#define WSA881X_CDC_DIG_CLK_CTL			(WSA881X_DIGITAL_BASE+0x0008)
+#define WSA881X_CLOCK_CONFIG			(WSA881X_DIGITAL_BASE+0x0009)
+#define WSA881X_ANA_CTL				(WSA881X_DIGITAL_BASE+0x000A)
+#define WSA881X_SWR_RESET_EN			(WSA881X_DIGITAL_BASE+0x000B)
+#define WSA881X_RESET_CTL			(WSA881X_DIGITAL_BASE+0x000C)
+#define WSA881X_TADC_VALUE_CTL			(WSA881X_DIGITAL_BASE+0x000F)
+#define WSA881X_TEMP_DETECT_CTL			(WSA881X_DIGITAL_BASE+0x0010)
+#define WSA881X_TEMP_MSB			(WSA881X_DIGITAL_BASE+0x0011)
+#define WSA881X_TEMP_LSB			(WSA881X_DIGITAL_BASE+0x0012)
+#define WSA881X_TEMP_CONFIG0			(WSA881X_DIGITAL_BASE+0x0013)
+#define WSA881X_TEMP_CONFIG1			(WSA881X_DIGITAL_BASE+0x0014)
+#define WSA881X_CDC_CLIP_CTL			(WSA881X_DIGITAL_BASE+0x0015)
+#define WSA881X_SDM_PDM9_LSB			(WSA881X_DIGITAL_BASE+0x0016)
+#define WSA881X_SDM_PDM9_MSB			(WSA881X_DIGITAL_BASE+0x0017)
+#define WSA881X_CDC_RX_CTL			(WSA881X_DIGITAL_BASE+0x0018)
+#define WSA881X_DEM_BYPASS_DATA0		(WSA881X_DIGITAL_BASE+0x0019)
+#define WSA881X_DEM_BYPASS_DATA1		(WSA881X_DIGITAL_BASE+0x001A)
+#define WSA881X_DEM_BYPASS_DATA2		(WSA881X_DIGITAL_BASE+0x001B)
+#define WSA881X_DEM_BYPASS_DATA3		(WSA881X_DIGITAL_BASE+0x001C)
+#define WSA881X_OTP_CTRL0			(WSA881X_DIGITAL_BASE+0x001D)
+#define WSA881X_OTP_CTRL1			(WSA881X_DIGITAL_BASE+0x001E)
+#define WSA881X_HDRIVE_CTL_GROUP1		(WSA881X_DIGITAL_BASE+0x001F)
+#define WSA881X_INTR_MODE			(WSA881X_DIGITAL_BASE+0x0020)
+#define WSA881X_INTR_MASK			(WSA881X_DIGITAL_BASE+0x0021)
+#define WSA881X_INTR_STATUS			(WSA881X_DIGITAL_BASE+0x0022)
+#define WSA881X_INTR_CLEAR			(WSA881X_DIGITAL_BASE+0x0023)
+#define WSA881X_INTR_LEVEL			(WSA881X_DIGITAL_BASE+0x0024)
+#define WSA881X_INTR_SET			(WSA881X_DIGITAL_BASE+0x0025)
+#define WSA881X_INTR_TEST			(WSA881X_DIGITAL_BASE+0x0026)
+#define WSA881X_PDM_TEST_MODE			(WSA881X_DIGITAL_BASE+0x0030)
+#define WSA881X_ATE_TEST_MODE			(WSA881X_DIGITAL_BASE+0x0031)
+#define WSA881X_PIN_CTL_MODE			(WSA881X_DIGITAL_BASE+0x0032)
+#define WSA881X_PIN_CTL_OE			(WSA881X_DIGITAL_BASE+0x0033)
+#define WSA881X_PIN_WDATA_IOPAD			(WSA881X_DIGITAL_BASE+0x0034)
+#define WSA881X_PIN_STATUS			(WSA881X_DIGITAL_BASE+0x0035)
+#define WSA881X_DIG_DEBUG_MODE			(WSA881X_DIGITAL_BASE+0x0037)
+#define WSA881X_DIG_DEBUG_SEL			(WSA881X_DIGITAL_BASE+0x0038)
+#define WSA881X_DIG_DEBUG_EN			(WSA881X_DIGITAL_BASE+0x0039)
+#define WSA881X_SWR_HM_TEST1			(WSA881X_DIGITAL_BASE+0x003B)
+#define WSA881X_SWR_HM_TEST2			(WSA881X_DIGITAL_BASE+0x003C)
+#define WSA881X_TEMP_DETECT_DBG_CTL		(WSA881X_DIGITAL_BASE+0x003D)
+#define WSA881X_TEMP_DEBUG_MSB			(WSA881X_DIGITAL_BASE+0x003E)
+#define WSA881X_TEMP_DEBUG_LSB			(WSA881X_DIGITAL_BASE+0x003F)
+#define WSA881X_SAMPLE_EDGE_SEL			(WSA881X_DIGITAL_BASE+0x0044)
+#define WSA881X_IOPAD_CTL			(WSA881X_DIGITAL_BASE+0x0045)
+#define WSA881X_SPARE_0				(WSA881X_DIGITAL_BASE+0x0050)
+#define WSA881X_SPARE_1				(WSA881X_DIGITAL_BASE+0x0051)
+#define WSA881X_SPARE_2				(WSA881X_DIGITAL_BASE+0x0052)
+#define WSA881X_OTP_REG_0			(WSA881X_DIGITAL_BASE+0x0080)
+#define WSA881X_OTP_REG_1			(WSA881X_DIGITAL_BASE+0x0081)
+#define WSA881X_OTP_REG_2			(WSA881X_DIGITAL_BASE+0x0082)
+#define WSA881X_OTP_REG_3			(WSA881X_DIGITAL_BASE+0x0083)
+#define WSA881X_OTP_REG_4			(WSA881X_DIGITAL_BASE+0x0084)
+#define WSA881X_OTP_REG_5			(WSA881X_DIGITAL_BASE+0x0085)
+#define WSA881X_OTP_REG_6			(WSA881X_DIGITAL_BASE+0x0086)
+#define WSA881X_OTP_REG_7			(WSA881X_DIGITAL_BASE+0x0087)
+#define WSA881X_OTP_REG_8			(WSA881X_DIGITAL_BASE+0x0088)
+#define WSA881X_OTP_REG_9			(WSA881X_DIGITAL_BASE+0x0089)
+#define WSA881X_OTP_REG_10			(WSA881X_DIGITAL_BASE+0x008A)
+#define WSA881X_OTP_REG_11			(WSA881X_DIGITAL_BASE+0x008B)
+#define WSA881X_OTP_REG_12			(WSA881X_DIGITAL_BASE+0x008C)
+#define WSA881X_OTP_REG_13			(WSA881X_DIGITAL_BASE+0x008D)
+#define WSA881X_OTP_REG_14			(WSA881X_DIGITAL_BASE+0x008E)
+#define WSA881X_OTP_REG_15			(WSA881X_DIGITAL_BASE+0x008F)
+#define WSA881X_OTP_REG_16			(WSA881X_DIGITAL_BASE+0x0090)
+#define WSA881X_OTP_REG_17			(WSA881X_DIGITAL_BASE+0x0091)
+#define WSA881X_OTP_REG_18			(WSA881X_DIGITAL_BASE+0x0092)
+#define WSA881X_OTP_REG_19			(WSA881X_DIGITAL_BASE+0x0093)
+#define WSA881X_OTP_REG_20			(WSA881X_DIGITAL_BASE+0x0094)
+#define WSA881X_OTP_REG_21			(WSA881X_DIGITAL_BASE+0x0095)
+#define WSA881X_OTP_REG_22			(WSA881X_DIGITAL_BASE+0x0096)
+#define WSA881X_OTP_REG_23			(WSA881X_DIGITAL_BASE+0x0097)
+#define WSA881X_OTP_REG_24			(WSA881X_DIGITAL_BASE+0x0098)
+#define WSA881X_OTP_REG_25			(WSA881X_DIGITAL_BASE+0x0099)
+#define WSA881X_OTP_REG_26			(WSA881X_DIGITAL_BASE+0x009A)
+#define WSA881X_OTP_REG_27			(WSA881X_DIGITAL_BASE+0x009B)
+#define WSA881X_OTP_REG_28			(WSA881X_DIGITAL_BASE+0x009C)
+#define WSA881X_OTP_REG_29			(WSA881X_DIGITAL_BASE+0x009D)
+#define WSA881X_OTP_REG_30			(WSA881X_DIGITAL_BASE+0x009E)
+#define WSA881X_OTP_REG_31			(WSA881X_DIGITAL_BASE+0x009F)
+#define WSA881X_OTP_REG_32			(WSA881X_DIGITAL_BASE+0x00A0)
+#define WSA881X_OTP_REG_33			(WSA881X_DIGITAL_BASE+0x00A1)
+#define WSA881X_OTP_REG_34			(WSA881X_DIGITAL_BASE+0x00A2)
+#define WSA881X_OTP_REG_35			(WSA881X_DIGITAL_BASE+0x00A3)
+#define WSA881X_OTP_REG_36			(WSA881X_DIGITAL_BASE+0x00A4)
+#define WSA881X_OTP_REG_37			(WSA881X_DIGITAL_BASE+0x00A5)
+#define WSA881X_OTP_REG_38			(WSA881X_DIGITAL_BASE+0x00A6)
+#define WSA881X_OTP_REG_39			(WSA881X_DIGITAL_BASE+0x00A7)
+#define WSA881X_OTP_REG_40			(WSA881X_DIGITAL_BASE+0x00A8)
+#define WSA881X_OTP_REG_41			(WSA881X_DIGITAL_BASE+0x00A9)
+#define WSA881X_OTP_REG_42			(WSA881X_DIGITAL_BASE+0x00AA)
+#define WSA881X_OTP_REG_43			(WSA881X_DIGITAL_BASE+0x00AB)
+#define WSA881X_OTP_REG_44			(WSA881X_DIGITAL_BASE+0x00AC)
+#define WSA881X_OTP_REG_45			(WSA881X_DIGITAL_BASE+0x00AD)
+#define WSA881X_OTP_REG_46			(WSA881X_DIGITAL_BASE+0x00AE)
+#define WSA881X_OTP_REG_47			(WSA881X_DIGITAL_BASE+0x00AF)
+#define WSA881X_OTP_REG_48			(WSA881X_DIGITAL_BASE+0x00B0)
+#define WSA881X_OTP_REG_49			(WSA881X_DIGITAL_BASE+0x00B1)
+#define WSA881X_OTP_REG_50			(WSA881X_DIGITAL_BASE+0x00B2)
+#define WSA881X_OTP_REG_51			(WSA881X_DIGITAL_BASE+0x00B3)
+#define WSA881X_OTP_REG_52			(WSA881X_DIGITAL_BASE+0x00B4)
+#define WSA881X_OTP_REG_53			(WSA881X_DIGITAL_BASE+0x00B5)
+#define WSA881X_OTP_REG_54			(WSA881X_DIGITAL_BASE+0x00B6)
+#define WSA881X_OTP_REG_55			(WSA881X_DIGITAL_BASE+0x00B7)
+#define WSA881X_OTP_REG_56			(WSA881X_DIGITAL_BASE+0x00B8)
+#define WSA881X_OTP_REG_57			(WSA881X_DIGITAL_BASE+0x00B9)
+#define WSA881X_OTP_REG_58			(WSA881X_DIGITAL_BASE+0x00BA)
+#define WSA881X_OTP_REG_59			(WSA881X_DIGITAL_BASE+0x00BB)
+#define WSA881X_OTP_REG_60			(WSA881X_DIGITAL_BASE+0x00BC)
+#define WSA881X_OTP_REG_61			(WSA881X_DIGITAL_BASE+0x00BD)
+#define WSA881X_OTP_REG_62			(WSA881X_DIGITAL_BASE+0x00BE)
+#define WSA881X_OTP_REG_63			(WSA881X_DIGITAL_BASE+0x00BF)
+/* Analog Register address space */
+#define WSA881X_BIAS_REF_CTRL			(WSA881X_ANALOG_BASE+0x0000)
+#define WSA881X_BIAS_TEST			(WSA881X_ANALOG_BASE+0x0001)
+#define WSA881X_BIAS_BIAS			(WSA881X_ANALOG_BASE+0x0002)
+#define WSA881X_TEMP_OP				(WSA881X_ANALOG_BASE+0x0003)
+#define WSA881X_TEMP_IREF_CTRL			(WSA881X_ANALOG_BASE+0x0004)
+#define WSA881X_TEMP_ISENS_CTRL			(WSA881X_ANALOG_BASE+0x0005)
+#define WSA881X_TEMP_CLK_CTRL			(WSA881X_ANALOG_BASE+0x0006)
+#define WSA881X_TEMP_TEST			(WSA881X_ANALOG_BASE+0x0007)
+#define WSA881X_TEMP_BIAS			(WSA881X_ANALOG_BASE+0x0008)
+#define WSA881X_TEMP_ADC_CTRL			(WSA881X_ANALOG_BASE+0x0009)
+#define WSA881X_TEMP_DOUT_MSB			(WSA881X_ANALOG_BASE+0x000A)
+#define WSA881X_TEMP_DOUT_LSB			(WSA881X_ANALOG_BASE+0x000B)
+#define WSA881X_ADC_EN_MODU_V			(WSA881X_ANALOG_BASE+0x0010)
+#define WSA881X_ADC_EN_MODU_I			(WSA881X_ANALOG_BASE+0x0011)
+#define WSA881X_ADC_EN_DET_TEST_V		(WSA881X_ANALOG_BASE+0x0012)
+#define WSA881X_ADC_EN_DET_TEST_I		(WSA881X_ANALOG_BASE+0x0013)
+#define WSA881X_ADC_SEL_IBIAS			(WSA881X_ANALOG_BASE+0x0014)
+#define WSA881X_ADC_EN_SEL_IBIAS		(WSA881X_ANALOG_BASE+0x0015)
+#define WSA881X_SPKR_DRV_EN			(WSA881X_ANALOG_BASE+0x001A)
+#define WSA881X_SPKR_DRV_GAIN			(WSA881X_ANALOG_BASE+0x001B)
+#define WSA881X_SPKR_DAC_CTL			(WSA881X_ANALOG_BASE+0x001C)
+#define WSA881X_SPKR_DRV_DBG			(WSA881X_ANALOG_BASE+0x001D)
+#define WSA881X_SPKR_PWRSTG_DBG			(WSA881X_ANALOG_BASE+0x001E)
+#define WSA881X_SPKR_OCP_CTL			(WSA881X_ANALOG_BASE+0x001F)
+#define WSA881X_SPKR_CLIP_CTL			(WSA881X_ANALOG_BASE+0x0020)
+#define WSA881X_SPKR_BBM_CTL			(WSA881X_ANALOG_BASE+0x0021)
+#define WSA881X_SPKR_MISC_CTL1			(WSA881X_ANALOG_BASE+0x0022)
+#define WSA881X_SPKR_MISC_CTL2			(WSA881X_ANALOG_BASE+0x0023)
+#define WSA881X_SPKR_BIAS_INT			(WSA881X_ANALOG_BASE+0x0024)
+#define WSA881X_SPKR_PA_INT			(WSA881X_ANALOG_BASE+0x0025)
+#define WSA881X_SPKR_BIAS_CAL			(WSA881X_ANALOG_BASE+0x0026)
+#define WSA881X_SPKR_BIAS_PSRR			(WSA881X_ANALOG_BASE+0x0027)
+#define WSA881X_SPKR_STATUS1			(WSA881X_ANALOG_BASE+0x0028)
+#define WSA881X_SPKR_STATUS2			(WSA881X_ANALOG_BASE+0x0029)
+#define WSA881X_BOOST_EN_CTL			(WSA881X_ANALOG_BASE+0x002A)
+#define WSA881X_BOOST_CURRENT_LIMIT		(WSA881X_ANALOG_BASE+0x002B)
+#define WSA881X_BOOST_PS_CTL			(WSA881X_ANALOG_BASE+0x002C)
+#define WSA881X_BOOST_PRESET_OUT1		(WSA881X_ANALOG_BASE+0x002D)
+#define WSA881X_BOOST_PRESET_OUT2		(WSA881X_ANALOG_BASE+0x002E)
+#define WSA881X_BOOST_FORCE_OUT			(WSA881X_ANALOG_BASE+0x002F)
+#define WSA881X_BOOST_LDO_PROG			(WSA881X_ANALOG_BASE+0x0030)
+#define WSA881X_BOOST_SLOPE_COMP_ISENSE_FB	(WSA881X_ANALOG_BASE+0x0031)
+#define WSA881X_BOOST_RON_CTL			(WSA881X_ANALOG_BASE+0x0032)
+#define WSA881X_BOOST_LOOP_STABILITY		(WSA881X_ANALOG_BASE+0x0033)
+#define WSA881X_BOOST_ZX_CTL			(WSA881X_ANALOG_BASE+0x0034)
+#define WSA881X_BOOST_START_CTL			(WSA881X_ANALOG_BASE+0x0035)
+#define WSA881X_BOOST_MISC1_CTL			(WSA881X_ANALOG_BASE+0x0036)
+#define WSA881X_BOOST_MISC2_CTL			(WSA881X_ANALOG_BASE+0x0037)
+#define WSA881X_BOOST_MISC3_CTL			(WSA881X_ANALOG_BASE+0x0038)
+#define WSA881X_BOOST_ATEST_CTL			(WSA881X_ANALOG_BASE+0x0039)
+#define WSA881X_SPKR_PROT_FE_GAIN		(WSA881X_ANALOG_BASE+0x003A)
+#define WSA881X_SPKR_PROT_FE_CM_LDO_SET		(WSA881X_ANALOG_BASE+0x003B)
+#define WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1	(WSA881X_ANALOG_BASE+0x003C)
+#define WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2	(WSA881X_ANALOG_BASE+0x003D)
+#define WSA881X_SPKR_PROT_ATEST1		(WSA881X_ANALOG_BASE+0x003E)
+#define WSA881X_SPKR_PROT_ATEST2		(WSA881X_ANALOG_BASE+0x003F)
+#define WSA881X_SPKR_PROT_FE_VSENSE_VCM		(WSA881X_ANALOG_BASE+0x0040)
+#define WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1	(WSA881X_ANALOG_BASE+0x0041)
+#define WSA881X_BONGO_RESRV_REG1		(WSA881X_ANALOG_BASE+0x0042)
+#define WSA881X_BONGO_RESRV_REG2		(WSA881X_ANALOG_BASE+0x0043)
+#define WSA881X_SPKR_PROT_SAR			(WSA881X_ANALOG_BASE+0x0044)
+#define WSA881X_SPKR_STATUS3			(WSA881X_ANALOG_BASE+0x0045)
+
+#define WSA881X_NUM_REGISTERS		(WSA881X_SPKR_STATUS3+1)
+#define WSA881X_MAX_REGISTER		(WSA881X_NUM_REGISTERS-1)
+#define WSA881X_CACHE_SIZE		WSA881X_NUM_REGISTERS
+#endif /* WSA881X_REGISTERS_H */
diff --git a/asoc/codecs/wsa881x-regmap-analog.c b/asoc/codecs/wsa881x-regmap-analog.c
new file mode 100644
index 0000000..7353057
--- /dev/null
+++ b/asoc/codecs/wsa881x-regmap-analog.c
@@ -0,0 +1,491 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015, 2018-2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "wsa881x-registers-analog.h"
+#include "wsa881x-analog.h"
+
+struct reg_default wsa881x_ana_reg_defaults[] = {
+	{WSA881X_CHIP_ID0, 0x00},
+	{WSA881X_CHIP_ID1, 0x00},
+	{WSA881X_CHIP_ID2, 0x00},
+	{WSA881X_CHIP_ID3, 0x02},
+	{WSA881X_BUS_ID, 0x00},
+	{WSA881X_CDC_RST_CTL, 0x00},
+	{WSA881X_CDC_TOP_CLK_CTL, 0x03},
+	{WSA881X_CDC_ANA_CLK_CTL, 0x00},
+	{WSA881X_CDC_DIG_CLK_CTL, 0x00},
+	{WSA881X_CLOCK_CONFIG, 0x00},
+	{WSA881X_ANA_CTL, 0x08},
+	{WSA881X_SWR_RESET_EN, 0x00},
+	{WSA881X_TEMP_DETECT_CTL, 0x01},
+	{WSA881X_TEMP_MSB, 0x00},
+	{WSA881X_TEMP_LSB, 0x00},
+	{WSA881X_TEMP_CONFIG0, 0x00},
+	{WSA881X_TEMP_CONFIG1, 0x00},
+	{WSA881X_CDC_CLIP_CTL, 0x03},
+	{WSA881X_SDM_PDM9_LSB, 0x00},
+	{WSA881X_SDM_PDM9_MSB, 0x00},
+	{WSA881X_CDC_RX_CTL, 0x7E},
+	{WSA881X_DEM_BYPASS_DATA0, 0x00},
+	{WSA881X_DEM_BYPASS_DATA1, 0x00},
+	{WSA881X_DEM_BYPASS_DATA2, 0x00},
+	{WSA881X_DEM_BYPASS_DATA3, 0x00},
+	{WSA881X_OTP_CTRL0, 0x00},
+	{WSA881X_OTP_CTRL1, 0x00},
+	{WSA881X_HDRIVE_CTL_GROUP1, 0x00},
+	{WSA881X_INTR_MODE, 0x00},
+	{WSA881X_INTR_MASK, 0x1F},
+	{WSA881X_INTR_STATUS, 0x00},
+	{WSA881X_INTR_CLEAR, 0x00},
+	{WSA881X_INTR_LEVEL, 0x00},
+	{WSA881X_INTR_SET, 0x00},
+	{WSA881X_INTR_TEST, 0x00},
+	{WSA881X_PDM_TEST_MODE, 0x00},
+	{WSA881X_ATE_TEST_MODE, 0x00},
+	{WSA881X_PIN_CTL_MODE, 0x00},
+	{WSA881X_PIN_CTL_OE, 0x00},
+	{WSA881X_PIN_WDATA_IOPAD, 0x00},
+	{WSA881X_PIN_STATUS, 0x00},
+	{WSA881X_DIG_DEBUG_MODE, 0x00},
+	{WSA881X_DIG_DEBUG_SEL, 0x00},
+	{WSA881X_DIG_DEBUG_EN, 0x00},
+	{WSA881X_SWR_HM_TEST1, 0x08},
+	{WSA881X_SWR_HM_TEST2, 0x00},
+	{WSA881X_TEMP_DETECT_DBG_CTL, 0x00},
+	{WSA881X_TEMP_DEBUG_MSB, 0x00},
+	{WSA881X_TEMP_DEBUG_LSB, 0x00},
+	{WSA881X_SAMPLE_EDGE_SEL, 0x0C},
+	{WSA881X_SPARE_0, 0x00},
+	{WSA881X_SPARE_1, 0x00},
+	{WSA881X_SPARE_2, 0x00},
+	{WSA881X_OTP_REG_0, 0x01},
+	{WSA881X_OTP_REG_1, 0xFF},
+	{WSA881X_OTP_REG_2, 0xC0},
+	{WSA881X_OTP_REG_3, 0xFF},
+	{WSA881X_OTP_REG_4, 0xC0},
+	{WSA881X_OTP_REG_5, 0xFF},
+	{WSA881X_OTP_REG_6, 0xFF},
+	{WSA881X_OTP_REG_7, 0xFF},
+	{WSA881X_OTP_REG_8, 0xFF},
+	{WSA881X_OTP_REG_9, 0xFF},
+	{WSA881X_OTP_REG_10, 0xFF},
+	{WSA881X_OTP_REG_11, 0xFF},
+	{WSA881X_OTP_REG_12, 0xFF},
+	{WSA881X_OTP_REG_13, 0xFF},
+	{WSA881X_OTP_REG_14, 0xFF},
+	{WSA881X_OTP_REG_15, 0xFF},
+	{WSA881X_OTP_REG_16, 0xFF},
+	{WSA881X_OTP_REG_17, 0xFF},
+	{WSA881X_OTP_REG_18, 0xFF},
+	{WSA881X_OTP_REG_19, 0xFF},
+	{WSA881X_OTP_REG_20, 0xFF},
+	{WSA881X_OTP_REG_21, 0xFF},
+	{WSA881X_OTP_REG_22, 0xFF},
+	{WSA881X_OTP_REG_23, 0xFF},
+	{WSA881X_OTP_REG_24, 0x03},
+	{WSA881X_OTP_REG_25, 0x01},
+	{WSA881X_OTP_REG_26, 0x03},
+	{WSA881X_OTP_REG_27, 0x11},
+	{WSA881X_OTP_REG_28, 0xFF},
+	{WSA881X_OTP_REG_29, 0xFF},
+	{WSA881X_OTP_REG_30, 0xFF},
+	{WSA881X_OTP_REG_31, 0xFF},
+	{WSA881X_OTP_REG_63, 0x40},
+	/* WSA881x Analog registers */
+	{WSA881X_BIAS_REF_CTRL, 0x6C},
+	{WSA881X_BIAS_TEST, 0x16},
+	{WSA881X_BIAS_BIAS, 0xF0},
+	{WSA881X_TEMP_OP, 0x00},
+	{WSA881X_TEMP_IREF_CTRL, 0x56},
+	{WSA881X_TEMP_ISENS_CTRL, 0x47},
+	{WSA881X_TEMP_CLK_CTRL, 0x87},
+	{WSA881X_TEMP_TEST, 0x00},
+	{WSA881X_TEMP_BIAS, 0x51},
+	{WSA881X_TEMP_ADC_CTRL, 0x00},
+	{WSA881X_TEMP_DOUT_MSB, 0x00},
+	{WSA881X_TEMP_DOUT_LSB, 0x00},
+	{WSA881X_ADC_EN_MODU_V, 0x00},
+	{WSA881X_ADC_EN_MODU_I, 0x00},
+	{WSA881X_ADC_EN_DET_TEST_V, 0x00},
+	{WSA881X_ADC_EN_DET_TEST_I, 0x00},
+	{WSA881X_ADC_SEL_IBIAS, 0x25},
+	{WSA881X_ADC_EN_SEL_IBIAS, 0x10},
+	{WSA881X_SPKR_DRV_EN, 0x74},
+	{WSA881X_SPKR_DRV_GAIN, 0x01},
+	{WSA881X_SPKR_DAC_CTL, 0x40},
+	{WSA881X_SPKR_DRV_DBG, 0x15},
+	{WSA881X_SPKR_PWRSTG_DBG, 0x00},
+	{WSA881X_SPKR_OCP_CTL, 0xD4},
+	{WSA881X_SPKR_CLIP_CTL, 0x90},
+	{WSA881X_SPKR_BBM_CTL, 0x00},
+	{WSA881X_SPKR_MISC_CTL1, 0x80},
+	{WSA881X_SPKR_MISC_CTL2, 0x00},
+	{WSA881X_SPKR_BIAS_INT, 0x56},
+	{WSA881X_SPKR_PA_INT, 0x54},
+	{WSA881X_SPKR_BIAS_CAL, 0xAC},
+	{WSA881X_SPKR_BIAS_PSRR, 0x54},
+	{WSA881X_SPKR_STATUS1, 0x00},
+	{WSA881X_SPKR_STATUS2, 0x00},
+	{WSA881X_BOOST_EN_CTL, 0x18},
+	{WSA881X_BOOST_CURRENT_LIMIT, 0x7A},
+	{WSA881X_BOOST_PS_CTL, 0xC0},
+	{WSA881X_BOOST_PRESET_OUT1, 0x77},
+	{WSA881X_BOOST_PRESET_OUT2, 0x70},
+	{WSA881X_BOOST_FORCE_OUT, 0x0E},
+	{WSA881X_BOOST_LDO_PROG, 0x16},
+	{WSA881X_BOOST_SLOPE_COMP_ISENSE_FB, 0x71},
+	{WSA881X_BOOST_RON_CTL, 0x0F},
+	{WSA881X_BOOST_LOOP_STABILITY, 0xAD},
+	{WSA881X_BOOST_ZX_CTL, 0x34},
+	{WSA881X_BOOST_START_CTL, 0x23},
+	{WSA881X_BOOST_MISC1_CTL, 0x80},
+	{WSA881X_BOOST_MISC2_CTL, 0x00},
+	{WSA881X_BOOST_MISC3_CTL, 0x00},
+	{WSA881X_BOOST_ATEST_CTL, 0x00},
+	{WSA881X_SPKR_PROT_FE_GAIN, 0x46},
+	{WSA881X_SPKR_PROT_FE_CM_LDO_SET, 0x3B},
+	{WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1, 0x8D},
+	{WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2, 0x8D},
+	{WSA881X_SPKR_PROT_ATEST1, 0x01},
+	{WSA881X_SPKR_PROT_ATEST2, 0x00},
+	{WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x8D},
+	{WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1, 0x4D},
+	{WSA881X_BONGO_RESRV_REG1, 0x00},
+	{WSA881X_BONGO_RESRV_REG2, 0x00},
+	{WSA881X_SPKR_PROT_SAR, 0x00},
+	{WSA881X_SPKR_STATUS3, 0x00},
+};
+
+struct reg_default wsa881x_ana_reg_defaults_0[] = {
+	{WSA881X_CHIP_ID0, 0x00},
+	{WSA881X_CHIP_ID1, 0x00},
+	{WSA881X_CHIP_ID2, 0x00},
+	{WSA881X_CHIP_ID3, 0x02},
+	{WSA881X_BUS_ID, 0x00},
+	{WSA881X_CDC_RST_CTL, 0x00},
+	{WSA881X_CDC_TOP_CLK_CTL, 0x03},
+	{WSA881X_CDC_ANA_CLK_CTL, 0x00},
+	{WSA881X_CDC_DIG_CLK_CTL, 0x00},
+	{WSA881X_CLOCK_CONFIG, 0x00},
+	{WSA881X_ANA_CTL, 0x08},
+	{WSA881X_SWR_RESET_EN, 0x00},
+	{WSA881X_TEMP_DETECT_CTL, 0x01},
+	{WSA881X_TEMP_MSB, 0x00},
+	{WSA881X_TEMP_LSB, 0x00},
+	{WSA881X_TEMP_CONFIG0, 0x00},
+	{WSA881X_TEMP_CONFIG1, 0x00},
+	{WSA881X_CDC_CLIP_CTL, 0x03},
+	{WSA881X_SDM_PDM9_LSB, 0x00},
+	{WSA881X_SDM_PDM9_MSB, 0x00},
+	{WSA881X_CDC_RX_CTL, 0x7E},
+	{WSA881X_DEM_BYPASS_DATA0, 0x00},
+	{WSA881X_DEM_BYPASS_DATA1, 0x00},
+	{WSA881X_DEM_BYPASS_DATA2, 0x00},
+	{WSA881X_DEM_BYPASS_DATA3, 0x00},
+	{WSA881X_OTP_CTRL0, 0x00},
+	{WSA881X_OTP_CTRL1, 0x00},
+	{WSA881X_HDRIVE_CTL_GROUP1, 0x00},
+	{WSA881X_INTR_MODE, 0x00},
+	{WSA881X_INTR_MASK, 0x1F},
+	{WSA881X_INTR_STATUS, 0x00},
+	{WSA881X_INTR_CLEAR, 0x00},
+	{WSA881X_INTR_LEVEL, 0x00},
+	{WSA881X_INTR_SET, 0x00},
+	{WSA881X_INTR_TEST, 0x00},
+	{WSA881X_PDM_TEST_MODE, 0x00},
+	{WSA881X_ATE_TEST_MODE, 0x00},
+	{WSA881X_PIN_CTL_MODE, 0x00},
+	{WSA881X_PIN_CTL_OE, 0x00},
+	{WSA881X_PIN_WDATA_IOPAD, 0x00},
+	{WSA881X_PIN_STATUS, 0x00},
+	{WSA881X_DIG_DEBUG_MODE, 0x00},
+	{WSA881X_DIG_DEBUG_SEL, 0x00},
+	{WSA881X_DIG_DEBUG_EN, 0x00},
+	{WSA881X_SWR_HM_TEST1, 0x08},
+	{WSA881X_SWR_HM_TEST2, 0x00},
+	{WSA881X_TEMP_DETECT_DBG_CTL, 0x00},
+	{WSA881X_TEMP_DEBUG_MSB, 0x00},
+	{WSA881X_TEMP_DEBUG_LSB, 0x00},
+	{WSA881X_SAMPLE_EDGE_SEL, 0x0C},
+	{WSA881X_SPARE_0, 0x00},
+	{WSA881X_SPARE_1, 0x00},
+	{WSA881X_SPARE_2, 0x00},
+	{WSA881X_OTP_REG_0, 0x01},
+	{WSA881X_OTP_REG_1, 0xFF},
+	{WSA881X_OTP_REG_2, 0xC0},
+	{WSA881X_OTP_REG_3, 0xFF},
+	{WSA881X_OTP_REG_4, 0xC0},
+	{WSA881X_OTP_REG_5, 0xFF},
+	{WSA881X_OTP_REG_6, 0xFF},
+	{WSA881X_OTP_REG_7, 0xFF},
+	{WSA881X_OTP_REG_8, 0xFF},
+	{WSA881X_OTP_REG_9, 0xFF},
+	{WSA881X_OTP_REG_10, 0xFF},
+	{WSA881X_OTP_REG_11, 0xFF},
+	{WSA881X_OTP_REG_12, 0xFF},
+	{WSA881X_OTP_REG_13, 0xFF},
+	{WSA881X_OTP_REG_14, 0xFF},
+	{WSA881X_OTP_REG_15, 0xFF},
+	{WSA881X_OTP_REG_16, 0xFF},
+	{WSA881X_OTP_REG_17, 0xFF},
+	{WSA881X_OTP_REG_18, 0xFF},
+	{WSA881X_OTP_REG_19, 0xFF},
+	{WSA881X_OTP_REG_20, 0xFF},
+	{WSA881X_OTP_REG_21, 0xFF},
+	{WSA881X_OTP_REG_22, 0xFF},
+	{WSA881X_OTP_REG_23, 0xFF},
+	{WSA881X_OTP_REG_24, 0x03},
+	{WSA881X_OTP_REG_25, 0x01},
+	{WSA881X_OTP_REG_26, 0x03},
+	{WSA881X_OTP_REG_27, 0x11},
+	{WSA881X_OTP_REG_28, 0xFF},
+	{WSA881X_OTP_REG_29, 0xFF},
+	{WSA881X_OTP_REG_30, 0xFF},
+	{WSA881X_OTP_REG_31, 0xFF},
+	{WSA881X_OTP_REG_63, 0x40},
+};
+
+struct reg_default wsa881x_ana_reg_defaults_1[] = {
+	{WSA881X_BIAS_REF_CTRL - WSA881X_ANALOG_BASE, 0x6C},
+	{WSA881X_BIAS_TEST - WSA881X_ANALOG_BASE, 0x16},
+	{WSA881X_BIAS_BIAS - WSA881X_ANALOG_BASE, 0xF0},
+	{WSA881X_TEMP_OP - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_TEMP_IREF_CTRL - WSA881X_ANALOG_BASE, 0x56},
+	{WSA881X_TEMP_ISENS_CTRL - WSA881X_ANALOG_BASE, 0x47},
+	{WSA881X_TEMP_CLK_CTRL - WSA881X_ANALOG_BASE, 0x87},
+	{WSA881X_TEMP_TEST - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_TEMP_BIAS - WSA881X_ANALOG_BASE, 0x51},
+	{WSA881X_TEMP_ADC_CTRL - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_TEMP_DOUT_MSB - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_TEMP_DOUT_LSB - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_ADC_EN_MODU_V - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_ADC_EN_MODU_I - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_ADC_EN_DET_TEST_V - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_ADC_EN_DET_TEST_I - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_ADC_SEL_IBIAS - WSA881X_ANALOG_BASE, 0x25},
+	{WSA881X_ADC_EN_SEL_IBIAS - WSA881X_ANALOG_BASE, 0x10},
+	{WSA881X_SPKR_DRV_EN - WSA881X_ANALOG_BASE, 0x74},
+	{WSA881X_SPKR_DRV_GAIN - WSA881X_ANALOG_BASE, 0x01},
+	{WSA881X_SPKR_DAC_CTL - WSA881X_ANALOG_BASE, 0x40},
+	{WSA881X_SPKR_DRV_DBG - WSA881X_ANALOG_BASE, 0x15},
+	{WSA881X_SPKR_PWRSTG_DBG - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_OCP_CTL - WSA881X_ANALOG_BASE, 0xD4},
+	{WSA881X_SPKR_CLIP_CTL - WSA881X_ANALOG_BASE, 0x90},
+	{WSA881X_SPKR_BBM_CTL - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_MISC_CTL1 - WSA881X_ANALOG_BASE, 0x80},
+	{WSA881X_SPKR_MISC_CTL2 - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_BIAS_INT - WSA881X_ANALOG_BASE, 0x56},
+	{WSA881X_SPKR_PA_INT - WSA881X_ANALOG_BASE, 0x54},
+	{WSA881X_SPKR_BIAS_CAL - WSA881X_ANALOG_BASE, 0xAC},
+	{WSA881X_SPKR_BIAS_PSRR - WSA881X_ANALOG_BASE, 0x54},
+	{WSA881X_SPKR_STATUS1 - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_STATUS2 - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_BOOST_EN_CTL - WSA881X_ANALOG_BASE, 0x18},
+	{WSA881X_BOOST_CURRENT_LIMIT - WSA881X_ANALOG_BASE, 0x7A},
+	{WSA881X_BOOST_PS_CTL - WSA881X_ANALOG_BASE, 0xC0},
+	{WSA881X_BOOST_PRESET_OUT1 - WSA881X_ANALOG_BASE, 0x77},
+	{WSA881X_BOOST_PRESET_OUT2 - WSA881X_ANALOG_BASE, 0x70},
+	{WSA881X_BOOST_FORCE_OUT - WSA881X_ANALOG_BASE, 0x0E},
+	{WSA881X_BOOST_LDO_PROG - WSA881X_ANALOG_BASE, 0x16},
+	{WSA881X_BOOST_SLOPE_COMP_ISENSE_FB - WSA881X_ANALOG_BASE, 0x71},
+	{WSA881X_BOOST_RON_CTL - WSA881X_ANALOG_BASE, 0x0F},
+	{WSA881X_BOOST_LOOP_STABILITY - WSA881X_ANALOG_BASE, 0xAD},
+	{WSA881X_BOOST_ZX_CTL - WSA881X_ANALOG_BASE, 0x34},
+	{WSA881X_BOOST_START_CTL - WSA881X_ANALOG_BASE, 0x23},
+	{WSA881X_BOOST_MISC1_CTL - WSA881X_ANALOG_BASE, 0x80},
+	{WSA881X_BOOST_MISC2_CTL - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_BOOST_MISC3_CTL - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_BOOST_ATEST_CTL - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_PROT_FE_GAIN - WSA881X_ANALOG_BASE, 0x46},
+	{WSA881X_SPKR_PROT_FE_CM_LDO_SET - WSA881X_ANALOG_BASE, 0x3B},
+	{WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1 - WSA881X_ANALOG_BASE, 0x8D},
+	{WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2 - WSA881X_ANALOG_BASE, 0x8D},
+	{WSA881X_SPKR_PROT_ATEST1 - WSA881X_ANALOG_BASE, 0x01},
+	{WSA881X_SPKR_PROT_ATEST2 - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_PROT_FE_VSENSE_VCM - WSA881X_ANALOG_BASE, 0x8D},
+	{WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1 - WSA881X_ANALOG_BASE, 0x4D},
+	{WSA881X_BONGO_RESRV_REG1 - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_BONGO_RESRV_REG2 - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_PROT_SAR - WSA881X_ANALOG_BASE, 0x00},
+	{WSA881X_SPKR_STATUS3 - WSA881X_ANALOG_BASE, 0x00},
+};
+
+static const struct reg_sequence wsa881x_rev_2_0_dig[] = {
+	{WSA881X_RESET_CTL, 0x00},
+	{WSA881X_TADC_VALUE_CTL, 0x01},
+	{WSA881X_INTR_MASK, 0x1B},
+	{WSA881X_IOPAD_CTL, 0x00},
+	{WSA881X_OTP_REG_28, 0x3F},
+	{WSA881X_OTP_REG_29, 0x3F},
+	{WSA881X_OTP_REG_30, 0x01},
+	{WSA881X_OTP_REG_31, 0x01},
+};
+
+static const struct reg_sequence wsa881x_rev_2_0_ana[] = {
+	{WSA881X_TEMP_ADC_CTRL, 0x03},
+	{WSA881X_ADC_SEL_IBIAS, 0x45},
+	{WSA881X_SPKR_DRV_GAIN, 0xC1},
+	{WSA881X_SPKR_DAC_CTL, 0x42},
+	{WSA881X_SPKR_BBM_CTL, 0x02},
+	{WSA881X_SPKR_MISC_CTL1, 0x40},
+	{WSA881X_SPKR_MISC_CTL2, 0x07},
+	{WSA881X_SPKR_BIAS_INT, 0x5F},
+	{WSA881X_SPKR_BIAS_PSRR, 0x44},
+	{WSA881X_BOOST_PS_CTL, 0xA0},
+	{WSA881X_BOOST_PRESET_OUT1, 0xB7},
+	{WSA881X_BOOST_LOOP_STABILITY, 0x8D},
+	{WSA881X_SPKR_PROT_ATEST2, 0x02},
+	{WSA881X_BONGO_RESRV_REG1, 0x5E},
+	{WSA881X_BONGO_RESRV_REG2, 0x07},
+};
+
+struct reg_default wsa881x_rev_2_0_regmap_ana[] = {
+	{WSA881X_TEMP_ADC_CTRL - WSA881X_ANALOG_BASE, 0x03},
+	{WSA881X_ADC_SEL_IBIAS - WSA881X_ANALOG_BASE, 0x45},
+	{WSA881X_SPKR_DRV_GAIN - WSA881X_ANALOG_BASE, 0xC1},
+	{WSA881X_SPKR_DAC_CTL - WSA881X_ANALOG_BASE, 0x42},
+	{WSA881X_SPKR_BBM_CTL - WSA881X_ANALOG_BASE, 0x02},
+	{WSA881X_SPKR_MISC_CTL1 - WSA881X_ANALOG_BASE, 0x40},
+	{WSA881X_SPKR_MISC_CTL2 - WSA881X_ANALOG_BASE, 0x07},
+	{WSA881X_SPKR_BIAS_INT - WSA881X_ANALOG_BASE, 0x5F},
+	{WSA881X_SPKR_BIAS_PSRR - WSA881X_ANALOG_BASE, 0x44},
+	{WSA881X_BOOST_PS_CTL - WSA881X_ANALOG_BASE, 0xA0},
+	{WSA881X_BOOST_PRESET_OUT1 - WSA881X_ANALOG_BASE, 0xB7},
+	{WSA881X_BOOST_LOOP_STABILITY - WSA881X_ANALOG_BASE, 0x8D},
+	{WSA881X_SPKR_PROT_ATEST2 - WSA881X_ANALOG_BASE, 0x02},
+	{WSA881X_BONGO_RESRV_REG1 - WSA881X_ANALOG_BASE, 0x5E},
+	{WSA881X_BONGO_RESRV_REG2 - WSA881X_ANALOG_BASE, 0x07},
+};
+
+/**
+ * wsa881x_update_reg_defaults_2_0 - update default values of regs for v2.0
+ *
+ * wsa881x v2.0 has different default values for certain analog and digital
+ * registers compared to v1.x. Therefore, update the values of these registers
+ * with the values from tables defined above for v2.0.
+ */
+void wsa881x_update_reg_defaults_2_0(void)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(wsa881x_rev_2_0_dig); i++) {
+		for (j = 0; j < ARRAY_SIZE(wsa881x_ana_reg_defaults); j++)
+			if (wsa881x_ana_reg_defaults[j].reg ==
+						wsa881x_rev_2_0_dig[i].reg)
+				wsa881x_ana_reg_defaults[j].def =
+						wsa881x_rev_2_0_dig[i].def;
+	}
+	for (i = 0; i < ARRAY_SIZE(wsa881x_rev_2_0_ana); i++) {
+		for (j = 0; j < ARRAY_SIZE(wsa881x_ana_reg_defaults); j++)
+			if (wsa881x_ana_reg_defaults[j].reg ==
+						wsa881x_rev_2_0_ana[i].reg)
+				wsa881x_ana_reg_defaults[j].def =
+						wsa881x_rev_2_0_ana[i].def;
+	}
+}
+EXPORT_SYMBOL(wsa881x_update_reg_defaults_2_0);
+
+/**
+ * wsa881x_update_regmap_2_0 - update regmap framework with new tables
+ * @regmap: pointer to wsa881x regmap structure
+ * @flag: indicates digital or analog wsa881x slave
+ *
+ * wsa881x v2.0 has some new registers for both analog and digital slaves.
+ * Update the regmap framework with all the new registers.
+ */
+void wsa881x_update_regmap_2_0(struct regmap *regmap, int flag)
+{
+	u16 ret = 0;
+
+	switch (flag) {
+	case WSA881X_DIGITAL_SLAVE:
+		ret = regmap_register_patch(regmap, wsa881x_rev_2_0_dig,
+					ARRAY_SIZE(wsa881x_rev_2_0_dig));
+		break;
+	case WSA881X_ANALOG_SLAVE:
+		ret = regmap_register_patch(regmap, wsa881x_rev_2_0_ana,
+					ARRAY_SIZE(wsa881x_rev_2_0_ana));
+		break;
+	default:
+		pr_debug("%s: unknown version", __func__);
+		ret = -EINVAL;
+		break;
+	}
+	if (ret)
+		pr_err("%s: Failed to update regmap defaults ret= %d\n",
+			__func__, ret);
+}
+EXPORT_SYMBOL(wsa881x_update_regmap_2_0);
+
+static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
+{
+	return wsa881x_ana_reg_readable[reg];
+}
+
+static bool wsa881x_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WSA881X_CHIP_ID0:
+	case WSA881X_CHIP_ID1:
+	case WSA881X_CHIP_ID2:
+	case WSA881X_CHIP_ID3:
+	case WSA881X_BUS_ID:
+	case WSA881X_TEMP_MSB:
+	case WSA881X_TEMP_LSB:
+	case WSA881X_SDM_PDM9_LSB:
+	case WSA881X_SDM_PDM9_MSB:
+	case WSA881X_OTP_REG_0:
+	case WSA881X_OTP_REG_1:
+	case WSA881X_OTP_REG_2:
+	case WSA881X_OTP_REG_3:
+	case WSA881X_OTP_REG_4:
+	case WSA881X_OTP_REG_5:
+	case WSA881X_OTP_REG_31:
+	case WSA881X_TEMP_DOUT_MSB:
+	case WSA881X_TEMP_DOUT_LSB:
+	case WSA881X_TEMP_OP:
+	case WSA881X_OTP_CTRL1:
+	case WSA881X_INTR_STATUS:
+	case WSA881X_ATE_TEST_MODE:
+	case WSA881X_PIN_STATUS:
+	case WSA881X_SWR_HM_TEST2:
+	case WSA881X_SPKR_STATUS1:
+	case WSA881X_SPKR_STATUS2:
+	case WSA881X_SPKR_STATUS3:
+	case WSA881X_SPKR_PROT_SAR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+struct regmap_config wsa881x_ana_regmap_config[] = {
+{
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_NONE,
+	.reg_defaults = wsa881x_ana_reg_defaults_0,
+	.num_reg_defaults = ARRAY_SIZE(wsa881x_ana_reg_defaults_0),
+	.max_register = WSA881X_MAX_REGISTER,
+	.volatile_reg = wsa881x_volatile_register,
+	.readable_reg = wsa881x_readable_register,
+	.reg_format_endian = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian = REGMAP_ENDIAN_NATIVE,
+},
+{
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_NONE,
+	.reg_defaults = wsa881x_ana_reg_defaults_1,
+	.num_reg_defaults = ARRAY_SIZE(wsa881x_ana_reg_defaults_1),
+	.max_register = WSA881X_MAX_REGISTER,
+	.volatile_reg = wsa881x_volatile_register,
+	.readable_reg = wsa881x_readable_register,
+	.reg_format_endian = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian = REGMAP_ENDIAN_NATIVE,
+}
+};
diff --git a/asoc/codecs/wsa881x-tables-analog.c b/asoc/codecs/wsa881x-tables-analog.c
new file mode 100644
index 0000000..bbc6b90
--- /dev/null
+++ b/asoc/codecs/wsa881x-tables-analog.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015, 2018-2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "wsa881x-registers-analog.h"
+
+const u8 wsa881x_ana_reg_readable[WSA881X_CACHE_SIZE] = {
+	[WSA881X_CHIP_ID0] = 1,
+	[WSA881X_CHIP_ID1] = 1,
+	[WSA881X_CHIP_ID2] = 1,
+	[WSA881X_CHIP_ID3] = 1,
+	[WSA881X_BUS_ID] = 1,
+	[WSA881X_CDC_RST_CTL] = 1,
+	[WSA881X_CDC_TOP_CLK_CTL] = 1,
+	[WSA881X_CDC_ANA_CLK_CTL] = 1,
+	[WSA881X_CDC_DIG_CLK_CTL] = 1,
+	[WSA881X_CLOCK_CONFIG] = 1,
+	[WSA881X_ANA_CTL] = 1,
+	[WSA881X_SWR_RESET_EN] = 1,
+	[WSA881X_RESET_CTL] = 1,
+	[WSA881X_TADC_VALUE_CTL] = 1,
+	[WSA881X_TEMP_DETECT_CTL] = 1,
+	[WSA881X_TEMP_MSB] = 1,
+	[WSA881X_TEMP_LSB] = 1,
+	[WSA881X_TEMP_CONFIG0] = 1,
+	[WSA881X_TEMP_CONFIG1] = 1,
+	[WSA881X_CDC_CLIP_CTL] = 1,
+	[WSA881X_SDM_PDM9_LSB] = 1,
+	[WSA881X_SDM_PDM9_MSB] = 1,
+	[WSA881X_CDC_RX_CTL] = 1,
+	[WSA881X_DEM_BYPASS_DATA0] = 1,
+	[WSA881X_DEM_BYPASS_DATA1] = 1,
+	[WSA881X_DEM_BYPASS_DATA2] = 1,
+	[WSA881X_DEM_BYPASS_DATA3] = 1,
+	[WSA881X_OTP_CTRL0] = 1,
+	[WSA881X_OTP_CTRL1] = 1,
+	[WSA881X_HDRIVE_CTL_GROUP1] = 1,
+	[WSA881X_INTR_MODE] = 1,
+	[WSA881X_INTR_MASK] = 1,
+	[WSA881X_INTR_STATUS] = 1,
+	[WSA881X_INTR_CLEAR] = 1,
+	[WSA881X_INTR_LEVEL] = 1,
+	[WSA881X_INTR_SET] = 1,
+	[WSA881X_INTR_TEST] = 1,
+	[WSA881X_PDM_TEST_MODE] = 1,
+	[WSA881X_ATE_TEST_MODE] = 1,
+	[WSA881X_PIN_CTL_MODE] = 1,
+	[WSA881X_PIN_CTL_OE] = 1,
+	[WSA881X_PIN_WDATA_IOPAD] = 1,
+	[WSA881X_PIN_STATUS] = 1,
+	[WSA881X_DIG_DEBUG_MODE] = 1,
+	[WSA881X_DIG_DEBUG_SEL] = 1,
+	[WSA881X_DIG_DEBUG_EN] = 1,
+	[WSA881X_SWR_HM_TEST1] = 1,
+	[WSA881X_SWR_HM_TEST2] = 1,
+	[WSA881X_TEMP_DETECT_DBG_CTL] = 1,
+	[WSA881X_TEMP_DEBUG_MSB] = 1,
+	[WSA881X_TEMP_DEBUG_LSB] = 1,
+	[WSA881X_SAMPLE_EDGE_SEL] = 1,
+	[WSA881X_IOPAD_CTL] = 1,
+	[WSA881X_SPARE_0] = 1,
+	[WSA881X_SPARE_1] = 1,
+	[WSA881X_SPARE_2] = 1,
+	[WSA881X_OTP_REG_0] = 1,
+	[WSA881X_OTP_REG_1] = 1,
+	[WSA881X_OTP_REG_2] = 1,
+	[WSA881X_OTP_REG_3] = 1,
+	[WSA881X_OTP_REG_4] = 1,
+	[WSA881X_OTP_REG_5] = 1,
+	[WSA881X_OTP_REG_6] = 1,
+	[WSA881X_OTP_REG_7] = 1,
+	[WSA881X_OTP_REG_8] = 1,
+	[WSA881X_OTP_REG_9] = 1,
+	[WSA881X_OTP_REG_10] = 1,
+	[WSA881X_OTP_REG_11] = 1,
+	[WSA881X_OTP_REG_12] = 1,
+	[WSA881X_OTP_REG_13] = 1,
+	[WSA881X_OTP_REG_14] = 1,
+	[WSA881X_OTP_REG_15] = 1,
+	[WSA881X_OTP_REG_16] = 1,
+	[WSA881X_OTP_REG_17] = 1,
+	[WSA881X_OTP_REG_18] = 1,
+	[WSA881X_OTP_REG_19] = 1,
+	[WSA881X_OTP_REG_20] = 1,
+	[WSA881X_OTP_REG_21] = 1,
+	[WSA881X_OTP_REG_22] = 1,
+	[WSA881X_OTP_REG_23] = 1,
+	[WSA881X_OTP_REG_24] = 1,
+	[WSA881X_OTP_REG_25] = 1,
+	[WSA881X_OTP_REG_26] = 1,
+	[WSA881X_OTP_REG_27] = 1,
+	[WSA881X_OTP_REG_28] = 1,
+	[WSA881X_OTP_REG_29] = 1,
+	[WSA881X_OTP_REG_30] = 1,
+	[WSA881X_OTP_REG_31] = 1,
+	[WSA881X_OTP_REG_63] = 1,
+	/* Analog Registers */
+	[WSA881X_BIAS_REF_CTRL] = 1,
+	[WSA881X_BIAS_TEST] = 1,
+	[WSA881X_BIAS_BIAS] = 1,
+	[WSA881X_TEMP_OP] = 1,
+	[WSA881X_TEMP_IREF_CTRL] = 1,
+	[WSA881X_TEMP_ISENS_CTRL] = 1,
+	[WSA881X_TEMP_CLK_CTRL] = 1,
+	[WSA881X_TEMP_TEST] = 1,
+	[WSA881X_TEMP_BIAS] = 1,
+	[WSA881X_TEMP_ADC_CTRL] = 1,
+	[WSA881X_TEMP_DOUT_MSB] = 1,
+	[WSA881X_TEMP_DOUT_LSB] = 1,
+	[WSA881X_ADC_EN_MODU_V] = 1,
+	[WSA881X_ADC_EN_MODU_I] = 1,
+	[WSA881X_ADC_EN_DET_TEST_V] = 1,
+	[WSA881X_ADC_EN_DET_TEST_I] = 1,
+	[WSA881X_ADC_SEL_IBIAS] = 1,
+	[WSA881X_ADC_EN_SEL_IBIAS] = 1,
+	[WSA881X_SPKR_DRV_EN] = 1,
+	[WSA881X_SPKR_DRV_GAIN] = 1,
+	[WSA881X_SPKR_DAC_CTL] = 1,
+	[WSA881X_SPKR_DRV_DBG] = 1,
+	[WSA881X_SPKR_PWRSTG_DBG] = 1,
+	[WSA881X_SPKR_OCP_CTL] = 1,
+	[WSA881X_SPKR_CLIP_CTL] = 1,
+	[WSA881X_SPKR_BBM_CTL] = 1,
+	[WSA881X_SPKR_MISC_CTL1] = 1,
+	[WSA881X_SPKR_MISC_CTL2] = 1,
+	[WSA881X_SPKR_BIAS_INT] = 1,
+	[WSA881X_SPKR_PA_INT] = 1,
+	[WSA881X_SPKR_BIAS_CAL] = 1,
+	[WSA881X_SPKR_BIAS_PSRR] = 1,
+	[WSA881X_SPKR_STATUS1] = 1,
+	[WSA881X_SPKR_STATUS2] = 1,
+	[WSA881X_BOOST_EN_CTL] = 1,
+	[WSA881X_BOOST_CURRENT_LIMIT] = 1,
+	[WSA881X_BOOST_PS_CTL] = 1,
+	[WSA881X_BOOST_PRESET_OUT1] = 1,
+	[WSA881X_BOOST_PRESET_OUT2] = 1,
+	[WSA881X_BOOST_FORCE_OUT] = 1,
+	[WSA881X_BOOST_LDO_PROG] = 1,
+	[WSA881X_BOOST_SLOPE_COMP_ISENSE_FB] = 1,
+	[WSA881X_BOOST_RON_CTL] = 1,
+	[WSA881X_BOOST_LOOP_STABILITY] = 1,
+	[WSA881X_BOOST_ZX_CTL] = 1,
+	[WSA881X_BOOST_START_CTL] = 1,
+	[WSA881X_BOOST_MISC1_CTL] = 1,
+	[WSA881X_BOOST_MISC2_CTL] = 1,
+	[WSA881X_BOOST_MISC3_CTL] = 1,
+	[WSA881X_BOOST_ATEST_CTL] = 1,
+	[WSA881X_SPKR_PROT_FE_GAIN] = 1,
+	[WSA881X_SPKR_PROT_FE_CM_LDO_SET] = 1,
+	[WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1] = 1,
+	[WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2] = 1,
+	[WSA881X_SPKR_PROT_ATEST1] = 1,
+	[WSA881X_SPKR_PROT_ATEST2] = 1,
+	[WSA881X_SPKR_PROT_FE_VSENSE_VCM] = 1,
+	[WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1] = 1,
+	[WSA881X_BONGO_RESRV_REG1] = 1,
+	[WSA881X_BONGO_RESRV_REG2] = 1,
+	[WSA881X_SPKR_PROT_SAR] = 1,
+	[WSA881X_SPKR_STATUS3] = 1,
+};
diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c
index 966fa8a..fc4f123 100644
--- a/asoc/codecs/wsa881x.c
+++ b/asoc/codecs/wsa881x.c
@@ -1395,6 +1395,7 @@
 			snd_soc_component_update_bits(wsa881x->component,
 					      WSA881X_SPKR_DRV_EN,
 					      0x80, 0x80);
+		break;
 	default:
 		break;
 	}
diff --git a/asoc/codecs/wsa883x/Android.mk b/asoc/codecs/wsa883x/Android.mk
new file mode 100644
index 0000000..66056e8
--- /dev/null
+++ b/asoc/codecs/wsa883x/Android.mk
@@ -0,0 +1,49 @@
+# Android makefile for audio kernel modules
+
+# Assume no targets will be supported
+
+# Check if this driver needs be built for current target
+ifeq ($(call is-board-platform,lahaina),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_LAHAINA=m
+endif
+
+AUDIO_CHIPSET := audio
+# Build/Package only in case of supported target
+ifeq ($(call is-board-platform-in-list,lahaina),true)
+
+LOCAL_PATH := $(call my-dir)
+
+# This makefile is only for DLKM
+ifneq ($(findstring vendor,$(LOCAL_PATH)),)
+
+ifneq ($(findstring opensource,$(LOCAL_PATH)),)
+	AUDIO_BLD_DIR := $(shell pwd)/vendor/qcom/opensource/audio-kernel
+endif # opensource
+
+DLKM_DIR := $(TOP)/device/qcom/common/dlkm
+
+# Build audio.ko as $(AUDIO_CHIPSET)_audio.ko
+###########################################################
+# This is set once per LOCAL_PATH, not per (kernel) module
+KBUILD_OPTIONS := AUDIO_ROOT=$(AUDIO_BLD_DIR)
+
+# We are actually building audio.ko here, as per the
+# requirement we are specifying <chipset>_audio.ko as LOCAL_MODULE.
+# This means we need to rename the module to <chipset>_audio.ko
+# after audio.ko is built.
+KBUILD_OPTIONS += MODNAME=wsa883x_dlkm
+KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
+KBUILD_OPTIONS += $(AUDIO_SELECT)
+
+###########################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE              := $(AUDIO_CHIPSET)_wsa883x.ko
+LOCAL_MODULE_KBUILD_NAME  := wsa883x_dlkm.ko
+LOCAL_MODULE_TAGS         := optional
+LOCAL_MODULE_DEBUG_ENABLE := true
+LOCAL_MODULE_PATH         := $(KERNEL_MODULES_OUT)
+include $(DLKM_DIR)/AndroidKernelModule.mk
+###########################################################
+
+endif # DLKM check
+endif # supported target check
diff --git a/asoc/codecs/wsa883x/Kbuild b/asoc/codecs/wsa883x/Kbuild
new file mode 100644
index 0000000..4eb844a
--- /dev/null
+++ b/asoc/codecs/wsa883x/Kbuild
@@ -0,0 +1,103 @@
+# We can build either as part of a standalone Kernel build or as
+# an external module.  Determine which mechanism is being used
+ifeq ($(MODNAME),)
+	KERNEL_BUILD := 1
+else
+	KERNEL_BUILD := 0
+endif
+
+ifeq ($(KERNEL_BUILD), 1)
+	# These are configurable via Kconfig for kernel-based builds
+	# Need to explicitly configure for Android-based builds
+	AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-4.19
+	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+	ifeq ($(CONFIG_ARCH_LAHAINA), y)
+		include $(AUDIO_ROOT)/config/lahainaauto.conf
+		INCS    +=  -include $(AUDIO_ROOT)/config/lahainaautoconf.h
+	endif
+endif
+
+# As per target team, build is done as follows:
+# Defconfig : build with default flags
+# Slub      : defconfig  + CONFIG_SLUB_DEBUG := y +
+#	      CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y
+# Perf      : Using appropriate msmXXXX-perf_defconfig
+#
+# Shipment builds (user variants) should not have any debug feature
+# enabled. This is identified using 'TARGET_BUILD_VARIANT'. Slub builds
+# are identified using the CONFIG_SLUB_DEBUG_ON configuration. Since
+# there is no other way to identify defconfig builds, QTI internal
+# representation of perf builds (identified using the string 'perf'),
+# is used to identify if the build is a slub or defconfig one. This
+# way no critical debug feature will be enabled for perf and shipment
+# builds. Other OEMs are also protected using the TARGET_BUILD_VARIANT
+# config.
+
+############ UAPI ############
+UAPI_DIR :=	uapi
+UAPI_INC :=	-I$(AUDIO_ROOT)/include/$(UAPI_DIR)
+
+############ COMMON ############
+COMMON_DIR :=	include
+COMMON_INC :=	-I$(AUDIO_ROOT)/$(COMMON_DIR)
+
+############ WSA883X ############
+
+# for WSA883X Codec
+ifdef CONFIG_SND_SOC_WSA883X
+	WSA883X_OBJS += wsa883x.o
+	WSA883X_OBJS += wsa883x-regmap.o
+	WSA883X_OBJS += wsa883x-tables.o
+	WSA883X_OBJS += wsa883x-temp-sensor.o
+endif
+
+LINUX_INC +=	-Iinclude/linux
+
+INCS +=		$(COMMON_INC) \
+		$(UAPI_INC)
+
+EXTRA_CFLAGS += $(INCS)
+
+
+CDEFINES +=	-DANI_LITTLE_BYTE_ENDIAN \
+		-DANI_LITTLE_BIT_ENDIAN \
+		-DDOT11F_LITTLE_ENDIAN_HOST \
+		-DANI_COMPILER_TYPE_GCC \
+		-DANI_OS_TYPE_ANDROID=6 \
+		-DPTT_SOCK_SVC_ENABLE \
+		-Wall\
+		-Werror\
+		-D__linux__
+
+KBUILD_CPPFLAGS += $(CDEFINES)
+
+# Currently, for versions of gcc which support it, the kernel Makefile
+# is disabling the maybe-uninitialized warning.  Re-enable it for the
+# AUDIO driver.  Note that we must use EXTRA_CFLAGS here so that it
+# will override the kernel settings.
+ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
+EXTRA_CFLAGS += -Wmaybe-uninitialized
+endif
+#EXTRA_CFLAGS += -Wmissing-prototypes
+
+ifeq ($(call cc-option-yn, -Wheader-guard),y)
+EXTRA_CFLAGS += -Wheader-guard
+endif
+
+ifeq ($(KERNEL_BUILD), 0)
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/ipc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/dsp/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/asoc/codecs/Module.symvers
+KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/audio-kernel/soc/Module.symvers
+endif
+
+# Module information used by KBuild framework
+obj-$(CONFIG_SND_SOC_WSA883X) += wsa883x_dlkm.o
+wsa883x_dlkm-y := $(WSA883X_OBJS)
+
+# inject some build related information
+DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"
diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h
new file mode 100644
index 0000000..509fc83
--- /dev/null
+++ b/asoc/codecs/wsa883x/internal.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef WSA883X_INTERNAL_H
+#define WSA883X_INTERNAL_H
+
+#include "wsa883x.h"
+#include "wsa883x-registers.h"
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#define SWR_SLV_MAX_REG_ADDR	0x2009
+#define SWR_SLV_START_REG_ADDR	0x40
+#define SWR_SLV_MAX_BUF_LEN	20
+#define BYTES_PER_LINE		12
+#define SWR_SLV_RD_BUF_LEN	8
+#define SWR_SLV_WR_BUF_LEN	32
+#define SWR_SLV_MAX_DEVICES	2
+#endif /* CONFIG_DEBUG_FS */
+
+#define WSA883X_DRV_NAME "wsa883x-codec"
+#define WSA883X_NUM_RETRY	5
+
+#define WSA883X_VERSION_ENTRY_SIZE 27
+
+enum {
+	G_18DB = 0,
+	G_16P5DB,
+	G_15DB,
+	G_13P5DB,
+	G_12DB,
+	G_10P5DB,
+	G_9DB,
+	G_7P5DB,
+	G_6DB,
+	G_4P5DB,
+	G_3DB,
+	G_1P5DB,
+	G_0DB,
+};
+
+enum {
+	DISABLE = 0,
+	ENABLE,
+};
+
+enum {
+	SWR_DAC_PORT,
+	SWR_COMP_PORT,
+	SWR_BOOST_PORT,
+	SWR_VISENSE_PORT,
+};
+
+struct swr_port {
+	u8 port_id;
+	u8 ch_mask;
+	u32 ch_rate;
+	u8 num_ch;
+	u8 port_type;
+};
+
+extern struct regmap_config wsa883x_regmap_config;
+
+/*
+ * Private data Structure for wsa883x. All parameters related to
+ * WSA883X codec needs to be defined here.
+ */
+struct wsa883x_priv {
+	struct regmap *regmap;
+	struct device *dev;
+	struct swr_device *swr_slave;
+	struct snd_soc_component *component;
+	bool comp_enable;
+	bool visense_enable;
+	bool ext_vdd_spk;
+	struct swr_port port[WSA883X_MAX_SWR_PORTS];
+	int global_pa_cnt;
+	int dev_mode;
+	struct mutex res_lock;
+	struct snd_info_entry *entry;
+	struct snd_info_entry *version_entry;
+	struct device_node *wsa_rst_np;
+	int pa_mute;
+	int curr_temp;
+	int variant;
+	struct irq_domain *virq;
+	struct wcd_irq_info irq_info;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_dent;
+	struct dentry *debugfs_peek;
+	struct dentry *debugfs_poke;
+	struct dentry *debugfs_reg_dump;
+	unsigned int read_data;
+#endif
+};
+
+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
new file mode 100644
index 0000000..7e518d2
--- /dev/null
+++ b/asoc/codecs/wsa883x/wsa883x-registers.h
@@ -0,0 +1,376 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef WSA883X_REGISTERS_H
+#define WSA883X_REGISTERS_H
+
+#define WSA883X_BASE                    0x3000
+#define WSA883X_REG(reg)    (reg - WSA883X_BASE)
+
+enum {
+	REG_NO_ACCESS,
+	RD_REG,
+	WR_REG,
+	RD_WR_REG,
+};
+
+#define WSA883X_ANA_BG_TSADC_BASE       (WSA883X_BASE+0x00000000)
+#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)
+#define WSA883X_OP_CTL                  (WSA883X_ANA_BG_TSADC_BASE+0x0003)
+#define WSA883X_IREF_CTL                (WSA883X_ANA_BG_TSADC_BASE+0x0004)
+#define WSA883X_ISENS_CTL               (WSA883X_ANA_BG_TSADC_BASE+0x0005)
+#define WSA883X_CLK_CTL                 (WSA883X_ANA_BG_TSADC_BASE+0x0006)
+#define WSA883X_TEST_CTL_1              (WSA883X_ANA_BG_TSADC_BASE+0x0007)
+#define WSA883X_BIAS_1                  (WSA883X_ANA_BG_TSADC_BASE+0x0008)
+#define WSA883X_ADC_CTL                 (WSA883X_ANA_BG_TSADC_BASE+0x0009)
+#define WSA883X_DOUT_MSB                (WSA883X_ANA_BG_TSADC_BASE+0x000A)
+#define WSA883X_DOUT_LSB                (WSA883X_ANA_BG_TSADC_BASE+0x000B)
+#define WSA883X_VBAT_SNS                (WSA883X_ANA_BG_TSADC_BASE+0x000C)
+#define WSA883X_ITRIM_CODE              (WSA883X_ANA_BG_TSADC_BASE+0x000D)
+
+#define WSA883X_ANA_IVSENSE_BASE        (WSA883X_BASE+0x0000000F)
+#define WSA883X_EN                      (WSA883X_ANA_IVSENSE_BASE+0x0000)
+#define WSA883X_OVERRIDE1               (WSA883X_ANA_IVSENSE_BASE+0x0001)
+#define WSA883X_OVERRIDE2               (WSA883X_ANA_IVSENSE_BASE+0x0002)
+#define WSA883X_VSENSE1                 (WSA883X_ANA_IVSENSE_BASE+0x0003)
+#define WSA883X_ISENSE1                 (WSA883X_ANA_IVSENSE_BASE+0x0004)
+#define WSA883X_ISENSE2                 (WSA883X_ANA_IVSENSE_BASE+0x0005)
+#define WSA883X_ISENSE_CAL              (WSA883X_ANA_IVSENSE_BASE+0x0006)
+#define WSA883X_MISC                    (WSA883X_ANA_IVSENSE_BASE+0x0007)
+#define WSA883X_ADC_0                   (WSA883X_ANA_IVSENSE_BASE+0x0008)
+#define WSA883X_ADC_1                   (WSA883X_ANA_IVSENSE_BASE+0x0009)
+#define WSA883X_ADC_2                   (WSA883X_ANA_IVSENSE_BASE+0x000A)
+#define WSA883X_ADC_3                   (WSA883X_ANA_IVSENSE_BASE+0x000B)
+#define WSA883X_ADC_4                   (WSA883X_ANA_IVSENSE_BASE+0x000C)
+#define WSA883X_ADC_5                   (WSA883X_ANA_IVSENSE_BASE+0x000D)
+#define WSA883X_ADC_6                   (WSA883X_ANA_IVSENSE_BASE+0x000E)
+#define WSA883X_ADC_7                   (WSA883X_ANA_IVSENSE_BASE+0x000F)
+#define WSA883X_STATUS                  (WSA883X_ANA_IVSENSE_BASE+0x0010)
+
+#define WSA883X_ANA_SPK_TOP_BASE        (WSA883X_BASE+0x00000025)
+#define WSA883X_DAC_CTRL_REG            (WSA883X_ANA_SPK_TOP_BASE+0x0000)
+#define WSA883X_DAC_EN_DEBUG_REG        (WSA883X_ANA_SPK_TOP_BASE+0x0001)
+#define WSA883X_DAC_OPAMP_BIAS1_REG     (WSA883X_ANA_SPK_TOP_BASE+0x0002)
+#define WSA883X_DAC_OPAMP_BIAS2_REG     (WSA883X_ANA_SPK_TOP_BASE+0x0003)
+#define WSA883X_DAC_VCM_CTRL_REG        (WSA883X_ANA_SPK_TOP_BASE+0x0004)
+#define WSA883X_DAC_VOLTAGE_CTRL_REG    (WSA883X_ANA_SPK_TOP_BASE+0x0005)
+#define WSA883X_ATEST1_REG              (WSA883X_ANA_SPK_TOP_BASE+0x0006)
+#define WSA883X_ATEST2_REG              (WSA883X_ANA_SPK_TOP_BASE+0x0007)
+#define WSA883X_SPKR_TOP_BIAS_REG1      (WSA883X_ANA_SPK_TOP_BASE+0x0008)
+#define WSA883X_SPKR_TOP_BIAS_REG2      (WSA883X_ANA_SPK_TOP_BASE+0x0009)
+#define WSA883X_SPKR_TOP_BIAS_REG3      (WSA883X_ANA_SPK_TOP_BASE+0x000A)
+#define WSA883X_SPKR_TOP_BIAS_REG4      (WSA883X_ANA_SPK_TOP_BASE+0x000B)
+#define WSA883X_SPKR_CLIP_DET_REG       (WSA883X_ANA_SPK_TOP_BASE+0x000C)
+#define WSA883X_SPKR_DRV_LF_BLK_EN      (WSA883X_ANA_SPK_TOP_BASE+0x000D)
+#define WSA883X_SPKR_DRV_LF_EN          (WSA883X_ANA_SPK_TOP_BASE+0x000E)
+#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_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)
+#define WSA883X_SPKR_PWRSTG_DBG         (WSA883X_ANA_SPK_TOP_BASE+0x0017)
+#define WSA883X_SPKR_OCP_CTL            (WSA883X_ANA_SPK_TOP_BASE+0x0018)
+#define WSA883X_SPKR_BBM_CTL            (WSA883X_ANA_SPK_TOP_BASE+0x0019)
+#define WSA883X_PA_STATUS0              (WSA883X_ANA_SPK_TOP_BASE+0x001A)
+#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_EN_CTRL                 (WSA883X_ANA_BOOST_BASE+0x0000)
+#define WSA883X_CURRENT_LIMIT           (WSA883X_ANA_BOOST_BASE+0x0001)
+#define WSA883X_IBIAS1                  (WSA883X_ANA_BOOST_BASE+0x0002)
+#define WSA883X_IBIAS2                  (WSA883X_ANA_BOOST_BASE+0x0003)
+#define WSA883X_IBIAS3                  (WSA883X_ANA_BOOST_BASE+0x0004)
+#define WSA883X_LDO_PROG                (WSA883X_ANA_BOOST_BASE+0x0005)
+#define WSA883X_STABILITY_CTRL1         (WSA883X_ANA_BOOST_BASE+0x0006)
+#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_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_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_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)
+#define WSA883X_CHIP_ID3                (WSA883X_DIG_CTRL_BASE+0x0004)
+#define WSA883X_BUS_ID                  (WSA883X_DIG_CTRL_BASE+0x0005)
+#define WSA883X_CDC_RST_CTL             (WSA883X_DIG_CTRL_BASE+0x0006)
+#define WSA883X_TOP_CLK_CFG             (WSA883X_DIG_CTRL_BASE+0x0007)
+#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_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)
+#define WSA883X_PA_FSM_STA              (WSA883X_DIG_CTRL_BASE+0x0013)
+#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_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)
+#define WSA883X_TEMP_LSB                (WSA883X_DIG_CTRL_BASE+0x0023)
+#define WSA883X_TEMP_CONFIG0            (WSA883X_DIG_CTRL_BASE+0x0024)
+#define WSA883X_TEMP_CONFIG1            (WSA883X_DIG_CTRL_BASE+0x0025)
+#define WSA883X_VBAT_ADC_FLT_CTL        (WSA883X_DIG_CTRL_BASE+0x0026)
+#define WSA883X_VBAT_DIN_MSB            (WSA883X_DIG_CTRL_BASE+0x0027)
+#define WSA883X_VBAT_DIN_LSB            (WSA883X_DIG_CTRL_BASE+0x0028)
+#define WSA883X_VBAT_DOUT               (WSA883X_DIG_CTRL_BASE+0x0029)
+#define WSA883X_SDM_PDM9_LSB            (WSA883X_DIG_CTRL_BASE+0x002A)
+#define WSA883X_SDM_PDM9_MSB            (WSA883X_DIG_CTRL_BASE+0x002B)
+#define WSA883X_CDC_RX_CTL              (WSA883X_DIG_CTRL_BASE+0x0030)
+#define WSA883X_CDC_SPK_DSM_A1_0        (WSA883X_DIG_CTRL_BASE+0x0031)
+#define WSA883X_CDC_SPK_DSM_A1_1        (WSA883X_DIG_CTRL_BASE+0x0032)
+#define WSA883X_CDC_SPK_DSM_A2_0        (WSA883X_DIG_CTRL_BASE+0x0033)
+#define WSA883X_CDC_SPK_DSM_A2_1        (WSA883X_DIG_CTRL_BASE+0x0034)
+#define WSA883X_CDC_SPK_DSM_A3_0        (WSA883X_DIG_CTRL_BASE+0x0035)
+#define WSA883X_CDC_SPK_DSM_A3_1        (WSA883X_DIG_CTRL_BASE+0x0036)
+#define WSA883X_CDC_SPK_DSM_A4_0        (WSA883X_DIG_CTRL_BASE+0x0037)
+#define WSA883X_CDC_SPK_DSM_A4_1        (WSA883X_DIG_CTRL_BASE+0x0038)
+#define WSA883X_CDC_SPK_DSM_A5_0        (WSA883X_DIG_CTRL_BASE+0x0039)
+#define WSA883X_CDC_SPK_DSM_A5_1        (WSA883X_DIG_CTRL_BASE+0x003A)
+#define WSA883X_CDC_SPK_DSM_A6_0        (WSA883X_DIG_CTRL_BASE+0x003B)
+#define WSA883X_CDC_SPK_DSM_A7_0        (WSA883X_DIG_CTRL_BASE+0x003C)
+#define WSA883X_CDC_SPK_DSM_C_0         (WSA883X_DIG_CTRL_BASE+0x003D)
+#define WSA883X_CDC_SPK_DSM_C_1         (WSA883X_DIG_CTRL_BASE+0x003E)
+#define WSA883X_CDC_SPK_DSM_C_2         (WSA883X_DIG_CTRL_BASE+0x003F)
+#define WSA883X_CDC_SPK_DSM_C_3         (WSA883X_DIG_CTRL_BASE+0x0040)
+#define WSA883X_CDC_SPK_DSM_R1          (WSA883X_DIG_CTRL_BASE+0x0041)
+#define WSA883X_CDC_SPK_DSM_R2          (WSA883X_DIG_CTRL_BASE+0x0042)
+#define WSA883X_CDC_SPK_DSM_R3          (WSA883X_DIG_CTRL_BASE+0x0043)
+#define WSA883X_CDC_SPK_DSM_R4          (WSA883X_DIG_CTRL_BASE+0x0044)
+#define WSA883X_CDC_SPK_DSM_R5          (WSA883X_DIG_CTRL_BASE+0x0045)
+#define WSA883X_CDC_SPK_DSM_R6          (WSA883X_DIG_CTRL_BASE+0x0046)
+#define WSA883X_CDC_SPK_DSM_R7          (WSA883X_DIG_CTRL_BASE+0x0047)
+#define WSA883X_CDC_SPK_GAIN_PDM_0      (WSA883X_DIG_CTRL_BASE+0x0048)
+#define WSA883X_CDC_SPK_GAIN_PDM_1      (WSA883X_DIG_CTRL_BASE+0x0049)
+#define WSA883X_CDC_SPK_GAIN_PDM_2      (WSA883X_DIG_CTRL_BASE+0x004A)
+#define WSA883X_PDM_WD_CTL              (WSA883X_DIG_CTRL_BASE+0x004B)
+#define WSA883X_DEM_BYPASS_DATA0        (WSA883X_DIG_CTRL_BASE+0x004C)
+#define WSA883X_DEM_BYPASS_DATA1        (WSA883X_DIG_CTRL_BASE+0x004D)
+#define WSA883X_DEM_BYPASS_DATA2        (WSA883X_DIG_CTRL_BASE+0x004E)
+#define WSA883X_DEM_BYPASS_DATA3        (WSA883X_DIG_CTRL_BASE+0x004F)
+#define WSA883X_WAVG_CTL                (WSA883X_DIG_CTRL_BASE+0x0050)
+#define WSA883X_WAVG_LRA_PER_0          (WSA883X_DIG_CTRL_BASE+0x0051)
+#define WSA883X_WAVG_LRA_PER_1          (WSA883X_DIG_CTRL_BASE+0x0052)
+#define WSA883X_WAVG_DELTA_THETA_0      (WSA883X_DIG_CTRL_BASE+0x0053)
+#define WSA883X_WAVG_DELTA_THETA_1      (WSA883X_DIG_CTRL_BASE+0x0054)
+#define WSA883X_WAVG_DIRECT_AMP_0       (WSA883X_DIG_CTRL_BASE+0x0055)
+#define WSA883X_WAVG_DIRECT_AMP_1       (WSA883X_DIG_CTRL_BASE+0x0056)
+#define WSA883X_WAVG_PTRN_AMP0_0        (WSA883X_DIG_CTRL_BASE+0x0057)
+#define WSA883X_WAVG_PTRN_AMP0_1        (WSA883X_DIG_CTRL_BASE+0x0058)
+#define WSA883X_WAVG_PTRN_AMP1_0        (WSA883X_DIG_CTRL_BASE+0x0059)
+#define WSA883X_WAVG_PTRN_AMP1_1        (WSA883X_DIG_CTRL_BASE+0x005A)
+#define WSA883X_WAVG_PTRN_AMP2_0        (WSA883X_DIG_CTRL_BASE+0x005B)
+#define WSA883X_WAVG_PTRN_AMP2_1        (WSA883X_DIG_CTRL_BASE+0x005C)
+#define WSA883X_WAVG_PTRN_AMP3_0        (WSA883X_DIG_CTRL_BASE+0x005D)
+#define WSA883X_WAVG_PTRN_AMP3_1        (WSA883X_DIG_CTRL_BASE+0x005E)
+#define WSA883X_WAVG_PTRN_AMP4_0        (WSA883X_DIG_CTRL_BASE+0x005F)
+#define WSA883X_WAVG_PTRN_AMP4_1        (WSA883X_DIG_CTRL_BASE+0x0060)
+#define WSA883X_WAVG_PTRN_AMP5_0        (WSA883X_DIG_CTRL_BASE+0x0061)
+#define WSA883X_WAVG_PTRN_AMP5_1        (WSA883X_DIG_CTRL_BASE+0x0062)
+#define WSA883X_WAVG_PTRN_AMP6_0        (WSA883X_DIG_CTRL_BASE+0x0063)
+#define WSA883X_WAVG_PTRN_AMP6_1        (WSA883X_DIG_CTRL_BASE+0x0064)
+#define WSA883X_WAVG_PTRN_AMP7_0        (WSA883X_DIG_CTRL_BASE+0x0065)
+#define WSA883X_WAVG_PTRN_AMP7_1        (WSA883X_DIG_CTRL_BASE+0x0066)
+#define WSA883X_WAVG_PER_0_1            (WSA883X_DIG_CTRL_BASE+0x0067)
+#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_DRE_CTL_0               (WSA883X_DIG_CTRL_BASE+0x006C)
+#define WSA883X_DRE_CTL_1               (WSA883X_DIG_CTRL_BASE+0x006D)
+#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)
+#define WSA883X_CLSH_V_PA_MIN           (WSA883X_DIG_CTRL_BASE+0x0073)
+#define WSA883X_CLSH_OVRD_VAL           (WSA883X_DIG_CTRL_BASE+0x0074)
+#define WSA883X_CLSH_HARD_MAX           (WSA883X_DIG_CTRL_BASE+0x0075)
+#define WSA883X_CLSH_SOFT_MAX           (WSA883X_DIG_CTRL_BASE+0x0076)
+#define WSA883X_CLSH_SIG_DP             (WSA883X_DIG_CTRL_BASE+0x0077)
+#define WSA883X_TAGC_CTL                (WSA883X_DIG_CTRL_BASE+0x0078)
+#define WSA883X_TAGC_TIME               (WSA883X_DIG_CTRL_BASE+0x0079)
+#define WSA883X_TAGC_E2E_GAIN           (WSA883X_DIG_CTRL_BASE+0x007A)
+#define WSA883X_TAGC_FORCE_VAL          (WSA883X_DIG_CTRL_BASE+0x007B)
+#define WSA883X_VAGC_CTL                (WSA883X_DIG_CTRL_BASE+0x007C)
+#define WSA883X_VAGC_TIME               (WSA883X_DIG_CTRL_BASE+0x007D)
+#define WSA883X_VAGC_ATTN_LVL_1_2       (WSA883X_DIG_CTRL_BASE+0x007E)
+#define WSA883X_VAGC_ATTN_LVL_3         (WSA883X_DIG_CTRL_BASE+0x007F)
+#define WSA883X_INTR_MODE               (WSA883X_DIG_CTRL_BASE+0x0080)
+#define WSA883X_INTR_MASK0              (WSA883X_DIG_CTRL_BASE+0x0081)
+#define WSA883X_INTR_MASK1              (WSA883X_DIG_CTRL_BASE+0x0082)
+#define WSA883X_INTR_STATUS0            (WSA883X_DIG_CTRL_BASE+0x0083)
+#define WSA883X_INTR_STATUS1            (WSA883X_DIG_CTRL_BASE+0x0084)
+#define WSA883X_INTR_CLEAR0             (WSA883X_DIG_CTRL_BASE+0x0085)
+#define WSA883X_INTR_CLEAR1             (WSA883X_DIG_CTRL_BASE+0x0086)
+#define WSA883X_INTR_LEVEL0             (WSA883X_DIG_CTRL_BASE+0x0087)
+#define WSA883X_INTR_LEVEL1             (WSA883X_DIG_CTRL_BASE+0x0088)
+#define WSA883X_INTR_SET0               (WSA883X_DIG_CTRL_BASE+0x0089)
+#define WSA883X_INTR_SET1               (WSA883X_DIG_CTRL_BASE+0x008A)
+#define WSA883X_INTR_TEST0              (WSA883X_DIG_CTRL_BASE+0x008B)
+#define WSA883X_INTR_TEST1              (WSA883X_DIG_CTRL_BASE+0x008C)
+#define WSA883X_OTP_CTRL0               (WSA883X_DIG_CTRL_BASE+0x0090)
+#define WSA883X_OTP_CTRL1               (WSA883X_DIG_CTRL_BASE+0x0091)
+#define WSA883X_HDRIVE_CTL_GROUP1       (WSA883X_DIG_CTRL_BASE+0x0092)
+#define WSA883X_PIN_CTL                 (WSA883X_DIG_CTRL_BASE+0x0093)
+#define WSA883X_PIN_CTL_OE              (WSA883X_DIG_CTRL_BASE+0x0094)
+#define WSA883X_PIN_WDATA_IOPAD         (WSA883X_DIG_CTRL_BASE+0x0095)
+#define WSA883X_PIN_STATUS              (WSA883X_DIG_CTRL_BASE+0x0096)
+#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_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_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)
+#define WSA883X_OTP_REG_3               (WSA883X_DIG_TRIM_BASE+0x0083)
+#define WSA883X_OTP_REG_4               (WSA883X_DIG_TRIM_BASE+0x0084)
+#define WSA883X_OTP_REG_5               (WSA883X_DIG_TRIM_BASE+0x0085)
+#define WSA883X_OTP_REG_6               (WSA883X_DIG_TRIM_BASE+0x0086)
+#define WSA883X_OTP_REG_7               (WSA883X_DIG_TRIM_BASE+0x0087)
+#define WSA883X_OTP_REG_8               (WSA883X_DIG_TRIM_BASE+0x0088)
+#define WSA883X_OTP_REG_9               (WSA883X_DIG_TRIM_BASE+0x0089)
+#define WSA883X_OTP_REG_10              (WSA883X_DIG_TRIM_BASE+0x008A)
+#define WSA883X_OTP_REG_11              (WSA883X_DIG_TRIM_BASE+0x008B)
+#define WSA883X_OTP_REG_12              (WSA883X_DIG_TRIM_BASE+0x008C)
+#define WSA883X_OTP_REG_13              (WSA883X_DIG_TRIM_BASE+0x008D)
+#define WSA883X_OTP_REG_14              (WSA883X_DIG_TRIM_BASE+0x008E)
+#define WSA883X_OTP_REG_15              (WSA883X_DIG_TRIM_BASE+0x008F)
+#define WSA883X_OTP_REG_16              (WSA883X_DIG_TRIM_BASE+0x0090)
+#define WSA883X_OTP_REG_17              (WSA883X_DIG_TRIM_BASE+0x0091)
+#define WSA883X_OTP_REG_18              (WSA883X_DIG_TRIM_BASE+0x0092)
+#define WSA883X_OTP_REG_19              (WSA883X_DIG_TRIM_BASE+0x0093)
+#define WSA883X_OTP_REG_20              (WSA883X_DIG_TRIM_BASE+0x0094)
+#define WSA883X_OTP_REG_21              (WSA883X_DIG_TRIM_BASE+0x0095)
+#define WSA883X_OTP_REG_22              (WSA883X_DIG_TRIM_BASE+0x0096)
+#define WSA883X_OTP_REG_23              (WSA883X_DIG_TRIM_BASE+0x0097)
+#define WSA883X_OTP_REG_24              (WSA883X_DIG_TRIM_BASE+0x0098)
+#define WSA883X_OTP_REG_25              (WSA883X_DIG_TRIM_BASE+0x0099)
+#define WSA883X_OTP_REG_26              (WSA883X_DIG_TRIM_BASE+0x009A)
+#define WSA883X_OTP_REG_27              (WSA883X_DIG_TRIM_BASE+0x009B)
+#define WSA883X_OTP_REG_28              (WSA883X_DIG_TRIM_BASE+0x009C)
+#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_63              (WSA883X_DIG_TRIM_BASE+0x00BF)
+
+#define WSA883X_DIG_EMEM_BASE           (WSA883X_BASE+0x000005C0)
+#define WSA883X_EMEM_0                  (WSA883X_DIG_EMEM_BASE+0x0000)
+#define WSA883X_EMEM_1                  (WSA883X_DIG_EMEM_BASE+0x0001)
+#define WSA883X_EMEM_2                  (WSA883X_DIG_EMEM_BASE+0x0002)
+#define WSA883X_EMEM_3                  (WSA883X_DIG_EMEM_BASE+0x0003)
+#define WSA883X_EMEM_4                  (WSA883X_DIG_EMEM_BASE+0x0004)
+#define WSA883X_EMEM_5                  (WSA883X_DIG_EMEM_BASE+0x0005)
+#define WSA883X_EMEM_6                  (WSA883X_DIG_EMEM_BASE+0x0006)
+#define WSA883X_EMEM_7                  (WSA883X_DIG_EMEM_BASE+0x0007)
+#define WSA883X_EMEM_8                  (WSA883X_DIG_EMEM_BASE+0x0008)
+#define WSA883X_EMEM_9                  (WSA883X_DIG_EMEM_BASE+0x0009)
+#define WSA883X_EMEM_10                 (WSA883X_DIG_EMEM_BASE+0x000A)
+#define WSA883X_EMEM_11                 (WSA883X_DIG_EMEM_BASE+0x000B)
+#define WSA883X_EMEM_12                 (WSA883X_DIG_EMEM_BASE+0x000C)
+#define WSA883X_EMEM_13                 (WSA883X_DIG_EMEM_BASE+0x000D)
+#define WSA883X_EMEM_14                 (WSA883X_DIG_EMEM_BASE+0x000E)
+#define WSA883X_EMEM_15                 (WSA883X_DIG_EMEM_BASE+0x000F)
+#define WSA883X_EMEM_16                 (WSA883X_DIG_EMEM_BASE+0x0010)
+#define WSA883X_EMEM_17                 (WSA883X_DIG_EMEM_BASE+0x0011)
+#define WSA883X_EMEM_18                 (WSA883X_DIG_EMEM_BASE+0x0012)
+#define WSA883X_EMEM_19                 (WSA883X_DIG_EMEM_BASE+0x0013)
+#define WSA883X_EMEM_20                 (WSA883X_DIG_EMEM_BASE+0x0014)
+#define WSA883X_EMEM_21                 (WSA883X_DIG_EMEM_BASE+0x0015)
+#define WSA883X_EMEM_22                 (WSA883X_DIG_EMEM_BASE+0x0016)
+#define WSA883X_EMEM_23                 (WSA883X_DIG_EMEM_BASE+0x0017)
+#define WSA883X_EMEM_24                 (WSA883X_DIG_EMEM_BASE+0x0018)
+#define WSA883X_EMEM_25                 (WSA883X_DIG_EMEM_BASE+0x0019)
+#define WSA883X_EMEM_26                 (WSA883X_DIG_EMEM_BASE+0x001A)
+#define WSA883X_EMEM_27                 (WSA883X_DIG_EMEM_BASE+0x001B)
+#define WSA883X_EMEM_28                 (WSA883X_DIG_EMEM_BASE+0x001C)
+#define WSA883X_EMEM_29                 (WSA883X_DIG_EMEM_BASE+0x001D)
+#define WSA883X_EMEM_30                 (WSA883X_DIG_EMEM_BASE+0x001E)
+#define WSA883X_EMEM_31                 (WSA883X_DIG_EMEM_BASE+0x001F)
+#define WSA883X_EMEM_32                 (WSA883X_DIG_EMEM_BASE+0x0020)
+#define WSA883X_EMEM_33                 (WSA883X_DIG_EMEM_BASE+0x0021)
+#define WSA883X_EMEM_34                 (WSA883X_DIG_EMEM_BASE+0x0022)
+#define WSA883X_EMEM_35                 (WSA883X_DIG_EMEM_BASE+0x0023)
+#define WSA883X_EMEM_36                 (WSA883X_DIG_EMEM_BASE+0x0024)
+#define WSA883X_EMEM_37                 (WSA883X_DIG_EMEM_BASE+0x0025)
+#define WSA883X_EMEM_38                 (WSA883X_DIG_EMEM_BASE+0x0026)
+#define WSA883X_EMEM_39                 (WSA883X_DIG_EMEM_BASE+0x0027)
+#define WSA883X_EMEM_40                 (WSA883X_DIG_EMEM_BASE+0x0028)
+#define WSA883X_EMEM_41                 (WSA883X_DIG_EMEM_BASE+0x0029)
+#define WSA883X_EMEM_42                 (WSA883X_DIG_EMEM_BASE+0x002A)
+#define WSA883X_EMEM_43                 (WSA883X_DIG_EMEM_BASE+0x002B)
+#define WSA883X_EMEM_44                 (WSA883X_DIG_EMEM_BASE+0x002C)
+#define WSA883X_EMEM_45                 (WSA883X_DIG_EMEM_BASE+0x002D)
+#define WSA883X_EMEM_46                 (WSA883X_DIG_EMEM_BASE+0x002E)
+#define WSA883X_EMEM_47                 (WSA883X_DIG_EMEM_BASE+0x002F)
+#define WSA883X_EMEM_48                 (WSA883X_DIG_EMEM_BASE+0x0030)
+#define WSA883X_EMEM_49                 (WSA883X_DIG_EMEM_BASE+0x0031)
+#define WSA883X_EMEM_50                 (WSA883X_DIG_EMEM_BASE+0x0032)
+#define WSA883X_EMEM_51                 (WSA883X_DIG_EMEM_BASE+0x0033)
+#define WSA883X_EMEM_52                 (WSA883X_DIG_EMEM_BASE+0x0034)
+#define WSA883X_EMEM_53                 (WSA883X_DIG_EMEM_BASE+0x0035)
+#define WSA883X_EMEM_54                 (WSA883X_DIG_EMEM_BASE+0x0036)
+#define WSA883X_EMEM_55                 (WSA883X_DIG_EMEM_BASE+0x0037)
+#define WSA883X_EMEM_56                 (WSA883X_DIG_EMEM_BASE+0x0038)
+#define WSA883X_EMEM_57                 (WSA883X_DIG_EMEM_BASE+0x0039)
+#define WSA883X_EMEM_58                 (WSA883X_DIG_EMEM_BASE+0x003A)
+#define WSA883X_EMEM_59                 (WSA883X_DIG_EMEM_BASE+0x003B)
+#define WSA883X_EMEM_60                 (WSA883X_DIG_EMEM_BASE+0x003C)
+#define WSA883X_EMEM_61                 (WSA883X_DIG_EMEM_BASE+0x003D)
+#define WSA883X_EMEM_62                 (WSA883X_DIG_EMEM_BASE+0x003E)
+#define WSA883X_EMEM_63                 (WSA883X_DIG_EMEM_BASE+0x003F)
+
+#define WSA883X_NUM_REGISTERS           (WSA883X_EMEM_63+1)
+#define WSA883X_MAX_REGISTER            (WSA883X_NUM_REGISTERS-1)
+
+#endif /* WSA883X_REGISTERS_H */
diff --git a/asoc/codecs/wsa883x/wsa883x-regmap.c b/asoc/codecs/wsa883x/wsa883x-regmap.c
new file mode 100644
index 0000000..8394e9c
--- /dev/null
+++ b/asoc/codecs/wsa883x/wsa883x-regmap.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include "wsa883x-registers.h"
+#include "wsa883x.h"
+
+extern const u8 wsa883x_reg_access[WSA883X_NUM_REGISTERS];
+
+static struct reg_default wsa883x_defaults[] = {
+	{WSA883X_REF_CTRL,                   0x6C},
+	{WSA883X_TEST_CTL_0,                 0x06},
+	{WSA883X_BIAS_0,                     0xD2},
+	{WSA883X_OP_CTL,                     0xE0},
+	{WSA883X_IREF_CTL,                   0x58},
+	{WSA883X_ISENS_CTL,                  0x47},
+	{WSA883X_CLK_CTL,                    0x87},
+	{WSA883X_TEST_CTL_1,                 0x00},
+	{WSA883X_BIAS_1,                     0x51},
+	{WSA883X_ADC_CTL,                    0x03},
+	{WSA883X_DOUT_MSB,                   0x00},
+	{WSA883X_DOUT_LSB,                   0x00},
+	{WSA883X_VBAT_SNS,                   0x00},
+	{WSA883X_ITRIM_CODE,                 0x1F},
+	{WSA883X_EN,                         0x00},
+	{WSA883X_OVERRIDE1,                  0x00},
+	{WSA883X_OVERRIDE2,                  0x08},
+	{WSA883X_VSENSE1,                    0xD3},
+	{WSA883X_ISENSE1,                    0xD4},
+	{WSA883X_ISENSE2,                    0x20},
+	{WSA883X_ISENSE_CAL,                 0x00},
+	{WSA883X_MISC,                       0x00},
+	{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_STATUS,                     0x00},
+	{WSA883X_DAC_CTRL_REG,               0x41},
+	{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_ATEST1_REG,                 0x00},
+	{WSA883X_ATEST2_REG,                 0x00},
+	{WSA883X_SPKR_TOP_BIAS_REG1,         0x4A},
+	{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_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_REG_GAIN,       0x00},
+	{WSA883X_SPKR_DRV_LF_OS_CAL_CTL1,    0x90},
+	{WSA883X_SPKR_DRV_LF_OS_CAL_CTL,     0x00},
+	{WSA883X_SPKR_PWM_CLK_CTL,           0x00},
+	{WSA883X_SPKR_PDRV_HS_CTL,           0x50},
+	{WSA883X_SPKR_PDRV_LS_CTL,           0x48},
+	{WSA883X_SPKR_PWRSTG_DBG,            0x00},
+	{WSA883X_SPKR_OCP_CTL,               0x00},
+	{WSA883X_SPKR_BBM_CTL,               0x90},
+	{WSA883X_PA_STATUS0,                 0x00},
+	{WSA883X_PA_STATUS1,                 0x00},
+	{WSA883X_PA_STATUS2,                 0x00},
+	{WSA883X_EN_CTRL,                    0x54},
+	{WSA883X_CURRENT_LIMIT,              0x90},
+	{WSA883X_IBIAS1,                     0x00},
+	{WSA883X_IBIAS2,                     0x00},
+	{WSA883X_IBIAS3,                     0x00},
+	{WSA883X_LDO_PROG,                   0x2A},
+	{WSA883X_STABILITY_CTRL1,            0x8E},
+	{WSA883X_STABILITY_CTRL2,            0x00},
+	{WSA883X_PWRSTAGE_CTRL1,             0x00},
+	{WSA883X_PWRSTAGE_CTRL2,             0x40},
+	{WSA883X_UVLO,                       0xE9},
+	{WSA883X_SEQUENCE_CTRL,              0x11},
+	{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_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_CKWD_CTL_0,                 0x34},
+	{WSA883X_CKWD_CTL_1,                 0x80},
+	{WSA883X_CKWD_CTL_2,                 0x00},
+	{WSA883X_CKSK_CTL_0,                 0x0A},
+	{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},
+	{WSA883X_CHIP_ID3,                   0x02},
+	{WSA883X_BUS_ID,                     0x00},
+	{WSA883X_CDC_RST_CTL,                0x01},
+	{WSA883X_TOP_CLK_CFG,                0x00},
+	{WSA883X_CDC_PATH_MODE,              0x00},
+	{WSA883X_CDC_CLK_CTL,                0xFF},
+	{WSA883X_SWR_RESET_EN,               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_TADC_VALUE_CTL,             0x03},
+	{WSA883X_TEMP_DETECT_CTL,            0x01},
+	{WSA883X_TEMP_MSB,                   0x00},
+	{WSA883X_TEMP_LSB,                   0x00},
+	{WSA883X_TEMP_CONFIG0,               0x00},
+	{WSA883X_TEMP_CONFIG1,               0x00},
+	{WSA883X_VBAT_ADC_FLT_CTL,           0x00},
+	{WSA883X_VBAT_DIN_MSB,               0x00},
+	{WSA883X_VBAT_DIN_LSB,               0x00},
+	{WSA883X_VBAT_DOUT,                  0x00},
+	{WSA883X_SDM_PDM9_LSB,               0x00},
+	{WSA883X_SDM_PDM9_MSB,               0x00},
+	{WSA883X_CDC_RX_CTL,                 0xFE},
+	{WSA883X_CDC_SPK_DSM_A1_0,           0x00},
+	{WSA883X_CDC_SPK_DSM_A1_1,           0x01},
+	{WSA883X_CDC_SPK_DSM_A2_0,           0x96},
+	{WSA883X_CDC_SPK_DSM_A2_1,           0x09},
+	{WSA883X_CDC_SPK_DSM_A3_0,           0xAB},
+	{WSA883X_CDC_SPK_DSM_A3_1,           0x05},
+	{WSA883X_CDC_SPK_DSM_A4_0,           0x1C},
+	{WSA883X_CDC_SPK_DSM_A4_1,           0x02},
+	{WSA883X_CDC_SPK_DSM_A5_0,           0x17},
+	{WSA883X_CDC_SPK_DSM_A5_1,           0x02},
+	{WSA883X_CDC_SPK_DSM_A6_0,           0xAA},
+	{WSA883X_CDC_SPK_DSM_A7_0,           0xE3},
+	{WSA883X_CDC_SPK_DSM_C_0,            0x69},
+	{WSA883X_CDC_SPK_DSM_C_1,            0x54},
+	{WSA883X_CDC_SPK_DSM_C_2,            0x02},
+	{WSA883X_CDC_SPK_DSM_C_3,            0x15},
+	{WSA883X_CDC_SPK_DSM_R1,             0xA4},
+	{WSA883X_CDC_SPK_DSM_R2,             0xB5},
+	{WSA883X_CDC_SPK_DSM_R3,             0x86},
+	{WSA883X_CDC_SPK_DSM_R4,             0x85},
+	{WSA883X_CDC_SPK_DSM_R5,             0xAA},
+	{WSA883X_CDC_SPK_DSM_R6,             0xE2},
+	{WSA883X_CDC_SPK_DSM_R7,             0x62},
+	{WSA883X_CDC_SPK_GAIN_PDM_0,         0x00},
+	{WSA883X_CDC_SPK_GAIN_PDM_1,         0xFC},
+	{WSA883X_CDC_SPK_GAIN_PDM_2,         0x05},
+	{WSA883X_PDM_WD_CTL,                 0x00},
+	{WSA883X_DEM_BYPASS_DATA0,           0x00},
+	{WSA883X_DEM_BYPASS_DATA1,           0x00},
+	{WSA883X_DEM_BYPASS_DATA2,           0x00},
+	{WSA883X_DEM_BYPASS_DATA3,           0x00},
+	{WSA883X_WAVG_CTL,                   0x06},
+	{WSA883X_WAVG_LRA_PER_0,             0xD1},
+	{WSA883X_WAVG_LRA_PER_1,             0x00},
+	{WSA883X_WAVG_DELTA_THETA_0,         0xE6},
+	{WSA883X_WAVG_DELTA_THETA_1,         0x04},
+	{WSA883X_WAVG_DIRECT_AMP_0,          0x50},
+	{WSA883X_WAVG_DIRECT_AMP_1,          0x00},
+	{WSA883X_WAVG_PTRN_AMP0_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP0_1,           0x00},
+	{WSA883X_WAVG_PTRN_AMP1_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP1_1,           0x00},
+	{WSA883X_WAVG_PTRN_AMP2_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP2_1,           0x00},
+	{WSA883X_WAVG_PTRN_AMP3_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP3_1,           0x00},
+	{WSA883X_WAVG_PTRN_AMP4_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP4_1,           0x00},
+	{WSA883X_WAVG_PTRN_AMP5_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP5_1,           0x00},
+	{WSA883X_WAVG_PTRN_AMP6_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP6_1,           0x00},
+	{WSA883X_WAVG_PTRN_AMP7_0,           0x50},
+	{WSA883X_WAVG_PTRN_AMP7_1,           0x00},
+	{WSA883X_WAVG_PER_0_1,               0x88},
+	{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_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_SIG_DP,                0x00},
+	{WSA883X_TAGC_CTL,                   0x10},
+	{WSA883X_TAGC_TIME,                  0x20},
+	{WSA883X_TAGC_E2E_GAIN,              0x02},
+	{WSA883X_TAGC_FORCE_VAL,             0x00},
+	{WSA883X_VAGC_CTL,                   0x00},
+	{WSA883X_VAGC_TIME,                  0x08},
+	{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_STATUS0,               0x00},
+	{WSA883X_INTR_STATUS1,               0x00},
+	{WSA883X_INTR_CLEAR0,                0x00},
+	{WSA883X_INTR_CLEAR1,                0x03},
+	{WSA883X_INTR_LEVEL0,                0x00},
+	{WSA883X_INTR_LEVEL1,                0x03},
+	{WSA883X_INTR_SET0,                  0x00},
+	{WSA883X_INTR_SET1,                  0x03},
+	{WSA883X_INTR_TEST0,                 0x00},
+	{WSA883X_INTR_TEST1,                 0x03},
+	{WSA883X_OTP_CTRL0,                  0x00},
+	{WSA883X_OTP_CTRL1,                  0x00},
+	{WSA883X_HDRIVE_CTL_GROUP1,          0x00},
+	{WSA883X_PIN_CTL,                    0x04},
+	{WSA883X_PIN_CTL_OE,                 0x00},
+	{WSA883X_PIN_WDATA_IOPAD,            0x00},
+	{WSA883X_PIN_STATUS,                 0x00},
+	{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_SAMPLE_EDGE_SEL,            0x7F},
+	{WSA883X_TEST_MODE_CTL,              0x00},
+	{WSA883X_IOPAD_CTL,                  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_1,                  0xFF},
+	{WSA883X_OTP_REG_2,                  0xC0},
+	{WSA883X_OTP_REG_3,                  0xFF},
+	{WSA883X_OTP_REG_4,                  0xC0},
+	{WSA883X_OTP_REG_5,                  0xFF},
+	{WSA883X_OTP_REG_6,                  0xFF},
+	{WSA883X_OTP_REG_7,                  0xFF},
+	{WSA883X_OTP_REG_8,                  0xFF},
+	{WSA883X_OTP_REG_9,                  0xFF},
+	{WSA883X_OTP_REG_10,                 0xFF},
+	{WSA883X_OTP_REG_11,                 0xFF},
+	{WSA883X_OTP_REG_12,                 0xFF},
+	{WSA883X_OTP_REG_13,                 0xFF},
+	{WSA883X_OTP_REG_14,                 0xFF},
+	{WSA883X_OTP_REG_15,                 0xFF},
+	{WSA883X_OTP_REG_16,                 0xFF},
+	{WSA883X_OTP_REG_17,                 0xFF},
+	{WSA883X_OTP_REG_18,                 0xFF},
+	{WSA883X_OTP_REG_19,                 0xFF},
+	{WSA883X_OTP_REG_20,                 0xFF},
+	{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_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_63,                 0x40},
+	{WSA883X_EMEM_0,                     0x00},
+	{WSA883X_EMEM_1,                     0x00},
+	{WSA883X_EMEM_2,                     0x00},
+	{WSA883X_EMEM_3,                     0x00},
+	{WSA883X_EMEM_4,                     0x00},
+	{WSA883X_EMEM_5,                     0x00},
+	{WSA883X_EMEM_6,                     0x00},
+	{WSA883X_EMEM_7,                     0x00},
+	{WSA883X_EMEM_8,                     0x00},
+	{WSA883X_EMEM_9,                     0x00},
+	{WSA883X_EMEM_10,                    0x00},
+	{WSA883X_EMEM_11,                    0x00},
+	{WSA883X_EMEM_12,                    0x00},
+	{WSA883X_EMEM_13,                    0x00},
+	{WSA883X_EMEM_14,                    0x00},
+	{WSA883X_EMEM_15,                    0x00},
+	{WSA883X_EMEM_16,                    0x00},
+	{WSA883X_EMEM_17,                    0x00},
+	{WSA883X_EMEM_18,                    0x00},
+	{WSA883X_EMEM_19,                    0x00},
+	{WSA883X_EMEM_20,                    0x00},
+	{WSA883X_EMEM_21,                    0x00},
+	{WSA883X_EMEM_22,                    0x00},
+	{WSA883X_EMEM_23,                    0x00},
+	{WSA883X_EMEM_24,                    0x00},
+	{WSA883X_EMEM_25,                    0x00},
+	{WSA883X_EMEM_26,                    0x00},
+	{WSA883X_EMEM_27,                    0x00},
+	{WSA883X_EMEM_28,                    0x00},
+	{WSA883X_EMEM_29,                    0x00},
+	{WSA883X_EMEM_30,                    0x00},
+	{WSA883X_EMEM_31,                    0x00},
+	{WSA883X_EMEM_32,                    0x00},
+	{WSA883X_EMEM_33,                    0x00},
+	{WSA883X_EMEM_34,                    0x00},
+	{WSA883X_EMEM_35,                    0x00},
+	{WSA883X_EMEM_36,                    0x00},
+	{WSA883X_EMEM_37,                    0x00},
+	{WSA883X_EMEM_38,                    0x00},
+	{WSA883X_EMEM_39,                    0x00},
+	{WSA883X_EMEM_40,                    0x00},
+	{WSA883X_EMEM_41,                    0x00},
+	{WSA883X_EMEM_42,                    0x00},
+	{WSA883X_EMEM_43,                    0x00},
+	{WSA883X_EMEM_44,                    0x00},
+	{WSA883X_EMEM_45,                    0x00},
+	{WSA883X_EMEM_46,                    0x00},
+	{WSA883X_EMEM_47,                    0x00},
+	{WSA883X_EMEM_48,                    0x00},
+	{WSA883X_EMEM_49,                    0x00},
+	{WSA883X_EMEM_50,                    0x00},
+	{WSA883X_EMEM_51,                    0x00},
+	{WSA883X_EMEM_52,                    0x00},
+	{WSA883X_EMEM_53,                    0x00},
+	{WSA883X_EMEM_54,                    0x00},
+	{WSA883X_EMEM_55,                    0x00},
+	{WSA883X_EMEM_56,                    0x00},
+	{WSA883X_EMEM_57,                    0x00},
+	{WSA883X_EMEM_58,                    0x00},
+	{WSA883X_EMEM_59,                    0x00},
+	{WSA883X_EMEM_60,                    0x00},
+	{WSA883X_EMEM_61,                    0x00},
+	{WSA883X_EMEM_62,                    0x00},
+	{WSA883X_EMEM_63,                    0x00},
+};
+
+static bool wsa883x_readable_register(struct device *dev, unsigned int reg)
+{
+	if (reg <= WSA883X_BASE)
+		return 0;
+
+	return wsa883x_reg_access[WSA883X_REG(reg)] & RD_REG;
+}
+
+static bool wsa883x_writeable_register(struct device *dev, unsigned int reg)
+{
+	if (reg <= WSA883X_BASE)
+		return 0;
+
+	return wsa883x_reg_access[WSA883X_REG(reg)] & WR_REG;
+}
+
+static bool wsa883x_volatile_register(struct device *dev, unsigned int reg)
+{
+	if (reg <= WSA883X_BASE)
+		return 0;
+
+	return ((wsa883x_reg_access[WSA883X_REG(reg)] & RD_REG) &&
+		!(wsa883x_reg_access[WSA883X_REG(reg)] & WR_REG));
+}
+
+struct regmap_config wsa881x_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wsa883x_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wsa883x_defaults),
+	.max_register = WSA883X_MAX_REGISTER,
+	.volatile_reg = wsa883x_volatile_register,
+	.readable_reg = wsa883x_readable_register,
+	.writeable_reg = wsa883x_writeable_register,
+	.reg_format_endian = REGMAP_ENDIAN_NATIVE,
+	.val_format_endian = REGMAP_ENDIAN_NATIVE,
+	.can_multi_write = true,
+};
diff --git a/asoc/codecs/wsa883x/wsa883x-tables.c b/asoc/codecs/wsa883x/wsa883x-tables.c
new file mode 100644
index 0000000..16b0a88
--- /dev/null
+++ b/asoc/codecs/wsa883x/wsa883x-tables.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015, 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] = {
+	[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,
+	[WSA883X_REG(WSA883X_OP_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_IREF_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ISENS_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CLK_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TEST_CTL_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_BIAS_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DOUT_MSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_DOUT_LSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_VBAT_SNS)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ITRIM_CODE)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EN)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OVERRIDE1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OVERRIDE2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_VSENSE1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ISENSE1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ISENSE2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ISENSE_CAL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_MISC)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_4)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_5)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_6)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ADC_7)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_STATUS)] = RD_REG,
+	[WSA883X_REG(WSA883X_DAC_CTRL_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DAC_EN_DEBUG_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DAC_OPAMP_BIAS1_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DAC_OPAMP_BIAS2_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DAC_VCM_CTRL_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DAC_VOLTAGE_CTRL_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ATEST1_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_ATEST2_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_TOP_BIAS_REG4)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_CLIP_DET_REG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_DRV_LF_BLK_EN)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_SPKR_DRV_LF_EN)] = RD_WR_REG,
+	[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_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_PA_STATUS0)] = RD_REG,
+	[WSA883X_REG(WSA883X_PA_STATUS1)] = RD_REG,
+	[WSA883X_REG(WSA883X_PA_STATUS2)] = RD_REG,
+	[WSA883X_REG(WSA883X_EN_CTRL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CURRENT_LIMIT)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_IBIAS1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_IBIAS2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_IBIAS3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_LDO_PROG)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_STABILITY_CTRL1)] = RD_WR_REG,
+	[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_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_SPARE1)] = 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_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,
+	[WSA883X_REG(WSA883X_CHIP_ID3)] = RD_REG,
+	[WSA883X_REG(WSA883X_BUS_ID)] = RD_REG,
+	[WSA883X_REG(WSA883X_CDC_RST_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TOP_CLK_CFG)] = RD_WR_REG,
+	[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_PA_FSM_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PA_FSM_TIMER0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PA_FSM_TIMER1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PA_FSM_STA)] = RD_REG,
+	[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_TADC_VALUE_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TEMP_DETECT_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TEMP_MSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_TEMP_LSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_TEMP_CONFIG0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TEMP_CONFIG1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_VBAT_ADC_FLT_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_VBAT_DIN_MSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_VBAT_DIN_LSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_VBAT_DOUT)] = RD_REG,
+	[WSA883X_REG(WSA883X_SDM_PDM9_LSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_SDM_PDM9_MSB)] = RD_REG,
+	[WSA883X_REG(WSA883X_CDC_RX_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A1_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A1_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A2_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A2_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A3_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A3_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A4_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A4_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A5_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A5_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A6_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_A7_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_C_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_C_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_C_2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_C_3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_R1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_R2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_R3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_R4)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_R5)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_R6)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_DSM_R7)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_GAIN_PDM_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_GAIN_PDM_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CDC_SPK_GAIN_PDM_2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PDM_WD_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DEM_BYPASS_DATA0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DEM_BYPASS_DATA1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DEM_BYPASS_DATA2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DEM_BYPASS_DATA3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_LRA_PER_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_LRA_PER_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_DELTA_THETA_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_DELTA_THETA_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_DIRECT_AMP_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_DIRECT_AMP_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP0_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP0_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP1_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP1_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP2_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP2_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP3_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP3_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP4_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP4_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP5_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP5_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP6_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP6_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP7_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PTRN_AMP7_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_WAVG_PER_0_1)] = RD_WR_REG,
+	[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_DRE_CTL_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_DRE_CTL_1)] = 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,
+	[WSA883X_REG(WSA883X_CLSH_V_PA_MIN)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CLSH_OVRD_VAL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CLSH_HARD_MAX)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CLSH_SOFT_MAX)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_CLSH_SIG_DP)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TAGC_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TAGC_TIME)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TAGC_E2E_GAIN)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_TAGC_FORCE_VAL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_VAGC_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_VAGC_TIME)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_VAGC_ATTN_LVL_1_2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_VAGC_ATTN_LVL_3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_MODE)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_MASK0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_MASK1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_STATUS0)] = RD_REG,
+	[WSA883X_REG(WSA883X_INTR_STATUS1)] = RD_REG,
+	[WSA883X_REG(WSA883X_INTR_CLEAR0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_CLEAR1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_LEVEL0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_LEVEL1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_SET0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_SET1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_TEST0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_INTR_TEST1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_CTRL0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_CTRL1)] = RD_REG,
+	[WSA883X_REG(WSA883X_HDRIVE_CTL_GROUP1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PIN_CTL)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PIN_CTL_OE)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PIN_WDATA_IOPAD)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_PIN_STATUS)] = RD_REG,
+	[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_SAMPLE_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_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,
+	[WSA883X_REG(WSA883X_OTP_REG_3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_4)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_5)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_6)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_7)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_8)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_9)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_10)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_11)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_12)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_13)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_14)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_15)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_16)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_17)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_18)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_19)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_20)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_21)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_22)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_23)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_24)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_25)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_26)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_OTP_REG_27)] = RD_WR_REG,
+	[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_63)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_0)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_1)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_2)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_3)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_4)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_5)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_6)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_7)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_8)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_9)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_10)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_11)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_12)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_13)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_14)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_15)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_16)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_17)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_18)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_19)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_20)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_21)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_22)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_23)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_24)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_25)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_26)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_27)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_28)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_29)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_30)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_31)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_32)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_33)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_34)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_35)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_36)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_37)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_38)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_39)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_40)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_41)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_42)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_43)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_44)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_45)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_46)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_47)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_48)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_49)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_50)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_51)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_52)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_53)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_54)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_55)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_56)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_57)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_58)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_59)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_60)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_61)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_62)] = RD_WR_REG,
+	[WSA883X_REG(WSA883X_EMEM_63)] = RD_WR_REG,
+};
diff --git a/asoc/codecs/wsa883x/wsa883x-temp-sensor.c b/asoc/codecs/wsa883x/wsa883x-temp-sensor.c
new file mode 100644
index 0000000..a328c75
--- /dev/null
+++ b/asoc/codecs/wsa883x/wsa883x-temp-sensor.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2015, 2017-2019 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/thermal.h>
+#include <sound/soc.h>
+#include "wsa883x-temp-sensor.h"
+
+#define T1_TEMP -10
+#define T2_TEMP 150
+#define LOW_TEMP_THRESHOLD 5
+#define HIGH_TEMP_THRESHOLD 45
+#define TEMP_INVALID	0xFFFF
+#define WSA883X_TEMP_RETRY 3
+/*
+ * wsa883x_get_temp - get wsa temperature
+ * @thermal: thermal zone device
+ * @temp: temperature value
+ *
+ * Get the temperature of wsa883x.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int wsa883x_get_temp(struct thermal_zone_device *thermal,
+		     int *temp)
+{
+	struct wsa883x_tz_priv *pdata;
+	struct snd_soc_component *component;
+	struct wsa_temp_register reg;
+	int dmeas, d1, d2;
+	int ret = 0;
+	int temp_val;
+	int t1 = T1_TEMP;
+	int t2 = T2_TEMP;
+	u8 retry = WSA883X_TEMP_RETRY;
+
+	if (!thermal)
+		return -EINVAL;
+
+	if (thermal->devdata) {
+		pdata = thermal->devdata;
+		if (pdata->component) {
+			component = pdata->component;
+		} else {
+			pr_err("%s: codec is NULL\n", __func__);
+			return -EINVAL;
+		}
+	} else {
+		pr_err("%s: pdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (atomic_cmpxchg(&pdata->is_suspend_spk, 1, 0)) {
+		/*
+		 * get_temp query happens as part of POST_PM_SUSPEND
+		 * from thermal core. To avoid calls to slimbus
+		 * as part of this thermal query, return default temp
+		 * and reset the suspend flag.
+		 */
+		if (!pdata->t0_init) {
+			if (temp)
+				*temp = pdata->curr_temp;
+			return 0;
+		}
+	}
+
+temp_retry:
+	if (pdata->wsa_temp_reg_read) {
+		ret = pdata->wsa_temp_reg_read(component, &reg);
+		if (ret) {
+			pr_err("%s: temp read failed: %d, current temp: %d\n",
+				__func__, ret, pdata->curr_temp);
+			if (temp)
+				*temp = pdata->curr_temp;
+			return 0;
+		}
+	} else {
+		pr_err("%s: wsa_temp_reg_read is NULL\n", __func__);
+		return -EINVAL;
+	}
+	/*
+	 * Temperature register values are expected to be in the
+	 * following range.
+	 * d1_msb  = 68 - 92 and d1_lsb  = 0, 64, 128, 192
+	 * d2_msb  = 185 -218 and  d2_lsb  = 0, 64, 128, 192
+	 */
+	if ((reg.d1_msb < 68 || reg.d1_msb > 92) ||
+	    (!(reg.d1_lsb == 0 || reg.d1_lsb == 64 || reg.d1_lsb == 128 ||
+		reg.d1_lsb == 192)) ||
+	    (reg.d2_msb < 185 || reg.d2_msb > 218) ||
+	    (!(reg.d2_lsb == 0 || reg.d2_lsb == 64 || reg.d2_lsb == 128 ||
+		reg.d2_lsb == 192))) {
+		printk_ratelimited("%s: Temperature registers[%d %d %d %d] are out of range\n",
+				   __func__, reg.d1_msb, reg.d1_lsb, reg.d2_msb,
+				   reg.d2_lsb);
+	}
+	dmeas = ((reg.dmeas_msb << 0x8) | reg.dmeas_lsb) >> 0x6;
+	d1 = ((reg.d1_msb << 0x8) | reg.d1_lsb) >> 0x6;
+	d2 = ((reg.d2_msb << 0x8) | reg.d2_lsb) >> 0x6;
+
+	if (d1 == d2)
+		temp_val = TEMP_INVALID;
+	else
+		temp_val = t1 + (((dmeas - d1) * (t2 - t1))/(d2 - d1));
+
+	if (temp_val <= LOW_TEMP_THRESHOLD ||
+		temp_val >= HIGH_TEMP_THRESHOLD) {
+		pr_debug("%s: T0: %d is out of range[%d, %d]\n", __func__,
+			 temp_val, LOW_TEMP_THRESHOLD, HIGH_TEMP_THRESHOLD);
+		if (retry--) {
+			msleep(20);
+			goto temp_retry;
+		}
+	}
+	pdata->curr_temp = temp_val;
+
+	if (temp)
+		*temp = temp_val;
+	pr_debug("%s: t0 measured: %d dmeas = %d, d1 = %d, d2 = %d\n",
+		  __func__, temp_val, dmeas, d1, d2);
+	return ret;
+}
+EXPORT_SYMBOL(wsa883x_get_temp);
+
+static struct thermal_zone_device_ops wsa883x_thermal_ops = {
+	.get_temp = wsa883x_get_temp,
+};
+
+
+static int wsa883x_pm_notify(struct notifier_block *nb,
+				unsigned long mode, void *_unused)
+{
+	struct wsa883x_tz_priv *pdata =
+			container_of(nb, struct wsa883x_tz_priv, pm_nb);
+
+	switch (mode) {
+	case PM_SUSPEND_PREPARE:
+		atomic_set(&pdata->is_suspend_spk, 1);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+int wsa883x_init_thermal(struct wsa883x_tz_priv *tz_pdata)
+{
+	struct thermal_zone_device *tz_dev;
+
+	if (tz_pdata == NULL) {
+		pr_err("%s: thermal pdata is NULL\n", __func__);
+		return -EINVAL;
+	}
+	/* Register with the thermal zone */
+	tz_dev = thermal_zone_device_register(tz_pdata->name,
+				0, 0, tz_pdata,
+				&wsa883x_thermal_ops, NULL, 0, 0);
+	if (IS_ERR(tz_dev)) {
+		pr_err("%s: thermal device register failed.\n", __func__);
+		return -EINVAL;
+	}
+	tz_pdata->tz_dev = tz_dev;
+	tz_pdata->pm_nb.notifier_call = wsa883x_pm_notify;
+	register_pm_notifier(&tz_pdata->pm_nb);
+	atomic_set(&tz_pdata->is_suspend_spk, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL(wsa883x_init_thermal);
+
+void wsa883x_deinit_thermal(struct thermal_zone_device *tz_dev)
+{
+	struct wsa883x_tz_priv *pdata;
+
+	if (tz_dev && tz_dev->devdata) {
+		pdata = tz_dev->devdata;
+		if (pdata)
+			unregister_pm_notifier(&pdata->pm_nb);
+	}
+	if (tz_dev)
+		thermal_zone_device_unregister(tz_dev);
+}
+EXPORT_SYMBOL(wsa883x_deinit_thermal);
diff --git a/asoc/codecs/wsa883x/wsa883x-temp-sensor.h b/asoc/codecs/wsa883x/wsa883x-temp-sensor.h
new file mode 100644
index 0000000..5a8c387
--- /dev/null
+++ b/asoc/codecs/wsa883x/wsa883x-temp-sensor.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015, 2018-2019, The Linux Foundation. All rights reserved.
+ */
+#ifndef WSA883X_TEMP_SENSOR_H
+#define WSA883X_TEMP_SENSOR_H
+
+#include <linux/thermal.h>
+#include <sound/soc.h>
+
+struct wsa_temp_register {
+	u8 d1_msb;
+	u8 d1_lsb;
+	u8 d2_msb;
+	u8 d2_lsb;
+	u8 dmeas_msb;
+	u8 dmeas_lsb;
+};
+typedef int32_t (*wsa_temp_register_read)(struct snd_soc_component *component,
+					struct wsa_temp_register *wsa_temp_reg);
+struct wsa883x_tz_priv {
+	struct thermal_zone_device *tz_dev;
+	struct snd_soc_component *component;
+	struct wsa_temp_register *wsa_temp_reg;
+	char name[80];
+	wsa_temp_register_read wsa_temp_reg_read;
+	struct notifier_block pm_nb;
+	atomic_t is_suspend_spk;
+	int t0_init;
+	int curr_temp;
+};
+
+int wsa883x_get_temp(struct thermal_zone_device *tz_dev, int *temp);
+int wsa883x_init_thermal(struct wsa883x_tz_priv *tz_pdata);
+void wsa883x_deinit_thermal(struct thermal_zone_device *tz_dev);
+#endif
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c
new file mode 100644
index 0000000..7869a2b
--- /dev/null
+++ b/asoc/codecs/wsa883x/wsa883x.c
@@ -0,0 +1,1305 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/bitops.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/debugfs.h>
+#include <soc/soundwire.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <asoc/msm-cdc-pinctrl.h>
+#include "wsa883x.h"
+#include "internal.h"
+
+#define T1_TEMP -10
+#define T2_TEMP 150
+#define LOW_TEMP_THRESHOLD 5
+#define HIGH_TEMP_THRESHOLD 45
+#define TEMP_INVALID	0xFFFF
+#define WSA883X_TEMP_RETRY 3
+
+enum {
+	WSA_4OHMS =4,
+	WSA_8OHMS = 8,
+	WSA_16OHMS = 16,
+	WSA_32OHMS = 32,
+};
+
+struct wsa_temp_register {
+	u8 d1_msb;
+	u8 d1_lsb;
+	u8 d2_msb;
+	u8 d2_lsb;
+	u8 dmeas_msb;
+	u8 dmeas_lsb;
+};
+
+static int wsa883x_get_temperature(struct snd_soc_component *component,
+				   int *temp);
+enum {
+	WSA8830 = 0,
+	WSA8835,
+};
+
+enum {
+	WSA883X_IRQ_INT_SAF2WAR = 0,
+	WSA883X_IRQ_INT_WAR2SAF,
+	WSA883X_IRQ_INT_DISABLE,
+	WSA883X_IRQ_INT_OCP,
+	WSA883X_IRQ_INT_CLIP,
+	WSA883X_IRQ_INT_PDM_WD,
+	WSA883X_IRQ_INT_CLK_WD,
+	WSA883X_IRQ_INT_INTR_PIN,
+	WSA883X_IRQ_INT_UVLO,
+	WSA883X_IRQ_INT_PA_ON_ERR,
+};
+
+static const struct regmap_irq wsa883x_irqs[WSA883X_NUM_IRQS] = {
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_SAF2WAR, 0, 0x01),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_WAR2SAF, 0, 0x02),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_DISABLE, 0, 0x04),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_OCP, 0, 0x08),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_CLIP, 0, 0x10),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_PDM_WD, 0, 0x20),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_CLK_WD, 0, 0x40),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_INTR_PIN, 0, 0x80),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_UVLO, 1, 0x01),
+	REGMAP_IRQ_REG(WSA883X_IRQ_INT_PA_ON_ERR, 1, 0x02),
+};
+
+static struct regmap_irq_chip wsa883x_regmap_irq_chip = {
+	.name = "wsa883x",
+	.irqs = wsa883x_irqs,
+	.num_irqs = ARRAY_SIZE(wsa883x_irqs),
+	.num_regs = 2,
+	.status_base = WSA883X_INTR_STATUS0,
+	.mask_base = WSA883X_INTR_MASK0,
+	.type_base = WSA883X_INTR_LEVEL0,
+	.ack_base = WSA883X_INTR_CLEAR0,
+	.use_ack = 1,
+	.runtime_pm = false,
+	.irq_drv_data = NULL,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int get_parameters(char *buf, u32 *param1, int num_of_par)
+{
+	char *token;
+	int base, cnt;
+
+	token = strsep(&buf, " ");
+	for (cnt = 0; cnt < num_of_par; cnt++) {
+		if (token) {
+			if ((token[1] == 'x') || (token[1] == 'X'))
+				base = 16;
+			else
+				base = 10;
+
+			if (kstrtou32(token, base, &param1[cnt]) != 0)
+				return -EINVAL;
+
+			token = strsep(&buf, " ");
+		} else {
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static bool is_swr_slave_reg_readable(int reg)
+{
+	int ret = true;
+
+	if (((reg > 0x46) && (reg < 0x4A)) ||
+	    ((reg > 0x4A) && (reg < 0x50)) ||
+	    ((reg > 0x55) && (reg < 0xD0)) ||
+	    ((reg > 0xD0) && (reg < 0xE0)) ||
+	    ((reg > 0xE0) && (reg < 0xF0)) ||
+	    ((reg > 0xF0) && (reg < 0x100)) ||
+	    ((reg > 0x105) && (reg < 0x120)) ||
+	    ((reg > 0x205) && (reg < 0x220)) ||
+	    ((reg > 0x305) && (reg < 0x320)) ||
+	    ((reg > 0x405) && (reg < 0x420)) ||
+	    ((reg > 0x128) && (reg < 0x130)) ||
+	    ((reg > 0x228) && (reg < 0x230)) ||
+	    ((reg > 0x328) && (reg < 0x330)) ||
+	    ((reg > 0x428) && (reg < 0x430)) ||
+	    ((reg > 0x138) && (reg < 0x205)) ||
+	    ((reg > 0x238) && (reg < 0x305)) ||
+	    ((reg > 0x338) && (reg < 0x405)) ||
+	    ((reg > 0x405) && (reg < 0xF00)) ||
+	    ((reg > 0xF05) && (reg < 0xF20)) ||
+	    ((reg > 0xF25) && (reg < 0xF30)) ||
+	    ((reg > 0xF35) && (reg < 0x2000)))
+		ret = false;
+
+	return ret;
+}
+
+static ssize_t swr_slave_reg_show(struct swr_device *pdev, char __user *ubuf,
+					size_t count, loff_t *ppos)
+{
+	int i, reg_val, len;
+	ssize_t total = 0;
+	char tmp_buf[SWR_SLV_MAX_BUF_LEN];
+
+	if (!ubuf || !ppos)
+		return 0;
+
+	for (i = (((int) *ppos/BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR);
+		i <= SWR_SLV_MAX_REG_ADDR; i++) {
+		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,
+			       (reg_val & 0xFF));
+		if ((total + len) >= count - 1)
+			break;
+		if (copy_to_user((ubuf + total), tmp_buf, len)) {
+			pr_err("%s: fail to copy reg dump\n", __func__);
+			total = -EFAULT;
+			goto copy_err;
+		}
+		total += len;
+		*ppos += len;
+	}
+
+copy_err:
+	*ppos = SWR_SLV_MAX_REG_ADDR * BYTES_PER_LINE;
+	return total;
+}
+
+static ssize_t codec_debug_dump(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	struct swr_device *pdev;
+
+	if (!count || !file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	if (*ppos < 0)
+		return -EINVAL;
+
+	return swr_slave_reg_show(pdev, ubuf, count, ppos);
+}
+
+static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char lbuf[SWR_SLV_RD_BUF_LEN];
+	struct swr_device *pdev = NULL;
+	struct wsa883x_priv *wsa883x = NULL;
+
+	if (!count || !file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	wsa883x = swr_get_dev_data(pdev);
+	if (!wsa883x)
+		return -EINVAL;
+
+	if (*ppos < 0)
+		return -EINVAL;
+
+	snprintf(lbuf, sizeof(lbuf), "0x%x\n",
+			(wsa883x->read_data & 0xFF));
+
+	return simple_read_from_buffer(ubuf, count, ppos, lbuf,
+					       strnlen(lbuf, 7));
+}
+
+static ssize_t codec_debug_peek_write(struct file *file,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char lbuf[SWR_SLV_WR_BUF_LEN];
+	int rc = 0;
+	u32 param[5];
+	struct swr_device *pdev = NULL;
+	struct wsa883x_priv *wsa883x = NULL;
+
+	if (!cnt || !file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	wsa883x = swr_get_dev_data(pdev);
+	if (!wsa883x)
+		return -EINVAL;
+
+	if (*ppos < 0)
+		return -EINVAL;
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+	rc = get_parameters(lbuf, param, 1);
+	if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0)))
+		return -EINVAL;
+	swr_read(pdev, pdev->dev_num, param[0], &wsa883x->read_data, 1);
+	if (rc == 0)
+		rc = cnt;
+	else
+		pr_err("%s: rc = %d\n", __func__, rc);
+
+	return rc;
+}
+
+static ssize_t codec_debug_write(struct file *file,
+	const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+	char lbuf[SWR_SLV_WR_BUF_LEN];
+	int rc = 0;
+	u32 param[5];
+	struct swr_device *pdev;
+
+	if (!file || !ppos || !ubuf)
+		return -EINVAL;
+
+	pdev = file->private_data;
+	if (!pdev)
+		return -EINVAL;
+
+	if (cnt > sizeof(lbuf) - 1)
+		return -EINVAL;
+
+	rc = copy_from_user(lbuf, ubuf, cnt);
+	if (rc)
+		return -EFAULT;
+
+	lbuf[cnt] = '\0';
+	rc = get_parameters(lbuf, param, 2);
+	if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) &&
+		(param[1] <= 0xFF) && (rc == 0)))
+		return -EINVAL;
+	swr_write(pdev, pdev->dev_num, param[0], &param[1]);
+	if (rc == 0)
+		rc = cnt;
+	else
+		pr_err("%s: rc = %d\n", __func__, rc);
+
+	return rc;
+}
+
+static const struct file_operations codec_debug_write_ops = {
+	.open = codec_debug_open,
+	.write = codec_debug_write,
+};
+
+static const struct file_operations codec_debug_read_ops = {
+	.open = codec_debug_open,
+	.read = codec_debug_read,
+	.write = codec_debug_peek_write,
+};
+
+static const struct file_operations codec_debug_dump_ops = {
+	.open = codec_debug_open,
+	.read = codec_debug_dump,
+};
+#endif
+
+static irqreturn_t wsa883x_saf2war_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_war2saf_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_otp_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_ocp_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_clip_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_pdm_wd_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_clk_wd_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_ext_int_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_uvlo_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wsa883x_pa_on_err_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
+static const char * const wsa_dev_mode_text[] = {
+	"speaker", "receiver", "ultrasound"
+};
+
+static const struct soc_enum wsa_dev_mode_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_dev_mode_text), wsa_dev_mode_text);
+
+static int wsa_dev_mode_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->dev_mode;
+
+	dev_dbg(component->dev, "%s: mode = 0x%x\n", __func__,
+			wsa883x->dev_mode);
+
+	return 0;
+}
+
+static int wsa_dev_mode_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	wsa883x->dev_mode =  ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static const char * const wsa_pa_gain_text[] = {
+	"G_18_DB", "G_16P5_DB", "G_15_DB", "G_13P5_DB", "G_12_DB", "G_10P5_DB",
+	"G_9_DB", "G_7P5_DB", "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB",
+	"G_0_DB"
+};
+
+static const struct soc_enum wsa_pa_gain_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_pa_gain_text), wsa_pa_gain_text);
+
+static int wsa_pa_gain_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->pa_gain;
+
+	dev_dbg(component->dev, "%s: PA gain = 0x%x\n", __func__,
+			wsa883x->pa_gain);
+
+	return 0;
+}
+
+static int wsa_pa_gain_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	wsa883x->pa_gain =  ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static int wsa883x_get_mute(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->pa_mute;
+
+	return 0;
+}
+
+static int wsa883x_set_mute(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: mute current %d, new %d\n",
+		__func__, wsa883x->pa_mute, value);
+
+	wsa883x->pa_mute = value;
+
+	return 0;
+}
+
+static int wsa_get_temp(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	int temp = 0;
+
+	wsa883x_get_temperature(component, &temp);
+	ucontrol->value.integer.value[0] = temp;
+
+	return 0;
+}
+
+static ssize_t wsa883x_codec_version_read(struct snd_info_entry *entry,
+			       void *file_private_data, struct file *file,
+			       char __user *buf, size_t count, loff_t pos)
+{
+	struct wsa883x_priv *wsa883x;
+	char buffer[WSA883X_VERSION_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;
+	}
+
+	len = snprintf(buffer, sizeof(buffer), "WSA883X-SOUNDWIRE_1_0\n");
+
+	return simple_read_from_buffer(buf, count, &pos, buffer, len);
+}
+
+static struct snd_info_entry_ops wsa883x_codec_info_ops = {
+	.read = wsa883x_codec_version_read,
+};
+
+/*
+ * wsa883x_codec_info_create_codec_entry - creates wsa883x module
+ * @codec_root: The parent directory
+ * @component: Codec instance
+ *
+ * Creates wsa883x module and version entry under the given
+ * parent directory.
+ *
+ * Return: 0 on success or negative error code on failure.
+ */
+int wsa883x_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
+					  struct snd_soc_component *component)
+{
+	struct snd_info_entry *version_entry;
+	struct wsa883x_priv *wsa883x;
+	struct snd_soc_card *card;
+	char name[80];
+
+	if (!codec_root || !component)
+		return -EINVAL;
+
+	wsa883x = snd_soc_component_get_drvdata(component);
+	card = component->card;
+	snprintf(name, sizeof(name), "%s.%x", "wsa883x",
+		 (u32)wsa883x->swr_slave->addr);
+
+	wsa883x->entry = snd_info_create_subdir(codec_root->module,
+						(const char *)name,
+						codec_root);
+	if (!wsa883x->entry) {
+		dev_dbg(component->dev, "%s: failed to create wsa883x entry\n",
+			__func__);
+		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__);
+		return -ENOMEM;
+	}
+
+	version_entry->private_data = wsa883x;
+	version_entry->size = WSA883X_VERSION_ENTRY_SIZE;
+	version_entry->content = SNDRV_INFO_CONTENT_DATA;
+	version_entry->c.ops = &wsa883x_codec_info_ops;
+
+	if (snd_info_register(version_entry) < 0) {
+		snd_info_free_entry(version_entry);
+		return -ENOMEM;
+	}
+	wsa883x->version_entry = version_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)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->comp_enable;
+	return 0;
+}
+
+static int wsa883x_set_compander(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: Compander enable current %d, new %d\n",
+		 __func__, wsa883x->comp_enable, value);
+	wsa883x->comp_enable = value;
+	return 0;
+}
+
+static int wsa883x_get_visense(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->visense_enable;
+	return 0;
+}
+
+static int wsa883x_set_visense(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: VIsense enable current %d, new %d\n",
+		 __func__, wsa883x->visense_enable, value);
+	wsa883x->visense_enable = value;
+	return 0;
+}
+
+static int wsa883x_get_ext_vdd_spk(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wsa883x->ext_vdd_spk;
+
+	return 0;
+}
+
+static int wsa883x_put_ext_vdd_spk(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	int value = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s: Ext VDD SPK enable current %d, new %d\n",
+		 __func__, wsa883x->ext_vdd_spk, value);
+	wsa883x->ext_vdd_spk = value;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new wsa883x_snd_controls[] = {
+	SOC_ENUM_EXT("WSA PA Gain", wsa_pa_gain_enum,
+		     wsa_pa_gain_get, wsa_pa_gain_put),
+
+	SOC_SINGLE_EXT("WSA PA Mute", SND_SOC_NOPM, 0, 1, 0,
+		wsa883x_get_mute, wsa883x_set_mute),
+
+	SOC_SINGLE_EXT("WSA Temp", SND_SOC_NOPM, 0, 1, 0,
+			wsa_get_temp, NULL),
+
+	SOC_ENUM_EXT("WSA MODE", wsa_dev_mode_enum,
+		     wsa_dev_mode_get, wsa_dev_mode_put),
+
+	SOC_SINGLE_EXT("COMP Switch", SND_SOC_NOPM, 0, 1, 0,
+		wsa883x_get_compander, wsa883x_set_compander),
+
+	SOC_SINGLE_EXT("VISENSE Switch", SND_SOC_NOPM, 0, 1, 0,
+		wsa883x_get_visense, wsa883x_set_visense),
+
+	SOC_SINGLE_EXT("External VDD_SPK", SND_SOC_NOPM, 0, 1, 0,
+		wsa883x_get_ext_vdd_spk, wsa883x_put_ext_vdd_spk),
+};
+
+static const struct snd_kcontrol_new swr_dac_port[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static int wsa883x_set_port(struct snd_soc_component *component, int port_idx,
+			u8 *port_id, u8 *num_ch, u8 *ch_mask, u32 *ch_rate,
+			u8 *port_type)
+{
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	*port_id = wsa883x->port[port_idx].port_id;
+	*num_ch = wsa883x->port[port_idx].num_ch;
+	*ch_mask = wsa883x->port[port_idx].ch_mask;
+	*ch_rate = wsa883x->port[port_idx].ch_rate;
+	*port_type = wsa883x->port[port_idx].port_type;
+	return 0;
+}
+
+static int wsa883x_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	u8 port_id[WSA883X_MAX_SWR_PORTS];
+	u8 num_ch[WSA883X_MAX_SWR_PORTS];
+	u8 ch_mask[WSA883X_MAX_SWR_PORTS];
+	u32 ch_rate[WSA883X_MAX_SWR_PORTS];
+	u8 port_type[WSA883X_MAX_SWR_PORTS];
+	u8 num_port = 0;
+
+	dev_dbg(component->dev, "%s: event %d name %s\n", __func__,
+		event, w->name);
+	if (wsa883x == NULL)
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wsa883x_set_port(component, SWR_DAC_PORT,
+				&port_id[num_port], &num_ch[num_port],
+				&ch_mask[num_port], &ch_rate[num_port],
+				&port_type[num_port]);
+		++num_port;
+
+		if (wsa883x->comp_enable) {
+			wsa883x_set_port(component, SWR_COMP_PORT,
+					&port_id[num_port], &num_ch[num_port],
+					&ch_mask[num_port], &ch_rate[num_port],
+					&port_type[num_port]);
+			++num_port;
+		}
+		if (wsa883x->visense_enable) {
+			wsa883x_set_port(component, SWR_VISENSE_PORT,
+					&port_id[num_port], &num_ch[num_port],
+					&ch_mask[num_port], &ch_rate[num_port],
+					&port_type[num_port]);
+			++num_port;
+		}
+		swr_connect_port(wsa883x->swr_slave, &port_id[0], num_port,
+				&ch_mask[0], &ch_rate[0], &num_ch[0],
+					&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],
+				&port_type[num_port]);
+		++num_port;
+
+		if (wsa883x->comp_enable) {
+			wsa883x_set_port(component, SWR_COMP_PORT,
+					&port_id[num_port], &num_ch[num_port],
+					&ch_mask[num_port], &ch_rate[num_port],
+					&port_type[num_port]);
+			++num_port;
+		}
+		if (wsa883x->visense_enable) {
+			wsa883x_set_port(component, SWR_VISENSE_PORT,
+					&port_id[num_port], &num_ch[num_port],
+					&ch_mask[num_port], &ch_rate[num_port],
+					&port_type[num_port]);
+			++num_port;
+		}
+		swr_disconnect_port(wsa883x->swr_slave, &port_id[0], num_port,
+				&ch_mask[0], &port_type[0]);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	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:
+		/* Force remove group */
+		swr_remove_from_group(wsa883x->swr_slave,
+				      wsa883x->swr_slave->dev_num);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* TODO Unvote for Global PA */
+		break;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget wsa883x_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("IN"),
+	SND_SOC_DAPM_MIXER_E("SWR DAC_Port", SND_SOC_NOPM, 0, 0, swr_dac_port,
+		ARRAY_SIZE(swr_dac_port), wsa883x_enable_swr_dac_port,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SPK("SPKR", wsa883x_spkr_event),
+};
+
+static const struct snd_soc_dapm_route wsa883x_audio_map[] = {
+	{"SWR DAC_Port", "Switch", "IN"},
+	{"SPKR", NULL, "SWR DAC_Port"},
+};
+
+int wsa883x_set_channel_map(struct snd_soc_component *component, u8 *port,
+			    u8 num_port, unsigned int *ch_mask,
+			    unsigned int *ch_rate, u8 *port_type)
+{
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	int i;
+
+	if (!port || !ch_mask || !ch_rate ||
+		(num_port > WSA883X_MAX_SWR_PORTS)) {
+		dev_err(component->dev,
+			"%s: Invalid port=%pK, ch_mask=%pK, ch_rate=%pK\n",
+			__func__, port, ch_mask, ch_rate);
+		return -EINVAL;
+	}
+	for (i = 0; i < num_port; i++) {
+		wsa883x->port[i].port_id = port[i];
+		wsa883x->port[i].ch_mask = ch_mask[i];
+		wsa883x->port[i].ch_rate = ch_rate[i];
+		wsa883x->port[i].num_ch = __sw_hweight8(ch_mask[i]);
+		if (port_type)
+			wsa883x->port[i].port_type = port_type[i];
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(wsa883x_set_channel_map);
+
+static void wsa883x_codec_init(struct snd_soc_component *component)
+{
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	if (!wsa883x)
+		return;
+
+}
+
+static int32_t wsa883x_temp_reg_read(struct snd_soc_component *component,
+				     struct wsa_temp_register *wsa_temp_reg)
+{
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	if (!wsa883x) {
+		dev_err(component->dev, "%s: wsa883x is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&wsa883x->res_lock);
+
+	/* TODO Vote for global PA */
+	snd_soc_component_update_bits(component, WSA883X_TADC_VALUE_CTL,
+				0x01, 0x00);
+	wsa_temp_reg->dmeas_msb = snd_soc_component_read32(
+					component, WSA883X_TEMP_MSB);
+	wsa_temp_reg->dmeas_lsb = snd_soc_component_read32(
+					component, WSA883X_TEMP_LSB);
+	snd_soc_component_update_bits(component, WSA883X_TADC_VALUE_CTL,
+					0x01, 0x01);
+	wsa_temp_reg->d1_msb = snd_soc_component_read32(
+					component, WSA883X_OTP_REG_1);
+	wsa_temp_reg->d1_lsb = snd_soc_component_read32(
+					component, WSA883X_OTP_REG_2);
+	wsa_temp_reg->d2_msb = snd_soc_component_read32(
+					component, WSA883X_OTP_REG_3);
+	wsa_temp_reg->d2_lsb = snd_soc_component_read32(
+					component, WSA883X_OTP_REG_4);
+
+	/* TODO Unvote for global PA */
+	mutex_unlock(&wsa883x->res_lock);
+
+	return 0;
+}
+
+static int wsa883x_get_temperature(struct snd_soc_component *component,
+				   int *temp)
+{
+	struct snd_soc_component *component;
+	struct wsa_temp_register reg;
+	int dmeas, d1, d2;
+	int ret = 0;
+	int temp_val = 0;
+	int t1 = T1_TEMP;
+	int t2 = T2_TEMP;
+	u8 retry = WSA883X_TEMP_RETRY;
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	if (!wsa883x)
+		return -EINVAL;
+
+	do {
+		ret = wsa883x_temp_reg_read(component, &reg)
+		if (ret) {
+			pr_err("%s: temp read failed: %d, current temp: %d\n",
+				__func__, ret, wsa883x->curr_temp);
+			if (temp)
+				*temp = wsa883x->curr_temp;
+			return 0;
+		}
+		/*
+		 * Temperature register values are expected to be in the
+		 * following range.
+		 * d1_msb  = 68 - 92 and d1_lsb  = 0, 64, 128, 192
+		 * d2_msb  = 185 -218 and  d2_lsb  = 0, 64, 128, 192
+		 */
+		if ((reg.d1_msb < 68 || reg.d1_msb > 92) ||
+		    (!(reg.d1_lsb == 0 || reg.d1_lsb == 64 || reg.d1_lsb == 128 ||
+			reg.d1_lsb == 192)) ||
+		    (reg.d2_msb < 185 || reg.d2_msb > 218) ||
+		    (!(reg.d2_lsb == 0 || reg.d2_lsb == 64 || reg.d2_lsb == 128 ||
+			reg.d2_lsb == 192))) {
+			printk_ratelimited("%s: Temperature registers[%d %d %d %d] are out of range\n",
+					   __func__, reg.d1_msb, reg.d1_lsb, reg.d2_msb,
+					   reg.d2_lsb);
+		}
+		dmeas = ((reg.dmeas_msb << 0x8) | reg.dmeas_lsb) >> 0x6;
+		d1 = ((reg.d1_msb << 0x8) | reg.d1_lsb) >> 0x6;
+		d2 = ((reg.d2_msb << 0x8) | reg.d2_lsb) >> 0x6;
+
+		if (d1 == d2)
+			temp_val = TEMP_INVALID;
+		else
+			temp_val = t1 + (((dmeas - d1) * (t2 - t1))/(d2 - d1));
+
+		if (temp_val <= LOW_TEMP_THRESHOLD ||
+			temp_val >= HIGH_TEMP_THRESHOLD) {
+			pr_debug("%s: T0: %d is out of range[%d, %d]\n", __func__,
+				 temp_val, LOW_TEMP_THRESHOLD, HIGH_TEMP_THRESHOLD);
+			if (retry--)
+				msleep(10);
+		} else {
+			break;
+		}
+	} while (retry);
+
+	wsa883x->curr_temp = temp_val;
+	if (temp)
+		*temp = temp_val;
+	pr_debug("%s: t0 measured: %d dmeas = %d, d1 = %d, d2 = %d\n",
+		  __func__, temp_val, dmeas, d1, d2);
+
+	return ret;
+}
+
+static int wsa883x_codec_probe(struct snd_soc_component *component)
+{
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+	struct swr_device *dev;
+
+	if (!wsa883x)
+		return -EINVAL;
+	snd_soc_component_init_regmap(component, wsa883x->regmap);
+
+	dev = wsa883x->swr_slave;
+	wsa883x->component = component;
+	wsa883x_codec_init(component);
+	wsa883x->global_pa_cnt = 0;
+
+	return 0;
+}
+
+static void wsa883x_codec_remove(struct snd_soc_component *component)
+{
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
+
+	if (!wsa883x)
+		return;
+
+	snd_soc_component_exit_regmap(component);
+
+	return;
+}
+
+static const struct snd_soc_component_driver soc_codec_dev_wsa883x = {
+	.name = DRV_NAME,
+	.probe = wsa883x_codec_probe,
+	.remove = wsa883x_codec_remove,
+	.controls = wsa883x_snd_controls,
+	.num_controls = ARRAY_SIZE(wsa883x_snd_controls),
+	.dapm_widgets = wsa883x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wsa883x_dapm_widgets),
+	.dapm_routes = wsa883x_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(wsa883x_audio_map),
+};
+
+static int wsa883x_gpio_ctrl(struct wsa883x_priv *wsa883x, bool enable)
+{
+	int ret = 0;
+
+	if (enable)
+		ret = msm_cdc_pinctrl_select_active_state(
+						wsa883x->wsa_rst_np);
+	else
+		ret = msm_cdc_pinctrl_select_sleep_state(
+						wsa883x->wsa_rst_np);
+	if (ret != 0)
+		dev_err(wsa883x->dev,
+			"%s: Failed to turn state %d; ret=%d\n",
+			__func__, enable, ret);
+
+	return ret;
+}
+
+static int wsa883x_swr_probe(struct swr_device *pdev)
+{
+	int ret = 0;
+	struct wsa883x_priv *wsa883x;
+	u8 devnum = 0;
+	bool pin_state_current = false;
+
+	wsa883x = devm_kzalloc(&pdev->dev, sizeof(struct wsa883x_priv),
+			    GFP_KERNEL);
+	if (!wsa883x)
+		return -ENOMEM;
+
+	wsa883x->wsa_rst_np = of_parse_phandle(pdev->dev.of_node,
+					     "qcom,spkr-sd-n-node", 0);
+	if (!wsa883x->wsa_rst_np) {
+		dev_dbg(&pdev->dev, "%s: pinctrl not defined\n", __func__);
+		goto err;
+	}
+	swr_set_dev_data(pdev, wsa883x);
+	wsa883x->swr_slave = pdev;
+	pin_state_current = msm_cdc_pinctrl_get_state(wsa883x->wsa_rst_np);
+	wsa883x_gpio_ctrl(wsa883x, true);
+	/*
+	 * Add 5msec delay to provide sufficient time for
+	 * soundwire auto enumeration of slave devices as
+	 * as per HW requirement.
+	 */
+	usleep_range(5000, 5010);
+	ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+			"%s get devnum %d for dev addr %lx failed\n",
+			__func__, devnum, pdev->addr);
+		goto dev_err;
+	}
+	pdev->dev_num = devnum;
+
+	wsa883x->regmap = devm_regmap_init_swr(pdev,
+					       &wsa883x_regmap_config);
+	if (IS_ERR(wsa883x->regmap)) {
+		ret = PTR_ERR(wsa883x->regmap);
+		dev_err(&pdev->dev, "%s: regmap_init failed %d\n",
+			__func__, ret);
+		goto dev_err;
+	}
+
+	/* Set all interrupts as edge triggered */
+	for (i = 0; i < wsa883x_regmap_irq_chip.num_regs; i++)
+		regmap_write(wsa883x->regmap, (WSA883X_INTR_LEVEL0 + i), 0);
+
+	wsa883x_regmap_irq_chip.irq_drv_data = wsa883x;
+	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;
+	ret = wcd_irq_init(&wsa883x->irq_info, &wsa883x->virq);
+
+	if (ret) {
+		dev_err(wsa883x->dev, "%s: IRQ init failed: %d\n",
+			__func__, ret);
+		goto dev_err;
+	}
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR,
+			"WSA SAF2WAR", wsa883x_saf2war_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF,
+			"WSA WAR2SAF", wsa883x_war2saf_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE,
+			"WSA OTP", wsa883x_otp_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP,
+			"WSA OCP", wsa883x_ocp_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLIP,
+			"WSA CLIP", wsa883x_clip_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD,
+			"WSA PDM WD", wsa883x_pdm_wd_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLK_WD,
+			"WSA CLK WD", wsa883x_clk_wd_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN,
+			"WSA EXT INT", wsa883x_ext_int_handle_irq, NULL);
+
+	/* Under Voltage Lock out (UVLO) interrupt handle */
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO,
+			"WSA UVLO", wsa883x_uvlo_handle_irq, NULL);
+
+	wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR,
+			"WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL);
+
+	ret = snd_soc_register_component(&pdev->dev, &soc_codec_dev_wsa883x,
+				     NULL, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Codec registration failed\n",
+			__func__);
+		goto err_irq;
+	}
+	mutex_init(&wsa883x->res_lock);
+
+#ifdef CONFIG_DEBUG_FS
+	if (!wsa883x->debugfs_dent) {
+		wsa883x->debugfs_dent = debugfs_create_dir(
+					dev_name(&pdev->dev), 0);
+		if (!IS_ERR(wsa883x->debugfs_dent)) {
+			wsa883x->debugfs_peek =
+				debugfs_create_file("swrslave_peek",
+				S_IFREG | 0444,
+				wsa883x->debugfs_dent,
+				(void *) pdev,
+				&codec_debug_read_ops);
+
+		wsa883x->debugfs_poke =
+				debugfs_create_file("swrslave_poke",
+				S_IFREG | 0444,
+				wsa883x->debugfs_dent,
+				(void *) pdev,
+				&codec_debug_write_ops);
+
+		wsa883x->debugfs_reg_dump =
+				debugfs_create_file(
+				"swrslave_reg_dump",
+				S_IFREG | 0444,
+				wsa883x->debugfs_dent,
+				(void *) pdev,
+				&codec_debug_dump_ops);
+	}
+}
+#endif
+
+	return 0;
+
+err_irq:
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLIP, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLK_WD, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR, NULL);
+	wcd_irq_exit(&wsa883x->irq_info, wsa883x->virq);
+dev_err:
+	if (pin_state_current == false)
+		wsa883x_gpio_ctrl(wsa883x, false);
+	swr_remove_device(pdev);
+err:
+	return ret;
+}
+
+static int wsa883x_swr_remove(struct swr_device *pdev)
+{
+	struct wsa883x_priv *wsa883x;
+
+	wsa883x = swr_get_dev_data(pdev);
+	if (!wsa883x) {
+		dev_err(&pdev->dev, "%s: wsa883x is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLIP, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_CLK_WD, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO, NULL);
+	wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR, NULL);
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove_recursive(wsa883x->debugfs_dent);
+	wsa883x->debugfs_dent = NULL;
+#endif
+	mutex_destroy(&wsa883x->res_lock);
+	snd_soc_unregister_component(&pdev->dev);
+	swr_set_dev_data(pdev, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int wsa883x_swr_suspend(struct device *dev)
+{
+	dev_dbg(dev, "%s: system suspend\n", __func__);
+	return 0;
+}
+
+static int wsa883x_swr_resume(struct device *dev)
+{
+	struct wsa883x_priv *wsa883x = swr_get_dev_data(to_swr_device(dev));
+
+	if (!wsa883x) {
+		dev_err(dev, "%s: wsa883x private data is NULL\n", __func__);
+		return -EINVAL;
+	}
+	dev_dbg(dev, "%s: system resume\n", __func__);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops wsa883x_swr_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(wsa883x_swr_suspend, wsa883x_swr_resume)
+};
+
+static const struct swr_device_id wsa883x_swr_id[] = {
+	{"wsa883x", 0},
+	{}
+};
+
+static const struct of_device_id wsa883x_swr_dt_match[] = {
+	{
+		.compatible = "qcom,wsa883x",
+	},
+	{}
+};
+
+static struct swr_driver wsa883x_swr_driver = {
+	.driver = {
+		.name = "wsa883x",
+		.owner = THIS_MODULE,
+		.pm = &wsa883x_swr_pm_ops,
+		.of_match_table = wsa883x_swr_dt_match,
+	},
+	.probe = wsa883x_swr_probe,
+	.remove = wsa883x_swr_remove,
+	.id_table = wsa883x_swr_id,
+};
+
+static int __init wsa883x_swr_init(void)
+{
+	return swr_driver_register(&wsa883x_swr_driver);
+}
+
+static void __exit wsa883x_swr_exit(void)
+{
+	swr_driver_unregister(&wsa883x_swr_driver);
+}
+
+module_init(wsa883x_swr_init);
+module_exit(wsa883x_swr_exit);
+
+MODULE_DESCRIPTION("WSA883x codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/asoc/codecs/wsa883x/wsa883x.h b/asoc/codecs/wsa883x/wsa883x.h
new file mode 100644
index 0000000..e080134
--- /dev/null
+++ b/asoc/codecs/wsa883x/wsa883x.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _WSA883X_H
+#define _WSA883X_H
+
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/info.h>
+#include "wsa883x-registers.h"
+
+#define WSA883X_MAX_SWR_PORTS   4
+
+#if IS_ENABLED(CONFIG_SND_SOC_WSA883X)
+int wsa883x_set_channel_map(struct snd_soc_component *component,
+				   u8 *port, u8 num_port, unsigned int *ch_mask,
+				   unsigned int *ch_rate, u8 *port_type);
+
+
+int wsa883x_codec_info_create_codec_entry(
+					struct snd_info_entry *codec_root,
+					struct snd_soc_component *component);
+#else
+static int wsa883x_set_channel_map(struct snd_soc_component *component,
+				   u8 *port, u8 num_port, unsigned int *ch_mask,
+				   unsigned int *ch_rate, u8 *port_type)
+{
+	return 0;
+}
+
+static int wsa883x_codec_info_create_codec_entry(
+					struct snd_info_entry *codec_root,
+					struct snd_soc_component *component)
+{
+	return 0;
+}
+
+#endif
+
+#endif /* _WSA883X_H */
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index 4347bec..4560299 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -408,8 +408,8 @@
 		gain_list[0] = volume_l;
 		gain_list[1] = volume_r;
 		gain_list[2] = volume_l;
-		num_channels = 3;
-		use_default = true;
+		if (use_default)
+			num_channels = 3;
 		rc = q6asm_set_multich_gain(prtd->audio_client, num_channels,
 					gain_list, chmap, use_default);
 	}
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 1b15444..e9d354b 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -3461,15 +3461,6 @@
 		.get = msm_dai_q6_afe_enc_cfg_get,
 		.put = msm_dai_q6_afe_enc_cfg_put,
 	},
-	{
-		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
-			   SNDRV_CTL_ELEM_ACCESS_INACTIVE),
-		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
-		.name = "SLIM_7_RX APTX_AD Enc Cfg",
-		.info = msm_dai_q6_afe_enc_cfg_info,
-		.get = msm_dai_q6_afe_enc_cfg_get,
-		.put = msm_dai_q6_afe_enc_cfg_put,
-	},
 	SOC_ENUM_EXT("AFE Input Channels", afe_chs_enum[0],
 		     msm_dai_q6_afe_input_channel_get,
 		     msm_dai_q6_afe_input_channel_put),
@@ -3482,7 +3473,16 @@
 		       msm_dai_q6_afe_scrambler_mode_put),
 	SOC_ENUM_EXT("TWS Channel Mode", tws_chs_mode_enum[0],
 		       msm_dai_q6_tws_channel_mode_get,
-		       msm_dai_q6_tws_channel_mode_put)
+		       msm_dai_q6_tws_channel_mode_put),
+	{
+		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			   SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+		.name = "SLIM_7_RX APTX_AD Enc Cfg",
+		.info = msm_dai_q6_afe_enc_cfg_info,
+		.get = msm_dai_q6_afe_enc_cfg_get,
+		.put = msm_dai_q6_afe_enc_cfg_put,
+	}
 };
 
 static int  msm_dai_q6_afe_dec_cfg_info(struct snd_kcontrol *kcontrol,
@@ -3895,7 +3895,7 @@
 				 dai));
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				 snd_ctl_new1(&afe_enc_config_controls[5],
-				 dai));
+				 dai_data));
 		rc = snd_ctl_add(dai->component->card->snd_card,
 				snd_ctl_new1(&avd_drift_config_controls[2],
 					dai));
@@ -5014,6 +5014,9 @@
 	SOC_ENUM_EXT("QUIN MI2S RX Format", mi2s_config_enum[0],
 		     msm_dai_q6_mi2s_format_get,
 		     msm_dai_q6_mi2s_format_put),
+	SOC_ENUM_EXT("SENARY MI2S RX Format", mi2s_config_enum[0],
+		     msm_dai_q6_mi2s_format_get,
+		     msm_dai_q6_mi2s_format_put),
 	SOC_ENUM_EXT("PRI MI2S TX Format", mi2s_config_enum[0],
 		     msm_dai_q6_mi2s_format_get,
 		     msm_dai_q6_mi2s_format_put),
@@ -5068,6 +5071,8 @@
 			ctrl = &mi2s_config_controls[3];
 		if (dai->id == MSM_QUIN_MI2S)
 			ctrl = &mi2s_config_controls[4];
+		if (dai->id == MSM_SENARY_MI2S)
+			ctrl = &mi2s_config_controls[5];
 	}
 
 	if (ctrl) {
@@ -5084,19 +5089,19 @@
 	ctrl = NULL;
 	if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.i2s.channel_mode) {
 		if (dai->id == MSM_PRIM_MI2S)
-			ctrl = &mi2s_config_controls[5];
-		if (dai->id == MSM_SEC_MI2S)
 			ctrl = &mi2s_config_controls[6];
-		if (dai->id == MSM_TERT_MI2S)
+		if (dai->id == MSM_SEC_MI2S)
 			ctrl = &mi2s_config_controls[7];
-		if (dai->id == MSM_QUAT_MI2S)
+		if (dai->id == MSM_TERT_MI2S)
 			ctrl = &mi2s_config_controls[8];
-		if (dai->id == MSM_QUIN_MI2S)
+		if (dai->id == MSM_QUAT_MI2S)
 			ctrl = &mi2s_config_controls[9];
-		if (dai->id == MSM_SENARY_MI2S)
+		if (dai->id == MSM_QUIN_MI2S)
 			ctrl = &mi2s_config_controls[10];
-		if (dai->id == MSM_INT5_MI2S)
+		if (dai->id == MSM_SENARY_MI2S)
 			ctrl = &mi2s_config_controls[11];
+		if (dai->id == MSM_INT5_MI2S)
+			ctrl = &mi2s_config_controls[12];
 	}
 
 	if (ctrl) {
@@ -5510,6 +5515,10 @@
 		dai_data->port_config.i2s.bit_width = 24;
 		dai_data->bitwidth = 24;
 		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		dai_data->port_config.i2s.bit_width = 32;
+		dai_data->bitwidth = 32;
+		break;
 	default:
 		pr_err("%s: format %d\n",
 			__func__, params_format(params));
diff --git a/asoc/msm-pcm-dtmf-v2.c b/asoc/msm-pcm-dtmf-v2.c
index 7f79471..3dc7a26 100644
--- a/asoc/msm-pcm-dtmf-v2.c
+++ b/asoc/msm-pcm-dtmf-v2.c
@@ -20,6 +20,8 @@
 
 #define DRV_NAME "msm-pcm-dtmf-v2"
 
+#define DTMF_MAX_DURATION 65535
+
 enum {
 	DTMF_IN_RX,
 	DTMF_IN_TX,
@@ -94,8 +96,12 @@
 	int64_t duration = ucontrol->value.integer.value[2];
 	uint16_t gain = ucontrol->value.integer.value[3];
 
-	pr_debug("%s: low_freq=%d high_freq=%d duration=%d gain=%d\n",
+	pr_debug("%s: low_freq=%d high_freq=%d duration=%lld gain=%d\n",
 		 __func__, low_freq, high_freq, (int)duration, gain);
+
+	if (duration == DTMF_MAX_DURATION)
+		duration = -1;
+
 	afe_dtmf_generate_rx(duration, high_freq, low_freq, gain);
 	return 0;
 }
diff --git a/asoc/msm-pcm-loopback-v2.c b/asoc/msm-pcm-loopback-v2.c
index 70c94e4..19fe190 100644
--- a/asoc/msm-pcm-loopback-v2.c
+++ b/asoc/msm-pcm-loopback-v2.c
@@ -132,7 +132,7 @@
 		ret = -EINVAL;
 		goto done;
 	}
-
+	mutex_lock(&loopback_session_lock);
 	pr_debug("%s: mute=%d\n", __func__, mute);
 	hfp_tx_mute = mute;
 	for (n = 0; n < LOOPBACK_SESSION_MAX; n++) {
@@ -145,6 +145,7 @@
 			pr_err("%s: Send mute command failed rc=%d\n",
 				__func__, ret);
 	}
+	mutex_unlock(&loopback_session_lock);
 done:
 	return ret;
 }
@@ -347,6 +348,8 @@
 
 	if (pcm->audio_client == NULL)
 		return;
+
+	mutex_lock(&loopback_session_lock);
 	q6asm_cmd(pcm->audio_client, CMD_CLOSE);
 
 	if (pcm->playback_substream != NULL) {
@@ -361,6 +364,7 @@
 	}
 	q6asm_audio_client_free(pcm->audio_client);
 	pcm->audio_client = NULL;
+	mutex_unlock(&loopback_session_lock);
 }
 
 static int msm_pcm_close(struct snd_pcm_substream *substream)
@@ -537,13 +541,15 @@
 		rc = -ENODEV;
 		goto exit;
 	}
+	mutex_lock(&loopback_session_lock);
 	prtd = substream->runtime->private_data;
 	if (!prtd) {
 		rc = -ENODEV;
+		mutex_unlock(&loopback_session_lock);
 		goto exit;
 	}
 	rc = pcm_loopback_set_volume(prtd, volume);
-
+	mutex_unlock(&loopback_session_lock);
 exit:
 	return rc;
 }
@@ -563,13 +569,15 @@
 		rc = -ENODEV;
 		goto exit;
 	}
+	mutex_lock(&loopback_session_lock);
 	prtd = substream->runtime->private_data;
 	if (!prtd) {
 		rc = -ENODEV;
+		mutex_unlock(&loopback_session_lock);
 		goto exit;
 	}
 	ucontrol->value.integer.value[0] = prtd->volume;
-
+	mutex_unlock(&loopback_session_lock);
 exit:
 	return rc;
 }
@@ -855,11 +863,13 @@
 			session_type,
 			chmixer_pspd);
 
+	mutex_lock(&loopback_session_lock);
 	if (chmixer_pspd->enable && substream->runtime) {
 		prtd = substream->runtime->private_data;
 		if (!prtd) {
 			pr_err("%s find invalid prtd fail\n", __func__);
 			ret = -EINVAL;
+			mutex_unlock(&loopback_session_lock);
 			goto done;
 		}
 
@@ -872,7 +882,7 @@
 					chmixer_pspd);
 		}
 	}
-
+	mutex_unlock(&loopback_session_lock);
 	if (reset_override_out_ch_map)
 		chmixer_pspd->override_out_ch_map = false;
 	if (reset_override_in_ch_map)
diff --git a/asoc/msm-pcm-q6-noirq.c b/asoc/msm-pcm-q6-noirq.c
index cd69d77..12a1f12 100644
--- a/asoc/msm-pcm-q6-noirq.c
+++ b/asoc/msm-pcm-q6-noirq.c
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/time.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -630,6 +631,8 @@
 
 static int msm_pcm_close(struct snd_pcm_substream *substream)
 {
+	struct msm_plat_data *pdata = NULL;
+	struct snd_soc_component *component = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd = runtime->private_data;
@@ -638,6 +641,25 @@
 	int dir = 0;
 	int ret = 0;
 
+	if (!soc_prtd) {
+		pr_debug("%s private_data not found\n",
+			__func__);
+		return 0;
+	}
+
+	component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = (struct msm_plat_data *) dev_get_drvdata(component->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&pdata->lock);
 	if (ac) {
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 			dir = IN;
@@ -672,6 +694,7 @@
 					 SNDRV_PCM_STREAM_CAPTURE);
 	kfree(prtd);
 	runtime->private_data = NULL;
+	mutex_unlock(&pdata->lock);
 
 	return 0;
 }
@@ -696,8 +719,11 @@
 		      struct snd_ctl_elem_value *ucontrol)
 {
 	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_soc_pcm_runtime *soc_prtd = NULL;
+	struct snd_soc_component *component = NULL;
 	struct msm_audio *prtd;
 
 	pr_debug("%s\n", __func__);
@@ -705,13 +731,29 @@
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
 	}
-	if (!substream->runtime) {
-		pr_debug("%s substream runtime not found\n", __func__);
+	soc_prtd = substream->private_data;
+	if (!substream->runtime || !soc_prtd) {
+		pr_debug("%s substream runtime or private_data not found\n",
+				 __func__);
 		return 0;
 	}
+
+	component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = (struct msm_plat_data *) dev_get_drvdata(component->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd)
 		ucontrol->value.integer.value[0] = prtd->volume;
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -720,8 +762,11 @@
 {
 	int rc = 0;
 	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_soc_pcm_runtime *soc_prtd = NULL;
+	struct snd_soc_component *component = NULL;
 	struct msm_audio *prtd;
 	int volume = ucontrol->value.integer.value[0];
 
@@ -730,15 +775,32 @@
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
 	}
-	if (!substream->runtime) {
-		pr_err("%s substream runtime not found\n", __func__);
+	soc_prtd = substream->private_data;
+	if (!substream->runtime || !soc_prtd) {
+		pr_err("%s substream runtime or private_data not found\n",
+				 __func__);
 		return 0;
 	}
+
+	component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = (struct msm_plat_data *) dev_get_drvdata(component->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd) {
 		rc = msm_pcm_set_volume(prtd, volume);
 		prtd->volume = volume;
 	}
+	mutex_unlock(&pdata->lock);
 	return rc;
 }
 
@@ -1338,6 +1400,8 @@
 
 	pdata->perf_mode = perf_mode;
 
+	mutex_init(&pdata->lock);
+
 	dev_set_drvdata(&pdev->dev, pdata);
 
 	dev_dbg(&pdev->dev, "%s: dev name %s\n",
@@ -1359,6 +1423,7 @@
 
 	dev_dbg(&pdev->dev, "Pull mode remove\n");
 	pdata = dev_get_drvdata(&pdev->dev);
+	mutex_destroy(&pdata->lock);
 	devm_kfree(&pdev->dev, pdata);
 	snd_soc_unregister_component(&pdev->dev);
 	return 0;
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index 7197ad6..60e84cb 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -1309,10 +1309,10 @@
 	pdata = dev_get_drvdata(component->dev);
 	if (!pdata) {
 		pr_err("%s pdata is NULL\n", __func__);
-		ret = -ENODEV;
-		goto done;
+		return -ENODEV;
 	}
 
+	mutex_lock(&pdata->lock);
 	substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
 	if (!substream) {
 		pr_err("%s substream not found\n", __func__);
@@ -1339,7 +1339,6 @@
 		goto done;
 	}
 
-	mutex_lock(&pdata->lock);
 	event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
 	if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
 	    (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
@@ -1514,8 +1513,11 @@
 		      struct snd_ctl_elem_value *ucontrol)
 {
 	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_soc_pcm_runtime *soc_prtd = NULL;
+	struct snd_soc_component *component = NULL;
 	struct msm_audio *prtd;
 
 	pr_debug("%s\n", __func__);
@@ -1523,13 +1525,30 @@
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
 	}
-	if (!substream->runtime) {
-		pr_debug("%s substream runtime not found\n", __func__);
+	soc_prtd = substream->private_data;
+	if (!substream->runtime || !soc_prtd) {
+		pr_debug("%s substream runtime or private_data not found\n",
+				 __func__);
 		return 0;
 	}
+
+	component = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
+	if (!component) {
+		pr_err("%s: component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = (struct msm_plat_data *) dev_get_drvdata(component->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd)
 		ucontrol->value.integer.value[0] = prtd->volume;
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -1635,9 +1654,11 @@
 		pr_debug("%s substream runtime not found\n", __func__);
 		return 0;
 	}
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd)
 		ucontrol->value.integer.value[0] = prtd->compress_enable;
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -1665,12 +1686,14 @@
 		pr_err("%s substream runtime not found\n", __func__);
 		return 0;
 	}
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd) {
 		pr_debug("%s: setting compress flag to 0x%x\n",
 		__func__, compress);
 		prtd->compress_enable = compress;
 	}
+	mutex_unlock(&pdata->lock);
 	return rc;
 }
 
@@ -1774,11 +1797,11 @@
 		}
 	}
 
-	if (!substream->runtime || !rtd)
+	if (!rtd)
 		return 0;
 
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
+	prtd = substream->runtime ? substream->runtime->private_data : NULL;
 	if (prtd) {
 		prtd->set_channel_map = true;
 			for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
@@ -1841,11 +1864,11 @@
 
 	memset(ucontrol->value.integer.value, 0,
 		sizeof(ucontrol->value.integer.value));
-	if (!substream->runtime || !rtd)
+	if (!rtd)
 		return 0; /* no channels set */
 
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
+	prtd = substream->runtime ? substream->runtime->private_data : NULL;
 
 	if (prtd && prtd->set_channel_map == true) {
 		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 0563d8c..9cddca0 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -123,6 +123,7 @@
 #define VA_CDC_DMA_TX_2_TEXT "VA_CDC_DMA_TX_2"
 #define TX_CDC_DMA_TX_3_TEXT "TX_CDC_DMA_TX_3"
 #define QUIN_TDM_TX_TEXT "QUIN_TDM_TX_0"
+#define TERT_TDM_TX_TEXT "TERT_TDM_TX_0"
 
 #define LSM_FUNCTION_TEXT "LSM Function"
 static const char * const lsm_port_text[] = {
@@ -131,7 +132,8 @@
 	SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT,
 	TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT,
 	INT3_MI2S_TX_TEXT, VA_CDC_DMA_TX_0_TEXT, VA_CDC_DMA_TX_1_TEXT,
-	VA_CDC_DMA_TX_2_TEXT, TX_CDC_DMA_TX_3_TEXT, QUIN_TDM_TX_TEXT
+	VA_CDC_DMA_TX_2_TEXT, TX_CDC_DMA_TX_3_TEXT, QUIN_TDM_TX_TEXT,
+	TERT_TDM_TX_TEXT
 };
 
 struct msm_pcm_route_bdai_pp_params {
@@ -2056,7 +2058,13 @@
 
 	pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
 
-	if (!is_mm_lsm_fe_id(val)) {
+	if (val == MSM_FRONTEND_DAI_DTMF_RX &&
+		afe_get_port_type(msm_bedais[reg].port_id) ==
+			MSM_AFE_PORT_TYPE_RX) {
+		pr_debug("%s(): set=%d port id=0x%x for dtmf generation\n",
+			__func__, set, msm_bedais[reg].port_id);
+		afe_set_dtmf_gen_rx_portid(msm_bedais[reg].port_id, set);
+	} else if (!is_mm_lsm_fe_id(val)) {
 		/* recheck FE ID in the mixer control defined in this file */
 		pr_err("%s: bad MM ID\n", __func__);
 		return;
@@ -3026,6 +3034,9 @@
 	case 15:
 		lsm_port = AFE_PORT_ID_QUINARY_TDM_TX;
 		break;
+	case 16:
+		lsm_port = AFE_PORT_ID_TERTIARY_TDM_TX;
+		break;
 	default:
 		pr_err("Default lsm port");
 		break;
@@ -3043,7 +3054,7 @@
 	u16 port_id;
 	enum afe_mad_type mad_type;
 
-	pr_debug("%s: enter\n", __func__);
+	pr_debug("%s: id name %s\n", __func__, kcontrol->id.name);
 	for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++)
 		if (!strnstr(kcontrol->id.name, lsm_port_text[i],
 			    strlen(lsm_port_text[i])))
@@ -3070,14 +3081,18 @@
 			strlen(lsm_port_text[10])))
 		port_id = AFE_PORT_ID_INT3_MI2S_TX;
 
-	if (strnstr(kcontrol->id.name, lsm_port_text[13],
-			strlen(lsm_port_text[13])))
-		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
-
 	if (strnstr(kcontrol->id.name, lsm_port_text[14],
 			strlen(lsm_port_text[14])))
+		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
+
+	if (strnstr(kcontrol->id.name, lsm_port_text[15],
+			strlen(lsm_port_text[15])))
 		port_id = AFE_PORT_ID_QUINARY_TDM_TX;
 
+	if (strnstr(kcontrol->id.name, lsm_port_text[16],
+			strlen(lsm_port_text[16])))
+		port_id = AFE_PORT_ID_TERTIARY_TDM_TX;
+
 	mad_type = afe_port_get_mad_type(port_id);
 	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
 		 mad_type);
@@ -3111,7 +3126,7 @@
 	u16 port_id;
 	enum afe_mad_type mad_type;
 
-	pr_debug("%s: enter\n", __func__);
+	pr_debug("%s: id name %s\n", __func__, kcontrol->id.name);
 	for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++)
 		if (strnstr(kcontrol->id.name, lsm_port_text[i],
 			    strlen(lsm_port_text[i])))
@@ -3158,14 +3173,18 @@
 			strlen(lsm_port_text[10])))
 		port_id = AFE_PORT_ID_INT3_MI2S_TX;
 
-	if (strnstr(kcontrol->id.name, lsm_port_text[13],
-			strlen(lsm_port_text[13])))
-		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
-
 	if (strnstr(kcontrol->id.name, lsm_port_text[14],
 			strlen(lsm_port_text[14])))
+		port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
+
+	if (strnstr(kcontrol->id.name, lsm_port_text[15],
+			strlen(lsm_port_text[15])))
 		port_id = AFE_PORT_ID_QUINARY_TDM_TX;
 
+	if (strnstr(kcontrol->id.name, lsm_port_text[16],
+			strlen(lsm_port_text[16])))
+		port_id = AFE_PORT_ID_TERTIARY_TDM_TX;
+
 	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
 		 mad_type);
 	return afe_port_set_mad_type(port_id, mad_type);
@@ -5444,6 +5463,10 @@
 		*index = 37;
 		port_id = AFE_PORT_ID_HDMI_OVER_DP_RX;
 		break;
+	case 38:
+		*index = 38;
+		port_id = AFE_PORT_ID_SENARY_MI2S_RX;
+		break;
 	default:
 		*index = 0; /* NONE */
 		pr_err("%s: Invalid value %d\n", __func__, value);
@@ -5501,7 +5524,7 @@
 	"WSA_CDC_DMA_TX_0", "WSA_CDC_DMA_TX_1", "WSA_CDC_DMA_TX_2",
 	"SLIM_7_RX", "RX_CDC_DMA_RX_0", "RX_CDC_DMA_RX_1", "RX_CDC_DMA_RX_2",
 	"RX_CDC_DMA_RX_3", "TX_CDC_DMA_TX_0", "TERT_TDM_RX_2", "SEC_TDM_TX_0",
-	"DISPLAY_PORT1",
+	"DISPLAY_PORT1", "SEN_MI2S_RX",
 };
 
 static const struct soc_enum msm_route_ec_ref_rx_enum[] = {
@@ -7040,7 +7063,10 @@
 	MSM_BACKEND_DAI_PRI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA30, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
-
+	SOC_DOUBLE_EXT("DTMF", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int0_mi2s_rx_mixer_controls[] = {
@@ -7607,6 +7633,10 @@
 	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
@@ -11191,6 +11221,73 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_tx_1_mixer_controls[] = {
+	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia2", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia6", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia7", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia8", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia9", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia10", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia11", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia12", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia13", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia14", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia15", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia16", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_1,
+	MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new quin_tdm_rx_1_mixer_controls[] = {
 	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_QUIN_TDM_RX_1,
@@ -11270,6 +11367,73 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_tx_2_mixer_controls[] = {
+	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia2", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia6", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia7", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia8", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia9", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia10", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia11", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia12", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia13", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia14", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia15", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia16", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_2,
+	MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new quin_tdm_rx_2_mixer_controls[] = {
 	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_QUIN_TDM_RX_2,
@@ -11349,6 +11513,73 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_tx_3_mixer_controls[] = {
+	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia2", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia6", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia7", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia8", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia9", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia10", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia11", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia12", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia13", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia14", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia15", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia16", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_TX_3,
+	MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new quin_tdm_rx_3_mixer_controls[] = {
 	SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_QUIN_TDM_RX_3,
@@ -15843,6 +16074,13 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new quin_tdm_rx_2_voice_mixer_controls[] = {
+	SOC_DOUBLE_EXT("VoiceMMode1", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_QUIN_TDM_RX_2,
+	MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new wsa_cdc_dma_rx_0_voice_mixer_controls[] = {
 	SOC_DOUBLE_EXT("Voip", SND_SOC_NOPM,
 			MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0,
@@ -17113,6 +17351,25 @@
 
 };
 
+static const struct snd_kcontrol_new rx_cdc_dma_rx_1_port_mixer_controls[] = {
+	SOC_DOUBLE_EXT("VA_CDC_DMA_TX_0", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_VA_CDC_DMA_TX_0, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_DOUBLE_EXT("TX_CDC_DMA_TX_3", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_TX_CDC_DMA_TX_3, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_DOUBLE_EXT("SLIM_8_TX", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_SLIMBUS_8_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_DOUBLE_EXT("TERT_MI2S_TX", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_RX_CDC_DMA_RX_1,
+	MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
 static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
 	SOC_DOUBLE_EXT("INTERNAL_FM_TX", SND_SOC_NOPM,
 	MSM_BACKEND_DAI_SLIMBUS_0_RX,
@@ -20786,6 +21043,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm2_mixer_controls[] = {
@@ -20842,6 +21103,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm3_mixer_controls[] = {
@@ -20897,6 +21162,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm4_mixer_controls[] = {
@@ -20952,6 +21221,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm5_mixer_controls[] = {
@@ -21007,6 +21280,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm6_mixer_controls[] = {
@@ -21062,6 +21339,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm7_mixer_controls[] = {
@@ -21117,6 +21398,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new lsm8_mixer_controls[] = {
@@ -21172,6 +21457,10 @@
 		MSM_BACKEND_DAI_QUIN_TDM_TX_0,
 		MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer,
 		msm_routing_put_listen_mixer),
+	SOC_DOUBLE_EXT("TERT_TDM_TX_0", SND_SOC_NOPM,
+		MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer,
+		msm_routing_put_listen_mixer),
 };
 
 static const struct snd_kcontrol_new slim_fm_switch_mixer_controls =
@@ -21322,6 +21611,8 @@
 		    msm_routing_lsm_func_get, msm_routing_lsm_func_put),
 	SOC_ENUM_EXT(QUIN_TDM_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
 		    msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+	SOC_ENUM_EXT(TERT_TDM_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		    msm_routing_lsm_func_get, msm_routing_lsm_func_put),
 	/* kcontrol of lsm_port */
 	SOC_ENUM_EXT("LSM1 Port", lsm_port_enum,
 			  msm_routing_lsm_port_get,
@@ -23701,12 +23992,21 @@
 	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				quin_tdm_rx_1_mixer_controls,
 				ARRAY_SIZE(quin_tdm_rx_1_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_TX_1 Audio Mixer", SND_SOC_NOPM, 0, 0,
+				quin_tdm_tx_1_mixer_controls,
+				ARRAY_SIZE(quin_tdm_tx_1_mixer_controls)),
 	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				quin_tdm_rx_2_mixer_controls,
 				ARRAY_SIZE(quin_tdm_rx_2_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_TX_2 Audio Mixer", SND_SOC_NOPM, 0, 0,
+				quin_tdm_tx_2_mixer_controls,
+				ARRAY_SIZE(quin_tdm_tx_2_mixer_controls)),
 	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				quin_tdm_rx_3_mixer_controls,
 				ARRAY_SIZE(quin_tdm_rx_3_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_TX_3 Audio Mixer", SND_SOC_NOPM, 0, 0,
+				quin_tdm_tx_3_mixer_controls,
+				ARRAY_SIZE(quin_tdm_tx_3_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SEN_TDM_TX_0 Audio Mixer", SND_SOC_NOPM, 0, 0,
 				sen_tdm_tx_0_mixer_controls,
 				ARRAY_SIZE(sen_tdm_tx_0_mixer_controls)),
@@ -23934,6 +24234,10 @@
 				SND_SOC_NOPM, 0, 0,
 				quat_tdm_rx_2_voice_mixer_controls,
 				ARRAY_SIZE(quat_tdm_rx_2_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("QUIN_TDM_RX_2_Voice Mixer",
+				SND_SOC_NOPM, 0, 0,
+				quin_tdm_rx_2_voice_mixer_controls,
+				ARRAY_SIZE(quin_tdm_rx_2_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("WSA_CDC_DMA_RX_0_Voice Mixer",
 			   SND_SOC_NOPM, 0, 0,
 			   wsa_cdc_dma_rx_0_voice_mixer_controls,
@@ -23942,6 +24246,10 @@
 			   SND_SOC_NOPM, 0, 0,
 			   rx_cdc_dma_rx_0_voice_mixer_controls,
 			   ARRAY_SIZE(rx_cdc_dma_rx_0_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX_CDC_DMA_RX_1_Voice Mixer",
+			   SND_SOC_NOPM, 0, 0,
+			   rx_cdc_dma_rx_1_voice_mixer_controls,
+			   ARRAY_SIZE(rx_cdc_dma_rx_1_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
 				ARRAY_SIZE(tx_voip_mixer_controls)),
@@ -24145,6 +24453,9 @@
 	SND_SOC_DAPM_MIXER("RX_CDC_DMA_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0,
 	rx_cdc_dma_rx_0_port_mixer_controls,
 	ARRAY_SIZE(rx_cdc_dma_rx_0_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX_CDC_DMA_RX_1 Port Mixer", SND_SOC_NOPM, 0, 0,
+	rx_cdc_dma_rx_1_port_mixer_controls,
+	ARRAY_SIZE(rx_cdc_dma_rx_1_port_mixer_controls)),
 	SND_SOC_DAPM_MIXER("QCHAT_Tx Mixer",
 	SND_SOC_NOPM, 0, 0, tx_qchat_mixer_controls,
 	ARRAY_SIZE(tx_qchat_mixer_controls)),
@@ -24614,6 +24925,7 @@
 	/* incall */
 	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"Incall_Music Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"Incall_Music Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
@@ -24707,9 +25019,11 @@
 	{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia4 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia8 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
+	{"MultiMedia9 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia4 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia8 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
+	{"MultiMedia9 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
 	{"MultiMedia1 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"},
 	{"MultiMedia1 Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"},
@@ -24880,6 +25194,7 @@
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"},
 	{"PRI_MI2S_RX Audio Mixer", "MultiMedia26", "MM_DL26"},
 	{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Audio Mixer"},
+	{"PRI_MI2S_RX Audio Mixer", "DTMF", "DTMF_DL_HL"},
 
 	{"INT0_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"INT0_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -26712,6 +27027,9 @@
 	{"QUAT_TDM_RX_2_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
 	{"QUAT_TDM_RX_2", NULL, "QUAT_TDM_RX_2_Voice Mixer"},
 
+	{"QUIN_TDM_RX_2_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
+	{"QUIN_TDM_RX_2", NULL, "QUIN_TDM_RX_2_Voice Mixer"},
+
 	{"WSA_CDC_DMA_RX_0_Voice Mixer", "Voip", "VOIP_DL"},
 	{"WSA_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
 	{"WSA_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
@@ -26722,6 +27040,11 @@
 	{"RX_CDC_DMA_RX_0_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
 	{"RX_CDC_DMA_RX_0", NULL, "RX_CDC_DMA_RX_0_Voice Mixer"},
 
+	{"RX_CDC_DMA_RX_1_Voice Mixer", "Voip", "VOIP_DL"},
+	{"RX_CDC_DMA_RX_1_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
+	{"RX_CDC_DMA_RX_1_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
+	{"RX_CDC_DMA_RX_1", NULL, "RX_CDC_DMA_RX_1_Voice Mixer"},
+
 	{"VOC_EXT_EC MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"VOC_EXT_EC MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
 	{"VOC_EXT_EC MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
@@ -26959,6 +27282,7 @@
 	{"CDC_DMA_UL_HL", NULL, "VA_CDC_DMA_TX_0"},
 	{"RX_CDC_DMA_RX_0_DL_HL", "Switch", "CDC_DMA_DL_HL"},
 	{"RX_CDC_DMA_RX_0", NULL, "RX_CDC_DMA_RX_0_DL_HL"},
+	{"RX_CDC_DMA_RX_1", NULL, "RX_CDC_DMA_RX_0_DL_HL"},
 	{"TX3_CDC_DMA_UL_HL", NULL, "TX_CDC_DMA_TX_3"},
 	{"LSM1 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
 	{"LSM1 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"},
@@ -26973,6 +27297,7 @@
 	{"LSM1 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM1 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM1 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM1 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM1_UL_HL", NULL, "LSM1 Mixer"},
 
 	{"LSM2 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -26988,6 +27313,7 @@
 	{"LSM2 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM2 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM2 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM2 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM2_UL_HL", NULL, "LSM2 Mixer"},
 
 
@@ -27004,6 +27330,7 @@
 	{"LSM3 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM3 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM3 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM3 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM3_UL_HL", NULL, "LSM3 Mixer"},
 
 
@@ -27020,6 +27347,7 @@
 	{"LSM4 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM4 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM4 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM4 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM4_UL_HL", NULL, "LSM4 Mixer"},
 
 	{"LSM5 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27035,6 +27363,7 @@
 	{"LSM5 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM5 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM5 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM5 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM5_UL_HL", NULL, "LSM5 Mixer"},
 
 	{"LSM6 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27048,6 +27377,7 @@
 	{"LSM6 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM6 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM6 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM6 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM6_UL_HL", NULL, "LSM6 Mixer"},
 
 	{"LSM7 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27061,6 +27391,7 @@
 	{"LSM7 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM7 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM7 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM7 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM7_UL_HL", NULL, "LSM7 Mixer"},
 
 	{"LSM8 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
@@ -27074,6 +27405,7 @@
 	{"LSM8 Mixer", "VA_CDC_DMA_TX_2", "VA_CDC_DMA_TX_2"},
 	{"LSM8 Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
 	{"LSM8 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"},
+	{"LSM8 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"},
 	{"LSM8_UL_HL", NULL, "LSM8 Mixer"},
 
 
@@ -27862,6 +28194,12 @@
 	{"RX_CDC_DMA_RX_0 Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
 	{"RX_CDC_DMA_RX_0", NULL, "RX_CDC_DMA_RX_0 Port Mixer"},
 
+	{"RX_CDC_DMA_RX_1 Port Mixer", "VA_CDC_DMA_TX_0", "VA_CDC_DMA_TX_0"},
+	{"RX_CDC_DMA_RX_1 Port Mixer", "TX_CDC_DMA_TX_3", "TX_CDC_DMA_TX_3"},
+	{"RX_CDC_DMA_RX_1 Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
+	{"RX_CDC_DMA_RX_1 Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+	{"RX_CDC_DMA_RX_1", NULL, "RX_CDC_DMA_RX_1 Port Mixer"},
+
 	{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
@@ -28870,6 +29208,11 @@
 	uint32_t be_idx = ucontrol->value.integer.value[0];
 	int i;
 
+	if (be_idx >= MSM_BACKEND_DAI_MAX) {
+		pr_err("%s: Invalid Backend index %d\n",  __func__, be_idx);
+		return -EINVAL;
+	}
+
 	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++) {
 		channel_map[i] = (char)(ucontrol->value.integer.value[i + 1]);
 		if (channel_map[i] > PCM_MAX_CHMAP_ID) {
diff --git a/asoc/msm-pcm-voice-v2.c b/asoc/msm-pcm-voice-v2.c
index f8acc30..5a25b3e 100644
--- a/asoc/msm-pcm-voice-v2.c
+++ b/asoc/msm-pcm-voice-v2.c
@@ -582,6 +582,20 @@
 	return 0;
 }
 
+static int msm_voice_ecns_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	uint32_t enable = ucontrol->value.integer.value[0];
+	uint32_t session_id = ucontrol->value.integer.value[1];
+	uint32_t module_id = ucontrol->value.integer.value[2];
+
+	pr_debug("%s: ecns enable=%d session_id=%#x\n", __func__, enable,
+		 session_id);
+	voc_set_ecns_enable(session_id, module_id, enable);
+
+	return 0;
+}
+
 static int msm_voice_hd_voice_put(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
@@ -695,6 +709,8 @@
 				msm_voice_tty_mode_put),
 	SOC_SINGLE_MULTI_EXT("Slowtalk Enable", SND_SOC_NOPM, 0, VSID_MAX, 0, 2,
 				NULL, msm_voice_slowtalk_put),
+	SOC_SINGLE_MULTI_EXT("Voice ECNS Enable", SND_SOC_NOPM, 0, VSID_MAX, 0, 3,
+				NULL, msm_voice_ecns_put),
 	SOC_SINGLE_MULTI_EXT("Voice Topology Disable", SND_SOC_NOPM, 0,
 			     VSID_MAX, 0, 2, NULL,
 			     msm_voice_topology_disable_put),
diff --git a/config/bengalauto.conf b/config/bengalauto.conf
new file mode 100644
index 0000000..d6fdadd
--- /dev/null
+++ b/config/bengalauto.conf
@@ -0,0 +1,34 @@
+CONFIG_PINCTRL_LPI=m
+CONFIG_AUDIO_EXT_CLK=m
+CONFIG_SND_SOC_WCD9XXX_V2=m
+CONFIG_SND_SOC_WCD_MBHC=m
+CONFIG_SND_SOC_WSA881X_ANALOG=m
+CONFIG_WCD9XXX_CODEC_CORE_V2=m
+CONFIG_MSM_CDC_PINCTRL=m
+CONFIG_MSM_QDSP6V2_CODECS=m
+CONFIG_MSM_ULTRASOUND=m
+CONFIG_MSM_QDSP6_APRV2_RPMSG=m
+CONFIG_MSM_ADSP_LOADER=m
+CONFIG_REGMAP_SWR=m
+CONFIG_MSM_QDSP6_SSR=m
+CONFIG_MSM_QDSP6_PDR=m
+CONFIG_MSM_QDSP6_NOTIFIER=m
+CONFIG_SND_SOC_MSM_HOSTLESS_PCM=m
+CONFIG_SND_SOC_MSM_QDSP6V2_INTF=m
+CONFIG_SOUNDWIRE=m
+CONFIG_SOUNDWIRE_MSTR_CTRL=m
+CONFIG_SND_SOC_QDSP6V2=m
+CONFIG_SND_SOC_WCD_MBHC_ADC=m
+CONFIG_QTI_PP=m
+CONFIG_SND_HWDEP_ROUTING=m
+CONFIG_SND_SOC_MSM_STUB=m
+CONFIG_MSM_AVTIMER=m
+CONFIG_SND_SOC_BOLERO=m
+CONFIG_VA_MACRO=m
+CONFIG_RX_MACRO=m
+CONFIG_TX_MACRO=m
+CONFIG_SND_SOC_WCD_IRQ=m
+CONFIG_SND_SOC_WCD937X=m
+CONFIG_SND_SOC_WCD937X_SLAVE=m
+CONFIG_SND_SOC_BENGAL=m
+CONFIG_SND_EVENT=m
diff --git a/config/bengalautoconf.h b/config/bengalautoconf.h
new file mode 100644
index 0000000..90d3e3c
--- /dev/null
+++ b/config/bengalautoconf.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
+
+#define CONFIG_PINCTRL_LPI 1
+#define CONFIG_AUDIO_EXT_CLK 1
+#define CONFIG_SND_SOC_WCD9XXX_V2 1
+#define CONFIG_SND_SOC_WCD_MBHC 1
+#define CONFIG_SND_SOC_WSA881X_ANALOG 1
+#define CONFIG_WCD9XXX_CODEC_CORE_V2 1
+#define CONFIG_MSM_CDC_PINCTRL 1
+#define CONFIG_MSM_QDSP6V2_CODECS 1
+#define CONFIG_MSM_ULTRASOUND 1
+#define CONFIG_MSM_QDSP6_APRV2_RPMSG 1
+#define CONFIG_SND_SOC_MSM_QDSP6V2_INTF 1
+#define CONFIG_MSM_ADSP_LOADER 1
+#define CONFIG_REGMAP_SWR 1
+#define CONFIG_MSM_QDSP6_SSR 1
+#define CONFIG_MSM_QDSP6_PDR 1
+#define CONFIG_MSM_QDSP6_NOTIFIER 1
+#define CONFIG_SND_SOC_MSM_HOSTLESS_PCM 1
+#define CONFIG_SOUNDWIRE 1
+#define CONFIG_SOUNDWIRE_MSTR_CTRL 1
+#define CONFIG_SND_SOC_WCD_MBHC_ADC 1
+#define CONFIG_SND_SOC_QDSP6V2 1
+#define CONFIG_QTI_PP 1
+#define CONFIG_SND_HWDEP_ROUTING 1
+#define CONFIG_SND_SOC_MSM_STUB 1
+#define CONFIG_MSM_AVTIMER 1
+#define CONFIG_SND_SOC_BOLERO 1
+#define CONFIG_VA_MACRO 1
+#define CONFIG_RX_MACRO 1
+#define CONFIG_TX_MACRO 1
+#define CONFIG_SND_SOC_WCD_IRQ 1
+#define CONFIG_SND_SOC_WCD937X 1
+#define CONFIG_SND_SOC_WCD937X_SLAVE 1
+#define CONFIG_SND_SOC_BENGAL 1
+#define CONFIG_SND_EVENT 1
diff --git a/dsp/Android.mk b/dsp/Android.mk
index df13d3d..c5ab3ff 100644
--- a/dsp/Android.mk
+++ b/dsp/Android.mk
@@ -27,6 +27,10 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_LITO=m
 endif
 
+ifeq ($(call is-board-platform, bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
 ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) $(TRINKET) kona lito bengal sdmshrike),true)
diff --git a/dsp/Kbuild b/dsp/Kbuild
index 81f8094..006de44 100644
--- a/dsp/Kbuild
+++ b/dsp/Kbuild
@@ -40,9 +40,9 @@
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
+		include $(AUDIO_ROOT)/config/bengalauto.conf
 		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_SM8150), y)
 		ifdef CONFIG_SND_SOC_SA8155
diff --git a/dsp/avtimer.c b/dsp/avtimer.c
index ad5e13a..e1d032d 100644
--- a/dsp/avtimer.c
+++ b/dsp/avtimer.c
@@ -271,6 +271,7 @@
 				rc = avcs_core_disable_avtimer(
 				avtimer.timer_handle);
 				avtimer.timer_handle = 0;
+				atomic_set(&avtimer.adsp_ready, 0);
 			}
 		}
 	}
diff --git a/dsp/codecs/Android.mk b/dsp/codecs/Android.mk
index 3d122f6..59a1603 100644
--- a/dsp/codecs/Android.mk
+++ b/dsp/codecs/Android.mk
@@ -19,6 +19,10 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_LITO=m
 endif
 
+ifeq ($(call is-board-platform,bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
 ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) $(TRINKET) kona lito bengal sdmshrike),true)
diff --git a/dsp/codecs/Kbuild b/dsp/codecs/Kbuild
index 3bdcd7d..8709901 100644
--- a/dsp/codecs/Kbuild
+++ b/dsp/codecs/Kbuild
@@ -34,9 +34,9 @@
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
+		include $(AUDIO_ROOT)/config/bengalauto.conf
 		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_SM8150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index c30415a..7297a1e 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -110,7 +110,7 @@
 	wait_queue_head_t wait_wakeup;
 	struct task_struct *task;
 	wait_queue_head_t lpass_core_hw_wait;
-	uint32_t lpass_hw_core_client_hdl;
+	uint32_t lpass_hw_core_client_hdl[AFE_LPASS_CORE_HW_VOTE_MAX];
 	void (*tx_cb)(uint32_t opcode,
 		uint32_t token, uint32_t *payload, void *priv);
 	void (*rx_cb)(uint32_t opcode,
@@ -571,6 +571,8 @@
 
 static int32_t afe_callback(struct apr_client_data *data, void *priv)
 {
+	uint16_t i = 0;
+
 	if (!data) {
 		pr_err("%s: Invalid param data\n", __func__);
 		return -EINVAL;
@@ -598,7 +600,8 @@
 
 		/* Reset the core client handle in SSR/PDR use cases */
 		mutex_lock(&this_afe.afe_cmd_lock);
-		this_afe.lpass_hw_core_client_hdl = 0;
+		for (i = 0; i < AFE_LPASS_CORE_HW_VOTE_MAX; i++)
+			this_afe.lpass_hw_core_client_hdl[i] = 0;
 		mutex_unlock(&this_afe.afe_cmd_lock);
 
 		/*
@@ -673,7 +676,9 @@
 
 		pr_debug("%s: AFE_CMD_RSP_REMOTE_LPASS_CORE_HW_VOTE_REQUEST handle %d\n",
 			__func__, payload[0]);
-		this_afe.lpass_hw_core_client_hdl = payload[0];
+		if (data->token < AFE_LPASS_CORE_HW_VOTE_MAX)
+			this_afe.lpass_hw_core_client_hdl[data->token] =
+								payload[0];
 		atomic_set(&this_afe.state, 0);
 		atomic_set(&this_afe.status, 0);
 		wake_up(&this_afe.lpass_core_hw_wait);
@@ -2897,7 +2902,8 @@
 
 	if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
 		port_id == AFE_PORT_ID_INT3_MI2S_TX ||
-		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3) {
+		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3 ||
+		port_id == AFE_PORT_ID_TERTIARY_TDM_TX) {
 		mad_type = MAD_SW_AUDIO;
 		return 0;
 	}
@@ -2926,7 +2932,8 @@
 
 	if (port_id == AFE_PORT_ID_TERTIARY_MI2S_TX ||
 		port_id == AFE_PORT_ID_INT3_MI2S_TX ||
-		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3)
+		port_id == AFE_PORT_ID_TX_CODEC_DMA_TX_3 ||
+		port_id == AFE_PORT_ID_TERTIARY_TDM_TX)
 		return MAD_SW_AUDIO;
 
 	i = port_id - SLIMBUS_0_RX;
@@ -7912,6 +7919,7 @@
 	if (this_afe.vi_tx_port != -1)
 		port = this_afe.vi_tx_port;
 
+	mutex_lock(&this_afe.afe_cmd_lock);
 	memset(&param_hdr, 0, sizeof(param_hdr));
 
 	param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
@@ -7922,7 +7930,7 @@
 	ret = q6afe_get_params(port, NULL, &param_hdr);
 	if (ret) {
 		pr_err("%s: Failed to get TH VI V-Vali data\n", __func__);
-		goto done;
+		goto get_params_fail;
 	}
 
 	th_vi_v_vali->pdata = param_hdr;
@@ -7934,6 +7942,8 @@
 		 th_vi_v_vali->param.status[SP_V2_SPKR_1],
 		 th_vi_v_vali->param.status[SP_V2_SPKR_2]);
 	ret = 0;
+get_params_fail:
+	mutex_unlock(&this_afe.afe_cmd_lock);
 done:
 	return ret;
 }
@@ -7951,6 +7961,7 @@
 	if (this_afe.vi_tx_port != -1)
 		port = this_afe.vi_tx_port;
 
+	mutex_lock(&this_afe.afe_cmd_lock);
 	memset(&param_hdr, 0, sizeof(param_hdr));
 
 	param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_TH_VI;
@@ -7961,7 +7972,7 @@
 	ret = q6afe_get_params(port, NULL, &param_hdr);
 	if (ret) {
 		pr_err("%s: Failed to get TH VI FTM data\n", __func__);
-		goto done;
+		goto get_params_fail;
 	}
 
 	th_vi->pdata = param_hdr;
@@ -7975,6 +7986,8 @@
 		 th_vi->param.status[SP_V2_SPKR_1],
 		 th_vi->param.status[SP_V2_SPKR_2]);
 	ret = 0;
+get_params_fail:
+	mutex_unlock(&this_afe.afe_cmd_lock);
 done:
 	return ret;
 }
@@ -7992,6 +8005,7 @@
 	if (this_afe.vi_tx_port != -1)
 		port = this_afe.vi_tx_port;
 
+	mutex_lock(&this_afe.afe_cmd_lock);
 	memset(&param_hdr, 0, sizeof(param_hdr));
 
 	param_hdr.module_id = AFE_MODULE_SPEAKER_PROTECTION_V2_EX_VI;
@@ -8003,7 +8017,7 @@
 	if (ret < 0) {
 		pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
 		       __func__, port, param_hdr.param_id, ret);
-		goto done;
+		goto get_params_fail;
 	}
 
 	ex_vi->pdata = param_hdr;
@@ -8019,6 +8033,8 @@
 		 ex_vi->param.status[SP_V2_SPKR_1],
 		 ex_vi->param.status[SP_V2_SPKR_2]);
 	ret = 0;
+get_params_fail:
+	mutex_unlock(&this_afe.afe_cmd_lock);
 done:
 	return ret;
 }
@@ -8044,6 +8060,7 @@
 		goto done;
 	}
 
+	mutex_lock(&this_afe.afe_cmd_lock);
 	memset(&param_hdr, 0, sizeof(param_hdr));
 
 	param_hdr.module_id = AFE_MODULE_FB_SPKR_PROT_V2_RX;
@@ -8055,7 +8072,7 @@
 	if (ret < 0) {
 		pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
 		       __func__, port_id, param_hdr.param_id, ret);
-		goto done;
+		goto get_params_fail;
 	}
 
 	memcpy(xt_logging, &this_afe.xt_logging_resp.param,
@@ -8069,6 +8086,8 @@
 		 xt_logging->max_temperature[SP_V2_SPKR_2],
 		 xt_logging->count_exceeded_temperature[SP_V2_SPKR_1],
 		 xt_logging->count_exceeded_temperature[SP_V2_SPKR_2]);
+get_params_fail:
+	mutex_unlock(&this_afe.afe_cmd_lock);
 done:
 	return ret;
 }
@@ -8094,6 +8113,7 @@
 		goto exit;
 	}
 
+	mutex_lock(&this_afe.afe_cmd_lock);
 	memset(&param_hdr, 0, sizeof(param_hdr));
 	param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
 	param_hdr.instance_id = INSTANCE_ID_0;
@@ -8104,12 +8124,14 @@
 	if (ret < 0) {
 		pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
 		       __func__, port, param_hdr.param_id, ret);
-		goto exit;
+		goto get_params_fail;
 	}
 
 	memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats,
 	       param_hdr.param_size);
 	ret = 0;
+get_params_fail:
+	mutex_unlock(&this_afe.afe_cmd_lock);
 exit:
 	return ret;
 }
@@ -8135,6 +8157,7 @@
 		goto exit;
 	}
 
+	mutex_lock(&this_afe.afe_cmd_lock);
 	memset(&param_hdr, 0, sizeof(param_hdr));
 	param_hdr.module_id = AUDPROC_MODULE_ID_FFNS;
 	param_hdr.instance_id = INSTANCE_ID_0;
@@ -8145,7 +8168,7 @@
 	if (ret < 0) {
 		pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n",
 			 __func__, port, param_hdr.param_id, ret);
-		goto exit;
+		goto get_params_fail;
 	}
 
 	memcpy(doa_tracking_data, &this_afe.doa_tracking_mon_resp.doa,
@@ -8157,6 +8180,8 @@
 			 __func__, i, doa_tracking_data->interf_angle_L16[i]);
 	}
 
+get_params_fail:
+	mutex_unlock(&this_afe.afe_cmd_lock);
 exit:
 	return ret;
 }
@@ -8175,6 +8200,7 @@
 	if (this_afe.vi_tx_port != -1)
 		port = this_afe.vi_tx_port;
 
+	mutex_lock(&this_afe.afe_cmd_lock);
 	memset(&param_hdr, 0, sizeof(param_hdr));
 	param_hdr.module_id = AFE_MODULE_FB_SPKR_PROT_VI_PROC_V2;
 	param_hdr.instance_id = INSTANCE_ID_0;
@@ -8185,7 +8211,7 @@
 	if (ret < 0) {
 		pr_err("%s: get param port 0x%x param id[0x%x]failed %d\n",
 		       __func__, port, param_hdr.param_id, ret);
-		goto fail_cmd;
+		goto get_params_fail;
 	}
 	memcpy(&calib_resp->res_cfg, &this_afe.calib_data.res_cfg,
 		sizeof(this_afe.calib_data.res_cfg));
@@ -8194,6 +8220,8 @@
 		calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_1],
 		calib_resp->res_cfg.r0_cali_q24[SP_V2_SPKR_2]);
 	ret = 0;
+get_params_fail:
+	mutex_unlock(&this_afe.afe_cmd_lock);
 fail_cmd:
 	return ret;
 }
@@ -9063,7 +9091,8 @@
 	this_afe.mmap_handle = 0;
 	this_afe.vi_tx_port = -1;
 	this_afe.vi_rx_port = -1;
-	this_afe.lpass_hw_core_client_hdl = 0;
+	for (i = 0; i < AFE_LPASS_CORE_HW_VOTE_MAX; i++)
+		this_afe.lpass_hw_core_client_hdl[i] = 0;
 	this_afe.prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
 	this_afe.th_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
 	this_afe.ex_ftm_cfg.mode = MSM_SPKR_PROT_DISABLED;
@@ -9195,7 +9224,7 @@
 	cmd_ptr->hdr.pkt_size = sizeof(hw_vote_cfg);
 	cmd_ptr->hdr.src_port = 0;
 	cmd_ptr->hdr.dest_port = 0;
-	cmd_ptr->hdr.token = 0;
+	cmd_ptr->hdr.token = hw_block_id;
 	cmd_ptr->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST;
 	cmd_ptr->hw_block_id = hw_block_id;
 	strlcpy(cmd_ptr->client_name, client_name,
@@ -9236,9 +9265,9 @@
 		goto done;
 	}
 
-	*client_handle = this_afe.lpass_hw_core_client_hdl;
+	*client_handle = this_afe.lpass_hw_core_client_hdl[hw_block_id];
 	pr_debug("%s: lpass_hw_core_client_hdl %d\n", __func__,
-		this_afe.lpass_hw_core_client_hdl);
+		this_afe.lpass_hw_core_client_hdl[hw_block_id]);
 done:
 	mutex_unlock(&this_afe.afe_cmd_lock);
 	return ret;
@@ -9268,7 +9297,7 @@
 
 	mutex_lock(&this_afe.afe_cmd_lock);
 
-	if (!this_afe.lpass_hw_core_client_hdl) {
+	if (!this_afe.lpass_hw_core_client_hdl[hw_block_id]) {
 		pr_debug("%s: SSR in progress, return\n", __func__);
 		goto done;
 	}
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index 9c5bf3d..d5c8e7e 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -104,8 +104,7 @@
 		if (lsm_session[n] == client)
 			return n;
 	}
-	pr_err("%s: cannot find matching lsm client. client = %pa\n",
-		__func__, client);
+	pr_err("%s: cannot find matching lsm client.\n", __func__);
 	return LSM_INVALID_SESSION_ID;
 }
 
@@ -376,10 +375,10 @@
 		return;
 	}
 	apr_deregister(client->apr);
+	q6lsm_mmap_apr_dereg();
 	client->mmap_apr = NULL;
 	mutex_lock(&session_lock);
 	q6lsm_session_free(client);
-	q6lsm_mmap_apr_dereg();
 	mutex_destroy(&client->cmd_lock);
 	kfree(client);
 	client = NULL;
diff --git a/dsp/q6voice.c b/dsp/q6voice.c
index 6de6686..e0491f1 100644
--- a/dsp/q6voice.c
+++ b/dsp/q6voice.c
@@ -110,6 +110,10 @@
 static int voice_send_set_pp_enable_cmd(
 	struct voice_data *v, struct module_instance_info mod_inst_info,
 	int enable);
+
+static int voice_send_cvp_ecns_enable_cmd(struct voice_data *v,
+	uint32_t module_id, int enable);
+
 static int is_cal_memory_allocated(void);
 static bool is_cvd_version_queried(void);
 static int is_voip_memory_allocated(void);
@@ -1544,6 +1548,124 @@
 	return ret;
 }
 
+static int voice_send_cvp_ecns_enable_cmd(struct voice_data *v,
+	uint32_t module_id, int enable)
+{
+	int ret;
+	struct cvp_set_channel_ecns_cmd_v2 cvp_set_ch_ecns_cmd;
+	void *apr_cvp;
+	u16 cvp_handle;
+	struct vss_icommon_param_data_ecns_t *cvp_config_param_data =
+				&cvp_set_ch_ecns_cmd.
+				cvp_set_ecns.param_data;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	apr_cvp = common.apr_q6_cvp;
+
+	if (!apr_cvp) {
+		pr_err("%s: apr_cvp is NULL\n", __func__);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cvp_handle = voice_get_cvp_handle(v);
+	memset(&cvp_set_ch_ecns_cmd, 0,
+		sizeof(cvp_set_ch_ecns_cmd));
+
+	cvp_set_ch_ecns_cmd.hdr.hdr_field =
+			APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE),
+			APR_PKT_VER);
+	cvp_set_ch_ecns_cmd.hdr.pkt_size =
+			APR_PKT_SIZE(APR_HDR_SIZE,
+			sizeof(cvp_set_ch_ecns_cmd) - APR_HDR_SIZE);
+	cvp_set_ch_ecns_cmd.hdr.src_svc = 0;
+	cvp_set_ch_ecns_cmd.hdr.src_domain = APR_DOMAIN_APPS;
+	cvp_set_ch_ecns_cmd.hdr.src_port =
+			voice_get_idx_for_session(v->session_id);
+	cvp_set_ch_ecns_cmd.hdr.dest_svc = 0;
+	cvp_set_ch_ecns_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+	cvp_set_ch_ecns_cmd.hdr.dest_port = cvp_handle;
+	cvp_set_ch_ecns_cmd.hdr.token = 0;
+	cvp_set_ch_ecns_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
+	cvp_set_ch_ecns_cmd.cvp_set_ecns.mem_size =
+			sizeof(struct vss_icommon_param_data_ecns_t);
+
+	cvp_config_param_data->module_id = module_id;
+	cvp_config_param_data->param_id = VOICE_PARAM_MOD_ENABLE;
+	cvp_config_param_data->param_size = MOD_ENABLE_PARAM_LEN;
+	cvp_config_param_data->reserved = 0;
+	cvp_config_param_data->enable = enable;
+
+	v->cvp_state = CMD_STATUS_FAIL;
+	v->async_err = 0;
+	ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_ch_ecns_cmd);
+
+	if (ret < 0) {
+		pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2 %d\n",
+		       __func__, ret);
+		goto done;
+	}
+	ret = wait_event_timeout(v->cvp_wait,
+				(v->cvp_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -ETIMEDOUT;
+		goto done;
+	}
+
+	if (v->async_err > 0) {
+		pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
+		       adsp_err_get_err_str(v->async_err), cvp_handle);
+		ret = adsp_err_get_lnx_err_code(v->async_err);
+		goto done;
+	}
+	ret = 0;
+done:
+	return ret;
+}
+
+/**
+ * voc_set_ecns_enable -
+ *       Command to set ECNS for voice module
+ *
+ * @session_id: voice session ID to send this command
+ * @module_id: voice module id
+ * @enable: enable/disable flag
+ *
+ * Returns 0 on success or error on failure
+ */
+int voc_set_ecns_enable(uint32_t session_id, uint32_t module_id,
+	 uint32_t enable)
+{
+	struct voice_data *v = voice_get_session(session_id);
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+		return -EINVAL;
+	}
+	mutex_lock(&v->lock);
+	v->ecns_enable = enable;
+	v->ecns_module_id = module_id;
+
+	if (is_voc_state_active(v->voc_state))
+		ret = voice_send_cvp_ecns_enable_cmd(v,
+				v->ecns_module_id, v->ecns_enable);
+
+	mutex_unlock(&v->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(voc_set_ecns_enable);
+
 static int voice_send_set_pp_enable_cmd(
 	struct voice_data *v, struct module_instance_info mod_inst_info,
 	int enable)
@@ -3852,6 +3974,7 @@
 				&cal_block->cal_data.paddr,
 				cal_block->map_data.map_size);
 
+			common.rtac_mem_map_table.dma_buf = NULL;
 			goto done_unlock;
 		}
 	}
@@ -4174,6 +4297,7 @@
 	struct cvp_set_mfc_config_cmd_v2 cvp_set_mfc_config_cmd;
 	void *apr_cvp;
 	u16 cvp_handle;
+	uint8_t ch_idx;
 	struct vss_icommon_param_data_mfc_config_v2_t *cvp_config_param_data =
 		&cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.param_data;
 	struct vss_param_mfc_config_info_t *mfc_config_info =
@@ -4222,9 +4346,15 @@
 	mfc_config_info->num_channels = v->dev_rx.no_of_channels;
 	mfc_config_info->bits_per_sample = 16;
 	mfc_config_info->sample_rate = v->dev_rx.sample_rate;
-	memcpy(&mfc_config_info->channel_type,
-	       v->dev_rx.channel_mapping,
-	       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
+
+	/*
+	 * Do not use memcpy here as channel_type in mfc_config structure is a
+	 * uint16_t array while channel_mapping array of device is of uint8_t
+	 */
+	for (ch_idx = 0; ch_idx < VSS_NUM_CHANNELS_MAX; ch_idx++) {
+		mfc_config_info->channel_type[ch_idx] =
+					v->dev_rx.channel_mapping[ch_idx];
+	}
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	v->async_err = 0;
@@ -4419,6 +4549,10 @@
 	if (v->dtmf_rx_detect_en)
 		voice_send_dtmf_rx_detection_cmd(v, v->dtmf_rx_detect_en);
 
+	if (v->ecns_enable)
+		voice_send_cvp_ecns_enable_cmd(v, v->ecns_module_id,
+			v->ecns_enable);
+
 	if (v->hd_enable)
 		voice_send_hd_cmd(v, v->hd_enable);
 
@@ -5075,6 +5209,9 @@
 	if (v->dtmf_rx_detect_en)
 		voice_send_dtmf_rx_detection_cmd(v, 0);
 
+	if (v->ecns_enable)
+		voice_send_cvp_ecns_enable_cmd(v, v->ecns_module_id, 0);
+
 	/* detach VOCPROC and wait for response from mvm */
 	mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h
index 1f9d64e..f3ee728 100644
--- a/include/asoc/wcd-mbhc-v2.h
+++ b/include/asoc/wcd-mbhc-v2.h
@@ -451,6 +451,8 @@
 };
 
 struct wcd_mbhc_cb {
+	void (*bcs_enable)
+		(struct wcd_mbhc *mbhc, bool bcs_enable);
 	int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on);
 	void (*trim_btn_reg)(struct snd_soc_component *component);
 	void (*compute_impedance)(struct wcd_mbhc *mbhc,
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index d1b4f3c..9e1a0b2 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -483,10 +483,14 @@
 int afe_get_doa_tracking_mon(u16 port_id,
 	struct doa_tracking_mon_param *doa_tracking_data);
 
-#define AFE_LPASS_CORE_HW_BLOCK_ID_NONE                        0
-#define AFE_LPASS_CORE_HW_BLOCK_ID_AVTIMER                     2
-#define AFE_LPASS_CORE_HW_MACRO_BLOCK                          3
-#define AFE_LPASS_CORE_HW_DCODEC_BLOCK                         4
+enum {
+	AFE_LPASS_CORE_HW_BLOCK_ID_NONE,
+	AFE_LPASS_CORE_HW_RSVD,
+	AFE_LPASS_CORE_HW_BLOCK_ID_AVTIMER,
+	AFE_LPASS_CORE_HW_MACRO_BLOCK,
+	AFE_LPASS_CORE_HW_DCODEC_BLOCK,
+	AFE_LPASS_CORE_HW_VOTE_MAX
+};
 
 /* Handles audio-video timer (avtimer) and BTSC vote requests from clients.
  */
diff --git a/include/dsp/q6voice.h b/include/dsp/q6voice.h
index 2edfbe2..35ace4e 100644
--- a/include/dsp/q6voice.h
+++ b/include/dsp/q6voice.h
@@ -312,6 +312,21 @@
 	struct vss_param_channel_mixer_info_t ch_mixer_info;
 } __packed;
 
+struct vss_icommon_param_data_ecns_t {
+	/* Valid ID of the module. */
+	uint32_t module_id;
+	/* Valid ID of the parameter. */
+	uint32_t param_id;
+	/*
+	 * Data size of the structure relating to the param_id/module_id
+	 * combination in uint8_t bytes.
+	 */
+	uint16_t param_size;
+	/* This field must be set to zero. */
+	uint16_t reserved;
+	uint32_t enable;
+} __packed;
+
 struct vss_icommon_cmd_set_param_ch_mixer_v2_t {
 	/*
 	 * Pointer to the unique identifier for an address (physical/virtual).
@@ -338,6 +353,33 @@
 	struct vss_icommon_param_data_ch_mixer_v2_t param_data;
 } __packed;
 
+
+struct vss_icommon_cmd_set_ecns_enable_t {
+	/*
+	 * Pointer to the unique identifier for an address (physical/virtual).
+	 *
+	 * If the parameter data payload is within the message payload
+	 * (in-band), set this field to 0. The parameter data begins at the
+	 * specified data payload address.
+	 *
+	 * If the parameter data is out-of-band, this field is the handle to
+	 * the physical address in the shared memory that holds the parameter
+	 * data.
+	 */
+	uint32_t mem_handle;
+	/*
+	 * Location of the parameter data payload.
+	 *
+	 * The payload is an array of vss_icommon_param_data_t. If the
+	 * mem_handle is 0, this field is ignored.
+	 */
+	uint64_t mem_address;
+	/* Size of the parameter data payload in bytes. */
+	uint32_t mem_size;
+
+	struct vss_icommon_param_data_ecns_t param_data;
+} __packed;
+
 struct vss_icommon_param_data_mfc_config_v2_t {
 	/* Valid ID of the module. */
 	uint32_t module_id;
@@ -809,6 +851,7 @@
 
 #define MODULE_ID_VOICE_MODULE_ST			0x00010EE3
 #define VOICE_PARAM_MOD_ENABLE				0x00010E00
+#define MOD_ENABLE_PARAM_LEN				4
 
 #define VSS_IPLAYBACK_CMD_START				0x000112BD
 /* Start in-call music delivery on the Tx voice path. */
@@ -1679,6 +1722,11 @@
 	struct apr_hdr hdr;
 } __packed;
 
+struct cvp_set_channel_ecns_cmd_v2 {
+	struct apr_hdr hdr;
+	struct vss_icommon_cmd_set_ecns_enable_t cvp_set_ecns;
+} __packed;
+
 struct cvp_set_rx_volume_index_cmd {
 	struct apr_hdr hdr;
 	struct vss_ivocproc_cmd_set_volume_index_t cvp_set_vol_idx;
@@ -1894,6 +1942,10 @@
 
 	bool mic_break_status;
 	struct work_struct voice_mic_break_work;
+
+	uint32_t ecns_enable;
+	uint32_t ecns_module_id;
+
 };
 
 #define MAX_VOC_SESSIONS 8
@@ -2042,6 +2094,8 @@
 int voc_set_route_flag(uint32_t session_id, uint8_t path_dir, uint8_t set);
 uint8_t voc_get_route_flag(uint32_t session_id, uint8_t path_dir);
 bool voc_get_mbd_enable(void);
+int voc_set_ecns_enable(uint32_t session_id, uint32_t module_id,
+			uint32_t enable);
 uint8_t voc_set_mbd_enable(bool enable);
 int voc_enable_dtmf_rx_detection(uint32_t session_id, uint32_t enable);
 void voc_disable_dtmf_det_on_active_sessions(void);
diff --git a/ipc/Android.mk b/ipc/Android.mk
index 62d78d0..3238a79 100644
--- a/ipc/Android.mk
+++ b/ipc/Android.mk
@@ -27,6 +27,10 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_LITO=m
 endif
 
+ifeq ($(call is-board-platform,bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
 ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) $(TRINKET) kona lito bengal sdmshrike),true)
diff --git a/ipc/Kbuild b/ipc/Kbuild
index bb63b6f..bbea673 100644
--- a/ipc/Kbuild
+++ b/ipc/Kbuild
@@ -41,9 +41,9 @@
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
+		include $(AUDIO_ROOT)/config/bengalauto.conf
 		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_SM8150), y)
 		ifdef CONFIG_SND_SOC_SA8155
diff --git a/soc/Android.mk b/soc/Android.mk
index 21d3d0a..9ed83d4 100644
--- a/soc/Android.mk
+++ b/soc/Android.mk
@@ -27,6 +27,10 @@
 AUDIO_SELECT  := CONFIG_SND_SOC_LITO=m
 endif
 
+ifeq ($(call is-board-platform,bengal),true)
+AUDIO_SELECT  := CONFIG_SND_SOC_BENGAL=m
+endif
+
 AUDIO_CHIPSET := audio
 # Build/Package only in case of supported target
 ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) $(TRINKET) kona lito bengal sdmshrike),true)
@@ -56,7 +60,7 @@
 KBUILD_OPTIONS += $(AUDIO_SELECT)
 
 ###########################################################
-ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET) kona lito),true)
+ifeq ($(call is-board-platform-in-list,$(MSMSTEPPE) $(TRINKET) kona lito bengal),true)
 ifneq ($(TARGET_BOARD_AUTO),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_pinctrl_lpi.ko
@@ -98,7 +102,7 @@
 include $(DLKM_DIR)/AndroidKernelModule.mk
 endif
 ###########################################################
-ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) kona lito sdmshrike),true)
+ifeq ($(call is-board-platform-in-list,msmnile $(MSMSTEPPE) kona lito bengal sdmshrike),true)
 ifneq ($(TARGET_PRODUCT), $(filter $(TARGET_PRODUCT), msmnile))
 include $(CLEAR_VARS)
 LOCAL_MODULE              := $(AUDIO_CHIPSET)_snd_event.ko
diff --git a/soc/Kbuild b/soc/Kbuild
index 83bb243..9e32c42 100644
--- a/soc/Kbuild
+++ b/soc/Kbuild
@@ -35,9 +35,9 @@
 		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_BENGAL), y)
-		include $(AUDIO_ROOT)/config/litoauto.conf
+		include $(AUDIO_ROOT)/config/bengalauto.conf
 		export
-		INCS    +=  -include $(AUDIO_ROOT)/config/litoautoconf.h
+		INCS    +=  -include $(AUDIO_ROOT)/config/bengalautoconf.h
 	endif
 	ifeq ($(CONFIG_ARCH_SM6150), y)
 		ifdef CONFIG_SND_SOC_SA6155
diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c
index ba39129..2b9e52e 100644
--- a/soc/pinctrl-lpi.c
+++ b/soc/pinctrl-lpi.c
@@ -112,6 +112,7 @@
 	struct gpio_chip     chip;
 	char __iomem        *base;
 	struct clk          *lpass_core_hw_vote;
+	struct clk          *lpass_audio_hw_vote;
 	struct mutex         slew_access_lock;
 	bool core_hw_vote_status;
 	struct mutex        core_hw_vote_lock;
@@ -626,6 +627,7 @@
 	char __iomem *slew_base;
 	u32 reg, slew_reg;
 	struct clk *lpass_core_hw_vote = NULL;
+	struct clk *lpass_audio_hw_vote = NULL;
 
 	ret = of_property_read_u32(dev->of_node, "reg", &reg);
 	if (ret < 0) {
@@ -796,6 +798,17 @@
 	}
 	state->lpass_core_hw_vote = lpass_core_hw_vote;
 
+	/* Register LPASS audio hw vote */
+	lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
+	if (IS_ERR(lpass_audio_hw_vote)) {
+		ret = PTR_ERR(lpass_audio_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_audio_hw_vote", ret);
+		lpass_audio_hw_vote = NULL;
+		ret = 0;
+	}
+	state->lpass_audio_hw_vote = lpass_audio_hw_vote;
+
 	state->core_hw_vote_status = false;
 	pm_runtime_set_autosuspend_delay(&pdev->dev, LPI_AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
@@ -842,14 +855,19 @@
 {
 	struct lpi_gpio_state *state = dev_get_drvdata(dev);
 	int ret = 0;
+	struct clk *hw_vote = state->lpass_core_hw_vote;
 
 	if (state->lpass_core_hw_vote == NULL) {
 		dev_dbg(dev, "%s: Invalid core hw node\n", __func__);
-		return 0;
+		if (state->lpass_audio_hw_vote == NULL) {
+			dev_dbg(dev, "%s: Invalid audio hw node\n", __func__);
+			return 0;
+		}
+		hw_vote = state->lpass_audio_hw_vote;
 	}
 
 	mutex_lock(&state->core_hw_vote_lock);
-	ret = clk_prepare_enable(state->lpass_core_hw_vote);
+	ret = clk_prepare_enable(hw_vote);
 	if (ret < 0) {
 		pm_runtime_set_autosuspend_delay(dev,
 						 LPI_AUTO_SUSPEND_DELAY_ERROR);
@@ -870,15 +888,20 @@
 int lpi_pinctrl_runtime_suspend(struct device *dev)
 {
 	struct lpi_gpio_state *state = dev_get_drvdata(dev);
+	struct clk *hw_vote = state->lpass_core_hw_vote;
 
 	if (state->lpass_core_hw_vote == NULL) {
 		dev_dbg(dev, "%s: Invalid core hw node\n", __func__);
-		return 0;
+		if (state->lpass_audio_hw_vote == NULL) {
+			dev_dbg(dev, "%s: Invalid audio hw node\n", __func__);
+			return 0;
+		}
+		hw_vote = state->lpass_audio_hw_vote;
 	}
 
 	mutex_lock(&state->core_hw_vote_lock);
 	if (state->core_hw_vote_status) {
-		clk_disable_unprepare(state->lpass_core_hw_vote);
+		clk_disable_unprepare(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 44d245d..242a512 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -25,6 +25,7 @@
 #include "swrm_registers.h"
 #include "swr-mstr-ctrl.h"
 
+#define SWRM_FRAME_SYNC_SEL    4000 /* 4KHz */
 #define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700
 #define SWRM_SYS_SUSPEND_WAIT 1
 
@@ -43,6 +44,14 @@
 #define ERR_AUTO_SUSPEND_TIMER_VAL 0x1
 
 #define SWRM_INTERRUPT_STATUS_MASK 0x1FDFD
+#define SWRM_LINK_STATUS_RETRY_CNT 0x5
+
+#define SWRM_ROW_48    48
+#define SWRM_ROW_50    50
+#define SWRM_ROW_64    64
+#define SWRM_COL_02    02
+#define SWRM_COL_16    16
+
 /* pm runtime auto suspend timer in msecs */
 static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000;
 module_param(auto_suspend_timer, int, 0664);
@@ -306,6 +315,11 @@
 			func, reg[i], val[i]);
 }
 
+static bool is_swr_clk_needed(struct swr_mstr_ctrl *swrm)
+{
+	return ((swrm->version <= SWRM_VERSION_1_5_1) ? true : false);
+}
+
 static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm,
 				int core_type, bool enable)
 {
@@ -341,6 +355,40 @@
 	return ret;
 }
 
+static int swrm_get_ssp_period(struct swr_mstr_ctrl *swrm,
+				int row, int col,
+				int frame_sync)
+{
+	if (!swrm || !row || !col || !frame_sync)
+		return 1;
+
+	return ((swrm->bus_clk * 2) / ((row * col) * frame_sync));
+}
+
+static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm)
+{
+	int ret = 0;
+
+	if (!swrm->handle)
+		return -EINVAL;
+
+	mutex_lock(&swrm->clklock);
+	if (!swrm->dev_up) {
+		ret = -ENODEV;
+		goto exit;
+	}
+	if (swrm->core_vote) {
+		ret = swrm->core_vote(swrm->handle, true);
+		if (ret)
+			dev_err_ratelimited(swrm->dev,
+				"%s: core vote request failed\n", __func__);
+	}
+exit:
+	mutex_unlock(&swrm->clklock);
+
+	return ret;
+}
+
 static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
 {
 	int ret = 0;
@@ -354,13 +402,15 @@
 			ret = -ENODEV;
 			goto exit;
 		}
-		if (swrm->core_vote) {
-			ret = swrm->core_vote(swrm->handle, true);
-			if (ret) {
-				dev_err_ratelimited(swrm->dev,
-					"%s: clock enable req failed",
-					__func__);
-				goto exit;
+		if (is_swr_clk_needed(swrm)) {
+			if (swrm->core_vote) {
+				ret = swrm->core_vote(swrm->handle, true);
+				if (ret) {
+					dev_err_ratelimited(swrm->dev,
+						"%s: core vote request failed\n",
+						__func__);
+					goto exit;
+				}
 			}
 		}
 		swrm->clk_ref_count++;
@@ -397,14 +447,21 @@
 	if (!swrm->dev_up)
 		goto err;
 
-	ret = swrm_clk_request(swrm, TRUE);
-	if (ret) {
-		dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
-				    __func__);
+	if (is_swr_clk_needed(swrm)) {
+		ret = swrm_clk_request(swrm, TRUE);
+		if (ret) {
+			dev_err_ratelimited(swrm->dev,
+					    "%s: clock request failed\n",
+					    __func__);
+			goto err;
+		}
+	} else if (swrm_core_vote_request(swrm)) {
 		goto err;
 	}
+
 	iowrite32(temp, swrm->swrm_dig_base + reg);
-	swrm_clk_request(swrm, FALSE);
+	if (is_swr_clk_needed(swrm))
+		swrm_clk_request(swrm, FALSE);
 err:
 	mutex_unlock(&swrm->devlock);
 	return ret;
@@ -420,15 +477,21 @@
 	if (!swrm->dev_up)
 		goto err;
 
-	ret = swrm_clk_request(swrm, TRUE);
-	if (ret) {
-		dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
-				    __func__);
+	if (is_swr_clk_needed(swrm)) {
+		ret = swrm_clk_request(swrm, TRUE);
+		if (ret) {
+			dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
+					    __func__);
+			goto err;
+		}
+	} else if (swrm_core_vote_request(swrm)) {
 		goto err;
 	}
+
 	temp = ioread32(swrm->swrm_dig_base + reg);
 	*value = temp;
-	swrm_clk_request(swrm, FALSE);
+	if (is_swr_clk_needed(swrm))
+		swrm_clk_request(swrm, FALSE);
 err:
 	mutex_unlock(&swrm->devlock);
 	return ret;
@@ -476,6 +539,34 @@
 	return 0;
 }
 
+static bool swrm_check_link_status(struct swr_mstr_ctrl *swrm, bool active)
+{
+	int retry = SWRM_LINK_STATUS_RETRY_CNT;
+	int ret = false;
+	int status = active ? 0x1 : 0x0;
+	int comp_sts = 0x0;
+
+	if ((swrm->version <= SWRM_VERSION_1_5_1))
+		return true;
+
+	do {
+		comp_sts = swr_master_read(swrm, SWRM_COMP_STATUS) & 0x01;
+		/* check comp status and status requested met */
+		if ((comp_sts && status) || (!comp_sts && !status)) {
+			ret = true;
+			break;
+		}
+		retry--;
+		usleep_range(500, 510);
+	} while (retry);
+
+	if (retry == 0)
+		dev_err(swrm->dev, "%s: link status not %s\n", __func__,
+			active ? "connected" : "disconnected");
+
+	return ret;
+}
+
 static bool swrm_is_port_en(struct swr_master *mstr)
 {
 	return !!(mstr->num_port);
@@ -591,6 +682,10 @@
 		if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) {
 			/* wait 500 us before retry on fifo read failure */
 			usleep_range(500, 505);
+			if (retry_attempt == (MAX_FIFO_RD_FAIL_RETRY - 1)) {
+				swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
+				swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
+			}
 			retry_attempt++;
 			goto retry_read;
 		} else {
@@ -1093,7 +1188,9 @@
 {
 	u8 bank;
 	u32 value, n_row, n_col;
+	u32 row = 0, col = 0;
 	int ret;
+	u8 ssp_period = 0;
 	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
 	int mask = (SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK |
 		    SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK |
@@ -1162,30 +1259,39 @@
 	if (enable) {
 		/* set col = 16 */
 		n_col = SWR_MAX_COL;
+		col = SWRM_COL_16;
 	} else {
 		/*
 		 * Do not change to col = 2 if there are still active ports
 		 */
-		if (!master->num_port)
+		if (!master->num_port) {
 			n_col = SWR_MIN_COL;
-		else
+			col = SWRM_COL_02;
+		} else {
 			n_col = SWR_MAX_COL;
+			col = SWRM_COL_16;
+		}
 	}
 	/* Use default 50 * x, frame shape. Change based on mclk */
 	if (swrm->mclk_freq == MCLK_FREQ_NATIVE) {
 		dev_dbg(swrm->dev, "setting 64 x %d frameshape\n",
 			n_col ? 16 : 2);
 		n_row = SWR_ROW_64;
+		row = SWRM_ROW_64;
 	} else {
 		dev_dbg(swrm->dev, "setting 50 x %d frameshape\n",
 			n_col ? 16 : 2);
 		n_row = SWR_ROW_50;
+		row = SWRM_ROW_50;
 	}
+	ssp_period = swrm_get_ssp_period(swrm, row, col, SWRM_FRAME_SYNC_SEL);
+	dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
+
 	value = swr_master_read(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank));
 	value &= (~mask);
 	value |= ((n_row << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
 		  (n_col << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
-		  (0 << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
+		  ((ssp_period - 1) << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
 	swr_master_write(swrm, SWRM_MCP_FRAME_CTRL_BANK_ADDR(bank), value);
 
 	dev_dbg(swrm->dev, "%s: regaddr: 0x%x, value: 0x%x\n", __func__,
@@ -1607,12 +1713,6 @@
 	struct swr_device *swr_dev;
 	struct swr_master *mstr = &swrm->master;
 
-	if (!swrm->dev_up || swrm->state == SWR_MSTR_SSR) {
-		complete(&swrm->broadcast);
-		dev_dbg(swrm->dev, "%s swrm is not up\n", __func__);
-		return IRQ_NONE;
-	}
-
 	if (unlikely(swrm_lock_sleep(swrm) == false)) {
 		dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__);
 		return IRQ_NONE;
@@ -1684,6 +1784,7 @@
 			break;
 		case SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS:
 			status = swr_master_read(swrm, SWRM_MCP_SLV_STATUS);
+			swrm_enable_slave_irq(swrm);
 			if (status == swrm->slave_status) {
 				dev_dbg(swrm->dev,
 					"%s: No change in slave status: %d\n",
@@ -1732,6 +1833,7 @@
 		case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
 			dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n",
 				__func__);
+			swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
 			break;
 		case SWRM_INTERRUPT_STATUS_CMD_ERROR:
 			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
@@ -1767,6 +1869,7 @@
 		case SWRM_INTERRUPT_STATUS_AUTO_ENUM_TABLE_IS_FULL_V2:
 			break;
 		case SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2:
+			swrm_check_link_status(swrm, 0x1);
 			break;
 		case SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED_V2:
 			break;
@@ -1828,10 +1931,21 @@
 		pr_err("%s: swrm or dev is null\n", __func__);
 		return IRQ_NONE;
 	}
+
 	mutex_lock(&swrm->devlock);
 	if (!swrm->dev_up) {
-		if (swrm->wake_irq > 0)
-			disable_irq_nosync(swrm->wake_irq);
+		if (swrm->wake_irq > 0) {
+			if (unlikely(!irq_get_irq_data(swrm->wake_irq))) {
+				pr_err("%s: irq data is NULL\n", __func__);
+				mutex_unlock(&swrm->devlock);
+				return IRQ_NONE;
+			}
+			mutex_lock(&swrm->irq_lock);
+			if (!irqd_irq_disabled(
+			    irq_get_irq_data(swrm->wake_irq)))
+				disable_irq_nosync(swrm->wake_irq);
+			mutex_unlock(&swrm->irq_lock);
+		}
 		mutex_unlock(&swrm->devlock);
 		return ret;
 	}
@@ -1840,8 +1954,17 @@
 		dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__);
 		goto exit;
 	}
-	if (swrm->wake_irq > 0)
-		disable_irq_nosync(swrm->wake_irq);
+	if (swrm->wake_irq > 0) {
+		if (unlikely(!irq_get_irq_data(swrm->wake_irq))) {
+			pr_err("%s: irq data is NULL\n", __func__);
+			return IRQ_NONE;
+		}
+		mutex_lock(&swrm->irq_lock);
+		if (!irqd_irq_disabled(
+		    irq_get_irq_data(swrm->wake_irq)))
+			disable_irq_nosync(swrm->wake_irq);
+		mutex_unlock(&swrm->irq_lock);
+	}
 	pm_runtime_get_sync(swrm->dev);
 	pm_runtime_mark_last_busy(swrm->dev);
 	pm_runtime_put_autosuspend(swrm->dev);
@@ -2022,12 +2145,17 @@
 	u8 retry_cmd_num = 3;
 	u32 reg[SWRM_MAX_INIT_REG];
 	u32 value[SWRM_MAX_INIT_REG];
+	u32 temp = 0;
 	int len = 0;
 
+	ssp_period = swrm_get_ssp_period(swrm, SWRM_ROW_50,
+					SWRM_COL_02, SWRM_FRAME_SYNC_SEL);
+	dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period);
+
 	/* Clear Rows and Cols */
 	val = ((row_ctrl << SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_SHFT) |
 		(col_ctrl << SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_SHFT) |
-		(ssp_period << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
+		((ssp_period - 1) << SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_SHFT));
 
 	reg[len] = SWRM_MCP_FRAME_CTRL_BANK_ADDR(0);
 	value[len++] = val;
@@ -2071,15 +2199,30 @@
 
 	swr_master_bulk_write(swrm, reg, value, len);
 
+	if (!swrm_check_link_status(swrm, 0x1)) {
+		dev_err(swrm->dev,
+			"%s: swr link failed to connect\n",
+			__func__);
+		return -EINVAL;
+	}
 	/*
 	 * For SWR master version 1.5.1, continue
 	 * execute on command ignore.
 	 */
-	if (swrm->version == SWRM_VERSION_1_5_1)
+	/* Execute it for versions >= 1.5.1 */
+	if (swrm->version >= SWRM_VERSION_1_5_1)
 		swr_master_write(swrm, SWRM_CMD_FIFO_CFG_ADDR,
 				(swr_master_read(swrm,
 					SWRM_CMD_FIFO_CFG_ADDR) | 0x80000000));
 
+	/* SW workaround to gate hw_ctl for SWR version >=1.6 */
+	if (swrm->version >= SWRM_VERSION_1_6) {
+		if (swrm->swrm_hctl_reg) {
+			temp = ioread32(swrm->swrm_hctl_reg);
+			temp &= 0xFFFFFFFD;
+			iowrite32(temp, swrm->swrm_hctl_reg);
+		}
+	}
 	return ret;
 }
 
@@ -2129,7 +2272,7 @@
 {
 	struct swr_mstr_ctrl *swrm;
 	struct swr_ctrl_platform_data *pdata;
-	u32 i, num_ports, port_num, port_type, ch_mask;
+	u32 i, num_ports, port_num, port_type, ch_mask, swrm_hctl_reg = 0;
 	u32 *temp, map_size, map_length, ch_iter = 0, old_port_num = 0;
 	int ret = 0;
 	struct clk *lpass_core_hw_vote = NULL;
@@ -2198,6 +2341,10 @@
 	}
 
 	swrm->core_vote = pdata->core_vote;
+	if (!(of_property_read_u32(pdev->dev.of_node,
+			"qcom,swrm-hctl-reg", &swrm_hctl_reg)))
+		swrm->swrm_hctl_reg = devm_ioremap(&pdev->dev,
+						swrm_hctl_reg, 0x4);
 	swrm->clk = pdata->clk;
 	if (!swrm->clk) {
 		dev_err(&pdev->dev, "%s: swrm->clk is NULL\n",
@@ -2295,6 +2442,7 @@
 	swrm->clk_ref_count = 0;
 	swrm->swr_irq_wakeup_capable = 0;
 	swrm->mclk_freq = MCLK_FREQ;
+	swrm->bus_clk = MCLK_FREQ;
 	swrm->dev_up = true;
 	swrm->state = SWR_MSTR_UP;
 	swrm->ipc_wakeup = false;
@@ -2302,6 +2450,7 @@
 	init_completion(&swrm->reset);
 	init_completion(&swrm->broadcast);
 	init_completion(&swrm->clk_off_complete);
+	mutex_init(&swrm->irq_lock);
 	mutex_init(&swrm->mlock);
 	mutex_init(&swrm->reslock);
 	mutex_init(&swrm->force_down_lock);
@@ -2448,6 +2597,7 @@
 	else if (swrm->irq)
 		free_irq(swrm->irq, swrm);
 err_irq_fail:
+	mutex_destroy(&swrm->irq_lock);
 	mutex_destroy(&swrm->mlock);
 	mutex_destroy(&swrm->reslock);
 	mutex_destroy(&swrm->force_down_lock);
@@ -2480,6 +2630,7 @@
 	swr_unregister_master(&swrm->master);
 	msm_aud_evt_unregister_client(&swrm->event_notifier);
 	device_init_wakeup(swrm->dev, false);
+	mutex_destroy(&swrm->irq_lock);
 	mutex_destroy(&swrm->mlock);
 	mutex_destroy(&swrm->reslock);
 	mutex_destroy(&swrm->iolock);
@@ -2534,6 +2685,20 @@
 	if ((swrm->state == SWR_MSTR_DOWN) ||
 	    (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) {
 		if (swrm->clk_stop_mode0_supp) {
+			if (swrm->wake_irq > 0) {
+				if (unlikely(!irq_get_irq_data
+				    (swrm->wake_irq))) {
+					pr_err("%s: irq data is NULL\n",
+						__func__);
+					mutex_unlock(&swrm->reslock);
+					return IRQ_NONE;
+				}
+				mutex_lock(&swrm->irq_lock);
+				if (!irqd_irq_disabled(
+				    irq_get_irq_data(swrm->wake_irq)))
+					disable_irq_nosync(swrm->wake_irq);
+				mutex_unlock(&swrm->irq_lock);
+			}
 			if (swrm->ipc_wakeup)
 				msm_aud_evt_blocking_notifier_call_chain(
 					SWR_WAKE_IRQ_DEREGISTER, (void *)swrm);
@@ -2568,6 +2733,8 @@
 			swrm_master_init(swrm);
 			/* wait for hw enumeration to complete */
 			usleep_range(100, 105);
+			if (!swrm_check_link_status(swrm, 0x1))
+				goto exit;
 			swrm_cmd_fifo_wr_cmd(swrm, 0x4, 0xF, 0x0,
 						SWRS_SCP_INT_STATUS_MASK_1);
 			if (swrm->state == SWR_MSTR_SSR) {
@@ -2578,7 +2745,17 @@
 		} else {
 			/*wake up from clock stop*/
 			swr_master_write(swrm, SWRM_MCP_BUS_CTRL_ADDR, 0x2);
+			/* clear and enable bus clash interrupt */
+			swr_master_write(swrm, SWRM_INTERRUPT_CLEAR, 0x08);
+			swrm->intr_mask |= 0x08;
+			swr_master_write(swrm, SWRM_INTERRUPT_MASK_ADDR,
+					 swrm->intr_mask);
+			swr_master_write(swrm,
+					 SWR_MSTR_RX_SWRM_CPU_INTERRUPT_EN,
+					 swrm->intr_mask);
 			usleep_range(100, 105);
+			if (!swrm_check_link_status(swrm, 0x1))
+				goto exit;
 		}
 		swrm->state = SWR_MSTR_UP;
 	}
@@ -2657,6 +2834,13 @@
 				}
 			}
 		} else {
+			/* Mask bus clash interrupt */
+			swrm->intr_mask &= ~((u32)0x08);
+			swr_master_write(swrm, SWRM_INTERRUPT_MASK_ADDR,
+					 swrm->intr_mask);
+			swr_master_write(swrm,
+					 SWR_MSTR_RX_SWRM_CPU_INTERRUPT_EN,
+					 swrm->intr_mask);
 			mutex_unlock(&swrm->reslock);
 			/* clock stop sequence */
 			swrm_cmd_fifo_wr_cmd(swrm, 0x2, 0xF, 0xF,
@@ -2664,6 +2848,8 @@
 			mutex_lock(&swrm->reslock);
 			usleep_range(100, 105);
 		}
+		if (!swrm_check_link_status(swrm, 0x0))
+			goto exit;
 		ret = swrm_clk_request(swrm, false);
 		if (ret) {
 			dev_err(dev, "%s: swrmn clk failed\n", __func__);
@@ -2866,8 +3052,15 @@
 						__func__, swrm->state);
 				else
 					swrm_device_suspend(&pdev->dev);
+				/*
+				 * add delay to ensure clk release happen
+				 * if interrupt triggered for clk stop,
+				 * wait for it to exit
+				 */
+				usleep_range(10000, 10500);
 			}
 			swrm->mclk_freq = *(int *)data;
+			swrm->bus_clk = swrm->mclk_freq;
 			mutex_unlock(&swrm->mlock);
 		}
 		break;
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index 321e84f..654dd0e 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -38,6 +38,7 @@
 #define SWRM_VERSION_1_3 0x01040000
 #define SWRM_VERSION_1_5 0x01050000
 #define SWRM_VERSION_1_5_1 0x01050001
+#define SWRM_VERSION_1_6   0x01060000
 
 #define SWR_MAX_CH_PER_PORT 8
 
@@ -123,8 +124,10 @@
 	struct mutex mlock;
 	struct mutex reslock;
 	struct mutex pm_lock;
+	struct mutex irq_lock;
 	u32 swrm_base_reg;
 	char __iomem *swrm_dig_base;
+	char __iomem *swrm_hctl_reg;
 	u8 rcmd_id;
 	u8 wcmd_id;
 	u32 master_id;
@@ -140,6 +143,7 @@
 	int wake_irq;
 	int version;
 	int mclk_freq;
+	int bus_clk;
 	u32 num_dev;
 	int slave_status;
 	struct swrm_mports mport_cfg[SWR_MAX_MSTR_PORT_NUM];
diff --git a/soc/swrm_registers.h b/soc/swrm_registers.h
index 6f2544b..63fe4ca 100644
--- a/soc/swrm_registers.h
+++ b/soc/swrm_registers.h
@@ -17,6 +17,7 @@
 #define SWRM_COMP_CFG_ENABLE_SHFT			0x0
 
 #define SWRM_COMP_SW_RESET		(SWRM_BASE_ADDRESS+0x00000008)
+#define SWRM_COMP_STATUS		(SWRM_BASE_ADDRESS+0x00000014)
 
 #define SWRM_COMP_PARAMS		(SWRM_BASE_ADDRESS+0x100)
 #define SWRM_COMP_PARAMS_DOUT_PORTS_MASK	0x0000001F