Skip to content

Commit 9a33c95

Browse files
meganukebmpCalcProgrammer1
authored andcommitted
Add support for PowerColor Red Devil RX9070XT
1 parent b113fd8 commit 9a33c95

6 files changed

Lines changed: 703 additions & 0 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*---------------------------------------------------------*\
2+
| PowerColorGPUControllerDetect.cpp |
3+
| |
4+
| Driver for PowerColor GPUs |
5+
| |
6+
| Nexrem 15 Aug 2025 |
7+
| |
8+
| This file is part of the OpenRGB project |
9+
| SPDX-License-Identifier: GPL-2.0-only |
10+
\*---------------------------------------------------------*/
11+
12+
#include "Detector.h"
13+
#include "pci_ids.h"
14+
#include "PowerColorRedDevilV2Controller/RGBController_PowerColorRedDevilV2.h"
15+
#include "PowerColorRedDevilV2Controller/PowerColorRedDevilV2Controller.h"
16+
17+
#define RED_DEVIL_V1_MAGIC_ADDR 0x90
18+
19+
static const unsigned char magic_v1[3] = {0x01, 0x05, 0x00};
20+
static const unsigned char magic_v2[3] = {0x01, 0x32, 0x00};
21+
22+
void DetectPowerColorRedDevilGPUControllersV2(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name)
23+
{
24+
/*---------------------------------------------------------*\
25+
| The controller reports a unique identifier for V1 and V2. |
26+
| Unfortunately they are on different addresses. Read it |
27+
| for good measure anyways. |
28+
\*---------------------------------------------------------*/
29+
unsigned char data[3];
30+
int ret = bus->i2c_smbus_read_i2c_block_data(i2c_addr, RED_DEVIL_V2_READ_REG_MAGIC, 3, data);
31+
if(ret == 3 && memcmp(data, magic_v2, 3) == 0)
32+
{
33+
PowerColorRedDevilV2Controller* controller = new PowerColorRedDevilV2Controller(bus, i2c_addr, name);
34+
RGBController_PowerColorRedDevilV2* rgb_controller = new RGBController_PowerColorRedDevilV2(controller);
35+
36+
ResourceManager::get()->RegisterRGBController(rgb_controller);
37+
}
38+
}
39+
40+
REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX9070XT", DetectPowerColorRedDevilGPUControllersV2, AMD_GPU_VEN, AMD_NAVI48_DEV, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX9070XT_SUB_DEV, 0x22);
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/*---------------------------------------------------------*\
2+
| PowerColorRedDevilV2Controller.cpp |
3+
| |
4+
| Driver for PowerColor Red Devil GPU |
5+
| |
6+
| Nexrem 15 Aug 2025 |
7+
| |
8+
| This file is part of the OpenRGB project |
9+
| SPDX-License-Identifier: GPL-2.0-only |
10+
\*---------------------------------------------------------*/
11+
12+
#include <string>
13+
#include "PowerColorRedDevilV2Controller.h"
14+
15+
16+
PowerColorRedDevilV2Controller::PowerColorRedDevilV2Controller(i2c_smbus_interface* bus, red_devil_v2_dev_id dev, std::string dev_name)
17+
{
18+
this->bus = bus;
19+
this->dev = dev;
20+
this->name = dev_name;
21+
}
22+
23+
PowerColorRedDevilV2Controller::~PowerColorRedDevilV2Controller()
24+
{
25+
26+
}
27+
28+
std::string PowerColorRedDevilV2Controller::GetDeviceLocation()
29+
{
30+
std::string return_string(bus->device_name);
31+
char addr[5];
32+
snprintf(addr, 5, "0x%02X", dev);
33+
return_string.append(", address ");
34+
return_string.append(addr);
35+
return("I2C:" + return_string);
36+
}
37+
38+
std::string PowerColorRedDevilV2Controller::GetDeviceName()
39+
{
40+
return(name);
41+
}
42+
43+
bool PowerColorRedDevilV2Controller::GetSync()
44+
{
45+
unsigned char data[3];
46+
RegisterRead(RED_DEVIL_V2_READ_REG_SYNC, data);
47+
48+
return data[0] && data[1] && data[2];
49+
}
50+
51+
void PowerColorRedDevilV2Controller::SetSync(bool sync)
52+
{
53+
if(sync)
54+
{
55+
unsigned char data[3] = {0x01, 0x01, 0x01};
56+
RegisterWrite(RED_DEVIL_V2_WRITE_REG_SYNC, data);
57+
}
58+
else
59+
{
60+
unsigned char data[3] = {0x00, 0x00, 0x00};
61+
RegisterWrite(RED_DEVIL_V2_WRITE_REG_SYNC, data);
62+
}
63+
}
64+
65+
/*------------------------------------------------------------------*\
66+
| Mode returns MMBBSS |
67+
\*------------------------------------------------------------------*/
68+
red_devil_v2_mode PowerColorRedDevilV2Controller::GetMode()
69+
{
70+
unsigned char data[3];
71+
red_devil_v2_mode mode;
72+
73+
RegisterRead(RED_DEVIL_V2_READ_REG_MODE, data);
74+
75+
mode.mode = data[0];
76+
mode.brightness = data[1];
77+
mode.speed = data[2];
78+
79+
return mode;
80+
}
81+
82+
void PowerColorRedDevilV2Controller::SetMode(red_devil_v2_mode mode)
83+
{
84+
if(mode.mode == RED_DEVIL_V2_MODE_SYNC)
85+
{
86+
SetSync(true);
87+
return;
88+
}
89+
90+
SetSync(false);
91+
92+
unsigned char data[3] =
93+
{
94+
mode.mode,
95+
mode.brightness,
96+
mode.speed
97+
};
98+
99+
RegisterWrite(RED_DEVIL_V2_WRITE_REG_MODE, data);
100+
}
101+
102+
RGBColor PowerColorRedDevilV2Controller::GetLedColor(int led)
103+
{
104+
/*------------------------------------------------------------------*\
105+
| On overflow read the first LED |
106+
\*------------------------------------------------------------------*/
107+
if(led >= RED_DEVIL_V2_NUM_LEDS)
108+
{
109+
led = 0;
110+
}
111+
112+
unsigned char data[3];
113+
RegisterRead(RED_DEVIL_V2_READ_REG_RGBX + led, data);
114+
115+
return ToRGBColor(data[0], data[1], data[2]);
116+
}
117+
118+
void PowerColorRedDevilV2Controller::SetLedColor(int led, RGBColor color)
119+
{
120+
/*------------------------------------------------------------------*\
121+
| Skip writing to invalid LEDs |
122+
\*------------------------------------------------------------------*/
123+
if(led >= RED_DEVIL_V2_NUM_LEDS)
124+
{
125+
return;
126+
}
127+
128+
unsigned char data[3] =
129+
{
130+
(unsigned char) RGBGetRValue(color),
131+
(unsigned char) RGBGetGValue(color),
132+
(unsigned char) RGBGetBValue(color)
133+
};
134+
135+
RegisterWrite(RED_DEVIL_V2_WRITE_REG_RGBX+led, data);
136+
}
137+
138+
void PowerColorRedDevilV2Controller::SetLedColorAll(RGBColor color)
139+
{
140+
unsigned char data[3] =
141+
{
142+
(unsigned char) RGBGetRValue(color),
143+
(unsigned char) RGBGetGValue(color),
144+
(unsigned char) RGBGetBValue(color)
145+
};
146+
147+
/*------------------------------------------------------------------*\
148+
| Factory firmware writes both, but we only need 1 of them. |
149+
| Write both anyways just in case... |
150+
\*------------------------------------------------------------------*/
151+
RegisterWrite(RED_DEVIL_V2_WRITE_REG_RGB1, data);
152+
RegisterWrite(RED_DEVIL_V2_WRITE_REG_RGB2, data);
153+
}
154+
155+
int PowerColorRedDevilV2Controller::RegisterRead(unsigned char reg, unsigned char *data)
156+
{
157+
int ret = bus->i2c_smbus_read_i2c_block_data(dev, reg, 3, data);
158+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
159+
return ret;
160+
}
161+
162+
int PowerColorRedDevilV2Controller::RegisterWrite(unsigned char reg, unsigned char *data)
163+
{
164+
int ret = bus->i2c_smbus_write_i2c_block_data(dev, reg, 3, data);
165+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
166+
return ret;
167+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*---------------------------------------------------------*\
2+
| PowerColorRedDevilV2Controller.h |
3+
| |
4+
| Driver for PowerColor Red Devil GPU |
5+
| |
6+
| Nexrem 15 Aug 2025 |
7+
| |
8+
| This file is part of the OpenRGB project |
9+
| SPDX-License-Identifier: GPL-2.0-only |
10+
\*---------------------------------------------------------*/
11+
12+
#include <string>
13+
#include "i2c_smbus.h"
14+
#include "RGBController.h"
15+
16+
#pragma once
17+
18+
typedef unsigned char red_devil_v2_dev_id;
19+
20+
struct red_devil_v2_mode
21+
{
22+
unsigned char mode;
23+
unsigned char brightness;
24+
unsigned char speed;
25+
};
26+
27+
#define RED_DEVIL_V2_NUM_LEDS 24
28+
29+
enum
30+
{
31+
RED_DEVIL_V2_WRITE_REG_MODE = 0x01,
32+
RED_DEVIL_V2_WRITE_REG_SYNC = 0x04,
33+
RED_DEVIL_V2_WRITE_REG_RGBX = 0x10,
34+
RED_DEVIL_V2_WRITE_REG_RGB1 = 0x30,
35+
RED_DEVIL_V2_WRITE_REG_RGB2 = 0x31
36+
};
37+
38+
enum
39+
{
40+
RED_DEVIL_V2_READ_REG_MODE = 0x81,
41+
RED_DEVIL_V2_READ_REG_MAGIC = 0x82,
42+
RED_DEVIL_V2_READ_REG_SYNC = 0x84,
43+
RED_DEVIL_V2_READ_REG_RGBX = 0x90
44+
};
45+
46+
enum
47+
{
48+
RED_DEVIL_V2_MODE_OFF = 0x00,
49+
RED_DEVIL_V2_MODE_STATIC = 0x01,
50+
RED_DEVIL_V2_MODE_BREATHING = 0x02,
51+
RED_DEVIL_V2_MODE_SECRET_RAINBOW = 0x03,
52+
RED_DEVIL_V2_MODE_RADIANCE = 0x04,
53+
RED_DEVIL_V2_MODE_DIFFUSE = 0x05,
54+
RED_DEVIL_V2_MODE_COLOR_SHIFT = 0x06,
55+
RED_DEVIL_V2_MODE_METEOR = 0x07,
56+
RED_DEVIL_V2_MODE_RIPPLE = 0x08,
57+
RED_DEVIL_V2_MODE_RAINBOW = 0x09,
58+
RED_DEVIL_V2_MODE_SYNC = 0xFF
59+
};
60+
61+
enum
62+
{
63+
RED_DEVIL_V2_BRIGHTNESS_MIN = 0x00,
64+
RED_DEVIL_V2_BRIGHTNESS_MAX = 0xFF
65+
};
66+
67+
enum
68+
{
69+
RED_DEVIL_V2_SPEED_MIN = 0xFF,
70+
RED_DEVIL_V2_SPEED_DEFAULT = 0x32,
71+
RED_DEVIL_V2_SPEED_MAX = 0x00
72+
};
73+
74+
75+
class PowerColorRedDevilV2Controller
76+
{
77+
public:
78+
PowerColorRedDevilV2Controller(i2c_smbus_interface* bus, red_devil_v2_dev_id dev, std::string dev_name);
79+
~PowerColorRedDevilV2Controller();
80+
81+
std::string GetDeviceLocation();
82+
std::string GetDeviceName();
83+
84+
bool GetSync();
85+
void SetSync(bool sync);
86+
87+
red_devil_v2_mode GetMode();
88+
void SetMode(red_devil_v2_mode mode);
89+
90+
RGBColor GetLedColor(int led);
91+
void SetLedColor(int led, RGBColor color);
92+
void SetLedColorAll(RGBColor color);
93+
94+
private:
95+
i2c_smbus_interface* bus;
96+
red_devil_v2_dev_id dev;
97+
std::string name;
98+
99+
int RegisterRead(unsigned char reg, unsigned char *data);
100+
int RegisterWrite(unsigned char reg, unsigned char *data);
101+
};

0 commit comments

Comments
 (0)