From: "Ismaïl Bahloul" <i.bahloul01@gmail.com>
To: linux-sound@vger.kernel.org
Cc: linux-usb@vger.kernel.org, alsa-devel@alsa-project.org,
perex@perex.cz, tiwai@suse.com, linux-kernel@vger.kernel.org
Subject: [RFC PATCH v4 0/3] ALSA: usb: add RME Babyface Pro driver (proprietary mode)
Date: Mon, 14 Sep 2026 18:23:31 +0100 [thread overview]
Message-ID: <20260914172334.49074-1-i.bahloul01@gmail.com> (raw)
Hi,
This is v4 of the RFC for a driver for the RME Babyface Pro in its
proprietary USB mode (VID 0x2a39, PID 0x3fc0). In that mode the PCM
stream runs on interrupt endpoints instead of the class-compliant
isochronous path, so it cannot be a quirk on top of snd-usb-audio and
needs a standalone driver, modelled on snd-usb-caiaq.
Changes since v3:
- A real bug in the crosspoint routing matrix, found while trying to
hardware-verify the dB TLV metadata added to the crosspoint faders
(below): the AN1/2 output's own crosspoint fader had no audible
effect on the signal, for every source, for as long as the matrix
has existed - a generated tone swept from off through +6 dB
produced no change at all, while the identical control targeting
any other output tracked the fader correctly. The vendor software's
own capture shows why: for this one output it always writes a
second register (the "low map") alongside the usual crosspoint
address, at the same value; the driver wrote only the usual
address. Three call sites (the live control, the probe-time
default, and the reconnect/resume replay) needed the same fix,
folded into one exported helper. Verified fixed with the same
tone-sweep method that found it, and that a real crosspoint value
survives an actual unbind/rebind, both the cached control and the
audible level.
- Two real bugs found, diagnosed and fixed by David Fredman, who also
became this driver's second tester, on an original (2015, non-FS)
Babyface Pro:
* The stream URBs were submitted without URB_NO_TRANSFER_DMA_MAP
even though their buffers come from usb_alloc_coherent(), so the
USB core tried to map them a second time and failed with -EAGAIN
on any IOMMU-translated host. That is the default on current AMD
and Intel desktops, which means v3 as posted would not have
streamed at all on most machines. Every other sound/usb driver
that allocates coherent buffers sets this flag; this one was the
exception.
* The mic preamp gain register was decoded as a 5-bit value plus a
rotating transaction counter. Bits 5-7 are in fact the fine part
of the gain: value = (fine << 5) | coarse, coarse 3 dB per step
saturating at 20, fine the 0-2 dB remainder. The control was
therefore reaching 21 of its 66 positions, and because the
rotating value landed in those same bits, the gain actually
applied depended on where the rotation stood - the same requested
setting did not give a repeatable gain. Measured on hardware
before and after: 0.808 dB per dB of control, against 1.000 after
the fix.
- The power-on masters no longer come up at unity, and the -20 dB
safety default is scoped to the two analog outputs only. The
routing default sends all 14 sources into every output at unity,
and they sum, on every fresh module load before alsa-restore can
restore the user's levels; AN1/2 and PH3/4 now come up at -20 dB,
the level the hardware's own DIM button writes. The four digital
outputs (AS1/2, ADAT3/4, ADAT5/6, ADAT7/8) keep the vendor
software's own 0 dB default instead, since nothing downstream of a
digital feed can be damaged by a loud signal the way a speaker or a
pair of headphones can - David Fredman flagged that the original
six-output default reached those too, for no reason a receiving
digital device could infer.
- The driver is no longer FS-specific. It runs unmodified on an
original (2015) Babyface Pro; the two models share VID:PID,
bcdDevice and iProduct shape, and nothing in the descriptors tells
them apart. card->driver, the card id, the shortname and the
Kconfig text are model-neutral accordingly. This seemed worth
getting right before the strings are frozen by a release, since
card->driver is what alsa-lib configs and UCM profiles match on.
- The front-panel DIM button acts now instead of only being decoded.
SET already toggled phantom from the same poll. Its scope (Phones
only) matches the one vendor capture we have of it; whether that is
the only possible target or just the default "Main Out" assignment
is an open protocol question, noted rather than guessed at.
- Added dB TLV information to the preamp gain, trim and crosspoint
controls; only the output masters had any before. Hardware-
verifying the crosspoint curve is what surfaced the routing bug
above.
- Fixed a state-restore bug in the input trim: it is one shared
register per input pair but two per-channel controls, and the
restore replayed the pair from its even index, so a trim set on the
odd channel was silently dropped on re-probe.
- Split into three patches rather than the four of v3. The v3 split
put the mixer in its own patch, which meant earlier patches carried
stub control functions that later patches replaced. The mixer and
the core share the device state structure and the whole
save/restore path, so that seam was artificial. The front panel
and the DSP EQ are genuinely separable: each of the three patches
here contains only final code, nothing a later patch rewrites, and
each builds in-tree on its own.
Known limitations, stated up front:
- USB autosuspend is not supported. It is explicitly disabled at
probe rather than left as an untested path: the panel poll and
keepalive work items run continuously and nothing pairs
usb_autopm_get/put around the stream. S3 suspend/resume works and
is tested.
- A few protocol details are not fully pinned down and are documented
as open: the preamp readback index semantics, a width
strip-ownership edge case, whether DIM's scope is reassignable with
TotalMix's Main Out setting, and the exact high-frequency warping
of the EQ coefficients against the vendor curve. None of them
affect the shipped controls.
- The latency profile is chosen at load time through the
frames_per_urb and nurbs module parameters; changing it means a
module reload. Runtime reconfiguration is a follow-up.
Validation: a full-duplex sweep across the whole rate x period matrix
with a signal-integrity tap, 30 start/stop cycles, mixer-state restore
across an interface unbind/rebind, and a mid-stream disconnect - 40 of
40 on the current tree. Each patch was also built in-tree on its own
against next-20260911.
I am still mainly after feedback on the interrupt-URB PCM design, the
control naming and topology, and the subdirectory layout.
Disclosure: the reverse-engineering (decoding the USB captures, the
magic packets and the front-panel behaviour) and substantial portions
of the kernel implementation were written with heavy assistance from
AI coding assistants, credited per patch as Assisted-by. All of it
was verified by hand on real hardware; the human authors remain
responsible for the result via Signed-off-by.
Thanks for reading,
Ismaïl
Ismaïl Bahloul (3):
ALSA: usb: add RME Babyface Pro driver (proprietary mode)
ALSA: usb: babyfacepro: add the front-panel poll and controls
ALSA: usb: babyfacepro: add the hardware DSP EQ
MAINTAINERS | 6 +
sound/usb/Kconfig | 20 +
sound/usb/Makefile | 2 +-
sound/usb/babyfacepro/Makefile | 4 +
sound/usb/babyfacepro/babyfacepro-ctl.c | 3494 +++++++++++++++++++++++
sound/usb/babyfacepro/babyfacepro.c | 1593 +++++++++++
sound/usb/babyfacepro/babyfacepro.h | 494 ++++
7 files changed, 5612 insertions(+), 1 deletion(-)
create mode 100644 sound/usb/babyfacepro/Makefile
create mode 100644 sound/usb/babyfacepro/babyfacepro-ctl.c
create mode 100644 sound/usb/babyfacepro/babyfacepro.c
create mode 100644 sound/usb/babyfacepro/babyfacepro.h
--
2.55.0
next reply other threads:[~2026-09-14 17:23 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-14 17:23 Ismaïl Bahloul [this message]
2026-09-14 17:23 ` [RFC PATCH v4 1/3] " Ismaïl Bahloul
2026-09-14 17:23 ` [RFC PATCH v4 2/3] ALSA: usb: babyfacepro: add the front-panel poll and controls Ismaïl Bahloul
2026-09-14 17:23 ` [RFC PATCH v4 3/3] ALSA: usb: babyfacepro: add the hardware DSP EQ Ismaïl Bahloul
2026-09-16 13:38 ` [RFC PATCH v4 0/3] ALSA: usb: add RME Babyface Pro driver (proprietary mode) Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260914172334.49074-1-i.bahloul01@gmail.com \
--to=i.bahloul01@gmail.com \
--cc=alsa-devel@alsa-project.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=perex@perex.cz \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®