The idea of feedback-based userspace software thermal management like this seems suboptimal to me — the failure modes are nasty. (By feedback-based, I mean using V/I sense from the amp.)
The goal is to prevent the voice coil from overheating, ever. So some kind of calculation runs at some interval t, and it needs to ensure that, over the upcoming time t, the input to the amp can’t possibly overheat the coil, and of course it can’t use V/I sense data to do understand the upcoming heat input.
So, at best, one estimates the coil temperature and comes up with an upper bound on how much heat can be added over time t (either based on worst-case music, e.g. a 0dBFS square wave or based on the actual samples), and either allows the next group of samples to be sent to the amp or not.
But this is all a tradeoff with real-time performance and battery life. You want t to be long to minimize performance impact and power consumption, especially if user code is involved. But you want t to be short to maximize the ability to play loud music, especially if you aren’t looking at the actual upcoming waveform.
And you don’t want your speakers to burn out of you are doing something CPU intensive and your userspace daemon doesn’t schedule.
To me, this all suggests that an in-kernel solution could work a lot better. The kernel is involved in sending samples to the hardware anyway — it has the opportunity to look at those samples right then, calculate the integrated power (could be as simple as the sum of the squares or even just a constant!), and decide whether it’s safe. And fetch the V/I sense data to figure out the status, and reduce the volume if it fails. And if the kernel code pushing samples to hardware stops running for whatever reason, the sound is inherently muted as long as the hardware isn’t configured to loop '90’s broken CD style.
There's no distinction between "user" and "kernel" that would mean kernel code gets scheduled more reliably than realtime userland threads. Or even that it necessarily has better access to the audio hardware.
If it's really really important then you'd want to move it to a custom core on the SoC of course, but that'd make a Linux port harder.
> There's no distinction between "user" and "kernel" that would mean kernel code gets scheduled more reliably than realtime userland threads.
The distinction is that the kernel submits buffers to hardware, so it can do safety-related checks synchronously. If it doesn’t get scheduled, nothing plays, and the tweeters don’t burn out.
This can be done in userspace, too. Something in the kernel (ALSA? A driver?) could call into what would be, in effect, a userspace audio codec driver. That userspace driver would do its safety checks and then send the buffer off to the codec for playback.
It’s a bit sad that x86’s abysmal context switching performance has helped nerf microkernel and userspace driver development for years. Fortunately we’re talking about ARM64 here. (On modern systems, the tens of thousands of cycles x86 spends doing nothing useful when context switching or handling interrupts don’t matter as much as they might have when CPUs we’re slower.)
The goal is to prevent the voice coil from overheating, ever. So some kind of calculation runs at some interval t, and it needs to ensure that, over the upcoming time t, the input to the amp can’t possibly overheat the coil, and of course it can’t use V/I sense data to do understand the upcoming heat input.
So, at best, one estimates the coil temperature and comes up with an upper bound on how much heat can be added over time t (either based on worst-case music, e.g. a 0dBFS square wave or based on the actual samples), and either allows the next group of samples to be sent to the amp or not.
But this is all a tradeoff with real-time performance and battery life. You want t to be long to minimize performance impact and power consumption, especially if user code is involved. But you want t to be short to maximize the ability to play loud music, especially if you aren’t looking at the actual upcoming waveform.
And you don’t want your speakers to burn out of you are doing something CPU intensive and your userspace daemon doesn’t schedule.
To me, this all suggests that an in-kernel solution could work a lot better. The kernel is involved in sending samples to the hardware anyway — it has the opportunity to look at those samples right then, calculate the integrated power (could be as simple as the sum of the squares or even just a constant!), and decide whether it’s safe. And fetch the V/I sense data to figure out the status, and reduce the volume if it fails. And if the kernel code pushing samples to hardware stops running for whatever reason, the sound is inherently muted as long as the hardware isn’t configured to loop '90’s broken CD style.