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 <quic_mengw@quicinc.com>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
42e49611b0
commit
95c95b2d67
@@ -1383,7 +1383,7 @@ int lpass_cdc_runtime_resume(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (priv->core_hw_vote_count == 0) {
|
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) {
|
if (ret < 0) {
|
||||||
dev_err_ratelimited(dev, "%s:lpass core hw enable failed\n",
|
dev_err_ratelimited(dev, "%s:lpass core hw enable failed\n",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -1401,7 +1401,7 @@ audio_vote:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (priv->core_audio_vote_count == 0) {
|
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) {
|
if (ret < 0) {
|
||||||
dev_err_ratelimited(dev, "%s:lpass audio hw enable failed\n",
|
dev_err_ratelimited(dev, "%s:lpass audio hw enable failed\n",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -1429,7 +1429,7 @@ int lpass_cdc_runtime_suspend(struct device *dev)
|
|||||||
if (priv->lpass_core_hw_vote != NULL) {
|
if (priv->lpass_core_hw_vote != NULL) {
|
||||||
if (--priv->core_hw_vote_count == 0)
|
if (--priv->core_hw_vote_count == 0)
|
||||||
digital_cdc_rsc_mgr_hw_vote_disable(
|
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)
|
if (priv->core_hw_vote_count < 0)
|
||||||
priv->core_hw_vote_count = 0;
|
priv->core_hw_vote_count = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -1442,7 +1442,7 @@ int lpass_cdc_runtime_suspend(struct device *dev)
|
|||||||
if (priv->lpass_audio_hw_vote != NULL) {
|
if (priv->lpass_audio_hw_vote != NULL) {
|
||||||
if (--priv->core_audio_vote_count == 0)
|
if (--priv->core_audio_vote_count == 0)
|
||||||
digital_cdc_rsc_mgr_hw_vote_disable(
|
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)
|
if (priv->core_audio_vote_count < 0)
|
||||||
priv->core_audio_vote_count = 0;
|
priv->core_audio_vote_count = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -366,7 +366,7 @@ int mi2s_tdm_hw_vote_req(struct msm_common_pdata *pdata, int enable)
|
|||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
if (atomic_read(&pdata->lpass_audio_hw_vote_ref_cnt) == 0) {
|
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) {
|
if (ret < 0) {
|
||||||
pr_err("%s lpass audio hw vote enable failed %d\n",
|
pr_err("%s lpass audio hw vote enable failed %d\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
@@ -377,7 +377,7 @@ int mi2s_tdm_hw_vote_req(struct msm_common_pdata *pdata, int enable)
|
|||||||
} else {
|
} else {
|
||||||
atomic_dec(&pdata->lpass_audio_hw_vote_ref_cnt);
|
atomic_dec(&pdata->lpass_audio_hw_vote_ref_cnt);
|
||||||
if (atomic_read(&pdata->lpass_audio_hw_vote_ref_cnt) == 0)
|
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)
|
else if (atomic_read(&pdata->lpass_audio_hw_vote_ref_cnt) < 0)
|
||||||
atomic_set(&pdata->lpass_audio_hw_vote_ref_cnt, 0);
|
atomic_set(&pdata->lpass_audio_hw_vote_ref_cnt, 0);
|
||||||
}
|
}
|
||||||
|
@@ -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) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <dsp/digital-cdc-rsc-mgr.h>
|
#include <dsp/digital-cdc-rsc-mgr.h>
|
||||||
|
#include <linux/dev_printk.h>
|
||||||
|
|
||||||
struct mutex hw_vote_lock;
|
struct mutex hw_vote_lock;
|
||||||
static bool is_init_done;
|
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
|
* digital_cdc_rsc_mgr_hw_vote_enable - Enables hw vote in DSP
|
||||||
*
|
*
|
||||||
* @vote_handle: vote handle for which voting needs to be done
|
* @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
|
* 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;
|
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);
|
ret = clk_prepare_enable(vote_handle);
|
||||||
mutex_unlock(&hw_vote_lock);
|
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);
|
trace_printk("%s: return %d\n", __func__, ret);
|
||||||
return 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
|
* digital_cdc_rsc_mgr_hw_vote_disable - Disables hw vote in DSP
|
||||||
*
|
*
|
||||||
* @vote_handle: vote handle for which voting needs to be disabled
|
* @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) {
|
if (!is_init_done || vote_handle == NULL) {
|
||||||
pr_err_ratelimited("%s: init failed or vote handle NULL\n",
|
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);
|
mutex_lock(&hw_vote_lock);
|
||||||
clk_disable_unprepare(vote_handle);
|
clk_disable_unprepare(vote_handle);
|
||||||
mutex_unlock(&hw_vote_lock);
|
mutex_unlock(&hw_vote_lock);
|
||||||
|
dev_dbg(dev, "%s: leave\n", __func__);
|
||||||
trace_printk("%s\n", __func__);
|
trace_printk("%s\n", __func__);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable);
|
EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
* 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
|
#ifndef DIGITAL_CDC_RSC_MGR_H
|
||||||
@@ -10,25 +11,25 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_DIGITAL_CDC_RSC_MGR
|
#ifdef CONFIG_DIGITAL_CDC_RSC_MGR
|
||||||
|
|
||||||
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);
|
||||||
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);
|
||||||
void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle);
|
void digital_cdc_rsc_mgr_hw_vote_reset(struct clk *vote_handle);
|
||||||
|
|
||||||
void digital_cdc_rsc_mgr_init(void);
|
void digital_cdc_rsc_mgr_init(void);
|
||||||
void digital_cdc_rsc_mgr_exit(void);
|
void digital_cdc_rsc_mgr_exit(void);
|
||||||
|
|
||||||
#else
|
#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;
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -905,7 +905,7 @@ int lpi_pinctrl_runtime_resume(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&state->core_hw_vote_lock);
|
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) {
|
if (ret < 0) {
|
||||||
pm_runtime_set_autosuspend_delay(dev,
|
pm_runtime_set_autosuspend_delay(dev,
|
||||||
LPI_AUTO_SUSPEND_DELAY_ERROR);
|
LPI_AUTO_SUSPEND_DELAY_ERROR);
|
||||||
@@ -941,7 +941,7 @@ int lpi_pinctrl_runtime_suspend(struct device *dev)
|
|||||||
|
|
||||||
mutex_lock(&state->core_hw_vote_lock);
|
mutex_lock(&state->core_hw_vote_lock);
|
||||||
if (state->core_hw_vote_status) {
|
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;
|
state->core_hw_vote_status = false;
|
||||||
}
|
}
|
||||||
mutex_unlock(&state->core_hw_vote_lock);
|
mutex_unlock(&state->core_hw_vote_lock);
|
||||||
|
@@ -425,7 +425,7 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm,
|
|||||||
if (++swrm->hw_core_clk_en == 1) {
|
if (++swrm->hw_core_clk_en == 1) {
|
||||||
ret =
|
ret =
|
||||||
digital_cdc_rsc_mgr_hw_vote_enable(
|
digital_cdc_rsc_mgr_hw_vote_enable(
|
||||||
swrm->lpass_core_hw_vote);
|
swrm->lpass_core_hw_vote, swrm->dev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err_ratelimited(swrm->dev,
|
dev_err_ratelimited(swrm->dev,
|
||||||
"%s:lpass core hw enable failed\n",
|
"%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;
|
swrm->hw_core_clk_en = 0;
|
||||||
else if (swrm->hw_core_clk_en == 0)
|
else if (swrm->hw_core_clk_en == 0)
|
||||||
digital_cdc_rsc_mgr_hw_vote_disable(
|
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) {
|
if (++swrm->aud_core_clk_en == 1) {
|
||||||
ret =
|
ret =
|
||||||
digital_cdc_rsc_mgr_hw_vote_enable(
|
digital_cdc_rsc_mgr_hw_vote_enable(
|
||||||
swrm->lpass_core_audio);
|
swrm->lpass_core_audio, swrm->dev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err_ratelimited(swrm->dev,
|
dev_err_ratelimited(swrm->dev,
|
||||||
"%s:lpass audio hw enable failed\n",
|
"%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;
|
swrm->aud_core_clk_en = 0;
|
||||||
else if (swrm->aud_core_clk_en == 0)
|
else if (swrm->aud_core_clk_en == 0)
|
||||||
digital_cdc_rsc_mgr_hw_vote_disable(
|
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);
|
swrm_device_down(&pdev->dev);
|
||||||
mutex_lock(&swrm->devlock);
|
mutex_lock(&swrm->devlock);
|
||||||
swrm->dev_up = false;
|
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;
|
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;
|
swrm->aud_core_clk_en = 0;
|
||||||
mutex_unlock(&swrm->devlock);
|
mutex_unlock(&swrm->devlock);
|
||||||
mutex_lock(&swrm->reslock);
|
mutex_lock(&swrm->reslock);
|
||||||
|
Reference in New Issue
Block a user