On Fri, Oct 4, 2019 at 2:34 PM Pierre-Louis Bossart < pierre-louis.bossart@xxxxxxxxxxxxxxx> wrote: > On 10/4/19 8:41 AM, Ranjani Sridharan wrote: > > Currently, the trigger orders SND_SOC_DPCM_TRIGGER_PRE/POST > > determine the order in which FE DAI and BE DAI are triggered. > > In the case of SND_SOC_DPCM_TRIGGER_PRE, the FE DAI is > > triggered before the BE DAI and in the case of > > SND_SOC_DPCM_TRIGGER_POST, the BE DAI is triggered before > > the FE DAI. And this order remains the same irrespective of the > > trigger command. > > > > In the case of the SOF driver, during playback, the FW > > expects the BE DAI to be triggered before the FE DAI during > > the START trigger. The BE DAI trigger handles the starting of > > Link DMA and so it must be started before the FE DAI is started > > to prevent xruns during pause/release. This can be addressed > > by setting the trigger order for the FE dai link to > > SND_SOC_DPCM_TRIGGER_POST. But during the STOP trigger, > > the FW expects the FE DAI to be triggered before the BE DAI. > > Retaining the same order during the START and STOP commands, > > results in FW error as the DAI component in the FW is still > > active. > > > > The issue can be fixed by mirroring the trigger order of > > FE and BE DAI's during the START and STOP trigger. So, with the > > trigger order set to SND_SOC_DPCM_TRIGGER_PRE, the FE DAI will be > > trigger first during SNDRV_PCM_TRIGGER_START/STOP/RESUME > > and the BE DAI will be triggered first during the > > STOP/SUSPEND/PAUSE commands. Conversely, with the trigger order > > set to SND_SOC_DPCM_TRIGGER_POST, the BE DAI will be triggered > > first during the SNDRV_PCM_TRIGGER_START/STOP/RESUME commands > > and the FE DAI will be triggered first during the > > SNDRV_PCM_TRIGGER_STOP/SUSPEND/PAUSE commands. > > > > Github Issue: https://github.com/thesofproject/linux/issues/1160 > > Signed-off-by: Ranjani Sridharan <ranjani.sridharan@xxxxxxxxxxxxxxx> > > --- > > sound/soc/soc-pcm.c | 99 ++++++++++++++++++++++++++++++++------------- > > 1 file changed, 72 insertions(+), 27 deletions(-) > > > > diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c > > index 66910500e3b6..8e5097eead27 100644 > > --- a/sound/soc/soc-pcm.c > > +++ b/sound/soc/soc-pcm.c > > @@ -2340,42 +2340,85 @@ int dpcm_be_dai_trigger(struct > snd_soc_pcm_runtime *fe, int stream, > > } > > EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); > > > > +static int dpcm_dai_trigger_fe_first(struct snd_pcm_substream > *substream, > > + int cmd, bool fe_first) > > the function name is odd with the fe_first repeat > > maybe 'dpcm_dai_trigger_fe_be' ? > Sure, will change in v2. > > > +{ > > + struct snd_soc_pcm_runtime *fe = substream->private_data; > > + int ret; > > + > > + /* call trigger on the frontend before the backend. */ > > + if (fe_first) { > > + dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n", > > + fe->dai_link->name, cmd); > > + > > + ret = soc_pcm_trigger(substream, cmd); > > + if (ret < 0) > > + return ret; > > + > > + ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); > > + return ret; > > + } > > + > > + /* call trigger on the frontend after the backend. */ > > + ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); > > + if (ret < 0) > > + return ret; > > + > > + dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", > > + fe->dai_link->name, cmd); > > + > > + ret = soc_pcm_trigger(substream, cmd); > > + > > + return ret; > > +} > > + > > static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, > int cmd) > > { > > struct snd_soc_pcm_runtime *fe = substream->private_data; > > - int stream = substream->stream, ret; > > + int stream = substream->stream; > > + int ret = 0; > > enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; > > > > fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; > > > > switch (trigger) { > > case SND_SOC_DPCM_TRIGGER_PRE: > > - /* call trigger on the frontend before the backend. */ > > - > > - dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n", > > - fe->dai_link->name, cmd); > > - > > - ret = soc_pcm_trigger(substream, cmd); > > - if (ret < 0) { > > - dev_err(fe->dev,"ASoC: trigger FE failed %d\n", > ret); > > - goto out; > > + switch (cmd) { > > + case SNDRV_PCM_TRIGGER_START: > > + case SNDRV_PCM_TRIGGER_RESUME: > > + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: > > + ret = dpcm_dai_trigger_fe_first(substream, cmd, > true); > > + break; > > + case SNDRV_PCM_TRIGGER_STOP: > > + case SNDRV_PCM_TRIGGER_SUSPEND: > > + ret = dpcm_dai_trigger_fe_first(substream, cmd, > false); > > + break; > > + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: > > + ret = dpcm_dai_trigger_fe_first(substream, cmd, > false); > > + break; > > can we group these 3 cases together? The last two are identical. > Ahh yes, I originally intended to set the state here as well but changed my mind later on . Will fix in v2. _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx https://mailman.alsa-project.org/mailman/listinfo/alsa-devel