From 9624ea812c7afd2e403c56366cadddb9ecfb88c6 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Mon, 15 Aug 2005 08:25:24 +0200
Subject: [PATCH] [ALSA] usb-audio: actually schedule playback URBs at frame
 boundaries

USB generic driver
Change prepare_playback_urb() not to stop preparing packets before a
frame boundary has been reached.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
 sound/usb/usbaudio.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 2b4f916a0a9a..3f7930c0b616 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -164,6 +164,7 @@ struct snd_usb_substream {
 	unsigned int curframesize;	/* current packet size in frames (for capture) */
 	unsigned int fill_max: 1;	/* fill max packet size always */
 	unsigned int fmt_type;		/* USB audio format type (1-3) */
+	unsigned int packs_per_ms;	/* packets per millisecond (for playback) */
 
 	unsigned int running: 1;	/* running status */
 
@@ -537,9 +538,13 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
 					urb->iso_frame_desc[i].length = 0;
 					urb->number_of_packets++;
 				}
+				break;
 			}
-			break;
  		}
+		/* finish at the frame boundary at/after the period boundary */
+		if (period_elapsed &&
+		    (i & (subs->packs_per_ms - 1)) == subs->packs_per_ms - 1)
+			break;
 	}
 	if (subs->hwptr_done + offs > runtime->buffer_size) {
 		/* err, the transferred area goes over buffer boundary. */
@@ -907,6 +912,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
 		packs_per_ms = 8 >> subs->datainterval;
 	else
 		packs_per_ms = 1;
+	subs->packs_per_ms = packs_per_ms;
 
 	if (is_playback) {
 		urb_packs = nrpacks;