4 minutes
Written: 2020-08-01 20:00 +0000
Updated: 2024-08-06 00:52 +0000
Explorations with Backlight Controllers
A short post detailing the many trials and tribulations of setting brightness on multiple monitors in tandem.
Background
As regular readers might know, I have a multi-screen setup, which accounts for having touch enabled on my primary laptop screen (detailed here). A failing of this setup was that I was not able to control the brightness of both monitors at the same time.
Existing Stack
Since I use i3
, my brightness control is simply done with bindsym
lines as follows1:
1bindsym XF86MonBrightnessDown exec light -U 10
2bindsym XF86MonBrightnessUp exec light -A 10
Note that to get the right bindsym
I use screenkey with the keysyms
preference. My software of choice was
Unfortunately, my existing setup (with light
, since that is in the Arch community
repo) did not actually allow dimming external screens arbitarily. To be more exact,
1light -h
1Usage:
2 light [OPTIONS] [VALUE]
3
4Commands:
5 -H, -h Show this help and exit
6 -V Show program version and exit
7 -L List available devices
8 -A Increase brightness by value
9 -U Decrease brightness by value
10 -T Multiply brightness by value (can be a non-whole number, ignores raw mode)
11 -S Set brightness to value
12 -G Get brightness
13 -N Set minimum brightness to value
14 -P Get minimum brightness
15 -O Save the current brightness
16 -I Restore the previously saved brightness
17
18Options:
19 -r Interpret input and output values in raw mode (ignored for -T)
20 -s Specify device target path to use, use -L to list available
21 -v Specify the verbosity level (default 0)
22 0: Values only
23 1: Values, Errors.
24 2: Values, Errors, Warnings.
25 3: Values, Errors, Warnings, Notices.
26
27Copyright (C) 2012 - 2018 Fredrik Haikarainen
28This is free software, see the source for copying conditions. There is NO
29warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
Clearly it is possible to target specific devices, but for arbitrary additions this is quite tough. Additionally, the project has been more or less been stuck in maintainence mode for a while now.
Multi-head Configurations
Exposing Brightness
The first hurdle faced in o was actually getting the external monitor to expose the right controls. This is accomplished neatly with ddci-driver
found here. As demonstrated (courtesy of the ArchWiki):
1# Load module
2sudo modprobe ddcci_backlight
3# Check that it worked
4sudo ddcutil capabilities | grep "Feature: 10"
5sudo ddcutil getvcp 10
6# Set brightness
7sudo ddcutil setvcp 10 70
One of the obvious caveats of this technique is that sudo
access or a dedicated polkit
agent is required. My preferred method of loading this comes from a comment on the ddcci-driver-linux-dkms
page of the AUR:
1# Put in /etc/systemd/system/ddcci-backlight.service:
2# https://aur.archlinux.org/packages/ddcci-driver-linux-dkms/
3# Placing "ddcci_backlight" into /etc/modules-load.d
4# leads to hang on boot with external (HDMI) monitor
5# connected to the laptop, so we need to add the module later.
6
7# And ddcci_backlight can't detect monitor during sddm.service startup.
8
9[Unit]
10After=multi-user.target
11Before=sddm.service
12
13[Service]
14Type=oneshot
15ExecStart=/usr/bin/modprobe ddcci_backlight
16ExecStop=/usr/bin/modprobe --remove ddcci_backlight
17RemainAfterExit=yes
18
19[Install]
20WantedBy=multi-user.target
This is then activated with a standard systemctl enable ddcci_backlight.service
command. At this point, the device interface should be exposed to most backlight controllers.
Xrandr
This is the most obvious of all methods, and does not even require the ddcci-driver
. We will simply tweak the brightness with xrandr
.
1# Get devices
2xrandr | grep " connected"
3# Tweak
4xrandr --output DP1 --brightness 0.2
Note that this is an in-exact method, since it actually adjusts the gamma value instead, and it effectively tints your screen rather than modifying the brightness.
Clight
clight is an excellent, highly performant alternative to redshift, but it tends to force the main screen brightness to zero. Nothing which can’t be configured away, but in practice, I work late and tend to turn off the tint anyway. This requires a daemon to be run, as well as needing to be turned on manually for i3
. A very elegant additional feature gained by using clight
is that external monitors are turned off automagically when lockscreens are activated.
Brillo
brillo is one of the newer controllers, and is pretty actively developed. The interface is almost exactly like light
, and unlike clight
there is no need to use a daemon. It meshes perfectly with a key-press based system like i3
and also has controls for keyboard LEDS as well as for smoothed ramping up and down of the brightness. Most importantly, it features an -e
flag which sets the brightness across all output devices. Essentially this means my configuration is simply modified to:
1bindsym XF86MonBrightnessDown exec brillo -e -U 10
2bindsym XF86MonBrightnessUp exec brillo -e -A 10
Conclusions
tl;dr moving from light
to brillo
with ddcci-driver-linux-dkms
was a fantastic idea.