diff options
author | Aditya Bavanari <abavanar@codeaurora.org> | 2020-03-13 21:44:15 +0530 |
---|---|---|
committer | Aditya Bavanari <abavanar@codeaurora.org> | 2020-03-20 16:44:51 +0530 |
commit | d80c2b32c3cb9563d0893f2fa3e73688a970c2cd (patch) | |
tree | 31fed33878ff876d6972e1d80fad5b8ba3d4bba8 | |
parent | b51434354d9c6d47fd5cfa04eb71353cbd9aac0b (diff) | |
download | msm-extra-d80c2b32c3cb9563d0893f2fa3e73688a970c2cd.tar.gz |
audio-kernel: Synchronize hw vote and unvote requests
HW vote and unvote is currently called from multiple
clients leading to synchronization issues
during SSR/PDR scenarios. Synchronize all the requests
by using a vote resource manager.
Change-Id: I7e63f69ab5d761a3bb4c7ce70bbef2e8bfd76cfb
Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
-rw-r--r-- | 4.0/asoc/codecs/bolero/bolero-cdc.c | 13 | ||||
-rw-r--r-- | 4.0/dsp/Kbuild | 2 | ||||
-rw-r--r-- | 4.0/dsp/hw-vote-rsc.c | 82 | ||||
-rw-r--r-- | 4.0/dsp/q6_init.c | 4 | ||||
-rw-r--r-- | 4.0/dsp/q6_init.h | 4 | ||||
-rw-r--r-- | 4.0/include/dsp/hw-vote-rsc.h | 15 | ||||
-rw-r--r-- | 4.0/soc/pinctrl-lpi.c | 8 | ||||
-rw-r--r-- | 4.0/soc/swr-mstr-ctrl.c | 11 |
8 files changed, 125 insertions, 14 deletions
diff --git a/4.0/asoc/codecs/bolero/bolero-cdc.c b/4.0/asoc/codecs/bolero/bolero-cdc.c index 5ddc674e..59b1c58f 100644 --- a/4.0/asoc/codecs/bolero/bolero-cdc.c +++ b/4.0/asoc/codecs/bolero/bolero-cdc.c @@ -14,6 +14,7 @@ #include <soc/snd_event.h> #include <linux/pm_runtime.h> #include <soc/swr-common.h> +#include <dsp/hw-vote-rsc.h> #include "bolero-cdc.h" #include "internal.h" #include "bolero-clk-rsc.h" @@ -835,6 +836,10 @@ static int bolero_ssr_enable(struct device *dev, void *data) if (priv->rsc_clk_cb) priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_GFMUX_UP); + /* Reset HW votes after SSR */ + hw_vote_rsc_reset(priv->lpass_core_hw_vote); + hw_vote_rsc_reset(priv->lpass_audio_hw_vote); + trace_printk("%s: clk count reset\n", __func__); regcache_cache_only(priv->regmap, false); mutex_lock(&priv->clk_lock); @@ -1379,7 +1384,7 @@ int bolero_runtime_resume(struct device *dev) } if (priv->core_hw_vote_count == 0) { - ret = clk_prepare_enable(priv->lpass_core_hw_vote); + ret = hw_vote_rsc_enable(priv->lpass_core_hw_vote); if (ret < 0) { dev_err(dev, "%s:lpass core hw enable failed\n", __func__); @@ -1397,7 +1402,7 @@ audio_vote: } if (priv->core_audio_vote_count == 0) { - ret = clk_prepare_enable(priv->lpass_audio_hw_vote); + ret = hw_vote_rsc_enable(priv->lpass_audio_hw_vote); if (ret < 0) { dev_err(dev, "%s:lpass audio hw enable failed\n", __func__); @@ -1422,7 +1427,7 @@ int bolero_runtime_suspend(struct device *dev) 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); + hw_vote_rsc_disable(priv->lpass_core_hw_vote); if (priv->core_hw_vote_count < 0) priv->core_hw_vote_count = 0; } else { @@ -1434,7 +1439,7 @@ int bolero_runtime_suspend(struct device *dev) if (priv->lpass_audio_hw_vote != NULL) { if (--priv->core_audio_vote_count == 0) - clk_disable_unprepare(priv->lpass_audio_hw_vote); + hw_vote_rsc_disable(priv->lpass_audio_hw_vote); if (priv->core_audio_vote_count < 0) priv->core_audio_vote_count = 0; } else { diff --git a/4.0/dsp/Kbuild b/4.0/dsp/Kbuild index 6f1a1801..53c510b9 100644 --- a/4.0/dsp/Kbuild +++ b/4.0/dsp/Kbuild @@ -112,6 +112,7 @@ ifdef CONFIG_SND_SOC_MSM_QDSP6V2_INTF Q6_OBJS += adsp_err.o Q6_OBJS += msm_audio_ion.o Q6_OBJS += avtimer.o + Q6_OBJS += hw-vote-rsc.o Q6_OBJS += q6_init.o endif @@ -131,6 +132,7 @@ ifdef CONFIG_SND_SOC_MSM_QDSP6V2_VM Q6_OBJS += adsp_err.o Q6_OBJS += msm_audio_ion_vm.o Q6_OBJS += avtimer.o + Q6_OBJS += hw-vote-rsc.o Q6_OBJS += q6_init.o endif diff --git a/4.0/dsp/hw-vote-rsc.c b/4.0/dsp/hw-vote-rsc.c new file mode 100644 index 00000000..b90c56b7 --- /dev/null +++ b/4.0/dsp/hw-vote-rsc.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/ratelimit.h> +#include <dsp/hw-vote-rsc.h> + +struct mutex hw_vote_lock; +static bool is_init_done; + +int hw_vote_rsc_enable(struct clk* vote_handle) +{ + int ret = 0; + + if (!is_init_done || vote_handle == NULL) { + pr_err_ratelimited("%s: init failed or vote handle NULL\n", + __func__); + return -EINVAL; + } + + mutex_lock(&hw_vote_lock); + ret = clk_prepare_enable(vote_handle); + mutex_unlock(&hw_vote_lock); + + trace_printk("%s\n", __func__); + return ret; +} +EXPORT_SYMBOL(hw_vote_rsc_enable); + +void hw_vote_rsc_disable(struct clk* vote_handle) +{ + if (!is_init_done || vote_handle == NULL) { + pr_err_ratelimited("%s: init failed or vote handle NULL\n", + __func__); + return; + } + + mutex_lock(&hw_vote_lock); + clk_disable_unprepare(vote_handle); + mutex_unlock(&hw_vote_lock); + trace_printk("%s\n", __func__); +} +EXPORT_SYMBOL(hw_vote_rsc_disable); + +void hw_vote_rsc_reset(struct clk* vote_handle) +{ + int count = 0; + + if (!is_init_done || vote_handle == NULL) { + pr_err_ratelimited("%s: init failed or vote handle NULL\n", + __func__); + return; + } + + mutex_lock(&hw_vote_lock); + while (__clk_is_enabled(vote_handle)) { + clk_disable_unprepare(vote_handle); + count++; + } + pr_debug("%s: Vote count after SSR: %d\n", __func__, count); + trace_printk("%s: Vote count after SSR: %d\n", __func__, count); + + while (count--) + clk_prepare_enable(vote_handle); + mutex_unlock(&hw_vote_lock); +} +EXPORT_SYMBOL(hw_vote_rsc_reset); + +void hw_vote_rsc_init() +{ + mutex_init(&hw_vote_lock); + is_init_done = true; +} + +void hw_vote_rsc_exit() +{ + mutex_destroy(&hw_vote_lock); + is_init_done = false; +} diff --git a/4.0/dsp/q6_init.c b/4.0/dsp/q6_init.c index fb18741d..f0f3d44b 100644 --- a/4.0/dsp/q6_init.c +++ b/4.0/dsp/q6_init.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2019-2020 The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> @@ -24,11 +24,13 @@ static int __init audio_q6_init(void) avtimer_init(); msm_mdf_init(); voice_mhi_init(); + hw_vote_rsc_init(); return 0; } static void __exit audio_q6_exit(void) { + hw_vote_rsc_exit(); msm_mdf_exit(); avtimer_exit(); audio_slimslave_exit(); diff --git a/4.0/dsp/q6_init.h b/4.0/dsp/q6_init.h index 4df2e032..028a9344 100644 --- a/4.0/dsp/q6_init.h +++ b/4.0/dsp/q6_init.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef __Q6_INIT_H__ @@ -16,6 +16,7 @@ int core_init(void); int rtac_init(void); int msm_audio_ion_init(void); int avtimer_init(void); +int hw_vote_rsc_init(void); #ifdef CONFIG_MSM_MDF int msm_mdf_init(void); void msm_mdf_exit(void); @@ -43,6 +44,7 @@ static inline void spk_params_exit(void) } #endif +void hw_vote_rsc_exit(void); void avtimer_exit(void); void msm_audio_ion_exit(void); void rtac_exit(void); diff --git a/4.0/include/dsp/hw-vote-rsc.h b/4.0/include/dsp/hw-vote-rsc.h new file mode 100644 index 00000000..35e8cd9c --- /dev/null +++ b/4.0/include/dsp/hw-vote-rsc.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef HW_VOTE_RSC_H +#define HW_VOTE_RSC_H + +int hw_vote_rsc_enable(struct clk* vote_handle); +void hw_vote_rsc_disable(struct clk* vote_handle); +void hw_vote_rsc_reset(struct clk* vote_handle); +void hw_vote_rsc_init(void); +void hw_vote_rsc_exit(void); + +#endif /* HW_VOTE_RSC_H */ diff --git a/4.0/soc/pinctrl-lpi.c b/4.0/soc/pinctrl-lpi.c index 4df9791c..2b8810d9 100644 --- a/4.0/soc/pinctrl-lpi.c +++ b/4.0/soc/pinctrl-lpi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include <linux/gpio.h> @@ -16,6 +16,7 @@ #include <linux/clk.h> #include <linux/bitops.h> #include <soc/snd_event.h> +#include <dsp/hw-vote-rsc.h> #include <linux/pm_runtime.h> #include <dsp/audio_notifier.h> @@ -842,7 +843,6 @@ static int lpi_pinctrl_remove(struct platform_device *pdev) gpiochip_remove(&state->chip); mutex_destroy(&state->core_hw_vote_lock); mutex_destroy(&state->slew_access_lock); - return 0; } @@ -869,7 +869,7 @@ int lpi_pinctrl_runtime_resume(struct device *dev) } mutex_lock(&state->core_hw_vote_lock); - ret = clk_prepare_enable(hw_vote); + ret = hw_vote_rsc_enable(hw_vote); if (ret < 0) { pm_runtime_set_autosuspend_delay(dev, LPI_AUTO_SUSPEND_DELAY_ERROR); @@ -903,7 +903,7 @@ int lpi_pinctrl_runtime_suspend(struct device *dev) mutex_lock(&state->core_hw_vote_lock); if (state->core_hw_vote_status) { - clk_disable_unprepare(hw_vote); + hw_vote_rsc_disable(hw_vote); state->core_hw_vote_status = false; } mutex_unlock(&state->core_hw_vote_lock); diff --git a/4.0/soc/swr-mstr-ctrl.c b/4.0/soc/swr-mstr-ctrl.c index 23ccd234..771d245d 100644 --- a/4.0/soc/swr-mstr-ctrl.c +++ b/4.0/soc/swr-mstr-ctrl.c @@ -22,6 +22,7 @@ #include <soc/swr-common.h> #include <linux/regmap.h> #include <dsp/msm-audio-event-notify.h> +#include <dsp/hw-vote-rsc.h> #include "swrm_registers.h" #include "swr-mstr-ctrl.h" @@ -378,7 +379,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, } if (++swrm->hw_core_clk_en == 1) { ret = - clk_prepare_enable( + hw_vote_rsc_enable( swrm->lpass_core_hw_vote); if (ret < 0) { dev_err(swrm->dev, @@ -392,7 +393,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, if (swrm->hw_core_clk_en < 0) swrm->hw_core_clk_en = 0; else if (swrm->hw_core_clk_en == 0) - clk_disable_unprepare( + hw_vote_rsc_disable( swrm->lpass_core_hw_vote); } } @@ -410,7 +411,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, } if (++swrm->aud_core_clk_en == 1) { ret = - clk_prepare_enable( + hw_vote_rsc_enable( swrm->lpass_core_audio); if (ret < 0) { dev_err(swrm->dev, @@ -424,7 +425,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, if (swrm->aud_core_clk_en < 0) swrm->aud_core_clk_en = 0; else if (swrm->aud_core_clk_en == 0) - clk_disable_unprepare( + hw_vote_rsc_disable( swrm->lpass_core_audio); } } @@ -3319,6 +3320,8 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) swrm_device_down(&pdev->dev); mutex_lock(&swrm->devlock); swrm->dev_up = false; + swrm->hw_core_clk_en = 0; + swrm->aud_core_clk_en = 0; mutex_unlock(&swrm->devlock); mutex_lock(&swrm->reslock); swrm->state = SWR_MSTR_SSR; |