2019-04-18 03:33:40

by Shengjiu Wang

[permalink] [raw]
Subject: [PATCH] ASoC: fsl_esai: Add pm runtime function

In imx8 when systerm enter suspend state, the power of subsystem will
be off, the clock enable state will be lost and register configuration
will be lost. So the driver need to enter runtime suspend state in
suspend.

With this implementation the suspend function almost same as runtime
suspend function, so remove the suspend function, just use
pm_runtime_force_suspend instead, and same for the resume function.

And also need to move clock enablement to runtime resume and clock
disablement to runtime suspend.

Signed-off-by: Shengjiu Wang <[email protected]>
---
sound/soc/fsl/fsl_esai.c | 141 ++++++++++++++++++++++++++---------------------
1 file changed, 77 insertions(+), 64 deletions(-)

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index bad0dfed6b68..b1e27db3752b 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>

@@ -466,30 +467,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
- int ret;
-
- /*
- * Some platforms might use the same bit to gate all three or two of
- * clocks, so keep all clocks open/close at the same time for safety
- */
- ret = clk_prepare_enable(esai_priv->coreclk);
- if (ret)
- return ret;
- if (!IS_ERR(esai_priv->spbaclk)) {
- ret = clk_prepare_enable(esai_priv->spbaclk);
- if (ret)
- goto err_spbaclk;
- }
- if (!IS_ERR(esai_priv->extalclk)) {
- ret = clk_prepare_enable(esai_priv->extalclk);
- if (ret)
- goto err_extalck;
- }
- if (!IS_ERR(esai_priv->fsysclk)) {
- ret = clk_prepare_enable(esai_priv->fsysclk);
- if (ret)
- goto err_fsysclk;
- }

if (!dai->active) {
/* Set synchronous mode */
@@ -506,16 +483,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,

return 0;

-err_fsysclk:
- if (!IS_ERR(esai_priv->extalclk))
- clk_disable_unprepare(esai_priv->extalclk);
-err_extalck:
- if (!IS_ERR(esai_priv->spbaclk))
- clk_disable_unprepare(esai_priv->spbaclk);
-err_spbaclk:
- clk_disable_unprepare(esai_priv->coreclk);
-
- return ret;
}

static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
@@ -576,20 +543,6 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
return 0;
}

-static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
-
- if (!IS_ERR(esai_priv->fsysclk))
- clk_disable_unprepare(esai_priv->fsysclk);
- if (!IS_ERR(esai_priv->extalclk))
- clk_disable_unprepare(esai_priv->extalclk);
- if (!IS_ERR(esai_priv->spbaclk))
- clk_disable_unprepare(esai_priv->spbaclk);
- clk_disable_unprepare(esai_priv->coreclk);
-}
-
static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
@@ -658,7 +611,6 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,

static const struct snd_soc_dai_ops fsl_esai_dai_ops = {
.startup = fsl_esai_startup,
- .shutdown = fsl_esai_shutdown,
.trigger = fsl_esai_trigger,
.hw_params = fsl_esai_hw_params,
.set_sysclk = fsl_esai_set_dai_sysclk,
@@ -947,6 +899,10 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}

+ pm_runtime_enable(&pdev->dev);
+
+ regcache_cache_only(esai_priv->regmap, true);
+
ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE);
if (ret)
dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
@@ -954,6 +910,13 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}

+static int fsl_esai_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
static const struct of_device_id fsl_esai_dt_ids[] = {
{ .compatible = "fsl,imx35-esai", },
{ .compatible = "fsl,vf610-esai", },
@@ -961,23 +924,37 @@ static int fsl_esai_probe(struct platform_device *pdev)
};
MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);

-#ifdef CONFIG_PM_SLEEP
-static int fsl_esai_suspend(struct device *dev)
-{
- struct fsl_esai *esai = dev_get_drvdata(dev);
-
- regcache_cache_only(esai->regmap, true);
- regcache_mark_dirty(esai->regmap);
-
- return 0;
-}
-
-static int fsl_esai_resume(struct device *dev)
+#ifdef CONFIG_PM
+static int fsl_esai_runtime_resume(struct device *dev)
{
struct fsl_esai *esai = dev_get_drvdata(dev);
int ret;

+ /*
+ * Some platforms might use the same bit to gate all three or two of
+ * clocks, so keep all clocks open/close at the same time for safety
+ */
+ ret = clk_prepare_enable(esai->coreclk);
+ if (ret)
+ return ret;
+ if (!IS_ERR(esai->spbaclk)) {
+ ret = clk_prepare_enable(esai->spbaclk);
+ if (ret)
+ goto err_spbaclk;
+ }
+ if (!IS_ERR(esai->extalclk)) {
+ ret = clk_prepare_enable(esai->extalclk);
+ if (ret)
+ goto err_extalclk;
+ }
+ if (!IS_ERR(esai->fsysclk)) {
+ ret = clk_prepare_enable(esai->fsysclk);
+ if (ret)
+ goto err_fsysclk;
+ }
+
regcache_cache_only(esai->regmap, false);
+ regcache_mark_dirty(esai->regmap);

/* FIFO reset for safety */
regmap_update_bits(esai->regmap, REG_ESAI_TFCR,
@@ -987,22 +964,58 @@ static int fsl_esai_resume(struct device *dev)

ret = regcache_sync(esai->regmap);
if (ret)
- return ret;
+ goto err_regcache_sync;

/* FIFO reset done */
regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0);
regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0);

return 0;
+
+err_regcache_sync:
+ if (!IS_ERR(esai->fsysclk))
+ clk_disable_unprepare(esai->fsysclk);
+err_fsysclk:
+ if (!IS_ERR(esai->extalclk))
+ clk_disable_unprepare(esai->extalclk);
+err_extalclk:
+ if (!IS_ERR(esai->spbaclk))
+ clk_disable_unprepare(esai->spbaclk);
+err_spbaclk:
+ clk_disable_unprepare(esai->coreclk);
+
+ return ret;
+}
+
+static int fsl_esai_runtime_suspend(struct device *dev)
+{
+ struct fsl_esai *esai = dev_get_drvdata(dev);
+
+ regcache_cache_only(esai->regmap, true);
+
+ if (!IS_ERR(esai->fsysclk))
+ clk_disable_unprepare(esai->fsysclk);
+ if (!IS_ERR(esai->extalclk))
+ clk_disable_unprepare(esai->extalclk);
+ if (!IS_ERR(esai->spbaclk))
+ clk_disable_unprepare(esai->spbaclk);
+ clk_disable_unprepare(esai->coreclk);
+
+ return 0;
}
-#endif /* CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */

static const struct dev_pm_ops fsl_esai_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(fsl_esai_suspend, fsl_esai_resume)
+ SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend,
+ fsl_esai_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
};

static struct platform_driver fsl_esai_driver = {
.probe = fsl_esai_probe,
+ .remove = fsl_esai_remove,
.driver = {
.name = "fsl-esai-dai",
.pm = &fsl_esai_pm_ops,
--
1.9.1


2019-04-18 09:01:43

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH] ASoC: fsl_esai: Add pm runtime function

On Thu, Apr 18, 2019 at 03:29:09AM +0000, S.j. Wang wrote:
> In imx8 when systerm enter suspend state, the power of subsystem will
> be off, the clock enable state will be lost and register configuration

Just for curiosity, we had similar situation on imx6sx, so we
added suspend/resume with regcache. Why will the clock enable
state be lost too? Does CCM on imx8 (might not be called CCM
though) have any difference? What about clock rate settings?

> will be lost. So the driver need to enter runtime suspend state in
> suspend.

> With this implementation the suspend function almost same as runtime
> suspend function, so remove the suspend function, just use
> pm_runtime_force_suspend instead, and same for the resume function.
>
> And also need to move clock enablement to runtime resume and clock
> disablement to runtime suspend.


> -static int fsl_esai_suspend(struct device *dev)
> - regcache_cache_only(esai->regmap, true);
> - regcache_mark_dirty(esai->regmap);

> +static int fsl_esai_runtime_resume(struct device *dev)
> regcache_cache_only(esai->regmap, false);
> + regcache_mark_dirty(esai->regmap);

Why move the regcache_mark_dirty from suspend to resume?
(I am not saying it's wrong but wondering if this is the
preferable way.)

2019-04-18 09:08:27

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH] ASoC: fsl_esai: Add pm runtime function

On Thu, Apr 18, 2019 at 02:00:12AM -0700, Nicolin Chen wrote:
> On Thu, Apr 18, 2019 at 03:29:09AM +0000, S.j. Wang wrote:

> > In imx8 when systerm enter suspend state, the power of subsystem will
> > be off, the clock enable state will be lost and register configuration

> Just for curiosity, we had similar situation on imx6sx, so we
> added suspend/resume with regcache. Why will the clock enable
> state be lost too? Does CCM on imx8 (might not be called CCM
> though) have any difference? What about clock rate settings?

That sounds like a bug somewhere else - I'd expect that after resume the
clocking would be restored to the state it was in before suspend.


Attachments:
(No filename) (681.00 B)
signature.asc (499.00 B)
Download all attachments

2019-04-18 10:18:31

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH] ASoC: fsl_esai: Add pm runtime function

On Thu, Apr 18, 2019 at 10:15:24AM +0000, S.j. Wang wrote:
> > On Thu, Apr 18, 2019 at 02:00:12AM -0700, Nicolin Chen wrote:
> > > On Thu, Apr 18, 2019 at 03:29:09AM +0000, S.j. Wang wrote:

> > > Just for curiosity, we had similar situation on imx6sx, so we added
> > > suspend/resume with regcache. Why will the clock enable state be lost
> > > too? Does CCM on imx8 (might not be called CCM
> > > though) have any difference? What about clock rate settings?

