Merge "asoc: bolero: remove extra semi-colon to avoid compile error"
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index cee08dc..dcd3b98 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -623,6 +623,8 @@
 	mutex_lock(&priv->clk_lock);
 	priv->dev_up = true;
 	mutex_unlock(&priv->clk_lock);
+	regcache_mark_dirty(priv->regmap);
+	regcache_sync(priv->regmap);
 	/* 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)
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index 0be5c4e..8ed9f23 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -764,9 +764,10 @@
 	port_cfg.size = size;
 	port_cfg.params = data;
 
-	ret = swrm_wcd_notify(
-		rx_priv->swr_ctrl_data[0].rx_swr_pdev,
-		SWR_SET_PORT_MAP, &port_cfg);
+	if (rx_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
 
 	return ret;
 }
@@ -1152,16 +1153,18 @@
 			     rx_priv->is_native_on) ||
 			    (rx_priv->clk_id == RX_CORE_CLK &&
 			     !rx_priv->is_native_on)) {
-				swrm_wcd_notify(
-				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
-				SWR_DEVICE_DOWN, NULL);
+				if (rx_priv->swr_ctrl_data)
+					swrm_wcd_notify(
+					rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+					SWR_DEVICE_DOWN, NULL);
 			}
 		}
 		if (rx_priv->is_native_on)
 			mclk_freq = MCLK_FREQ_NATIVE;
-		swrm_wcd_notify(
-			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
-			SWR_CLK_FREQ, &mclk_freq);
+		if (rx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_CLK_FREQ, &mclk_freq);
 		ret = rx_macro_mclk_enable(rx_priv, 1, true);
 		if (ret)
 			rx_priv->dapm_mclk_enable = false;
@@ -1213,12 +1216,14 @@
 		break;
 	case BOLERO_MACRO_EVT_SSR_DOWN:
 		rx_priv->dev_up = false;
-		swrm_wcd_notify(
-			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
-			SWR_DEVICE_DOWN, NULL);
-		swrm_wcd_notify(
-			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
-			SWR_DEVICE_SSR_DOWN, NULL);
+		if (rx_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_DEVICE_DOWN, NULL);
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
 		break;
 	case BOLERO_MACRO_EVT_SSR_UP:
 		rx_priv->dev_up = true;
@@ -1237,9 +1242,10 @@
 						rx_priv->default_clk_id,
 						RX_CORE_CLK, false);
 
-		swrm_wcd_notify(
-			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
-			SWR_DEVICE_SSR_UP, NULL);
+		if (rx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				rx_priv->swr_ctrl_data[0].rx_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
 		break;
 	}
 	return ret;
@@ -3570,6 +3576,8 @@
 	int ret = 0;
 	u8 bcl_pmic_params[3];
 	u32 default_clk_id = 0;
+	u32 is_used_rx_swr_gpio = 1;
+	const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
 	rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv),
 			    GFP_KERNEL);
@@ -3598,13 +3606,30 @@
 			__func__, "qcom,default-clk-id");
 		default_clk_id = RX_CORE_CLK;
 	}
+	if (of_find_property(pdev->dev.of_node, is_used_rx_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_rx_swr_gpio_dt,
+					   &is_used_rx_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_rx_swr_gpio_dt);
+			is_used_rx_swr_gpio = 1;
+		}
+	}
 	rx_priv->rx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
 					"qcom,rx-swr-gpios", 0);
-	if (!rx_priv->rx_swr_gpio_p) {
+	if (!rx_priv->rx_swr_gpio_p && is_used_rx_swr_gpio) {
 		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
 			__func__);
 		return -EINVAL;
 	}
+	if (msm_cdc_pinctrl_get_state(rx_priv->rx_swr_gpio_p) < 0) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
 	rx_io_base = devm_ioremap(&pdev->dev, rx_base_addr,
 				  RX_MACRO_MAX_OFFSET);
 	if (!rx_io_base) {
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index cb3aa59..1c9ccd0 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -346,19 +346,22 @@
 
 	switch (event) {
 	case BOLERO_MACRO_EVT_SSR_DOWN:
-		swrm_wcd_notify(
-			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-			SWR_DEVICE_DOWN, NULL);
-		swrm_wcd_notify(
-			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-			SWR_DEVICE_SSR_DOWN, NULL);
+		if (tx_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+				SWR_DEVICE_DOWN, NULL);
+			swrm_wcd_notify(
+				tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
 		break;
 	case BOLERO_MACRO_EVT_SSR_UP:
 		/* reset swr after ssr/pdr */
 		tx_priv->reset_swr = true;
