37 Commits
2.0.1 ... 2.1.0

Author SHA1 Message Date
souldbminersmwc
fc4b3b8352 2.1.0 2026-04-25 16:40:55 -04:00
souldbminersmwc
5123f7b1de Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-25 16:39:31 -04:00
souldbminersmwc
3251d104c4 hocclk: rename UV tables to correct names 2026-04-25 16:30:10 -04:00
Lightos1
ea2d604c20 fix comment 2026-04-25 22:22:31 +02:00
souldbminersmwc
ae71cd447d ldr: add comment 2026-04-25 16:19:44 -04:00
souldbminersmwc
4261dd83f0 hoc: 133mhz step mode 2026-04-25 16:16:26 -04:00
souldbminersmwc
4dc01c024a hocclk: change capitilization 2026-04-25 15:59:05 -04:00
souldbminersmwc
9e26329173 hocclk: soc max volt dno side voltage 2026-04-25 15:57:37 -04:00
souldbminersmwc
36441e6dea add config support and update build script for soc vmax 2026-04-25 15:44:56 -04:00
Lightos1
cdf28607c9 move loader.json 2026-04-25 20:48:31 +02:00
Lightos1
b383fa7ec2 improve alignment 2026-04-25 20:30:46 +02:00
Lightos1
d7178ddd2c Add soc uncap 2026-04-25 20:22:23 +02:00
souldbminersmwc
9d149f0939 hocclk: fix trackbar reloading issues 2026-04-25 11:20:48 -04:00
souldbminersmwc
170dd79347 hocclk: cpu config rework 2026-04-25 11:06:22 -04:00
souldbminersmwc
d97d359ec2 hocclk: more configurator stuff 2026-04-24 17:00:59 -04:00
souldbminersmwc
9ff9e315a0 hocclk: improve kip saving mechanism 2026-04-24 16:42:59 -04:00
souldbminersmwc
cde560c4bd Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-24 16:35:25 -04:00
souldbminersmwc
a15860ba8d hocclk: make dram ti 2026-04-24 16:35:01 -04:00
Lightos1
76e6f1bd27 Merge pull request #71 from dominatorul/patch-4
Update README.md
2026-04-24 17:41:41 +02:00
Lightos1
2c1ad1b755 fix formating 2026-04-24 17:41:21 +02:00
Lightos1
2f2e5e9fb8 add new line 2026-04-24 17:38:28 +02:00
Lightos1
65b77a2d0b make step mode mariko only 2026-04-24 17:34:37 +02:00
Dominator
5d4812bde5 Update README.md
Updated clock specifications for MEM, CPU, and GPU with standardized terms.
2026-04-24 04:24:03 +03:00
souldbminersmwc
addd2de4d9 hocclk: add CPU LUT and add copyright 2026-04-23 18:50:51 -04:00
souldbminersmwc
0df8ce745f use original voltages 2026-04-22 18:06:27 -04:00
souldbminersmwc
62d055f163 hocclk: add missing -35mV step to configurator 2026-04-22 16:58:36 -04:00
souldbminersmwc
fa1510a40d Add B3's low ram freq DVFS
Co-Authored-By: halop <4215938+halop@users.noreply.github.com>
2026-04-22 16:56:09 -04:00
souldbminersmwc
e6942f95e7 hocclk: add BQ24193 temp driver 2026-04-22 16:40:51 -04:00
souldbminersmwc
94b63003ab hocclk: reorder options 2026-04-22 16:14:30 -04:00
souldbminersmwc
8aa20dc0cf hocclk: fix PLL ram mode and default to it 2026-04-22 15:49:07 -04:00
souldbminersmwc
db92c60cd2 hocclk: improve pll ram mode 2026-04-21 20:03:12 -04:00
souldbminersmwc
c8c7b233f5 hocclk: minor refactor 2026-04-21 19:52:31 -04:00
souldbminersmwc
5a9afcbb74 hocmon: rename tabs 2026-04-21 19:48:42 -04:00
souldbminersmwc
8127a0c3b7 hocclk: dram voltage color changes for mariko/erista 2026-04-21 19:48:27 -04:00
souldbminersmwc
7c5e746594 hocclk: ui changes 2026-04-21 19:46:21 -04:00
souldbminersmwc
7d30c4d384 bump version 2026-04-21 19:38:32 -04:00
souldbminersmwc
883b4fc3f4 hocclk: fix pointer dereference 2026-04-21 19:35:05 -04:00
41 changed files with 1187 additions and 521 deletions

View File

@@ -78,21 +78,21 @@ Refer to COMPILATION.md
---
## Clock table
### MEM clocks
### MEM clocks (mhz)
* 3200 → max on mariko, JEDEC.
* 2933 → JEDEC.
* 2666 → JEDEC.
* 2400 → max on erista, JEDEC.
* 2133 → mariko safe max (4266 Modules), JEDEC.
* 1996 → JEDEC.
* 1866 → mariko safe max (3733 Modules), JEDEC.
* 2133 → Mariko JEDEC standard max (4266 Modules)
* 1996 → JEDEC standard
* 1866 → Mariko JEDEC standard max (3733 Modules)
* 1600 → official docked, boost mode, erista safe max, JEDEC.
* 1331 → official handheld, JEDEC.
* 1065
* 800
* 665
### CPU clocks
### CPU clocks (mhz)
* 2703 → mariko absolute max, dangerous
* 2601 → unsafe
* 2499
@@ -115,16 +115,16 @@ Refer to COMPILATION.md
* 714
* 612 → sleep mode
### GPU clocks
### GPU clocks (mhz)
* 1536 → absolute max clock on mariko. very dangerous
* 1459
* 1382
* 1305
* 1267 → NVIDIA T214 rating
* 1267 → NVIDIA T214(mariko) rating
* 1228 → mariko HiOPT safe clock
* 1152 → mariko SLT max clock
* 1075 → mariko no UV max clock. absolute max clock on erista. very dangerous
* 998 → NVIDIA T210 rating
* 998 → NVIDIA T210 (erista) rating
* 960 (erista only) → erista slt/hiopt safe max clock
* 921 → erista no UV max clock
* 844
@@ -154,6 +154,7 @@ Refer to COMPILATION.md
* **Souldbminer** - hoc-clk and loader development
* **Lightos** - Loader patches development, hoc-clk development, guides
* **TDRR** - HOC Logo Design
* **SciresM** - Atmosphere CFW
* **CTCaer** - L4T, Hekate, proper RAM timings
* **KazushiMe** - Switch OC Suite

View File

@@ -0,0 +1,88 @@
{
"name": "Loader",
"title_id": "0x0100000000000001",
"main_thread_stack_size": "0x4000",
"main_thread_priority": 49,
"default_cpu_id": 3,
"process_category": 1,
"use_secure_memory": true,
"immortal": true,
"kernel_capabilities": [
{
"type": "handle_table_size",
"value": 128
},
{
"type": "syscalls",
"value": {
"svcSetHeapSize" : "0x01",
"svcSetMemoryPermission" : "0x02",
"svcSetMemoryAttribute" : "0x03",
"svcMapMemory" : "0x04",
"svcUnmapMemory" : "0x05",
"svcQueryMemory" : "0x06",
"svcExitProcess" : "0x07",
"svcCreateThread" : "0x08",
"svcStartThread" : "0x09",
"svcExitThread" : "0x0A",
"svcSleepThread" : "0x0B",
"svcGetThreadPriority" : "0x0C",
"svcSetThreadPriority" : "0x0D",
"svcGetThreadCoreMask" : "0x0E",
"svcSetThreadCoreMask" : "0x0F",
"svcGetCurrentProcessorNumber" : "0x10",
"svcSignalEvent" : "0x11",
"svcClearEvent" : "0x12",
"svcMapSharedMemory" : "0x13",
"svcUnmapSharedMemory" : "0x14",
"svcCreateTransferMemory" : "0x15",
"svcCloseHandle" : "0x16",
"svcResetSignal" : "0x17",
"svcWaitSynchronization" : "0x18",
"svcCancelSynchronization" : "0x19",
"svcArbitrateLock" : "0x1A",
"svcArbitrateUnlock" : "0x1B",
"svcWaitProcessWideKeyAtomic" : "0x1C",
"svcSignalProcessWideKey" : "0x1D",
"svcGetSystemTick" : "0x1E",
"svcConnectToNamedPort" : "0x1F",
"svcSendSyncRequestLight" : "0x20",
"svcSendSyncRequest" : "0x21",
"svcSendSyncRequestWithUserBuffer" : "0x22",
"svcSendAsyncRequestWithUserBuffer" : "0x23",
"svcGetProcessId" : "0x24",
"svcGetThreadId" : "0x25",
"svcBreak" : "0x26",
"svcOutputDebugString" : "0x27",
"svcReturnFromException" : "0x28",
"svcGetInfo" : "0x29",
"svcWaitForAddress" : "0x34",
"svcSignalToAddress" : "0x35",
"svcSynchronizePreemptionState" : "0x36",
"svcCreateSession" : "0x40",
"svcAcceptSession" : "0x41",
"svcReplyAndReceiveLight" : "0x42",
"svcReplyAndReceive" : "0x43",
"svcReplyAndReceiveWithUserBuffer" : "0x44",
"svcCreateEvent" : "0x45",
"svcReadWriteRegister" : "0x4E",
"svcQueryIoMapping" : "0x55",
"svcSetProcessMemoryPermission" : "0x73",
"svcMapProcessMemory" : "0x74",
"svcUnmapProcessMemory" : "0x75",
"svcMapProcessCodeMemory" : "0x77",
"svcUnmapProcessCodeMemory" : "0x78",
"svcCreateProcess" : "0x79",
"svcCallSecureMonitor" : "0x7F"
}
}, {
"type": "map",
"value": {
"address": "0x7000F000",
"is_ro": false,
"size": "0x00001000",
"is_io": true
}
}
]
}

View File

