MLK-17034-2: ASoC: fsl_sai: Move clock operation to pm runtime function
authorShengjiu Wang <shengjiu.wang@nxp.com>
Tue, 28 Nov 2017 08:17:17 +0000 (16:17 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:49:46 +0000 (14:49 -0500)
In imx8 when systerm enter suspend state, the power of subsystem will be
off, the clock enable state will be lost after resume, but the runtime
resume function will be called after resume by pm, so need to move clock
enablement to runtime resume and clock disablement to runtime suspend.
Then after resume the clock enable state can be recovered.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
sound/soc/fsl/fsl_sai.c

index 19a2700..e3f42bc 100644 (file)
@@ -710,7 +710,6 @@ 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;
 
        if (sai->is_stream_opened[tx])
@@ -718,12 +717,6 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
        else
                sai->is_stream_opened[tx] = true;
 
-       ret = clk_prepare_enable(sai->bus_clk);
-       if (ret) {
-               dev_err(dev, "failed to enable bus clock: %d\n", ret);
-               return ret;
-       }
-
        /* EDMA engine needs periods of size multiple of tx/rx maxburst */
        if (sai->soc->constrain_period_size)
                snd_pcm_hw_constraint_step(substream->runtime, 0,
@@ -743,10 +736,8 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
        struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
-       if (sai->is_stream_opened[tx]) {
-               clk_disable_unprepare(sai->bus_clk);
+       if (sai->is_stream_opened[tx])
                sai->is_stream_opened[tx] = false;
-       }
 }
 
 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
@@ -1166,6 +1157,25 @@ static int fsl_sai_runtime_resume(struct device *dev)
 {
        struct fsl_sai *sai = dev_get_drvdata(dev);
        unsigned char offset = sai->soc->reg_offset;
+       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;
+       }
 
        request_bus_freq(BUS_FREQ_AUDIO);
 
@@ -1181,7 +1191,22 @@ static int fsl_sai_runtime_resume(struct device *dev)
        usleep_range(1000, 2000);
        regmap_write(sai->regmap, FSL_SAI_TCSR(offset), 0);
        regmap_write(sai->regmap, FSL_SAI_RCSR(offset), 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;
 }
 
 static int fsl_sai_runtime_suspend(struct device *dev)
@@ -1195,6 +1220,14 @@ static int fsl_sai_runtime_suspend(struct device *dev)
        if (sai->soc->flags & SAI_FLAG_PMQOS)
                pm_qos_remove_request(&sai->pm_qos_req);
 
+       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);
+
        return 0;
 }
 #endif