mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
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.
This commit is contained in:
commit
2ad1e059cb
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user