megi's PinePhone Development Log RSS


2022–04–02: Pinephone keyboard power manager

I noted previously on this blog, that Pinephone keyboard's charger doesn't have ideal behavior when combined with the phone (see Pinephone Keyboard – p-boot landscape mode for more details).

So that's something I've endeavored to fix the past few days. :)

Linux kernel

I decided for a kernel based solution for a few reasons. One is that I maintain the multi-distro demo image which shares one kernel between multiple Linux distributions, so any feature I implement in the kernel will be available to all distros at once, without having to integrate the same feature into 15 different distributions' varying init systems and userspace environments. The feature will also be available to all distros which use my kernel without much effort.

Other reason is that I have more control from the kernel over the system state, so I can reliably perform tasks prior to suspend to RAM, or after resume, or before system shutdown, etc. I can do this regardless of what mechanisms the Linux distribution uses for system sleep, whether it's systemd based sleep, or autosleep with wakelocks. The code is the same in all cases.

Implementing this feature in the kernel is also much simpler in general. I get direct access to states of power supply objects and other useful kernel features, like LED triggers.

How the power manager works

Power manager polls the status of various power supplies that represent the phone's and keyboard's battery charger, USB inputs and updates their status based on a simple control algorithm I've devised. This algorithm improves the charging and discharging behavior of Pinephone (and Pinephone Pro) when used together with the keyboard.

Basically, the algorithm tries to ensure that:

The driver also provides a set of LED triggers that you can associate with any of the phone's LEDs to get notified of the status of the batteries. For example, to get notified when the keyboard power is not being used via a red notification LED, you can simply:

echo kbpwr-kb-offline > /sys/class/leds/red:indicator/trigger

Or if you instead want to get notified when the capacity of both batteries is running dangerously low:

echo kbpwr-kb-capacity > /sys/class/leds/red:indicator/trigger

Power manager also handles several edge cases.

When you're turning off the phone, the driver will automatically shut the keyboard power down, so that the phone can be turned off. This would otherwise be a problem with Pinephone Pro, which would just restart if the keyboard was not powered down.

I'm still figuring out how I'd like the keyboard power supply to be handled on suspend/resume.

Other changes coming soon

In order for the power manager driver to have identical interface to chargers on Pinephone and Pinephone Pro, I had to extend the rk818 and axp20× drivers, to make them present the same power supply properties, and for those properties to have the same meaning on both phones.

One benefit of this is that I've unified the rk818-battery and rk818-charger drivers, so they are now presenting a single rk818-battery power supply interface to userspace. This will be less confusing to userspace. :)

I'll do some extensive testing, and push the changes out later next week.

I've made a tool to easily monitor the status of the phone while I test the algorithm in real usage.

The tool prints the current status reported by various power supplies in the phone, so I can see that the algorithm works as expected.

Now, I'll have to do the testing with both original Pinephone and Pinephone Pro… :)