-
-
Notifications
You must be signed in to change notification settings - Fork 502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Odroid N2 | Significant audio distortion with USB DAC #5949
Comments
Many thanks for your report. Probably a limitation of the mainline kernel, but I didn't hear of this until now. 3.5mm jack and HDMI audio work fine? And you did try all USB ports, whether it makes a difference? I can test it when I find time, having N2+ and a (cheap) USB DAC here as well. |
I did some more testing based on your question, and I have a more specific condition for this to happen. While I don't have a good way of testing the HDMI audio (so I don't know whether there's an issue there or not), I was able to test the internal 3.5mm output, and it worked fine. So did my USB DAC afterwards. I was able to replicate this on another fresh install, too. It doesn't matter which USB port I have the DAC plugged into. It sounds extremely distorted until I first use Is it possible that something might not be initialized properly except when switching to the internal 3.5mm output? |
Probably it's related to hardware interrupts all done on the same CPU. E.g. on legacy kernel C2 images we apply SMP affinities. Can you show: cat /proc/interrupts Here is what is shows in my case (Odroid N2+): root@OdroidN2:~# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5
9: 0 0 0 0 0 0 GICv2 25 Level vgic
11: 1880 1663 4531 2093 1961 1717 GICv2 30 Level arch_timer
12: 0 0 0 0 0 0 GICv2 27 Level kvm guest vtimer
14: 250 0 0 0 0 0 GICv2 225 Edge ttyAML0
15: 24 0 0 0 0 0 GICv2 71 Edge ffd1c000.i2c
16: 573 0 0 0 0 0 GICv2 35 Edge meson
17: 15 0 0 0 0 0 GICv2 89 Edge dw_hdmi_top_irq, ff600000.hdmi-tx
18: 0 0 0 0 0 0 GICv2 63 Level ff400000.usb, ff400000.usb
19: 30760 0 0 0 0 0 GICv2 62 Level xhci-hcd:usb1
20: 1 0 0 0 0 0 GICv2 48 Level ffe09000.usb
21: 0 0 0 0 0 0 GICv2 222 Edge ffe05000.sd
22: 5077 0 0 0 0 0 GICv2 223 Edge ffe07000.mmc
27: 2 0 0 0 0 0 GICv2 228 Edge ff808000.ir
28: 2 0 0 0 0 0 GICv2 232 Edge ff809000.adc
29: 4 0 0 0 0 0 GICv2 192 Level panfrost-gpu
30: 0 0 0 0 0 0 GICv2 193 Level panfrost-mmu
31: 0 0 0 0 0 0 GICv2 194 Level panfrost-job
32: 0 0 0 0 0 0 GICv2 76 Edge vdec
33: 0 0 0 0 0 0 GICv2 64 Edge esparserirq
IPI0: 98 102 491 181 480 342 Rescheduling interrupts
IPI1: 1636 1892 4033 18074 3087 7800 Function call interrupts
IPI2: 0 0 0 0 0 0 CPU stop interrupts
IPI3: 0 0 0 0 0 0 CPU stop (for crash dump) interrupts
IPI4: 0 0 0 0 0 0 Timer broadcast interrupts
IPI5: 68 22 42 89 70 58 IRQ work interrupts
IPI6: 0 0 0 0 0 0 CPU wake-up interrupts
Err: 0 If the IDs are/stay the same, USB-related interrupts can be moved to a different core. In my case they stay the same across reboots, so the interrupts can be done by the first A73 core instead: root@OdroidN2:~# echo 4 > /proc/irq/18/smp_affinity
root@OdroidN2:~# echo 4 > /proc/irq/19/smp_affinity
root@OdroidN2:~# echo 4 > /proc/irq/20/smp_affinity
root@OdroidN2:~# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5
18: 0 0 0 0 0 0 GICv2 63 Level ff400000.usb, ff400000.usb
19: 32392 0 2664 0 0 0 GICv2 62 Level xhci-hcd:usb1
20: 1 0 0 0 0 0 GICv2 48 Level ffe09000.usb As you can see, now |
|
Seems to be 18, 19, and 20 on mine as well. |
Looks good, most IRQs are the same. The graphics/panfrost ones are different, somehow, and you do not seem to use the serial console, while I use no Ethernet (a USB WiFi adapter instead). Not sure whether the IDs depend on the order the devices are detected by the kernel, e.g. Test whether changing the affinity helps to solve the USB sound quirks. If so, I'll think about how to implement this into our Odroid N2 images OOTB. |
So, I've been trying to do some testing to see whether changing the CPU affinity helps, but I actually can't replicate this issue any more, even on a fresh install. I'm absolutely baffled, since I was able to replicate it for months (and swapped to the ODROID Ubuntu distribution on this device for a bit, assuming it was a temporary bug), but . . . it doesn't seem to be happening for me now that I want to test the affinity settings you suggested. I'm following exactly the same steps I was before from the same image, on the same hardware, with a different result. I'm absolutely mystified, but I guess it works for me out of the box now? |
Strange indeed. A I see you used Linux 5.19. Probably you switched to edge kernel to solve or test another issue? Then with edge Linux the issue may still exist. Yours is Linux 5.10, right? uname -a |
No, I'm actually on 5.19.17.
This is just from the DietPi image on the dietpi.com site with whatever updates it does (so, no switching kernels or branches) and installing the Roon bridge and dependencies/enabling the USB DAC. No other changes. I just double-checked the image I've been using to make sure it's the same as what's currently, and it's the same. Both have a SHA256 sum of |
Ah okay, I just didn't recognise yet that the "current" kernel branch for meson64 obviously moved to Linux 5.19 already. Seems to have been done with Armbian v22.11. Let me keep this issue open, so when I'm back home from holiday I'll check whether/how Armbian's boot scripts do tweak SMP affinities on meson64/Odroid N2 and how. I actually also read somewhere else that it doesn't have any benefit nowadays, but it doesn't sound logic to me to let a single core dealing with all hardware interrupts. |
Okay, lacking a better method, this should do it: cat << '_EOF_' > /var/lib/dietpi/postboot.d/smp_affinities.sh
#!/bin/dash
while read -r line
do
[ "$skipped" ] || { skipped=1; continue; } # Skip first line
irq=${line%%:*}
expr "$irq" : '^[0-9]\+$' > /dev/null || break # Stop when reaching non-numeric IRQs
case "$line" in
*mmc*) echo 1 > "/proc/irq/$irq/smp_affinity_list";;
*xhci-hcd*) echo 2 > "/proc/irq/$irq/smp_affinity_list";;
*eth0*) echo 3 > "/proc/irq/$irq/smp_affinity_list";;
esac
done < /proc/interrupts
_EOF_
|
@Kreeblah |
I tested it here with a cheap LogiLink USB DAC and test OGG and MP3 audio files and could not face any audio distortion on different ports with a USB WiFi adapter attached as well. Hence I cannot test whether above SMP affinity tweak is helping. We are talking about the digital audio stream to the DAC, so the USB data transfer must be significantly disturbed for such effect, but if anyone can verify it, and that the above tweak helps, I'll add this OOTB to our Odroid N2 images, as other USB-related tasks would then benefit as well. |
Adding that script to set affinities works fine for me, though there was a point at which I stopped being able to replicate this issue on my hardware without it, and I'm still not sure why, or what was causing it originally. Still, it's probably worth including this in the OOTB images since the N2 has several cores to work with anyway. |
Okay thanks for reporting back. I'll reread current information about SMP affinities and whether they really make still sense with current Linux. I remember some discussion which stated it wouldn't have benefits today, and that this is also a reason why it isn't possible on Raspberry Pi (the handles are write-protected). We shouldn't add a script if it has no actual benefit 😉. |
Now that I've had that script running for a few days, I've noticed something else. Up until a few days ago, using the volume slider in Roon would sometimes cause one channel (left or right) to cut out until I changed the volume again. I figured that was just an issue with my DAC, but it hasn't happened since then. I'll need to do some more testing, though, since I updated to v8.15 shortly after it became available, so I'll need to isolate whether it's a result of the new version or the CPU affinity script. |
I took a more in-depth look, and it doesn't seem that the CPU affinity script is what improved things there. Removing the script doesn't seem to make a difference. I think the new version resolved things for me. It turns out I do still occasionally get some odd behavior when adjusting the volume (occasionally it'll drop to 0 instead of the value it was supposed to go to), but that seems to be extremely rare. I've only gotten it to happen a couple of times despite trying to make it happen. That's a separate issue, though, so if it ends up being a big thing, I'll open a new one. As far as what I originally reported here, though, I haven't been able to replicate it in a while, so I think it's solved out of the box now. |
Okay, thanks for testing. I was reading a little about SMP IRQ affinities and generally it is possible that this enhances performance or lower latency on high load systems or real-time applications. Sometimes it is not about balancing IRQs between CPU cores but to have interrupts for a hardware device and the related process on the same core for cache sharing. The cache is btw also a reason why letting multiple cores handling the same interrupt is usually not beneficial. Also power saving considerations play a role as you do not want all core to wake up regularly if actually one core would be able to deal with all interrupts. However, there is a daemon for balancing IRQs among cores which is interesting to have a look at when looking deeper into this topic:
I think the cases where this makes a real difference are low, otherwise the default wouldn't be that CPU0 handles all hardware interrupts by default. Marking this issue as closed but added to archive to remember and in case have another look when we find evidence that it helps. |
Creating a bug report/issue
Required Information
Linux DietPi 5.19.17-meson64 #22.11.1 SMP PREEMPT Wed Nov 30 11:05:42 UTC 2022 aarch64 GNU/Linux
Additional Information (if applicable)
Steps to reproduce
Expected behaviour
Actual behaviour
Extra details
The text was updated successfully, but these errors were encountered: