diff --git a/Source/hoc-clk/common/include/hocclk/board.h b/Source/hoc-clk/common/include/hocclk/board.h index 351f3179..99a609a5 100644 --- a/Source/hoc-clk/common/include/hocclk/board.h +++ b/Source/hoc-clk/common/include/hocclk/board.h @@ -143,6 +143,14 @@ enum { DVFSMode_EnumMax, }; +enum { + CPUDVFSMode_Disabled = 0, + CPUDVFSMode_Modify, // LUT Modify dvfs + // DVFSMode_OfficialService, + // DVFSMode_Hack, + CPUDVFSMode_EnumMax, +}; + typedef enum { GpuSchedulingMode_DoNotOverride = 0, GpuSchedulingMode_Enabled, diff --git a/Source/hoc-clk/common/include/hocclk/config.h b/Source/hoc-clk/common/include/hocclk/config.h index 89d5baae..34d2994b 100644 --- a/Source/hoc-clk/common/include/hocclk/config.h +++ b/Source/hoc-clk/common/include/hocclk/config.h @@ -52,8 +52,12 @@ typedef enum { HocClkConfigValue_OverwriteRefreshRate, HocClkConfigValue_MaxDisplayClockH, - HocClkConfigValue_DVFSMode, - HocClkConfigValue_DVFSOffset, + HocClkConfigValue_GPUDVFSMode, + HocClkConfigValue_GPUDVFSOffset, + + HocClkConfigValue_CPUDVFSMode, + HocClkConfigValue_CPUDVFSOffset, + HocClkConfigValue_LiveCpuUv, HocClkConfigValue_EnableExperimentalSettings, @@ -288,11 +292,17 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case HocClkConfigValue_MaxDisplayClockH: return pretty ? "Max Display Clock (Handheld)" : "drr_max_clock"; - case HocClkConfigValue_DVFSMode: - return pretty ? "DVFS Mode" : "dvfs_mode"; + case HocClkConfigValue_GPUDVFSMode: + return pretty ? "GPU DVFS Mode" : "dvfs_mode"; - case HocClkConfigValue_DVFSOffset: - return pretty ? "DVFS Offset" : "dvfs_offset"; + case HocClkConfigValue_GPUDVFSOffset: + return pretty ? "GPU DVFS Offset" : "dvfs_offset"; + + case HocClkConfigValue_CPUDVFSMode: + return pretty ? "CPU DVFS Mode" : "cpu_dvfs_mode"; + + case HocClkConfigValue_CPUDVFSOffset: + return pretty ? "CPU DVFS Offset" : "cpu_dvfs_offset"; case HocClkConfigValue_GPUScheduling: return pretty ? "GPU Scheduling" : "gpu_scheduling"; @@ -604,7 +614,8 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val) case HocClkConfigValue_ThermalThrottle: case HocClkConfigValue_IsFirstLoad: - case HocClkConfigValue_DVFSMode: + case HocClkConfigValue_GPUDVFSMode: + case HocClkConfigValue_CPUDVFSMode: return 1ULL; case HocClkConfigValue_AutoRAMCPUOverclock: return 0ULL; @@ -800,8 +811,10 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_t6_tRTW_fine_tune: case KipConfigValue_t7_tWTR_fine_tune: case KipCrc32: - case HocClkConfigValue_DVFSMode: - case HocClkConfigValue_DVFSOffset: + case HocClkConfigValue_GPUDVFSMode: + case HocClkConfigValue_GPUDVFSOffset: + case HocClkConfigValue_CPUDVFSMode: + case HocClkConfigValue_CPUDVFSOffset: case HocClkConfigValue_GPUScheduling: case HocClkConfigValue_RAMVoltDisplayMode: case HocClkConfigValue_CpuGovernorMinimumFreq: diff --git a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp index 51abe481..0d384311 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp @@ -506,7 +506,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Default: 800 mV" }; - case HocClkConfigValue_DVFSMode: + case HocClkConfigValue_GPUDVFSMode: return { "The mode used for GPU DVFS", "Adjusts GPU vmin when RAM clock is changed due to a higher requirement", @@ -516,12 +516,28 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Default: PCV Hijack" }; - case HocClkConfigValue_DVFSOffset: + case HocClkConfigValue_GPUDVFSOffset: return { "The offset added/subtracted to the GPU vmin when the RAM clock is changed due to a higher requirement in PCV Hijack mode", "Default: 0 mV (Disabled)" }; + case HocClkConfigValue_CPUDVFSMode: + return { + "The mode used for CPU DVFS", + "Adjusts CPU vmin when RAM clock is changed due to a higher requirement", + "Options:", + "- Disabled: disabled...", + "- LUT Modify: Modify CLDVFS Lut", + "Default: LUT Modify" + }; + + case HocClkConfigValue_CPUDVFSOffset: + return { + "The offset added/subtracted to the CPU vmin when the RAM clock is changed due to a higher requirement in LUT Modify mode", + "Default: 0 mV (Disabled)" + }; + case KipConfigValue_eristaGpuUV: return { "GPU undervolt level", diff --git a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp index e02cfc88..08b9adbf 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp @@ -2477,6 +2477,27 @@ class CpuSubmenuGui : public MiscGui { this->configList->values[KipConfigValue_marikoCpuUVHigh] ? &mCpuClockThresholdsUV : &mCpuClockThresholds, {}, maxClkOptions, false, true); + std::vector dvfsOffset = { + NamedValue("-80 mV", 0xFFFFFFB0), NamedValue("-75 mV", 0xFFFFFFB5), NamedValue("-70 mV", 0xFFFFFFBA), NamedValue("-65 mV", 0xFFFFFFBF), + NamedValue("-60 mV", 0xFFFFFFC4), NamedValue("-55 mV", 0xFFFFFFC9), NamedValue("-50 mV", 0xFFFFFFCE), NamedValue("-45 mV", 0xFFFFFFD3), + NamedValue("-40 mV", 0xFFFFFFD8), NamedValue("-35 mV", 0xFFFFFFDD), NamedValue("-30 mV", 0xFFFFFFE2), NamedValue("-25 mV", 0xFFFFFFE7), + NamedValue("-20 mV", 0xFFFFFFEC), NamedValue("-15 mV", 0xFFFFFFF1), NamedValue("-10 mV", 0xFFFFFFF6), NamedValue(" -5 mV", 0xFFFFFFFB), + NamedValue("Disabled", 0), NamedValue(" +5 mV", 5), NamedValue("+10 mV", 10), NamedValue("+15 mV", 15), + NamedValue("+20 mV", 20), + }; + + std::vector dvfsValues = { + NamedValue("Disabled", CPUDVFSMode_Disabled), + NamedValue("LUT Modify", CPUDVFSMode_Modify), + // NamedValue("Official Service", DVFSMode_OfficialService), + }; + + addConfigButton(HocClkConfigValue_CPUDVFSMode, "CPU DVFS Mode", ValueRange(0, 0, 1, "", 0), "CPU DVFS Mode", &thresholdsDisabled, {}, dvfsValues, + false); + + addConfigButton(HocClkConfigValue_CPUDVFSOffset, "CPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "CPU DVFS Offset", &thresholdsDisabled, {}, + dvfsOffset, false); + } else { addConfigTrackbar(KipConfigValue_eristaCpuUV, "CPU UV", ValueRange(0, 5, 1)); @@ -2648,10 +2669,10 @@ class GpuSubmenuGui : public MiscGui { // NamedValue("Official Service", DVFSMode_OfficialService), }; - addConfigButton(HocClkConfigValue_DVFSMode, "GPU DVFS Mode", ValueRange(0, 0, 1, "", 0), "GPU DVFS Mode", &thresholdsDisabled, {}, dvfsValues, + addConfigButton(HocClkConfigValue_GPUDVFSMode, "GPU DVFS Mode", ValueRange(0, 0, 1, "", 0), "GPU DVFS Mode", &thresholdsDisabled, {}, dvfsValues, false); - addConfigButton(HocClkConfigValue_DVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {}, + addConfigButton(HocClkConfigValue_GPUDVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {}, dvfsOffset, false); tsl::elm::ListItem *customTableSubmenu = new tsl::elm::ListItem("GPU Voltage Table"); diff --git a/Source/hoc-clk/sysmodule/src/board/board_volt.cpp b/Source/hoc-clk/sysmodule/src/board/board_volt.cpp index b53946a7..d65d099c 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_volt.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_volt.cpp @@ -25,6 +25,7 @@ #include #include "../file/file_utils.hpp" +#include "../file/config.hpp" #include "../hos/rgltr.h" #include "../i2c/i2cDrv.h" #include "board.hpp" @@ -593,6 +594,7 @@ namespace board { return baseVolt; } + /* Mariko only! */ constexpr u32 PmicVmin = 250; constexpr u32 PmicStep = 5; @@ -602,6 +604,12 @@ namespace board { } void ApplyCpuDvfs(u32 ramFreqMhz) { + /* Don't reapply the table if it has been*/ + static u32 lastRamFreqMhz = 0; + if(ramFreqMhz == lastRamFreqMhz) { + return; + } + /* Get the minimum DRAM OC Cpu Vmin */ u32 vmin = GetMinimumCpuVmin(ramFreqMhz, GetCpuSpeedoBracket()); @@ -615,7 +623,6 @@ namespace board { if(vlt < vmin) { vlt = vmin; } - /* Don't know if modifying and passing argument causes undefined behavior? */ u32 tempVlt = vlt; vlt = ConvertVoltToLut(tempVlt); @@ -624,12 +631,18 @@ namespace board { /* Pet the watchdog to avoid it hanging the system during this operation */ i2c::wdt::Pet(); - /* DSB to prevent a hang during setting the new LUT */ + /* DSB to prevent a hang during setting the new LUT. ST will not work, SY is needed */ __asm__("dsb SY"); /* Copy the edited LUT into it's appropriate location */ memcpy((void*)(cldvfs + CL_DVFS_OUTPUT_LUT_0), NewCpuVoltTable, sizeof(NewCpuVoltTable)); + + file::utils::LogLine("[cpudvfs]: Set voltage to %dmV for %dMHz", vmin, ramFreqMhz); + /* Pet the watchdog to avoid it hanging the system during this operation */ + i2c::wdt::Pet(); + svcSleepThread(100'000'000); // 100ms + lastRamFreqMhz = ramFreqMhz; } } // namespace board diff --git a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp index 22937f8b..a93de5c3 100644 --- a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp +++ b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp @@ -20,6 +20,7 @@ #include "../file/config.hpp" #include #include +#include "../file/file_utils.hpp" /* PMIC Registers */ #define MAX77620_REG_CNFGGLBL2 ((u8)0x01) @@ -68,6 +69,8 @@ namespace i2c::wdt { return; } + file::utils::LogLine("[Watchdog] armed"); + Result rc; u8 twd; @@ -108,6 +111,7 @@ namespace i2c::wdt { if (!isWdtEnabled) { return; } + file::utils::LogLine("[Watchdog] disarmed"); Result rc = update_bits(MAX77620_REG_CNFGGLBL2, MAX77620_WDTEN, (u8)0x00); ASSERT_RESULT_OK(rc, "update_bits"); diff --git a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp index cc971dd0..f38e3814 100644 --- a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp +++ b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp @@ -427,7 +427,7 @@ namespace mgr { } void ApplyGpuDvfs(u32 targetHz) { - s32 dvfsOffset = file::config::GetConfigValue(HocClkConfigValue_DVFSOffset); + s32 dvfsOffset = file::config::GetConfigValue(HocClkConfigValue_GPUDVFSOffset); dvfsOffset = std::max(dvfsOffset, -80); u32 vmin = board::GetMinimumGpuVmin(targetHz / 1000000, board::GetGpuSpeedoBracket()); @@ -450,8 +450,39 @@ namespace mgr { } } + void ApplyCpuDvfs(u32 targetHz) { + if(file::config::GetConfigValue(HocClkConfigValue_CPUDVFSMode) == CPUDVFSMode_Modify) { + board::ApplyCpuDvfs(targetHz / 1'000'000); // convert to mhz + u32 ltargetHz = gContext.overrideFreqs[HocClkModule_CPU]; + if (!ltargetHz) { + ltargetHz = file::config::GetAutoClockHz(gContext.applicationId, HocClkModule_CPU, gContext.profile, false); + if (!ltargetHz) + ltargetHz = file::config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_CPU, gContext.profile, false); + } + + u32 maxHz = GetMaxAllowedHz(HocClkModule_CPU, gContext.profile); + u32 nearestHz = ltargetHz ? GetNearestHz(HocClkModule_CPU, ltargetHz, maxHz) : 0; + board::SetHz(HocClkModule_CPU, 1'785'000'000); + svcSleepThread(5'000'000); + if(nearestHz != 0) { + board::SetHz(HocClkModule_CPU, nearestHz); + } else { + board::ResetToStockCpu(); + } + } + } + + void ResetCpuDvfs() { + if(file::config::GetConfigValue(HocClkConfigValue_CPUDVFSMode) == CPUDVFSMode_Modify) { + board::ApplyCpuDvfs(0); + board::SetHz(HocClkModule_CPU, 1'785'000'000); + svcSleepThread(5'000'000); + board::ResetToStockCpu(); + } + } + void DVFSReset() { - if (file::config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { + if (file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack) { board::PcvHijackGpuVolts(0); // Reset to vMin u32 targetHz = GetNearestOverrideHz(HocClkModule_GPU); @@ -462,7 +493,7 @@ namespace mgr { } } - void HandleFreqReset(HocClkModule module, bool isBoost, bool didHijackPcv) { + void HandleFreqReset(HocClkModule module, bool isBoost, bool didHijackPcv, bool didApplyCpuDvfs) { switch (module) { case HocClkModule_CPU: if (!(isBoost || (file::config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode) && isBoost))) @@ -485,6 +516,10 @@ namespace mgr { DVFSReset(); didHijackPcv = true; } + if(!didApplyCpuDvfs) { + ResetCpuDvfs(); + didApplyCpuDvfs = true; + } break; case HocClkModule_Display: if (file::config::GetConfigValue(HocClkConfigValue_OverwriteRefreshRate)) { @@ -506,9 +541,10 @@ namespace mgr { u32 nearestFreq = GetCurrentNearestFrequency(HocClkModule_MEM); if (targetRamHz != nearestFreq) { - if (file::config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { + if (file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack) { ApplyGpuDvfs(targetRamHz); } + ApplyCpuDvfs(targetRamHz); board::SetHz(HocClkModule_MEM, targetRamHz); } @@ -520,7 +556,7 @@ namespace mgr { std::uint32_t nearestHz = 0; static bool prepareBoostExit = false; - bool didHijackPcv = false; + bool didHijackPcv = false, didApplyCpuDvfs = false; bool skipCpuDueToBoost = isBoost && !file::config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode); if (skipCpuDueToBoost) { board::SetHz(HocClkModule_CPU, board::GetHz(HocClkModule_CPU)); @@ -570,7 +606,7 @@ namespace mgr { gContext.stable.freqs[HocClkModule_Display] = targetHz; gContext.stable.realFreqs[HocClkModule_Display] = targetHz; } else { - HandleFreqReset(HocClkModule_Display, isBoost, didHijackPcv); + HandleFreqReset(HocClkModule_Display, isBoost, didHijackPcv, didApplyCpuDvfs); } } @@ -605,9 +641,13 @@ namespace mgr { targetHz / 100000 - targetHz / 1000000 * 10); // The logic MUST be done in this order otherwise you WILL get crashes - if (module == HocClkModule_MEM && targetHz > oldHz && file::config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { + if (module == HocClkModule_MEM && targetHz > oldHz && file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack) { ApplyGpuDvfs(targetHz); } + if (module == HocClkModule_MEM && targetHz > oldHz && board::GetSocType() == HocClkSocType_Mariko) { + ApplyCpuDvfs(targetHz); + } + board::SetHz((HocClkModule)module, nearestHz); gContext.freqs[module] = nearestHz; @@ -615,15 +655,22 @@ namespace mgr { gContext.stable.freqs[module] = nearestHz; } - if (module == HocClkModule_MEM && targetHz < oldHz && file::config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { + if (module == HocClkModule_MEM && targetHz < oldHz && file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack) { ApplyGpuDvfs(targetHz); } + if (module == HocClkModule_MEM && targetHz < oldHz && board::GetSocType() == HocClkSocType_Mariko) { + ApplyCpuDvfs(targetHz); + } - if (module == HocClkModule_MEM && file::config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) + if (module == HocClkModule_MEM && file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack) didHijackPcv = false; + + if(module == HocClkModule_MEM && board::GetSocType() == HocClkSocType_Mariko && file::config::GetConfigValue(HocClkConfigValue_CPUDVFSMode) == CPUDVFSMode_Modify) { + didApplyCpuDvfs = true; + } } } else { - HandleFreqReset((HocClkModule)module, isBoost, didHijackPcv); + HandleFreqReset((HocClkModule)module, isBoost, didHijackPcv, didApplyCpuDvfs); } } } @@ -652,7 +699,7 @@ namespace mgr { // restore clocks to stock values on app or profile change if (hasChanged) { board::ResetToStock(); - if (file::config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { + if (file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack) { board::PcvHijackGpuVolts(0); board::ResetToStockGpu(); }