| dkms | ||
| mafw-firewire | ||
| modprobe | ||
| scripts | ||
| tools | ||
| udev | ||
| wireplumber | ||
| .gitignore | ||
| Makefile | ||
| PKGBUILD | ||
| README.md | ||
| snd-mafw.install | ||
snd-mafw
ALSA driver for M-Audio FireWire interfaces built on BridgeCo BeBoB chips, adding the mixer that the in-kernel driver does not have.
Why this exists
The kernel already ships snd-bebob, which streams these devices correctly. It
exposes no ALSA mixer controls at all, because FFADO does the BeBoB mixer in
userspace (ffado-mixer):
$ amixer -c 0 controls
$ # nothing
On a FireWire Solo that is not merely inconvenient — it means silence. The device powers up with its internal routing muted, so audio reaches the hardware and is discarded. The hardware meter shows exactly that:
Stream In 1: 1030291456 <- our audio arrives
Analog Out 1: 0 <- and goes nowhere
The Windows driver programs that routing at startup. Nothing on Linux did.
snd-mafw streams using the same kernel AMDTP engine as snd-bebob, and adds
the AV/C audio-subunit function-block layer needed to program the routing and
expose it to alsamixer, amixer and PipeWire.
Status
| Model | ID | State |
|---|---|---|
| FireWire Solo | 0x000d6c:0x010062 |
supported, tested |
| FireWire 410 | 0x0007f5:0x010046 |
identified, not claimed |
| FireWire Audiophile | 0x000d6c:0x010060 |
identified, not claimed |
| Ozonic | 0x000d6c:0x00000a |
identified, not claimed |
| NRV10 | 0x000d6c:0x010081 |
identified, not claimed |
| FireWire 1814 | 0x000d6c:0x010071 |
identified, not claimed |
| ProjectMix I/O | 0x000d6c:0x010091 |
identified, not claimed |
Only the Solo is bound. Everything else reports "not supported yet" and is left
to snd-bebob, rather than being claimed and then failing. Enabling a model is a
matter of setting .supported = true in its mafw_spec once it has been tested
on real hardware.
FW1814 and ProjectMix need a genuinely different control path — their firmware
freezes on unrecognised AV/C commands and their mixer is a write-only register
block at 0xffc700700000 — so they are not simply a flag away.
Build and use
make # syncs vendored headers, builds the module
sudo make install
sudo tools/mafw-bind.sh # take the device from snd-bebob
snd-mafw and snd-bebob match the same hardware, and which wins at boot
depends on module load order. mafw-bind rebinds one unit at runtime instead of
hijacking snd-bebob's module aliases, which would break every other BeBoB
device on the system.
sudo tools/mafw-bind.sh --status # what is bound where
sudo tools/mafw-bind.sh --revert # hand it back
For PipeWire:
sudo cp wireplumber/51-mafw.conf /etc/wireplumber/wireplumber.conf.d/
systemctl --user restart wireplumber
Note that this is a WirePlumber drop-in. monitor.alsa.rules under
pipewire.conf.d is a pipewire-media-session leftover that WirePlumber 0.5
ignores. There is no PipeWire plugin to install — an ALSA driver is consumed by
the ALSA monitor directly.
Diagnostics
The device only describes its topology over AV/C, so the driver publishes what it found:
cat /proc/asound/*/firewire/function-blocks # discovered mixer topology
cat /proc/asound/*/firewire/channel-map # which PCM channel reaches which jack
cat /proc/asound/*/firewire/formation # channels and rates per sample rate
cat /proc/asound/*/firewire/clock # rate, clock source, lock state
cat /proc/asound/*/firewire/meter # live signal levels
channel-map is the one to reach for when audio is inaudible but the stream is
running: it shows whether playback channels 1/2 land on the analog outputs or on
the S/PDIF pair.
To confirm audio end to end, watch the meter while playing:
speaker-test -D hw:0,0 -c 4 -F S32_LE -t sine &
watch -n0.5 cat /proc/asound/*/firewire/meter
Analog Out 1/2 becoming non-zero is the objective proof that routing works.
Mixer controls
Controls are generated from whatever function blocks the device reports:
- Selector blocks become enumerated
... Routecontrols. On BeBoB hardware routing is expressed with selector blocks, not mixer blocks — see the note in FFADO'sbebob_functionblock.cpp. - Feature blocks become
... Volume(with a dB TLV taken from the device's own reported min/max, in 1/256 dB units per AV/C Audio Subunit 10.3.1) and... Switchwhere the device implements mute.
Block names come from a per-model table. Where no table entry exists yet,
controls appear as FB Selector 3, FB Volume 5 and so on — functional, just
unlabelled. Read function-blocks to see what each id actually does, then add
entries to the model's mafw_fb_name table.
At probe the driver unmutes and un-attenuates blocks that are fully silent,
which is what makes a freshly powered device audible. Levels that are set to
anything other than the minimum are left alone, and selectors are never changed
automatically. Disable with modprobe snd-mafw default_routing=0.
Vendored kernel headers
sound/firewire/*.h are not shipped in linux-headers, but struct amdtp_stream and struct cmp_connection are embedded by value, so the headers
have to be vendored into mafw-firewire/include/.
Symbol CRCs do not cover struct layout. A stale copy would corrupt memory rather
than fail to load, so mafw_device.h hard-errors below Linux 6.8 and warns above
the tested ceiling, and DKMS re-syncs the headers on every rebuild.
After a manual kernel change:
bash scripts/sync-kernel-headers.sh
Credits
Streaming, formation discovery, channel mapping and the BridgeCo AV/C commands
are adapted from sound/firewire/bebob by Takashi Sakamoto. The function-block
protocol details come from FFADO (libffado/src/bebob, libffado/src/libavc).
Both are GPL-2.0, as is this driver.