/*---------------------------------------------------------*\ | ENESMBusController.cpp | | | | Driver for ENE SMBus devices | | | | Adam Honse (CalcProgrammer1) 19 Aug 2018 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include #include "ENESMBusController.h" #include "LogManager.h" static const char* ene_channels[] = /* ENE channel strings */ { "Audio", "Backplate", "Back I/O", "Center", "Center", "DRAM", "PCIe", "RGB Header", "RGB Header 2", "RGB Header", "SSD", "Unknown", }; ENESMBusController::ENESMBusController(ENESMBusInterface* interface, ene_dev_id dev) { this->interface = interface; this->dev = dev; supports_mode_14 = false; if(interface->GetInterfaceType() != ENE_INTERFACE_TYPE_ROG_ARION) { UpdateDeviceName(); // Read the device configuration table for (int i = 0; i < 64; i++) { config_table[i] = ENERegisterRead(ENE_REG_CONFIG_TABLE + i); } /*-----------------------------------------------------------------*\ | If this is running with TRACE or higher loglevel then | | dump the entire Feature list to log | \*-----------------------------------------------------------------*/ if(LogManager::get()->getLoglevel() >= LL_TRACE) { LOG_TRACE("[ENE SMBus] ENE config table for 0x%02X:", dev); LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[0], config_table[1], config_table[2], config_table[3], config_table[4], config_table[5], config_table[6], config_table[7], config_table[8], config_table[9], config_table[10], config_table[11], config_table[12], config_table[13], config_table[14], config_table[15]); LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[16], config_table[17], config_table[18], config_table[19], config_table[20], config_table[21], config_table[22], config_table[23], config_table[24], config_table[25], config_table[26], config_table[27], config_table[28], config_table[29], config_table[30], config_table[31]); LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[32], config_table[33], config_table[34], config_table[35], config_table[36], config_table[37], config_table[38], config_table[39], config_table[40], config_table[41], config_table[42], config_table[43], config_table[44], config_table[45], config_table[46], config_table[47]); LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[48], config_table[49], config_table[50], config_table[51], config_table[52], config_table[53], config_table[54], config_table[55], config_table[56], config_table[57], config_table[58], config_table[59], config_table[60], config_table[61], config_table[62], config_table[63]); } } else { LOG_TRACE("[ENE SMBus] ROG STRIX ARION detected, filling in hard coded config table entries.", dev); memset(config_table, 0, sizeof(config_table)); config_table[ENE_CONFIG_LED_COUNT] = 4; config_table[0x03] = 4; strcpy(device_name, "ROG STRIX ARION"); } // Read LED count from configuration table led_count = config_table[ENE_CONFIG_LED_COUNT]; // LED-0116 - First generation motherboard controller if (strcmp(device_name, "LED-0116") == 0) { direct_reg = ENE_REG_COLORS_DIRECT; effect_reg = ENE_REG_COLORS_EFFECT; channel_cfg = ENE_CONFIG_CHANNEL_V1; } // DIMM_LED-0102 - First generation DRAM controller (Trident Z RGB) else if (strcmp(device_name, "DIMM_LED-0102") == 0) { direct_reg = ENE_REG_COLORS_DIRECT; effect_reg = ENE_REG_COLORS_EFFECT; channel_cfg = ENE_CONFIG_CHANNEL_V1; } // AUDA0-E6K5-0101 - Second generation DRAM controller (Geil Super Luce) else if (strcmp(device_name, "AUDA0-E6K5-0101") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V1; // Check for Mode 14 support, only known to exist on modules where the // DRAM 3 zone ID exists for(std::size_t cfg_zone_idx = 0; cfg_zone_idx < ENE_NUM_ZONES; cfg_zone_idx++) { if(config_table[channel_cfg + cfg_zone_idx] == (unsigned char)ENE_LED_CHANNEL_DRAM_3) { supports_mode_14 = true; break; } } } // AUMA0-E6K5-0106 - Second generation motherboard controller else if (strcmp(device_name, "AUMA0-E6K5-0106") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; } // AUMA0-E6K5-0105 - Second generation motherboard controller else if (strcmp(device_name, "AUMA0-E6K5-0105") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; } // AUMA0-E6K5-0104 - Second generation motherboard controller else if (strcmp(device_name, "AUMA0-E6K5-0104") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; } // AUMA0-E8K4-0101 - First generation motherboard controller else if (strcmp(device_name, "AUMA0-E8K4-0101") == 0) { direct_reg = ENE_REG_COLORS_DIRECT; effect_reg = ENE_REG_COLORS_EFFECT; channel_cfg = ENE_CONFIG_CHANNEL_V1; } // AUMA0-E6K5-0107 - Second generation GPU controller else if (strcmp(device_name, "AUMA0-E6K5-0107") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; // Read LED count from configuration table led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; } // AUMA0-E6K5-1110 - Third generation GPU controller? // found an ASUS ROG Strix 4080 OC, seems to be equal to AUMA0-E6K5-0107 else if (strcmp(device_name, "AUMA0-E6K5-1110") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; // Read LED count from configuration table led_count = config_table[ENE_CONFIG_LED_COUNT_1110]; } // AUMA0-E6K5-1111 - Fourth generation GPU controller? // found on ASUS ROG Strix 4090 OC EVA-02 Edition, seems to be equal to AUMA0-E6K5-0107 else if (strcmp(device_name, "AUMA0-E6K5-1111") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; // Read LED count from configuration table led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; } // AUMA0-E6K5-1107 - Second generation GPU controller // Found on ASUS TUF 4070 TI OC, seems to be equal to AUMA0-E6K5-0107 else if (strcmp(device_name, "AUMA0-E6K5-1107") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; // Read LED count from configuration table led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; } // AUMA0-E6K5-0008 // Found on ASUS STRIX 4070 Super OC else if (strcmp(device_name, "AUMA0-E6K5-0008") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V1; // Read LED count from configuration table led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; } // ROG ARION - ASUS ROG Arion external SSD enclosure // This device does not support ENE read, so we fake the device name string // if the interface is ROG Arion type. It uses second generation registers. else if(strcmp(device_name, "ROG STRIX ARION") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; } // Assume first generation controller if string does not match else { direct_reg = ENE_REG_COLORS_DIRECT; effect_reg = ENE_REG_COLORS_EFFECT; channel_cfg = ENE_CONFIG_CHANNEL_V1; } } ENESMBusController::~ENESMBusController() { delete interface; } std::string ENESMBusController::GetDeviceName() { return(device_name); } std::string ENESMBusController::GetDeviceLocation() { std::string return_string = interface->GetLocation(); char addr[5]; snprintf(addr, 5, "0x%02X", dev); return_string.append(", address "); return_string.append(addr); return(return_string); } const char * ENESMBusController::GetChannelName(unsigned int cfg_zone) { LOG_TRACE("[%s] Config table for zone %02d: %02d", device_name, cfg_zone, config_table[channel_cfg + cfg_zone]); if(interface->GetInterfaceType() == ENE_INTERFACE_TYPE_ROG_ARION) { return(ene_channels[10]); } else { switch(config_table[channel_cfg + cfg_zone]) { case (unsigned char)ENE_LED_CHANNEL_AUDIO: return(ene_channels[0]); break; case (unsigned char)ENE_LED_CHANNEL_BACKPLATE: return(ene_channels[1]); break; case (unsigned char)ENE_LED_CHANNEL_BACK_IO: return(ene_channels[2]); break; case (unsigned char)ENE_LED_CHANNEL_CENTER: return(ene_channels[3]); break; case (unsigned char)ENE_LED_CHANNEL_CENTER_START: return(ene_channels[4]); break; case (unsigned char)ENE_LED_CHANNEL_DRAM: case (unsigned char)ENE_LED_CHANNEL_DRAM_2: case (unsigned char)ENE_LED_CHANNEL_DRAM_3: return(ene_channels[5]); break; case (unsigned char)ENE_LED_CHANNEL_PCIE: return(ene_channels[6]); break; case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER: return(ene_channels[7]); break; case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER_2: return(ene_channels[8]); break; case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER_3: return(ene_channels[9]); break; default: return(ene_channels[11]); break; } } } unsigned int ENESMBusController::GetLEDCount(unsigned int cfg_zone) { LOG_TRACE("[%s] LED Count for zone %02d: %02d", device_name, cfg_zone, config_table[0x03 + cfg_zone]); return(config_table[0x03 + cfg_zone]); } unsigned char ENESMBusController::GetLEDRed(unsigned int led) { return(ENERegisterRead(direct_reg + ( 3 * led ))); } unsigned char ENESMBusController::GetLEDGreen(unsigned int led) { return(ENERegisterRead(direct_reg + ( 3 * led ) + 2)); } unsigned char ENESMBusController::GetLEDBlue(unsigned int led) { return(ENERegisterRead(direct_reg + ( 3 * led ) + 1)); } unsigned char ENESMBusController::GetLEDRedEffect(unsigned int led) { return(ENERegisterRead(effect_reg + ( 3 * led ))); } unsigned char ENESMBusController::GetLEDGreenEffect(unsigned int led) { return(ENERegisterRead(effect_reg + ( 3 * led ) + 2)); } unsigned char ENESMBusController::GetLEDBlueEffect(unsigned int led) { return(ENERegisterRead(effect_reg + ( 3 * led ) + 1)); } void ENESMBusController::SaveMode() { ENERegisterWrite(ENE_REG_APPLY, ENE_SAVE_VAL); } void ENESMBusController::SetAllColorsDirect(RGBColor* colors) { unsigned char* color_buf = new unsigned char[led_count * 3]; unsigned int bytes_sent = 0; for(unsigned int i = 0; i < (led_count * 3); i += 3) { color_buf[i + 0] = RGBGetRValue(colors[i / 3]); color_buf[i + 1] = RGBGetBValue(colors[i / 3]); color_buf[i + 2] = RGBGetGValue(colors[i / 3]); } while(bytes_sent < (led_count * 3)) { int bytes_to_send = (led_count * 3) - bytes_sent; if(bytes_to_send > interface->GetMaxBlock()) { bytes_to_send = interface->GetMaxBlock(); } ENERegisterWriteBlock(direct_reg + bytes_sent, &color_buf[bytes_sent], bytes_to_send); bytes_sent += bytes_to_send; } delete[] color_buf; } void ENESMBusController::SetAllColorsEffect(RGBColor* colors) { unsigned char* color_buf = new unsigned char[led_count * 3]; unsigned int bytes_sent = 0; for(unsigned int i = 0; i < (led_count * 3); i += 3) { color_buf[i + 0] = RGBGetRValue(colors[i / 3]); color_buf[i + 1] = RGBGetBValue(colors[i / 3]); color_buf[i + 2] = RGBGetGValue(colors[i / 3]); } while(bytes_sent < (led_count * 3)) { int bytes_to_send = (led_count * 3) - bytes_sent; if(bytes_to_send > interface->GetMaxBlock()) { bytes_to_send = interface->GetMaxBlock(); } ENERegisterWriteBlock(effect_reg + bytes_sent, &color_buf[bytes_sent], bytes_to_send); bytes_sent += bytes_to_send; } ENERegisterWrite(ENE_REG_APPLY, ENE_APPLY_VAL); delete[] color_buf; } void ENESMBusController::SetDirect(unsigned char direct) { ENERegisterWrite(ENE_REG_DIRECT, direct); ENERegisterWrite(ENE_REG_APPLY, ENE_APPLY_VAL); } void ENESMBusController::SetLEDColorDirect(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) { unsigned char colors[3] = { red, blue, green }; ENERegisterWriteBlock(direct_reg + ( 3 * led ), colors, 3); } void ENESMBusController::SetLEDColorEffect(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) { unsigned char colors[3] = { red, blue, green }; ENERegisterWriteBlock(effect_reg + (3 * led), colors, 3); ENERegisterWrite(ENE_REG_APPLY, ENE_APPLY_VAL); } void ENESMBusController::SetMode(unsigned char mode, unsigned char speed, unsigned char direction) { ENERegisterWrite(ENE_REG_MODE, mode); ENERegisterWrite(ENE_REG_SPEED, speed); ENERegisterWrite(ENE_REG_DIRECTION, direction); ENERegisterWrite(ENE_REG_APPLY, ENE_APPLY_VAL); } bool ENESMBusController::SupportsMode14() { return(supports_mode_14); } void ENESMBusController::UpdateDeviceName() { for (int i = 0; i < 16; i++) { device_name[i] = ENERegisterRead(ENE_REG_DEVICE_NAME + i); } } unsigned char ENESMBusController::ENERegisterRead(ene_register reg) { return(interface->ENERegisterRead(dev, reg)); } void ENESMBusController::ENERegisterWrite(ene_register reg, unsigned char val) { interface->ENERegisterWrite(dev, reg, val); } void ENESMBusController::ENERegisterWriteBlock(ene_register reg, unsigned char * data, unsigned char sz) { interface->ENERegisterWriteBlock(dev, reg, data, sz); }