diff options
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r-- | sound/usb/pcm.c | 40 |
1 files changed, 18 insertions, 22 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b375d58871e7..ca3256d6fde3 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -241,16 +241,17 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) | |||
241 | struct snd_usb_endpoint *ep = subs->sync_endpoint; | 241 | struct snd_usb_endpoint *ep = subs->sync_endpoint; |
242 | 242 | ||
243 | if (subs->data_endpoint->iface != subs->sync_endpoint->iface || | 243 | if (subs->data_endpoint->iface != subs->sync_endpoint->iface || |
244 | subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) { | 244 | subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) { |
245 | err = usb_set_interface(subs->dev, | 245 | err = usb_set_interface(subs->dev, |
246 | subs->sync_endpoint->iface, | 246 | subs->sync_endpoint->iface, |
247 | subs->sync_endpoint->alt_idx); | 247 | subs->sync_endpoint->altsetting); |
248 | if (err < 0) { | 248 | if (err < 0) { |
249 | clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); | ||
249 | snd_printk(KERN_ERR | 250 | snd_printk(KERN_ERR |
250 | "%d:%d:%d: cannot set interface (%d)\n", | 251 | "%d:%d:%d: cannot set interface (%d)\n", |
251 | subs->dev->devnum, | 252 | subs->dev->devnum, |
252 | subs->sync_endpoint->iface, | 253 | subs->sync_endpoint->iface, |
253 | subs->sync_endpoint->alt_idx, err); | 254 | subs->sync_endpoint->altsetting, err); |
254 | return -EIO; | 255 | return -EIO; |
255 | } | 256 | } |
256 | } | 257 | } |
@@ -282,22 +283,6 @@ static void stop_endpoints(struct snd_usb_substream *subs, bool wait) | |||
282 | } | 283 | } |
283 | } | 284 | } |
284 | 285 | ||
285 | static int deactivate_endpoints(struct snd_usb_substream *subs) | ||
286 | { | ||
287 | int reta, retb; | ||
288 | |||
289 | reta = snd_usb_endpoint_deactivate(subs->sync_endpoint); | ||
290 | retb = snd_usb_endpoint_deactivate(subs->data_endpoint); | ||
291 | |||
292 | if (reta < 0) | ||
293 | return reta; | ||
294 | |||
295 | if (retb < 0) | ||
296 | return retb; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int search_roland_implicit_fb(struct usb_device *dev, int ifnum, | 286 | static int search_roland_implicit_fb(struct usb_device *dev, int ifnum, |
302 | unsigned int altsetting, | 287 | unsigned int altsetting, |
303 | struct usb_host_interface **alts, | 288 | struct usb_host_interface **alts, |
@@ -595,6 +580,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) | |||
595 | subs->pcm_format, | 580 | subs->pcm_format, |
596 | subs->channels, | 581 | subs->channels, |
597 | subs->period_bytes, | 582 | subs->period_bytes, |
583 | 0, 0, | ||
598 | subs->cur_rate, | 584 | subs->cur_rate, |
599 | subs->cur_audiofmt, | 585 | subs->cur_audiofmt, |
600 | NULL); | 586 | NULL); |
@@ -631,6 +617,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs) | |||
631 | subs->pcm_format, | 617 | subs->pcm_format, |
632 | sync_fp->channels, | 618 | sync_fp->channels, |
633 | sync_period_bytes, | 619 | sync_period_bytes, |
620 | 0, 0, | ||
634 | subs->cur_rate, | 621 | subs->cur_rate, |
635 | sync_fp, | 622 | sync_fp, |
636 | NULL); | 623 | NULL); |
@@ -653,6 +640,8 @@ static int configure_endpoint(struct snd_usb_substream *subs) | |||
653 | subs->pcm_format, | 640 | subs->pcm_format, |
654 | subs->channels, | 641 | subs->channels, |
655 | subs->period_bytes, | 642 | subs->period_bytes, |
643 | subs->period_frames, | ||
644 | subs->buffer_periods, | ||
656 | subs->cur_rate, | 645 | subs->cur_rate, |
657 | subs->cur_audiofmt, | 646 | subs->cur_audiofmt, |
658 | subs->sync_endpoint); | 647 | subs->sync_endpoint); |
@@ -689,6 +678,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
689 | 678 | ||
690 | subs->pcm_format = params_format(hw_params); | 679 | subs->pcm_format = params_format(hw_params); |
691 | subs->period_bytes = params_period_bytes(hw_params); | 680 | subs->period_bytes = params_period_bytes(hw_params); |
681 | subs->period_frames = params_period_size(hw_params); | ||
682 | subs->buffer_periods = params_periods(hw_params); | ||
692 | subs->channels = params_channels(hw_params); | 683 | subs->channels = params_channels(hw_params); |
693 | subs->cur_rate = params_rate(hw_params); | 684 | subs->cur_rate = params_rate(hw_params); |
694 | 685 | ||
@@ -730,7 +721,8 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
730 | down_read(&subs->stream->chip->shutdown_rwsem); | 721 | down_read(&subs->stream->chip->shutdown_rwsem); |
731 | if (!subs->stream->chip->shutdown) { | 722 | if (!subs->stream->chip->shutdown) { |
732 | stop_endpoints(subs, true); | 723 | stop_endpoints(subs, true); |
733 | deactivate_endpoints(subs); | 724 | snd_usb_endpoint_deactivate(subs->sync_endpoint); |
725 | snd_usb_endpoint_deactivate(subs->data_endpoint); | ||
734 | } | 726 | } |
735 | up_read(&subs->stream->chip->shutdown_rwsem); | 727 | up_read(&subs->stream->chip->shutdown_rwsem); |
736 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 728 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
@@ -1363,6 +1355,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1363 | frames = 0; | 1355 | frames = 0; |
1364 | urb->number_of_packets = 0; | 1356 | urb->number_of_packets = 0; |
1365 | spin_lock_irqsave(&subs->lock, flags); | 1357 | spin_lock_irqsave(&subs->lock, flags); |
1358 | subs->frame_limit += ep->max_urb_frames; | ||
1366 | for (i = 0; i < ctx->packets; i++) { | 1359 | for (i = 0; i < ctx->packets; i++) { |
1367 | if (ctx->packet_size[i]) | 1360 | if (ctx->packet_size[i]) |
1368 | counts = ctx->packet_size[i]; | 1361 | counts = ctx->packet_size[i]; |
@@ -1377,6 +1370,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1377 | subs->transfer_done += counts; | 1370 | subs->transfer_done += counts; |
1378 | if (subs->transfer_done >= runtime->period_size) { | 1371 | if (subs->transfer_done >= runtime->period_size) { |
1379 | subs->transfer_done -= runtime->period_size; | 1372 | subs->transfer_done -= runtime->period_size; |
1373 | subs->frame_limit = 0; | ||
1380 | period_elapsed = 1; | 1374 | period_elapsed = 1; |
1381 | if (subs->fmt_type == UAC_FORMAT_TYPE_II) { | 1375 | if (subs->fmt_type == UAC_FORMAT_TYPE_II) { |
1382 | if (subs->transfer_done > 0) { | 1376 | if (subs->transfer_done > 0) { |
@@ -1399,8 +1393,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1399 | break; | 1393 | break; |
1400 | } | 1394 | } |
1401 | } | 1395 | } |
1402 | if (period_elapsed && | 1396 | /* finish at the period boundary or after enough frames */ |
1403 | !snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */ | 1397 | if ((period_elapsed || |
1398 | subs->transfer_done >= subs->frame_limit) && | ||
1399 | !snd_usb_endpoint_implicit_feedback_sink(ep)) | ||
1404 | break; | 1400 | break; |
1405 | } | 1401 | } |
1406 | bytes = frames * ep->stride; | 1402 | bytes = frames * ep->stride; |