mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
ASoC: Intel: add a status for runtime suspend/resume
For runtime suspend/resume, it is some different with suspend/resume, e.g. codec power supply won't be switch off, codec jack detection still working(to wake up system from Jack event), won't call call snd_soc_suspend/resume, etc. So here, we add a platform PM status, HSW_PM_STATE_RTD3, to make the status more clear, when in idle, it will enter this status, to transfer from HSW_PM_STATE_RTD3 to HSW_PM_STATE_D3, we will do those extra jobs, and vice versa for resuming. Signed-off-by: Jie Yang <yang.jie@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
c41cda1dbe
commit
cd311dd123
1 changed files with 36 additions and 34 deletions
|
@ -119,8 +119,9 @@ struct hsw_pcm_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hsw_pm_state {
|
enum hsw_pm_state {
|
||||||
HSW_PM_STATE_D3 = 0,
|
HSW_PM_STATE_D0 = 0,
|
||||||
HSW_PM_STATE_D0 = 1,
|
HSW_PM_STATE_RTD3 = 1,
|
||||||
|
HSW_PM_STATE_D3 = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* private data for the driver */
|
/* private data for the driver */
|
||||||
|
@ -1035,12 +1036,12 @@ static int hsw_pcm_runtime_suspend(struct device *dev)
|
||||||
struct hsw_priv_data *pdata = dev_get_drvdata(dev);
|
struct hsw_priv_data *pdata = dev_get_drvdata(dev);
|
||||||
struct sst_hsw *hsw = pdata->hsw;
|
struct sst_hsw *hsw = pdata->hsw;
|
||||||
|
|
||||||
if (pdata->pm_state == HSW_PM_STATE_D3)
|
if (pdata->pm_state >= HSW_PM_STATE_RTD3)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sst_hsw_dsp_runtime_suspend(hsw);
|
sst_hsw_dsp_runtime_suspend(hsw);
|
||||||
sst_hsw_dsp_runtime_sleep(hsw);
|
sst_hsw_dsp_runtime_sleep(hsw);
|
||||||
pdata->pm_state = HSW_PM_STATE_D3;
|
pdata->pm_state = HSW_PM_STATE_RTD3;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1051,7 +1052,7 @@ static int hsw_pcm_runtime_resume(struct device *dev)
|
||||||
struct sst_hsw *hsw = pdata->hsw;
|
struct sst_hsw *hsw = pdata->hsw;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (pdata->pm_state == HSW_PM_STATE_D0)
|
if (pdata->pm_state != HSW_PM_STATE_RTD3)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = sst_hsw_dsp_load(hsw);
|
ret = sst_hsw_dsp_load(hsw);
|
||||||
|
@ -1091,7 +1092,7 @@ static void hsw_pcm_complete(struct device *dev)
|
||||||
struct hsw_pcm_data *pcm_data;
|
struct hsw_pcm_data *pcm_data;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
if (pdata->pm_state == HSW_PM_STATE_D0)
|
if (pdata->pm_state != HSW_PM_STATE_D3)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err = sst_hsw_dsp_load(hsw);
|
err = sst_hsw_dsp_load(hsw);
|
||||||
|
@ -1139,41 +1140,42 @@ static int hsw_pcm_prepare(struct device *dev)
|
||||||
|
|
||||||
if (pdata->pm_state == HSW_PM_STATE_D3)
|
if (pdata->pm_state == HSW_PM_STATE_D3)
|
||||||
return 0;
|
return 0;
|
||||||
/* suspend all active streams */
|
else if (pdata->pm_state == HSW_PM_STATE_D0) {
|
||||||
for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
|
/* suspend all active streams */
|
||||||
pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
|
for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
|
||||||
|
pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
|
||||||
|
|
||||||
if (!pcm_data->substream)
|
if (!pcm_data->substream)
|
||||||
continue;
|
continue;
|
||||||
dev_dbg(dev, "suspending pcm %d\n", i);
|
dev_dbg(dev, "suspending pcm %d\n", i);
|
||||||
snd_pcm_suspend_all(pcm_data->hsw_pcm);
|
snd_pcm_suspend_all(pcm_data->hsw_pcm);
|
||||||
|
|
||||||
/* We need to wait until the DSP FW stops the streams */
|
/* We need to wait until the DSP FW stops the streams */
|
||||||
msleep(2);
|
msleep(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* preserve persistent memory */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
|
||||||
|
pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
|
||||||
|
|
||||||
|
if (!pcm_data->substream)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dev_dbg(dev, "saving context pcm %d\n", i);
|
||||||
|
err = sst_module_runtime_save(pcm_data->runtime,
|
||||||
|
&pcm_data->context);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_soc_suspend(pdata->soc_card->dev);
|
snd_soc_suspend(pdata->soc_card->dev);
|
||||||
snd_soc_poweroff(pdata->soc_card->dev);
|
snd_soc_poweroff(pdata->soc_card->dev);
|
||||||
|
|
||||||
/* enter D3 state and stall */
|
|
||||||
sst_hsw_dsp_runtime_suspend(hsw);
|
|
||||||
|
|
||||||
/* preserve persistent memory */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
|
|
||||||
pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
|
|
||||||
|
|
||||||
if (!pcm_data->substream)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
dev_dbg(dev, "saving context pcm %d\n", i);
|
|
||||||
err = sst_module_runtime_save(pcm_data->runtime,
|
|
||||||
&pcm_data->context);
|
|
||||||
if (err < 0)
|
|
||||||
dev_err(dev, "failed to save context for PCM %d\n", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* put the DSP to sleep */
|
|
||||||
sst_hsw_dsp_runtime_sleep(hsw);
|
|
||||||
pdata->pm_state = HSW_PM_STATE_D3;
|
pdata->pm_state = HSW_PM_STATE_D3;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue