Files
OpenRGB/Controllers/ZotacBlackwellGPUController/RGBController_ZotacBlackwellGPU.cpp

370 lines
15 KiB
C++

/*---------------------------------------------------------*\
| RGBController_ZotacBlackwellGPU.cpp |
| |
| RGBController for ZOTAC Blackwell (RTX 50 series) GPU |
| |
| Eder Sánchez 27 Mar 2026 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "RGBController_ZotacBlackwellGPU.h"
/**------------------------------------------------------------------*\
@name ZOTAC RTX 50 series GPU
@category GPU
@type I2C
@save :robot:
@direct :x:
@effects :tools:
@detectors DetectZotacBlackwellGPUControllersPCI
@comment
Supports ZOTAC Blackwell (RTX 50 series) GPUs with 3 zones:
Logo, Side Bar, and Infinity Mirror.
The controller uses individual SMBus byte writes (registers
0x20-0x2F) with a 3ms delay between each transaction.
To add new cards, add PCI ID entries in `pci_ids/pci_ids.h`
and detection entries in
`Controllers/ZotacBlackwellGPUController/ZotacBlackwellGPUControllerDetect.cpp`.
\*-------------------------------------------------------------------*/
RGBController_ZotacBlackwellGPU::RGBController_ZotacBlackwellGPU(ZotacBlackwellGPUController* controller_ptr)
{
controller = controller_ptr;
name = controller->GetName();
vendor = "ZOTAC";
description = "ZOTAC RTX 50 series RGB GPU Device (" + controller->GetVersion() + ")";
location = controller->GetDeviceLocation();
type = DEVICE_TYPE_GPU;
version = controller->GetVersion();
/*---------------------------------------------------------*\
| Static mode |
\*---------------------------------------------------------*/
mode STATIC;
STATIC.name = "Static";
STATIC.value = ZOTAC_BLACKWELL_GPU_MODE_STATIC;
STATIC.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR;
STATIC.brightness_min = 0;
STATIC.brightness_max = 100;
STATIC.brightness = 100;
STATIC.color_mode = MODE_COLORS_PER_LED;
modes.push_back(STATIC);
/*---------------------------------------------------------*\
| Breathe mode |
\*---------------------------------------------------------*/
mode BREATHE;
BREATHE.name = "Breathe";
BREATHE.value = ZOTAC_BLACKWELL_GPU_MODE_BREATHE;
BREATHE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
BREATHE.brightness_min = 0;
BREATHE.brightness_max = 100;
BREATHE.brightness = 100;
BREATHE.speed_min = 0;
BREATHE.speed_max = 100;
BREATHE.speed = 20;
BREATHE.color_mode = MODE_COLORS_PER_LED;
modes.push_back(BREATHE);
/*---------------------------------------------------------*\
| Fade mode |
\*---------------------------------------------------------*/
mode FADE;
FADE.name = "Fade";
FADE.value = ZOTAC_BLACKWELL_GPU_MODE_FADE;
FADE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED;
FADE.speed_min = 0;
FADE.speed_max = 100;
FADE.speed = 20;
FADE.color_mode = MODE_COLORS_NONE;
modes.push_back(FADE);
/*---------------------------------------------------------*\
| Wink mode |
\*---------------------------------------------------------*/
mode WINK;
WINK.name = "Wink";
WINK.value = ZOTAC_BLACKWELL_GPU_MODE_WINK;
WINK.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
WINK.brightness_min = 0;
WINK.brightness_max = 100;
WINK.brightness = 100;
WINK.speed_min = 0;
WINK.speed_max = 100;
WINK.speed = 20;
WINK.color_mode = MODE_COLORS_PER_LED;
modes.push_back(WINK);
/*---------------------------------------------------------*\
| Glide mode |
\*---------------------------------------------------------*/
mode GLIDE;
GLIDE.name = "Glide";
GLIDE.value = ZOTAC_BLACKWELL_GPU_MODE_GLIDE;
GLIDE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_PER_LED_COLOR;
GLIDE.brightness_min = 0;
GLIDE.brightness_max = 100;
GLIDE.brightness = 100;
GLIDE.speed_min = 0;
GLIDE.speed_max = 100;
GLIDE.speed = 20;
GLIDE.color_mode = MODE_COLORS_PER_LED;
modes.push_back(GLIDE);
/*---------------------------------------------------------*\
| Prism mode (called "Rainbow" in older firmware) |
\*---------------------------------------------------------*/
mode PRISM;
PRISM.name = "Prism";
PRISM.value = ZOTAC_BLACKWELL_GPU_MODE_PRISM;
PRISM.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
PRISM.speed_min = 0;
PRISM.speed_max = 100;
PRISM.speed = 20;
PRISM.color_mode = MODE_COLORS_NONE;
modes.push_back(PRISM);
/*---------------------------------------------------------*\
| Bokeh mode |
\*---------------------------------------------------------*/
mode BOKEH;
BOKEH.name = "Bokeh";
BOKEH.value = ZOTAC_BLACKWELL_GPU_MODE_BOKEH;
BOKEH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
BOKEH.brightness_min = 0;
BOKEH.brightness_max = 100;
BOKEH.brightness = 100;
BOKEH.speed_min = 0;
BOKEH.speed_max = 100;
BOKEH.speed = 20;
BOKEH.color_mode = MODE_COLORS_PER_LED;
modes.push_back(BOKEH);
/*---------------------------------------------------------*\
| Beacon mode |
\*---------------------------------------------------------*/
mode BEACON;
BEACON.name = "Beacon";
BEACON.value = ZOTAC_BLACKWELL_GPU_MODE_BEACON;
BEACON.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
BEACON.brightness_min = 0;
BEACON.brightness_max = 100;
BEACON.brightness = 100;
BEACON.speed_min = 0;
BEACON.speed_max = 100;
BEACON.speed = 20;
BEACON.color_mode = MODE_COLORS_PER_LED;
modes.push_back(BEACON);
/*---------------------------------------------------------*\
| Tandem mode |
\*---------------------------------------------------------*/
mode TANDEM;
TANDEM.name = "Tandem";
TANDEM.value = ZOTAC_BLACKWELL_GPU_MODE_TANDEM;
TANDEM.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
TANDEM.brightness_min = 0;
TANDEM.brightness_max = 100;
TANDEM.brightness = 100;
TANDEM.speed_min = 0;
TANDEM.speed_max = 100;
TANDEM.speed = 20;
TANDEM.color_mode = MODE_COLORS_PER_LED;
modes.push_back(TANDEM);
/*---------------------------------------------------------*\
| Tidal mode |
\*---------------------------------------------------------*/
mode TIDAL;
TIDAL.name = "Tidal";
TIDAL.value = ZOTAC_BLACKWELL_GPU_MODE_TIDAL;
TIDAL.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_PER_LED_COLOR;
TIDAL.brightness_min = 0;
TIDAL.brightness_max = 100;
TIDAL.brightness = 100;
TIDAL.speed_min = 0;
TIDAL.speed_max = 100;
TIDAL.speed = 20;
TIDAL.color_mode = MODE_COLORS_PER_LED;
modes.push_back(TIDAL);
/*---------------------------------------------------------*\
| Astra mode |
\*---------------------------------------------------------*/
mode ASTRA;
ASTRA.name = "Astra";
ASTRA.value = ZOTAC_BLACKWELL_GPU_MODE_ASTRA;
ASTRA.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
ASTRA.brightness_min = 0;
ASTRA.brightness_max = 100;
ASTRA.brightness = 100;
ASTRA.speed_min = 0;
ASTRA.speed_max = 100;
ASTRA.speed = 20;
ASTRA.color_mode = MODE_COLORS_PER_LED;
modes.push_back(ASTRA);
/*---------------------------------------------------------*\
| Cosmic mode |
\*---------------------------------------------------------*/
mode COSMIC;
COSMIC.name = "Cosmic";
COSMIC.value = ZOTAC_BLACKWELL_GPU_MODE_COSMIC;
COSMIC.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
COSMIC.brightness_min = 0;
COSMIC.brightness_max = 100;
COSMIC.brightness = 100;
COSMIC.speed_min = 0;
COSMIC.speed_max = 100;
COSMIC.speed = 20;
COSMIC.color_mode = MODE_COLORS_PER_LED;
modes.push_back(COSMIC);
/*---------------------------------------------------------*\
| Volta mode |
\*---------------------------------------------------------*/
mode VOLTA;
VOLTA.name = "Volta";
VOLTA.value = ZOTAC_BLACKWELL_GPU_MODE_VOLTA;
VOLTA.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR;
VOLTA.brightness_min = 0;
VOLTA.brightness_max = 100;
VOLTA.brightness = 100;
VOLTA.speed_min = 0;
VOLTA.speed_max = 100;
VOLTA.speed = 20;
VOLTA.color_mode = MODE_COLORS_PER_LED;
modes.push_back(VOLTA);
SetupZones();
}
RGBController_ZotacBlackwellGPU::~RGBController_ZotacBlackwellGPU()
{
delete controller;
}
void RGBController_ZotacBlackwellGPU::SetupZones()
{
/*---------------------------------------------------------*\
| Zone 0: Logo |
\*---------------------------------------------------------*/
zone logo_zone;
logo_zone.name = "Logo";
logo_zone.type = ZONE_TYPE_SINGLE;
logo_zone.leds_min = 1;
logo_zone.leds_max = 1;
logo_zone.leds_count = 1;
logo_zone.matrix_map = NULL;
zones.push_back(logo_zone);
led logo_led;
logo_led.name = "Logo LED";
leds.push_back(logo_led);
/*---------------------------------------------------------*\
| Zone 1: Side Bar |
\*---------------------------------------------------------*/
zone sidebar_zone;
sidebar_zone.name = "Side Bar";
sidebar_zone.type = ZONE_TYPE_SINGLE;
sidebar_zone.leds_min = 1;
sidebar_zone.leds_max = 1;
sidebar_zone.leds_count = 1;
sidebar_zone.matrix_map = NULL;
zones.push_back(sidebar_zone);
led sidebar_led;
sidebar_led.name = "Side Bar LED";
leds.push_back(sidebar_led);
/*---------------------------------------------------------*\
| Zone 2: Infinity Mirror |
\*---------------------------------------------------------*/
zone infinity_zone;
infinity_zone.name = "Infinity Mirror";
infinity_zone.type = ZONE_TYPE_SINGLE;
infinity_zone.leds_min = 1;
infinity_zone.leds_max = 1;
infinity_zone.leds_count = 1;
infinity_zone.matrix_map = NULL;
zones.push_back(infinity_zone);
led infinity_led;
infinity_led.name = "Infinity Mirror LED";
leds.push_back(infinity_led);
SetupColors();
}
void RGBController_ZotacBlackwellGPU::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_ZotacBlackwellGPU::DeviceUpdateLEDs()
{
DeviceUpdateMode();
}
void RGBController_ZotacBlackwellGPU::UpdateZoneLEDs(int zone)
{
DeviceUpdateZone(zone);
}
void RGBController_ZotacBlackwellGPU::UpdateSingleLED(int led)
{
DeviceUpdateZone(led);
}
void RGBController_ZotacBlackwellGPU::DeviceUpdateZone(int zone)
{
unsigned int mode_val = modes[active_mode].value;
unsigned int brightness = modes[active_mode].brightness;
unsigned int speed = modes[active_mode].speed;
unsigned int direction = modes[active_mode].direction == MODE_DIRECTION_RIGHT
? ZOTAC_BLACKWELL_GPU_DIR_RIGHT
: ZOTAC_BLACKWELL_GPU_DIR_LEFT;
RGBColor color1;
RGBColor color2 = ToRGBColor(0, 0, 0);
switch(modes[active_mode].color_mode)
{
case MODE_COLORS_PER_LED:
color1 = colors[zone];
break;
case MODE_COLORS_MODE_SPECIFIC:
color1 = (modes[active_mode].colors.size() >= 1)
? modes[active_mode].colors[0]
: ToRGBColor(0, 0, 0);
color2 = (modes[active_mode].colors.size() >= 2)
? modes[active_mode].colors[1]
: ToRGBColor(0, 0, 0);
break;
default:
color1 = ToRGBColor(0, 0, 0);
break;
}
controller->SetMode(zone, mode_val, color1, color2, brightness, speed, direction);
controller->Commit();
}
void RGBController_ZotacBlackwellGPU::DeviceUpdateMode()
{
for(unsigned int zone_idx = 0; zone_idx < ZOTAC_BLACKWELL_GPU_NUM_ZONES; zone_idx++)
{
DeviceUpdateZone(zone_idx);
}
}