Thursday, January 17, 2019

Saturday, January 05, 2019

i2c on your unused/legacy VGA output

Almost every PC/notebook still has a VGA connector, which can be used as a very cheap way to quickly test various i2c peripherals. On a VGA connector, it would have been used to query the remote monitor for its supported resolutions, but most graphics drivers in Linux just use the
kernel's generic i2c support.

This is a quick note for myself, so that I can easily copy & paste whenever needed again ;-).

From the linked Wikipedia page:

Pin 9 KEY/PWR formerly key, now +5V DC, powers EDID EEPROM chip on some monitors
Pin 10 GND Ground (VSync, DDC)
Pin 12 ID1/SDA formerly Monitor ID bit 1, I²C data since DDC2
Pin 15 ID3/SCL formerly Monitor ID bit 3, I²C clock since DDC2

Step 1, make sure your graphics card actually exports this i2c device (check the names of all busses in /sys/bus/i2c/devices).

$ grep "" /sys/bus/i2c/devices/i2c-*/name
/sys/bus/i2c/devices/i2c-0/name:SMBus I801 adapter at 0580
/sys/bus/i2c/devices/i2c-1/name:i915 gmbus ssc
/sys/bus/i2c/devices/i2c-2/name:i915 gmbus vga
/sys/bus/i2c/devices/i2c-3/name:i915 gmbus panel
/sys/bus/i2c/devices/i2c-4/name:i915 gmbus dpc
/sys/bus/i2c/devices/i2c-5/name:i915 gmbus dpb
/sys/bus/i2c/devices/i2c-6/name:i915 gmbus dpd
/sys/bus/i2c/devices/i2c-7/name:DPDDC-B
/sys/bus/i2c/devices/i2c-8/name:DPDDC-C



Step 2, make sure a user can conveniently access this bus without becoming root.

$ cat /etc/udev/rules.d/99-i2c-vga-chmod.rules 
ACTION=="add", SUBSYSTEM=="i2c-dev", ATTR{name}=="i915 gmbus vga", MODE="0660", GROUP="users", SYMLINK+="i2c-vga"

#
# udevadm info -a -p \$(udevadm info -q path -n /dev/i2c-2)
#
# Udevadm info starts with the device specified by the devpath and then
# walks up the chain of parent devices. It prints for every device
# found, all possible attributes in the udev rules key format.
# A rule to match, can be composed by the attributes of the device
# and the attributes from one single parent device.

#   looking at device '/devices/pci0000:00/0000:00:02.0/i2c-2/i2c-dev/i2c-2':
#     KERNEL=="i2c-2"
#     SUBSYSTEM=="i2c-dev"
#     DRIVER==""
#     ATTR{name}=="i915 gmbus vga"

#   looking at parent device '/devices/pci0000:00/0000:00:02.0/i2c-2':
#     KERNELS=="i2c-2"
#     SUBSYSTEMS=="i2c"
#     DRIVERS==""
#     ATTRS{name}=="i915 gmbus vga"
(...)

Step 3, make sure the i2c-dev kernel module is loaded upon boot.

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

i2c-dev

Step 4, solder a matching cable from 15pin DSUB to whatever is convenient for you, I suggest some individual connectors for pin headers.




Step5, Profit!

(I'm using a HYT271 humidity and gemperature sensor for testing, it's showing 39 %rh and 26 °C, the small utility is by David Wragg and to be found on github.)





It should be noted that this will obviously work almost identical on DVI/DisplayPort/HDMI outputs, your motherboard's SMBUS, your random USB peripheral that exposes an i2c bus, ...

A quick warning, these i2c-busses are often bit-banged and will consume a considerable amount of cycles on your 3Ghz Octacore i7 while clocking out a few kBits/second via i2c. :-)