diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/usbaudio.c | 76 |
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 | */ |
906 | static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) | 904 | static 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 | ||