From 95c95b2d67ee05309f31fb5d55399c97b6c84c74 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Tue, 21 Dec 2021 09:12:31 +0800 Subject: [PATCH] asoc: update digital_cdc_rsc_mgr_hw_vote API Update digital_cdc_rsc_mgr_hw_vote_enable/disable API with device info for easy debug. Also, add swrm clock enable checks during SSR. When SSR happens, swrm->hw_core_clk_en and swrm->aud_core_clk_en will be reset without resetting audio_vote and core_vote clk. This would cause clk mismatch in audio driver and adsp and device fails suspending when there's no audio usecase. Make this change to reset audio_vote and core_vote clk when receiving SWR_DEVICE_SSR_DOWN. Change-Id: I9875aac9f6faf8b6481457a70f31b005073369e0 Signed-off-by: Meng Wang --- asoc/codecs/lpass-cdc/lpass-cdc.c | 8 ++++---- asoc/msm_common.c | 4 ++-- dsp/digital-cdc-rsc-mgr.c | 13 +++++++++---- include/dsp/digital-cdc-rsc-mgr.h | 13 +++++++------ soc/pinctrl-lpi.c | 4 ++-- soc/swr-mstr-ctrl.c | 14 ++++++++++---- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/asoc/codecs/lpass-cdc/lpass-cdc.c b/asoc/codecs/lpass-cdc/lpass-cdc.c index 08b884031a..ded26c3c0c 100644 --- a/asoc/codecs/lpass-cdc/lpass-cdc.c +++ b/asoc/codecs/lpass-cdc/lpass-cdc.c @@ -1383,7 +1383,7 @@ int lpass_cdc_runtime_resume(struct device *dev) } if (priv->core_hw_vote_count == 0) { - ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote, dev); if (ret < 0) { dev_err_ratelimited(dev, "%s:lpass core hw enable failed\n", __func__); @@ -1401,7 +1401,7 @@ audio_vote: } if (priv->core_audio_vote_count == 0) { - ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote, dev); if (ret < 0) { dev_err_ratelimited(dev, "%s:lpass audio hw enable failed\n", __func__); @@ -1429,7 +1429,7 @@ int lpass_cdc_runtime_suspend(struct device *dev) if (priv->lpass_core_hw_vote != NULL) { if (--priv->core_hw_vote_count == 0) digital_cdc_rsc_mgr_hw_vote_disable( - priv->lpass_core_hw_vote); + priv->lpass_core_hw_vote, dev); if (priv->core_hw_vote_count < 0) priv->core_hw_vote_count = 0; } else { @@ -1442,7 +1442,7 @@ int lpass_cdc_runtime_suspend(struct device *dev) if (priv->lpass_audio_hw_vote != NULL) { if (--priv->core_audio_vote_count == 0) digital_cdc_rsc_mgr_hw_vote_disable( - priv->lpass_audio_hw_vote); + priv->lpass_audio_hw_vote, dev); if (priv->core_audio_vote_count < 0) priv->core_audio_vote_count = 0; } else { diff --git a/asoc/msm_common.c b/asoc/msm_common.c index addba64041..9d183c63d6 100644 --- a/asoc/msm_common.c +++ b/asoc/msm_common.c @@ -366,7 +366,7 @@ int mi2s_tdm_hw_vote_req(struct msm_common_pdata *pdata, int enable) if (enable) { if (atomic_read(&pdata->lpass_audio_hw_vote_ref_cnt) == 0) { - ret = digital_cdc_rsc_mgr_hw_vote_enable(pdata->lpass_audio_hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable(pdata->lpass_audio_hw_vote, NULL); if (ret < 0) { pr_err("%s lpass audio hw vote enable failed %d\n", __func__, ret); @@ -377,7 +377,7 @@ int mi2s_tdm_hw_vote_req(struct msm_common_pdata *pdata, int enable) } else { atomic_dec(&pdata->lpass_audio_hw_vote_ref_cnt); if (atomic_read(&pdata->lpass_audio_hw_vote_ref_cnt) == 0) - digital_cdc_rsc_mgr_hw_vote_disable(pdata->lpass_audio_hw_vote); + digital_cdc_rsc_mgr_hw_vote_disable(pdata->lpass_audio_hw_vote, NULL); else if (atomic_read(&pdata->lpass_audio_hw_vote_ref_cnt) < 0) atomic_set(&pdata->lpass_audio_hw_vote_ref_cnt, 0); } diff --git a/dsp/digital-cdc-rsc-mgr.c b/dsp/digital-cdc-rsc-mgr.c index be5d5cad79..c69fea55a3 100644 --- a/dsp/digital-cdc-rsc-mgr.c +++ b/dsp/digital-cdc-rsc-mgr.c @@ -1,12 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include #include #include +#include struct mutex hw_vote_lock; static bool is_init_done; @@ -15,10 +17,11 @@ static bool is_init_done; * digital_cdc_rsc_mgr_hw_vote_enable - Enables hw vote in DSP * * @vote_handle: vote handle for which voting needs to be done + * @dev: indicate which device votes * * Returns 0 on success or -EINVAL/error code on failure */ -int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle) +int digital_cdc_rsc_mgr_hw_vote_enable(struct clk *vote_handle, struct device *dev) { int ret = 0; @@ -32,7 +35,7 @@ int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle) ret = clk_prepare_enable(vote_handle); mutex_unlock(&hw_vote_lock); - pr_debug("%s: return %d\n", __func__, ret); + dev_dbg(dev, "%s: return %d\n", __func__, ret); trace_printk("%s: return %d\n", __func__, ret); return ret; } @@ -42,9 +45,10 @@ EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_enable); * digital_cdc_rsc_mgr_hw_vote_disable - Disables hw vote in DSP * * @vote_handle: vote handle for which voting needs to be disabled + * @dev: indicate which device unvotes * */ -void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle) +void digital_cdc_rsc_mgr_hw_vote_disable(struct clk *vote_handle, struct device *dev) { if (!is_init_done || vote_handle == NULL) { pr_err_ratelimited("%s: init failed or vote handle NULL\n", @@ -55,6 +59,7 @@ void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle) mutex_lock(&hw_vote_lock); clk_disable_unprepare(vote_handle); mutex_unlock(&hw_vote_lock); + dev_dbg(dev, "%s: leave\n", __func__); trace_printk("%s\n", __func__); } EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable); diff --git a/include/dsp/digital-cdc-rsc-mgr.h b/include/dsp/digital-cdc-rsc-mgr.h index dbfbb9fcc5..95e70ea1f4 100644 --- a/include/dsp/digital-cdc-rsc-mgr.h +++ b/include/dsp/digital-cdc-rsc-mgr.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef DIGITAL_CDC_RSC_MGR_H @@ -10,25 +11,25 @@ #ifdef CONFIG_DIGITAL_CDC_RSC_MGR -int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle); -void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle); -void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle); +int digital_cdc_rsc_mgr_hw_vote_enable(struct clk *vote_handle, struct device *dev); +void digital_cdc_rsc_mgr_hw_vote_disable(struct clk *vote_handle, struct device *dev); +void digital_cdc_rsc_mgr_hw_vote_reset(struct clk *vote_handle); void digital_cdc_rsc_mgr_init(void); void digital_cdc_rsc_mgr_exit(void); #else -static inline int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle) +static inline int digital_cdc_rsc_mgr_hw_vote_enable(struct clk *vote_handle, struct device *dev) { return 0; } -static inline void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle) +static inline void digital_cdc_rsc_mgr_hw_vote_disable(struct clk *vote_handle, struct device *dev) { } -static inline void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle) +static inline void digital_cdc_rsc_mgr_hw_vote_reset(struct clk *vote_handle) { } diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c index 6b87df8225..ec7d19182b 100644 --- a/soc/pinctrl-lpi.c +++ b/soc/pinctrl-lpi.c @@ -905,7 +905,7 @@ int lpi_pinctrl_runtime_resume(struct device *dev) } mutex_lock(&state->core_hw_vote_lock); - ret = digital_cdc_rsc_mgr_hw_vote_enable(hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable(hw_vote, dev); if (ret < 0) { pm_runtime_set_autosuspend_delay(dev, LPI_AUTO_SUSPEND_DELAY_ERROR); @@ -941,7 +941,7 @@ int lpi_pinctrl_runtime_suspend(struct device *dev) mutex_lock(&state->core_hw_vote_lock); if (state->core_hw_vote_status) { - digital_cdc_rsc_mgr_hw_vote_disable(hw_vote); + digital_cdc_rsc_mgr_hw_vote_disable(hw_vote, dev); state->core_hw_vote_status = false; } mutex_unlock(&state->core_hw_vote_lock); diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 200ed224af..d88dab5132 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -425,7 +425,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, if (++swrm->hw_core_clk_en == 1) { ret = digital_cdc_rsc_mgr_hw_vote_enable( - swrm->lpass_core_hw_vote); + swrm->lpass_core_hw_vote, swrm->dev); if (ret < 0) { dev_err_ratelimited(swrm->dev, "%s:lpass core hw enable failed\n", @@ -439,7 +439,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, swrm->hw_core_clk_en = 0; else if (swrm->hw_core_clk_en == 0) digital_cdc_rsc_mgr_hw_vote_disable( - swrm->lpass_core_hw_vote); + swrm->lpass_core_hw_vote, swrm->dev); } } } @@ -457,7 +457,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, if (++swrm->aud_core_clk_en == 1) { ret = digital_cdc_rsc_mgr_hw_vote_enable( - swrm->lpass_core_audio); + swrm->lpass_core_audio, swrm->dev); if (ret < 0) { dev_err_ratelimited(swrm->dev, "%s:lpass audio hw enable failed\n", @@ -471,7 +471,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, swrm->aud_core_clk_en = 0; else if (swrm->aud_core_clk_en == 0) digital_cdc_rsc_mgr_hw_vote_disable( - swrm->lpass_core_audio); + swrm->lpass_core_audio, swrm->dev); } } } @@ -3681,7 +3681,13 @@ 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; + if (swrm->hw_core_clk_en) + digital_cdc_rsc_mgr_hw_vote_disable( + swrm->lpass_core_hw_vote, swrm->dev); swrm->hw_core_clk_en = 0; + if (swrm->aud_core_clk_en) + digital_cdc_rsc_mgr_hw_vote_disable( + swrm->lpass_core_audio, swrm->dev); swrm->aud_core_clk_en = 0; mutex_unlock(&swrm->devlock); mutex_lock(&swrm->reslock);