Merge "asoc: sm6150: Add support for audio over display port"
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 749f87b..5001b7f 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -18,7 +18,7 @@
 #include <linux/printk.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
-
+#include <soc/snd_event.h>
 #include "bolero-cdc.h"
 #include "internal.h"
 
@@ -26,6 +26,7 @@
 #define BOLERO_VERSION_1_1 0x0002
 #define BOLERO_VERSION_1_2 0x0003
 #define BOLERO_VERSION_ENTRY_SIZE 32
+#define BOLERO_CDC_STRING_LEN 80
 
 static struct snd_soc_codec_driver bolero;
 
@@ -61,6 +62,11 @@
 	u16 current_mclk_mux_macro;
 
 	mutex_lock(&priv->clk_lock);
+	if (!priv->dev_up) {
+		dev_dbg_ratelimited(priv->dev,
+			"%s: SSR in progress, exit\n", __func__);
+		goto err;
+	}
 	current_mclk_mux_macro =
 		priv->current_mclk_mux_macro[macro_id];
 	if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) {
@@ -93,6 +99,11 @@
 	u16 current_mclk_mux_macro;
 
 	mutex_lock(&priv->clk_lock);
+	if (!priv->dev_up) {
+		dev_dbg_ratelimited(priv->dev,
+			"%s: SSR in progress, exit\n", __func__);
+		goto err;
+	}
 	current_mclk_mux_macro =
 		priv->current_mclk_mux_macro[macro_id];
 	if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) {
@@ -118,6 +129,65 @@
 	return ret;
 }
 
+static int bolero_cdc_update_wcd_event(void *handle, u16 event, u32 data)
+{
+	struct bolero_priv *priv = (struct bolero_priv *)handle;
+
+	if (!priv) {
+		pr_err("%s:Invalid bolero priv handle\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case WCD_BOLERO_EVT_RX_MUTE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(priv->codec,
+				BOLERO_MACRO_EVT_RX_MUTE, data);
+		break;
+	case WCD_BOLERO_EVT_IMPED_TRUE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(priv->codec,
+				BOLERO_MACRO_EVT_IMPED_TRUE, data);
+		break;
+	case WCD_BOLERO_EVT_IMPED_FALSE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(priv->codec,
+				BOLERO_MACRO_EVT_IMPED_FALSE, data);
+		break;
+	default:
+		dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n",
+			__func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int bolero_cdc_register_notifier(void *handle,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct bolero_priv *priv = (struct bolero_priv *)handle;
+
+	if (!priv) {
+		pr_err("%s: bolero priv is null\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		return blocking_notifier_chain_register(&priv->notifier,
+							nblock);
+
+	return blocking_notifier_chain_unregister(&priv->notifier,
+						  nblock);
+}
+
+static void bolero_cdc_notifier_call(struct bolero_priv *priv,
+				     u32 data)
+{
+	dev_dbg(priv->dev, "%s: notifier call, data:%d\n", __func__, data);
+	blocking_notifier_call_chain(&priv->notifier,
+				     data, (void *)priv->wcd_dev);
+}
+
 static bool bolero_is_valid_macro_dev(struct device *dev)
 {
 	if (of_device_is_compatible(dev->parent->of_node, "qcom,bolero-codec"))
@@ -135,6 +205,46 @@
 }
 
 /**
+ * bolero_clear_amic_tx_hold - clears AMIC register on analog codec
+ *
+ * @dev: bolero device ptr.
+ *
+ */
+void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n)
+{
+	struct bolero_priv *priv;
+	u16 event;
+	u16 amic = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return;
+	}
+
+	if (!bolero_is_valid_codec_dev(dev)) {
+		pr_err("%s: invalid codec\n", __func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+	event = BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR;
+	if (adc_n == BOLERO_ADC0)
+		amic = 0x1;
+	else if (adc_n == BOLERO_ADC2)
+		amic = 0x2;
+	else if (adc_n == BOLERO_ADC3)
+		amic = 0x3;
+	else
+		return;
+
+	bolero_cdc_notifier_call(priv, (amic << 0x10 | event));
+}
+EXPORT_SYMBOL(bolero_clear_amic_tx_hold);
+
+/**
  * bolero_get_device_ptr - Get child or macro device ptr
  *
  * @dev: bolero device ptr.
@@ -230,6 +340,7 @@
 	priv->macro_params[macro_id].num_dais = ops->num_dais;
 	priv->macro_params[macro_id].dai_ptr = ops->dai_ptr;
 	priv->macro_params[macro_id].mclk_fn = ops->mclk_fn;
+	priv->macro_params[macro_id].event_handler = ops->event_handler;
 	priv->macro_params[macro_id].dev = dev;
 	priv->current_mclk_mux_macro[macro_id] =
 				bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
@@ -237,7 +348,7 @@
 	priv->num_macros_registered++;
 	priv->macros_supported[macro_id] = true;
 
-	if (priv->num_macros_registered == priv->child_num) {
+	if (priv->num_macros_registered == priv->num_macros) {
 		ret = bolero_copy_dais_from_macro(priv);
 		if (ret < 0) {
 			dev_err(dev, "%s: copy_dais failed\n", __func__);
@@ -290,12 +401,13 @@
 	priv->macro_params[macro_id].num_dais = 0;
 	priv->macro_params[macro_id].dai_ptr = NULL;
 	priv->macro_params[macro_id].mclk_fn = NULL;
+	priv->macro_params[macro_id].event_handler = NULL;
 	priv->macro_params[macro_id].dev = NULL;
 	priv->num_dais -= priv->macro_params[macro_id].num_dais;
 	priv->num_macros_registered--;
 
 	/* UNREGISTER CODEC HERE */
-	if (priv->child_num - 1 == priv->num_macros_registered)
+	if (priv->num_macros - 1 == priv->num_macros_registered)
 		snd_soc_unregister_codec(dev->parent);
 }
 EXPORT_SYMBOL(bolero_unregister_macro);
@@ -427,10 +539,64 @@
 	return simple_read_from_buffer(buf, count, &pos, buffer, len);
 }
 
+static int bolero_ssr_enable(struct device *dev, void *data)
+{
+	struct bolero_priv *priv = data;
+	int macro_idx;
+
+	if (priv->initial_boot) {
+		priv->initial_boot = false;
+		return 0;
+	}
+
+	if (priv->macro_params[VA_MACRO].event_handler)
+		priv->macro_params[VA_MACRO].event_handler(priv->codec,
+			BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET, 0x0);
+
+	regcache_cache_only(priv->regmap, 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)
+			continue;
+		priv->macro_params[macro_idx].event_handler(priv->codec,
+			BOLERO_MACRO_EVT_SSR_UP, 0x0);
+	}
+	mutex_lock(&priv->clk_lock);
+	priv->dev_up = true;
+	mutex_unlock(&priv->clk_lock);
+	bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_SSR_UP);
+	return 0;
+}
+
+static void bolero_ssr_disable(struct device *dev, void *data)
+{
+	struct bolero_priv *priv = data;
+	int macro_idx;
+
+	regcache_cache_only(priv->regmap, true);
+
+	mutex_lock(&priv->clk_lock);
+	priv->dev_up = false;
+	mutex_unlock(&priv->clk_lock);
+	/* 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)
+			continue;
+		priv->macro_params[macro_idx].event_handler(priv->codec,
+			BOLERO_MACRO_EVT_SSR_DOWN, 0x0);
+	}
+	bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_SSR_DOWN);
+}
+
 static struct snd_info_entry_ops bolero_info_ops = {
 	.read = bolero_version_read,
 };
 
+static const struct snd_event_ops bolero_ssr_ops = {
+	.enable = bolero_ssr_enable,
+	.disable = bolero_ssr_disable,
+};
+
 /*
  * bolero_info_create_codec_entry - creates bolero module
  * @codec_root: The parent directory
@@ -521,6 +687,16 @@
 	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) {
+		snd_event_notify(priv->dev, SND_EVENT_UP);
+	} else {
+		dev_err(codec->dev,
+			"%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+		goto err;
+	}
+
 	dev_dbg(codec->dev, "%s: bolero soc codec probe success\n", __func__);
 err:
 	return ret;
@@ -531,6 +707,7 @@
 	struct bolero_priv *priv = dev_get_drvdata(codec->dev);
 	int macro_idx;
 
+	snd_event_client_deregister(priv->dev);
 	/* call exit for supported macros */
 	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++)
 		if (priv->macro_params[macro_idx].exit)
@@ -555,7 +732,12 @@
 static void bolero_add_child_devices(struct work_struct *work)
 {
 	struct bolero_priv *priv;
-	int rc;
+	bool wcd937x_node = false;
+	struct platform_device *pdev;
+	struct device_node *node;
+	int ret = 0, count = 0;
+	struct wcd_ctrl_platform_data *platdata = NULL;
+	char plat_dev_name[BOLERO_CDC_STRING_LEN] = "";
 
 	priv = container_of(work, struct bolero_priv,
 			    bolero_add_child_devices_work);
@@ -569,12 +751,53 @@
 			__func__);
 		return;
 	}
-	rc = of_platform_populate(priv->dev->of_node, NULL, NULL, priv->dev);
-	if (rc)
-		dev_err(priv->dev, "%s: failed to add child nodes, rc=%d\n",
-			__func__, rc);
-	else
-		dev_dbg(priv->dev, "%s: added child node\n", __func__);
+
+	platdata = &priv->plat_data;
+	priv->child_count = 0;
+
+	for_each_available_child_of_node(priv->dev->of_node, node) {
+		wcd937x_node = false;
+		if (strnstr(node->name, "wcd937x", strlen("wcd937x")) != NULL)
+			wcd937x_node = true;
+
+		strlcpy(plat_dev_name, node->name,
+				(BOLERO_CDC_STRING_LEN - 1));
+
+		pdev = platform_device_alloc(plat_dev_name, -1);
+		if (!pdev) {
+			dev_err(priv->dev, "%s: pdev memory alloc failed\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err;
+		}
+		pdev->dev.parent = priv->dev;
+		pdev->dev.of_node = node;
+
+		if (wcd937x_node) {
+			priv->dev->platform_data = platdata;
+			priv->wcd_dev = &pdev->dev;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s: Cannot add platform device\n",
+				__func__);
+			platform_device_put(pdev);
+			goto fail_pdev_add;
+		}
+
+		if (priv->child_count < BOLERO_CDC_CHILD_DEVICES_MAX)
+			priv->pdev_child_devices[priv->child_count++] = pdev;
+		else
+			goto err;
+	}
+	return;
+fail_pdev_add:
+	for (count = 0; count < priv->child_count; count++)
+		platform_device_put(priv->pdev_child_devices[count]);
+err:
+	return;
 }
 
 static int bolero_probe(struct platform_device *pdev)
@@ -595,11 +818,11 @@
 			__func__);
 		return ret;
 	}
-	priv->child_num = num_macros;
-	if (priv->child_num > MAX_MACRO) {
+	priv->num_macros = num_macros;
+	if (priv->num_macros > MAX_MACRO) {
 		dev_err(&pdev->dev,
-			"%s:child_num(%d) > MAX_MACRO(%d) than supported\n",
-			__func__, priv->child_num, MAX_MACRO);
+			"%s:num_macros(%d) > MAX_MACRO(%d) than supported\n",
+			__func__, priv->num_macros, MAX_MACRO);
 		return -EINVAL;
 	}
 	priv->va_without_decimation = of_property_read_bool(pdev->dev.of_node,
@@ -608,6 +831,8 @@
 		bolero_reg_access[VA_MACRO] = bolero_va_top_reg_access;
 
 	priv->dev = &pdev->dev;
+	priv->dev_up = true;
+	priv->initial_boot = true;
 	priv->regmap = bolero_regmap_init(priv->dev,
 					  &bolero_regmap_config);
 	if (IS_ERR_OR_NULL((void *)(priv->regmap))) {
@@ -617,6 +842,10 @@
 	priv->read_dev = __bolero_reg_read;
 	priv->write_dev = __bolero_reg_write;
 
+	priv->plat_data.handle = (void *) priv;
+	priv->plat_data.update_wcd_event = bolero_cdc_update_wcd_event;
+	priv->plat_data.register_notifier = bolero_cdc_register_notifier;
+
 	dev_set_drvdata(&pdev->dev, priv);
 	mutex_init(&priv->io_lock);
 	mutex_init(&priv->clk_lock);
diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h
index f7e95ee..aa52491 100644
--- a/asoc/codecs/bolero/bolero-cdc.h
+++ b/asoc/codecs/bolero/bolero-cdc.h
@@ -31,6 +31,23 @@
 	MCLK_MUX_MAX
 };
 
+enum {
+	BOLERO_ADC0 = 1,
+	BOLERO_ADC1,
+	BOLERO_ADC2,
+	BOLERO_ADC3,
+	BOLERO_ADC_MAX
+};
+
+enum {
+	BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
+	BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */
+	BOLERO_MACRO_EVT_IMPED_FALSE, /* for imped false */
+	BOLERO_MACRO_EVT_SSR_DOWN,
+	BOLERO_MACRO_EVT_SSR_UP,
+	BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET
+};
+
 struct macro_ops {
 	int (*init)(struct snd_soc_codec *codec);
 	int (*exit)(struct snd_soc_codec *codec);
@@ -38,6 +55,8 @@
 	struct device *dev;
 	struct snd_soc_dai_driver *dai_ptr;
 	int (*mclk_fn)(struct device *dev, bool enable);
+	int (*event_handler)(struct snd_soc_codec *codec, u16 event,
+			     u32 data);
 	char __iomem *io_base;
 };
 
@@ -52,6 +71,7 @@
 int bolero_info_create_codec_entry(
 		struct snd_info_entry *codec_root,
 		struct snd_soc_codec *codec);
+void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n);
 #else
 static inline int bolero_register_macro(struct device *dev,
 					u16 macro_id,
@@ -83,5 +103,9 @@
 {
 	return 0;
 }
+
+static inline void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n)
+{
+}
 #endif /* CONFIG_SND_SOC_BOLERO */
 #endif /* BOLERO_CDC_H */
diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h
index 2979ee0..0129c39 100644
--- a/asoc/codecs/bolero/internal.h
+++ b/asoc/codecs/bolero/internal.h
@@ -15,6 +15,15 @@
 
 #include "bolero-cdc-registers.h"
 
+#define BOLERO_CDC_CHILD_DEVICES_MAX 5
+
+/* from bolero to WCD events */
+enum {
+	BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
+	BOLERO_WCD_EVT_SSR_DOWN,
+	BOLERO_WCD_EVT_SSR_UP,
+};
+
 enum {
 	REG_NO_ACCESS,
 	RD_REG,
@@ -22,6 +31,21 @@
 	RD_WR_REG
 };
 