@@ -40,13 +40,15 @@ volatile CustomizeTable C = {
.eristaEmcMaxClock1 = 1600000,
.eristaEmcMaxClock2 = 1600000,
/* Available: 66MHz step rate, 100MHz step rate and jedec. */
/* Available: 66MHz step rate, 100MHz step rate, 133MHz step rate and jedec. */
/* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */
.stepMode = StepMode_66MHz,
.marikoEmcMaxClock = 2133000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.marikoEmcVddqVolt = 600000,
.emcDvbShift = 0,
.marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */
// Primary
.t1_tRCD = 0,
@@ -65,21 +67,21 @@ volatile CustomizeTable C = {
/* Frequency where non low timings gets used. */
.timingEmcTbreak = DISABLED,
.low_t6_tRTW = DISABLED,
.low_t7_tWTR = DISABLED,
.low_t6_tRTW = 0,
.low_t7_tWTR = 0,
.readLatency = {
DISABLED,
DISABLED,
DISABLED,
DISABLED,
/* 1333 */ 0,
/* 1600 */ 0,
/* 1866 */ 0,
/* 2133 */ 0,
},
.writeLatency = {
DISABLED,
DISABLED,
DISABLED,
DISABLED,
/* 1333 */ 0,
/* 1600 */ 0,
/* 1866 */ 0,
/* 2133 */ 0,
},
/* You can mix and match different latencies if needed */

View File

@@ -40,6 +40,7 @@ enum StepMode: u32 {
StepMode_66MHz = 0,
StepMode_100MHz = 1,
StepMode_Jedec = 2,
StepMode_133MHz = 3,
};
/*
@@ -93,6 +94,7 @@ typedef struct CustomizeTable {
u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt;
u32 emcDvbShift;
u32 marikoSocVmax;
// advanced config
u32 t1_tRCD;
u32 t2_tRP;

View File

@@ -52,6 +52,8 @@ namespace ams::ldr {
R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014);
R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015);
R_DEFINE_ERROR_RESULT(InvalidMtcTablePattern, 1016);
R_DEFINE_ERROR_RESULT(InvalidSocVoltPattern, 1017);
R_DEFINE_ERROR_RESULT(InvalidSocVoltLimit, 1018);
}
namespace ams::ldr::hoc {

View File

@@ -154,6 +154,7 @@ namespace ams::ldr::hoc::pcv {
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
{ C.marikoEmcMaxClock, 1600'000, 3500'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 },
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu },

View File

@@ -26,6 +26,16 @@ namespace ams::ldr::hoc::pcv {
constexpr u32 NopIns = 0x1f2003d5;
template <typename Compare>
u32 *ScanAssembly(u32 *ptr, u32 scanLimit, u32 pattern, Compare comp) {
for (u32 i = 0; i < scanLimit; ++i) {
if (comp(pattern, ptr[i])) {
return ptr + i;
}
}
return nullptr;
}
inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) {
return ((ins1 ^ ins2) >> 5) == 0;
};
@@ -61,4 +71,75 @@ namespace ams::ldr::hoc::pcv {
return ((ins1 & ImmMask) ^ (ins2 & ImmMask)) == 0;
};
/* Csel (Conditional Select) */
/*
SF | Op | S | | RM | Cond | 0 | 0 | Rn | Rd
31 | 30 | 29 | 28 27 26 25 24 23 | 20 19 18 17 16 | 15 14 13 12 | 11 | 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmCompareCselNoReg = [](u32 ins1, u32 ins2) {
constexpr u32 ClearReg = ~(((1 << 10) - 1) | (((1 << 5) - 1) << 16));
return ((ins1 & ClearReg) ^ (ins2 & ClearReg)) == 0;
};
/* Mul */
/*
SF | Op54 | Op31 | RM | o0 | RA | RN | RD
31 | 30 29 28 27 26 25 24 | 23 22 21 | 20 19 18 17 16 | 15 | 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmCompareMullNoReg = [](u32 ins1, u32 ins2) {
constexpr u32 ClearReg = ~(((1 << 10) - 1) | (((1 << 5) - 1) << 16));
return ((ins1 & ClearReg) ^ (ins2 & ClearReg)) == 0;
};
/* Mul */
/* MUL W11, W24, W26 */
/* multiplies by 1000, mV -> uV */
/*
SF | Op54 | Op31 | RM | o0 | RA | RN | RD
31 | 30 29 28 27 26 25 24 | 23 22 21 | 20 19 18 17 16 | 15 | 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmGetMullRn = [](u32 ins) {
constexpr u32 Mask = ((1 << 5) - 1) << 5;
return (ins & Mask) >> 5;
};
inline auto AsmGetMullRm = [](u32 ins) {
constexpr u32 Mask = ((1 << 5) - 1) << 16;
return (ins & Mask) >> 16;
};
/* Subs (Shifted register) */
/*
SF | Op | S | | Shift | 0 | RM | Imm6 | Rn | Rd
31 | 30 | 29 | 28 27 26 25 24 | 23 22 | 21 | 20 19 18 17 16 | 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmSubsSetRn = [](u32 ins, u8 rn) {
constexpr u32 RnMaskClear = ~(((1u << 5) - 1u) << 5);
constexpr u32 RnMaskSet = (1u << 5) - 1u;
return (ins & RnMaskClear) | ((static_cast<u32>(rn) & RnMaskSet) << 5);
};
/* Subs (Immediate) */
/*
SF | Op | S | | Sh | Imm12 | Rn | Rd
31 | 30 | 29 | 28 27 26 25 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmSubsSetImm12 = [](u32 ins, u16 imm12) {
constexpr u32 ClearMask = ~(((1u << 12) - 1) << 10);
constexpr u32 SetImm12Mask = ( 1u << 12) - 1;
return (ins & ClearMask) | ((imm12 & SetImm12Mask) << 10);
};
inline auto AsmSubsCompareNoReg = [](u32 ins1, u32 ins2) {
return ((ins1 ^ ins2) >> 10) == 0;
};
inline auto AsmCompareBrConNoImm19 = [](u32 ins1, u32 ins2) {
constexpr u32 ClearImm19 = ~(((1 << 19) - 1) << 5);
return (ins1 & ClearImm19) == (ins2 & ClearImm19);
};
}

View File

@@ -279,12 +279,6 @@ namespace ams::ldr::hoc::pcv::mariko {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
/* Verify the limit. */
/* TODO: Make this a little bit cleaner at some point. */
if (AsmGetImm16(ins1) != (GpuClkOsLimit & 0xFFFF) || AsmGetImm16(ins2) != (GpuClkOsLimit >> 16)) {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
u32 max_clock;
switch (C.marikoGpuUV) {
case 0:
@@ -615,6 +609,25 @@ namespace ams::ldr::hoc::pcv::mariko {
newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit));
}
void MtcGenerate133StepTable() {
const u32 StepFreqs133[] = { 1733000, 1866000, 2000000, 2133000, 2266000, 2400000, 2533000, 2666000, 2800000, 2933000, 3066000, 3200000, 3333000, 3466000, }; // Avoid rounding issues
constexpr u32 StepFreqs133Size = std::size(StepFreqs133);
for (u32 i = 0; i < StepFreqs133Size; ++i) {
if (StepFreqs133[i] <= C.marikoEmcMaxClock) {
newEmcList.push_back(StepFreqs133[i]);
} else {
break;
}
}
if (newEmcList.back() != C.marikoEmcMaxClock) {
newEmcList.push_back(static_cast<u32>(C.marikoEmcMaxClock));
}
newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit));
}
void MtcGenerateFreqTables() {
if (C.marikoEmcMaxClock <= EmcClkOSLimit) {
return;
@@ -635,6 +648,9 @@ namespace ams::ldr::hoc::pcv::mariko {
case StepMode_Jedec:
MtcGenerateJedecTable();
return;
case StepMode_133MHz:
MtcGenerate133StepTable();
return;
default:
stepRate = 66667;
break;
@@ -782,21 +798,43 @@ namespace ams::ldr::hoc::pcv::mariko {
R_SKIP();
}
u32 max0 = 1050;
u32 max1 = 1025;
u32 max2 = 1000;
s32 voltAdd = 25 * C.emcDvbShift;
#define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000),
DvbEntry emcDvbTableNew[] = {
{ 204000, { 637, 637, 637, } },
{ 1331200, { 650, 637, 637, } },
{ 1600000, { 675, 650, 637, } },
{ 1866000, { DVB_VOLT(700, 675, 650) } },
{ 2133000, { DVB_VOLT(725, 700, 675) } },
{ 2400000, { DVB_VOLT(750, 725, 700) } },
{ 2666000, { DVB_VOLT(775, 750, 725) } },
{ 2933000, { DVB_VOLT(800, 775, 750) } },
{ 3200000, { DVB_VOLT(800, 800, 775) } },
{ 0xFFFFFFFF, { } },
if (C.marikoSocVmax && C.marikoSocVmax > 1000) {
max0 = C.marikoSocVmax;
max1 = C.marikoSocVmax;
max2 = C.marikoSocVmax;
}
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)
};
};
#define DVB(v) \
static_cast<u32>((v)[0]), \
static_cast<u32>((v)[1]), \
static_cast<u32>((v)[2])
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
u32 j = MtcTableCountDefault;
for (u32 i = MtcTableCountDefault; i < newEmcList.size(); ++i) {
if (newEmcList[i] >= emcDvbTableNew[j].freq && newEmcList[i] < emcDvbTableNew[j + 1].freq) {
@@ -849,7 +887,7 @@ namespace ams::ldr::hoc::pcv::mariko {
regulator *entry = reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_2_3.default_uv));
constexpr u32 uv_step = 5'000;
constexpr u32 uv_min = 250'000;
constexpr u32 uv_min = 250'000;
auto validator = [entry]() {
R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry());
@@ -914,6 +952,124 @@ namespace ams::ldr::hoc::pcv::mariko {
R_SUCCEED();
}
Result GetSocSpeedo(u32 &socSpeedo) {
constexpr u64 FusePhysicalAddress = 0x7000F000;
u64 virtualAddress = 0;
constexpr u64 Size = 0x1000;
u64 outSize;
/* TODO: use svc::QueryMemoryMapping instead. */
R_TRY(svcQueryMemoryMapping(&virtualAddress, &outSize, FusePhysicalAddress, Size));
constexpr u32 FuseOffset = 2048;
constexpr u32 SocSpeedoOffset = 308;
socSpeedo = *reinterpret_cast<u32 *>(virtualAddress + FuseOffset + SocSpeedoOffset);
R_SUCCEED();
}
u32 GetSocProcessId(u32 socSpeedo) {
if (socSpeedo <= 1597) {
return 0;
}
if (socSpeedo <= 1708) {
return 1;
}
/* >= 1709. */
return 2;
}
Result SocVoltAsm(u32 *compareSpeedos) {
constexpr u32 VoltageScanLimit = 10;
/* Might actually be speedo id. */
u32 *writeProcessId = ScanAssembly(compareSpeedos, VoltageScanLimit, SocVoltWriteProcessIdAsm, asm_compare_no_rd);
R_UNLESS(writeProcessId != nullptr, ldr::ResultInvalidSocVoltPattern());
u8 writeProcessIdRd = asm_get_rd(*writeProcessId);
/* This writes 1050mV. */
u32 *writeVoltage = ScanAssembly(writeProcessId, VoltageScanLimit, SocVoltWriteVoltageAsm, asm_compare_no_rd);
R_UNLESS(writeVoltage != nullptr, ldr::ResultInvalidSocVoltPattern());
u8 writeVoltageRd = asm_get_rd(*writeVoltage);
/* A csel instruction is used to select the soc voltage limit register. */
/* We care about its destination register since that is used for verification. */
constexpr u32 VoltageSelectScanLimit = 24;
u32 *selectVoltage = ScanAssembly(writeVoltage, VoltageSelectScanLimit, SocVoltSelectRegisterAsm, AsmCompareCselNoReg);
R_UNLESS(selectVoltage != nullptr, ldr::ResultInvalidSocVoltPattern());
/* Todo: check rm and rn? */
u8 selectVoltageRd = asm_get_rd(*selectVoltage);
/* rdCsel is then multiplied by 1000 to convert to uV. */
/* This is pretty far down the function. */
constexpr u32 MultiplierScanLimit = 200;
u32 *multiplier = ScanAssembly(selectVoltage, MultiplierScanLimit, SocVoltMultiplyVoltsAsm, AsmCompareMullNoReg);
R_UNLESS(multiplier != nullptr, ldr::ResultInvalidSocVoltPattern());
u8 multiplierRn = AsmGetMullRn(*multiplier);
u8 multiplierRm = AsmGetMullRm(*multiplier);
/* One of the two registers has to be rdCsel. */
R_UNLESS((multiplierRn == selectVoltageRd) || (multiplierRm == selectVoltageRd), ldr::ResultInvalidSocVoltPattern());
u8 multiplierRd = asm_get_rd(*multiplier);
/* Subs instruction is then used to verify against absolute limit. */
u32 limitValidationPattern = AsmSubsSetRn(SocVoltValidateLimitAsm, multiplierRd);
u32 *limitValidation = ScanAssembly(multiplier, VoltageScanLimit, limitValidationPattern, AsmSubsCompareNoReg);
R_UNLESS(limitValidation != nullptr, ldr::ResultInvalidSocVoltPattern());
/* There is a b.gt instruction right after (checks for socVoltageCap < socVoltageMax). */
u32 *branchToAbort = limitValidation + 1;
R_UNLESS(AsmCompareBrConNoImm19(*branchToAbort, SocVoltBranchToAbortAsm), ldr::ResultInvalidSocVoltPattern());
if (!C.marikoSocVmax || C.marikoSocVmax <= 1000) {
R_SKIP();
}
/* Adjust 1598 speedo minimum to ensure it always goes down process id 0 branch. */
/* 2200 should be high enough :D */
u32 compareSpeedosPatch = AsmSubsSetImm12(*compareSpeedos, 2200);
PATCH_OFFSET(compareSpeedos, compareSpeedosPatch);
u32 socSpeedo = 0;
R_TRY(GetSocSpeedo(socSpeedo));
/* Adjust processId from 0 to [process id of switch booting this]. */
/* We're overwriting the orr instruction entirly. */
u32 processId = GetSocProcessId(socSpeedo);
u32 writeProcessIdPatch = asm_set_rd(asm_set_imm16(SocVoltWriteVoltageAsm, processId), writeProcessIdRd);
PATCH_OFFSET(writeProcessId, writeProcessIdPatch);
/* Adjust voltage limit. */
u32 voltageLimitPatch = asm_set_rd(asm_set_imm16(SocVoltWriteVoltageAsm, C.marikoSocVmax), writeVoltageRd);
PATCH_OFFSET(writeVoltage, voltageLimitPatch);
/* Branches to an abort if limits are invalid -- we patch the branch instruction with NOP. */
PATCH_OFFSET(branchToAbort, NopIns);
R_SUCCEED();
}
Result SocVoltLimit(u32 *ptr) {
R_UNLESS(!std::memcmp(ptr - SocVoltLimitMaxDefaultIndex, socVoltLimitArray, sizeof(socVoltLimitArray)), ldr::ResultInvalidSocVoltLimit());
if (!C.marikoSocVmax || C.marikoSocVmax <= SocVoltLimitOfficial) {
R_SKIP();
}
constexpr u32 Step = 25;
u32 maxVolt = C.marikoSocVmax;
if (maxVolt % Step) {
maxVolt = maxVolt / Step * Step; /* Round. */
}
u32 volt = SocVoltLimitOfficial;
for (u32 i = 1; i < DvfsTableEntryCount - SocVoltLimitMaxDefaultIndex && volt < maxVolt; ++i) {
volt += Step;
PATCH_OFFSET(ptr + i, volt);
}
R_SUCCEED();
}
void Patch(uintptr_t mapped_nso, size_t nso_size) {
nsoStart = reinterpret_cast<u32 *>(mapped_nso);
MtcGenerateFreqTables();
@@ -932,13 +1088,15 @@ namespace ams::ldr::hoc::pcv::mariko {
{ "GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn },
{ "GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax },
{ "GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit },
{ "MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit },
{ "MEM Freq Mtc", &MemFreqMtcTable, 1, nullptr, EmcClkOSLimit },
{ "MEM Freq Dvb", &MemFreqDvbTable, 1, nullptr, EmcClkOSLimit },
{ "MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit },
{ "MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit },
{ "MEM Vddq", &EmcVddqVolt, 2, nullptr, EmcVddqDefault },
{ "MEM Vdd2", &MemVoltHandler, 2, nullptr, MemVdd2Default },
{ "Mem Table Asm", &MemMtcTableAsm, 0, &MemMtcGetGetTablePatternFn },
{ "MEM Table Asm", &MemMtcTableAsm, 1, &MemMtcGetGetTablePatternFn },
{ "SOC Volt Asm", &SocVoltAsm, 1, &SocVoltPatternFn },
{ "SOC Volt Limit", &SocVoltLimit, 1, nullptr, SocVoltLimitOfficial },
};
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(MarikoMtcTable); ptr += sizeof(u32)) {

View File

@@ -112,7 +112,7 @@ namespace ams::ldr::hoc::pcv::mariko {
struct DvbEntry {
u64 freq;
s32 volt[4] = {};
u32 volt[4] = {};
};
constexpr DvbEntry EmcDvbTableDefault[] = {
@@ -124,16 +124,37 @@ namespace ams::ldr::hoc::pcv::mariko {
{ 1600000, { 675, 650, 637, } },
};
/* Movz */
/*
SF | OPC | HW | Imm16 | RD
31 | 30 29 28 27 26 25 24 23 | 22 21 | 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0
*/
constexpr u32 SocVoltCompareSpeedoAsm = 0x7118FAFF; /* subs imm, compares to >=1598 max speedo and then goes down process id 1 route. */
constexpr u32 SocVoltWriteProcessIdAsm = 0x2A1F03F4; /* orr, writes id 0. */
constexpr u32 SocVoltWriteVoltageAsm = 0x52808358; /* Movz imm, writes 1050mV. */
constexpr u32 SocVoltSelectRegisterAsm = 0x1A9A3118; /* Csel, selects the voltage -- we need the register of this. */
constexpr u32 SocVoltMultiplyVoltsAsm = 0x1B1A7F0B; /* Mul, converts from mV -> uV */
constexpr u32 SocVoltValidateLimitAsm = 0x6B0A017F; /* Subs, checks limits */
constexpr u32 SocVoltBranchToAbortAsm = 0x540020AC; /* B.ge Branches to abort if limits are invalid. */
ALWAYS_INLINE bool SocVoltPatternFn(u32 *ptr) {
return asm_compare_no_rd(*ptr, SocVoltCompareSpeedoAsm);
}
constexpr u32 SocVoltLimitOfficial = 1050;
constexpr u32 SocVoltLimitMaxDefaultIndex = 17;
static const u32 socVoltLimitArray[DvfsTableEntryCount] = { 637, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, };
constexpr u32 EmcListDefault[] = { 204000, 1331200, 1600000, };
constexpr u32 EmcListSizeDefault = std::size(EmcListDefault);
constexpr u32 EmcListEndDefault = EmcListSizeDefault - 1;
constexpr u32 EmcRateStep = 33'000;
constexpr u32 EmcRateStepScale = 33'200;
constexpr u32 EmcClkOSAlt = 1331'200;
constexpr u32 EmcClkOSAlt = 1331'200;
constexpr u32 EmcClkPllmLimit = 2133'000'000;
constexpr u32 EmcVddqDefault = 600'000;
constexpr u32 MemVdd2Default = 1100'000;
constexpr u32 EmcVddqDefault = 600'000;
constexpr u32 MemVdd2Default = 1100'000;
constexpr u32 MTC_TABLE_REV = 3;
constexpr u32 MtcTableCountDefault = 3;
@@ -260,8 +281,8 @@ namespace ams::ldr::hoc::pcv::mariko {
/* Adrp */
/*
OP | ImmLow | ImmHigh | RD
31 | 30 29 28 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0
OP | ImmLow | | ImmHigh | RD
31 | 30 29 | 28 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0
*/
/* ADD (immediate) */

View File

@@ -142,7 +142,7 @@ public:
});
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Status Monitor Pro", APP_VERSION, true);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true);
rootFrame->setContent(Status);
return rootFrame;

View File

@@ -122,7 +122,7 @@ public:
});
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Status Monitor Pro", APP_VERSION, true);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true);
rootFrame->setContent(Status);
return rootFrame;

View File

@@ -92,6 +92,7 @@ typedef enum
HocClkThermalSensor_GPU,
HocClkThermalSensor_MEM, // Returns the PLLX sensor value on Mariko
HocClkThermalSensor_PLLX,
HocClkThermalSensor_BQ24193,
HocClkThermalSensor_EnumMax
} HocClkThermalSensor;
@@ -125,9 +126,9 @@ typedef enum {
} HocClkSpeedo;
typedef enum {
GPUUVLevel_NoUV = 0,
GPUUVLevel_SLT,
GPUUVLevel_HiOPT,
GPUUVLevel_HiOPT = 0,
GPUUVLevel_HiOPT15,
GPUUVLevel_HighUV,
GPUUVLevel_EnumMax,
} GPUUndervoltLevel;
@@ -164,8 +165,8 @@ typedef enum {
} RamDisplayMode;
typedef enum {
MemoryFrequencyMeasurementMode_Actmon = 0,
MemoryFrequencyMeasurementMode_PLL,
MemoryFrequencyMeasurementMode_PLL = 0,
MemoryFrequencyMeasurementMode_Actmon,
MemoryFrequencyMeasurementMode_EnumMax,
} MemoryFrequencyMeasurementMode;

View File

@@ -60,7 +60,7 @@ typedef struct
u16 resolutionHeight;
// Reserved for future use
u8 reserved[0x428];
u8 reserved[0x424];
} HocClkContext;
typedef struct
@@ -73,6 +73,6 @@ typedef struct
#define HOCCLK_FREQ_LIST_MAX 32
#define GLOBAL_PROFILE_ID 0xA111111111111111
#define HOCCLK_GLOBAL_PROFILE_TID 0xA111111111111111
static_assert(sizeof(HocClkContext) == 0x500);

View File

@@ -85,6 +85,7 @@ typedef enum {
KipConfigValue_marikoEmcMaxClock,
KipConfigValue_marikoEmcVddqVolt,
KipConfigValue_emcDvbShift,
KipConfigValue_marikoSocVmax,
KipConfigValue_t1_tRCD,
KipConfigValue_t2_tRP,
@@ -310,7 +311,8 @@ 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_marikoSocVmax:
return pretty ? "SOC Vmax" : "soc_vmax";
// Memory timings
case KipConfigValue_t1_tRCD:
return pretty ? "t1 - tRCD" : "t1_trcd";
@@ -566,6 +568,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_marikoEmcMaxClock:
case KipConfigValue_marikoEmcVddqVolt:
case KipConfigValue_emcDvbShift:
case KipConfigValue_marikoSocVmax:
case KipConfigValue_t1_tRCD:
case KipConfigValue_t2_tRP:
case KipConfigValue_t3_tRAS:

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.0.1
APP_VERSION := 2.1.0
TARGET_VERSION := $(APP_VERSION)
#---------------------------------------------------------------------------------

View File

@@ -36,6 +36,7 @@ tsl::elm::ListItem* ramBWItemAll = NULL;
tsl::elm::ListItem* ramBWItemCpu = NULL;
tsl::elm::ListItem* ramBWItemGpu = NULL;
tsl::elm::ListItem* ramBWItemMax = NULL;
tsl::elm::ListItem* bqtempitem = NULL;
ImageElement* CatImage = NULL;
HideableCategoryHeader* CatHeader = NULL;
@@ -73,6 +74,10 @@ void AboutGui::listUI()
this->listElement->addItem(eristaPLLXItem);
}
bqtempitem =
new tsl::elm::ListItem("BQ24193 Temp:");
this->listElement->addItem(bqtempitem);
this->listElement->addItem(
new tsl::elm::CategoryHeader("RAM Bandwidth")
);
@@ -382,4 +387,23 @@ void AboutGui::refresh()
sprintf(strings[9], "%u MB/s", context->partLoad[HocClkPartLoad_RamBWPeak]);
ramBWItemMax->setValue(strings[9]);
switch(context->temps[HocClkThermalSensor_BQ24193]) {
case 0:
strcpy(strings[10], "Normal");
break;
case 1:
strcpy(strings[10], "Warm");
break;
case 2:
strcpy(strings[10], "Hot");
break;
case 3:
strcpy(strings[10], "Overheat");
break;
default:
strcpy(strings[10], "Unknown");
}
bqtempitem->setValue(strings[10]);
}

View File

@@ -290,6 +290,9 @@ public:
: applicationId(appId), profileList(pList), profile(prof) {}
void listUI() override {
BaseMenuGui::refresh(); // get latest context
if(!this->context)
return;
Result rc = hocclkIpcGetConfigValues(&configList);
if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc);

View File

@@ -28,7 +28,6 @@
#include "base_menu_gui.h"
#include "freq_choice_gui.h"
#include "value_choice_gui.h"
#define HOCCLK_GLOBAL_PROFILE_TID 0xA111111111111111
class AppProfileGui : public BaseMenuGui
{
protected:

View File

@@ -301,6 +301,9 @@ public:
GovernorOverrideSubMenuGui(u32 initialPacked) : packed(initialPacked) {}
void listUI() override {
BaseMenuGui::refresh(); // get latest context
if(!this->context)
return;
Result rc = hocclkIpcGetConfigValues(&configList); // idk why this is needed, probably some refreshing issue
if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc);

View File

@@ -71,6 +71,10 @@ MiscGui::MiscGui()
MiscGui::~MiscGui()
{
if (shouldSaveKip) {
sendKipData();
shouldSaveKip = false;
}
if (s_kipThreadPending) {
threadWaitForExit(&s_kipThread);
threadClose(&s_kipThread);
@@ -94,7 +98,7 @@ void MiscGui::addConfigToggle(HocClkConfigValue configVal, const char* altName,
if (R_FAILED(rc)) {
FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc);
} else if (kip) {
sendKipData();
shouldSaveKip = true;
}
this->lastContextUpdate = armGetSystemTick();
});
@@ -102,6 +106,59 @@ void MiscGui::addConfigToggle(HocClkConfigValue configVal, const char* altName,
this->configToggles[configVal] = toggle;
}
void MiscGui::addConfigTrackbar(HocClkConfigValue configVal, const char* altName, const ValueRange& range, bool kip) {
struct IndexedBar : tsl::elm::NamedStepTrackBar {
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++) {
u32 disp = (r.min + i * r.step) / r.divisor;
std::string s = std::to_string(disp);
if (!r.suffix.empty()) s += " " + r.suffix;
m_stepDescriptions.push_back(s);
}
m_numSteps = (u8)m_stepDescriptions.size();
m_selection = m_stepDescriptions[0];
}
};
const char* name = altName ? altName : hocclkFormatConfigValue(configVal, true);
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)
curStep = (u16)((cur - range.min) / range.step);
bar->setProgress(curStep);
bar->setValueChangedListener([this, configVal, kip, range](u16 v) {
this->configList->values[configVal] = range.min + (u32)v * range.step;
Result rc = hocclkIpcSetConfigValues(this->configList);
if (R_FAILED(rc)) FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc);
if (kip) shouldSaveKip = true;
});
this->listElement->addItem(bar);
}
void MiscGui::addMappedConfigTrackbar(HocClkConfigValue configVal, const char* altName,
std::vector<u32> vals,
std::initializer_list<std::string> names, bool kip) {
const char* name = altName ? altName : hocclkFormatConfigValue(configVal, true);
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++) {
if (vals[i] == cur) { curIdx = i; break; }
}
bar->setProgress(curIdx);
bar->setValueChangedListener([this, configVal, kip, vals](u16 idx) {
if (idx < (u16)vals.size())
this->configList->values[configVal] = vals[idx];
Result rc = hocclkIpcSetConfigValues(this->configList);
if (R_FAILED(rc)) FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc);
if (kip) shouldSaveKip = true;
});
this->listElement->addItem(bar);
}
void MiscGui::addConfigButton(HocClkConfigValue configVal,
const char* altName,
@@ -173,7 +230,7 @@ void MiscGui::addConfigButton(HocClkConfigValue configVal,
return false;
}
if (kip) {
sendKipData();
shouldSaveKip = true;
}
this->lastContextUpdate = armGetSystemTick();
return true;
@@ -198,7 +255,7 @@ void MiscGui::addConfigButton(HocClkConfigValue configVal,
return false;
}
if (kip) {
sendKipData();
shouldSaveKip = true;
}
this->lastContextUpdate = armGetSystemTick();
return true;
@@ -291,7 +348,7 @@ void MiscGui::addConfigButtonS(HocClkConfigValue configVal,
return false;
}
if (kip) {
sendKipData();
shouldSaveKip = true;
}
this->lastContextUpdate = armGetSystemTick();
return true;
@@ -316,7 +373,7 @@ void MiscGui::addConfigButtonS(HocClkConfigValue configVal,
return false;
}
if (kip) {
sendKipData();
shouldSaveKip = true;
}
this->lastContextUpdate = armGetSystemTick();
return true;
@@ -529,6 +586,8 @@ public:
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
this->listElement->addItem(new tsl::elm::CategoryHeader("General Settings"));
ValueThresholds thresholdsDisabled(0, 0);
std::vector<NamedValue> ramVoltDispModes = {
@@ -556,6 +615,7 @@ protected:
false
);
addConfigButton(
HocClkConfigValue_PollingIntervalMs,
"Polling Interval",
@@ -569,9 +629,10 @@ protected:
tsl::elm::CustomDrawer* exSetWarning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString("\uE150 Experimental Settings are incomplete ", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
renderer->drawString("and may not work correctly! Here be dragons!", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
renderer->drawString("and may not work correctly or at all!", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
renderer->drawString("Here be dragons!", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
});
exSetWarning->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 70);
exSetWarning->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 90);
this->listElement->addItem(exSetWarning);
addConfigToggle(HocClkConfigValue_EnableExperimentalSettings, nullptr);
@@ -584,6 +645,8 @@ public:
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental Settings"));
ValueThresholds thresholdsDisabled(0, 0);
@@ -605,8 +668,8 @@ protected:
std::vector<NamedValue> ramRFMeasurementMethods = {
NamedValue("Actmon", MemoryFrequencyMeasurementMode_Actmon),
NamedValue("PLL", MemoryFrequencyMeasurementMode_PLL),
NamedValue("Actmon", MemoryFrequencyMeasurementMode_Actmon),
};
addConfigButton(
HocClkConfigValue_MemoryFrequencyMeasurementMode,
@@ -659,13 +722,14 @@ protected:
NamedValue("1024mA", 1024),
NamedValue("1280mA", 1280),
NamedValue("1536mA", 1536),
NamedValue("1664mA", 1664), // Why Nintendo?
NamedValue("1792mA", 1792),
NamedValue("2048mA", 2048),
NamedValue("2304mA", 2304),
NamedValue("2560mA", 2560),
};
ValueThresholds chargerThresholds(1792, 1793);
ValueThresholds chargerThresholds(1664, 1793);
addConfigButton(
HocClkConfigValue_BatteryChargeCurrent,
@@ -689,6 +753,8 @@ public:
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
this->listElement->addItem(new tsl::elm::CategoryHeader("Governor Settings"));
ValueThresholds thresholdsDisabled(0, 0);
@@ -722,6 +788,8 @@ public:
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
ValueThresholds thresholdsDisabled(0, 0);
BaseMenuGui::refresh(); // get latest context
@@ -773,6 +841,8 @@ public:
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
this->listElement->addItem(new tsl::elm::CategoryHeader("Safety Settings"));
addConfigToggle(HocClkConfigValue_UncappedClocks, nullptr);
addConfigToggle(HocClkConfigValue_ThermalThrottle, nullptr);
@@ -822,11 +892,58 @@ public:
protected:
void listUI() override {
BaseMenuGui::refresh();
if(!this->context)
return;
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
ValueThresholds thresholdsDisabled(0, 0);
std::vector<NamedValue> noNamedValues = {};
this->listElement->addItem(new tsl::elm::CategoryHeader("RAM Settings"));
this->listElement->addItem(new tsl::elm::CategoryHeader("RAM Settings"));
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";
if (socSpeedo <= 1597) {
autoText = "1050 mV";
} else if (socSpeedo <= 1708) {
autoText = "1025 mV";
} else if(socSpeedo >= 1709) {
autoText = "1000 mV";
}
std::vector<NamedValue> marikovmaxconf = {
NamedValue("Do not override", 0, autoText),
NamedValue("1000 mV", 1000),
NamedValue("1025 mV", 1025),
NamedValue("1050 mV", 1050),
NamedValue("1075 mV", 1075),
NamedValue("1100 mV", 1100),
NamedValue("1125 mV", 1125),
NamedValue("1150 mV", 1150),
NamedValue("1175 mV", 1175),
NamedValue("1200 mV", 1200),
};
ValueThresholds marikovmaxT(1075, 1150);
addConfigButton(
KipConfigValue_marikoSocVmax,
"SoC Max Volt",
ValueRange(0, 12, 1, "", 0),
"SoC Max Volt",
&marikovmaxT,
{},
marikovmaxconf,
false,
true
);
}
addConfigToggle(KipConfigValue_hpMode, "HP Mode", true);
std::map<uint32_t, std::string> emc_voltage_label = {
@@ -838,7 +955,7 @@ protected:
{1250000, "Unsafe Max"},
};
ValueThresholds vdd2Thresholds(1212500, 1250000);
ValueThresholds vdd2Thresholds(IsMariko() ? 1212500 : 1237500, 1250000);
addConfigButton(
KipConfigValue_commonEmcMemVolt,
"RAM VDD2 Voltage",
@@ -865,25 +982,16 @@ protected:
);
}
addConfigButton(
KipConfigValue_emcDvbShift,
"SoC DVB Shift",
ValueRange(0, 10, 1, "", 1),
"SoC DVB Shift",
&thresholdsDisabled,
{},
{},
false,
true
);
if (IsMariko()) {
std::vector<NamedValue> stepMode = {
NamedValue("66MHz", 0),
NamedValue("100MHz", 1),
NamedValue("133MHz", 3), // Mantain compatability
NamedValue("JEDEC.", 2),
};
std::vector<NamedValue> stepMode = {
NamedValue("66MHz", 0),
NamedValue("100MHz", 1),
NamedValue("Jedec", 2),
};
addConfigButton(KipConfigValue_stepMode, "Step Mode", ValueRange(0, 0, 2, "", 0), "Step Mode", &thresholdsDisabled, {}, stepMode, false, true);
addConfigButton(KipConfigValue_stepMode, "Step Mode", ValueRange(0, 0, 2, "", 0), "Step Mode", &thresholdsDisabled, {}, stepMode, false, true);
}
if (IsErista()) {
tsl::elm::ListItem* freqSubmenu = new tsl::elm::ListItem("RAM Frequency Editor");
@@ -997,40 +1105,18 @@ public:
protected:
void listUI() override {
ValueThresholds thresholdsDisabled(0, 0);
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
this->listElement->addItem(new tsl::elm::CategoryHeader("Memory Timings"));
addConfigButton(KipConfigValue_t1_tRCD, "t1 tRCD", ValueRange(0, 7, 1, "", 1), "tRCD", &thresholdsDisabled, {}, {}, false, true);
addConfigButton(KipConfigValue_t2_tRP, "t2 tRP", ValueRange(0, 7, 1, "", 1), "tRP", &thresholdsDisabled, {}, {}, false, true);
addConfigButton(KipConfigValue_t3_tRAS, "t3 tRAS", ValueRange(0, 9, 1, "", 1), "tRAS", &thresholdsDisabled, {}, {}, false, true);
addConfigButton(KipConfigValue_t4_tRRD, "t4 tRRD", ValueRange(0, 6, 1, "", 1), "tRRD", &thresholdsDisabled, {}, {}, false, true);
u32 tRFCCount = 10;
if (IsErista()) {
tRFCCount = 5;
}
addConfigButton(KipConfigValue_t5_tRFC, "t5 tRFC", ValueRange(0, tRFCCount, 1, "", 1), "tRFC", &thresholdsDisabled, {}, {}, false, true);
addConfigButton(KipConfigValue_t6_tRTW, "t6 tRTW", ValueRange(0, 9, 1, "", 1), "tRTW", &thresholdsDisabled, {}, {}, false, true);
addConfigButton(KipConfigValue_t7_tWTR, "t7 tWTR", ValueRange(0, 9, 1, "", 1), "tWTR", &thresholdsDisabled, {}, {}, false, true);
addConfigButton(KipConfigValue_t8_tREFI, "t8 tREFI", ValueRange(0, 6, 1, "", 1), "tREFI", &thresholdsDisabled, {}, {}, false, true);
std::vector<NamedValue> t6_tRTW_fine_tune = {
NamedValue("-2", 0xFFFFFFFE),
NamedValue("-1", 0xFFFFFFFF),
NamedValue(" 0", 0),
NamedValue("+1", 1),
NamedValue("+2", 2),
};
std::vector<NamedValue> t7_tWTR_fine_tune = {
NamedValue("-3", 0xFFFFFFFD),
NamedValue("-2", 0xFFFFFFFE),
NamedValue("-1", 0xFFFFFFFF),
NamedValue(" 0", 0),
NamedValue("+1", 1),
NamedValue("+2", 2),
NamedValue("+3", 3),
};
addConfigTrackbar(KipConfigValue_t1_tRCD, "t1 tRCD", ValueRange(0, 7, 1));
addConfigTrackbar(KipConfigValue_t2_tRP, "t2 tRP", ValueRange(0, 7, 1));
addConfigTrackbar(KipConfigValue_t3_tRAS, "t3 tRAS", ValueRange(0, 9, 1));
addConfigTrackbar(KipConfigValue_t4_tRRD, "t4 tRRD", ValueRange(0, 6, 1));
addConfigTrackbar(KipConfigValue_t5_tRFC, "t5 tRFC", ValueRange(0, IsErista() ? 5u : 10u, 1));
addConfigTrackbar(KipConfigValue_t6_tRTW, "t6 tRTW", ValueRange(0, 9, 1));
addConfigTrackbar(KipConfigValue_t7_tWTR, "t7 tWTR", ValueRange(0, 9, 1));
addConfigTrackbar(KipConfigValue_t8_tREFI, "t8 tREFI", ValueRange(0, 6, 1));
/* Yes this is duplicated code, yes I don't care. */
std::vector<NamedValue> timingTbreakFreqs = {
@@ -1101,13 +1187,18 @@ protected:
nv.name = formatMemClockKhzLabel(nv.value, unit);
}
ValueThresholds thresholdsDisabled(0, 0);
this->listElement->addItem(new tsl::elm::CategoryHeader("Advanced"));
addConfigButton(KipConfigValue_timingEmcTbreak, "RAM-Timing tBreak", ValueRange(0, 1, 1, "", 1), "tBreak", &thresholdsDisabled, {}, timingTbreakFreqs, false, true);
addConfigButton(KipConfigValue_low_t6_tRTW, "Low t6 tRTW", ValueRange(0, 10, 1, "", 1), "low tRTW", &thresholdsDisabled, {}, {}, false, true );
addConfigButton(KipConfigValue_low_t7_tWTR, "Low t7 tWTR", ValueRange(0, 10, 1, "", 1), "low tWTR", &thresholdsDisabled, {}, {}, false, true );
addConfigButton(KipConfigValue_t2_tRP_cap, "1333WL t2 RP Cap", ValueRange(0, 8, 1, "", 1), "tRP Cap", &thresholdsDisabled, {}, {}, false, true );
addConfigButton(KipConfigValue_t6_tRTW_fine_tune, "t6 tRTW Fine Tune", ValueRange(0, 4, 1, "", 0), "tRTW Fine Tune", &thresholdsDisabled, {}, t6_tRTW_fine_tune, false, true);
addConfigButton(KipConfigValue_t7_tWTR_fine_tune, "t7 tWTR Fine Tune", ValueRange(0, 6, 1, "", 0), "tWTR Fine Tune", &thresholdsDisabled, {}, t7_tWTR_fine_tune, false, true);
addConfigTrackbar(KipConfigValue_low_t6_tRTW, "Low t6 tRTW", ValueRange(0, 9, 1));
addConfigTrackbar(KipConfigValue_low_t7_tWTR, "Low t7 tWTR", ValueRange(0, 9, 1));
addConfigTrackbar(KipConfigValue_t2_tRP_cap, "1333WL t2 RP Cap", ValueRange(0, 8, 1));
addMappedConfigTrackbar(KipConfigValue_t6_tRTW_fine_tune, "t6 tRTW Fine Tune",
{0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u},
{"-2", "-1", " 0", "+1", "+2"});
addMappedConfigTrackbar(KipConfigValue_t7_tWTR_fine_tune, "t7 tWTR Fine Tune",
{0xFFFFFFFDu, 0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u, 3u},
{"-3", "-2", "-1", " 0", "+1", "+2", "+3"});
}
};
@@ -1275,7 +1366,7 @@ protected:
FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc);
return false;
}
sendKipData();
shouldSaveKip = true;
this->lastContextUpdate = armGetSystemTick();
return true;
},
@@ -1335,7 +1426,7 @@ protected:
FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc);
return false;
}
sendKipData();
shouldSaveKip = true;
this->lastContextUpdate = armGetSystemTick();
return true;
},
@@ -1384,6 +1475,90 @@ protected:
this->listElement->addItem(new tsl::elm::CategoryHeader("CPU Settings"));
if(IsMariko()) {
addConfigTrackbar(KipConfigValue_marikoCpuUVLow, "CPU Low UV", ValueRange(0, 8, 1));
addConfigTrackbar(KipConfigValue_marikoCpuUVHigh, "CPU High UV", ValueRange(0, 12, 1));
std::vector<NamedValue> marikoTableConf = {
// NamedValue("Auto", 0),
NamedValue("Default", 1),
NamedValue("1581MHz Tbreak", 2),
NamedValue("1683MHz Tbreak", 3),
NamedValue("Extreme UV Table", 4)
};
addConfigButton(
KipConfigValue_tableConf,
"CPU UV Table",
ValueRange(0, 12, 1, "", 0),
"CPU UV Table",
&thresholdsDisabled,
{},
marikoTableConf,
false,
true
);
addConfigButton(
KipConfigValue_marikoCpuLowVmin,
"CPU Low VMIN",
ValueRange(550, 750, 5, "mV", 1),
"CPU VMIN",
&thresholdsDisabled,
{},
{},
false,
true
);
addConfigButton(
KipConfigValue_marikoCpuHighVmin,
"CPU High VMIN",
ValueRange(650, 900, 5, "mV", 1),
"CPU VMIN",
&thresholdsDisabled,
{},
{},
false,
true
);
ValueThresholds mCpuVoltThresholds(1160, 1180);
addConfigButton(
KipConfigValue_marikoCpuMaxVolt,
"CPU Max Voltage",
ValueRange(1000, 1200, 5, "mV", 1),
"CPU Max Voltage",
&mCpuVoltThresholds,
{},
{},
false,
true
);
std::vector<NamedValue> maxClkOptions = {
NamedValue("1963 MHz", 1963500),
NamedValue("2091 MHz", 2091000),
NamedValue("2193 MHz", 2193000),
NamedValue("2295 MHz", 2295000),
NamedValue("2397 MHz", 2397000),
NamedValue("2499 MHz", 2499000),
NamedValue("2601 MHz", 2601000),
NamedValue("2703 MHz", 2703000),
};
addConfigButton(
KipConfigValue_marikoCpuMaxClock,
"CPU Max Clock",
ValueRange(0, 0, 1, "", 1),
"CPU Max Clock",
this->configList->values[KipConfigValue_marikoCpuUVHigh] ? &mCpuClockThresholdsUV : &mCpuClockThresholds,
{},
maxClkOptions,
false,
true
);
std::vector<NamedValue> ClkOptions = {
NamedValue("1963 MHz", 1963500),
NamedValue("2091 MHz", 2091000),
@@ -1407,41 +1582,10 @@ protected:
true
);
} else {
std::vector<NamedValue> ClkOptionsE = {
NamedValue("1785 MHz", 1785000),
NamedValue("1887 MHz", 1887000),
NamedValue("1989 MHz", 1989000),
NamedValue("2091 MHz", 2091000),
NamedValue("2193 MHz", 2193000),
NamedValue("2295 MHz", 2295000),
NamedValue("2397 MHz", 2397000),
};
addConfigButton(
KipConfigValue_eristaCpuBoostClock,
"CPU Boost Clock",
ValueRange(0, 0, 1, "", 1),
"CPU Boost Clock",
this->configList->values[KipConfigValue_eristaCpuUV] ? &eCpuClockThresholdsUV : &eCpuClockThresholds,
{},
ClkOptionsE,
false,
true
);
}
if(IsErista()) {
addConfigButton(
KipConfigValue_eristaCpuUV,
"CPU UV",
ValueRange(0, 5, 1, "", 1),
"CPU UV",
&thresholdsDisabled,
{},
{},
false,
true
);
addConfigTrackbar(KipConfigValue_eristaCpuUV, "CPU UV", ValueRange(0, 5, 1));
addConfigToggle(KipConfigValue_eristaCpuUnlock, "CPU Unlock", true);
addConfigButton(
KipConfigValue_eristaCpuVmin,
"CPU VMIN",
@@ -1487,112 +1631,29 @@ protected:
maxClkOptions,
false
);
} else {
std::vector<NamedValue> marikoTableConf = {
// NamedValue("Auto", 0),
NamedValue("Default", 1),
NamedValue("1581MHz Tbreak", 2),
NamedValue("1683MHz Tbreak", 3),
NamedValue("Extreme UV Table", 4)
};
addConfigButton(
KipConfigValue_tableConf,
"CPU UV Table",
ValueRange(0, 12, 1, "", 0),
"CPU UV Table",
&thresholdsDisabled,
{},
marikoTableConf,
false,
true
);
addConfigButton(
KipConfigValue_marikoCpuUVLow,
"CPU Low UV",
ValueRange(0, 8, 1, "", 1),
"CPU Low UV",
&thresholdsDisabled,
{},
{},
false,
true
);
addConfigButton(
KipConfigValue_marikoCpuUVHigh,
"CPU High UV",
ValueRange(0, 12, 1, "", 1),
"CPU High UV",
&thresholdsDisabled,
{},
{},
false,
true
);
std::vector<NamedValue> maxClkOptions = {
NamedValue("1963 MHz", 1963500),
std::vector<NamedValue> ClkOptionsE = {
NamedValue("1785 MHz", 1785000),
NamedValue("1887 MHz", 1887000),
NamedValue("1989 MHz", 1989000),
NamedValue("2091 MHz", 2091000),
NamedValue("2193 MHz", 2193000),
NamedValue("2295 MHz", 2295000),
NamedValue("2397 MHz", 2397000),
NamedValue("2499 MHz", 2499000),
NamedValue("2601 MHz", 2601000),
NamedValue("2703 MHz", 2703000),
};
addConfigButton(
KipConfigValue_marikoCpuMaxClock,
"CPU Max Clock",
KipConfigValue_eristaCpuBoostClock,
"CPU Boost Clock",
ValueRange(0, 0, 1, "", 1),
"CPU Max Clock",
this->configList->values[KipConfigValue_marikoCpuUVHigh] ? &mCpuClockThresholdsUV : &mCpuClockThresholds,
"CPU Boost Clock",
this->configList->values[KipConfigValue_eristaCpuUV] ? &eCpuClockThresholdsUV : &eCpuClockThresholds,
{},
maxClkOptions,
ClkOptionsE,
false,
true
);
addConfigButton(
KipConfigValue_marikoCpuLowVmin,
"CPU Low VMIN",
ValueRange(550, 750, 5, "mV", 1),
"CPU VMIN",
&thresholdsDisabled,
{},
{},
false,
true
);
addConfigButton(
KipConfigValue_marikoCpuHighVmin,
"CPU High VMIN",
ValueRange(650, 900, 5, "mV", 1),
"CPU VMIN",
&thresholdsDisabled,
{},
{},
false,
true
);
ValueThresholds mCpuVoltThresholds(1160, 1180);
addConfigButton(
KipConfigValue_marikoCpuMaxVolt,
"CPU Max Voltage",
ValueRange(1000, 1200, 5, "mV", 1),
"CPU Max Voltage",
&mCpuVoltThresholds,
{},
{},
false,
true
);
addConfigToggle(HocClkConfigValue_OverwriteBoostMode, nullptr);
}
addConfigToggle(HocClkConfigValue_OverwriteBoostMode, nullptr);
}
};
@@ -1602,6 +1663,8 @@ public:
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
this->listElement->addItem(new tsl::elm::CategoryHeader("RAM Frequency Editor"));
ValueThresholds thresholdsDisabled(0, 0);
@@ -1672,6 +1735,8 @@ public:
protected:
void listUI() override {
Result rc = hocclkIpcGetConfigValues(this->configList);
if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; }
ValueThresholds thresholdsDisabled(0, 0);
std::vector<NamedValue> noNamedValues = {};
@@ -1825,6 +1890,7 @@ protected:
NamedValue("-50 mV", 0xFFFFFFCE),
NamedValue("-45 mV", 0xFFFFFFD3),
NamedValue("-40 mV", 0xFFFFFFD8),
NamedValue("-35 mV", 0xFFFFFFDD),
NamedValue("-30 mV", 0xFFFFFFE2),
NamedValue("-25 mV", 0xFFFFFFE7),
NamedValue("-20 mV", 0xFFFFFFEC),
@@ -2019,9 +2085,9 @@ protected:
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString("\uE150 Setting GPU Clocks past", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
renderer->drawString("1075MHz without UV, 1152MHz on SLT", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
renderer->drawString("or 1228MHz on HiOPT can cause ", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
renderer->drawString("permanent damage to your Switch!", false, x + 20, y + 90, 18, tsl::style::color::ColorText);
renderer->drawString("1228MHz without a proper undervolt", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
renderer->drawString("can cause degradation or damage", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
renderer->drawString("to your console!", false, x + 20, y + 90, 18, tsl::style::color::ColorText);
renderer->drawString("Proceed at your own risk!", false, x + 20, y + 110, 18, tsl::style::color::ColorText);
});
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 130);
@@ -2041,9 +2107,9 @@ protected:
addConfigButton(KipConfigValue_g_volt_921600, "921.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_998400, "998.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_1075200, "1075.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false, true);
if(this->configList->values[KipConfigValue_marikoGpuUV] >= GPUUVLevel_SLT)
if(this->configList->values[KipConfigValue_marikoGpuUV] >= GPUUVLevel_HiOPT15)
addConfigButton(KipConfigValue_g_volt_1152000, "1152.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false, true);
if(this->configList->values[KipConfigValue_marikoGpuUV] >= GPUUVLevel_HiOPT) {
if(this->configList->values[KipConfigValue_marikoGpuUV] >= GPUUVLevel_HighUV) {
addConfigButton(KipConfigValue_g_volt_1228800, "1228.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_1267200, "1267.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_1305600, "1305.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false, true);
@@ -2059,9 +2125,9 @@ protected:
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString("\uE150 Setting GPU Clocks past", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
renderer->drawString("921MHz without UV and 960MHz on", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
renderer->drawString("SLT or HiOPT can cause ", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
renderer->drawString("permanent damage to your Switch!", false, x + 20, y + 90, 18, tsl::style::color::ColorText);
renderer->drawString("921MHz without a proper undervolt", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
renderer->drawString("can cause degradation or damage", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
renderer->drawString("to your console!", false, x + 20, y + 90, 18, tsl::style::color::ColorText);
renderer->drawString("Proceed at your own risk!", false, x + 20, y + 110, 18, tsl::style::color::ColorText);
});
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 130);
@@ -2090,9 +2156,9 @@ protected:
addConfigButton(KipConfigValue_g_volt_e_844800, "844.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_e_883200, "883.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_e_921600, "921.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts, false, true);
if(this->configList->values[KipConfigValue_eristaGpuUV] >= GPUUVLevel_SLT)
if(this->configList->values[KipConfigValue_eristaGpuUV] >= GPUUVLevel_HiOPT15)
addConfigButton(KipConfigValue_g_volt_e_960000, "960.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts, false, true);
if(this->configList->values[KipConfigValue_eristaGpuUV] >= GPUUVLevel_HiOPT) {
if(this->configList->values[KipConfigValue_eristaGpuUV] >= GPUUVLevel_HighUV) {
addConfigButton(KipConfigValue_g_volt_e_998400, "998.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_e_1036800, "1036.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts_noAuto, false, true);
addConfigButton(KipConfigValue_g_volt_e_1075200, "1075.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts_noAuto, false, true);

View File

@@ -18,6 +18,7 @@
#pragma once
#include "../../ipc.h"
#include "base_menu_gui.h"
#include <initializer_list>
#include <set>
#include <unordered_map>
#include <string>
@@ -44,6 +45,10 @@ protected:
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,
std::vector<u32> vals,
std::initializer_list<std::string> names, bool kip = true);
void addConfigButton(HocClkConfigValue configVal,
const char* altName,
const ValueRange& range,
@@ -72,4 +77,5 @@ protected:
tsl::elm::ToggleListItem* enabledToggle;
u8 frameCounter = 60;
bool shouldSaveKip = false;
};

View File

@@ -31,6 +31,14 @@
"highest_cpu_id": 3
}
}, {
"type": "map",
"value": {
"address": "0x70000000",
"is_ro": false,
"size": "0x00001000",
"is_io": true
}
}, {
"type": "map",
"value": {
"address": "0x60006000",

View File

@@ -44,7 +44,7 @@
#include "../file_utils.hpp"
namespace board {
u64 clkVirtAddr, dsiVirtAddr;
u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr;
HocClkSocType gSocType;
u8 gDramID;
@@ -153,6 +153,9 @@ namespace board {
rc = QueryMemoryMapping(&dsiVirtAddr, 0x54300000, 0x40000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (dsi)");
rc = QueryMemoryMapping(&apbVirtAddr, 0x70000000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (apb)");
display::DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr, .isLite = (GetConsoleType() == HocClkConsoleType_Hoag), .isRetroSUPER = integrations::GetRETROSuperStatus()};
display::Initialize(&cfg);
@@ -175,6 +178,7 @@ namespace board {
max17050Exit();
tmp451Exit();
display::Shutdown();
ExitLoad();
@@ -185,7 +189,6 @@ namespace board {
rgltrExit();
batteryInfoExit();
pmdmntExit();
display::Shutdown();
nvExit();
}

View File

@@ -32,7 +32,7 @@
#include <pwm.h>
#include "board.hpp"
#include "../soctherm.hpp"
#include "bq24193.hpp"
namespace board {
s32 GetTemperatureMilli(HocClkThermalSensor sensor) {
@@ -82,6 +82,11 @@ namespace board {
}
case HocClkThermalSensor_PLLX: {
millis = temps.pllx;
break;
}
case HocClkThermalSensor_BQ24193: {
millis = bq24193::getBQTemp();
break;
}
default: {
ASSERT_ENUM_VALID(HocClkThermalSensor, sensor);

View File

@@ -1,6 +1,8 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
*
* Copyright (c) B3711
*
* 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.
@@ -30,6 +32,7 @@
namespace board {
GpuVoltData voltData = {};
u32 cpuVoltTable[32] = {}; // 32LUT
u64 cldvfs;
CpuDfllData cachedTune;
@@ -371,14 +374,25 @@ namespace board {
/* Assuming mariko. */
const u32 vmax = 800;
constexpr u32 VoltageTableOffset = 312;
if (!std::memcmp(&buffer[index + VoltageTableOffset], &vmax, sizeof(vmax))) {
std::memcpy(voltData.voltTable, &buffer[index + VoltageTableOffset], sizeof(voltData.voltTable));
voltData.voltTableAddress = base + memoryInfo.addr + VoltageTableOffset + index;
constexpr u32 GpuVoltageTableOffset = 312;
if (!std::memcmp(&buffer[index + GpuVoltageTableOffset], &vmax, sizeof(vmax))) {
std::memcpy(voltData.voltTable, &buffer[index + GpuVoltageTableOffset], sizeof(voltData.voltTable));
voltData.voltTableAddress = base + memoryInfo.addr + GpuVoltageTableOffset + index;
}
constexpr u32 CpuVoltageTableOffset = 0xB8;
std::memcpy(cpuVoltTable, &buffer[index + CpuVoltageTableOffset], sizeof(cpuVoltTable)); // TODO: verify the CPU table
svcCloseHandle(handle);
handle = INVALID_HANDLE;
for(int i = 0; i < (int)std::size(cpuVoltTable); ++i) {
fileUtils::LogLine("[dvfs] cpu volt %d: %u mV", i, cpuVoltTable[i]);
}
for(int i = 0; i < (int)std::size(voltData.voltTable); ++i) {
fileUtils::LogLine("[dvfs] gpu volt %d: %u mV", i, voltData.voltTable[i]);
}
return;
}
}
@@ -429,17 +443,34 @@ namespace board {
static const u32 gpuVoltArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, };
if (freqMhz <= 1600) {
return 0;
if (freqMhz <= 1600) return 0;
if (bracket >= std::size(ramTable)) bracket = 0;
u32 bracketStart = ramTable[bracket][0];
u32 rampStartVolt = (bracket == 0) ? 535 : 525;
u32 rampSpan = 590 - rampStartVolt;
if (freqMhz >= 1633 && freqMhz < bracketStart) {
u32 raw = rampStartVolt + ((freqMhz - 1633) * rampSpan) / (bracketStart - 1633);
u32 volt = ((raw + 2) / 5) * 5;
if (volt < rampStartVolt) volt = rampStartVolt;
if (volt > 590) volt = 590;
return volt;
}
u32 baseVolt = gpuVoltArray[std::size(gpuVoltArray) - 1];
for (u32 i = 0; i < std::size(gpuVoltArray); ++i) {
if (freqMhz <= ramTable[bracket][i]) {
return gpuVoltArray[i];
baseVolt = gpuVoltArray[i];
break;
}
}
return gpuVoltArray[std::size(gpuVoltArray) - 1];
return baseVolt;
}
}
}

View File

@@ -26,8 +26,6 @@ namespace board {
u64 voltTableAddress;
u32 ramVmin;
};
/* TODO: Find out what component this actually targets. */
struct UnkRegulator {
u32 voltageMin;
u32 voltageStep;

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* Copyright (c) CtCaer
*
* 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 "bq24193.hpp"
namespace bq24193 {
static u8 bq24193_get_reg(u8 reg)
{
u8 out;
I2cRead_OutU8(I2cDevice_Bq24193, reg, &out);
return out;
}
u8 getBQTemp() {
u8 regVal = bq24193_get_reg(BQ24193_FaultReg);
return regVal & BQ24193_FAULT_THERM_MASK;
}
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* Copyright (c) CtCaer
*
* 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 "board.hpp"
#include <i2c.h>
namespace bq24193 {
#define BQ24193_I2C_ADDR 0x6B
// REG 0 masks.
#define BQ24193_INCONFIG_INLIMIT_MASK (7<<0)
#define BQ24193_INCONFIG_VINDPM_MASK 0x78
#define BQ24193_INCONFIG_HIZ_EN_MASK (1<<7)
// REG 1 masks.
#define BQ24193_PORCONFIG_BOOST_MASK (1<<0)
#define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1) // 3000uV HOS default.
#define BQ24193_PORCONFIG_CHGCONFIG_MASK (3<<4)
#define BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN (1<<4)
#define BQ24193_PORCONFIG_I2CWATCHDOG_MASK (1<<6)
#define BQ24193_PORCONFIG_RESET_MASK (1<<7)
// REG 2 masks.
#define BQ24193_CHRGCURR_20PCT_MASK (1<<0)
#define BQ24193_CHRGCURR_ICHG_MASK 0xFC
// REG 3 masks.
#define BQ24193_PRECHRG_ITERM 0x0F
#define BQ24193_PRECHRG_IPRECHG 0xF0
// REG 4 masks.
#define BQ24193_CHRGVOLT_VTHRES (1<<0)
#define BQ24193_CHRGVOLT_BATTLOW (1<<1)
#define BQ24193_CHRGVOLT_VREG 0xFC
// REG 5 masks.
#define BQ24193_CHRGTERM_ISET_MASK (1<<0)
#define BQ24193_CHRGTERM_CHGTIMER_MASK (3<<1)
#define BQ24193_CHRGTERM_ENTIMER_MASK (1<<3)
#define BQ24193_CHRGTERM_WATCHDOG_MASK (3<<4)
#define BQ24193_CHRGTERM_TERM_ST_MASK (1<<6)
#define BQ24193_CHRGTERM_TERM_EN_MASK (1<<7)
// REG 6 masks.
#define BQ24193_IRTHERMAL_THERM_MASK (3<<0)
#define BQ24193_IRTHERMAL_VCLAMP_MASK (7<<2)
#define BQ24193_IRTHERMAL_BATTCOMP_MASK (7<<5)
// REG 7 masks.
#define BQ24193_MISC_INT_MASK (3<<0)
#define BQ24193_MISC_VSET_MASK (1<<4)
#define BQ24193_MISC_BATFET_DI_MASK (1<<5)
#define BQ24193_MISC_TMR2X_EN_MASK (1<<6)
#define BQ24193_MISC_DPDM_EN_MASK (1<<7)
// REG 8 masks.
#define BQ24193_STATUS_VSYS_MASK (1<<0)
#define BQ24193_STATUS_THERM_MASK (1<<1)
#define BQ24193_STATUS_PG_MASK (1<<2)
#define BQ24193_STATUS_DPM_MASK (1<<3)
#define BQ24193_STATUS_CHRG_MASK (3<<4)
#define BQ24193_STATUS_VBUS_MASK (3<<6)
// REG 9 masks.
#define BQ24193_FAULT_THERM_MASK (7<<0)
#define BQ24193_FAULT_BATT_OVP_MASK (1<<3)
#define BQ24193_FAULT_CHARGE_MASK (3<<4)
#define BQ24193_FAULT_BOOST_MASK (1<<6)
#define BQ24193_FAULT_WATCHDOG_MASK (1<<7)
// REG A masks.
#define BQ24193_VENDORPART_DEV_MASK (3<<0)
#define BQ24193_VENDORPART_PN_MASK (7<<3)
enum BQ24193_reg {
BQ24193_InputSource = 0x00,
BQ24193_PORConfig = 0x01,
BQ24193_ChrgCurr = 0x02,
BQ24193_PreChrgTerm = 0x03,
BQ24193_ChrgVolt = 0x04,
BQ24193_ChrgTermTimer = 0x05,
BQ24193_IRCompThermal = 0x06,
BQ24193_Misc = 0x07,
BQ24193_Status = 0x08,
BQ24193_FaultReg = 0x09,
BQ24193_VendorPart = 0x0A,
};
enum BQ24193_reg_prop {
BQ24193_InputVoltageLimit, // REG 0.
BQ24193_InputCurrentLimit, // REG 0.
BQ24193_SystemMinimumVoltage, // REG 1.
BQ24193_FastChargeCurrentLimit, // REG 2.
BQ24193_ChargeVoltageLimit, // REG 4.
BQ24193_RechargeThreshold, // REG 4.
BQ24193_ThermalRegulation, // REG 6.
BQ24193_ChargeStatus, // REG 8.
BQ24193_TempStatus, // REG 9.
BQ24193_DevID, // REG A.
BQ24193_ProductNumber, // REG A.
};
// 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
enum BQ24193_Temp {
BQ24193_Temp_Normal = 0,
BQ24193_Temp_Warm = 2,
BQ24193_Temp_Cool = 3,
BQ24193_Temp_Cold = 5,
BQ24193_Temp_Hot = 6,
};
u8 getBQTemp();
}

View File

@@ -1,132 +1,116 @@
/*
* Copyright (c) Souldbminer
*
* Copyright (c) KazushiMe
*
* 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 "pllmb.hpp"
namespace pllmb {
static const u8 qlin_hw_to_pdiv[17] = {
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 30, 32
};
#define GET_BITS(VAL, HIGH, LOW) ((VAL & ((1UL << (HIGH + 1UL)) - 1UL)) >> LOW)
#define GET_BIT(VAL, BIT) GET_BITS(VAL, BIT, BIT)
enum pdiv_type {
PDIV_QLIN,
PDIV_POW2
};
struct pll_desc_t {
u32 base_offset;
u8 divm_shift;
u8 divm_width;
u8 divn_shift;
u8 divn_width;
u8 divp_shift;
u8 divp_width;
pdiv_type ptype;
};
static const pll_desc_t pll_table[] = {
{ PLLM_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLMB_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLP_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ PLLA_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ PLLU_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ _PLLD_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ PLLX_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLA1_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLDP_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLD2_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLC4_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLRE_BASE, 0, 8, 8, 8, 16, 4, PDIV_QLIN },
{ PLLC_BASE, 0, 8, 10, 8, 20, 5, PDIV_QLIN },
{ PLLC2_BASE, 0, 8, 10, 8, 20, 5, PDIV_QLIN },
{ PLLC3_BASE, 0, 8, 10, 8, 20, 5, PDIV_QLIN },
};
static inline u32 clk_read32(u32 offset)
{
return *(volatile u32 *)(uintptr_t)(board::clkVirtAddr + offset);
static inline volatile u32& REG(uintptr_t addr) {
return *reinterpret_cast<volatile u32*>(addr);
}
static inline u32 extract(u32 val, u8 shift, u8 width)
{
return (val >> shift) & ((1u << width) - 1u);
}
// From jetson nano kernel
typedef enum {
/* divider = 2 */
CLK_PLLX = 5,
CLK_PLLM = 2,
CLK_PLLMB = 37,
/* PLLX & PLLG are backup PLLs for CPU & GPU */
/* divider = 1 */
CLK_CCLK_G = 18, // A57 CPU cluster
CLK_EMC = 36,
} PTO_ID; // PLL Test Output Register ID
static u64 pll_rate_from_desc(const pll_desc_t &pll, u64 osc_hz,
bool undivided)
{
u32 base = clk_read32(pll.base_offset);
u32 divm = extract(base, pll.divm_shift, pll.divm_width);
u32 divn = extract(base, pll.divn_shift, pll.divn_width);
/* See if GM20B clock GPC PLL regs are accessible. */
if (divm == 0 || divn == 0)
return 0;
#define PLLX_MISC0 0xE4
#define PLLM_MISC2 0x9C
u64 vco = osc_hz * divn / divm;
double ptoGetMHz(PTO_ID pto_id, u32 divider = 1, u32 presel_reg = 0, u32 presel_mask = 0) {
u32 pre_val, val, presel_val;
if (undivided)
return vco;
u32 hw_p = extract(base, pll.divp_shift, pll.divp_width);
u32 pdiv;
if (pll.ptype == PDIV_QLIN)
pdiv = (hw_p < 17) ? qlin_hw_to_pdiv[hw_p] : 1;
else
pdiv = 1u << hw_p;
return vco / pdiv;
}
static u64 pll_rate_by_offset(u32 base_offset, u64 osc_hz,
bool undivided)
{
for (const auto &pll : pll_table) {
if (pll.base_offset == base_offset)
return pll_rate_from_desc(pll, osc_hz, undivided);
}
return 0;
}
u64 getRamClockRatePLLMB()
{
u32 clk_src = clk_read32(CLK_SOURCE_EMC);
u32 src = (clk_src >> 29) & 0x7;
u32 div = (clk_src >> 0) & 0xff;
u32 pll_off;
bool undivided = false;
switch (src) {
case EMC_SRC_PLLM:
pll_off = PLLM_BASE;
break;
case EMC_SRC_PLLM_UD:
pll_off = PLLM_BASE;
undivided = true;
break;
case EMC_SRC_PLLMB:
pll_off = PLLMB_BASE;
break;
case EMC_SRC_PLLMB_UD:
pll_off = PLLMB_BASE;
undivided = true;
break;
case EMC_SRC_PLLP:
pll_off = PLLP_BASE;
break;
case EMC_SRC_PLLP_UD:
pll_off = PLLP_BASE;
undivided = true;
break;
case EMC_SRC_PLLC:
pll_off = PLLC_BASE;
break;
case EMC_SRC_CLK_M:
return OSC_HZ;
default:
return 0;
if (presel_reg) {
val = REG(board::clkVirtAddr + presel_reg);
usleep(10);
presel_val = val & presel_mask;
val &= ~presel_mask;
val |= presel_mask;
REG(board::clkVirtAddr + presel_reg) = val;
usleep(10);
}
u64 pll_hz = pll_rate_by_offset(pll_off, OSC_HZ, undivided);
return pll_hz / (div + 2) * 2;
constexpr u32 cycle_count = 16;
pre_val = REG(board::clkVirtAddr + 0x60);
val = BIT(23) | BIT(13) | (cycle_count - 1);
val |= pto_id << 14;
REG(board::clkVirtAddr + 0x60) = val;
usleep(10);
REG(board::clkVirtAddr + 0x60) = val | BIT(10);
usleep(10);
REG(board::clkVirtAddr + 0x60) = val;
usleep(10);
REG(board::clkVirtAddr + 0x60) = val | BIT(9);
usleep(500);
while(REG(board::clkVirtAddr + 0x64) & BIT(31))
;
val = REG(board::clkVirtAddr + 0x64);
val &= 0xFFFFFF;
val *= divider;
double rate_hz = (u64)val * 32768. / cycle_count;
usleep(10);
REG(board::clkVirtAddr + 0x60) = pre_val;
usleep(10);
if (presel_reg) {
val = REG(board::clkVirtAddr + presel_reg);
usleep(10);
val &= ~presel_mask;
val |= presel_val;
REG(board::clkVirtAddr + presel_reg) = val;
usleep(10);
}
return rate_hz;
}
u64 getRamClockRatePLLMB() {
// printf("\n"
// "EMC: %6.1f MHz\n"
// "CCLK_G: %6.1f MHz\n"
// "PLLX: %6.1f MHz\n"
// "PLLM: %6.1f MHz\n"
// "PLLMB: %6.1f MHz\n",
// ptoGetMHz(CLK_EMC),
// ptoGetMHz(CLK_CCLK_G),
// ptoGetMHz(CLK_PLLX, 2, PLLX_MISC0, BIT(22)),
// ptoGetMHz(CLK_PLLM, 2, PLLM_MISC2, BIT(8)),
// ptoGetMHz(CLK_PLLMB, 2, PLLM_MISC2, BIT(9))
// );
u32 pllmb = ptoGetMHz(CLK_PLLMB, 2, PLLM_MISC2, BIT(9));
u32 pllm = ptoGetMHz(CLK_PLLM, 2, PLLM_MISC2, BIT(8));
return pllmb == 0 ? pllm : pllmb; // pllmb is zeroed out at times, fallback to pllm
}
}

View File

@@ -1,3 +1,22 @@
/*
* Copyright (c) Souldbminer
*
* Copyright (c) KazushiMe
*
* 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 <cstdint>
#include <switch.h>
@@ -6,16 +25,5 @@
#include <registers.h>
namespace pllmb {
typedef enum PLLSource {
EMC_SRC_PLLM = 0,
EMC_SRC_PLLC = 1,
EMC_SRC_PLLP = 2,
EMC_SRC_CLK_M = 3,
EMC_SRC_PLLM_UD = 4,
EMC_SRC_PLLMB_UD = 5,
EMC_SRC_PLLMB = 6,
EMC_SRC_PLLP_UD = 7
} PLLSource;
u64 getRamClockRatePLLMB();
}

View File

@@ -286,7 +286,7 @@ namespace clockManager {
if (!targetHz) {
targetHz = config::GetAutoClockHz(gContext.applicationId, HocClkModule_GPU, gContext.profile, false);
if (!targetHz) {
targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HocClkModule_GPU, gContext.profile, false);
targetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_GPU, gContext.profile, false);
}
}
u32 maxHz = GetMaxAllowedHz(HocClkModule_GPU, gContext.profile);
@@ -357,7 +357,7 @@ namespace clockManager {
if (!targetHz) {
targetHz = config::GetAutoClockHz(gContext.applicationId, (HocClkModule)module, gContext.profile, returnRaw);
if (!targetHz)
targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, (HocClkModule)module, gContext.profile, returnRaw);
targetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, (HocClkModule)module, gContext.profile, returnRaw);
}
if (module == HocClkModule_Governor) {
@@ -528,7 +528,7 @@ namespace clockManager {
if (!targetHz) {
targetHz = config::GetAutoClockHz(gContext.applicationId, HocClkModule_Display, gContext.profile, true);
if (!targetHz)
targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HocClkModule_Display, gContext.profile, true);
targetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Display, gContext.profile, true);
}
if (board::GetConsoleType() != HocClkConsoleType_Hoag)

View File

@@ -17,6 +17,7 @@
#include "governor.hpp"
#include "process_management.hpp"
#include <hocclk/clock_manager.h>
namespace governor {
#define POLL_NS 5'000'000 // 5 ms governor poll rate
@@ -43,7 +44,7 @@ namespace governor {
if (!tempTargetHz) {
tempTargetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HocClkModule_Governor, clockManager::gContext.profile, true);
if (!tempTargetHz)
tempTargetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HocClkModule_Governor, clockManager::gContext.profile, true);
tempTargetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Governor, clockManager::gContext.profile, true);
}
auto resolve = [](u8 app, u8 temp) -> u8 {
@@ -107,7 +108,7 @@ namespace governor {
clockManager::gContext.profile, false);
if (!hz)
hz = config::GetAutoClockHz(
GLOBAL_PROFILE_ID, module,
HOCCLK_GLOBAL_PROFILE_TID, module,
clockManager::gContext.profile, false);
return hz;
}
@@ -295,7 +296,7 @@ namespace governor {
if (!targetHz) {
targetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HocClkModule_Display, clockManager::gContext.profile, false);
if (!targetHz)
targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HocClkModule_Display, clockManager::gContext.profile, false);
targetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Display, clockManager::gContext.profile, false);
}
u8 maxDisplay;

View File

@@ -69,6 +69,7 @@ namespace kip {
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));
CUST_WRITE_FIELD_BATCH(&table, marikoSocVmax, config::GetConfigValue(KipConfigValue_marikoSocVmax));
CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, config::GetConfigValue(KipConfigValue_t1_tRCD));
CUST_WRITE_FIELD_BATCH(&table, t2_tRP, config::GetConfigValue(KipConfigValue_t2_tRP));
@@ -208,6 +209,7 @@ namespace kip {
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);
configValues.values[KipConfigValue_marikoSocVmax] = cust_get_marikoSocVmax(&table);
configValues.values[KipConfigValue_t1_tRCD] = cust_get_tRCD(&table);
configValues.values[KipConfigValue_t2_tRP] = cust_get_tRP(&table);

View File

@@ -44,6 +44,8 @@ namespace kip {
u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt;
u32 emcDvbShift;
u32 marikoSocVmax;
// advanced config
u32 t1_tRCD;
u32 t2_tRP;
@@ -266,6 +268,7 @@ namespace kip {
static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); }
static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); }
static inline bool cust_set_marikoCpuMaxClock(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxClock, v); }
static inline bool cust_set_marikoSocVmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoSocVmax, v); }
/* GPU VOLT ARRAY HELPERS */
static inline bool cust_set_erista_gpu_volt(const char* p, int idx, u32 v) {
@@ -354,6 +357,7 @@ namespace kip {
static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); }
static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); }
static inline u32 cust_get_marikoCpuMaxClock(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxClock); }
static inline u32 cust_get_marikoSocVmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoSocVmax); }
static inline u32 cust_get_erista_gpu_volt(const CustomizeTable* t, int idx) {
if (!t || idx < 0 || idx >= 27) return 0;

View File

@@ -1,7 +1,7 @@
#!/bin/sh
SRC="Source/Atmosphere/stratosphere/loader/source/oc"
DEST="build/stratosphere/loader/source/oc"
SRC="Source/Atmosphere/stratosphere/loader/"
DEST="build/stratosphere/loader/"
mkdir -p "dist/atmosphere/kips/"
mkdir -p "$DEST"

16
dist/README.md vendored
View File

@@ -78,21 +78,21 @@ Refer to COMPILATION.md
---
## Clock table
### MEM clocks
### MEM clocks (mhz)
* 3200 → max on mariko, JEDEC.
* 2933 → JEDEC.
* 2666 → JEDEC.
* 2400 → max on erista, JEDEC.
* 2133 → mariko safe max (4266 Modules), JEDEC.
* 1996 → JEDEC.
* 1866 → mariko safe max (3733 Modules), JEDEC.
* 2133 → Mariko JEDEC standard max (4266 Modules)
* 1996 → JEDEC standard
* 1866 → Mariko JEDEC standard max (3733 Modules)
* 1600 → official docked, boost mode, erista safe max, JEDEC.
* 1331 → official handheld, JEDEC.
* 1065
* 800
* 665
### CPU clocks
### CPU clocks (mhz)
* 2703 → mariko absolute max, dangerous
* 2601 → unsafe
* 2499
@@ -115,16 +115,16 @@ Refer to COMPILATION.md
* 714
* 612 → sleep mode
### GPU clocks
### GPU clocks (mhz)
* 1536 → absolute max clock on mariko. very dangerous
* 1459
* 1382
* 1305
* 1267 → NVIDIA T214 rating
* 1267 → NVIDIA T214(mariko) rating
* 1228 → mariko HiOPT safe clock
* 1152 → mariko SLT max clock
* 1075 → mariko no UV max clock. absolute max clock on erista. very dangerous
* 998 → NVIDIA T210 rating
* 998 → NVIDIA T210 (erista) rating
* 960 (erista only) → erista slt/hiopt safe max clock
* 921 → erista no UV max clock
* 844

Binary file not shown.

View File

@@ -2,140 +2,140 @@
"Information": "Información",
"IDDQ:": "IDDQ:",
"Module: ": "Módulo:",
"sys-dock status:": "estado del sys-dock:",
"sys-dock status:": "Estado de sys-dock:",
"SaltyNX status:": "Estado de SaltyNX:",
"RR Display status:": "Estado de visualización RR:",
"Wafer Position:": "Posición de la oblea:",
"RR Display status:": "Estado de pantalla RR:",
"Wafer Position:": "Posición del wafer:",
"Credits": "Créditos",
"Developers": "Desarrolladores",
"Contributors": "Colaboradores",
"Testers": "Probadores",
"Special Thanks": "agradecimiento especial",
"Testers": "Testers",
"Special Thanks": "Agradecimientos especiales",
"Unknown": "Desconocido",
"Installed": "Instalado",
"Not Installed": "No instalado",
"X: %u Y: %u": "X: %u Y: %u",
"THE BEER-WARE LICENSE": "LA LICENCIA DE CERVEZA",
"THE BEER-WARE LICENSE": "LICENCIA BEER-WARE",
"Default": "Predeterminado",
"Do Not Override": "No anular",
"Disabled": "Discapacitado",
"Enabled": "Habilitado",
"Do Not Override": "No sobrescribir",
"Disabled": "Desactivado",
"Enabled": "Activado",
" \\ue0e3 Reset": "\\ue0e3 Restablecer",
"Display": "Pantalla",
"Application changed\\n\\n": "Aplicación modificada\\n\\n",
"The running application changed\\n\\n": "La aplicación en ejecución cambió\\n\\n",
"while editing was going on.": "mientras se realizaba la edición.",
"Board": "tablero",
"Application changed\\n\\n": "Aplicación cambiada\\n\\n",
"The running application changed\\n\\n": "La aplicación en ejecución ha cambiado\\n\\n",
"while editing was going on.": "mientras se estaba editando.",
"Board": "Placa",
"%u.%u%u mV": "%u.%u%u mV",
"Could not connect to hoc-clk sysmodule.\\n\\n": "No se pudo conectar al módulo del sistema hoc-clk.\\n\\n",
"Please make sure everything is\\n\\n": "Por favor asegúrese de que todo esté\\n\\n",
"correctly installed and enabled.": "correctamente instalado y habilitado.",
"Fatal error": "error fatal",
"Temporary Overrides ": "Anulaciones temporales",
"Sleep Mode": "Modo de suspensión",
"Stock": "Valores",
"Dev OC": "Desarrollador OC",
"Boost Mode": "Modo de impulso",
"Could not connect to hoc-clk sysmodule.\\n\\n": "No se pudo conectar al sysmodule hoc-clk.\\n\\n",
"Please make sure everything is\\n\\n": "Asegúrate de que todo esté\\n\\n",
"correctly installed and enabled.": "correctamente instalado y activado.",
"Fatal error": "Error fatal",
"Temporary Overrides ": "Ajustes temporales",
"Sleep Mode": "Modo reposo",
"Stock": "Valores de fábrica",
"Dev OC": "OC de desarrollo",
"Boost Mode": "Modo boost",
"Safe Max": "Máximo seguro",
"Unsafe Max": "Máximo inseguro",
"Unsafe Max": "Máximo no seguro",
"Absolute Max": "Máximo absoluto",
"Handheld Safe Max": "Caja fuerte de mano máx.",
"Enable": "Habilitar",
"Handheld Safe Max": "Máximo seguro en portátil",
"Enable": "Activar",
"Edit App Profile": "Editar perfil de aplicación",
"Edit Global Profile": "Editar perfil global",
"Temporary Overrides": "Anulaciones temporales",
"Temporary Overrides": "Ajustes temporales",
"Settings": "Configuración",
"About": "Acerca de",
"Compiling with minimal features": "Compilando con características mínimas",
"General Settings": "Configuraciones generales",
"Governor Settings": "Configuración del gobernador",
"Safety Settings": "Configuraciones de seguridad",
"Save KIP Settings": "Guardar configuración de KIP",
"Compiling with minimal features": "Compilado con funciones mínimas",
"General Settings": "Configuración general",
"Governor Settings": "Configuración del governor",
"Safety Settings": "Configuración de seguridad",
"Save KIP Settings": "Guardar configuración KIP",
"RAM Settings": "Configuración de RAM",
"CPU Settings": "Configuración de la CPU",
"CPU Settings": "Configuración de CPU",
"GPU Settings": "Configuración de GPU",
"Display Settings": "Configuración de pantalla",
"Experimental": "Experimental",
"GPU Scheduling Override Method": "Método de anulación de programación de GPU",
"can be dangerous and may cause": "puede ser peligroso y puede causar",
"damage to your battery or charger!": "¡Daños a su batería o cargador!",
"Charge Current Override": "Anulación de corriente de carga",
"GPU Scheduling Override Method": "Método de sobrescritura del scheduling de GPU",
"can be dangerous and may cause": "puede ser peligroso y causar",
"damage to your battery or charger!": "daños a la batería o al cargador.",
"Charge Current Override": "Sobrescritura de corriente de carga",
"RAM Voltage Display Mode": "Modo de visualización de voltaje de RAM",
"Polling Interval": "Intervalo de sondeo",
"CPU Governor Minimum Frequency": "Frecuencia mínima del gobernador de CPU",
"refresh rates may cause stress": "Las frecuencias de actualización pueden causar estrés.",
"or damage to your display! ": "o daños a su pantalla!",
"Proceed at your own risk!": Continúe bajo su propio riesgo!",
"Max Handheld Display": "Pantalla portátil máxima",
"Display Clock": "Reloj de pantalla",
"Official Rating": "Calificación oficial",
"CPU Governor Minimum Frequency": "Frecuencia mínima del governor de CPU",
"refresh rates may cause stress": "las tasas de refresco pueden causar estrés",
"or damage to your display! ": "o dañar la pantalla.",
"Proceed at your own risk!": Úsalo bajo tu propio riesgo!",
"Max Handheld Display": "Frecuencia máxima de pantalla en portátil",
"Display Clock": "Frecuencia de pantalla",
"Official Rating": "Valor oficial",
"TDP Threshold": "Umbral de TDP",
"Power": "poder",
"Thermal Throttle Limit": "Límite del acelerador térmico",
"HP Mode": "Modo HP",
"Power": "Potencia",
"Thermal Throttle Limit": "Límite de thermal throttling",
"HP Mode": "Modo alto rendimiento",
"Default (Mariko)": "Predeterminado (Mariko)",
"Default (Erista)": "Predeterminado (Erista)",
"Rating": "Calificación",
"Safe Max (Mariko)": "Max seguro (Mariko)",
"Safe Max (Erista)": "Safe Max (Erista)",
"RAM VDD2 Voltage": "Voltaje RAM VDD2",
"Voltage": "voltaje",
"RAM VDDQ Voltage": "Voltaje RAM VDDQ",
"RAM Frequency Editor": "Editor de frecuencia RAM",
"JEDEC.": "JEDEC.",
"High speedo needed!": "¡Se necesita alta velocidad!",
"3333MHz (Needs extreme Speedo/PLL)": "3333MHz (Necesita Speedo/PLL extremo)",
"3366MHz (Needs extreme Speedo/PLL)": "3366MHz (Necesita Speedo/PLL extremo)",
"3400MHz (Needs extreme Speedo/PLL)": "3400MHz (Necesita Speedo/PLL extremo)",
"3433MHz (Needs ridiculous Speedo/PLL)": "3433MHz (Necesita Speedo/PLL ridículo)",
"3466MHz (Needs ridiculous Speedo/PLL)": "3466MHz (Necesita Speedo/PLL ridículo)",
"3500MHz (Needs ridiculous Speedo/PLL)": "3500MHz (Necesita Speedo/PLL ridículo)",
"Ram Max Clock": "Ram Max Reloj",
"RAM Latency Editor": "Editor de latencia de RAM",
"RAM Timing Reductions": "Reducciones de tiempo de RAM",
"Memory Timings": "Tiempos de memoria",
"Rating": "Valor",
"Safe Max (Mariko)": "Máximo seguro (Mariko)",
"Safe Max (Erista)": "Máximo seguro (Erista)",
"RAM VDD2 Voltage": "Voltaje VDD2 de RAM",
"Voltage": "Voltaje",
"RAM VDDQ Voltage": "Voltaje VDDQ de RAM",
"RAM Frequency Editor": "Editor de frecuencia de RAM",
"JEDEC.": "JEDEC",
"High speedo needed!": "¡Se necesita alto speedo!",
"3333MHz (Needs extreme Speedo/PLL)": "3333MHz (requiere Speedo/PLL extremo)",
"3366MHz (Needs extreme Speedo/PLL)": "3366MHz (requiere Speedo/PLL extremo)",
"3400MHz (Needs extreme Speedo/PLL)": "3400MHz (requiere Speedo/PLL extremo)",
"3433MHz (Needs ridiculous Speedo/PLL)": "3433MHz (requiere Speedo/PLL muy alto)",
"3466MHz (Needs ridiculous Speedo/PLL)": "3466MHz (requiere Speedo/PLL muy alto)",
"3500MHz (Needs ridiculous Speedo/PLL)": "3500MHz (requiere Speedo/PLL muy alto)",
"Ram Max Clock": "Frecuencia máxima de RAM",
"RAM Latency Editor": "Editor de latencias de RAM",
"RAM Timing Reductions": "Reducción de timings de RAM",
"Memory Timings": "Timings de memoria",
"Advanced": "Avanzado",
"t6 tRTW Fine Tune": "t6 tRTW Ajuste fino",
"t6 tRTW Fine Tune": "Ajuste fino t6 tRTW",
"tRTW Fine Tune": "Ajuste fino tRTW",
"t7 tWTR Fine Tune": "t7 tWTR Ajuste fino",
"tWTR Fine Tune": "Ajuste fino de tWTR",
"Memory Latencies": "Latencias de la memoria",
"Read Latency": "Leer latencia",
"t7 tWTR Fine Tune": "Ajuste fino t7 tWTR",
"tWTR Fine Tune": "Ajuste fino tWTR",
"Memory Latencies": "Latencias de memoria",
"Read Latency": "Latencia de lectura",
"Write Latency": "Latencia de escritura",
"CPU Boost Clock": "Reloj de aumento de CPU",
"CPU UV": "procesador ultravioleta",
"CPU Boost Clock": "Frecuencia boost de CPU",
"CPU UV": "Undervolt de CPU",
"CPU Unlock": "Desbloqueo de CPU",
"CPU VMIN": "CPU VMIN",
"CPU Max Voltage": "Voltaje máximo de la CPU",
"CPU Max Clock": "Reloj máximo de CPU",
"Extreme UV Table": "Mesa UV extrema",
"CPU UV Table": "Tabla UV de CPU",
"CPU Low UV": "CPU baja radiación ultravioleta",
"CPU High UV": "CPU alta UV",
"CPU VMIN": "VMIN de CPU",
"CPU Max Voltage": "Voltaje máximo de CPU",
"CPU Max Clock": "Frecuencia máxima de CPU",
"Extreme UV Table": "Tabla de undervolt extrema",
"CPU UV Table": "Tabla de undervolt de CPU",
"CPU Low UV": "Undervolt bajo de CPU",
"CPU High UV": "Undervolt alto de CPU",
"CPU Low VMIN": "VMIN bajo de CPU",
"CPU High VMIN": "VMIN alto de CPU",
"No Undervolt": "Sin subvoltaje",
"SLT Table": "Mesa TR",
"No Undervolt": "Sin undervolt",
"SLT Table": "Tabla SLT",
"HiOPT Table": "Tabla HiOPT",
"GPU Undervolt Table": "Tabla de subvoltaje de GPU",
"GPU Undervolt Table": "Tabla de undervolt de GPU",
"GPU Minimum Voltage": "Voltaje mínimo de GPU",
"Calculate GPU Vmin": "Calcular GPU Vmin",
"GPU VMIN": "GPU VMIN",
"Calculate GPU Vmin": "Calcular Vmin de GPU",
"GPU VMIN": "VMIN de GPU",
"GPU Maximum Voltage": "Voltaje máximo de GPU",
"GPU Voltage Offset": "Compensación de voltaje de GPU",
"Do not override": "no anular",
"Enabled (Default)": "Habilitado (predeterminado)",
"96.6% limit": "límite del 96,6%",
"99.7% limit": "límite del 99,7%",
"GPU Scheduling Override": "Anulación de programación de GPU",
"Official Service": "Servicio Oficial",
"GPU DVFS Mode": "Modo GPU DVFS",
"GPU DVFS Offset": "Compensación DVFS de GPU",
"GPU Voltage Offset": "Offset de voltaje de GPU",
"Do not override": "No sobrescribir",
"Enabled (Default)": "Activado (predeterminado)",
"96.6% limit": "Límite 96,6%",
"99.7% limit": "Límite 99,7%",
"GPU Scheduling Override": "Sobrescritura de scheduling de GPU",
"Official Service": "Servicio oficial",
"GPU DVFS Mode": "Modo DVFS de GPU",
"GPU DVFS Offset": "Offset DVFS de GPU",
"GPU Voltage Table": "Tabla de voltaje de GPU",
"GPU Custom Table (mV)": "Tabla personalizada de GPU (mV)",
"1075MHz without UV, 1152MHz on SLT": "1075MHz sin UV, 1152MHz en SLT",
"or 1228MHz on HiOPT can cause ": "o 1228MHz en HiOPT pueden causar",
"permanent damage to your Switch!": Daño permanente a tu Switch!",
"921MHz without UV and 960MHz on": "921MHz sin UV y 960MHz encendido",
"SLT or HiOPT can cause ": "SLT o HiOPT pueden causar"
}
"1075MHz without UV, 1152MHz on SLT": "1075MHz sin undervolt, 1152MHz en SLT",
"or 1228MHz on HiOPT can cause ": "o 1228MHz en HiOPT pueden causar ",
"permanent damage to your Switch!": daño permanente a tu Switch!",
"921MHz without UV and 960MHz on": "921MHz sin undervolt y 960MHz en",
"SLT or HiOPT can cause ": "SLT o HiOPT pueden causar "
}

Binary file not shown.

Binary file not shown.