diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index c0c51ca582..8db452930e 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/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); diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h index 21c96520c4..d353a2d21b 100644 --- a/asoc/codecs/bolero/internal.h +++ b/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;