ALSA: pcm: add SNDRV_PCM_TRIGGER_DRAIN trigger
authorLibin Yang <libin.yang@intel.com>
Wed, 31 Dec 2014 14:09:54 +0000 (22:09 +0800)
committerTakashi Iwai <tiwai@suse.de>
Wed, 31 Dec 2014 16:10:08 +0000 (17:10 +0100)
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@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/pcm.h
include/uapi/sound/asound.h
sound/core/pcm_native.c

index 3652c9439af941a4bad1daff5268126abb7d2876..bf32cea2202e629ad853b28a333b2e15b440d4a0 100644 (file)
@@ -106,6 +106,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)
 
index 1f23cd635957846dd6fbb683c1a525cc51b06179..0e88e7a0f0ebf227894f05ef6ed2225931b9d6d6 100644 (file)
@@ -268,6 +268,7 @@ typedef int __bitwise snd_pcm_subformat_t;
 #define SNDRV_PCM_INFO_SYNC_START      0x00400000      /* pcm support some kind of sync go */
 #define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP        0x00800000      /* period wakeup can be disabled */
 #define SNDRV_PCM_INFO_HAS_WALL_CLOCK   0x01000000      /* has audio wall clock for audio/system time sync */
+#define SNDRV_PCM_INFO_DRAIN_TRIGGER   0x40000000              /* internal kernel flag - trigger in drain */
 #define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
 
 typedef int __bitwise snd_pcm_state_t;
index 095d9572ad2b3a683b3d671845d63c38a2856b30..ff3abc3b4ff51077a742c6ebf75b355e635271e0 100644 (file)
@@ -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);
@@ -1566,6 +1567,13 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
                        snd_pcm_post_stop(substream, new_state);
                }
        }
+
+       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
+           runtime->trigger_master == substream &&
+           (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER))
+               return substream->ops->trigger(substream,
+                                              SNDRV_PCM_TRIGGER_DRAIN);
+
        return 0;
 }