diff --git a/README.md b/README.md index 569f1920..b22b57a6 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to ``` kip1=atmosphere/kips/hoc.kip + secmon=atmosphere/exosphere.bin ``` *(No changes needed if using fusee.)* diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index 69bf226d..ee0b3c7a 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -35,8 +35,8 @@ volatile CustomizeTable C = { /* Disables RAM powerdown */ .hpMode = DISABLED, -.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */ -.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */ +.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */ +.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */ .eristaEmcMaxClock1 = 1600000, .eristaEmcMaxClock2 = 1600000, @@ -47,7 +47,7 @@ volatile CustomizeTable C = { .marikoEmcMaxClock = 2133000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */ .marikoEmcVddqVolt = 600000, -.emcDvbShift = 0, +.emcDvbShift = 0, .marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */ /* Primary. */ @@ -86,35 +86,37 @@ volatile CustomizeTable C = { /* You can mix and match different latencies if needed */ /* - * Read: - * 2133RL = 40 - * 1866RL = 36 - * 1600RL = 32 - * 1331RL = 28 - * Write: - * 2133WL = 18 - * 1866WL = 16 - * 1600WL = 14 - * 1331WL = 12 + * Read: + * 2133RL = 40 + * 1866RL = 36 + * 1600RL = 32 + * 1331RL = 28 + * Write: + * 2133WL = 18 + * 1866WL = 16 + * 1600WL = 14 + * 1331WL = 12 */ -.mem_burst_read_latency = RL_1600, +/* Erista only. */ +.mem_burst_read_latency = RL_1600, .mem_burst_write_latency = WL_1600, -.eristaCpuUV = 0, -.eristaCpuVmin = 800, +.eristaCpuUV = 0, +.eristaCpuVmin = 800, .eristaCpuMaxVolt = 1200, /* Unlocks up to 2397 Mhz CPU, usage is not recommended. */ -.eristaCpuUnlock = DISABLED, +.eristaCpuUnlock = DISABLED, -.marikoCpuUVLow = 0, // No undervolt +.marikoCpuUVLow = 0, // No undervolt .marikoCpuUVHigh = 0, // No undervolt -.tableConf = TBREAK_1683, -.marikoCpuLowVmin = 620, +.tableConf = TBREAK_1683, +.marikoCpuLowVmin = 620, .marikoCpuHighVmin = 750, + /* 1120mV is NVIDIA rating */ -.marikoCpuMaxVolt = 1120, +.marikoCpuMaxVolt = 1120, /* Supported values: 1963500, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000. */ /* 1963500 is official rating of T214/Mariko, fully safe. */ @@ -125,17 +127,16 @@ volatile CustomizeTable C = { /* 2703000 is potentially dangerous and not advised. */ .marikoCpuMaxClock = 1963500, -.eristaCpuBoostClock = 1785000, // Default boost clock -.marikoCpuBoostClock = 1963500, // Default boost clock +.eristaCpuBoostClock = 1785000, /* Default boost clock */ +.marikoCpuBoostClock = 1963500, /* Default boost clock */ -.eristaGpuUV = 0, +.eristaGpuUV = 0, .eristaGpuVmin = 810, .marikoGpuUV = 0, - -/* Vmin past 795mV won't work due boot voltage being 800mV. */ +/* Vmin past 795mV won't work due boot voltage being 800mV (can be adjusted though). */ .marikoGpuVmin = 610, - +.marikoGpuBootVolt = 800, /* Used during boot and when temp is <20°C */ .marikoGpuVmax = 800, .commonGpuVoltOffset = 0, @@ -147,7 +148,6 @@ volatile CustomizeTable C = { /* AUTO: Voltage is optimally chosen; with commonGpuVoltOffset applied. */ /* AUTO only works up to 1305 GPU on Mariko and 998 GPU on Erista (it is reccomended to manually set your 998MHz voltage though) */ /* You can overwrite auto with any voltage (in mv) of your choice - offset will not be applied. */ - .eristaGpuVoltArray = { AUTO /* 76 */, AUTO /* 115 */, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp index 3a3d9ddb..5cfb87ca 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp @@ -20,8 +20,8 @@ #pragma once -#define CUST_REV 3 -#define KIP_VERSION 231 +#define CUST_REV 4 +#define KIP_VERSION 240 #include "oc_common.hpp" #include "pcv/pcv_common.hpp" @@ -30,8 +30,8 @@ namespace ams::ldr::hoc { enum TableConfig: u32 { DEFAULT_TABLE = 1, - TBREAK_1581 = 2, - TBREAK_1683 = 3, + TBREAK_1581 = 2, + TBREAK_1683 = 3, EXTREME_TABLE = 4, }; @@ -42,19 +42,6 @@ enum StepMode: u32 { StepMode_133MHz = 3, }; -/* - * Read: - * 2133RL = 40 - * 1866RL = 36 - * 1600RL = 32 - * 1331RL = 28 - * Write: - * 2133WL = 18 - * 1866WL = 16 - * 1600WL = 14 - * 1331WL = 12 - */ - enum ReadLatency: u32 { RL_2133 = 40, RL_1866 = 36, @@ -74,11 +61,8 @@ using CustomizeGpuDvfsTable = pcv::cvb_entry_t[pcv::DvfsTableEntryLimit]; static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(CustomizeGpuDvfsTable)); static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(pcv::cvb_entry_t) * pcv::DvfsTableEntryLimit); -constexpr uint32_t ERISTA_MTC_MAGIC = 0x43544D45; // EMTC -constexpr uint32_t MARIKO_MTC_MAGIC = 0x43544D4D; // MMTC - struct CustomizeTable { - u8 cust[4] = {'C', 'U', 'S', 'T'}; + u8 cust[4] = {'C', 'U', 'S', 'T'}; u32 custRev = CUST_REV; u32 kipVersion = KIP_VERSION; @@ -137,6 +121,7 @@ struct CustomizeTable { u32 marikoGpuUV; u32 marikoGpuVmin; + u32 marikoGpuBootVolt; u32 marikoGpuVmax; u32 commonGpuVoltOffset; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp index 80d2db11..a56588e6 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp @@ -66,27 +66,32 @@ namespace ams::ldr::hoc { size_t maximum_patched_count = 0; patternFn pattern_search_fn = nullptr; Pointer value_search; - size_t patched_count = 0; - Result Apply(Pointer* ptr) { + Result Apply(Pointer *ptr) { Result res = patcher_fn(ptr); - if (R_SUCCEEDED(res)) + if (R_SUCCEEDED(res)) { patched_count++; + } return res; } - Result SearchAndApply(Pointer* ptr) { + Result SearchAndApply(Pointer *ptr) { bool searchOk = false; if (pattern_search_fn) { - if (pattern_search_fn(ptr)) searchOk = true; + if (pattern_search_fn(ptr)) { + searchOk = true; + } } else { - if (value_search == *(ptr)) searchOk = true; + if (value_search == *(ptr)) { + searchOk = true; + } } - if (searchOk) + if (searchOk) { return Apply(ptr); + } R_THROW(ldr::ResultUnsuccessfulPatcher()); } @@ -94,8 +99,9 @@ namespace ams::ldr::hoc { Result CheckResult() { R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher()); - if (maximum_patched_count) + if (maximum_patched_count) { R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher()); + } R_SUCCEED(); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp index 96ab2180..a34c2dd6 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp @@ -22,20 +22,20 @@ namespace ams::ldr::hoc::pcv { - Result MemFreqPllmLimit(u32* ptr) { - clk_pll_param* entry = reinterpret_cast(ptr); + Result MemFreqPllmLimit(u32 *ptr) { + clk_pll_param *entry = reinterpret_cast(ptr); R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry()); // Double the max clk simply - u32 max_clk = entry->freq * 2; - entry->freq = max_clk; + u32 max_clk = entry->freq * 2; + entry->freq = max_clk; entry->vco_max = max_clk; R_SUCCEED(); } - Result MemVoltHandler(u32* ptr) { + Result MemVoltHandler(u32 *ptr) { // ptr value might be default_uv or max_uv - regulator* entries[2] = { + regulator *entries[2] = { reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_1.default_uv)), reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_1.max_uv)), }; @@ -44,16 +44,16 @@ namespace ams::ldr::hoc::pcv { constexpr u32 uv_min = 600'000; auto validator = [](regulator* entry) { - R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); R_SUCCEED(); }; - regulator* entry = nullptr; - for (auto& i : entries) { + regulator *entry = nullptr; + for (auto &i : entries) { if (R_SUCCEEDED(validator(i))) { entry = i; } @@ -76,24 +76,25 @@ namespace ams::ldr::hoc::pcv { } void SafetyCheck() { - // if (C.custRev != CUST_REV) - // CRASH("Triggered"); - struct sValidator { volatile u32 value; u32 min; u32 max; - bool value_required = false; u32 panic; + bool value_required = false; Result check() { - if (!value_required && !value) + if (!value_required && !value) { R_SUCCEED(); + } - if (min && value < min) + if (min && value < min) { R_THROW(ldr::ResultSafetyCheckFailure()); - if (max && value > max) + } + + if (max && value > max) { R_THROW(ldr::ResultSafetyCheckFailure()); + } R_SUCCEED(); } @@ -102,28 +103,24 @@ namespace ams::ldr::hoc::pcv { u32 eristaCpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq); u32 marikoCpuDvfsMaxFreq; if (C.marikoCpuUVHigh) { - marikoCpuDvfsMaxFreq = static_cast( - GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq - ); + marikoCpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq); } else { - marikoCpuDvfsMaxFreq = static_cast( - GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq - ); + marikoCpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq); } u32 eristaGpuDvfsMaxFreq; switch (C.eristaGpuUV) { - case 0: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); - break; - case 1: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq); - break; - case 2: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq); - break; - default: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); - break; + case 0: + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); + break; + case 1: + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq); + break; + case 2: + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq); + break; + default: + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); + break; } u32 marikoGpuDvfsMaxFreq; @@ -142,22 +139,21 @@ namespace ams::ldr::hoc::pcv { break; } - using namespace ams::ldr::hoc::pcv; sValidator validators[] = { - { C.eristaCpuBoostClock, 1020'000, 2397'000, true, panic::Cpu }, - { C.marikoCpuBoostClock, 1020'000, 2703'000, true, panic::Cpu }, - { C.eristaCpuMaxVolt, 1000, 1260, false, panic::Cpu }, - { C.marikoCpuMaxVolt, 1000, 1200, false, panic::Cpu }, - { eristaCpuDvfsMaxFreq, 1785'000, 2397'000, false, panic::Cpu }, - { marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu }, - { C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV - { GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc }, - { C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc }, - { C.marikoEmcVddqVolt, 400'000, 750'000, false, panic::Emc }, - { C.marikoSocVmax, 1000, 1200, false, panic::Emc }, - { eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu }, - { marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu }, - { C.marikoGpuVmax, 800, 960, false, panic::Gpu }, + { C.eristaCpuBoostClock, 1020'000, 2397'000, panic::Cpu, true }, + { C.marikoCpuBoostClock, 1020'000, 2703'000, panic::Cpu, true }, + { C.eristaCpuMaxVolt, 1000, 1260, panic::Cpu, }, + { C.marikoCpuMaxVolt, 1000, 1200, panic::Cpu, }, + { eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, }, + { marikoCpuDvfsMaxFreq, 1785'000, 2703'000, panic::Cpu, }, + { C.commonEmcMemVolt, 912'500, 1350'000, panic::Emc, }, /* Official vmax for the RAMs is 1400-1500mV */ + { GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, panic::Emc, }, + { C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, }, + { C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, }, + { C.marikoSocVmax, 1000, 1200, panic::Emc, }, + { eristaGpuDvfsMaxFreq, 768'000, 1152'000, panic::Gpu, }, + { marikoGpuDvfsMaxFreq, 768'000, 1536'000, panic::Gpu, }, + { C.marikoGpuVmax, 800, 960, panic::Gpu, }, }; for (auto &v : validators) { diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp index a0a06777..3bd40045 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp @@ -118,34 +118,34 @@ namespace ams::ldr::hoc::pcv { cvb_entry_t *customize_table; if (isMariko) { switch (C.marikoGpuUV) { - case 0: - customize_table = const_cast(C.marikoGpuDvfsTable); - break; - case 1: - customize_table = const_cast(C.marikoGpuDvfsTableSLT); - break; - case 2: - customize_table = const_cast(C.marikoGpuDvfsTableHiOPT); - break; - default: - customize_table = const_cast(C.marikoGpuDvfsTable); - break; - } + case 0: + customize_table = const_cast(C.marikoGpuDvfsTable); + break; + case 1: + customize_table = const_cast(C.marikoGpuDvfsTableSLT); + break; + case 2: + customize_table = const_cast(C.marikoGpuDvfsTableHiOPT); + break; + default: + customize_table = const_cast(C.marikoGpuDvfsTable); + break; + } } else { switch (C.eristaGpuUV) { - case 0: - customize_table = const_cast(C.eristaGpuDvfsTable); - break; - case 1: - customize_table = const_cast(C.eristaGpuDvfsTableSLT); - break; - case 2: - customize_table = const_cast(C.eristaGpuDvfsTableHiOPT); - break; - default: - customize_table = const_cast(C.eristaGpuDvfsTable); - break; - } + case 0: + customize_table = const_cast(C.eristaGpuDvfsTable); + break; + case 1: + customize_table = const_cast(C.eristaGpuDvfsTableSLT); + break; + case 2: + customize_table = const_cast(C.eristaGpuDvfsTableHiOPT); + break; + default: + customize_table = const_cast(C.eristaGpuDvfsTable); + break; + } } size_t default_entry_count = GetDvfsTableEntryCount(default_table); @@ -195,26 +195,6 @@ namespace ams::ldr::hoc::pcv { Result MemFreqPllmLimit(u32 *ptr); Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2 - template - Result MemMtcCustomizeTable(T *dst, T *src) { - constexpr u32 mtc_magic = std::is_same_v ? MARIKO_MTC_MAGIC : ERISTA_MTC_MAGIC; - R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic()); - - constexpr u32 ZERO_VAL = UINT32_MAX; - // Skip params from dvfs_ver to clock_src; - for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32)) { - u32 *src_ent = reinterpret_cast(reinterpret_cast(src) + offset); - u32 *dst_ent = reinterpret_cast(reinterpret_cast(dst) + offset); - u32 src_val = *src_ent; - - if (src_val){ - PATCH_OFFSET(dst_ent, src_val == ZERO_VAL ? 0 : src_val); - } - } - - R_SUCCEED(); - }; - void SafetyCheck(); void Patch(uintptr_t mapped_nso, size_t nso_size); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp index 3ba1d333..2482c80c 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp @@ -145,11 +145,11 @@ namespace ams::ldr::hoc::pcv { constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1; template - size_t GetDvfsTableEntryCount(T* table_head) { + size_t GetDvfsTableEntryCount(T *table_head) { using NT = std::remove_const_t>; auto is_empty = [](NT* entry) { - uint8_t* m = reinterpret_cast(entry); + u8 *m = reinterpret_cast(entry); for (size_t i = 0; i < sizeof(NT); i++) { if (*(m + i)) { return false; @@ -158,7 +158,7 @@ namespace ams::ldr::hoc::pcv { return true; }; - NT* table = const_cast(table_head); + NT *table = const_cast(table_head); size_t count = 0; while (count < DvfsTableEntryLimit) { if (is_empty(table++)) { @@ -170,10 +170,10 @@ namespace ams::ldr::hoc::pcv { } template - T* GetDvfsTableLastEntry(T* table_head) { + T *GetDvfsTableLastEntry(T *table_head) { using NT = std::remove_const_t>; - NT* table = const_cast(table_head); + NT *table = const_cast(table_head); size_t count = GetDvfsTableEntryCount(table_head); if (!count) { return nullptr; 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 0d42cd67..85ef4de2 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp @@ -136,17 +136,13 @@ namespace ams::ldr::hoc::pcv::erista { Result GpuFreqMaxAsm(u32 *ptr32) { // Check if both two instructions match the pattern u32 ins1 = *ptr32, ins2 = *(ptr32 + 1); - if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1]))) + if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1]))) { R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); + } // Both instructions should operate on the same register u8 rd = asm_get_rd(ins1); - if (rd != asm_get_rd(ins2)) - R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); - - /* Verify the limit. */ - /* TODO: Make this a little bit cleaner at some point. */ - if (AsmGetImm16(ins1) != (GpuClkOsLimit & 0xFFFF) || AsmGetImm16(ins2) != (GpuClkOsLimit >> 16)) { + if (rd != asm_get_rd(ins2)) { R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); } @@ -165,6 +161,7 @@ namespace ams::ldr::hoc::pcv::erista { max_clock = GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq; break; } + u32 asm_patch[2] = { asm_set_rd(asm_set_imm16(GpuAsmPattern[0], max_clock), rd), asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd) @@ -279,22 +276,20 @@ namespace ams::ldr::hoc::pcv::erista { // WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv); // WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2); // WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv); - // ams::ldr::hoc::pcv::mariko::CalculateMrw2(); // table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast(mrw2); // table->dram_timings.rl = RL; - /* This needs some clean up. */ constexpr double MC_ARB_DIV = 4.0; constexpr u32 MC_ARB_SFA = 2; - table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV; - table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2; - table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1; - table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1; - table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2; - table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1; - table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1; - table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV; + table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2; + table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2; + table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(tR2P / MC_ARB_DIV); table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp index a5b2e5e5..d5787206 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -50,15 +50,18 @@ namespace ams::ldr::hoc::pcv::mariko { R_THROW(ldr::ResultInvalidGpuDvfs()); } - if (!C.marikoGpuVmin) { - R_SKIP(); - } - PATCH_OFFSET(ptr, C.marikoGpuVmin); - PATCH_OFFSET(ptr + 3, C.marikoGpuVmin); - PATCH_OFFSET(ptr + 6, C.marikoGpuVmin); - PATCH_OFFSET(ptr + 9, C.marikoGpuVmin); - PATCH_OFFSET(ptr + 12, C.marikoGpuVmin); + if(C.marikoGpuBootVolt) { + PATCH_OFFSET(ptr - 3, C.marikoGpuBootVolt); + } + + if (C.marikoGpuVmin) { + PATCH_OFFSET(ptr, C.marikoGpuVmin); + PATCH_OFFSET(ptr + 3, C.marikoGpuVmin); + PATCH_OFFSET(ptr + 6, C.marikoGpuVmin); + PATCH_OFFSET(ptr + 9, C.marikoGpuVmin); + PATCH_OFFSET(ptr + 12, C.marikoGpuVmin); + } R_SUCCEED(); } @@ -822,8 +825,8 @@ namespace ams::ldr::hoc::pcv::mariko { auto DvbVolt = [&](s32 zero, s32 one, s32 two) { return std::array{ ClampVolt(zero, max0), - ClampVolt(one, max1), - ClampVolt(two, max2) + ClampVolt(one, max1), + ClampVolt(two, max2) }; }; @@ -832,16 +835,36 @@ namespace ams::ldr::hoc::pcv::mariko { static_cast((v)[1]), \ static_cast((v)[2]) DvbEntry emcDvbOcTableBrackets[] = { - { 204000, { 637, 637, 637, }, }, - { 1331200, { 650, 637, 637, }, }, - { 1600000, { 675, 650, 637, }, }, - { 1866000, { DVB(DvbVolt( 700, 675, 650)) }, }, - { 2133000, { DVB(DvbVolt( 725, 700, 675)) }, }, - { 2400000, { DVB(DvbVolt( 750, 725, 700)) }, }, - { 2666000, { DVB(DvbVolt( 850, 825, 800)) }, }, - { 2933000, { DVB(DvbVolt( 950, 925, 900)) }, }, - { 3200000, { DVB(DvbVolt(1050, 1025, 1000)) }, }, - { ~0u, { }, }, + { 204000, { 637, 637, 637, }, }, + { 1331200, { 650, 637, 637, }, }, + { 1600000, { 675, 650, 637, }, }, + { 1866000, { DVB(DvbVolt( 700, 675, 650)) }, }, + { 2133000, { DVB(DvbVolt( 725, 700, 675)) }, }, + { 2246000, { DVB(DvbVolt( 750, 725, 700)) }, }, + { 2400000, { DVB(DvbVolt( 775, 750, 725)) }, }, + { 2466000, { DVB(DvbVolt( 800, 775, 750)) }, }, + { 2533000, { DVB(DvbVolt( 810, 785, 760)) }, }, + { 2566000, { DVB(DvbVolt( 820, 795, 770)) }, }, + { 2600000, { DVB(DvbVolt( 830, 805, 780)) }, }, + { 2633000, { DVB(DvbVolt( 840, 815, 790)) }, }, + { 2666000, { DVB(DvbVolt( 850, 825, 800)) }, }, + { 2700000, { DVB(DvbVolt( 860, 835, 810)) }, }, + { 2733000, { DVB(DvbVolt( 870, 845, 820)) }, }, + { 2766000, { DVB(DvbVolt( 880, 855, 830)) }, }, + { 2800000, { DVB(DvbVolt( 895, 865, 840)) }, }, + { 2833000, { DVB(DvbVolt( 900, 875, 850)) }, }, + { 2866000, { DVB(DvbVolt( 910, 885, 860)) }, }, + { 2900000, { DVB(DvbVolt( 920, 895, 870)) }, }, + { 2933000, { DVB(DvbVolt( 950, 905, 880)) }, }, + { 2966000, { DVB(DvbVolt( 960, 915, 890)) }, }, + { 3000000, { DVB(DvbVolt( 970, 925, 900)) }, }, + { 3033000, { DVB(DvbVolt( 980, 940, 910)) }, }, + { 3066000, { DVB(DvbVolt(1000, 955, 920)) }, }, + { 3100000, { DVB(DvbVolt(1010, 990, 930)) }, }, + { 3133000, { DVB(DvbVolt(1025, 1005, 940)) }, }, + { 3166000, { DVB(DvbVolt(1035, 1015, 950)) }, }, + { 3200000, { DVB(DvbVolt(1050, 1025, 960)) }, }, + { ~0u, { }, }, }; #undef DVB DvbEntry emcDvbTableOc[newEmcList.size()]; diff --git a/Source/hoc-clk/common/include/hocclk/config.h b/Source/hoc-clk/common/include/hocclk/config.h index 603effdd..afb333d9 100644 --- a/Source/hoc-clk/common/include/hocclk/config.h +++ b/Source/hoc-clk/common/include/hocclk/config.h @@ -76,6 +76,7 @@ typedef enum { HocClkConfigValue_MarikoMiddleFreqs, KipConfigValue_custRev, + KipConfigValue_KipVersion, // KipConfigValue_mtcConf, KipConfigValue_hpMode, @@ -138,6 +139,7 @@ typedef enum { KipConfigValue_marikoGpuUV, KipConfigValue_marikoGpuVmin, + KipConfigValue_marikoGpuBootVolt, KipConfigValue_marikoGpuVmax, KipConfigValue_commonGpuVoltOffset, @@ -295,6 +297,8 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr // KIP config values case KipConfigValue_custRev: return pretty ? "Custom Revision" : "kip_cust_rev"; + case KipConfigValue_KipVersion: + return pretty ? "KIP Version" : "kip_version"; // case KipConfigValue_mtcConf: // return pretty ? "MTC Config" : "kip_mtc_conf"; case KipConfigValue_hpMode: @@ -413,6 +417,8 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr return pretty ? "Mariko GPU Undervolt" : "mariko_gpu_uv"; case KipConfigValue_marikoGpuVmin: return pretty ? "Mariko GPU Vmin" : "mariko_gpu_vmin"; + case KipConfigValue_marikoGpuBootVolt: + return pretty ? "Mariko GPU Boot Voltage" : "mariko_gpu_boot_volt"; case KipConfigValue_marikoGpuVmax: return pretty ? "Mariko GPU Vmax" : "mariko_gpu_vmax"; @@ -566,7 +572,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case HocClkConfigValue_GPUSchedulingMethod: case HocClkConfigValue_MarikoMiddleFreqs: return (input & 0x1) == input; - + case KipConfigValue_KipVersion: case KipConfigValue_custRev: // case KipConfigValue_mtcConf: case KipConfigValue_hpMode: @@ -616,6 +622,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_eristaGpuVmin: case KipConfigValue_marikoGpuUV: case KipConfigValue_marikoGpuVmin: + case KipConfigValue_marikoGpuBootVolt: case KipConfigValue_marikoGpuVmax: case KipConfigValue_commonGpuVoltOffset: case KipConfigValue_gpuSpeedo: @@ -690,6 +697,6 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in return ((input >= 800) && (input <= 1325)); default: - return false; + return true; } } \ No newline at end of file diff --git a/Source/hoc-clk/overlay/Makefile b/Source/hoc-clk/overlay/Makefile index 8ea269b1..cba8b621 100644 --- a/Source/hoc-clk/overlay/Makefile +++ b/Source/hoc-clk/overlay/Makefile @@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk # version control constants #--------------------------------------------------------------------------------- #TARGET_VERSION := $(shell git describe --dirty --always --tags) -APP_VERSION := 2.3.1 # ensure to set KIP_VERSION and CUST_REV in sysmodule Makefile when updating this +APP_VERSION := 2.4.0 # ensure to set KIP_VERSION and CUST_REV in sysmodule Makefile when updating this TARGET_VERSION := $(APP_VERSION) #--------------------------------------------------------------------------------- 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 793d7e75..fb53a489 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 @@ -24,7 +24,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, { case HocClkConfigValue_PollingIntervalMs: return { - "The interval (in miliseconds) where clocks are applied, tempratures and voltages are polled and logs are written (if enabled).", + "The interval (in milliseconds) where clocks are applied, temperatures and voltages are polled and logs are written (if enabled).", "Higher values may cause more delay between changing a setting and it taking effect, and lower values may increase sysmodule memory usage", "Default: 300ms" }; @@ -35,6 +35,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Options:", "- MHz: Megahertz (e.g. 1600 MHz)", "- MT/s: MegaTransfers per second (e.g. 3200 MT/s)", + "- MHz and MT/s: Display in both MHz and MT/s", "Default: MHz" }; @@ -109,8 +110,10 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, case HocClkConfigValue_OverwriteRefreshRate: return { - "Conrols the avaiability of display refresh rate features.", - "When enabled, allows changing the display refresh rate and using display refresh rate related features." + "Controls the availability of display refresh rate features.", + "When enabled, allows changing the display refresh rate and using display refresh rate related features.", + "This feature conflicts with FPSLocker's feature that does the same thing.", + "Default: OFF" }; case HocClkConfigValue_MaxDisplayClockH: @@ -193,32 +196,6 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, " - Speedo 1487-1598: Bracket 0", " - Speedo 1598-1709: Bracket 1", " - Speedo 1709-1820: Bracket 2", - "SOC Volt Table:", - " - 1331/1600MHz tables are not modified", - " - 1633-1866MHz:", - " - Bracket 0: 700mV", - " - Bracket 1: 675mV", - " - Bracket 2: 650mV", - " - 1900-2133MHz:", - " - Bracket 0: 725mV", - " - Bracket 1: 700mV", - " - Bracket 2: 675mV", - " - 2166-2400MHz:", - " - Bracket 0: 750mV", - " - Bracket 1: 725mV", - " - Bracket 2: 700mV", - " - 2433-2666MHz:", - " - Bracket 0: 850mV", - " - Bracket 1: 825mV", - " - Bracket 2: 800mV", - " - 2700-2933MHz:", - " - Bracket 0: 950mV", - " - Bracket 1: 925mV", - " - Bracket 2: 900mV", - " - 2966-3200MHz:", - " - Bracket 0: 1050mV", - " - Bracket 1: 1025mV", - " - Bracket 2: 1000mV", "Default: 0" }; @@ -261,7 +238,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, " - 1600, 1866, 1996, 2133, 2400, 2666, 2933 and 3200 MHz are used", "The RAM max clock will always be available regardless of the step mode, but the intermediate frequencies will be limited by the selected step mode.", "This setting does not affect performance and the option you choose mostly is based on your personal taste", - "33 MHz step mode is not possible due to certian limitations of Horizon OS", + "33 MHz step mode is not possible due to certain limitations of Horizon OS", "Default: 66 MHz", }; @@ -356,13 +333,13 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, case KipConfigValue_t6_tRTW_fine_tune: return { - "Finetunes the raw calculation of t6", + "Fine-tunes the raw calculation of t6", "Default: 0" }; case KipConfigValue_t7_tWTR_fine_tune: return { - "Finetunes the raw calculation of t6", + "Fine-tunes the raw calculation of t7", "Default: 0" }; @@ -379,11 +356,11 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Example:", "If 1333 is set to 2000 MHz, 1600 set to 2500 MHz, 1866 set to 2766 MHz and 2133 set to 2933 MHz:", "Frequencies below 2000 MHz use 1333, 2033-2500 MHz use 1600, 2533-2766 MHz use 1866 and 2800-2933 MHz use 2133. ", - "Either of these can be ommited and it will work (say you set 1333 to -, then <2000 MHz will use 1600 latency)", - "If all of these parameters are ommited the latency will automatically be calculated as follows:", + "Either of these can be omitted and it will work (say you set 1333 to -, then <2000 MHz will use 1600 latency)", + "If all of these parameters are omitted the latency will automatically be calculated as follows:", "1633-1866 MHz - 1866 WRL", "1900+ MHz - 2133 WRL", - "These properties apply for both write and read latencies, and you can mix-and-match the brackets if nessesary", + "These properties apply for both write and read latencies, and you can mix-and-match the brackets if necessary", "Default: -" }; @@ -499,7 +476,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Options:", " - HiOPT: L4T Custom HiOPT table", " - HiOPT - 15mV: L4T Custom HiOPT table with a 15mV offset", - " - High UV: The highest undervolt table, reccomended", + " - High UV: The highest undervolt table, recommended", "Default: HiOPT" }; @@ -538,14 +515,14 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Options:", " - HiOPT: L4T Custom HiOPT table", " - HiOPT - 15mV: L4T Custom HiOPT table with a 15mV offset", - " - High UV: The highest undervolt table, reccomended", + " - High UV: The highest undervolt table, recommended", "Default: HiOPT" }; case KipConfigValue_eristaGpuVmin: return { "Minimum GPU voltage", - "Default: 810 mV (812mV as erista is stepped my 6.5mV instead of 5mV)" + "Default: 810 mV (812mV as erista is stepped by 6.5mV instead of 5mV)" }; case KipConfigValue_commonGpuVoltOffset: @@ -563,7 +540,12 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "- Enabled: Enables GPU scheduling, 96.5% GPU max load", "Default: Do not override" }; - + case KipConfigValue_marikoGpuBootVolt: + return { + "The voltage supplied to the GPU during boot and when the temperature is below 20°C (in mV).", + "Warning: Changing this value may cause instability.", + "Default: 800mV" + }; default: return {}; } 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 1b3d05ce..0ff44c7e 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp @@ -922,6 +922,14 @@ protected: ); } if(!IsAula()) { + tsl::elm::CustomDrawer* warningTextDV = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("\uE150 Adjust the display voltage", false, x + 20, y + 30, 18, tsl::style::color::ColorText); + renderer->drawString("with caution to avoid damage", false, x + 20, y + 50, 18, tsl::style::color::ColorText); + renderer->drawString("to your display panel! ", false, x + 20, y + 70, 18, tsl::style::color::ColorText); + renderer->drawString("Proceed at your own risk!", false, x + 20, y + 90, 18, tsl::style::color::ColorText); + }); + warningTextDV->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 110); + this->listElement->addItem(warningTextDV); addConfigButton( HocClkConfigValue_DisplayVoltage, "Display Voltage", @@ -1059,7 +1067,7 @@ protected: {1250000, "Unsafe Max"}, }; - ValueThresholds vdd2Thresholds(IsMariko() ? 1212500 : 1237500, 1250000); + ValueThresholds vdd2Thresholds(IsMariko() ? 1212500 : 1237500, IsMariko() ? 1250000 : 1275000); addConfigButton( KipConfigValue_commonEmcMemVolt, "RAM VDD2 Voltage", @@ -1073,12 +1081,13 @@ protected: ); if(IsMariko()) { + ValueThresholds vddqThresholds(675000, 725000); addConfigButton( KipConfigValue_marikoEmcVddqVolt, "RAM VDDQ Voltage", - ValueRange(400000, 700000, 5000, "mV", 1000), + ValueRange(400000, 750000, 5000, "mV", 1000), "RAM VDDQ Voltage", - &thresholdsDisabled, + &vddqThresholds, {}, {}, false, @@ -1293,10 +1302,12 @@ protected: ValueThresholds thresholdsDisabled(0, 0); this->listElement->addItem(new tsl::elm::CategoryHeader("Advanced")); - addConfigButton(KipConfigValue_timingEmcTbreak, "RAM-Timing tBreak", ValueRange(0, 1, 1, "", 1), "tBreak", &thresholdsDisabled, {}, timingTbreakFreqs, false, true); - addConfigTrackbar(KipConfigValue_low_t6_tRTW, "Low t6 tRTW", ValueRange(0, 9, 1)); - addConfigTrackbar(KipConfigValue_low_t7_tWTR, "Low t7 tWTR", ValueRange(0, 9, 1)); - addConfigTrackbar(KipConfigValue_t2_tRP_cap, "1333WL t2 RP Cap", ValueRange(0, 8, 1)); + if(IsMariko()) { + addConfigButton(KipConfigValue_timingEmcTbreak, "RAM-Timing tBreak", ValueRange(0, 1, 1, "", 1), "tBreak", &thresholdsDisabled, {}, timingTbreakFreqs, false, true); + addConfigTrackbar(KipConfigValue_low_t6_tRTW, "Low t6 tRTW", ValueRange(0, 9, 1)); + addConfigTrackbar(KipConfigValue_low_t7_tWTR, "Low t7 tWTR", ValueRange(0, 9, 1)); + addConfigTrackbar(KipConfigValue_t2_tRP_cap, "1333WL t2 RP Cap", ValueRange(0, 8, 1)); + } addMappedConfigTrackbar(KipConfigValue_t6_tRTW_fine_tune, "t6 tRTW Fine Tune", {0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u}, {"-2", "-1", " 0", "+1", "+2"}); @@ -1931,6 +1942,7 @@ protected: // return false; // }); + addConfigButton(KipConfigValue_marikoGpuBootVolt, "GPU Boot Volt", ValueRange(700, 800, 5, "mV", 1), "GPU Boot Voltage", &thresholdsDisabled, {}, {}, false, true); addConfigButton(KipConfigValue_marikoGpuVmin, "GPU VMIN", ValueRange(0, 0, 0, "0", 1), "GPU VMIN", &thresholdsDisabled, {}, mGpuVoltsVmin, false, true); ValueThresholds MgpuVmaxThresholds(805, 850); addConfigButton( diff --git a/Source/hoc-clk/sysmodule/Makefile b/Source/hoc-clk/sysmodule/Makefile index aea82a5f..e54363df 100644 --- a/Source/hoc-clk/sysmodule/Makefile +++ b/Source/hoc-clk/sysmodule/Makefile @@ -28,9 +28,9 @@ INCLUDES := ../common/include src/hos src/soc src/i2c src/util src/pwr src/ipc EXEFS_SRC := exefs_src LIBNAMES := minIni # major minor patch -TARGET_VERSION := 2.3.1 -KIP_VERSION := 231 -CUST_REV := 3 +TARGET_VERSION := 2.4.0 +KIP_VERSION := 240 +CUST_REV := 4 #--------------------------------------------------------------------------------- # options for code generation diff --git a/Source/hoc-clk/sysmodule/src/board/board.cpp b/Source/hoc-clk/sysmodule/src/board/board.cpp index 8f15d034..1c321b18 100644 --- a/Source/hoc-clk/sysmodule/src/board/board.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board.cpp @@ -48,6 +48,7 @@ #include "../tsensor/aotag.hpp" #include "../hos/integrations.hpp" #include "../file/file_utils.hpp" +#include "../hos/rgltr.h" namespace board { u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr; @@ -137,6 +138,9 @@ namespace board { rc = pmdmntInitialize(); ASSERT_RESULT_OK(rc, "pmdmntInitialize"); + rc = rgltrInitialize(); + ASSERT_RESULT_OK(rc, "rgltrInitialize"); + rc = QueryMemoryMapping(&clkVirtAddr, 0x60006000, 0x1000); ASSERT_RESULT_OK(rc, "QueryMemoryMapping (clk)"); @@ -201,7 +205,7 @@ namespace board { apmExtExit(); psmExit(); - + rgltrExit(); if (HOSSVC_HAS_TC) { tcExit(); } diff --git a/Source/hoc-clk/sysmodule/src/board/board_freq.cpp b/Source/hoc-clk/sysmodule/src/board/board_freq.cpp index 918a1f51..7e1c0d48 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_freq.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_freq.cpp @@ -41,6 +41,7 @@ #include "../soc/pllmb.hpp" #include "../file/config.hpp" #include "../soc/gm20b.hpp" +#include "../file/config.hpp" namespace board { #define MIDDLE_FREQ_TABLE_START_POINT 1228800000 static u32 currentInjectedHz = 0; @@ -75,6 +76,14 @@ namespace board { ASSERT_RESULT_OK(pcvSetClockRate(moduleID, hz), "pcvSetClockRate"); } + void HandleCpuUv() + { + if (board::GetSocType() == HocClkSocType_Erista) + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); // Erista tbreak is always 1581MHz + else + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); + } + void SetHz(HocClkModule module, u32 hz) { Result rc = 0; bool usesGovenor = module > HocClkModule_MEM; @@ -116,7 +125,9 @@ namespace board { PcvSetHz(GetPcvModule(module), pcvHz); } } - + if(config::GetConfigValue(HocClkConfigValue_LiveCpuUv) && module == HocClkModule_CPU) { + HandleCpuUv(); + } if (useGm20b) { gm20b::setClock(hz / 1000); currentInjectedHz = hz; diff --git a/Source/hoc-clk/sysmodule/src/board/board_freq.hpp b/Source/hoc-clk/sysmodule/src/board/board_freq.hpp index 9804c2c8..dae4007a 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_freq.hpp +++ b/Source/hoc-clk/sysmodule/src/board/board_freq.hpp @@ -44,7 +44,8 @@ namespace board { u32 GetRealHz(HocClkModule module); void GetFreqList(HocClkModule module, u32 *outList, u32 maxCount, u32 *outCount); u32 GetHighestDockedDisplayRate(); - + void HandleCpuUv(); + void ResetToStock(); void ResetToStockDisplay(); diff --git a/Source/hoc-clk/sysmodule/src/board/board_volt.cpp b/Source/hoc-clk/sysmodule/src/board/board_volt.cpp index c8d34166..e8e7d0ce 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_volt.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_volt.cpp @@ -28,6 +28,7 @@ #include "board_volt.hpp" #include "../file/file_utils.hpp" #include "../i2c/i2cDrv.h" +#include "../hos/rgltr.h" namespace board { GpuVoltData voltData = {}; @@ -49,7 +50,8 @@ namespace board { u32 tune1_high; }; - EristaCpuUvEntry eristaCpuUvTable[5] = { + EristaCpuUvEntry eristaCpuUvTable[6] = { + {0xFFEAD0FF, 0x0}, {0xffff, 0x27007ff}, {0xefff, 0x27407ff}, {0xdfff, 0x27807ff}, @@ -134,19 +136,16 @@ namespace board { return; } } else { - if (GetHz(HocClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak - *tune0_ptr = cachedTune.tune0Low; // I think each erista has a different tune0/tune1? - *tune1_ptr = cachedTune.tune1Low; - return; - } else { - if (levelLow) { - *tune0_ptr = eristaCpuUvTable[levelLow-1].tune0; - *tune1_ptr = eristaCpuUvTable[levelLow-1].tune1; - } else { - *tune0_ptr = 0x0; - *tune1_ptr = 0x0; - } - } + // if (GetHz(HocClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak + // *tune0_ptr = cachedTune.tune0Low; // I think each erista has a different tune0/tune1? + // *tune1_ptr = cachedTune.tune1Low; + // return; + // } else { + // if (levelLow) { + *tune0_ptr = eristaCpuUvTable[levelLow].tune0; + *tune1_ptr = eristaCpuUvTable[levelLow].tune1; + // } else { + // } } } @@ -213,10 +212,13 @@ namespace board { PcvPowerDomainId_Max77812_Dram = 0x3A000005, // vddq } PowerDomainId; */ + /* + Note: I think Nintendo's I2C driver (or my driver, but it looks correct to me) + */ u32 GetVoltage(HocClkVoltage voltage) { u32 out = 0; BatteryChargeInfo info; - + RgltrSession s; switch (voltage) { case HocClkVoltage_SOC: out = I2c_BuckConverter_GetUvOut(&I2c_SOC); @@ -228,14 +230,18 @@ namespace board { if(GetSocType() == HocClkSocType_Mariko) { out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_CPU); } else { - out = I2c_BuckConverter_GetUvOut(&I2c_Erista_CPU); + rgltrOpenSession(&s, PcvPowerDomainId_Max77621_Cpu); + rgltrGetVoltage(&s, &out); + rgltrCloseSession(&s); } break; case HocClkVoltage_GPU: if(GetSocType() == HocClkSocType_Mariko) { out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_GPU); } else { - out = I2c_BuckConverter_GetUvOut(&I2c_Erista_GPU); + rgltrOpenSession(&s, PcvPowerDomainId_Max77621_Gpu); + rgltrGetVoltage(&s, &out); + rgltrCloseSession(&s); } break; case HocClkVoltage_EMCVDDQ: @@ -453,5 +459,4 @@ namespace board { return baseVolt; } - } \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/file/kip.cpp b/Source/hoc-clk/sysmodule/src/file/kip.cpp index f00517e0..226444df 100644 --- a/Source/hoc-clk/sysmodule/src/file/kip.cpp +++ b/Source/hoc-clk/sysmodule/src/file/kip.cpp @@ -24,7 +24,6 @@ namespace kip { bool kipAvailable = false; - void SetKipData() { // TODO: figure out if this REALLY causes issues (i doubt it) @@ -76,7 +75,7 @@ namespace kip { CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock2)); CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, config::GetConfigValue(KipConfigValue_marikoEmcMaxClock)); CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt)); - CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, config::GetConfigValue(KipConfigValue_emcDvbShift) > 8 && config::GetConfigValue(KipConfigValue_emcDvbShift) <= 16 ? 8 : config::GetConfigValue(KipConfigValue_emcDvbShift)); // 2.2.0 -> 2.3.0 compat + CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, config::GetConfigValue(KipConfigValue_emcDvbShift)); CUST_WRITE_FIELD_BATCH(&table, marikoSocVmax, config::GetConfigValue(KipConfigValue_marikoSocVmax)); CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, config::GetConfigValue(KipConfigValue_t1_tRCD)); @@ -127,6 +126,7 @@ namespace kip { CUST_WRITE_FIELD_BATCH(&table, marikoGpuUV, config::GetConfigValue(KipConfigValue_marikoGpuUV)); CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmin, config::GetConfigValue(KipConfigValue_marikoGpuVmin)); + CUST_WRITE_FIELD_BATCH(&table, marikoGpuBootVolt, config::GetConfigValue(KipConfigValue_marikoGpuBootVolt)); CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmax, config::GetConfigValue(KipConfigValue_marikoGpuVmax)); CUST_WRITE_FIELD_BATCH(&table, commonGpuVoltOffset, config::GetConfigValue(KipConfigValue_commonGpuVoltOffset)); @@ -196,6 +196,7 @@ namespace kip { // } if ((u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip") != config::GetConfigValue(KipCrc32) && !config::GetConfigValue(HocClkConfigValue_IsFirstLoad)) { + MigrateKipData(cust_get_cust_rev(&table), cust_get_kip_version(&table)); SetKipData(); notification::writeNotification("Horizon OC\nKIP wurde aktualisiert\nBitte Konsole neu starten"); return; @@ -225,6 +226,7 @@ namespace kip { clockManager::gContext.kipVersion = kipVersion; configValues.values[KipConfigValue_custRev] = cust_get_cust_rev(&table); + configValues.values[KipConfigValue_KipVersion] = cust_get_kip_version(&table); // Run this after the check so we can do migration process configValues.values[KipConfigValue_hpMode] = cust_get_hp_mode(&table); configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table); @@ -233,7 +235,7 @@ namespace kip { configValues.values[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table); configValues.values[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table); configValues.values[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table); - configValues.values[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table) > 8 && cust_get_emc_dvb_shift(&table) <= 16 ? 8 : cust_get_emc_dvb_shift(&table); // 2.2.0 -> 2.3.0 compat + configValues.values[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table); configValues.values[KipConfigValue_marikoSocVmax] = cust_get_marikoSocVmax(&table); configValues.values[KipConfigValue_t1_tRCD] = cust_get_tRCD(&table); @@ -283,6 +285,7 @@ namespace kip { configValues.values[KipConfigValue_eristaGpuVmin] = cust_get_erista_gpu_vmin(&table); configValues.values[KipConfigValue_marikoGpuUV] = cust_get_mariko_gpu_uv(&table); configValues.values[KipConfigValue_marikoGpuVmin] = cust_get_mariko_gpu_vmin(&table); + configValues.values[KipConfigValue_marikoGpuBootVolt] = cust_get_mariko_gpu_boot_volt(&table); configValues.values[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table); configValues.values[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table); configValues.values[KipConfigValue_gpuSpeedo] = board::GetFuseData()->gpuSpeedo; // cust_get_gpu_speedo(&table); @@ -313,5 +316,17 @@ namespace kip { notification::writeNotification("Horizon OC\nKonfigurationspuffer stimmt nicht überein"); } } + + void MigrateKipData(u32 custRev, u32 version) { + HocClkConfigValueList configValues; + config::GetConfigValues(&configValues); + u32 previousVersion = configValues.values[KipConfigValue_KipVersion]; + if(previousVersion < 240 && version >= 240) { + // <2.4.0 -> 2.4.0 migration: add marikoGpuBootVolt with default value of 800mV + configValues.values[KipConfigValue_marikoGpuBootVolt] = 800; + } + config::SetConfigValues(&configValues, true); + // This function cannot do anything at the moment. The capabilities will be expanded in the next release + } } diff --git a/Source/hoc-clk/sysmodule/src/file/kip.hpp b/Source/hoc-clk/sysmodule/src/file/kip.hpp index 2b8421b9..47fcfe8d 100644 --- a/Source/hoc-clk/sysmodule/src/file/kip.hpp +++ b/Source/hoc-clk/sysmodule/src/file/kip.hpp @@ -26,8 +26,6 @@ #include #include -#pragma pack(push, 1) - namespace kip { extern bool kipAvailable; @@ -90,6 +88,7 @@ namespace kip { u32 marikoGpuUV; u32 marikoGpuVmin; + u32 marikoGpuBootVolt; u32 marikoGpuVmax; u32 commonGpuVoltOffset; @@ -105,8 +104,6 @@ namespace kip { u32 reserved[60]; } CustomizeTable; - #pragma pack(pop) - #define CUST_MAGIC "CUST" #define CUST_MAGIC_LEN 4 @@ -264,6 +261,7 @@ namespace kip { static inline bool cust_set_erista_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaGpuVmin, v); } static inline bool cust_set_mariko_gpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuUV, v); } static inline bool cust_set_mariko_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmin, v); } + static inline bool cust_set_mariko_gpu_boot_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuBootVolt, v); } static inline bool cust_set_mariko_gpu_vmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmax, v); } static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); } static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); } @@ -354,6 +352,7 @@ namespace kip { static inline u32 cust_get_erista_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaGpuVmin); } static inline u32 cust_get_mariko_gpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuUV); } static inline u32 cust_get_mariko_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmin); } + static inline u32 cust_get_mariko_gpu_boot_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuBootVolt); } static inline u32 cust_get_mariko_gpu_vmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmax); } static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); } static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); } @@ -500,7 +499,7 @@ namespace kip { DECL_MARIKO_GPU_VOLT_GET(1459200, 21) DECL_MARIKO_GPU_VOLT_GET(1497600, 22) DECL_MARIKO_GPU_VOLT_GET(1536000, 23) - + void MigrateKipData(u32 custRev, u32 version); void SetKipData(); void GetKipData(); } \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/hos/rgltr.h b/Source/hoc-clk/sysmodule/src/hos/rgltr.h new file mode 100644 index 00000000..33268b8a --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/hos/rgltr.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) ppkantorski (bord2death) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once +#include +#include "pcv_types.h" + +typedef struct { + Service s; +} RgltrSession; + +Result rgltrInitialize(void); + +void rgltrExit(void); + +Service* rgltrGetServiceSession(void); + +Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id); +void rgltrCloseSession(RgltrSession* session); +Result rgltrGetVoltage(RgltrSession* session, u32 *out_volt); +Result rgltrGetPowerModuleNumLimit(u32 *out); +Result rgltrGetVoltageEnabled(RgltrSession* session, u32 *out); +Result rgltrRequestVoltage(RgltrSession* session, u32 microvolt); +Result rgltrCancelVoltageRequest(RgltrSession* session); \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/hos/rgltr_services.cpp b/Source/hoc-clk/sysmodule/src/hos/rgltr_services.cpp new file mode 100644 index 00000000..4904df88 --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/hos/rgltr_services.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) ppkantorski (bord2death) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include "rgltr.h" +#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc. + +// Global service handle +Service g_rgltrSrv; + +Result rgltrInitialize(void) { + if (hosversionBefore(8, 0, 0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + return smGetService(&g_rgltrSrv, "rgltr"); +} + +void rgltrExit(void) { + serviceClose(&g_rgltrSrv); +} + +Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id) { + const u32 in = (u32)module_id; + return serviceDispatchIn( + &g_rgltrSrv, + 0, + in, + .out_num_objects = 1, + .out_objects = &session_out->s + ); +} + +Result rgltrGetVoltage(RgltrSession* session, u32* out_volt) { + u32 temp = 0; + Result rc = serviceDispatchOut(&session->s, 4, temp); + if (R_SUCCEEDED(rc)) { + *out_volt = temp; + } + return rc; +} + +Result rgltrRequestVoltage(RgltrSession* session, u32 microvolt) { + return serviceDispatchIn(&session->s, 5, microvolt); +} + +Result rgltrCancelVoltageRequest(RgltrSession* session) { + return serviceDispatch(&session->s, 6); +} + +void rgltrCloseSession(RgltrSession* session) { + serviceClose(&session->s); +} \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/hos/rgltr_services.h b/Source/hoc-clk/sysmodule/src/hos/rgltr_services.h new file mode 100644 index 00000000..d8a886bf --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/hos/rgltr_services.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) ppkantorski (bord2death) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include // for Service, Result, hosversionBefore(), smGetService(), serviceClose(), etc. +#include "rgltr.h" // for RgltrSession, PowerDomainId, etc. + +extern Service g_rgltrSrv; + +Result rgltrInitialize(void); +void rgltrExit(void); + +Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id); + +Result rgltrGetVoltage(RgltrSession* session, u32* out_volt); + +void rgltrCloseSession(RgltrSession* session); \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp index d74a9d97..66f46b36 100644 --- a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp +++ b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp @@ -185,7 +185,23 @@ namespace clockManager { if (module == HocClkModule_GPU && board::GetSocType() == HocClkSocType_Mariko) { constexpr u32 kStep = 38400000; constexpr u32 kPcvStep = 76800000; - constexpr u32 kMax = 1228800000; + + u32 kMax = 0; + for (u32 i = 0; i < count; i++) { + for (u32 j = 0; j < count; j++) { + if (freqs[j] == freqs[i] + kStep) { + kMax = freqs[j]; + break; + } + } + } + + if (kMax == 0) { + for (u32 i = 0; i < count; i++) { + if (freqs[i] > kMax) + kMax = freqs[i]; + } + } for (u32 f = kPcvStep; f <= kMax && gFreqTable[module].count < HOCCLK_FREQ_LIST_MAX; f += kStep) { if (f % kPcvStep != 0) { @@ -221,6 +237,52 @@ namespace clockManager { continue; } + // Workaround for PCV bug involving 38.4mhz step rate on erista + if (module == HocClkModule_GPU && board::GetSocType() == HocClkSocType_Erista) { + static const struct { + u32 hz; + HocClkConfigValue kval; + } eristaGpuVoltMap[] = { + { 76800000, KipConfigValue_g_volt_e_76800 }, + { 115200000, KipConfigValue_g_volt_e_115200 }, + { 153600000, KipConfigValue_g_volt_e_153600 }, + { 192000000, KipConfigValue_g_volt_e_192000 }, + { 230400000, KipConfigValue_g_volt_e_230400 }, + { 268800000, KipConfigValue_g_volt_e_268800 }, + { 307200000, KipConfigValue_g_volt_e_307200 }, + { 345600000, KipConfigValue_g_volt_e_345600 }, + { 384000000, KipConfigValue_g_volt_e_384000 }, + { 422400000, KipConfigValue_g_volt_e_422400 }, + { 460800000, KipConfigValue_g_volt_e_460800 }, + { 499200000, KipConfigValue_g_volt_e_499200 }, + { 537600000, KipConfigValue_g_volt_e_537600 }, + { 576000000, KipConfigValue_g_volt_e_576000 }, + { 614400000, KipConfigValue_g_volt_e_614400 }, + { 652800000, KipConfigValue_g_volt_e_652800 }, + { 691200000, KipConfigValue_g_volt_e_691200 }, + { 729600000, KipConfigValue_g_volt_e_729600 }, + { 768000000, KipConfigValue_g_volt_e_768000 }, + { 806400000, KipConfigValue_g_volt_e_806400 }, + { 844800000, KipConfigValue_g_volt_e_844800 }, + { 883200000, KipConfigValue_g_volt_e_883200 }, + { 921600000, KipConfigValue_g_volt_e_921600 }, + { 960000000, KipConfigValue_g_volt_e_960000 }, + { 998400000, KipConfigValue_g_volt_e_998400 }, + {1036800000, KipConfigValue_g_volt_e_1036800 }, + {1075200000, KipConfigValue_g_volt_e_1075200 }, + }; + bool skip = false; + for (auto& entry : eristaGpuVoltMap) { + if (entry.hz == freqs[i]) { + if (config::GetConfigValue(entry.kval) == 2000) { + skip = true; + } + break; + } + } + if (skip) continue; + } + *hz = freqs[i]; fileUtils::LogLine("[mgr] %02u - %u - %u.%u MHz", gFreqTable[module].count, *hz, *hz / 1000000, *hz / 100000 - *hz / 1000000 * 10); @@ -231,26 +293,27 @@ namespace clockManager { fileUtils::LogLine("[mgr] count = %u", gFreqTable[module].count); } - void HandleSafetyFeatures() + bool HandleSafetyFeatures() { if (config::GetConfigValue(HocClkConfigValue_HandheldTDP) && (gContext.profile != HocClkProfile_Docked)) { if (board::GetConsoleType() == HocClkConsoleType_Hoag) { if (board::GetPowerMw(HocClkPowerSensor_Avg) < -(int)config::GetConfigValue(HocClkConfigValue_LiteTDPLimit)) { ResetToStockClocks(); - return; + return true; } } else { if (board::GetPowerMw(HocClkPowerSensor_Avg) < -(int)config::GetConfigValue(HocClkConfigValue_HandheldTDPLimit)) { ResetToStockClocks(); - return; + return true; } } } if (((tmp451TempSoc() / 1000) > (int)config::GetConfigValue(HocClkConfigValue_ThermalThrottleThreshold)) && config::GetConfigValue(HocClkConfigValue_ThermalThrottle)) { ResetToStockClocks(); - return; + return true; } + return false; } void HandleMiscFeatures() { @@ -267,6 +330,9 @@ namespace clockManager { if(board::GetConsoleType() == HocClkConsoleType_Aula) AulaDisplay::SetDisplayColorMode((AulaColorMode)config::GetConfigValue(HocClkConfigValue_AulaDisplayColorPreset)); + if(config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { + board::HandleCpuUv(); + } } } @@ -299,13 +365,6 @@ namespace clockManager { } } - void HandleCpuUv() - { - if (board::GetSocType() == HocClkSocType_Erista) - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); // Erista tbreak is always 1581MHz - else - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); - } void DVFSReset() { @@ -452,10 +511,6 @@ namespace clockManager { gContext.stable.freqs[module] = nearestHz; } - if (module == HocClkModule_CPU && config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { - HandleCpuUv(); - } - if (module == HocClkModule_MEM && board::GetSocType() == HocClkSocType_Mariko && targetHz < oldHz && config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { ApplyGpuDvfs(targetHz); } @@ -711,11 +766,11 @@ namespace clockManager { bool isBoost = apmExtIsBoostMode(mode); - HandleSafetyFeatures(); + bool shouldSkipClockSet = HandleSafetyFeatures(); HandleMiscFeatures(); // GPU clock should always be the same unless PCV has overwriten our change, so reset it - if (RefreshContext() || config::Refresh() || board::GetRealHz(HocClkModule_GPU) != gContext.freqs[HocClkModule_GPU]) { + if ((RefreshContext() || config::Refresh() || (board::GetRealHz(HocClkModule_GPU) != gContext.freqs[HocClkModule_GPU])) && !shouldSkipClockSet) { SetClocks(isBoost); } } diff --git a/build_noexo.sh b/build_noexo.sh new file mode 100644 index 00000000..be0446aa --- /dev/null +++ b/build_noexo.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +CORES="$(nproc --all)" + +SRC="Source/Atmosphere/stratosphere/loader/" +DEST="build/stratosphere/loader/" +mkdir -p "dist/atmosphere/kips/" +mkdir -p "$DEST" + +echo +echo "*** Patching loader ***" +cp -vr "$SRC"/. "$DEST"/ +echo + +echo "CORES: $CORES" +echo + +echo "*** Compiling loader ***" +cd build/stratosphere/loader || exit 1 +make -j$CORES +hactool -t kip1 out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=hoc.kip +cd ../../../ # exit +cp -v build/stratosphere/loader/hoc.kip dist/atmosphere/kips/hoc.kip + +cd Source/hoc-clk/ +./build.sh +cp -r dist/ ../../ + +cd ../../ + +echo "*** Compiling horizon-oc-monitor ***" +cd Source/Horizon-OC-Monitor/ +make -j$CORES +cp -v Horizon-OC-Monitor.ovl ../../dist/switch/.overlays/Horizon-OC-Monitor.ovl diff --git a/dist/README.md b/dist/README.md new file mode 100644 index 00000000..ff3e6be6 --- /dev/null +++ b/dist/README.md @@ -0,0 +1,214 @@ + +
+ +logo + +--- + +![License: GPL-2.0](https://img.shields.io/badge/GPL--2.0-red?style=for-the-badge) +![Nintendo Switch](https://img.shields.io/badge/Nintendo_Switch-E60012?style=for-the-badge\&logo=nintendo-switch\&logoColor=white) +[![Discord](https://img.shields.io/badge/Discord-5865F2?style=for-the-badge\&logo=discord\&logoColor=white)](https://dsc.gg/horizonoc) +![VSCode](https://img.shields.io/badge/VSCode-0078D4?style=for-the-badge\&logo=visual%20studio%20code\&logoColor=white) +![Made with Notepad++](assets/np++.png?raw=true) +![C++](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge\&logo=c%2B%2B\&logoColor=white) +![Downloads](https://img.shields.io/github/downloads/Horizon-OC/Horizon-OC/total.svg?style=for-the-badge) + +--- + +
+ +## ⚠️ Disclaimer + +> **THIS TOOL CAN BE DANGEROUS IF MISUSED. PROCEED WITH CAUTION.** +> Due to the design of Horizon OS, **overclocking RAM can cause NAND OR SD CORRUPTION.** +> Ensure you have a **full NAND, PROINFO, EMUMMC and SD backup** before proceeding. + +--- + +## About + +**Horizon OC** is an open-source overclocking tool for Nintendo Switch consoles running **Atmosphere custom firmware**. +It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration tools. + +--- + +## Default clocks + +* **CPU:** Up to 1963MHz (Mariko) / 1785MHz (Erista) +* **GPU:** Up to 1075MHz (Mariko) / 921MHz (Erista) +* **RAM:** Up to 1866/2133MHz (Mariko) / 1600MHz (Erista) +* Over/undervolting support +* Built-in configurator +* Compatible with most homebrew + +> It is recommended to read the [guide](https://rentry.co/howtoget60fps) before proceeding, as this can help you get a *significant* performance boost over the default settings, often times with less power draw and heat output + +--- + +## Installation + +1. Ensure you have the latest versions of + + * [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere) + * [Ultrahand Overlay](https://github.com/ppkantorski/Ultrahand-Overlay) +2. Download and extract the **Horizon OC Package** to the root of your SD card. +3. If using **Hekate**, edit `hekate_ipl.ini` to include: + + ``` + kip1=atmosphere/kips/hoc.kip + ``` + + *(No changes needed if using fusee.)* + +--- + +## Configuration + +1. Open the Horizon OC Overlay +2. Open the settings menu +3. Adjust your overclocking settings as desired. A helpful guide can be found [here.](https://rentry.co/mariko#oc-settings-for-horizon-oc) +4. Click **Save KIP Settings** to apply your configuration. + +--- + +## Building from Source + +Refer to COMPILATION.md + +--- +## Clock table + +### MEM clocks (mhz) + +* 3200 → max on mariko, JEDEC. +* 3166 +* 3133 +* 3100 +* 3066 +* 3033 +* 3000 +* 2966 +* 2933 → JEDEC. +* 2900 +* 2866 +* 2833 +* 2800 +* 2766 +* 2733 +* 2700 +* 2666 → JEDEC. +* 2633 +* 2600 +* 2566 +* 2533 +* 2500 +* 2466 +* 2433 +* 2400 → max on erista, JEDEC. +* 2366 +* 2333 +* 2300 +* 2266 +* 2233 +* 2200 +* 2166 +* 2133 → Mariko JEDEC standard max (4266 Modules) +* 2100 +* 2066 +* 2033 +* 2000 +* 1996 → JEDEC standard +* 1966 +* 1933 +* 1900 +* 1866 → Mariko JEDEC standard max (3733 Modules) +* 1833 +* 1800 +* 1766 +* 1733 +* 1700 +* 1666 +* 1633 +* 1600 → official docked, boost mode, Erista JEDEC standard max (3200 Modules), JEDEC. +* 1331 → official handheld, JEDEC. +* 1065 +* 800 +* 665 + +### CPU clocks (mhz) +* 2703 → mariko absolute max, dangerous +* 2601 → unsafe +* 2499 +* 2397 → mariko safe max with UV (low speedo) +* 2295 +* 2193 +* 2091 +* 1963 → mariko no UV max clock +* 1887 +* 1785 → erista no UV max clock, boost mode +* 1683 +* 1581 +* 1428 +* 1326 +* 1224 → sdev oc +* 1122 +* 1020 → official docked & handheld +* 918 +* 816 +* 714 +* 612 → sleep mode + +### GPU clocks (mhz) +* 1536 → absolute max clock on mariko. very dangerous +* 1459 +* 1382 +* 1305 +* 1267 → NVIDIA T214(mariko) rating +* 1228 → mariko High UV safe clock +* 1152 → mariko hiOpt-15mV max clock +* 1075 → mariko hiOpt max clock. absolute max clock on erista. very dangerous +* 998 → NVIDIA T210 (erista) rating +* 960 (erista only) → erista high uv/hiOpt-15mV safe max clock +* 921 → erista no UV max clock +* 844 +* 768 → official docked +* 691 +* 614 +* 537 +* 460 → max handheld +* 384 → official handheld +* 307 → official handheld +* 230 +* 153 +* 76 → boost mode + +**Notes:** +1. On Erista, CPU in handheld is capped to 1581MHz +2. GPU overclock is capped at 460MHz on erista in handheld +3. On Mariko, cap with hiOpt is 614MHz, with hiOpt-15mV it is 691MHz and with High UV it's 768MHz +4. Clocks higher than 768MHz on erista need the official charger is plugged in. + +--- + +## Credits +* **Lightos's Cat** - Cat +* **Souldbminer** - hoc-clk and loader development +* **Lightos** - Loader patches development, hoc-clk development, guides +* **TDRR** - HOC Logo Design +* **tetetete-ctrl** - Website design +* **SciresM** - Atmosphere CFW +* **CTCaer** - L4T, Hekate, proper RAM timings +* **KazushiMe** - Switch OC Suite +* **Hanai3bi (Meha)** - Switch OC Suite, EOS, sys-clk-eos +* **NaGaa95** - L4T-OC kernel, Status Monitor fork +* **B3711 (halop)** - EOS, contributions +* **sys-clk team (m4xw, p-sam, natinusala)** - sys-clk +* **Dominatorul** - Soctherm driver, guides, general help +* **ppkantorski** - Ultrahand sys-clk & Status Monitor fork +* **MasaGratoR and ZachyCatGames** - General help +* **MasaGratoR** - Status Monitor & Display Refresh Rate driver +* **Dominatorul, Samybigio, Arcdelta, Miki, Happy, Winnerboi77, Blaise, Alvise, agjeococh, frost, letum00, and Xenshen** - Testing +* **Samybigio2011, Miki** - Italian translations +* **angelblaster** - Korean translations +* **q1332348216-glitch** - Chinese translations +* **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T diff --git a/dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp b/dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp index 9de57192..c57011fd 100644 Binary files a/dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp and b/dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp differ diff --git a/dist/atmosphere/kips/hoc.kip b/dist/atmosphere/kips/hoc.kip index 8c85f0e6..701024e6 100644 Binary files a/dist/atmosphere/kips/hoc.kip and b/dist/atmosphere/kips/hoc.kip differ diff --git a/dist/switch/.overlays/Horizon-OC-Monitor.ovl b/dist/switch/.overlays/Horizon-OC-Monitor.ovl index 125e34cf..a091cb59 100644 Binary files a/dist/switch/.overlays/Horizon-OC-Monitor.ovl and b/dist/switch/.overlays/Horizon-OC-Monitor.ovl differ diff --git a/dist/switch/.overlays/horizon-oc-overlay.ovl b/dist/switch/.overlays/horizon-oc-overlay.ovl index 76d055a0..7ae042c2 100644 Binary files a/dist/switch/.overlays/horizon-oc-overlay.ovl and b/dist/switch/.overlays/horizon-oc-overlay.ovl differ