[alsa-devel] [PATCH 1/2] [ALSA] add SNDRV_PCM_TRIGGER_DRAIN trigger
Yang, Libin
libin.yang at intel.com
Mon Dec 22 08:42:38 CET 2014
Hi Takashi,
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai at suse.de]
> Sent: Friday, December 19, 2014 4:48 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 Fri, 19 Dec 2014 06:29:33 +0000,
> Yang, Libin wrote:
> >
> > Hi Takashi,
> >
> > Thanks for review, please see my comments.
> >
> >
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai at suse.de]
> > > Sent: Thursday, December 18, 2014 4:30 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 Thu, 18 Dec 2014 15:36:03 +0800,
> > > libin.yang at intel.com wrote:
> > > >
> > > > From: Libin Yang <libin.yang at intel.com>
> > > >
> > > > Add SNDRV_PCM_TRIGGER_DRAIN trigger for pcm drain.
> > > >
> > > > Some audio devices require notification of drain events in order
> > > > to properly drain and shutdown an audio stream.
> > > >
> > > > Signed-off-by: Libin Yang <libin.yang at intel.com>
> > > > ---
> > > > include/sound/pcm.h | 1 +
> > > > sound/core/pcm_native.c | 5 +++++
> > > > 2 files changed, 6 insertions(+)
> > > >
> > > > diff --git a/include/sound/pcm.h b/include/sound/pcm.h index
> > > > 8bb00a2..bb77aa3 100644
> > > > --- a/include/sound/pcm.h
> > > > +++ b/include/sound/pcm.h
> > > > @@ -109,6 +109,7 @@ struct snd_pcm_ops {
> > > > #define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 4
> > > > #define SNDRV_PCM_TRIGGER_SUSPEND 5
> > > > #define SNDRV_PCM_TRIGGER_RESUME 6
> > > > +#define SNDRV_PCM_TRIGGER_DRAIN 7
> > > >
> > > > #define SNDRV_PCM_POS_XRUN
> ((snd_pcm_uframes_t)-1)
> > > >
> > > > diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> > > > index
> > > > 166d59c..15fe682 100644
> > > > --- a/sound/core/pcm_native.c
> > > > +++ b/sound/core/pcm_native.c
> > > > @@ -1517,6 +1517,11 @@ static int snd_pcm_do_drain_init(struct
> > > > snd_pcm_substream *substream, int state) {
> > > > struct snd_pcm_runtime *runtime = substream->runtime;
> > > > if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> > > > +
> > > > + if (substream->runtime->trigger_master == substream)
> > > > + substream->ops->trigger(substream,
> > > > + SNDRV_PCM_TRIGGER_DRAIN);
> > >
> > > The return value check is missing.
> >
> > Actually, the code doesn't care the return value and I don't want to
> > let the trigger return value impact the snd_pcm_do_drain_init() flow
> > just like snd_pcm_do_stop().
>
> Well, the fundamental problem in this patch is that it was written *just for
> your hardware* although this is a public API extension.
> Consider again about it: if the return value of this trigger doesn't matter for
> your hardware, the driver can simply return zero always.
> Why do you need to drop the check in the common code? Wouldn't any
> driver return any error there?
Right, I will add the return value check.
>
>
> > > 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?
And in the snd_pcm_hw_refine():
@@ -420,7 +420,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
hw = &substream->runtime->hw;
if (!params->info) {
- params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
+ params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES
+ & ~SNDRV_PCM_INFO_DRAIN_TRIGGER;
if (!hw_support_mmap(substream))
params->info &= ~(SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID);
Do you think whether it is OK?
>
> So, in general I found it good to have this kind of API extension.
> But let's add it a bit more carefully.
>
>
> thanks,
>
> Takashi
Regards,
Libin
More information about the Alsa-devel
mailing list