+/* from WCD to bolero events */
+enum {
+	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 */
+};
+
+struct wcd_ctrl_platform_data {
+	void *handle;
+	int (*update_wcd_event)(void *handle, u16 event, u32 data);
+	int (*register_notifier)(void *handle,
+				 struct notifier_block *nblock,
+				 bool enable);
+};
+
 struct bolero_priv {
 	struct device *dev;
 	struct snd_soc_codec *codec;
@@ -30,11 +54,13 @@
 	struct mutex clk_lock;
 	bool va_without_decimation;
 	bool macros_supported[MAX_MACRO];
+	bool dev_up;
+	bool initial_boot;
 	struct macro_ops macro_params[MAX_MACRO];
 	struct snd_soc_dai_driver *bolero_dais;
 	u16 num_dais;
 	u16 num_macros_registered;
-	u16 child_num;
+	u16 num_macros;
 	u16 current_mclk_mux_macro[MAX_MACRO];
 	struct work_struct bolero_add_child_devices_work;
 	u32 version;
@@ -47,6 +73,12 @@
 			u16 macro_id, u16 reg, u8 *val);
 	int (*write_dev)(struct bolero_priv *priv,
 			 u16 macro_id, u16 reg, u8 val);
+	struct platform_device *pdev_child_devices
+			[BOLERO_CDC_CHILD_DEVICES_MAX];
+	u16 child_count;
+	struct wcd_ctrl_platform_data plat_data;
+	struct device *wcd_dev;
+	struct blocking_notifier_head notifier;
 };
 
 struct regmap *bolero_regmap_init(struct device *dev,
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index 006f863..6c936cb 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -75,6 +75,107 @@
 #define RX_MACRO_RX_PATH_OFFSET 0x80
 #define RX_MACRO_COMP_OFFSET 0x40
 
+#define MAX_IMPED_PARAMS 6
+
+struct wcd_imped_val {
+	u32 imped_val;
+	u8 index;
+};
+
+static const struct wcd_imped_val imped_index[] = {
+	{4, 0},
+	{5, 1},
+	{6, 2},
+	{7, 3},
+	{8, 4},
+	{9, 5},
+	{10, 6},
+	{11, 7},
+	{12, 8},
+	{13, 9},
+};
+
+struct rx_macro_reg_mask_val {
+	u16 reg;
+	u8 mask;
+	u8 val;
+};
+
+static const struct rx_macro_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf2},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf4},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf7},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xf9},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfa},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfb},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfc},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x00},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x00},
+	},
+	{
+		{BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX0_RX_PATH_SEC1, 0x01, 0x01},
+		{BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0xff, 0xfd},
+		{BOLERO_CDC_RX_RX1_RX_PATH_SEC1, 0x01, 0x01},
+	},
+};
+
 enum {
 	INTERP_HPHL,
 	INTERP_HPHR,
@@ -160,6 +261,12 @@
 	{176400, 0xB}, {352800, 0xC},
 };
 
+struct rx_macro_bcl_pmic_params {
+	u8 id;
+	u8 sid;
+	u8 ppid;
+};
+
 static int rx_macro_hw_params(struct snd_pcm_substream *substream,
 			       struct snd_pcm_hw_params *params,
 			       struct snd_soc_dai *dai);
@@ -258,6 +365,9 @@
 	struct platform_device *pdev_child_devices
 			[RX_MACRO_CHILD_DEVICES_MAX];
 	int child_count;
+	int is_softclip_on;
+	int softclip_clk_users;
+	struct rx_macro_bcl_pmic_params bcl_pmic_params;
 };
 
 static struct snd_soc_dai_driver rx_macro_dai[];
@@ -321,6 +431,14 @@
 static const struct soc_enum rx_macro_ear_mode_enum =
 	SOC_ENUM_SINGLE_EXT(2, rx_macro_ear_mode_text);
 
+static const char * const rx_macro_vbat_bcl_gsm_mode_text[] = {"OFF", "ON"};
+static const struct soc_enum rx_macro_vbat_bcl_gsm_mode_enum =
+	SOC_ENUM_SINGLE_EXT(2, rx_macro_vbat_bcl_gsm_mode_text);
+
+static const struct snd_kcontrol_new rx_int2_1_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("RX AUX VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
 RX_MACRO_DAPM_ENUM(rx_int0_2, BOLERO_CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
 		rx_int_mix_mux_text);
 RX_MACRO_DAPM_ENUM(rx_int1_2, BOLERO_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
@@ -477,6 +595,80 @@
 	},
 };
 
+static int get_impedance_index(int imped)
+{
+	int i = 0;
+
+	if (imped < imped_index[i].imped_val) {
+		pr_debug("%s, detected impedance is less than %d Ohm\n",
+			__func__, imped_index[i].imped_val);
+		i = 0;
+		goto ret;
+	}
+	if (imped >= imped_index[ARRAY_SIZE(imped_index) - 1].imped_val) {
+		pr_debug("%s, detected impedance is greater than %d Ohm\n",
+			__func__,
+			imped_index[ARRAY_SIZE(imped_index) - 1].imped_val);
+		i = ARRAY_SIZE(imped_index) - 1;
+		goto ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(imped_index) - 1; i++) {
+		if (imped >= imped_index[i].imped_val &&
+			imped < imped_index[i + 1].imped_val)
+			break;
+	}
+ret:
+	pr_debug("%s: selected impedance index = %d\n",
+			__func__, imped_index[i].index);
+	return imped_index[i].index;
+}
+
+/*
+ * rx_macro_wcd_clsh_imped_config -
+ * This function updates HPHL and HPHR gain settings
+ * according to the impedance value.
+ *
+ * @codec: codec pointer handle
+ * @imped: impedance value of HPHL/R
+ * @reset: bool variable to reset registers when teardown
+ */
+static void rx_macro_wcd_clsh_imped_config(struct snd_soc_codec *codec,
+					   int imped, bool reset)
+{
+	int i;
+	int index = 0;
+	int table_size;
+
+	static const struct rx_macro_reg_mask_val
+				(*imped_table_ptr)[MAX_IMPED_PARAMS];
+
+	table_size = ARRAY_SIZE(imped_table);
+	imped_table_ptr = imped_table;
+	/* reset = 1, which means request is to reset the register values */
+	if (reset) {
+		for (i = 0; i < MAX_IMPED_PARAMS; i++)
+			snd_soc_update_bits(codec,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask, 0);
+		return;
+	}
+	index = get_impedance_index(imped);
+	if (index >= (ARRAY_SIZE(imped_index) - 1)) {
+		pr_debug("%s, impedance not in range = %d\n", __func__, imped);
+		return;
+	}
+	if (index >= table_size) {
+		pr_debug("%s, impedance index not in range = %d\n", __func__,
+			index);
+		return;
+	}
+	for (i = 0; i < MAX_IMPED_PARAMS; i++)
+		snd_soc_update_bits(codec,
+				imped_table_ptr[index][i].reg,
+				imped_table_ptr[index][i].mask,
+				imped_table_ptr[index][i].val);
+}
+
 static bool rx_macro_get_data(struct snd_soc_codec *codec,
 			       struct device **rx_dev,
 			       struct rx_macro_priv **rx_priv,
@@ -770,6 +962,11 @@
 	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
 	int ret = 0, mclk_mux = MCLK_MUX0;
 
+	if (regmap == NULL) {
+		dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	dev_dbg(rx_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
 		__func__, mclk_enable, dapm, rx_priv->rx_mclk_users);
 
@@ -906,6 +1103,50 @@
 	return 0;
 }
 
+static int rx_macro_event_handler(struct snd_soc_codec *codec, u16 event,
+				  u32 data)
+{
+	u16 reg = 0, reg_mix = 0, rx_idx = 0, mute = 0x0;
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_RX_MUTE:
+		rx_idx = data >> 0x10;
+		mute = data & 0xffff;
+		reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL + (rx_idx *
+					RX_MACRO_RX_PATH_OFFSET);
+		reg_mix = BOLERO_CDC_RX_RX0_RX_PATH_MIX_CTL + (rx_idx *
+					RX_MACRO_RX_PATH_OFFSET);
+		snd_soc_update_bits(codec, reg, 0x10, mute << 0x10);
+		snd_soc_update_bits(codec, reg_mix, 0x10, mute << 0x10);
+		break;
+	case BOLERO_MACRO_EVT_IMPED_TRUE:
+		rx_macro_wcd_clsh_imped_config(codec, data, true);
+		break;
+	case BOLERO_MACRO_EVT_IMPED_FALSE:
+		rx_macro_wcd_clsh_imped_config(codec, data, false);
+		break;
+	case BOLERO_MACRO_EVT_SSR_DOWN:
+		swrm_wcd_notify(
+			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+			SWR_DEVICE_SSR_DOWN, NULL);
+		swrm_wcd_notify(
+			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+			SWR_DEVICE_DOWN, NULL);
+		break;
+	case BOLERO_MACRO_EVT_SSR_UP:
+		swrm_wcd_notify(
+			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+			SWR_DEVICE_SSR_UP, NULL);
+		break;
+	}
+	return 0;
+}
+
 static int rx_macro_find_playback_dai_id_for_port(int port_id,
 						  struct rx_macro_priv *rx_priv)
 {
@@ -1056,7 +1297,6 @@
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_write(codec, gain_reg,
 			snd_soc_read(codec, gain_reg));
-		snd_soc_update_bits(codec, mix_reg, 0x10, 0x00);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		/* Clk Disable */
@@ -1106,7 +1346,6 @@
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_write(codec, gain_reg,
 			snd_soc_read(codec, gain_reg));
-		snd_soc_update_bits(codec, reg, 0x10, 0x00);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		rx_macro_enable_interp_clk(codec, event, w->shift);
@@ -1159,6 +1398,52 @@
 	return 0;
 }
 
+static void rx_macro_enable_softclip_clk(struct snd_soc_codec *codec,
+					 struct rx_macro_priv *rx_priv,
+					 bool enable)
+{
+	if (enable) {
+		if (rx_priv->softclip_clk_users == 0)
+			snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_SOFTCLIP_CRC,
+				0x01, 0x01);
+		rx_priv->softclip_clk_users++;
+	} else {
+		rx_priv->softclip_clk_users--;
+		if (rx_priv->softclip_clk_users == 0)
+			snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_SOFTCLIP_CRC,
+				0x01, 0x00);
+	}
+}
+
+static int rx_macro_config_softclip(struct snd_soc_codec *codec,
+				struct rx_macro_priv *rx_priv,
+				int event)
+{
+	dev_dbg(codec->dev, "%s: event %d, enabled %d\n",
+		__func__, event, rx_priv->is_softclip_on);
+
+	if (!rx_priv->is_softclip_on)
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock */
+		rx_macro_enable_softclip_clk(codec, rx_priv, true);
+		/* Enable Softclip control */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_SOFTCLIP_SOFTCLIP_CTRL, 0x01, 0x00);
+		rx_macro_enable_softclip_clk(codec, rx_priv, false);
+	}
+
+	return 0;
+}
+
 static inline void
 rx_macro_enable_clsh_block(struct rx_macro_priv *rx_priv, bool enable)
 {
@@ -1391,6 +1676,191 @@
 	return 0;
 }
 
+static int rx_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+		((snd_soc_read(codec, BOLERO_CDC_RX_BCL_VBAT_CFG) & 0x04) ?
+		  1 : 0);
+
+	dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int rx_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+	dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	/* Set Vbat register configuration for GSM mode bit based on value */
+	if (ucontrol->value.integer.value[0])
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
+						0x04, 0x04);
+	else
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
+						0x04, 0x00);
+
+	return 0;
+}
+
+static int rx_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_softclip_on;
+
+	dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int rx_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_softclip_on =  ucontrol->value.integer.value[0];
+
+	dev_dbg(codec->dev, "%s: soft clip enable = %d\n", __func__,
+		rx_priv->is_softclip_on);
+
+	return 0;
+}
+
+static int rx_macro_enable_vbat(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol,
+				 int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+	if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable clock for VBAT block */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x10);
+		/* Enable VBAT block */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_CFG, 0x01, 0x01);
+		/* Update interpolator with 384K path */
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
+					0x80, 0x80);
+		/* Update DSM FS rate */
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_SEC7,
+					0x02, 0x02);
+		/* Use attenuation mode */
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
+					0x02, 0x00);
+		/* BCL block needs softclip clock to be enabled */
+		rx_macro_enable_softclip_clk(codec, rx_priv, true);
+		/* Enable VBAT at channel level */
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
+					0x02, 0x02);
+		/* Set the ATTK1 gain */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0xFF);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x03);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		/* Set the ATTK2 gain */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0xFF);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x03);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		/* Set the ATTK3 gain */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0xFF);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x03);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
+					0x80, 0x00);
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_SEC7,
+					0x02, 0x00);
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_BCL_VBAT_CFG,
+					0x02, 0x02);
+		snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG1,
+					0x02, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD1,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD2,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD3,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD4,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD5,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD6,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD7,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD8,
+				0xFF, 0x00);
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_RX_BCL_VBAT_BCL_GAIN_UPD9,
+				0xFF, 0x00);
+		rx_macro_enable_softclip_clk(codec, rx_priv, false);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_CFG, 0x01, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_PATH_CTL, 0x10, 0x00);
+		break;
+	default:
+		dev_err(rx_dev, "%s: Invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
 static void rx_macro_idle_detect_control(struct snd_soc_codec *codec,
 					 struct rx_macro_priv *rx_priv,
 					 int interp, int event)
@@ -1504,6 +1974,9 @@
 						       event);
 			rx_macro_config_compander(codec, rx_priv,
 						interp_idx, event);
+			if (interp_idx ==  INTERP_AUX)
+				rx_macro_config_softclip(codec, rx_priv,
+							event);
 			rx_macro_config_classh(codec, rx_priv,
 						interp_idx, event);
 		}
@@ -1518,6 +1991,9 @@
 						interp_idx, event);
 			rx_macro_config_compander(codec, rx_priv,
 						interp_idx, event);
+			if (interp_idx ==  INTERP_AUX)
+				rx_macro_config_softclip(codec, rx_priv,
+							event);
 			rx_macro_hphdelay_lutbypass(codec, rx_priv, interp_idx,
 						       event);
 			rx_macro_hd2_control(codec, interp_idx, event);
@@ -1570,6 +2046,11 @@
 	u16 reg_add = 0, coeff_idx = 0, idx = 0;
 	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
 
