Controlling Monitor Settings with ddcutil

ddcutil is an application that helps you with managing monitor setting. In a laptop you can control your screen brightness with key or some utility application in your gui. In standalone monitor this level of integration is simply unheard. But not because they are incapable of, just because nobody really bothered to implement them in systems I guess.

As per the ddcutil documentation most monitors since 2000 supports DDC/CI communication. This system allows us to change monitor brightness, edit color setttings or change input sources.

My main needs for this integration was;

  • Change brightness
    • By buttons
    • Based on time of day
  • Change input source if I boot up a new device

Prerequisites

First of all we need to install ddcutil.

sudo apt install ddcutil

The communication runs over i2c so we will need to have i2c-dev module loaded in our system as well. We can load it across reboot by creating a file at /etc/modules-load.d/i2c-dev.conf with contents below:

i2c-dev
/etc/modules-load.d/i2c-dev.conf

and load it right away with using

sudo modprobe i2c-dev

Testing ddcutil

To test ddcutil we can list capable displays with

test
sudo ddcutil detect

will produce something like below a standalone monitor that is capable and a laptop display that is not. The meaningful areas are I2C bus id 3 which will be the target whenever we need to control the display. If any error shows up about your display like my laptop display did your monitor does not support ddc.

sudo ddcutil detect
Display 1
   I2C bus:             /dev/i2c-3
   EDID synopsis:
      Mfg id:           GSM
      Model:            LG HDR QHD
      Serial number:    007XXXXXXXX
      Manufacture year: 2020
      EDID version:     1.3
   VCP version:         2.1

Invalid display
   I2C bus:             /dev/i2c-13
    ...
   DDC communication failed
   This is an eDP laptop display. Laptop displays do not support DDC/CI.

Setting up permissions

Using ddcutil with root is cumbersome and not really an option for scripts that I want to run unattended. There are two steps to make it non root useable.

First we need to enable assigning devices to i2c group if not enabled. This way any user that belongs to i2c group will be able to use ddcutil without sudo. On my system related file did exist but the related code was commented out.

KERNEL=="i2c-[0-9]*", GROUP="i2c", MODE="0660"
/etc/udev/rules.d/45-ddcutil-i2c.rules

We can add our user to this group by so;

sudo usermod $USER -aG i2c
## Controlling the Monitor To control a capable display first we need to find out what is it really capable of. ddcutil has a function for listing display capabilities and using that I can see that my monitor is capable of changing brightnes and input source (among other things like gamma, color values etc.) which what I want to control. As you can see in the command we pass a `--bus` flag to the command. This bus cam from `ddcutil detect` command and shown at `I2C bus: /dev/i2c-3`. We only need the numeric part for command to function.
ddcutil capabilites --bus=$BUS
...
Feature: 10 (Brightness)
...
Feature: 60 (Input Source)
      Values:
         00: Unrecognized value
         0f: DisplayPort-1
         11: HDMI-1
         12: HDMI-2
...

Scripts

To control my display I created 2 scripts one for changing the input source and the other is changing the brightness.

To change monitor setting we use setvcp followed by capability address, note the 0x part because they are hexadecimal numbers, and the new value we want the monitor to use.

#!/usr/bin/env bash

ddcutil --bus=3 setvcp 0x10 $1 &&
wait 
brightness_control
#!/usr/bin/env bash

ddcutil --bus=3 setvcp 0x60 0x11 &&
wait 
change_input