diff options
author | Daniel Mack <zonque@gmail.com> | 2012-08-30 12:52:29 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-08-31 15:03:08 -0400 |
commit | fbcfbf5f673847657ccd98afb4d8e13af7fdc372 (patch) | |
tree | a6fda9b6813f578f90e5a10df3a9f45f64d96ad7 /sound/usb | |
parent | 03d2f44e967b3c2cf79a6dfb904c8880616c7f83 (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.c | 29 |
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 | ||