[Comprehensive guide] How to use Mackie Onyx 1640i with Debian Linux on Lenovo Thinkpad T420 with near 0 xruns at 48kHz with around 20.322[ms] total roundtrip latency. [Part 3]

So this is the part 3 of my blog post to see part 2 visit:
https://lovelybabylon.noblogs.org/comprehensive-guide-how-to-use-mackie-onyx-1640i-with-debian-linux-on-lenovo-thinkpad-t420-with-near-0-xruns-at-48khz-with-around-20-322ms-total-roundtrip-latency-part-2

Another ALSA developer Takashi Sakamoto contacted me via email because he saw my messages on ALSA mailinglist. So I was asked to test new driver (kernel module) for devices based on OXFW970/OXFW971 chip. So it turned out my Mackie Onyx 1640i is using this OXFORD 971 chip (while some models are based on TC Applied Technologies DICE chipset family chip using snd-dice kernel driver instead). So I compiled and tested his code but it didn’t work at first few tries. The audio was playing in slow motion, distorted or you could hear only clicks and pops. You can read more about the issue [here]. Apparently there was a regression in kernels v5.13+. Also with the versions v5.13+ the “Ricoh FireWire patch” no longer applies smoothly. So please make sure to use kernel older than v5.13. And my suggestion is to you use Takashi’s improved driver on the top of kernel v5.12.0-rc3 instead. So you take advantage of both worlds. His work is most likely going to be a part of kernel v5.16.

At the end we managed to fix the issues with audio/video. I need to say the driver is way more stable then stock kernel driver. It runs almost XRUNs free all the time. Even with 64 samples 3 periods, that is 1.3ms block latency! Thank you Takashi! Enjoy!

Thank you for your time and I hope it was helpful.

[Comprehensive guide] How to use Mackie Onyx 1640i with Debian Linux on Lenovo Thinkpad T420 with near 0 xruns at 48kHz with around 20.322[ms] total roundtrip latency. [Part 2]

Welcome to part 2 of my guide. To see part 1 visit:
https://lovelybabylon.noblogs.org/comprehensive-guide-how-to-use-mackie-onyx-1640i-with-debian-linux-on-lenovo-thinkpad-t420-with-near-0-xruns-at-48khz-with-around-20-322ms-total-roundtrip-latency-part-1/

Since I still experienced XRUNS in the long run even when using playback only. I continued to wiggle around with different kernels and the latest kernel that I tried was v5.12-rc3 that could apply mentioned in the previous parts FireWire (IEEE 1394): Ricoh Co Ltd R5C832 PCIe IEEE 1394 Controller (rev 04) patch. You can find already patched source code [here] and used config [here]. I am sure the patch doesn’t apply nicely to kernels v5.13+ but someone could try to adapt it by hand.

Following the fact I am recompiling the kernel I used some other useful setting from ALSA-Project Wiki. Mentioned here [XRUN_Debug]. So I enabled the necessary kernel build options:
areyouloco@studio:~/code/linux$ grep \
-e "CONFIG_SND_PCM_XRUN_DEBUG" \
-e "CONFIG_SND_VERBOSE_PROCFS" \
-e "CONFIG_SND_DEBUG" .config
CONFIG_SND_VERBOSE_PROCFS=y
CONFIG_SND_DEBUG=y
CONFIG_SND_DEBUG_VERBOSE=y
CONFIG_SND_PCM_XRUN_DEBUG=y

If you use tools like make menuconfig/make xconfig that options are in: Device Drivers —> Sound card support —> Advanced Linux Sound Architecture —> Debug

ALSA Debugging

In order to use that kernel debugging options I am going to enable it by using second option. It should be enough:
# Enable basic debugging and dump stack, check hardware pointer on the period update
# Usefull to just see, if PCM stream is stopped for a reason (usually wrong audio process timing from scheduler)
# And to check the values from driver
areyouloco@studio:~/code/linux$ sudo echo 11 > /proc/asound/card2/pcm0p/xrun_debug

In my case it was card2. You can check it out by running:
areyouloco@studio:~/code/linux$ cat /proc/asound/cards

I also uploaded new kernel version 5.12.0-rc3-rt3-fw-00003-g608d0b4b4952 that is the last one I’ve tried that supported Ricoh FireWire patch, RT patch and tweaks from above.

So I manged to get debug info about that XRUN that makes the JACK process hang. Here is more detailed bug report.

[…]

Still hunting that long playback hang…

Follow up:
https://lovelybabylon.noblogs.org/comprehensive-guide-how-to-use-mackie-onyx-1640i-with-debian-linux-on-lenovo-thinkpad-t420-with-near-0-xruns-at-48khz-with-around-20-322ms-total-roundtrip-latency-part-3/

[Comprehensive guide] How to use Mackie Onyx 1640i with Debian Linux on Lenovo Thinkpad T420 with near 0 xruns at 48kHz with around 20.322[ms] total roundtrip latency. [Part 1]

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!

Link to part 2: https://lovelybabylon.noblogs.org/comprehensive-guide-how-to-use-mackie-onyx-1640i-with-debian-linux-on-lenovo-thinkpad-t420-with-near-0-xruns-at-48khz-with-around-20-322ms-total-roundtrip-latency-part-2/

linux debian hacks soldering hardware bash