int counts;
unsigned int transfer_done, frame_limit, avail = 0;
int i, stride, period_elapsed = 0;
- unsigned long flags;
- int err = 0;
stride = ep->stride;
ctx->queued = 0;
urb->number_of_packets = 0;
- spin_lock_irqsave(&subs->lock, flags);
- frame_limit = subs->frame_limit + ep->max_urb_frames;
- transfer_done = subs->transfer_done;
+ scoped_guard(spinlock_irqsave, &subs->lock) {
+ frame_limit = subs->frame_limit + ep->max_urb_frames;
+ transfer_done = subs->transfer_done;
- if (subs->lowlatency_playback &&
- runtime->state != SNDRV_PCM_STATE_DRAINING) {
- unsigned int hwptr = subs->hwptr_done / stride;
-
- /* calculate the byte offset-in-buffer of the appl_ptr */
- avail = (runtime->control->appl_ptr - runtime->hw_ptr_base)
- % runtime->buffer_size;
- if (avail <= hwptr)
- avail += runtime->buffer_size;
- avail -= hwptr;
- }
+ if (subs->lowlatency_playback &&
+ runtime->state != SNDRV_PCM_STATE_DRAINING) {
+ unsigned int hwptr = subs->hwptr_done / stride;
+
+ /* calculate the byte offset-in-buffer of the appl_ptr */
+ avail = (runtime->control->appl_ptr - runtime->hw_ptr_base)
+ % runtime->buffer_size;
+ if (avail <= hwptr)
+ avail += runtime->buffer_size;
+ avail -= hwptr;
+ }
- for (i = 0; i < ctx->packets; i++) {
- counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, avail);
- if (counts < 0)
- break;
- /* set up descriptor */
- urb->iso_frame_desc[i].offset = frames * stride;
- urb->iso_frame_desc[i].length = counts * stride;
- frames += counts;
- avail -= counts;
- urb->number_of_packets++;
- transfer_done += counts;
- if (transfer_done >= runtime->period_size) {
- transfer_done -= runtime->period_size;
- frame_limit = 0;
- period_elapsed = 1;
- if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
- if (transfer_done > 0) {
- /* FIXME: fill-max mode is not
- * supported yet */
- frames -= transfer_done;
- counts -= transfer_done;
- urb->iso_frame_desc[i].length =
- counts * stride;
- transfer_done = 0;
- }
- i++;
- if (i < ctx->packets) {
- /* add a transfer delimiter */
- urb->iso_frame_desc[i].offset =
- frames * stride;
- urb->iso_frame_desc[i].length = 0;
- urb->number_of_packets++;
- }
+ for (i = 0; i < ctx->packets; i++) {
+ counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, avail);
+ if (counts < 0)
break;
+ /* set up descriptor */
+ urb->iso_frame_desc[i].offset = frames * stride;
+ urb->iso_frame_desc[i].length = counts * stride;
+ frames += counts;
+ avail -= counts;
+ urb->number_of_packets++;
+ transfer_done += counts;
+ if (transfer_done >= runtime->period_size) {
+ transfer_done -= runtime->period_size;
+ frame_limit = 0;
+ period_elapsed = 1;
+ if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
+ if (transfer_done > 0) {
+ /* FIXME: fill-max mode is not
+ * supported yet */
+ frames -= transfer_done;
+ counts -= transfer_done;
+ urb->iso_frame_desc[i].length =
+ counts * stride;
+ transfer_done = 0;
+ }
+ i++;
+ if (i < ctx->packets) {
+ /* add a transfer delimiter */
+ urb->iso_frame_desc[i].offset =
+ frames * stride;
+ urb->iso_frame_desc[i].length = 0;
+ urb->number_of_packets++;
+ }
+ break;
+ }
}
+ /* finish at the period boundary or after enough frames */
+ if ((period_elapsed || transfer_done >= frame_limit) &&
+ !snd_usb_endpoint_implicit_feedback_sink(ep))
+ break;
}
- /* finish at the period boundary or after enough frames */
- if ((period_elapsed || transfer_done >= frame_limit) &&
- !snd_usb_endpoint_implicit_feedback_sink(ep))
- break;
- }
- if (!frames) {
- err = -EAGAIN;
- goto unlock;
- }
-
- bytes = frames * stride;
- subs->transfer_done = transfer_done;
- subs->frame_limit = frame_limit;
- if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
- subs->cur_audiofmt->dsd_dop)) {
- fill_playback_urb_dsd_dop(subs, urb, bytes);
- } else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 &&
- subs->cur_audiofmt->dsd_bitrev)) {
- fill_playback_urb_dsd_bitrev(subs, urb, bytes);
- } else {
- /* usual PCM */
- if (!subs->tx_length_quirk)
- copy_to_urb(subs, urb, 0, stride, bytes);
- else
- bytes = copy_to_urb_quirk(subs, urb, stride, bytes);
+ if (!frames)
+ return -EAGAIN;
+
+ bytes = frames * stride;
+ subs->transfer_done = transfer_done;
+ subs->frame_limit = frame_limit;
+ if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
+ subs->cur_audiofmt->dsd_dop)) {
+ fill_playback_urb_dsd_dop(subs, urb, bytes);
+ } else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 &&
+ subs->cur_audiofmt->dsd_bitrev)) {
+ fill_playback_urb_dsd_bitrev(subs, urb, bytes);
+ } else {
+ /* usual PCM */
+ if (!subs->tx_length_quirk)
+ copy_to_urb(subs, urb, 0, stride, bytes);
+ else
+ bytes = copy_to_urb_quirk(subs, urb, stride, bytes);
/* bytes is now amount of outgoing data */
- }
+ }
- subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+ subs->last_frame_number = usb_get_current_frame_number(subs->dev);
- if (subs->trigger_tstamp_pending_update) {
- /* this is the first actual URB submitted,
- * update trigger timestamp to reflect actual start time
- */
- snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
- subs->trigger_tstamp_pending_update = false;
- }
+ if (subs->trigger_tstamp_pending_update) {
+ /* this is the first actual URB submitted,
+ * update trigger timestamp to reflect actual start time
+ */
+ snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
+ subs->trigger_tstamp_pending_update = false;
+ }
- if (period_elapsed && !subs->running && subs->lowlatency_playback) {
- subs->period_elapsed_pending = 1;
- period_elapsed = 0;
+ if (period_elapsed && !subs->running && subs->lowlatency_playback) {
+ subs->period_elapsed_pending = 1;
+ period_elapsed = 0;
+ }
}
- unlock:
- spin_unlock_irqrestore(&subs->lock, flags);
- if (err < 0)
- return err;
urb->transfer_buffer_length = bytes;
if (period_elapsed) {
if (in_stream_lock)
static void retire_playback_urb(struct snd_usb_substream *subs,
struct urb *urb)
{
- unsigned long flags;
struct snd_urb_ctx *ctx = urb->context;
bool period_elapsed = false;
- spin_lock_irqsave(&subs->lock, flags);
- if (ctx->queued) {
- if (subs->inflight_bytes >= ctx->queued)
- subs->inflight_bytes -= ctx->queued;
- else
- subs->inflight_bytes = 0;
- }
+ scoped_guard(spinlock_irqsave, &subs->lock) {
+ if (ctx->queued) {
+ if (subs->inflight_bytes >= ctx->queued)
+ subs->inflight_bytes -= ctx->queued;
+ else
+ subs->inflight_bytes = 0;
+ }
- subs->last_frame_number = usb_get_current_frame_number(subs->dev);
- if (subs->running) {
- period_elapsed = subs->period_elapsed_pending;
- subs->period_elapsed_pending = 0;
+ subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+ if (subs->running) {
+ period_elapsed = subs->period_elapsed_pending;
+ subs->period_elapsed_pending = 0;
+ }
}
- spin_unlock_irqrestore(&subs->lock, flags);
if (period_elapsed)
snd_pcm_period_elapsed(subs->pcm_substream);
}