diff options
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r-- | sound/usb/usbaudio.c | 320 |
1 files changed, 187 insertions, 133 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8298c462c291..5aa5fe651a8a 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -41,10 +41,12 @@ | |||
41 | #include <sound/driver.h> | 41 | #include <sound/driver.h> |
42 | #include <linux/bitops.h> | 42 | #include <linux/bitops.h> |
43 | #include <linux/init.h> | 43 | #include <linux/init.h> |
44 | #include <linux/interrupt.h> | ||
44 | #include <linux/list.h> | 45 | #include <linux/list.h> |
45 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
46 | #include <linux/string.h> | 47 | #include <linux/string.h> |
47 | #include <linux/usb.h> | 48 | #include <linux/usb.h> |
49 | #include <linux/vmalloc.h> | ||
48 | #include <linux/moduleparam.h> | 50 | #include <linux/moduleparam.h> |
49 | #include <sound/core.h> | 51 | #include <sound/core.h> |
50 | #include <sound/info.h> | 52 | #include <sound/info.h> |
@@ -79,7 +81,7 @@ module_param_array(vid, int, NULL, 0444); | |||
79 | MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device."); | 81 | MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device."); |
80 | module_param_array(pid, int, NULL, 0444); | 82 | module_param_array(pid, int, NULL, 0444); |
81 | MODULE_PARM_DESC(pid, "Product ID for the USB audio device."); | 83 | MODULE_PARM_DESC(pid, "Product ID for the USB audio device."); |
82 | module_param(nrpacks, int, 0444); | 84 | module_param(nrpacks, int, 0644); |
83 | MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); | 85 | MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); |
84 | module_param(async_unlink, bool, 0444); | 86 | module_param(async_unlink, bool, 0444); |
85 | MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); | 87 | MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); |
@@ -97,7 +99,7 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); | |||
97 | 99 | ||
98 | #define MAX_PACKS 10 | 100 | #define MAX_PACKS 10 |
99 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ | 101 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ |
100 | #define MAX_URBS 5 /* max. 20ms long packets */ | 102 | #define MAX_URBS 8 |
101 | #define SYNC_URBS 4 /* always four urbs for sync */ | 103 | #define SYNC_URBS 4 /* always four urbs for sync */ |
102 | #define MIN_PACKS_URB 1 /* minimum 1 packet per urb */ | 104 | #define MIN_PACKS_URB 1 /* minimum 1 packet per urb */ |
103 | 105 | ||
@@ -126,11 +128,10 @@ struct audioformat { | |||
126 | 128 | ||
127 | struct snd_urb_ctx { | 129 | struct snd_urb_ctx { |
128 | struct urb *urb; | 130 | struct urb *urb; |
131 | unsigned int buffer_size; /* size of data buffer, if data URB */ | ||
129 | snd_usb_substream_t *subs; | 132 | snd_usb_substream_t *subs; |
130 | int index; /* index for urb array */ | 133 | int index; /* index for urb array */ |
131 | int packets; /* number of packets per urb */ | 134 | int packets; /* number of packets per urb */ |
132 | int transfer; /* transferred size */ | ||
133 | char *buf; /* buffer for capture */ | ||
134 | }; | 135 | }; |
135 | 136 | ||
136 | struct snd_urb_ops { | 137 | struct snd_urb_ops { |
@@ -165,12 +166,11 @@ struct snd_usb_substream { | |||
165 | unsigned int curframesize; /* current packet size in frames (for capture) */ | 166 | unsigned int curframesize; /* current packet size in frames (for capture) */ |
166 | unsigned int fill_max: 1; /* fill max packet size always */ | 167 | unsigned int fill_max: 1; /* fill max packet size always */ |
167 | unsigned int fmt_type; /* USB audio format type (1-3) */ | 168 | unsigned int fmt_type; /* USB audio format type (1-3) */ |
169 | unsigned int packs_per_ms; /* packets per millisecond (for playback) */ | ||
168 | 170 | ||
169 | unsigned int running: 1; /* running status */ | 171 | unsigned int running: 1; /* running status */ |
170 | 172 | ||
171 | unsigned int hwptr; /* free frame position in the buffer (only for playback) */ | ||
172 | unsigned int hwptr_done; /* processed frame position in the buffer */ | 173 | unsigned int hwptr_done; /* processed frame position in the buffer */ |
173 | unsigned int transfer_sched; /* scheduled frames since last period (for playback) */ | ||
174 | unsigned int transfer_done; /* processed frames since last period update */ | 174 | unsigned int transfer_done; /* processed frames since last period update */ |
175 | unsigned long active_mask; /* bitmask of active urbs */ | 175 | unsigned long active_mask; /* bitmask of active urbs */ |
176 | unsigned long unlink_mask; /* bitmask of unlinked urbs */ | 176 | unsigned long unlink_mask; /* bitmask of unlinked urbs */ |
@@ -178,13 +178,14 @@ struct snd_usb_substream { | |||
178 | unsigned int nurbs; /* # urbs */ | 178 | unsigned int nurbs; /* # urbs */ |
179 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ | 179 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ |
180 | snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ | 180 | snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ |
181 | char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */ | 181 | char *syncbuf; /* sync buffer for all sync URBs */ |
182 | char *tmpbuf; /* temporary buffer for playback */ | 182 | dma_addr_t sync_dma; /* DMA address of syncbuf */ |
183 | 183 | ||
184 | u64 formats; /* format bitmasks (all or'ed) */ | 184 | u64 formats; /* format bitmasks (all or'ed) */ |
185 | unsigned int num_formats; /* number of supported audio formats (list) */ | 185 | unsigned int num_formats; /* number of supported audio formats (list) */ |
186 | struct list_head fmt_list; /* format list */ | 186 | struct list_head fmt_list; /* format list */ |
187 | spinlock_t lock; | 187 | spinlock_t lock; |
188 | struct tasklet_struct start_period_elapsed; /* for start trigger */ | ||
188 | 189 | ||
189 | struct snd_urb_ops ops; /* callbacks (must be filled at init) */ | 190 | struct snd_urb_ops ops; /* callbacks (must be filled at init) */ |
190 | }; | 191 | }; |
@@ -311,27 +312,17 @@ static int prepare_capture_urb(snd_usb_substream_t *subs, | |||
311 | struct urb *urb) | 312 | struct urb *urb) |
312 | { | 313 | { |
313 | int i, offs; | 314 | int i, offs; |
314 | unsigned long flags; | ||
315 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 315 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
316 | 316 | ||
317 | offs = 0; | 317 | offs = 0; |
318 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 318 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
319 | urb->number_of_packets = 0; | ||
320 | spin_lock_irqsave(&subs->lock, flags); | ||
321 | for (i = 0; i < ctx->packets; i++) { | 319 | for (i = 0; i < ctx->packets; i++) { |
322 | urb->iso_frame_desc[i].offset = offs; | 320 | urb->iso_frame_desc[i].offset = offs; |
323 | urb->iso_frame_desc[i].length = subs->curpacksize; | 321 | urb->iso_frame_desc[i].length = subs->curpacksize; |
324 | offs += subs->curpacksize; | 322 | offs += subs->curpacksize; |
325 | urb->number_of_packets++; | ||
326 | subs->transfer_sched += subs->curframesize; | ||
327 | if (subs->transfer_sched >= runtime->period_size) { | ||
328 | subs->transfer_sched -= runtime->period_size; | ||
329 | break; | ||
330 | } | ||
331 | } | 323 | } |
332 | spin_unlock_irqrestore(&subs->lock, flags); | ||
333 | urb->transfer_buffer = ctx->buf; | ||
334 | urb->transfer_buffer_length = offs; | 324 | urb->transfer_buffer_length = offs; |
325 | urb->number_of_packets = ctx->packets; | ||
335 | #if 0 // for check | 326 | #if 0 // for check |
336 | if (! urb->bandwidth) { | 327 | if (! urb->bandwidth) { |
337 | int bustime; | 328 | int bustime; |
@@ -359,6 +350,7 @@ static int retire_capture_urb(snd_usb_substream_t *subs, | |||
359 | unsigned char *cp; | 350 | unsigned char *cp; |
360 | int i; | 351 | int i; |
361 | unsigned int stride, len, oldptr; | 352 | unsigned int stride, len, oldptr; |
353 | int period_elapsed = 0; | ||
362 | 354 | ||
363 | stride = runtime->frame_bits >> 3; | 355 | stride = runtime->frame_bits >> 3; |
364 | 356 | ||
@@ -378,6 +370,10 @@ static int retire_capture_urb(snd_usb_substream_t *subs, | |||
378 | if (subs->hwptr_done >= runtime->buffer_size) | 370 | if (subs->hwptr_done >= runtime->buffer_size) |
379 | subs->hwptr_done -= runtime->buffer_size; | 371 | subs->hwptr_done -= runtime->buffer_size; |
380 | subs->transfer_done += len; | 372 | subs->transfer_done += len; |
373 | if (subs->transfer_done >= runtime->period_size) { | ||
374 | subs->transfer_done -= runtime->period_size; | ||
375 | period_elapsed = 1; | ||
376 | } | ||
381 | spin_unlock_irqrestore(&subs->lock, flags); | 377 | spin_unlock_irqrestore(&subs->lock, flags); |
382 | /* copy a data chunk */ | 378 | /* copy a data chunk */ |
383 | if (oldptr + len > runtime->buffer_size) { | 379 | if (oldptr + len > runtime->buffer_size) { |
@@ -388,15 +384,9 @@ static int retire_capture_urb(snd_usb_substream_t *subs, | |||
388 | } else { | 384 | } else { |
389 | memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); | 385 | memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); |
390 | } | 386 | } |
391 | /* update the pointer, call callback if necessary */ | ||
392 | spin_lock_irqsave(&subs->lock, flags); | ||
393 | if (subs->transfer_done >= runtime->period_size) { | ||
394 | subs->transfer_done -= runtime->period_size; | ||
395 | spin_unlock_irqrestore(&subs->lock, flags); | ||
396 | snd_pcm_period_elapsed(subs->pcm_substream); | ||
397 | } else | ||
398 | spin_unlock_irqrestore(&subs->lock, flags); | ||
399 | } | 387 | } |
388 | if (period_elapsed) | ||
389 | snd_pcm_period_elapsed(subs->pcm_substream); | ||
400 | return 0; | 390 | return 0; |
401 | } | 391 | } |
402 | 392 | ||
@@ -492,12 +482,10 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs, | |||
492 | /* | 482 | /* |
493 | * prepare urb for playback data pipe | 483 | * prepare urb for playback data pipe |
494 | * | 484 | * |
495 | * we copy the data directly from the pcm buffer. | 485 | * Since a URB can handle only a single linear buffer, we must use double |
496 | * the current position to be copied is held in hwptr field. | 486 | * buffering when the data to be transferred overflows the buffer boundary. |
497 | * since a urb can handle only a single linear buffer, if the total | 487 | * To avoid inconsistencies when updating hwptr_done, we use double buffering |
498 | * transferred area overflows the buffer boundary, we cannot send | 488 | * for all URBs. |
499 | * it directly from the buffer. thus the data is once copied to | ||
500 | * a temporary buffer and urb points to that. | ||
501 | */ | 489 | */ |
502 | static int prepare_playback_urb(snd_usb_substream_t *subs, | 490 | static int prepare_playback_urb(snd_usb_substream_t *subs, |
503 | snd_pcm_runtime_t *runtime, | 491 | snd_pcm_runtime_t *runtime, |
@@ -506,6 +494,7 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, | |||
506 | int i, stride, offs; | 494 | int i, stride, offs; |
507 | unsigned int counts; | 495 | unsigned int counts; |
508 | unsigned long flags; | 496 | unsigned long flags; |
497 | int period_elapsed = 0; | ||
509 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 498 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
510 | 499 | ||
511 | stride = runtime->frame_bits >> 3; | 500 | stride = runtime->frame_bits >> 3; |
@@ -530,80 +519,85 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, | |||
530 | urb->iso_frame_desc[i].length = counts * stride; | 519 | urb->iso_frame_desc[i].length = counts * stride; |
531 | offs += counts; | 520 | offs += counts; |
532 | urb->number_of_packets++; | 521 | urb->number_of_packets++; |
533 | subs->transfer_sched += counts; | 522 | subs->transfer_done += counts; |
534 | if (subs->transfer_sched >= runtime->period_size) { | 523 | if (subs->transfer_done >= runtime->period_size) { |
535 | subs->transfer_sched -= runtime->period_size; | 524 | subs->transfer_done -= runtime->period_size; |
525 | period_elapsed = 1; | ||
536 | if (subs->fmt_type == USB_FORMAT_TYPE_II) { | 526 | if (subs->fmt_type == USB_FORMAT_TYPE_II) { |
537 | if (subs->transfer_sched > 0) { | 527 | if (subs->transfer_done > 0) { |
538 | /* FIXME: fill-max mode is not supported yet */ | 528 | /* FIXME: fill-max mode is not |
539 | offs -= subs->transfer_sched; | 529 | * supported yet */ |
540 | counts -= subs->transfer_sched; | 530 | offs -= subs->transfer_done; |
541 | urb->iso_frame_desc[i].length = counts * stride; | 531 | counts -= subs->transfer_done; |
542 | subs->transfer_sched = 0; | 532 | urb->iso_frame_desc[i].length = |
533 | counts * stride; | ||
534 | subs->transfer_done = 0; | ||
543 | } | 535 | } |
544 | i++; | 536 | i++; |
545 | if (i < ctx->packets) { | 537 | if (i < ctx->packets) { |
546 | /* add a transfer delimiter */ | 538 | /* add a transfer delimiter */ |
547 | urb->iso_frame_desc[i].offset = offs * stride; | 539 | urb->iso_frame_desc[i].offset = |
540 | offs * stride; | ||
548 | urb->iso_frame_desc[i].length = 0; | 541 | urb->iso_frame_desc[i].length = 0; |
549 | urb->number_of_packets++; | 542 | urb->number_of_packets++; |
550 | } | 543 | } |
544 | break; | ||
551 | } | 545 | } |
552 | break; | ||
553 | } | 546 | } |
547 | /* finish at the frame boundary at/after the period boundary */ | ||
548 | if (period_elapsed && | ||
549 | (i & (subs->packs_per_ms - 1)) == subs->packs_per_ms - 1) | ||
550 | break; | ||
554 | } | 551 | } |
555 | if (subs->hwptr + offs > runtime->buffer_size) { | 552 | if (subs->hwptr_done + offs > runtime->buffer_size) { |
556 | /* err, the transferred area goes over buffer boundary. | 553 | /* err, the transferred area goes over buffer boundary. */ |
557 | * copy the data to the temp buffer. | 554 | unsigned int len = runtime->buffer_size - subs->hwptr_done; |
558 | */ | 555 | memcpy(urb->transfer_buffer, |
559 | int len; | 556 | runtime->dma_area + subs->hwptr_done * stride, |
560 | len = runtime->buffer_size - subs->hwptr; | 557 | len * stride); |
561 | urb->transfer_buffer = subs->tmpbuf; | 558 | memcpy(urb->transfer_buffer + len * stride, |
562 | memcpy(subs->tmpbuf, runtime->dma_area + subs->hwptr * stride, len * stride); | 559 | runtime->dma_area, |
563 | memcpy(subs->tmpbuf + len * stride, runtime->dma_area, (offs - len) * stride); | 560 | (offs - len) * stride); |
564 | subs->hwptr += offs; | ||
565 | subs->hwptr -= runtime->buffer_size; | ||
566 | } else { | 561 | } else { |
567 | /* set the buffer pointer */ | 562 | memcpy(urb->transfer_buffer, |
568 | urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride; | 563 | runtime->dma_area + subs->hwptr_done * stride, |
569 | subs->hwptr += offs; | 564 | offs * stride); |
570 | if (subs->hwptr == runtime->buffer_size) | ||
571 | subs->hwptr = 0; | ||
572 | } | 565 | } |
566 | subs->hwptr_done += offs; | ||
567 | if (subs->hwptr_done >= runtime->buffer_size) | ||
568 | subs->hwptr_done -= runtime->buffer_size; | ||
573 | spin_unlock_irqrestore(&subs->lock, flags); | 569 | spin_unlock_irqrestore(&subs->lock, flags); |
574 | urb->transfer_buffer_length = offs * stride; | 570 | urb->transfer_buffer_length = offs * stride; |
575 | ctx->transfer = offs; | 571 | if (period_elapsed) { |
576 | 572 | if (likely(subs->running)) | |
573 | snd_pcm_period_elapsed(subs->pcm_substream); | ||
574 | else | ||
575 | tasklet_hi_schedule(&subs->start_period_elapsed); | ||
576 | } | ||
577 | return 0; | 577 | return 0; |
578 | } | 578 | } |
579 | 579 | ||
580 | /* | 580 | /* |
581 | * process after playback data complete | 581 | * process after playback data complete |
582 | * | 582 | * - nothing to do |
583 | * update the current position and call callback if a period is processed. | ||
584 | */ | 583 | */ |
585 | static int retire_playback_urb(snd_usb_substream_t *subs, | 584 | static int retire_playback_urb(snd_usb_substream_t *subs, |
586 | snd_pcm_runtime_t *runtime, | 585 | snd_pcm_runtime_t *runtime, |
587 | struct urb *urb) | 586 | struct urb *urb) |
588 | { | 587 | { |
589 | unsigned long flags; | ||
590 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | ||
591 | |||
592 | spin_lock_irqsave(&subs->lock, flags); | ||
593 | subs->transfer_done += ctx->transfer; | ||
594 | subs->hwptr_done += ctx->transfer; | ||
595 | ctx->transfer = 0; | ||
596 | if (subs->hwptr_done >= runtime->buffer_size) | ||
597 | subs->hwptr_done -= runtime->buffer_size; | ||
598 | if (subs->transfer_done >= runtime->period_size) { | ||
599 | subs->transfer_done -= runtime->period_size; | ||
600 | spin_unlock_irqrestore(&subs->lock, flags); | ||
601 | snd_pcm_period_elapsed(subs->pcm_substream); | ||
602 | } else | ||
603 | spin_unlock_irqrestore(&subs->lock, flags); | ||
604 | return 0; | 588 | return 0; |
605 | } | 589 | } |
606 | 590 | ||
591 | /* | ||
592 | * Delay the snd_pcm_period_elapsed() call until after the start trigger | ||
593 | * callback so that we're not longer in the substream's lock. | ||
594 | */ | ||
595 | static void start_period_elapsed(unsigned long data) | ||
596 | { | ||
597 | snd_usb_substream_t *subs = (snd_usb_substream_t *)data; | ||
598 | snd_pcm_period_elapsed(subs->pcm_substream); | ||
599 | } | ||
600 | |||
607 | 601 | ||
608 | /* | 602 | /* |
609 | */ | 603 | */ |
@@ -683,6 +677,42 @@ static void snd_complete_sync_urb(struct urb *urb, struct pt_regs *regs) | |||
683 | } | 677 | } |
684 | 678 | ||
685 | 679 | ||
680 | /* get the physical page pointer at the given offset */ | ||
681 | static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, | ||
682 | unsigned long offset) | ||
683 | { | ||
684 | void *pageptr = subs->runtime->dma_area + offset; | ||
685 | return vmalloc_to_page(pageptr); | ||
686 | } | ||
687 | |||
688 | /* allocate virtual buffer; may be called more than once */ | ||
689 | static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) | ||
690 | { | ||
691 | snd_pcm_runtime_t *runtime = subs->runtime; | ||
692 | if (runtime->dma_area) { | ||
693 | if (runtime->dma_bytes >= size) | ||
694 | return 0; /* already large enough */ | ||
695 | vfree_nocheck(runtime->dma_area); | ||
696 | } | ||
697 | runtime->dma_area = vmalloc_nocheck(size); | ||
698 | if (! runtime->dma_area) | ||
699 | return -ENOMEM; | ||
700 | runtime->dma_bytes = size; | ||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | /* free virtual buffer; may be called more than once */ | ||
705 | static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs) | ||
706 | { | ||
707 | snd_pcm_runtime_t *runtime = subs->runtime; | ||
708 | if (runtime->dma_area) { | ||
709 | vfree_nocheck(runtime->dma_area); | ||
710 | runtime->dma_area = NULL; | ||
711 | } | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | |||
686 | /* | 716 | /* |
687 | * unlink active urbs. | 717 | * unlink active urbs. |
688 | */ | 718 | */ |
@@ -824,8 +854,14 @@ static int wait_clear_urbs(snd_usb_substream_t *subs) | |||
824 | */ | 854 | */ |
825 | static snd_pcm_uframes_t snd_usb_pcm_pointer(snd_pcm_substream_t *substream) | 855 | static snd_pcm_uframes_t snd_usb_pcm_pointer(snd_pcm_substream_t *substream) |
826 | { | 856 | { |
827 | snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data; | 857 | snd_usb_substream_t *subs; |
828 | return subs->hwptr_done; | 858 | snd_pcm_uframes_t hwptr_done; |
859 | |||
860 | subs = (snd_usb_substream_t *)substream->runtime->private_data; | ||
861 | spin_lock(&subs->lock); | ||
862 | hwptr_done = subs->hwptr_done; | ||
863 | spin_unlock(&subs->lock); | ||
864 | return hwptr_done; | ||
829 | } | 865 | } |
830 | 866 | ||
831 | 867 | ||
@@ -858,11 +894,13 @@ static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
858 | static void release_urb_ctx(snd_urb_ctx_t *u) | 894 | static void release_urb_ctx(snd_urb_ctx_t *u) |
859 | { | 895 | { |
860 | if (u->urb) { | 896 | if (u->urb) { |
897 | if (u->buffer_size) | ||
898 | usb_buffer_free(u->subs->dev, u->buffer_size, | ||
899 | u->urb->transfer_buffer, | ||
900 | u->urb->transfer_dma); | ||
861 | usb_free_urb(u->urb); | 901 | usb_free_urb(u->urb); |
862 | u->urb = NULL; | 902 | u->urb = NULL; |
863 | } | 903 | } |
864 | kfree(u->buf); | ||
865 | u->buf = NULL; | ||
866 | } | 904 | } |
867 | 905 | ||
868 | /* | 906 | /* |
@@ -880,8 +918,9 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force) | |||
880 | release_urb_ctx(&subs->dataurb[i]); | 918 | release_urb_ctx(&subs->dataurb[i]); |
881 | for (i = 0; i < SYNC_URBS; i++) | 919 | for (i = 0; i < SYNC_URBS; i++) |
882 | release_urb_ctx(&subs->syncurb[i]); | 920 | release_urb_ctx(&subs->syncurb[i]); |
883 | kfree(subs->tmpbuf); | 921 | usb_buffer_free(subs->dev, SYNC_URBS * 4, |
884 | subs->tmpbuf = NULL; | 922 | subs->syncbuf, subs->sync_dma); |
923 | subs->syncbuf = NULL; | ||
885 | subs->nurbs = 0; | 924 | subs->nurbs = 0; |
886 | } | 925 | } |
887 | 926 | ||
@@ -893,7 +932,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
893 | { | 932 | { |
894 | unsigned int maxsize, n, i; | 933 | unsigned int maxsize, n, i; |
895 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; | 934 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; |
896 | unsigned int npacks[MAX_URBS], urb_packs, total_packs; | 935 | unsigned int npacks[MAX_URBS], urb_packs, total_packs, packs_per_ms; |
897 | 936 | ||
898 | /* calculate the frequency in 16.16 format */ | 937 | /* calculate the frequency in 16.16 format */ |
899 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 938 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) |
@@ -920,24 +959,40 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
920 | else | 959 | else |
921 | subs->curpacksize = maxsize; | 960 | subs->curpacksize = maxsize; |
922 | 961 | ||
923 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 962 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) |
924 | urb_packs = nrpacks; | 963 | packs_per_ms = 8 >> subs->datainterval; |
925 | else | 964 | else |
926 | urb_packs = (nrpacks * 8) >> subs->datainterval; | 965 | packs_per_ms = 1; |
966 | subs->packs_per_ms = packs_per_ms; | ||
927 | 967 | ||
928 | /* allocate a temporary buffer for playback */ | ||
929 | if (is_playback) { | 968 | if (is_playback) { |
930 | subs->tmpbuf = kmalloc(maxsize * urb_packs, GFP_KERNEL); | 969 | urb_packs = nrpacks; |
931 | if (! subs->tmpbuf) { | 970 | urb_packs = max(urb_packs, (unsigned int)MIN_PACKS_URB); |
932 | snd_printk(KERN_ERR "cannot malloc tmpbuf\n"); | 971 | urb_packs = min(urb_packs, (unsigned int)MAX_PACKS); |
933 | return -ENOMEM; | 972 | } else |
934 | } | 973 | urb_packs = 1; |
935 | } | 974 | urb_packs *= packs_per_ms; |
936 | 975 | ||
937 | /* decide how many packets to be used */ | 976 | /* decide how many packets to be used */ |
938 | total_packs = (period_bytes + maxsize - 1) / maxsize; | 977 | if (is_playback) { |
939 | if (total_packs < 2 * MIN_PACKS_URB) | 978 | unsigned int minsize; |
940 | total_packs = 2 * MIN_PACKS_URB; | 979 | /* determine how small a packet can be */ |
980 | minsize = (subs->freqn >> (16 - subs->datainterval)) | ||
981 | * (frame_bits >> 3); | ||
982 | /* with sync from device, assume it can be 12% lower */ | ||
983 | if (subs->syncpipe) | ||
984 | minsize -= minsize >> 3; | ||
985 | minsize = max(minsize, 1u); | ||
986 | total_packs = (period_bytes + minsize - 1) / minsize; | ||
987 | /* round up to multiple of packs_per_ms */ | ||
988 | total_packs = (total_packs + packs_per_ms - 1) | ||
989 | & ~(packs_per_ms - 1); | ||
990 | /* we need at least two URBs for queueing */ | ||
991 | if (total_packs < 2 * MIN_PACKS_URB * packs_per_ms) | ||
992 | total_packs = 2 * MIN_PACKS_URB * packs_per_ms; | ||
993 | } else { | ||
994 | total_packs = MAX_URBS * urb_packs; | ||
995 | } | ||
941 | subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; | 996 | subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; |
942 | if (subs->nurbs > MAX_URBS) { | 997 | if (subs->nurbs > MAX_URBS) { |
943 | /* too much... */ | 998 | /* too much... */ |
@@ -956,7 +1011,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
956 | subs->nurbs = 2; | 1011 | subs->nurbs = 2; |
957 | npacks[0] = (total_packs + 1) / 2; | 1012 | npacks[0] = (total_packs + 1) / 2; |
958 | npacks[1] = total_packs - npacks[0]; | 1013 | npacks[1] = total_packs - npacks[0]; |
959 | } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB) { | 1014 | } else if (npacks[subs->nurbs-1] < MIN_PACKS_URB * packs_per_ms) { |
960 | /* the last packet is too small.. */ | 1015 | /* the last packet is too small.. */ |
961 | if (subs->nurbs > 2) { | 1016 | if (subs->nurbs > 2) { |
962 | /* merge to the first one */ | 1017 | /* merge to the first one */ |
@@ -975,27 +1030,20 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
975 | snd_urb_ctx_t *u = &subs->dataurb[i]; | 1030 | snd_urb_ctx_t *u = &subs->dataurb[i]; |
976 | u->index = i; | 1031 | u->index = i; |
977 | u->subs = subs; | 1032 | u->subs = subs; |
978 | u->transfer = 0; | ||
979 | u->packets = npacks[i]; | 1033 | u->packets = npacks[i]; |
1034 | u->buffer_size = maxsize * u->packets; | ||
980 | if (subs->fmt_type == USB_FORMAT_TYPE_II) | 1035 | if (subs->fmt_type == USB_FORMAT_TYPE_II) |
981 | u->packets++; /* for transfer delimiter */ | 1036 | u->packets++; /* for transfer delimiter */ |
982 | if (! is_playback) { | ||
983 | /* allocate a capture buffer per urb */ | ||
984 | u->buf = kmalloc(maxsize * u->packets, GFP_KERNEL); | ||
985 | if (! u->buf) { | ||
986 | release_substream_urbs(subs, 0); | ||
987 | return -ENOMEM; | ||
988 | } | ||
989 | } | ||
990 | u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); | 1037 | u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); |
991 | if (! u->urb) { | 1038 | if (! u->urb) |
992 | release_substream_urbs(subs, 0); | 1039 | goto out_of_memory; |
993 | return -ENOMEM; | 1040 | u->urb->transfer_buffer = |
994 | } | 1041 | usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL, |
995 | u->urb->dev = subs->dev; | 1042 | &u->urb->transfer_dma); |
1043 | if (! u->urb->transfer_buffer) | ||
1044 | goto out_of_memory; | ||
996 | u->urb->pipe = subs->datapipe; | 1045 | u->urb->pipe = subs->datapipe; |
997 | u->urb->transfer_flags = URB_ISO_ASAP; | 1046 | u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
998 | u->urb->number_of_packets = u->packets; | ||
999 | u->urb->interval = 1 << subs->datainterval; | 1047 | u->urb->interval = 1 << subs->datainterval; |
1000 | u->urb->context = u; | 1048 | u->urb->context = u; |
1001 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); | 1049 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); |
@@ -1003,21 +1051,24 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
1003 | 1051 | ||
1004 | if (subs->syncpipe) { | 1052 | if (subs->syncpipe) { |
1005 | /* allocate and initialize sync urbs */ | 1053 | /* allocate and initialize sync urbs */ |
1054 | subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4, | ||
1055 | GFP_KERNEL, &subs->sync_dma); | ||
1056 | if (! subs->syncbuf) | ||
1057 | goto out_of_memory; | ||
1006 | for (i = 0; i < SYNC_URBS; i++) { | 1058 | for (i = 0; i < SYNC_URBS; i++) { |
1007 | snd_urb_ctx_t *u = &subs->syncurb[i]; | 1059 | snd_urb_ctx_t *u = &subs->syncurb[i]; |
1008 | u->index = i; | 1060 | u->index = i; |
1009 | u->subs = subs; | 1061 | u->subs = subs; |
1010 | u->packets = 1; | 1062 | u->packets = 1; |
1011 | u->urb = usb_alloc_urb(1, GFP_KERNEL); | 1063 | u->urb = usb_alloc_urb(1, GFP_KERNEL); |
1012 | if (! u->urb) { | 1064 | if (! u->urb) |
1013 | release_substream_urbs(subs, 0); | 1065 | goto out_of_memory; |
1014 | return -ENOMEM; | ||
1015 | } | ||
1016 | u->urb->transfer_buffer = subs->syncbuf + i * 4; | 1066 | u->urb->transfer_buffer = subs->syncbuf + i * 4; |
1067 | u->urb->transfer_dma = subs->sync_dma + i * 4; | ||
1017 | u->urb->transfer_buffer_length = 4; | 1068 | u->urb->transfer_buffer_length = 4; |
1018 | u->urb->dev = subs->dev; | ||
1019 | u->urb->pipe = subs->syncpipe; | 1069 | u->urb->pipe = subs->syncpipe; |
1020 | u->urb->transfer_flags = URB_ISO_ASAP; | 1070 | u->urb->transfer_flags = URB_ISO_ASAP | |
1071 | URB_NO_TRANSFER_DMA_MAP; | ||
1021 | u->urb->number_of_packets = 1; | 1072 | u->urb->number_of_packets = 1; |
1022 | u->urb->interval = 1 << subs->syncinterval; | 1073 | u->urb->interval = 1 << subs->syncinterval; |
1023 | u->urb->context = u; | 1074 | u->urb->context = u; |
@@ -1025,6 +1076,10 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
1025 | } | 1076 | } |
1026 | } | 1077 | } |
1027 | return 0; | 1078 | return 0; |
1079 | |||
1080 | out_of_memory: | ||
1081 | release_substream_urbs(subs, 0); | ||
1082 | return -ENOMEM; | ||
1028 | } | 1083 | } |
1029 | 1084 | ||
1030 | 1085 | ||
@@ -1293,7 +1348,8 @@ static int snd_usb_hw_params(snd_pcm_substream_t *substream, | |||
1293 | unsigned int channels, rate, format; | 1348 | unsigned int channels, rate, format; |
1294 | int ret, changed; | 1349 | int ret, changed; |
1295 | 1350 | ||
1296 | ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 1351 | ret = snd_pcm_alloc_vmalloc_buffer(substream, |
1352 | params_buffer_bytes(hw_params)); | ||
1297 | if (ret < 0) | 1353 | if (ret < 0) |
1298 | return ret; | 1354 | return ret; |
1299 | 1355 | ||
@@ -1349,7 +1405,7 @@ static int snd_usb_hw_free(snd_pcm_substream_t *substream) | |||
1349 | subs->cur_rate = 0; | 1405 | subs->cur_rate = 0; |
1350 | subs->period_bytes = 0; | 1406 | subs->period_bytes = 0; |
1351 | release_substream_urbs(subs, 0); | 1407 | release_substream_urbs(subs, 0); |
1352 | return snd_pcm_lib_free_pages(substream); | 1408 | return snd_pcm_free_vmalloc_buffer(substream); |
1353 | } | 1409 | } |
1354 | 1410 | ||
1355 | /* | 1411 | /* |
@@ -1372,9 +1428,7 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream) | |||
1372 | subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); | 1428 | subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); |
1373 | 1429 | ||
1374 | /* reset the pointer */ | 1430 | /* reset the pointer */ |
1375 | subs->hwptr = 0; | ||
1376 | subs->hwptr_done = 0; | 1431 | subs->hwptr_done = 0; |
1377 | subs->transfer_sched = 0; | ||
1378 | subs->transfer_done = 0; | 1432 | subs->transfer_done = 0; |
1379 | subs->phase = 0; | 1433 | subs->phase = 0; |
1380 | 1434 | ||
@@ -1390,7 +1444,7 @@ static snd_pcm_hardware_t snd_usb_playback = | |||
1390 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1444 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
1391 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1445 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1392 | SNDRV_PCM_INFO_MMAP_VALID), | 1446 | SNDRV_PCM_INFO_MMAP_VALID), |
1393 | .buffer_bytes_max = (128*1024), | 1447 | .buffer_bytes_max = (256*1024), |
1394 | .period_bytes_min = 64, | 1448 | .period_bytes_min = 64, |
1395 | .period_bytes_max = (128*1024), | 1449 | .period_bytes_max = (128*1024), |
1396 | .periods_min = 2, | 1450 | .periods_min = 2, |
@@ -1402,7 +1456,7 @@ static snd_pcm_hardware_t snd_usb_capture = | |||
1402 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1456 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
1403 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1457 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1404 | SNDRV_PCM_INFO_MMAP_VALID), | 1458 | SNDRV_PCM_INFO_MMAP_VALID), |
1405 | .buffer_bytes_max = (128*1024), | 1459 | .buffer_bytes_max = (256*1024), |
1406 | .period_bytes_min = 64, | 1460 | .period_bytes_min = 64, |
1407 | .period_bytes_max = (128*1024), | 1461 | .period_bytes_max = (128*1024), |
1408 | .periods_min = 2, | 1462 | .periods_min = 2, |
@@ -1794,6 +1848,7 @@ static snd_pcm_ops_t snd_usb_playback_ops = { | |||
1794 | .prepare = snd_usb_pcm_prepare, | 1848 | .prepare = snd_usb_pcm_prepare, |
1795 | .trigger = snd_usb_pcm_trigger, | 1849 | .trigger = snd_usb_pcm_trigger, |
1796 | .pointer = snd_usb_pcm_pointer, | 1850 | .pointer = snd_usb_pcm_pointer, |
1851 | .page = snd_pcm_get_vmalloc_page, | ||
1797 | }; | 1852 | }; |
1798 | 1853 | ||
1799 | static snd_pcm_ops_t snd_usb_capture_ops = { | 1854 | static snd_pcm_ops_t snd_usb_capture_ops = { |
@@ -1805,6 +1860,7 @@ static snd_pcm_ops_t snd_usb_capture_ops = { | |||
1805 | .prepare = snd_usb_pcm_prepare, | 1860 | .prepare = snd_usb_pcm_prepare, |
1806 | .trigger = snd_usb_pcm_trigger, | 1861 | .trigger = snd_usb_pcm_trigger, |
1807 | .pointer = snd_usb_pcm_pointer, | 1862 | .pointer = snd_usb_pcm_pointer, |
1863 | .page = snd_pcm_get_vmalloc_page, | ||
1808 | }; | 1864 | }; |
1809 | 1865 | ||
1810 | 1866 | ||
@@ -2021,6 +2077,9 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat | |||
2021 | 2077 | ||
2022 | INIT_LIST_HEAD(&subs->fmt_list); | 2078 | INIT_LIST_HEAD(&subs->fmt_list); |
2023 | spin_lock_init(&subs->lock); | 2079 | spin_lock_init(&subs->lock); |
2080 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
2081 | tasklet_init(&subs->start_period_elapsed, start_period_elapsed, | ||
2082 | (unsigned long)subs); | ||
2024 | 2083 | ||
2025 | subs->stream = as; | 2084 | subs->stream = as; |
2026 | subs->direction = stream; | 2085 | subs->direction = stream; |
@@ -2029,10 +2088,6 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat | |||
2029 | subs->ops = audio_urb_ops[stream]; | 2088 | subs->ops = audio_urb_ops[stream]; |
2030 | else | 2089 | else |
2031 | subs->ops = audio_urb_ops_high_speed[stream]; | 2090 | subs->ops = audio_urb_ops_high_speed[stream]; |
2032 | snd_pcm_lib_preallocate_pages(as->pcm->streams[stream].substream, | ||
2033 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
2034 | snd_dma_continuous_data(GFP_KERNEL), | ||
2035 | 64 * 1024, 128 * 1024); | ||
2036 | snd_pcm_set_ops(as->pcm, stream, | 2091 | snd_pcm_set_ops(as->pcm, stream, |
2037 | stream == SNDRV_PCM_STREAM_PLAYBACK ? | 2092 | stream == SNDRV_PCM_STREAM_PLAYBACK ? |
2038 | &snd_usb_playback_ops : &snd_usb_capture_ops); | 2093 | &snd_usb_playback_ops : &snd_usb_capture_ops); |
@@ -2078,7 +2133,6 @@ static void snd_usb_audio_pcm_free(snd_pcm_t *pcm) | |||
2078 | snd_usb_stream_t *stream = pcm->private_data; | 2133 | snd_usb_stream_t *stream = pcm->private_data; |
2079 | if (stream) { | 2134 | if (stream) { |
2080 | stream->pcm = NULL; | 2135 | stream->pcm = NULL; |
2081 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
2082 | snd_usb_audio_stream_free(stream); | 2136 | snd_usb_audio_stream_free(stream); |
2083 | } | 2137 | } |
2084 | } | 2138 | } |