[alsa-devel] Buffer size for ALSA USB PCM audio

Clemens Ladisch clemens at ladisch.de
Tue Aug 13 23:54:39 CEST 2013


Alan Stern wrote:
> On Mon, 12 Aug 2013, Takashi Iwai wrote:
>> So... Clemens, Daniel, Eldad, could you guys review the latest version
>> of Alan's patch?  I'd love to sort this out for 3.12.
>
> Here's a revised version of the patch (still untested).

> -	maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
> -				>> (16 - ep->datainterval);
> +	maxsize = ((ep->freqmax + 0xffff) >> (16 - ep->datainterval))
> +			* (frame_bits >> 3);

What do you assume prevents firmware writers from splitting frames
across packages?  The specification?  Sanity?  :)  (see txfr_quirk)

> The difference is that this version tries always to keep a period's
> worth of bytes in the USB hardware queue.

Having truncated URBs is possible only when URBs are shorter than one
period, so I think that a queue length of at least two periods, together
with a minimum period size, should ensure the isochrounous scheduling
threshold.

This isn't tested either.


Regards,
Clemens


 sound/usb/endpoint.c |    3 ++-
 sound/usb/pcm.c      |   16 ++++++++++++++--
 2 files changed, 16 insertions(+), 3 deletions(-)

--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -638,7 +638,8 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 		if (sync_ep)
 			minsize -= minsize >> 3;
 		minsize = max(minsize, 1u);
-		total_packs = (period_bytes + minsize - 1) / minsize;
+		/* try to make the queue length the same as two periods */
+		total_packs = (2 * period_bytes + minsize - 1) / minsize;
 		/* we need at least two URBs for queueing */
 		if (total_packs < 2) {
 			total_packs = 2;
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1131,10 +1131,22 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 		return err;

 	param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
-	if (subs->speed == USB_SPEED_FULL)
+	switch (subs->speed) {
+	case USB_SPEED_FULL:
 		/* full speed devices have fixed data packet interval */
 		ptmin = 1000;
-	if (ptmin == 1000)
+		break;
+	case USB_SPEED_HIGH:
+		/*
+		 * Assume we have an EHCI controller with an Isochronous
+		 * Scheduling Threshold of one frame (8 microframes), and
+		 * add 2 microframes for boundary cases.  Increase by 4%
+		 * to have a margin for clock inaccuracies.
+		 */
+		ptmin = max(ptmin, (8 + 2) * 130u);
+		break;
+	}
+	if (ptmin >= 1000)
 		/* if period time doesn't go below 1 ms, no rules needed */
 		param_period_time_if_needed = -1;
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,


More information about the Alsa-devel mailing list