]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
ALSA: usb-audio: support delay calculation on capture streams
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Wed, 19 Dec 2012 17:39:05 +0000 (11:39 -0600)
committerTakashi Iwai <tiwai@suse.de>
Mon, 24 Dec 2012 09:53:57 +0000 (10:53 +0100)
Enable delay report on capture path. The delay is reset when an
URB is retired and increment at each call to .pointer based
on frame counter changes. The precision of the delay
information is limited to 1ms as in the playback case.

This reverts commit 3f94fad09538ec988919ec3f371841182df71d04.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/pcm.c

index c6593101c049b88ca6e5661f8765b3f3df0b4d33..3a384479e92376840f234c8c7accf810c12b49c7 100644 (file)
@@ -59,7 +59,12 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
 
        /* Approximation based on number of samples per USB frame (ms),
           some truncation for 44.1 but the estimate is good enough */
-       est_delay =  subs->last_delay - (frame_diff * rate / 1000);
+       est_delay =  frame_diff * rate / 1000;
+       if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
+               est_delay = subs->last_delay - est_delay;
+       else
+               est_delay = subs->last_delay + est_delay;
+
        if (est_delay < 0)
                est_delay = 0;
        return est_delay;
@@ -78,8 +83,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
                return SNDRV_PCM_POS_XRUN;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               substream->runtime->delay = snd_usb_pcm_delay(subs,
+       substream->runtime->delay = snd_usb_pcm_delay(subs,
                                                substream->runtime->rate);
        spin_unlock(&subs->lock);
        return hwptr_done / (substream->runtime->frame_bits >> 3);
@@ -1147,6 +1151,10 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
        int i, period_elapsed = 0;
        unsigned long flags;
        unsigned char *cp;
+       int current_frame_number;
+
+       /* read frame number here, update pointer in critical section */
+       current_frame_number = usb_get_current_frame_number(subs->dev);
 
        stride = runtime->frame_bits >> 3;
 
@@ -1180,6 +1188,15 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
                        subs->transfer_done -= runtime->period_size;
                        period_elapsed = 1;
                }
+               /* capture delay is by construction limited to one URB,
+                * reset delays here
+                */
+               runtime->delay = subs->last_delay = 0;
+
+               /* realign last_frame_number */
+               subs->last_frame_number = current_frame_number;
+               subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
+
                spin_unlock_irqrestore(&subs->lock, flags);
                /* copy a data chunk */
                if (oldptr + bytes > runtime->buffer_size * stride) {