Merge "soc: swr-mstr: Avoid race condition during device up"
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 5001b7f..d6a196b 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -428,7 +428,7 @@
 {
 	struct bolero_priv *priv;
 	u16 mclk_mux0_macro, mclk_mux1_macro;
-	int ret = 0;
+	int ret = 0, ret1 = 0;
 
 	if (!dev) {
 		pr_err("%s: dev is null\n", __func__);
@@ -468,24 +468,32 @@
 			dev_err(dev,
 				"%s: MCLK_MUX0 en failed for macro:%d mclk_mux0_macro:%d\n",
 				__func__, macro_id, mclk_mux0_macro);
-			goto err;
+			/*
+			 * for disable case, need to proceed still for mclk_mux1
+			 * counter to decrement
+			 */
+			if (enable)
+				goto err;
 		}
-		ret = priv->macro_params[mclk_mux1_macro].mclk_fn(
+		/*
+		 * need different return value as ret variable
+		 * is used to track mclk_mux0 enable success or fail
+		 */
+		ret1 = priv->macro_params[mclk_mux1_macro].mclk_fn(
 			priv->macro_params[mclk_mux1_macro].dev, enable);
-		if (ret < 0) {
+		if (ret1 < 0)
 			dev_err(dev,
 				"%s: MCLK_MUX1 %s failed for macro:%d, mclk_mux1_macro:%d\n",
 				__func__,
 				enable ? "enable" : "disable",
 				macro_id, mclk_mux1_macro);
+		/* disable mclk_mux0 only if ret is success(0) */
+		if (!ret)
 			priv->macro_params[mclk_mux0_macro].mclk_fn(
 				priv->macro_params[mclk_mux0_macro].dev,
 				false);
+		if (enable && ret1)
 			goto err;
-		}
-		priv->macro_params[mclk_mux0_macro].mclk_fn(
-			priv->macro_params[mclk_mux0_macro].dev,
-			false);
 		break;
 	case MCLK_MUX_MAX:
 	default:
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index 37cfefe..986375d 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -343,6 +343,7 @@
 	int rx_mclk_cnt;
 	bool is_native_on;
 	bool is_ear_mode_on;
+	bool dev_up;
 	u16 mclk_mux;
 	struct mutex mclk_lock;
 	struct mutex swr_clk_lock;
@@ -1087,16 +1088,20 @@
 				__func__);
 			return ret;
 		}
-		if (rx_priv->rx_mclk_cnt++ == 0)
-			iowrite32(0x1, rx_priv->rx_mclk_mode_muxsel);
+		if (rx_priv->rx_mclk_cnt++ == 0) {
+			if (rx_priv->dev_up)
+				iowrite32(0x1, rx_priv->rx_mclk_mode_muxsel);
+		}
 	} else {
 		if (rx_priv->rx_mclk_cnt <= 0) {
 			dev_dbg(dev, "%s:rx mclk already disabled\n", __func__);
 			rx_priv->rx_mclk_cnt = 0;
 			return 0;
 		}
-		if (--rx_priv->rx_mclk_cnt == 0)
-			iowrite32(0x0, rx_priv->rx_mclk_mode_muxsel);
+		if (--rx_priv->rx_mclk_cnt == 0) {
+			if (rx_priv->dev_up)
+				iowrite32(0x0, rx_priv->rx_mclk_mode_muxsel);
+		}
 		clk_disable_unprepare(rx_priv->rx_npl_clk);
 		clk_disable_unprepare(rx_priv->rx_core_clk);
 	}
@@ -1132,6 +1137,7 @@
 		rx_macro_wcd_clsh_imped_config(codec, data, false);
 		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_SSR_DOWN, NULL);
@@ -1140,6 +1146,12 @@
 			SWR_DEVICE_DOWN, NULL);
 		break;
 	case BOLERO_MACRO_EVT_SSR_UP:
+		rx_priv->dev_up = true;
+		/* enable&disable MCLK_MUX1 to reset GFMUX reg */
+		bolero_request_clock(rx_priv->dev,
+				RX_MACRO, MCLK_MUX1, true);
+		bolero_request_clock(rx_priv->dev,
+				RX_MACRO, MCLK_MUX1, false);
 		swrm_wcd_notify(
 			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
 			SWR_DEVICE_SSR_UP, NULL);
@@ -3028,6 +3040,7 @@
 		dev_err(rx_dev, "%s: failed to add snd_ctls\n", __func__);
 		return ret;
 	}
+	rx_priv->dev_up = true;
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF1 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback");
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index 9a6dff3..ec870ad 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -756,6 +756,11 @@
 	struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
 	int ret = 0;
 
