aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2012-08-30 12:52:29 -0400
committerTakashi Iwai <tiwai@suse.de>2012-08-31 15:03:08 -0400
commitfbcfbf5f673847657ccd98afb4d8e13af7fdc372 (patch)
treea6fda9b6813f578f90e5a10df3a9f45f64d96ad7 /sound/usb
parent03d2f44e967b3c2cf79a6dfb904c8880616c7f83 (diff)
ALSA: snd-usb: restore delay information
Parts of commit 294c4fb8 ("ALSA: usb: refine delay information with USB frame counter") were unfortunately lost during the refactoring of the snd-usb driver in 3.5. This patch adds them back, restoring the correct delay information behaviour. Signed-off-by: Daniel Mack <zonque@gmail.com> Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Cc: stable@kernel.org [3.5+] Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/pcm.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 1546577ae458..5ceb8f1d63fb 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1091,7 +1091,16 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
1091 subs->hwptr_done += bytes; 1091 subs->hwptr_done += bytes;
1092 if (subs->hwptr_done >= runtime->buffer_size * stride) 1092 if (subs->hwptr_done >= runtime->buffer_size * stride)
1093 subs->hwptr_done -= runtime->buffer_size * stride; 1093 subs->hwptr_done -= runtime->buffer_size * stride;
1094
1095 /* update delay with exact number of samples queued */
1096 runtime->delay = subs->last_delay;
1094 runtime->delay += frames; 1097 runtime->delay += frames;
1098 subs->last_delay = runtime->delay;
1099
1100 /* realign last_frame_number */
1101 subs->last_frame_number = usb_get_current_frame_number(subs->dev);
1102 subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
1103
1095 spin_unlock_irqrestore(&subs->lock, flags); 1104 spin_unlock_irqrestore(&subs->lock, flags);
1096 urb->transfer_buffer_length = bytes; 1105 urb->transfer_buffer_length = bytes;
1097 if (period_elapsed) 1106 if (period_elapsed)
@@ -1109,12 +1118,26 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
1109 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; 1118 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
1110 int stride = runtime->frame_bits >> 3; 1119 int stride = runtime->frame_bits >> 3;
1111 int processed = urb->transfer_buffer_length / stride; 1120 int processed = urb->transfer_buffer_length / stride;
1121 int est_delay;
1112 1122
1113 spin_lock_irqsave(&subs->lock, flags); 1123 spin_lock_irqsave(&subs->lock, flags);
1114 if (processed > runtime->delay) 1124 est_delay = snd_usb_pcm_delay(subs, runtime->rate);
1115 runtime->delay = 0; 1125 /* update delay with exact number of samples played */
1126 if (processed > subs->last_delay)
1127 subs->last_delay = 0;
1116 else 1128 else
1117 runtime->delay -= processed; 1129 subs->last_delay -= processed;
1130 runtime->delay = subs->last_delay;
1131
1132 /*
1133 * Report when delay estimate is off by more than 2ms.
1134 * The error should be lower than 2ms since the estimate relies
1135 * on two reads of a counter updated every ms.
1136 */
1137 if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
1138 snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
1139 est_delay, subs->last_delay);
1140
1118 spin_unlock_irqrestore(&subs->lock, flags); 1141 spin_unlock_irqrestore(&subs->lock, flags);
1119} 1142}
1120 1143