01 Jan 2020
ddcutil is a program for messing with monitor settings. Brightness and colour levels and all that and ‒ the one I’m interested in ‒ input source. It works by magic. Or, as
ddcutil’s docs put it:
ddcutil primarily uses DDC/CI (Display Data Channel Command Interface) to communicate with monitors implementing MCCS (Monitor Control Command Set) over I2C.
Whatever that means.
ddcutil will only work if the monitor supports that stuff. Reading around suggests that most but not all do.
ddcutil will not work on laptops as they use a different interface.
Its usefulness for me is that I have a Nintendo Switch plugged into my main monitor as well as my PC. When I want to play on my Switch, rather than leaning over my desk and using the super fiddly buttons on the front of my monitor, I can just hit a key combo to switch between the DisplayPort input my PC uses and the HDMI used by my Switch.
The same approach could be applied to VFIO passthrough setups or just, as mentioned above, for adjusting brightness and so on.
ddcutil the i2c-dev module must be loaded. On some distros it’s built into the kernel, if it’s not it’ll need to be explicitly loaded.
To check whether i2c-dev is built in, run:
grep i2c-dev.ko /lib/modules/`uname -r`/modules.builtin
If you get output then you’re all good. If not then you need to explicitly load the module by adding the line
/etc/modules or create a file containing that line in
In my case, on Arch, the module was not included in the kernel so I created the file
/etc/modules-load.d/i2c-dev.conf containing the single line:
That’ll only take effect next time you reboot so for now you can load the module directly with:
sudo modprobe i2c_dev
Once the i2c_dev module is loaded we can do:
sudo ddcutil detect
To detect monitors. The output in my case is:
Display 1 I2C bus: /dev/i2c-5 EDID synopsis: Mfg id: DEL Model: DELL U2715H Serial number: GH85D67S05JS Manufacture year: 2016 EDID version: 1.4 VCP version: 2.1
If you’ve got multiple monitors, pay attention to that
Display number ‒ you’ll need to use that with subsequent commands. So if you want to operate on display 2, for example, wherever I use
ddcutil, you’ll want to use
ddcutil -d 2.
Once you’ve settled on a display, run:
sudo ddcutil capabilities
Which will output a load of stuff that
ddcutil can mess with on the monitor.
The one I’m interested in is Feature 60 (Input Source) (I believe feature codes are common across devices but don’t take my word for that).
Feature: 60 (Input Source) Values: 0f: DisplayPort-1 10: DisplayPort-2 11: HDMI-1 12: HDMI-2
There we see feature code 60 with its possible values and what they mean.
We can get the current value of any particular feature by using
ddcutil getvcp. Feature codes are hexidecimal and need to be prepended with
0x when used in commands. So to get the current input source we can do:
sudo ddcutil getvcp 0x60
VCP code 0x60 (Input Source ): DisplayPort-2 (sl=0x10)
We can change settings with
ddcutil setvcp. So, if I want to switch to HDMI 2, which has the code 12 in the output up above, we can do:
sudo ddcutil setvcp 0x60 0x12
And my monitor will switch over to HDMI input. It takes a couple of seconds but it works. Magic.
So to make this super-useful to me I wrote a little bash script which toggles between DisplayPort 2 (my PC) and HDMI 2 (my Switch) and bound it to a key combo:
#!/usr/bin/env bash notify-send "Switching..." if sudo ddcutil getvcp 0x60 | grep "DisplayPort" > /dev/null 2>&1;then sudo ddcutil setvcp 0x60 0x12 else sudo ddcutil setvcp 0x60 0x10 fi
As you can see,
ddcutil requires root permissions to do its thing. You can handle this in whatever way you like in any scripts you make ‒ I just use sudo because I am not clever like you are.