[PATCH 2/5] ALSA: usb-audio: Pre-calculate buffer byte size

Takashi Iwai tiwai at suse.de
Tue Jun 1 18:24:54 CEST 2021


There are a bunch of lines calculating the buffer size in bytes at
each time.  Keep the value in subs->buffer_bytes and use it
consistently for the code simplicity.

Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 sound/usb/card.h |  1 +
 sound/usb/pcm.c  | 48 ++++++++++++++++++++++++------------------------
 2 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index a741e7da83a2..b346653d4b76 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -158,6 +158,7 @@ struct snd_usb_substream {
 
 	unsigned int running: 1;	/* running status */
 
+	unsigned int buffer_bytes;	/* buffer size in bytes */
 	unsigned int hwptr_done;	/* processed byte position in the buffer */
 	unsigned int transfer_done;		/* processed frames since last period update */
 	unsigned int frame_limit;	/* limits number of packets in URB */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 359c759a7023..e8121af8e1d5 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -600,6 +600,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 		goto unlock;
 
 	/* reset the pointer */
+	subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
 	subs->hwptr_done = 0;
 	subs->transfer_done = 0;
 	subs->last_delay = 0;
@@ -1147,8 +1148,8 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
 		spin_lock_irqsave(&subs->lock, flags);
 		oldptr = subs->hwptr_done;
 		subs->hwptr_done += bytes;
-		if (subs->hwptr_done >= runtime->buffer_size * stride)
-			subs->hwptr_done -= runtime->buffer_size * stride;
+		if (subs->hwptr_done >= subs->buffer_bytes)
+			subs->hwptr_done -= subs->buffer_bytes;
 		frames = (bytes + (oldptr % stride)) / stride;
 		subs->transfer_done += frames;
 		if (subs->transfer_done >= runtime->period_size) {
@@ -1166,9 +1167,9 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
 
 		spin_unlock_irqrestore(&subs->lock, flags);
 		/* copy a data chunk */
-		if (oldptr + bytes > runtime->buffer_size * stride) {
-			unsigned int bytes1 =
-					runtime->buffer_size * stride - oldptr;
+		if (oldptr + bytes > subs->buffer_bytes) {
+			unsigned int bytes1 = subs->buffer_bytes - oldptr;
+
 			memcpy(runtime->dma_area + oldptr, cp, bytes1);
 			memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
 		} else {
@@ -1184,10 +1185,9 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs,
 					     struct urb *urb, unsigned int bytes)
 {
 	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
-	unsigned int stride = runtime->frame_bits >> 3;
 	unsigned int dst_idx = 0;
 	unsigned int src_idx = subs->hwptr_done;
-	unsigned int wrap = runtime->buffer_size * stride;
+	unsigned int wrap = subs->buffer_bytes;
 	u8 *dst = urb->transfer_buffer;
 	u8 *src = runtime->dma_area;
 	u8 marker[] = { 0x05, 0xfa };
@@ -1233,8 +1233,8 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs,
 			subs->hwptr_done++;
 		}
 	}
-	if (subs->hwptr_done >= runtime->buffer_size * stride)
-		subs->hwptr_done -= runtime->buffer_size * stride;
+	if (subs->hwptr_done >= subs->buffer_bytes)
+		subs->hwptr_done -= subs->buffer_bytes;
 }
 
 static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb,
@@ -1242,10 +1242,10 @@ static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb,
 {
 	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
 
-	if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
+	if (subs->hwptr_done + bytes > subs->buffer_bytes) {
 		/* err, the transferred area goes over buffer boundary. */
-		unsigned int bytes1 =
-			runtime->buffer_size * stride - subs->hwptr_done;
+		unsigned int bytes1 = subs->buffer_bytes - subs->hwptr_done;
+
 		memcpy(urb->transfer_buffer + offset,
 		       runtime->dma_area + subs->hwptr_done, bytes1);
 		memcpy(urb->transfer_buffer + offset + bytes1,
@@ -1255,8 +1255,8 @@ static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb,
 		       runtime->dma_area + subs->hwptr_done, bytes);
 	}
 	subs->hwptr_done += bytes;
-	if (subs->hwptr_done >= runtime->buffer_size * stride)
-		subs->hwptr_done -= runtime->buffer_size * stride;
+	if (subs->hwptr_done >= subs->buffer_bytes)
+		subs->hwptr_done -= subs->buffer_bytes;
 }
 
 static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs,
@@ -1295,7 +1295,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 	int i, stride, period_elapsed = 0;
 	unsigned long flags;
 
-	stride = runtime->frame_bits >> 3;
+	stride = ep->stride;
 
 	frames = 0;
 	urb->number_of_packets = 0;
@@ -1304,8 +1304,8 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 	for (i = 0; i < ctx->packets; i++) {
 		counts = snd_usb_endpoint_next_packet_size(ep, ctx, i);
 		/* set up descriptor */
-		urb->iso_frame_desc[i].offset = frames * ep->stride;
-		urb->iso_frame_desc[i].length = counts * ep->stride;
+		urb->iso_frame_desc[i].offset = frames * stride;
+		urb->iso_frame_desc[i].length = counts * stride;
 		frames += counts;
 		urb->number_of_packets++;
 		subs->transfer_done += counts;
@@ -1320,14 +1320,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 					frames -= subs->transfer_done;
 					counts -= subs->transfer_done;
 					urb->iso_frame_desc[i].length =
-						counts * ep->stride;
+						counts * stride;
 					subs->transfer_done = 0;
 				}
 				i++;
 				if (i < ctx->packets) {
 					/* add a transfer delimiter */
 					urb->iso_frame_desc[i].offset =
-						frames * ep->stride;
+						frames * stride;
 					urb->iso_frame_desc[i].length = 0;
 					urb->number_of_packets++;
 				}
@@ -1340,7 +1340,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 		    !snd_usb_endpoint_implicit_feedback_sink(ep))
 			break;
 	}
-	bytes = frames * ep->stride;
+	bytes = frames * stride;
 
 	if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
 		     subs->cur_audiofmt->dsd_dop)) {
@@ -1350,14 +1350,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 		/* bit-reverse the bytes */
 		u8 *buf = urb->transfer_buffer;
 		for (i = 0; i < bytes; i++) {
-			int idx = (subs->hwptr_done + i)
-				% (runtime->buffer_size * stride);
+			int idx = (subs->hwptr_done + i) % subs->buffer_bytes;
+
 			buf[i] = bitrev8(runtime->dma_area[idx]);
 		}
 
 		subs->hwptr_done += bytes;
-		if (subs->hwptr_done >= runtime->buffer_size * stride)
-			subs->hwptr_done -= runtime->buffer_size * stride;
+		if (subs->hwptr_done >= subs->buffer_bytes)
+			subs->hwptr_done -= subs->buffer_bytes;
 	} else {
 		/* usual PCM */
 		if (!subs->tx_length_quirk)
-- 
2.26.2



More information about the Alsa-devel mailing list