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