Monitor Brightness on the Desktop
Since I found the buttons on my monitor to be inconvenient, I decided to try to go for a commandline utility that could set the brightness. There are several ways this can be implemented:
- the driver offers screen brightness setting through ACPI (via /sys/class/backlight, should work on most laptops)
- the driver offers a backlight control via X11
- the driver offers an i2c device (/dev/i2c-*, can be used with ddccontrol)
- using VESA BIOS Extensions functions (which works by mapping the video card memory and often using real mode calls, which might not support setting brightness, not 100% sure about that though)
- using setpci (this is not recommended)
All of those methods end up using
DCC/CI in the end I
guess. Sadly, with the proprietary AMD driver I was using, none of those
options were working. The solution was to get rid of it and go back to
the open source radeon driver. Minor downside of that: I had to disable
the desktop compositor because it was tearing like crazy (Xfce, uses
Xrender which doesn't do VSync). The radeon driver offers an i2c
interface (after loading the i2c-dev kernel module), so I'm quite happy
there's at least one method that works now. To set the brightness I use
ddccontrol:
ddccontrol -r 0x10 -w 30 dev:/dev/i2c-2
The argument to -r being the Command Interface function and the value
after -w being the new value/brightness. You can use gddccontrol to
easily find out what functions your monitor offers.
For my convenience, I of course wrote a small Python script with some
profiles to quickly change the brightness:
#!/usr/bin/env python3
"""
Change screen brightness through DDC/CI using ddccontrol
sudo ddccontrol -r 0x10 -w 20 dev:/dev/i2c-4
-r: control to query
-w: value to write
Controls:
0x10: Brightness (0-100)
0x12: Contrast (0-100)
0xd6: DPMS (1=on, 4=standby)
Devices:
i2c-2: U2713HM
i2c-4: SyncMaster 2253LW
"""
devs = {0: "dev:/dev/i2c-2", 1: "dev:/dev/i2c-4"}
presets = {"default": [4, None],
"normal": [4, 20],
"sun": [100, 100],
"movie": [30, None],
"movie2": [60, None]}
import argparse
p = argparse.ArgumentParser("br – monitor brightness changer")
p.add_argument("-m", "--monitor", type=int, choices=devs.keys(), default=0)
p.add_argument("-b", "--brightness", type=int, choices=range(0, 100+1))
p.add_argument("preset", nargs="?", choices=presets.keys(), default="default")
args = p.parse_args()
def br(dev, brightness):
from subprocess import call
cmd = ["sudo", "ddccontrol", "-r", "0x10", "-w", str(brightness), dev]
print(" ".join(cmd))
return call(cmd)
if args.brightness:
if args.monitor is not None:
br(devs[args.monitor], args.brightness)
else:
for dev in devs.values():
br(dev, args.brightness)
else:
for idx, dev in devs.items():
preset = presets[args.preset][idx]
if preset is None:
continue
br(dev, preset)