[alsa-devel] [PATCH 1/2] [ALSA] add SNDRV_PCM_TRIGGER_DRAIN trigger
Takashi Iwai
tiwai at suse.de
Tue Dec 30 16:02:45 CET 2014
At Tue, 30 Dec 2014 08:42:28 +0000,
Yang, Libin wrote:
>
> Hi Takashi,
>
> Regards,
> Libin
>
>
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai at suse.de]
> > Sent: Thursday, December 25, 2014 6:11 PM
> > To: Yang, Libin
> > Cc: broonie at kernel.org; alsa-devel at alsa-project.org;
> > liam.r.girdwood at linux.intel.com; Jie, Yang
> > Subject: Re: [PATCH 1/2] [ALSA] add SNDRV_PCM_TRIGGER_DRAIN trigger
> >
> > At Mon, 22 Dec 2014 07:42:38 +0000,
> > Yang, Libin wrote:
> > >
> > > Hi Takashi,
> > >
> > > > > > Besides, this patch will break many drivers. Many of them will
> > > > > > spew errors if an unexpected trigger command is issued. So, you
> > > > > > have to limit this trigger only to some drivers. A typical
> > > > > > workaround is to add a new
> > > > > > SNDRV_PCM_INFO_* and issue the trigger only when the flag is
> > > > > > set, as done for resume and pause operations.
> > > > >
> > > > > Yes, that's a good suggestion. Thanks for reminding me.
> > > >
> > > > OTOH, the info flag will be exposed to user-space while this is a
> > > > kernel-space- only information. So, in the code copying the info
> > > > flag
> > > > (snd_pcm_hw_refine()) would need to drop this bit, too.
> > >
> > > Thanks, I will drop this bit in snd_pcm_hw_refine().
> > >
> > > >
> > > > Alternatively, we may add just a new flag in struct snd_pcm or
> > > > struct snd_pcm_substream and let the driver setting it manually.
> > > > This might need more changes in ASoC side, though, as the PCM
> > > > creation isn't directly done by the driver.
> > >
> > > Yes, it is a little complex for asoc if using this method.
> > > Not sure if it is OK we set the flag in snd_soc_ops->startup() each
> > > time when the function is called.
> > >
> > > What do you think we just use the first method?
> > >
> > > >
> > > >
> > > > > > Also, do you want to see this trigger even if the stream isn't
> > > > > > started before drain is issued? Also, why no need for this
> > > > > > trigger for
> > > > capture streams?
> > > > >
> > > > > In this case, the trigger action will be started. For the stream
> > > > > not started case, if I skip the trigger , I don't know where I can
> > > > > have the chance to trigger later. And I didn't find the suitable
> > > > > place to trigger my
> > > > code.
> > > > > Put the trigger at the end of the function snd_pcm_do_drain_init()
> > > > > or in the function snd_pcm_post_drain_init() will be OK?
> > > > >
> > > > > I didn't include the capture case because we found the capture
> > > > > currently don't need the trigger.
> > > > >
> > > > > Our issue is the fw don't know when to stop fetching the data. For
> > > > > playback we need fill silence data when draining, otherwise the fw
> > > > > will get
> > > > the old data.
> > > > > But for capture, after the driver has fetched the data, it will
> > > > > stopped and no old data will be fetched.
> > > >
> > > > A similar problem here. If you extend the API, don't build up only
> > > > from the bottom. Rather define from a higher POV.
> > > >
> > > > If calling the drain trigger for capture stream doesn't make *any*
> > > > sense for all hardware, then we shouldn't add it. This would be the
> > > > only reason not to do it. What about empty streams...?
> > > >
> > > > That being said, we need to define the proper abstraction, what this
> > > > trigger does for which purpose, not specific to a certain hardware.
> > > > That is, the requirement goes up from your hardware level while the
> > > > design comes down from the abstraction level.
> > >
> > > Right. I will include the capture.
> > >
> > > My patch will be like:
> > >
> > > @@ -1566,6 +1567,11 @@ static int snd_pcm_do_drain_init(struct
> > snd_pcm_substream *substream, int state)
> > > snd_pcm_post_stop(substream, new_state);
> > > }
> > > }
> > > +
> > > + if (substream->runtime->trigger_master == substream &&
> > > + (substream->runtime->hw.info &
> > SNDRV_PCM_INFO_DRAIN_TRIGGER))
> > > + return substream->ops->trigger(substream,
> > > + SNDRV_PCM_TRIGGER_DRAIN);
> > > +
> > > return 0;
> > > }
> > >
> > > I moved the trigger at the end of the function. Or do you think we
> > > need trigger before snd_pcm_do_stop() for capture case based on your
> > knowledge?
> >
> > The place would be OK, but you can't call it unconditionally there.
> > In some cases (e.g. XRUN), the trigger won't be called at all.
> > The trigger state change is a bit tricky, so be careful to track the state change
> > there.
> >
>
> Right. What do you think the following code?
>
> @@ -1518,6 +1519,8 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state
> static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
> {
> struct snd_pcm_runtime *runtime = substream->runtime;
> + int trigger = 0;
> +
> if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> switch (runtime->status->state) {
> case SNDRV_PCM_STATE_PREPARED:
> @@ -1525,10 +1528,12 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
> if (! snd_pcm_playback_empty(substream)) {
> snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
> snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
> + trigger = 1;
> }
> break;
> case SNDRV_PCM_STATE_RUNNING:
> runtime->status->state = SNDRV_PCM_STATE_DRAINING;
> + trigger = 1;
> break;
> case SNDRV_PCM_STATE_XRUN:
> runtime->status->state = SNDRV_PCM_STATE_SETUP;
> @@ -1545,6 +1550,12 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
> snd_pcm_post_stop(substream, new_state);
> }
> }
> +
> + if (substream->runtime->trigger_master == substream && trigger &&
> + (substream->runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER))
> + return substream->ops->trigger(substream,
> + SNDRV_PCM_TRIGGER_DRAIN);
> +
Better to use bool in such a case.
In anyway, an easier way would be to check like
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
runtime->trigger_master == substream &&
(runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER))
Takashi
More information about the Alsa-devel
mailing list