+	if (regmap == NULL) {
+		dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return;
+	}
+
 	regmap_write(regmap,
 		(BOLERO_CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx),
 		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
@@ -1881,6 +2362,13 @@
 	SOC_ENUM_EXT("RX_EAR Mode", rx_macro_ear_mode_enum,
 		rx_macro_get_ear_mode, rx_macro_put_ear_mode),
 
+	SOC_ENUM_EXT("RX_GSM mode Enable", rx_macro_vbat_bcl_gsm_mode_enum,
+			rx_macro_vbat_bcl_gsm_mode_func_get,
+			rx_macro_vbat_bcl_gsm_mode_func_put),
+	SOC_SINGLE_EXT("RX_Softclip Enable", SND_SOC_NOPM, 0, 1, 0,
+		     rx_macro_soft_clip_enable_get,
+		     rx_macro_soft_clip_enable_put),
+
 	SOC_SINGLE_SX_TLV("IIR0 INP0 Volume",
 		BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40,
 		digital_gain),
@@ -2079,6 +2567,12 @@
 		0, &rx_int2_mix2_inp_mux, rx_macro_enable_rx_path_clk,
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_MIXER_E("RX INT2_1 VBAT", SND_SOC_NOPM,
+		0, 0, rx_int2_1_vbat_mix_switch,
+		ARRAY_SIZE(rx_int2_1_vbat_mix_switch),
+		rx_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -2269,6 +2763,10 @@
 	{"HPHR_OUT", NULL, "RX_MCLK"},
 
 	{"RX INT2_1 INTERP", NULL, "RX INT2_1 MIX1"},
+
+	{"RX INT2_1 VBAT", "RX AUX VBAT Enable", "RX INT2_1 INTERP"},
+	{"RX INT2 SEC MIX", NULL, "RX INT2_1 VBAT"},
+
 	{"RX INT2 SEC MIX", NULL, "RX INT2_1 INTERP"},
 	{"RX INT2 MIX2", NULL, "RX INT2 SEC MIX"},
 	{"RX INT2 MIX2", NULL, "RX INT2 MIX2 INP"},
@@ -2383,6 +2881,11 @@
 	struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL);
 	int ret = 0;
 
+	if (regmap == NULL) {
+		dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	mutex_lock(&rx_priv->swr_clk_lock);
 
 	dev_dbg(rx_priv->dev, "%s: swrm clock %s\n",
@@ -2434,6 +2937,53 @@
 	return ret;
 }
 
+static void rx_macro_init_bcl_pmic_reg(struct snd_soc_codec *codec)
+{
+	struct device *rx_dev = NULL;
+	struct rx_macro_priv *rx_priv = NULL;
+
+	if (!codec) {
+		pr_err("%s: NULL codec pointer!\n", __func__);
+		return;
+	}
+
+	if (!rx_macro_get_data(codec, &rx_dev, &rx_priv, __func__))
+		return;
+
+	switch (rx_priv->bcl_pmic_params.id) {
+	case 0:
+		/* Enable ID0 to listen to respective PMIC group interrupts */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
+		/* Update MC_SID0 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1, 0x0F,
+			rx_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID0 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG2, 0xFF,
+			rx_priv->bcl_pmic_params.ppid);
+		break;
+	case 1:
+		/* Enable ID1 to listen to respective PMIC group interrupts */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
+		/* Update MC_SID1 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG3, 0x0F,
+			rx_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID1 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_RX_BCL_VBAT_DECODE_CFG1, 0xFF,
+			rx_priv->bcl_pmic_params.ppid);
+		break;
+	default:
+		dev_err(rx_dev, "%s: PMIC ID is invalid\n",
+		       __func__, rx_priv->bcl_pmic_params.id);
+		break;
+	}
+}
+
 static int rx_macro_init(struct snd_soc_codec *codec)
 {
 	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
@@ -2486,6 +3036,7 @@
 	snd_soc_update_bits(codec, BOLERO_CDC_RX_RX0_RX_PATH_CFG3, 0x03, 0x02);
 	snd_soc_update_bits(codec, BOLERO_CDC_RX_RX1_RX_PATH_CFG3, 0x03, 0x02);
 	snd_soc_update_bits(codec, BOLERO_CDC_RX_RX2_RX_PATH_CFG3, 0x03, 0x02);
+	rx_macro_init_bcl_pmic_reg(codec);
 
 	rx_priv->codec = codec;
 
@@ -2621,6 +3172,7 @@
 	ops->dai_ptr = rx_macro_dai;
 	ops->num_dais = ARRAY_SIZE(rx_macro_dai);
 	ops->mclk_fn = rx_macro_mclk_ctrl;
+	ops->event_handler = rx_macro_event_handler;
 }
 
 static int rx_macro_probe(struct platform_device *pdev)
@@ -2631,6 +3183,7 @@
 	char __iomem *rx_io_base = NULL, *muxsel_io = NULL;
 	int ret = 0;
 	struct clk *rx_core_clk = NULL, *rx_npl_clk = NULL;
+	u8 bcl_pmic_params[3];
 
 	rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv),
 			    GFP_KERNEL);
@@ -2700,6 +3253,19 @@
 		return ret;
 	}
 	rx_priv->rx_npl_clk = rx_npl_clk;
+
+	ret = of_property_read_u8_array(pdev->dev.of_node,
+				"qcom,rx-bcl-pmic-params", bcl_pmic_params,
+				sizeof(bcl_pmic_params));
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,rx-bcl-pmic-params");
+	} else {
+		rx_priv->bcl_pmic_params.id = bcl_pmic_params[0];
+		rx_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
+		rx_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
+	}
+
 	dev_set_drvdata(&pdev->dev, rx_priv);
 	mutex_init(&rx_priv->mclk_lock);
 	mutex_init(&rx_priv->swr_clk_lock);
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index 4f9736e..44826de 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -19,6 +19,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
+#include <soc/swr-wcd.h>
 #include "bolero-cdc.h"
 #include "bolero-cdc-registers.h"
 #include "../msm-cdc-pinctrl.h"
@@ -42,6 +43,8 @@
 #define TX_MACRO_DMIC_SAMPLE_RATE_UNDEFINED 0
 #define TX_MACRO_MCLK_FREQ 9600000
 #define TX_MACRO_TX_PATH_OFFSET 0x80
+#define TX_MACRO_SWR_MIC_MUX_SEL_MASK 0xF
+#define TX_MACRO_ADC_MUX_CFG_OFFSET 0x2
 
 #define TX_MACRO_TX_UNMUTE_DELAY_MS	40
 
@@ -107,6 +110,12 @@
 	TX_MACRO_CLK_DIV_16,
 };
 
+enum {
+	MSM_DMIC,
+	SWR_MIC,
+	ANC_FB_TUNE1
+};
+
 struct tx_mute_work {
 	struct tx_macro_priv *tx_priv;
 	u32 decimator;
@@ -183,6 +192,11 @@
 	struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL);
 	int ret = 0;
 
+	if (regmap == NULL) {
+		dev_err(tx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	dev_dbg(tx_priv->dev, "%s: mclk_enable = %u,clk_users= %d\n",
 		__func__, mclk_enable, tx_priv->tx_mclk_users);
 
@@ -290,6 +304,33 @@
 	return ret;
 }
 
+static int tx_macro_event_handler(struct snd_soc_codec *codec, u16 event,
+				  u32 data)
+{
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(codec, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_SSR_DOWN:
+		swrm_wcd_notify(
+			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+			SWR_DEVICE_SSR_DOWN, NULL);
+		swrm_wcd_notify(
+			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+			SWR_DEVICE_DOWN, NULL);
+		break;
+	case BOLERO_MACRO_EVT_SSR_UP:
+		swrm_wcd_notify(
+			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+			SWR_DEVICE_SSR_UP, NULL);
+		break;
+	}
+	return 0;
+}
+
 static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
 {
 	struct delayed_work *hpf_delayed_work = NULL;
@@ -298,6 +339,7 @@
 	struct snd_soc_codec *codec = NULL;
 	u16 dec_cfg_reg = 0, hpf_gate_reg = 0;
 	u8 hpf_cut_off_freq = 0;
+	u16 adc_mux_reg = 0, adc_n = 0, adc_reg = 0;
 
 	hpf_delayed_work = to_delayed_work(work);
 	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
@@ -313,6 +355,19 @@
 	dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
 		__func__, hpf_work->decimator, hpf_cut_off_freq);
 
+	adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+			TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
+	if (snd_soc_read(codec, adc_mux_reg) & SWR_MIC) {
+		adc_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+			TX_MACRO_ADC_MUX_CFG_OFFSET * hpf_work->decimator;
+		adc_n = snd_soc_read(codec, adc_reg) &
+				TX_MACRO_SWR_MIC_MUX_SEL_MASK;
+		if (adc_n >= BOLERO_ADC_MAX)
+			goto tx_hpf_set;
+		/* analog mic clear TX hold */
+		bolero_clear_amic_tx_hold(codec->dev, adc_n);
+	}
+tx_hpf_set:
 	snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
 			    hpf_cut_off_freq << 5);
 	snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
@@ -394,7 +449,7 @@
 			__func__, e->reg);
 		return -EINVAL;
 	}
-	if (strnstr(widget->name, "smic", strlen(widget->name))) {
+	if (strnstr(widget->name, "SMIC", strlen(widget->name))) {
 		if (val != 0) {
 			if (val < 5)
 				snd_soc_update_bits(codec, mic_sel_reg,
@@ -1319,6 +1374,11 @@
 	struct regmap *regmap = dev_get_regmap(tx_priv->dev->parent, NULL);
 	int ret = 0;
 
+	if (regmap == NULL) {
+		dev_err(tx_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	mutex_lock(&tx_priv->swr_clk_lock);
 
 	dev_dbg(tx_priv->dev, "%s: swrm clock %s\n",
@@ -1608,6 +1668,7 @@
 	ops->dai_ptr = tx_macro_dai;
 	ops->num_dais = ARRAY_SIZE(tx_macro_dai);
 	ops->mclk_fn = tx_macro_mclk_ctrl;
+	ops->event_handler = tx_macro_event_handler;
 }
 
 static int tx_macro_probe(struct platform_device *pdev)
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index 03bdfa1..1d28e41 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -46,6 +46,7 @@
 #define VA_MACRO_TX_DMIC_CLK_DIV_SHFT 0x01
 
 #define BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS	40
+#define MAX_RETRY_ATTEMPTS 50
 
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static int va_tx_unmute_delay = BOLERO_CDC_VA_TX_UNMUTE_DELAY_MS;
@@ -143,6 +144,11 @@
 	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;
+	}
+
 	dev_dbg(va_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
 		__func__, mclk_enable, dapm, va_priv->va_mclk_users);
 
@@ -173,8 +179,7 @@
 				0x02, 0x02);
 		}
 	} else {
-		va_priv->va_mclk_users--;
-		if (va_priv->va_mclk_users == 0) {
+		if (va_priv->va_mclk_users == 1) {
 			regmap_update_bits(regmap,
 				BOLERO_CDC_VA_TOP_CSR_TOP_CFG0,
 				0x02, 0x00);
@@ -187,12 +192,47 @@
 			bolero_request_clock(va_priv->dev,
 					VA_MACRO, MCLK_MUX0, false);
 		}
+		va_priv->va_mclk_users--;
 	}
 exit:
 	mutex_unlock(&va_priv->mclk_lock);
 	return ret;
 }
 
+static int va_macro_event_handler(struct snd_soc_codec *codec, u16 event,
+				  u32 data)
+{
+	struct device *va_dev = NULL;
+	struct va_macro_priv *va_priv = NULL;
+	int retry_cnt = MAX_RETRY_ATTEMPTS;
+
+	if (!va_macro_get_data(codec, &va_dev, &va_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET:
+		while ((va_priv->va_mclk_users != 0) && (retry_cnt != 0)) {
+			dev_dbg(va_dev, "%s:retry_cnt: %d\n",
+				__func__, retry_cnt);
+			/*
+			 * loop and check every 20ms for va_mclk user count
+			 * to get reset to 0 which ensures userspace teardown
+			 * is done and SSR powerup seq can proceed.
+			 */
+			msleep(20);
+			retry_cnt--;
+		}
+		if (retry_cnt == 0)
+			dev_err(va_dev,
+				"%s: va_mclk_users is non-zero still, audio SSR fail!!\n",
+				__func__);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
 static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -1049,13 +1089,13 @@
 			   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", 0, SND_SOC_NOPM, 0, 0,
+	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_wod_dapm_widgets[] = {
-	SND_SOC_DAPM_SUPPLY_S("VA_MCLK", 0, SND_SOC_NOPM, 0, 0,
+	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),
 };
@@ -1460,6 +1500,7 @@
 	ops->exit = va_macro_deinit;
 	ops->io_base = va_io_base;
 	ops->mclk_fn = va_macro_mclk_ctrl;
+	ops->event_handler = va_macro_event_handler;
 }
 
 static int va_macro_probe(struct platform_device *pdev)
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index 47c5cd4..d527186 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -50,6 +50,7 @@
 #define WSA_MACRO_MUX_CFG_OFFSET 0x8
 #define WSA_MACRO_MUX_CFG1_OFFSET 0x4
 #define WSA_MACRO_RX_COMP_OFFSET 0x40
+#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40
 #define WSA_MACRO_RX_PATH_OFFSET 0x80
 #define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10
 #define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C
@@ -82,6 +83,12 @@
 	WSA_MACRO_COMP_MAX
 };
 
+enum {
+	WSA_MACRO_SOFTCLIP0, /* RX0 */
+	WSA_MACRO_SOFTCLIP1, /* RX1 */
+	WSA_MACRO_SOFTCLIP_MAX
+};
+
 struct interp_sample_rate {
 	int sample_rate;
 	int rate_val;
@@ -141,6 +148,12 @@
 			  int action);
 };
 
+struct wsa_macro_bcl_pmic_params {
+	u8 id;
+	u8 sid;
+	u8 ppid;
+};
+
 enum {
 	WSA_MACRO_AIF_INVALID = 0,
 	WSA_MACRO_AIF1_PB,
@@ -205,6 +218,9 @@
 	int ear_spkr_gain;
 	int spkr_gain_offset;
 	int spkr_mode;
+	int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX];
+	int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX];
+	struct wsa_macro_bcl_pmic_params bcl_pmic_params;
 };
 
 static int wsa_macro_config_ear_spkr_gain(struct snd_soc_codec *codec,
@@ -242,10 +258,24 @@
 	"NO_MAX_STATE", "MAX_STATE_1", "MAX_STATE_2"
 };
 
+static const char * const wsa_macro_vbat_bcl_gsm_mode_text[] = {
+	"OFF", "ON"
+};
+
+static const struct snd_kcontrol_new wsa_int0_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA RX0 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
+static const struct snd_kcontrol_new wsa_int1_vbat_mix_switch[] = {
+	SOC_DAPM_SINGLE("WSA RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
+};
+
 static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum,
 				wsa_macro_ear_spkr_pa_gain_text);
 static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_spkr_boost_stage_enum,
 			wsa_macro_speaker_boost_stage_text);
+static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_vbat_bcl_gsm_mode_enum,
+			wsa_macro_vbat_bcl_gsm_mode_text);
 
 /* RX INT0 */
 static const struct soc_enum rx0_prim_inp0_chain_enum =
@@ -829,6 +859,33 @@
 	return ret;
 }
 
+static int wsa_macro_event_handler(struct snd_soc_codec *codec, u16 event,
+				   u32 data)
+{
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	switch (event) {
+	case BOLERO_MACRO_EVT_SSR_DOWN:
+		swrm_wcd_notify(
+			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+			SWR_DEVICE_SSR_DOWN, NULL);
+		swrm_wcd_notify(
+			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+			SWR_DEVICE_DOWN, NULL);
+		break;
+	case BOLERO_MACRO_EVT_SSR_UP:
+		swrm_wcd_notify(
+			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+			SWR_DEVICE_SSR_UP, NULL);
+		break;
+	}
+	return 0;
+}
+
 static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w,
 					struct snd_kcontrol *kcontrol,
 					int event)
@@ -1095,6 +1152,82 @@
 	return 0;
 }
 
+static void wsa_macro_enable_softclip_clk(struct snd_soc_codec *codec,
+					 struct wsa_macro_priv *wsa_priv,
+					 int path,
+					 bool enable)
+{
+	u16 softclip_clk_reg = BOLERO_CDC_WSA_SOFTCLIP0_CRC +
+			(path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
+	u8 softclip_mux_mask = (1 << path);
+	u8 softclip_mux_value = (1 << path);
+
+	dev_dbg(codec->dev, "%s: path %d, enable %d\n",
+		__func__, path, enable);
+	if (enable) {
+		if (wsa_priv->softclip_clk_users[path] == 0) {
+			snd_soc_update_bits(codec,
+				softclip_clk_reg, 0x01, 0x01);
+			snd_soc_update_bits(codec,
+				BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, softclip_mux_value);
+		}
+		wsa_priv->softclip_clk_users[path]++;
+	} else {
+		wsa_priv->softclip_clk_users[path]--;
+		if (wsa_priv->softclip_clk_users[path] == 0) {
+			snd_soc_update_bits(codec,
+				softclip_clk_reg, 0x01, 0x00);
+			snd_soc_update_bits(codec,
+				BOLERO_CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0,
+				softclip_mux_mask, 0x00);
+		}
+	}
+}
+
+static int wsa_macro_config_softclip(struct snd_soc_codec *codec,
+				int path, int event)
+{
+	u16 softclip_ctrl_reg = 0;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int softclip_path = 0;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (path == WSA_MACRO_COMP1)
+		softclip_path = WSA_MACRO_SOFTCLIP0;
+	else if (path == WSA_MACRO_COMP2)
+		softclip_path = WSA_MACRO_SOFTCLIP1;
+
+	dev_dbg(codec->dev, "%s: event %d path %d, enabled %d\n",
+		__func__, event, softclip_path,
+		wsa_priv->is_softclip_on[softclip_path]);
+
+	if (!wsa_priv->is_softclip_on[softclip_path])
+		return 0;
+
+	softclip_ctrl_reg = BOLERO_CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL +
+				(softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		/* Enable Softclip clock and mux */
+		wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
+						true);
+		/* Enable Softclip control */
+		snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_update_bits(codec, softclip_ctrl_reg, 0x01, 0x00);
+		wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
+						false);
+	}
+
+	return 0;
+}
+
 static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
 {
 	u16 prim_int_reg = 0;
@@ -1204,6 +1337,7 @@
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		wsa_macro_config_compander(codec, w->shift, event);
+		wsa_macro_config_softclip(codec, w->shift, event);
 		/* apply gain after int clk is enabled */
 		if ((wsa_priv->spkr_gain_offset ==
 			WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
@@ -1231,6 +1365,7 @@
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		wsa_macro_config_compander(codec, w->shift, event);
+		wsa_macro_config_softclip(codec, w->shift, event);
 		wsa_macro_enable_prim_interpolator(codec, reg, event);
 		if ((wsa_priv->spkr_gain_offset ==
 			WSA_MACRO_GAIN_OFFSET_M1P5_DB) &&
@@ -1356,6 +1491,127 @@
 	return 0;
 }
 
+
+static int wsa_macro_enable_vbat(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol,
+				 int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	u16 vbat_path_cfg = 0;
+	int softclip_path = 0;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+	if (!strcmp(w->name, "WSA_RX INT0 VBAT")) {
+		vbat_path_cfg = BOLERO_CDC_WSA_RX0_RX_PATH_CFG1;
+		softclip_path = WSA_MACRO_SOFTCLIP0;
+	} else if (!strcmp(w->name, "WSA_RX INT1 VBAT")) {
+		vbat_path_cfg = BOLERO_CDC_WSA_RX1_RX_PATH_CFG1;
+		softclip_path = WSA_MACRO_SOFTCLIP1;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Enable clock for VBAT block */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x10);
+		/* Enable VBAT block */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x01);
+		/* Update interpolator with 384K path */
+		snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x80);
+		/* Use attenuation mode */
+		snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
+					0x02, 0x00);
+		/*
+		 * BCL block needs softclip clock and mux config to be enabled
+		 */
+		wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
+					      true);
+		/* Enable VBAT at channel level */
+		snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x02);
+		/* Set the ATTK1 gain */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0xFF);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x03);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		/* Set the ATTK2 gain */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0xFF);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x03);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		/* Set the ATTK3 gain */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0xFF);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x03);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, vbat_path_cfg, 0x80, 0x00);
+		snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
+					0x02, 0x02);
+		snd_soc_update_bits(codec, vbat_path_cfg, 0x02, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD1,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD2,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD3,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD4,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD5,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD6,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD7,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD8,
+			0xFF, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
+			0xFF, 0x00);
+		wsa_macro_enable_softclip_clk(codec, wsa_priv, softclip_path,
+					      false);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG, 0x01, 0x00);
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_PATH_CTL, 0x10, 0x00);
+		break;
+	default:
+		dev_err(wsa_dev, "%s: Invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
 static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
 				 struct snd_kcontrol *kcontrol,
 				 int event)
@@ -1637,6 +1893,80 @@
 	return 0;
 }
 
+static int wsa_macro_vbat_bcl_gsm_mode_func_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+	    ((snd_soc_read(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG) & 0x04) ?
+	    1 : 0);
+
+	dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_vbat_bcl_gsm_mode_func_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+	dev_dbg(codec->dev, "%s: value: %lu\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	/* Set Vbat register configuration for GSM mode bit based on value */
+	if (ucontrol->value.integer.value[0])
+		snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
+						0x04, 0x04);
+	else
+		snd_soc_update_bits(codec, BOLERO_CDC_WSA_VBAT_BCL_VBAT_CFG,
+						0x04, 0x00);
+
+	return 0;
+}
+
+static int wsa_macro_soft_clip_enable_get(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->is_softclip_on[path];
+
+	dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
+		__func__, ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int wsa_macro_soft_clip_enable_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	int path = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	wsa_priv->is_softclip_on[path] =  ucontrol->value.integer.value[0];
+
+	dev_dbg(codec->dev, "%s: soft clip enable for %d: %d\n", __func__,
+		path, wsa_priv->is_softclip_on[path]);
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
 	SOC_ENUM_EXT("EAR SPKR PA Gain", wsa_macro_ear_spkr_pa_gain_enum,
 		     wsa_macro_ear_spkr_pa_gain_get,
@@ -1649,6 +1979,17 @@
 		wsa_macro_spkr_boost_stage_enum,
 		wsa_macro_spkr_right_boost_stage_get,
 		wsa_macro_spkr_right_boost_stage_put),
+	SOC_ENUM_EXT("GSM mode Enable", wsa_macro_vbat_bcl_gsm_mode_enum,
+		     wsa_macro_vbat_bcl_gsm_mode_func_get,
+		     wsa_macro_vbat_bcl_gsm_mode_func_put),
+	SOC_SINGLE_EXT("WSA_Softclip0 Enable", SND_SOC_NOPM,
+			WSA_MACRO_SOFTCLIP0, 1, 0,
+			wsa_macro_soft_clip_enable_get,
+			wsa_macro_soft_clip_enable_put),
+	SOC_SINGLE_EXT("WSA_Softclip1 Enable", SND_SOC_NOPM,
+			WSA_MACRO_SOFTCLIP1, 1, 0,
+			wsa_macro_soft_clip_enable_get,
+			wsa_macro_soft_clip_enable_put),
 	SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume",
 			  BOLERO_CDC_WSA_RX0_RX_VOL_CTL,
 			  0, -84, 40, digital_gain),
@@ -1862,6 +2203,17 @@
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 		SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 VBAT", SND_SOC_NOPM,
+		0, 0, wsa_int0_vbat_mix_switch,
+		ARRAY_SIZE(wsa_int0_vbat_mix_switch),
+		wsa_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 VBAT", SND_SOC_NOPM,
+		0, 0, wsa_int1_vbat_mix_switch,
+		ARRAY_SIZE(wsa_int1_vbat_mix_switch),
+		wsa_macro_enable_vbat,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
 
 	SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
@@ -1939,6 +2291,10 @@
 	{"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
 	{"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
 	{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
+
+	{"WSA_RX INT0 VBAT", "WSA RX0 VBAT Enable", "WSA_RX INT0 INTERP"},
+	{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 VBAT"},
+
 	{"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
 	{"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
 
@@ -1974,6 +2330,10 @@
 
 	{"WSA_RX INT1 SEC MIX", NULL, "WSA_RX INT1 MIX"},
 	{"WSA_RX INT1 INTERP", NULL, "WSA_RX INT1 SEC MIX"},
+
+	{"WSA_RX INT1 VBAT", "WSA RX1 VBAT Enable", "WSA_RX INT1 INTERP"},
+	{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 VBAT"},
+
 	{"WSA_RX INT1 CHAIN", NULL, "WSA_RX INT1 INTERP"},
 	{"WSA_SPK2 OUT", NULL, "WSA_RX INT1 CHAIN"},
 	{"WSA_SPK2 OUT", NULL, "WSA_MCLK"},
@@ -2006,6 +2366,53 @@
 	{BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
 };
 
+static void wsa_macro_init_bcl_pmic_reg(struct snd_soc_codec *codec)
+{
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!codec) {
+		pr_err("%s: NULL codec pointer!\n", __func__);
+		return;
+	}
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return;
+
+	switch (wsa_priv->bcl_pmic_params.id) {
+	case 0:
+		/* Enable ID0 to listen to respective PMIC group interrupts */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x02, 0x02);
+		/* Update MC_SID0 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG1, 0x0F,
+			wsa_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID0 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG2, 0xFF,
+			wsa_priv->bcl_pmic_params.ppid);
+		break;
+	case 1:
+		/* Enable ID1 to listen to respective PMIC group interrupts */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CTL1, 0x01, 0x01);
+		/* Update MC_SID1 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG3, 0x0F,
+			wsa_priv->bcl_pmic_params.sid);
+		/* Update MC_PPID1 */
+		snd_soc_update_bits(codec,
+			BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_CFG4, 0xFF,
+			wsa_priv->bcl_pmic_params.ppid);
+		break;
+	default:
+		dev_err(wsa_dev, "%s: PMIC ID is invalid %d\n",
+		       __func__, wsa_priv->bcl_pmic_params.id);
+		break;
+	}
+}
+
 static void wsa_macro_init_reg(struct snd_soc_codec *codec)
 {
 	int i;
@@ -2015,6 +2422,8 @@
 				wsa_macro_reg_init[i].reg,
 				wsa_macro_reg_init[i].mask,
 				wsa_macro_reg_init[i].val);
+
+	wsa_macro_init_bcl_pmic_reg(codec);
 }
 
 static int wsa_swrm_clock(void *handle, bool enable)
@@ -2235,6 +2644,7 @@
 	ops->dai_ptr = wsa_macro_dai;
 	ops->num_dais = ARRAY_SIZE(wsa_macro_dai);
 	ops->mclk_fn = wsa_macro_mclk_ctrl;
+	ops->event_handler = wsa_macro_event_handler;
 }
 
 static int wsa_macro_probe(struct platform_device *pdev)
@@ -2245,6 +2655,7 @@
 	char __iomem *wsa_io_base;
 	int ret = 0;
 	struct clk *wsa_core_clk, *wsa_npl_clk;
+	u8 bcl_pmic_params[3];
 
 	wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
 				GFP_KERNEL);
@@ -2300,6 +2711,19 @@
 		return ret;
 	}
 	wsa_priv->wsa_npl_clk = wsa_npl_clk;
+
+	ret = of_property_read_u8_array(pdev->dev.of_node,
+				"qcom,wsa-bcl-pmic-params", bcl_pmic_params,
+				sizeof(bcl_pmic_params));
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,wsa-bcl-pmic-params");
+	} else {
+		wsa_priv->bcl_pmic_params.id = bcl_pmic_params[0];
+		wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1];
+		wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2];
+	}
+
 	dev_set_drvdata(&pdev->dev, wsa_priv);
 	mutex_init(&wsa_priv->mclk_lock);
 	mutex_init(&wsa_priv->swr_clk_lock);
diff --git a/asoc/codecs/wcd934x/wcd934x.c b/asoc/codecs/wcd934x/wcd934x.c
index 3667676..2a6d829 100644
--- a/asoc/codecs/wcd934x/wcd934x.c
+++ b/asoc/codecs/wcd934x/wcd934x.c
@@ -10010,9 +10010,13 @@
 					(&priv->mbhc->wcd_mbhc, false);
 	}
 
-	if (priv->swr.ctrl_data)
+	if (priv->swr.ctrl_data) {
+		if (is_snd_event_fwk_enabled())
+			swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
 		swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev,
 				SWR_DEVICE_DOWN, NULL);
+	}
 	tavil_dsd_reset(priv->dsd_config);
 	if (!is_snd_event_fwk_enabled())
 		snd_soc_card_change_online_state(codec->component.card, 0);
@@ -10110,6 +10114,9 @@
 		goto done;
 	}
 
