aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/usbaudio.c76
1 files changed, 37 insertions, 39 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 286fa14e48bd..8fcb5d5a94b6 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -173,7 +173,7 @@ struct snd_usb_substream {
173 173
174 unsigned int running: 1; /* running status */ 174 unsigned int running: 1; /* running status */
175 175
176 unsigned int hwptr_done; /* processed frame position in the buffer */ 176 unsigned int hwptr_done; /* processed byte position in the buffer */
177 unsigned int transfer_done; /* processed frames since last period update */ 177 unsigned int transfer_done; /* processed frames since last period update */
178 unsigned long active_mask; /* bitmask of active urbs */ 178 unsigned long active_mask; /* bitmask of active urbs */
179 unsigned long unlink_mask; /* bitmask of unlinked urbs */ 179 unsigned long unlink_mask; /* bitmask of unlinked urbs */
@@ -342,7 +342,7 @@ static int retire_capture_urb(struct snd_usb_substream *subs,
342 unsigned long flags; 342 unsigned long flags;
343 unsigned char *cp; 343 unsigned char *cp;
344 int i; 344 int i;
345 unsigned int stride, len, oldptr; 345 unsigned int stride, frames, bytes, oldptr;
346 int period_elapsed = 0; 346 int period_elapsed = 0;
347 347
348 stride = runtime->frame_bits >> 3; 348 stride = runtime->frame_bits >> 3;
@@ -353,29 +353,28 @@ static int retire_capture_urb(struct snd_usb_substream *subs,
353 snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status); 353 snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
354 // continue; 354 // continue;
355 } 355 }
356 len = urb->iso_frame_desc[i].actual_length / stride; 356 frames = urb->iso_frame_desc[i].actual_length / stride;
357 if (! len) 357 bytes = frames * stride;
358 continue;
359 /* update the current pointer */ 358 /* update the current pointer */
360 spin_lock_irqsave(&subs->lock, flags); 359 spin_lock_irqsave(&subs->lock, flags);
361 oldptr = subs->hwptr_done; 360 oldptr = subs->hwptr_done;
362 subs->hwptr_done += len; 361 subs->hwptr_done += bytes;
363 if (subs->hwptr_done >= runtime->buffer_size) 362 if (subs->hwptr_done >= runtime->buffer_size * stride)
364 subs->hwptr_done -= runtime->buffer_size; 363 subs->hwptr_done -= runtime->buffer_size * stride;
365 subs->transfer_done += len; 364 subs->transfer_done += frames;
366 if (subs->transfer_done >= runtime->period_size) { 365 if (subs->transfer_done >= runtime->period_size) {
367 subs->transfer_done -= runtime->period_size; 366 subs->transfer_done -= runtime->period_size;
368 period_elapsed = 1; 367 period_elapsed = 1;
369 } 368 }
370 spin_unlock_irqrestore(&subs->lock, flags); 369 spin_unlock_irqrestore(&subs->lock, flags);
371 /* copy a data chunk */ 370 /* copy a data chunk */
372 if (oldptr + len > runtime->buffer_size) { 371 if (oldptr + bytes > runtime->buffer_size * stride) {
373 unsigned int cnt = runtime->buffer_size - oldptr; 372 unsigned int bytes1 =
374 unsigned int blen = cnt * stride; 373 runtime->buffer_size * stride - oldptr;
375 memcpy(runtime->dma_area + oldptr * stride, cp, blen); 374 memcpy(runtime->dma_area + oldptr, cp, bytes1);
376 memcpy(runtime->dma_area, cp + blen, len * stride - blen); 375 memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
377 } else { 376 } else {
378 memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); 377 memcpy(runtime->dma_area + oldptr, cp, bytes);
379 } 378 }
380 } 379 }
381 if (period_elapsed) 380 if (period_elapsed)
@@ -562,24 +561,24 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
562 struct snd_pcm_runtime *runtime, 561 struct snd_pcm_runtime *runtime,
563 struct urb *urb) 562 struct urb *urb)
564{ 563{
565 int i, stride, offs; 564 int i, stride;
566 unsigned int counts; 565 unsigned int counts, frames, bytes;
567 unsigned long flags; 566 unsigned long flags;
568 int period_elapsed = 0; 567 int period_elapsed = 0;
569 struct snd_urb_ctx *ctx = urb->context; 568 struct snd_urb_ctx *ctx = urb->context;
570 569
571 stride = runtime->frame_bits >> 3; 570 stride = runtime->frame_bits >> 3;
572 571
573 offs = 0; 572 frames = 0;
574 urb->dev = ctx->subs->dev; /* we need to set this at each time */ 573 urb->dev = ctx->subs->dev; /* we need to set this at each time */
575 urb->number_of_packets = 0; 574 urb->number_of_packets = 0;
576 spin_lock_irqsave(&subs->lock, flags); 575 spin_lock_irqsave(&subs->lock, flags);
577 for (i = 0; i < ctx->packets; i++) { 576 for (i = 0; i < ctx->packets; i++) {
578 counts = snd_usb_audio_next_packet_size(subs); 577 counts = snd_usb_audio_next_packet_size(subs);
579 /* set up descriptor */ 578 /* set up descriptor */
580 urb->iso_frame_desc[i].offset = offs * stride; 579 urb->iso_frame_desc[i].offset = frames * stride;
581 urb->iso_frame_desc[i].length = counts * stride; 580 urb->iso_frame_desc[i].length = counts * stride;
582 offs += counts; 581 frames += counts;
583 urb->number_of_packets++; 582 urb->number_of_packets++;
584 subs->transfer_done += counts; 583 subs->transfer_done += counts;
585 if (subs->transfer_done >= runtime->period_size) { 584 if (subs->transfer_done >= runtime->period_size) {
@@ -589,7 +588,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
589 if (subs->transfer_done > 0) { 588 if (subs->transfer_done > 0) {
590 /* FIXME: fill-max mode is not 589 /* FIXME: fill-max mode is not
591 * supported yet */ 590 * supported yet */
592 offs -= subs->transfer_done; 591 frames -= subs->transfer_done;
593 counts -= subs->transfer_done; 592 counts -= subs->transfer_done;
594 urb->iso_frame_desc[i].length = 593 urb->iso_frame_desc[i].length =
595 counts * stride; 594 counts * stride;
@@ -599,7 +598,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
599 if (i < ctx->packets) { 598 if (i < ctx->packets) {
600 /* add a transfer delimiter */ 599 /* add a transfer delimiter */
601 urb->iso_frame_desc[i].offset = 600 urb->iso_frame_desc[i].offset =
602 offs * stride; 601 frames * stride;
603 urb->iso_frame_desc[i].length = 0; 602 urb->iso_frame_desc[i].length = 0;
604 urb->number_of_packets++; 603 urb->number_of_packets++;
605 } 604 }
@@ -609,26 +608,25 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
609 if (period_elapsed) /* finish at the period boundary */ 608 if (period_elapsed) /* finish at the period boundary */
610 break; 609 break;
611 } 610 }
612 if (subs->hwptr_done + offs > runtime->buffer_size) { 611 bytes = frames * stride;
612 if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
613 /* err, the transferred area goes over buffer boundary. */ 613 /* err, the transferred area goes over buffer boundary. */
614 unsigned int len = runtime->buffer_size - subs->hwptr_done; 614 unsigned int bytes1 =
615 runtime->buffer_size * stride - subs->hwptr_done;
615 memcpy(urb->transfer_buffer, 616 memcpy(urb->transfer_buffer,
616 runtime->dma_area + subs->hwptr_done * stride, 617 runtime->dma_area + subs->hwptr_done, bytes1);
617 len * stride); 618 memcpy(urb->transfer_buffer + bytes1,
618 memcpy(urb->transfer_buffer + len * stride, 619 runtime->dma_area, bytes - bytes1);
619 runtime->dma_area,
620 (offs - len) * stride);
621 } else { 620 } else {
622 memcpy(urb->transfer_buffer, 621 memcpy(urb->transfer_buffer,
623 runtime->dma_area + subs->hwptr_done * stride, 622 runtime->dma_area + subs->hwptr_done, bytes);
624 offs * stride);
625 } 623 }
626 subs->hwptr_done += offs; 624 subs->hwptr_done += bytes;
627 if (subs->hwptr_done >= runtime->buffer_size) 625 if (subs->hwptr_done >= runtime->buffer_size * stride)
628 subs->hwptr_done -= runtime->buffer_size; 626 subs->hwptr_done -= runtime->buffer_size * stride;
629 runtime->delay += offs; 627 runtime->delay += frames;
630 spin_unlock_irqrestore(&subs->lock, flags); 628 spin_unlock_irqrestore(&subs->lock, flags);
631 urb->transfer_buffer_length = offs * stride; 629 urb->transfer_buffer_length = bytes;
632 if (period_elapsed) 630 if (period_elapsed)
633 snd_pcm_period_elapsed(subs->pcm_substream); 631 snd_pcm_period_elapsed(subs->pcm_substream);
634 return 0; 632 return 0;
@@ -901,18 +899,18 @@ static int wait_clear_urbs(struct snd_usb_substream *subs)
901 899
902 900
903/* 901/*
904 * return the current pcm pointer. just return the hwptr_done value. 902 * return the current pcm pointer. just based on the hwptr_done value.
905 */ 903 */
906static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) 904static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream)
907{ 905{
908 struct snd_usb_substream *subs; 906 struct snd_usb_substream *subs;
909 snd_pcm_uframes_t hwptr_done; 907 unsigned int hwptr_done;
910 908
911 subs = (struct snd_usb_substream *)substream->runtime->private_data; 909 subs = (struct snd_usb_substream *)substream->runtime->private_data;
912 spin_lock(&subs->lock); 910 spin_lock(&subs->lock);
913 hwptr_done = subs->hwptr_done; 911 hwptr_done = subs->hwptr_done;
914 spin_unlock(&subs->lock); 912 spin_unlock(&subs->lock);
915 return hwptr_done; 913 return hwptr_done / (substream->runtime->frame_bits >> 3);
916} 914}
917 915
918 916