diff options
Diffstat (limited to 'sound/soc/intel/haswell')
-rw-r--r-- | sound/soc/intel/haswell/sst-haswell-ipc.c | 13 | ||||
-rw-r--r-- | sound/soc/intel/haswell/sst-haswell-pcm.c | 31 |
2 files changed, 35 insertions, 9 deletions
diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index 344a1e9bbce5..f95f271aab0c 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c @@ -2098,6 +2098,14 @@ static u64 hsw_reply_msg_match(u64 header, u64 *mask) return header; } +static bool hsw_is_dsp_busy(struct sst_dsp *dsp) +{ + u64 ipcx; + + ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); + return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)); +} + int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) { struct sst_hsw_ipc_fw_version version; @@ -2117,6 +2125,10 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) ipc->ops.shim_dbg = hsw_shim_dbg; ipc->ops.tx_data_copy = hsw_tx_data_copy; ipc->ops.reply_msg_match = hsw_reply_msg_match; + ipc->ops.is_dsp_busy = hsw_is_dsp_busy; + + ipc->tx_data_max_size = IPC_MAX_MAILBOX_BYTES; + ipc->rx_data_max_size = IPC_MAX_MAILBOX_BYTES; ret = sst_ipc_init(ipc); if (ret != 0) @@ -2201,7 +2213,6 @@ dma_err: dsp_new_err: sst_ipc_fini(ipc); ipc_init_err: - kfree(hsw); return ret; } EXPORT_SYMBOL_GPL(sst_hsw_dsp_init); diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c index 23ae0400d6db..e593e7a4b7a7 100644 --- a/sound/soc/intel/haswell/sst-haswell-pcm.c +++ b/sound/soc/intel/haswell/sst-haswell-pcm.c @@ -928,10 +928,15 @@ static void hsw_pcm_free_modules(struct hsw_priv_data *pdata) for (i = 0; i < ARRAY_SIZE(mod_map); i++) { pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; - sst_hsw_runtime_module_free(pcm_data->runtime); + if (pcm_data->runtime){ + sst_hsw_runtime_module_free(pcm_data->runtime); + pcm_data->runtime = NULL; + } } - if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES)) { + if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES) && + pdata->runtime_waves) { sst_hsw_runtime_module_free(pdata->runtime_waves); + pdata->runtime_waves = NULL; } } @@ -1204,6 +1209,20 @@ static int hsw_pcm_runtime_idle(struct device *dev) return 0; } +static int hsw_pcm_suspend(struct device *dev) +{ + struct hsw_priv_data *pdata = dev_get_drvdata(dev); + struct sst_hsw *hsw = pdata->hsw; + + /* enter D3 state and stall */ + sst_hsw_dsp_runtime_suspend(hsw); + /* free all runtime modules */ + hsw_pcm_free_modules(pdata); + /* put the DSP to sleep, fw unloaded after runtime modules freed */ + sst_hsw_dsp_runtime_sleep(hsw); + return 0; +} + static int hsw_pcm_runtime_suspend(struct device *dev) { struct hsw_priv_data *pdata = dev_get_drvdata(dev); @@ -1220,8 +1239,7 @@ static int hsw_pcm_runtime_suspend(struct device *dev) return ret; sst_hsw_set_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES); } - sst_hsw_dsp_runtime_suspend(hsw); - sst_hsw_dsp_runtime_sleep(hsw); + hsw_pcm_suspend(dev); pdata->pm_state = HSW_PM_STATE_RTD3; return 0; @@ -1361,10 +1379,7 @@ static int hsw_pcm_prepare(struct device *dev) if (err < 0) dev_err(dev, "failed to save context for PCM %d\n", i); } - /* enter D3 state and stall */ - sst_hsw_dsp_runtime_suspend(hsw); - /* put the DSP to sleep */ - sst_hsw_dsp_runtime_sleep(hsw); + hsw_pcm_suspend(dev); } snd_soc_suspend(pdata->soc_card->dev); |