+	if (tavil->swr.ctrl_data && is_snd_event_fwk_enabled())
+		swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
 	tavil_set_spkr_mode(codec, tavil->swr.spkr_mode);
 	/*
 	 * Once the codec initialization is completed, the svs vote
diff --git a/asoc/codecs/wcd937x/internal.h b/asoc/codecs/wcd937x/internal.h
index e2f1e03..4ca8272 100644
--- a/asoc/codecs/wcd937x/internal.h
+++ b/asoc/codecs/wcd937x/internal.h
@@ -74,6 +74,14 @@
 			rx_port_mapping[MAX_PORT][MAX_CH_PER_PORT];
 	struct regulator_bulk_data *supplies;
 
+	struct notifier_block nblock;
+	/* wcd callback to bolero */
+	void *handle;
+	int (*update_wcd_event)(void *handle, u16 event, u32 data);
+	int (*register_notifier)(void *handle,
+				struct notifier_block *nblock,
+				bool enable);
+
 	u32 version;
 	/* Entry for version info */
 	struct snd_info_entry *entry;
@@ -99,6 +107,32 @@
 	int num_supplies;
 };
 
+struct wcd_ctrl_platform_data {
+	void *handle;
+	int (*update_wcd_event)(void *handle, u16 event, u32 data);
+	int (*register_notifier)(void *handle,
+				 struct notifier_block *nblock,
+				 bool enable);
+};
+
+enum {
+	WCD_RX1,
+	WCD_RX2,
+	WCD_RX3
+};
+
+enum {
+	BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR = 1,
+	BOLERO_WCD_EVT_SSR_DOWN,
+	BOLERO_WCD_EVT_SSR_UP,
+};
+
+enum {
+	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 */
+};
+
 enum {
 	/* INTR_CTRL_INT_MASK_0 */
 	WCD937X_IRQ_MBHC_BUTTON_RELEASE_DET = 0,
diff --git a/asoc/codecs/wcd937x/wcd937x-mbhc.c b/asoc/codecs/wcd937x/wcd937x-mbhc.c
index 52bc009..c95de4b 100644
--- a/asoc/codecs/wcd937x/wcd937x-mbhc.c
+++ b/asoc/codecs/wcd937x/wcd937x-mbhc.c
@@ -974,6 +974,7 @@
 		return -EINVAL;
 	}
 
+	wcd937x_mbhc_hs_detect_exit(codec);
 	wcd_mbhc_deinit(wcd_mbhc);
 	ret = wcd_mbhc_init(wcd_mbhc, codec, &mbhc_cb, &intr_ids,
 			    wcd_mbhc_registers, WCD937X_ZDET_SUPPORTED);
diff --git a/asoc/codecs/wcd937x/wcd937x-regmap.c b/asoc/codecs/wcd937x/wcd937x-regmap.c
index f445abc..0d15c10 100644
--- a/asoc/codecs/wcd937x/wcd937x-regmap.c
+++ b/asoc/codecs/wcd937x/wcd937x-regmap.c
@@ -450,8 +450,10 @@
 {
 	if(reg <= WCD937X_BASE_ADDRESS)
 		return 0;
-	return (wcd937x_reg_access[WCD937X_REG(reg)] & RD_REG)
-		& ~(wcd937x_reg_access[WCD937X_REG(reg)] & WR_REG);
+	if ((wcd937x_reg_access[WCD937X_REG(reg)] & RD_REG)
+		&& !(wcd937x_reg_access[WCD937X_REG(reg)] & WR_REG))
+		return true;
+	return false;
 }
 
 struct regmap_config wcd937x_regmap_config = {
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 75ff26b..0bdfda1 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -48,6 +48,8 @@
 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
 
 static int wcd937x_handle_post_irq(void *data);
+static int wcd937x_reset(struct device *dev);
+static int wcd937x_reset_low(struct device *dev);
 
 static const struct regmap_irq wcd937x_irqs[WCD937X_NUM_IRQS] = {
 	REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),
@@ -142,8 +144,8 @@
 			u8 *port_type, u8 path)
 {
 	int i, j;
-	u8 num_ports;
-	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT];
+	u8 num_ports = 0;
+	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT] = NULL;
 	struct wcd937x_priv *wcd937x = snd_soc_codec_get_drvdata(codec);
 
 	switch (path) {
@@ -186,8 +188,8 @@
 	u32 slave_port_type, master_port_type;
 	u32 i, ch_iter = 0;
 	int ret = 0;
-	u8 *num_ports;
-	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT];
+	u8 *num_ports = NULL;
+	struct codec_port_info (*map)[MAX_PORT][MAX_CH_PER_PORT] = NULL;
 	struct wcd937x_priv *wcd937x = dev_get_drvdata(dev);
 
 	switch (path) {
@@ -568,8 +570,16 @@
 		ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
 					    wcd937x->rx_swr_dev->dev_num,
 					    true);
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX2 << 0x10));
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX2 << 0x10 | 0x1));
 		blocking_notifier_call_chain(&wcd937x->mbhc->notifier,
 					     WCD_EVENT_PRE_HPHR_PA_OFF,
 					     &wcd937x->mbhc->wcd_mbhc);
@@ -607,8 +617,16 @@
 		ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
 				    wcd937x->rx_swr_dev->dev_num,
 				    true);
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10));
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10 | 0x1));
 		blocking_notifier_call_chain(&wcd937x->mbhc->notifier,
 					     WCD_EVENT_PRE_HPHL_PA_OFF,
 					     &wcd937x->mbhc->wcd_mbhc);
@@ -650,6 +668,16 @@
 		ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
 			    wcd937x->rx_swr_dev->dev_num,
 			    true);
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX3 << 0x10));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX3 << 0x10 | 0x1));
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		usleep_range(1000, 1010);
@@ -685,6 +713,16 @@
 		ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
 			    wcd937x->rx_swr_dev->dev_num,
 			    true);
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10));
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (wcd937x->update_wcd_event)
+			wcd937x->update_wcd_event(wcd937x->handle,
+						WCD_BOLERO_EVT_RX_MUTE,
+						(WCD_RX1 << 0x10 | 0x1));
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		usleep_range(7000, 7010);
@@ -1180,6 +1218,73 @@
 }
 EXPORT_SYMBOL(wcd937x_micbias_control);
 
+static int wcd937x_get_logical_addr(struct swr_device *swr_dev)
+{
+	int ret = 0;
+	uint8_t devnum = 0;
+
+	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;
+	}
+	swr_dev->dev_num = devnum;
+	return 0;
+}
+
+static int wcd937x_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data)
+{
+	u16 event = (val & 0xffff);
+	u16 amic = (val >> 0x10);
+	u16 mask = 0x40, reg = 0x0;
+	int ret = 0;
+	struct wcd937x_priv *wcd937x = dev_get_drvdata((struct device *)data);
+	struct snd_soc_codec *codec = wcd937x->codec;
+	struct wcd_mbhc *mbhc;
+
+	switch (event) {
+	case BOLERO_WCD_EVT_TX_CH_HOLD_CLEAR:
+		if (amic == 0x1 || amic == 0x2)
+			reg = WCD937X_ANA_TX_CH2;
+		else if (amic == 0x3)
+			reg = WCD937X_ANA_TX_CH3_HPF;
+		else
+			return 0;
+		if (amic == 0x2)
+			mask = 0x20;
+		snd_soc_update_bits(codec, reg, mask, 0x00);
+		break;
+	case BOLERO_WCD_EVT_SSR_DOWN:
+		wcd937x_reset_low(wcd937x->dev);
+		break;
+	case BOLERO_WCD_EVT_SSR_UP:
+		wcd937x_reset(wcd937x->dev);
+		wcd937x_get_logical_addr(wcd937x->tx_swr_dev);
+		wcd937x_get_logical_addr(wcd937x->rx_swr_dev);
+		regcache_mark_dirty(wcd937x->regmap);
+		regcache_sync(wcd937x->regmap);
+		/* Initialize MBHC module */
+		mbhc = &wcd937x->mbhc->wcd_mbhc;
+		ret = wcd937x_mbhc_post_ssr_init(wcd937x->mbhc, codec);
+		if (ret) {
+			dev_err(codec->dev, "%s: mbhc initialization failed\n",
+				__func__);
+		} else {
+			wcd937x_mbhc_hs_detect(codec, mbhc->mbhc_cfg);
+		}
+		break;
+	default:
+		dev_err(codec->dev, "%s: invalid event %d\n", __func__, event);
+		break;
+	}
+	return 0;
+}
+
 static int __wcd937x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
 					  int event)
 {
@@ -1443,11 +1548,11 @@
 	SND_SOC_DAPM_PGA_E("EAR PGA", WCD937X_ANA_EAR, 7, 0, NULL, 0,
 				wcd937x_codec_enable_ear_pa,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-				SND_SOC_DAPM_POST_PMD),
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_PGA_E("AUX PGA", WCD937X_AUX_AUXPA, 7, 0, NULL, 0,
 				wcd937x_codec_enable_aux_pa,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-				SND_SOC_DAPM_POST_PMD),
+				SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_PGA_E("HPHL PGA", WCD937X_ANA_HPH, 7, 0, NULL, 0,
 				wcd937x_codec_enable_hphl_pa,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
@@ -1754,7 +1859,6 @@
 		return -EINVAL;
 
 	wcd937x->codec = codec;
-
 	variant = (snd_soc_read(codec, WCD937X_DIGITAL_EFUSE_REG_0) & 0x0E) >> 1;
 	wcd937x->variant = variant;
 
@@ -1802,6 +1906,19 @@
 		snd_soc_dapm_sync(dapm);
 	}
 	wcd937x->version = WCD937X_VERSION_1_0;
+       /* Register event notifier */
+	wcd937x->nblock.notifier_call = wcd937x_event_notify;
+	if (wcd937x->register_notifier) {
+		ret = wcd937x->register_notifier(wcd937x->handle,
+						&wcd937x->nblock,
+						true);
+		if (ret) {
+			dev_err(codec->dev,
+				"%s: Failed to register notifier %d\n",
+				__func__, ret);
+			return ret;
+		}
+	}
 	return ret;
 
 err_hwdep:
@@ -1818,6 +1935,10 @@
 	if (!wcd937x)
 		return -EINVAL;
 
+	if (wcd937x->register_notifier)
+		return wcd937x->register_notifier(wcd937x->handle,
+						&wcd937x->nblock,
+						false);
 	return 0;
 }
 
@@ -1842,7 +1963,7 @@
 	},
 };
 
-int wcd937x_reset(struct device *dev)
+static int wcd937x_reset(struct device *dev)
 {
 	struct wcd937x_priv *wcd937x = NULL;
 	int rc = 0;
@@ -1945,6 +2066,36 @@
 	}
 }
 
