aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/intel/sst-baytrail-ipc.c
diff options
context:
space:
mode:
authorLiam Girdwood2014-05-08 16:07:26 +0300
committerMark Brown2014-05-12 22:02:18 +0100
commitaf94aa558be506c5afe106e8cf34362bfce221aa (patch)
treed53557da737bb0840b47b685e5b908f9ef774a3f /sound/soc/intel/sst-baytrail-ipc.c
parent609a13e5c9229ad4f5c78eeb1aefd583fdee9e58 (diff)
ASoC: Intel: Add Baytrail suspend/resume support
Add suspend and resume support to Baytrail SST DSP. This is implemented by unloading firmware modules and putting DSP into reset prior suspend and restarting DSP again in normal boot state after resume. Context restore for running streams is implemented by scheduling a work from sst_byt_pcm_trigger() that will allocate a stream with existing parameters and start it from last known buffer position before suspend. [Jarkko: Squashed together 5 WIP patches from Liam and 1 from me] Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/intel/sst-baytrail-ipc.c')
-rw-r--r--sound/soc/intel/sst-baytrail-ipc.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c
index 029da82f07d7..3e1dad3449bd 100644
--- a/sound/soc/intel/sst-baytrail-ipc.c
+++ b/sound/soc/intel/sst-baytrail-ipc.c
@@ -173,6 +173,7 @@ struct sst_byt {
/* boot */
wait_queue_head_t boot_wait;
bool boot_complete;
+ struct sst_fw *fw;
/* IPC messaging */
struct list_head tx_list;
@@ -789,6 +790,73 @@ static struct sst_dsp_device byt_dev = {
.ops = &sst_byt_ops,
};
+int sst_byt_dsp_suspend_noirq(struct device *dev, struct sst_pdata *pdata)
+{
+ struct sst_byt *byt = pdata->dsp;
+
+ dev_dbg(byt->dev, "dsp reset\n");
+ sst_dsp_reset(byt->dsp);
+ sst_byt_drop_all(byt);
+ dev_dbg(byt->dev, "dsp in reset\n");
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_noirq);
+
+int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata)
+{
+ struct sst_byt *byt = pdata->dsp;
+
+ dev_dbg(byt->dev, "free all blocks and unload fw\n");
+ sst_fw_unload(byt->fw);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_late);
+
+int sst_byt_dsp_boot(struct device *dev, struct sst_pdata *pdata)
+{
+ struct sst_byt *byt = pdata->dsp;
+ int ret;
+
+ dev_dbg(byt->dev, "reload dsp fw\n");
+
+ sst_dsp_reset(byt->dsp);
+
+ ret = sst_fw_reload(byt->fw);
+ if (ret < 0) {
+ dev_err(dev, "error: failed to reload firmware\n");
+ return ret;
+ }
+
+ /* wait for DSP boot completion */
+ byt->boot_complete = false;
+ sst_dsp_boot(byt->dsp);
+ dev_dbg(byt->dev, "dsp booting...\n");
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sst_byt_dsp_boot);
+
+int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata)
+{
+ struct sst_byt *byt = pdata->dsp;
+ int err;
+
+ dev_dbg(byt->dev, "wait for dsp reboot\n");
+
+ err = wait_event_timeout(byt->boot_wait, byt->boot_complete,
+ msecs_to_jiffies(IPC_BOOT_MSECS));
+ if (err == 0) {
+ dev_err(byt->dev, "ipc: error DSP boot timeout\n");
+ return -EIO;
+ }
+
+ dev_dbg(byt->dev, "dsp rebooted\n");
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready);
+
int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
{
struct sst_byt *byt;
@@ -855,6 +923,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
}
pdata->dsp = byt;
+ byt->fw = byt_sst_fw;
return 0;