-		swrm_wcd_notify(
-			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-			SWR_DEVICE_SSR_UP, NULL);
+		if (tx_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
 		break;
 	}
 	return 0;
@@ -375,9 +378,10 @@
 	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
 		return -EINVAL;
 
-	ret = swrm_wcd_notify(
-		tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-		SWR_REGISTER_WAKE_IRQ, &ipc_wakeup);
+	if (tx_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+			SWR_REGISTER_WAKE_IRQ, &ipc_wakeup);
 
 	return ret;
 }
@@ -1948,9 +1952,10 @@
 	port_cfg.size = size;
 	port_cfg.params = data;
 
-	ret = swrm_wcd_notify(
-		tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-		SWR_SET_PORT_MAP, &port_cfg);
+	if (tx_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
 
 	return ret;
 }
@@ -1977,6 +1982,8 @@
 	char __iomem *tx_io_base = NULL;
 	int ret = 0;
 	const char *dmic_sample_rate = "qcom,tx-dmic-sample-rate";
+	u32 is_used_tx_swr_gpio = 1;
+	const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
 	tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct tx_macro_priv),
 			    GFP_KERNEL);
@@ -1993,13 +2000,30 @@
 		return ret;
 	}
 	dev_set_drvdata(&pdev->dev, tx_priv);
+	if (of_find_property(pdev->dev.of_node, is_used_tx_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_tx_swr_gpio_dt,
+					   &is_used_tx_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_tx_swr_gpio_dt);
+			is_used_tx_swr_gpio = 1;
+		}
+	}
 	tx_priv->tx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
 					"qcom,tx-swr-gpios", 0);
-	if (!tx_priv->tx_swr_gpio_p) {
+	if (!tx_priv->tx_swr_gpio_p && is_used_tx_swr_gpio) {
 		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
 			__func__);
 		return -EINVAL;
 	}
+	if (msm_cdc_pinctrl_get_state(tx_priv->tx_swr_gpio_p) < 0) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
 	tx_io_base = devm_ioremap(&pdev->dev,
 				   tx_base_addr, TX_MACRO_MAX_OFFSET);
 	if (!tx_io_base) {
@@ -2064,7 +2088,8 @@
 	if (!tx_priv)
 		return -EINVAL;
 
-	kfree(tx_priv->swr_ctrl_data);
+	if (tx_priv->swr_ctrl_data)
+		kfree(tx_priv->swr_ctrl_data);
 	for (count = 0; count < tx_priv->child_count &&
 		count < TX_MACRO_CHILD_DEVICES_MAX; count++)
 		platform_device_unregister(tx_priv->pdev_child_devices[count]);
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index f41392d..1b48157 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -473,9 +473,10 @@
 	port_cfg.size = size;
 	port_cfg.params = data;
 
-	ret = swrm_wcd_notify(
-		wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
-		SWR_SET_PORT_MAP, &port_cfg);
+	if (wsa_priv->swr_ctrl_data)
+		ret = swrm_wcd_notify(
+			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+			SWR_SET_PORT_MAP, &port_cfg);
 
 	return ret;
 }
@@ -910,19 +911,22 @@
 
 	switch (event) {
 	case BOLERO_MACRO_EVT_SSR_DOWN:
-		swrm_wcd_notify(
-			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
-			SWR_DEVICE_DOWN, NULL);
-		swrm_wcd_notify(
-			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
-			SWR_DEVICE_SSR_DOWN, NULL);
+		if (wsa_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_DOWN, NULL);
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_SSR_DOWN, NULL);
+		}
 		break;
 	case BOLERO_MACRO_EVT_SSR_UP:
 		/* reset swr after ssr/pdr */
 		wsa_priv->reset_swr = true;
-		swrm_wcd_notify(
-			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
-			SWR_DEVICE_SSR_UP, NULL);
+		if (wsa_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_SSR_UP, NULL);
 		break;
 	}
 	return 0;
@@ -1135,12 +1139,14 @@
 			wsa_priv->rx_1_count++;
 		ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
 
