diff --git a/Source/sys-clk/common/include/memmem.h b/Source/sys-clk/common/include/memmem.h new file mode 100644 index 00000000..0c04ae4e --- /dev/null +++ b/Source/sys-clk/common/include/memmem.h @@ -0,0 +1,17 @@ +#ifndef MEMMEM_IMPL_H +#define MEMMEM_IMPL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *memmem_impl(void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Source/sys-clk/common/include/sysclk/board.h b/Source/sys-clk/common/include/sysclk/board.h index beea679e..b3c8e527 100644 --- a/Source/sys-clk/common/include/sysclk/board.h +++ b/Source/sys-clk/common/include/sysclk/board.h @@ -132,6 +132,14 @@ typedef enum { GPUUVLevel_EnumMax, } GPUUndervoltLevel; +enum { + DVFSMode_Disabled, + DVFSMode_Hijack, + // DVFSMode_OfficialService, + // DVFSMode_Hack, + DVFSMode_EnumMax, +}; + #define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax) static inline const char* sysclkFormatModule(SysClkModule module, bool pretty) diff --git a/Source/sys-clk/common/include/sysclk/config.h b/Source/sys-clk/common/include/sysclk/config.h index d4f06a76..8859103f 100644 --- a/Source/sys-clk/common/include/sysclk/config.h +++ b/Source/sys-clk/common/include/sysclk/config.h @@ -57,6 +57,9 @@ typedef enum { HorizonOCConfigValue_OverwriteRefreshRate, HorizonOCConfigValue_EnableUnsafeDisplayFreqs, + + HorizonOCConfigValue_DVFSMode, + HocClkConfigValue_FixCpuVoltBug, KipConfigValue_custRev, @@ -226,6 +229,9 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr case HorizonOCConfigValue_EnableUnsafeDisplayFreqs: return pretty ? "Enable Unsafe Display Frequencies" : "drr_unsafe"; + case HorizonOCConfigValue_DVFSMode: + return pretty ? "DVFS Mode" : "dvfs_mode"; + // KIP config values case KipConfigValue_custRev: return pretty ? "Custom Revision" : "kip_cust_rev"; @@ -411,6 +417,7 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val) case HocClkConfigValue_EnforceBoardLimit: case HocClkConfigValue_FixCpuVoltBug: case HocClkConfigValue_IsFirstLoad: + case HorizonOCConfigValue_DVFSMode: return 1ULL; case HocClkConfigValue_ThermalThrottleThreshold: return 70ULL; @@ -542,6 +549,7 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in case KipConfigValue_t6_tRTW_fine_tune: case KipConfigValue_t7_tWTR_fine_tune: case KipCrc32: + case HorizonOCConfigValue_DVFSMode: return true; case HorizonOCConfigValue_BatteryChargeCurrent: return ((input >= 1024) && (input <= 3072)) || !input; diff --git a/Source/sys-clk/common/src/memmem.c b/Source/sys-clk/common/src/memmem.c new file mode 100644 index 00000000..4530609b --- /dev/null +++ b/Source/sys-clk/common/src/memmem.c @@ -0,0 +1,59 @@ +#include "memmem.h" + +void *memmem_impl(void *haystack, size_t haystacklen, const void *needle, size_t needlelen) +{ + const unsigned char *cmpp; + const unsigned char *p; + const unsigned char *endp; + const unsigned char *q; + const unsigned char *endq; + unsigned char found; + + if(haystack == NULL) + { + return NULL; + } + if(needle == NULL) + { + return haystack; + } + if(haystacklen == 0) + { + return NULL; + } + if(needlelen == 0) + { + return haystack; + } + + if(needlelen > haystacklen) + { + return NULL; + } + + endp = haystack + haystacklen - needlelen; + endq = needle + needlelen; + for(p = haystack; p <= endp; p++) + { + found = 1; + cmpp = p; + for(q = needle; q < endq; q++) + { + if(*cmpp != *q) + { + found = 0; + break; + } + else + { + cmpp++; + } + } + if(found) + { + return (void*)p; + } + } + + return NULL; +} 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 933fdf40..a107b883 100644 --- a/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp @@ -344,8 +344,26 @@ void MiscGui::listUI() }); this->listElement->addItem(gpuSubmenu); + this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental")); + std::vector dvfsValues = { + NamedValue("Disabled", DVFSMode_Disabled), + NamedValue("PCV Hijack", DVFSMode_Hijack), + // NamedValue("Official Service", DVFSMode_OfficialService), + // NamedValue("Hack", DVFSMode_Hack), + }; + + addConfigButton( + HorizonOCConfigValue_DVFSMode, + "GPU DVFS Mode", + ValueRange(0, 0, 1, "", 0), + "GPU DVFS Mode", + &thresholdsDisabled, + {}, + dvfsValues, + false + ); + #if IS_MINIMAL == 0 - this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental")); std::vector chargerCurrents = { NamedValue("Disabled", 0), NamedValue("1024mA", 1024), diff --git a/Source/sys-clk/sysmodule/src/board.cpp b/Source/sys-clk/sysmodule/src/board.cpp index fd159337..42134190 100644 --- a/Source/sys-clk/sysmodule/src/board.cpp +++ b/Source/sys-clk/sysmodule/src/board.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #define MAX(A, B) std::max(A, B) #define MIN(A, B) std::min(A, B) @@ -1050,7 +1051,7 @@ void Board::CacheDvfsTable() { break; } - u8 *resultPattern = static_cast(memmem(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern))); + u8 *resultPattern = static_cast(memmem_impl(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern))); u32 index = resultPattern - buffer; if (!resultPattern) { @@ -1104,6 +1105,7 @@ void Board::PcvHijackDvfs(u32 vmin) { } svcCloseHandle(handle); + FileUtils::LogLine("[dvfs] voltage set to %u mV", vmin); } #define MC_REGISTER_BASE 0x70019000 diff --git a/Source/sys-clk/sysmodule/src/clock_manager.cpp b/Source/sys-clk/sysmodule/src/clock_manager.cpp index 63ef241e..0c86d16e 100644 --- a/Source/sys-clk/sysmodule/src/clock_manager.cpp +++ b/Source/sys-clk/sysmodule/src/clock_manager.cpp @@ -47,8 +47,9 @@ bool hasChanged = true; ClockManager *ClockManager::instance = NULL; Thread governorTHREAD; u32 initialConfigValues[SysClkConfigValue_EnumMax]; // initial config. used for safety checks - +u64 previousRamHz; bool kipAvailable = false; + ClockManager *ClockManager::GetInstance() { return instance; @@ -110,6 +111,7 @@ ClockManager::ClockManager() this->context->dramID = Board::GetDramID(); this->context->isDram8GB = Board::IsDram8GB(); + previousRamHz = Board::GetHz(SysClkModule_MEM); } @@ -196,7 +198,7 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p { if (this->config->GetConfigValue(HocClkConfigValue_UncappedClocks)) { - return 4294967294; // Integer limit, uncapped clocks ON + return ~0; // Integer limit, uncapped clocks ON } else { @@ -246,7 +248,7 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p if(profile < SysClkProfile_HandheldCharging && Board::GetSocType() == SysClkSocType_Erista) { return 1581000000; } else { - return 4294967294; + return ~0; } } } @@ -441,7 +443,6 @@ void ClockManager::GovernorThread(void* arg) bool prevBoostMode = true; - void ClockManager::Tick() { std::scoped_lock lock{this->contextMutex}; @@ -485,6 +486,7 @@ void ClockManager::Tick() if (this->RefreshContext() || this->config->Refresh()) { + if(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)) { I2c_Bq24193_SetFastChargeCurrentLimit(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)); } @@ -496,10 +498,13 @@ void ClockManager::Tick() // ResetToStockClocks(); return; } + previousRamHz = Board::GetHz(SysClkModule_MEM); bool returnRaw = false; for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + u32 oldHz = Board::GetHz((SysClkModule)module); + if(module > SysClkModule_MEM) returnRaw = true; else @@ -559,16 +564,48 @@ void ClockManager::Tick() nearestHz / 1000000, nearestHz / 100000 - nearestHz / 1000000 * 10, targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10 ); - /* Dvfs here. */ + if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz > oldHz) { + Board::PcvHijackDvfs(Board::GetMinimumGpuVoltage(targetHz / 1000000)); + I2c_BuckConverter_SetMvOut(&I2c_Mariko_GPU, Board::GetMinimumGpuVoltage(targetHz / 1000000)); + this->context->voltages[HocClkVoltage_GPU] = Board::GetMinimumGpuVoltage(targetHz / 1000000) * 1000; + } + Board::SetHz((SysClkModule)module, nearestHz); this->context->freqs[module] = nearestHz; + + } + + if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz < oldHz) { + Board::PcvHijackDvfs(0); + // I2c_BuckConverter_SetMvOut(&I2c_Mariko_GPU, 0); + + targetHz = this->context->overrideFreqs[SysClkModule_GPU]; + if (!targetHz) + { + targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_GPU, this->context->profile, false); + if(!targetHz) + targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, this->context->profile, false); + } + if(targetHz) { + Board::SetHz(SysClkModule_GPU, ~0); + Board::SetHz(SysClkModule_GPU, targetHz); + } else { + Board::SetHz(SysClkModule_GPU, ~0); + Board::ResetToStockGpu(); + } } if(module == SysClkModule_CPU && this->config->GetConfigValue(HocClkConfigValue_FixCpuVoltBug)) { FixCpuBug(); } } + // else { + // if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko) { + // Board::PcvHijackDvfs(0); + // } + // } + } } } @@ -713,7 +750,7 @@ bool ClockManager::RefreshContext() for (unsigned int voltageSource = 0; voltageSource < HocClkVoltage_EnumMax; voltageSource++) { - this->context->voltages[voltageSource] = Board::GetVoltage(HocClkVoltage_GPU); + this->context->voltages[voltageSource] = Board::GetVoltage((HocClkVoltage)voltageSource); } if (this->ConfigIntervalTimeout(SysClkConfigValue_CsvWriteIntervalMs, ns, &this->lastCsvWriteNs))