Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 182691
b: refs/heads/master
c: adc8d31
h: refs/heads/master
i:
  182689: 6b1a73b
  182687: 291dcb8
v: v3
  • Loading branch information
Clemens Ladisch authored and Takashi Iwai committed Dec 28, 2009
1 parent 4e53f70 commit 0115a97
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 40 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7d2b451e65d255427c108e990507964ac39c13ee
refs/heads/master: adc8d31326c32a2a1e145ab80accbc3c6570b117
76 changes: 37 additions & 39 deletions trunk/sound/usb/usbaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ struct snd_usb_substream {

unsigned int running: 1; /* running status */

unsigned int hwptr_done; /* processed frame position in the buffer */
unsigned int hwptr_done; /* processed byte position in the buffer */
unsigned int transfer_done; /* processed frames since last period update */
unsigned long active_mask; /* bitmask of active urbs */
unsigned long unlink_mask; /* bitmask of unlinked urbs */
Expand Down Expand Up @@ -342,7 +342,7 @@ static int retire_capture_urb(struct snd_usb_substream *subs,
unsigned long flags;
unsigned char *cp;
int i;
unsigned int stride, len, oldptr;
unsigned int stride, frames, bytes, oldptr;
int period_elapsed = 0;

stride = runtime->frame_bits >> 3;
Expand All @@ -353,29 +353,28 @@ static int retire_capture_urb(struct snd_usb_substream *subs,
snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
// continue;
}
len = urb->iso_frame_desc[i].actual_length / stride;
if (! len)
continue;
frames = urb->iso_frame_desc[i].actual_length / stride;
bytes = frames * stride;
/* update the current pointer */
spin_lock_irqsave(&subs->lock, flags);
oldptr = subs->hwptr_done;
subs->hwptr_done += len;
if (subs->hwptr_done >= runtime->buffer_size)
subs->hwptr_done -= runtime->buffer_size;
subs->transfer_done += len;
subs->hwptr_done += bytes;
if (subs->hwptr_done >= runtime->buffer_size * stride)
subs->hwptr_done -= runtime->buffer_size * stride;
subs->transfer_done += frames;
if (subs->transfer_done >= runtime->period_size) {
subs->transfer_done -= runtime->period_size;
period_elapsed = 1;
}
spin_unlock_irqrestore(&subs->lock, flags);
/* copy a data chunk */
if (oldptr + len > runtime->buffer_size) {
unsigned int cnt = runtime->buffer_size - oldptr;
unsigned int blen = cnt * stride;
memcpy(runtime->dma_area + oldptr * stride, cp, blen);
memcpy(runtime->dma_area, cp + blen, len * stride - blen);
if (oldptr + bytes > runtime->buffer_size * stride) {
unsigned int bytes1 =
runtime->buffer_size * stride - oldptr;
memcpy(runtime->dma_area + oldptr, cp, bytes1);
memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
} else {
memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
memcpy(runtime->dma_area + oldptr, cp, bytes);
}
}
if (period_elapsed)
Expand Down Expand Up @@ -562,24 +561,24 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
struct snd_pcm_runtime *runtime,
struct urb *urb)
{
int i, stride, offs;
unsigned int counts;
int i, stride;
unsigned int counts, frames, bytes;
unsigned long flags;
int period_elapsed = 0;
struct snd_urb_ctx *ctx = urb->context;

stride = runtime->frame_bits >> 3;

offs = 0;
frames = 0;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
for (i = 0; i < ctx->packets; i++) {
counts = snd_usb_audio_next_packet_size(subs);
/* set up descriptor */
urb->iso_frame_desc[i].offset = offs * stride;
urb->iso_frame_desc[i].offset = frames * stride;
urb->iso_frame_desc[i].length = counts * stride;
offs += counts;
frames += counts;
urb->number_of_packets++;
subs->transfer_done += counts;
if (subs->transfer_done >= runtime->period_size) {
Expand All @@ -589,7 +588,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
if (subs->transfer_done > 0) {
/* FIXME: fill-max mode is not
* supported yet */
offs -= subs->transfer_done;
frames -= subs->transfer_done;
counts -= subs->transfer_done;
urb->iso_frame_desc[i].length =
counts * stride;
Expand All @@ -599,7 +598,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
if (i < ctx->packets) {
/* add a transfer delimiter */
urb->iso_frame_desc[i].offset =
offs * stride;
frames * stride;
urb->iso_frame_desc[i].length = 0;
urb->number_of_packets++;
}
Expand All @@ -609,26 +608,25 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
if (period_elapsed) /* finish at the period boundary */
break;
}
if (subs->hwptr_done + offs > runtime->buffer_size) {
bytes = frames * stride;
if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
/* err, the transferred area goes over buffer boundary. */
unsigned int len = runtime->buffer_size - subs->hwptr_done;
unsigned int bytes1 =
runtime->buffer_size * stride - subs->hwptr_done;
memcpy(urb->transfer_buffer,
runtime->dma_area + subs->hwptr_done * stride,
len * stride);
memcpy(urb->transfer_buffer + len * stride,
runtime->dma_area,
(offs - len) * stride);
runtime->dma_area + subs->hwptr_done, bytes1);
memcpy(urb->transfer_buffer + bytes1,
runtime->dma_area, bytes - bytes1);
} else {
memcpy(urb->transfer_buffer,
runtime->dma_area + subs->hwptr_done * stride,
offs * stride);
runtime->dma_area + subs->hwptr_done, bytes);
}
subs->hwptr_done += offs;
if (subs->hwptr_done >= runtime->buffer_size)
subs->hwptr_done -= runtime->buffer_size;
runtime->delay += offs;
subs->hwptr_done += bytes;
if (subs->hwptr_done >= runtime->buffer_size * stride)
subs->hwptr_done -= runtime->buffer_size * stride;
runtime->delay += frames;
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = offs * stride;
urb->transfer_buffer_length = bytes;
if (period_elapsed)
snd_pcm_period_elapsed(subs->pcm_substream);
return 0;
Expand Down Expand Up @@ -901,18 +899,18 @@ static int wait_clear_urbs(struct snd_usb_substream *subs)


/*
* return the current pcm pointer. just return the hwptr_done value.
* return the current pcm pointer. just based on the hwptr_done value.
*/
static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_usb_substream *subs;
snd_pcm_uframes_t hwptr_done;
unsigned int hwptr_done;

subs = (struct snd_usb_substream *)substream->runtime->private_data;
spin_lock(&subs->lock);
hwptr_done = subs->hwptr_done;
spin_unlock(&subs->lock);
return hwptr_done;
return hwptr_done / (substream->runtime->frame_bits >> 3);
}


Expand Down

0 comments on commit 0115a97

Please sign in to comment.