diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index a63bababe95c..7deb11b2ba83 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -389,33 +389,77 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, { int ret = 0; + mutex_lock(&swrm->devlock); if (core_type == LPASS_HW_CORE) { if (swrm->lpass_core_hw_vote) { if (enable) { - ret = - clk_prepare_enable(swrm->lpass_core_hw_vote); - if (ret < 0) - dev_err(swrm->dev, - "%s:lpass core hw enable failed\n", - __func__); - } else - clk_disable_unprepare(swrm->lpass_core_hw_vote); + if (!swrm->dev_up) { + dev_dbg(swrm->dev, "%s: device is down or SSR state\n", + __func__); + trace_printk("%s: device is down or SSR state\n", + __func__); + mutex_unlock(&swrm->devlock); + return -ENODEV; + } + if (++swrm->hw_core_clk_en == 1) { + ret = + clk_prepare_enable( + swrm->lpass_core_hw_vote); + if (ret < 0) { + dev_err(swrm->dev, + "%s:lpass core hw enable failed\n", + __func__); + --swrm->hw_core_clk_en; + } + } + } else { + --swrm->hw_core_clk_en; + if (swrm->hw_core_clk_en < 0) + swrm->hw_core_clk_en = 0; + else if (swrm->hw_core_clk_en == 0) + clk_disable_unprepare( + swrm->lpass_core_hw_vote); + } } } if (core_type == LPASS_AUDIO_CORE) { if (swrm->lpass_core_audio) { if (enable) { - ret = - clk_prepare_enable(swrm->lpass_core_audio); - if (ret < 0) - dev_err(swrm->dev, - "%s:lpass audio hw enable failed\n", - __func__); - } else - clk_disable_unprepare(swrm->lpass_core_audio); + if (!swrm->dev_up) { + dev_dbg(swrm->dev, "%s: device is down or SSR state\n", + __func__); + trace_printk("%s: device is down or SSR state\n", + __func__); + mutex_unlock(&swrm->devlock); + return -ENODEV; + } + if (++swrm->aud_core_clk_en == 1) { + ret = + clk_prepare_enable( + swrm->lpass_core_audio); + if (ret < 0) { + dev_err(swrm->dev, + "%s:lpass audio hw enable failed\n", + __func__); + --swrm->aud_core_clk_en; + } + } + } else { + --swrm->aud_core_clk_en; + if (swrm->aud_core_clk_en < 0) + swrm->aud_core_clk_en = 0; + else if (swrm->aud_core_clk_en == 0) + clk_disable_unprepare( + swrm->lpass_core_audio); + } } } + mutex_unlock(&swrm->devlock); + dev_dbg(swrm->dev, "%s: hw_clk_en: %d audio_core_clk_en: %d\n", + __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en); + trace_printk("%s: hw_clk_en: %d audio_core_clk_en: %d\n", + __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en); return ret; } @@ -2160,22 +2204,15 @@ static void swrm_device_wakeup_vote(struct swr_master *mstr) dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); return; } - if (++swrm->hw_core_clk_en == 1) - if (swrm_request_hw_vote(swrm, LPASS_HW_CORE, true)) { - dev_err(swrm->dev, "%s:lpass core hw enable failed\n", - __func__); - --swrm->hw_core_clk_en; - } - if ( ++swrm->aud_core_clk_en == 1) - if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { - dev_err(swrm->dev, "%s:lpass audio hw enable failed\n", - __func__); - --swrm->aud_core_clk_en; - } - dev_dbg(swrm->dev, "%s: hw_clk_en: %d audio_core_clk_en: %d\n", - __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en); - trace_printk("%s: hw_clk_en: %d audio_core_clk_en: %d\n", - __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en); + mutex_lock(&swrm->reslock); + if (swrm_request_hw_vote(swrm, LPASS_HW_CORE, true)) + dev_err(swrm->dev, "%s:lpass core hw enable failed\n", + __func__); + if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) + dev_err(swrm->dev, "%s:lpass audio hw enable failed\n", + __func__); + mutex_unlock(&swrm->reslock); + pm_runtime_get_sync(swrm->dev); } @@ -2190,22 +2227,11 @@ static void swrm_device_wakeup_unvote(struct swr_master *mstr) } pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); - dev_dbg(swrm->dev, "%s: hw_clk_en: %d audio_core_clk_en: %d\n", - __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en); - trace_printk("%s: hw_clk_en: %d audio_core_clk_en: %d\n", - __func__, swrm->hw_core_clk_en, swrm->aud_core_clk_en); - --swrm->aud_core_clk_en; - if (swrm->aud_core_clk_en < 0) - swrm->aud_core_clk_en = 0; - else if (swrm->aud_core_clk_en == 0) - swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); - - --swrm->hw_core_clk_en; - if (swrm->hw_core_clk_en < 0) - swrm->hw_core_clk_en = 0; - else if (swrm->hw_core_clk_en == 0) - swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); + mutex_lock(&swrm->reslock); + swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); + swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); + mutex_unlock(&swrm->reslock); swrm_unlock_sleep(swrm); } @@ -3205,12 +3231,19 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) break; case SWR_DEVICE_SSR_DOWN: trace_printk("%s: swr device down called\n", __func__); + mutex_lock(&swrm->mlock); + if (swrm->state == SWR_MSTR_DOWN) + dev_dbg(swrm->dev, "%s:SWR master is already Down:%d\n", + __func__, swrm->state); + else + swrm_device_down(&pdev->dev); mutex_lock(&swrm->devlock); swrm->dev_up = false; mutex_unlock(&swrm->devlock); mutex_lock(&swrm->reslock); swrm->state = SWR_MSTR_SSR; mutex_unlock(&swrm->reslock); + mutex_unlock(&swrm->mlock); break; case SWR_DEVICE_SSR_UP: /* wait for clk voting to be zero */