sysclk: make dvfs work

This commit is contained in:
souldbminersmwc
2026-02-11 19:09:55 -05:00
parent 11c456e00c
commit dd447553d4
7 changed files with 157 additions and 8 deletions

View File

@@ -0,0 +1,17 @@
#ifndef MEMMEM_IMPL_H
#define MEMMEM_IMPL_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *memmem_impl(void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -344,8 +344,26 @@ void MiscGui::listUI()
});
this->listElement->addItem(gpuSubmenu);
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
std::vector<NamedValue> 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<NamedValue> chargerCurrents = {
NamedValue("Disabled", 0),
NamedValue("1024mA", 1024),

View File

@@ -41,6 +41,7 @@
#include <cstring>
#include <registers.h>
#include <notification.h>
#include <memmem.h>
#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<u8 *>(memmem(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern)));
u8 *resultPattern = static_cast<u8 *>(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

View File

@@ -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))