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 |
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?
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
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 --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 */