Commit 2ad1e059 authored by Mark Brown's avatar Mark Brown

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.
parents 7ed1bf73 374b50e2
......@@ -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) \
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment