ASoC: Intel: add support for platform suspend
authorVinod Koul <vinod.koul@intel.com>
Thu, 12 Feb 2015 04:29:58 +0000 (09:59 +0530)
committerMark Brown <broonie@kernel.org>
Mon, 23 Feb 2015 15:43:59 +0000 (00:43 +0900)
This adds support for platform suspend and resume. We ensure all pcms are
suspended by invoking snd_soc_suspend() and then stop the DSP

Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/sst-mfld-platform-pcm.c
sound/soc/intel/sst-mfld-platform.h

index ea0fa4b90bb0e1c2e0a630c8d16d65b44dab949c..2fbaf2c75d1709e517a5fb1b1d8012f58865992c 100644 (file)
@@ -667,6 +667,9 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
 
 static int sst_soc_probe(struct snd_soc_platform *platform)
 {
+       struct sst_data *drv = dev_get_drvdata(platform->dev);
+
+       drv->soc_card = platform->component.card;
        return sst_dsp_init_v2_dpcm(platform);
 }
 
@@ -729,9 +732,64 @@ static int sst_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+
+static int sst_soc_prepare(struct device *dev)
+{
+       struct sst_data *drv = dev_get_drvdata(dev);
+       int i;
+
+       /* suspend all pcms first */
+       snd_soc_suspend(drv->soc_card->dev);
+       snd_soc_poweroff(drv->soc_card->dev);
+
+       /* set the SSPs to idle */
+       for (i = 0; i < drv->soc_card->num_rtd; i++) {
+               struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+
+               if (dai->active) {
+                       send_ssp_cmd(dai, dai->name, 0);
+                       sst_handle_vb_timer(dai, false);
+               }
+       }
+
+       return 0;
+}
+
+static void sst_soc_complete(struct device *dev)
+{
+       struct sst_data *drv = dev_get_drvdata(dev);
+       int i;
+
+       /* restart SSPs */
+       for (i = 0; i < drv->soc_card->num_rtd; i++) {
+               struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+
+               if (dai->active) {
+                       sst_handle_vb_timer(dai, true);
+                       send_ssp_cmd(dai, dai->name, 1);
+               }
+       }
+       snd_soc_resume(drv->soc_card->dev);
+}
+
+#else
+
+#define sst_soc_prepare NULL
+#define sst_soc_complete NULL
+
+#endif
+
+
+static const struct dev_pm_ops sst_platform_pm = {
+       .prepare        = sst_soc_prepare,
+       .complete       = sst_soc_complete,
+};
+
 static struct platform_driver sst_platform_driver = {
        .driver         = {
                .name           = "sst-mfld-platform",
+               .pm             = &sst_platform_pm,
        },
        .probe          = sst_platform_probe,
        .remove         = sst_platform_remove,
index 79c8d1246a8fb396a4e703694f85e26fb378203b..9094314be2b043e724bfcf3db3f0f54b10dd61d4 100644 (file)
@@ -174,6 +174,7 @@ struct sst_data {
        struct sst_platform_data *pdata;
        struct snd_sst_bytes_v2 *byte_stream;
        struct mutex lock;
+       struct snd_soc_card *soc_card;
 };
 int sst_register_dsp(struct sst_device *sst);
 int sst_unregister_dsp(struct sst_device *sst);