+static int wcd937x_reset_low(struct device *dev)
+{
+	struct wcd937x_priv *wcd937x = NULL;
+	int rc = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	wcd937x = dev_get_drvdata(dev);
+	if (!wcd937x)
+		return -EINVAL;
+
+	if (!wcd937x->rst_np) {
+		dev_err(dev, "%s: reset gpio device node not specified\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	rc = msm_cdc_pinctrl_select_sleep_state(wcd937x->rst_np);
+	if (rc) {
+		dev_err(dev, "%s: wcd sleep state request fail!\n",
+				__func__);
+		return rc;
+	}
+	/* 20ms sleep required after pulling the reset gpio to LOW */
+	usleep_range(20, 30);
+
+	return rc;
+}
+
 struct wcd937x_pdata *wcd937x_populate_dt_data(struct device *dev)
 {
 	struct wcd937x_pdata *pdata = NULL;
@@ -1985,6 +2136,7 @@
 	int ret = 0, i = 0;
 	struct wcd937x_priv *wcd937x = NULL;
 	struct wcd937x_pdata *pdata = NULL;
+	struct wcd_ctrl_platform_data *plat_data = NULL;
 
 	wcd937x = devm_kzalloc(dev, sizeof(struct wcd937x_priv), GFP_KERNEL);
 	if (!wcd937x)
@@ -2008,6 +2160,30 @@
 		return ret;
 	}
 
+	plat_data = dev_get_platdata(dev->parent);
+	if (!plat_data) {
+		dev_err(dev, "%s: platform data from parent is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+	wcd937x->handle = (void *)plat_data->handle;
+	if (!wcd937x->handle) {
+		dev_err(dev, "%s: handle is NULL\n", __func__);
+		return -EINVAL;
+	}
+	wcd937x->update_wcd_event = plat_data->update_wcd_event;
+	if (!wcd937x->update_wcd_event) {
+		dev_err(dev, "%s: update_wcd_event api is null!\n",
+			__func__);
+		return -EINVAL;
+	}
+	wcd937x->register_notifier = plat_data->register_notifier;
+	if (!wcd937x->register_notifier) {
+		dev_err(dev, "%s: register_notifier api is null!\n",
+			__func__);
+		return -EINVAL;
+	}
+
 	ret = msm_cdc_enable_static_supplies(dev, wcd937x->supplies,
 					     pdata->regulator,
 					     pdata->num_supplies);
diff --git a/asoc/codecs/wcd937x/wcd937x_slave.c b/asoc/codecs/wcd937x/wcd937x_slave.c
index 36c2af1..252504f 100644
--- a/asoc/codecs/wcd937x/wcd937x_slave.c
+++ b/asoc/codecs/wcd937x/wcd937x_slave.c
@@ -85,6 +85,21 @@
 	.unbind = wcd937x_slave_unbind,
 };
 
+static int wcd937x_swr_up(struct swr_device *pdev)
+{
+	return 0;
+}
+
+static int wcd937x_swr_down(struct swr_device *pdev)
+{
+	return 0;
+}
+
+static int wcd937x_swr_reset(struct swr_device *pdev)
+{
+	return 0;
+}
+
 static int wcd937x_swr_probe(struct swr_device *pdev)
 {
 	return component_add(&pdev->dev, &wcd937x_slave_comp_ops);
@@ -105,6 +120,9 @@
 	.probe = wcd937x_swr_probe,
 	.remove = wcd937x_swr_remove,
 	.id_table = wcd937x_swr_id,
+	.device_up = wcd937x_swr_up,
+	.device_down = wcd937x_swr_down,
+	.reset_device = wcd937x_swr_reset,
 };
 
 static int __init wcd937x_slave_init(void)
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 9e44594..1c9ad1a 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -301,342 +301,342 @@
 
 #define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
 struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
-	{ PRIMARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_PRI_I2S_RX},
-	{ PRIMARY_I2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_PRI_I2S_TX},
-	{ SLIMBUS_0_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_0_RX},
-	{ SLIMBUS_0_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_0_TX},
-	{ HDMI_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_HDMI},
-	{ INT_BT_SCO_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_INT_BT_SCO_RX},
-	{ INT_BT_SCO_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_INT_BT_SCO_TX},
-	{ INT_FM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_INT_FM_RX},
-	{ INT_FM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_INT_FM_TX},
-	{ RT_PROXY_PORT_001_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ PRIMARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX},
+	{ PRIMARY_I2S_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX},
+	{ SLIMBUS_0_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX},
+	{ SLIMBUS_0_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX},
+	{ HDMI_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_HDMI},
+	{ INT_BT_SCO_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX},
+	{ INT_BT_SCO_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX},
+	{ INT_FM_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_INT_FM_RX},
+	{ INT_FM_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_INT_FM_TX},
+	{ RT_PROXY_PORT_001_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_AFE_PCM_RX},
-	{ RT_PROXY_PORT_001_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ RT_PROXY_PORT_001_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_AFE_PCM_TX},
-	{ AFE_PORT_ID_PRIMARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_AUXPCM_RX},
-	{ AFE_PORT_ID_PRIMARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_AUXPCM_TX},
-	{ VOICE_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ VOICE_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_VOICE_PLAYBACK_TX},
-	{ VOICE2_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ VOICE2_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_VOICE2_PLAYBACK_TX},
-	{ VOICE_RECORD_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ VOICE_RECORD_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INCALL_RECORD_RX},
-	{ VOICE_RECORD_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ VOICE_RECORD_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INCALL_RECORD_TX},
-	{ MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_MI2S_RX},
-	{ MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_MI2S_TX},
-	{ SECONDARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SEC_I2S_RX},
-	{ SLIMBUS_1_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_1_RX},
-	{ SLIMBUS_1_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_1_TX},
-	{ SLIMBUS_2_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_2_RX},
-	{ SLIMBUS_2_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_2_TX},
-	{ SLIMBUS_3_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_3_RX},
-	{ SLIMBUS_3_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_3_TX},
-	{ SLIMBUS_4_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_4_RX},
-	{ SLIMBUS_4_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_4_TX},
-	{ SLIMBUS_5_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_5_RX},
-	{ SLIMBUS_5_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_5_TX},
-	{ SLIMBUS_6_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_6_RX},
-	{ SLIMBUS_6_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_6_TX},
-	{ SLIMBUS_7_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_7_RX},
-	{ SLIMBUS_7_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_7_TX},
-	{ SLIMBUS_8_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_8_RX},
-	{ SLIMBUS_8_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_SLIMBUS_8_TX},
-	{ SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_STUB_RX},
-	{ SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_STUB_TX},
-	{ SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_STUB_1_TX},
-	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_MI2S_RX},
+	{ MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_MI2S_TX},
+	{ SECONDARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX},
+	{ SLIMBUS_1_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX},
+	{ SLIMBUS_1_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX},
+	{ SLIMBUS_2_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_RX},
+	{ SLIMBUS_2_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_TX},
+	{ SLIMBUS_3_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX},
+	{ SLIMBUS_3_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX},
+	{ SLIMBUS_4_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX},
+	{ SLIMBUS_4_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX},
+	{ SLIMBUS_5_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX},
+	{ SLIMBUS_5_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX},
+	{ SLIMBUS_6_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX},
+	{ SLIMBUS_6_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX},
+	{ SLIMBUS_7_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX},
+	{ SLIMBUS_7_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX},
+	{ SLIMBUS_8_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX},
+	{ SLIMBUS_8_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX},
+	{ SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_STUB_RX},
+	{ SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_STUB_TX},
+	{ SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_STUB_1_TX},
+	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_MI2S_RX},
-	{ AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_MI2S_TX},
-	{ AFE_PORT_ID_SECONDARY_MI2S_RX,  0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_MI2S_RX,  0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_MI2S_RX},
-	{ AFE_PORT_ID_SECONDARY_MI2S_TX,  0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_MI2S_TX,  0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_MI2S_TX},
-	{ AFE_PORT_ID_PRIMARY_MI2S_RX,    0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_MI2S_RX,    0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_MI2S_RX},
-	{ AFE_PORT_ID_PRIMARY_MI2S_TX,    0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_MI2S_TX,    0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_MI2S_TX},
-	{ AFE_PORT_ID_TERTIARY_MI2S_RX,   0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_MI2S_RX,   0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_MI2S_RX},
-	{ AFE_PORT_ID_TERTIARY_MI2S_TX,   0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_MI2S_TX,   0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_MI2S_TX},
-	{ AUDIO_PORT_ID_I2S_RX,           0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AUDIO_PORT_ID_I2S_RX,           0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_AUDIO_I2S_RX},
-	{ AFE_PORT_ID_SECONDARY_PCM_RX,	  0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_PCM_RX,	  0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_AUXPCM_RX},
-	{ AFE_PORT_ID_SECONDARY_PCM_TX,   0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_PCM_TX,   0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_AUXPCM_TX},
-	{ AFE_PORT_ID_PRIMARY_SPDIF_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_SPDIF_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_SPDIF_RX},
-	{ AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_MI2S_RX_SD1},
-	{ AFE_PORT_ID_QUINARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_MI2S_RX},
-	{ AFE_PORT_ID_QUINARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_MI2S_TX},
-	{ AFE_PORT_ID_SENARY_MI2S_TX,   0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SENARY_MI2S_TX,   0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SENARY_MI2S_TX},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_0},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_0},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_1},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_1},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_2},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_2},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_3},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_3},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_4},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_4},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_5},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_5},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_6},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_6},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_RX_7},
-	{ AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_TDM_TX_7},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_0},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_0},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_1},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_1},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_2},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_2},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_3},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_3},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_4},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_4},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_5},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_5},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_6},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_6},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_RX_7},
-	{ AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_TDM_TX_7},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_0},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_0},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_1},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_1},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_2},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_2},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_3},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_3},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_4},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_4},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_5},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_5},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_6},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_6},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_RX_7},
-	{ AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_TDM_TX_7},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_0},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_0},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_1},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_1},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_2},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_2},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_3},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_3},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_4},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_4},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_5},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_5},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_6},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_6},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_RX_7},
-	{ AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_TDM_TX_7},
-	{ AFE_PORT_ID_QUINARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_0},
-	{ AFE_PORT_ID_QUINARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_0},
-	{ AFE_PORT_ID_QUINARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_1},
-	{ AFE_PORT_ID_QUINARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_1},
-	{ AFE_PORT_ID_QUINARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_2},
-	{ AFE_PORT_ID_QUINARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_2},
-	{ AFE_PORT_ID_QUINARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_3},
-	{ AFE_PORT_ID_QUINARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_3},
-	{ AFE_PORT_ID_QUINARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_4},
-	{ AFE_PORT_ID_QUINARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_4},
-	{ AFE_PORT_ID_QUINARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_5},
-	{ AFE_PORT_ID_QUINARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_5},
-	{ AFE_PORT_ID_QUINARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_6},
-	{ AFE_PORT_ID_QUINARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_6},
-	{ AFE_PORT_ID_QUINARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_RX_7},
-	{ AFE_PORT_ID_QUINARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_TDM_TX_7},
-	{ INT_BT_A2DP_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ INT_BT_A2DP_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT_BT_A2DP_RX},
-	{ AFE_PORT_ID_USB_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_USB_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_USB_AUDIO_RX},
-	{ AFE_PORT_ID_USB_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_USB_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_USB_AUDIO_TX},
-	{ DISPLAY_PORT_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ DISPLAY_PORT_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_DISPLAY_PORT},
-	{ DISPLAY_PORT_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ DISPLAY_PORT_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_DISPLAY_PORT1},
-	{ AFE_PORT_ID_TERTIARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_AUXPCM_RX},
-	{ AFE_PORT_ID_TERTIARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TERTIARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TERT_AUXPCM_TX},
-	{ AFE_PORT_ID_QUATERNARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_AUXPCM_RX},
-	{ AFE_PORT_ID_QUATERNARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUATERNARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUAT_AUXPCM_TX},
-	{ AFE_PORT_ID_QUINARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_AUXPCM_RX},
-	{ AFE_PORT_ID_QUINARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_QUINARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_QUIN_AUXPCM_TX},
-	{ AFE_PORT_ID_INT0_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT0_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT0_MI2S_RX},
-	{ AFE_PORT_ID_INT0_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT0_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT0_MI2S_TX},
-	{ AFE_PORT_ID_INT1_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT1_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT1_MI2S_RX},
-	{ AFE_PORT_ID_INT1_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT1_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT1_MI2S_TX},
-	{ AFE_PORT_ID_INT2_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT2_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT2_MI2S_RX},
-	{ AFE_PORT_ID_INT2_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT2_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT2_MI2S_TX},
-	{ AFE_PORT_ID_INT3_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT3_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT3_MI2S_RX},
-	{ AFE_PORT_ID_INT3_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT3_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT3_MI2S_TX},
-	{ AFE_PORT_ID_INT4_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT4_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT4_MI2S_RX},
-	{ AFE_PORT_ID_INT4_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT4_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT4_MI2S_TX},
-	{ AFE_PORT_ID_INT5_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT5_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT5_MI2S_RX},
-	{ AFE_PORT_ID_INT5_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT5_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT5_MI2S_TX},
-	{ AFE_PORT_ID_INT6_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT6_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT6_MI2S_RX},
-	{ AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_INT6_MI2S_TX},
-	{ AFE_PORT_ID_WSA_CODEC_DMA_RX_0, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_WSA_CODEC_DMA_RX_0, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_WSA_CDC_DMA_RX_0},
-	{ AFE_PORT_ID_WSA_CODEC_DMA_TX_0, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_WSA_CODEC_DMA_TX_0, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_WSA_CDC_DMA_TX_0},
-	{ AFE_PORT_ID_WSA_CODEC_DMA_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_WSA_CODEC_DMA_RX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_WSA_CDC_DMA_RX_1},
-	{ AFE_PORT_ID_WSA_CODEC_DMA_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_WSA_CODEC_DMA_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_WSA_CDC_DMA_TX_1},
-	{ AFE_PORT_ID_WSA_CODEC_DMA_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_WSA_CODEC_DMA_TX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_WSA_CDC_DMA_TX_2},
-	{ AFE_PORT_ID_VA_CODEC_DMA_TX_0, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_VA_CODEC_DMA_TX_0, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_VA_CDC_DMA_TX_0},
-	{ AFE_PORT_ID_VA_CODEC_DMA_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_VA_CODEC_DMA_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_VA_CDC_DMA_TX_1},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_0, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_0, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_0},
-	{ AFE_PORT_ID_TX_CODEC_DMA_TX_0, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TX_CODEC_DMA_TX_0, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TX_CDC_DMA_TX_0},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_1},
-	{ AFE_PORT_ID_TX_CODEC_DMA_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TX_CODEC_DMA_TX_1, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TX_CDC_DMA_TX_1},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_2},
-	{ AFE_PORT_ID_TX_CODEC_DMA_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TX_CODEC_DMA_TX_2, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TX_CDC_DMA_TX_2},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_3},
-	{ AFE_PORT_ID_TX_CODEC_DMA_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TX_CODEC_DMA_TX_3, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TX_CDC_DMA_TX_3},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_4},
-	{ AFE_PORT_ID_TX_CODEC_DMA_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TX_CODEC_DMA_TX_4, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TX_CDC_DMA_TX_4},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_5},
-	{ AFE_PORT_ID_TX_CODEC_DMA_TX_5, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_TX_CODEC_DMA_TX_5, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_TX_CDC_DMA_TX_5},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_6, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_6, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_6},
-	{ AFE_PORT_ID_RX_CODEC_DMA_RX_7, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_RX_CODEC_DMA_RX_7, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_RX_CDC_DMA_RX_7},
-	{ AFE_PORT_ID_PRIMARY_SPDIF_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_PRIMARY_SPDIF_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_PRI_SPDIF_TX},
-	{ AFE_PORT_ID_SECONDARY_SPDIF_RX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_SPDIF_RX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_SPDIF_RX},
-	{ AFE_PORT_ID_SECONDARY_SPDIF_TX, 0, {0}, {0}, 0, 0, 0, 0, {0},
+	{ AFE_PORT_ID_SECONDARY_SPDIF_TX, 0, {0}, {0}, 0, 0, 0, 0,
 	  LPASS_BE_SEC_SPDIF_TX},
 };
 
@@ -646,128 +646,128 @@
 static struct msm_pcm_routing_fdai_data
 	fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = {
 	/* MULTIMEDIA1 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA2 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA3 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA4 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA5 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA6 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA7*/
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA8 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA9 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA10 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA11 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA12 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA13 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA14 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA15 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA16 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA17 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA18 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA19 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA20 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA21 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA28 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* MULTIMEDIA29 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* VOIP */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* AFE_RX */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* AFE_TX */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* VOICE_STUB */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* DTMF_RX */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* QCHAT */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* VOLTE_STUB */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM1 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM2 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM3 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM4 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM5 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM6 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM7 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* LSM8 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* VOICE2_STUB */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* VOICEMMODE1 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 	/* VOICEMMODE2 */
-	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
-	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+	{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM},
+	 {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL}, LEGACY_PCM} },
 };
 
 static unsigned long session_copp_map[MSM_FRONTEND_DAI_MAX][2]
@@ -1293,12 +1293,6 @@
 		return -EINVAL;
 	}
 
-	if (!route_check_fe_id_adm_support(fe_id)) {
-		/* ignore adm open if not supported for fe_id */
-		pr_debug("%s: No ADM support for fe id %d\n", __func__, fe_id);
-		return 0;
-	}
-
 	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
 		session_type = SESSION_TYPE_RX;
 		if (passthr_mode != LEGACY_PCM)
@@ -1322,14 +1316,20 @@
 			 (fe_id <= MSM_FRONTEND_DAI_LSM8);
 	mutex_lock(&routing_lock);
 
-	payload.num_copps = 0; /* only RX needs to use payload */
 	fe_dai_map[fe_id][session_type].strm_id = dspst_id;
+	fe_dai_map[fe_id][session_type].perf_mode = perf_mode;
+	fe_dai_map[fe_id][session_type].passthr_mode = passthr_mode;
+	if (!route_check_fe_id_adm_support(fe_id)) {
+		/* ignore adm open if not supported for fe_id */
+		pr_debug("%s: No ADM support for fe id %d\n", __func__, fe_id);
+		mutex_unlock(&routing_lock);
+		return 0;
+	}
+
+	payload.num_copps = 0; /* only RX needs to use payload */
 	/* re-enable EQ if active */
 	msm_qti_pp_send_eq_values(fe_id);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if (test_bit(fe_id, &msm_bedais[i].fe_sessions[0]))
-			msm_bedais[i].passthr_mode[fe_id] = passthr_mode;
-
 		if (!is_be_dai_extproc(i) &&
 			(afe_get_port_type(msm_bedais[i].port_id) ==
 			port_type) &&
@@ -1431,8 +1431,7 @@
 			}
 			if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD
 			    && passthr_mode != COMPRESSED_PASSTHROUGH_GEN
