diff --git a/Source/sys-clk/common/include/sysclk/client/ipc.h b/Source/sys-clk/common/include/sysclk/client/ipc.h index 2778050d..931e8a14 100644 --- a/Source/sys-clk/common/include/sysclk/client/ipc.h +++ b/Source/sys-clk/common/include/sysclk/client/ipc.h @@ -52,6 +52,7 @@ Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode); Result hocClkIpcSetKipData(); Result hocClkIpcGetKipData(); Result hocClkIpcUpdateEmcRegs(); +Result hocClkIpcCalculateGpuVmin(); static inline Result sysclkIpcRemoveOverride(SysClkModule module) { diff --git a/Source/sys-clk/common/include/sysclk/ipc.h b/Source/sys-clk/common/include/sysclk/ipc.h index 61678e94..a1ab8516 100644 --- a/Source/sys-clk/common/include/sysclk/ipc.h +++ b/Source/sys-clk/common/include/sysclk/ipc.h @@ -52,6 +52,7 @@ enum SysClkIpcCmd HocClkIpcCmd_SetKipData = 13, HocClkIpcCmd_GetKipData = 14, HocClkIpcCmd_UpdateEmcRegs = 15, + HocClkIpcCmd_CalculateGpuVmin = 16, }; diff --git a/Source/sys-clk/common/src/client/ipc.c b/Source/sys-clk/common/src/client/ipc.c index 0e96c846..a52a3a69 100644 --- a/Source/sys-clk/common/src/client/ipc.c +++ b/Source/sys-clk/common/src/client/ipc.c @@ -175,4 +175,9 @@ Result hocClkIpcUpdateEmcRegs() { u32 temp = 0; return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_UpdateEmcRegs, temp); +} +Result hocClkIpcCalculateGpuVmin() +{ + u32 temp = 0; + return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_CalculateGpuVmin, temp); } \ No newline at end of file diff --git a/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp index 56415e1a..30cc9175 100644 --- a/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp @@ -886,6 +886,19 @@ protected: false ); + tsl::elm::ListItem* vminCalcBtn = new tsl::elm::ListItem("Calculate GPU Vmin"); + vminCalcBtn->setClickListener([this](u64 keys) { + if (keys & HidNpadButton_A) { + Result rc = hocClkIpcCalculateGpuVmin(); + if (R_FAILED(rc)) { + FatalGui::openWithResultCode("hocClkIpcCalculateGpuVmin", rc); + return false; + } + return true; + } + return false; + }); + addConfigButton( KipConfigValue_marikoGpuVmin, "GPU VMIN", diff --git a/Source/sys-clk/sysmodule/src/clock_manager.cpp b/Source/sys-clk/sysmodule/src/clock_manager.cpp index a8b0758b..1a346a69 100644 --- a/Source/sys-clk/sysmodule/src/clock_manager.cpp +++ b/Source/sys-clk/sysmodule/src/clock_manager.cpp @@ -939,4 +939,56 @@ void ClockManager::UpdateRamTimings() { bool hpMode = (bool)this->config->GetConfigValue(KipConfigValue_hpMode); Board::UpdateShadowRegs(t1_tRCD, t2_tRP, t3_tRAS, t4_tRRD, t5_tRFC, t6_tRTW, t7_tWTR, t8_tREFI, ramFreq, rlAdd, wlAdd, hpMode); +} + +unsigned int ramBrackets[][22] = +{ + { 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, }, + { 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, }, + { 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, }, + { 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, } +}; + +unsigned int gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800}; + +int ClockManager::GetSpeedoBracket (int speedo) +{ + int speedoBracket = 3; + if ((speedo < 1754) && (speedoBracket = 2, speedo < 1690)) { + speedoBracket = !!(1625 < speedo); + } + + return speedoBracket; +} + +unsigned int ClockManager::GetGpuVoltage (unsigned int freq, int speedo) +{ + long int loop; + int bracket = GetSpeedoBracket(speedo); + + if (freq < 1601) + return 0; + + loop = 0; + do + { + if (freq <= ramBrackets[bracket][loop]) + return gpuDvfsArray[loop]; + + loop++; + } while (loop != 22); + + return 800; +} + +void ClockManager::calculateGpuVmin (void) +{ + if(this->config->Refresh()) { + SysClkConfigValueList configValues; + this->config->GetConfigValues(&configValues); + + int speedo = Board::getGPUSpeedo(), freq = this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock); + configValues.values[KipConfigValue_marikoGpuVmin] = GetGpuVoltage(freq, speedo); + this->config->SetConfigValues(&configValues, true); + } } \ No newline at end of file diff --git a/Source/sys-clk/sysmodule/src/clock_manager.h b/Source/sys-clk/sysmodule/src/clock_manager.h index da6dedec..9a8140c0 100644 --- a/Source/sys-clk/sysmodule/src/clock_manager.h +++ b/Source/sys-clk/sysmodule/src/clock_manager.h @@ -68,6 +68,10 @@ class ClockManager std::uint32_t count; std::uint32_t list[SYSCLK_FREQ_LIST_MAX]; } freqTable[SysClkModule_EnumMax]; + int GetSpeedoBracket (int speedo); + unsigned int GetGpuVoltage (unsigned int freq, int speedo); + void calculateGpuVmin(void); + protected: bool IsAssignableHz(SysClkModule module, std::uint32_t hz); std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile); diff --git a/Source/sys-clk/sysmodule/src/ipc_service.cpp b/Source/sys-clk/sysmodule/src/ipc_service.cpp index 83b7e0d5..653dffe0 100644 --- a/Source/sys-clk/sysmodule/src/ipc_service.cpp +++ b/Source/sys-clk/sysmodule/src/ipc_service.cpp @@ -214,6 +214,11 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8* return ipcSrv->UpdateEmcRegs(); } break; + case HocClkIpcCmd_CalculateGpuVmin: + if (r->data.size >= 0) { + return ipcSrv->CalculateGPUVmin(); + } + break; } return SYSCLK_ERROR(Generic); @@ -387,3 +392,8 @@ Result IpcService::UpdateEmcRegs() { return 0; } + +Result IpcService::CalculateGPUVmin() { + this->clockMgr->calculateGpuVmin(); + return 0; +} \ No newline at end of file diff --git a/Source/sys-clk/sysmodule/src/ipc_service.h b/Source/sys-clk/sysmodule/src/ipc_service.h index 8c547aee..7f5f083c 100644 --- a/Source/sys-clk/sysmodule/src/ipc_service.h +++ b/Source/sys-clk/sysmodule/src/ipc_service.h @@ -58,6 +58,7 @@ class IpcService Result SetKipData(); Result GetKipData(); Result UpdateEmcRegs(); + Result CalculateGPUVmin(); bool running; Thread thread; LockableMutex threadMutex;