From adcd59848aa86106015c6d16a40df807c0fd6f29 Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Sun, 23 Feb 2020 14:08:59 -0600 Subject: [PATCH] Add RGB Fusion GPU controller and NVAPI I1C interface --- .../RGBFusionGPUController.cpp | 47 ++ .../RGBFusionGPUController.h | 54 ++ .../RGBFusionGPUControllerDetect.cpp | 67 +++ OpenRGB.cpp | 9 +- OpenRGB.pro | 11 +- RGBController/AorusGPUDetect.cpp | 21 - RGBController/RGBController_AorusGPU.cpp | 83 --- RGBController/RGBController_AorusGPU.h | 33 -- RGBController/RGBController_RGBFusionGPU.cpp | 125 ++++ RGBController/RGBController_RGBFusionGPU.h | 28 + i2c_smbus/i2c_smbus_nvapi.cpp | 88 +++ i2c_smbus/i2c_smbus_nvapi.h | 21 + i2c_smbus/nvapi.cpp | 560 ++++++++++++++++++ i2c_smbus/nvapi.h | 465 +++++++++++++++ 14 files changed, 1470 insertions(+), 142 deletions(-) create mode 100644 Controllers/RGBFusionGPUController/RGBFusionGPUController.cpp create mode 100644 Controllers/RGBFusionGPUController/RGBFusionGPUController.h create mode 100644 Controllers/RGBFusionGPUController/RGBFusionGPUControllerDetect.cpp delete mode 100644 RGBController/AorusGPUDetect.cpp delete mode 100644 RGBController/RGBController_AorusGPU.cpp delete mode 100644 RGBController/RGBController_AorusGPU.h create mode 100644 RGBController/RGBController_RGBFusionGPU.cpp create mode 100644 RGBController/RGBController_RGBFusionGPU.h create mode 100644 i2c_smbus/i2c_smbus_nvapi.cpp create mode 100644 i2c_smbus/i2c_smbus_nvapi.h create mode 100644 i2c_smbus/nvapi.cpp create mode 100644 i2c_smbus/nvapi.h diff --git a/Controllers/RGBFusionGPUController/RGBFusionGPUController.cpp b/Controllers/RGBFusionGPUController/RGBFusionGPUController.cpp new file mode 100644 index 00000000..82a3eb2c --- /dev/null +++ b/Controllers/RGBFusionGPUController/RGBFusionGPUController.cpp @@ -0,0 +1,47 @@ +/*-----------------------------------------*\ +| RGBFusionGPUController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion GPU | +| lighting controller | +| | +| Adam Honse (CalcProgrammer1) 2/20/2020 | +\*-----------------------------------------*/ + +#include "RGBFusionGPUController.h" + +RGBFusionGPUController::RGBFusionGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev) +{ + this->bus = bus; + this->dev = dev; +} + +RGBFusionGPUController::~RGBFusionGPUController() +{ + +} + +std::string RGBFusionGPUController::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(return_string); +} + +void RGBFusionGPUController::SetColor(unsigned char red, unsigned char green, unsigned char blue) +{ + bus->i2c_smbus_write_byte(dev, RGB_FUSION_GPU_REG_COLOR); + bus->i2c_smbus_write_byte(dev, red); + bus->i2c_smbus_write_byte(dev, green); + bus->i2c_smbus_write_byte(dev, blue); +} + +void RGBFusionGPUController::SetMode(unsigned char mode, unsigned char speed) +{ + bus->i2c_smbus_write_byte(dev, RGB_FUSION_GPU_REG_MODE); + bus->i2c_smbus_write_byte(dev, mode); + bus->i2c_smbus_write_byte(dev, speed); + bus->i2c_smbus_write_byte(dev, 0x63); +} diff --git a/Controllers/RGBFusionGPUController/RGBFusionGPUController.h b/Controllers/RGBFusionGPUController/RGBFusionGPUController.h new file mode 100644 index 00000000..863894e0 --- /dev/null +++ b/Controllers/RGBFusionGPUController/RGBFusionGPUController.h @@ -0,0 +1,54 @@ +/*-----------------------------------------*\ +| RGBFusionGPUController.h | +| | +| Definitions and types for Gigabyte Aorus | +| RGB Fusion GPU lighting controller | +| | +| Adam Honse (CalcProgrammer1) 2/20/2020 | +\*-----------------------------------------*/ + +#include +#include "i2c_smbus.h" + +#pragma once + +typedef unsigned char rgb_fusion_dev_id; + +enum +{ + RGB_FUSION_GPU_REG_COLOR = 0x40, + RGB_FUSION_GPU_REG_MODE = 0x88 +}; + +enum +{ + RGB_FUSION_GPU_MODE_STATIC = 0x01, + RGB_FUSION_GPU_MODE_BREATHING = 0x02, + RGB_FUSION_GPU_MODE_FLASHING = 0x04, + RGB_FUSION_GPU_MODE_DUAL_FLASHING = 0x08, + RGB_FUSION_GPU_MODE_SPECTRUM_CYCLE = 0x11 +}; + +enum +{ + RGB_FUSION_GPU_SPEED_SLOWEST = 0x00, + RGB_FUSION_GPU_SPEED_NORMAL = 0x05, + RGB_FUSION_GPU_SPEED_FASTEST = 0x09 +}; + +class RGBFusionGPUController +{ +public: + RGBFusionGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev); + ~RGBFusionGPUController(); + + std::string GetDeviceLocation(); + + void SetColor(unsigned char red, unsigned char green, unsigned char blue); + void SetMode(unsigned char mode, unsigned char speed); + +private: + i2c_smbus_interface* bus; + rgb_fusion_dev_id dev; + +}; diff --git a/Controllers/RGBFusionGPUController/RGBFusionGPUControllerDetect.cpp b/Controllers/RGBFusionGPUController/RGBFusionGPUControllerDetect.cpp new file mode 100644 index 00000000..16997827 --- /dev/null +++ b/Controllers/RGBFusionGPUController/RGBFusionGPUControllerDetect.cpp @@ -0,0 +1,67 @@ +#include "RGBFusionGPUController.h" +#include "RGBController.h" +#include "RGBController_RGBFusionGPU.h" +#include "i2c_smbus.h" +#include +#include +#include + +/******************************************************************************************\ +* * +* TestForRGBFusionGPUController * +* * +* Tests the given address to see if an RGB Fusion controller exists there. First * +* does a quick write to test for a response * +* * +\******************************************************************************************/ + +bool TestForRGBFusionGPUController(i2c_smbus_interface* bus, unsigned char address) +{ + bool pass = false; + + int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE); + + if (res >= 0) + { + pass = true; + + res = bus->i2c_smbus_read_byte_data(address, 0xAB); + + if (res != 0x14) + { + pass = false; + } + } + + return(pass); + +} /* TestForRGBFusionGPUController() */ + +/******************************************************************************************\ +* * +* DetectRGBFusionGPUControllers * +* * +* Detect RGB Fusion controllers on the enumerated I2C busses at address 0x47. * +* * +* bus - pointer to i2c_smbus_interface where RGB Fusion device is connected * +* dev - I2C address of RGB Fusion device * +* * +\******************************************************************************************/ + +void DetectRGBFusionGPUControllers(std::vector& busses, std::vector& rgb_controllers) +{ + RGBFusionGPUController* new_rgb_fusion; + RGBController_RGBFusionGPU* new_controller; + + // for (unsigned int bus = 0; bus < busses.size(); bus++) + // { + // Check for RGB Fusion controller at 0x47 + // if (TestForRGBFusionGPUController(busses[bus], 0x47)) +// { + new_rgb_fusion = new RGBFusionGPUController(busses[2], 0x47); + new_controller = new RGBController_RGBFusionGPU(new_rgb_fusion); + rgb_controllers.push_back(new_controller); + // } + // } + +} /* DetectRGBFusionGPUControllers() */ diff --git a/OpenRGB.cpp b/OpenRGB.cpp index bfad1c4d..2682da83 100644 --- a/OpenRGB.cpp +++ b/OpenRGB.cpp @@ -17,6 +17,7 @@ #include "i2c_smbus_piix4.h" #include "i2c_smbus_i801.h" #include "i2c_smbus_nct6775.h" +#include "i2c_smbus_nvapi.h" #include "super_io.h" #include "wmi.h" #else /* WIN32 */ @@ -170,6 +171,9 @@ void DetectI2CBusses() // Detect Nuvoton Super IO SMBus adapters DetectNuvotonI2CBusses(); + i2c_smbus_nvapi * nvapi_bus = new i2c_smbus_nvapi(); + strcpy(nvapi_bus->device_name, "NVAPI Bus"); + busses.push_back(nvapi_bus); } /* DetectI2CBusses() */ #else /* WIN32 */ @@ -254,6 +258,7 @@ void DetectHyperXControllers(std::vector &busses, std::vec void DetectPatriotViperControllers(std::vector &busses, std::vector &rgb_controllers); void DetectPolychromeControllers(std::vector& busses, std::vector& rgb_controllers); void DetectRGBFusionControllers(std::vector& busses, std::vector& rgb_controllers); +void DetectRGBFusionGPUControllers(std::vector& busses, std::vector& rgb_controllers); void DetectMSIRGBControllers(std::vector &rgb_controllers); void DetectLEDStripControllers(std::vector &rgb_controllers); void DetectHue2Controllers(std::vector &rgb_controllers); @@ -261,7 +266,6 @@ void DetectHuePlusControllers(std::vector &rgb_controllers); void DetectOpenRazerControllers(std::vector &rgb_controllers); void DetectE131Controllers(std::vector &rgb_controllers); void DetectAMDWraithPrismControllers(std::vector& rgb_controllers); -void DetectAorusGPUControllers(std::vector &rgb_controllers); void DetectMSI3ZoneControllers(std::vector& rgb_controllers); void DetectPoseidonZRGBControllers(std::vector& rgb_controllers); void DetectCorsairCmdrProControllers(std::vector &rgb_controllers); @@ -291,6 +295,8 @@ void DetectRGBControllers(void) DetectHyperXControllers(busses, rgb_controllers); DetectPatriotViperControllers(busses, rgb_controllers); DetectPolychromeControllers(busses, rgb_controllers); + DetectRGBFusionGPUControllers(busses, rgb_controllers); + DetectRGBFusionControllers(busses, rgb_controllers); DetectMSIRGBControllers(rgb_controllers); @@ -313,7 +319,6 @@ void DetectRGBControllers(void) | Windows-only devices | \*-------------------------------------*/ #ifdef WIN32 - //DetectAorusGPUControllers(rgb_controllers); DetectOpenRazerControllers(rgb_controllers); /*-------------------------------------*\ | Linux-only devices | diff --git a/OpenRGB.pro b/OpenRGB.pro index 97727337..aad78b7a 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -35,6 +35,7 @@ INCLUDEPATH += \ Controllers/PoseidonZRGBController/ \ Controllers/RGBFusionController/ \ Controllers/RGBFusion2Controller/ \ + Controllers/RGBFusionGPUController/ \ Controllers/ThermaltakeRiingController/ \ RGBController/ \ qt/ @@ -96,6 +97,8 @@ SOURCES += \ Controllers/RGBFusionController/RGBFusionControllerDetect.cpp \ Controllers/RGBFusion2Controller/RGBFusion2Controller.cpp \ Controllers/RGBFusion2Controller/RGBFusion2ControllerDetect.cpp \ + Controllers/RGBFusionGPUController/RGBFusionGPUController.cpp \ + Controllers/RGBFusionGPUController/RGBFusionGPUControllerDetect.cpp \ Controllers/ThermaltakeRiingController/ThermaltakeRiingController.cpp \ Controllers/ThermaltakeRiingController/ThermaltakeRiingControllerDetect.cpp \ RGBController/RGBController.cpp \ @@ -122,6 +125,7 @@ SOURCES += \ RGBController/RGBController_PoseidonZRGB.cpp \ RGBController/RGBController_RGBFusion.cpp \ RGBController/RGBController_RGBFusion2.cpp \ + RGBController/RGBController_RGBFusionGPU.cpp \ RGBController/RGBController_ThermaltakeRiing.cpp \ HEADERS += \ @@ -157,6 +161,7 @@ HEADERS += \ Controllers/PoseidonZRGBController/PoseidonZRGBController.h \ Controllers/RGBFusionController/RGBFusionController.h \ Controllers/RGBFusion2Controller/RGBFusion2Controller.h \ + Controllers/RGBFusionGPUController/RGBFusionGPUController.h \ Controllers/ThermaltakeRiingController/ThermaltakeRiingController.h \ RGBController/RGBController.h \ RGBController/RGBController_AMDWraithPrism.h \ @@ -180,6 +185,7 @@ HEADERS += \ RGBController/RGBController_PoseidonZRGB.h \ RGBController/RGBController_RGBFusion.h \ RGBController/RGBController_RGBFusion2.h \ + RGBController/RGBController_RGBFusionGPU.h \ RGBController/RGBController_ThermaltakeRiing.h \ RESOURCES += \ @@ -205,12 +211,12 @@ win32:INCLUDEPATH += \ win32:SOURCES += \ i2c_smbus/i2c_smbus_i801.cpp \ i2c_smbus/i2c_smbus_nct6775.cpp \ + i2c_smbus/i2c_smbus_nvapi.cpp \ i2c_smbus/i2c_smbus_piix4.cpp \ + i2c_smbus/nvapi.cpp \ serial_port/find_usb_serial_port_win.cpp \ wmi/wmi.cpp \ - RGBController/AorusGPUDetect.cpp \ RGBController/OpenRazerWindowsDetect.cpp \ - RGBController/RGBController_AorusGPU.cpp \ RGBController/RGBController_OpenRazerWindows.cpp \ win32:HEADERS += \ @@ -219,7 +225,6 @@ win32:HEADERS += \ i2c_smbus/i2c_smbus_nct6775.h \ i2c_smbus/i2c_smbus_piix4.h \ wmi/wmi.h \ - RGBController/RGBController_AorusGPU.h \ RGBController/RGBController_OpenRazerWindows.h \ win32:contains(QMAKE_TARGET.arch, x86_64) { diff --git a/RGBController/AorusGPUDetect.cpp b/RGBController/AorusGPUDetect.cpp deleted file mode 100644 index a2f4e093..00000000 --- a/RGBController/AorusGPUDetect.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "RGBController.h" -#include "RGBController_AorusGPU.h" -#include -#include -#include - - -/******************************************************************************************\ -* * -* DetectAorusGPUControllers * -* * -* Detect devices supported by the Aorus GPU driver * -* * * -\******************************************************************************************/ - -void DetectAorusGPUControllers(std::vector &rgb_controllers) -{ - RGBController_AorusGPU * aorus_rgb = new RGBController_AorusGPU(); - - rgb_controllers.push_back(aorus_rgb); -} /* DetectLEDStripControllers() */ \ No newline at end of file diff --git a/RGBController/RGBController_AorusGPU.cpp b/RGBController/RGBController_AorusGPU.cpp deleted file mode 100644 index 0fef9d7c..00000000 --- a/RGBController/RGBController_AorusGPU.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AorusGPU.cpp | -| | -| Generic RGB Interface for OpenAuraSDK | -| Aorus GPU | -| | -| Adam Honse (CalcProgrammer1) 6/17/2019 | -\*-----------------------------------------*/ - -#include "RGBController_AorusGPU.h" - -#include - -static HMODULE handle; -static unsigned char data[] = { 0x8E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00 }; - -void RGBController_AorusGPU::UpdateLEDs() -{ - RGBColor color = colors[0]; - data[9] = RGBGetRValue(color); - data[10] = RGBGetGValue(color); - data[11] = RGBGetBValue(color); - - GvWriteI2C(0x00000000, data, 0x00000000); -} - -void RGBController_AorusGPU::UpdateZoneLEDs(int zone) -{ - UpdateLEDs(); -} - -void RGBController_AorusGPU::UpdateSingleLED(int led) -{ - UpdateLEDs(); -} - -RGBController_AorusGPU::RGBController_AorusGPU() -{ - name = "Aorus GPU"; - type = DEVICE_TYPE_GPU; - - handle = LoadLibrary("GvDisplay.dll"); - - GvWriteI2C = (_GvWriteI2C)GetProcAddress(handle, "GvWriteI2C"); - GvFreeDispLib = (_GvFreeDispLib)GetProcAddress(handle, "GvFreeDispLib"); - GvInitDispLib = (_GvInitDispLib)GetProcAddress(handle, "GvInitDispLib"); - - GvFreeDispLib(); - GvInitDispLib(); - - colors.push_back(0x00000000); - - mode aorus_mode; - aorus_mode.name = "Static"; - modes.push_back(aorus_mode); - - led aorus_led; - aorus_led.name = "GPU LED"; - leds.push_back(aorus_led); - - zone aorus_zone; - aorus_zone.name = "GPU LED"; - std::vector aorus_zone_map; - aorus_zone_map.push_back(0); - aorus_zone.map.push_back(aorus_zone_map); - zones.push_back(aorus_zone); -} - -void RGBController_AorusGPU::SetCustomMode() -{ - -} - -void RGBController_AorusGPU::UpdateMode() -{ - -} \ No newline at end of file diff --git a/RGBController/RGBController_AorusGPU.h b/RGBController/RGBController_AorusGPU.h deleted file mode 100644 index a7bb611f..00000000 --- a/RGBController/RGBController_AorusGPU.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AorusGPU.h | -| | -| Generic RGB Interface for OpenAuraSDK | -| Aorus GPU | -| | -| Adam Honse (CalcProgrammer1) 6/17/2019 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" - -typedef unsigned int uint32; -typedef uint32(*_GvWriteI2C)(uint32, void*, uint32); -typedef void (*_GvFreeDispLib)(); -typedef void (*_GvInitDispLib)(); - -class RGBController_AorusGPU : public RGBController -{ -public: - RGBController_AorusGPU(); - void UpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void UpdateMode(); - -private: - _GvWriteI2C GvWriteI2C; - _GvFreeDispLib GvFreeDispLib; - _GvInitDispLib GvInitDispLib; -}; diff --git a/RGBController/RGBController_RGBFusionGPU.cpp b/RGBController/RGBController_RGBFusionGPU.cpp new file mode 100644 index 00000000..ea771cb7 --- /dev/null +++ b/RGBController/RGBController_RGBFusionGPU.cpp @@ -0,0 +1,125 @@ +/*-----------------------------------------*\ +| RGBController_RGBFusionGPU.cpp | +| | +| Generic RGB Interface for OpenRGB | +| Gigabyte RGB Fusion GPU Driver | +| | +| Adam Honse (CalcProgrammer1) 2/23/2020 | +\*-----------------------------------------*/ + +#include "RGBController_RGBFusionGPU.h" + + +void RGBController_RGBFusionGPU::UpdateLEDs() +{ + RGBColor color = colors[0]; + unsigned char red = RGBGetRValue(color); + unsigned char grn = RGBGetGValue(color); + unsigned char blu = RGBGetBValue(color); + + rgb_fusion->SetColor(red, grn, blu); +} + +void RGBController_RGBFusionGPU::UpdateZoneLEDs(int zone) +{ + UpdateLEDs(); +} + +void RGBController_RGBFusionGPU::UpdateSingleLED(int led) +{ + UpdateLEDs(); +} + +RGBController_RGBFusionGPU::RGBController_RGBFusionGPU(RGBFusionGPUController* rgb_fusion_ptr) +{ + rgb_fusion = rgb_fusion_ptr; + + name = "Gigabyte GPU"; + description = "RGB Fusion GPU"; + location = rgb_fusion->GetDeviceLocation(); + + type = DEVICE_TYPE_GPU; + + mode Static; + Static.name = "Static"; + Static.value = RGB_FUSION_GPU_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = RGB_FUSION_GPU_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + Breathing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + Breathing.speed = RGB_FUSION_GPU_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = RGB_FUSION_GPU_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + Flashing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + Flashing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + Flashing.speed = RGB_FUSION_GPU_SPEED_NORMAL; + Flashing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Flashing); + + mode DualFlashing; + DualFlashing.name = "Dual Flashing"; + DualFlashing.value = RGB_FUSION_GPU_MODE_DUAL_FLASHING; + DualFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + DualFlashing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + DualFlashing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + DualFlashing.speed = RGB_FUSION_GPU_SPEED_NORMAL; + DualFlashing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(DualFlashing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = RGB_FUSION_GPU_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED; + SpectrumCycle.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + SpectrumCycle.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + SpectrumCycle.speed = RGB_FUSION_GPU_SPEED_NORMAL; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + colors.resize(1); + + zone* new_zone = new zone(); + led* new_led = new led(); + + std::vector* zone_row = new std::vector(); + + // Set zone name to channel name + new_zone->name = "GPU Zone"; + new_led->name = "GPU LED"; + + zone_row->push_back(0); + + // Aura devices can be either single or linear, never matrix + // That means only one row is needed + new_zone->map.push_back(*zone_row); + + // Push new LED to LEDs vector + leds.push_back(*new_led); + + // Push new zone to zones vector + zones.push_back(*new_zone); + + // Initialize active mode + active_mode = 0; +} + +void RGBController_RGBFusionGPU::SetCustomMode() +{ + active_mode = 0; +} + +void RGBController_RGBFusionGPU::UpdateMode() +{ + rgb_fusion->SetMode(modes[active_mode].value, modes[active_mode].speed); +} diff --git a/RGBController/RGBController_RGBFusionGPU.h b/RGBController/RGBController_RGBFusionGPU.h new file mode 100644 index 00000000..fc458fb5 --- /dev/null +++ b/RGBController/RGBController_RGBFusionGPU.h @@ -0,0 +1,28 @@ +/*-----------------------------------------*\ +| RGBController_RGBFusionGPU.h | +| | +| Generic RGB Interface for OpenRGB | +| Gigabyte RGB Fusion GPU Driver | +| | +| Adam Honse (CalcProgrammer1) 2/23/2020 | +\*-----------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RGBFusionGPUController.h" + +class RGBController_RGBFusionGPU : public RGBController +{ +public: + RGBController_RGBFusionGPU(RGBFusionGPUController* rgb_fusion_ptr); + void UpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void SetCustomMode(); + void UpdateMode(); + +private: + RGBFusionGPUController* rgb_fusion; +}; diff --git a/i2c_smbus/i2c_smbus_nvapi.cpp b/i2c_smbus/i2c_smbus_nvapi.cpp new file mode 100644 index 00000000..d63279d8 --- /dev/null +++ b/i2c_smbus/i2c_smbus_nvapi.cpp @@ -0,0 +1,88 @@ +/*-----------------------------------------*\ +| i2c_smbus_nvapi.cpp | +| | +| NVidia NvAPI I2C driver for Windows | +| | +| Adam Honse (CalcProgrammer1) 2/21/2020 | +\*-----------------------------------------*/ + +#include "i2c_smbus_nvapi.h" +#include "nvapi.h" + +static NV_PHYSICAL_GPU_HANDLE gpu_handles[64]; +static NV_S32 gpu_count = 0; + +i2c_smbus_nvapi::i2c_smbus_nvapi() +{ + NV_STATUS initialize = NvAPI_Initialize(); + + NvAPI_EnumPhysicalGPUs(gpu_handles, &gpu_count); +} + +s32 i2c_smbus_nvapi::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) +{ + NV_STATUS ret; + unsigned int unknown = 0; + NV_I2C_INFO_V3 i2c_data; + uint8_t data_buf[8]; + uint8_t chip_addr; + + chip_addr = command; + + i2c_data.i2c_reg_address = &chip_addr; + i2c_data.reg_addr_size = 1; + + i2c_data.data = data_buf; + i2c_data.size = 0; + + i2c_data.is_ddc_port = 0; + i2c_data.port_id = 1; + i2c_data.is_port_id_set = 1; + + i2c_data.i2c_speed = 0xFFFF; + i2c_data.i2c_speed_khz = NV_I2C_SPEED::NVAPI_I2C_SPEED_DEFAULT; + + + i2c_data.i2c_dev_address = (addr << 1) | read_write; + + switch (size) + { + case I2C_SMBUS_QUICK: + i2c_data.reg_addr_size = 0; + i2c_data.size = 0; + break; + case I2C_SMBUS_BYTE: + i2c_data.reg_addr_size = 0; + data_buf[0] = command; + i2c_data.size = 1; + break; + case I2C_SMBUS_BYTE_DATA: + data_buf[0] = data->byte; + i2c_data.size = 1; + break; + case I2C_SMBUS_WORD_DATA: + data_buf[0] = (data->word & 0x00ff); + data_buf[1] = (data->word & 0xff00) >> 8; + i2c_data.size = 2; + break; + case I2C_SMBUS_BLOCK_DATA: + chip_addr = command; + i2c_data.size = 0; + break; + default: + return -1; + } + + if(read_write == I2C_SMBUS_WRITE) + { + ret = NvAPI_I2CWriteEx(gpu_handles[0], &i2c_data, &unknown); + } + else + { + ret = NvAPI_I2CReadEx(gpu_handles[0], &i2c_data, &unknown); + + data->byte = i2c_data.data[0]; + } + + return(ret); +} diff --git a/i2c_smbus/i2c_smbus_nvapi.h b/i2c_smbus/i2c_smbus_nvapi.h new file mode 100644 index 00000000..c0284ce6 --- /dev/null +++ b/i2c_smbus/i2c_smbus_nvapi.h @@ -0,0 +1,21 @@ +/*-----------------------------------------*\ +| i2c_smbus_nvapi.h | +| | +| Definitions and types for NVidia NvAPI | +| I2C driver | +| | +| Adam Honse (CalcProgrammer1) 2/21/2020 | +\*-----------------------------------------*/ + +#include "i2c_smbus.h" + +#pragma once + +class i2c_smbus_nvapi : public i2c_smbus_interface +{ +public: + i2c_smbus_nvapi(); + +private: + s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); +}; \ No newline at end of file diff --git a/i2c_smbus/nvapi.cpp b/i2c_smbus/nvapi.cpp new file mode 100644 index 00000000..6af354dc --- /dev/null +++ b/i2c_smbus/nvapi.cpp @@ -0,0 +1,560 @@ +#define _WIN32_LEAN_AND_MEAN +#include + +#include "nvapi.h" + +// Constructors for NvAPI structures that just zero the memory and set the right version +NV_DELTA_ENTRY::NV_DELTA_ENTRY() +{ + memset(this, 0, sizeof *this); +} + +NV_GPU_PSTATES20_V2::NV_GPU_PSTATES20_V2() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_PSTATES20_V2, 2); +} + +NV_CLOCK_FREQUENCIES_V2::NV_CLOCK_FREQUENCIES_V2() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_CLOCK_FREQUENCIES_V2, 2); +} + +NV_GPU_PERFORMANCE_TABLE_V1::NV_GPU_PERFORMANCE_TABLE_V1() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_PERFORMANCE_TABLE_V1, 1); +} + +NV_DYNAMIC_PSTATES_V1::NV_DYNAMIC_PSTATES_V1() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_DYNAMIC_PSTATES_V1, 1); +} + +NV_GPU_POWER_POLICIES_INFO_V1::NV_GPU_POWER_POLICIES_INFO_V1() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_POWER_POLICIES_INFO_V1, 1); +} + +NV_GPU_POWER_POLICIES_STATUS_V1::NV_GPU_POWER_POLICIES_STATUS_V1() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_POWER_POLICIES_STATUS_V1, 1); +} + +NV_GPU_VOLTAGE_DOMAINS_STATUS_V1::NV_GPU_VOLTAGE_DOMAINS_STATUS_V1() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_VOLTAGE_DOMAINS_STATUS_V1, 1); +} + +NV_GPU_THERMAL_SETTINGS_V2::NV_GPU_THERMAL_SETTINGS_V2() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_THERMAL_SETTINGS_V2, 2); +} + +NV_GPU_THERMAL_POLICIES_INFO_V2::NV_GPU_THERMAL_POLICIES_INFO_V2() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_THERMAL_POLICIES_INFO_V2, 2); +} + +NV_GPU_THERMAL_POLICIES_STATUS_V2::NV_GPU_THERMAL_POLICIES_STATUS_V2() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_THERMAL_POLICIES_STATUS_V2, 2); +} + +NV_GPU_COOLER_SETTINGS_V2::NV_GPU_COOLER_SETTINGS_V2() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_COOLER_SETTINGS_V2, 2); +} + +NV_GPU_COOLER_LEVELS_V1::NV_GPU_COOLER_LEVELS_V1() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_GPU_COOLER_LEVELS_V1, 1); +} + +NV_MEMORY_INFO_V2::NV_MEMORY_INFO_V2() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_MEMORY_INFO_V2, 2); +} + +NV_DISPLAY_DRIVER_VERSION_V1::NV_DISPLAY_DRIVER_VERSION_V1() +{ + memset(this, 0, sizeof *this); + version = NV_STRUCT_VERSION(NV_DISPLAY_DRIVER_VERSION_V1, 1); +} + +NV_I2C_INFO_V3::NV_I2C_INFO_V3() +{ + memset(this, 0, sizeof * this); + version = NV_STRUCT_VERSION(NV_I2C_INFO_V3, 3); +} + +// Interface: 0150E828 +static NV_STATUS (*pNvAPI_Initialize)(); + +// Interface: D22BDD7E +static NV_STATUS (*pNvAPI_Unload)(); + +// Interface: 9ABDD40D +static NV_STATUS (*pNvAPI_EnumDisplayHandle)( + NV_S32 this_enum, + NV_DISPLAY_HANDLE *display_handle); + +// Interface: E5AC921F +static NV_STATUS (*pNvAPI_EnumPhysicalGPUs)( + NV_PHYSICAL_GPU_HANDLE *physical_gpu_handles, + NV_S32 *gpu_count); + +// Interface: F951A4D1 +static NV_STATUS (*pNvAPI_GetDisplayDriverVersion)( + NV_DISPLAY_HANDLE display_handle, + NV_DISPLAY_DRIVER_VERSION_V1 *display_driver_version); + +// Interface: 01053FA5 +static NV_STATUS (*pNvAPI_GetInterfaceVersionString)( + NV_SHORT_STRING version); + +// Interface: 34EF9506 +static NV_STATUS (*pNvAPI_GetPhysicalGPUsFromDisplay)( + NV_DISPLAY_HANDLE display_handle, + NV_PHYSICAL_GPU_HANDLE *gpu_handles, + NV_U32 *gpu_count); + +// Interface: 774AA982 +static NV_STATUS (*pNvAPI_GetMemoryInfo)( + NV_DISPLAY_HANDLE display_handle, + NV_MEMORY_INFO_V2 *memory_info); + +// Interface: 0CEEE8E9F +static NV_STATUS (*pNvAPI_GPU_GetFullName)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_SHORT_STRING name); + +// Interface: 6FF81213 +static NV_STATUS (*pNvAPI_GPU_GetPStates20)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_PSTATES20_V2 *pstates); + +// Interface: 0F4DAE6B +static NV_STATUS (*pNvAPI_GPU_SetPStates20)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_PSTATES20_V2 *pstates); + +// Interface: DCB616C3 +static NV_STATUS (*pNvAPI_GPU_GetAllClockFrequencies)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_CLOCK_FREQUENCIES_V2 *frequencies); + +// Interface: 60DED2ED +static NV_STATUS (*pNvAPI_GPU_GetDynamicPStates)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_DYNAMIC_PSTATES_V1 *dynamic_pstates); + +// Interface: 34206D86 +static NV_STATUS (*pNvAPI_GPU_GetPowerPoliciesInfo)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_INFO_V1 *policies_info); + +// Interface: 70916171 +static NV_STATUS (*pNvAPI_GPU_GetPowerPoliciesStatus)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_STATUS_V1 *policies_status); + +// Interface: 0C16C7E2C +static NV_STATUS (*pNvAPI_GPU_GetVoltageDomainStatus)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_VOLTAGE_DOMAINS_STATUS_V1 *voltage_domains_status); + +// Interface: 0E3640A56 +static NV_STATUS (*pNvAPI_GPU_GetThermalSettings)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_THERMAL_TARGET sensor_index, + NV_GPU_THERMAL_SETTINGS_V2 *thermal_settings); + +// Interface: 014B83A5F +static NV_STATUS (*pNvAPI_GPU_GetSerialNumber)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_SHORT_STRING serial_number); + +// Interface: 0AD95F5ED +static NV_STATUS (*pNvAPI_GPU_SetPowerPoliciesStatus)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_STATUS_V1* policies_status); + +// Interface: 00D258BB5 +static NV_STATUS (*pNvAPI_GPU_GetThermalPoliciesInfo)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_INFO_V2* thermal_info); + +// Interface: 0E9C425A1 +static NV_STATUS (*pNvAPI_GPU_GetThermalPoliciesStatus)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_STATUS_V2* thermal_status); + +// Interface: 034C0B13D +static NV_STATUS (*pNvAPI_GPU_SetThermalPoliciesStatus)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_STATUS_V2* thermal_status); + +// Interface: DA141340 +static NV_STATUS (*pNvAPI_GPU_GetCoolerSettings)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_S32 cooler_index, + NV_GPU_COOLER_SETTINGS_V2 *cooler_settings); + +// Interface: 891FA0AE +static NV_STATUS (*pNvAPI_GPU_SetCoolerLevels)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_S32 cooler_index, + NV_GPU_COOLER_LEVELS_V1 *cooler_levels); + +// Interface: 2DDFB66E +static NV_STATUS (*pNvAPI_GPU_GetPCIIdentifiers)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_U32 *device_id, + NV_U32 *sub_system_id, + NV_U32 *revision_id, + NV_U32 *ext_device_id); + +// Interface: 283AC65A +static NV_STATUS (*pNvAPI_I2CWriteEx)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_I2C_INFO_V3* i2c_info, + NV_U32 *unknown); + +// Interface: 4D7B0709 +static NV_STATUS(*pNvAPI_I2CReadEx)( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_I2C_INFO_V3* i2c_info, + NV_U32 *unknown); + +static bool QueryInterfaceOpaque(FARPROC query_interface, NV_U32 id, void **result) +{ + void *address = ((void *(*)(NV_U32))query_interface)(id); + if (address) { + *result = address; + return true; + } + return false; +} + +template +static void QueryInterfaceCast(FARPROC query_interface, NV_U32 id, const char *function_name, F &function_pointer) +{ + const bool result = QueryInterfaceOpaque(query_interface, id, (void **)&function_pointer); + ////Log::write("%s querying interface '0x%08x' '%s'", result ? "success" : "failure", id, function_name); +} + +#define QueryInterface(query_interface, id, function) \ + QueryInterfaceCast((query_interface), (id), #function, p ## function) + +static void QueryInterfaces(FARPROC query_interface) +{ + //Log::write("querying interfaces with '0x%p'", query_interface); + + QueryInterface(query_interface, 0x0150E828, NvAPI_Initialize); + QueryInterface(query_interface, 0xD22BDD7E, NvAPI_Unload); + QueryInterface(query_interface, 0x9ABDD40D, NvAPI_EnumDisplayHandle); + QueryInterface(query_interface, 0xE5AC921F, NvAPI_EnumPhysicalGPUs); + QueryInterface(query_interface, 0xF951A4D1, NvAPI_GetDisplayDriverVersion); + QueryInterface(query_interface, 0x01053FA5, NvAPI_GetInterfaceVersionString); + QueryInterface(query_interface, 0x34EF9506, NvAPI_GetPhysicalGPUsFromDisplay); + QueryInterface(query_interface, 0x774AA982, NvAPI_GetMemoryInfo); + + QueryInterface(query_interface, 0x0CEEE8E9F, NvAPI_GPU_GetFullName); + QueryInterface(query_interface, 0x6FF81213, NvAPI_GPU_GetPStates20); + QueryInterface(query_interface, 0x0F4DAE6B, NvAPI_GPU_SetPStates20); + QueryInterface(query_interface, 0xDCB616C3, NvAPI_GPU_GetAllClockFrequencies); + QueryInterface(query_interface, 0x60DED2ED, NvAPI_GPU_GetDynamicPStates); + QueryInterface(query_interface, 0x34206D86, NvAPI_GPU_GetPowerPoliciesInfo); + QueryInterface(query_interface, 0x70916171, NvAPI_GPU_GetPowerPoliciesStatus); + QueryInterface(query_interface, 0x0C16C7E2C, NvAPI_GPU_GetVoltageDomainStatus); + QueryInterface(query_interface, 0x0E3640A56, NvAPI_GPU_GetThermalSettings); + QueryInterface(query_interface, 0x014B83A5F, NvAPI_GPU_GetSerialNumber); + QueryInterface(query_interface, 0x0AD95F5ED, NvAPI_GPU_SetPowerPoliciesStatus); + QueryInterface(query_interface, 0x00D258BB5, NvAPI_GPU_GetThermalPoliciesInfo); + QueryInterface(query_interface, 0x0E9C425A1, NvAPI_GPU_GetThermalPoliciesStatus); + QueryInterface(query_interface, 0x034C0B13D, NvAPI_GPU_SetThermalPoliciesStatus); + QueryInterface(query_interface, 0xDA141340, NvAPI_GPU_GetCoolerSettings); + QueryInterface(query_interface, 0x891FA0AE, NvAPI_GPU_SetCoolerLevels); + QueryInterface(query_interface, 0x2DDFB66E, NvAPI_GPU_GetPCIIdentifiers); + + QueryInterface(query_interface, 0x283AC65A, NvAPI_I2CWriteEx); + QueryInterface(query_interface, 0x4D7B0709, NvAPI_I2CReadEx); +} + +NV_STATUS NvAPI_Initialize() +{ + if (!pNvAPI_Initialize) { + const char *name = sizeof(void*) == 4 ? "nvapi.dll" : "nvapi64.dll"; + HMODULE nvapi = LoadLibraryA(name); + if (!nvapi) { + //Log::write("failed to load '%s'", name); + return -1; + } + + //Log::write("loaded '%s' '0x%p'", name, nvapi); + + FARPROC query_interface = GetProcAddress(nvapi, "nvapi_QueryInterface"); + if (!query_interface) { + //Log::write("failed to find 'nvapi_QueryInterface'"); + return -1; + } + + QueryInterfaces(query_interface); + } + + return pNvAPI_Initialize + ? (*pNvAPI_Initialize)() + : -1; +} + +NV_STATUS NvAPI_Unload() +{ + return pNvAPI_Unload + ? (*pNvAPI_Unload)() + : -1; +} + +NV_STATUS NvAPI_EnumDisplayHandle( + NV_S32 this_enum, + NV_DISPLAY_HANDLE *display_handle) +{ + return pNvAPI_EnumDisplayHandle + ? (*pNvAPI_EnumDisplayHandle)(this_enum, display_handle) + : -1; +} + +NV_STATUS NvAPI_EnumPhysicalGPUs( + NV_PHYSICAL_GPU_HANDLE *physical_gpu_handles, + NV_S32 *gpu_count) +{ + return pNvAPI_EnumPhysicalGPUs + ? (*pNvAPI_EnumPhysicalGPUs)(physical_gpu_handles, gpu_count) + : -1; +} + +NV_STATUS NvAPI_GetDisplayDriverVersion( + NV_DISPLAY_HANDLE display_handle, + NV_DISPLAY_DRIVER_VERSION_V1 *display_driver_version) +{ + return pNvAPI_GetDisplayDriverVersion + ? (*pNvAPI_GetDisplayDriverVersion)(display_handle, display_driver_version) + : -1; +} + +NV_STATUS NvAPI_GetInterfaceVersionString( + NV_SHORT_STRING version) +{ + return pNvAPI_GetInterfaceVersionString + ? (*pNvAPI_GetInterfaceVersionString)(version) + : -1; +} + +NV_STATUS NvAPI_GetPhysicalGPUsFromDisplay( + NV_DISPLAY_HANDLE display_handle, + NV_PHYSICAL_GPU_HANDLE *gpu_handles, + NV_U32 *gpu_count) +{ + return pNvAPI_GetPhysicalGPUsFromDisplay + ? (*pNvAPI_GetPhysicalGPUsFromDisplay)(display_handle, gpu_handles, gpu_count) + : -1; +} + +NV_STATUS NvAPI_GetMemoryInfo( + NV_DISPLAY_HANDLE display_handle, + NV_MEMORY_INFO_V2 *memory_info) +{ + return pNvAPI_GetMemoryInfo + ? (*pNvAPI_GetMemoryInfo)(display_handle, memory_info) + : -1; +} + +NV_STATUS NvAPI_GPU_GetFullName( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_SHORT_STRING name) +{ + return pNvAPI_GPU_GetFullName + ? (*pNvAPI_GPU_GetFullName)(physical_gpu_handle, name) + : -1; +} + +NV_STATUS NvAPI_GPU_GetPStates20( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_PSTATES20_V2 *pstates) +{ + return pNvAPI_GPU_GetPStates20 + ? (*pNvAPI_GPU_GetPStates20)(physical_gpu_handle, pstates) + : -1; +} + +NV_STATUS NvAPI_GPU_SetPStates20( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_PSTATES20_V2 *pstates) +{ + return pNvAPI_GPU_SetPStates20 + ? (*pNvAPI_GPU_GetPStates20)(physical_gpu_handle, pstates) + : -1; +} + +NV_STATUS NvAPI_GPU_GetAllClockFrequencies( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_CLOCK_FREQUENCIES_V2 *frequencies) +{ + return pNvAPI_GPU_GetAllClockFrequencies + ? (*pNvAPI_GPU_GetAllClockFrequencies)(physical_gpu_handle, frequencies) + : -1; +} + +NV_STATUS NvAPI_GPU_GetDynamicPStates( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_DYNAMIC_PSTATES_V1 *dynamic_pstates) +{ + return pNvAPI_GPU_GetDynamicPStates + ? (*pNvAPI_GPU_GetDynamicPStates)(physical_gpu_handle, dynamic_pstates) + : -1; +} + +NV_STATUS NvAPI_GPU_GetPowerPoliciesInfo( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_INFO_V1 *policies_info) +{ + return pNvAPI_GPU_GetPowerPoliciesInfo + ? (*pNvAPI_GPU_GetPowerPoliciesInfo)(physical_gpu_handle, policies_info) + : -1; +} + +NV_STATUS NvAPI_GPU_GetPowerPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_STATUS_V1 *policies_status) +{ + return pNvAPI_GPU_GetPowerPoliciesStatus + ? (*NvAPI_GPU_GetPowerPoliciesStatus)(physical_gpu_handle, policies_status) + : -1; +} + +NV_STATUS NvAPI_GPU_GetVoltageDomainStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_VOLTAGE_DOMAINS_STATUS_V1 *voltage_domains_status) +{ + return pNvAPI_GPU_GetVoltageDomainStatus + ? (*pNvAPI_GPU_GetVoltageDomainStatus)(physical_gpu_handle, voltage_domains_status) + : -1; +} + +NV_STATUS NvAPI_GPU_GetThermalSettings( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_THERMAL_TARGET sensor_index, + NV_GPU_THERMAL_SETTINGS_V2 *thermal_settings) +{ + return pNvAPI_GPU_GetThermalSettings + ? (*pNvAPI_GPU_GetThermalSettings)(physical_gpu_handle, sensor_index, thermal_settings) + : -1; +} + +NV_STATUS NvAPI_GPU_GetSerialNumber( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_SHORT_STRING serial_number) +{ + return pNvAPI_GPU_GetSerialNumber + ? (*pNvAPI_GPU_GetSerialNumber)(physical_gpu_handle, serial_number) + : -1; +} + +NV_STATUS NvAPI_GPU_SetPowerPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_STATUS_V1* policies_status) +{ + return pNvAPI_GPU_SetPowerPoliciesStatus + ? (*pNvAPI_GPU_SetPowerPoliciesStatus)(physical_gpu_handle, policies_status) + : -1; +} + +NV_STATUS NvAPI_GPU_GetThermalPoliciesInfo( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_INFO_V2* thermal_info) +{ + return pNvAPI_GPU_GetThermalPoliciesInfo + ? (*pNvAPI_GPU_GetThermalPoliciesInfo)(physical_gpu_handle, thermal_info) + : -1; +} + +NV_STATUS NvAPI_GPU_GetThermalPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_STATUS_V2* thermal_status) +{ + return pNvAPI_GPU_GetThermalPoliciesStatus + ? (*pNvAPI_GPU_GetThermalPoliciesStatus)(physical_gpu_handle, thermal_status) + : -1; +} + +NV_STATUS NvAPI_GPU_SetThermalPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_STATUS_V2* thermal_status) +{ + return pNvAPI_GPU_SetThermalPoliciesStatus + ? (*pNvAPI_GPU_SetThermalPoliciesStatus)(physical_gpu_handle, thermal_status) + : -1; +} + +NV_STATUS NvAPI_GPU_GetCoolerSettings( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_S32 cooler_index, + NV_GPU_COOLER_SETTINGS_V2 *cooler_settings) +{ + return pNvAPI_GPU_GetCoolerSettings + ? (*pNvAPI_GPU_GetCoolerSettings)(physical_gpu_handle, cooler_index, cooler_settings) + : -1; +} + +NV_STATUS NvAPI_GPU_SetCoolerLevels( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_S32 cooler_index, + NV_GPU_COOLER_LEVELS_V1 *cooler_levels) +{ + return pNvAPI_GPU_SetCoolerLevels + ? (*pNvAPI_GPU_SetCoolerLevels)(physical_gpu_handle, cooler_index, cooler_levels) + : -1; +} + +NV_STATUS NvAPI_GPU_GetPCIIdentifiers( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_U32 *device_id, + NV_U32 *sub_system_id, + NV_U32 *revision_id, + NV_U32 *ext_device_id) +{ + return pNvAPI_GPU_GetPCIIdentifiers + ? (*pNvAPI_GPU_GetPCIIdentifiers)(physical_gpu_handle, device_id, sub_system_id, revision_id, ext_device_id) + : -1; +} + +NV_STATUS NvAPI_I2CWriteEx( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_I2C_INFO_V3* i2c_info, + NV_U32 *unknown) +{ + return pNvAPI_I2CWriteEx + ? (*pNvAPI_I2CWriteEx)(physical_gpu_handle, i2c_info, unknown) + : -1; +} + +NV_STATUS NvAPI_I2CReadEx( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_I2C_INFO_V3* i2c_info, + NV_U32 *unknown) +{ + return pNvAPI_I2CReadEx + ? (*pNvAPI_I2CReadEx)(physical_gpu_handle, i2c_info, unknown) + : -1; +} diff --git a/i2c_smbus/nvapi.h b/i2c_smbus/nvapi.h new file mode 100644 index 00000000..e859b95e --- /dev/null +++ b/i2c_smbus/nvapi.h @@ -0,0 +1,465 @@ +#ifndef NVAPI_H +#define NVAPI_H + +#include + +typedef int32_t NV_S32; +typedef uint32_t NV_U32; +typedef uint8_t NV_U8; + +typedef NV_S32* NV_HANDLE; +typedef NV_HANDLE NV_PHYSICAL_GPU_HANDLE; +typedef NV_HANDLE NV_VIRTUAL_GPU_HANDLE; +typedef NV_HANDLE NV_UNATTACHED_DISPLAY_HANDLE; +typedef NV_HANDLE NV_DISPLAY_HANDLE; + +typedef char NV_SHORT_STRING[64]; + +typedef NV_S32 NV_STATUS; + +#define NV_STRUCT_VERSION(STRUCT, VERSION) \ + (((VERSION) << 16) | sizeof(STRUCT)) + +enum class NV_CLOCK_SYSTEM : NV_S32 { + GPU, + MEMORY, + SHADER +}; + +enum class NV_DYNAMIC_PSTATES_SYSTEM : NV_S32 { + GPU, + FB, + VID, + BUS +}; + +struct NV_DELTA_ENTRY { + NV_DELTA_ENTRY(); + NV_S32 value; + NV_S32 value_min; + NV_S32 value_max; +}; + +struct NV_GPU_PSTATES20_V2 { + NV_GPU_PSTATES20_V2(); + NV_U32 version; + NV_U32 flags; + NV_U32 state_count; + NV_U32 clock_count; + NV_U32 voltage_count; + struct { + NV_U32 state_num; + NV_U32 flags; + struct { + NV_U32 domain; + NV_U32 type; // NOTE(dweiler): 0 = single frequency, 1 = dynamic frequencu + NV_U32 flags; // NOTE(dweiler): flags don't appear to be enforced by NVAPI + NV_DELTA_ENTRY frequency_delta; // NOTE(dweiler): only valid when type == 1 + NV_U32 min_or_single_frequency; // NOTE(dweiler): only valid when type == 0 + NV_U32 max_frequency; // NOTE(dweiler): only valid when type == 1 + NV_U32 voltage_domain; // NOTE(dweiler): only valid when type == 1 + NV_U32 min_voltage; // NOTE(dweiler): only valid when type == 1 + NV_U32 max_voltage; // NOTE(dweiler): only valid when type == 1 + } clocks[8]; + struct { + NV_U32 domain; + NV_U32 flags; // NOTE(dweiler): base voltage can only be changed if bit 0 is set + NV_U32 voltage; + NV_DELTA_ENTRY voltage_delta; + } base_voltages[4]; // NOTE(dweiler): base voltage (resting voltage wheen given a pstate) for all available voltage domains + } states[16]; + struct { + NV_U32 voltage_count; + struct { + NV_U32 domain; + NV_U32 flags; + NV_U32 voltage; + NV_DELTA_ENTRY voltage_delta; + } voltages[4]; + } over_voltage; +}; + +enum class NV_CLOCK_FREQUENCY_TYPE : NV_S32 { + CURRENT, + BASE, + BOOST, + LAST +}; + +struct NV_CLOCK_FREQUENCIES_V2 { + NV_CLOCK_FREQUENCIES_V2(); + NV_U32 version; + NV_U32 clock_type; + struct { + NV_U32 present; + NV_U32 frequency; + } entries[32]; +}; + +struct NV_GPU_PERFORMANCE_TABLE_V1 { + NV_GPU_PERFORMANCE_TABLE_V1(); + NV_U32 version; + NV_U32 plevel_count; + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 domain_entries; + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 pstate_level; + NV_U32 : 32; // NOTE(dweiler): unknown value + struct { + struct { + NV_U32 domain; + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 clock; + NV_U32 default_clock; + NV_U32 min_clock; + NV_U32 max_clock; + NV_U32 : 32; // NOTE(dweiler): unknown value + } domains[32]; + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 setting_flags; + } entries[10]; + NV_U32 unknown[450]; // NOTE(dweiler): the following block of memory is completely unknown +}; + +struct NV_DYNAMIC_PSTATES_V1 { + NV_DYNAMIC_PSTATES_V1(); + NV_U32 version; + NV_U32 flags; + struct { + NV_U32 present; + NV_U32 value; + } pstates[8]; +}; + +struct NV_GPU_POWER_POLICIES_INFO_V1 { + NV_GPU_POWER_POLICIES_INFO_V1(); + NV_U32 version; + NV_U32 flags; + struct { + NV_U32 pstate; + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 min_power; + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 default_power; + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 max_power; + NV_U32 : 32; // NOTE(dweiler): unknown value + } entries[4]; +}; + +struct NV_GPU_POWER_POLICIES_STATUS_V1 { + NV_GPU_POWER_POLICIES_STATUS_V1(); + NV_U32 version; + NV_U32 count; + struct { + NV_U32 pstate; // NOTE(dweiler): assumed? + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_U32 power; + NV_U32 : 32; // NOTE(dweiler): unknown value + } entries[4]; +}; + +struct NV_GPU_VOLTAGE_DOMAINS_STATUS_V1 { + NV_GPU_VOLTAGE_DOMAINS_STATUS_V1(); + NV_U32 version; + NV_U32 flags; + NV_U32 count; + struct { + NV_U32 voltage_domain; + NV_U32 current_voltage; + } entries[16]; +}; + +enum class NV_THERMAL_CONTROLLER : NV_S32 { + NONE, + GPU_INTERNAL, + ADM103, + MAX6649, + MAX1617, + LM99, + LM89, + LM64, + ADT7473, + SBMAX6649, + VBIOSEVT, + OS, + UNKNOWN = -1 +}; + +enum class NV_THERMAL_TARGET : NV_S32 { + NONE = 0, + GPU = 1, + MEMORY = 2, + POWER_SUPPLY = 4, + BOARD = 8, + ALL = 15, + UNKNOWN = -1 +}; + +enum class NV_I2C_SPEED : NV_U32 { + NVAPI_I2C_SPEED_DEFAULT, + NVAPI_I2C_SPEED_3KHZ, + NVAPI_I2C_SPEED_10KHZ, + NVAPI_I2C_SPEED_33KHZ, + NVAPI_I2C_SPEED_100KHZ, + NVAPI_I2C_SPEED_200KHZ, + NVAPI_I2C_SPEED_400KHZ +}; + +struct NV_GPU_THERMAL_SETTINGS_V2 { + NV_GPU_THERMAL_SETTINGS_V2(); + NV_U32 version; + NV_U32 count; + struct { + NV_THERMAL_CONTROLLER controller; + NV_S32 default_min; + NV_S32 default_max; + NV_S32 current_temperature; + NV_THERMAL_TARGET target; + } sensor[3]; +}; + +struct NV_GPU_THERMAL_POLICIES_INFO_V2 { + NV_GPU_THERMAL_POLICIES_INFO_V2(); + NV_U32 version; + NV_U32 flags; + struct { + NV_U32 controller; // NOTE(dweiler): can't be NV_THERMAL_CONTROLLER since this needs to be unsigned + NV_U32 : 32; // NOTE(dweiler): unknown value + NV_S32 min; // NOTE(dweiler): stored as multiples of 256 + NV_S32 default_; // NOTE(dweiler): stored as multiples of 256 + NV_S32 max; // NOTE(dweiler): stored as multiples of 256 + NV_U32 default_flags; // NOTE(dweiler): bit zero of the flags indicates the thermal priority + } entries[4]; +}; + +struct NV_GPU_THERMAL_POLICIES_STATUS_V2 { + NV_GPU_THERMAL_POLICIES_STATUS_V2(); + NV_U32 version; + NV_U32 count; + struct { + NV_U32 controller; + NV_U32 value; // NOTE(dweiler): stored as multiples of 256 + NV_U32 flags; // NOTE(dweiler): bit zero of the flags indicates the thermal priority + } entries[4]; +}; + +struct NV_GPU_COOLER_SETTINGS_V2 { + NV_GPU_COOLER_SETTINGS_V2(); + NV_U32 version; + NV_U32 count; + struct { + NV_S32 type; + NV_S32 controller; + NV_S32 default_min; + NV_S32 default_max; + NV_S32 current_min; + NV_S32 current_max; + NV_S32 current_level; + NV_S32 default_policy; + NV_S32 current_policy; + NV_S32 target; + NV_S32 control_type; + NV_S32 active; + } coolers[20]; +}; + +struct NV_GPU_COOLER_LEVELS_V1 { + NV_GPU_COOLER_LEVELS_V1(); + NV_U32 version; + struct { + NV_S32 level; + NV_S32 policy; // NOTE(dweiler): 0x20 is default policy, 0x01 is user supplied policy + // TODO(dweiler): figure out what other policy values are valid + } levels[20]; +}; + +struct NV_MEMORY_INFO_V2 { + NV_MEMORY_INFO_V2(); + NV_U32 version; + NV_U32 values[5]; +}; + +struct NV_DISPLAY_DRIVER_VERSION_V1 { + NV_DISPLAY_DRIVER_VERSION_V1(); + NV_U32 version; + NV_U32 driver_version; // NOTE(dweiler): major = (driver_version / 100), minor = (driver_version % 100) + NV_U32 : 32; // NOTE(dweiler): unknown vaue + NV_SHORT_STRING build_branch; + NV_SHORT_STRING adapter; +}; + +struct NV_I2C_INFO_V3 { + NV_I2C_INFO_V3(); + NV_U32 version; + NV_U32 display_mask; + NV_U8 is_ddc_port; + NV_U8 i2c_dev_address; + NV_U8* i2c_reg_address; + NV_U32 reg_addr_size; + NV_U8* data; + NV_U32 size; + NV_U32 i2c_speed; + NV_I2C_SPEED i2c_speed_khz; + NV_U8 port_id; + NV_U32 is_port_id_set; +}; + +// Interface: 0150E828 +NV_STATUS NvAPI_Initialize(); + +// Interface: D22BDD7E +NV_STATUS NvAPI_Unload(); + +// Interface: 9ABDD40D +NV_STATUS NvAPI_EnumDisplayHandle( + NV_S32 this_enum, + NV_DISPLAY_HANDLE *display_handle); + +// Interface: E5AC921F +NV_STATUS NvAPI_EnumPhysicalGPUs( + NV_PHYSICAL_GPU_HANDLE *physical_gpu_handles, + NV_S32 *gpu_count); + +// Interface: F951A4D1 +NV_STATUS NvAPI_GetDisplayDriverVersion( + NV_DISPLAY_HANDLE display_handle, + NV_DISPLAY_DRIVER_VERSION_V1 *display_driver_version); + +// Interface: 01053FA5 +NV_STATUS NvAPI_GetInterfaceVersionString( + NV_SHORT_STRING version); + +// Interface: 34EF9506 +NV_STATUS NvAPI_GetPhysicalGPUsFromDisplay( + NV_DISPLAY_HANDLE display_handle, + NV_PHYSICAL_GPU_HANDLE *gpu_handles, + NV_U32 *gpu_count); + +// Interface: 774AA982 +NV_STATUS NvAPI_GetMemoryInfo( + NV_DISPLAY_HANDLE display_handle, + NV_MEMORY_INFO_V2 *memory_info); + +// Interface: 0CEEE8E9F +NV_STATUS NvAPI_GPU_GetFullName( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_SHORT_STRING name); + +// Interface: 6FF81213 +NV_STATUS NvAPI_GPU_GetPStates20( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_PSTATES20_V2 *pstates); + +// Interface: 0F4DAE6B +NV_STATUS NvAPI_GPU_SetPStates20( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_PSTATES20_V2 *pstates); + +// Get frequencies of all clocks of the GPU +// +// The actual frequencies (current, base, boost) returned is based on the value +// set in frequencies->clock_type before calling this function. The value values +// are part of the NV_CLOCK_FREQUENCY_TYPE enumeration. +// +// Interface: DCB616C3 +NV_STATUS NvAPI_GPU_GetAllClockFrequencies( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_CLOCK_FREQUENCIES_V2 *frequencies); + +// Interface: 60DED2ED +NV_STATUS NvAPI_GPU_GetDynamicPStates( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_DYNAMIC_PSTATES_V1 *dynamic_pstates); + +// Interface: 34206D86 +NV_STATUS NvAPI_GPU_GetPowerPoliciesInfo( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_INFO_V1 *policies_info); + +// Interface: 70916171 +NV_STATUS NvAPI_GPU_GetPowerPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_STATUS_V1 *policies_status); + +// Interface: 0C16C7E2C +NV_STATUS NvAPI_GPU_GetVoltageDomainStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_VOLTAGE_DOMAINS_STATUS_V1 *voltage_domains_status); + +// Get the thermal settings of the GPU +// +// The value of [sensor_index] must be one of the values of NV_THERMAL_TARGET, +// either a single sensor, or the special value NV_THERMAL_TARGET::ALL for all +// sensors present on the GPU +// +// Interface: 0E3640A56 +NV_STATUS NvAPI_GPU_GetThermalSettings( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_THERMAL_TARGET sensor_index, + NV_GPU_THERMAL_SETTINGS_V2 *thermal_settings); + +// Get the serial number of the GPU +// +// The NV_SHORT_STRING will be filled out accordingly +// +// Interface: 014B83A5F +NV_STATUS NvAPI_GPU_GetSerialNumber( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_SHORT_STRING serial_number); + +// Interface: 0AD95F5ED +NV_STATUS NvAPI_GPU_SetPowerPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_POWER_POLICIES_STATUS_V1* policies_status); + +// Interface: 00D258BB5 +NV_STATUS NvAPI_GPU_GetThermalPoliciesInfo( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_INFO_V2* thermal_info); + +// Interface: 0E9C425A1 +NV_STATUS NvAPI_GPU_GetThermalPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_STATUS_V2* thermal_status); + +// Interface: 034C0B13D +NV_STATUS NvAPI_GPU_SetThermalPoliciesStatus( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_THERMAL_POLICIES_STATUS_V2* thermal_status); + +// Interface: DA141340 +NV_STATUS NvAPI_GPU_GetCoolerSettings( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_S32 cooler_index, + NV_GPU_COOLER_SETTINGS_V2 *cooler_settings); + +// Interface: 891FA0AE +NV_STATUS NvAPI_GPU_SetCoolerLevels( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_S32 cooler_index, + NV_GPU_COOLER_LEVELS_V1 *cooler_levels); + +// Interface: 2DDFB66E +NV_STATUS NvAPI_GPU_GetPCIIdentifiers( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_U32 *device_id, + NV_U32 *sub_system_id, + NV_U32 *revision_id, + NV_U32 *ext_device_id); + +// Interface: 283AC65A +NV_STATUS NvAPI_I2CWriteEx( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_I2C_INFO_V3 *i2c_info, + NV_U32 *unknown); + +// Interface: 4D7B0709 +NV_STATUS NvAPI_I2CReadEx( + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_I2C_INFO_V3* i2c_info, + NV_U32 *unknown); +#endif