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. :)
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
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:
- When charging via USB PSU plugged into a keyboard:
- Phone's internal battery is charged as fast as possible, first.
- When the internal battery is fully charged, keyboard battery starts
charging, while still supplying enough power to the phone so that internal
battery doesn't start discharging.
- When discharging:
- Keyboard's battery is used first without re-charging Phone's internal
battery (unless absolutely necessary)
- When the keyboard battery is almost discharged, phone battery starts
- Phone battery is kept charged to at least 20% when possible. This is
necessary for stability, and to be able to use the parts of the phone supplied
directly from the phone's battery, like the modem and wifi.
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
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
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