summaryrefslogtreecommitdiff
path: root/sound/usb/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r--sound/usb/pcm.c40
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)
struct snd_usb_endpoint *ep = subs->sync_endpoint;
if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
- subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) {
+ subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) {
err = usb_set_interface(subs->dev,
subs->sync_endpoint->iface,
- subs->sync_endpoint->alt_idx);
+ subs->sync_endpoint->altsetting);
if (err < 0) {
+ clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
snd_printk(KERN_ERR
"%d:%d:%d: cannot set interface (%d)\n",
subs->dev->devnum,
subs->sync_endpoint->iface,
- subs->sync_endpoint->alt_idx, err);
+ subs->sync_endpoint->altsetting, err);
return -EIO;
}
}
@@ -282,22 +283,6 @@ static void stop_endpoints(struct snd_usb_substream *subs, bool wait)
}
}
-static int deactivate_endpoints(struct snd_usb_substream *subs)
-{
- int reta, retb;
-
- reta = snd_usb_endpoint_deactivate(subs->sync_endpoint);
- retb = snd_usb_endpoint_deactivate(subs->data_endpoint);
-
- if (reta < 0)
- return reta;
-
- if (retb < 0)
- return retb;
-
- return 0;
-}
-
static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
unsigned int altsetting,
struct usb_host_interface **alts,
@@ -595,6 +580,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
subs->channels,
subs->period_bytes,
+ 0, 0,
subs->cur_rate,
subs->cur_audiofmt,
NULL);
@@ -631,6 +617,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
sync_fp->channels,
sync_period_bytes,
+ 0, 0,
subs->cur_rate,
sync_fp,
NULL);
@@ -653,6 +640,8 @@ static int configure_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
subs->channels,
subs->period_bytes,
+ subs->period_frames,
+ subs->buffer_periods,
subs->cur_rate,
subs->cur_audiofmt,
subs->sync_endpoint);
@@ -689,6 +678,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
subs->pcm_format = params_format(hw_params);
subs->period_bytes = params_period_bytes(hw_params);
+ subs->period_frames = params_period_size(hw_params);
+ subs->buffer_periods = params_periods(hw_params);
subs->channels = params_channels(hw_params);
subs->cur_rate = params_rate(hw_params);
@@ -730,7 +721,8 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
down_read(&subs->stream->chip->shutdown_rwsem);
if (!subs->stream->chip->shutdown) {
stop_endpoints(subs, true);
- deactivate_endpoints(subs);
+ snd_usb_endpoint_deactivate(subs->sync_endpoint);
+ snd_usb_endpoint_deactivate(subs->data_endpoint);
}
up_read(&subs->stream->chip->shutdown_rwsem);
return snd_pcm_lib_free_vmalloc_buffer(substream);
@@ -1363,6 +1355,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
frames = 0;
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
+ subs->frame_limit += ep->max_urb_frames;
for (i = 0; i < ctx->packets; i++) {
if (ctx->packet_size[i])
counts = ctx->packet_size[i];
@@ -1377,6 +1370,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
subs->transfer_done += counts;
if (subs->transfer_done >= runtime->period_size) {
subs->transfer_done -= runtime->period_size;
+ subs->frame_limit = 0;
period_elapsed = 1;
if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
if (subs->transfer_done > 0) {
@@ -1399,8 +1393,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
break;
}
}
- if (period_elapsed &&
- !snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
+ /* finish at the period boundary or after enough frames */
+ if ((period_elapsed ||
+ subs->transfer_done >= subs->frame_limit) &&
+ !snd_usb_endpoint_implicit_feedback_sink(ep))
break;
}
bytes = frames * ep->stride;