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 | |
| 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>
| -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 | ||
