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.