-		swrm_wcd_notify(
-			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
-			SWR_DEVICE_UP, NULL);
-		swrm_wcd_notify(
-			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
-			SWR_SET_NUM_RX_CH, &ch_cnt);
+		if (wsa_priv->swr_ctrl_data) {
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_DEVICE_UP, NULL);
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_SET_NUM_RX_CH, &ch_cnt);
+		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		if (!(strnstr(w->name, "RX0", sizeof("WSA_RX0"))) &&
@@ -1151,9 +1157,10 @@
 			wsa_priv->rx_1_count--;
 		ch_cnt = wsa_priv->rx_0_count + wsa_priv->rx_1_count;
 
-		swrm_wcd_notify(
-			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
-			SWR_SET_NUM_RX_CH, &ch_cnt);
+		if (wsa_priv->swr_ctrl_data)
+			swrm_wcd_notify(
+				wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
+				SWR_SET_NUM_RX_CH, &ch_cnt);
 		break;
 	}
 	dev_dbg(wsa_priv->dev, "%s: current swr ch cnt: %d\n",
@@ -2880,6 +2887,8 @@
 	char __iomem *wsa_io_base;
 	int ret = 0;
 	u8 bcl_pmic_params[3];
+	u32 is_used_wsa_swr_gpio = 1;
+	const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
 	wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
 				GFP_KERNEL);
@@ -2894,13 +2903,30 @@
 			__func__, "reg");
 		return ret;
 	}
+	if (of_find_property(pdev->dev.of_node, is_used_wsa_swr_gpio_dt,
+			     NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   is_used_wsa_swr_gpio_dt,
+					   &is_used_wsa_swr_gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, is_used_wsa_swr_gpio_dt);
+			is_used_wsa_swr_gpio = 1;
+		}
+	}
 	wsa_priv->wsa_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
 					"qcom,wsa-swr-gpios", 0);
-	if (!wsa_priv->wsa_swr_gpio_p) {
+	if (!wsa_priv->wsa_swr_gpio_p && is_used_wsa_swr_gpio) {
 		dev_err(&pdev->dev, "%s: swr_gpios handle not provided!\n",
 			__func__);
 		return -EINVAL;
 	}
+	if (msm_cdc_pinctrl_get_state(wsa_priv->wsa_swr_gpio_p) < 0) {
+		dev_err(&pdev->dev, "%s: failed to get swr pin state\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
 	wsa_io_base = devm_ioremap(&pdev->dev,
 				   wsa_base_addr, WSA_MACRO_MAX_OFFSET);
 	if (!wsa_io_base) {
diff --git a/asoc/codecs/msm-cdc-pinctrl.c b/asoc/codecs/msm-cdc-pinctrl.c
index 8ed0c8e..0dadb74 100644
--- a/asoc/codecs/msm-cdc-pinctrl.c
+++ b/asoc/codecs/msm-cdc-pinctrl.c
@@ -122,9 +122,10 @@
  * msm_cdc_pinctrl_get_state: get curren pinctrl state
  * @np: pointer to struct device_node
  *
- * Returns 0 for sleep state, 1 for active state
+ * Returns 0 for sleep state, 1 for active state,
+ * error code for failure
  */
-bool msm_cdc_pinctrl_get_state(struct device_node *np)
+int msm_cdc_pinctrl_get_state(struct device_node *np)
 {
 	struct msm_cdc_pinctrl_info *gpio_data;
 
diff --git a/asoc/codecs/wcd-clsh.c b/asoc/codecs/wcd-clsh.c
index 0f403ac..bda3893 100644
--- a/asoc/codecs/wcd-clsh.c
+++ b/asoc/codecs/wcd-clsh.c
@@ -34,6 +34,10 @@
 		return WCD_CLSH_STRINGIFY(CLS_AB);
 	case CLS_AB_HIFI:
 		return WCD_CLSH_STRINGIFY(CLS_AB_HIFI);
+	case CLS_AB_LP:
+		return WCD_CLSH_STRINGIFY(CLS_AB_LP);
+	case CLS_AB_LOHIFI:
+		return WCD_CLSH_STRINGIFY(CLS_AB_LOHIFI);
 	default:
 		return WCD_CLSH_STRINGIFY(CLS_H_INVALID);
 	};
@@ -107,7 +111,7 @@
 					  int mode)
 {
 	if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
-	    mode == CLS_AB_HIFI)
+	    mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI)
 		snd_soc_component_update_bits(component,
 				WCD9XXX_ANA_RX_SUPPLIES,
 				0x08, 0x08); /* set to HIFI */
@@ -122,7 +126,7 @@
 				int mode)
 {
 	if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
-	    mode == CLS_AB_HIFI) {
+	    mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI) {
 		snd_soc_component_update_bits(component,
 				WCD9XXX_ANA_RX_SUPPLIES,
 				0x04, 0x04);
@@ -154,7 +158,7 @@
 		snd_soc_component_update_bits(component,
 				WCD9XXX_CLASSH_MODE_2,
 				0xFF, 0x1C);
-		if (mode == CLS_H_LOHIFI) {
+		if (mode == CLS_H_LOHIFI || mode == CLS_AB_LOHIFI) {
 			snd_soc_component_update_bits(component,
 					WCD9XXX_HPH_NEW_INT_PA_MISC2,
 					0x20, 0x20);
@@ -258,6 +262,8 @@
 		break;
 	case CLS_H_LP:
 	case CLS_H_LOHIFI:
+	case CLS_AB_LP:
+	case CLS_AB_LOHIFI:
 		val = 0x04;
 		break;
 	default:
diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h
index e1fea5c..87bea04 100644
--- a/asoc/codecs/wcd938x/internal.h
+++ b/asoc/codecs/wcd938x/internal.h
@@ -94,6 +94,8 @@
 	/* Entry for version info */
 	struct snd_info_entry *entry;
 	struct snd_info_entry *version_entry;
+	int flyback_cur_det_disable;
+	int ear_rx_path;
 };
 
 struct wcd938x_micbias_setting {
diff --git a/asoc/codecs/wcd938x/wcd938x-regmap.c b/asoc/codecs/wcd938x/wcd938x-regmap.c
index a06f975..6f59258 100644
--- a/asoc/codecs/wcd938x/wcd938x-regmap.c
+++ b/asoc/codecs/wcd938x/wcd938x-regmap.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/regmap.h>
@@ -494,8 +494,10 @@
 {
 	if(reg <= WCD938X_BASE_ADDRESS)
 		return 0;
-	return (wcd938x_reg_access[WCD938X_REG(reg)] & RD_REG)
-		& ~(wcd938x_reg_access[WCD938X_REG(reg)] & WR_REG);
+	if ((wcd938x_reg_access[WCD938X_REG(reg)] & RD_REG)
+		&& !(wcd938x_reg_access[WCD938X_REG(reg)] & WR_REG))
+		return true;
+	return false;
 }
 
 struct regmap_config wcd938x_regmap_config = {
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 4ded2d2..98ea22e 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -29,6 +29,7 @@
 
 #define WCD938X_VERSION_1_0 1
 #define WCD938X_VERSION_ENTRY_SIZE 32
+#define EAR_RX_PATH_AUX 1
 
 #define ADC_MODE_VAL_HIFI     0x01
 #define ADC_MODE_VAL_LO_HIF   0x02
@@ -166,6 +167,12 @@
 				      0xC0, 0x80);
 	snd_soc_component_update_bits(component, WCD938X_DIGITAL_CDC_DMIC_CTL,
 				      0x02, 0x02);
+	snd_soc_component_update_bits(component,
+				WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP,
+				0xFF, 0x14);
+	snd_soc_component_update_bits(component,
+				WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP,
+				0x1F, 0x08);
 
 	return 0;
 }
@@ -364,6 +371,8 @@
 				WCD938X_DIGITAL_CDC_RX2_CTL, 0x40, 0x00);
 		snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				WCD938X_AUX_AUXPA, 0x10, 0x10);
 	}
 	wcd938x->rx_clk_cnt++;
 
