On Thu, Jun 18, 2026 at 10:33 AM <[email protected]> wrote:
>
> From: Shengjiu Wang <[email protected]>
>
> 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 <[email protected]>
> ---
> 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
>

Reply via email to