Re: [PATCH 2/8] usb: gadget: f_uac2/u_audio: add feedback endpoint support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dne 01. 03. 21 v 14:05 Ruslan Bilovol napsal(a):
> +static void u_audio_set_fback_frequency(enum usb_device_speed speed,
> +					unsigned int freq, void *buf)
> +{
> +	u32 ff = 0;
> +
> +	if (speed == USB_SPEED_FULL) {
> +		/*
> +		 * Full-speed feedback endpoints report frequency
> +		 * in samples/microframe
> +		 * Format is encoded in Q10.10 left-justified in the 24 bits,
> +		 * so that it has a Q10.14 format.
> +		 */
> +		ff = DIV_ROUND_UP((freq << 14), 1000);
> +	} else {
> +		/*
> +		 * High-speed feedback endpoints report frequency
> +		 * in samples/microframe.
> +		 * Format is encoded in Q12.13 fitted into four bytes so that
> +		 * the binary point is located between the second and the third
> +		 * byte format (that is Q16.16)
> +		 *
> +		 * Prevent integer overflow by calculating in Q12.13 format and
> +		 * then shifting to Q16.16
> +		 */
> +		ff = DIV_ROUND_UP((freq << 13), (8*1000)) << 3;
> +	}

Hi Ruslan,

Thanks a lot for your patch. The HS calculation of Q16.16 feedback value
overflows at some 524kHz, disallowing use of larger samplerates (e.g.
768kHz or higher).

I tested the formula used in alsa USB driver
https://github.com/torvalds/linux/blob/d99676af540c2dc829999928fb81c58c80a1dce4/sound/usb/endpoint.c#L80
which uses only 10bit shift. The feedback control in UAC2 gadget now
works up to 4M samplerate with 1Hz precision (tested on RPi4 with
bInterval = 1, checked in stream0 proc file on linux host).

--- a/drivers/usb/gadget/function/u_audio.c
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -118,7 +119,8 @@ static void u_audio_set_fback_frequency(enum
usb_device_speed speed,
                 * Prevent integer overflow by calculating in Q12.13
format and
                 * then shifting to Q16.16
                 */
-               ff = DIV_ROUND_UP((freq << 13), (8*1000)) << 3;
+               //ff = DIV_ROUND_UP((freq << 13), (8*1000)) << 3;
+               ff = ((freq << 10) + 62) / 125;
        }
        *(__le32 *)buf = cpu_to_le32(ff);
 }


Best regards,

Pavel.







[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux