0

I am building custom game controllers on Linux that use the i2c bus present in video ports such as HDMI, dvi, and VGA, on standard PC hardware (x86_64).

I would like to verify my current i2c bus speed settings, and maybe change them. As I would understand it, this would be a setting of a Linux kernel driver, though I haven't figured it out yet, so maybe I'm way off on this.

So what I tried is:

lsmod | grep i2c i2c_algo_bit 16384 1 i915 i2c_i801 36864 0 i2c_smbus 20480 1 i2c_i801 

ok the i2c_algo_bit is the device I am using (I think), looked at i2c_smbus also.

modinfo i915 modinfo i915 | grep -i "baud \| freq \| hz \| rate \| speed" 

I tried reading the module info for i2c-i801, and i915 but I don't see anything indicative of the currently set bus speed. I2c, (DDC) has several possible settings, from 50kHz to 400kHz. I would like to set it to 400kHz if it is not already set to that.

How do I verify the frequency of the i2c bus? and how do I change it?

1
  • The i2c bus doesn't really have a fixed speed. Every device can have a different maximum speed, and the speed is negotiated at the start of the controller/target interaction. Also, bus characteristics (like impedance and pull up power) can limit the speed. So you need to frame your question differently -- given two devices on the bus, what is their maximum speed? Commented Apr 27 at 19:14

2 Answers 2

1

I looked into this for a 6.8.0 series Kernel, since that is what currently have on a Ubuntu 24.04.2 LTS system.

The system used a Quadro K4200 video card which exposes a I2C bus which can read the identity of attached monitor:

$ sudo i2cdump -y -r 0-0x7f 1 0x50 c | tail -8 | cut -b 5-51 | edid-decode edid-decode (hex): 00 ff ff ff ff ff ff 00 22 f0 6a 28 01 01 01 01 02 15 01 03 80 36 23 78 2e fc 81 a4 55 4d 9d 25 12 50 54 21 08 00 81 40 81 80 95 00 a9 40 b3 00 d1 c0 01 01 01 01 28 3c 80 a0 70 b0 23 40 30 20 36 00 22 60 21 00 00 1a 00 00 00 fd 00 3b 3d 18 50 11 00 0a 20 20 20 20 20 20 00 00 00 fc 00 48 50 20 5a 52 32 34 77 0a 20 20 20 20 00 00 00 ff 00 43 4e 54 31 30 32 31 34 30 36 0a 20 20 00 83 ---------------- Block 0, Base EDID: EDID Structure Version & Revision: 1.3 Vendor & Product Identification: Manufacturer: HWP Model: 10346 Serial Number: 16843009 Made in: week 2 of 2011 Basic Display Parameters & Features: Digital display Maximum image size: 54 cm x 35 cm Gamma: 2.20 DPMS levels: Off RGB color display Default (sRGB) color space is primary color space First detailed timing is the preferred timing Color Characteristics: Red : 0.6435, 0.3349 Green: 0.3037, 0.6132 Blue : 0.1464, 0.0703 White: 0.3125, 0.3291 Established Timings I & II: DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz DMT 0x09: 800x600 60.316541 Hz 4:3 37.879 kHz 40.000000 MHz DMT 0x10: 1024x768 60.003840 Hz 4:3 48.363 kHz 65.000000 MHz Standard Timings: DMT 0x20: 1280x960 60.000000 Hz 4:3 60.000 kHz 108.000000 MHz DMT 0x23: 1280x1024 60.019740 Hz 5:4 63.981 kHz 108.000000 MHz DMT 0x2f: 1440x900 59.887445 Hz 16:10 55.935 kHz 106.500000 MHz DMT 0x33: 1600x1200 60.000000 Hz 4:3 75.000 kHz 162.000000 MHz DMT 0x3a: 1680x1050 59.954250 Hz 16:10 65.290 kHz 146.250000 MHz DMT 0x52: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz Detailed Timing Descriptors: DTD 1: 1920x1200 59.950171 Hz 8:5 74.038 kHz 154.000000 MHz (546 mm x 352 mm) Hfront 48 Hsync 32 Hback 80 Hpol P Vfront 3 Vsync 6 Vback 26 Vpol N Display Range Limits: Monitor ranges (GTF): 59-61 Hz V, 24-80 kHz H, max dotclock 170 MHz Display Product Name: 'HP ZR24w' Display Product Serial Number: 'CNT1021406' Checksum: 0x83 

