summaryrefslogtreecommitdiff
path: root/sound/soc/sof
diff options
context:
space:
mode:
authorKeyon Jie <yang.jie@linux.intel.com>2019-10-25 17:41:18 -0500
committerMark Brown <broonie@kernel.org>2019-10-28 14:45:53 +0000
commitac8c046f19f94ec419c60d7a073af75a71386e97 (patch)
treebbe84047d476f70b9f808cf583e6fefebb226fd9 /sound/soc/sof
parent0b50b3b1c3bc2a2c9eeab418b3de3e60e0530cf4 (diff)
ASoC: SOF: ignore suspend/resume for D0ix compatible streams
During system suspend, the PM framework will freeze all applications and the ALSA/ASoC core will suspend all RUNNING PCM streams. However, D0ix-compatible PCM streams should keep the related pipelines active in the DSP when the system is entering S0ix. The TRIGGER_SUSPEND event is trapped in such cases to prevent the pipelines from being stopped. Likewise, the TRIGGER_RESUME/START events should not affect the pipeline state. The SOF driver also triggers some DSP Firmware pipelines based on the DAPM widgets power events. In such cases, we also ignore PRE_PMU and POST_PMD events to keep the pipelines active. 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-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof')
-rw-r--r--sound/soc/sof/pcm.c31
-rw-r--r--sound/soc/sof/topology.c17
2 files changed, 47 insertions, 1 deletions
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 9ba505cf5966..3d5cd1b445ba 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -346,6 +346,16 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
break;
case SNDRV_PCM_TRIGGER_RESUME:
+ if (spcm->stream[substream->stream].suspend_ignored) {
+ /*
+ * this case will be triggered when INFO_RESUME is
+ * supported, no need to resume streams that remained
+ * enabled in D0ix.
+ */
+ spcm->stream[substream->stream].suspend_ignored = false;
+ return 0;
+ }
+
/* set up hw_params */
ret = sof_pcm_prepare(component, substream);
if (ret < 0) {
@@ -356,9 +366,30 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
/* fallthrough */
case SNDRV_PCM_TRIGGER_START:
+ if (spcm->stream[substream->stream].suspend_ignored) {
+ /*
+ * This case will be triggered when INFO_RESUME is
+ * not supported, no need to re-start streams that
+ * remained enabled in D0ix.
+ */
+ spcm->stream[substream->stream].suspend_ignored = false;
+ return 0;
+ }
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (sdev->s0_suspend &&
+ spcm->stream[substream->stream].d0i3_compatible) {
+ /*
+ * trap the event, not sending trigger stop to
+ * prevent the FW pipelines from being stopped,
+ * and mark the flag to ignore the upcoming DAPM
+ * PM events.
+ */
+ spcm->stream[substream->stream].suspend_ignored = true;
+ return 0;
+ }
+ /* fallthrough */
case SNDRV_PCM_TRIGGER_STOP:
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
ipc_first = true;
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index cc138ac6a8eb..e0e2ae734632 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -135,7 +135,9 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_sof_widget *swidget = w->dobj.private;
+ int stream = SNDRV_PCM_STREAM_CAPTURE;
struct snd_sof_dev *sdev;
+ struct snd_sof_pcm *spcm;
int ret = 0;
if (!swidget)
@@ -146,11 +148,19 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w,
dev_dbg(sdev->dev, "received event %d for widget %s\n",
event, w->name);
+ /* get runtime PCM params using widget's stream name */
+ spcm = snd_sof_find_spcm_name(sdev, swidget->widget->sname);
+
/* process events */
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ if (spcm->stream[stream].suspend_ignored) {
+ dev_dbg(sdev->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n");
+ return 0;
+ }
+
/* set pcm params */
- ret = ipc_pcm_params(swidget, SOF_IPC_STREAM_CAPTURE);
+ ret = ipc_pcm_params(swidget, stream);
if (ret < 0) {
dev_err(sdev->dev,
"error: failed to set pcm params for widget %s\n",
@@ -166,6 +176,11 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w,
swidget->widget->name);
break;
case SND_SOC_DAPM_POST_PMD:
+ if (spcm->stream[stream].suspend_ignored) {
+ dev_dbg(sdev->dev, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n");
+ return 0;
+ }
+
/* stop trigger */
ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP);
if (ret < 0)