aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>2012-12-19 12:39:05 -0500
committerTakashi Iwai <tiwai@suse.de>2012-12-24 04:53:57 -0500
commite4cc6153401fc59d6d4ca0317be5774bdbd399ba (patch)
treeb8b91c4a0b7a93d7088e7c5db9f038774a539864 /sound/usb/pcm.c
parenta49f0d1ea3ec94fc7cf33a7c36a16343b74bd565 (diff)
ALSA: usb-audio: support delay calculation on capture streams
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>
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index c6593101c049..3a384479e923 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -59,7 +59,12 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
59 59
60 /* Approximation based on number of samples per USB frame (ms), 60 /* Approximation based on number of samples per USB frame (ms),
61 some truncation for 44.1 but the estimate is good enough */ 61 some truncation for 44.1 but the estimate is good enough */
62 est_delay = subs->last_delay - (frame_diff * rate / 1000); 62 est_delay = frame_diff * rate / 1000;
63 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
64 est_delay = subs->last_delay - est_delay;
65 else
66 est_delay = subs->last_delay + est_delay;
67
63 if (est_delay < 0) 68 if (est_delay < 0)
64 est_delay = 0; 69 est_delay = 0;
65 return est_delay; 70 return est_delay;
@@ -78,8 +83,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
78 return SNDRV_PCM_POS_XRUN; 83 return SNDRV_PCM_POS_XRUN;
79 spin_lock(&subs->lock); 84 spin_lock(&subs->lock);
80 hwptr_done = subs->hwptr_done; 85 hwptr_done = subs->hwptr_done;
81 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 86 substream->runtime->delay = snd_usb_pcm_delay(subs,
82 substream->runtime->delay = snd_usb_pcm_delay(subs,
83 substream->runtime->rate); 87 substream->runtime->rate);
84 spin_unlock(&subs->lock); 88 spin_unlock(&subs->lock);
85 return hwptr_done / (substream->runtime->frame_bits >> 3); 89 return hwptr_done / (substream->runtime->frame_bits >> 3);
@@ -1147,6 +1151,10 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
1147 int i, period_elapsed = 0; 1151 int i, period_elapsed = 0;
1148 unsigned long flags; 1152 unsigned long flags;
1149 unsigned char *cp; 1153 unsigned char *cp;
1154 int current_frame_number;
1155
1156 /* read frame number here, update pointer in critical section */
1157 current_frame_number = usb_get_current_frame_number(subs->dev);
1150 1158
1151 stride = runtime->frame_bits >> 3; 1159 stride = runtime->frame_bits >> 3;
1152 1160
@@ -1180,6 +1188,15 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
1180 subs->transfer_done -= runtime->period_size; 1188 subs->transfer_done -= runtime->period_size;
1181 period_elapsed = 1; 1189 period_elapsed = 1;
1182 } 1190 }
1191 /* capture delay is by construction limited to one URB,
1192 * reset delays here
1193 */
1194 runtime->delay = subs->last_delay = 0;
1195
1196 /* realign last_frame_number */
1197 subs->last_frame_number = current_frame_number;
1198 subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
1199
1183 spin_unlock_irqrestore(&subs->lock, flags); 1200 spin_unlock_irqrestore(&subs->lock, flags);
1184 /* copy a data chunk */ 1201 /* copy a data chunk */
1185 if (oldptr + bytes > runtime->buffer_size * stride) { 1202 if (oldptr + bytes > runtime->buffer_size * stride) {