2 Commits

Author SHA1 Message Date
Lightos1
624952ca49 delete ams_patch.bat 2026-05-10 22:41:37 +02:00
Lightos1
a32f42290f custom soc table: fix in (never) years 2026-05-10 22:23:49 +02:00
39 changed files with 754 additions and 1234 deletions

View File

@@ -211,5 +211,4 @@ Refer to COMPILATION.md
* **Samybigio2011, Miki** - Italian translations
* **angelblaster** - Korean translations
* **q1332348216-glitch** - Chinese translations
* **th3-ne0undr5c0r** - French translations
* **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T

View File

@@ -48,6 +48,15 @@ volatile CustomizeTable C = {
.marikoEmcVddqVolt = 600000,
.emcDvbShift = 0,
.marikoSocVoltArray = {
0,
0,
0,
0,
900,
},
.marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */
/* Primary. */

View File

@@ -21,7 +21,7 @@
#pragma once
#define CUST_REV 3
#define KIP_VERSION 231
#define KIP_VERSION 220
#include "oc_common.hpp"
#include "pcv/pcv_common.hpp"
@@ -92,7 +92,8 @@ struct CustomizeTable {
StepMode stepMode;
u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt;
s32 emcDvbShift;
u32 emcDvbShift;
u32 marikoSocVoltArray[pcv::DvfsTableEntryLimit - 3]; /* Don't overwrite default tables. */
u32 marikoSocVmax;
// advanced config
u32 t1_tRCD;

View File

@@ -153,7 +153,7 @@ namespace ams::ldr::hoc::pcv {
{ 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.marikoEmcVddqVolt, 250'000, 700'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 },

View File

@@ -38,14 +38,14 @@ namespace ams::ldr::hoc::pcv {
};
static_assert(sizeof(cvb_entry_t) == 0x38);
struct CvbCpuDfllData {
struct cvb_cpu_dfll_data {
u32 tune0_low;
u32 tune0_high;
u32 tune1_low;
u32 tune1_high;
u32 tune_high_min_millivolts;
u32 tune_high_margin_millivolts;
u64 dvco_calibration_max;
unsigned int tune_high_min_millivolts;
unsigned int tune_high_margin_millivolts;
unsigned long dvco_calibration_max;
};
struct __attribute__((packed)) div_nmp {
@@ -115,25 +115,6 @@ namespace ams::ldr::hoc::pcv {
};
static_assert(sizeof(regulator) == 0x120);
struct __attribute__((packed)) CvbMeta {
u64 socType;
CvbCpuDfllData dfllData; /* Maybe? */
u32 unkZero2[6];
u32 unkMagic;
u32 unkZero3;
u32 highVmin;
u32 unkStepMaybe;
u32 vmin;
u32 unkZero4[3];
u32 pllMinMilliVolts;
u32 vmax;
u32 unkScale2;
u32 speedoScale;
u32 voltageScale;
u32 unkZero5;
};
static_assert(sizeof(CvbMeta) == 0x78);
constexpr u32 CpuClkOSLimit = 1785'000;
constexpr u32 GpuClkOsLimit = 921'600;
constexpr u32 EmcClkOSLimit = 1600'000;

View File

@@ -66,12 +66,11 @@ namespace ams::ldr::hoc::pcv::erista {
}
Result CpuVoltDfll(u32* ptr) {
CvbCpuDfllData *entry = reinterpret_cast<CvbCpuDfllData *>(ptr);
R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
cvb_cpu_dfll_data *entry = reinterpret_cast<cvb_cpu_dfll_data *>(ptr);
R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
if (!C.eristaCpuUV) {
R_SKIP();
@@ -101,7 +100,6 @@ namespace ams::ldr::hoc::pcv::erista {
default:
break;
}
R_SUCCEED();
}
@@ -123,10 +121,10 @@ namespace ams::ldr::hoc::pcv::erista {
}
if (C.eristaGpuVmin) {
PATCH_OFFSET(ptr, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 3, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 6, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 9, C.eristaGpuVmin);
PATCH_OFFSET(ptr , C.eristaGpuVmin);
PATCH_OFFSET(ptr + 3, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 6, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 9, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 12, C.eristaGpuVmin);
}
@@ -167,10 +165,8 @@ namespace ams::ldr::hoc::pcv::erista {
}
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)
};
PATCH_OFFSET(ptr32, asm_patch[0]);
asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd)};
PATCH_OFFSET(ptr32, asm_patch[0]);
PATCH_OFFSET(ptr32 + 1, asm_patch[1]);
R_SUCCEED();
@@ -214,9 +210,7 @@ namespace ams::ldr::hoc::pcv::erista {
}
u32 trefbw = refresh_raw + 0x40;
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
CalculateTimings(tCK_avg);
@@ -245,6 +239,7 @@ namespace ams::ldr::hoc::pcv::erista {
WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw);
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control);
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw);
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw);
@@ -285,7 +280,7 @@ namespace ams::ldr::hoc::pcv::erista {
/* This needs some clean up. */
constexpr double MC_ARB_DIV = 4.0;
constexpr u32 MC_ARB_SFA = 2;
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;
@@ -330,8 +325,8 @@ namespace ams::ldr::hoc::pcv::erista {
table->la_scale_regs.mc_ptsa_grant_decrement = grant_decrement;
constexpr u32 MaskHigh = 0xFF00FFFF;
constexpr u32 Mask2 = 0xFFFFFF00;
constexpr u32 Mask3 = 0xFF00FF00;
constexpr u32 Mask2 = 0xFFFFFF00;
constexpr u32 Mask3 = 0xFF00FF00;
const u32 allowance1 = static_cast<u32>(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF;
const u32 allowance2 = static_cast<u32>(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF;
@@ -359,10 +354,10 @@ namespace ams::ldr::hoc::pcv::erista {
table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & Mask2) | allowance1;
table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1;
table->dram_timings.t_rp = tRFCpb;
table->dram_timings.t_rp = tRFCpb;
table->dram_timings.t_rfc = tRFCab;
table->emc_cfg_2 = 0x11083D;
table->min_volt = std::clamp(900 + (C.emcDvbShift * 25), 900, 1050);
table->emc_cfg_2 = 0x11083D;
table->min_volt = std::min(static_cast<u32>(1050), 900 + C.emcDvbShift * 25);
}
/* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */

View File

@@ -140,7 +140,7 @@ namespace ams::ldr::hoc::pcv::erista {
MtcTableIndex index;
};
const inline MtcDramIndex mtcIndexTable[] = {
constexpr MtcDramIndex mtcIndexTable[] = {
{ ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH, T210SdevEmcDvfsTableS6gb01, },

View File

@@ -94,29 +94,23 @@ namespace ams::ldr::hoc::pcv::mariko {
}
Result CpuVoltDVFS(u32 *ptr) {
CvbMeta *cpuCvbMeta = reinterpret_cast<CvbMeta *>(reinterpret_cast<u8 *>(ptr) - offsetof(CvbMeta, vmin));
if (MatchesPattern(ptr, cpuVoltagePatchOffsets, cpuVoltagePatchValues)) {
if (C.marikoCpuLowVmin) {
PATCH_OFFSET(ptr, C.marikoCpuLowVmin);
}
R_UNLESS(cpuCvbMeta->highVmin == CpuHighVminOfficial, ldr::ResultInvalidCpuMinVolt());
R_UNLESS(cpuCvbMeta->unkStepMaybe == 38, ldr::ResultInvalidCpuMinVolt());
R_UNLESS(cpuCvbMeta->vmax == CpuVoltOfficial, ldr::ResultInvalidCpuMinVolt());
R_UNLESS(cpuCvbMeta->unkScale2 == 1000, ldr::ResultInvalidCpuMinVolt());
R_UNLESS(cpuCvbMeta->speedoScale == 100, ldr::ResultInvalidCpuMinVolt());
R_UNLESS(cpuCvbMeta->voltageScale == 1000, ldr::ResultInvalidCpuMinVolt());
R_UNLESS(cpuCvbMeta->unkZero5 == 0, ldr::ResultInvalidCpuMinVolt());
if (C.marikoCpuHighVmin) {
PATCH_OFFSET(ptr - 2, C.marikoCpuHighVmin);
}
if (C.marikoCpuLowVmin) {
PATCH_OFFSET(&(cpuCvbMeta->vmin), C.marikoCpuLowVmin);
if (C.marikoCpuMaxVolt) {
PATCH_OFFSET(ptr + 5, C.marikoCpuMaxVolt);
}
R_SUCCEED();
}
if (C.marikoCpuHighVmin) {
PATCH_OFFSET(&(cpuCvbMeta->highVmin), C.marikoCpuHighVmin);
}
if (C.marikoCpuMaxVolt) {
PATCH_OFFSET(&(cpuCvbMeta->vmax), C.marikoCpuMaxVolt);
}
R_SUCCEED();
R_THROW(ldr::ResultInvalidCpuMinVolt());
}
Result CpuVoltThermals(u32 *ptr) {
@@ -140,80 +134,80 @@ namespace ams::ldr::hoc::pcv::mariko {
}
Result CpuVoltDfll(u32 *ptr) {
CvbCpuDfllData *entry = reinterpret_cast<CvbCpuDfllData *>(ptr);
cvb_cpu_dfll_data *entry = reinterpret_cast<cvb_cpu_dfll_data *>(ptr);
R_UNLESS(entry->tune0_low == 0xFFCF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_low == 0x12207FF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune0_low == 0xFFCF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_low == 0x12207FF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_high == 0x3FFF7FF, ldr::ResultInvalidCpuVoltDfllEntry());
switch (C.marikoCpuUVLow) {
case 1:
PATCH_OFFSET(&(entry->tune0_low), 0xffa0);
PATCH_OFFSET(&(entry->tune0_low), 0xffa0);
PATCH_OFFSET(&(entry->tune0_high), 0xffff);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_high), 0x0);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_high), 0);
break;
case 2:
PATCH_OFFSET(&(entry->tune0_high), 0xffdf);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27207ff);
break;
case 3:
PATCH_OFFSET(&(entry->tune0_low), 0xffdf);
PATCH_OFFSET(&(entry->tune0_low), 0xffdf);
PATCH_OFFSET(&(entry->tune0_high), 0xffdf);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27307ff);
break;
case 4:
PATCH_OFFSET(&(entry->tune0_low), 0xffff);
PATCH_OFFSET(&(entry->tune0_low), 0xffff);
PATCH_OFFSET(&(entry->tune0_high), 0xffdf);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21107ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27407ff);
break;
case 5:
PATCH_OFFSET(&(entry->tune0_high), 0xffdf);
PATCH_OFFSET(&(entry->tune1_low), 0x21607ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21607ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27707ff);
break;
case 6:
PATCH_OFFSET(&(entry->tune0_high), 0xffdf);
PATCH_OFFSET(&(entry->tune1_low), 0x21607ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21607ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27807ff);
break;
case 7:
PATCH_OFFSET(&(entry->tune0_high), 0xdfff);
PATCH_OFFSET(&(entry->tune1_low), 0x21607ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21607ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27b07ff);
break;
case 8:
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_high), 0xdfff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27b07ff);
break;
case 9:
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_high), 0xdfff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27c07ff);
break;
case 10:
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_high), 0xdfff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27d07ff);
break;
case 11:
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_high), 0xdfff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27e07ff);
break;
case 12:
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_low), 0xdfff);
PATCH_OFFSET(&(entry->tune0_high), 0xdfff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_low), 0x21707ff);
PATCH_OFFSET(&(entry->tune1_high), 0x27f07ff);
break;
default:
@@ -222,7 +216,7 @@ namespace ams::ldr::hoc::pcv::mariko {
switch (C.marikoCpuUVHigh) {
case 1:
PATCH_OFFSET(&(entry->tune1_high), 0x0);
PATCH_OFFSET(&(entry->tune1_high), 0);
PATCH_OFFSET(&(entry->tune0_high), 0xffff);
break;
case 2:
@@ -307,7 +301,7 @@ namespace ams::ldr::hoc::pcv::mariko {
asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd)
};
PATCH_OFFSET(ptr32, asm_patch[0]);
PATCH_OFFSET(ptr32, asm_patch[0]);
PATCH_OFFSET(ptr32 + 1, asm_patch[1]);
R_SUCCEED();
@@ -372,7 +366,7 @@ namespace ams::ldr::hoc::pcv::mariko {
}
u32 trefbw = refresh_raw + 0x40;
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
@@ -802,9 +796,9 @@ namespace ams::ldr::hoc::pcv::mariko {
R_SKIP();
}
s32 max0 = 1050;
s32 max1 = 1025;
s32 max2 = 1000;
u32 max0 = 1050;
u32 max1 = 1025;
u32 max2 = 1000;
s32 voltAdd = 25 * C.emcDvbShift;
if (C.marikoSocVmax && C.marikoSocVmax > 1000) {
@@ -813,17 +807,11 @@ namespace ams::ldr::hoc::pcv::mariko {
max2 = C.marikoSocVmax;
}
constexpr s32 MinVolt = 637;
auto ClampVolt = [&](s32 value, s32 max) {
return std::clamp(value + voltAdd, MinVolt, max);
};
auto DvbVolt = [&](s32 zero, s32 one, s32 two) {
return std::array<s32, 3>{
ClampVolt(zero, max0),
ClampVolt(one, max1),
ClampVolt(two, max2)
auto DvbVolt = [&](u32 zero, u32 one, u32 two) {
return std::array<u32, 3>{
std::min(zero + voltAdd, max0),
std::min(one + voltAdd, max1),
std::min(two + voltAdd, max2)
};
};
@@ -831,33 +819,32 @@ namespace ams::ldr::hoc::pcv::mariko {
static_cast<u32>((v)[0]), \
static_cast<u32>((v)[1]), \
static_cast<u32>((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, { }, },
DvbEntry emcDvbTableNew[] = {
{ 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(775, 750, 725)) } },
{ 2933000, { DVB(DvbVolt(800, 775, 750)) } },
{ 3200000, { DVB(DvbVolt(800, 800, 775)) } },
{ 0xFFFFFFFF, { } },
};
#undef DVB
DvbEntry emcDvbTableOc[newEmcList.size()];
u32 bracketIndex = 0;
for (u32 i = 0; i < newEmcList.size(); ++i) {
while (newEmcList[i] >= emcDvbOcTableBrackets[bracketIndex + 1].freq) {
++bracketIndex;
u32 j = MtcTableCountDefault;
for (u32 i = MtcTableCountDefault; i < newEmcList.size(); ++i) {
if (newEmcList[i] >= emcDvbTableNew[j].freq && newEmcList[i] < emcDvbTableNew[j + 1].freq) {
emcDvbTableNew[j].freq = newEmcList[i];
++j;
} else {
break;
}
emcDvbTableOc[i].freq = newEmcList[i];
std::memcpy(emcDvbTableOc[i].volt, emcDvbOcTableBrackets[bracketIndex].volt, sizeof(emcDvbTableOc[i].volt));
}
std::memset(mem_dvb_table_head, 0, sizeof(EmcDvbTableDefault));
std::memcpy(mem_dvb_table_head, &emcDvbTableOc, sizeof(emcDvbTableOc));
std::memcpy(mem_dvb_table_head, &emcDvbTableNew, sizeof(emcDvbTableNew));
/* Max dvfs entry is 32, but HOS doesn't seem to boot if exact freq doesn't exist in dvb table,
reason why it's like this

View File

@@ -48,11 +48,11 @@ namespace ams::ldr::hoc::pcv::mariko {
{ },
};
constexpr u32 CpuClkOfficial = 1963'500;
constexpr u32 CpuVoltOfficial = 1120;
constexpr u32 CpuHighVminOfficial = 850;
constexpr u32 CpuVminOfficial = 620;
constexpr u32 CpuTune0Low = 0xFFCF;
constexpr u32 CpuClkOfficial = 1963'500;
constexpr u32 CpuVoltOfficial = 1120;
constexpr u32 CpuVminOfficial = 620;
constexpr u32 CpuTune0Low = 0xFFCF;
static const u32 cpuVoltagePatchValues[] = { 850, 38, 1120, 1000, 100, 1000, 0 };
static const s32 cpuVoltagePatchOffsets[] = { -2, -1, 5, 6, 7, 8, 9 };
@@ -230,7 +230,7 @@ namespace ams::ldr::hoc::pcv::mariko {
MtcTableIndex index;
};
const inline MtcDramIndex mtcIndexTable[] = {
constexpr MtcDramIndex mtcIndexTable[] = {
{ HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, },
{ AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, },
{ IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, },

View File

@@ -35,6 +35,7 @@ echo
echo "*** Copying assets ***"
mkdir -p "$DIST_DIR/config/horizon-oc"
cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template"
cp -vf "$ROOT_DIR/../../README.md" "$DIST_DIR/README.md"
mkdir -p "$DIST_DIR/config/ultrahand/assets/notifications"
cp -vf "$ROOT_DIR/assets/hoc.rgba" "$DIST_DIR/config/ultrahand/assets/notifications/hoc.rgba"

View File

@@ -90,6 +90,35 @@ typedef enum {
KipConfigValue_emcDvbShift,
KipConfigValue_marikoSocVmax,
KipConfigValue_s_volt_1666000,
KipConfigValue_s_volt_1733000,
KipConfigValue_s_volt_1800000,
KipConfigValue_s_volt_1866000,
KipConfigValue_s_volt_1933000,
KipConfigValue_s_volt_2000000,
KipConfigValue_s_volt_2066000,
KipConfigValue_s_volt_2133000,
KipConfigValue_s_volt_2200000,
KipConfigValue_s_volt_2266000,
KipConfigValue_s_volt_2333000,
KipConfigValue_s_volt_2400000,
KipConfigValue_s_volt_2466000,
KipConfigValue_s_volt_2533000,
KipConfigValue_s_volt_2600000,
KipConfigValue_s_volt_2666000,
KipConfigValue_s_volt_2733000,
KipConfigValue_s_volt_2800000,
KipConfigValue_s_volt_2866000,
KipConfigValue_s_volt_2933000,
KipConfigValue_s_volt_3000000,
KipConfigValue_s_volt_3066000,
KipConfigValue_s_volt_3133000,
KipConfigValue_s_volt_3200000,
KipConfigValue_s_volt_3266000,
KipConfigValue_s_volt_3333000,
KipConfigValue_s_volt_3400000,
KipConfigValue_s_volt_3466000,
KipConfigValue_t1_tRCD,
KipConfigValue_t2_tRP,
KipConfigValue_t3_tRAS,
@@ -317,6 +346,36 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
return pretty ? "Mariko EMC VDDQ Voltage" : "mariko_emc_vddq_volt";
case KipConfigValue_emcDvbShift:
return pretty ? "EMC DVB Shift" : "emc_dvb_shift";
case KipConfigValue_s_volt_1666000: return pretty ? "Mariko Soc Volt 1666 MHz" : "s_volt_1666000";
case KipConfigValue_s_volt_1733000: return pretty ? "Mariko Soc Volt 1733 MHz" : "s_volt_1733000";
case KipConfigValue_s_volt_1800000: return pretty ? "Mariko Soc Volt 1800 MHz" : "s_volt_1800000";
case KipConfigValue_s_volt_1866000: return pretty ? "Mariko Soc Volt 1866 MHz" : "s_volt_1866000";
case KipConfigValue_s_volt_1933000: return pretty ? "Mariko Soc Volt 1933 MHz" : "s_volt_1933000";
case KipConfigValue_s_volt_2000000: return pretty ? "Mariko Soc Volt 2000 MHz" : "s_volt_2000000";
case KipConfigValue_s_volt_2066000: return pretty ? "Mariko Soc Volt 2066 MHz" : "s_volt_2066000";
case KipConfigValue_s_volt_2133000: return pretty ? "Mariko Soc Volt 2133 MHz" : "s_volt_2133000";
case KipConfigValue_s_volt_2200000: return pretty ? "Mariko Soc Volt 2200 MHz" : "s_volt_2200000";
case KipConfigValue_s_volt_2266000: return pretty ? "Mariko Soc Volt 2266 MHz" : "s_volt_2266000";
case KipConfigValue_s_volt_2333000: return pretty ? "Mariko Soc Volt 2333 MHz" : "s_volt_2333000";
case KipConfigValue_s_volt_2400000: return pretty ? "Mariko Soc Volt 2400 MHz" : "s_volt_2400000";
case KipConfigValue_s_volt_2466000: return pretty ? "Mariko Soc Volt 2466 MHz" : "s_volt_2466000";
case KipConfigValue_s_volt_2533000: return pretty ? "Mariko Soc Volt 2533 MHz" : "s_volt_2533000";
case KipConfigValue_s_volt_2600000: return pretty ? "Mariko Soc Volt 2600 MHz" : "s_volt_2600000";
case KipConfigValue_s_volt_2666000: return pretty ? "Mariko Soc Volt 2666 MHz" : "s_volt_2666000";
case KipConfigValue_s_volt_2733000: return pretty ? "Mariko Soc Volt 2733 MHz" : "s_volt_2733000";
case KipConfigValue_s_volt_2800000: return pretty ? "Mariko Soc Volt 2800 MHz" : "s_volt_2800000";
case KipConfigValue_s_volt_2866000: return pretty ? "Mariko Soc Volt 2866 MHz" : "s_volt_2866000";
case KipConfigValue_s_volt_2933000: return pretty ? "Mariko Soc Volt 2933 MHz" : "s_volt_2933000";
case KipConfigValue_s_volt_3000000: return pretty ? "Mariko Soc Volt 3000 MHz" : "s_volt_3000000";
case KipConfigValue_s_volt_3066000: return pretty ? "Mariko Soc Volt 3066 MHz" : "s_volt_3066000";
case KipConfigValue_s_volt_3133000: return pretty ? "Mariko Soc Volt 3133 MHz" : "s_volt_3133000";
case KipConfigValue_s_volt_3200000: return pretty ? "Mariko Soc Volt 3200 MHz" : "s_volt_3200000";
case KipConfigValue_s_volt_3266000: return pretty ? "Mariko Soc Volt 3266 MHz" : "s_volt_3266000";
case KipConfigValue_s_volt_3333000: return pretty ? "Mariko Soc Volt 3333 MHz" : "s_volt_3333000";
case KipConfigValue_s_volt_3400000: return pretty ? "Mariko Soc Volt 3400 MHz" : "s_volt_3400000";
case KipConfigValue_s_volt_3466000: return pretty ? "Mariko Soc Volt 3466 MHz" : "s_volt_3466000";
case KipConfigValue_marikoSocVmax:
return pretty ? "SOC Vmax" : "soc_vmax";
// Memory timings
@@ -578,6 +637,34 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_marikoEmcMaxClock:
case KipConfigValue_marikoEmcVddqVolt:
case KipConfigValue_emcDvbShift:
case KipConfigValue_s_volt_1666000:
case KipConfigValue_s_volt_1733000:
case KipConfigValue_s_volt_1800000:
case KipConfigValue_s_volt_1866000:
case KipConfigValue_s_volt_1933000:
case KipConfigValue_s_volt_2000000:
case KipConfigValue_s_volt_2066000:
case KipConfigValue_s_volt_2133000:
case KipConfigValue_s_volt_2200000:
case KipConfigValue_s_volt_2266000:
case KipConfigValue_s_volt_2333000:
case KipConfigValue_s_volt_2400000:
case KipConfigValue_s_volt_2466000:
case KipConfigValue_s_volt_2533000:
case KipConfigValue_s_volt_2600000:
case KipConfigValue_s_volt_2666000:
case KipConfigValue_s_volt_2733000:
case KipConfigValue_s_volt_2800000:
case KipConfigValue_s_volt_2866000:
case KipConfigValue_s_volt_2933000:
case KipConfigValue_s_volt_3000000:
case KipConfigValue_s_volt_3066000:
case KipConfigValue_s_volt_3133000:
case KipConfigValue_s_volt_3200000:
case KipConfigValue_s_volt_3266000:
case KipConfigValue_s_volt_3333000:
case KipConfigValue_s_volt_3400000:
case KipConfigValue_s_volt_3466000:
case KipConfigValue_marikoSocVmax:
case KipConfigValue_t1_tRCD:
case KipConfigValue_t2_tRP:

View File

@@ -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.2.0 # ensure to set KIP_VERSION and CUST_REV in sysmodule Makefile when updating this
TARGET_VERSION := $(APP_VERSION)
#---------------------------------------------------------------------------------

View File

@@ -1,570 +0,0 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "config_info_strings.h"
std::vector<std::string> ConfigInfoStrings(HocClkConfigValue val, bool isMariko, bool isHoag)
{
switch (val)
{
case HocClkConfigValue_PollingIntervalMs:
return {
"The interval (in miliseconds) where clocks are applied, tempratures 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"
};
case HocClkConfigValue_RamDisplayUnit:
return {
"The unit used when displaying RAM frequency values.",
"Options:",
"- MHz: Megahertz (e.g. 1600 MHz)",
"- MT/s: MegaTransfers per second (e.g. 3200 MT/s)",
"Default: MHz"
};
case HocClkConfigValue_RAMVoltDisplayMode:
return {
"The method used to display RAM voltage values.",
"Options:",
"- VDD2 - Display VDD2 voltage",
"- VDDQ - Display VDDQ voltage",
"Default: VDD2"
};
case HocClkConfigValue_EnableExperimentalSettings:
return {
"When enabled, shows settings that are still being tested and may be unstable or not work at all.",
"Use with caution and report any issues to the developers."
};
case HocClkConfigValue_MarikoMiddleFreqs:
return {
"Allows usage of frequencies stepped by 38.4MHz instead of 76.8MHz below 1228MHz GPU clock",
"Default: OFF"
};
case HocClkConfigValue_LiveCpuUv:
return {
"Allows changing CPU undervolt settings without a reboot",
"Default: OFF"
};
case HocClkConfigValue_GPUSchedulingMethod:
return {
"Method used for GPU scheduling override",
"Options:",
"- INI: override via system_settings.ini",
"- NV Service: override via nvservices sysmodule (experimental)",
"Default: INI"
};
case HocClkConfigValue_MemoryFrequencyMeasurementMode:
return {
"How the RAM real frequency is measured",
"Options:",
"- PLL: Measure from PLLMB and PLLM (more accurate)",
"- Actmon: Measure from Actmon (less accurate)",
"Default: PLL"
};
case HocClkConfigValue_BatteryChargeCurrent:
return {
"Overrides the charge current to the battery. Use with caution!",
isHoag ? "Default: 1664 mA" : "2048 mA"
};
case HocClkConfigValue_AulaDisplayColorPreset:
return {
"Current display color preset. Default is Basic",
"Options:",
"- Saturated: Based on Vivid but over-saturated.",
"- Washed: Washed out colors.",
"- Basic: Real natural profile.",
"- Natural: Not actually natural.. Extra saturation.",
"- Vivid: Saturated.",
"Default: Do not override"
};
case HocClkConfigValue_CpuGovernorMinimumFreq:
return {
"The minimum frequency that the CPU governor will allow.",
"Default: 612MHz"
};
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."
};
case HocClkConfigValue_MaxDisplayClockH:
return {
"The maximum display clock frequency in handheld mode (in Hz).",
"Warning: Changing this value may cause instability or display damage.",
"Default: 60 Hz"
};
case HocClkConfigValue_DisplayVoltage:
return {
"The voltage supplied to the display panel (in mV).",
"Warning: Changing this value may cause instability.",
"Default: 1200mV"
};
case HocClkConfigValue_UncappedClocks:
if(isMariko) {
return {
"When enabled, disables clock cappings",
"Warning: Enabling this may cause damage to your device without a proper undervolt. Use with caution!",
"Clock cappings:",
"- Handheld:",
" - GPU (HiOPT): 614 MHz",
" - GPU (HiOPT - 15mV): 691 MHz",
" - GPU (High UV): 768 MHz",
"- USB Charger",
" - GPU (HiOPT): 844 MHz",
" - GPU (HiOPT - 15mV): 921 MHz",
" - GPU (High UV): 998 MHz",
"- PD Charger / Docked:",
" - No capping applied",
"Default: OFF"
};
} else {
return {
"When enabled, disables clock cappings",
"Warning: Enabling this may cause damage to your device without a proper undervolt. Use with caution!",
"Clock cappings:",
"- Handheld:",
" - GPU: 460 MHz",
" - CPU: 1581 MHz",
"- USB Charger",
" - GPU: 768 MHz",
"- PD Charger / Docked:",
" - No capping applied",
"Default: OFF"
};
}
case HocClkConfigValue_ThermalThrottle:
return {
"If enabled, Resets to stock clocks after the threshold is applied",
"Default: ON",
};
case HocClkConfigValue_HandheldTDP:
return {
"If enabled, Resets to stock clocks when power consumption is above the threshold in handheld mode",
"Default: ON",
};
case HocClkConfigValue_HandheldTDPLimit:
case HocClkConfigValue_LiteTDPLimit:
return {
"The power consumption threshold (in mW) for resetting to stock clocks in handheld mode when Handheld TDP is enabled.",
isHoag ? "Default: 6400mW" : "Default: 9600mW"
};
case HocClkConfigValue_ThermalThrottleThreshold:
return {
"The temperature threshold (in °C) for resetting to stock clocks when Thermal Throttle is enabled.",
"Default: 70°C"
};
case KipConfigValue_emcDvbShift:
return {
"Each level adds/removes 25mV from the SOC Voltage table",
"Consoles are bracketed by SoC Speedo. The brackets are as follows:",
" - 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"
};
case KipConfigValue_marikoSocVmax:
return {
"The maximum available SOC Voltage that the DVB-adjusted table can use",
"Default: Do not override"
};
case KipConfigValue_hpMode:
return {
"When enabled, disables RAM powerdown. Helps with latency significantly",
"Default: OFF"
};
case KipConfigValue_commonEmcMemVolt:
return {
"RAM VDD2 voltage",
"Increasing this WILL NOT increase your maximum frequency, but may help with timing reduction.",
"Undervolting RAM is pointless and may hurt performance and stability",
"Default: 1175 mV"
};
case KipConfigValue_marikoEmcVddqVolt:
return {
"RAM VDDQ voltage",
"Increasing this may help, but the default value is usually good enough.",
"Undervolting RAM is pointless and may hurt performance and stability",
"Default: 600 mV"
};
case KipConfigValue_stepMode:
return {
"The step that RAM clocks take.",
"Options (with examples):",
" - 66MHz - 66 MHz step (ex. 1600, 1666, 1733, etc.)",
" - 100MHz - 100 MHz step (ex. 1600, 1700, 1800, etc.)",
" - 133MHz - 66 MHz step (ex. 1600, 1733, 1866, etc.)",
" - JEDEC:",
" - 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",
"Default: 66 MHz",
};
case KipConfigValue_marikoEmcMaxClock:
return {
"The maximum RAM frequency available.",
"Higher frequencies may cause instability, so increase this gradually and test for stability.",
"Default: 2133 MHz"
};
case KipConfigValue_eristaEmcMaxClock:
case KipConfigValue_eristaEmcMaxClock1:
case KipConfigValue_eristaEmcMaxClock2:
return {
"The RAM frequency used in the particular slot. Higher frequencies may cause instability, so increase this gradually and test for stability.",
"Default: Disabled (1600 MHz)"
};
case KipConfigValue_t1_tRCD:
return {
"RAS-to-CAS delay",
"Default: 0"
};
case KipConfigValue_t2_tRP:
return {
"Row precharge time",
"Default: 0"
};
case KipConfigValue_t3_tRAS:
return {
"Row active time",
"Default: 0"
};
case KipConfigValue_t4_tRRD:
return {
"Row refresh time",
"Default: 0"
};
case KipConfigValue_t5_tRFC:
return {
"Refresh Cycle Time",
"Default: 0"
};
case KipConfigValue_t6_tRTW:
return {
"Read To Write (High bracket)",
"Default: 0"
};
case KipConfigValue_t7_tWTR:
return {
"Write To Read (High bracket)",
"Default: 0"
};
case KipConfigValue_t8_tREFI:
return {
"Refresh command interval",
"Default: 0"
};
case KipConfigValue_timingEmcTbreak:
return {
"Frequency where t6 and t7 break between the low and high brackets",
"Example:",
"Tbreak is set to 1866 MHz, and t6Low is set to 4 and t6High is set to 2. At frequencies below 1866 MHz, t6 will be 4, and at frequencies above 1866 MHz, t6 will be 2.",
"Default: Disabled"
};
case KipConfigValue_low_t6_tRTW:
return {
"Read To Write (Low bracket)",
"Default: 0"
};
case KipConfigValue_low_t7_tWTR:
return {
"Write To Read (Low bracket)",
"Default: 0"
};
case KipConfigValue_t2_tRP_cap:
return {
"Cap for t2 when 1333WL is used.",
"The default value is sufficient for most RAMs but some may need a lower value",
"Default: 2"
};
case KipConfigValue_t6_tRTW_fine_tune:
return {
"Finetunes the raw calculation of t6",
"Default: 0"
};
case KipConfigValue_t7_tWTR_fine_tune:
return {
"Finetunes the raw calculation of t6",
"Default: 0"
};
case KipConfigValue_write_latency_1333:
case KipConfigValue_write_latency_1600:
case KipConfigValue_write_latency_1866:
case KipConfigValue_write_latency_2133:
case KipConfigValue_read_latency_1333:
case KipConfigValue_read_latency_1600:
case KipConfigValue_read_latency_1866:
case KipConfigValue_read_latency_2133:
return {
"Latency bracket settings",
"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:",
"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",
"Default: -"
};
case KipConfigValue_mem_burst_read_latency:
return {
"The read latency for the ram",
"Default: 1600 RL"
};
case KipConfigValue_mem_burst_write_latency:
return {
"The write latency for the ram",
"Default: 1600 WL"
};
case KipConfigValue_marikoCpuUVLow:
return {
"The CPU UV level used before tBreak",
"Default: 0"
};
case KipConfigValue_marikoCpuUVHigh:
return {
"The CPU UV level used after tBreak",
"Default: 0"
};
case KipConfigValue_tableConf:
return {
"The current UV table used. The tbreaks are as follows:",
"1581 MHz tBreak and 1683 MHz tBreak use their respective tBreaks",
"The other tables use 1581 MHz as tBreak",
"The \"Default\" table does not contain frequencies past 1963 MHz and may not undervolt correctly"
};
case KipConfigValue_marikoCpuLowVmin:
return {
"The CPU vmin used before tBreak",
"Default: 620 mV"
};
case KipConfigValue_marikoCpuHighVmin:
return {
"The CPU vmin used after tBreak",
"Default: 750 mV"
};
case KipConfigValue_marikoCpuMaxVolt:
return {
"The maximum voltage that the CPU can use",
"Change this setting with caution!",
"Default: 1120 mV"
};
case KipConfigValue_marikoCpuMaxClock:
return {
"The maximum available CPU clock",
"Default: 1963 MHz"
};
case KipConfigValue_marikoCpuBoostClock:
return {
"The clock used for the CPU in \"boost mode\"",
"Default: 1963 MHz"
};
case KipConfigValue_eristaCpuUV:
return {
"CPU undervolt level",
"Default: 0"
};
case KipConfigValue_eristaCpuUnlock:
return {
"Unlock unsafe CPU clocks",
"Default: OFF"
};
case KipConfigValue_eristaCpuVmin:
return {
"Minimum CPU voltage",
"Default: 825 mV"
};
case KipConfigValue_eristaCpuMaxVolt:
return {
"Maximum CPU voltage",
"Default: 1235 mV"
};
case HocClkConfigValue_EristaMaxCpuClock:
return {
"The maximum available CPU clock",
"Default: 1785 MHz"
};
case KipConfigValue_eristaCpuBoostClock:
return {
"The clock used for the CPU in \"boost mode\"",
"Default: 1785 MHz"
};
case HocClkConfigValue_OverwriteBoostMode:
return {
"If enabled, profiles can override the boost mode setting",
"Default: OFF"
};
case KipConfigValue_marikoGpuUV:
return {
"GPU undervolt level",
"Options:",
" - HiOPT: L4T Custom HiOPT table",
" - HiOPT - 15mV: L4T Custom HiOPT table with a 15mV offset",
" - High UV: The highest undervolt table, reccomended",
"Default: HiOPT"
};
case KipConfigValue_marikoGpuVmin:
return {
"Minimum GPU voltage",
"Note: DVFS may change this value when the RAM clock is changed if the DVFS mode is set to PCV Hijack",
"Default: 610 mV"
};
case KipConfigValue_marikoGpuVmax:
return {
"Maximum GPU voltage",
"Default: 800 mV"
};
case HocClkConfigValue_DVFSMode:
return {
"The mode used for GPU DVFS",
"Adjusts GPU vmin when RAM clock is changed due to a higher requirement",
"Options:",
"- Disabled: disabled...",
"- PCV Hijack: hijack PCV for override",
"Default: PCV Hijack"
};
case HocClkConfigValue_DVFSOffset:
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 KipConfigValue_eristaGpuUV:
return {
"GPU undervolt level",
"Options:",
" - HiOPT: L4T Custom HiOPT table",
" - HiOPT - 15mV: L4T Custom HiOPT table with a 15mV offset",
" - High UV: The highest undervolt table, reccomended",
"Default: HiOPT"
};
case KipConfigValue_eristaGpuVmin:
return {
"Minimum GPU voltage",
"Default: 810 mV (812mV as erista is stepped my 6.5mV instead of 5mV)"
};
case KipConfigValue_commonGpuVoltOffset:
return {
"The offset added/subtracted to all AUTO GPU voltages",
"Default: 0 mV (Disabled)"
};
case HocClkConfigValue_GPUScheduling:
return {
"The scheduling method used for GPU clocks",
"Options:",
"- Do Not Override: Do not override existing scheduling mode",
"- Disabled: Disables GPU scheduling, 99.7% GPU max load",
"- Enabled: Enables GPU scheduling, 96.5% GPU max load",
"Default: Do not override"
};
default:
return {};
}
}

View File

@@ -1,23 +0,0 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "misc_gui.h"
#include <vector>
#include <string>
std::vector<std::string> ConfigInfoStrings(HocClkConfigValue val, bool isMariko, bool isHoag);

View File

@@ -1,88 +0,0 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "info_gui.h"
#include "ult_ext.h"
#include <sstream>
InfoGui::InfoGui(std::string title, std::vector<std::string> strings)
: m_title(std::move(title)), m_strings(std::move(strings)) {}
static constexpr s32 TEXT_SIZE = 16;
static constexpr s32 LINE_H = 22;
static constexpr s32 PARA_GAP = 10;
static constexpr s32 MARGIN_L = 20;
static constexpr s32 MARGIN_R = 35;
static std::vector<std::string> wrapText(const std::string& text, s32 maxWidth)
{
constexpr float CHAR_W = 10.0f;
// Preserve leading whitespace as an indent prefix for wrapped continuation lines.
std::string indent;
for (char c : text) {
if (c == ' ') indent += ' ';
else break;
}
std::vector<std::string> lines;
std::istringstream ss(text);
std::string word, line = indent; // seed with indent so first word inherits it
bool first = true;
while (ss >> word) {
std::string candidate = (first && !indent.empty()) ? indent + word
: line.empty() ? word
: line + " " + word;
first = false;
if (static_cast<s32>(candidate.size() * CHAR_W) <= maxWidth)
line = std::move(candidate);
else {
if (!line.empty() && line != indent) lines.push_back(line);
line = indent + word;
}
}
if (!line.empty() && line != indent) lines.push_back(line);
if (lines.empty()) lines.emplace_back("");
return lines;
}
void InfoGui::listUI()
{
this->listElement->addItem(new tsl::elm::CategoryHeader(m_title));
const s32 maxWidth = tsl::cfg::FramebufferWidth - MARGIN_L - MARGIN_R;
for (const auto& para : m_strings) {
for (const auto& lineText : wrapText(para, maxWidth)) {
auto* d = new FocusableDrawer(
[lineText](tsl::gfx::Renderer* r, s32 x, s32 y, s32 w, s32 h) {
r->drawString((lineText + "\n").c_str(), false,
x + MARGIN_L, y + LINE_H - 5,
TEXT_SIZE, tsl::style::color::ColorText);
});
d->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, LINE_H);
this->listElement->addItem(d, LINE_H);
}
// paragraph gap
auto* gap = new tsl::elm::CustomDrawer(
[](tsl::gfx::Renderer*, s32, s32, s32, s32) {});
gap->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, PARA_GAP);
this->listElement->addItem(gap, PARA_GAP);
}
}

View File

@@ -18,7 +18,6 @@
#include "misc_gui.h"
#include "fatal_gui.h"
#include "config_info_strings.h"
#include "../format.h"
#include <cstdio>
#include <cstring>
@@ -58,6 +57,7 @@ class SafetySubMenuGui;
class RamSubmenuGui;
class RamTimingsSubmenuGui;
class RamLatenciesSubmenuGui;
class SocCustomTableSubmenuGui;
class CpuSubmenuGui;
class GpuSubmenuGui;
class GpuCustomTableSubmenuGui;
@@ -89,24 +89,7 @@ MiscGui::~MiscGui()
void MiscGui::addConfigToggle(HocClkConfigValue configVal, const char* altName, bool kip) {
const char* configName = altName ? altName : hocclkFormatConfigValue(configVal, true);
auto infoStrings = ConfigInfoStrings(configVal, IsMariko(), IsHoag());
struct YAwareToggle : tsl::elm::ToggleListItem {
std::vector<std::string> m_info;
std::string m_title;
YAwareToggle(const char* text, bool state, std::string title, std::vector<std::string> info)
: tsl::elm::ToggleListItem(text, state), m_info(std::move(info)), m_title(std::move(title)) {}
bool onClick(u64 keys) override {
if (!m_info.empty() && (keys & HidNpadButton_Y) && !(keys & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(m_title, m_info);
return true;
}
return tsl::elm::ToggleListItem::onClick(keys);
}
};
auto* toggle = new YAwareToggle(configName, this->configList->values[configVal],
configName, std::move(infoStrings));
tsl::elm::ToggleListItem* toggle = new tsl::elm::ToggleListItem(configName, this->configList->values[configVal]);
if (!kip)
toggle->setTextColor(tsl::Color(120, 235, 255, 255));
toggle->setStateChangedListener([this, configVal, kip](bool state) {
@@ -124,13 +107,9 @@ void MiscGui::addConfigToggle(HocClkConfigValue configVal, const char* altName,
}
void MiscGui::addConfigTrackbar(HocClkConfigValue configVal, const char* altName, const ValueRange& range, bool kip) {
auto infoStrings = ConfigInfoStrings(configVal, IsMariko(), IsHoag());
struct IndexedBar : tsl::elm::NamedStepTrackBar {
std::vector<std::string> m_info;
std::string m_title;
IndexedBar(const char* label, const ValueRange& r, std::string title, std::vector<std::string> info)
: tsl::elm::NamedStepTrackBar("", {""}, true, label),
m_info(std::move(info)), m_title(std::move(title)) {
IndexedBar(const char* label, const ValueRange& r)
: tsl::elm::NamedStepTrackBar("", {""}, true, label) {
m_stepDescriptions.clear();
u32 numSteps = (r.max - r.min) / r.step + 1;
for (u32 i = 0; i < numSteps; i++) {
@@ -142,17 +121,9 @@ void MiscGui::addConfigTrackbar(HocClkConfigValue configVal, const char* altName
m_numSteps = (u8)m_stepDescriptions.size();
m_selection = m_stepDescriptions[0];
}
bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState& touchPos,
HidAnalogStickState leftJoyStick, HidAnalogStickState rightJoyStick) override {
if (!m_info.empty() && (keysDown & HidNpadButton_Y) && !(keysDown & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(m_title, m_info);
return true;
}
return tsl::elm::NamedStepTrackBar::handleInput(keysDown, keysHeld, touchPos, leftJoyStick, rightJoyStick);
}
};
const char* name = altName ? altName : hocclkFormatConfigValue(configVal, true);
auto* bar = new IndexedBar(name, range, name, std::move(infoStrings));
auto* bar = new IndexedBar(name, range);
u32 cur = (u32)this->configList->values[configVal];
u16 curStep = 0;
if (cur >= range.min && cur <= range.max && range.step > 0 && (cur - range.min) % range.step == 0)
@@ -171,25 +142,7 @@ void MiscGui::addMappedConfigTrackbar(HocClkConfigValue configVal, const char* a
std::vector<u32> vals,
std::initializer_list<std::string> names, bool kip) {
const char* name = altName ? altName : hocclkFormatConfigValue(configVal, true);
auto infoStrings = ConfigInfoStrings(configVal, IsMariko(), IsHoag());
struct YAwareTrackBar : tsl::elm::NamedStepTrackBar {
std::vector<std::string> m_info;
std::string m_title;
YAwareTrackBar(const char* label, std::initializer_list<std::string> steps, std::string title, std::vector<std::string> info)
: tsl::elm::NamedStepTrackBar("", steps, true, label),
m_info(std::move(info)), m_title(std::move(title)) {}
bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState& touchPos,
HidAnalogStickState leftJoyStick, HidAnalogStickState rightJoyStick) override {
if (!m_info.empty() && (keysDown & HidNpadButton_Y) && !(keysDown & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(m_title, m_info);
return true;
}
return tsl::elm::NamedStepTrackBar::handleInput(keysDown, keysHeld, touchPos, leftJoyStick, rightJoyStick);
}
};
auto* bar = new YAwareTrackBar(name, names, name, std::move(infoStrings));
auto* bar = new tsl::elm::NamedStepTrackBar("", names, true, name);
u32 cur = (u32)this->configList->values[configVal];
u16 curIdx = 0;
for (u16 i = 0; i < (u16)vals.size(); i++) {
@@ -218,7 +171,6 @@ void MiscGui::addConfigButton(HocClkConfigValue configVal,
bool kip)
{
const char* configName = altName ? altName : hocclkFormatConfigValue(configVal, true);
auto infoStrings = ConfigInfoStrings(configVal, IsMariko(), IsHoag());
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(configName);
if (!kip)
@@ -252,14 +204,8 @@ void MiscGui::addConfigButton(HocClkConfigValue configVal,
ValueThresholds thresholdsCopy = (thresholds ? *thresholds : ValueThresholds{});
listItem->setClickListener(
[this, configVal, range, categoryName, thresholdsCopy, labels, showDefaultValue, kip,
infoStrings = std::move(infoStrings), configName = std::string(configName)](u64 keys)
[this, configVal, range, categoryName, thresholdsCopy, labels, showDefaultValue, kip](u64 keys)
{
if (!infoStrings.empty() && (keys & HidNpadButton_Y) && !(keys & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(configName, infoStrings);
return true;
}
if ((keys & HidNpadButton_A) == 0)
return false;
@@ -342,8 +288,6 @@ void MiscGui::addConfigButtonS(HocClkConfigValue configVal,
const char* subText,
bool kip)
{
const char* configName = altName ? altName : hocclkFormatConfigValue(configVal, true);
auto infoStrings = ConfigInfoStrings(configVal, IsMariko(), IsHoag());
tsl::elm::ListItem* listItem = new tsl::elm::ListItem("");
if (!kip)
listItem->setTextColor(tsl::Color(120, 235, 255, 255));
@@ -378,14 +322,8 @@ void MiscGui::addConfigButtonS(HocClkConfigValue configVal,
ValueThresholds thresholdsCopy = (thresholds ? *thresholds : ValueThresholds{});
listItem->setClickListener(
[this, configVal, range, categoryName, thresholdsCopy, labels, showDefaultValue, kip,
infoStrings = std::move(infoStrings), configName = std::string(configName)](u64 keys)
[this, configVal, range, categoryName, thresholdsCopy, labels, showDefaultValue, kip](u64 keys)
{
if (!infoStrings.empty() && (keys & HidNpadButton_Y) && !(keys & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(configName, infoStrings);
return true;
}
if ((keys & HidNpadButton_A) == 0)
return false;
@@ -473,7 +411,6 @@ void MiscGui::addFreqButton(HocClkConfigValue configVal,
const std::map<uint32_t, std::string>& labels)
{
const char* configName = altName ? altName : hocclkFormatConfigValue(configVal, true);
auto infoStrings = ConfigInfoStrings(configVal, IsMariko(), IsHoag());
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(configName);
@@ -483,14 +420,8 @@ void MiscGui::addFreqButton(HocClkConfigValue configVal,
listItem->setValue(valueText);
listItem->setClickListener(
[this, configVal, module, labels,
infoStrings = std::move(infoStrings), configName = std::string(configName)](u64 keys)
[this, configVal, module, labels](u64 keys)
{
if (!infoStrings.empty() && (keys & HidNpadButton_Y) && !(keys & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(configName, infoStrings);
return true;
}
if ((keys & HidNpadButton_A) == 0)
return false;
@@ -553,11 +484,8 @@ void MiscGui::listUI()
tsl::elm::CustomDrawer* rebootSetWarning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString("\uE150 Settings marked in blue", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
renderer->drawString("don't require a reboot to apply!", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
renderer->drawString("You can also press \ue0e3 to show", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
renderer->drawString("information about each setting.", false, x + 20, y + 90, 18, tsl::style::color::ColorText);
});
rebootSetWarning->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 110);
rebootSetWarning->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 70);
this->listElement->addItem(rebootSetWarning);
tsl::elm::ListItem* sysmoduleSettingsSubMenu = new tsl::elm::ListItem("General Settings");
@@ -688,7 +616,7 @@ protected:
false
);
addConfigButton(
HocClkConfigValue_PollingIntervalMs,
"Polling Interval",
@@ -1005,11 +933,8 @@ protected:
this->listElement->addItem(new tsl::elm::CategoryHeader("RAM Settings"));
addMappedConfigTrackbar(KipConfigValue_emcDvbShift, "DVB Shift",
{0xFFFFFFFCu, 0xFFFFFFFDu, 0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u},
{"-4", "-3", "-2", "-1", " 0", "1", "2", "3", "4", "5", "6", "7", "8"});
addConfigTrackbar(KipConfigValue_emcDvbShift, "SoC DVB Shift", ValueRange(0, 16, 1)); // yes, DVB 16 is nessesary
if(IsMariko()) {
u32 socSpeedo = this->context->speedos[HocClkSpeedo_SOC];
std::string autoText = "1000 mV";
@@ -1047,7 +972,7 @@ protected:
true
);
}
addConfigToggle(KipConfigValue_hpMode, "HP Mode", true);
std::map<uint32_t, std::string> emc_voltage_label = {
@@ -1200,6 +1125,18 @@ protected:
timingsSubmenu->setValue(R_ARROW);
this->listElement->addItem(timingsSubmenu);
if (IsMariko()) {
tsl::elm::ListItem *customSocTableSubmenu = new tsl::elm::ListItem("SOC Voltage Table");
customSocTableSubmenu->setClickListener([](u64 keys) {
if (keys & HidNpadButton_A) {
tsl::changeTo<SocCustomTableSubmenuGui>();
return true;
}
return false;
});
customSocTableSubmenu->setValue(R_ARROW);
this->listElement->addItem(customSocTableSubmenu);
}
}
};
@@ -1423,12 +1360,7 @@ protected:
tsl::elm::ListItem* item = new tsl::elm::ListItem(label);
item->setValue(makeValueText(currentVal));
item->setClickListener([this, tierIdx, thisKey, keysArr, label](u64 keys) -> bool {
auto infoStrings = ConfigInfoStrings(thisKey, IsMariko(), IsHoag());
if (!infoStrings.empty() && (keys & HidNpadButton_Y) && !(keys & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(std::string(label), infoStrings);
return true;
}
item->setClickListener([this, tierIdx, thisKey, keysArr](u64 keys) -> bool {
if ((keys & HidNpadButton_A) == 0)
return false;
@@ -1564,6 +1496,66 @@ protected:
}
};
class SocCustomTableSubmenuGui : public MiscGui {
public:
SocCustomTableSubmenuGui() { }
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList); // populate config list early otherwise wont work
if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc);
return;
}
this->listElement->addItem(new tsl::elm::CategoryHeader("SOC Custom Table (mV)"));
ValueThresholds socVmaxThresholds(1075, 1150);
std::vector<NamedValue> socVolts = {
NamedValue("No Override", 0),
NamedValue("650mV", 650), NamedValue("675mV", 675), NamedValue("700mV", 700),
NamedValue("725mV", 725), NamedValue("750mV", 750), NamedValue("775mV", 775),
NamedValue("800mV", 800), NamedValue("825mV", 825), NamedValue("850mV", 850),
NamedValue("875mV", 875), NamedValue("900mV", 900), NamedValue("925mV", 925),
NamedValue("950mV", 950), NamedValue("975mV", 975), NamedValue("1000mV", 1000),
NamedValue("1025mV", 1025), NamedValue("1050mV", 1050), NamedValue("1075mV", 1075),
NamedValue("1100mV", 1100), NamedValue("1125mV", 1125), NamedValue("1150mV", 1150),
NamedValue("1175mV", 1175), NamedValue("1200mV", 1200),
};
addConfigButton(KipConfigValue_s_volt_1666000, "1666MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_1733000, "1733MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_1800000, "1800MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_1866000, "1866MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_1933000, "1933MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2000000, "2000MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2066000, "2066MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2133000, "2133MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2200000, "2200MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2266000, "2266MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2333000, "2333MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2400000, "2400MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2466000, "2466MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2533000, "2533MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2600000, "2600MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2666000, "2666MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2733000, "2733MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2800000, "2800MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2866000, "2866MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_2933000, "2933MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3000000, "3000MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3066000, "3066MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3133000, "3133MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3200000, "3200MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3266000, "3266MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3333000, "3333MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3400000, "3400MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
addConfigButton(KipConfigValue_s_volt_3466000, "3466MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &socVmaxThresholds, {}, socVolts, false, true);
}
};
class CpuSubmenuGui : public MiscGui {
public:
CpuSubmenuGui() { }
@@ -1644,7 +1636,7 @@ protected:
true
);
std::vector<NamedValue> maxClkOptions = {
NamedValue("1963 MHz", 1963500),
NamedValue("2091 MHz", 2091000),

View File

@@ -25,7 +25,6 @@
#include <vector>
#include "freq_choice_gui.h"
#include "value_choice_gui.h"
#include "info_gui.h"
class MiscGui : public BaseMenuGui
{
public:
@@ -33,7 +32,7 @@ public:
~MiscGui();
void listUI() override;
void refresh() override;
protected:
HocClkConfigValueList* configList;
std::map<HocClkConfigValue, tsl::elm::ListItem*> configButtons;
@@ -44,7 +43,7 @@ protected:
std::set<HocClkConfigValue> configButtonSKeys;
std::map<HocClkConfigValue, std::string> configButtonSSubtext;
std::set<HocClkConfigValue> emcClockConfigs;
void addConfigToggle(HocClkConfigValue configVal, const char* altName, bool kip = false);
void addConfigTrackbar(HocClkConfigValue configVal, const char* altName, const ValueRange& range, bool kip = true);
void addMappedConfigTrackbar(HocClkConfigValue configVal, const char* altName,
@@ -75,8 +74,8 @@ protected:
HocClkModule module,
const std::map<uint32_t, std::string>& labels = {});
void updateConfigToggles();
tsl::elm::ToggleListItem* enabledToggle;
u8 frameCounter = 60;
bool shouldSaveKip = false;
};
};

View File

@@ -95,18 +95,6 @@ public:
}
};
class FocusableDrawer : public tsl::elm::CustomDrawer {
public:
template<typename... Args>
FocusableDrawer(Args&&... args) : tsl::elm::CustomDrawer(std::forward<Args>(args)...) {
m_isItem = true;
}
Element* requestFocus(Element*, tsl::FocusDirection) override {
return this;
}
void drawHighlight(tsl::gfx::Renderer*) override {}
};
class HideableCustomDrawer : public tsl::elm::Element {
private:
bool visible;

View File

@@ -28,8 +28,8 @@ 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
TARGET_VERSION := 2.2.0
KIP_VERSION := 220
CUST_REV := 3
#---------------------------------------------------------------------------------

View File

@@ -3,7 +3,7 @@
"title_id": "0x00FF0000636C6BFF",
"title_id_range_min": "0x00FF0000636C6BFF",
"title_id_range_max": "0x00FF0000636C6BFF",
"main_thread_stack_size": "0x0000C000",
"main_thread_stack_size": "0x0000B000",
"main_thread_priority": 16,
"default_cpu_id": 3,
"process_category": 1,

View File

@@ -37,6 +37,7 @@
#include <registers.h>
#include <battery.h>
#include "../display/display_refresh_rate.hpp"
#include <rgltr.h>
#include <notification.h>
#include "board.hpp"
@@ -134,6 +135,9 @@ namespace board {
rc = tmp451Initialize();
ASSERT_RESULT_OK(rc, "tmp451Initialize");
rc = rgltrInitialize();
ASSERT_RESULT_OK(rc, "rgltrInitialize");
rc = pmdmntInitialize();
ASSERT_RESULT_OK(rc, "pmdmntInitialize");
@@ -216,6 +220,7 @@ namespace board {
pwmChannelSessionClose(&iCon);
pwmExit();
rgltrExit();
batteryInfoExit();
pmdmntExit();
nvExit();
@@ -240,7 +245,7 @@ namespace board {
svcCallSecureMonitor(&args);
if (args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed
notification::writeNotification("Horizon OC\nSecmon-Lesen fehlgeschlagen!\nDies könnte ein Hardwareproblem sein!");
notification::writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
return false;
}

View File

@@ -27,6 +27,7 @@
#include <switch.h>
#include <pwm.h>
#include <cmath>
#include <rgltr.h>
namespace board {

View File

@@ -22,12 +22,13 @@
#include <memmem.h>
#include <registers.h>
#include <cstring>
#include <rgltr.h>
#include <battery.h>
#include "board.hpp"
#include "board_freq.hpp"
#include "board_volt.hpp"
#include "../file/file_utils.hpp"
#include "../i2c/i2cDrv.h"
namespace board {
GpuVoltData voltData = {};
@@ -214,39 +215,59 @@ namespace board {
} PowerDomainId;
*/
u32 GetVoltage(HocClkVoltage voltage) {
RgltrSession session;
Result rc = 0;
u32 out = 0;
BatteryChargeInfo info;
switch (voltage) {
case HocClkVoltage_SOC:
out = I2c_BuckConverter_GetUvOut(&I2c_SOC);
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd0);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break;
case HocClkVoltage_EMCVDD2:
out = I2c_BuckConverter_GetUvOut(&I2c_VDD2);
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd1);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break;
case HocClkVoltage_CPU:
if(GetSocType() == HocClkSocType_Mariko) {
out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_CPU);
if (GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Cpu);
} else {
out = I2c_BuckConverter_GetUvOut(&I2c_Erista_CPU);
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Cpu);
}
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break;
case HocClkVoltage_GPU:
if(GetSocType() == HocClkSocType_Mariko) {
out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_GPU);
if (GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Gpu);
} else {
out = I2c_BuckConverter_GetUvOut(&I2c_Erista_GPU);
}
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Gpu);
}
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break;
case HocClkVoltage_EMCVDDQ:
if(GetSocType() == HocClkSocType_Mariko) {
out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_DRAM_VDDQ);
if (GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Dram);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
} else {
out = I2c_BuckConverter_GetUvOut(&I2c_VDD2);
out = GetVoltage(HocClkVoltage_EMCVDD2); // VDD2 and VDDQ are always connected to the same rail on Erista
}
break;
case HocClkVoltage_Display:
out = I2c_BuckConverter_GetUvOut(&I2c_Display);
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Ldo0);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break;
case HocClkVoltage_Battery:
batteryInfoGetChargeInfo(&info);

View File

@@ -31,7 +31,7 @@ namespace kip {
// if(board::GetSocType() == HocClkSocType_Mariko) {
// if(R_FAILED(I2c_BuckConverter_SetMvOut(&I2c_Mariko_DRAM_VDDQ, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt) / 1000))) {
// fileUtils::LogLine("[clock_manager] Failed set i2c vddq");
// notification::writeNotification("Horizon OC\nI2C-Schreiben fehlgeschlagen!\nbeim Setzen von vddq");
// notification::writeNotification("Horizon OC\nFailed to write I2C\nwhile setting vddq");
// }
// }
CustomizeTable table;
@@ -39,7 +39,7 @@ namespace kip {
fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r");
if (fp == NULL) {
notification::writeNotification("Horizon OC\nKIP konnte nicht geöffnet werden!");
notification::writeNotification("Horizon OC\nKip opening failed");
kipAvailable = false;
return;
} else {
@@ -49,19 +49,19 @@ namespace kip {
if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) {
fileUtils::LogLine("[kip] Failed to read KIP file");
notification::writeNotification("Horizon OC\nKIP konnte nicht gelesen werden!");
notification::writeNotification("Horizon OC\nKip read failed");
return;
}
u32 custRev = cust_get_cust_rev(&table);
u32 kipVersion = cust_get_kip_version(&table);
if (custRev < CUST_REV || kipVersion < KIP_VERSION) {
notification::writeNotification("Horizon OC\nVeraltetes KIP erkannt!\nBitte Horizon OC aktualisieren");
notification::writeNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC");
fileUtils::LogLine("Cust revision: %u", custRev);
fileUtils::LogLine("Kip version: %u", kipVersion);
return;
} else if (custRev > CUST_REV || kipVersion > KIP_VERSION) {
notification::writeNotification("Horizon OC\nVeraltetes Sysmodule erkannt!\nBitte Horizon OC aktualisieren");
notification::writeNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC");
fileUtils::LogLine("Cust revision: %u", custRev);
fileUtils::LogLine("Kip version: %u", kipVersion);
return;
@@ -76,7 +76,12 @@ 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));
for (u32 i = 0; i < 28; i++) {
table.marikoSocVoltArray[i] = config::GetConfigValue((HocClkConfigValue)(KipConfigValue_s_volt_1666000 + i));
}
CUST_WRITE_FIELD_BATCH(&table, marikoSocVmax, config::GetConfigValue(KipConfigValue_marikoSocVmax));
CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, config::GetConfigValue(KipConfigValue_t1_tRCD));
@@ -145,7 +150,7 @@ namespace kip {
if (!cust_write_table("sdmc:/atmosphere/kips/hoc.kip", &table)) {
fileUtils::LogLine("[kip] Failed to write KIP file");
notification::writeNotification("Horizon OC\nKIP konnte nicht geschrieben werden!");
notification::writeNotification("Horizon OC\nKip write failed");
}
HocClkConfigValueList configValues;
@@ -160,7 +165,7 @@ namespace kip {
}
} else {
fileUtils::LogLine("[kip] Warning: Failed to set config values from KIP");
notification::writeNotification("Horizon OC\nKIP-Konfiguration konnte nicht gesetzt werden!");
notification::writeNotification("Horizon OC\nKip config set failed");
}
}
@@ -172,7 +177,7 @@ namespace kip {
fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r");
if (fp == NULL) {
notification::writeNotification("Horizon OC\nKIP konnte nicht geöffnet werden!");
notification::writeNotification("Horizon OC\nKip opening failed");
kipAvailable = false;
return;
} else {
@@ -186,23 +191,23 @@ namespace kip {
CustomizeTable table;
if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) {
fileUtils::LogLine("[kip] Failed to read KIP file for GetKipData");
notification::writeNotification("Horizon OC\nKIP konnte nicht gelesen werden!");
notification::writeNotification("Horizon OC\nKip read failed");
return;
}
// if(cust_get_cust_rev(&table) != CUST_REV) {
// notification::writeNotification("Horizon OC\nKIP-Versionskonflikt!\nBitte Horizon OC neu installieren");
// notification::writeNotification("Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC");
// return;
// }
if ((u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip") != config::GetConfigValue(KipCrc32) && !config::GetConfigValue(HocClkConfigValue_IsFirstLoad)) {
SetKipData();
notification::writeNotification("Horizon OC\nKIP wurde aktualisiert\nBitte Konsole neu starten");
notification::writeNotification("Horizon OC\nKIP has been updated\nPlease reboot your console");
return;
}
if (config::GetConfigValue(HocClkConfigValue_IsFirstLoad) == true) {
configValues.values[HocClkConfigValue_IsFirstLoad] = (u64)false;
notification::writeNotification("Horizon OC wurde installiert");
notification::writeNotification("Horizon OC has been installed");
}
configValues.values[KipCrc32] = (u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum
@@ -212,12 +217,12 @@ namespace kip {
u32 custRev = cust_get_cust_rev(&table);
u32 kipVersion = cust_get_kip_version(&table);
if (custRev < CUST_REV || kipVersion < KIP_VERSION) {
notification::writeNotification("Horizon OC\nVeraltetes KIP erkannt!\nBitte Horizon OC aktualisieren");
notification::writeNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC");
fileUtils::LogLine("Cust revision: %u", custRev);
fileUtils::LogLine("Kip version: %u", kipVersion);
return;
} else if (custRev > CUST_REV || kipVersion > KIP_VERSION) {
notification::writeNotification("Horizon OC\nVeraltetes Sysmodule erkannt!\nBitte Horizon OC aktualisieren");
notification::writeNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC");
fileUtils::LogLine("Cust revision: %u", custRev);
fileUtils::LogLine("Kip version: %u", kipVersion);
return;
@@ -233,7 +238,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);
@@ -295,6 +300,10 @@ namespace kip {
configValues.values[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i);
}
for (u32 i = 0; i < 28; i++) {
configValues.values[KipConfigValue_s_volt_1666000 + i] = cust_get_mariko_soc_volt(&table, i);
}
configValues.values[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table);
configValues.values[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table);
@@ -306,12 +315,11 @@ namespace kip {
}
} else {
fileUtils::LogLine("[kip] Warning: Failed to set config values from KIP");
notification::writeNotification("Horizon OC\nKIP-Konfiguration konnte nicht gesetzt werden!");
notification::writeNotification("Horizon OC\nKip config set failed");
}
} else {
fileUtils::LogLine("[kip] Error: Config value list buffer size mismatch");
notification::writeNotification("Horizon OC\nKonfigurationspuffer stimmt nicht überein");
notification::writeNotification("Horizon OC\nConfig Buffer Mismatch");
}
}
}
}

View File

@@ -44,6 +44,7 @@ namespace kip {
u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt;
u32 emcDvbShift;
u32 marikoSocVoltArray[31 - 3]; /* LUT Limit - 3 stock entries. */
u32 marikoSocVmax;
// advanced config
@@ -287,6 +288,14 @@ namespace kip {
return cust_write_table(p, &t);
}
static inline bool cust_set_mariko_soc_volt(const char* p, int idx, u32 v) {
if (idx < 0 || idx >= 24) return false;
CustomizeTable t;
if (!cust_read_table(p, &t)) return false;
t.marikoSocVoltArray[idx] = v;
return cust_write_table(p, &t);
}
static inline u32 cust_get_field(const CustomizeTable* t, u32 offset) {
if (!t) return 0;
return *(u32*)((u8*)t + offset);
@@ -370,6 +379,11 @@ namespace kip {
return t->marikoGpuVoltArray[idx];
}
static inline u32 cust_get_mariko_soc_volt(const CustomizeTable* t, int idx) {
if (!t || idx < 0 || idx >= 24) return 0;
return t->marikoSocVoltArray[idx];
}
#define DECL_ERISTA_GPU_VOLT_HELPER(freq, idx) \
static inline bool cust_set_erista_gpu_volt_##freq( \
const char* p, u32 v) { \
@@ -382,6 +396,12 @@ namespace kip {
return cust_set_mariko_gpu_volt(p, idx, v); \
}
#define DECL_MARIKO_SOC_VOLT_HELPER(freq, idx) \
static inline bool cust_set_mariko_soc_volt_##freq( \
const char* p, u32 v) { \
return cust_set_mariko_soc_volt(p, idx, v); \
}
DECL_ERISTA_GPU_VOLT_HELPER(76800, 0)
DECL_ERISTA_GPU_VOLT_HELPER(115200, 1)
DECL_ERISTA_GPU_VOLT_HELPER(153600, 2)
@@ -501,6 +521,35 @@ namespace kip {
DECL_MARIKO_GPU_VOLT_GET(1497600, 22)
DECL_MARIKO_GPU_VOLT_GET(1536000, 23)
DECL_MARIKO_SOC_VOLT_HELPER(1666000, 10)
DECL_MARIKO_SOC_VOLT_HELPER(1733000, 11)
DECL_MARIKO_SOC_VOLT_HELPER(1800000, 12)
DECL_MARIKO_SOC_VOLT_HELPER(1866000, 13)
DECL_MARIKO_SOC_VOLT_HELPER(1933000, 14)
DECL_MARIKO_SOC_VOLT_HELPER(2000000, 15)
DECL_MARIKO_SOC_VOLT_HELPER(2066000, 16)
DECL_MARIKO_SOC_VOLT_HELPER(2133000, 17)
DECL_MARIKO_SOC_VOLT_HELPER(2200000, 18)
DECL_MARIKO_SOC_VOLT_HELPER(2266000, 19)
DECL_MARIKO_SOC_VOLT_HELPER(2333000, 10)
DECL_MARIKO_SOC_VOLT_HELPER(2400000, 11)
DECL_MARIKO_SOC_VOLT_HELPER(2466000, 12)
DECL_MARIKO_SOC_VOLT_HELPER(2533000, 13)
DECL_MARIKO_SOC_VOLT_HELPER(2600000, 14)
DECL_MARIKO_SOC_VOLT_HELPER(2666000, 15)
DECL_MARIKO_SOC_VOLT_HELPER(2733000, 16)
DECL_MARIKO_SOC_VOLT_HELPER(2800000, 17)
DECL_MARIKO_SOC_VOLT_HELPER(2866000, 18)
DECL_MARIKO_SOC_VOLT_HELPER(2933000, 19)
DECL_MARIKO_SOC_VOLT_HELPER(3000000, 20)
DECL_MARIKO_SOC_VOLT_HELPER(3066000, 21)
DECL_MARIKO_SOC_VOLT_HELPER(3133000, 22)
DECL_MARIKO_SOC_VOLT_HELPER(3200000, 23)
DECL_MARIKO_SOC_VOLT_HELPER(3266000, 24)
DECL_MARIKO_SOC_VOLT_HELPER(3333000, 25)
DECL_MARIKO_SOC_VOLT_HELPER(3400000, 26)
DECL_MARIKO_SOC_VOLT_HELPER(3466000, 27)
void SetKipData();
void GetKipData();
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <switch.h>
#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);

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
*/
#include <switch.h>
#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);
}

View File

@@ -1,6 +1,5 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
* 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,
@@ -13,21 +12,21 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#pragma once
#include "base_menu_gui.h"
#include <string>
#include <vector>
class InfoGui : public BaseMenuGui
{
public:
InfoGui(std::string title, std::vector<std::string> strings);
~InfoGui() = default;
void listUI() override;
#include <switch.h> // for Service, Result, hosversionBefore(), smGetService(), serviceClose(), etc.
#include "rgltr.h" // for RgltrSession, PowerDomainId, etc.
private:
std::string m_title;
std::vector<std::string> m_strings;
};
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);

