From 540eaa53660f5c93c48b28ddf40ae14f4a629e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Triszka?= Date: Wed, 22 May 2024 20:50:16 +0000 Subject: [PATCH] EVGA ACX30 Motherboard --- .gitlab/CODEOWNERS | 1 + .../EVGAACX30SMBusController.cpp | 109 ++++++++++++ .../EVGAACX30SMBusController.h | 76 ++++++++ .../EVGASMBusControllerDetect.cpp | 90 ++++++++++ .../RGBController_EVGAACX30SMBus.cpp | 163 ++++++++++++++++++ .../RGBController_EVGAACX30SMBus.h | 35 ++++ 6 files changed, 474 insertions(+) create mode 100644 Controllers/EVGASMBusController/EVGAACX30SMBusController.cpp create mode 100644 Controllers/EVGASMBusController/EVGAACX30SMBusController.h create mode 100644 Controllers/EVGASMBusController/EVGASMBusControllerDetect.cpp create mode 100644 Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.cpp create mode 100644 Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.h diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 64622d28..80cf0f32 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -43,6 +43,7 @@ CODEOWNERS @Calcprogrammer1 /Controllers/EVGAGP102GPUController/ /Controllers/EVGAPascalGPUController/ /Controllers/EVGATuringGPUController/ @TheRogueZeta +/Controllers/EVGASMBusController/ @balika011 /Controllers/EVGAUSBController/ @Dr_No /Controllers/EVisionKeyboardController/ /Controllers/EspurnaController/ diff --git a/Controllers/EVGASMBusController/EVGAACX30SMBusController.cpp b/Controllers/EVGASMBusController/EVGAACX30SMBusController.cpp new file mode 100644 index 00000000..88b82ba7 --- /dev/null +++ b/Controllers/EVGASMBusController/EVGAACX30SMBusController.cpp @@ -0,0 +1,109 @@ +/*---------------------------------------------------------*\ +| EVGAACX30SMBusController.cpp | +| | +| Driver for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "EVGAACX30SMBusController.h" +#include "dmiinfo.h" +#include "LogManager.h" + +using namespace std::chrono_literals; + +EVGAACX30SMBusController::EVGAACX30SMBusController(i2c_smbus_interface *bus, uint8_t dev) +{ + this->bus = bus; + this->dev = dev; + + DMIInfo dmi; + + device_name = "EVGA " + dmi.getMainboard(); +} + +EVGAACX30SMBusController::~EVGAACX30SMBusController() +{ + +} + +std::string EVGAACX30SMBusController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string EVGAACX30SMBusController::GetDeviceName() +{ + return(device_name); +} + +std::string EVGAACX30SMBusController::GetFirmwareVersion() +{ + uint16_t version = bus->i2c_smbus_read_byte_data(dev, ACX30_REG_VER_HIGH) << 8 | bus->i2c_smbus_read_byte_data(dev, ACX30_REG_VER_LOW); + uint8_t ptype = bus->i2c_smbus_read_byte_data(dev, ACX30_REG_PTYPE); + + char ver[9]; + snprintf(ver, 9, "0x%X", version); + char pt[9]; + snprintf(pt, 9, "0x%X", ptype); + + std::string return_string; + return_string.append(ver); + return_string.append(", ptype "); + return_string.append(pt); + return return_string; +} + +uint8_t EVGAACX30SMBusController::GetMode() +{ + return bus->i2c_smbus_read_byte_data(dev, ACX30_REG_MODE); +} + +void EVGAACX30SMBusController::Unlock() +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_CONTROL, 0xE5); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_CONTROL, 0xE9); + bus->i2c_smbus_read_byte_data(dev, ACX30_REG_CONTROL); +} + +void EVGAACX30SMBusController::Lock() +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_CONTROL, 0xE0); + bus->i2c_smbus_read_byte_data(dev, ACX30_REG_CONTROL); +} + +void EVGAACX30SMBusController::SetColors(uint8_t red, uint8_t green, uint8_t blue) +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_RED, red); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_GREEN, green); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_BLUE, blue); +} + +void EVGAACX30SMBusController::SetMode(uint8_t mode) +{ + if (mode == ACX30_MODE_OFF) + { + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_21, 0xE7); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_22, 0xCE); + } + else + { + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_21, 0xE5); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_22, 0xE7); + } + + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_MODE, mode); +} + +void EVGAACX30SMBusController::SetSpeed(uint8_t speed) +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_SPEED, speed); +} diff --git a/Controllers/EVGASMBusController/EVGAACX30SMBusController.h b/Controllers/EVGASMBusController/EVGAACX30SMBusController.h new file mode 100644 index 00000000..0fb92721 --- /dev/null +++ b/Controllers/EVGASMBusController/EVGAACX30SMBusController.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------*\ +| EVGAACX30SMBusController.h | +| | +| Driver for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +enum +{ + /*------------------------------------------------------------------------------------------*\ + | Acx30 Common Registers | + \*------------------------------------------------------------------------------------------*/ + ACX30_REG_01 = 0x01, + ACX30_REG_PTYPE = 0x03, + ACX30_REG_VER_LOW = 0x04, + ACX30_REG_VER_HIGH = 0x05, + ACX30_REG_RED = 0x09, + ACX30_REG_GREEN = 0x0A, + ACX30_REG_BLUE = 0x0B, + ACX30_REG_MODE = 0x0C, + ACX30_REG_CONTROL = 0x0E, + ACX30_REG_SPEED = 0x19, + ACX30_REG_20 = 0x20, + ACX30_REG_21 = 0x21, + ACX30_REG_22 = 0x22, +}; + +/*----------------------------------------------------------------------------------------------*\ +| Definitions for Acx30 | +\*----------------------------------------------------------------------------------------------*/ + +enum +{ + ACX30_MODE_OFF = 0x00, /* OFF mode */ + ACX30_MODE_STATIC = 0x01, /* Static color mode */ + ACX30_MODE_SPECTRUM_CYCLE = 0x02, /* Spectrum Cycle effect mode */ + ACX30_MODE_BREATHING = 0x05, /* Breathing effect mode */ +}; + +enum +{ + ACX30_SPEED_MIN = 0x00, /* Slowest speed */ + ACX30_SPEED_DEFAULT = 0x04, /* Default speed */ + ACX30_SPEED_MAX = 0xFF, /* Fastest speed */ +}; + +class EVGAACX30SMBusController +{ +public: + EVGAACX30SMBusController(i2c_smbus_interface *bus, uint8_t dev); + ~EVGAACX30SMBusController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetFirmwareVersion(); + uint8_t GetMode(); + void Unlock(); + void Lock(); + void SetColors(uint8_t red, uint8_t green, uint8_t blue); + void SetMode(uint8_t mode); + void SetSpeed(uint8_t speed); + +private: + std::string device_name; + i2c_smbus_interface* bus; + uint8_t dev; +}; diff --git a/Controllers/EVGASMBusController/EVGASMBusControllerDetect.cpp b/Controllers/EVGASMBusController/EVGASMBusControllerDetect.cpp new file mode 100644 index 00000000..f1b2f03a --- /dev/null +++ b/Controllers/EVGASMBusController/EVGASMBusControllerDetect.cpp @@ -0,0 +1,90 @@ +/*---------------------------------------------------------*\ +| EVGASMBusControllerDetect.cpp | +| | +| Detector for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "Detector.h" +#include "EVGAACX30SMBusController.h" +#include "LogManager.h" +#include "RGBController.h" +#include "RGBController_EVGAACX30SMBus.h" +#include "i2c_smbus.h" +#include "pci_ids.h" + +/******************************************************************************************\ +* * +* TestForAcx30SMBusController * +* * +* Tests the given address to see if an EVGA ACX 30 controller exists there. * +* First does a quick write to test for a response * +* Then checks if it has 1st bit set in register 1 * +* * +\******************************************************************************************/ + +#define EVGA_DETECTOR_NAME "EVGA SMBus Detectector" +#define VENDOR_NAME "EVGA" +#define SMBUS_ADDRESS 0x28 + +bool TestForAcx30SMBusController(i2c_smbus_interface *bus, uint8_t address) +{ + bool pass = false; + + int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE); + + if (res >= 0) + { + res = bus->i2c_smbus_read_byte_data(address, 0x01); + + if (res > 0 && (res & 1)) + { + pass = true; + } + } + + return(pass); +} /* TestForAcx30SMBusController() */ + +/******************************************************************************************\ +* * +* DetectAcx30SMBusControllers * +* * +* Detect EVGA ACX 30 SMBus controllers on the enumerated I2C busses at address 0x28. * +* * +\******************************************************************************************/ + +void DetectAcx30SMBusControllers(std::vector &busses) +{ + for(unsigned int bus = 0; bus < busses.size(); bus++) + { + IF_MOBO_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + { + if(busses[bus]->pci_subsystem_vendor == EVGA_SUB_VEN) + { + LOG_DEBUG(SMBUS_CHECK_DEVICE_MESSAGE_EN, EVGA_DETECTOR_NAME, bus, VENDOR_NAME, SMBUS_ADDRESS); + // Check for ACX 30 controller at 0x28 + if(TestForAcx30SMBusController(busses[bus], SMBUS_ADDRESS)) + { + EVGAACX30SMBusController *controller = new EVGAACX30SMBusController(busses[bus], SMBUS_ADDRESS); + RGBController_EVGAACX30SMBus *rgb_controller = new RGBController_EVGAACX30SMBus(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + else + { + LOG_DEBUG(SMBUS_CHECK_DEVICE_FAILURE_EN, EVGA_DETECTOR_NAME, bus, VENDOR_NAME); + } + } + } +} /* DetectAcx30SMBusControllers() */ + +REGISTER_I2C_DETECTOR("EVGA Motherboard SMBus Controllers", DetectAcx30SMBusControllers); diff --git a/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.cpp b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.cpp new file mode 100644 index 00000000..5cf265d1 --- /dev/null +++ b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.cpp @@ -0,0 +1,163 @@ +/*---------------------------------------------------------*\ +| RGBController_EVGAACX30SMBus.cpp | +| | +| RGBController for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_EVGAACX30SMBus.h" + +/**------------------------------------------------------------------*\ + @name EVGA ACX 30 + @category Motherboard + @type SMBus + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectAcx30SMBusControllers + @comment EVGA ACX 30 LED controllers will save with each update. + Per ARGB LED support is not possible with these devices. +\*-------------------------------------------------------------------*/ + +RGBController_EVGAACX30SMBus::RGBController_EVGAACX30SMBus(EVGAACX30SMBusController *controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "EVGA"; + version = controller->GetFirmwareVersion(); + type = DEVICE_TYPE_MOTHERBOARD; + description = "EVGA ACX 30 LED Device"; + location = controller->GetDeviceLocation(); + active_mode = controller->GetMode(); + + mode Off; + Off.name = "Off"; + Off.value = ACX30_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = ACX30_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = ACX30_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.speed_min = ACX30_SPEED_MIN; + SpectrumCycle.speed_max = ACX30_SPEED_MAX; + SpectrumCycle.speed = ACX30_SPEED_DEFAULT; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ACX30_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = ACX30_SPEED_MIN; + Breathing.speed_max = ACX30_SPEED_MAX; + Breathing.speed = ACX30_SPEED_DEFAULT; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + SetupZones(); +} + +RGBController_EVGAACX30SMBus::~RGBController_EVGAACX30SMBus() +{ + delete controller; +} + +void RGBController_EVGAACX30SMBus::SetupZones() +{ + /*---------------------------------------------------------*\ + | Acx30 motherboards only have a single zone/LED | + \*---------------------------------------------------------*/ + + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + zone* new_zone = new zone(); + + /*---------------------------------------------------------*\ + | Set single zone name to "Motherboard" | + \*---------------------------------------------------------*/ + new_zone->name = "Motherboard"; + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->leds_min = 1; + new_zone->leds_max = 1; + new_zone->leds_count = 1; + new_zone->matrix_map = NULL; + + /*---------------------------------------------------------*\ + | Push new zone to zones vector | + \*---------------------------------------------------------*/ + zones.push_back(*new_zone); + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + led* new_led = new led(); + + /*---------------------------------------------------------*\ + | Set single LED name to "Motherboard" | + \*---------------------------------------------------------*/ + new_led->name = "Motherboard"; + + /*---------------------------------------------------------*\ + | Push new LED to LEDs vector | + \*---------------------------------------------------------*/ + leds.push_back(*new_led); + + SetupColors(); +} + +void RGBController_EVGAACX30SMBus::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_EVGAACX30SMBus::DeviceUpdateLEDs() +{ + for(int led = 0; led < colors.size(); led++) + { + UpdateSingleLED(led); + } +} + +void RGBController_EVGAACX30SMBus::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_EVGAACX30SMBus::UpdateSingleLED(int led) +{ + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + + controller->Unlock(); + controller->SetColors(red, grn, blu); + controller->Lock(); +} + +void RGBController_EVGAACX30SMBus::DeviceUpdateMode() +{ + controller->Unlock(); + controller->SetMode(modes[active_mode].value); + controller->SetSpeed(modes[active_mode].speed); + controller->Lock(); + + DeviceUpdateLEDs(); +} diff --git a/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.h b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.h new file mode 100644 index 00000000..72ffd438 --- /dev/null +++ b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_EVGAACX30SMBus.h | +| | +| RGBController for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "EVGAACX30SMBusController.h" + +class RGBController_EVGAACX30SMBus : public RGBController +{ +public: + RGBController_EVGAACX30SMBus(EVGAACX30SMBusController* controller_ptr); + ~RGBController_EVGAACX30SMBus(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + EVGAACX30SMBusController *controller; +};