@@ -539,8 +548,11 @@
 				WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x02, 0x02);
 		/* 5 msec delay as per HW requirement */
 		usleep_range(5000, 5010);
-		snd_soc_component_update_bits(component, WCD938X_FLYBACK_EN,
-				0x04, 0x00);
+		if (wcd938x->flyback_cur_det_disable == 0)
+			snd_soc_component_update_bits(component,
+					WCD938X_FLYBACK_EN,
+					0x04, 0x00);
+		wcd938x->flyback_cur_det_disable++;
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_PRE_DAC,
 			     WCD_CLSH_STATE_EAR,
@@ -573,13 +585,17 @@
 				WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0x04, 0x04);
 		snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL, 0x01, 0x01);
+		if (wcd938x->flyback_cur_det_disable == 0)
+			snd_soc_component_update_bits(component,
+					WCD938X_FLYBACK_EN,
+					0x04, 0x00);
+		wcd938x->flyback_cur_det_disable++;
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_PRE_DAC,
 			     WCD_CLSH_STATE_AUX,
 			     wcd938x->hph_mode);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		wcd938x_rx_clk_disable(component);
 		snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x04, 0x00);
 		break;
@@ -614,6 +630,8 @@
 		/* 100 usec delay as per HW requirement */
 		usleep_range(100, 110);
 		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x13);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/*
@@ -630,7 +648,8 @@
 		}
 		snd_soc_component_update_bits(component,
 				WCD938X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x02);
-		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
+			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_RX_SUPPLIES, 0x02, 0x02);
 		if (wcd938x->update_wcd_event)
@@ -650,6 +669,8 @@
 	case SND_SOC_DAPM_POST_PMD:
 		/* 7 msec delay as per HW requirement */
 		usleep_range(7000, 7010);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x00);
 		blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
 					     WCD_EVENT_POST_HPHR_PA_OFF,
 					     &wcd938x->mbhc->wcd_mbhc);
@@ -690,6 +711,8 @@
 		/* 100 usec delay as per HW requirement */
 		usleep_range(100, 110);
 		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x13);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/*
@@ -706,7 +729,8 @@
 		}
 		snd_soc_component_update_bits(component,
 				WCD938X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x02);
-		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
+			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_RX_SUPPLIES, 0x02, 0x02);
 		if (wcd938x->update_wcd_event)
@@ -726,6 +750,8 @@
 	case SND_SOC_DAPM_POST_PMD:
 		/* 7 msec delay as per HW requirement */
 		usleep_range(7000, 7010);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x00);
 		blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
 					     WCD_EVENT_POST_HPHL_PA_OFF,
 					     &wcd938x->mbhc->wcd_mbhc);
@@ -758,14 +784,17 @@
 		ret = swr_slvdev_datapath_control(wcd938x->rx_swr_dev,
 			    wcd938x->rx_swr_dev->dev_num,
 			    true);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_PDM_WD_CTL2, 0x05, 0x05);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/* 1 msec delay as per HW requirement */
 		usleep_range(1000, 1010);
-		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
+			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_RX_SUPPLIES,
-					0x20, 0x20);
+					0x02, 0x02);
 		if (wcd938x->update_wcd_event)
 			wcd938x->update_wcd_event(wcd938x->handle,
 						WCD_BOLERO_EVT_RX_MUTE,
@@ -780,10 +809,18 @@
 	case SND_SOC_DAPM_POST_PMD:
 		/* 1 msec delay as per HW requirement */
 		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_PDM_WD_CTL2, 0x05, 0x00);
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_POST_PA,
 			     WCD_CLSH_STATE_AUX,
 			     hph_mode);
+
+		wcd938x->flyback_cur_det_disable--;
+		if (wcd938x->flyback_cur_det_disable == 0)
+			snd_soc_component_update_bits(component,
+						      WCD938X_FLYBACK_EN,
+						      0x04, 0x04);
 		break;
 	};
 	return ret;
@@ -807,11 +844,27 @@
 		ret = swr_slvdev_datapath_control(wcd938x->rx_swr_dev,
 			    wcd938x->rx_swr_dev->dev_num,
 			    true);
+		/*
+		 * Enable watchdog interrupt for HPHL or AUX
+		 * depending on mux value
+		 */
+		wcd938x->ear_rx_path =
+			snd_soc_component_read32(
+				component, WCD938X_DIGITAL_CDC_EAR_PATH_CTL);
+		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
+			snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_PDM_WD_CTL2,
+					0x05, 0x05);
+		else
+			snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_PDM_WD_CTL0,
+					0x17, 0x13);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		/* 6 msec delay as per HW requirement */
 		usleep_range(6000, 6010);
-		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI)
+		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
+			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_RX_SUPPLIES,
 					0x02, 0x02);
@@ -829,12 +882,24 @@
 	case SND_SOC_DAPM_POST_PMD:
 		/* 7 msec delay as per HW requirement */
 		usleep_range(7000, 7010);
+		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
+			snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_PDM_WD_CTL2,
+					0x05, 0x00);
+		else
+			snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_PDM_WD_CTL0,
+					0x17, 0x00);
 		wcd_cls_h_fsm(component, &wcd938x->clsh_info,
 			     WCD_CLSH_EVENT_POST_PA,
 			     WCD_CLSH_STATE_EAR,
 			     hph_mode);
-		snd_soc_component_update_bits(component, WCD938X_FLYBACK_EN,
-				0x04, 0x04);
+
+		wcd938x->flyback_cur_det_disable--;
+		if (wcd938x->flyback_cur_det_disable == 0)
+			snd_soc_component_update_bits(component,
+						      WCD938X_FLYBACK_EN,
+						      0x04, 0x04);
 		break;
 	};
 	return ret;
@@ -1538,6 +1603,7 @@
 		wcd938x_reset(wcd938x->dev);
 		wcd938x_get_logical_addr(wcd938x->tx_swr_dev);
 		wcd938x_get_logical_addr(wcd938x->rx_swr_dev);
+		wcd938x_init_reg(component);
 		regcache_mark_dirty(wcd938x->regmap);
 		regcache_sync(wcd938x->regmap);
 		/* Initialize MBHC module */
