aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Mark Brown <broonie@kernel.org> 2022-04-20 14:22:08 +0100
committerGravatar Mark Brown <broonie@kernel.org> 2022-04-20 14:22:08 +0100
commit2ad1e059cb3c2c53dc639e4f816daddcfc0e91fd (patch)
treeff2f7b09d53c76cc4c2e8c4de784d4a8b41e82b0
parentASoC: SOF: add INTEL_IPC4 plumbing (diff)
parentASoC: soc-pcm: improve BE transition for TRIGGER_START (diff)
downloadlinux-2ad1e059cb3c2c53dc639e4f816daddcfc0e91fd.tar.gz
linux-2ad1e059cb3c2c53dc639e4f816daddcfc0e91fd.tar.bz2
linux-2ad1e059cb3c2c53dc639e4f816daddcfc0e91fd.zip
ASoC: soc-pcm: improve BE state transitions
Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>: With additional tests with the introduction of a 'deep-buffer' PCM device mixed with the regular low-latency path, we came up with two improvements in the BE state machine and transitions. The short explanation is that the BE cannot directly use the trigger commands provided by the FE, and a translation is needed to deal with paused states.
-rw-r--r--include/sound/soc-dpcm.h2
-rw-r--r--sound/soc/soc-pcm.c38
2 files changed, 37 insertions, 3 deletions
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index 75b92d883976..5b689c663290 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -103,6 +103,8 @@ struct snd_soc_dpcm_runtime {
int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
int be_start; /* refcount protected by BE stream pcm lock */
+ int be_pause; /* refcount protected by BE stream pcm lock */
+ bool fe_pause; /* used to track STOP after PAUSE */
};
#define for_each_dpcm_fe(be, stream, _dpcm) \
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 11c9853e9e80..6f43db35a5c8 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2090,6 +2090,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
int cmd)
{
struct snd_soc_pcm_runtime *be;
+ bool pause_stop_transition;
struct snd_soc_dpcm *dpcm;
unsigned long flags;
int ret = 0;
@@ -2121,6 +2122,13 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
if (be->dpcm[stream].be_start != 1)
goto next;
+ if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_PAUSED)
+ ret = soc_pcm_trigger(be_substream,
+ SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+ else
+ ret = soc_pcm_trigger(be_substream,
+ SNDRV_PCM_TRIGGER_START);
+
ret = soc_pcm_trigger(be_substream, cmd);
if (ret) {
be->dpcm[stream].be_start--;
@@ -2148,10 +2156,12 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (!be->dpcm[stream].be_start &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) &&
- (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
goto next;
+ fe->dpcm[stream].fe_pause = false;
+ be->dpcm[stream].be_pause--;
+
be->dpcm[stream].be_start++;
if (be->dpcm[stream].be_start != 1)
goto next;
@@ -2175,14 +2185,33 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
if (be->dpcm[stream].be_start != 0)
goto next;
- ret = soc_pcm_trigger(be_substream, cmd);
+ pause_stop_transition = false;
+ if (fe->dpcm[stream].fe_pause) {
+ pause_stop_transition = true;
+ fe->dpcm[stream].fe_pause = false;
+ be->dpcm[stream].be_pause--;
+ }
+
+ if (be->dpcm[stream].be_pause != 0)
+ ret = soc_pcm_trigger(be_substream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+ else
+ ret = soc_pcm_trigger(be_substream, SNDRV_PCM_TRIGGER_STOP);
+
if (ret) {
if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_START)
be->dpcm[stream].be_start++;
+ if (pause_stop_transition) {
+ fe->dpcm[stream].fe_pause = true;
+ be->dpcm[stream].be_pause++;
+ }
goto next;
}
- be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
+ if (be->dpcm[stream].be_pause != 0)
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
+ else
+ be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
+
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
@@ -2204,6 +2233,9 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
goto next;
+ fe->dpcm[stream].fe_pause = true;
+ be->dpcm[stream].be_pause++;
+
be->dpcm[stream].be_start--;
if (be->dpcm[stream].be_start != 0)
goto next;