aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2005-08-15 02:24:44 -0400
committerJaroslav Kysela <perex@suse.cz>2005-08-30 02:45:43 -0400
commit7efd8bc800324a967a37e8a425433468b7f06adb (patch)
tree9366f8d7b709cca8fa243708910783b8977919b7
parentb263a9bdf9394062a4fc4272ebed60de331c5490 (diff)
[ALSA] usb-audio: double-buffer all playback data
USB generic driver We always had to use double buffering when capturing, and when playback data for one URB crosses a buffer boundary. The latter would make hwptr updates less precise because the double-buffered data is read from the buffer much earlier than the other data is read by the host controller. Double-buffering all data allows to update hwptr immediately after the data was copied to the USB buffer(s), which has the additional benefit of avoiding the latency imposed by the host controller's delay of up to one frame when interrupting. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
-rw-r--r--sound/usb/usbaudio.c151
1 files changed, 65 insertions, 86 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index a703d96bfcb4..2b4f916a0a9a 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -41,6 +41,7 @@
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>
@@ -129,8 +130,6 @@ struct snd_urb_ctx {
129 snd_usb_substream_t *subs; 130 snd_usb_substream_t *subs;
130 int index; /* index for urb array */ 131 int index; /* index for urb array */
131 int packets; /* number of packets per urb */ 132 int packets; /* number of packets per urb */
132 int transfer; /* transferred size */
133 char *buf; /* buffer for capture */
134}; 133};
135 134
136struct snd_urb_ops { 135struct snd_urb_ops {
@@ -168,9 +167,7 @@ struct snd_usb_substream {
168 167
169 unsigned int running: 1; /* running status */ 168 unsigned int running: 1; /* running status */
170 169
171 unsigned int hwptr; /* free frame position in the buffer (only for playback) */
172 unsigned int hwptr_done; /* processed frame position in the buffer */ 170 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 */ 171 unsigned int transfer_done; /* processed frames since last period update */
175 unsigned long active_mask; /* bitmask of active urbs */ 172 unsigned long active_mask; /* bitmask of active urbs */
176 unsigned long unlink_mask; /* bitmask of unlinked urbs */ 173 unsigned long unlink_mask; /* bitmask of unlinked urbs */
@@ -179,12 +176,12 @@ struct snd_usb_substream {
179 snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ 176 snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */
180 snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ 177 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 */ 178 char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */
182 char *tmpbuf; /* temporary buffer for playback */
183 179
184 u64 formats; /* format bitmasks (all or'ed) */ 180 u64 formats; /* format bitmasks (all or'ed) */
185 unsigned int num_formats; /* number of supported audio formats (list) */ 181 unsigned int num_formats; /* number of supported audio formats (list) */
186 struct list_head fmt_list; /* format list */ 182 struct list_head fmt_list; /* format list */
187 spinlock_t lock; 183 spinlock_t lock;
184 struct tasklet_struct start_period_elapsed; /* for start trigger */
188 185
189 struct snd_urb_ops ops; /* callbacks (must be filled at init) */ 186 struct snd_urb_ops ops; /* callbacks (must be filled at init) */
190}; 187};
@@ -320,7 +317,6 @@ static int prepare_capture_urb(snd_usb_substream_t *subs,
320 urb->iso_frame_desc[i].length = subs->curpacksize; 317 urb->iso_frame_desc[i].length = subs->curpacksize;
321 offs += subs->curpacksize; 318 offs += subs->curpacksize;
322 } 319 }
323 urb->transfer_buffer = ctx->buf;
324 urb->transfer_buffer_length = offs; 320 urb->transfer_buffer_length = offs;
325 urb->number_of_packets = ctx->packets; 321 urb->number_of_packets = ctx->packets;
326#if 0 // for check 322#if 0 // for check
@@ -482,12 +478,10 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
482/* 478/*
483 * prepare urb for playback data pipe 479 * prepare urb for playback data pipe
484 * 480 *
485 * we copy the data directly from the pcm buffer. 481 * Since a URB can handle only a single linear buffer, we must use double
486 * the current position to be copied is held in hwptr field. 482 * buffering when the data to be transferred overflows the buffer boundary.
487 * since a urb can handle only a single linear buffer, if the total 483 * To avoid inconsistencies when updating hwptr_done, we use double buffering
488 * transferred area overflows the buffer boundary, we cannot send 484 * for all URBs.
489 * it directly from the buffer. thus the data is once copied to
490 * a temporary buffer and urb points to that.
491 */ 485 */
492static int prepare_playback_urb(snd_usb_substream_t *subs, 486static int prepare_playback_urb(snd_usb_substream_t *subs,
493 snd_pcm_runtime_t *runtime, 487 snd_pcm_runtime_t *runtime,
@@ -496,6 +490,7 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
496 int i, stride, offs; 490 int i, stride, offs;
497 unsigned int counts; 491 unsigned int counts;
498 unsigned long flags; 492 unsigned long flags;
493 int period_elapsed = 0;
499 snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; 494 snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
500 495
501 stride = runtime->frame_bits >> 3; 496 stride = runtime->frame_bits >> 3;
@@ -520,21 +515,25 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
520 urb->iso_frame_desc[i].length = counts * stride; 515 urb->iso_frame_desc[i].length = counts * stride;
521 offs += counts; 516 offs += counts;
522 urb->number_of_packets++; 517 urb->number_of_packets++;
523 subs->transfer_sched += counts; 518 subs->transfer_done += counts;
524 if (subs->transfer_sched >= runtime->period_size) { 519 if (subs->transfer_done >= runtime->period_size) {
525 subs->transfer_sched -= runtime->period_size; 520 subs->transfer_done -= runtime->period_size;
521 period_elapsed = 1;
526 if (subs->fmt_type == USB_FORMAT_TYPE_II) { 522 if (subs->fmt_type == USB_FORMAT_TYPE_II) {
527 if (subs->transfer_sched > 0) { 523 if (subs->transfer_done > 0) {
528 /* FIXME: fill-max mode is not supported yet */ 524 /* FIXME: fill-max mode is not
529 offs -= subs->transfer_sched; 525 * supported yet */
530 counts -= subs->transfer_sched; 526 offs -= subs->transfer_done;
531 urb->iso_frame_desc[i].length = counts * stride; 527 counts -= subs->transfer_done;
532 subs->transfer_sched = 0; 528 urb->iso_frame_desc[i].length =
529 counts * stride;
530 subs->transfer_done = 0;
533 } 531 }
534 i++; 532 i++;
535 if (i < ctx->packets) { 533 if (i < ctx->packets) {
536 /* add a transfer delimiter */ 534 /* add a transfer delimiter */
537 urb->iso_frame_desc[i].offset = offs * stride; 535 urb->iso_frame_desc[i].offset =
536 offs * stride;
538 urb->iso_frame_desc[i].length = 0; 537 urb->iso_frame_desc[i].length = 0;
539 urb->number_of_packets++; 538 urb->number_of_packets++;
540 } 539 }
@@ -542,58 +541,55 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
542 break; 541 break;
543 } 542 }
544 } 543 }
545 if (subs->hwptr + offs > runtime->buffer_size) { 544 if (subs->hwptr_done + offs > runtime->buffer_size) {
546 /* err, the transferred area goes over buffer boundary. 545 /* err, the transferred area goes over buffer boundary. */
547 * copy the data to the temp buffer. 546 unsigned int len = runtime->buffer_size - subs->hwptr_done;
548 */ 547 memcpy(urb->transfer_buffer,
549 int len; 548 runtime->dma_area + subs->hwptr_done * stride,
550 len = runtime->buffer_size - subs->hwptr; 549 len * stride);
551 urb->transfer_buffer = subs->tmpbuf; 550 memcpy(urb->transfer_buffer + len * stride,
552 memcpy(subs->tmpbuf, runtime->dma_area + subs->hwptr * stride, len * stride); 551 runtime->dma_area,
553 memcpy(subs->tmpbuf + len * stride, runtime->dma_area, (offs - len) * stride); 552 (offs - len) * stride);
554 subs->hwptr += offs;
555 subs->hwptr -= runtime->buffer_size;
556 } else { 553 } else {
557 /* set the buffer pointer */ 554 memcpy(urb->transfer_buffer,
558 urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride; 555 runtime->dma_area + subs->hwptr_done * stride,
559 subs->hwptr += offs; 556 offs * stride);
560 if (subs->hwptr == runtime->buffer_size)
561 subs->hwptr = 0;
562 } 557 }
558 subs->hwptr_done += offs;
559 if (subs->hwptr_done >= runtime->buffer_size)
560 subs->hwptr_done -= runtime->buffer_size;
563 spin_unlock_irqrestore(&subs->lock, flags); 561 spin_unlock_irqrestore(&subs->lock, flags);
564 urb->transfer_buffer_length = offs * stride; 562 urb->transfer_buffer_length = offs * stride;
565 ctx->transfer = offs; 563 if (period_elapsed) {
566 564 if (likely(subs->running))
565 snd_pcm_period_elapsed(subs->pcm_substream);
566 else
567 tasklet_hi_schedule(&subs->start_period_elapsed);
568 }
567 return 0; 569 return 0;
568} 570}
569 571
570/* 572/*
571 * process after playback data complete 573 * process after playback data complete
572 * 574 * - nothing to do
573 * update the current position and call callback if a period is processed.
574 */ 575 */
575static int retire_playback_urb(snd_usb_substream_t *subs, 576static int retire_playback_urb(snd_usb_substream_t *subs,
576 snd_pcm_runtime_t *runtime, 577 snd_pcm_runtime_t *runtime,
577 struct urb *urb) 578 struct urb *urb)
578{ 579{
579 unsigned long flags;
580 snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
581
582 spin_lock_irqsave(&subs->lock, flags);
583 subs->transfer_done += ctx->transfer;
584 subs->hwptr_done += ctx->transfer;
585 ctx->transfer = 0;
586 if (subs->hwptr_done >= runtime->buffer_size)
587 subs->hwptr_done -= runtime->buffer_size;
588 if (subs->transfer_done >= runtime->period_size) {
589 subs->transfer_done -= runtime->period_size;
590 spin_unlock_irqrestore(&subs->lock, flags);
591 snd_pcm_period_elapsed(subs->pcm_substream);
592 } else
593 spin_unlock_irqrestore(&subs->lock, flags);
594 return 0; 580 return 0;
595} 581}
596 582
583/*
584 * Delay the snd_pcm_period_elapsed() call until after the start trigger
585 * callback so that we're not longer in the substream's lock.
586 */
587static void start_period_elapsed(unsigned long data)
588{
589 snd_usb_substream_t *subs = (snd_usb_substream_t *)data;
590 snd_pcm_period_elapsed(subs->pcm_substream);
591}
592
597 593
598/* 594/*
599 */ 595 */
@@ -848,11 +844,10 @@ static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
848static void release_urb_ctx(snd_urb_ctx_t *u) 844static void release_urb_ctx(snd_urb_ctx_t *u)
849{ 845{
850 if (u->urb) { 846 if (u->urb) {
847 kfree(u->urb->transfer_buffer);
851 usb_free_urb(u->urb); 848 usb_free_urb(u->urb);
852 u->urb = NULL; 849 u->urb = NULL;
853 } 850 }
854 kfree(u->buf);
855 u->buf = NULL;
856} 851}
857 852
858/* 853/*
@@ -870,8 +865,6 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
870 release_urb_ctx(&subs->dataurb[i]); 865 release_urb_ctx(&subs->dataurb[i]);
871 for (i = 0; i < SYNC_URBS; i++) 866 for (i = 0; i < SYNC_URBS; i++)
872 release_urb_ctx(&subs->syncurb[i]); 867 release_urb_ctx(&subs->syncurb[i]);
873 kfree(subs->tmpbuf);
874 subs->tmpbuf = NULL;
875 subs->nurbs = 0; 868 subs->nurbs = 0;
876} 869}
877 870
@@ -923,24 +916,15 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
923 urb_packs = 1; 916 urb_packs = 1;
924 urb_packs *= packs_per_ms; 917 urb_packs *= packs_per_ms;
925 918
926 /* allocate a temporary buffer for playback */
927 if (is_playback) {
928 subs->tmpbuf = kmalloc(maxsize * urb_packs, GFP_KERNEL);
929 if (! subs->tmpbuf) {
930 snd_printk(KERN_ERR "cannot malloc tmpbuf\n");
931 return -ENOMEM;
932 }
933 }
934
935 /* decide how many packets to be used */ 919 /* decide how many packets to be used */
936 if (is_playback) { 920 if (is_playback) {
937 unsigned int minsize; 921 unsigned int minsize;
938 /* determine how small a packet can be */ 922 /* determine how small a packet can be */
939 minsize = (subs->freqn >> (16 - subs->datainterval)) 923 minsize = (subs->freqn >> (16 - subs->datainterval))
940 * (frame_bits >> 3); 924 * (frame_bits >> 3);
941 /* with sync from device, assume it can be 25% lower */ 925 /* with sync from device, assume it can be 12% lower */
942 if (subs->syncpipe) 926 if (subs->syncpipe)
943 minsize -= minsize >> 2; 927 minsize -= minsize >> 3;
944 minsize = max(minsize, 1u); 928 minsize = max(minsize, 1u);
945 total_packs = (period_bytes + minsize - 1) / minsize; 929 total_packs = (period_bytes + minsize - 1) / minsize;
946 /* round up to multiple of packs_per_ms */ 930 /* round up to multiple of packs_per_ms */
@@ -989,27 +973,22 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
989 snd_urb_ctx_t *u = &subs->dataurb[i]; 973 snd_urb_ctx_t *u = &subs->dataurb[i];
990 u->index = i; 974 u->index = i;
991 u->subs = subs; 975 u->subs = subs;
992 u->transfer = 0;
993 u->packets = npacks[i]; 976 u->packets = npacks[i];
994 if (subs->fmt_type == USB_FORMAT_TYPE_II) 977 if (subs->fmt_type == USB_FORMAT_TYPE_II)
995 u->packets++; /* for transfer delimiter */ 978 u->packets++; /* for transfer delimiter */
996 if (! is_playback) {
997 /* allocate a capture buffer per urb */
998 u->buf = kmalloc(maxsize * u->packets, GFP_KERNEL);
999 if (! u->buf) {
1000 release_substream_urbs(subs, 0);
1001 return -ENOMEM;
1002 }
1003 }
1004 u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); 979 u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
1005 if (! u->urb) { 980 if (! u->urb) {
1006 release_substream_urbs(subs, 0); 981 release_substream_urbs(subs, 0);
1007 return -ENOMEM; 982 return -ENOMEM;
1008 } 983 }
1009 u->urb->dev = subs->dev; 984 u->urb->transfer_buffer = kmalloc(maxsize * u->packets,
985 GFP_KERNEL);
986 if (! u->urb->transfer_buffer) {
987 release_substream_urbs(subs, 0);
988 return -ENOMEM;
989 }
1010 u->urb->pipe = subs->datapipe; 990 u->urb->pipe = subs->datapipe;
1011 u->urb->transfer_flags = URB_ISO_ASAP; 991 u->urb->transfer_flags = URB_ISO_ASAP;
1012 u->urb->number_of_packets = u->packets;
1013 u->urb->interval = 1 << subs->datainterval; 992 u->urb->interval = 1 << subs->datainterval;
1014 u->urb->context = u; 993 u->urb->context = u;
1015 u->urb->complete = snd_usb_complete_callback(snd_complete_urb); 994 u->urb->complete = snd_usb_complete_callback(snd_complete_urb);
@@ -1029,7 +1008,6 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
1029 } 1008 }
1030 u->urb->transfer_buffer = subs->syncbuf + i * 4; 1009 u->urb->transfer_buffer = subs->syncbuf + i * 4;
1031 u->urb->transfer_buffer_length = 4; 1010 u->urb->transfer_buffer_length = 4;
1032 u->urb->dev = subs->dev;
1033 u->urb->pipe = subs->syncpipe; 1011 u->urb->pipe = subs->syncpipe;
1034 u->urb->transfer_flags = URB_ISO_ASAP; 1012 u->urb->transfer_flags = URB_ISO_ASAP;
1035 u->urb->number_of_packets = 1; 1013 u->urb->number_of_packets = 1;
@@ -1386,9 +1364,7 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
1386 subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); 1364 subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
1387 1365
1388 /* reset the pointer */ 1366 /* reset the pointer */
1389 subs->hwptr = 0;
1390 subs->hwptr_done = 0; 1367 subs->hwptr_done = 0;
1391 subs->transfer_sched = 0;
1392 subs->transfer_done = 0; 1368 subs->transfer_done = 0;
1393 subs->phase = 0; 1369 subs->phase = 0;
1394 1370
@@ -2035,6 +2011,9 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
2035 2011
2036 INIT_LIST_HEAD(&subs->fmt_list); 2012 INIT_LIST_HEAD(&subs->fmt_list);
2037 spin_lock_init(&subs->lock); 2013 spin_lock_init(&subs->lock);
2014 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2015 tasklet_init(&subs->start_period_elapsed, start_period_elapsed,
2016 (unsigned long)subs);
2038 2017
2039 subs->stream = as; 2018 subs->stream = as;
2040 subs->direction = stream; 2019 subs->direction = stream;