diff mbox series

[2/2] ASoC: fsl: Move clock operation to PM runtime

Message ID 20190420155846.10027-3-daniel.baluta@nxp.com (mailing list archive)
State New, archived
Headers show
Series Add runtime PM for SAI digital audio interface | expand

Commit Message

Daniel Baluta April 20, 2019, 3:59 p.m. UTC
From: Shengjiu Wang <shengjiu.wang@nxp.com>

Turn off/on clocks when device enters suspend/resume. This
helps saving power.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
 sound/soc/fsl/fsl_sai.c | 54 +++++++++++++++++++++++++++++++++--------
 1 file changed, 44 insertions(+), 10 deletions(-)

Comments

Nicolin Chen April 21, 2019, 5:54 a.m. UTC | #1
On Sat, Apr 20, 2019 at 03:59:05PM +0000, Daniel Baluta wrote:
> Turn off/on clocks when device enters suspend/resume. This
> helps saving power.

> @@ -934,6 +933,25 @@ static int fsl_sai_runtime_suspend(struct device *dev)
>  static int fsl_sai_runtime_resume(struct device *dev)
>  {
>  	struct fsl_sai *sai = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = clk_prepare_enable(sai->bus_clk);
> +	if (ret) {
> +		dev_err(dev, "failed to enable bus clock: %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
> +		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
> +		if (ret)
> +			goto disable_bus_clk;
> +	}
> +
> +	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
> +		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
> +		if (ret)
> +			goto disable_tx_clk;
> +	}

The driver only enables mclk_clks for I2S master mode. But this
change enables them for I2S slave mode also. It doesn't sound a
right thing to me since we are supposed to save power?
Viorel Suman April 22, 2019, 11:02 a.m. UTC | #2
Hi Nicolin,

On Sb, 2019-04-20 at 22:54 -0700, Nicolin Chen wrote:
> On Sat, Apr 20, 2019 at 03:59:05PM +0000, Daniel Baluta wrote:
> > 
> > Turn off/on clocks when device enters suspend/resume. This
> > helps saving power.
> > 
> > @@ -934,6 +933,25 @@ static int fsl_sai_runtime_suspend(struct device *dev)
> >  static int fsl_sai_runtime_resume(struct device *dev)
> >  {
> >  	struct fsl_sai *sai = dev_get_drvdata(dev);
> > +	int ret;
> > +
> > +	ret = clk_prepare_enable(sai->bus_clk);
> > +	if (ret) {
> > +		dev_err(dev, "failed to enable bus clock: %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
> > +		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
> > +		if (ret)
> > +			goto disable_bus_clk;
> > +	}
> > +
> > +	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
> > +		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
> > +		if (ret)
> > +			goto disable_tx_clk;
> > +	}
> The driver only enables mclk_clks for I2S master mode. But this
> change enables them for I2S slave mode also. It doesn't sound a
> right thing to me since we are supposed to save power?

This change does not enable them for I2S slave mode, please check "fsl_sai_hw_params"
and "fsl_sai_hw_free" functions: the field "sai->mclk_streams" is modified only for
the case when "if (!sai->is_slave_mode)";

Regards,
Viorel
Nicolin Chen April 22, 2019, 6:15 p.m. UTC | #3
On Mon, Apr 22, 2019 at 11:02:22AM +0000, Viorel Suman wrote:
> Hi Nicolin,
> 
> On Sb, 2019-04-20 at 22:54 -0700, Nicolin Chen wrote:
> > On Sat, Apr 20, 2019 at 03:59:05PM +0000, Daniel Baluta wrote:
> > > 
> > > Turn off/on clocks when device enters suspend/resume. This
> > > helps saving power.
> > > 
> > > @@ -934,6 +933,25 @@ static int fsl_sai_runtime_suspend(struct device *dev)
> > >  static int fsl_sai_runtime_resume(struct device *dev)
> > >  {
> > >  	struct fsl_sai *sai = dev_get_drvdata(dev);
> > > +	int ret;
> > > +
> > > +	ret = clk_prepare_enable(sai->bus_clk);
> > > +	if (ret) {
> > > +		dev_err(dev, "failed to enable bus clock: %d\n", ret);
> > > +		return ret;
> > > +	}
> > > +
> > > +	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
> > > +		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
> > > +		if (ret)
> > > +			goto disable_bus_clk;
> > > +	}
> > > +
> > > +	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
> > > +		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
> > > +		if (ret)
> > > +			goto disable_tx_clk;
> > > +	}
> > The driver only enables mclk_clks for I2S master mode. But this
> > change enables them for I2S slave mode also. It doesn't sound a
> > right thing to me since we are supposed to save power?
> 
> This change does not enable them for I2S slave mode, please check "fsl_sai_hw_params"
> and "fsl_sai_hw_free" functions: the field "sai->mclk_streams" is modified only for
> the case when "if (!sai->is_slave_mode)";

Thanks for the input. This should be fine then.

Nicolin
diff mbox series

Patch

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index aeeb07b74177..a224c07ce31f 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -594,15 +594,8 @@  static int fsl_sai_startup(struct snd_pcm_substream *substream,
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-	struct device *dev = &sai->pdev->dev;
 	int ret;
 
-	ret = clk_prepare_enable(sai->bus_clk);
-	if (ret) {
-		dev_err(dev, "failed to enable bus clock: %d\n", ret);
-		return ret;
-	}
-
 	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE,
 			   FSL_SAI_CR3_TRCE);
 
@@ -619,8 +612,6 @@  static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
 	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
 	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0);
-
-	clk_disable_unprepare(sai->bus_clk);
 }
 
 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
@@ -925,6 +916,14 @@  static int fsl_sai_runtime_suspend(struct device *dev)
 {
 	struct fsl_sai *sai = dev_get_drvdata(dev);
 
+	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
+		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
+
+	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
+		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
+
+	clk_disable_unprepare(sai->bus_clk);
+
 	regcache_cache_only(sai->regmap, true);
 	regcache_mark_dirty(sai->regmap);
 
@@ -934,6 +933,25 @@  static int fsl_sai_runtime_suspend(struct device *dev)
 static int fsl_sai_runtime_resume(struct device *dev)
 {
 	struct fsl_sai *sai = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(sai->bus_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable bus clock: %d\n", ret);
+		return ret;
+	}
+
+	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) {
+		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]);
+		if (ret)
+			goto disable_bus_clk;
+	}
+
+	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) {
+		ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]);
+		if (ret)
+			goto disable_tx_clk;
+	}
 
 	regcache_cache_only(sai->regmap, false);
 	regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
@@ -941,7 +959,23 @@  static int fsl_sai_runtime_resume(struct device *dev)
 	usleep_range(1000, 2000);
 	regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
 	regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
-	return regcache_sync(sai->regmap);
+
+	ret = regcache_sync(sai->regmap);
+	if (ret)
+		goto disable_rx_clk;
+
+	return 0;
+
+disable_rx_clk:
+	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
+		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
+disable_tx_clk:
+	if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK))
+		clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]);
+disable_bus_clk:
+	clk_disable_unprepare(sai->bus_clk);
+
+	return ret;
 }
 #endif /* CONFIG_PM */