@@ -1795,7 +1861,7 @@
 
 static const char * const rx_hph_mode_mux_text[] = {
 	"CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
-	"CLS_H_ULP", "CLS_AB_HIFI",
+	"CLS_H_ULP", "CLS_AB_HIFI", "CLS_AB_LP", "CLS_AB_LOHIFI",
 };
 
 static const struct soc_enum rx_hph_mode_mux_enum =
@@ -2687,6 +2753,13 @@
 	return pdata;
 }
 
+static irqreturn_t wcd938x_wd_handle_irq(int irq, void *data)
+{
+	pr_err_ratelimited("%s: Watchdog interrupt for irq =%d triggered\n",
+			   __func__, irq);
+	return IRQ_HANDLED;
+}
+
 static int wcd938x_bind(struct device *dev)
 {
 	int ret = 0, i = 0;
@@ -2750,6 +2823,18 @@
 	}
 	wcd938x->tx_swr_dev->slave_irq = wcd938x->virq;
 
+	/* Request for watchdog interrupt */
+	wcd_request_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHR_PDM_WD_INT,
+			"HPHR PDM WD INT", wcd938x_wd_handle_irq, NULL);
+	wcd_request_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHL_PDM_WD_INT,
+			"HPHL PDM WD INT", wcd938x_wd_handle_irq, NULL);
+	wcd_request_irq(&wcd938x->irq_info, WCD938X_IRQ_AUX_PDM_WD_INT,
+			"AUX PDM WD INT", wcd938x_wd_handle_irq, NULL);
+	/* Enable watchdog interrupt for HPH and AUX */
+	wcd_enable_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHR_PDM_WD_INT);
+	wcd_enable_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHL_PDM_WD_INT);
+	wcd_enable_irq(&wcd938x->irq_info, WCD938X_IRQ_AUX_PDM_WD_INT);
+
 	ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x,
 				     NULL, 0);
 	if (ret) {
@@ -2860,6 +2945,7 @@
 		return -ENOMEM;
 
 	dev_set_drvdata(dev, wcd938x);
+	wcd938x->dev = dev;
 
 	pdata = wcd938x_populate_dt_data(dev);
 	if (!pdata) {
@@ -2921,9 +3007,10 @@
 		goto err;
 	}
 
+	mutex_init(&wcd938x->micb_lock);
 	ret = wcd938x_add_slave_components(dev, &match);
 	if (ret)
-		goto err;
+		goto err_lock_init;
 
 	wcd938x_reset(dev);
 
@@ -2932,13 +3019,19 @@
 	return component_master_add_with_match(dev,
 					&wcd938x_comp_ops, match);
 
+err_lock_init:
+	mutex_destroy(&wcd938x->micb_lock);
 err:
 	return ret;
 }
 
 static int wcd938x_remove(struct platform_device *pdev)
 {
+	struct wcd938x_priv *wcd938x = NULL;
+
+	wcd938x = platform_get_drvdata(pdev);
 	component_master_del(&pdev->dev, &wcd938x_comp_ops);
+	mutex_destroy(&wcd938x->micb_lock);
 	dev_set_drvdata(&pdev->dev, NULL);
 
 	return 0;
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index d9e0927..a3618ca 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -4738,9 +4738,9 @@
 	chmixer_pspd->output_channel = ucontrol->value.integer.value[3];
 	chmixer_pspd->port_idx = ucontrol->value.integer.value[4];
 
-	if (chmixer_pspd->input_channel <= 0 ||
+	if (chmixer_pspd->input_channel < 0 ||
 		chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
-		chmixer_pspd->output_channel <= 0 ||
+		chmixer_pspd->output_channel < 0 ||
 		chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
 		pr_err("%s: Invalid channels, in %d, out %d\n",
 				__func__, chmixer_pspd->input_channel,
@@ -4795,7 +4795,7 @@
 		if (prtd && prtd->audio_client) {
 			stream_id = prtd->audio_client->session;
 			be_id = chmixer_pspd->port_idx;
-			ret = msm_pcm_routing_set_channel_mixer_runtime(be_id,
+			msm_pcm_routing_set_channel_mixer_runtime(be_id,
 					stream_id, session_type, chmixer_pspd);
 		}
 	}
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index ed6af11..35ebff4 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -3738,6 +3738,9 @@
 				 snd_ctl_new1(&afe_enc_config_controls[4],
 				 dai));
 		rc = snd_ctl_add(dai->component->card->snd_card,
+				 snd_ctl_new1(&afe_enc_config_controls[5],
+				 dai));
+		rc = snd_ctl_add(dai->component->card->snd_card,
 				snd_ctl_new1(&avd_drift_config_controls[2],
 					dai));
 		break;
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index 3b20ecc..af15843 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -1934,9 +1934,9 @@
 	chmixer_pspd->output_channel = ucontrol->value.integer.value[3];
 	chmixer_pspd->port_idx = ucontrol->value.integer.value[4];
 
-	if (chmixer_pspd->input_channel <= 0 ||
+	if (chmixer_pspd->input_channel < 0 ||
 		chmixer_pspd->input_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8 ||
-		chmixer_pspd->output_channel <= 0 ||
+		chmixer_pspd->output_channel < 0 ||
 		chmixer_pspd->output_channel > PCM_FORMAT_MAX_NUM_CHANNEL_V8) {
 		pr_err("%s: Invalid channels, in %d, out %d\n",
 				__func__, chmixer_pspd->input_channel,
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 66eef64..f2c7cfc 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -10820,6 +10820,26 @@
 	return ((struct apr_svc *)(session[session_id].ac)->apr)->id;
 }
 
+uint8_t q6asm_get_asm_stream_id(int session_id)
+{
+	uint8_t stream_id = 1;
+	pr_debug("%s:\n", __func__);
+
+	if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) {
+		pr_err("%s: invalid session_id = %d\n", __func__, session_id);
+		goto done;
+	}
+	if (session[session_id].ac == NULL) {
+		pr_err("%s: session not created for session id = %d\n",
+		       __func__, session_id);
+		goto done;
+	}
+	stream_id = (session[session_id].ac)->stream_id;
+
+done:
+	return stream_id;
+}
+
 int q6asm_get_asm_topology(int session_id)
 {
 	int topology = -EINVAL;
diff --git a/dsp/rtac.c b/dsp/rtac.c
index 37b7e49..7c7137e 100644
--- a/dsp/rtac.c
+++ b/dsp/rtac.c
@@ -985,6 +985,7 @@
 	u32 user_buf_size = 0;
 	u32 bytes_returned = 0;
 	u32 session_id = 0;
+	u8  stream_id = 0;
 	u32 payload_size;
 	u32 data_size = 0;
 	struct apr_hdr asm_params;
@@ -1044,6 +1045,13 @@
 		goto err;
 	}
 
+	stream_id = q6asm_get_asm_stream_id(session_id);
+	if ((stream_id != 1) && (stream_id != 2)) {
+		pr_err("%s: Invalid stream id %u\n", __func__, stream_id);
+		result = -EINVAL;
+		goto err;
+	}
+
 	switch (opcode) {
 	case ASM_STREAM_CMD_SET_PP_PARAMS_V2:
 	case ASM_STREAM_CMD_SET_PP_PARAMS_V3:
@@ -1103,10 +1111,10 @@
 		payload_size);
 	asm_params.src_svc = q6asm_get_apr_service_id(session_id);
 	asm_params.src_domain = APR_DOMAIN_APPS;
-	asm_params.src_port = (session_id << 8) | 0x0001;
+	asm_params.src_port = (session_id << 8) | stream_id;
 	asm_params.dest_svc = APR_SVC_ASM;
 	asm_params.dest_domain = APR_DOMAIN_ADSP;
-	asm_params.dest_port = (session_id << 8) | 0x0001;
+	asm_params.dest_port = (session_id << 8) | stream_id;
 	asm_params.token = session_id;
 	asm_params.opcode = opcode;
 
diff --git a/include/asoc/msm-cdc-pinctrl.h b/include/asoc/msm-cdc-pinctrl.h
index 4024d90..73022ab 100644
--- a/include/asoc/msm-cdc-pinctrl.h
+++ b/include/asoc/msm-cdc-pinctrl.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  */
 
 #ifndef __MFD_CDC_PINCTRL_H_
@@ -11,7 +11,7 @@
 #if IS_ENABLED(CONFIG_MSM_CDC_PINCTRL)
 extern int msm_cdc_pinctrl_select_sleep_state(struct device_node *np);
 extern int msm_cdc_pinctrl_select_active_state(struct device_node *np);
-extern bool msm_cdc_pinctrl_get_state(struct device_node *np);
+extern int msm_cdc_pinctrl_get_state(struct device_node *np);
 extern int msm_cdc_get_gpio_state(struct device_node *np);
 int msm_cdc_pinctrl_drv_init(void);
 void msm_cdc_pinctrl_drv_exit(void);
@@ -36,7 +36,7 @@
 void msm_cdc_pinctrl_drv_exit(void)
 {
 }
-bool msm_cdc_pinctrl_get_state(struct device_node *np)
+int msm_cdc_pinctrl_get_state(struct device_node *np)
 {
 	return true;
 }
diff --git a/include/asoc/wcd-clsh.h b/include/asoc/wcd-clsh.h
index 64250e1..c8e49fd 100644
--- a/include/asoc/wcd-clsh.h
+++ b/include/asoc/wcd-clsh.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _WCD_CLSH
@@ -62,6 +62,8 @@
 	CLS_H_LOHIFI, /* LoHIFI */
 	CLS_H_ULP, /* Ultra Low power */
 	CLS_AB_HIFI, /* Class-AB */
+	CLS_AB_LP, /* Class-AB Low Power */
+	CLS_AB_LOHIFI, /* Class-AB Low HIFI */
 	CLS_NONE, /* None of the above modes */
 };
 
diff --git a/include/dsp/q6asm-v2.h b/include/dsp/q6asm-v2.h
index 1bb44b4..de7e31b 100644
--- a/include/dsp/q6asm-v2.h
+++ b/include/dsp/q6asm-v2.h
@@ -711,6 +711,7 @@
 int q6asm_stream_send_meta_data(struct audio_client *ac, uint32_t stream_id,
 		uint32_t initial_samples, uint32_t trailing_samples);
 
+uint8_t q6asm_get_asm_stream_id(int session_id);
 int q6asm_get_asm_topology(int session_id);
 int q6asm_get_asm_app_type(int session_id);
 
diff --git a/soc/soundwire.c b/soc/soundwire.c
index 23e373a..72a94ac 100644
--- a/soc/soundwire.c
+++ b/soc/soundwire.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/kernel.h>
@@ -998,10 +998,14 @@
 	if (!drv)
 		return -EINVAL;
 
-	if (dev->type == &swr_dev_type)
+	if (dev->type == &swr_dev_type) {
 		swr_dev = to_swr_device(dev);
-	else
+		if (!swr_dev)
+			return -EINVAL;
+	} else {
 		return 0;
+	}
+
 	if (drv->id_table)
 		return swr_match(drv->id_table, swr_dev) != NULL;
 
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index 45781c7..194e976 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -984,6 +984,26 @@
 
 	mutex_lock(&swrm->mlock);
 
+	/*
+	 * During disable if master is already down, which implies an ssr/pdr
+	 * scenario, just mark ports as disabled and exit
+	 */
+	if (swrm->state == SWR_MSTR_SSR && !enable) {
+		if (!test_bit(DISABLE_PENDING, &swrm->port_req_pending)) {
+			dev_dbg(swrm->dev, "%s:No pending disconn port req\n",
+				__func__);
+			goto exit;
+		}
+		clear_bit(DISABLE_PENDING, &swrm->port_req_pending);
+		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);
+			pm_runtime_put_autosuspend(swrm->dev);
+		}
+		goto exit;
+	}
 	bank = get_inactive_bank_num(swrm);
 
 	if (enable) {
@@ -2282,6 +2302,7 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
 	int ret = 0;
+	bool clk_err = false;
 	struct swr_master *mstr = &swrm->master;
 	struct swr_device *swr_dev;
 
@@ -2295,6 +2316,7 @@
 			dev_err(dev, "%s:lpass core hw enable failed\n",
 				__func__);
 			ret = 0;
+			clk_err = true;
 		}
 	}
 
@@ -2342,7 +2364,7 @@
 		swrm->state = SWR_MSTR_UP;
 	}
 exit:
-	if (swrm->lpass_core_hw_vote)
+	if (swrm->lpass_core_hw_vote && !clk_err)
 		clk_disable_unprepare(swrm->lpass_core_hw_vote);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, auto_suspend_timer);
 	mutex_unlock(&swrm->reslock);
@@ -2354,6 +2376,7 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
 	int ret = 0;
+	bool clk_err = false;
 	struct swr_master *mstr = &swrm->master;
 	struct swr_device *swr_dev;
 	int current_state = 0;
@@ -2370,6 +2393,7 @@
 			dev_err(dev, "%s:lpass core hw enable failed\n",
 				__func__);
 			ret = 0;
+			clk_err = true;
 		}
 	}
 
@@ -2423,7 +2447,7 @@
 	if (current_state != SWR_MSTR_SSR)
 		swrm->state = SWR_MSTR_DOWN;
 exit:
-	if (swrm->lpass_core_hw_vote)
+	if (swrm->lpass_core_hw_vote && !clk_err)
 		clk_disable_unprepare(swrm->lpass_core_hw_vote);
 	mutex_unlock(&swrm->reslock);
 	return ret;