aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2012-04-12 07:51:12 -0400
committerTakashi Iwai <tiwai@suse.de>2012-04-13 04:24:08 -0400
commitedcd3633e72a1590c4cf46befe5e6cd03b5aec3e (patch)
tree57aab87190179ba8995d05a93c3ece3a91f870ae /sound
parent8fdff6a319e7dac757c558bd283dc4577e68cde7 (diff)
ALSA: snd-usb: switch over to new endpoint streaming logic
With the previous commit that added the new streaming model, all endpoint and streaming related code is now in endpoint.c, and pcm.c only acts as a wrapper for handling the packet's payload. Signed-off-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/card.c8
-rw-r--r--sound/usb/card.h4
-rw-r--r--sound/usb/endpoint.c40
-rw-r--r--sound/usb/endpoint.h3
-rw-r--r--sound/usb/pcm.c418
-rw-r--r--sound/usb/stream.c31
6 files changed, 385 insertions, 119 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 6bc88b7ce4f..d5b5c3388e2 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -131,8 +131,9 @@ static void snd_usb_stream_disconnect(struct list_head *head)
131 subs = &as->substream[idx]; 131 subs = &as->substream[idx];
132 if (!subs->num_formats) 132 if (!subs->num_formats)
133 continue; 133 continue;
134 snd_usb_release_substream_urbs(subs, 1);
135 subs->interface = -1; 134 subs->interface = -1;
135 subs->data_endpoint = NULL;
136 subs->sync_endpoint = NULL;
136 } 137 }
137} 138}
138 139
@@ -350,6 +351,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
350 chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), 351 chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
351 le16_to_cpu(dev->descriptor.idProduct)); 352 le16_to_cpu(dev->descriptor.idProduct));
352 INIT_LIST_HEAD(&chip->pcm_list); 353 INIT_LIST_HEAD(&chip->pcm_list);
354 INIT_LIST_HEAD(&chip->ep_list);
353 INIT_LIST_HEAD(&chip->midi_list); 355 INIT_LIST_HEAD(&chip->midi_list);
354 INIT_LIST_HEAD(&chip->mixer_list); 356 INIT_LIST_HEAD(&chip->mixer_list);
355 357
@@ -567,6 +569,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
567 list_for_each(p, &chip->pcm_list) { 569 list_for_each(p, &chip->pcm_list) {
568 snd_usb_stream_disconnect(p); 570 snd_usb_stream_disconnect(p);
569 } 571 }
572 /* release the endpoint resources */
573 list_for_each(p, &chip->ep_list) {
574 snd_usb_endpoint_free(p);
575 }
570 /* release the midi resources */ 576 /* release the midi resources */
571 list_for_each(p, &chip->midi_list) { 577 list_for_each(p, &chip->midi_list) {
572 snd_usbmidi_disconnect(p); 578 snd_usbmidi_disconnect(p);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 9acbd4a1228..8a08687e5bc 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -145,6 +145,10 @@ struct snd_usb_substream {
145 struct snd_urb_ctx syncurb[SYNC_URBS]; /* sync urb table */ 145 struct snd_urb_ctx syncurb[SYNC_URBS]; /* sync urb table */
146 char *syncbuf; /* sync buffer for all sync URBs */ 146 char *syncbuf; /* sync buffer for all sync URBs */
147 dma_addr_t sync_dma; /* DMA address of syncbuf */ 147 dma_addr_t sync_dma; /* DMA address of syncbuf */
148 /* data and sync endpoints for this stream */
149 struct snd_usb_endpoint *data_endpoint;
150 struct snd_usb_endpoint *sync_endpoint;
151 unsigned long flags;
148 152
149 u64 formats; /* format bitmasks (all or'ed) */ 153 u64 formats; /* format bitmasks (all or'ed) */
150 unsigned int num_formats; /* number of supported audio formats (list) */ 154 unsigned int num_formats; /* number of supported audio formats (list) */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index ea25265427a..1b0ed22cff7 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -912,46 +912,6 @@ void snd_usb_init_substream(struct snd_usb_stream *as,
912 subs->fmt_type = fp->fmt_type; 912 subs->fmt_type = fp->fmt_type;
913} 913}
914 914
915int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
916{
917 struct snd_usb_substream *subs = substream->runtime->private_data;
918
919 switch (cmd) {
920 case SNDRV_PCM_TRIGGER_START:
921 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
922 subs->ops.prepare = prepare_playback_urb;
923 return 0;
924 case SNDRV_PCM_TRIGGER_STOP:
925 return deactivate_urbs_old(subs, 0, 0);
926 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
927 subs->ops.prepare = prepare_nodata_playback_urb;
928 return 0;
929 }
930
931 return -EINVAL;
932}
933
934int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
935{
936 struct snd_usb_substream *subs = substream->runtime->private_data;
937
938 switch (cmd) {
939 case SNDRV_PCM_TRIGGER_START:
940 subs->ops.retire = retire_capture_urb;
941 return start_urbs(subs, substream->runtime);
942 case SNDRV_PCM_TRIGGER_STOP:
943 return deactivate_urbs_old(subs, 0, 0);
944 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
945 subs->ops.retire = retire_paused_capture_urb;
946 return 0;
947 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
948 subs->ops.retire = retire_capture_urb;
949 return 0;
950 }
951
952 return -EINVAL;
953}
954
955int snd_usb_substream_prepare(struct snd_usb_substream *subs, 915int snd_usb_substream_prepare(struct snd_usb_substream *subs,
956 struct snd_pcm_runtime *runtime) 916 struct snd_pcm_runtime *runtime)
957{ 917{
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 9f083d7d6cf..e540768de3d 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -15,9 +15,6 @@ void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
15int snd_usb_substream_prepare(struct snd_usb_substream *subs, 15int snd_usb_substream_prepare(struct snd_usb_substream *subs,
16 struct snd_pcm_runtime *runtime); 16 struct snd_pcm_runtime *runtime);
17 17
18int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
19int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
20
21 18
22#define SND_USB_ENDPOINT_TYPE_DATA 0 19#define SND_USB_ENDPOINT_TYPE_DATA 0
23#define SND_USB_ENDPOINT_TYPE_SYNC 1 20#define SND_USB_ENDPOINT_TYPE_SYNC 1
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 0eed6115c2d..0f107834c10 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/ratelimit.h>
19#include <linux/usb.h> 20#include <linux/usb.h>
20#include <linux/usb/audio.h> 21#include <linux/usb/audio.h>
21#include <linux/usb/audio-v2.h> 22#include <linux/usb/audio-v2.h>
@@ -34,6 +35,9 @@
34#include "clock.h" 35#include "clock.h"
35#include "power.h" 36#include "power.h"
36 37
38#define SUBSTREAM_FLAG_DATA_EP_STARTED 0
39#define SUBSTREAM_FLAG_SYNC_EP_STARTED 1
40
37/* return the estimated delay based on USB frame counters */ 41/* return the estimated delay based on USB frame counters */
38snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, 42snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
39 unsigned int rate) 43 unsigned int rate)
@@ -208,6 +212,84 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
208 } 212 }
209} 213}
210 214
215static int start_endpoints(struct snd_usb_substream *subs)
216{
217 int err;
218
219 if (!subs->data_endpoint)
220 return -EINVAL;
221
222 if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
223 struct snd_usb_endpoint *ep = subs->data_endpoint;
224
225 snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
226
227 ep->data_subs = subs;
228 err = snd_usb_endpoint_start(ep);
229 if (err < 0) {
230 clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
231 return err;
232 }
233 }
234
235 if (subs->sync_endpoint &&
236 !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
237 struct snd_usb_endpoint *ep = subs->sync_endpoint;
238
239 snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
240
241 ep->sync_slave = subs->data_endpoint;
242 err = snd_usb_endpoint_start(ep);
243 if (err < 0) {
244 clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
245 return err;
246 }
247 }
248
249 return 0;
250}
251
252static void stop_endpoints(struct snd_usb_substream *subs,
253 int force, int can_sleep, int wait)
254{
255 if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
256 snd_usb_endpoint_stop(subs->sync_endpoint,
257 force, can_sleep, wait);
258
259 if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
260 snd_usb_endpoint_stop(subs->data_endpoint,
261 force, can_sleep, wait);
262}
263
264static int activate_endpoints(struct snd_usb_substream *subs)
265{
266 if (subs->sync_endpoint) {
267 int ret;
268
269 ret = snd_usb_endpoint_activate(subs->sync_endpoint);
270 if (ret < 0)
271 return ret;
272 }
273
274 return snd_usb_endpoint_activate(subs->data_endpoint);
275}
276
277static int deactivate_endpoints(struct snd_usb_substream *subs)
278{
279 int reta, retb;
280
281 reta = snd_usb_endpoint_deactivate(subs->sync_endpoint);
282 retb = snd_usb_endpoint_deactivate(subs->data_endpoint);
283
284 if (reta < 0)
285 return reta;
286
287 if (retb < 0)
288 return retb;
289
290 return 0;
291}
292
211/* 293/*
212 * find a matching format and set up the interface 294 * find a matching format and set up the interface
213 */ 295 */
@@ -232,40 +314,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
232 if (fmt == subs->cur_audiofmt) 314 if (fmt == subs->cur_audiofmt)
233 return 0; 315 return 0;
234 316
235 /* close the old interface */ 317 subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
236 if (subs->interface >= 0 && subs->interface != fmt->iface) { 318 alts, fmt->endpoint, subs->direction,
237 if (usb_set_interface(subs->dev, subs->interface, 0) < 0) { 319 SND_USB_ENDPOINT_TYPE_DATA);
238 snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n", 320 if (!subs->data_endpoint)
239 dev->devnum, fmt->iface, fmt->altsetting); 321 return -EINVAL;
240 return -EIO;
241 }
242 subs->interface = -1;
243 subs->altset_idx = 0;
244 }
245
246 /* set interface */
247 if (subs->interface != fmt->iface || subs->altset_idx != fmt->altset_idx) {
248 if (usb_set_interface(dev, fmt->iface, fmt->altsetting) < 0) {
249 snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n",
250 dev->devnum, fmt->iface, fmt->altsetting);
251 return -EIO;
252 }
253 snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting);
254 subs->interface = fmt->iface;
255 subs->altset_idx = fmt->altset_idx;
256 }
257
258 /* create a data pipe */
259 ep = fmt->endpoint & USB_ENDPOINT_NUMBER_MASK;
260 if (is_playback)
261 subs->datapipe = usb_sndisocpipe(dev, ep);
262 else
263 subs->datapipe = usb_rcvisocpipe(dev, ep);
264 subs->datainterval = fmt->datainterval;
265 subs->syncpipe = subs->syncinterval = 0;
266 subs->maxpacksize = fmt->maxpacksize;
267 subs->syncmaxsize = 0;
268 subs->fill_max = 0;
269 322
270 /* we need a sync pipe in async OUT or adaptive IN mode */ 323 /* we need a sync pipe in async OUT or adaptive IN mode */
271 /* check the number of EP, since some devices have broken 324 /* check the number of EP, since some devices have broken
@@ -276,6 +329,15 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
276 if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || 329 if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
277 (! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && 330 (! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
278 altsd->bNumEndpoints >= 2) { 331 altsd->bNumEndpoints >= 2) {
332 switch (subs->stream->chip->usb_id) {
333 case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
334 case USB_ID(0x0763, 0x2081):
335 ep = 0x81;
336 iface = usb_ifnum_to_if(dev, 2);
337 alts = &iface->altsetting[1];
338 goto add_sync_ep;
339 }
340
279 /* check sync-pipe endpoint */ 341 /* check sync-pipe endpoint */
280 /* ... and check descriptor size before accessing bSynchAddress 342 /* ... and check descriptor size before accessing bSynchAddress
281 because there is a version of the SB Audigy 2 NX firmware lacking 343 because there is a version of the SB Audigy 2 NX firmware lacking
@@ -295,28 +357,16 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
295 dev->devnum, fmt->iface, fmt->altsetting); 357 dev->devnum, fmt->iface, fmt->altsetting);
296 return -EINVAL; 358 return -EINVAL;
297 } 359 }
298 ep &= USB_ENDPOINT_NUMBER_MASK; 360add_sync_ep:
299 if (is_playback) 361 subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
300 subs->syncpipe = usb_rcvisocpipe(dev, ep); 362 alts, ep, !subs->direction,
301 else 363 SND_USB_ENDPOINT_TYPE_SYNC);
302 subs->syncpipe = usb_sndisocpipe(dev, ep); 364
303 if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && 365 if (!subs->sync_endpoint)
304 get_endpoint(alts, 1)->bRefresh >= 1 && 366 return -EINVAL;
305 get_endpoint(alts, 1)->bRefresh <= 9) 367
306 subs->syncinterval = get_endpoint(alts, 1)->bRefresh; 368 subs->data_endpoint->sync_master = subs->sync_endpoint;
307 else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) 369 }
308 subs->syncinterval = 1;
309 else if (get_endpoint(alts, 1)->bInterval >= 1 &&
310 get_endpoint(alts, 1)->bInterval <= 16)
311 subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
312 else
313 subs->syncinterval = 3;
314 subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
315 }
316
317 /* always fill max packet size */
318 if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX)
319 subs->fill_max = 1;
320 370
321 if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) 371 if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0)
322 return err; 372 return err;
@@ -390,12 +440,22 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
390 if (changed) { 440 if (changed) {
391 mutex_lock(&subs->stream->chip->shutdown_mutex); 441 mutex_lock(&subs->stream->chip->shutdown_mutex);
392 /* format changed */ 442 /* format changed */
393 snd_usb_release_substream_urbs(subs, 0); 443 stop_endpoints(subs, 0, 0, 0);
394 /* influenced: period_bytes, channels, rate, format, */ 444 deactivate_endpoints(subs);
395 ret = snd_usb_init_substream_urbs(subs, params_period_bytes(hw_params), 445
396 params_rate(hw_params), 446 ret = activate_endpoints(subs);
397 snd_pcm_format_physical_width(params_format(hw_params)) * 447 if (ret < 0)
398 params_channels(hw_params)); 448 goto unlock;
449
450 ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
451 subs->sync_endpoint);
452 if (ret < 0)
453 goto unlock;
454
455 if (subs->sync_endpoint)
456 ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
457 hw_params, fmt, NULL);
458unlock:
399 mutex_unlock(&subs->stream->chip->shutdown_mutex); 459 mutex_unlock(&subs->stream->chip->shutdown_mutex);
400 } 460 }
401 461
@@ -415,7 +475,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
415 subs->cur_rate = 0; 475 subs->cur_rate = 0;
416 subs->period_bytes = 0; 476 subs->period_bytes = 0;
417 mutex_lock(&subs->stream->chip->shutdown_mutex); 477 mutex_lock(&subs->stream->chip->shutdown_mutex);
418 snd_usb_release_substream_urbs(subs, 0); 478 stop_endpoints(subs, 0, 1, 1);
419 mutex_unlock(&subs->stream->chip->shutdown_mutex); 479 mutex_unlock(&subs->stream->chip->shutdown_mutex);
420 return snd_pcm_lib_free_vmalloc_buffer(substream); 480 return snd_pcm_lib_free_vmalloc_buffer(substream);
421} 481}
@@ -435,19 +495,28 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
435 return -ENXIO; 495 return -ENXIO;
436 } 496 }
437 497
498 if (snd_BUG_ON(!subs->data_endpoint))
499 return -EIO;
500
438 /* some unit conversions in runtime */ 501 /* some unit conversions in runtime */
439 subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize); 502 subs->data_endpoint->maxframesize =
440 subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); 503 bytes_to_frames(runtime, subs->data_endpoint->maxpacksize);
504 subs->data_endpoint->curframesize =
505 bytes_to_frames(runtime, subs->data_endpoint->curpacksize);
441 506
442 /* reset the pointer */ 507 /* reset the pointer */
443 subs->hwptr_done = 0; 508 subs->hwptr_done = 0;
444 subs->transfer_done = 0; 509 subs->transfer_done = 0;
445 subs->phase = 0;
446 subs->last_delay = 0; 510 subs->last_delay = 0;
447 subs->last_frame_number = 0; 511 subs->last_frame_number = 0;
448 runtime->delay = 0; 512 runtime->delay = 0;
449 513
450 return snd_usb_substream_prepare(subs, runtime); 514 /* for playback, submit the URBs now; otherwise, the first hwptr_done
515 * updates for all URBs would happen at the same time when starting */
516 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
517 return start_endpoints(subs);
518
519 return 0;
451} 520}
452 521
453static struct snd_pcm_hardware snd_usb_hardware = 522static struct snd_pcm_hardware snd_usb_hardware =
@@ -842,16 +911,171 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
842 911
843static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) 912static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
844{ 913{
914 int ret;
845 struct snd_usb_stream *as = snd_pcm_substream_chip(substream); 915 struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
846 struct snd_usb_substream *subs = &as->substream[direction]; 916 struct snd_usb_substream *subs = &as->substream[direction];
847 917
848 if (!as->chip->shutdown && subs->interface >= 0) { 918 stop_endpoints(subs, 0, 0, 0);
849 usb_set_interface(subs->dev, subs->interface, 0); 919 ret = deactivate_endpoints(subs);
850 subs->interface = -1;
851 }
852 subs->pcm_substream = NULL; 920 subs->pcm_substream = NULL;
853 snd_usb_autosuspend(subs->stream->chip); 921 snd_usb_autosuspend(subs->stream->chip);
854 return 0; 922
923 return ret;
924}
925
926/* Since a URB can handle only a single linear buffer, we must use double
927 * buffering when the data to be transferred overflows the buffer boundary.
928 * To avoid inconsistencies when updating hwptr_done, we use double buffering
929 * for all URBs.
930 */
931static void retire_capture_urb(struct snd_usb_substream *subs,
932 struct urb *urb)
933{
934 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
935 unsigned int stride, frames, bytes, oldptr;
936 int i, period_elapsed = 0;
937 unsigned long flags;
938 unsigned char *cp;
939
940 stride = runtime->frame_bits >> 3;
941
942 for (i = 0; i < urb->number_of_packets; i++) {
943 cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
944 if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
945 snd_printdd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
946 // continue;
947 }
948 bytes = urb->iso_frame_desc[i].actual_length;
949 frames = bytes / stride;
950 if (!subs->txfr_quirk)
951 bytes = frames * stride;
952 if (bytes % (runtime->sample_bits >> 3) != 0) {
953#ifdef CONFIG_SND_DEBUG_VERBOSE
954 int oldbytes = bytes;
955#endif
956 bytes = frames * stride;
957 snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
958 oldbytes, bytes);
959 }
960 /* update the current pointer */
961 spin_lock_irqsave(&subs->lock, flags);
962 oldptr = subs->hwptr_done;
963 subs->hwptr_done += bytes;
964 if (subs->hwptr_done >= runtime->buffer_size * stride)
965 subs->hwptr_done -= runtime->buffer_size * stride;
966 frames = (bytes + (oldptr % stride)) / stride;
967 subs->transfer_done += frames;
968 if (subs->transfer_done >= runtime->period_size) {
969 subs->transfer_done -= runtime->period_size;
970 period_elapsed = 1;
971 }
972 spin_unlock_irqrestore(&subs->lock, flags);
973 /* copy a data chunk */
974 if (oldptr + bytes > runtime->buffer_size * stride) {
975 unsigned int bytes1 =
976 runtime->buffer_size * stride - oldptr;
977 memcpy(runtime->dma_area + oldptr, cp, bytes1);
978 memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
979 } else {
980 memcpy(runtime->dma_area + oldptr, cp, bytes);
981 }
982 }
983
984 if (period_elapsed)
985 snd_pcm_period_elapsed(subs->pcm_substream);
986}
987
988static void prepare_playback_urb(struct snd_usb_substream *subs,
989 struct urb *urb)
990{
991 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
992 struct snd_urb_ctx *ctx = urb->context;
993 unsigned int counts, frames, bytes;
994 int i, stride, period_elapsed = 0;
995 unsigned long flags;
996
997 stride = runtime->frame_bits >> 3;
998
999 frames = 0;
1000 urb->number_of_packets = 0;
1001 spin_lock_irqsave(&subs->lock, flags);
1002 for (i = 0; i < ctx->packets; i++) {
1003 counts = ctx->packet_size[i];
1004 /* set up descriptor */
1005 urb->iso_frame_desc[i].offset = frames * stride;
1006 urb->iso_frame_desc[i].length = counts * stride;
1007 frames += counts;
1008 urb->number_of_packets++;
1009 subs->transfer_done += counts;
1010 if (subs->transfer_done >= runtime->period_size) {
1011 subs->transfer_done -= runtime->period_size;
1012 period_elapsed = 1;
1013 if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
1014 if (subs->transfer_done > 0) {
1015 /* FIXME: fill-max mode is not
1016 * supported yet */
1017 frames -= subs->transfer_done;
1018 counts -= subs->transfer_done;
1019 urb->iso_frame_desc[i].length =
1020 counts * stride;
1021 subs->transfer_done = 0;
1022 }
1023 i++;
1024 if (i < ctx->packets) {
1025 /* add a transfer delimiter */
1026 urb->iso_frame_desc[i].offset =
1027 frames * stride;
1028 urb->iso_frame_desc[i].length = 0;
1029 urb->number_of_packets++;
1030 }
1031 break;
1032 }
1033 }
1034 if (period_elapsed &&
1035 !snd_usb_endpoint_implict_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
1036 break;
1037 }
1038 bytes = frames * stride;
1039 if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
1040 /* err, the transferred area goes over buffer boundary. */
1041 unsigned int bytes1 =
1042 runtime->buffer_size * stride - subs->hwptr_done;
1043 memcpy(urb->transfer_buffer,
1044 runtime->dma_area + subs->hwptr_done, bytes1);
1045 memcpy(urb->transfer_buffer + bytes1,
1046 runtime->dma_area, bytes - bytes1);
1047 } else {
1048 memcpy(urb->transfer_buffer,
1049 runtime->dma_area + subs->hwptr_done, bytes);
1050 }
1051 subs->hwptr_done += bytes;
1052 if (subs->hwptr_done >= runtime->buffer_size * stride)
1053 subs->hwptr_done -= runtime->buffer_size * stride;
1054 runtime->delay += frames;
1055 spin_unlock_irqrestore(&subs->lock, flags);
1056 urb->transfer_buffer_length = bytes;
1057 if (period_elapsed)
1058 snd_pcm_period_elapsed(subs->pcm_substream);
1059}
1060
1061/*
1062 * process after playback data complete
1063 * - decrease the delay count again
1064 */
1065static void retire_playback_urb(struct snd_usb_substream *subs,
1066 struct urb *urb)
1067{
1068 unsigned long flags;
1069 struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
1070 int stride = runtime->frame_bits >> 3;
1071 int processed = urb->transfer_buffer_length / stride;
1072
1073 spin_lock_irqsave(&subs->lock, flags);
1074 if (processed > runtime->delay)
1075 runtime->delay = 0;
1076 else
1077 runtime->delay -= processed;
1078 spin_unlock_irqrestore(&subs->lock, flags);
855} 1079}
856 1080
857static int snd_usb_playback_open(struct snd_pcm_substream *substream) 1081static int snd_usb_playback_open(struct snd_pcm_substream *substream)
@@ -874,6 +1098,56 @@ static int snd_usb_capture_close(struct snd_pcm_substream *substream)
874 return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE); 1098 return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE);
875} 1099}
876 1100
1101static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream,
1102 int cmd)
1103{
1104 struct snd_usb_substream *subs = substream->runtime->private_data;
1105
1106 switch (cmd) {
1107 case SNDRV_PCM_TRIGGER_START:
1108 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1109 subs->data_endpoint->prepare_data_urb = prepare_playback_urb;
1110 subs->data_endpoint->retire_data_urb = retire_playback_urb;
1111 return 0;
1112 case SNDRV_PCM_TRIGGER_STOP:
1113 stop_endpoints(subs, 0, 0, 0);
1114 return 0;
1115 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1116 subs->data_endpoint->prepare_data_urb = NULL;
1117 subs->data_endpoint->retire_data_urb = NULL;
1118 return 0;
1119 }
1120
1121 return -EINVAL;
1122}
1123
1124int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1125{
1126 int err;
1127 struct snd_usb_substream *subs = substream->runtime->private_data;
1128
1129 switch (cmd) {
1130 case SNDRV_PCM_TRIGGER_START:
1131 err = start_endpoints(subs);
1132 if (err < 0)
1133 return err;
1134
1135 subs->data_endpoint->retire_data_urb = retire_capture_urb;
1136 return 0;
1137 case SNDRV_PCM_TRIGGER_STOP:
1138 stop_endpoints(subs, 0, 0, 0);
1139 return 0;
1140 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1141 subs->data_endpoint->retire_data_urb = NULL;
1142 return 0;
1143 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1144 subs->data_endpoint->retire_data_urb = retire_capture_urb;
1145 return 0;
1146 }
1147
1148 return -EINVAL;
1149}
1150
877static struct snd_pcm_ops snd_usb_playback_ops = { 1151static struct snd_pcm_ops snd_usb_playback_ops = {
878 .open = snd_usb_playback_open, 1152 .open = snd_usb_playback_open,
879 .close = snd_usb_playback_close, 1153 .close = snd_usb_playback_close,
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 5ff8010b2d6..6b7d7a2b7ba 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -73,6 +73,31 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
73 } 73 }
74} 74}
75 75
76/*
77 * initialize the substream instance.
78 */
79
80static void snd_usb_init_substream(struct snd_usb_stream *as,
81 int stream,
82 struct audioformat *fp)
83{
84 struct snd_usb_substream *subs = &as->substream[stream];
85
86 INIT_LIST_HEAD(&subs->fmt_list);
87 spin_lock_init(&subs->lock);
88
89 subs->stream = as;
90 subs->direction = stream;
91 subs->dev = as->chip->dev;
92 subs->txfr_quirk = as->chip->txfr_quirk;
93
94 snd_usb_set_pcm_ops(as->pcm, stream);
95
96 list_add_tail(&fp->list, &subs->fmt_list);
97 subs->formats |= fp->formats;
98 subs->num_formats++;
99 subs->fmt_type = fp->fmt_type;
100}
76 101
77/* 102/*
78 * add this endpoint to the chip instance. 103 * add this endpoint to the chip instance.
@@ -94,9 +119,9 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
94 if (as->fmt_type != fp->fmt_type) 119 if (as->fmt_type != fp->fmt_type)
95 continue; 120 continue;
96 subs = &as->substream[stream]; 121 subs = &as->substream[stream];
97 if (!subs->endpoint) 122 if (!subs->data_endpoint)
98 continue; 123 continue;
99 if (subs->endpoint == fp->endpoint) { 124 if (subs->data_endpoint->ep_num == fp->endpoint) {
100 list_add_tail(&fp->list, &subs->fmt_list); 125 list_add_tail(&fp->list, &subs->fmt_list);
101 subs->num_formats++; 126 subs->num_formats++;
102 subs->formats |= fp->formats; 127 subs->formats |= fp->formats;
@@ -109,7 +134,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
109 if (as->fmt_type != fp->fmt_type) 134 if (as->fmt_type != fp->fmt_type)
110 continue; 135 continue;
111 subs = &as->substream[stream]; 136 subs = &as->substream[stream];
112 if (subs->endpoint) 137 if (subs->data_endpoint)
113 continue; 138 continue;
114 err = snd_pcm_new_stream(as->pcm, stream, 1); 139 err = snd_pcm_new_stream(as->pcm, stream, 1);
115 if (err < 0) 140 if (err < 0)