-			    && passthr_mode !=
-					    COMPRESSED_PASSTHROUGH_IEC61937)
+			    && passthr_mode != COMPRESSED_PASSTHROUGH_IEC61937)
 				msm_routing_send_device_pp_params(
 						msm_bedais[i].port_id,
 						copp_idx, fe_id);
@@ -1560,6 +1559,7 @@
 	payload.num_copps = 0; /* only RX needs to use payload */
 	fe_dai_map[fedai_id][session_type].strm_id = dspst_id;
 	fe_dai_map[fedai_id][session_type].perf_mode = perf_mode;
+	fe_dai_map[fedai_id][session_type].passthr_mode = LEGACY_PCM;
 
 	/* re-enable EQ if active */
 	msm_qti_pp_send_eq_values(fedai_id);
@@ -1577,8 +1577,6 @@
 				channels = msm_bedais[i].channel;
 			else
 				channels = msm_bedais[i].adm_override_ch;
-			msm_bedais[i].passthr_mode[fedai_id] =
-				LEGACY_PCM;
 
 			bits_per_sample = msm_routing_get_bit_width(
 						msm_bedais[i].format);
@@ -1647,12 +1645,9 @@
 					num_copps++;
 				}
 			}
-			if ((perf_mode == LEGACY_PCM_MODE) &&
-				(msm_bedais[i].passthr_mode[fedai_id] ==
-				LEGACY_PCM))
+			if (perf_mode == LEGACY_PCM_MODE)
 				msm_pcm_routing_cfg_pp(msm_bedais[i].port_id,
-						       copp_idx, topology,
-						       channels);
+						copp_idx, topology, channels);
 		}
 	}
 	if (num_copps) {
@@ -1737,8 +1732,7 @@
 			if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID ||
 				topology == DS2_ADM_COPP_TOPOLOGY_ID) &&
 			    (fdai->perf_mode == LEGACY_PCM_MODE) &&
-			    (msm_bedais[i].passthr_mode[fedai_id] ==
-					LEGACY_PCM))
+			    (fdai->passthr_mode == LEGACY_PCM))
 				msm_pcm_routing_deinit_pp(msm_bedais[i].port_id,
 							  topology);
 		}
@@ -1789,16 +1783,17 @@
 		return;
 	}
 
-	passthr_mode = msm_bedais[reg].passthr_mode[val];
-	if (afe_get_port_type(msm_bedais[reg].port_id) ==
-		MSM_AFE_PORT_TYPE_RX) {
-		session_type = SESSION_TYPE_RX;
+	session_type =
+		(afe_get_port_type(msm_bedais[reg].port_id) == MSM_AFE_PORT_TYPE_RX) ?
+		SESSION_TYPE_RX : SESSION_TYPE_TX;
+	fdai = &fe_dai_map[val][session_type];
+	passthr_mode = fdai->passthr_mode;
+	if (session_type == SESSION_TYPE_RX) {
 		if (passthr_mode != LEGACY_PCM)
 			path_type = ADM_PATH_COMPRESSED_RX;
 		else
 			path_type = ADM_PATH_PLAYBACK;
 	} else {
-		session_type = SESSION_TYPE_TX;
 		if ((passthr_mode != LEGACY_PCM) && (passthr_mode != LISTEN))
 			path_type = ADM_PATH_COMPRESSED_TX;
 		else
@@ -1815,7 +1810,6 @@
 			voc_start_playback(set, msm_bedais[reg].port_id);
 
 		set_bit(val, &msm_bedais[reg].fe_sessions[0]);
-		fdai = &fe_dai_map[val][session_type];
 		if (msm_bedais[reg].active && fdai->strm_id !=
 			INVALID_SESSION) {
 			int app_type, app_type_idx, copp_idx, acdb_dev_id;
@@ -1913,7 +1907,6 @@
 			(msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX)))
 			voc_start_playback(set, msm_bedais[reg].port_id);
 		clear_bit(val, &msm_bedais[reg].fe_sessions[0]);
-		fdai = &fe_dai_map[val][session_type];
 		if (msm_bedais[reg].active && fdai->strm_id !=
 			INVALID_SESSION) {
 			int idx;
@@ -22405,7 +22398,7 @@
 			clear_bit(idx,
 				  &session_copp_map[i][session_type][be_id]);
 			if ((fdai->perf_mode == LEGACY_PCM_MODE) &&
-				(bedai->passthr_mode[i] == LEGACY_PCM))
+				(fdai->passthr_mode == LEGACY_PCM))
 				msm_pcm_routing_deinit_pp(bedai->port_id,
 							  topology);
 		}
@@ -22414,10 +22407,6 @@
 	bedai->active = 0;
 	bedai->sample_rate = 0;
 	bedai->channel = 0;
-	for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
-		if (bedai->passthr_mode[i] != LISTEN)
-			bedai->passthr_mode[i] = LEGACY_PCM;
-	}
 	mutex_unlock(&routing_lock);
 
 	return 0;
@@ -22463,24 +22452,24 @@
 				route_check_fe_id_adm_support(i)))
 			continue;
 
+		session_type = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+						SESSION_TYPE_RX : SESSION_TYPE_TX;
+		fdai = &fe_dai_map[i][session_type];
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			if (bedai->passthr_mode[i] != LEGACY_PCM)
+			if (fdai->passthr_mode != LEGACY_PCM)
 				path_type = ADM_PATH_COMPRESSED_RX;
 			else
 				path_type = ADM_PATH_PLAYBACK;
-			session_type = SESSION_TYPE_RX;
 		} else {
-			if ((bedai->passthr_mode[i] != LEGACY_PCM) &&
-			    (bedai->passthr_mode[i] != LISTEN))
+			if ((fdai->passthr_mode != LEGACY_PCM) &&
+			    (fdai->passthr_mode != LISTEN))
 				path_type = ADM_PATH_COMPRESSED_TX;
 			else
 				path_type = ADM_PATH_LIVE_REC;
-			session_type = SESSION_TYPE_TX;
 		}
 
 		is_lsm = (i >= MSM_FRONTEND_DAI_LSM1) &&
 				 (i <= MSM_FRONTEND_DAI_LSM8);
-		fdai = &fe_dai_map[i][session_type];
 		if (fdai->strm_id != INVALID_SESSION) {
 			int app_type, app_type_idx, copp_idx, acdb_dev_id;
 
@@ -22533,12 +22522,9 @@
 			topology = msm_routing_get_adm_topology(i, session_type,
 								be_id);
 
-			if ((bedai->passthr_mode[i] ==
-					COMPRESSED_PASSTHROUGH_DSD)
-				|| (bedai->passthr_mode[i] ==
-					COMPRESSED_PASSTHROUGH_GEN)
-				|| (bedai->passthr_mode[i] ==
-					COMPRESSED_PASSTHROUGH_IEC61937))
+			if ((fdai->passthr_mode == COMPRESSED_PASSTHROUGH_DSD)
+				|| (fdai->passthr_mode == COMPRESSED_PASSTHROUGH_GEN)
+				|| (fdai->passthr_mode == COMPRESSED_PASSTHROUGH_IEC61937))
 				topology = COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY;
 
 			copp_idx = adm_open(bedai->port_id, path_type,
@@ -22564,10 +22550,9 @@
 					bedai->sample_rate);
 
 			msm_pcm_routing_build_matrix(i, session_type, path_type,
-						     fdai->perf_mode,
-						     bedai->passthr_mode[i]);
+				fdai->perf_mode, fdai->passthr_mode);
 			if ((fdai->perf_mode == LEGACY_PCM_MODE) &&
-				(bedai->passthr_mode[i] == LEGACY_PCM))
+				(fdai->passthr_mode == LEGACY_PCM))
 				msm_pcm_routing_cfg_pp(bedai->port_id, copp_idx,
 						       topology, channels);
 		}
@@ -22638,7 +22623,7 @@
 	int index, topo_id, be_idx;
 	unsigned long pp_config = 0;
 	bool mute_on;
-	int latency;
+	int latency, session_type;
 	bool compr_passthr_mode = true;
 
 	pr_debug("%s: port_id %d, copp_idx %d\n", __func__, port_id, copp_idx);
@@ -22676,8 +22661,12 @@
 		return -EINVAL;
 	}
 
-	if ((msm_bedais[be_idx].passthr_mode[fe_id] == LEGACY_PCM) ||
-		(msm_bedais[be_idx].passthr_mode[fe_id] == LISTEN))
+	session_type =
+		(afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) ?
+		SESSION_TYPE_RX : SESSION_TYPE_TX;
+
+	if ((fe_dai_map[fe_id][session_type].passthr_mode == LEGACY_PCM) ||
+		(fe_dai_map[fe_id][session_type].passthr_mode == LISTEN))
 		compr_passthr_mode = false;
 
 	pp_config = msm_bedais_pp_params[index].pp_params_config;
@@ -22764,7 +22753,7 @@
 	int port_id = 0;
 	int index, be_idx, i, topo_id, idx;
 	bool mute;
-	int latency;
+	int latency, session_type;
 	bool compr_passthr_mode = true;
 
 	pr_debug("%s: pp_id: 0x%x\n", __func__, pp_id);
@@ -22790,10 +22779,14 @@
 		return -EINVAL;
 	}
 
+	session_type =
+		(afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) ?
+		SESSION_TYPE_RX : SESSION_TYPE_TX;
+
 	for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0],
 				MSM_FRONTEND_DAI_MM_SIZE) {
-		if ((msm_bedais[be_idx].passthr_mode[i] == LEGACY_PCM) ||
-			(msm_bedais[be_idx].passthr_mode[i] == LISTEN))
+		if ((fe_dai_map[i][session_type].passthr_mode == LEGACY_PCM) ||
+			(fe_dai_map[i][session_type].passthr_mode == LISTEN))
 			compr_passthr_mode = false;
 
 		for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
@@ -22808,7 +22801,7 @@
 				continue;
 		pr_debug("%s: port: 0x%x, copp %ld, be active: %d, passt: %d\n",
 			 __func__, port_id, copp, msm_bedais[be_idx].active,
-			 msm_bedais[be_idx].passthr_mode[i]);
+			 fe_dai_map[i][session_type].passthr_mode);
 		switch (pp_id) {
 		case ADM_PP_PARAM_MUTE_ID:
 			pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__);
diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h
index b4ff50f..26a5428 100644
--- a/asoc/msm-pcm-routing-v2.h
+++ b/asoc/msm-pcm-routing-v2.h
@@ -523,7 +523,6 @@
 	unsigned int  channel;
 	unsigned int  format;
 	unsigned int  adm_override_ch;
-	u32 passthr_mode[MSM_FRONTEND_DAI_MAX];
 	char *name;
 };
 
@@ -532,6 +531,7 @@
 	int strm_id; /* ASM stream ID */
 	int perf_mode;
 	struct msm_pcm_routing_evt event_info;
+	u32 passthr_mode;
 };
 
 #define MAX_APP_TYPES	16
diff --git a/asoc/sm6150.c b/asoc/sm6150.c
index 0128d52..1849605 100644
--- a/asoc/sm6150.c
+++ b/asoc/sm6150.c
@@ -28,7 +28,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/info.h>
-#include <dsp/audio_notifier.h>
+#include <soc/snd_event.h>
 #include <dsp/q6afe-v2.h>
 #include <dsp/q6core.h>
 #include "device_event.h"
@@ -201,6 +201,7 @@
 	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 msm_asoc_wcd93xx_codec {
@@ -628,10 +629,7 @@
 static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_sample_rate,
 				cdc_dma_sample_rate_text);
 
-static struct platform_device *spdev;
-
 static int msm_hifi_control;
