USB Audio Gadget on Radxa Zero

I spent a couple of evenings getting g_audio to work on a Radxa Zero 1.5 running Armbian 22.11.1 Jammy, Linux 6.0.10-meson64. Leaving this here to help others out. Magic point to make it work is bullet number three.

  1. Add g_audio to /etc/modules to auto-load when booting. You may also need to add dwc2 and roles (see below). On this specific kernel they were already built-in.

  2. Create /etc/modprobe.d/g_audio.conf with something like the following:
    options g_audio c_srate=44100 c_ssize=4 c_chmask=3 p_chmask=0

Late 5.x kernels and beyond support setting multiple capture sample rates like c_srate=44100,48000,88200,96000. This works fine up until 96 kHz when playing from a Linux host, but not beyond: playback would silently fail (literally). On an iOS host with a Lightning-to-USB adapter, you must set a single sample rate, because the adapter will otherwise reset to select other rates, causing the Zero to go into an endless rebooting loop.

c_chmask is a bitmask, so 3 means stereo (channel 1 and 2).

c_ssize is the sample size in bytes; so 2 for 16-bit (S16_LE) and 4 for 32-bit little endian (S32_LE). 3 is for 24-bit audio (S24_3LE), but that only gave me garbled audio.

p_chmask=0 stops announcing it as a player, which conveniently removes it from aplay -l lists on the player host.

  1. By default USB role of the Radxa Zero is set to host. As a result, the Radxa won’t show up as a playback device when connected on its OTG port. To change this to device, I added the following to rc.local:

echo device > /sys/class/usb_role/ffe09000.usb-role-switch/role

Hope this helps!

I noticed stuttering audio after some minutes of use. Changing the CPU frequency governor from ondemand to performance or even schedutil seems to fix that.