diff options
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r-- | sound/usb/pcm.c | 70 |
1 files changed, 58 insertions, 12 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 62ec808ed792..f782ce19bf5a 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, | |||
212 | } | 212 | } |
213 | } | 213 | } |
214 | 214 | ||
215 | static int start_endpoints(struct snd_usb_substream *subs) | 215 | static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) |
216 | { | 216 | { |
217 | int err; | 217 | int err; |
218 | 218 | ||
@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs) | |||
225 | snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); | 225 | snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); |
226 | 226 | ||
227 | ep->data_subs = subs; | 227 | ep->data_subs = subs; |
228 | err = snd_usb_endpoint_start(ep); | 228 | err = snd_usb_endpoint_start(ep, can_sleep); |
229 | if (err < 0) { | 229 | if (err < 0) { |
230 | clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); | 230 | clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); |
231 | return err; | 231 | return err; |
@@ -236,10 +236,25 @@ static int start_endpoints(struct snd_usb_substream *subs) | |||
236 | !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { | 236 | !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { |
237 | struct snd_usb_endpoint *ep = subs->sync_endpoint; | 237 | struct snd_usb_endpoint *ep = subs->sync_endpoint; |
238 | 238 | ||
239 | if (subs->data_endpoint->iface != subs->sync_endpoint->iface || | ||
240 | subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) { | ||
241 | err = usb_set_interface(subs->dev, | ||
242 | subs->sync_endpoint->iface, | ||
243 | subs->sync_endpoint->alt_idx); | ||
244 | if (err < 0) { | ||
245 | snd_printk(KERN_ERR | ||
246 | "%d:%d:%d: cannot set interface (%d)\n", | ||
247 | subs->dev->devnum, | ||
248 | subs->sync_endpoint->iface, | ||
249 | subs->sync_endpoint->alt_idx, err); | ||
250 | return -EIO; | ||
251 | } | ||
252 | } | ||
253 | |||
239 | snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); | 254 | snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); |
240 | 255 | ||
241 | ep->sync_slave = subs->data_endpoint; | 256 | ep->sync_slave = subs->data_endpoint; |
242 | err = snd_usb_endpoint_start(ep); | 257 | err = snd_usb_endpoint_start(ep, can_sleep); |
243 | if (err < 0) { | 258 | if (err < 0) { |
244 | clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); | 259 | clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); |
245 | return err; | 260 | return err; |
@@ -544,13 +559,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
544 | subs->last_frame_number = 0; | 559 | subs->last_frame_number = 0; |
545 | runtime->delay = 0; | 560 | runtime->delay = 0; |
546 | 561 | ||
547 | /* clear the pending deactivation on the target EPs */ | ||
548 | deactivate_endpoints(subs); | ||
549 | |||
550 | /* for playback, submit the URBs now; otherwise, the first hwptr_done | 562 | /* for playback, submit the URBs now; otherwise, the first hwptr_done |
551 | * updates for all URBs would happen at the same time when starting */ | 563 | * updates for all URBs would happen at the same time when starting */ |
552 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) | 564 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) |
553 | return start_endpoints(subs); | 565 | return start_endpoints(subs, 1); |
554 | 566 | ||
555 | return 0; | 567 | return 0; |
556 | } | 568 | } |
@@ -1032,6 +1044,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1032 | struct urb *urb) | 1044 | struct urb *urb) |
1033 | { | 1045 | { |
1034 | struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; | 1046 | struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; |
1047 | struct snd_usb_endpoint *ep = subs->data_endpoint; | ||
1035 | struct snd_urb_ctx *ctx = urb->context; | 1048 | struct snd_urb_ctx *ctx = urb->context; |
1036 | unsigned int counts, frames, bytes; | 1049 | unsigned int counts, frames, bytes; |
1037 | int i, stride, period_elapsed = 0; | 1050 | int i, stride, period_elapsed = 0; |
@@ -1043,7 +1056,11 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1043 | urb->number_of_packets = 0; | 1056 | urb->number_of_packets = 0; |
1044 | spin_lock_irqsave(&subs->lock, flags); | 1057 | spin_lock_irqsave(&subs->lock, flags); |
1045 | for (i = 0; i < ctx->packets; i++) { | 1058 | for (i = 0; i < ctx->packets; i++) { |
1046 | counts = ctx->packet_size[i]; | 1059 | if (ctx->packet_size[i]) |
1060 | counts = ctx->packet_size[i]; | ||
1061 | else | ||
1062 | counts = snd_usb_endpoint_next_packet_size(ep); | ||
1063 | |||
1047 | /* set up descriptor */ | 1064 | /* set up descriptor */ |
1048 | urb->iso_frame_desc[i].offset = frames * stride; | 1065 | urb->iso_frame_desc[i].offset = frames * stride; |
1049 | urb->iso_frame_desc[i].length = counts * stride; | 1066 | urb->iso_frame_desc[i].length = counts * stride; |
@@ -1094,7 +1111,16 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1094 | subs->hwptr_done += bytes; | 1111 | subs->hwptr_done += bytes; |
1095 | if (subs->hwptr_done >= runtime->buffer_size * stride) | 1112 | if (subs->hwptr_done >= runtime->buffer_size * stride) |
1096 | subs->hwptr_done -= runtime->buffer_size * stride; | 1113 | subs->hwptr_done -= runtime->buffer_size * stride; |
1114 | |||
1115 | /* update delay with exact number of samples queued */ | ||
1116 | runtime->delay = subs->last_delay; | ||
1097 | runtime->delay += frames; | 1117 | runtime->delay += frames; |
1118 | subs->last_delay = runtime->delay; | ||
1119 | |||
1120 | /* realign last_frame_number */ | ||
1121 | subs->last_frame_number = usb_get_current_frame_number(subs->dev); | ||
1122 | subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ | ||
1123 | |||
1098 | spin_unlock_irqrestore(&subs->lock, flags); | 1124 | spin_unlock_irqrestore(&subs->lock, flags); |
1099 | urb->transfer_buffer_length = bytes; | 1125 | urb->transfer_buffer_length = bytes; |
1100 | if (period_elapsed) | 1126 | if (period_elapsed) |
@@ -1112,12 +1138,32 @@ static void retire_playback_urb(struct snd_usb_substream *subs, | |||
1112 | struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; | 1138 | struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; |
1113 | int stride = runtime->frame_bits >> 3; | 1139 | int stride = runtime->frame_bits >> 3; |
1114 | int processed = urb->transfer_buffer_length / stride; | 1140 | int processed = urb->transfer_buffer_length / stride; |
1141 | int est_delay; | ||
1142 | |||
1143 | /* ignore the delay accounting when procssed=0 is given, i.e. | ||
1144 | * silent payloads are procssed before handling the actual data | ||
1145 | */ | ||
1146 | if (!processed) | ||
1147 | return; | ||
1115 | 1148 | ||
1116 | spin_lock_irqsave(&subs->lock, flags); | 1149 | spin_lock_irqsave(&subs->lock, flags); |
1117 | if (processed > runtime->delay) | 1150 | est_delay = snd_usb_pcm_delay(subs, runtime->rate); |
1118 | runtime->delay = 0; | 1151 | /* update delay with exact number of samples played */ |
1152 | if (processed > subs->last_delay) | ||
1153 | subs->last_delay = 0; | ||
1119 | else | 1154 | else |
1120 | runtime->delay -= processed; | 1155 | subs->last_delay -= processed; |
1156 | runtime->delay = subs->last_delay; | ||
1157 | |||
1158 | /* | ||
1159 | * Report when delay estimate is off by more than 2ms. | ||
1160 | * The error should be lower than 2ms since the estimate relies | ||
1161 | * on two reads of a counter updated every ms. | ||
1162 | */ | ||
1163 | if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) | ||
1164 | snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", | ||
1165 | est_delay, subs->last_delay); | ||
1166 | |||
1121 | spin_unlock_irqrestore(&subs->lock, flags); | 1167 | spin_unlock_irqrestore(&subs->lock, flags); |
1122 | } | 1168 | } |
1123 | 1169 | ||
@@ -1175,7 +1221,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream | |||
1175 | 1221 | ||
1176 | switch (cmd) { | 1222 | switch (cmd) { |
1177 | case SNDRV_PCM_TRIGGER_START: | 1223 | case SNDRV_PCM_TRIGGER_START: |
1178 | err = start_endpoints(subs); | 1224 | err = start_endpoints(subs, 0); |
1179 | if (err < 0) | 1225 | if (err < 0) |
1180 | return err; | 1226 | return err; |
1181 | 1227 | ||