View File

@@ -103,10 +103,6 @@ u32 I2c_BuckConverter_MultiplierToMvOut(const I2c_BuckConverter_Domain* domain,
return (domain->uv_min + domain->uv_step * multiplier) / 1000;
}
u32 I2c_BuckConverter_MultiplierToUvOut(const I2c_BuckConverter_Domain* domain, u8 multiplier) {
return domain->uv_min + domain->uv_step * multiplier;
}
u8 I2c_BuckConverter_MvOutToMultiplier(const I2c_BuckConverter_Domain* domain, u32 mvolt) {
u32 uvolt = mvolt * 1000;
if (uvolt < domain->uv_min)
@@ -133,22 +129,6 @@ u32 I2c_BuckConverter_GetMvOut(const I2c_BuckConverter_Domain* domain) {
return I2c_BuckConverter_MultiplierToMvOut(domain, val & domain->volt_mask);
}
u32 I2c_BuckConverter_GetUvOut(const I2c_BuckConverter_Domain* domain) {
u8 val;
// Retry 5 times if received POR value
for (int i = 0; i < 5; i++) {
if (R_FAILED(I2cRead_OutU8(domain->device, domain->reg, &val)))
return 0u;
// Wait 1us
svcSleepThread(1E3);
if (!domain->por_val || val != domain->por_val)
break;
}
return I2c_BuckConverter_MultiplierToUvOut(domain, val & domain->volt_mask);
}
Result I2c_BuckConverter_SetMvOut(const I2c_BuckConverter_Domain* domain, u32 mvolt) {
u8 val;
Result res = I2cRead_OutU8(domain->device, domain->reg, &val);

View File

@@ -21,7 +21,6 @@ const u8 MAX17050_CURRENT_REG = 0x0A;
// Buck Converter
typedef enum I2c_BuckConverter_Reg {
I2c_Max77620_SD0VOLT_REG = 0x16,
I2c_Max77620_SD1VOLT_REG = 0x17, // Used for Erista DDR VDDQ+VDD2 / Mariko VDD2
I2c_Max77620_LDO0VOLT_REG = 0x23, // Used for Erista DDR VDDQ+VDD2 / Mariko VDD2
I2c_Max77621_VOLT_REG = 0x00,
@@ -40,17 +39,16 @@ typedef struct I2c_BuckConverter_Domain {
u8 por_val;
} I2c_BuckConverter_Domain;
const I2c_BuckConverter_Domain I2c_SOC = { I2cDevice_Max77620Pmic, I2c_Max77620_SD0VOLT_REG, 0x7F, 12500, 600000, 1400000, };
const I2c_BuckConverter_Domain I2c_VDD2 = { I2cDevice_Max77620Pmic, I2c_Max77620_SD1VOLT_REG, 0x7F, 12500, 600000, 1350000, };
const I2c_BuckConverter_Domain I2c_Display = { I2cDevice_Max77620Pmic, I2c_Max77620_LDO0VOLT_REG, 0x3F, 25000, 800000, 1325000, };
const I2c_BuckConverter_Domain I2c_Erista_CPU = { I2cDevice_Max77621Cpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, };
const I2c_BuckConverter_Domain I2c_Erista_GPU = { I2cDevice_Max77621Gpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, };
const I2c_BuckConverter_Domain I2c_Erista_DRAM = { I2cDevice_Max77620Pmic, I2c_Max77620_SD1VOLT_REG, 0x3F, 12500, 600000, 1250000, };
const I2c_BuckConverter_Domain I2c_Display = { I2cDevice_Max77620Pmic, I2c_Max77620_LDO0VOLT_REG, 0x7F, 25000, 800000, 1325000, };
const I2c_BuckConverter_Domain I2c_Mariko_CPU = { I2cDevice_Max77812_2, I2c_Max77812_CPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 };
const I2c_BuckConverter_Domain I2c_Mariko_GPU = { I2cDevice_Max77812_2, I2c_Max77812_GPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 };
const I2c_BuckConverter_Domain I2c_Mariko_DRAM_VDDQ = { I2cDevice_Max77812_2, I2c_Max77812_MEMVOLT_REG, 0xFF, 5000, 250000, 700000, 0x78 };
const I2c_BuckConverter_Domain I2c_Mariko_DRAM_VDD2 = { I2cDevice_Max77620Pmic, I2c_Max77620_SD1VOLT_REG, 0x7F, 12500, 600000, 1250000, };
u32 I2c_BuckConverter_GetMvOut(const I2c_BuckConverter_Domain* domain);
u32 I2c_BuckConverter_GetUvOut(const I2c_BuckConverter_Domain* domain);
Result I2c_BuckConverter_SetMvOut(const I2c_BuckConverter_Domain* domain, u32 mvolt);
// Bq24193 Battery management

View File

@@ -38,7 +38,7 @@
#include "ipc/ipc_service.hpp"
#include "file/config.hpp"
#define INNER_HEAP_SIZE 0x40000
#define INNER_HEAP_SIZE 0x3A000
extern "C"
{

View File

@@ -252,6 +252,7 @@ namespace clockManager {
return;
}
}
void HandleMiscFeatures()
{
// these dont need to run that often, so dont bother
@@ -380,6 +381,7 @@ namespace clockManager {
board::SetHz(HocClkModule_CPU, board::GetHz(HocClkModule_CPU));
prepareBoostExit = false;
}
bool returnRaw = false; // Return a value scaled to MHz instead of raw value
for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) {
u32 oldHz = board::GetHz((HocClkModule)module); // Get Old hz (used primarily for DVFS Logic)
@@ -713,9 +715,8 @@ namespace clockManager {
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()) {
SetClocks(isBoost);
}
}

View File

@@ -1,98 +0,0 @@
#include <cstdio>
#include <cstdint>
#include <iterator>
typedef uint32_t u32;
typedef int32_t s32;
struct DvbEntry {
u32 freq;
u32 volts[3];
};
DvbEntry oldDvbTable[] = {
{ 204000, { 637, 637, 637, }, },
{ 1331200, { 650, 637, 637, }, },
{ 1600000, { 675, 650, 637, }, },
{ 1866000, { 700, 675, 650, }, },
{ 2133000, { 725, 700, 675, }, },
{ 2400000, { 750, 725, 700, }, },
{ 2666000, { 775, 750, 725, }, },
{ 2933000, { 800, 775, 750, }, },
{ 3200000, { 800, 800, 775, }, },
{ ~0u, { }, },
};
DvbEntry newDvbTable[] = {
{ 204000, { 637, 637, 637, }, },
{ 1331200, { 650, 637, 637, }, },
{ 1600000, { 675, 650, 637, }, },
{ 1866000, { 700, 675, 650, }, },
{ 2133000, { 725, 700, 675, }, },
{ 2400000, { 750, 725, 700, }, },
{ 2666000, { 850, 825, 800, }, },
{ 2933000, { 950, 925, 900, }, },
{ 3200000, { 1050, 1025, 1000, }, },
{ ~0u, { }, },
};
constexpr u32 DvbTableSize = std::size(oldDvbTable);
u32 PrintAndScan(const char *message) {
u32 scanV;
printf("%s: ", message);
scanf("%i", &scanV);
return scanV;
}
u32 GetProcessId(u32 speedo) {
if (speedo <= 1597) {
return 0;
}
if (speedo <= 1708) {
return 1;
}
/* >= 1709. */
return 2;
}
u32 GetVoltageAndIndex(u32 dvbShift, u32 emc, u32 processId, DvbEntry *dvbTable, u32 &index) {
for (u32 i = 0; i < DvbTableSize - 1; ++i) {
if (emc < dvbTable[i].freq || emc >= dvbTable[i + 1].freq) {
continue;
}
index = i;
return dvbTable[i].volts[processId] + (25 * dvbShift);
}
return 0;
}
s32 GetShift(u32 oldVoltage, u32 processId, DvbEntry *dvbTable, u32 index) {
return (static_cast<s32>(oldVoltage) - static_cast<s32>(dvbTable[index].volts[processId])) / 25;
}
int main() {
u32 oldDvb = PrintAndScan("Enter old dvb shift");
u32 emcMaxMhz = PrintAndScan("Enter max ram freq (MHz)");
u32 speedo = PrintAndScan("Enter soc speedo");
u32 emcMaxKhz = emcMaxMhz * 1000;
u32 processId = GetProcessId(speedo);
#define INVALID_TABLE_INDEX 32
u32 tableIndex = INVALID_TABLE_INDEX;
u32 oldVoltage = GetVoltageAndIndex(oldDvb, emcMaxKhz, processId, oldDvbTable, tableIndex);
if (oldVoltage == 0 || tableIndex == INVALID_TABLE_INDEX) {
printf("Invalid values!\n");
return -1;
}
s32 newShift = GetShift(oldVoltage, processId, newDvbTable, tableIndex);
printf("New dvb table shift: %d", newShift);
}

View File

@@ -1,120 +0,0 @@
from dataclasses import dataclass
from typing import List
u32 = int
s32 = int
@dataclass
class DvbEntry:
freq: u32
volts: List[u32]
oldDvbTable = [
DvbEntry(204000, [637, 637, 637]),
DvbEntry(1331200, [650, 637, 637]),
DvbEntry(1600000, [675, 650, 637]),
DvbEntry(1866000, [700, 675, 650]),
DvbEntry(2133000, [725, 700, 675]),
DvbEntry(2400000, [750, 725, 700]),
DvbEntry(2666000, [775, 750, 725]),
DvbEntry(2933000, [800, 775, 750]),
DvbEntry(3200000, [800, 800, 775]),
DvbEntry(0xFFFFFFFF, []),
]
newDvbTable = [
DvbEntry(204000, [637, 637, 637]),
DvbEntry(1331200, [650, 637, 637]),
DvbEntry(1600000, [675, 650, 637]),
DvbEntry(1866000, [700, 675, 650]),
DvbEntry(2133000, [725, 700, 675]),
DvbEntry(2400000, [750, 725, 700]),
DvbEntry(2666000, [850, 825, 800]),
DvbEntry(2933000, [950, 925, 900]),
DvbEntry(3200000, [1050, 1025, 1000]),
DvbEntry(0xFFFFFFFF, []),
]
DVB_TABLE_SIZE = len(oldDvbTable)
INVALID_TABLE_INDEX = 32
def print_and_scan(message: str) -> u32:
return int(input(f"{message}: "))
def get_process_id(speedo: u32) -> u32:
if speedo <= 1597:
return 0
if speedo <= 1708:
return 1
# >= 1709
return 2
def get_voltage_and_index(
dvb_shift: u32,
emc: u32,
process_id: u32,
dvb_table: List[DvbEntry],
):
for i in range(DVB_TABLE_SIZE - 1):
if emc < dvb_table[i].freq or emc >= dvb_table[i + 1].freq:
continue
voltage = dvb_table[i].volts[process_id] + (25 * dvb_shift)
return voltage, i
return 0, INVALID_TABLE_INDEX
def get_shift(
old_voltage: u32,
process_id: u32,
dvb_table: List[DvbEntry],
index: u32,
) -> s32:
return (
int(old_voltage)
- int(dvb_table[index].volts[process_id])
) // 25
def main():
old_dvb = print_and_scan("Enter old dvb shift")
emc_max_mhz = print_and_scan("Enter max ram freq (MHz)")
speedo = print_and_scan("Enter soc speedo")
emc_max_khz = emc_max_mhz * 1000
process_id = get_process_id(speedo)
table_index = INVALID_TABLE_INDEX
old_voltage, table_index = get_voltage_and_index(
old_dvb,
emc_max_khz,
process_id,
oldDvbTable,
)
if old_voltage == 0 or table_index == INVALID_TABLE_INDEX:
print("Invalid values!")
return -1
new_shift = get_shift(
old_voltage,
process_id,
newDvbTable,
table_index,
)
print(f"New dvb table shift: {new_shift}")
if __name__ == "__main__":
main()

214
dist/README.md vendored Normal file
View File

@@ -0,0 +1,214 @@
<div align="center">
<img src="assets/logo.png" alt="logo" width="768"/>
---
![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)
---
</div>
## ⚠️ 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

Binary file not shown.

Binary file not shown.

Binary file not shown.