asoc: bolero: reset all clks after SSR/PDR

After SSR/PDR, the lpass clocks will be in off state. Force restart
clocks after SSR/PDR, if enabled before SSR/PDR, to reenable the clocks.

Change-Id: I3d850d92bdc6324aa7a64a83a9066f388a85c7f7
Signed-off-by: Meng Wang <mengw@codeaurora.org>
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index cee08dc..2a2f785 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -614,11 +614,12 @@
 	if (priv->rsc_clk_cb)
 		priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_UP);
 
-	if (priv->macro_params[VA_MACRO].event_handler)
-		priv->macro_params[VA_MACRO].event_handler(
-			priv->component,
-			BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET, 0x0);
-
+	for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) {
+		if (priv->macro_params[macro_idx].event_handler)
+			priv->macro_params[macro_idx].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_CLK_RESET, 0x0);
+	}
 	regcache_cache_only(priv->regmap, false);
 	mutex_lock(&priv->clk_lock);
 	priv->dev_up = true;
diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h
index e533eb8..3bb82b9 100644
--- a/asoc/codecs/bolero/bolero-cdc.h
+++ b/asoc/codecs/bolero/bolero-cdc.h
@@ -38,6 +38,7 @@
 	BOLERO_MACRO_EVT_SSR_DOWN,
 	BOLERO_MACRO_EVT_SSR_UP,
 	BOLERO_MACRO_EVT_WAIT_VA_CLK_RESET,
+	BOLERO_MACRO_EVT_CLK_RESET,
 	BOLERO_MACRO_EVT_REG_WAKE_IRQ
 };
 
diff --git a/asoc/codecs/bolero/bolero-clk-rsc.c b/asoc/codecs/bolero/bolero-clk-rsc.c
index 82f3879..d325d76 100644
--- a/asoc/codecs/bolero/bolero-clk-rsc.c
+++ b/asoc/codecs/bolero/bolero-clk-rsc.c
@@ -10,6 +10,7 @@
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include "bolero-cdc.h"
 #include "bolero-clk-rsc.h"
 
@@ -91,6 +92,51 @@
 	return NULL;
 }
 
+int bolero_rsc_clk_reset(struct device *dev, int clk_id)
+{
+	struct device *clk_dev = NULL;
+	struct bolero_clk_rsc *priv = NULL;
+	int count = 0;
+
+	if (!dev) {
+		pr_err("%s: dev is null %d\n", __func__);
+		return -EINVAL;
+	}
+
+	if (clk_id < 0 || clk_id >= MAX_CLK - NPL_CLK_OFFSET) {
+		pr_err("%s: Invalid clk_id: %d\n",
+			__func__, clk_id);
+		return -EINVAL;
+	}
+
+	clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent);
+	if (!clk_dev) {
+		pr_err("%s: Invalid rsc clk device\n", __func__);
+		return -EINVAL;
+	}
+
+	priv = dev_get_drvdata(clk_dev);
+	if (!priv) {
+		pr_err("%s: Invalid rsc clk priviate data\n", __func__);
+		return -EINVAL;
+	}
+	mutex_lock(&priv->rsc_clk_lock);
+	while (__clk_is_enabled(priv->clk[clk_id])) {
+		clk_disable_unprepare(priv->clk[clk_id + NPL_CLK_OFFSET]);
+		clk_disable_unprepare(priv->clk[clk_id]);
+		count++;
+	}
+	dev_dbg(priv->dev,
+		"%s: clock reset after ssr, count %d\n", __func__, count);
+	while (count--) {
+		clk_prepare_enable(priv->clk[clk_id]);
+		clk_prepare_enable(priv->clk[clk_id + NPL_CLK_OFFSET]);
+	}
+	mutex_unlock(&priv->rsc_clk_lock);
+	return 0;
+}
+EXPORT_SYMBOL(bolero_rsc_clk_reset);
+
 static int bolero_clk_rsc_mux0_clk_request(struct bolero_clk_rsc *priv,
 					   int clk_id,
 					   bool enable)
diff --git a/asoc/codecs/bolero/bolero-clk-rsc.h b/asoc/codecs/bolero/bolero-clk-rsc.h
index b378f73..fc3c02f 100644
--- a/asoc/codecs/bolero/bolero-clk-rsc.h
+++ b/asoc/codecs/bolero/bolero-clk-rsc.h
@@ -18,6 +18,7 @@
 				int default_clk_id,
 				int clk_id_req,
 				bool enable);
+int bolero_rsc_clk_reset(struct device *dev, int clk_id);
 #else
 static inline void bolero_clk_rsc_fs_gen_request(struct device *dev,
 						bool enable)
@@ -37,6 +38,9 @@
 {
 	return 0;
 }
-
+static inline int bolero_rsc_clk_reset(struct device *dev, int clk_id)
+{
+	return 0;
+}
 #endif /* CONFIG_SND_SOC_BOLERO */
 #endif /* BOLERO_CLK_RSC_H */
diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c
index 0be5c4e..8702dba 100644
--- a/asoc/codecs/bolero/rx-macro.c
+++ b/asoc/codecs/bolero/rx-macro.c
@@ -1241,6 +1241,9 @@
 			rx_priv->swr_ctrl_data[0].rx_swr_pdev,
 			SWR_DEVICE_SSR_UP, NULL);
 		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(rx_dev, RX_CORE_CLK);
+		break;
 	}
 	return ret;
 }
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index cb3aa59..20606f6 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -360,6 +360,9 @@
 			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
 			SWR_DEVICE_SSR_UP, NULL);
 		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(tx_dev, TX_CORE_CLK);
+		break;
 	}
 	return 0;
 }
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index ba9c7f1..a94ca77 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -234,6 +234,9 @@
 				"%s: va_mclk_users is non-zero still, audio SSR fail!!\n",
 				__func__);
 		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(va_dev, VA_CORE_CLK);
+		break;
 	default:
 		break;
 	}
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index f41392d..5b07cbd 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -924,6 +924,9 @@
 			wsa_priv->swr_ctrl_data[0].wsa_swr_pdev,
 			SWR_DEVICE_SSR_UP, NULL);
 		break;
+	case BOLERO_MACRO_EVT_CLK_RESET:
+		bolero_rsc_clk_reset(wsa_dev, WSA_CORE_CLK);
+		break;
 	}
 	return 0;
 }