diff options
Diffstat (limited to 'sound/soc/sof/pm.c')
-rw-r--r-- | sound/soc/sof/pm.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 8ef1d51025d8..278abfd10490 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -153,6 +153,15 @@ static int sof_restore_pipelines(struct snd_sof_dev *sdev) continue; } + /* + * The link DMA channel would be invalidated for running + * streams but not for streams that were in the PAUSED + * state during suspend. So invalidate it here before setting + * the dai config in the DSP. + */ + if (config->type == SOF_DAI_INTEL_HDA) + config->hda.link_dma_ch = DMA_CHAN_INVALID; + ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, @@ -204,7 +213,7 @@ static int sof_send_pm_ipc(struct snd_sof_dev *sdev, int cmd) sizeof(pm_ctx), &reply, sizeof(reply)); } -static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) +static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) { struct snd_pcm_substream *substream; struct snd_sof_pcm *spcm; @@ -229,7 +238,7 @@ static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) } /* set internal flag for BE */ - snd_sof_dsp_hw_params_upon_resume(sdev); + return snd_sof_dsp_hw_params_upon_resume(sdev); } #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) @@ -333,8 +342,15 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) snd_sof_release_trace(sdev); /* set restore_stream for all streams during system suspend */ - if (!runtime_suspend) - sof_set_hw_params_upon_resume(sdev); + if (!runtime_suspend) { + ret = sof_set_hw_params_upon_resume(sdev); + if (ret < 0) { + dev_err(sdev->dev, + "error: setting hw_params flag during suspend %d\n", + ret); + return ret; + } + } #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) /* cache debugfs contents during runtime suspend */ @@ -343,11 +359,20 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) #endif /* notify DSP of upcoming power down */ ret = sof_send_pm_ipc(sdev, SOF_IPC_PM_CTX_SAVE); - if (ret < 0) { + if (ret == -EBUSY || ret == -EAGAIN) { + /* + * runtime PM has logic to handle -EBUSY/-EAGAIN so + * pass these errors up + */ dev_err(sdev->dev, "error: ctx_save ipc error during suspend %d\n", ret); return ret; + } else if (ret < 0) { + /* FW in unexpected state, continue to power down */ + dev_warn(sdev->dev, + "ctx_save ipc error %d, proceeding with suspend\n", + ret); } /* power down all DSP cores */ @@ -369,6 +394,14 @@ int snd_sof_runtime_suspend(struct device *dev) } EXPORT_SYMBOL(snd_sof_runtime_suspend); +int snd_sof_runtime_idle(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + + return snd_sof_dsp_runtime_idle(sdev); +} +EXPORT_SYMBOL(snd_sof_runtime_idle); + int snd_sof_runtime_resume(struct device *dev) { return sof_resume(dev, true); |