diff options
author | Keyon Jie <yang.jie@linux.intel.com> | 2019-10-25 17:41:21 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-10-28 14:46:39 +0000 |
commit | c470fc3f61b25e955f8ba90fc9dc554881e4e72c (patch) | |
tree | e33fbe385ef35cc2e3ec97fc8fe454ec23c44d96 /sound | |
parent | 5655ce660a6d3eec4a3ad37feb99fb228540d1a9 (diff) |
ASoC: SOF: PM: Add support for DSP D0i3 state when entering S0ix
When system is entering into S0ix, the PCI device may transition to the
D0i3 substate instead of D3. In D0i3, some always-on functionality can
be enabled, such as acoustic event detection, voice activity detection
or hotwording. When an event is detected, the DSP firmware can wake-up
the device for a transition to D0 with an interrupt.
Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20191025224122.7718-26-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/sof/pm.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 99e4e6ffff74..560a937e0484 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -430,12 +430,58 @@ EXPORT_SYMBOL(snd_sof_set_d0_substate); int snd_sof_resume(struct device *dev) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + int ret; + + if (sdev->s0_suspend) { + /* resume from D0I3 */ + dev_dbg(sdev->dev, "DSP will exit from D0i3...\n"); + ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I0); + if (ret == -ENOTSUPP) { + /* fallback to resume from D3 */ + dev_dbg(sdev->dev, "D0i3 not supported, fall back to resume from D3...\n"); + goto d3_resume; + } else if (ret < 0) { + dev_err(sdev->dev, "error: failed to exit from D0I3 %d\n", + ret); + return ret; + } + + /* platform-specific resume from D0i3 */ + return snd_sof_dsp_resume(sdev); + } + +d3_resume: + /* resume from D3 */ return sof_resume(dev, false); } EXPORT_SYMBOL(snd_sof_resume); int snd_sof_suspend(struct device *dev) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + int ret; + + if (sdev->s0_suspend) { + /* suspend to D0i3 */ + dev_dbg(sdev->dev, "DSP is trying to enter D0i3...\n"); + ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I3); + if (ret == -ENOTSUPP) { + /* fallback to D3 suspend */ + dev_dbg(sdev->dev, "D0i3 not supported, fall back to D3...\n"); + goto d3_suspend; + } else if (ret < 0) { + dev_err(sdev->dev, "error: failed to enter D0I3, %d\n", + ret); + return ret; + } + + /* platform-specific suspend to D0i3 */ + return snd_sof_dsp_suspend(sdev); + } + +d3_suspend: + /* suspend to D3 */ return sof_suspend(dev, false); } EXPORT_SYMBOL(snd_sof_suspend); |