From: "Ismaïl Bahloul" <i.bahloul01@gmail.com>
To: linux-sound@vger.kernel.org
Cc: tiwai@suse.com, perex@perex.cz, linux-usb@vger.kernel.org,
alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org,
corbet@lwn.net, skhan@linuxfoundation.org, rdunlap@infradead.org,
linux-doc@vger.kernel.org,
"Ismaïl Bahloul" <i.bahloul01@gmail.com>
Subject: [PATCH v8 0/8] ALSA: usb: add RME Babyface Pro driver (proprietary mode)
Date: Thu, 5 Nov 2026 16:15:45 +0100 [thread overview]
Message-ID: <20261105151553.223722-1-i.bahloul01@gmail.com> (raw)
Hi Takashi,
This is v8 of the RME Babyface Pro proprietary-mode driver. The split
is unchanged from v5: a minimal core first, the mixer added piece by
piece, suspend/resume near the end, the front panel and the DSP EQ
last, and a design document. The series is still based on
next-20261026, so this is a fix round, not a rebase. It answers your
reply to v7: your three points are the first item below, and what I
did with the Sashiko findings is the second.
This is not an RFC. Apart from the stereo split one, which a user
reported from USB captures of the vendor software, every point below
is a fix to a defect found in review of v7, or a change you asked for.
None of them changes the protocol or the control layout.
Changes since v7:
- Your comments on v7. The mutexes, the spinlocks, the RCU read
sides and the PCM stream locks use guard(), scoped_guard() and
guard(rcu) in place of paired lock and unlock calls with goto
labels, so the driver has no manual lock handling left. Each
critical section covers the same code as before, and the places that
used to jump to an unlock label now return. The per-channel loops
in babyface_capture_copy() and babyface_playback_copy() are one
memcpy() of the words the frame and the stream have in common, and a
memset() of the rest: the words are S32_LE with 24 msbits on both
sides, so they go over as they are. bf_seen_before() keeps the last
eight units it saw in a fixed table (patch 6) instead of a list that
grew with every unit; a unit pushed out by eight newer ones is taken
for a first probe again.
- Sashiko. I went through its findings on v7 again. The ones that
hold are fixed in the items below. Two I left alone: the control
names, which stay as they are (see patch 3), and the module
parameters it wants in kernel-parameters.txt, which documents the
kernel's own; the driver's are in the Kconfig help and in patch 8.
- Probe and stream (patch 1). probe() returned 0 after freeing the
card when an URB or DMA buffer allocation failed; it now returns
-ENOMEM. Trigger START re-checks the rate and period that prepare()
checks, so a substream prepared before the other direction changed
the session cannot start against stale geometry. in_done and
out_inflight are initialised before the URBs go out, and a URB that
cannot be resubmitted is treated as fatal instead of waiting for a
run of errors that a later good completion would clear.
- Output masters (patch 2). Every snd_ctl_new1() result is checked
before the name is written. The output pair switch is a mono
switch, which is what the hardware does; it used to advertise two
channels and ignore the second.
- Preamp and trim (patch 3). The same NULL checks in the trim
controls, with trim_kctl stored only after snd_ctl_add() succeeds
(it could be left dangling on failure). The Boost 0x0003 commit
value is re-sent on AN 1>2, on the input link and in the state
replay, not only on preamp writes, so Boost no longer falls back to
-10dBV. The ref level is derived from the 0x17 readback at probe,
the phantom bit is sampled under the mutex, and the unused
bf_gain_db() is gone. The preamp and capture control names stay as
they are, with .index selecting the channel: the companion mixer
and the asound.state files already reference them, and the index is
the ALSA convention for a per-channel control. Turning a playback
pair's stereo split off wrote 0x1000 to both sides of its AN1/2
crosspoint, 6 dB below what the vendor software writes for a joined
pair, and lost the level set on that crosspoint; it now restores
the cached crosspoint.
- Routing flags (patch 4). bf_state_apply_flags() used to write
0x1000 to the AN1 and AN2 crosspoints on every probe and resume,
even at width 0, after the default mixer had left those inputs
muted. The cache still said 0, so a later write of 0 returned early
and could not mute them again. The width replay is now guarded and
shares one helper with the width control. DIM, mute, the master
controls and the front-panel wheels all derive the Phones level from
one helper, so they no longer cancel each other. bf_ms_put()
restores each output block's own crosspoint, the loopback control
notifies the pair it clears, and the enum and integer puts check
their bounds before narrowing.
- Suspend/resume (patch 5). No change of its own; it inherits the
replay fixes from patch 4.
- Front panel (patch 6). The MIX level is kept in dB2 instead of the
quantised register value, so clicks below the curve's first point
are no longer lost and a muted input comes up on the first click;
SELECT re-seeds the level while MIX is on. The MIX gate is no
longer re-armed on the tick that leaves the mode, reprobe is set
before the card becomes visible, and the panel master writers
respect DIM.
- EQ (patch 7). The low-cut frequency uses div64_s64() for the
variable divisor, so a 32-bit module does not need __divdi3 (not
exported on ARM). A band of type Off is identity rather than a high
shelf, the default slope matches the value the control reports, and
a failed strip upload is returned to the caller.
- Documentation (patch 8). Wording follows the one-map crosspoint
model; no functional change.
Every patch builds in-tree on its own against next-20261026 with W=1
and no warnings. checkpatch --strict reports no errors; the known
false positives are the same as v7 ('ang' for the CORDIC angle, and the
MAINTAINERS note on the patches that add files).
Validated on the unit with this tree:
- regress.sh --mixer-restore --disconnect-test passes 41/41: the
full-duplex sweep of the nine rates at periods 256 to 2048 with no
xruns, runtime renegotiation, 30 start/stop cycles, the mixer state
restored across an unbind/rebind, and an unbind in the middle of a
capture.
- The DIM/mute/volume matrix was checked on the wire with usbmon:
DIM writes the exact 0xcb/0x0333 pair, a volume change while DIM
is on keeps that pair, mute writes 0x3b/0x0000, unmute while DIM
is on restores 0xcb/0x0333, and releasing DIM restores the new
volume.
- The probe/rebind replay was checked on the wire too: after the
default mixer writes 0x0000 to the AN1/AN2 crosspoints, no 0x1000
write follows, so the width block no longer unmutes the inputs.
- The MIX-wheel arithmetic is covered by fader_selftest: a muted
crosspoint seeds at the curve's first point, one clockwise click
leaves mute, and two counter-clockwise clicks from the old -52 dB
sticking point move.
- The physical MIX-wheel gesture was checked on the unit: from a
muted AN3 crosspoint, one clockwise click moved it to 0x0004 (the
old code left it at 0 for the first five clicks), two clockwise and
two counter-clockwise clicks stepped it to 0x0003, and the level
followed the wheel in both directions.
- The stereo split was checked through the AN1/2 digital loopback:
with PB1 at the default crosspoint, split then join comes back at
the level it started from (-51.5 dB before and after; it used to
come back at -54.5 dB).
Known limitations, unchanged from v7:
- USB autosuspend is not supported; it is disabled at probe. S3
suspend/resume works.
- A few protocol details remain open (documented in the source, not
blocking): the preamp readback index semantics, a width
strip-ownership edge case, whether DIM's scope follows TotalMix's
Main Out setting, and the exact high-frequency warping of the EQ
coefficients against the vendor curve.
- The URB size and count are load-time parameters, though the size
follows the period the application asks for.
Disclosure: as with previous versions, the reverse-engineering and
substantial portions of the kernel implementation were written with
heavy assistance from AI coding assistants. All of it was verified by
hand on real hardware; the human authors remain responsible for the
result via Signed-off-by.
Thanks,
Ismaïl
Ismaïl Bahloul (8):
ALSA: usb: add RME Babyface Pro driver core (probe, PCM stream)
ALSA: usb: babyfacepro: add output masters and crosspoint routing
ALSA: usb: babyfacepro: add mic preamp, phantom/pad and input trim
ALSA: usb: babyfacepro: add routing flags and varispeed pitch
ALSA: usb: babyfacepro: add S3 suspend/resume
ALSA: usb: babyfacepro: add the front-panel poll and controls
ALSA: usb: babyfacepro: add the hardware DSP EQ
Documentation: sound: add the Babyface Pro proprietary-mode design doc
Documentation/sound/cards/babyface-pro.rst | 218 ++
Documentation/sound/cards/index.rst | 1 +
MAINTAINERS | 6 +
sound/usb/Kconfig | 17 +
sound/usb/Makefile | 2 +-
sound/usb/babyfacepro/Makefile | 4 +
sound/usb/babyfacepro/babyfacepro-ctl.c | 3946 ++++++++++++++++++++
sound/usb/babyfacepro/babyfacepro.c | 1943 ++++++++++
sound/usb/babyfacepro/babyfacepro.h | 568 +++
9 files changed, 6704 insertions(+), 1 deletion(-)
create mode 100644 Documentation/sound/cards/babyface-pro.rst
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.56.0
next reply other threads:[~2026-11-05 15:16 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 15:15 Ismaïl Bahloul [this message]
2026-11-05 15:15 ` [PATCH v8 1/8] ALSA: usb: add RME Babyface Pro driver core (probe, PCM stream) Ismaïl Bahloul
2026-11-05 15:15 ` [PATCH v8 2/8] ALSA: usb: babyfacepro: add output masters and crosspoint routing Ismaïl Bahloul
2026-11-05 15:15 ` [PATCH v8 3/8] ALSA: usb: babyfacepro: add mic preamp, phantom/pad and input trim Ismaïl Bahloul
2026-11-05 15:15 ` [PATCH v8 4/8] ALSA: usb: babyfacepro: add routing flags and varispeed pitch Ismaïl Bahloul
2026-11-05 15:15 ` [PATCH v8 5/8] ALSA: usb: babyfacepro: add S3 suspend/resume Ismaïl Bahloul
2026-11-05 15:15 ` [PATCH v8 6/8] ALSA: usb: babyfacepro: add the front-panel poll and controls Ismaïl Bahloul
2026-11-05 15:15 ` [PATCH v8 7/8] ALSA: usb: babyfacepro: add the hardware DSP EQ Ismaïl Bahloul
2026-11-05 15:15 ` [PATCH v8 8/8] Documentation: sound: add the Babyface Pro proprietary-mode design doc Ismaïl Bahloul
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=20261105151553.223722-1-i.bahloul01@gmail.com \
--to=i.bahloul01@gmail.com \
--cc=alsa-devel@alsa-project.org \
--cc=corbet@lwn.net \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=perex@perex.cz \
--cc=rdunlap@infradead.org \
--cc=skhan@linuxfoundation.org \
--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®