+	if (regmap == NULL) {
+		dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	dev_dbg(wsa_priv->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
 		__func__, mclk_enable, dapm, wsa_priv->wsa_mclk_users);
 
@@ -2431,6 +2436,11 @@
 	struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;
 	struct regmap *regmap = dev_get_regmap(wsa_priv->dev->parent, NULL);
 
+	if (regmap == NULL) {
+		dev_err(wsa_priv->dev, "%s: regmap is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	mutex_lock(&wsa_priv->swr_clk_lock);
 
 	dev_dbg(wsa_priv->dev, "%s: swrm clock %s\n",
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 864aeda..8436605 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -166,7 +166,7 @@
 			char *prop, u8 path)
 {
 	u32 *dt_array, map_size, map_length;
-	u32 port_num, ch_mask, ch_rate, old_port_num = 0;
+	u32 port_num = 0, ch_mask, ch_rate, old_port_num = 0;
 	u32 slave_port_type, master_port_type;
 	u32 i, ch_iter = 0;
 	int ret = 0;
@@ -188,7 +188,8 @@
 	if (!of_find_property(dev->of_node, prop,
 				&map_size)) {
 		dev_err(dev, "missing port mapping prop %s\n", prop);
-		goto err_pdata_fail;
+		ret = -EINVAL;
+		goto err;
 	}
 
 	map_length = map_size / (NUM_SWRS_DT_PARAMS * sizeof(u32));
@@ -197,13 +198,14 @@
 
 	if (!dt_array) {
 		ret = -ENOMEM;
-		goto err_pdata_fail;
+		goto err;
 	}
 	ret = of_property_read_u32_array(dev->of_node, prop, dt_array,
 				NUM_SWRS_DT_PARAMS * map_length);
 	if (ret) {
 		dev_err(dev, "%s: Failed to read  port mapping from prop %s\n",
 					__func__, prop);
+		ret = -EINVAL;
 		goto err_pdata_fail;
 	}
 
@@ -230,7 +232,8 @@
 
 err_pdata_fail:
 	kfree(dt_array);
-	return -EINVAL;
+err:
+	return ret;
 }
 
 static int wcd937x_tx_connect_port(struct snd_soc_codec *codec,
diff --git a/asoc/codecs/wcd937x/wcd937x_slave.c b/asoc/codecs/wcd937x/wcd937x_slave.c
index 252504f..baab26f 100644
--- a/asoc/codecs/wcd937x/wcd937x_slave.c
+++ b/asoc/codecs/wcd937x/wcd937x_slave.c
@@ -31,6 +31,11 @@
 	uint8_t devnum = 0;
 	struct swr_device *pdev = to_swr_device(dev);
 
+	if (pdev == NULL) {
+		dev_err(dev, "%s: pdev is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	wcd937x_slave = devm_kzalloc(&pdev->dev,
 				sizeof(struct wcd937x_slave_priv), GFP_KERNEL);
 	if (!wcd937x_slave)
@@ -59,6 +64,11 @@
 	struct wcd937x_slave_priv *wcd937x_slave = NULL;
 	struct swr_device *pdev = to_swr_device(dev);
 
+	if (pdev == NULL) {
+		dev_err(dev, "%s: pdev is NULL\n", __func__);
+		return;
+	}
+
 	wcd937x_slave = swr_get_dev_data(pdev);
 	if (!wcd937x_slave) {
 		dev_err(&pdev->dev, "%s: wcd937x_slave is NULL\n", __func__);
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 83bba1c..516b83f 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -1932,6 +1932,12 @@
 				if (test_bit(idx, &copp))
 					break;
 
+			if (idx >= MAX_COPPS_PER_PORT) {
+				pr_debug("%s: copp idx is invalid, exiting\n",
+								__func__);
+				mutex_unlock(&routing_lock);
+				return;
+			}
 			port_id = msm_bedais[reg].port_id;
 			topology = adm_get_topology_for_port_copp_idx(port_id,
 								      idx);
@@ -22898,6 +22904,12 @@
 			for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
 				if (test_bit(idx, &copp))
 					break;
+
+			if (idx >= MAX_COPPS_PER_PORT) {
+				pr_debug("%s: copp idx is invalid, exiting\n",
+								__func__);
+				continue;
+			}
 			fdai->be_srate = bedai->sample_rate;
 			port_id = bedai->port_id;
 			topology = adm_get_topology_for_port_copp_idx(port_id,
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index 4e621a9..b9c11ac 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -2833,6 +2833,9 @@
 	    (topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY))
 		rate = 16000;
 
+	if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY)
+		channel_mode = 1;
+
 	/*
 	 * Routing driver reuses the same adm for streams with the same
 	 * app_type, sample_rate etc.
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index fe55341..ddcc101 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -4892,6 +4892,7 @@
 #define COMPRESSED_PASSTHROUGH_DEFAULT_TOPOLOGY         0x0001076B
 #define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY            0x00010774
 #define VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY			0x00010F89
+#define VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY		0x10000003
 #define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY			0x00010F72
 #define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY		0x00010F75
 #define VPM_TX_DM_RFECNS_COPP_TOPOLOGY			0x00010F86