slop driver for m-audio firewire series audio cards
Find a file
2026-08-25 10:31:24 +05:00
dkms srach linox pkgbuild 2026-08-25 10:30:40 +05:00
mafw-firewire working driver 2026-08-25 10:09:49 +05:00
modprobe working driver 2026-08-25 10:09:49 +05:00
scripts working driver 2026-08-25 10:09:49 +05:00
tools working driver 2026-08-25 10:09:49 +05:00
udev working driver 2026-08-25 10:09:49 +05:00
wireplumber working driver 2026-08-25 10:09:49 +05:00
.gitignore srach linox pkgbuild 2026-08-25 10:31:24 +05:00
Makefile working driver 2026-08-25 10:09:49 +05:00
PKGBUILD srach linox pkgbuild 2026-08-25 10:30:40 +05:00
README.md working driver 2026-08-25 10:09:49 +05:00
snd-mafw.install working driver 2026-08-25 10:09:49 +05:00

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 ... Route controls. On BeBoB hardware routing is expressed with selector blocks, not mixer blocks — see the note in FFADO's bebob_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 ... Switch where 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.