diff --git a/Controllers/TForceXtreemController/RGBController_TForceXtreem.cpp b/Controllers/TForceXtreemController/RGBController_TForceXtreem.cpp index 0622582d3..268554e39 100644 --- a/Controllers/TForceXtreemController/RGBController_TForceXtreem.cpp +++ b/Controllers/TForceXtreemController/RGBController_TForceXtreem.cpp @@ -14,24 +14,25 @@ #include "ResourceManager.h" /**------------------------------------------------------------------*\ - @name T-Force Xtreem + @name T-Force Xtreem / Delta @category RAM @type SMBus @save :white_check_mark: @direct :white_check_mark: @effects :white_check_mark: - @detectors DetectTForceXtreemControllers + @detectors DetectTForceXtreemControllers,DetectTForceDeltaControllers @comment Verified models: TeamGroup T-Force Xtreem ARGB DDR4 + TeamGroup T-Force Delta RGB DDR5 \*-------------------------------------------------------------------*/ -RGBController_TForceXtreem::RGBController_TForceXtreem(TForceXtreemController * controller_ptr) +RGBController_TForceXtreem::RGBController_TForceXtreem(TForceXtreemController * controller_ptr, const std::string& device_name) { controller = controller_ptr; type = DEVICE_TYPE_DRAM; - name = "T-Force Xtreem RGB"; + name = device_name; vendor = "TeamGroup"; location = controller->GetDeviceLocation(); @@ -416,15 +417,17 @@ void RGBController_TForceXtreem::UpdateSingleLED(int led) void RGBController_TForceXtreem::SetupZones() { + unsigned int led_count = controller->GetLEDCount(); + /*---------------------------------------------------------*\ | Set up zone | \*---------------------------------------------------------*/ zone new_zone; new_zone.name = "DRAM"; new_zone.type = ZONE_TYPE_LINEAR; - new_zone.leds_min = XTREEM_LED_COUNT; - new_zone.leds_max = XTREEM_LED_COUNT; - new_zone.leds_count = XTREEM_LED_COUNT; + new_zone.leds_min = led_count; + new_zone.leds_max = led_count; + new_zone.leds_count = led_count; new_zone.matrix_map = NULL; zones.push_back(new_zone); @@ -436,6 +439,7 @@ void RGBController_TForceXtreem::SetupZones() led new_led; new_led.name = "DRAM LED "; new_led.name.append(std::to_string(led_idx)); + new_led.value = led_idx; leds.push_back(new_led); } diff --git a/Controllers/TForceXtreemController/RGBController_TForceXtreem.h b/Controllers/TForceXtreemController/RGBController_TForceXtreem.h index 40b2b87cc..a9fefe1e9 100644 --- a/Controllers/TForceXtreemController/RGBController_TForceXtreem.h +++ b/Controllers/TForceXtreemController/RGBController_TForceXtreem.h @@ -11,13 +11,14 @@ #pragma once +#include #include "RGBController.h" #include "TForceXtreemController.h" class RGBController_TForceXtreem : public RGBController { public: - RGBController_TForceXtreem(TForceXtreemController* controller_ptr); + RGBController_TForceXtreem(TForceXtreemController* controller_ptr, const std::string& device_name = "T-Force Xtreem RGB"); ~RGBController_TForceXtreem(); void SetupZones(); diff --git a/Controllers/TForceXtreemController/TForceXtreemController.cpp b/Controllers/TForceXtreemController/TForceXtreemController.cpp index 63e3f50d3..d77658d8c 100644 --- a/Controllers/TForceXtreemController/TForceXtreemController.cpp +++ b/Controllers/TForceXtreemController/TForceXtreemController.cpp @@ -13,10 +13,12 @@ #include "TForceXtreemController.h" #include "LogManager.h" -TForceXtreemController::TForceXtreemController(i2c_smbus_interface *bus, ene_dev_id dev) +TForceXtreemController::TForceXtreemController(i2c_smbus_interface *bus, ene_dev_id dev, unsigned int led_count, bool folded) { this->bus = bus; this->dev = dev; + this->led_count = led_count; + this->folded = folded; } TForceXtreemController::~TForceXtreemController() @@ -37,59 +39,66 @@ std::string TForceXtreemController::GetDeviceLocation() unsigned int TForceXtreemController::GetLEDCount() { - return(XTREEM_LED_COUNT); + return(led_count); } -/*---------------------------------------------------*\ -| LEDs are in a single strip that is folded in half. | -| That makes the LED order: 0-14-1-13-2-...-7-9-8 | -\*---------------------------------------------------*/ -#define XTREEM_LED_OFFSET(x) ((((x) & 0x01) > 0) ? XTREEM_LED_COUNT - 1 - ((x) >> 1) : ((x) >> 1)) +/*-----------------------------------------------------------*\ +| For folded strips (e.g. Xtreem), LEDs are in a single strip | +| folded in half, giving order: 0-(N-1)-1-(N-2)-2-... | +| For linear strips (e.g. Delta), offset is simply the index. | +\*-----------------------------------------------------------*/ +unsigned int TForceXtreemController::GetLEDOffset(unsigned int led) +{ + if(folded) + return (led & 0x01) ? led_count - 1 - (led >> 1) : (led >> 1); + else + return led; +} unsigned char TForceXtreemController::GetLEDRed(unsigned int led) { - return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ))); + return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * GetLEDOffset(led) ))); } unsigned char TForceXtreemController::GetLEDGreen(unsigned int led) { - return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 2)); + return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * GetLEDOffset(led) ) + 2)); } unsigned char TForceXtreemController::GetLEDBlue(unsigned int led) { - return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 1)); + return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * GetLEDOffset(led) ) + 1)); } unsigned char TForceXtreemController::GetLEDRedEffect(unsigned int led) { - return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * XTREEM_LED_OFFSET(led) ))); + return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * GetLEDOffset(led) ))); } unsigned char TForceXtreemController::GetLEDGreenEffect(unsigned int led) { - return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 2)); + return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * GetLEDOffset(led) ) + 2)); } unsigned char TForceXtreemController::GetLEDBlueEffect(unsigned int led) { - return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 1)); + return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * GetLEDOffset(led) ) + 1)); } void TForceXtreemController::SetAllColorsDirect(RGBColor* colors) { - unsigned char* color_buf = new unsigned char[XTREEM_LED_COUNT * 3]; + unsigned char* color_buf = new unsigned char[led_count * 3]; unsigned int bytes_sent = 0; - for(unsigned int i = 0; i < XTREEM_LED_COUNT; i++) + for(unsigned int i = 0; i < led_count; i++) { - unsigned int offset = 3 * XTREEM_LED_OFFSET(i); + unsigned int offset = 3 * GetLEDOffset(i); color_buf[offset + 0] = RGBGetRValue(colors[i]); color_buf[offset + 1] = RGBGetBValue(colors[i]); color_buf[offset + 2] = RGBGetGValue(colors[i]); } - while(bytes_sent < (XTREEM_LED_COUNT * 3)) + while(bytes_sent < (led_count * 3)) { ENERegisterWriteBlock(XTREEM_REG_COLORS_DIRECT + bytes_sent, &color_buf[bytes_sent], 3); @@ -101,18 +110,18 @@ void TForceXtreemController::SetAllColorsDirect(RGBColor* colors) void TForceXtreemController::SetAllColorsEffect(RGBColor* colors) { - unsigned char* color_buf = new unsigned char[XTREEM_LED_COUNT * 3]; + unsigned char* color_buf = new unsigned char[led_count * 3]; unsigned int bytes_sent = 0; - for(unsigned int i = 0; i < XTREEM_LED_COUNT; i++) + for(unsigned int i = 0; i < led_count; i++) { - unsigned int offset = 3 * XTREEM_LED_OFFSET(i); + unsigned int offset = 3 * GetLEDOffset(i); color_buf[offset + 0] = RGBGetRValue(colors[i]); color_buf[offset + 1] = RGBGetBValue(colors[i]); color_buf[offset + 2] = RGBGetGValue(colors[i]); } - while(bytes_sent < (XTREEM_LED_COUNT * 3)) + while(bytes_sent < (led_count * 3)) { ENERegisterWriteBlock(XTREEM_REG_COLORS_EFFECT + bytes_sent, &color_buf[bytes_sent], 3); @@ -135,14 +144,14 @@ void TForceXtreemController::SetLEDColorDirect(unsigned int led, unsigned char r { unsigned char colors[3] = { red, blue, green }; - ENERegisterWriteBlock(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ), colors, 3); + ENERegisterWriteBlock(XTREEM_REG_COLORS_DIRECT + ( 3 * GetLEDOffset(led) ), colors, 3); } void TForceXtreemController::SetLEDColorEffect(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) { unsigned char colors[3] = { red, blue, green }; - ENERegisterWriteBlock(XTREEM_REG_COLORS_EFFECT + (3 * XTREEM_LED_OFFSET(led)), colors, 3); + ENERegisterWriteBlock(XTREEM_REG_COLORS_EFFECT + (3 * GetLEDOffset(led)), colors, 3); ENERegisterWrite(XTREEM_REG_APPLY, XTREEM_APPLY_VAL); } diff --git a/Controllers/TForceXtreemController/TForceXtreemController.h b/Controllers/TForceXtreemController/TForceXtreemController.h index 1ca872632..90ced68da 100644 --- a/Controllers/TForceXtreemController/TForceXtreemController.h +++ b/Controllers/TForceXtreemController/TForceXtreemController.h @@ -17,6 +17,7 @@ #define XTREEM_APPLY_VAL 0x01 /* Value for Apply Changes Register */ #define XTREEM_LED_COUNT 15 +#define DELTA_LED_COUNT 8 typedef unsigned short ene_register; typedef unsigned char ene_dev_id; @@ -83,7 +84,7 @@ enum class TForceXtreemController { public: - TForceXtreemController(i2c_smbus_interface *bus, ene_dev_id dev); + TForceXtreemController(i2c_smbus_interface *bus, ene_dev_id dev, unsigned int led_count = XTREEM_LED_COUNT, bool folded = true); ~TForceXtreemController(); std::string GetDeviceLocation(); @@ -106,6 +107,10 @@ class TForceXtreemController void ENERegisterWriteBlock(ene_register reg, unsigned char * data, unsigned char sz); private: + unsigned int GetLEDOffset(unsigned int led); + i2c_smbus_interface * bus; ene_dev_id dev; + unsigned int led_count; + bool folded; }; diff --git a/Controllers/TForceXtreemController/TForceXtreemControllerDetect.cpp b/Controllers/TForceXtreemController/TForceXtreemControllerDetect.cpp index 1423f6627..f955b17f4 100644 --- a/Controllers/TForceXtreemController/TForceXtreemControllerDetect.cpp +++ b/Controllers/TForceXtreemController/TForceXtreemControllerDetect.cpp @@ -13,6 +13,7 @@ #include "LogManager.h" #include "RGBController_TForceXtreem.h" #include "i2c_smbus.h" +#include "pci_ids.h" #define DETECTOR_NAME "TForce Xtreem Controller" @@ -114,21 +115,67 @@ bool TestForTForceXtreemController(i2c_smbus_interface* bus, unsigned char addre /******************************************************************************************\ * * -* DetectTForceXtreemDRAMControllers * +* TestForTForceDeltaController * * * -* Detects T-Force Xtreem controllers on DRAM devices * -* * -* bus - pointer to i2c_smbus_interface where device is connected * -* slots - SPD accessors to occupied slots * +* Tests the given address to see if an ENE controller exists there using the * +* standard ENE test pattern (0xA0-0xAF incrementing 0x00-0x0F). The Delta DDR5 * +* does not respond to the Xtreem-specific test at 0x90-0xA0. * * * \******************************************************************************************/ -void DetectTForceXtreemControllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &/*name*/) +static bool TestForTForceDeltaController(i2c_smbus_interface* bus, unsigned char address) { + bool pass = false; + + LOG_DEBUG("[%s] looking for Delta DDR5 devices at 0x%02X...", DETECTOR_NAME, address); + + int res = bus->i2c_smbus_read_byte(address); + + if(res < 0) + { + res = bus->i2c_smbus_read_byte_data(address, 0x00); + } + + if(res >= 0) + { + pass = true; + + LOG_DEBUG("[%s] Detected an I2C device at address %02X, testing ENE register range", DETECTOR_NAME, address); + + for(int i = 0xA0; i < 0xB0; i++) + { + res = bus->i2c_smbus_read_byte_data(address, i); + + if(res != (i - 0xA0)) + { + LOG_VERBOSE("[%s] Delta detection failed testing register %02X. Expected %02X, got %02X.", DETECTOR_NAME, i, (i - 0xA0), res); + + pass = false; + break; + } + } + } + + return(pass); + +} /* TestForTForceDeltaController() */ + +/******************************************************************************************\ +* * +* RemapENERamModules * +* * +* Remaps ENE RAM modules from the default 0x77 master address to individual * +* per-slot addresses from the xtreem_ram_addresses list. * +* * +\******************************************************************************************/ +typedef bool (*ENETestFunction)(i2c_smbus_interface*, unsigned char); + +static void RemapENERamModules(i2c_smbus_interface* bus, std::vector& slots, ENETestFunction test_func) +{ LOG_DEBUG("[%s] Remapping ENE SMBus RAM modules on 0x77", DETECTOR_NAME); - for(SPDWrapper *slot : slots) + for(SPDWrapper* slot : slots) { int address_list_idx = slot->index() - 1; int res; @@ -136,7 +183,7 @@ void DetectTForceXtreemControllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &/*name*/) +{ + RemapENERamModules(bus, slots, TestForTForceXtreemController); // Add ENE controllers at their remapped addresses for(unsigned int address_list_idx = 0; address_list_idx < XTREEM_RAM_ADDRESS_COUNT; address_list_idx++) @@ -181,4 +244,88 @@ void DetectTForceXtreemControllers(i2c_smbus_interface* bus, std::vector &busses) +{ + for(unsigned int bus = 0; bus < busses.size(); bus++) + { + int address_list_idx = -1; + + IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + { + LOG_DEBUG("[T-Force Delta DDR5] Remapping ENE SMBus RAM modules on 0x77"); + + for(unsigned int slot = 0; slot < 8; slot++) + { + if(!TestForTForceDeltaController(busses[bus], 0x77)) + { + LOG_DEBUG("[T-Force Delta DDR5] No device detected at 0x77, aborting remap"); + break; + } + + do + { + address_list_idx++; + + if(address_list_idx < XTREEM_RAM_ADDRESS_COUNT) + { + LOG_DEBUG("[T-Force Delta DDR5] Testing address %02X to see if there is a device there", xtreem_ram_addresses[address_list_idx]); + + int res = busses[bus]->i2c_smbus_write_quick(xtreem_ram_addresses[address_list_idx], I2C_SMBUS_WRITE); + + if(res < 0) + { + break; + } + } + else + { + break; + } + } while(true); + + if(address_list_idx < XTREEM_RAM_ADDRESS_COUNT) + { + LOG_DEBUG("[T-Force Delta DDR5] Remapping slot %d to address %02X", slot, xtreem_ram_addresses[address_list_idx]); + + XtreemRegisterWrite(busses[bus], 0x77, XTREEM_REG_SLOT_INDEX, slot); + XtreemRegisterWrite(busses[bus], 0x77, XTREEM_REG_I2C_ADDRESS, (xtreem_ram_addresses[address_list_idx] << 1)); + } + } + + // Add controllers at their remapped addresses + for(unsigned int addr_idx = 0; addr_idx < XTREEM_RAM_ADDRESS_COUNT; addr_idx++) + { + if(TestForTForceDeltaController(busses[bus], xtreem_ram_addresses[addr_idx])) + { + TForceXtreemController* controller = new TForceXtreemController(busses[bus], xtreem_ram_addresses[addr_idx], DELTA_LED_COUNT, false); + RGBController_TForceXtreem* rgb_controller = new RGBController_TForceXtreem(controller, "T-Force Delta RGB"); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + + std::this_thread::sleep_for(1ms); + } + } + } +} /* DetectTForceDeltaDRAMControllers() */ + REGISTER_I2C_DIMM_DETECTOR("T-Force Xtreem DDR4 DRAM", DetectTForceXtreemControllers, JEDEC_TEAMGROUP, SPD_DDR4_SDRAM); +REGISTER_I2C_DETECTOR("T-Force Delta DDR5 DRAM", DetectTForceDeltaDRAMControllers);