-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;
@@ -1250,8 +1248,10 @@
 {
 	int ch_num = cdc_dma_get_port_idx(kcontrol);
 
-	if (ch_num < 0)
+	if (ch_num < 0) {
+		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);
@@ -1264,8 +1264,10 @@
 {
 	int ch_num = cdc_dma_get_port_idx(kcontrol);
 
-	if (ch_num < 0)
+	if (ch_num < 0) {
+		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;
 
@@ -1279,6 +1281,11 @@
 {
 	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_rx_cfg[ch_num].bit_format) {
 	case SNDRV_PCM_FORMAT_S32_LE:
 		ucontrol->value.integer.value[0] = 3;
@@ -1307,6 +1314,11 @@
 	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_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S32_LE;
@@ -1437,8 +1449,10 @@
 {
 	int ch_num = cdc_dma_get_port_idx(kcontrol);
 
-	if (ch_num < 0)
+	if (ch_num < 0) {
+		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);
@@ -1453,8 +1467,10 @@
 {
 	int ch_num = cdc_dma_get_port_idx(kcontrol);
 
-	if (ch_num < 0)
+	if (ch_num < 0) {
+		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]);
@@ -1471,6 +1487,11 @@
 {
 	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;
@@ -1482,6 +1503,11 @@
 {
 	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__,
@@ -1495,6 +1521,11 @@
 	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;
@@ -1551,6 +1582,11 @@
 {
 	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;
@@ -1607,6 +1643,11 @@
 {
 	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;
@@ -1635,6 +1676,11 @@
 	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;
@@ -4595,121 +4641,6 @@
 	afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
 }
 
-static int msm_adsp_power_up_config(struct snd_soc_codec *codec,
-				    struct snd_card *card)
-{
-	int ret = 0;
-	unsigned long timeout;
-	int adsp_ready = 0;
-	bool snd_card_online = 0;
-
-	timeout = jiffies +
-		msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
-
-	do {
-		if (!snd_card_online) {
-			snd_card_online = snd_card_is_online_state(card);
-			pr_debug("%s: Sound card is %s\n", __func__,
-				 snd_card_online ? "Online" : "Offline");
-		}
-		if (!adsp_ready) {
-			adsp_ready = q6core_is_adsp_ready();
-			pr_debug("%s: ADSP Audio is %s\n", __func__,
-				 adsp_ready ? "ready" : "not ready");
-		}
-		if (snd_card_online && adsp_ready)
-			break;
-
-		/*
-		 * Sound card/ADSP will be coming up after subsystem restart and
-		 * it might not be fully up when the control reaches
-		 * here. So, wait for 50msec before checking ADSP state
-		 */
-		msleep(50);
-	} while (time_after(timeout, jiffies));
-
-	if (!snd_card_online || !adsp_ready) {
-		pr_err("%s: Timeout. Sound card is %s, ADSP Audio is %s\n",
-		       __func__,
-		       snd_card_online ? "Online" : "Offline",
-		       adsp_ready ? "ready" : "not ready");
-		ret = -ETIMEDOUT;
-		goto err;
-	}
-
-	ret = msm_afe_set_config(codec);
-	if (ret)
-		pr_err("%s: Failed to set AFE config. err %d\n",
-			__func__, ret);
-
-	return 0;
-
-err:
-	return ret;
-}
-
-static int sm6150_notifier_service_cb(struct notifier_block *this,
-					 unsigned long opcode, void *ptr)
-{
-	int ret;
-	struct snd_soc_card *card = NULL;
-	const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
-	struct snd_soc_pcm_runtime *rtd;
-	struct snd_soc_codec *codec;
-
-	pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
-
-	switch (opcode) {
-	case AUDIO_NOTIFIER_SERVICE_DOWN:
-		/*
-		 * Use flag to ignore initial boot notifications
-		 * On initial boot msm_adsp_power_up_config is
-		 * called on init. There is no need to clear
-		 * and set the config again on initial boot.
-		 */
-		if (is_initial_boot)
-			break;
-		msm_afe_clear_config();
-		break;
-	case AUDIO_NOTIFIER_SERVICE_UP:
-		if (is_initial_boot) {
-			is_initial_boot = false;
-			break;
-		}
-		if (!spdev)
-			return -EINVAL;
-
-		card = platform_get_drvdata(spdev);
-		rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
-		if (!rtd) {
-			dev_err(card->dev,
-				"%s: snd_soc_get_pcm_runtime for %s failed!\n",
-				__func__, be_dl_name);
-			ret = -EINVAL;
-			goto err;
-		}
-		codec = rtd->codec;
-
-		ret = msm_adsp_power_up_config(codec, card->snd_card);
-		if (ret < 0) {
-			dev_err(card->dev,
-				"%s: msm_adsp_power_up_config failed ret = %d!\n",
-				__func__, ret);
-			goto err;
-		}
-		break;
-	default:
-		break;
-	}
-err:
-	return NOTIFY_OK;
-}
-
-static struct notifier_block service_nb = {
-	.notifier_call  = sm6150_notifier_service_cb,
-	.priority = -INT_MAX,
-};
-
 static int msm_audrx_tavil_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int ret = 0;
@@ -4797,11 +4728,12 @@
 
 	msm_codec_fn.get_afe_config_fn = tavil_get_afe_config;
 
-	ret = msm_adsp_power_up_config(codec, rtd->card->snd_card);
+	ret = msm_afe_set_config(codec);
 	if (ret) {
 		pr_err("%s: Failed to set AFE config %d\n", __func__, ret);
 		goto err;
 	}
+	pdata->is_afe_config_done = true;
 
 	config_data = msm_codec_fn.get_afe_config_fn(codec,
 						     AFE_AANC_VERSION);
@@ -8309,6 +8241,108 @@
 		mi2s_intf_conf[count].msm_is_mi2s_master = 0;
 	}
 }
+
+static int sm6150_ssr_enable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata;
+	int ret = 0;
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!strcmp(card->name, "sm6150-tavil-snd-card")) {
+		pdata = snd_soc_card_get_drvdata(card);
+		if (!pdata->is_afe_config_done) {
+			const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
+			struct snd_soc_pcm_runtime *rtd;
+
+			rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
+			if (!rtd) {
+				dev_err(dev,
+					"%s: snd_soc_get_pcm_runtime for %s failed!\n",
+					__func__, be_dl_name);
+				ret = -EINVAL;
+				goto err;
+			}
+			ret = msm_afe_set_config(rtd->codec);
+			if (ret)
+				dev_err(dev, "%s: Failed to set AFE config. err %d\n",
+					__func__, ret);
+			else
+				pdata->is_afe_config_done = true;
+		}
+	}
+	snd_soc_card_change_online_state(card, 1);
+	dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
+
+err:
+	return ret;
+}
+
+static void sm6150_ssr_disable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata;
+
+	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, "sm6150-tavil-snd-card")) {
+		pdata = snd_soc_card_get_drvdata(card);
+		msm_afe_clear_config();
+		pdata->is_afe_config_done = false;
+	}
+}
+
+static const struct snd_event_ops sm6150_ssr_ops = {
+	.enable = sm6150_ssr_enable,
+	.disable = sm6150_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;
+	int ret;
+	int i;
+
+	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, &sm6150_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;
@@ -8371,7 +8405,6 @@
 		goto err;
 	}
 	dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
-	spdev = pdev;
 
 	pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
 						"qcom,hph-en1-gpio", 0);
@@ -8438,15 +8471,7 @@
 	}
 
 	msm_i2s_auxpcm_init(pdev);
-	if (!strcmp(card->name, "sm6150-tavil-snd-card")) {
-		is_initial_boot = true;
-		ret = audio_notifier_register("sm6150",
-					      AUDIO_NOTIFIER_ADSP_DOMAIN,
-					      &service_nb);
-		if (ret < 0)
-			pr_err("%s: Audio notifier register failed ret = %d\n",
-				   __func__, ret);
-	} else {
+	if (strcmp(card->name, "sm6150-tavil-snd-card")) {
 		pdata->dmic01_gpio_p = of_parse_phandle(pdev->dev.of_node,
 						      "qcom,cdc-dmic01-gpios",
 						       0);
@@ -8454,13 +8479,19 @@
 						      "qcom,cdc-dmic23-gpios",
 						       0);
 	}
+
+	ret = msm_audio_ssr_register(&pdev->dev);
+	if (ret)
+		pr_err("%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+
 err:
 	return ret;
 }
 
 static int msm_asoc_machine_remove(struct platform_device *pdev)
 {
-	audio_notifier_deregister("sm6150");
+	snd_event_master_deregister(&pdev->dev);
 	msm_i2s_auxpcm_deinit();
 
 	return 0;
diff --git a/include/soc/swr-wcd.h b/include/soc/swr-wcd.h
index 75d0e65..8ea8616 100644
--- a/include/soc/swr-wcd.h
+++ b/include/soc/swr-wcd.h
@@ -24,6 +24,8 @@
 	SWR_SUBSYS_RESTART,
 	SWR_SET_NUM_RX_CH,
 	SWR_CLK_FREQ,
+	SWR_DEVICE_SSR_DOWN,
+	SWR_DEVICE_SSR_UP,
 };
 
 struct swr_mstr_port {
diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c
index f5ba3d6..21d51fb 100644
--- a/soc/pinctrl-lpi.c
+++ b/soc/pinctrl-lpi.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <soc/snd_event.h>
 #include <dsp/audio_notifier.h>
 
 #include "core.h"
@@ -59,6 +60,7 @@
 #define LPI_GPIO_FUNC_FUNC5			"func5"
 
 static bool lpi_dev_up;
+static struct device *lpi_dev;
 
 /* The index of each function in lpi_gpio_functions[] array */
 enum lpi_gpio_func_index {
@@ -384,12 +386,14 @@
 			initial_boot = false;
 			break;
 		}
+		snd_event_notify(lpi_dev, SND_EVENT_DOWN);
 		lpi_dev_up = false;
 		break;
 	case AUDIO_NOTIFIER_SERVICE_UP:
 		if (initial_boot)
 			initial_boot = false;
 		lpi_dev_up = true;
+		snd_event_notify(lpi_dev, SND_EVENT_UP);
 		break;
 	default:
 		break;
@@ -402,6 +406,15 @@
 	.priority = -INT_MAX,
 };
 
+static void lpi_pinctrl_ssr_disable(struct device *dev, void *data)
+{
+	lpi_dev_up = false;
+}
+
+static const struct snd_event_ops lpi_pinctrl_ssr_ops = {
+	.disable = lpi_pinctrl_ssr_disable,
+};
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/seq_file.h>
 
@@ -576,6 +589,7 @@
 		goto err_range;
 	}
 
+	lpi_dev = &pdev->dev;
 	lpi_dev_up = true;
 	ret = audio_notifier_register("lpi_tlmm", AUDIO_NOTIFIER_ADSP_DOMAIN,
 				      &service_nb);
@@ -585,8 +599,19 @@
 		goto err_range;
 	}
 
+	ret = snd_event_client_register(dev, &lpi_pinctrl_ssr_ops, NULL);
+	if (!ret) {
+		snd_event_notify(dev, SND_EVENT_UP);
+	} else {
+		dev_err(dev, "%s: snd_event registration failed, ret [%d]\n",
+			__func__, ret);
+		goto err_snd_evt;
+	}
+
 	return 0;
 
+err_snd_evt:
+	audio_notifier_deregister("lpi_tlmm");
 err_range:
 	gpiochip_remove(&state->chip);
 err_chip:
@@ -597,6 +622,7 @@
 {
 	struct lpi_gpio_state *state = platform_get_drvdata(pdev);
 
+	snd_event_client_deregister(&pdev->dev);
 	audio_notifier_deregister("lpi_tlmm");
 	gpiochip_remove(&state->chip);
 	return 0;
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index d3fb087..7232fe8 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -248,35 +248,47 @@
 					u16 reg, u32 *value)
 {
 	u32 temp = (u32)(*value);
-	int ret;
+	int ret = 0;
+
+	mutex_lock(&swrm->devlock);
+	if (!swrm->dev_up)
+		goto err;
 
 	ret = swrm_clk_request(swrm, TRUE);
-
-	if (ret)
-		return -EINVAL;
-
+	if (ret) {
+		dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
+				    __func__);
+		goto err;
+	}
 	iowrite32(temp, swrm->swrm_dig_base + reg);
-
 	swrm_clk_request(swrm, FALSE);
-
-	return 0;
+err:
+	mutex_unlock(&swrm->devlock);
+	return ret;
 }
 
 static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
 					u16 reg, u32 *value)
 {
 	u32 temp = 0;
-	int ret;
+	int ret = 0;
+
+	mutex_lock(&swrm->devlock);
+	if (!swrm->dev_up)
+		goto err;
 
 	ret = swrm_clk_request(swrm, TRUE);
-
-	if (ret)
-		return -EINVAL;
-
+	if (ret) {
+		dev_err_ratelimited(swrm->dev, "%s: clock request failed\n",
+				    __func__);
+		goto err;
+	}
 	temp = ioread32(swrm->swrm_dig_base + reg);
 	*value = temp;
 	swrm_clk_request(swrm, FALSE);
-	return 0;
+err:
+	mutex_unlock(&swrm->devlock);
+	return ret;
 }
 
 static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr)
@@ -501,6 +513,13 @@
 		dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
 		return -EINVAL;
 	}
+	mutex_lock(&swrm->devlock);
+	if (!swrm->dev_up) {
+		mutex_unlock(&swrm->devlock);
+		return 0;
+	}
+	mutex_unlock(&swrm->devlock);
+
 	pm_runtime_get_sync(swrm->dev);
 	if (dev_num)
 		ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr,
@@ -527,6 +546,12 @@
 		dev_err(&master->dev, "%s: swrm is NULL\n", __func__);
 		return -EINVAL;
 	}
+	mutex_lock(&swrm->devlock);
+	if (!swrm->dev_up) {
+		mutex_unlock(&swrm->devlock);
+		return 0;
+	}
+	mutex_unlock(&swrm->devlock);
 
 	pm_runtime_get_sync(swrm->dev);
 	if (dev_num)
@@ -554,6 +579,12 @@
 	}
 	if (len <= 0)
 		return -EINVAL;
+	mutex_lock(&swrm->devlock);
+	if (!swrm->dev_up) {
+		mutex_unlock(&swrm->devlock);
+		return 0;
+	}
+	mutex_unlock(&swrm->devlock);
 
 	pm_runtime_get_sync(swrm->dev);
 	if (dev_num) {
@@ -921,8 +952,6 @@
 	}
 	mutex_lock(&swrm->mlock);
 
-	if (enable)
-		pm_runtime_get_sync(swrm->dev);
 	bank = get_inactive_bank_num(swrm);
 
 	if (enable) {
@@ -983,6 +1012,8 @@
 	else {
 		swrm_disable_ports(master, inactive_bank);
 		swrm_cleanup_disabled_port_reqs(master);
+	}
+	if (!swrm_is_port_en(master)) {
 		dev_dbg(&master->dev, "%s: pm_runtime auto suspend triggered\n",
 			__func__);
 		pm_runtime_mark_last_busy(swrm->dev);
@@ -1014,6 +1045,8 @@
 	}
 
 	mutex_lock(&swrm->mlock);
+	if (!swrm_is_port_en(master))
+		pm_runtime_get_sync(swrm->dev);
 
 	for (i = 0; i < portinfo->num_port; i++) {
 		ret = swrm_get_master_port(swrm, &mstr_port_id, &mstr_ch_msk,
@@ -1639,6 +1672,7 @@
 	swrm->num_rx_chs = 0;
 	swrm->clk_ref_count = 0;
 	swrm->mclk_freq = MCLK_FREQ;
+	swrm->dev_up = true;
 	swrm->state = SWR_MSTR_RESUME;
 	init_completion(&swrm->reset);
 	init_completion(&swrm->broadcast);
@@ -1646,6 +1680,7 @@
 	mutex_init(&swrm->reslock);
 	mutex_init(&swrm->force_down_lock);
 	mutex_init(&swrm->iolock);
+	mutex_init(&swrm->devlock);
 
 	for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
 		INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
@@ -1916,11 +1951,16 @@
 	mutex_lock(&swrm->force_down_lock);
 	swrm->state = SWR_MSTR_SSR;
 	mutex_unlock(&swrm->force_down_lock);
-	/* Use pm runtime function to tear down */
-	ret = pm_runtime_put_sync_suspend(dev);
-	pm_runtime_get_noresume(dev);
+	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+		ret = swrm_runtime_suspend(dev);
+		if (!ret) {
+			pm_runtime_disable(dev);
+			pm_runtime_set_suspended(dev);
+			pm_runtime_enable(dev);
+		}
+	}
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -1959,6 +1999,16 @@
 			mutex_unlock(&swrm->mlock);
 		}
 		break;
+	case SWR_DEVICE_SSR_DOWN:
+		mutex_lock(&swrm->devlock);
+		swrm->dev_up = false;
+		mutex_unlock(&swrm->devlock);
+		break;
+	case SWR_DEVICE_SSR_UP:
+		mutex_lock(&swrm->devlock);
+		swrm->dev_up = true;
+		mutex_unlock(&swrm->devlock);
+		break;
 	case SWR_DEVICE_DOWN:
 		dev_dbg(swrm->dev, "%s: swr master down called\n", __func__);
 		mutex_lock(&swrm->mlock);
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index b3dfd7d..8625966 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -113,6 +113,7 @@
 	struct completion reset;
 	struct completion broadcast;
 	struct mutex iolock;
+	struct mutex devlock;
 	struct mutex mlock;
 	struct mutex reslock;
 	u32 swrm_base_reg;
@@ -149,6 +150,8 @@
 	u32 clk_stop_mode0_supp;
 	struct work_struct wakeup_work;
 	u32 wakeup_req;
+
+	bool dev_up;
 };
 
 #endif /* _SWR_WCD_CTRL_H */