Browse Source

ASoC: bolero: Fix issue in clock sequence during VA concurrency

Fix issue in clock sequence when switching between VA clock to
TX clock and viceversa during VA usecase.

Change-Id: I4a7d423916b70b4b3c54d0d9a28b8ea874584525
Signed-off-by: Sudheer Papothi <[email protected]>
Sudheer Papothi 5 years ago
parent
commit
cf3b406a5f
1 changed files with 104 additions and 87 deletions
  1. 104 87
      asoc/codecs/bolero/tx-macro.c

+ 104 - 87
asoc/codecs/bolero/tx-macro.c

@@ -159,7 +159,8 @@ struct tx_macro_priv {
 	int child_count;
 	int tx_swr_clk_cnt;
 	int va_swr_clk_cnt;
-	int swr_clk_type;
+	int va_clk_status;
+	int tx_clk_status;
 };
 
 static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -1477,50 +1478,53 @@ static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
 		(enable ? "enable" : "disable"), tx_priv->tx_mclk_users);
 
 	if (enable) {
-		if (tx_priv->swr_clk_users == 0) {
+		if (tx_priv->swr_clk_users == 0)
 			msm_cdc_pinctrl_select_active_state(
 						tx_priv->tx_swr_gpio_p);
 
+		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) {
+				if (tx_priv->swr_clk_users == 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,
-							   TX_CORE_CLK,
+							   VA_CORE_CLK,
 							   true);
-			if (clk_type == TX_MCLK) {
-				ret = tx_macro_mclk_enable(tx_priv, 1);
-				if (ret < 0) {
+			if (ret < 0) {
+				if (tx_priv->swr_clk_users == 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;
-				}
+				dev_err_ratelimited(tx_priv->dev,
+					"%s: swr request clk 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->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->swr_clk_users == 0) {
 			dev_dbg(tx_priv->dev, "%s: reset_swr: %d\n",
 				__func__, tx_priv->reset_swr);
 			if (tx_priv->reset_swr)
@@ -1534,12 +1538,12 @@ static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
 				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;
 		}
+		ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   false);
 		tx_priv->swr_clk_users++;
 	} else {
 		if (tx_priv->swr_clk_users <= 0) {
@@ -1548,44 +1552,44 @@ static int tx_macro_tx_va_mclk_enable(struct tx_macro_priv *tx_priv,
 			tx_priv->swr_clk_users = 0;
 			return 0;
 		}
+		ret = bolero_clk_rsc_request_clock(tx_priv->dev,
+						   TX_CORE_CLK,
+						   TX_CORE_CLK,
+						   true);
 		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);
+		if (tx_priv->swr_clk_users == 0)
 			regmap_update_bits(regmap,
 				BOLERO_CDC_TX_CLK_RST_CTRL_SWR_CONTROL,
 				0x01, 0x00);
-			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;
-				}
+		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,
-							   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);
+		if (tx_priv->swr_clk_users == 0)
 			msm_cdc_pinctrl_select_sleep_state(
 						tx_priv->tx_swr_gpio_p);
-		}
 	}
 	return 0;
 
@@ -1609,53 +1613,66 @@ static int tx_macro_swrm_clock(void *handle, bool enable)
 	}
 
 	mutex_lock(&tx_priv->swr_clk_lock);
-	dev_dbg(tx_priv->dev, "%s: swrm clock %s\n",
-		__func__, (enable ? "enable" : "disable"));
+	dev_dbg(tx_priv->dev,
+		"%s: swrm clock %s tx_swr_clk_cnt: %d va_swr_clk_cnt: %d\n",
+		__func__, (enable ? "enable" : "disable"),
+		tx_priv->tx_swr_clk_cnt, tx_priv->va_swr_clk_cnt);
 
 	if (enable) {
 		pm_runtime_get_sync(tx_priv->dev);
-		/*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)) {
+		if (tx_priv->va_swr_clk_cnt && !tx_priv->tx_swr_clk_cnt) {
 			ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
 							VA_MCLK, enable);
 			if (ret)
 				goto done;
-			tx_priv->swr_clk_type = VA_MCLK;
+			tx_priv->va_clk_status++;
 		} 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;
+			tx_priv->tx_clk_status++;
 		}
 		pm_runtime_mark_last_busy(tx_priv->dev);
 		pm_runtime_put_autosuspend(tx_priv->dev);
 	} else {
-		if (tx_priv->swr_clk_type == VA_MCLK) {
+		if (tx_priv->va_clk_status && !tx_priv->tx_clk_status) {
 			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 {
+			--tx_priv->va_clk_status;
+		} else if (!tx_priv->va_clk_status && tx_priv->tx_clk_status) {
 			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->tx_clk_status;
+		} else if (tx_priv->va_clk_status && tx_priv->tx_clk_status) {
+			if (!tx_priv->va_swr_clk_cnt && tx_priv->tx_swr_clk_cnt) {
+				ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+								VA_MCLK, enable);
 				if (ret)
 					goto done;
-				tx_priv->swr_clk_type = VA_MCLK;
+				--tx_priv->va_clk_status;
+			} else {
+				ret = tx_macro_tx_va_mclk_enable(tx_priv, regmap,
+								TX_MCLK, enable);
+				if (ret)
+					goto done;
+				--tx_priv->tx_clk_status;
 			}
+
+		} else {
+			dev_dbg(tx_priv->dev,
+				"%s: Both clocks are disabled\n", __func__);
 		}
 	}
-	dev_dbg(tx_priv->dev, "%s: swrm clock users %d\n",
-		__func__, tx_priv->swr_clk_users);
+
+	dev_dbg(tx_priv->dev,
+		"%s: swrm clock users %d tx_clk_sts_cnt: %d va_clk_sts_cnt: %d\n",
+		__func__, tx_priv->swr_clk_users, tx_priv->tx_clk_status,
+		tx_priv->va_clk_status);
 done:
 	mutex_unlock(&tx_priv->swr_clk_lock);
 	return ret;