ASoC: bolero: Enable RCO for VA usecase

Add support to enable RCO during VA usecase.

Change-Id: Ic6b640f62a8a88b5d5b616fc05798917913356ed
Signed-off-by: Sudheer Papothi <spapothi@codeaurora.org>
diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c
index b7d7d37..8ef4769 100644
--- a/asoc/codecs/bolero/tx-macro.c
+++ b/asoc/codecs/bolero/tx-macro.c
@@ -110,6 +110,11 @@
 	ANC_FB_TUNE1
 };
 
+enum {
+	TX_MCLK,
+	VA_MCLK,
+};
+
 struct tx_mute_work {
 	struct tx_macro_priv *tx_priv;
 	u32 decimator;
@@ -152,6 +157,7 @@
 	int child_count;
 	int tx_swr_clk_cnt;
 	int va_swr_clk_cnt;
+	int swr_clk_type;
 };
 
 static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -1457,33 +1463,60 @@
 			  0, -84, 40, digital_gain),
 };
 
-static int tx_macro_swrm_clock(void *handle, bool enable)
+static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
+				      struct regmap *regmap, int clk_type,
+				      bool enable)
 {
-	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
-	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: clock type %s, enable: %s\n",
+		__func__, (clk_type ? "VA_MCLK" : "TX_MCLK"),
+		(enable ? "enable" : "disable"));
 
-	mutex_lock(&tx_priv->swr_clk_lock);
-
-	dev_dbg(tx_priv->dev, "%s: swrm clock %s\n",
-		__func__, (enable ? "enable" : "disable"));
 	if (enable) {
 		if (tx_priv->swr_clk_users == 0) {
 			msm_cdc_pinctrl_select_active_state(
 						tx_priv->tx_swr_gpio_p);
-			ret = tx_macro_mclk_enable(tx_priv, 1);
-			if (ret < 0) {
-				msm_cdc_pinctrl_select_sleep_state(
-						tx_priv->tx_swr_gpio_p);
-				dev_err(tx_priv->dev,
-					"%s: request clock enable failed\n",
-					__func__);
-				goto exit;
+
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   true);
+			if (clk_type == TX_MCLK) {
+				ret = tx_macro_mclk_enable(tx_priv, 1);
+				if (ret < 0) {
+					msm_cdc_pinctrl_select_sleep_state(
+							tx_priv->tx_swr_gpio_p);
+					dev_err_ratelimited(tx_priv->dev,
+						"%s: request clock enable failed\n",
+						__func__);
+					goto done;
+				}
+			}
+			if (clk_type == VA_MCLK) {
+				ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+								   TX_CORE_CLK,
+								   VA_CORE_CLK,
+								   true);
+				if (ret < 0) {
+					msm_cdc_pinctrl_select_sleep_state(
+							tx_priv->tx_swr_gpio_p);
+					dev_err_ratelimited(tx_priv->dev,
+						"%s: swr request clk failed\n",
+						__func__);
+					goto done;
+				}
+				if (tx_priv->tx_mclk_users == 0) {
+					regmap_update_bits(regmap,
+						BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK,
+						0x01, 0x01);
+					regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+						0x01, 0x01);
+					regmap_update_bits(regmap,
+				      BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+						0x01, 0x01);
+				}
 			}
 			if (tx_priv->reset_swr)
 				regmap_update_bits(regmap,
@@ -1496,29 +1529,126 @@
 				regmap_update_bits(regmap,
 					BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
 					0x02, 0x00);
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   false);
 			tx_priv->reset_swr = false;
 		}
 		tx_priv->swr_clk_users++;
 	} else {
 		if (tx_priv->swr_clk_users <= 0) {
-			dev_err(tx_priv->dev,
+			dev_err_ratelimited(tx_priv->dev,
 				"tx swrm clock users already 0\n");
 			tx_priv->swr_clk_users = 0;
-			goto exit;
+			return 0;
 		}
 		tx_priv->swr_clk_users--;
 		if (tx_priv->swr_clk_users == 0) {
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   true);
 			regmap_update_bits(regmap,
 				BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
 				0x01, 0x00);
-			tx_macro_mclk_enable(tx_priv, 0);
+			if (clk_type == TX_MCLK)
+				tx_macro_mclk_enable(tx_priv, 0);
+			if (clk_type == VA_MCLK) {
+				if (tx_priv->tx_mclk_users == 0) {
+					regmap_update_bits(regmap,
+				      BOLERO_CDC_TX_CLK_RST_CTRL_FS_CNT_CONTROL,
+						0x01, 0x00);
+					regmap_update_bits(regmap,
+					BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL,
+						0x01, 0x00);
+				}
+				ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+								   TX_CORE_CLK,
+								   VA_CORE_CLK,
+								   false);
+				if (ret < 0) {
+					dev_err_ratelimited(tx_priv->dev,
+						"%s: swr request clk failed\n",
+						__func__);
+					goto done;
+				}
+			}
+			ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+							   TX_CORE_CLK,
+							   TX_CORE_CLK,
+							   false);
 			msm_cdc_pinctrl_select_sleep_state(
 						tx_priv->tx_swr_gpio_p);
 		}
 	}
+	return 0;
+
+done:
+	bolero_clk_rsc_request_clock(tx_priv->dev,
+				TX_CORE_CLK,
+				TX_CORE_CLK,
+				false);
+	return ret;
+}
+
+static int tx_macro_swrm_clock(void *handle, bool enable)
+{
+	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
+	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",
+		__func__, (enable ? "enable" : "disable"));
+
+	if (enable) {
+		/*For standalone VA usecase, enable VA macro clock */
+		if (tx_priv->va_swr_clk_cnt && !tx_priv->tx_swr_clk_cnt
+			&& (tx_priv->swr_clk_type == TX_MCLK)) {
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			tx_priv->swr_clk_type = VA_MCLK;
+		} else {
+			/* Disable VA MCLK if its already enabled */
+			if (tx_priv->swr_clk_type == VA_MCLK)
+				tx_macro_tx_va_mclk_enable(tx_priv,
+							regmap, VA_MCLK, false);
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							TX_MCLK, enable);
+			if (ret)
+				goto done;
+			tx_priv->swr_clk_type = TX_MCLK;
+		}
+	} else {
+		if (tx_priv->swr_clk_type == VA_MCLK) {
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							VA_MCLK, enable);
+			if (ret)
+				goto done;
+			tx_priv->swr_clk_type = TX_MCLK;
+		} else {
+			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+							TX_MCLK, enable);
+			if (tx_priv->va_swr_clk_cnt) {
+				ret = tx_macro_tx_va_mclk_enable(tx_priv,
+						regmap, VA_MCLK, true);
+				if (ret)
+					goto done;
+				tx_priv->swr_clk_type = VA_MCLK;
+			}
+		}
+	}
 	dev_dbg(tx_priv->dev, "%s: swrm clock users %d\n",
 		__func__, tx_priv->swr_clk_users);
-exit:
+done:
 	mutex_unlock(&tx_priv->swr_clk_lock);
 	return ret;
 }