Standalone power management in Linux
I use the wonderful i3 window manager. Since I run it on my laptop, I need some sort of power management: suspend when lid is closed, adjust screen brightness and CPU performance when running on battery power, etc. My first thought was to use gnome-power-manager
, but that seems to have disappeared in Fedora 17. I then tried xfce4-power-manager
(yum install xfce4-power-manager
, then start by running xfce4-power-manager
and then xfce4-power-manager-settings
to configure), which mostly of worked: I could get it to suspend and adjust brightness, but suspend-and-LOCK wouldn’t work for whatever reason.
So I decided to do it a different, and more customizable way. (Most of the following is probably a waste of time if you’re using something like Unity, Gnome, KDE, Xfce, etc., which all take care of these things for you.)
ACPI events for suspend
Let’s start with suspending and locking. First, install acpid
if you don’t already have it and start it (I’m using Fedora here, but the instructions should be pretty much the same for Ubuntu):
yum install acpid
acpid
Now we can listen to APCI events and react to them. To check that it works, run acpi_listen
and try things like adjusting screen brightness and closing/opening the lid. This should generate events like this:
$ acpi_listen
video/brightnessdown BRTDN 00000087 00000000
video/brightnessup BRTUP 00000086 00000000
video/brightnessup BRTUP 00000086 00000000
button/lid LID close
button/lid LID open
Next, in /etc/acpi/events
, I created the file lidbtn
(you can call it anything you want) with the following content:
event=button[ /]lid
action=/etc/acpi/lid.sh
The above simply specifies that on any button/lid event, /etc/acpi/lid.sh
should be executed. In /etc/acpi/lid.sh
, I have the following:
#!/bin/sh
grep -q closed /proc/acpi/button/lid/*/state
if [ $? = 0 ]; then
/usr/local/sbin/physlock -d -u fooninja
pm-suspend
fi
If the lid is closed, physlock
and pm-suspend
will be executed. physlock is a neat, lightweight locking tool, written because vlock
had issues with suspend/hibernate.
Performance settings depending on AC/battery power
To adjust things depending on whether the laptop is running on AC or battery, I created /etc/pm/power.d/performance
with the following. Note that for Ubuntu, at least in 12.04.1, change cpupower -c $cpu frequency-set
to cpufreq-set -c $cpu
—and don’t forget to install cpufrequtils
first.
#!/bin/sh
if [ "$1" = "true" ]; then
# Battery
# Normal-(ish?) power management for HDD
hdparm -B 192 /dev/sda
# Turn down brightness
echo 10 > /sys/class/backlight/acpi_video0/brightness
# 60 seconds before X goes black
xset dpms 0 0 60
# Slower CPU performance (less power usage)
for cpu in 0 1 2 3; do cpupower -c $cpu frequency-set -g powersave; done
else
# AC
# Least aggressive power management, keeps Load_Cycle_Count from increasing too much
hdparm -B 254 /dev/sda
# Turn up brightness
echo 13 > /sys/class/backlight/acpi_video0/brightness
# 600 seconds before X goes black
xset dpms 0 0 600
# Maximum CPU performance
for cpu in 0 1 2 3; do cpupower -c $cpu frequency-set -g performance; done
fi
Don’t copy the above code blindly (unless you happen to have an X220, and the same preferences…)! And don’t forget to make it executable: chmod +x /etc/pm/power.d/performance
.
Screen brightness
Next step was getting the laptop’s hotkeys for adjusting brightness to work. I could use ACPI events (video/brightnessdown
, video/brightnessup
) to trigger something, or just bind the X keycodes. I opted for the latter.
You should be able to set brightness manually, with e.g. echo 10 > /sys/class/backlight/acpi_video0/brightness
. To make life easier I installed xbacklight
, which lets you set or increase/decrease by a specificed amount.
Next, I used xev
to grab the keycodes for the brightness up/down buttons and put the following in my ~/.i3/config
:
bindcode 232 exec xbacklight -dec 10
bindcode 233 exec xbacklight -inc 10
Sound
To get the hotkeys for sound to work, I again used xev
to get the keycodes, and then bound them to amixer
commands:
bindcode 121 exec amixer set Master toggle -q
bindcode 122 exec amixer set Master 1%- unmute -q
bindcode 123 exec amixer set Master 1%+ unmute -q