First of all it took me long time to make that setup work as it should. So I decided to share that knowledge.
Hardware I used:
-Mackie Onyx 1640i (OXFW971 chip)
-Lenovo Thinkpad T420 (with internal FireWire: Ricoh Co Ltd R5C832 PCIe IEEE 1394 Controller (rev 04) daughter board)
-FireWire cable (shorter than 4.5[m] 6pin-to-4pin)
Software I used:
-Debian 11.0 Bullseye (Stable)
-Cadence 5:0.9.1 (KXStudio repos)
-JACKD 1.9.17 (with ALSA backend)
I will start with the custom build kernel that I am using. I had to recompile kernel to make use of RT_PREEMPT and some FireWire tweaking patch. Kernel version I used was the latest one at the time from the kernel.org website (vanilla 5.10.1 + rt20 patch and firewire patch which makes version 5.10.1-rt20-fw). As I will not go into details about RT patch and building the kernel itself but I will share some background about that FireWire stack patch. FFADO website is mentioning a tool for Windows that modifies Ricoh FIFO buffer in favor of audio. I asked around and I got an untested reverse engineered patch (big thanks to Clemens Ladisch one of the ALSA developers!) based on that Windows tool but for Linux kernel. I’ve tested it myself and I’ve send it to one more interested person. And we both agreed that with that patch we encounter less xruns in the long run. CAUTION! Patch no longer apply nicely on kernels v5.13+ so be sure to choose older version or apply it by hand.
--- linux/drivers/firewire/ohci.c
+++ linux/drivers/firewire/ohci.c
@@ -275,6 +275,8 @@
#define PCI_DEVICE_ID_AGERE_FW643 0x5901
#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
+#define PCI_DEVICE_ID_RICOH_R5C832 0x0832
+#define PCI_DEVICE_ID_RICOH_R5C832_E 0xe832
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020
#define PCI_DEVICE_ID_TI_TSB82AA2 0x8025
@@ -289,6 +291,7 @@
#define QUIRK_NO_MSI 0x10
#define QUIRK_TI_SLLZ059 0x20
#define QUIRK_IR_WAKE 0x40
+#define QUIRK_RICOH_FIFO_SIZE 0x80
/* In case of multiple matches in ohci_quirks[], only the first one is used. */
static const struct {
@@ -315,6 +318,12 @@
{PCI_VENDOR_ID_O2, PCI_ANY_ID, PCI_ANY_ID,
QUIRK_NO_MSI},
+ {PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, PCI_ANY_ID,
+ QUIRK_CYCLE_TIMER | QUIRK_RICOH_FIFO_SIZE},
+
+ {PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832_E, PCI_ANY_ID,
+ QUIRK_CYCLE_TIMER | QUIRK_NO_MSI | QUIRK_RICOH_FIFO_SIZE},
+
{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
@@ -354,8 +363,14 @@
“, disable MSI = ” __stringify(QUIRK_NO_MSI)
“, TI SLLZ059 erratum = ” __stringify(QUIRK_TI_SLLZ059)
“, IR wake unreliable = ” __stringify(QUIRK_IR_WAKE)
+ “, Ricoh FIFO configurable = ” __stringify(QUIRK_RICOH_FIFO_SIZE)
“)”);
+static bool param_ricoh_audio;
+module_param_named(ricoh_audio, param_ricoh_audio, bool, 0444);
+MODULE_PARM_DESC(ricoh_audio,
+ “Prioritize audio over disk traffic on Ricoh controllers”);
+
#define OHCI_PARAM_DEBUG_AT_AR 1
#define OHCI_PARAM_DEBUG_SELFIDS 2
#define OHCI_PARAM_DEBUG_IRQS 4
@@ -2279,6 +2294,40 @@
return 1;
}
+static void configure_ricoh_fifo(struct fw_ohci *ohci)
+{
+ struct pci_dev *dev = to_pci_dev(ohci->card.device);
+ int where;
+ u32 val;
+
+ switch (dev->device) {
+ case PCI_DEVICE_ID_RICOH_R5C832:
+ where = 0x88;
+ break;
+ case PCI_DEVICE_ID_RICOH_R5C832_E:
+ where = 0xe8;
+ break;
+ default:
+ return;
+ }
+
+ /* undocumented magic */
+ pci_read_config_dword(dev, where, &val);
+ val &= ~(0xff << 24);
+ if (param_ricoh_audio)
+ val |= 0x20 << 24;
+ pci_write_config_dword(dev, where, val);
+
+ /* adjust the max_rec field */
+ val = reg_read(ohci, OHCI1394_BusOptions);
+ val &= ~(0xf << 12);
+ if (param_ricoh_audio)
+ val |= 0x8 << 12; /* 512 bytes */
+ else
+ val |= 0xa << 12; /* 2048 bytes */
+ reg_write(ohci, OHCI1394_BusOptions, val);
+}
+
static int ohci_enable(struct fw_card *card,
const __be32 *config_rom, size_t length)
{
@@ -2331,6 +2380,9 @@
ohci->quirks &= ~QUIRK_TI_SLLZ059;
}
+ if (ohci->quirks & QUIRK_RICOH_FIFO_SIZE)
+ configure_ricoh_fifo(ohci);
+
reg_write(ohci, OHCI1394_HCControlClear,
OHCI1394_HCControl_noByteSwapData);
You can recompile kernel yourself and apply that patch or use my already build kernel that includes it. This patch gives you a new kernel module parameter for the FireWire stack that improves the sound buffer at the expense of disk writes. To activate this patch you will have to create a file /etc/modprobe.d/ricoh-firewire.conf with the following content:
options firewire-ohci ricoh_audio=1 quirks=208
and reload the firewire-ohci module or simply reboot.
areyouloco@studio:~/code/linux$ sudo modinfo firewire-ohci
filename: /lib/modules/5.12.2-rt3-fw/kernel/drivers/firewire/firewire-ohci.ko
parm: quirks:Chip quirks (default = 0, nonatomic cycle timer = 0x1, reset packet generation = 0x2, AR/selfID endianness = 0x4, no 1394a enhancements = 0x8, disable MSI = 0x10, TI SLLZ059 erratum = 0x20, IR wake unreliable = 0x40, Ricoh FIFO configurable = 0x80) (int)
parm: ricoh_audio:Prioritize audio over disk traffic on Ricoh controllers (bool)
//Debian default quirks are 0x50 we need to add “Ricoh FIFO configurable = 0x80”, so in hexadecimal 0x50 + 0x80 gives us quirks=0xd0 or if you prefer decimal it’s value 208
Next you will have to apply all the tweaks you think you can manage to apply from Linux Audio Wiki with some small changes. For example to add:
@audio - rtprio 95
@audio - memlock unlimited
@audio - nice -20
into /etc/security/limits.d/audio.conf.
Or to add:
vm.swappiness=0
dev.hpet.max-user-freq=3072
fs.inotify.max_user_watches=524288
kernel.perf_event_max_sample_rate=63000
into /etc/sysctl.d/10-audio-tweaks.conf.
Next we will go to the software. I’ve added KXStudio Repos to my Debian box to use their great audio software and plugins. Just install the meta-packages to be able to use Cadence to start and manage JACK for example.
Here are the screenshots from the known working Cadence (JACK) settings that I use with Mackie Onyx 1640i:
Previously I’ve used FFADO as a JACK back-end that gives the ability to go with even less latency but suffers from two unsolved bugs. One is minor. Simply one channel has wrong name but the other one makes long time use not possible. So I moved to stable, working and newer ALSA FireWire stack. I would advise to use FFADO backend only when recording for time shorter than around 45 minutes. To be able to get even smaller latency times but at the cost of stability and possible xruns.
Other problem I have encountered is that I have to start JACK with Cadence a few times to make it work. It’s like starting a car engine with broken battery. I will try as many times as needed to make it start. Few times it produces xruns constantly with time passing but at some point it produces few or no xruns at start and stays there.
That’s about it. I could forget what additional tweaks I could have made. So if you managed to reproduce the steps above and you are still getting XRUNS please leave a comment and we will figure it out!