The Quadro K4200 uses the nouveau driver, which also has a dependency on the i2c-algo-bit module, as does the i915 driver from the question.

Looking under /sys/class/i2c-adapter for the I2C buses provided by the Quadro K4200, I can't see any files available to user space which define the I2C bus speed.

The i2c-algo-bit.c source code shows this a software bit-banged driver where software controls the individual SCL and SDA signals on the I2C bus with software used to insert minimum delays between toggling of the signals on the I2C bus.

struct i2c_algo_bit_data has the following field which is used control the software timing:

 int udelay; /* half clock cycle time in us, minimum 2 us for fast-mode I2C, minimum 5 us for standard-mode I2C and SMBus, maximum 50 us for SMBus */ 

The functions in i2c-algo-bit.c have calls to udelay(), sometimes delaying for adap->udelay and other times (adap->udelay + 1) / 2.

The i915/display/intel_gmbus.c driver used in the question hard-codes the I2C bus speed with the following macro:

#define I2C_RISEFALL_TIME 10 

Which is used in the intel_gpio_setup function to initialise the i2c_algo_bit_data udelay:

 algo->udelay = I2C_RISEFALL_TIME; 

Therefore, the I2C bus speed used by the i915 will be a maximum of 50 kHz (since the half clock cycle time is hard coded as 10 microseconds). The actual bus speed will probably be lower, due to software delays used to control the timing.

The nouveau driver used for the Quadro K4200 also hard codes the same udelay value for the i2c-algo-bit module, in the nvkm_i2c_bus_ctor function in nouveau/nvkm/subdev/i2c/bus.c

1

The DDC standard says that hardware must support 100 kHz clock rate, and that only the graphics adapter can be the (clock) master of the I²C bus there. So, your device needs to be able to work at any speed of 100 kHz and below, including I²C-funky things like clock stretching. (Never implement I²C yourself in software. If your microcontroller has no I²C peripheral, use a different microcontroller, or use a different bus.)

If I might have one word of advice:

Don't.

I used to do technical support for an embedded device that had its own EEPROMs on the same I²C bus that was also used for the mini-HDMI header it had in the front.

Sometimes (as in: multiple independent clients of mine) using the graphical user interface while the hardware backend was querying hardware properties from the internal EEPROMs led to the EEPROMs misinterpreting replies from the EDID-containing screen memory as write commands, due to colliding timing of bus interactions.

And that was with devices that were specialist devices, where such bus transactions would not happen more than once a minute, maybe. Extrapolate to how many transactions your controller will cause, and how likely it is that you'll clash with the actual function of DDC and make a user have a really bad day.

Graphics card drivers often just bitbang I²C buses, and they can't be aware of multi-transfer transactions on the I²C bus.

Don't try to hang a game controller off screen interface. That will only end in tears, it requires very questionable privileges for any software that needs to interact with the controller, and I²C-to-USB adapters are < 2€ at even the most expensive but trustworthy electronics distributors; no way your "I buy a display connector, find an unused graphics card port or build a pass-through device that still works although video signals are extremely high-bandwidth, sensitive signals" comes even close to the cost of that.

If you're building a game controller for a 1980's console, maybe consider the specific buses that these consoles had – you'd be writing very custom low-level software for them anyways.

More realistically, just make your custom game controller's microcontroller speak USB directly. The Human Interface Device class is about the simplest thing you can implement in USB. All relevant microcontroller families you'd use for anything that's not going to be produced by the millions or needs to persist on microwatts contain members that have USB hardware built in. Literally any microcontroller has a UART interface, if you need something you can plug into the back of your original IBM PC.

2
  • Its already built, and working. graphics, are looking for address 50 via poling, which is why video devices are hot pluggable, despite garnering that functionality from a non hot plug technology. but I am only asking how to verify, and maybe increase the frequency. Commented Apr 28 at 2:14
  • you can't, standard-wise, increase the frequency, and it's not usually a setting that can be adjusted; this is something every graphic cards driver and/or graphics card implements differently, usually; the fact that you can use your specific card's DDC as general I²C bus is lucky, already! Also, honestly, simply the wrong bus if you need more data rate. Well, I've warned you about the consequences of doing this in the wild from professional experience – all I can do. Commented Apr 28 at 9:28

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.