ASoC: Intel: add support for platform suspend

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>
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c
index ea0fa4b..2fbaf2c 100644
--- a/sound/soc/intel/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/sst-mfld-platform-pcm.c
@@ -667,6 +667,9 @@
 
 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 @@
 	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,
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h
index 79c8d12..9094314 100644
--- a/sound/soc/intel/sst-mfld-platform.h
+++ b/sound/soc/intel/sst-mfld-platform.h
@@ -174,6 +174,7 @@
 	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);