Browse Source

asoc: codecs: bolero: Keep track of lpass core votes

Unvote lpass audio and hw votes from bolero suspend
only if the voting was done from the corresponding
resume function.

Change-Id: I299b8e5639efe2883980abc5d0904733fbdc5a77
Signed-off-by: Karthikeyan Mani <[email protected]>
Karthikeyan Mani 5 years ago
parent
commit
ac555db98e
2 changed files with 48 additions and 15 deletions
  1. 45 15
      asoc/codecs/bolero/bolero-cdc.c
  2. 3 0
      asoc/codecs/bolero/internal.h

+ 45 - 15
asoc/codecs/bolero/bolero-cdc.c

@@ -960,9 +960,13 @@ static int bolero_probe(struct platform_device *pdev)
 	priv->plat_data.update_wcd_event = bolero_cdc_update_wcd_event;
 	priv->plat_data.register_notifier = bolero_cdc_register_notifier;
 
+	priv->core_hw_vote_count = 0;
+	priv->core_audio_vote_count = 0;
+
 	dev_set_drvdata(&pdev->dev, priv);
 	mutex_init(&priv->io_lock);
 	mutex_init(&priv->clk_lock);
+	mutex_init(&priv->vote_lock);
 	INIT_WORK(&priv->bolero_add_child_devices_work,
 		  bolero_add_child_devices);
 	schedule_work(&priv->bolero_add_child_devices_work);
@@ -1002,6 +1006,7 @@ static int bolero_remove(struct platform_device *pdev)
 	of_platform_depopulate(&pdev->dev);
 	mutex_destroy(&priv->io_lock);
 	mutex_destroy(&priv->clk_lock);
+	mutex_destroy(&priv->vote_lock);
 	return 0;
 }
 
@@ -1015,21 +1020,35 @@ int bolero_runtime_resume(struct device *dev)
 		return 0;
 	}
 
-	ret = clk_prepare_enable(priv->lpass_core_hw_vote);
-	if (ret < 0)
-		dev_err(dev, "%s:lpass core hw enable failed\n",
-			__func__);
+	mutex_lock(&priv->vote_lock);
+	if (priv->core_hw_vote_count == 0) {
+		ret = clk_prepare_enable(priv->lpass_core_hw_vote);
+		if (ret < 0) {
+			dev_err(dev, "%s:lpass core hw enable failed\n",
+				__func__);
+			goto audio_vote;
+		}
+	}
+	priv->core_hw_vote_count++;
 
+audio_vote:
 	if (priv->lpass_audio_hw_vote == NULL) {
 		dev_dbg(dev, "%s: Invalid lpass audio hw node\n", __func__);
-		return 0;
+		goto done;
 	}
 
-	ret = clk_prepare_enable(priv->lpass_audio_hw_vote);
-	if (ret < 0)
-		dev_err(dev, "%s:lpass audio hw enable failed\n",
-			__func__);
+	if (priv->core_audio_vote_count == 0) {
+		ret = clk_prepare_enable(priv->lpass_audio_hw_vote);
+		if (ret < 0) {
+			dev_err(dev, "%s:lpass audio hw enable failed\n",
+				__func__);
+			goto done;
+		}
+	}
+	priv->core_audio_vote_count++;
 
+done:
+	mutex_unlock(&priv->vote_lock);
 	pm_runtime_set_autosuspend_delay(priv->dev, BOLERO_AUTO_SUSPEND_DELAY);
 	return 0;
 }
@@ -1039,17 +1058,28 @@ int bolero_runtime_suspend(struct device *dev)
 {
 	struct bolero_priv *priv = dev_get_drvdata(dev->parent);
 
-	if (priv->lpass_core_hw_vote != NULL)
-		clk_disable_unprepare(priv->lpass_core_hw_vote);
-	else
+	mutex_lock(&priv->vote_lock);
+	if (priv->lpass_core_hw_vote != NULL) {
+		if (--priv->core_hw_vote_count == 0)
+			clk_disable_unprepare(priv->lpass_core_hw_vote);
+		if (priv->core_hw_vote_count < 0)
+			priv->core_hw_vote_count = 0;
+	} else {
 		dev_dbg(dev, "%s: Invalid lpass core hw node\n",
 			__func__);
+	}
 
-	if (priv->lpass_audio_hw_vote != NULL)
-		clk_disable_unprepare(priv->lpass_audio_hw_vote);
-	else
+	if (priv->lpass_audio_hw_vote != NULL) {
+		if (--priv->core_audio_vote_count == 0)
+			clk_disable_unprepare(priv->lpass_audio_hw_vote);
+		if (priv->core_audio_vote_count < 0)
+			priv->core_audio_vote_count = 0;
+	} else {
 		dev_dbg(dev, "%s: Invalid lpass audio hw node\n",
 			__func__);
+	}
+
+	mutex_unlock(&priv->vote_lock);
 	return 0;
 }
 EXPORT_SYMBOL(bolero_runtime_suspend);

+ 3 - 0
asoc/codecs/bolero/internal.h

@@ -46,6 +46,7 @@ struct bolero_priv {
 	struct regmap *regmap;
 	struct mutex io_lock;
 	struct mutex clk_lock;
+	struct mutex vote_lock;
 	bool va_without_decimation;
 	bool macros_supported[MAX_MACRO];
 	bool dev_up;
@@ -60,6 +61,8 @@ struct bolero_priv {
 	u32 version;
 	struct clk *lpass_core_hw_vote;
 	struct clk *lpass_audio_hw_vote;
+	int core_hw_vote_count;
+	int core_audio_vote_count;
 
 	/* Entry for version info */
 	struct snd_info_entry *entry;