multun / blog

3 stars 2 forks source link

Porting a ram stick LED driver from windows to linux #6

Open multun opened 2 years ago

multun commented 2 years ago

https://linuxfr.org/users/benoar/journaux/des-dimms-ddr-rgb-en-smbus-vraiment-pita

https://gitlab.com/CalcProgrammer1/OpenRGB/-/issues/2375

The low level bridge between the C# and kernel seems to be from this company https://www.cpuid-pro.com/products-system-information-kit.php

The kernel driver

LLAccessLib

LLAccessService

The LLAccessService service protocol

Userland SMBus drivers

Due to the lack of ready made kernel-land drivers, iCUE implements userland SMBus drivers for common controllers using their kernel RPC in LLAccessService

datasheet: https://www.intel.com/Assets/PDF/datasheet/290562.pdf

linux driver: https://github.com/torvalds/linux/blob/master/drivers/i2c/busses/i2c-piix4.c

Userland ee1004 driver

Making SMBus work on my motherboard

loading the correct module does nothing

[19722.892945] ACPI Warning: SystemIO range 0x0000000000000B00-0x0000000000000B08 conflicts with OpRegion 0x0000000000000B00-0x0000000000000B0F (\GSA1.SMBI) (20211217/utaddress-204)
[19722.892952] ACPI: OSL: Resource conflict; ACPI support missing from driver?

Turns out an SMBus driver inside the ACPI tables conflicts with the kernel's driver. https://uefi.org/specs/ACPI/6.4/13_ACPI_System_Mgmt_Bus_Interface_Spec/using-the-smbus-protocols.html https://github.com/Lekensteyn/acpi-stuff/blob/master/notes.txt https://lwn.net/Articles/391230/

The ACPI smbus driver is called from WMI stuff https://docs.microsoft.com/en-us/previous-versions/windows/hardware/design/dn614028(v=vs.85)?redirectedfrom=MSDN#E6OAC https://paste.awesom.eu/Zelj&ln

The chosen path is to use the already existing kernel driver. Unfortunately, the current driver does not implement auto-probing. https://www.spinics.net/lists/linux-i2c/msg32331.html

See code from the eeprom module. ee1004 is for DDR4 spd5118 is for DDR5 (somebody wrote a driver => source)

iCUE's C# LED driver

iCUE is a mix of qt5 and C#. It seems like a migration is in progress, and fortunately, support for my device was already migrated to C#. The probing part is done in CorsairLink4.Module.Dram.DramLedFactory.GetDramLedDevices.

There are three types of LED controllers: RBG, SingleLed, or RBGPro. The type of the controller is detected by first probing 0x58 to 0x60, then by parsing the serial number from SPD metadata (It seems like it should really be done the other way around, if the SMBus address of the controller can be deduced from SPD metadata).

https://en.wikipedia.org/wiki/Serial_presence_detect

Single LED driver

There are two known modes:

def ConvertBrightness(percentage):
    return int((100 - input) / 100 * 63)

For example, this command turns off the LED for a single LED module:

sudo modprobe i2c-dev
sudo i2cset 0 "${DEV_ADDR}" 160 63 b