diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp index 112d2e4f..61b8ce0d 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp @@ -58,7 +58,7 @@ namespace ams::ldr::hoc::pcv { static const u32 cpuVoltThermalData[] = { 620, 1120, 20000, 620, 1120, 70000, 950, 1132, 0, 950, 1227, 0 }; - static const u32 allowedCpuMaxFrequencies[] = { 1'963'000, 2'091'000, 2'193'000, 2'295'000, 2'397'000, 2'499'000, 2'601'000, 2'703'000, }; + static const u32 allowedCpuMaxFrequencies[] = { 1'963'000, 2'091'000, 2'193'000, 2'295'000, 2'397'000, 2'499'000, 2'601'000, 2'703'000, 2'805'000, 2'907'000, 3'009'000, }; constexpr cvb_entry_t GpuCvbTableDefault[] = { // GPUB01_NA_CVB_TABLE @@ -207,15 +207,20 @@ namespace ams::ldr::hoc::pcv { constexpr u32 CpuVminOfficial = 825; constexpr u32 CpuVoltL4T = 1235'000; + constexpr u16 CpuMinVolts[] = { 950, 850, 825, 810 }; + inline bool CpuMaxVoltPatternFn(u32* ptr32) { + u32 val = *ptr32; + return (val == 1132 || val == 1170 || val == 1227); + } static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 }; static const u32 cpuVoltDvfsOffsets[] = { 5, 6, 7, 8, 9 }; static_assert(sizeof(cpuVoltDvfsPattern) == sizeof(cpuVoltDvfsOffsets), "Invalid cpuVoltDvfsPattern"); static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 }; static_assert(sizeof(cpuVoltageThermalPattern) == 0x3c, "invalid cpuVoltageThermalPattern size"); - - constexpr u32 GpuClkPllLimit = 921'600'000; + constexpr u32 GpuClkPllLimit = 2'600'000; + constexpr u32 GpuClkPllMax = 921'600'000; constexpr u32 GpuVminOfficial = 810; static const u32 gpuVoltDvfsPattern[] = { 810, 1150, 1000, 100, 1000, 10, }; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp index 9cbfa54e..83d70822 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp @@ -167,20 +167,6 @@ namespace ams::ldr::hoc::pcv::erista { R_SUCCEED(); } - Result GpuFreqPllLimit(u32 *ptr) { - clk_pll_param *entry = reinterpret_cast(ptr); - - // All zero except for freq - for (size_t i = 1; i < sizeof(clk_pll_param) / sizeof(u32); i++) { - R_UNLESS(*(ptr + i) == 0, ldr::ResultInvalidGpuPllEntry()); - } - - // Double the max clk simply - u32 max_clk = entry->freq * 2; - entry->freq = max_clk; - R_SUCCEED(); - } - /* Note: This does not have proper timings, so base latency adjustment will not work. */ /* However, it may still achieve a slightly higher frequency, but not as much as it could be. */ /* I'm certainly not insane enough to attempt this pain again, so this will have to do *for now*. */ @@ -421,18 +407,60 @@ namespace ams::ldr::hoc::pcv::erista { R_SUCCEED(); } + Result CpuVoltRange(u32* ptr) { + u32 min_volt_got = *(ptr - 1); + for (const auto& mv : CpuMinVolts) { + if (min_volt_got != mv) + continue; + + if (!C.eristaCpuMaxVolt) + R_SKIP(); + + PATCH_OFFSET(ptr, C.eristaCpuMaxVolt); + R_SUCCEED(); + } + R_THROW(ldr::ResultInvalidCpuMinVolt()); + } + + Result GpuFreqPllMax(u32 *ptr) { + clk_pll_param *entry = reinterpret_cast(ptr); + + // All zero except for freq + for (size_t i = 1; i < sizeof(clk_pll_param) / sizeof(u32); i++) { + R_UNLESS(*(ptr + i) == 0, ldr::ResultInvalidGpuPllEntry()); + } + + // Double the max clk simply + u32 max_clk = entry->freq * 2; + entry->freq = max_clk; + R_SUCCEED(); + } + + Result GpuFreqPllLimit(u32 *ptr) { + u32 prev_freq = *(ptr - 1); + + if (prev_freq != 128000 && prev_freq != 1300000 && prev_freq != 76800) { + R_THROW(ldr::ResultInvalidGpuPllEntry()); + } + + PATCH_OFFSET(ptr, 3600000); + + R_SUCCEED(); + } void Patch(uintptr_t mapped_nso, size_t nso_size) { PatcherEntry patches[] = { {"CPU Freq Table", CpuFreqCvbTable, 1, nullptr, static_cast(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq)}, {"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, 825}, + {"CPU Volt Limit", &CpuVoltRange, 0, &CpuMaxVoltPatternFn}, {"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, 825}, {"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF}, {"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, 810}, {"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, 810}, {"GPU Freq Table", GpuFreqCvbTable, 1, nullptr, static_cast(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq)}, {"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn}, - {"GPU Freq PLL", &GpuFreqPllLimit, 1, nullptr, GpuClkPllLimit}, + {"GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax}, + {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit}, {"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit}, {"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit}, {"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit}, diff --git a/dist/switch/.overlays/horizon-oc-overlay.ovl b/dist/switch/.overlays/horizon-oc-overlay.ovl index f98a8991..3716e6f2 100644 Binary files a/dist/switch/.overlays/horizon-oc-overlay.ovl and b/dist/switch/.overlays/horizon-oc-overlay.ovl differ