Re: [PATCH V2] ASoC: fsl_audmix: rework runtime PM handling in probe

From: Shengjiu Wang

Date: Tue Jun 30 2026 - 08:37:24 EST


On Thu, Jun 18, 2026 at 10:33 AM <shengjiu.wang@xxxxxxxxxxx> wrote:
>
> From: Shengjiu Wang <shengjiu.wang@xxxxxxx>
>
> After pm_runtime_enable() the AUDMIX block is powered off and stays
> suspended until the first runtime resume. Register writes issued between
> probe() and the first resume (e.g. from DAPM or ALSA control paths)
> target unpowered hardware and cause a system hang.
>
> Fix this by calling pm_runtime_resume_and_get() immediately after
> pm_runtime_enable() to power the hardware up and enable its clocks.
> Release the reference afterwards with pm_runtime_put() to allow the
> runtime PM framework to suspend the device and switch the regmap to
> cache-only mode when idle.
>
> When CONFIG_PM is disabled or runtime PM is not enabled, pm_runtime_*
> calls are stubs that do not power up the hardware. Handle this case
> explicitly by calling fsl_audmix_runtime_resume() directly so the
> hardware is always initialised and its clocks are enabled, ensuring
> register accesses succeed regardless of PM configuration.
>
> Fixes: be1df61cf06ef ("ASoC: fsl: Add Audio Mixer CPU DAI driver")
> Signed-off-by: Shengjiu Wang <shengjiu.wang@xxxxxxx>
> ---
> Changes in v2:
> - remove the call of regcache_cache_only in probe, rework the runtime
> handling in probe, call the pm_runtime_put() to enable the cache only.
> - refine the commit message
>
> sound/soc/fsl/fsl_audmix.c | 24 ++++++++++++++++++++++--
> 1 file changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c
> index f819f33ec46b..2885cc10b02d 100644
> --- a/sound/soc/fsl/fsl_audmix.c
> +++ b/sound/soc/fsl/fsl_audmix.c
> @@ -457,6 +457,9 @@ static const struct of_device_id fsl_audmix_ids[] = {
> };
> MODULE_DEVICE_TABLE(of, fsl_audmix_ids);
>
> +static int fsl_audmix_runtime_resume(struct device *dev);
> +static int fsl_audmix_runtime_suspend(struct device *dev);
> +
> static int fsl_audmix_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -488,13 +491,25 @@ static int fsl_audmix_probe(struct platform_device *pdev)
> spin_lock_init(&priv->lock);
> platform_set_drvdata(pdev, priv);
> pm_runtime_enable(dev);
> + if (!pm_runtime_enabled(dev)) {
> + ret = fsl_audmix_runtime_resume(dev);
> + if (ret)
> + goto err_disable_pm;
> + }
> +
> + ret = pm_runtime_resume_and_get(dev);
> + if (ret < 0)
> + goto err_pm_get_sync;
> +
> + /* To enable regmap cache only when runtime PM enabled */
> + pm_runtime_put(dev);

Check the comments from Sashiko. Needs to use pm_runtime_put_sync to
avoid the race
of asynchronous.
Will send the next version.

Best regards
Shengjiu Wang
>
> ret = devm_snd_soc_register_component(dev, &fsl_audmix_component,
> fsl_audmix_dai,
> ARRAY_SIZE(fsl_audmix_dai));
> if (ret) {
> dev_err(dev, "failed to register ASoC DAI\n");
> - goto err_disable_pm;
> + goto err_pm_get_sync;
> }
>
> /*
> @@ -506,12 +521,15 @@ static int fsl_audmix_probe(struct platform_device *pdev)
> if (IS_ERR(priv->pdev)) {
> ret = PTR_ERR(priv->pdev);
> dev_err(dev, "failed to register platform: %d\n", ret);
> - goto err_disable_pm;
> + goto err_pm_get_sync;
> }
> }
>
> return 0;
>
> +err_pm_get_sync:
> + if (!pm_runtime_status_suspended(dev))
> + fsl_audmix_runtime_suspend(dev);
> err_disable_pm:
> pm_runtime_disable(dev);
> return ret;
> @@ -522,6 +540,8 @@ static void fsl_audmix_remove(struct platform_device *pdev)
> struct fsl_audmix *priv = dev_get_drvdata(&pdev->dev);
>
> pm_runtime_disable(&pdev->dev);
> + if (!pm_runtime_status_suspended(&pdev->dev))
> + fsl_audmix_runtime_suspend(&pdev->dev);
>
> if (priv->pdev)
> platform_device_unregister(priv->pdev);
> --
> 2.34.1
>