add gpu voltage request
This commit is contained in:
@@ -335,9 +335,9 @@ namespace board {
|
||||
}
|
||||
|
||||
/* 800mV on Mariko, 950mV on Erista. */
|
||||
u32 vmax = GetSocType() == HocClkSocType_Mariko ? 800 : 950;
|
||||
u32 bootVoltage = GetSocType() == HocClkSocType_Mariko ? 800 : 950;
|
||||
constexpr u32 GpuVoltageTableOffset = 312;
|
||||
if (!std::memcmp(&buffer[index + GpuVoltageTableOffset], &vmax, sizeof(vmax))) {
|
||||
if (!std::memcmp(&buffer[index + GpuVoltageTableOffset], &bootVoltage, sizeof(bootVoltage))) {
|
||||
std::memcpy(voltData.voltTable, &buffer[index + GpuVoltageTableOffset], sizeof(voltData.voltTable));
|
||||
voltData.voltTableAddress = base + memoryInfo.addr + GpuVoltageTableOffset + index;
|
||||
}
|
||||
@@ -365,18 +365,34 @@ namespace board {
|
||||
return;
|
||||
}
|
||||
|
||||
void PcvHijackGpuVolts(u32 vmin) {
|
||||
void PcvHijackGpuVolts(u32 vmin, bool forceOverwrite) {
|
||||
u32 table[192];
|
||||
static_assert(sizeof(table) == sizeof(voltData.voltTable), "Invalid gpu voltage table size!");
|
||||
std::memcpy(table, voltData.voltTable, sizeof(voltData.voltTable));
|
||||
|
||||
if (voltData.ramVmin == vmin) {
|
||||
/* forceOverwrite needs to be handled regardless. */
|
||||
if (voltData.ramVmin == vmin && !forceOverwrite) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < std::size(table); ++i) {
|
||||
if (table[i] && table[i] <= vmin) {
|
||||
table[i] = vmin;
|
||||
/* Skip adjusting table if vmin is zero (voltage reset), unless forced. */
|
||||
if (vmin != 0 || forceOverwrite) {
|
||||
/* Only apply forced voltage override if it's safe to do so. */
|
||||
if (forceOverwrite && vmin < voltData.ramVmin) {
|
||||
vmin = voltData.ramVmin;
|
||||
}
|
||||
|
||||
if (vmin != 0) {
|
||||
for (u32 i = 0; i < std::size(table); ++i) {
|
||||
if (!table[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool raiseVoltageRamOc = table[i] <= vmin && !forceOverwrite;
|
||||
if (raiseVoltageRamOc || forceOverwrite) {
|
||||
table[i] = vmin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +404,7 @@ namespace board {
|
||||
|
||||
Result rc = svcWriteDebugProcessMemory(handle, table, voltData.voltTableAddress, sizeof(table));
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (R_SUCCEEDED(rc) && !forceOverwrite) {
|
||||
voltData.ramVmin = vmin;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace board {
|
||||
u32 CalculateTbreak(u32 table);
|
||||
u32 GetVoltage(HocClkVoltage voltage);
|
||||
void CacheGpuVoltTable();
|
||||
void PcvHijackGpuVolts(u32 vmin);
|
||||
void PcvHijackGpuVolts(u32 vmin, bool forceOverwrite);
|
||||
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket);
|
||||
|
||||
} // namespace board
|
||||
|
||||
@@ -235,6 +235,15 @@ namespace ipcService {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case HocClkIpcCmd_RequestGpuVoltage:
|
||||
if (r->data.size >= sizeof(u32)) {
|
||||
u32 voltage;
|
||||
memcpy(&voltage, r->data.ptr, sizeof(u32));
|
||||
clockManager::ApplyGpuVoltageRequest(voltage);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return HOCCLK_ERROR(Generic);
|
||||
|
||||
@@ -332,6 +332,28 @@ namespace clockManager {
|
||||
}
|
||||
}
|
||||
|
||||
u32 ClampGpuVoltage(u32 voltage) {
|
||||
constexpr u32 MaxGpuVoltage = 960;
|
||||
return std::min(voltage, MaxGpuVoltage);
|
||||
}
|
||||
|
||||
u32 GetCurrentNearestGpuFrequency() {
|
||||
u32 gpuHz = board::GetHz(HocClkModule_GPU);
|
||||
u32 maxHz = GetMaxAllowedHz(HocClkModule_GPU, gContext.profile);
|
||||
return GetNearestHz(HocClkModule_GPU, gpuHz, maxHz);
|
||||
}
|
||||
|
||||
void ApplyGpuVoltageRequest(u32 voltage) {
|
||||
fileUtils::LogLine("Unclamped voltage request: %u", voltage);
|
||||
voltage = ClampGpuVoltage(voltage);
|
||||
fileUtils::LogLine("Actual voltage: %u", voltage);
|
||||
|
||||
board::PcvHijackGpuVolts(voltage, true);
|
||||
|
||||
/* Update the voltage using the currently nearest valid gpu frequency. */
|
||||
board::SetHz(HocClkModule_GPU, GetCurrentNearestGpuFrequency());
|
||||
}
|
||||
|
||||
void ApplyGpuDvfs(u32 targetHz) {
|
||||
s32 dvfsOffset = config::GetConfigValue(HocClkConfigValue_DVFSOffset);
|
||||
dvfsOffset = std::max(dvfsOffset, -80);
|
||||
@@ -342,19 +364,14 @@ namespace clockManager {
|
||||
}
|
||||
|
||||
/* Prevent console from combusting if for some reason bad shit happens :P */
|
||||
vmin = std::min(vmin, 1000u);
|
||||
|
||||
/* Get nearest gpu clock; we need this in a second to update the voltage. */
|
||||
u32 gpuHz = board::GetHz(HocClkModule_GPU);
|
||||
u32 maxHz = GetMaxAllowedHz(HocClkModule_GPU, gContext.profile);
|
||||
u32 nearestGpuHz = GetNearestHz(HocClkModule_GPU, gpuHz, maxHz);
|
||||
vmin = ClampGpuVoltage(vmin);
|
||||
|
||||
/* Hijack gpu volt table. */
|
||||
board::PcvHijackGpuVolts(vmin);
|
||||
board::PcvHijackGpuVolts(vmin, false);
|
||||
|
||||
/* Update gpu frequency to actually use the voltage. */
|
||||
if (targetHz) {
|
||||
board::SetHz(HocClkModule_GPU, nearestGpuHz);
|
||||
board::SetHz(HocClkModule_GPU, GetCurrentNearestGpuFrequency());
|
||||
} else {
|
||||
/* If the target frequency is zero, we reset the frequency to ensure it gets updated even without any frequency override. */
|
||||
board::ResetToStockGpu();
|
||||
@@ -363,7 +380,7 @@ namespace clockManager {
|
||||
|
||||
void DVFSReset() {
|
||||
if (config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
board::PcvHijackGpuVolts(0); // Reset to vMin
|
||||
board::PcvHijackGpuVolts(0, false); // Reset to vMin
|
||||
|
||||
u32 targetHz = gContext.overrideFreqs[HocClkModule_GPU];
|
||||
if (!targetHz) {
|
||||
@@ -515,6 +532,7 @@ namespace clockManager {
|
||||
if (module == HocClkModule_MEM && targetHz > oldHz && config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
ApplyGpuDvfs(targetHz);
|
||||
}
|
||||
|
||||
board::SetHz((HocClkModule)module, nearestHz);
|
||||
gContext.freqs[module] = nearestHz;
|
||||
|
||||
@@ -560,7 +578,7 @@ namespace clockManager {
|
||||
if (hasChanged) {
|
||||
board::ResetToStock();
|
||||
if (config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
board::PcvHijackGpuVolts(0);
|
||||
board::PcvHijackGpuVolts(0, false);
|
||||
board::ResetToStockGpu();
|
||||
}
|
||||
WaitForNextTick();
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace clockManager {
|
||||
|
||||
void GetFreqList(HocClkModule module, std::uint32_t *list, std::uint32_t maxCount, std::uint32_t *outCount);
|
||||
|
||||
void ApplyGpuVoltageRequest(u32 voltage);
|
||||
|
||||
void Tick();
|
||||
void WaitForNextTick();
|
||||
} // namespace clockManager
|
||||
|
||||
Reference in New Issue
Block a user