> > That sounds like a bug somewhere else - I'd expect that after resume the
> > clocking would be restored to the state it was in before suspend.

> There is limitation in our internal design. That is in imx8 the power of
> subsystem will be disabled at suspend, include the clock state , clock rate.

Right, that's fairly normal but usually it'd be restored as part of the
resume process?

> This patch is to enable the pm runtime, so I think it is better to move the
> clock operation to pm runtime, and close the clock at suspend to reduce
> the power.

It's definitely good to turn the clock off as much as possible, yes.


Attachments:
(No filename) (1.09 kB)
signature.asc (499.00 B)
Download all attachments

2019-04-18 10:22:42

by Shengjiu Wang

[permalink] [raw]
Subject: Re: [PATCH] ASoC: fsl_esai: Add pm runtime function

Hi
>
>
> On Thu, Apr 18, 2019 at 03:29:09AM +0000, S.j. Wang wrote:
> > In imx8 when systerm enter suspend state, the power of subsystem will
> > be off, the clock enable state will be lost and register configuration
>
> Just for curiosity, we had similar situation on imx6sx, so we added
> suspend/resume with regcache. Why will the clock enable state be lost too?
> Does CCM on imx8 (might not be called CCM
> though) have any difference? What about clock rate settings?
>
> > will be lost. So the driver need to enter runtime suspend state in
> > suspend.
>
> > With this implementation the suspend function almost same as runtime
> > suspend function, so remove the suspend function, just use
> > pm_runtime_force_suspend instead, and same for the resume function.
> >
> > And also need to move clock enablement to runtime resume and clock
> > disablement to runtime suspend.
>
>
> > -static int fsl_esai_suspend(struct device *dev)
> > - regcache_cache_only(esai->regmap, true);
> > - regcache_mark_dirty(esai->regmap);
>
> > +static int fsl_esai_runtime_resume(struct device *dev)
> > regcache_cache_only(esai->regmap, false);
> > + regcache_mark_dirty(esai->regmap);
>
> Why move the regcache_mark_dirty from suspend to resume?
> (I am not saying it's wrong but wondering if this is the preferable way.)

Seems I should not do this change.
I will remain regcache_mark_dirty(esai->regmap); at its old place.

Best regards
Wang shengjiu


2019-04-18 10:36:14

by Shengjiu Wang

[permalink] [raw]
Subject: Re: [PATCH] ASoC: fsl_esai: Add pm runtime function

Hi

>
> On Thu, Apr 18, 2019 at 02:00:12AM -0700, Nicolin Chen wrote:
> > On Thu, Apr 18, 2019 at 03:29:09AM +0000, S.j. Wang wrote:
>
> > > In imx8 when systerm enter suspend state, the power of subsystem
> > > will be off, the clock enable state will be lost and register
> > > configuration
>
> > Just for curiosity, we had similar situation on imx6sx, so we added
> > suspend/resume with regcache. Why will the clock enable state be lost
> > too? Does CCM on imx8 (might not be called CCM
> > though) have any difference? What about clock rate settings?
>
> That sounds like a bug somewhere else - I'd expect that after resume the
> clocking would be restored to the state it was in before suspend.

There is limitation in our internal design. That is in imx8 the power of
subsystem will be disabled at suspend, include the clock state , clock rate.

I should not add it in comments, please ignore them, I will change the
description.

This patch is to enable the pm runtime, so I think it is better to move the
clock operation to pm runtime, and close the clock at suspend to reduce
the power.

Best regards
Wang shengjiu


2019-04-18 11:15:15

by Shengjiu Wang

[permalink] [raw]
Subject: Re: [PATCH] ASoC: fsl_esai: Add pm runtime function

Hi

> On Thu, Apr 18, 2019 at 10:15:24AM +0000, S.j. Wang wrote:
> > > On Thu, Apr 18, 2019 at 02:00:12AM -0700, Nicolin Chen wrote:
> > > > On Thu, Apr 18, 2019 at 03:29:09AM +0000, S.j. Wang wrote:
>
> > > > Just for curiosity, we had similar situation on imx6sx, so we
> > > > added suspend/resume with regcache. Why will the clock enable
> > > > state be lost too? Does CCM on imx8 (might not be called CCM
> > > > though) have any difference? What about clock rate settings?
>
> > > That sounds like a bug somewhere else - I'd expect that after resume
> > > the clocking would be restored to the state it was in before suspend.
>
> > There is limitation in our internal design. That is in imx8 the power
> > of subsystem will be disabled at suspend, include the clock state , clock
> rate.
>
> Right, that's fairly normal but usually it'd be restored as part of the resume
> process?
>
> > This patch is to enable the pm runtime, so I think it is better to
> > move the clock operation to pm runtime, and close the clock at
> > suspend to reduce the power.
>
> It's definitely good to turn the clock off as much as possible, yes.

Thanks, will send v2.

Best regards
Wang shengjiu