Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab020c0a90 | ||
|
|
44dc402b54 | ||
|
|
a1d047f48d | ||
|
|
cbed5e11ab | ||
|
|
1ad3f6c441 | ||
|
|
820a26ba2a | ||
|
|
f0952119b6 | ||
|
|
ca5ddbd779 | ||
|
|
be49a27118 | ||
|
|
190353dc11 | ||
|
|
4a1772df77 | ||
|
|
460d1b8471 | ||
|
|
2493c798bc | ||
|
|
7525baf567 | ||
|
|
3f9a5f61fb | ||
|
|
b9156d6861 | ||
|
|
5d59be7b77 | ||
|
|
dd4c5a8732 | ||
|
|
837543fb0f | ||
|
|
03ede8f171 | ||
|
|
078d8164fc | ||
|
|
ceff8a083e | ||
|
|
b32efcc177 | ||
|
|
d57fccc463 | ||
|
|
26cf028f2d | ||
|
|
6e80c9a75f | ||
|
|
42bdfb55f2 | ||
|
|
e0967a9fd6 | ||
|
|
2406ce4f86 | ||
|
|
3b40a4a3e5 | ||
|
|
38c408dde6 | ||
|
|
5e62eb3f5d | ||
|
|
b4b5599ed2 | ||
|
|
b4917f3e1a | ||
|
|
e6b4cb6612 | ||
|
|
b1ca62ce61 | ||
|
|
243f614887 | ||
|
|
a8577378f6 | ||
|
|
564703b7c5 | ||
|
|
5ef56bed25 | ||
|
|
afddb963a9 | ||
|
|
aa72176196 | ||
|
|
7af0721847 | ||
|
|
2a6320e646 | ||
|
|
fc212bb419 | ||
|
|
14e0053335 | ||
|
|
8f28daceef | ||
|
|
f1044673d0 | ||
|
|
61a0ebffee | ||
|
|
8de8f4013e | ||
|
|
dd447553d4 | ||
|
|
11c456e00c | ||
|
|
5efb4bdd6b | ||
|
|
e331f1249b | ||
|
|
786467d7ea | ||
|
|
496e77301b | ||
|
|
d657f1d156 | ||
|
|
7ab5c2f540 | ||
|
|
71900721cf | ||
|
|
0bc9547701 | ||
|
|
96ac254022 | ||
|
|
92f378a80f | ||
|
|
589af01ad8 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -6,4 +6,4 @@
|
||||
url = https://github.com/ppkantorski/libultrahand
|
||||
[submodule "Source/sys-clk/overlay/lib/libultrahand"]
|
||||
path = Source/sys-clk/overlay/lib/libultrahand
|
||||
url = https://github.com/ppkantorski/libultrahand
|
||||
url = https://github.com/ppkantorski/libultrahand
|
||||
@@ -8,4 +8,4 @@
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Contact me on discord (soul_9017) or email me (souldbminer@gmail.com)
|
||||
Contact Souldbminer or Lightos_ on discord (souldbminer, lightos_)
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
/* Never edit these. */
|
||||
#define AUTO 0
|
||||
#define AUTO_RAM 0
|
||||
#define ENABLED 1
|
||||
#define DISABLED 0
|
||||
#define DEACTIVATED_GPU_FREQ 2000
|
||||
@@ -37,6 +36,8 @@ volatile CustomizeTable C = {
|
||||
|
||||
.commonEmcMemVolt = 1175000, /* LPDDR4X JEDEC Specification */
|
||||
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
|
||||
.eristaEmcMaxClock1 = 1600000,
|
||||
.eristaEmcMaxClock2 = 1600000,
|
||||
|
||||
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
|
||||
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */
|
||||
@@ -105,7 +106,7 @@ volatile CustomizeTable C = {
|
||||
/* For automatic vmin detection, set this to AUTO. */
|
||||
/* vmin past 795mV won't work due to HOS limitation */
|
||||
/* Vmin is automatically set to 800mV when SoC temperature is below 20C */
|
||||
.marikoGpuVmin = AUTO,
|
||||
.marikoGpuVmin = AUTO,
|
||||
|
||||
.marikoGpuVmax = 800,
|
||||
|
||||
@@ -176,6 +177,10 @@ volatile CustomizeTable C = {
|
||||
DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */,
|
||||
},
|
||||
|
||||
/* Advanced. */
|
||||
.fineTune_t6_tRTW = 0,
|
||||
.fineTune_t7_tWTR = 0,
|
||||
|
||||
/* You shouldn't have to anything past here. */
|
||||
.eristaCpuDvfsTable = {
|
||||
{ 204000, { 721094, }, { } },
|
||||
@@ -460,7 +465,7 @@ volatile CustomizeTable C = {
|
||||
{ 921600, { }, { 970060,-10108, -614,-179, 1508, -13 } },
|
||||
{ 998400, { }, { 1065665,-16075, -497,-179, 3213, 9 } },
|
||||
{ 1075200, { }, { 1132576,-16093, -648, 0, 1077, 40 } },
|
||||
{ 1152000, { }, { 1180029,-14534, -830, 0, 1469, 110 } },
|
||||
// { 1152000, { }, { 1180029,-14534, -830, 0, 1469, 110 } },
|
||||
// { 1228800, { }, { 1248293,-16383, -859, 0, 3722, 313 } },
|
||||
// { 1267200, { }, { 1286399,-17475, -867, 0, 3681, 559 } },
|
||||
},
|
||||
|
||||
@@ -80,6 +80,8 @@ typedef struct CustomizeTable {
|
||||
|
||||
u32 commonEmcMemVolt;
|
||||
u32 eristaEmcMaxClock;
|
||||
u32 eristaEmcMaxClock1;
|
||||
u32 eristaEmcMaxClock2;
|
||||
u32 marikoEmcMaxClock;
|
||||
u32 marikoEmcVddqVolt;
|
||||
u32 emcDvbShift;
|
||||
@@ -121,12 +123,16 @@ typedef struct CustomizeTable {
|
||||
|
||||
u32 commonGpuVoltOffset;
|
||||
|
||||
/* TODO: Automatically detect speedo. */
|
||||
u32 gpuSpeedo;
|
||||
|
||||
u32 eristaGpuVoltArray[27];
|
||||
u32 marikoGpuVoltArray[24];
|
||||
u32 reserved[64];
|
||||
|
||||
u32 fineTune_t6_tRTW;
|
||||
u32 fineTune_t7_tWTR;
|
||||
|
||||
u32 reserved[60];
|
||||
|
||||
CustomizeCpuDvfsTable eristaCpuDvfsTable;
|
||||
CustomizeCpuDvfsTable eristaCpuDvfsTableSLT;
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) Lightos_
|
||||
*
|
||||
* 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 "../oc_common.hpp"
|
||||
#include "../mtc_timing_value.hpp"
|
||||
|
||||
namespace ams::ldr::hoc::pcv::erista {
|
||||
|
||||
void CalculateTimings(double tCK_avg) {
|
||||
tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3) + finetRTW;
|
||||
tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL_DBI + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
|
||||
tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL_DBI)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
|
||||
|
||||
pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
|
||||
tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0;
|
||||
|
||||
const double tMMRI = tRCD + (tCK_avg * 3);
|
||||
pdex2mrr = tMMRI + 10;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) Lightos_
|
||||
*
|
||||
* 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
|
||||
|
||||
namespace ams::ldr::hoc::pcv::erista {
|
||||
|
||||
void CalculateTimings(double tCK_avg);
|
||||
|
||||
}
|
||||
@@ -21,3 +21,4 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
void CalculateTimings();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,7 @@ namespace ams::ldr::hoc {
|
||||
#define PACK_U32(high, low) ((static_cast<u32>(high) << 16) | (static_cast<u32>(low) & 0xFFFF))
|
||||
#define PACK_U32_NIBBLE_HIGH_BYTE_LOW(high, low) ((static_cast<u32>(high & 0xF) << 28) | (static_cast<u32>(low) & 0xFF))
|
||||
|
||||
/* Primary timings. */
|
||||
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
||||
const std::array<double, 7> tRRD_values = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? 8gb uses 7.5 tRRD on >=1331. */
|
||||
const std::array<u32, 11> tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
||||
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
||||
|
||||
|
||||
/* Burst latency, not to be confused with base latency (tWRL). */
|
||||
const u32 BL = 16;
|
||||
@@ -75,56 +68,14 @@ namespace ams::ldr::hoc {
|
||||
/* Write recovery time. */
|
||||
const u32 tWR = 18;
|
||||
|
||||
/* TOOD: Fix erista */
|
||||
namespace pcv::erista {
|
||||
const double tCK_avg = 1000'000.0 / C.eristaEmcMaxClock;
|
||||
|
||||
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
||||
const u32 tRPpb = tRP_values[C.t2_tRP];
|
||||
const u32 tRAS = tRAS_values[C.t3_tRAS];
|
||||
const double tRRD = tRRD_values[C.t4_tRRD];
|
||||
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
||||
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
||||
|
||||
const u32 tRC = tRAS + tRPpb;
|
||||
const u32 tRFCab = tRFCpb * 2;
|
||||
const double tXSR = (double) (tRFCab + 7.5);
|
||||
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
||||
const double tRPab = tRPpb + 3;
|
||||
|
||||
const u32 tR2P = 12;
|
||||
|
||||
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
||||
const u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * (C.eristaEmcMaxClock / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg));
|
||||
|
||||
const u32 wdv = WL;
|
||||
const u32 wsv = WL - 2;
|
||||
const u32 wev = 0xA + (WL - 14);
|
||||
|
||||
const double freq_mhz = C.eristaEmcMaxClock / 1000.0;
|
||||
|
||||
const u32 quse_width = CEIL(((3.7165006256863955 - freq_mhz) + (-0.002446584377651142 * freq_mhz)) - FLOOR(freq_mhz / -0.9952024303111688));
|
||||
const u32 quse = CEIL(MIN(RL_DBI + (2.991255208275918 - (quse_width + (-0.00511180626826906 * freq_mhz))), freq_mhz * 0.021333773138874437));
|
||||
const u32 ibdly = 0x10000000 + FLOOR(MAX(RL_DBI - 1.9999956603408224, quse - 5.9999987787411175) + (-0.0011929079761504341 * freq_mhz));
|
||||
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
|
||||
const u32 obdlyLow = WL - MIN(static_cast<double>(WL), 12 - (CEIL(-0.0003991 * freq_mhz) * 2));
|
||||
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
|
||||
const u32 tCKE = CEIL(1.0795 * CEIL(0.0074472 * (C.eristaEmcMaxClock / 1000.0)));
|
||||
|
||||
const double tMMRI = tRCD + (tCK_avg * 3);
|
||||
const double pdex2mrr = tMMRI + 10;
|
||||
const u32 tWTPDEN = tW2P + 1 + CEIL(tDQSS_max / tCK_avg) + CEIL(tDQS2DQ_max / tCK_avg) + 6;
|
||||
const u32 tR2W = CEIL(RL_DBI + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST) + 9.0) - (C.t6_tRTW * 3);
|
||||
|
||||
const double pdex_local = (0.011 * freq_mhz) - 1.443;
|
||||
const u32 pdex2rw = static_cast<u32>(ROUND(pdex_local)) < 22 ? 22 : (static_cast<u32>(ROUND(pdex_local)) > 33 ? 33 : static_cast<u32>(ROUND(pdex_local)));
|
||||
|
||||
const double cke2pden = (static_cast<double>((C.eristaEmcMaxClock / 1000.0) * 0.00875) - 0.65);
|
||||
}
|
||||
|
||||
namespace pcv::mariko {
|
||||
const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock;
|
||||
const double ramFreqMhz = C.marikoEmcMaxClock / 1000.0;
|
||||
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
||||
const std::array<double, 8> tRRD_values = { 10.0, 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 };
|
||||
const std::array<u32, 11> tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
||||
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
||||
|
||||
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
||||
const u32 tRPpb = tRP_values[C.t2_tRP];
|
||||
@@ -132,6 +83,8 @@ namespace ams::ldr::hoc {
|
||||
const double tRRD = tRRD_values[C.t4_tRRD];
|
||||
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
||||
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
||||
const s32 finetRTW = C.fineTune_t6_tRTW;
|
||||
const s32 finetWTR = C.fineTune_t7_tWTR;
|
||||
|
||||
const u32 tRC = tRAS + tRPpb;
|
||||
const u32 tRFCab = tRFCpb * 2;
|
||||
@@ -140,7 +93,48 @@ namespace ams::ldr::hoc {
|
||||
const double tRPab = tRPpb + 3;
|
||||
|
||||
const u32 tR2P = CEIL((RL_DBI * 0.426) - 2.0);
|
||||
const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3);
|
||||
inline u32 tR2W;
|
||||
inline u32 rext;
|
||||
|
||||
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
||||
inline u32 tWTPDEN;
|
||||
inline u32 tW2R;
|
||||
|
||||
inline u32 pdex2rw;
|
||||
|
||||
inline u32 tCLKSTOP;
|
||||
|
||||
inline double pdex2mrr;
|
||||
}
|
||||
|
||||
namespace pcv::mariko {
|
||||
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
||||
const std::array<double, 7> tRRD_values = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? 8gb uses 7.5 tRRD on >=1331. */
|
||||
const std::array<u32, 11> tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
||||
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
||||
|
||||
const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock;
|
||||
|
||||
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
||||
const u32 tRPpb = tRP_values[C.t2_tRP];
|
||||
const u32 tRAS = tRAS_values[C.t3_tRAS];
|
||||
const double tRRD = tRRD_values[C.t4_tRRD];
|
||||
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
||||
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
||||
const s32 finetRTW = C.fineTune_t6_tRTW;
|
||||
const s32 finetWTR = C.fineTune_t7_tWTR;
|
||||
|
||||
const u32 tRC = tRAS + tRPpb;
|
||||
const u32 tRFCab = tRFCpb * 2;
|
||||
const double tXSR = static_cast<double>(tRFCab + 7.5);
|
||||
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
||||
const double tRPab = tRPpb + 3;
|
||||
|
||||
const u32 tR2P = CEIL((RL_DBI * 0.426) - 2.0);
|
||||
const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3) + finetRTW;
|
||||
const u32 tRTM = FLOOR((10.0 + RL_DBI) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
|
||||
const u32 tRATM = CEIL((tRTM - 10.0) + (RL_DBI * 0.426));
|
||||
inline u32 rext;
|
||||
@@ -158,7 +152,7 @@ namespace ams::ldr::hoc {
|
||||
const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
|
||||
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
||||
const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL_DBI + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
|
||||
const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL_DBI)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg);
|
||||
const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL_DBI)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
|
||||
const u32 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753));
|
||||
const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0;
|
||||
|
||||
@@ -168,7 +162,6 @@ namespace ams::ldr::hoc {
|
||||
|
||||
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
|
||||
const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0);
|
||||
|
||||
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
|
||||
|
||||
const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
|
||||
|
||||
@@ -138,19 +138,20 @@ void SafetyCheck() {
|
||||
break;
|
||||
}
|
||||
|
||||
using namespace ams::ldr::hoc::pcv;
|
||||
sValidator validators[] = {
|
||||
{ C.eristaCpuBoostClock, 1020'000, 2295'000, true },
|
||||
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true },
|
||||
{ C.commonEmcMemVolt, 912'500, 1350'000 }, // Official burst vmax for the RAMs is 1500mV
|
||||
{ C.eristaCpuMaxVolt, 1000, 1257 },
|
||||
{ C.eristaEmcMaxClock, 1600'000, 2600'000 },
|
||||
{ C.marikoCpuMaxVolt, 1000, 1235 },
|
||||
{ C.marikoEmcMaxClock, 1600'000, 3500'000 },
|
||||
{ C.marikoEmcVddqVolt, 250'000, 700'000 },
|
||||
{ eristaCpuDvfsMaxFreq, 1785'000, 2295'000 },
|
||||
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000 },
|
||||
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000 },
|
||||
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000 },
|
||||
{ C.commonEmcMemVolt, 912'500, 1350'000 }, // Official burst vmax for the RAMs is 1500mV
|
||||
{ C.eristaCpuMaxVolt, 1000, 1257 },
|
||||
{ GET_MAX_OF_ARR(erista::maxClocks), 1600'000, 2600'000 },
|
||||
{ C.marikoCpuMaxVolt, 1000, 1235 },
|
||||
{ C.marikoEmcMaxClock, 1600'000, 3500'000 },
|
||||
{ C.marikoEmcVddqVolt, 250'000, 700'000 },
|
||||
{ eristaCpuDvfsMaxFreq, 1785'000, 2295'000 },
|
||||
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000 },
|
||||
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000 },
|
||||
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000 },
|
||||
};
|
||||
|
||||
for (auto& i : validators) {
|
||||
|
||||
@@ -122,16 +122,6 @@ namespace ams::ldr::hoc::pcv {
|
||||
{0xFFFFFFFF, 35},
|
||||
};
|
||||
|
||||
static const u32 ramBrackets[][22] = {
|
||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
|
||||
};
|
||||
|
||||
static const u32 gpuBudgetDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||
|
||||
|
||||
/* GPU Max Clock asm Pattern:
|
||||
*
|
||||
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
||||
@@ -188,6 +178,9 @@ namespace ams::ldr::hoc::pcv {
|
||||
}
|
||||
|
||||
namespace erista {
|
||||
const u32 maxClocks[] = { C.eristaEmcMaxClock2, C.eristaEmcMaxClock1, C.eristaEmcMaxClock, };
|
||||
#define GET_MAX_OF_ARR(ARR) (*std::max_element(ARR, ARR + std::size(ARR)))
|
||||
|
||||
constexpr cvb_entry_t CpuCvbTableDefault[] = {
|
||||
// CPU_PLL_CVB_TABLE_ODN
|
||||
{ 204000, {721094}, { } },
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "pcv.hpp"
|
||||
#include "../mtc_timing_value.hpp"
|
||||
#include "../erista/calculate_timings_erista.hpp"
|
||||
|
||||
namespace ams::ldr::hoc::pcv::erista {
|
||||
|
||||
@@ -180,325 +181,19 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
// void MemMtcTableAutoAdjustBaseLatency(EristaMtcTable *table) {
|
||||
// using namespace pcv::erista;
|
||||
/* #define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \
|
||||
TABLE->burst_regs.PARAM = VALUE; \
|
||||
TABLE->shadow_regs_ca_train.PARAM = VALUE; \
|
||||
TABLE->shadow_regs_quse_train.PARAM = VALUE; \
|
||||
TABLE->shadow_regs_rdwr_train.PARAM = VALUE;
|
||||
*/
|
||||
// #define GET_CYCLE(PARAM) ((u32)((double)(PARAM) / tCK_avg))
|
||||
|
||||
/* This condition is insane but it's done in eos. */
|
||||
/* Need to clean up at some point. */
|
||||
// u32 rext;
|
||||
// u32 wext;
|
||||
// if (C.eristaEmcMaxClock < 3200001) {
|
||||
// if (C.eristaEmcMaxClock < 2133001) {
|
||||
// rext = 26;
|
||||
// wext = 22;
|
||||
// } else {
|
||||
// rext = 28;
|
||||
// wext = 22;
|
||||
//
|
||||
// if (2400000 < C.eristaEmcMaxClock) {
|
||||
// wext = 25;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// rext = 30;
|
||||
// wext = 25;
|
||||
// }
|
||||
|
||||
// u32 refresh_raw = 0xFFFF;
|
||||
// u32 trefbw = 0;
|
||||
//
|
||||
// if (C.t8_tREFI != 6) {
|
||||
// refresh_raw = static_cast<u32>(std::floor(static_cast<double>(tREFpb_values[C.t8_tREFI]) / tCK_avg)) - 0x40;
|
||||
// refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
||||
// }
|
||||
//
|
||||
// trefbw = refresh_raw + 0x40;
|
||||
// trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
||||
//
|
||||
// if (C.hpMode) {
|
||||
// WRITE_PARAM_ALL_REG(table, emc_cfg, 0x13200000);
|
||||
// } else {
|
||||
// WRITE_PARAM_ALL_REG(table, emc_cfg, 0xF3200000);
|
||||
// }
|
||||
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rc, /*0x00000060*/ GET_CYCLE(tRC));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rfc, /*0x00000120*/ GET_CYCLE(tRFCab));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_ras, /*0x00000044*/ GET_CYCLE(tRAS));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rp, /*0x0000001D*/ GET_CYCLE(tRPpb));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_r2w, /*0x0000002A*/ tR2W);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_w2r, /*0x00000021*/ tW2R);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_r2p, 0x0000000C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_w2p, 0x0000002D);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rd_rcd, /*0x0000001D*/ GET_CYCLE(tRCD));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wr_rcd, /*0x0000001D*/ GET_CYCLE(tRCD));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rrd, /*0x00000010*/ GET_CYCLE(tRRD));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rext, 0x00000017);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wdv, 0x0000000E);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_quse, 0x00000024);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_qrst, 0x0006000C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_qsafe, 0x00000034);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv, 0x0000003C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_refresh, /*0x00001820*/ refresh_raw);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_burst_refresh_num, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2wr, 0x00000010);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2rd, 0x00000010);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_pchg2pden, 0x00000003);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_act2pden, 0x00000003);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_ar2pden, 0x00000003);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rw2pden, /*0x00000038*/ GET_CYCLE(tRW2PDEN));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_txsr, /*0x0000012C*/ MIN(GET_CYCLE(tXSR), (u32) 1022));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tcke, 0x0000000D);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tfaw, /*0x00000040*/ GET_CYCLE(tFAW));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_trpab, /*0x00000022*/ GET_CYCLE(tRPab));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tclkstable, 0x00000004);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tclkstop, 0x00000014);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_trefbw, /* 0x00001860*/ trefbw);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tppd, 0x00000004);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_odt_write, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, /*0x0000002E*/ GET_CYCLE(pdex2mrr));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wext, 0x00000016);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rfc_slr, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt2, 0x01900017);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt, 0x0640002F);
|
||||
// // table->emc_mrs = 0x00000000;
|
||||
// // table->emc_emrs = 0x00000000;
|
||||
// // table->emc_mrw = 0x00170040;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_fbio_spare, 0x00000012);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_fbio_cfg5, 0x9960A00D);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2cke, 0x00000002);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_cke2pden, 0x0000000E);
|
||||
// // table->emc_emrs2 = 0x00000000;
|
||||
// // table->emc_mrw2 = 0x0802002D;
|
||||
// // table->emc_mrw3 = 0x0C0D00C0;
|
||||
// // table->emc_mrw4 = 0xC0000000;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_r2r, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_einput, 0x00000014);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_einput_duration, 0x0000001D);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_puterm_extra, 0x0000001F);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tckesr, 0x00000018);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tpd, 0x0000000C);
|
||||
// table->emc_auto_cal_config = 0x201A51D8;
|
||||
// table->emc_cfg_2 = 0x00110835;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_cfg_dig_dll, 0x002C03A9);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_cfg_dig_dll_period, 0x00008000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_mask, 0x0000003E);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wdv_mask, 0x0000000E);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, 0x0000003C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_early, 0x0000003A);
|
||||
// table->emc_auto_cal_config8 = 0x00770000;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_zcal_interval, 0x00064000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_zcal_wait_cnt, 0x00310640);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_fdpd_ctrl_dq, 0x8020221F);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_fdpd_ctrl_cmd, 0x0220F40F);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_brick_ctrl_fdpd, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_brick_ctrl_fdpd, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_brick_ctrl_rfu1, 0x1FFF1FFF);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_brick_ctrl_rfu2, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_timing_0, 0x01186190);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_tr_ctrl_1, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv, 0x0000003C);
|
||||
// table->emc_sel_dpd_ctrl = 0x00040000;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, /*0x00000608*/ (u32) (refresh_raw / 4));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, 0x8000308C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_txsrdll, /*0x0000012C*/ MIN(GET_CYCLE(tXSR), (u32) 1022));
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qpop, 0x0000002C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv_mask, 0x0000003E);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qsafe, 0x00000034);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qrst, 0x0006000C);
|
||||
// table->emc_auto_cal_config2 = 0x05500000;
|
||||
// table->emc_auto_cal_config3 = 0x00770000;
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_tr_dvfs, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_auto_cal_channel, 0xC1E0030A);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_ibdly, 0x1000001C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_obdly, 0x10000002);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_txdsrvttgen, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_we_duration, 0x0000000D);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_ws_duration, 0x00000008);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wev, 0x0000000A);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wsv, 0x0000000C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_cfg_3, 0x00000040);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw6, 0x08037171);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw7, 0x48037171);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw8, 0x080B6666);
|
||||
// // table->emc_mrw9 = 0x0C0E7272;
|
||||
// // table->emc_mrw10 = 0x880C4848;
|
||||
// // table->emc_mrw11 = 0x480C4848; /* Check them maybe */
|
||||
// // table->emc_mrw12 = 0x880E1718;
|
||||
// // table->emc_mrw13 = 0x480E1814;
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw14, 0x08161414);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw15, 0x48161414);
|
||||
// // table->emc_fdpd_ctrl_cmd_no_ramp = 0x00000001;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wdv_chk, 0x00000006);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_cfg_pipe_2, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_cfg_pipe_1, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_cfg_pipe, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_qpop, 0x0000002C);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_quse_width, 0x00000009);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_puterm_width, 0x0000000E);
|
||||
// table->emc_auto_cal_config7 = 0x00770000;
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_refctrl2, 0x00000000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_fbio_cfg7, 0x00003BFF);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rfcpb, /*0x00000090*/ GET_CYCLE(tRFCpb));
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_dqs_brlshft_0, 0x00000000); /* brlshft may or may not be important, I don't think it matters but who knows. */
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_dqs_brlshft_1, 0x00000000);
|
||||
// table->emc_auto_cal_config4 = 0x00770000;
|
||||
// table->emc_auto_cal_config5 = 0x00770000;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_ccdmw, 0x00000020);
|
||||
// table->emc_auto_cal_config6 = 0x00770000;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_dll_cfg_0, 0x1F13612F);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_dll_cfg_1, 0x00000014);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_config_sample_delay, 0x00000020);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_0, 0x10000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_1, 0x08000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_2, 0x08000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_3, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_4, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_5, 0x00001000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_bypass, 0xEFFF2210);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_pwrd_0, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_pwrd_1, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_pwrd_2, 0xDCDCDCDC);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_ctrl_0, 0x0A0A0A0A);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_ctrl_1, 0x0A0A0A0A);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_ctrl_2, 0x000A0A0A);
|
||||
// // table->trim_regs.emc_pmacro_ib_vref_dq_0 = 0x15171414;
|
||||
// // table->trim_regs.emc_pmacro_ib_vref_dq_1 = 0x15131513;
|
||||
// // table->trim_regs.emc_pmacro_ib_vref_dqs_0 = 0x11111111;
|
||||
// // table->trim_regs.emc_pmacro_ib_vref_dqs_1 = 0x11111111;
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_0, 0x000C000C);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_1, 0x000B000B);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_2, 0x000A000A);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_3, 0x000C000C);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_4, 0x0000000C);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_short_cmd_0, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_short_cmd_1, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_short_cmd_2, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_vttgen_ctrl_0, 0x00030808);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_vttgen_ctrl_1, 0x00015C00);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_bg_bias_ctrl_0, 0x00000034);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_pad_cfg_ctrl, 0x00020000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_zctrl, 0x00000550);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_pad_rx_ctrl, 0x00000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_pad_rx_ctrl, 0x00000033);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_rx_term_mode, 0x00003000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_rx_term_mode, 0x00000011);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_pad_tx_ctrl, 0x02000000);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_pad_tx_ctrl, 0x02000101);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_common_pad_tx_ctrl, 0x00000007);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_autocal_cfg_common, 0x0000080D);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_vttgen_ctrl_2, 0x00102020);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ib_rxrt, 0x00000055);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_ctrl, 0x00009080);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_quse_cors_ctrl, 0x01124000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_quse_fine_ctrl, 0x01125B6A);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_quse_ctrl_misc, 0x0F081000);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_write_fine_ctrl, 0x1114FC00);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_write_ctrl_misc, 0x07004300);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_write_vref_ctrl, 0x00103200);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_read_fine_ctrl, 0x1110FC00);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_read_ctrl_misc, 0x0F085300);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_read_vref_ctrl, 0x00105800);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_fine_ctrl, 0x0513801F);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_ctrl_misc, 0x1F101100);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_ctrl_misc1, 0x00000014);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_vref_ctrl, 0x00103200);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_training_settle, 0x07070404);
|
||||
// // WRITE_PARAM_ALL_REG(table, emc_training_mpc, 0x00000000);
|
||||
//
|
||||
// const u32 mc_tRCD = (int) ((double) (GET_CYCLE(tRCD) >> 2) - 2.0);
|
||||
// const u32 mc_tRPpb = (int) (((double) (GET_CYCLE(tRPpb) >> 2) - 1.0) + 2.0);
|
||||
// const u32 mc_tRC = (uint) ((double) (GET_CYCLE(tRC) >> 2) - 1.0);
|
||||
// const u32 mc_tR2W = (uint) (((double) ((uint)tR2W >> 2) - 1.0) + 2.0);
|
||||
// const u32 mc_tW2R = (uint) (((double) (tW2R >> 2) - 1.0) + 2.0);
|
||||
// const u32 mc_tRAS = MIN(GET_CYCLE(tRAS), (u32) 0x7F);
|
||||
// const u32 mc_tRRD = MIN(GET_CYCLE(tRRD), (u32) 31);
|
||||
//
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_ras = (int) ((double) (mc_tRAS >> 2) - 2.0);
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_rcd = (int) ((double) (GET_CYCLE(tRCD) >> 2) - 2.0);
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_rp = (int) (((double) (GET_CYCLE(tRPpb) >> 2) - 1.0) + 2.0);
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_rc = (int) ((double) (GET_CYCLE(tRC) >> 2) - 1.0);
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_faw = (int) ((double) (GET_CYCLE(tFAW) >> 2) - 1.0);
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_rrd = (int) ((double) (mc_tRRD >> 2) - 1.0);
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_r2w = (uint) (((double) ((uint) tR2W >> 2) - 1.0) + 2.0);
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_w2r = (uint) (((double) (tW2R >> 2) - 1.0) + 2.0);
|
||||
//
|
||||
// table->burst_mc_regs.mc_emem_arb_da_turns = (table->burst_mc_regs.mc_emem_arb_da_turns & 0x0000FFFF) | (mc_tW2R << 24) | (mc_tR2W << 16);
|
||||
// table->burst_mc_regs.mc_emem_arb_da_covers = (((uint) (mc_tRCD + 3 + mc_tRPpb) >> 1 & 0xff) << 8) | (((uint) (mc_tRCD + 11 + mc_tRPpb) >> 1 & 0xff) << 0x10) | ((mc_tRC >> 1) & 0xff);
|
||||
// table->burst_mc_regs.mc_emem_arb_misc0 = (table->burst_mc_regs.mc_emem_arb_misc0 & 0xffe08000U) | ((mc_tRC + 1) & 0xff); /* Missing in l4t dump? TODO */
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_rfcpb = GET_CYCLE(tRFCpb) >> 2;
|
||||
//
|
||||
// table->burst_mc_regs.mc_emem_arb_cfg = 0x0000000c;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_rcd = 0x00000006;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_rp = 0x00000007;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_rc = 0x00000018;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_ras = 0x0000000f;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_faw = 0x0000000f;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_rrd = 0x00000003;
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_rap2pre = 0x00000003;
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_wap2pre = 0x0000000d;
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_r2r = 0x00000007;
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_w2w = 0x00000007;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_r2w = 0x0000000c;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_w2r = 0x0000000a;
|
||||
// // table->burst_mc_regs.mc_emem_arb_da_turns = 0x05060303;
|
||||
// // table->burst_mc_regs.mc_emem_arb_da_covers = 0x000d080c;
|
||||
// table->burst_mc_regs.mc_emem_arb_ring1_throttle = 0x001f0000;
|
||||
// // table->burst_mc_regs.mc_emem_arb_timing_rfcpb = 0x00000023;
|
||||
// table->burst_mc_regs.mc_emem_arb_timing_ccdmw = 0x00000008;
|
||||
// table->burst_mc_regs.mc_emem_arb_refpb_hp_ctrl = 0x000a1020;
|
||||
// table->burst_mc_regs.mc_emem_arb_refpb_bank_ctrl = 0x80001028;
|
||||
// // table->burst_mc_regs.mc_emem_arb_dhyst_ctrl = 0x00000002;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_0 = 0x0000001a;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_1 = 0x0000001a;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_2 = 0x0000001a;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_3 = 0x0000001a;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_4 = 0x0000001a;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_5 = 0x0000001a;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_6 = 0x0000001a;
|
||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_7 = 0x0000001a;
|
||||
// table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = 0x000000d0;
|
||||
// table->la_scale_regs.mc_ftop_ptsa_rate = 0x00000018;
|
||||
// table->la_scale_regs.mc_ptsa_grant_decrement = 0x00001203;
|
||||
// table->la_scale_regs.mc_latency_allowance_avpc_0 = 0x00800004;
|
||||
// table->la_scale_regs.mc_latency_allowance_xusb_1 = 0x00800038;
|
||||
// table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = 0x00800005;
|
||||
// table->la_scale_regs.mc_latency_allowance_sdmmca_0 = 0x00800014;
|
||||
// table->la_scale_regs.mc_latency_allowance_isp2_0 = 0x0000002c;
|
||||
// table->la_scale_regs.mc_latency_allowance_isp2_1 = 0x00800080;
|
||||
// table->la_scale_regs.mc_latency_allowance_vic_0 = 0x0080001d;
|
||||
// table->la_scale_regs.mc_latency_allowance_nvdec_0 = 0x00800095;
|
||||
// table->la_scale_regs.mc_latency_allowance_tsec_0 = 0x00800041;
|
||||
// table->la_scale_regs.mc_latency_allowance_ppcs_1 = 0x00800080;
|
||||
// table->la_scale_regs.mc_latency_allowance_xusb_0 = 0x0080003d;
|
||||
// table->la_scale_regs.mc_latency_allowance_ppcs_0 = 0x00340049;
|
||||
// table->la_scale_regs.mc_latency_allowance_gpu2_0 = 0x00800019;
|
||||
// table->la_scale_regs.mc_latency_allowance_hc_1 = 0x00000080;
|
||||
// table->la_scale_regs.mc_latency_allowance_sdmmc_0 = 0x00800090;
|
||||
// table->la_scale_regs.mc_latency_allowance_mpcore_0 = 0x00800004;
|
||||
// table->la_scale_regs.mc_latency_allowance_vi2_0 = 0x00000080;
|
||||
// table->la_scale_regs.mc_latency_allowance_hc_0 = 0x00080016;
|
||||
// table->la_scale_regs.mc_latency_allowance_gpu_0 = 0x00800019;
|
||||
// table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = 0x00800005;
|
||||
// table->la_scale_regs.mc_latency_allowance_nvenc_0 = 0x00800018;
|
||||
// table->dram_timings.t_rp = tRFCpb;
|
||||
// table->dram_timings.t_rfc = tRFCab;
|
||||
// }
|
||||
|
||||
/* These timings are slightly off from eos, I am not sure why but I am going to figure it out at some point. */
|
||||
/* Note: This does not have proper timings, so base latency adjustment will not work. */
|
||||
/* However, it may still achieve a slightly higher frequency, but not as much as it could be. */
|
||||
/* I'm certainly not insane enough to attempt this pain again, so this will have to do *for now*. */
|
||||
void MemMtcTableAutoAdjust(EristaMtcTable *table) {
|
||||
const double tCK_avg = 1000'000.0 / table->rate_khz;
|
||||
|
||||
#define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \
|
||||
TABLE->burst_regs.PARAM = VALUE; \
|
||||
TABLE->shadow_regs_ca_train.PARAM = VALUE; \
|
||||
TABLE->shadow_regs_rdwr_train.PARAM = VALUE;
|
||||
|
||||
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
||||
|
||||
/* Ram power down */
|
||||
/* B31: DRAM_CLKSTOP_PD */
|
||||
/* B30: DRAM_CLKSTOP_SR */
|
||||
@@ -515,9 +210,19 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
||||
}
|
||||
|
||||
if (table->rate_khz > 3200000) {
|
||||
rext = 30;
|
||||
} else if (table->rate_khz >= 2133001) {
|
||||
rext = 28;
|
||||
} else {
|
||||
rext = 26;
|
||||
}
|
||||
|
||||
u32 trefbw = refresh_raw + 0x40;
|
||||
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
||||
|
||||
CalculateTimings(tCK_avg);
|
||||
|
||||
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
|
||||
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
|
||||
WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8)));
|
||||
@@ -531,15 +236,15 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
|
||||
WRITE_PARAM_ALL_REG(table, emc_trpab, MIN(GET_CYCLE_CEIL(tRPab), static_cast<u32>(0x3F)));
|
||||
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR));
|
||||
WRITE_PARAM_ALL_REG(table, emc_tcke, tCKE);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(7.425) + 2);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tXP));
|
||||
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tXP) + 8);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tclkstop, tCLKSTOP);
|
||||
WRITE_PARAM_ALL_REG(table, emc_r2p, tR2P);
|
||||
WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W);
|
||||
WRITE_PARAM_ALL_REG(table, emc_w2p, tW2P);
|
||||
WRITE_PARAM_ALL_REG(table, emc_w2r, tW2R);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rext, C.eristaEmcMaxClock < 2133001 ? 26 : 28); // rext shouldn't be causing issues?
|
||||
WRITE_PARAM_ALL_REG(table, emc_wext, (C.eristaEmcMaxClock >= 2533000) ? 0x19 : 0x16);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rext, rext);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wext, (table->rate_khz >= 2533000) ? 0x19 : 0x16);
|
||||
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);
|
||||
@@ -547,20 +252,46 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
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);
|
||||
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.75));
|
||||
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.763));
|
||||
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(1.75));
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(1.05));
|
||||
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(14.0));
|
||||
WRITE_PARAM_ALL_REG(table, emc_cke2pden, /* cke2pden */ GET_CYCLE_CEIL(8.5));
|
||||
(void) cke2pden;
|
||||
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(8.499));
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(pdex2mrr));
|
||||
WRITE_PARAM_ALL_REG(table, emc_rw2pden, tWTPDEN);
|
||||
|
||||
/* Accept imperfection or prepare for suffering. */
|
||||
// WRITE_PARAM_ALL_REG(table, emc_einput, einput);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_einput_duration, einput_duration);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_obdly, obdly);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_ibdly, ibdly);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wdv_mask, wdv);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_quse_width, quse_width);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_quse, quse);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wdv, wdv);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wsv, wsv);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_wev, wev);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_qrst, qrst);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qrst, qrst);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_qsafe, qsafe);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qsafe, qsafe);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qpop, qpop);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_qpop, qpop);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv, rdv);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv_mask, rdv + 2);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_early, rdv - 2);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
|
||||
// ams::ldr::hoc::pcv::mariko::CalculateMrw2();
|
||||
// table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
|
||||
// table->dram_timings.rl = RL_DBI;
|
||||
|
||||
/* This needs some clean up. */
|
||||
constexpr double MC_ARB_DIV = 4.0;
|
||||
constexpr u32 MC_ARB_SFA = 2;
|
||||
|
||||
table->burst_mc_regs.mc_emem_arb_cfg = C.eristaEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV;
|
||||
table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
|
||||
@@ -593,54 +324,50 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
|
||||
table->burst_mc_regs.mc_emem_arb_misc0 = (table->burst_mc_regs.mc_emem_arb_misc0 & 0xFFE08000) | (table->burst_mc_regs.mc_emem_arb_timing_rc + 1);
|
||||
|
||||
table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = 0x115;
|
||||
u32 mpcorer_ptsa_rate = MAX(static_cast<u32>(227), (table->rate_khz / 1600000) * 208);
|
||||
table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = mpcorer_ptsa_rate;
|
||||
|
||||
if (C.eristaEmcMaxClock >= 2133000) {
|
||||
table->la_scale_regs.mc_ftop_ptsa_rate = 0x1F;
|
||||
} else {
|
||||
table->la_scale_regs.mc_ftop_ptsa_rate = 0x1B;
|
||||
}
|
||||
u32 ftop_ptsa_rate = MAX(static_cast<u32>(31), (table->rate_khz / 1600000) * 24);
|
||||
table->la_scale_regs.mc_ftop_ptsa_rate = ftop_ptsa_rate;
|
||||
|
||||
table->la_scale_regs.mc_ptsa_grant_decrement = 0x17ff;
|
||||
u32 grant_decrement = MAX(static_cast<u32>(6143), (table->rate_khz / 1600000) * 4611);
|
||||
table->la_scale_regs.mc_ptsa_grant_decrement = grant_decrement;
|
||||
|
||||
constexpr u32 MaskHigh = 0xFF00FFFF;
|
||||
constexpr u32 Mask2 = 0xFFFFFF00;
|
||||
constexpr u32 Mask3 = 0xFF00FF00;
|
||||
|
||||
const u32 allowance1 = static_cast<u32>(0x32000 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
||||
const u32 allowance2 = static_cast<u32>(0x9C40 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
||||
const u32 allowance3 = static_cast<u32>(0xB540 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
||||
const u32 allowance4 = static_cast<u32>(0x9600 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
||||
const u32 allowance5 = static_cast<u32>(0x8980 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
||||
const u32 allowance1 = static_cast<u32>(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||
const u32 allowance2 = static_cast<u32>(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||
const u32 allowance3 = static_cast<u32>(0xB540 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||
const u32 allowance4 = static_cast<u32>(0x9600 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||
const u32 allowance5 = static_cast<u32>(0x8980 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||
|
||||
table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_isp2_1 = (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16) | allowance1;
|
||||
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
||||
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
||||
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->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_isp2_1 = allowance1 | (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
||||
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_rfc = tRFCab;
|
||||
table->dram_timings.rl = RL_DBI;
|
||||
// WRITE_PARAM_ALL_REG(table, emc_obdly, obdly);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_ibdly, ibdly);
|
||||
|
||||
table->emc_cfg_2 = 0x11083D;
|
||||
}
|
||||
table->min_volt = std::min(static_cast<u32>(1050), 900 + C.emcDvbShift * 25);
|
||||
}
|
||||
|
||||
Result MemFreqMtcTable(u32 *ptr) {
|
||||
u32 khz_list[] = {1600000, 1331200, 1065600, 800000, 665600, 408000, 204000, 102000, 68000, 40800};
|
||||
@@ -655,25 +382,32 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
R_UNLESS(table_list[i]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
|
||||
}
|
||||
|
||||
if (C.eristaEmcMaxClock <= EmcClkOSLimit)
|
||||
if (GET_MAX_OF_ARR(maxClocks) <= EmcClkOSLimit) {
|
||||
R_SKIP();
|
||||
}
|
||||
|
||||
// Make room for new mtc table, discarding useless 40.8 MHz table
|
||||
// 40800 overwritten by 68000, ..., 1331200 overwritten by 1600000, leaving table_list[0] not overwritten
|
||||
for (u32 i = khz_list_size - 1; i > 0; i--)
|
||||
std::memcpy(static_cast<void *>(table_list[i]), static_cast<void *>(table_list[i - 1]), sizeof(EristaMtcTable));
|
||||
// Make room for new mtc table, discarding useless 40.8, 68000 and 102000 MHz table
|
||||
// 40800 overwritten by 68000, ..., 1331200 overwritten by 1600000, leaving table_list[0], table_list[1] and table_list[2] not overwritten
|
||||
for (u32 i = khz_list_size - 1; i > 2; --i) {
|
||||
std::memcpy(static_cast<void *>(table_list[i]), static_cast<void *>(table_list[i - 3]), sizeof(EristaMtcTable));
|
||||
}
|
||||
|
||||
MemMtcTableAutoAdjust(table_list[0]);
|
||||
for (u32 i = 0; i < std::size(maxClocks); ++i) {
|
||||
if (maxClocks[i] > EmcClkOSLimit) {
|
||||
table_list[i]->rate_khz = maxClocks[i];
|
||||
MemMtcTableAutoAdjust(table_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
PATCH_OFFSET(ptr, C.eristaEmcMaxClock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemFreqMax(u32 *ptr) {
|
||||
if (C.eristaEmcMaxClock <= EmcClkOSLimit)
|
||||
if (GET_MAX_OF_ARR(maxClocks) <= EmcClkOSLimit) {
|
||||
R_SKIP();
|
||||
}
|
||||
|
||||
PATCH_OFFSET(ptr, C.eristaEmcMaxClock);
|
||||
PATCH_OFFSET(ptr, GET_MAX_OF_ARR(maxClocks));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
@@ -50,30 +50,6 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
return ramScale;
|
||||
}
|
||||
|
||||
u32 GetSpeedoBracket() {
|
||||
u32 speedoBracket = 3;
|
||||
if ((C.gpuSpeedo < 1754) && (speedoBracket = 2, C.gpuSpeedo < 1690)) {
|
||||
speedoBracket = !!(1625 < C.gpuSpeedo);
|
||||
}
|
||||
|
||||
return speedoBracket;
|
||||
}
|
||||
|
||||
u32 GetGpuBudgetDvfsVoltage() {
|
||||
u32 bracket = GetSpeedoBracket();
|
||||
|
||||
if (ramFreqMhz <= 1600)
|
||||
return 0;
|
||||
|
||||
for (u32 voltageIndex = 0; voltageIndex < 22; voltageIndex++) {
|
||||
if (ramFreqMhz <= ramBrackets[bracket][voltageIndex]) {
|
||||
return gpuBudgetDvfsArray[voltageIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return 800;
|
||||
}
|
||||
|
||||
/* Note: EOS (probably?) has a bug in this function that always results in high vmin, this is fixed here. */
|
||||
u32 GetAutoVoltage() {
|
||||
u32 voltage = GetGpuVminVoltage();
|
||||
@@ -102,14 +78,13 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
}
|
||||
|
||||
/* C.marikoGpuVmin is non zero, user sets manual voltage. */
|
||||
if (C.marikoGpuVmin != 0 && C.marikoGpuVmin != 1) {
|
||||
if (C.marikoGpuVmin) {
|
||||
PATCH_OFFSET(ptr, C.marikoGpuVmin);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
/* C.marikoGpuVmin is zero OR one, auto voltage is applied. */
|
||||
/* Get vmin depending on speedo and ram clock. */
|
||||
u32 autoVmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage();
|
||||
/* C.marikoGpuVmin is zero, auto voltage is applied. */
|
||||
u32 autoVmin = GetAutoVoltage();
|
||||
PATCH_OFFSET(ptr, autoVmin);
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -122,8 +97,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
u32 vmin = C.marikoGpuVmin;
|
||||
|
||||
/* Automatic voltage. */
|
||||
if (!C.marikoGpuVmin || C.marikoGpuVmin == 1) {
|
||||
vmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage();
|
||||
if (!C.marikoGpuVmin) {
|
||||
vmin = GetAutoVoltage();
|
||||
PATCH_OFFSET(ptr, vmin);
|
||||
PATCH_OFFSET(ptr + 3, vmin);
|
||||
PATCH_OFFSET(ptr + 6, vmin);
|
||||
@@ -572,25 +547,25 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
const u32 allowance4 = static_cast<u32>(0x9600 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF;
|
||||
const u32 allowance5 = static_cast<u32>(0x8980 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF;
|
||||
|
||||
table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_isp2_1 = (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16) | allowance1;
|
||||
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
||||
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
||||
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->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_isp2_1 = allowance1 | (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
||||
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
||||
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_rfc = tRFCab;
|
||||
|
||||
@@ -153,12 +153,6 @@ Result sysclkIpcGetFreqList(SysClkModule module, u32* list, u32 maxCount, u32* o
|
||||
);
|
||||
}
|
||||
|
||||
Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode)
|
||||
{
|
||||
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_SetReverseNXRTMode, mode);
|
||||
}
|
||||
|
||||
|
||||
Result hocClkIpcSetKipData()
|
||||
{
|
||||
u32 temp = 0;
|
||||
@@ -169,15 +163,4 @@ Result hocClkIpcGetKipData()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
||||
}
|
||||
|
||||
Result hocClkIpcUpdateEmcRegs()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_UpdateEmcRegs, temp);
|
||||
}
|
||||
Result hocClkIpcCalculateGpuVmin()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_CalculateGpuVmin, temp);
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM --- Root directory ---
|
||||
set ROOT_DIR=%~dp0
|
||||
set DIST_DIR=%ROOT_DIR%dist
|
||||
|
||||
REM --- Number of CPU cores ---
|
||||
set CORES=%NUMBER_OF_PROCESSORS%
|
||||
|
||||
REM --- Optional first argument as DIST_DIR ---
|
||||
if not "%~1"=="" set DIST_DIR=%~1
|
||||
|
||||
echo DIST_DIR: %DIST_DIR%
|
||||
echo CORES: %CORES%
|
||||
|
||||
REM ========================
|
||||
REM sysmodule
|
||||
REM ========================
|
||||
echo *** sysmodule ***
|
||||
|
||||
REM Extract TITLE_ID from perms.json using findstr (rough approximation)
|
||||
for /f "tokens=2 delims=: " %%A in ('findstr /i "title_id" "%ROOT_DIR%sysmodule\perms.json"') do (
|
||||
set TITLE_ID=%%A
|
||||
)
|
||||
|
||||
REM Remove quotes and 0x prefix
|
||||
set TITLE_ID=!TITLE_ID:"=!
|
||||
set TITLE_ID=!TITLE_ID:0x=!
|
||||
|
||||
REM Build sysmodule
|
||||
pushd "%ROOT_DIR%sysmodule"
|
||||
make -j %CORES%
|
||||
popd
|
||||
|
||||
REM Copy sysmodule files to dist
|
||||
if not exist "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\flags" mkdir "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\flags"
|
||||
copy /Y "%ROOT_DIR%sysmodule\out\horizon-oc.nsp" "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\exefs.nsp"
|
||||
type nul > "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\flags\boot2.flag"
|
||||
copy /Y "%ROOT_DIR%sysmodule\toolbox.json" "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\toolbox.json"
|
||||
|
||||
REM ========================
|
||||
REM overlay
|
||||
REM ========================
|
||||
echo *** overlay ***
|
||||
pushd "%ROOT_DIR%overlay"
|
||||
make -j %CORES%
|
||||
popd
|
||||
|
||||
if not exist "%DIST_DIR%\switch\.overlays" mkdir "%DIST_DIR%\switch\.overlays"
|
||||
copy /Y "%ROOT_DIR%overlay\out\horizon-oc-overlay.ovl" "%DIST_DIR%\switch\.overlays\horizon-oc-overlay.ovl"
|
||||
|
||||
REM ========================
|
||||
REM assets
|
||||
REM ========================
|
||||
echo *** assets ***
|
||||
if not exist "%DIST_DIR%\config\horizon-oc" mkdir "%DIST_DIR%\config\horizon-oc"
|
||||
copy /Y "%ROOT_DIR%config.ini.template" "%DIST_DIR%\config\horizon-oc\config.ini.template"
|
||||
copy /Y "%ROOT_DIR%..\..\README.md" "%DIST_DIR%\README.md"
|
||||
|
||||
endlocal
|
||||
@@ -36,3 +36,7 @@ echo "*** 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"
|
||||
|
||||
echo "*** lang ***"
|
||||
|
||||
cp -r "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/"
|
||||
|
||||
@@ -124,8 +124,8 @@ typedef struct {
|
||||
bool displaySyncDocked;
|
||||
bool displaySyncDockedOutOfFocus60;
|
||||
} DisplayRefreshConfig;
|
||||
|
||||
bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config);
|
||||
void DisplayRefresh_SetDockedState(bool isDocked);
|
||||
bool DisplayRefresh_SetRate(uint32_t new_refreshRate);
|
||||
bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal);
|
||||
uint8_t DisplayRefresh_GetDockedHighestAllowed(void);
|
||||
|
||||
41
Source/sys-clk/common/include/memmem.h
Normal file
41
Source/sys-clk/common/include/memmem.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Roy Merkel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MEMMEM_IMPL_H
|
||||
#define MEMMEM_IMPL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *memmem_impl(const void *haystack, size_t haystacklen,
|
||||
const void *needle, size_t needlelen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -12,9 +12,8 @@
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -310,6 +309,9 @@
|
||||
#define EMC_PMACRO_CMD_CTRL_1_0 0x784
|
||||
#define EMC_PMACRO_CMD_CTRL_2_0 0x788
|
||||
|
||||
#define MC_REGISTER_BASE 0x70019000
|
||||
#define MC_REGISTER_REGION_SIZE 0x1000
|
||||
|
||||
#define MC_INTSTATUS_0 0x000
|
||||
#define MC_INTMASK_0 0x004
|
||||
#define MC_ERR_STATUS_0 0x008
|
||||
@@ -489,4 +491,40 @@
|
||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xBEC
|
||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS_0 0xC00
|
||||
#define MC_SECURITY_CARVEOUT2_BOM_0 0xC5C
|
||||
#define MC_SECURITY_CARVEOUT3_BOM_0 0xCAC
|
||||
#define MC_SECURITY_CARVEOUT3_BOM_0 0xCAC
|
||||
|
||||
#define CLDVFS_REGION_BASE 0x70110000
|
||||
#define CLDVFS_REGION_SIZE 0x1000
|
||||
#define CL_DVFS_CTRL_0 0x0
|
||||
#define CL_DVFS_CONFIG_0 0x4
|
||||
#define CL_DVFS_PARAMS_0 0x8
|
||||
#define CL_DVFS_TUNE0_0 0xC
|
||||
#define CL_DVFS_TUNE1_0 0x10
|
||||
#define CL_DVFS_FREQ_REQ_0 0x14
|
||||
#define CL_DVFS_SCALE_RAMP_0 0x18
|
||||
#define CL_DVFS_DROOP_CTRL_0 0x1C
|
||||
#define CL_DVFS_OUTPUT_CFG_0 0x20
|
||||
#define CL_DVFS_OUTPUT_FORCE_0 0x24
|
||||
#define CL_DVFS_MONITOR_CTRL_0 0x28
|
||||
#define CL_DVFS_MONITOR_DATA_0 0x2C
|
||||
#define CL_DVFS_I2C_CFG_0 0x40
|
||||
#define CL_DVFS_I2C_VDD_REG_ADDR_0 0x44
|
||||
#define CL_DVFS_I2C_STS_0 0x48
|
||||
#define CL_DVFS_INTR_STS_0 0x5C
|
||||
#define CL_DVFS_INTR_EN_0 0x60
|
||||
#define DVFS_DFLL_THROTTLE_CTRL_0 0x64
|
||||
#define DVFS_DFLL_THROTTLE_LIGHT_0 0x68
|
||||
#define DVFS_DFLL_THROTTLE_MEDIUM_0 0x6C
|
||||
#define DVFS_DFLL_THROTTLE_HEAVY_0 0x70
|
||||
#define DVFS_CC4_HVC_0 0x74
|
||||
#define CL_DVFS_MONITOR_DATA_0 0x2C
|
||||
#define CL_DVFS_I2C_CFG_0 0x40
|
||||
#define CL_DVFS_I2C_VDD_REG_ADDR_0 0x44
|
||||
#define CL_DVFS_I2C_STS_0 0x48
|
||||
#define CL_DVFS_INTR_STS_0 0x5C
|
||||
#define CL_DVFS_INTR_EN_0 0x60
|
||||
#define DVFS_DFLL_THROTTLE_CTRL_0 0x64
|
||||
#define DVFS_DFLL_THROTTLE_LIGHT_0 0x68
|
||||
#define DVFS_DFLL_THROTTLE_MEDIUM_0 0x6C
|
||||
#define DVFS_DFLL_THROTTLE_HEAVY_0 0x70
|
||||
#define CL_DVFS_I2C_CLK_DIVISOR_REGISTER_0 0x16C
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -102,22 +102,12 @@ typedef enum
|
||||
SysClkPartLoad_EMC = 0,
|
||||
SysClkPartLoad_EMCCpu,
|
||||
HocClkPartLoad_GPU,
|
||||
HocClkPartLoad_CPUAvg,
|
||||
HocClkPartLoad_CPUMax,
|
||||
HocClkPartLoad_BAT,
|
||||
HocClkPartLoad_FAN,
|
||||
SysClkPartLoad_EnumMax
|
||||
} SysClkPartLoad;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ReverseNX_NotFound = 0,
|
||||
ReverseNX_SystemDefault = 0,
|
||||
ReverseNX_Handheld,
|
||||
ReverseNX_Docked,
|
||||
} ReverseNXMode;
|
||||
|
||||
|
||||
typedef enum {
|
||||
HorizonOCSpeedo_CPU = 0,
|
||||
HorizonOCSpeedo_GPU,
|
||||
@@ -132,6 +122,36 @@ typedef enum {
|
||||
GPUUVLevel_EnumMax,
|
||||
} GPUUndervoltLevel;
|
||||
|
||||
enum {
|
||||
DVFSMode_Disabled = 0,
|
||||
DVFSMode_Hijack,
|
||||
// DVFSMode_OfficialService,
|
||||
// DVFSMode_Hack,
|
||||
DVFSMode_EnumMax,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GpuSchedulingMode_DoNotOverride = 0,
|
||||
GpuSchedulingMode_Enabled,
|
||||
GpuSchedulingMode_Disabled,
|
||||
GpuSchedulingMode_EnumMax,
|
||||
} GpuSchedulingMode;
|
||||
|
||||
typedef enum {
|
||||
GpuSchedulingOverrideMethod_Ini = 0,
|
||||
GpuSchedulingOverrideMethod_NvService,
|
||||
GpuSchedulingOverrideMethod_EnumMax,
|
||||
} GpuSchedulingOverrideMethod;
|
||||
|
||||
typedef enum {
|
||||
GovernorState_DoNotOverride = 0,
|
||||
GovernorState_Disabled,
|
||||
GovernorState_Enabled_CpuGpu,
|
||||
GovernorState_Enabled_Cpu,
|
||||
GovernorState_Enabled_Gpu,
|
||||
GovernorState_EnumMax,
|
||||
} GovernorState;
|
||||
|
||||
#define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
|
||||
|
||||
static inline const char* sysclkFormatModule(SysClkModule module, bool pretty)
|
||||
|
||||
@@ -48,11 +48,8 @@ Result sysclkIpcSetProfiles(u64 tid, SysClkTitleProfileList* profiles);
|
||||
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues);
|
||||
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues);
|
||||
Result sysclkIpcGetFreqList(SysClkModule module, u32* list, u32 maxCount, u32* outCount);
|
||||
Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode);
|
||||
Result hocClkIpcSetKipData();
|
||||
Result hocClkIpcGetKipData();
|
||||
Result hocClkIpcUpdateEmcRegs();
|
||||
Result hocClkIpcCalculateGpuVmin();
|
||||
|
||||
static inline Result sysclkIpcRemoveOverride(SysClkModule module)
|
||||
{
|
||||
|
||||
@@ -43,10 +43,12 @@ typedef struct
|
||||
uint32_t voltages[HocClkVoltage_EnumMax];
|
||||
u16 speedos[HorizonOCSpeedo_EnumMax];
|
||||
u16 iddq[HorizonOCSpeedo_EnumMax];
|
||||
GpuSchedulingMode gpuSchedulingMode;
|
||||
bool isSysDockInstalled;
|
||||
u8 maxDisplayFreq;
|
||||
u8 fps;
|
||||
u8 dramID;
|
||||
bool isDram8GB;
|
||||
u8 fps;
|
||||
} SysClkContext;
|
||||
|
||||
typedef struct
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -51,20 +51,26 @@ typedef enum {
|
||||
|
||||
HocClkConfigValue_LiteTDPLimit,
|
||||
|
||||
HocClkConfigValue_EnforceBoardLimit,
|
||||
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
|
||||
HorizonOCConfigValue_OverwriteRefreshRate,
|
||||
HorizonOCConfigValue_EnableUnsafeDisplayFreqs,
|
||||
HocClkConfigValue_FixCpuVoltBug,
|
||||
|
||||
HorizonOCConfigValue_DVFSMode,
|
||||
HorizonOCConfigValue_DVFSOffset,
|
||||
HorizonOCConfigValue_LiveCpuUv,
|
||||
HorizonOCConfigValue_EnableExperimentalSettings,
|
||||
|
||||
HorizonOCConfigValue_GPUScheduling,
|
||||
HorizonOCConfigValue_GPUSchedulingMethod,
|
||||
KipConfigValue_custRev,
|
||||
// KipConfigValue_mtcConf,
|
||||
KipConfigValue_hpMode,
|
||||
|
||||
KipConfigValue_commonEmcMemVolt,
|
||||
KipConfigValue_eristaEmcMaxClock,
|
||||
KipConfigValue_eristaEmcMaxClock1,
|
||||
KipConfigValue_eristaEmcMaxClock2,
|
||||
KipConfigValue_marikoEmcMaxClock,
|
||||
KipConfigValue_marikoEmcVddqVolt,
|
||||
KipConfigValue_emcDvbShift,
|
||||
@@ -158,6 +164,9 @@ typedef enum {
|
||||
KipConfigValue_g_volt_e_1036800,
|
||||
KipConfigValue_g_volt_e_1075200,
|
||||
|
||||
KipConfigValue_t6_tRTW_fine_tune,
|
||||
KipConfigValue_t7_tWTR_fine_tune,
|
||||
|
||||
KipCrc32,
|
||||
HocClkConfigValue_IsFirstLoad,
|
||||
SysClkConfigValue_EnumMax,
|
||||
@@ -208,21 +217,33 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
||||
case HocClkConfigValue_LiteTDPLimit:
|
||||
return pretty ? "Handheld TDP Limit" : "tdp_limit_l";
|
||||
|
||||
case HocClkConfigValue_EnforceBoardLimit:
|
||||
return pretty ? "Enforce Board Limit" : "enforce_board_limit";
|
||||
|
||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||
return pretty ? "Battery Charge Current" : "bat_charge_current";
|
||||
|
||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||
return pretty ? "Display Refresh Rate Changing" : "drr_changing";
|
||||
|
||||
case HocClkConfigValue_FixCpuVoltBug:
|
||||
return pretty ? "Fix CPU Volt Bug" : "cpu_volt_bugfix";
|
||||
|
||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||
return pretty ? "Enable Unsafe Display Frequencies" : "drr_unsafe";
|
||||
|
||||
case HorizonOCConfigValue_DVFSMode:
|
||||
return pretty ? "DVFS Mode" : "dvfs_mode";
|
||||
|
||||
case HorizonOCConfigValue_DVFSOffset:
|
||||
return pretty ? "DVFS Offset" : "dvfs_offset";
|
||||
|
||||
case HorizonOCConfigValue_GPUScheduling:
|
||||
return pretty ? "GPU Scheduling" : "gpu_scheduling";
|
||||
|
||||
case HorizonOCConfigValue_GPUSchedulingMethod:
|
||||
return pretty ? "GPU Scheduling Method" : "gpu_sched_method";
|
||||
|
||||
case HorizonOCConfigValue_LiveCpuUv:
|
||||
return pretty ? "Live CPU Undervolt" : "live_cpu_uv";
|
||||
|
||||
case HorizonOCConfigValue_EnableExperimentalSettings:
|
||||
return pretty ? "Enable Experimental Settings" : "enable_experimental_settings";
|
||||
|
||||
// KIP config values
|
||||
case KipConfigValue_custRev:
|
||||
return pretty ? "Custom Revision" : "kip_cust_rev";
|
||||
@@ -235,7 +256,11 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
||||
case KipConfigValue_commonEmcMemVolt:
|
||||
return pretty ? "Common EMC/MEM Voltage" : "common_emc_mem_volt";
|
||||
case KipConfigValue_eristaEmcMaxClock:
|
||||
return pretty ? "Erista EMC Max Clock" : "erista_emc_max_clock";
|
||||
return pretty ? "Erista EMC Max Clock 1" : "erista_emc_max_clock";
|
||||
case KipConfigValue_eristaEmcMaxClock1:
|
||||
return pretty ? "Erista EMC Max Clock 2" : "erista_emc_max_clock1";
|
||||
case KipConfigValue_eristaEmcMaxClock2:
|
||||
return pretty ? "Erista EMC Max Clock 3" : "erista_emc_max_clock2";
|
||||
case KipConfigValue_marikoEmcMaxClock:
|
||||
return pretty ? "Mariko EMC Max Clock" : "mariko_emc_max_clock";
|
||||
case KipConfigValue_marikoEmcVddqVolt:
|
||||
@@ -370,6 +395,8 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
||||
case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400";
|
||||
case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800";
|
||||
case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200";
|
||||
case KipConfigValue_t6_tRTW_fine_tune: return pretty ? "t6 - tRTW Fine Tune" : "t6_tRTW_fine_fune";
|
||||
case KipConfigValue_t7_tWTR_fine_tune: return pretty ? "t7 - tWTR Fine Tune" : "t7_tWTR_fine_tune";
|
||||
case KipCrc32:
|
||||
return pretty ? "CRC32" : "crc32";
|
||||
case HocClkConfigValue_IsFirstLoad:
|
||||
@@ -394,6 +421,9 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
|
||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||
case HorizonOCConfigValue_GPUScheduling:
|
||||
case HorizonOCConfigValue_LiveCpuUv:
|
||||
case HorizonOCConfigValue_GPUSchedulingMethod:
|
||||
return 0ULL;
|
||||
case HocClkConfigValue_EristaMaxCpuClock:
|
||||
return 1785ULL;
|
||||
@@ -403,9 +433,8 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
|
||||
|
||||
case HocClkConfigValue_ThermalThrottle:
|
||||
case HocClkConfigValue_HandheldTDP:
|
||||
case HocClkConfigValue_EnforceBoardLimit:
|
||||
case HocClkConfigValue_FixCpuVoltBug:
|
||||
case HocClkConfigValue_IsFirstLoad:
|
||||
case HorizonOCConfigValue_DVFSMode:
|
||||
return 1ULL;
|
||||
case HocClkConfigValue_ThermalThrottleThreshold:
|
||||
return 70ULL;
|
||||
@@ -429,7 +458,7 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
||||
case HocClkConfigValue_LiteTDPLimit:
|
||||
case SysClkConfigValue_PollingIntervalMs:
|
||||
return input > 0;
|
||||
|
||||
|
||||
case SysClkConfigValue_TempLogIntervalMs:
|
||||
case SysClkConfigValue_FreqLogIntervalMs:
|
||||
case SysClkConfigValue_PowerLogIntervalMs:
|
||||
@@ -438,18 +467,21 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
||||
case HocClkConfigValue_OverwriteBoostMode:
|
||||
case HocClkConfigValue_ThermalThrottle:
|
||||
case HocClkConfigValue_HandheldTDP:
|
||||
case HocClkConfigValue_EnforceBoardLimit:
|
||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||
case HocClkConfigValue_FixCpuVoltBug:
|
||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||
case HocClkConfigValue_IsFirstLoad:
|
||||
case HorizonOCConfigValue_EnableExperimentalSettings:
|
||||
case HorizonOCConfigValue_LiveCpuUv:
|
||||
case HorizonOCConfigValue_GPUSchedulingMethod:
|
||||
return (input & 0x1) == input;
|
||||
|
||||
|
||||
case KipConfigValue_custRev:
|
||||
// case KipConfigValue_mtcConf:
|
||||
case KipConfigValue_hpMode:
|
||||
case KipConfigValue_commonEmcMemVolt:
|
||||
case KipConfigValue_eristaEmcMaxClock:
|
||||
case KipConfigValue_eristaEmcMaxClock1:
|
||||
case KipConfigValue_eristaEmcMaxClock2:
|
||||
case KipConfigValue_marikoEmcMaxClock:
|
||||
case KipConfigValue_marikoEmcVddqVolt:
|
||||
case KipConfigValue_emcDvbShift:
|
||||
@@ -534,7 +566,12 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
||||
case KipConfigValue_g_volt_e_1075200:
|
||||
case KipConfigValue_eristaCpuVmin:
|
||||
case KipConfigValue_eristaCpuUnlock:
|
||||
case KipConfigValue_t6_tRTW_fine_tune:
|
||||
case KipConfigValue_t7_tWTR_fine_tune:
|
||||
case KipCrc32:
|
||||
case HorizonOCConfigValue_DVFSMode:
|
||||
case HorizonOCConfigValue_DVFSOffset:
|
||||
case HorizonOCConfigValue_GPUScheduling:
|
||||
return true;
|
||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||
return ((input >= 1024) && (input <= 3072)) || !input;
|
||||
|
||||
@@ -48,11 +48,8 @@ enum SysClkIpcCmd
|
||||
SysClkIpcCmd_GetConfigValues = 9,
|
||||
SysClkIpcCmd_SetConfigValues = 10,
|
||||
SysClkIpcCmd_GetFreqList = 11,
|
||||
SysClkIpcCmd_SetReverseNXRTMode = 12,
|
||||
HocClkIpcCmd_SetKipData = 13,
|
||||
HocClkIpcCmd_GetKipData = 14,
|
||||
HocClkIpcCmd_UpdateEmcRegs = 15,
|
||||
HocClkIpcCmd_CalculateGpuVmin = 16,
|
||||
HocClkIpcCmd_SetKipData = 12,
|
||||
HocClkIpcCmd_GetKipData = 13,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -153,12 +153,6 @@ Result sysclkIpcGetFreqList(SysClkModule module, u32* list, u32 maxCount, u32* o
|
||||
);
|
||||
}
|
||||
|
||||
Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode)
|
||||
{
|
||||
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_SetReverseNXRTMode, mode);
|
||||
}
|
||||
|
||||
|
||||
Result hocClkIpcSetKipData()
|
||||
{
|
||||
u32 temp = 0;
|
||||
@@ -169,15 +163,4 @@ Result hocClkIpcGetKipData()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
||||
}
|
||||
|
||||
Result hocClkIpcUpdateEmcRegs()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_UpdateEmcRegs, temp);
|
||||
}
|
||||
Result hocClkIpcCalculateGpuVmin()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_CalculateGpuVmin, temp);
|
||||
}
|
||||
@@ -42,10 +42,23 @@ static bool g_canChangeRefreshRateDocked = false;
|
||||
static uint8_t g_lastVActiveSet = 0;
|
||||
|
||||
// Refresh rate tables
|
||||
static const uint8_t g_dockedRefreshRates[] = {40, 45, 50, 55, 60, 70, 72, 75, 80, 90, 95, 100, 110, 120};
|
||||
static bool g_dockedAllowed[14] = {0};
|
||||
static bool g_dockedAllowed720p[14] = {0};
|
||||
static const uint8_t g_dockedRefreshRates[] = {40, 45, 50, 55, 60, 70, 72, 75, 80, 90, 95, 100, 110, 120, 130, 140, 144, 150, 160, 165, 170, 180, 190, 200, 210, 220, 230, 240};
|
||||
// Calculate with this tool:
|
||||
|
||||
// https://tomverbeure.github.io/video_timings_calculator?horiz_pixels=1920&vert_pixels=1080&refresh_rate=240&margins=false&interlaced=false&bpc=8&color_fmt=rgb444&video_opt=false&custom_hblank=80&custom_vblank=6
|
||||
|
||||
/*
|
||||
typedef struct {
|
||||
uint16_t hFrontPorch;
|
||||
uint8_t hSyncWidth;
|
||||
uint8_t hBackPorch;
|
||||
uint8_t vFrontPorch;
|
||||
uint8_t vSyncWidth;
|
||||
uint8_t vBackPorch;
|
||||
uint8_t VIC;
|
||||
uint32_t pixelClock_kHz;
|
||||
} DockedTimings;
|
||||
*/
|
||||
static const DockedTimings g_dockedTimings1080p[] = {
|
||||
{8, 32, 40, 7, 8, 6, 0, 88080}, // 40Hz
|
||||
{8, 32, 40, 9, 8, 6, 0, 99270}, // 45Hz
|
||||
@@ -60,7 +73,21 @@ static const DockedTimings g_dockedTimings1080p[] = {
|
||||
{8, 32, 40, 36, 8, 6, 0, 214700}, // 95Hz
|
||||
{528, 44, 148, 4, 5, 36, 64, 297000}, // 100Hz
|
||||
{8, 32, 40, 44, 8, 6, 0, 250360}, // 110Hz
|
||||
{88, 44, 148, 4, 5, 36, 63, 297000} // 120Hz
|
||||
{88, 44, 148, 4, 5, 36, 63, 297000}, // 120Hz
|
||||
{8, 32, 40, 55, 8, 6, 0, 298750}, //130Hz CVT-RBv2
|
||||
{8, 32, 40, 61, 8, 6, 0, 323400}, //140Hz CVT-RBv2
|
||||
{8, 32, 40, 63, 8, 6, 0, 333216}, //144Hz CVT-RBv2
|
||||
{8, 32, 40, 67, 8, 6, 0, 348300}, //150Hz CVT-RBv2
|
||||
{8, 32, 40, 72, 8, 6, 0, 373120}, //160Hz CVT-RBv2
|
||||
{8, 32, 40, 75, 8, 6, 0, 385770}, //165Hz CVT-RBv2
|
||||
{8, 32, 40, 78, 8, 6, 0, 398480}, //170Hz CVT-RBv2
|
||||
{8, 32, 40, 84, 8, 6, 0, 424080}, //180Hz CVT-RBv2
|
||||
{8, 32, 40, 90, 8, 6, 0, 449920}, //190Hz CVT-RBv2
|
||||
{8, 32, 40, 96, 8, 6, 0, 476000}, //200Hz CVT-RBv2
|
||||
{8, 32, 40, 102, 8, 6, 0, 502320}, //210Hz CVT-RBv2
|
||||
{8, 32, 40, 108, 8, 6, 0, 528880}, //220Hz CVT-RBv2
|
||||
{8, 32, 40, 114, 8, 6, 0, 555680}, //230Hz CVT-RBv2
|
||||
{8, 32, 40, 121, 8, 6, 0, 583200}, //240Hz CVT-RBv2
|
||||
};
|
||||
|
||||
static const HandheldTimings g_handheldTimingsRETRO[] = {
|
||||
@@ -81,15 +108,6 @@ static uint8_t _getDockedRefreshRateIterator(uint32_t refreshRate) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
static void _setDefaultDockedSettings(void) {
|
||||
memset(g_dockedAllowed, 0, sizeof(g_dockedAllowed));
|
||||
g_dockedAllowed[_getDockedRefreshRateIterator(50)] = true;
|
||||
g_dockedAllowed[_getDockedRefreshRateIterator(60)] = true;
|
||||
memset(g_dockedAllowed720p, 0, sizeof(g_dockedAllowed720p));
|
||||
g_dockedAllowed720p[_getDockedRefreshRateIterator(50)] = true;
|
||||
g_dockedAllowed720p[_getDockedRefreshRateIterator(60)] = true;
|
||||
}
|
||||
|
||||
static void _changeOledElvssSettings(const uint32_t* offsets, const uint32_t* value, uint32_t size, uint32_t start) {
|
||||
if (!g_config.dsiVirtAddr || !value || !size) return;
|
||||
|
||||
@@ -126,13 +144,14 @@ static void _changeOledElvssSettings(const uint32_t* offsets, const uint32_t* va
|
||||
dsi[DSI_VIDEO_MODE_CONTROL] = false;
|
||||
svcSleepThread(20000000);
|
||||
}
|
||||
|
||||
void DisplayRefresh_SetDockedState(bool isDocked) {
|
||||
g_config.isDocked = isDocked;
|
||||
}
|
||||
|
||||
bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config) {
|
||||
if (!config) return false;
|
||||
|
||||
g_config = *config;
|
||||
_setDefaultDockedSettings();
|
||||
g_initialized = true;
|
||||
return true;
|
||||
}
|
||||
@@ -180,69 +199,20 @@ void DisplayRefresh_CorrectOledGamma(uint32_t refresh_rate) {
|
||||
}
|
||||
|
||||
void DisplayRefresh_SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p) {
|
||||
struct {
|
||||
unsigned int Hz_40: 1;
|
||||
unsigned int Hz_45: 1;
|
||||
unsigned int Hz_50: 1;
|
||||
unsigned int Hz_55: 1;
|
||||
unsigned int Hz_60: 1;
|
||||
unsigned int Hz_70: 1;
|
||||
unsigned int Hz_72: 1;
|
||||
unsigned int Hz_75: 1;
|
||||
unsigned int Hz_80: 1;
|
||||
unsigned int Hz_90: 1;
|
||||
unsigned int Hz_95: 1;
|
||||
unsigned int Hz_100: 1;
|
||||
unsigned int Hz_110: 1;
|
||||
unsigned int Hz_120: 1;
|
||||
unsigned int reserved: 18;
|
||||
} rates;
|
||||
|
||||
memcpy(&rates, &refreshRates, 4);
|
||||
|
||||
bool* target = is720p ? g_dockedAllowed720p : g_dockedAllowed;
|
||||
target[_getDockedRefreshRateIterator(40)] = rates.Hz_40;
|
||||
target[_getDockedRefreshRateIterator(45)] = rates.Hz_45;
|
||||
target[_getDockedRefreshRateIterator(50)] = rates.Hz_50;
|
||||
target[_getDockedRefreshRateIterator(55)] = rates.Hz_55;
|
||||
target[_getDockedRefreshRateIterator(60)] = true;
|
||||
target[_getDockedRefreshRateIterator(70)] = rates.Hz_70;
|
||||
target[_getDockedRefreshRateIterator(72)] = rates.Hz_72;
|
||||
target[_getDockedRefreshRateIterator(75)] = rates.Hz_75;
|
||||
target[_getDockedRefreshRateIterator(80)] = rates.Hz_80;
|
||||
target[_getDockedRefreshRateIterator(90)] = rates.Hz_90;
|
||||
target[_getDockedRefreshRateIterator(95)] = rates.Hz_95;
|
||||
target[_getDockedRefreshRateIterator(100)] = rates.Hz_100;
|
||||
target[_getDockedRefreshRateIterator(110)] = rates.Hz_110;
|
||||
target[_getDockedRefreshRateIterator(120)] = rates.Hz_120;
|
||||
// Function kept for API compatibility but does nothing
|
||||
(void)refreshRates;
|
||||
(void)is720p;
|
||||
}
|
||||
|
||||
uint8_t DisplayRefresh_GetDockedHighestAllowed(void) {
|
||||
const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]);
|
||||
|
||||
if (g_lastVActive == 1080) {
|
||||
for (int i = numRates - 1; g_dockedRefreshRates[i] > 60; i--) {
|
||||
if (g_dockedAllowed[i])
|
||||
return (g_dockedRefreshRates[i] > g_dockedHighestRefreshRate) ? g_dockedHighestRefreshRate : g_dockedRefreshRates[i];
|
||||
}
|
||||
} else if (g_lastVActive == 720) {
|
||||
for (int i = numRates - 1; g_dockedRefreshRates[i] > 60; i--) {
|
||||
if (g_dockedAllowed720p[i])
|
||||
return (g_dockedRefreshRates[i] > g_dockedHighestRefreshRate) ? g_dockedHighestRefreshRate : g_dockedRefreshRates[i];
|
||||
}
|
||||
}
|
||||
return 60;
|
||||
return (g_dockedHighestRefreshRate > 60) ? g_dockedHighestRefreshRate : 60;
|
||||
}
|
||||
|
||||
static void _getDockedHighestRefreshRate(uint32_t fd_in) {
|
||||
uint8_t highestRefreshRate = 60;
|
||||
uint32_t fd = fd_in;
|
||||
|
||||
if (!fd && nvOpen(&fd, "/dev/nvdisp-disp1")) {
|
||||
g_dockedHighestRefreshRate = 60;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!fd) nvOpen(&fd, "/dev/nvdisp-disp1");
|
||||
NvdcModeDB2 db2 = {0};
|
||||
int rc = nvIoctl(fd, NVDISP_GET_MODE_DB2, &db2);
|
||||
|
||||
@@ -288,8 +258,8 @@ static void _getDockedHighestRefreshRate(uint32_t fd_in) {
|
||||
rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux);
|
||||
if (rc == 0) {
|
||||
g_dockedLinkRate = dpaux.set.link_rate;
|
||||
if (display_b.hActive == 1920 && display_b.vActive == 1080 && highestRefreshRate > 75 && dpaux.set.link_rate < 20)
|
||||
highestRefreshRate = 75;
|
||||
// if (display_b.hActive == 1920 && display_b.vActive == 1080 && highestRefreshRate > 75 && dpaux.set.link_rate < 20 && )
|
||||
// highestRefreshRate = 75;
|
||||
}
|
||||
|
||||
if (!fd_in) nvClose(fd);
|
||||
@@ -403,10 +373,6 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
||||
|
||||
if (display_b.vActive != g_lastVActiveSet) {
|
||||
g_lastVActiveSet = display_b.vActive;
|
||||
if (display_b.vActive != 720 && display_b.vActive != 1080) {
|
||||
memset(g_dockedAllowed, 0, sizeof(g_dockedAllowed));
|
||||
g_dockedAllowed[_getDockedRefreshRateIterator(60)] = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch;
|
||||
@@ -416,15 +382,13 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
||||
int8_t itr = -1;
|
||||
const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]);
|
||||
|
||||
// Find closest matching refresh rate
|
||||
if ((new_refreshRate <= 60) && ((60 % new_refreshRate) == 0)) {
|
||||
itr = _getDockedRefreshRateIterator(60);
|
||||
}
|
||||
|
||||
if (itr == -1) {
|
||||
for (size_t i = 0; i < numRates; i++) {
|
||||
bool* allowed = (display_b.vActive == 720) ? g_dockedAllowed720p : g_dockedAllowed;
|
||||
if (allowed[i] != true) continue;
|
||||
|
||||
uint8_t val = g_dockedRefreshRates[i];
|
||||
if ((val % new_refreshRate) == 0) {
|
||||
itr = i;
|
||||
@@ -437,9 +401,8 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
||||
if (!g_config.matchLowestDocked) {
|
||||
itr = _getDockedRefreshRateIterator(60);
|
||||
} else {
|
||||
bool* allowed = (display_b.vActive == 1080) ? g_dockedAllowed : g_dockedAllowed720p;
|
||||
for (size_t i = 0; i < numRates; i++) {
|
||||
if ((allowed[i] == true) && (new_refreshRate < g_dockedRefreshRates[i])) {
|
||||
if (new_refreshRate < g_dockedRefreshRates[i]) {
|
||||
itr = i;
|
||||
break;
|
||||
}
|
||||
@@ -449,15 +412,13 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
||||
|
||||
if (itr == -1) itr = _getDockedRefreshRateIterator(60);
|
||||
|
||||
bool increase = refreshRateNow < g_dockedRefreshRates[itr];
|
||||
bool* allowed = (display_b.vActive == 720) ? g_dockedAllowed720p : g_dockedAllowed;
|
||||
|
||||
while(itr >= 0 && itr < (int8_t)numRates && allowed[itr] != true) {
|
||||
if (!g_config.displaySyncDocked) {
|
||||
if (increase) itr++;
|
||||
else itr--;
|
||||
} else {
|
||||
itr++;
|
||||
// Clamp to highest allowed refresh rate
|
||||
if (g_dockedRefreshRates[itr] > g_dockedHighestRefreshRate) {
|
||||
for (int8_t i = itr; i >= 0; i--) {
|
||||
if (g_dockedRefreshRates[i] <= g_dockedHighestRefreshRate) {
|
||||
itr = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,8 +590,7 @@ bool DisplayRefresh_SetRate(uint32_t new_refreshRate) {
|
||||
|
||||
bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal) {
|
||||
if (!out_refreshRate || !g_initialized || !g_config.clkVirtAddr) return false;
|
||||
|
||||
uint32_t value = 60;
|
||||
static uint32_t value = 60;
|
||||
|
||||
if (g_config.isRetroSUPER && !g_config.isDocked) {
|
||||
uint32_t fd = 0;
|
||||
@@ -705,7 +665,10 @@ bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(internal) {
|
||||
*out_refreshRate = value;
|
||||
return true;
|
||||
}
|
||||
uint32_t fd = 0;
|
||||
if (!nvOpen(&fd, "/dev/nvdisp-disp1")) {
|
||||
NvdcMode2 display_b = {0};
|
||||
|
||||
83
Source/sys-clk/common/src/memmem.c
Normal file
83
Source/sys-clk/common/src/memmem.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Roy Merkel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "memmem.h"
|
||||
|
||||
void *memmem_impl(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
|
||||
{
|
||||
const unsigned char *cmpp;
|
||||
const unsigned char *p;
|
||||
const unsigned char *endp;
|
||||
const unsigned char *q;
|
||||
const unsigned char *endq;
|
||||
unsigned char found;
|
||||
|
||||
if(haystack == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(needle == NULL)
|
||||
{
|
||||
return (void*)haystack;
|
||||
}
|
||||
if(haystacklen == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(needlelen == 0)
|
||||
{
|
||||
return (void*)haystack;
|
||||
}
|
||||
|
||||
if(needlelen > haystacklen)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
endp = haystack + haystacklen - needlelen;
|
||||
endq = needle + needlelen;
|
||||
for(p = haystack; p <= endp; p++)
|
||||
{
|
||||
found = 1;
|
||||
cmpp = p;
|
||||
for(q = needle; q < endq; q++)
|
||||
{
|
||||
if(*cmpp != *q)
|
||||
{
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmpp++;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
{
|
||||
return (void*)p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk
|
||||
# version control constants
|
||||
#---------------------------------------------------------------------------------
|
||||
#TARGET_VERSION := $(shell git describe --dirty --always --tags)
|
||||
APP_VERSION := 0.35
|
||||
APP_VERSION := 0.40
|
||||
TARGET_VERSION := $(APP_VERSION)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
@@ -55,7 +55,7 @@ CFLAGS := -Os -Wall -flto -fdata-sections -ffunction-sections -fno-rtti -fno-com
|
||||
CFLAGS += $(INCLUDE) -D__SWITCH__
|
||||
|
||||
# Enable appearance overriding
|
||||
UI_OVERRIDE_PATH := /config/sys-clk/
|
||||
UI_OVERRIDE_PATH := /config/horizon-oc/
|
||||
CFLAGS += -DUI_OVERRIDE_PATH="\"$(UI_OVERRIDE_PATH)\""
|
||||
|
||||
# Disable fstream
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
tsl::elm::ListItem* SpeedoItem = NULL;
|
||||
tsl::elm::ListItem* IddqItem = NULL;
|
||||
tsl::elm::ListItem* sysdockStatusItem = NULL;
|
||||
ImageElement* CatImage = NULL;
|
||||
HideableCategoryHeader* CatHeader = NULL;
|
||||
HideableCustomDrawer* CatSpacer = NULL;
|
||||
@@ -41,17 +42,21 @@ AboutGui::~AboutGui()
|
||||
void AboutGui::listUI()
|
||||
{
|
||||
this->listElement->addItem(
|
||||
new tsl::elm::CategoryHeader("Speedo/IDDQ")
|
||||
new tsl::elm::CategoryHeader("Information")
|
||||
);
|
||||
|
||||
SpeedoItem =
|
||||
new tsl::elm::ListItem("Speedos:");
|
||||
new tsl::elm::ListItem("Speedo:");
|
||||
this->listElement->addItem(SpeedoItem);
|
||||
|
||||
IddqItem =
|
||||
new tsl::elm::ListItem("IDDQ:");
|
||||
this->listElement->addItem(IddqItem);
|
||||
|
||||
sysdockStatusItem =
|
||||
new tsl::elm::ListItem("sys-dock status:");
|
||||
this->listElement->addItem(sysdockStatusItem);
|
||||
|
||||
this->listElement->addItem(
|
||||
new tsl::elm::CategoryHeader("Credits")
|
||||
);
|
||||
@@ -221,4 +226,5 @@ void AboutGui::refresh()
|
||||
sprintf(strings[1], "%u/%u/%u", this->context->iddq[HorizonOCSpeedo_CPU], this->context->iddq[HorizonOCSpeedo_GPU], this->context->iddq[HorizonOCSpeedo_SOC]);
|
||||
SpeedoItem->setValue(strings[0]);
|
||||
IddqItem->setValue(strings[1]);
|
||||
sysdockStatusItem->setValue(this->context->isSysDockInstalled ? "Installed" : "Not Installed");
|
||||
}
|
||||
@@ -95,7 +95,8 @@ void AppProfileGui::openValueChoiceGui(
|
||||
enableThresholds,
|
||||
labels,
|
||||
namedValues,
|
||||
showDefaultValue
|
||||
showDefaultValue,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@@ -148,6 +149,36 @@ void AppProfileGui::addModuleListItemToggle(SysClkProfile profile, SysClkModule
|
||||
this->listElement->addItem(toggle);
|
||||
}
|
||||
|
||||
std::string AppProfileGui::formatValueDisplay(
|
||||
std::uint32_t value,
|
||||
const std::vector<NamedValue>& namedValues,
|
||||
const std::string& suffix,
|
||||
std::uint32_t divisor,
|
||||
int decimalPlaces
|
||||
)
|
||||
{
|
||||
if (value == 0) {
|
||||
return FREQ_DEFAULT_TEXT;
|
||||
}
|
||||
|
||||
if (!namedValues.empty()) {
|
||||
for (const auto& namedValue : namedValues) {
|
||||
if (namedValue.value == value) {
|
||||
return namedValue.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
if (decimalPlaces > 0) {
|
||||
double displayValue = (double)value / divisor;
|
||||
snprintf(buf, sizeof(buf), "%.*f%s", decimalPlaces, displayValue, suffix.c_str());
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%u%s", value / divisor, suffix.c_str());
|
||||
}
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void AppProfileGui::addModuleListItemValue(
|
||||
SysClkProfile profile,
|
||||
SysClkModule module,
|
||||
@@ -158,26 +189,17 @@ void AppProfileGui::addModuleListItemValue(
|
||||
const std::string& suffix,
|
||||
std::uint32_t divisor,
|
||||
int decimalPlaces,
|
||||
ValueThresholds thresholds
|
||||
ValueThresholds thresholds,
|
||||
std::vector<NamedValue> namedValues,
|
||||
bool showDefaultValue
|
||||
)
|
||||
{
|
||||
tsl::elm::ListItem* listItem =
|
||||
new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
||||
|
||||
std::uint32_t storedValue = this->profileList->mhzMap[profile][module];
|
||||
if (storedValue == 0) {
|
||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
||||
} else {
|
||||
char buf[32];
|
||||
if (decimalPlaces > 0) {
|
||||
double displayValue = (double)storedValue / divisor;
|
||||
snprintf(buf, sizeof(buf), "%.*f%s", decimalPlaces, displayValue, suffix.c_str());
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%u%s", storedValue / divisor, suffix.c_str());
|
||||
}
|
||||
listItem->setValue(buf);
|
||||
}
|
||||
|
||||
|
||||
listItem->setValue(this->formatValueDisplay(storedValue, namedValues, suffix, divisor, decimalPlaces));
|
||||
|
||||
listItem->setClickListener(
|
||||
[this,
|
||||
listItem,
|
||||
@@ -190,13 +212,14 @@ void AppProfileGui::addModuleListItemValue(
|
||||
suffix,
|
||||
divisor,
|
||||
decimalPlaces,
|
||||
thresholds](u64 keys)
|
||||
thresholds,
|
||||
namedValues,
|
||||
showDefaultValue](u64 keys)
|
||||
{
|
||||
if ((keys & HidNpadButton_A) == HidNpadButton_A)
|
||||
{
|
||||
std::uint32_t currentValue =
|
||||
this->profileList->mhzMap[profile][module] * divisor;
|
||||
|
||||
ValueRange range(
|
||||
min,
|
||||
max,
|
||||
@@ -205,36 +228,19 @@ void AppProfileGui::addModuleListItemValue(
|
||||
divisor,
|
||||
decimalPlaces
|
||||
);
|
||||
|
||||
this->openValueChoiceGui(
|
||||
listItem,
|
||||
currentValue,
|
||||
range,
|
||||
categoryName,
|
||||
|
||||
[this, listItem, profile, module, divisor, suffix, decimalPlaces, thresholds](std::uint32_t value) -> bool
|
||||
[this, listItem, profile, module, divisor, suffix, decimalPlaces, thresholds, namedValues](std::uint32_t value) -> bool
|
||||
{
|
||||
this->profileList->mhzMap[profile][module] = value / divisor;
|
||||
|
||||
if (value == 0) {
|
||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
||||
} else {
|
||||
char buf[32];
|
||||
if (decimalPlaces > 0) {
|
||||
double displayValue = (double)value / divisor;
|
||||
snprintf(buf, sizeof(buf), "%.*f%s",
|
||||
decimalPlaces, displayValue, suffix.c_str());
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%u%s",
|
||||
value / divisor, suffix.c_str());
|
||||
}
|
||||
listItem->setValue(buf);
|
||||
}
|
||||
|
||||
listItem->setValue(this->formatValueDisplay(value / divisor, namedValues, suffix, divisor, decimalPlaces));
|
||||
|
||||
Result rc =
|
||||
sysclkIpcSetProfiles(this->applicationId,
|
||||
this->profileList);
|
||||
|
||||
if (R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode(
|
||||
@@ -243,58 +249,132 @@ void AppProfileGui::addModuleListItemValue(
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
thresholds,
|
||||
false
|
||||
false,
|
||||
{},
|
||||
namedValues,
|
||||
showDefaultValue
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ((keys & HidNpadButton_Y) == HidNpadButton_Y)
|
||||
{
|
||||
this->profileList->mhzMap[profile][module] = 0;
|
||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
||||
|
||||
Result rc =
|
||||
sysclkIpcSetProfiles(this->applicationId,
|
||||
this->profileList);
|
||||
|
||||
if (R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcSetProfiles", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this->listElement->addItem(listItem);
|
||||
}
|
||||
|
||||
void AppProfileGui::addProfileUI(SysClkProfile profile)
|
||||
{
|
||||
Result rc = sysclkIpcGetConfigValues(&configList); // idk why this is needed, probably some refreshing issue
|
||||
{
|
||||
BaseMenuGui::refresh();
|
||||
if(!this->context)
|
||||
return;
|
||||
Result rc = sysclkIpcGetConfigValues(&configList);
|
||||
if (R_FAILED(rc)) [[unlikely]] {
|
||||
FatalGui::openWithResultCode("sysclkIpcGetConfigValues", rc);
|
||||
return;
|
||||
}
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true) + std::string(" ") + ult::DIVIDER_SYMBOL + " Reset"));
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true) + std::string(" ") + ult::DIVIDER_SYMBOL + " \ue0e3 Reset"));
|
||||
this->addModuleListItem(profile, SysClkModule_CPU);
|
||||
this->addModuleListItem(profile, SysClkModule_GPU);
|
||||
this->addModuleListItem(profile, SysClkModule_MEM);
|
||||
#if IS_MINIMAL == 0
|
||||
ValueThresholds lcdThresholds(60, 65);
|
||||
if(!IsHoag() && configList.values[HorizonOCConfigValue_OverwriteRefreshRate]) {
|
||||
if(profile != SysClkProfile_Docked)
|
||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
||||
else
|
||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 50, 120, 5, " Hz", 1, 0);
|
||||
if(profile != SysClkProfile_Docked) {
|
||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
||||
} else {
|
||||
if(IsAula() && this->context->isSysDockInstalled) {
|
||||
std::vector<NamedValue> dockedFreqs = {
|
||||
NamedValue("40 Hz", 40),
|
||||
NamedValue("45 Hz", 45),
|
||||
NamedValue("50 Hz", 50),
|
||||
NamedValue("55 Hz", 55),
|
||||
NamedValue("60 Hz", 60),
|
||||
NamedValue("70 Hz", 70),
|
||||
NamedValue("72 Hz", 72),
|
||||
NamedValue("75 Hz", 75),
|
||||
NamedValue("80 Hz", 80),
|
||||
NamedValue("90 Hz", 90),
|
||||
NamedValue("95 Hz", 95),
|
||||
NamedValue("100 Hz", 100),
|
||||
NamedValue("110 Hz", 110),
|
||||
NamedValue("120 Hz", 120),
|
||||
NamedValue("130 Hz", 130),
|
||||
NamedValue("140 Hz", 140),
|
||||
NamedValue("144 Hz", 144),
|
||||
NamedValue("150 Hz", 150),
|
||||
NamedValue("160 Hz", 160),
|
||||
NamedValue("165 Hz", 165),
|
||||
NamedValue("170 Hz", 170),
|
||||
NamedValue("180 Hz", 180),
|
||||
NamedValue("190 Hz", 190),
|
||||
NamedValue("200 Hz", 200),
|
||||
NamedValue("210 Hz", 210),
|
||||
NamedValue("220 Hz", 220),
|
||||
NamedValue("230 Hz", 230),
|
||||
NamedValue("240 Hz", 240)
|
||||
};
|
||||
|
||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 40, 240, 1, " Hz", 1, 0, ValueThresholds(), dockedFreqs);
|
||||
} else if (IsAula() && !this->context->isSysDockInstalled) {
|
||||
std::vector<NamedValue> dockedFreqsLimited = {
|
||||
NamedValue("50 Hz", 50),
|
||||
NamedValue("55 Hz", 55),
|
||||
NamedValue("60 Hz", 60),
|
||||
NamedValue("65 Hz", 65),
|
||||
NamedValue("70 Hz", 70),
|
||||
NamedValue("72 Hz", 72),
|
||||
NamedValue("75 Hz", 75)
|
||||
};
|
||||
|
||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 50, 75, 1, " Hz", 1, 0, ValueThresholds(), dockedFreqsLimited);
|
||||
} else {
|
||||
std::vector<NamedValue> dockedFreqsStandard = {
|
||||
NamedValue("50 Hz", 50),
|
||||
NamedValue("55 Hz", 55),
|
||||
NamedValue("60 Hz", 60),
|
||||
NamedValue("65 Hz", 65),
|
||||
NamedValue("70 Hz", 70),
|
||||
NamedValue("72 Hz", 72),
|
||||
NamedValue("75 Hz", 75),
|
||||
NamedValue("80 Hz", 80),
|
||||
NamedValue("85 Hz", 85),
|
||||
NamedValue("90 Hz", 90),
|
||||
NamedValue("95 Hz", 95),
|
||||
NamedValue("100 Hz", 100),
|
||||
NamedValue("105 Hz", 105),
|
||||
NamedValue("110 Hz", 110),
|
||||
NamedValue("115 Hz", 115),
|
||||
NamedValue("120 Hz", 120)
|
||||
};
|
||||
|
||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 50, 120, 1, " Hz", 1, 0, ValueThresholds(), dockedFreqsStandard);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
this->addModuleListItemToggle(profile, HorizonOCModule_Governor);
|
||||
std::vector<NamedValue> governorSettings = {
|
||||
NamedValue("Do Not Override", GovernorState_DoNotOverride),
|
||||
NamedValue("Disabled", GovernorState_Disabled),
|
||||
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
|
||||
NamedValue("CPU", GovernorState_Enabled_Cpu),
|
||||
NamedValue("GPU", GovernorState_Enabled_Gpu),
|
||||
};
|
||||
|
||||
this->addModuleListItemValue(profile, HorizonOCModule_Governor, "Governor", 0, 0, 1, "", 1, 0, ValueThresholds(), governorSettings, false);
|
||||
}
|
||||
|
||||
void AppProfileGui::listUI()
|
||||
@@ -334,4 +414,4 @@ void AppProfileGui::update()
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,22 +23,17 @@
|
||||
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../ipc.h"
|
||||
#include "base_menu_gui.h"
|
||||
#include "freq_choice_gui.h"
|
||||
#include "value_choice_gui.h"
|
||||
#define SYSCLK_GLOBAL_PROFILE_TID 0xA111111111111111
|
||||
|
||||
class AppProfileGui : public BaseMenuGui
|
||||
{
|
||||
protected:
|
||||
std::uint64_t applicationId;
|
||||
SysClkTitleProfileList* profileList;
|
||||
|
||||
void openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module);
|
||||
void addModuleListItem(SysClkProfile profile, SysClkModule module);
|
||||
void addModuleListItemToggle(SysClkProfile profile, SysClkModule module);
|
||||
@@ -54,6 +49,13 @@ class AppProfileGui : public BaseMenuGui
|
||||
const std::vector<NamedValue>& namedValues = {},
|
||||
bool showDefaultValue = true
|
||||
);
|
||||
std::string formatValueDisplay(
|
||||
std::uint32_t value,
|
||||
const std::vector<NamedValue>& namedValues,
|
||||
const std::string& suffix,
|
||||
std::uint32_t divisor,
|
||||
int decimalPlaces
|
||||
);
|
||||
void addModuleListItemValue(
|
||||
SysClkProfile profile,
|
||||
SysClkModule module,
|
||||
@@ -64,14 +66,15 @@ class AppProfileGui : public BaseMenuGui
|
||||
const std::string& suffix,
|
||||
std::uint32_t divisor,
|
||||
int decimalPlaces,
|
||||
ValueThresholds thresholds = {}
|
||||
ValueThresholds thresholds,
|
||||
std::vector<NamedValue> namedValues = {},
|
||||
bool showDefaultValue = true
|
||||
);
|
||||
void addProfileUI(SysClkProfile profile);
|
||||
|
||||
public:
|
||||
AppProfileGui(std::uint64_t applicationId, SysClkTitleProfileList* profileList);
|
||||
~AppProfileGui();
|
||||
void listUI() override;
|
||||
static void changeTo(std::uint64_t applicationId);
|
||||
void update() override;
|
||||
};
|
||||
};
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -36,13 +36,13 @@ BaseMenuGui::BaseMenuGui() : tempColors{ tsl::Color(0), tsl::Color(0), tsl::Colo
|
||||
this->context = nullptr;
|
||||
this->lastContextUpdate = 0;
|
||||
this->listElement = nullptr;
|
||||
|
||||
|
||||
|
||||
|
||||
// Pre-cache hardware model during initialization
|
||||
IsAula();
|
||||
IsMariko();
|
||||
IsHoag();
|
||||
|
||||
|
||||
// Initialize display strings
|
||||
memset(displayStrings, 0, sizeof(displayStrings));
|
||||
}
|
||||
@@ -55,14 +55,14 @@ BaseMenuGui::~BaseMenuGui() {
|
||||
void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||
BaseGui::preDraw(renderer);
|
||||
if(!this->context) [[unlikely]] return;
|
||||
|
||||
|
||||
// All constants pre-calculated and cached
|
||||
static constexpr const char* const labels[] = {
|
||||
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "FAN", "DISP"
|
||||
};
|
||||
|
||||
static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
|
||||
|
||||
|
||||
static u32 labelWidths[10];
|
||||
static bool positionsInitialized = false;
|
||||
|
||||
@@ -77,29 +77,29 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||
static u32 maxProfileValueWidth = renderer->getTextDimensions("PD Charger", false, SMALL_TEXT_SIZE).first; // longest word
|
||||
|
||||
u32 y = 91;
|
||||
|
||||
|
||||
// === TOP SECTION ===
|
||||
renderer->drawRoundedRect(14, 70-1, 420, 30+2, 15.0f, renderer->aWithOpacity(tsl::tableBGColor));
|
||||
|
||||
|
||||
// App ID - use pre-formatted string
|
||||
renderer->drawString(labels[0], false, positions[0], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
renderer->drawString(displayStrings[0], false, positions[0] + labelWidths[0] + 9, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
||||
|
||||
|
||||
// Profile - use pre-formatted string
|
||||
renderer->drawString(labels[1], false, 423 - maxProfileValueWidth - labelWidths[1] - 9, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
renderer->drawString(displayStrings[1], false, 423 - maxProfileValueWidth, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
||||
|
||||
|
||||
y = 129; // Direct assignment instead of += 38
|
||||
|
||||
|
||||
// === MAIN DATA SECTION ===
|
||||
renderer->drawRoundedRect(14, 106, 420, 156, 10.0f, renderer->aWithOpacity(tsl::tableBGColor));
|
||||
|
||||
|
||||
// === FREQUENCY SECTION ===
|
||||
// Labels first (better cache locality)
|
||||
renderer->drawString(labels[2], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
renderer->drawString(labels[3], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
renderer->drawString(labels[4], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
|
||||
|
||||
// Current frequencies - use pre-formatted strings
|
||||
renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU
|
||||
renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU
|
||||
@@ -107,7 +107,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||
|
||||
y = 149; // Direct assignment (129 + 20)
|
||||
|
||||
// renderer->drawString(displayStrings[19], false, positions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU Usage
|
||||
renderer->drawString(displayStrings[19], false, positions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU Usage
|
||||
renderer->drawString(displayStrings[17], false, positions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU Usage
|
||||
renderer->drawString(displayStrings[18], false, positions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // RAM Usage
|
||||
|
||||
@@ -115,39 +115,39 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||
renderer->drawString(displayStrings[5], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real
|
||||
renderer->drawString(displayStrings[6], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real
|
||||
renderer->drawString(displayStrings[7], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM real
|
||||
|
||||
|
||||
y = 169; // Direct assignment (149 + 20)
|
||||
|
||||
|
||||
// === VOLTAGES ===
|
||||
renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage
|
||||
renderer->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage
|
||||
|
||||
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
|
||||
|
||||
|
||||
y = 191; // Direct assignment (169 + 22)
|
||||
|
||||
|
||||
// === TEMPERATURE SECTION ===
|
||||
// Labels
|
||||
renderer->drawString(labels[5], false, positions[5], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
renderer->drawString(labels[6], false, positions[6]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
renderer->drawString(labels[7], false, positions[7], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
|
||||
|
||||
// Temperatures with color - use pre-computed colors
|
||||
renderer->drawString(displayStrings[11], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_SOC]); // SOC
|
||||
renderer->drawString(displayStrings[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_PCB]); // PCB
|
||||
renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_Skin]); // Skin
|
||||
|
||||
|
||||
y = 211; // Direct assignment (191 + 20)
|
||||
|
||||
|
||||
renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
||||
|
||||
|
||||
// Power labels and values
|
||||
renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
renderer->drawString(labels[9], false, positions[9], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
|
||||
|
||||
renderer->drawString(displayStrings[15], false, dataPositions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power now
|
||||
renderer->drawString(displayStrings[16], false, dataPositions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power avg
|
||||
|
||||
|
||||
y+=20;
|
||||
|
||||
renderer->drawString(labels[10], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||
@@ -181,9 +181,9 @@ void BaseMenuGui::refresh()
|
||||
if (armTicksToNs(ticks - this->lastContextUpdate) <= 1000000000UL) [[likely]] {
|
||||
return; // Early exit for most calls
|
||||
}
|
||||
|
||||
|
||||
this->lastContextUpdate = ticks;
|
||||
|
||||
|
||||
// Lazy context allocation
|
||||
if (!this->context) [[unlikely]] {
|
||||
this->context = new SysClkContext;
|
||||
@@ -206,30 +206,30 @@ void BaseMenuGui::refresh()
|
||||
// === FORMAT ALL DISPLAY STRINGS (once per second) ===
|
||||
// App ID (hex conversion)
|
||||
sprintf(displayStrings[0], "%016lX", context->applicationId);
|
||||
|
||||
|
||||
// Profile
|
||||
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true));
|
||||
|
||||
|
||||
// Current frequencies
|
||||
u32 hz = context->freqs[SysClkModule_CPU]; // CPU
|
||||
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
|
||||
hz = context->freqs[SysClkModule_GPU]; // GPU
|
||||
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
hz = context->freqs[SysClkModule_MEM]; // MEM
|
||||
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
|
||||
// Real frequencies
|
||||
hz = context->realFreqs[SysClkModule_CPU]; // CPU
|
||||
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
|
||||
hz = context->realFreqs[SysClkModule_GPU]; // GPU
|
||||
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
|
||||
hz = context->realFreqs[SysClkModule_MEM]; // MEM
|
||||
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
|
||||
// Voltages
|
||||
sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0);
|
||||
sprintf(displayStrings[9], "%.1f mV", context->voltages[HocClkVoltage_GPU] / 1000.0);
|
||||
@@ -243,31 +243,30 @@ void BaseMenuGui::refresh()
|
||||
//sprintf(displayStrings[10], "%u mV", vddVoltageUv / 1000U);
|
||||
sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDD2] / 1000U);
|
||||
}
|
||||
|
||||
|
||||
// Temperatures and pre-compute colors
|
||||
u32 millis = context->temps[SysClkThermalSensor_SOC]; // SOC
|
||||
sprintf(displayStrings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||
tempColors[SysClkThermalSensor_SOC] = tsl::GradientColor(millis * 0.001f);
|
||||
|
||||
|
||||
millis = context->temps[SysClkThermalSensor_PCB]; // PCB
|
||||
sprintf(displayStrings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||
tempColors[SysClkThermalSensor_PCB] = tsl::GradientColor(millis * 0.001f);
|
||||
|
||||
|
||||
millis = context->temps[SysClkThermalSensor_Skin]; // Skin
|
||||
sprintf(displayStrings[13], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||
tempColors[SysClkThermalSensor_Skin] = tsl::GradientColor(millis * 0.001f);
|
||||
|
||||
|
||||
// SOC voltage (if available)
|
||||
sprintf(displayStrings[14], "%u mV", context->voltages[HocClkVoltage_SOC] / 1000U);
|
||||
|
||||
|
||||
// Power
|
||||
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now
|
||||
sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg
|
||||
|
||||
|
||||
sprintf(displayStrings[17], "%u%%", context->partLoad[HocClkPartLoad_GPU] / 10);
|
||||
sprintf(displayStrings[18], "%u%%", context->partLoad[SysClkPartLoad_EMC] / 10);
|
||||
// sprintf(displayStrings[19], "%u", context->partLoad[HocClkPartLoad_CPUAvg]);
|
||||
sprintf(displayStrings[19], "%u%%", context->partLoad[HocClkPartLoad_CPUMax] / 10);
|
||||
|
||||
millis = context->temps[HorizonOCThermalSensor_Battery]; // Battery
|
||||
sprintf(displayStrings[20], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||
|
||||
@@ -118,32 +118,32 @@ void FreqChoiceGui::listUI()
|
||||
std::uint32_t hz = this->hzList[i];
|
||||
uint32_t mhz = hz / 1000000;
|
||||
|
||||
if (checkMax && IsMariko()) {
|
||||
if (moduleName == "cpu" &&
|
||||
this->configList->values[HocClkConfigValue_MarikoMaxCpuClock] < mhz)
|
||||
continue;
|
||||
// if (checkMax && IsMariko()) {
|
||||
// if (moduleName == "cpu" &&
|
||||
// this->configList->values[HocClkConfigValue_MarikoMaxCpuClock] < mhz)
|
||||
// continue;
|
||||
|
||||
// if (moduleName == "gpu" &&
|
||||
// this->configList->values[HocClkConfigValue_MarikoMaxGpuClock] < mhz)
|
||||
// continue;
|
||||
// // if (moduleName == "gpu" &&
|
||||
// // this->configList->values[HocClkConfigValue_MarikoMaxGpuClock] < mhz)
|
||||
// // continue;
|
||||
|
||||
// if (moduleName == "mem" &&
|
||||
// this->configList->values[HocClkConfigValue_MarikoMaxMemClock] < mhz)
|
||||
// continue;
|
||||
// // if (moduleName == "mem" &&
|
||||
// // this->configList->values[HocClkConfigValue_MarikoMaxMemClock] < mhz)
|
||||
// // continue;
|
||||
|
||||
} else if (checkMax && IsErista()) {
|
||||
if (moduleName == "cpu" &&
|
||||
this->configList->values[HocClkConfigValue_EristaMaxCpuClock] < mhz)
|
||||
continue;
|
||||
// } else if (checkMax && IsErista()) {
|
||||
// if (moduleName == "cpu" &&
|
||||
// this->configList->values[HocClkConfigValue_EristaMaxCpuClock] < mhz)
|
||||
// continue;
|
||||
|
||||
// if (moduleName == "gpu" &&
|
||||
// this->configList->values[HocClkConfigValue_EristaMaxGpuClock] < mhz)
|
||||
// continue;
|
||||
// // if (moduleName == "gpu" &&
|
||||
// // this->configList->values[HocClkConfigValue_EristaMaxGpuClock] < mhz)
|
||||
// // continue;
|
||||
|
||||
// if (moduleName == "mem" &&
|
||||
// this->configList->values[HocClkConfigValue_EristaMaxMemClock] < mhz)
|
||||
// continue;
|
||||
}
|
||||
// // if (moduleName == "mem" &&
|
||||
// // this->configList->values[HocClkConfigValue_EristaMaxMemClock] < mhz)
|
||||
// // continue;
|
||||
// }
|
||||
|
||||
if (moduleName == "mem" && mhz <= 600)
|
||||
continue;
|
||||
@@ -155,7 +155,7 @@ void FreqChoiceGui::listUI()
|
||||
|
||||
if (IsMariko())
|
||||
{
|
||||
unsafe_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2296 : 1963;
|
||||
unsafe_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2296 : 1964;
|
||||
if(this->configList->values[KipConfigValue_marikoGpuUV] == 0) {
|
||||
unsafe_gpu = 1076;
|
||||
} else if (this->configList->values[KipConfigValue_marikoGpuUV] == 1) {
|
||||
|
||||
@@ -99,11 +99,16 @@ void GlobalOverrideGui::addModuleListItemValue(
|
||||
const std::string& suffix,
|
||||
std::uint32_t divisor,
|
||||
int decimalPlaces,
|
||||
ValueThresholds thresholds
|
||||
ValueThresholds thresholds,
|
||||
const std::vector<NamedValue>& namedValues,
|
||||
bool showDefaultValue
|
||||
)
|
||||
{
|
||||
bool hasNamedValues = !namedValues.empty();
|
||||
|
||||
this->customFormatModules[module] = std::make_tuple(suffix, divisor, decimalPlaces);
|
||||
if (!hasNamedValues) {
|
||||
this->customFormatModules[module] = std::make_tuple(suffix, divisor, decimalPlaces);
|
||||
}
|
||||
|
||||
tsl::elm::ListItem* listItem =
|
||||
new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
||||
@@ -121,7 +126,10 @@ void GlobalOverrideGui::addModuleListItemValue(
|
||||
suffix,
|
||||
divisor,
|
||||
decimalPlaces,
|
||||
thresholds](u64 keys)
|
||||
thresholds,
|
||||
namedValues,
|
||||
hasNamedValues,
|
||||
showDefaultValue](u64 keys)
|
||||
{
|
||||
if ((keys & HidNpadButton_A) == HidNpadButton_A)
|
||||
{
|
||||
@@ -147,7 +155,7 @@ void GlobalOverrideGui::addModuleListItemValue(
|
||||
range,
|
||||
categoryName,
|
||||
|
||||
[this, listItem, module, divisor, suffix, decimalPlaces, thresholds](std::uint32_t value) -> bool
|
||||
[this, listItem, module, divisor, suffix, decimalPlaces, thresholds, namedValues, hasNamedValues, showDefaultValue](std::uint32_t value) -> bool
|
||||
{
|
||||
if (!this->context) {
|
||||
return false;
|
||||
@@ -158,6 +166,13 @@ void GlobalOverrideGui::addModuleListItemValue(
|
||||
|
||||
if (value == 0) {
|
||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
||||
} else if (hasNamedValues) {
|
||||
for (const auto& namedValue : namedValues) {
|
||||
if (namedValue.value == value / divisor) {
|
||||
listItem->setValue(namedValue.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char buf[32];
|
||||
if (decimalPlaces > 0) {
|
||||
@@ -188,8 +203,8 @@ void GlobalOverrideGui::addModuleListItemValue(
|
||||
thresholds,
|
||||
false,
|
||||
std::map<std::uint32_t, std::string>(),
|
||||
std::vector<NamedValue>(),
|
||||
true
|
||||
namedValues,
|
||||
showDefaultValue
|
||||
);
|
||||
|
||||
return true;
|
||||
@@ -285,16 +300,25 @@ void GlobalOverrideGui::listUI()
|
||||
}
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(
|
||||
"Temporary Overrides " + ult::DIVIDER_SYMBOL + " Reset"));
|
||||
"Temporary Overrides " + ult::DIVIDER_SYMBOL + " \ue0e3 Reset"));
|
||||
this->addModuleListItem(SysClkModule_CPU);
|
||||
this->addModuleListItem(SysClkModule_GPU);
|
||||
this->addModuleListItem(SysClkModule_MEM);
|
||||
#if IS_MINIMAL == 0
|
||||
ValueThresholds lcdThresholds(60, 65);
|
||||
if(!IsHoag() && configList.values[HorizonOCConfigValue_OverwriteRefreshRate])
|
||||
this->addModuleListItemValue(HorizonOCModule_Display, "Display", 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
||||
this->addModuleListItemValue(HorizonOCModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
||||
#endif
|
||||
this->addModuleToggleItem(HorizonOCModule_Governor);
|
||||
|
||||
std::vector<NamedValue> governorSettings = {
|
||||
NamedValue("Do Not Override", GovernorState_DoNotOverride),
|
||||
NamedValue("Disabled", GovernorState_Disabled),
|
||||
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
|
||||
NamedValue("CPU", GovernorState_Enabled_Cpu),
|
||||
NamedValue("GPU", GovernorState_Enabled_Gpu),
|
||||
};
|
||||
|
||||
this->addModuleListItemValue(HorizonOCModule_Governor, "Governor", 0, 0, 1, "", 1, 0, ValueThresholds(), governorSettings, false);
|
||||
}
|
||||
|
||||
void GlobalOverrideGui::refresh()
|
||||
@@ -306,17 +330,30 @@ void GlobalOverrideGui::refresh()
|
||||
|
||||
for (std::uint16_t m = 0; m < SysClkModule_EnumMax; m++) {
|
||||
if (m == HorizonOCModule_Governor) {
|
||||
auto *toggle =
|
||||
static_cast<tsl::elm::ToggleListItem *>(this->listItems[m]);
|
||||
if (!toggle)
|
||||
continue;
|
||||
|
||||
bool newState = this->context->overrideFreqs[m] != 0;
|
||||
|
||||
if (toggle->getState() != newState) {
|
||||
toggle->setState(newState);
|
||||
if (this->listItems[m] != nullptr &&
|
||||
this->listHz[m] != this->context->overrideFreqs[m]) {
|
||||
|
||||
std::string displayText = FREQ_DEFAULT_TEXT;
|
||||
std::uint32_t currentValue = this->context->overrideFreqs[m];
|
||||
|
||||
std::vector<NamedValue> governorSettings = {
|
||||
NamedValue("Do Not Override", GovernorState_DoNotOverride),
|
||||
NamedValue("Disabled", GovernorState_Disabled),
|
||||
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
|
||||
NamedValue("CPU", GovernorState_Enabled_Cpu),
|
||||
NamedValue("GPU", GovernorState_Enabled_Gpu),
|
||||
};
|
||||
|
||||
for (const auto& setting : governorSettings) {
|
||||
if (setting.value == currentValue) {
|
||||
displayText = setting.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->listItems[m]->setValue(displayText);
|
||||
this->listHz[m] = currentValue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -23,10 +24,7 @@
|
||||
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../ipc.h"
|
||||
#include "base_menu_gui.h"
|
||||
#include "freq_choice_gui.h"
|
||||
@@ -63,7 +61,9 @@ class GlobalOverrideGui : public BaseMenuGui
|
||||
const std::string& suffix,
|
||||
std::uint32_t divisor,
|
||||
int decimalPlaces,
|
||||
ValueThresholds thresholds = {}
|
||||
ValueThresholds thresholds = {},
|
||||
const std::vector<NamedValue>& namedValues = {},
|
||||
bool showDefaultValue = true
|
||||
);
|
||||
public:
|
||||
GlobalOverrideGui();
|
||||
@@ -71,4 +71,4 @@ class GlobalOverrideGui : public BaseMenuGui
|
||||
void listUI() override;
|
||||
void refresh() override;
|
||||
void setModuleCustomFormat(SysClkModule module, const std::string& suffix, std::uint32_t divisor, int decimalPlaces);
|
||||
};
|
||||
};
|
||||
@@ -47,7 +47,7 @@ std::map<uint32_t, std::string> gpu_freq_label_e = {
|
||||
{768000000, "Docked"},
|
||||
{921600000, "Safe Max"},
|
||||
{960000000, "Unsafe Max"},
|
||||
{1075200000, "Aboslute Max"},
|
||||
{1075200000, "Absolute Max"},
|
||||
};
|
||||
|
||||
std::map<uint32_t, std::string> gpu_freq_label_m = {
|
||||
@@ -59,5 +59,6 @@ std::map<uint32_t, std::string> gpu_freq_label_m = {
|
||||
{768000000, "Docked"},
|
||||
{1075200000, "Safe Max"},
|
||||
{1305600000, "Unsafe Max"},
|
||||
{1536000000, "Aboslute Max"},
|
||||
};
|
||||
{1536000000, "Absolute Max"},
|
||||
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#if IS_MINIMAL == 1
|
||||
#pragma message("Compiling with minimal features")
|
||||
#endif
|
||||
|
||||
class RamSubmenuGui;
|
||||
class RamTimingsSubmenuGui;
|
||||
class RamLatenciesSubmenuGui;
|
||||
@@ -238,21 +239,45 @@ void MiscGui::addFreqButton(SysClkConfigValue configVal,
|
||||
|
||||
void MiscGui::listUI()
|
||||
{
|
||||
Result rc = sysclkIpcGetConfigValues(configList);
|
||||
if (R_FAILED(rc)) [[unlikely]] {
|
||||
FatalGui::openWithResultCode("sysclkIpcGetConfigValues", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
ValueThresholds thresholdsDisabled(0, 0);
|
||||
std::vector<NamedValue> noNamedValues = {};
|
||||
|
||||
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Settings"));
|
||||
|
||||
addConfigToggle(HocClkConfigValue_UncappedClocks, nullptr);
|
||||
addConfigToggle(HocClkConfigValue_OverwriteBoostMode, nullptr);
|
||||
#if IS_MINIMAL == 0
|
||||
addConfigToggle(HocClkConfigValue_FixCpuVoltBug, nullptr);
|
||||
#endif
|
||||
std::vector<NamedValue> gpuSchedValues = {
|
||||
NamedValue("Do not override", GpuSchedulingMode_DoNotOverride),
|
||||
NamedValue("Enabled", GpuSchedulingMode_Enabled, "96.5% limit"),
|
||||
NamedValue("Disabled", GpuSchedulingMode_Disabled, "99.7% limit"),
|
||||
};
|
||||
tsl::elm::CustomDrawer* gpuSchedInfoText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 This option requires a reboot", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("to take effect", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
|
||||
});
|
||||
gpuSchedInfoText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 70);
|
||||
this->listElement->addItem(gpuSchedInfoText);
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_GPUScheduling,
|
||||
"GPU Scheduling Override",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"GPU Scheduling Override",
|
||||
&thresholdsDisabled,
|
||||
{},
|
||||
gpuSchedValues,
|
||||
false
|
||||
);
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Safety Settings"));
|
||||
addConfigToggle(HocClkConfigValue_UncappedClocks, nullptr);
|
||||
addConfigToggle(HocClkConfigValue_ThermalThrottle, nullptr);
|
||||
addConfigToggle(HocClkConfigValue_HandheldTDP, nullptr);
|
||||
addConfigToggle(HocClkConfigValue_EnforceBoardLimit, nullptr);
|
||||
// addConfigToggle(HocClkConfigValue_EnforceBoardLimit, nullptr);
|
||||
|
||||
#if IS_MINIMAL == 0
|
||||
std::map<uint32_t, std::string> labels_pwr_l = {
|
||||
@@ -280,7 +305,6 @@ void MiscGui::listUI()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
ValueThresholds throttleThresholds(70, 80);
|
||||
addConfigButton(
|
||||
HocClkConfigValue_ThermalThrottleThreshold,
|
||||
@@ -291,11 +315,57 @@ void MiscGui::listUI()
|
||||
);
|
||||
#endif
|
||||
|
||||
if(IsMariko()) {
|
||||
addFreqButton(HocClkConfigValue_MarikoMaxCpuClock, nullptr, SysClkModule_CPU, cpu_freq_label_m);
|
||||
} else {
|
||||
addFreqButton(HocClkConfigValue_EristaMaxCpuClock, nullptr, SysClkModule_CPU, cpu_freq_label_e);
|
||||
if (IsMariko()) {
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("DVFS"));
|
||||
std::vector<NamedValue> dvfsValues = {
|
||||
NamedValue("Disabled", DVFSMode_Disabled),
|
||||
NamedValue("PCV Hijack", DVFSMode_Hijack),
|
||||
// NamedValue("Official Service", DVFSMode_OfficialService),
|
||||
// NamedValue("Hack", DVFSMode_Hack),
|
||||
};
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_DVFSMode,
|
||||
"GPU DVFS Mode",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"GPU DVFS Mode",
|
||||
&thresholdsDisabled,
|
||||
{},
|
||||
dvfsValues,
|
||||
false
|
||||
);
|
||||
|
||||
std::vector<NamedValue> dvfsOffset = {
|
||||
NamedValue("-50 mV", 0xFFFFFFCE),
|
||||
NamedValue("-45 mV", 0xFFFFFFD3),
|
||||
NamedValue("-40 mV", 0xFFFFFFD8),
|
||||
NamedValue("-30 mV", 0xFFFFFFE2),
|
||||
NamedValue("-25 mV", 0xFFFFFFE7),
|
||||
NamedValue("-20 mV", 0xFFFFFFEC),
|
||||
NamedValue("-10 mV", 0xFFFFFFF6),
|
||||
NamedValue(" -5 mV", 0xFFFFFFFB),
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue(" +5 mV", 5),
|
||||
NamedValue("+10 mV", 10),
|
||||
NamedValue("+15 mV", 15),
|
||||
NamedValue("+20 mV", 20),
|
||||
};
|
||||
|
||||
addConfigButton(HorizonOCConfigValue_DVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {}, dvfsOffset, false);
|
||||
}
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Display"));
|
||||
|
||||
addConfigToggle(HorizonOCConfigValue_OverwriteRefreshRate, nullptr);
|
||||
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 Enabling unsafe display", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("refresh rates may cause stress", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("or damage to your display! ", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("Proceed at your own risk!", false, x + 20, y + 90, 18, tsl::style::color::ColorText);
|
||||
});
|
||||
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 110);
|
||||
this->listElement->addItem(warningText);
|
||||
addConfigToggle(HorizonOCConfigValue_EnableUnsafeDisplayFreqs, nullptr);
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("KIP"));
|
||||
|
||||
@@ -343,81 +413,99 @@ void MiscGui::listUI()
|
||||
});
|
||||
this->listElement->addItem(gpuSubmenu);
|
||||
|
||||
|
||||
#if IS_MINIMAL == 0
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
NamedValue("2816mA", 2816),
|
||||
NamedValue("3072mA", 3072),
|
||||
};
|
||||
if(!IsHoag()) {
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
NamedValue("2816mA", 2816),
|
||||
NamedValue("3072mA", 3072),
|
||||
// std::vector<NamedValue> chargerCurrents = {
|
||||
// NamedValue("Disabled", 0),
|
||||
// NamedValue("1024mA", 1024),
|
||||
// NamedValue("1280mA", 1280),
|
||||
// NamedValue("1536mA", 1536),
|
||||
// NamedValue("1792mA", 1792),
|
||||
// NamedValue("2048mA", 2048),
|
||||
// NamedValue("2304mA", 2304),
|
||||
// NamedValue("2560mA", 2560),
|
||||
// NamedValue("2816mA", 2816),
|
||||
// NamedValue("3072mA", 3072),
|
||||
// };
|
||||
if(this->configList->values[HorizonOCConfigValue_EnableExperimentalSettings]) {
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
|
||||
|
||||
addConfigToggle(HorizonOCConfigValue_LiveCpuUv, nullptr);
|
||||
std::vector<NamedValue> gpuSchedMethodValues = {
|
||||
NamedValue("INI", GpuSchedulingOverrideMethod_Ini),
|
||||
NamedValue("NV Service", GpuSchedulingOverrideMethod_NvService),
|
||||
};
|
||||
|
||||
ValueThresholds chargerThresholds(2048, 2560);
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
"Charge Current Override",
|
||||
HorizonOCConfigValue_GPUSchedulingMethod,
|
||||
"GPU Scheduling Override Method",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"Charge Current Override",
|
||||
&chargerThresholds,
|
||||
"GPU Scheduling Override Method",
|
||||
&thresholdsDisabled,
|
||||
{},
|
||||
chargerCurrents,
|
||||
gpuSchedMethodValues,
|
||||
false
|
||||
);
|
||||
addConfigToggle(HorizonOCConfigValue_OverwriteRefreshRate, nullptr);
|
||||
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 Enabling unsafe display", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("refresh rates may cause stress", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("or damage to your display! ", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("Proceed at your own risk!", false, x + 20, y + 90, 18, tsl::style::color::ColorText);
|
||||
tsl::elm::CustomDrawer* chargeWarningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 Overriding the charge current", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("can be dangerous and may cause", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("damage to your battery or charger!", false, x + 20, y + 70, 18, tsl::style::color::ColorText);
|
||||
});
|
||||
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 110);
|
||||
this->listElement->addItem(warningText);
|
||||
addConfigToggle(HorizonOCConfigValue_EnableUnsafeDisplayFreqs, nullptr);
|
||||
} else {
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
};
|
||||
chargeWarningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 90);
|
||||
this->listElement->addItem(chargeWarningText);
|
||||
|
||||
ValueThresholds chargerThresholds(1792, 2048);
|
||||
if(!IsHoag()) {
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
NamedValue("2816mA", 2816),
|
||||
NamedValue("3072mA", 3072),
|
||||
};
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
"Charge Current Override",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"Charge Current Override",
|
||||
&chargerThresholds,
|
||||
{},
|
||||
chargerCurrents,
|
||||
false
|
||||
);
|
||||
ValueThresholds chargerThresholds(2048, 2049);
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
"Charge Current Override",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"Charge Current Override",
|
||||
&chargerThresholds,
|
||||
{},
|
||||
chargerCurrents,
|
||||
false
|
||||
);
|
||||
}
|
||||
else {
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
};
|
||||
|
||||
ValueThresholds chargerThresholds(1792, 1793);
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
"Charge Current Override",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"Charge Current Override",
|
||||
&chargerThresholds,
|
||||
{},
|
||||
chargerCurrents,
|
||||
false
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -542,16 +630,9 @@ protected:
|
||||
};
|
||||
|
||||
if(IsErista()) {
|
||||
addConfigButton(
|
||||
KipConfigValue_eristaEmcMaxClock,
|
||||
"RAM Max Clock",
|
||||
ValueRange(0, 1, 1, "", 1),
|
||||
"RAM Max Clock",
|
||||
&eristaRamThresholds,
|
||||
{},
|
||||
eristaMaxEmcClock,
|
||||
false
|
||||
);
|
||||
addConfigButton(KipConfigValue_eristaEmcMaxClock, "RAM Max Clock", ValueRange(0, 1, 1, "", 1), "RAM Max Clock", &eristaRamThresholds, {}, eristaMaxEmcClock, false);
|
||||
addConfigButton(KipConfigValue_eristaEmcMaxClock1, "RAM Max Clock", ValueRange(0, 1, 1, "", 1), "RAM Max Clock", &eristaRamThresholds, {}, eristaMaxEmcClock, false);
|
||||
addConfigButton(KipConfigValue_eristaEmcMaxClock2, "RAM Max Clock", ValueRange(0, 1, 1, "", 1), "RAM Max Clock", &eristaRamThresholds, {}, eristaMaxEmcClock, false);
|
||||
} else {
|
||||
addConfigButton(
|
||||
KipConfigValue_marikoEmcMaxClock,
|
||||
@@ -590,7 +671,7 @@ protected:
|
||||
addConfigButton(
|
||||
KipConfigValue_marikoEmcVddqVolt,
|
||||
"RAM VDDQ Voltage",
|
||||
ValueRange(550000, 700000, 5000, "mV", 1000),
|
||||
ValueRange(400000, 700000, 5000, "mV", 1000),
|
||||
"RAM VDDQ Voltage",
|
||||
&thresholdsDisabled,
|
||||
{},
|
||||
@@ -650,36 +731,28 @@ protected:
|
||||
addConfigButton(KipConfigValue_t6_tRTW, "t6 tRTW", ValueRange(0, 10, 1, "", 1), "tRTW", &thresholdsDisabled, {}, {}, false);
|
||||
addConfigButton(KipConfigValue_t7_tWTR, "t7 tWTR", ValueRange(0, 10, 1, "", 1), "tWTR", &thresholdsDisabled, {}, {}, false);
|
||||
addConfigButton(KipConfigValue_t8_tREFI, "t8 tREFI", ValueRange(0, 6, 1, "", 1), "tREFI", &thresholdsDisabled, {}, {}, false);
|
||||
#if IS_MINIMAL == 0
|
||||
if(IsMariko()) {
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
|
||||
|
||||
tsl::elm::ListItem* emcUpdBtn = new tsl::elm::ListItem("Update RAM Timings");
|
||||
emcUpdBtn->setClickListener([this](u64 keys) {
|
||||
if (keys & HidNpadButton_A) {
|
||||
if(this->context->freqs[SysClkModule_MEM] > 1600000000) {
|
||||
Result rc = hocClkIpcUpdateEmcRegs();
|
||||
if (R_FAILED(rc)) {
|
||||
FatalGui::openWithResultCode("hocClkIpcUpdateEmcRegs", rc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
writeNotification("Horizon OC\nSet your ram frequency to max\nbefore applying timings!");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this->listElement->addItem(emcUpdBtn);
|
||||
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 This feature is EXPERIMENTAL", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("and should only be used for testing!", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
|
||||
});
|
||||
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 70);
|
||||
this->listElement->addItem(warningText);
|
||||
}
|
||||
#endif
|
||||
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),
|
||||
};
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Advanced"));
|
||||
addConfigButton(KipConfigValue_t6_tRTW_fine_tune, "t6 tRTW Fine Tune", ValueRange(0, 4, 1, "", 0), "tRTW Fine Tune", &thresholdsDisabled, {}, t6_tRTW_fine_tune, false);
|
||||
addConfigButton(KipConfigValue_t7_tWTR_fine_tune, "t7 tWTR Fine Tune", ValueRange(0, 6, 1, "", 0), "tWTR Fine Tune", &thresholdsDisabled, {}, t7_tWTR_fine_tune, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -937,7 +1010,7 @@ protected:
|
||||
};
|
||||
|
||||
std::vector<NamedValue> mGpuVoltsVmin = {
|
||||
NamedValue("Auto", 0), NamedValue("Auto (RAM)", 1),
|
||||
NamedValue("Auto", 0),
|
||||
NamedValue("480mV", 480), NamedValue("485mV", 485), NamedValue("490mV", 490),
|
||||
NamedValue("495mV", 495), NamedValue("500mV", 500), NamedValue("505mV", 505),
|
||||
NamedValue("510mV", 510), NamedValue("515mV", 515), NamedValue("520mV", 520),
|
||||
@@ -1188,7 +1261,7 @@ protected:
|
||||
};
|
||||
|
||||
if (IsMariko()) {
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@@ -30,7 +30,8 @@ ValueChoiceGui::ValueChoiceGui(std::uint32_t selectedValue,
|
||||
bool enableThresholds,
|
||||
std::map<std::uint32_t, std::string> labels,
|
||||
std::vector<NamedValue> namedValues,
|
||||
bool showDefaultValue)
|
||||
bool showDefaultValue,
|
||||
bool showDNO)
|
||||
: selectedValue(selectedValue),
|
||||
range(range),
|
||||
categoryName(categoryName),
|
||||
@@ -39,7 +40,8 @@ ValueChoiceGui::ValueChoiceGui(std::uint32_t selectedValue,
|
||||
enableThresholds(enableThresholds),
|
||||
labels(labels),
|
||||
namedValues(namedValues),
|
||||
showDefaultValue(showDefaultValue)
|
||||
showDefaultValue(showDefaultValue),
|
||||
showDNO(showDNO)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -52,7 +54,7 @@ std::string ValueChoiceGui::formatValue(std::uint32_t value)
|
||||
std::ostringstream oss;
|
||||
if(showDefaultValue) {
|
||||
if (value == 0) {
|
||||
return VALUE_DEFAULT_TEXT;
|
||||
return this->showDNO ? FREQ_DEFAULT_TEXT : VALUE_DEFAULT_TEXT;
|
||||
}
|
||||
}
|
||||
double displayValue = static_cast<double>(value) / static_cast<double>(range.divisor);
|
||||
@@ -164,17 +166,16 @@ void ValueChoiceGui::listUI()
|
||||
if (!categoryName.empty()) {
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(categoryName));
|
||||
}
|
||||
|
||||
|
||||
if (showDefaultValue) {
|
||||
this->listElement->addItem(this->createValueListItem(0, this->selectedValue == 0, 0));
|
||||
}
|
||||
for (const auto& namedValue : namedValues) {
|
||||
int safety = enableThresholds ? getSafetyLevel(namedValue.value) : 0;
|
||||
bool selected = (namedValue.value == this->selectedValue);
|
||||
this->listElement->addItem(this->createNamedValueListItem(namedValue, selected, safety));
|
||||
}
|
||||
|
||||
if (showDefaultValue) {
|
||||
this->listElement->addItem(this->createValueListItem(0, this->selectedValue == 0, 0));
|
||||
}
|
||||
|
||||
if (namedValues.empty()) {
|
||||
for (std::uint32_t value = range.min; value <= range.max; value += range.step)
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ protected:
|
||||
|
||||
std::vector<NamedValue> namedValues;
|
||||
bool showDefaultValue = true;
|
||||
|
||||
bool showDNO = false;
|
||||
tsl::elm::ListItem* createValueListItem(std::uint32_t value, bool selected, int safety);
|
||||
tsl::elm::ListItem* createNamedValueListItem(const NamedValue& namedValue, bool selected, int safety);
|
||||
std::string formatValue(std::uint32_t value);
|
||||
@@ -86,7 +86,8 @@ public:
|
||||
bool enableThresholds = false,
|
||||
std::map<std::uint32_t, std::string> labels = {},
|
||||
std::vector<NamedValue> namedValues = {},
|
||||
bool showDefaultValue = true);
|
||||
bool showDefaultValue = true,
|
||||
bool showDNO = false);
|
||||
~ValueChoiceGui();
|
||||
|
||||
void addNamedValue(const std::string& name, std::uint32_t value, const std::string& rightText = "")
|
||||
|
||||
@@ -39,7 +39,7 @@ DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_V
|
||||
|
||||
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
||||
|
||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||
CFLAGS := -g -Wall -Os -ffunction-sections \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__SWITCH__
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2023 CTCaer
|
||||
* Copyright (c) 2023 p-sam
|
||||
* Copyright (c) 2026 Souldbminer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -47,7 +48,7 @@
|
||||
|
||||
#define PTO_CLK_CNT_BUSY BIT(31)
|
||||
#define PTO_CLK_CNT 0xFFFFFF
|
||||
#define CLK_PTO_CCLK_G 0x12
|
||||
#define CLK_PTO_CCLK_G_DIV2 0x13
|
||||
#define CLK_PTO_EMC 0x24
|
||||
|
||||
#define CLOCK(x) (*(volatile u32 *)(g_clk_base + (x)))
|
||||
@@ -117,7 +118,7 @@ static u32 g_mem_freq = 0;
|
||||
static u32 g_emc_lall = 0;
|
||||
static u32 g_emc_lcpu = 0;
|
||||
|
||||
static u32 _clock_get_dev_freq(u32 id)
|
||||
static u32 _clock_get_dev_freq(u32 id, u32 multiplier)
|
||||
{
|
||||
const u32 pto_win = 16;
|
||||
const u32 pto_osc = 32768;
|
||||
@@ -148,7 +149,7 @@ static u32 _clock_get_dev_freq(u32 id)
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||
usleep(2);
|
||||
|
||||
u32 freq_khz = (u64)cnt * pto_osc / pto_win / 1000;
|
||||
u32 freq_khz = (u64)cnt * multiplier * pto_osc / pto_win;
|
||||
|
||||
return freq_khz;
|
||||
}
|
||||
@@ -203,8 +204,8 @@ static void _clock_update_freqs(void)
|
||||
return;
|
||||
}
|
||||
|
||||
g_mem_freq = _clock_get_dev_freq(CLK_PTO_EMC) * 1000;
|
||||
g_cpu_freq = _clock_get_dev_freq(CLK_PTO_CCLK_G) * 1000;
|
||||
g_mem_freq = _clock_get_dev_freq(CLK_PTO_EMC, 1);
|
||||
g_cpu_freq = _clock_get_dev_freq(CLK_PTO_CCLK_G_DIV2, 2);
|
||||
|
||||
if (!g_gpu_base)
|
||||
{
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"title_id": "0x00FF0000636C6BFF",
|
||||
"title_id_range_min": "0x00FF0000636C6BFF",
|
||||
"title_id_range_max": "0x00FF0000636C6BFF",
|
||||
"main_thread_stack_size": "0x00008000",
|
||||
"main_thread_priority": 63,
|
||||
"main_thread_stack_size": "0x0000C000",
|
||||
"main_thread_priority": 16,
|
||||
"default_cpu_id": 3,
|
||||
"process_category": 0,
|
||||
"is_retail": true,
|
||||
@@ -25,7 +25,7 @@
|
||||
"type": "kernel_flags",
|
||||
"value": {
|
||||
"highest_thread_priority": 63,
|
||||
"lowest_thread_priority": 41,
|
||||
"lowest_thread_priority": 16,
|
||||
"lowest_cpu_id": 0,
|
||||
"highest_cpu_id": 3
|
||||
}
|
||||
@@ -57,6 +57,15 @@
|
||||
"is_io": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "map",
|
||||
"value": {
|
||||
"address": "0x70110000",
|
||||
"size": "0x1000",
|
||||
"is_ro": false,
|
||||
"is_io": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "syscalls",
|
||||
"value": {
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -41,6 +41,8 @@
|
||||
#include <cstring>
|
||||
#include <registers.h>
|
||||
#include <notification.h>
|
||||
#include <memmem.h>
|
||||
#include <minIni.h>
|
||||
|
||||
#define MAX(A, B) std::max(A, B)
|
||||
#define MIN(A, B) std::min(A, B)
|
||||
@@ -64,12 +66,16 @@
|
||||
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
|
||||
#define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0))
|
||||
#define NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD 0x80044715
|
||||
#define NVSCHED_CTRL_ENABLE 0x00000601
|
||||
#define NVSCHED_CTRL_DISABLE 0x00000602
|
||||
|
||||
#define systemtickfrequency 19200000
|
||||
#define systemtickfrequencyF 19200000.0f
|
||||
#define CPU_TICK_WAIT (1'000'000'000 / 60)
|
||||
constexpr u64 CpuTimeOutNs = 500'000'000;
|
||||
constexpr double Systemtickfrequency = 19200000.0 * (static_cast<double>(CpuTimeOutNs) / 1'000'000'000.0);
|
||||
Result nvInitialize_rc;
|
||||
Result nvCheck = 1;
|
||||
Result nvCheck_sched = 1;
|
||||
|
||||
LEvent threadexit;
|
||||
Thread gpuLThread;
|
||||
Thread cpuCore0Thread;
|
||||
Thread cpuCore1Thread;
|
||||
@@ -84,20 +90,37 @@ Result pwmDutyCycleCheck = 1;
|
||||
double Rotation_Duty = 0;
|
||||
u8 fanLevel;
|
||||
|
||||
uint32_t GPU_Load_u = 0, fd = 0;
|
||||
uint32_t GPU_Load_u = 0, fd = 0, fd2 = 0;
|
||||
BatteryChargeInfo info;
|
||||
|
||||
static SysClkSocType g_socType = SysClkSocType_Erista;
|
||||
static HorizonOCConsoleType g_consoleType = HorizonOCConsoleType_Iowa;
|
||||
|
||||
std::atomic<uint64_t> idletick0{systemtickfrequency};
|
||||
std::atomic<uint64_t> idletick1{systemtickfrequency};
|
||||
std::atomic<uint64_t> idletick2{systemtickfrequency};
|
||||
std::atomic<uint64_t> idletick3{systemtickfrequency};
|
||||
u64 idletick0 = 0;
|
||||
u64 idletick1 = 0;
|
||||
u64 idletick2 = 0;
|
||||
// u64 idletick3 = 0;
|
||||
|
||||
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
|
||||
u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC
|
||||
u32 speedoBracket;
|
||||
u16 cpuIDDQ, gpuIDDQ, socIDDQ;
|
||||
u8 g_dramID = 0;
|
||||
u64 cldvfs, cldvfs_temp;
|
||||
u32 cachedEristaUvLowTune0 = 0, cachedEristaUvLowTune1 = 0, cachedMarikoUvHighTune0 = 0;
|
||||
|
||||
static const u32 ramBrackets[][22] = {
|
||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
|
||||
};
|
||||
|
||||
static const u32 gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||
|
||||
u32 dvfsTable[6][32] = {};
|
||||
u64 dvfsAddress;
|
||||
u32 ramVmin;
|
||||
|
||||
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
||||
{
|
||||
@@ -149,16 +172,16 @@ PcvModuleId Board::GetPcvModuleId(SysClkModule sysclkModule)
|
||||
return pcvModuleId;
|
||||
}
|
||||
|
||||
void CheckCore(void* idletick_ptr) {
|
||||
std::atomic<uint64_t>* idletick = (std::atomic<uint64_t>*)idletick_ptr;
|
||||
while (true) {
|
||||
uint64_t idletick_a;
|
||||
uint64_t idletick_b;
|
||||
svcGetInfo(&idletick_b, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
||||
svcSleepThread(CPU_TICK_WAIT);
|
||||
svcGetInfo(&idletick_a, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
||||
idletick->store(idletick_a - idletick_b, std::memory_order_release);
|
||||
}
|
||||
void CheckCore(void *idletickPtr) {
|
||||
u64* idletick = static_cast<u64 *>(idletickPtr);
|
||||
while(true) {
|
||||
u64 idletickA;
|
||||
u64 idletickB;
|
||||
svcGetInfo(&idletickB, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
||||
svcWaitForAddress(&threadexit, ArbitrationType_WaitIfEqual, 0, CpuTimeOutNs);
|
||||
svcGetInfo(&idletickA, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
||||
*idletick = idletickA - idletickB;
|
||||
}
|
||||
}
|
||||
|
||||
void gpuLoadThread(void*) {
|
||||
@@ -190,7 +213,6 @@ void miscThreadFunc(void*) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Board::Initialize()
|
||||
{
|
||||
Result rc = 0;
|
||||
@@ -222,8 +244,11 @@ void Board::Initialize()
|
||||
|
||||
rc = tmp451Initialize();
|
||||
ASSERT_RESULT_OK(rc, "tmp451Initialize");
|
||||
|
||||
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
|
||||
nvInitialize_rc = nvInitialize();
|
||||
if (R_SUCCEEDED(nvInitialize_rc)) {
|
||||
nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
|
||||
nvCheck_sched = nvOpen(&fd2, "/dev/nvsched-ctrl");
|
||||
}
|
||||
|
||||
rc = rgltrInitialize();
|
||||
ASSERT_RESULT_OK(rc, "rgltrInitialize");
|
||||
@@ -238,17 +263,17 @@ void Board::Initialize()
|
||||
|
||||
threadCreate(&gpuLThread, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2);
|
||||
threadStart(&gpuLThread);
|
||||
|
||||
threadCreate(&cpuCore0Thread, CheckCore, &idletick0, NULL, 0x500, 0x10, 0);
|
||||
threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x500, 0x10, 1);
|
||||
threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x500, 0x10, 2);
|
||||
threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x500, 0x10, 3);
|
||||
threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x3F, 3);
|
||||
leventClear(&threadexit);
|
||||
threadCreate(&cpuCore0Thread, CheckCore, &idletick0, NULL, 0x1000, 0x10, 0);
|
||||
threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1);
|
||||
threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2);
|
||||
// threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3);
|
||||
threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x10, 3);
|
||||
|
||||
threadStart(&cpuCore0Thread);
|
||||
threadStart(&cpuCore1Thread);
|
||||
threadStart(&cpuCore2Thread);
|
||||
threadStart(&cpuCore3Thread);
|
||||
// threadStart(&cpuCore3Thread);
|
||||
threadStart(&miscThread);
|
||||
batteryInfoInitialize();
|
||||
|
||||
@@ -268,6 +293,16 @@ void Board::Initialize()
|
||||
}
|
||||
|
||||
FetchHardwareInfos();
|
||||
rc = svcQueryMemoryMapping(&cldvfs, &cldvfs_temp, CLDVFS_REGION_BASE, CLDVFS_REGION_SIZE);
|
||||
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (cldvfs)");
|
||||
if(Board::GetSocType() == SysClkSocType_Erista) {
|
||||
cachedEristaUvLowTune0 = *(u32*)(cldvfs + CL_DVFS_TUNE0_0);
|
||||
cachedEristaUvLowTune1 = *(u32*)(cldvfs + CL_DVFS_TUNE1_0);
|
||||
} else {
|
||||
Board::SetHz(SysClkModule_CPU, 1785000000);
|
||||
cachedMarikoUvHighTune0 = *(u32*)(cldvfs + CL_DVFS_TUNE0_0);
|
||||
Board::ResetToStockCpu();
|
||||
}
|
||||
}
|
||||
|
||||
void Board::fuseReadSpeedos() {
|
||||
@@ -311,7 +346,7 @@ void Board::fuseReadSpeedos() {
|
||||
cpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_CPU_IDDQ_CALIB);
|
||||
gpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_SOC_IDDQ_CALIB);
|
||||
socIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_GPU_IDDQ_CALIB);
|
||||
|
||||
|
||||
svcCloseHandle(debug);
|
||||
return;
|
||||
}
|
||||
@@ -378,7 +413,7 @@ void Board::Exit()
|
||||
threadClose(&cpuCore0Thread);
|
||||
threadClose(&cpuCore1Thread);
|
||||
threadClose(&cpuCore2Thread);
|
||||
threadClose(&cpuCore3Thread);
|
||||
// threadClose(&cpuCore3Thread);
|
||||
threadClose(&miscThread);
|
||||
|
||||
pwmChannelSessionClose(&g_ICon);
|
||||
@@ -386,6 +421,7 @@ void Board::Exit()
|
||||
rgltrExit();
|
||||
batteryInfoExit();
|
||||
pmdmntExit();
|
||||
nvExit();
|
||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
||||
DisplayRefresh_Shutdown();
|
||||
}
|
||||
@@ -421,8 +457,7 @@ SysClkProfile Board::GetProfile()
|
||||
void Board::SetHz(SysClkModule module, std::uint32_t hz)
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
if(module == HorizonOCModule_Display && Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||
if(module == HorizonOCModule_Display && Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||
DisplayRefresh_SetRate(hz);
|
||||
return;
|
||||
}
|
||||
@@ -436,13 +471,22 @@ void Board::SetHz(SysClkModule module, std::uint32_t hz)
|
||||
ASSERT_RESULT_OK(rc, "clkrstOpenSession");
|
||||
rc = clkrstSetClockRate(&session, hz);
|
||||
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
||||
|
||||
if (module == SysClkModule_CPU) {
|
||||
svcSleepThread(200'000);
|
||||
rc = clkrstSetClockRate(&session, hz);
|
||||
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
||||
}
|
||||
clkrstCloseSession(&session);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = pcvSetClockRate(Board::GetPcvModule(module), hz);
|
||||
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
||||
if (module == SysClkModule_CPU) {
|
||||
svcSleepThread(200'000);
|
||||
rc = pcvSetClockRate(Board::GetPcvModule(module), hz);
|
||||
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +502,7 @@ std::uint32_t Board::GetHz(SysClkModule module)
|
||||
hz = 60;
|
||||
return hz;
|
||||
}
|
||||
|
||||
|
||||
if(HOSSVC_HAS_CLKRST)
|
||||
{
|
||||
ClkrstSession session = {0};
|
||||
@@ -690,14 +734,15 @@ void Board::ResetToStockGpu()
|
||||
}
|
||||
|
||||
void Board::ResetToStockDisplay() {
|
||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||
DisplayRefresh_SetRate(60);
|
||||
}
|
||||
}
|
||||
|
||||
u8 Board::GetHighestDockedDisplayRate() {
|
||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||
return DisplayRefresh_GetDockedHighestAllowed();
|
||||
else
|
||||
} else
|
||||
return 60;
|
||||
}
|
||||
|
||||
@@ -752,8 +797,17 @@ std::int32_t Board::GetPowerMw(SysClkPowerSensor sensor)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 GetMaxCpuLoad() {
|
||||
float cpuUsage0 = std::clamp(((Systemtickfrequency - idletick0) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||
float cpuUsage1 = std::clamp(((Systemtickfrequency - idletick1) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||
float cpuUsage2 = std::clamp(((Systemtickfrequency - idletick2) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||
// float cpuUsage3 = std::clamp(((Systemtickfrequency - idletick3) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||
|
||||
return std::round(std::max({cpuUsage0, cpuUsage1, cpuUsage2}));
|
||||
}
|
||||
|
||||
std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
||||
{
|
||||
{
|
||||
switch(loadSource)
|
||||
{
|
||||
case SysClkPartLoad_EMC:
|
||||
@@ -762,8 +816,8 @@ std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
||||
return t210EmcLoadCpu();
|
||||
case HocClkPartLoad_GPU:
|
||||
return GPU_Load_u;
|
||||
case HocClkPartLoad_CPUAvg:
|
||||
return idletick0;
|
||||
case HocClkPartLoad_CPUMax:
|
||||
return GetMaxCpuLoad();
|
||||
case HocClkPartLoad_BAT:
|
||||
batteryInfoGetChargeInfo(&info);
|
||||
return info.RawBatteryCharge;
|
||||
@@ -792,6 +846,7 @@ u8 Board::GetDramID() {
|
||||
void Board::FetchHardwareInfos()
|
||||
{
|
||||
fuseReadSpeedos();
|
||||
SetSpeedoBracket();
|
||||
u64 sku = 0, dramID = 0;
|
||||
Result rc = splInitialize();
|
||||
ASSERT_RESULT_OK(rc, "splInitialize");
|
||||
@@ -801,7 +856,7 @@ void Board::FetchHardwareInfos()
|
||||
|
||||
rc = splGetConfig(SplConfigItem_DramId, &dramID);
|
||||
ASSERT_RESULT_OK(rc, "splGetConfig");
|
||||
|
||||
|
||||
splExit();
|
||||
|
||||
switch(sku)
|
||||
@@ -816,9 +871,12 @@ void Board::FetchHardwareInfos()
|
||||
g_socType = SysClkSocType_Erista;
|
||||
}
|
||||
|
||||
if (g_socType == SysClkSocType_Mariko) {
|
||||
CacheDvfsTable();
|
||||
}
|
||||
|
||||
g_consoleType = (HorizonOCConsoleType)sku;
|
||||
g_dramID = (u8)dramID;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -926,174 +984,347 @@ std::uint32_t Board::GetVoltage(HocClkVoltage voltage)
|
||||
return out > 0 ? out : 0;
|
||||
}
|
||||
|
||||
#define MC_REGISTER_BASE 0x70019000
|
||||
#define MC_REGISTER_REGION_SIZE 0x1000
|
||||
void Board::SetSpeedoBracket() {
|
||||
if (cpuSpeedo2 >= 1754) {
|
||||
speedoBracket = 3;
|
||||
} else if (cpuSpeedo2 >= 1690) {
|
||||
speedoBracket = 2;
|
||||
} else if (cpuSpeedo2 > 1625) {
|
||||
speedoBracket = 1;
|
||||
} else {
|
||||
speedoBracket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define EMC_REGISTER_BASE 0x7001b000
|
||||
#define EMC_REGISTER_REGION_SIZE 0x1000
|
||||
u32 Board::GetMinimumGpuVoltage(u32 freqMhz) {
|
||||
if (freqMhz <= 1600)
|
||||
return 0;
|
||||
|
||||
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
||||
|
||||
#define WRITE_REGISTER_EMC(TIMING_OFFSET, VALUE) \
|
||||
do { \
|
||||
args = {}; \
|
||||
args.X[0] = 0xF0000002; \
|
||||
args.X[1] = EMC_REGISTER_BASE + (TIMING_OFFSET); \
|
||||
args.X[2] = 0xFFFFFFFF; \
|
||||
args.X[3] = (VALUE); \
|
||||
svcCallSecureMonitor(&args); \
|
||||
} while (false)
|
||||
|
||||
#define WRITE_REGISTER_MC(TIMING_OFFSET, VALUE) \
|
||||
do { \
|
||||
args = {}; \
|
||||
args.X[0] = 0xF0000002; \
|
||||
args.X[1] = MC_REGISTER_BASE + (TIMING_OFFSET); \
|
||||
args.X[2] = 0xFFFFFFFF; \
|
||||
args.X[3] = (VALUE); \
|
||||
svcCallSecureMonitor(&args); \
|
||||
} while (false)
|
||||
|
||||
|
||||
// NOTE: needs patch to exosphere to expose emc region to secmon. MC does NOT need this patch
|
||||
|
||||
u32 tRCD_values[] = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
u32 tRP_values[] = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
u32 tRAS_values[] = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
||||
double tRRD_values[] = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? */
|
||||
u32 tRFC_values[] = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
||||
u32 tWTR_values[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
u32 tREFpb_values[] = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
||||
|
||||
// Credit to Lightos for these timings!
|
||||
|
||||
|
||||
void Board::UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32 tRFC_i, u32 tRTW_i, u32 tWTR_i, u32 tREFpb_i, u32 ramFreq, u32 rlAdd, u32 wlAdd, bool hpMode) {
|
||||
// timing stuff
|
||||
|
||||
SecmonArgs args = {};
|
||||
|
||||
constexpr double MC_ARB_DIV = 4.0;
|
||||
constexpr u32 MC_ARB_SFA = 2;
|
||||
|
||||
double tCK_avg = 1000'000.0 / ramFreq;
|
||||
u32 BL = 16;
|
||||
u32 RL = 28 + rlAdd;
|
||||
u32 WL = 14 + wlAdd;
|
||||
u32 RL_DBI = RL + 4;
|
||||
|
||||
u32 tRCD = tRCD_values[tRCD_i];
|
||||
u32 tRPpb = tRP_values[tRP_i];
|
||||
u32 tRAS = tRAS_values[tRAS_i];
|
||||
double tRRD = tRRD_values[tRRD_i];
|
||||
u32 tRFCpb = tRFC_values[tRFC_i];
|
||||
u32 tWTR = 10 - tWTR_values[tWTR_i];
|
||||
u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
||||
|
||||
double tDQSCK_max = 3.5;
|
||||
u32 tWPRE = 2;
|
||||
|
||||
double tRPST = 0.5;
|
||||
|
||||
u32 tR2W = CEIL(RL_DBI + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST) + 9.0) - (tRTW_i * 3);
|
||||
|
||||
u32 tRC = tRAS + tRPpb;
|
||||
u32 tRFCab = tRFCpb * 2;
|
||||
u32 tRPab = tRPpb + 3;
|
||||
|
||||
u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * (ramFreq / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg));
|
||||
|
||||
double tMMRI = tRCD + (tCK_avg * 3);
|
||||
double pdex2mrr = tMMRI + 10;
|
||||
u32 emc_cfg = hpMode ? 0x13200000 : 0xF3200000;
|
||||
|
||||
u32 refresh_raw = 0xFFFF;
|
||||
if (tREFpb_i != 6) {
|
||||
refresh_raw = CEIL(tREFpb_values[tREFpb_i] / tCK_avg) - 0x40;
|
||||
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
||||
for (u32 voltageIndex = 0; voltageIndex < 22; ++voltageIndex) {
|
||||
if (freqMhz <= ramBrackets[speedoBracket][voltageIndex]) {
|
||||
return gpuDvfsArray[voltageIndex];
|
||||
}
|
||||
}
|
||||
|
||||
u32 trefbw = refresh_raw + 0x40;
|
||||
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
||||
return 800;
|
||||
}
|
||||
|
||||
u32 tR2P = 12 + (rlAdd / 2);
|
||||
u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
||||
Handle Board::GetPcvHandle() {
|
||||
constexpr u64 PcvID = 0x10000000000001a;
|
||||
u64 processIDList[80]{};
|
||||
s32 processCount = 0;
|
||||
Handle handle = INVALID_HANDLE;
|
||||
|
||||
double tXSR = (double) (tRFCab + 7.5);
|
||||
DebugEventInfo debugEvent{};
|
||||
|
||||
args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = EMC_REGISTER_BASE + EMC_INTSTATUS_0;
|
||||
svcCallSecureMonitor(&args);
|
||||
/* Get all running processes. */
|
||||
Result resultGetProcessList = svcGetProcessList(&processCount, processIDList, std::size(processIDList));
|
||||
if (R_FAILED(resultGetProcessList)) {
|
||||
return INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if(args.X[1] == (EMC_REGISTER_BASE + EMC_INTSTATUS_0)) { // if param 1 is identical read failed, exosphere needs patch!
|
||||
writeNotification("Horizon OC\nExosphere not patched\nfor EMC r/w");
|
||||
/* Try to find pcv. */
|
||||
for (int i = 0; i < processCount; ++i) {
|
||||
if (handle != INVALID_HANDLE) {
|
||||
svcCloseHandle(handle);
|
||||
handle = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* Try to debug process, if it fails, try next process. */
|
||||
Result resultSvcDebugProcess = svcDebugActiveProcess(&handle, processIDList[i]);
|
||||
if (R_FAILED(resultSvcDebugProcess)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Try to get a debug event. */
|
||||
Result resultDebugEvent = svcGetDebugEvent(&debugEvent, handle);
|
||||
if (R_SUCCEEDED(resultDebugEvent)) {
|
||||
if (debugEvent.info.create_process.program_id == PcvID) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Failed to get handle. */
|
||||
return INVALID_HANDLE;
|
||||
}
|
||||
|
||||
void Board::CacheDvfsTable() {
|
||||
const u32 voltagePattern[] = { 600000, 12500, 1400000, };
|
||||
|
||||
Handle handle = GetPcvHandle();
|
||||
if (handle == INVALID_HANDLE) {
|
||||
FileUtils::LogLine("[Board] Invalid handle!");
|
||||
return;
|
||||
}
|
||||
|
||||
// actually write the timings
|
||||
WRITE_REGISTER_EMC(EMC_CFG_0, emc_cfg);
|
||||
WRITE_REGISTER_EMC(EMC_RD_RCD_0, GET_CYCLE_CEIL(tRCD));
|
||||
WRITE_REGISTER_EMC(EMC_WR_RCD_0, GET_CYCLE_CEIL(tRCD));
|
||||
WRITE_REGISTER_EMC(EMC_RC_0, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8)));
|
||||
WRITE_REGISTER_EMC(EMC_RAS_0, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F)));
|
||||
WRITE_REGISTER_EMC(EMC_RRD_0, GET_CYCLE_CEIL(tRRD));
|
||||
WRITE_REGISTER_EMC(EMC_RFCPB_0, GET_CYCLE_CEIL(tRFCpb));
|
||||
WRITE_REGISTER_EMC(EMC_RFC_0, GET_CYCLE_CEIL(tRFCab));
|
||||
WRITE_REGISTER_EMC(EMC_RP_0, GET_CYCLE_CEIL(tRPpb));
|
||||
WRITE_REGISTER_EMC(EMC_TRPAB_0, MIN(GET_CYCLE_CEIL(tRPab), static_cast<u32>(0x3F)));
|
||||
WRITE_REGISTER_EMC(EMC_R2W_0, tR2W);
|
||||
WRITE_REGISTER_EMC(EMC_W2R_0, tW2R);
|
||||
WRITE_REGISTER_EMC(EMC_REFRESH_0, refresh_raw);
|
||||
WRITE_REGISTER_EMC(EMC_PRE_REFRESH_REQ_CNT_0, refresh_raw / 4);
|
||||
WRITE_REGISTER_EMC(EMC_TREFBW_0, trefbw);
|
||||
WRITE_REGISTER_EMC(EMC_PDEX2MRR_0, GET_CYCLE_CEIL(pdex2mrr));
|
||||
WRITE_REGISTER_EMC(EMC_TXSR_0, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
||||
WRITE_REGISTER_EMC(EMC_TXSRDLL_0, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
||||
MemoryInfo memoryInfo = {};
|
||||
u64 address = 0;
|
||||
u32 pageInfo = 0;
|
||||
constexpr u32 PageSize = 0x1000;
|
||||
u8 buffer[PageSize];
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RCD_0, CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RP_0, CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RC_0, CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RAS_0, CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_FAW_0, CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RRD_0, CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RFCPB_0, CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1);
|
||||
/* Loop until failure. */
|
||||
while (true) {
|
||||
/* Find pcv heap. */
|
||||
while (true) {
|
||||
Result resultProcessMemory = svcQueryDebugProcessMemory(&memoryInfo, &pageInfo, handle, address);
|
||||
address = memoryInfo.addr + memoryInfo.size;
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_R2W_0, CEIL(tR2W / MC_ARB_DIV) - 1 + MC_ARB_SFA);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_W2R_0, CEIL(tW2R / MC_ARB_DIV) - 1 + MC_ARB_SFA);
|
||||
if (R_FAILED(resultProcessMemory) || !address) {
|
||||
svcCloseHandle(handle);
|
||||
FileUtils::LogLine("[Board] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory));
|
||||
handle = INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RAP2PRE_0, CEIL(tR2P / MC_ARB_DIV));
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_WAP2PRE_0, CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA);
|
||||
if (memoryInfo.size && (memoryInfo.perm & 3) == 3 && static_cast<char>(memoryInfo.type) == 0x04) {
|
||||
/* Found valid memory. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32 da_turns = 0;
|
||||
da_turns |= u8((CEIL(tR2W / MC_ARB_DIV) - 1 + MC_ARB_SFA) / 2) << 16;
|
||||
da_turns |= u8((CEIL(tW2R / MC_ARB_DIV) - 1 + MC_ARB_SFA) / 2) << 24;
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_DA_TURNS_0, da_turns);
|
||||
for (u64 base = 0; base < memoryInfo.size; base += PageSize) {
|
||||
u32 memorySize = std::min(memoryInfo.size, static_cast<u64>(PageSize));
|
||||
if (R_FAILED(svcReadDebugProcessMemory(buffer, handle, base + memoryInfo.addr, memorySize))) {
|
||||
break;
|
||||
}
|
||||
|
||||
u32 da_covers = 0;
|
||||
u8 r_cover = ((CEIL(tR2P / MC_ARB_DIV)) + (CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1) + (CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2)) / 2;
|
||||
u8 w_cover = ((CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA) + (CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1) + (CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2)) / 2;
|
||||
da_covers |= ((u32)(CEIL(GET_CYCLE_CEIL(tRC) / (u32)MC_ARB_DIV) - 1) / 2);
|
||||
da_covers |= (r_cover << 8);
|
||||
da_covers |= (w_cover << 16);
|
||||
u8 *resultPattern = static_cast<u8 *>(memmem_impl(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern)));
|
||||
u32 index = resultPattern - buffer;
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_DA_COVERS_0, da_covers);
|
||||
// TODO: modify mc_emem_arb_misc0
|
||||
|
||||
WRITE_REGISTER_MC(MC_TIMING_CONTROL_0, 0x1); // update timing regs as they are shadowed
|
||||
WRITE_REGISTER_EMC(EMC_TIMING_CONTROL_0, 0x1);
|
||||
if (!resultPattern) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Assuming mariko. */
|
||||
const u32 vmax = 800;
|
||||
constexpr u32 DvfsTableOffset = 312;
|
||||
if (!std::memcmp(&buffer[index + DvfsTableOffset], &vmax, sizeof(vmax))) {
|
||||
std::memcpy(dvfsTable, &buffer[index + DvfsTableOffset], sizeof(dvfsTable));
|
||||
dvfsAddress = base + memoryInfo.addr + DvfsTableOffset + index;
|
||||
}
|
||||
|
||||
svcCloseHandle(handle);
|
||||
handle = INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
svcCloseHandle(handle);
|
||||
handle = INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
void Board::PcvHijackDvfs(u32 vmin) {
|
||||
u32 table[192];
|
||||
static_assert(sizeof(table) == sizeof(dvfsTable));
|
||||
std::memcpy(table, dvfsTable, sizeof(dvfsTable));
|
||||
|
||||
if (ramVmin == vmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < std::size(table); ++i) {
|
||||
if (table[i] && table[i] <= vmin) {
|
||||
table[i] = vmin;
|
||||
}
|
||||
}
|
||||
|
||||
Handle handle = GetPcvHandle();
|
||||
if (handle == INVALID_HANDLE) {
|
||||
FileUtils::LogLine("Invalid handle!");
|
||||
return;
|
||||
}
|
||||
|
||||
Result rc = svcWriteDebugProcessMemory(handle, table, dvfsAddress, sizeof(table));
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
ramVmin = vmin;
|
||||
}
|
||||
|
||||
svcCloseHandle(handle);
|
||||
FileUtils::LogLine("[dvfs] voltage set to %u mV", vmin);
|
||||
}
|
||||
|
||||
bool Board::IsDram8GB() {
|
||||
SecmonArgs args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
|
||||
svcCallSecureMonitor(&args);
|
||||
SecmonArgs args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
if(args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed
|
||||
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
|
||||
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
|
||||
return false;
|
||||
} else
|
||||
return args.X[1] == 0x00002000 ? true : false;
|
||||
}
|
||||
|
||||
void Board::SetGpuSchedulingMode(GpuSchedulingMode mode, GpuSchedulingOverrideMethod method) {
|
||||
if (nvCheck_sched == 1 && method == GpuSchedulingOverrideMethod_NvService) {
|
||||
return;
|
||||
}
|
||||
u32 temp;
|
||||
bool enabled = false;
|
||||
switch(mode) {
|
||||
case GpuSchedulingMode_DoNotOverride:
|
||||
if (method == GpuSchedulingOverrideMethod_Ini) {
|
||||
const char* ini_path = "sdmc:/atmosphere/config/system_settings.ini";
|
||||
const char* section = "am.gpu";
|
||||
const char* key = "gpu_scheduling_enabled";
|
||||
|
||||
// Remove the key from the INI
|
||||
ini_puts(section, key, NULL, ini_path);
|
||||
}
|
||||
return;
|
||||
case GpuSchedulingMode_Disabled:
|
||||
if(method == GpuSchedulingOverrideMethod_NvService)
|
||||
nvIoctl(fd2, NVSCHED_CTRL_DISABLE, &temp);
|
||||
else
|
||||
enabled = false;
|
||||
break;
|
||||
case GpuSchedulingMode_Enabled:
|
||||
if(method == GpuSchedulingOverrideMethod_NvService)
|
||||
nvIoctl(fd2, NVSCHED_CTRL_ENABLE, &temp);
|
||||
else
|
||||
enabled = true;
|
||||
break;
|
||||
default:
|
||||
ASSERT_ENUM_VALID(GpuSchedulingMode, mode);
|
||||
}
|
||||
if(method == GpuSchedulingOverrideMethod_Ini) {
|
||||
const char* ini_path = "sdmc:/atmosphere/config/system_settings.ini";
|
||||
const char* section = "am.gpu";
|
||||
const char* key = "gpu_scheduling_enabled";
|
||||
|
||||
const char* value = enabled ? "u8!0x1" : "u8!0x0";
|
||||
|
||||
ini_puts(section, key, value, ini_path);
|
||||
}
|
||||
}
|
||||
void Board::SetDisplayRefreshDockedState(bool docked) {
|
||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||
DisplayRefresh_SetDockedState(docked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct EristaCpuUvEntry {
|
||||
u32 tune0;
|
||||
u32 tune1;
|
||||
} EristaCpuUvEntry;
|
||||
typedef struct MarikoCpuUvEntry {
|
||||
u32 tune0_low;
|
||||
u32 tune0_high;
|
||||
u32 tune1_low;
|
||||
u32 tune1_high;
|
||||
} MarikoCpuUvEntry;
|
||||
|
||||
EristaCpuUvEntry eristaCpuUvTable[5] = {
|
||||
{0xffff, 0x27007ff},
|
||||
{0xefff, 0x27407ff},
|
||||
{0xdfff, 0x27807ff},
|
||||
{0xdfdf, 0x27a07ff},
|
||||
{0xcfdf, 0x37007ff},
|
||||
};
|
||||
|
||||
MarikoCpuUvEntry marikoCpuUvLow[12] = {
|
||||
{0xffa0, 0xffff, 0x21107ff, 0},
|
||||
{0x0, 0xffdf, 0x21107ff, 0x27207ff},
|
||||
{0xffdf, 0xffdf, 0x21107ff, 0x27307ff},
|
||||
{0xffff, 0xffdf, 0x21107ff, 0x27407ff},
|
||||
{0x0, 0xffdf, 0x21607ff, 0x27707ff},
|
||||
{0x0, 0xffdf, 0x21607ff, 0x27807ff},
|
||||
{0x0, 0xdfff, 0x21607ff, 0x27b07ff},
|
||||
{0xdfff, 0xdfff, 0x21707ff, 0x27b07ff},
|
||||
{0xdfff, 0xdfff, 0x21707ff, 0x27c07ff},
|
||||
{0xdfff, 0xdfff, 0x21707ff, 0x27d07ff},
|
||||
{0xdfff, 0xdfff, 0x21707ff, 0x27e07ff},
|
||||
{0xdfff, 0xdfff, 0x21707ff, 0x27f07ff},
|
||||
};
|
||||
|
||||
MarikoCpuUvEntry marikoCpuUvHigh[12] = {
|
||||
{0x0, 0xffff, 0, 0},
|
||||
{0x0, 0xffdf, 0, 0x27207ff},
|
||||
{0x0, 0xffdf, 0, 0x27307ff},
|
||||
{0x0, 0xffdf, 0, 0x27407ff},
|
||||
{0x0, 0xffdf, 0, 0x27707ff},
|
||||
{0x0, 0xffdf, 0, 0x27807ff},
|
||||
{0x0, 0xdfff, 0, 0x27b07ff},
|
||||
{0x0, 0xdfff, 0, 0x27c07ff},
|
||||
{0x0, 0xdfff, 0, 0x27d07ff},
|
||||
{0x0, 0xdfff, 0, 0x27e07ff},
|
||||
{0x0, 0xdfff, 0, 0x27f07ff},
|
||||
{0x0, 0xdfff, 0, 0x27f07ff},
|
||||
};
|
||||
void Board::SetCpuUvLevel(u32 levelLow, u32 levelHigh, u32 tbreakPoint) {
|
||||
|
||||
u32* tune0_ptr = (u32*)(cldvfs + CL_DVFS_TUNE0_0);
|
||||
u32* tune1_ptr = (u32*)(cldvfs + CL_DVFS_TUNE1_0);
|
||||
if(Board::GetSocType() == SysClkSocType_Mariko) {
|
||||
if(Board::GetHz(SysClkModule_CPU) < tbreakPoint && (levelLow || levelHigh)) {
|
||||
if(levelLow) {
|
||||
*tune0_ptr = marikoCpuUvLow[levelLow-1].tune0_low;
|
||||
*tune1_ptr = marikoCpuUvLow[levelLow-1].tune1_low;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if(levelLow) {
|
||||
*tune0_ptr = marikoCpuUvLow[levelLow-1].tune0_low;
|
||||
*tune1_ptr = marikoCpuUvLow[levelLow-1].tune1_low;
|
||||
}
|
||||
if(levelHigh) {
|
||||
*tune0_ptr = marikoCpuUvHigh[levelHigh-1].tune0_high;
|
||||
*tune1_ptr = marikoCpuUvHigh[levelHigh-1].tune1_high;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(Board::GetHz(SysClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak
|
||||
*tune0_ptr = 0xCFFF;
|
||||
*tune1_ptr = 0xFF072201;
|
||||
return;
|
||||
} else if (Board::GetHz(SysClkModule_CPU) >= tbreakPoint || (!levelHigh)) {
|
||||
*tune0_ptr = cachedMarikoUvHighTune0; // per console?
|
||||
*tune1_ptr = 0xFFF7FF3F;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(Board::GetHz(SysClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak
|
||||
*tune0_ptr = cachedEristaUvLowTune0; // I think each erista has a different tune0/tune1?
|
||||
*tune1_ptr = cachedEristaUvLowTune1;
|
||||
return;
|
||||
} else {
|
||||
if(levelLow) {
|
||||
*tune0_ptr = eristaCpuUvTable[levelLow-1].tune0;
|
||||
*tune1_ptr = eristaCpuUvTable[levelLow-1].tune1;
|
||||
} else {
|
||||
*tune0_ptr = 0x0;
|
||||
*tune1_ptr = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
enum TableConfig: u32 {
|
||||
DEFAULT_TABLE = 1,
|
||||
TBREAK_1581 = 2,
|
||||
TBREAK_1683 = 3,
|
||||
EXTREME_TABLE = 4,
|
||||
};
|
||||
*/
|
||||
u32 Board::CalculateTbreak(u32 table) {
|
||||
if(Board::GetSocType() == SysClkSocType_Erista)
|
||||
return 1581000000;
|
||||
else {
|
||||
switch(table) {
|
||||
case 1 ... 2:
|
||||
case 4:
|
||||
return 1581000000;
|
||||
case 3:
|
||||
return 1683000000;
|
||||
default:
|
||||
return 1581000000;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -33,6 +33,8 @@
|
||||
class Board
|
||||
{
|
||||
public:
|
||||
static void PcvHijackDvfs(u32 vmin);
|
||||
static u32 GetMinimumGpuVoltage(u32 freqMhz);
|
||||
static void fuseReadSpeedos();
|
||||
static u16 getSpeedo(HorizonOCSpeedo speedoType);
|
||||
static u16 getIDDQ(HorizonOCSpeedo speedoType);
|
||||
@@ -61,10 +63,17 @@ class Board
|
||||
static std::uint32_t GetVoltage(HocClkVoltage voltage);
|
||||
static u8 GetFanRotationLevel();
|
||||
static u8 GetDramID();
|
||||
static void UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32 tRFC_i, u32 tRTW_i, u32 tWTR_i, u32 tREFpb_i, u32 ramFreq, u32 rlAdd, u32 wlAdd, bool hpMode);
|
||||
static bool IsDram8GB();
|
||||
static void SetGpuSchedulingMode(GpuSchedulingMode mode, GpuSchedulingOverrideMethod method);
|
||||
static void SetDisplayRefreshDockedState(bool docked);
|
||||
static void SetCpuUvLevel(u32 levelLow, u32 levelHigh, u32 tbreakPoint);
|
||||
static u32 CalculateTbreak(u32 table);
|
||||
protected:
|
||||
static void FetchHardwareInfos();
|
||||
static PcvModule GetPcvModule(SysClkModule sysclkModule);
|
||||
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
|
||||
private:
|
||||
static void SetSpeedoBracket();
|
||||
static void CacheDvfsTable();
|
||||
static Handle GetPcvHandle();
|
||||
};
|
||||
|
||||
@@ -41,14 +41,18 @@
|
||||
#include <crc32.h>
|
||||
|
||||
#define HOSPPC_HAS_BOOST (hosversionAtLeast(7,0,0))
|
||||
bool isGovernorEnabled = false; // to avoid thread messes
|
||||
bool lastGovernorState = false;
|
||||
bool isGpuGovernorEnabled = false;
|
||||
bool isCpuGovernorEnabled = false;
|
||||
bool lastGpuGovernorState = false;
|
||||
bool lastCpuGovernorState = false;
|
||||
bool hasChanged = true;
|
||||
ClockManager *ClockManager::instance = NULL;
|
||||
Thread governorTHREAD;
|
||||
Thread cpuGovernorTHREAD;
|
||||
Thread gpuGovernorTHREAD;
|
||||
u32 initialConfigValues[SysClkConfigValue_EnumMax]; // initial config. used for safety checks
|
||||
|
||||
bool kipAvailable = false;
|
||||
bool isCpuGovernorInBoostMode = false;
|
||||
|
||||
ClockManager *ClockManager::GetInstance()
|
||||
{
|
||||
return instance;
|
||||
@@ -88,11 +92,22 @@ ClockManager::ClockManager()
|
||||
this->lastTempLogNs = 0;
|
||||
this->lastCsvWriteNs = 0;
|
||||
|
||||
this->rnxSync = new ReverseNXSync;
|
||||
this->sysDockIntegration = new SysDockIntegration;
|
||||
memset(&initialConfigValues, 0, sizeof(initialConfigValues));
|
||||
this->GetKipData();
|
||||
|
||||
threadCreate(
|
||||
&governorTHREAD,
|
||||
&cpuGovernorTHREAD,
|
||||
ClockManager::CpuGovernorThread,
|
||||
this,
|
||||
NULL,
|
||||
0x2000,
|
||||
0x3F,
|
||||
-2
|
||||
);
|
||||
|
||||
threadCreate(
|
||||
&gpuGovernorTHREAD,
|
||||
ClockManager::GovernorThread,
|
||||
this,
|
||||
NULL,
|
||||
@@ -101,7 +116,8 @@ ClockManager::ClockManager()
|
||||
-2
|
||||
);
|
||||
|
||||
threadStart(&governorTHREAD);
|
||||
threadStart(&cpuGovernorTHREAD);
|
||||
threadStart(&gpuGovernorTHREAD);
|
||||
|
||||
for(int i = 0; i < HorizonOCSpeedo_EnumMax; i++) {
|
||||
this->context->speedos[i] = Board::getSpeedo((HorizonOCSpeedo)i);
|
||||
@@ -110,42 +126,15 @@ ClockManager::ClockManager()
|
||||
|
||||
this->context->dramID = Board::GetDramID();
|
||||
this->context->isDram8GB = Board::IsDram8GB();
|
||||
}
|
||||
|
||||
|
||||
void ClockManager::FixCpuBug() {
|
||||
if(this->config->Refresh() && this->RefreshContext()) {
|
||||
u32 targetHz = 0;
|
||||
u32 maxHz = 0;
|
||||
u32 nearestHz = 0;
|
||||
|
||||
// ResetToStockClocks();
|
||||
|
||||
targetHz = this->context->overrideFreqs[SysClkModule_CPU];
|
||||
if (!targetHz) {
|
||||
targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_CPU, this->context->profile, false);
|
||||
if(!targetHz)
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_CPU, this->context->profile, false);
|
||||
}
|
||||
|
||||
if (targetHz) {
|
||||
maxHz = this->GetMaxAllowedHz(SysClkModule_CPU, this->context->profile);
|
||||
nearestHz = this->GetNearestHz(SysClkModule_CPU, targetHz, maxHz);
|
||||
|
||||
while ((nearestHz = this->GetNearestHz(SysClkModule_CPU, targetHz, maxHz)) != targetHz) {
|
||||
Board::SetHz(SysClkModule_CPU, 1020000000);
|
||||
svcSleepThread(1'000'000);
|
||||
Board::SetHz(SysClkModule_CPU, maxHz);
|
||||
this->context->freqs[SysClkModule_CPU] = maxHz;
|
||||
}
|
||||
Board::SetHz(SysClkModule_CPU, targetHz);
|
||||
}
|
||||
}
|
||||
Board::SetGpuSchedulingMode((GpuSchedulingMode)this->config->GetConfigValue(HorizonOCConfigValue_GPUScheduling), (GpuSchedulingOverrideMethod)this->config->GetConfigValue(HorizonOCConfigValue_GPUSchedulingMethod));
|
||||
this->context->gpuSchedulingMode = (GpuSchedulingMode)this->config->GetConfigValue(HorizonOCConfigValue_GPUScheduling);
|
||||
this->context->isSysDockInstalled = this->sysDockIntegration->getCurrentSysDockState();
|
||||
}
|
||||
|
||||
ClockManager::~ClockManager()
|
||||
{
|
||||
threadClose(&governorTHREAD);
|
||||
threadClose(&cpuGovernorTHREAD);
|
||||
threadClose(&gpuGovernorTHREAD);
|
||||
delete this->config;
|
||||
delete this->context;
|
||||
}
|
||||
@@ -196,7 +185,7 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
{
|
||||
if (this->config->GetConfigValue(HocClkConfigValue_UncappedClocks))
|
||||
{
|
||||
return 4294967294; // Integer limit, uncapped clocks ON
|
||||
return ~0; // Integer limit, uncapped clocks ON
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -213,10 +202,10 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
return 614400000;
|
||||
case 1:
|
||||
return 691200000;
|
||||
case 2:
|
||||
case 2:
|
||||
return 768000000;
|
||||
default:
|
||||
return 614400000;
|
||||
return 614400000;
|
||||
}
|
||||
default:
|
||||
return 460800000;
|
||||
@@ -233,10 +222,10 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
return 844800000;
|
||||
case 1:
|
||||
return 921600000;
|
||||
case 2:
|
||||
case 2:
|
||||
return 998400000;
|
||||
default:
|
||||
return 844800000;
|
||||
return 844800000;
|
||||
}
|
||||
default:
|
||||
return 768000000;
|
||||
@@ -246,7 +235,7 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
if(profile < SysClkProfile_HandheldCharging && Board::GetSocType() == SysClkSocType_Erista) {
|
||||
return 1581000000;
|
||||
} else {
|
||||
return 4294967294;
|
||||
return ~0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,6 +326,160 @@ u32 findIndexMHz(u32 arr[], u32 size, u32 value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ClockManager::CpuGovernorThread(void* arg)
|
||||
{
|
||||
ClockManager* mgr = static_cast<ClockManager*>(arg);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!mgr->running)
|
||||
{
|
||||
svcSleepThread(50'000'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isCpuGovernorEnabled)
|
||||
{
|
||||
svcSleepThread(50'000'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::uint32_t mode = 0;
|
||||
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
|
||||
bool isInBoostMode = R_SUCCEEDED(rc) && apmExtIsBoostMode(mode);
|
||||
|
||||
if (isInBoostMode)
|
||||
{
|
||||
isCpuGovernorInBoostMode = true;
|
||||
svcSleepThread(50'000'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
isCpuGovernorInBoostMode = false;
|
||||
|
||||
auto& table = mgr->freqTable[SysClkModule_CPU];
|
||||
if (table.count == 0)
|
||||
{
|
||||
svcSleepThread(50'000'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::scoped_lock lock{mgr->contextMutex};
|
||||
|
||||
u32 currentHz = Board::GetHz(SysClkModule_CPU);
|
||||
|
||||
u32 index = table.count - 1;
|
||||
for (u32 i = 0; i < table.count; i++)
|
||||
{
|
||||
if (table.list[i] == currentHz)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (table.list[index] != currentHz)
|
||||
{
|
||||
for (u32 i = 0; i < table.count; i++)
|
||||
{
|
||||
if (table.list[i] >= currentHz)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 targetHz = mgr->context->overrideFreqs[SysClkModule_CPU];
|
||||
if (!targetHz)
|
||||
{
|
||||
targetHz = mgr->config->GetAutoClockHz(
|
||||
mgr->context->applicationId,
|
||||
SysClkModule_CPU,
|
||||
mgr->context->profile,
|
||||
false
|
||||
);
|
||||
|
||||
if (!targetHz)
|
||||
{
|
||||
targetHz = mgr->config->GetAutoClockHz(
|
||||
GLOBAL_PROFILE_ID,
|
||||
SysClkModule_CPU,
|
||||
mgr->context->profile,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int gpuLoad = Board::GetPartLoad(HocClkPartLoad_GPU);
|
||||
int cpuLoad = Board::GetPartLoad(HocClkPartLoad_CPUMax);
|
||||
|
||||
if (isGpuGovernorEnabled && gpuLoad < 800)
|
||||
{
|
||||
if (cpuLoad < 600 && index > 0)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
else if (cpuLoad > 800 && index + 1 < table.count)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpuLoad < 600 && index > 0)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
else if (cpuLoad > 800 && index + 1 < table.count)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
u32 maxHz = mgr->GetMaxAllowedHz(SysClkModule_CPU, mgr->context->profile);
|
||||
|
||||
if (targetHz)
|
||||
{
|
||||
u32 targetIndex = table.count - 1;
|
||||
for (u32 i = 0; i < table.count; i++)
|
||||
{
|
||||
if (table.list[i] >= targetHz)
|
||||
{
|
||||
targetIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index > targetIndex)
|
||||
{
|
||||
index = targetIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxHz > 0 && table.list[index] > maxHz)
|
||||
{
|
||||
for (u32 i = table.count; i > 0; i--)
|
||||
{
|
||||
if (table.list[i - 1] <= maxHz)
|
||||
{
|
||||
index = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 newHz = table.list[index];
|
||||
if (mgr->IsAssignableHz(SysClkModule_CPU, newHz))
|
||||
{
|
||||
Board::SetHz(SysClkModule_CPU, newHz);
|
||||
mgr->context->freqs[SysClkModule_CPU] = newHz;
|
||||
}
|
||||
|
||||
svcSleepThread(50'000'000);
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::GovernorThread(void* arg)
|
||||
{
|
||||
ClockManager* mgr = static_cast<ClockManager*>(arg);
|
||||
@@ -349,8 +492,7 @@ void ClockManager::GovernorThread(void* arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!isGovernorEnabled)
|
||||
if (!isGpuGovernorEnabled)
|
||||
{
|
||||
svcSleepThread(50'000'000);
|
||||
continue;
|
||||
@@ -362,12 +504,12 @@ void ClockManager::GovernorThread(void* arg)
|
||||
svcSleepThread(50'000'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
std::scoped_lock lock{mgr->contextMutex};
|
||||
|
||||
u32 currentHz = Board::GetHz(SysClkModule_GPU);
|
||||
|
||||
u32 index = 0;
|
||||
u32 index = table.count - 1;
|
||||
for (u32 i = 0; i < table.count; i++)
|
||||
{
|
||||
if (table.list[i] == currentHz)
|
||||
@@ -377,6 +519,18 @@ void ClockManager::GovernorThread(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
if (table.list[index] != currentHz)
|
||||
{
|
||||
for (u32 i = 0; i < table.count; i++)
|
||||
{
|
||||
if (table.list[i] >= currentHz)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 targetHz = mgr->context->overrideFreqs[SysClkModule_GPU];
|
||||
if (!targetHz)
|
||||
{
|
||||
@@ -398,17 +552,34 @@ void ClockManager::GovernorThread(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
int load = Board::GetPartLoad(HocClkPartLoad_GPU);
|
||||
int gpuLoad = Board::GetPartLoad(HocClkPartLoad_GPU);
|
||||
int cpuLoad = Board::GetPartLoad(HocClkPartLoad_CPUMax);
|
||||
|
||||
if (load < 600 && index > 0)
|
||||
if (isCpuGovernorEnabled && !isCpuGovernorInBoostMode && cpuLoad < 600)
|
||||
{
|
||||
index--;
|
||||
if (gpuLoad < 600 && index > 0)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
else if (gpuLoad > 750 && index + 1 < table.count)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else if (load > 800 && index + 1 < table.count)
|
||||
else
|
||||
{
|
||||
index++;
|
||||
if (gpuLoad < 600 && index > 0)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
else if (gpuLoad > 800 && index + 1 < table.count)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
u32 maxHz = mgr->GetMaxAllowedHz(SysClkModule_GPU, mgr->context->profile);
|
||||
|
||||
if (targetHz)
|
||||
{
|
||||
u32 targetIndex = table.count - 1;
|
||||
@@ -427,6 +598,17 @@ void ClockManager::GovernorThread(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
if (maxHz > 0 && table.list[index] > maxHz)
|
||||
{
|
||||
for (u32 i = table.count; i > 0; i--)
|
||||
{
|
||||
if (table.list[i - 1] <= maxHz)
|
||||
{
|
||||
index = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 newHz = table.list[index];
|
||||
if (mgr->IsAssignableHz(SysClkModule_GPU, newHz))
|
||||
@@ -439,16 +621,21 @@ void ClockManager::GovernorThread(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
bool prevBoostMode = true;
|
||||
|
||||
void ClockManager::Tick()
|
||||
GovernorState ClockManager::GetEffectiveGovernorState(GovernorState appState, GovernorState tempState)
|
||||
{
|
||||
std::scoped_lock lock{this->contextMutex};
|
||||
std::uint32_t mode = 0;
|
||||
AppletOperationMode opMode = appletGetOperationMode();
|
||||
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
|
||||
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
|
||||
if (tempState == GovernorState_Disabled)
|
||||
{
|
||||
return GovernorState_Disabled;
|
||||
}
|
||||
if (tempState != GovernorState_DoNotOverride)
|
||||
{
|
||||
return tempState;
|
||||
}
|
||||
return appState;
|
||||
}
|
||||
|
||||
void ClockManager::HandleSafetyFeatures() {
|
||||
AppletOperationMode opMode = appletGetOperationMode();
|
||||
if(this->config->GetConfigValue(HocClkConfigValue_HandheldTDP) && opMode == AppletOperationMode_Handheld) {
|
||||
if(Board::GetConsoleType() == HorizonOCConsoleType_Hoag) {
|
||||
if(Board::GetPowerMw(SysClkPowerSensor_Avg) < -(int)this->config->GetConfigValue(HocClkConfigValue_LiteTDPLimit)) {
|
||||
@@ -463,115 +650,241 @@ void ClockManager::Tick()
|
||||
}
|
||||
}
|
||||
|
||||
if(this->config->GetConfigValue(HocClkConfigValue_EnforceBoardLimit) && opMode == AppletOperationMode_Console ) {
|
||||
if(Board::GetPowerMw(SysClkPowerSensor_Now) < 0) {
|
||||
ResetToStockClocks();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(((tmp451TempSoc() / 1000) > (int)this->config->GetConfigValue(HocClkConfigValue_ThermalThrottleThreshold)) && this->config->GetConfigValue(HocClkConfigValue_ThermalThrottle)) {
|
||||
ResetToStockClocks();
|
||||
return;
|
||||
}
|
||||
bool isBoost = apmExtIsBoostMode(mode);
|
||||
// if(isBoost) {
|
||||
// Board::SetHz(SysClkModule_CPU, Board::GetSocType() == SysClkSocType_Mariko ? this->config->GetConfigValue(HocClkConfigValue_MarikoBoostCpuClock) * 1000'000 : this->config->GetConfigValue(HocClkConfigValue_EristaBoostCpuClock) * 1000'000);
|
||||
// }
|
||||
prevBoostMode = isBoost;
|
||||
}
|
||||
|
||||
bool noGPU = false;
|
||||
void ClockManager::HandleMiscFeatures() {
|
||||
if(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)) {
|
||||
I2c_Bq24193_SetFastChargeCurrentLimit(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent));
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::HandleGovernor(uint32_t targetHz) {
|
||||
GovernorState appGovernorState = (GovernorState)targetHz;
|
||||
|
||||
u32 tempTargetHz = this->context->overrideFreqs[HorizonOCModule_Governor];
|
||||
if (!tempTargetHz)
|
||||
{
|
||||
tempTargetHz = this->config->GetAutoClockHz(this->context->applicationId, HorizonOCModule_Governor, this->context->profile, true);
|
||||
if(!tempTargetHz)
|
||||
tempTargetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Governor, this->context->profile, true);
|
||||
}
|
||||
GovernorState tempGovernorState = (GovernorState)tempTargetHz;
|
||||
|
||||
GovernorState effectiveState = this->GetEffectiveGovernorState(appGovernorState, tempGovernorState);
|
||||
|
||||
bool newCpuGovernorState = (effectiveState == GovernorState_Enabled_CpuGpu || effectiveState == GovernorState_Enabled_Cpu);
|
||||
bool newGpuGovernorState = (effectiveState == GovernorState_Enabled_CpuGpu || effectiveState == GovernorState_Enabled_Gpu);
|
||||
|
||||
isCpuGovernorEnabled = newCpuGovernorState;
|
||||
isGpuGovernorEnabled = newGpuGovernorState;
|
||||
|
||||
if(newCpuGovernorState == false && lastCpuGovernorState == true) {
|
||||
svcSleepThread(150'000'000); // thread syncing. probably a cleaner way to do this but hey, it works!
|
||||
Board::ResetToStockCpu();
|
||||
}
|
||||
if(newGpuGovernorState == false && lastGpuGovernorState == true) {
|
||||
svcSleepThread(150'000'000);
|
||||
Board::ResetToStockGpu();
|
||||
}
|
||||
|
||||
if(newCpuGovernorState != lastCpuGovernorState || newGpuGovernorState != lastGpuGovernorState) {
|
||||
FileUtils::LogLine("[mgr] Governor state changed: CPU %s, GPU %s", newCpuGovernorState ? "enabled" : "disabled", newGpuGovernorState ? "enabled" : "disabled");
|
||||
lastCpuGovernorState = newCpuGovernorState;
|
||||
lastGpuGovernorState = newGpuGovernorState;
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::DVFSBeforeSet(u32 targetHz) {
|
||||
s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset);
|
||||
u32 vmin = Board::GetMinimumGpuVoltage(targetHz / 1000000) + dvfsOffset;
|
||||
|
||||
Board::PcvHijackDvfs(vmin);
|
||||
|
||||
/* Update the voltage. */
|
||||
if (I2c_BuckConverter_GetMvOut(&I2c_Mariko_GPU) < vmin) {
|
||||
I2c_BuckConverter_SetMvOut(&I2c_Mariko_GPU, vmin);
|
||||
}
|
||||
|
||||
this->context->voltages[HocClkVoltage_GPU] = vmin * 1000;
|
||||
}
|
||||
void ClockManager::DVFSAfterSet(u32 targetHz) {
|
||||
s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset);
|
||||
dvfsOffset = std::max(dvfsOffset, -50);
|
||||
u32 vmin = Board::GetMinimumGpuVoltage(targetHz / 1000000) + dvfsOffset;
|
||||
Board::PcvHijackDvfs(vmin);
|
||||
|
||||
targetHz = this->context->overrideFreqs[SysClkModule_GPU];
|
||||
if (!targetHz)
|
||||
{
|
||||
targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_GPU, this->context->profile, false);
|
||||
if(!targetHz)
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, this->context->profile, false);
|
||||
}
|
||||
if(targetHz) {
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::SetHz(SysClkModule_GPU, targetHz);
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::HandleCpuUv() {
|
||||
if(Board::GetSocType() == SysClkSocType_Erista)
|
||||
Board::SetCpuUvLevel(this->config->GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000);
|
||||
else
|
||||
Board::SetCpuUvLevel(this->config->GetConfigValue(KipConfigValue_marikoCpuUVLow), this->config->GetConfigValue(KipConfigValue_marikoCpuUVHigh), Board::CalculateTbreak(this->config->GetConfigValue(KipConfigValue_tableConf)));
|
||||
}
|
||||
|
||||
void ClockManager::DVFSReset() {
|
||||
if (Board::GetSocType() == SysClkSocType_Mariko && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
Board::PcvHijackDvfs(0);
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::ResetToStockGpu();
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::HandleFreqReset(SysClkModule module, bool isBoost) {
|
||||
switch (module)
|
||||
{
|
||||
case SysClkModule_CPU:
|
||||
if(!(isBoost || (this->config->GetConfigValue(HocClkConfigValue_OverwriteBoostMode) && isBoost)))
|
||||
Board::ResetToStockCpu();
|
||||
if(this->config->GetConfigValue(HorizonOCConfigValue_LiveCpuUv)) {
|
||||
if(Board::GetSocType() == SysClkSocType_Erista)
|
||||
Board::SetCpuUvLevel(this->config->GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000);
|
||||
else
|
||||
Board::SetCpuUvLevel(this->config->GetConfigValue(KipConfigValue_marikoCpuUVLow), this->config->GetConfigValue(KipConfigValue_marikoCpuUVHigh), Board::CalculateTbreak(this->config->GetConfigValue(KipConfigValue_tableConf)));
|
||||
}
|
||||
|
||||
break;
|
||||
case SysClkModule_GPU:
|
||||
Board::ResetToStockGpu();
|
||||
break;
|
||||
case SysClkModule_MEM:
|
||||
Board::ResetToStockMem();
|
||||
DVFSReset();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ClockManager::SetClocks(bool isBoost) {
|
||||
std::uint32_t targetHz = 0;
|
||||
std::uint32_t maxHz = 0;
|
||||
std::uint32_t nearestHz = 0;
|
||||
|
||||
if(isBoost && !this->config->GetConfigValue(HocClkConfigValue_OverwriteBoostMode)) {
|
||||
return; // Return if we are't overwriting boost mode
|
||||
}
|
||||
|
||||
bool returnRaw = false; // Return a value scaled to MHz instead of raw value
|
||||
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
u32 oldHz = Board::GetHz((SysClkModule)module); // Get Old RAM hz (used primarily for DVFS Logic)
|
||||
|
||||
if(module > SysClkModule_MEM)
|
||||
returnRaw = true;
|
||||
else
|
||||
returnRaw = false;
|
||||
targetHz = this->context->overrideFreqs[module];
|
||||
if (!targetHz)
|
||||
{
|
||||
targetHz = this->config->GetAutoClockHz(this->context->applicationId, (SysClkModule)module, this->context->profile, returnRaw);
|
||||
if(!targetHz)
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, (SysClkModule)module, this->context->profile, returnRaw);
|
||||
}
|
||||
|
||||
if(module == HorizonOCModule_Governor) {
|
||||
HandleGovernor(targetHz);
|
||||
}
|
||||
|
||||
if(module == HorizonOCModule_Display && this->config->GetConfigValue(HorizonOCConfigValue_OverwriteRefreshRate) && Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||
if(targetHz)
|
||||
Board::SetHz(HorizonOCModule_Display, targetHz);
|
||||
else
|
||||
Board::ResetToStockDisplay();
|
||||
}
|
||||
|
||||
// Skip GPU and CPU if governors handle them
|
||||
if(module > SysClkModule_MEM) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool noCPU = isCpuGovernorEnabled;
|
||||
bool noGPU = isGpuGovernorEnabled;
|
||||
|
||||
if(noCPU && module == SysClkModule_CPU)
|
||||
continue;
|
||||
if(noGPU && module == SysClkModule_GPU)
|
||||
continue;
|
||||
|
||||
if (targetHz)
|
||||
{
|
||||
maxHz = this->GetMaxAllowedHz((SysClkModule)module, this->context->profile);
|
||||
nearestHz = this->GetNearestHz((SysClkModule)module, targetHz, maxHz);
|
||||
|
||||
if (nearestHz != this->context->freqs[module]) {
|
||||
FileUtils::LogLine(
|
||||
"[mgr] %s clock set : %u.%u MHz (target = %u.%u MHz)",
|
||||
Board::GetModuleName((SysClkModule)module, true),
|
||||
nearestHz / 1000000, nearestHz / 100000 - nearestHz / 1000000 * 10,
|
||||
targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10
|
||||
);
|
||||
|
||||
if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz > oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
DVFSBeforeSet(targetHz);
|
||||
}
|
||||
|
||||
Board::SetHz((SysClkModule)module, nearestHz);
|
||||
this->context->freqs[module] = nearestHz;
|
||||
|
||||
if(module == SysClkModule_CPU && this->config->GetConfigValue(HorizonOCConfigValue_LiveCpuUv))
|
||||
{
|
||||
HandleCpuUv();
|
||||
}
|
||||
|
||||
if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz < oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
DVFSAfterSet(targetHz);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
HandleFreqReset((SysClkModule)module, isBoost);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ClockManager::Tick()
|
||||
{
|
||||
std::scoped_lock lock{this->contextMutex};
|
||||
std::uint32_t mode = 0;
|
||||
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
|
||||
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
|
||||
|
||||
bool isBoost = apmExtIsBoostMode(mode);
|
||||
|
||||
HandleSafetyFeatures();
|
||||
|
||||
if (this->RefreshContext() || this->config->Refresh())
|
||||
{
|
||||
if(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)) {
|
||||
I2c_Bq24193_SetFastChargeCurrentLimit(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent));
|
||||
}
|
||||
std::uint32_t targetHz = 0;
|
||||
std::uint32_t maxHz = 0;
|
||||
std::uint32_t nearestHz = 0;
|
||||
|
||||
if(apmExtIsBoostMode(mode) && !this->config->GetConfigValue(HocClkConfigValue_OverwriteBoostMode)) {
|
||||
// ResetToStockClocks();
|
||||
return;
|
||||
}
|
||||
|
||||
bool returnRaw = false;
|
||||
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
if(module > SysClkModule_MEM)
|
||||
returnRaw = true;
|
||||
else
|
||||
returnRaw = false;
|
||||
targetHz = this->context->overrideFreqs[module];
|
||||
if (!targetHz)
|
||||
{
|
||||
targetHz = this->config->GetAutoClockHz(this->context->applicationId, (SysClkModule)module, this->context->profile, returnRaw);
|
||||
if(!targetHz)
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, (SysClkModule)module, this->context->profile, returnRaw);
|
||||
}
|
||||
|
||||
if(module == HorizonOCModule_Governor) {
|
||||
bool newGovernorState = targetHz;
|
||||
if(newGovernorState != lastGovernorState) {
|
||||
FileUtils::LogLine("[mgr] Governor state changed: %s", newGovernorState ? "enabled" : "disabled");
|
||||
lastGovernorState = newGovernorState;
|
||||
|
||||
hasChanged = true;
|
||||
Board::ResetToStock();
|
||||
}
|
||||
isGovernorEnabled = newGovernorState;
|
||||
}
|
||||
|
||||
if(module == HorizonOCModule_Display && this->config->GetConfigValue(HorizonOCConfigValue_OverwriteRefreshRate) && Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||
if(targetHz)
|
||||
Board::SetHz(HorizonOCModule_Display, targetHz);
|
||||
else
|
||||
Board::ResetToStockDisplay();
|
||||
|
||||
}
|
||||
|
||||
if(targetHz && this->context->realFreqs[HorizonOCModule_Display] != targetHz && module == HorizonOCModule_Display)
|
||||
this->context->realFreqs[HorizonOCModule_Display] = targetHz;
|
||||
|
||||
// Skip GPU if governor handles it
|
||||
if(module > SysClkModule_MEM) {
|
||||
continue;
|
||||
}
|
||||
if(isGovernorEnabled) {
|
||||
noGPU = true;
|
||||
} else {
|
||||
noGPU = false;
|
||||
}
|
||||
if(noGPU && module == SysClkModule_GPU)
|
||||
continue;
|
||||
|
||||
if (targetHz)
|
||||
{
|
||||
maxHz = this->GetMaxAllowedHz((SysClkModule)module, this->context->profile);
|
||||
nearestHz = this->GetNearestHz((SysClkModule)module, targetHz, maxHz);
|
||||
|
||||
if (nearestHz != this->context->freqs[module]) {
|
||||
FileUtils::LogLine(
|
||||
"[mgr] %s clock set : %u.%u MHz (target = %u.%u MHz)",
|
||||
Board::GetModuleName((SysClkModule)module, true),
|
||||
nearestHz / 1000000, nearestHz / 100000 - nearestHz / 1000000 * 10,
|
||||
targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10
|
||||
);
|
||||
|
||||
Board::SetHz((SysClkModule)module, nearestHz);
|
||||
this->context->freqs[module] = nearestHz;
|
||||
}
|
||||
if(module == SysClkModule_CPU && this->config->GetConfigValue(HocClkConfigValue_FixCpuVoltBug)) {
|
||||
FixCpuBug();
|
||||
}
|
||||
}
|
||||
}
|
||||
HandleMiscFeatures();
|
||||
SetClocks(isBoost);
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::ResetToStockClocks() {
|
||||
Board::ResetToStockCpu();
|
||||
if(this->config->GetConfigValue(HorizonOCConfigValue_LiveCpuUv))
|
||||
{
|
||||
if(Board::GetSocType() == SysClkSocType_Erista)
|
||||
Board::SetCpuUvLevel(this->config->GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000);
|
||||
else
|
||||
Board::SetCpuUvLevel(this->config->GetConfigValue(KipConfigValue_marikoCpuUVLow), this->config->GetConfigValue(KipConfigValue_marikoCpuUVHigh), Board::CalculateTbreak(this->config->GetConfigValue(KipConfigValue_tableConf)));
|
||||
}
|
||||
|
||||
Board::ResetToStockGpu();
|
||||
}
|
||||
|
||||
@@ -586,7 +899,7 @@ void ClockManager::WaitForNextTick()
|
||||
bool ClockManager::RefreshContext()
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
|
||||
std::uint32_t mode = 0;
|
||||
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
|
||||
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
|
||||
@@ -597,7 +910,6 @@ bool ClockManager::RefreshContext()
|
||||
FileUtils::LogLine("[mgr] TitleID change: %016lX", applicationId);
|
||||
this->context->applicationId = applicationId;
|
||||
hasChanged = true;
|
||||
this->rnxSync->Reset(applicationId);
|
||||
}
|
||||
|
||||
SysClkProfile profile = Board::GetProfile();
|
||||
@@ -611,8 +923,12 @@ bool ClockManager::RefreshContext()
|
||||
// restore clocks to stock values on app or profile change
|
||||
if (hasChanged)
|
||||
{
|
||||
// this->rnxSync->ToggleSync(this->GetConfig()->GetConfigValue(HocClkConfigValue_SyncReverseNXMode));
|
||||
Board::ResetToStock();
|
||||
if (Board::GetSocType() == SysClkSocType_Mariko && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
Board::PcvHijackDvfs(0);
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::ResetToStockGpu();
|
||||
}
|
||||
this->WaitForNextTick();
|
||||
}
|
||||
|
||||
@@ -634,23 +950,6 @@ bool ClockManager::RefreshContext()
|
||||
{
|
||||
FileUtils::LogLine("[mgr] %s override change: %u.%u MHz", Board::GetModuleName((SysClkModule)module, true), hz / 1000000, hz / 100000 - hz / 1000000 * 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileUtils::LogLine("[mgr] %s override disabled", Board::GetModuleName((SysClkModule)module, true));
|
||||
switch (module)
|
||||
{
|
||||
case SysClkModule_CPU:
|
||||
if(!(apmExtIsBoostMode(mode) || (this->config->GetConfigValue(HocClkConfigValue_OverwriteBoostMode) && apmExtIsBoostMode(mode))))
|
||||
Board::ResetToStockCpu();
|
||||
break;
|
||||
case SysClkModule_GPU:
|
||||
Board::ResetToStockGpu();
|
||||
break;
|
||||
case SysClkModule_MEM:
|
||||
Board::ResetToStockMem();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->context->overrideFreqs[module] = hz;
|
||||
hasChanged = true;
|
||||
}
|
||||
@@ -713,7 +1012,7 @@ bool ClockManager::RefreshContext()
|
||||
FileUtils::WriteContextToCsv(this->context);
|
||||
}
|
||||
|
||||
this->context->maxDisplayFreq = Board::GetHighestDockedDisplayRate();
|
||||
// this->context->maxDisplayFreq = Board::GetHighestDockedDisplayRate();
|
||||
|
||||
u32 targetHz = this->context->overrideFreqs[HorizonOCModule_Display];
|
||||
if (!targetHz)
|
||||
@@ -723,18 +1022,15 @@ bool ClockManager::RefreshContext()
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Display, this->context->profile, true);
|
||||
}
|
||||
|
||||
if(targetHz && this->context->realFreqs[HorizonOCModule_Display] > targetHz)
|
||||
this->context->realFreqs[HorizonOCModule_Display] = targetHz; // clean up display real freqs, should probably be moved to the real freqs loop?
|
||||
|
||||
if(targetHz && this->context->realFreqs[HorizonOCModule_Display] > targetHz && this->context->profile != SysClkProfile_Docked)
|
||||
this->context->realFreqs[HorizonOCModule_Display] = targetHz; // clean up display real freqs, should probably be moved to the real freqs loop?
|
||||
|
||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
||||
Board::SetDisplayRefreshDockedState(this->context->profile == SysClkProfile_Docked);
|
||||
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
void ClockManager::SetRNXRTMode(ReverseNXMode mode)
|
||||
{
|
||||
this->rnxSync->SetRTMode(mode);
|
||||
}
|
||||
|
||||
void ClockManager::SetKipData() {
|
||||
// TODO: figure out if this REALLY causes issues (i doubt it)
|
||||
// if(Board::GetSocType() == SysClkSocType_Mariko) {
|
||||
@@ -768,6 +1064,8 @@ void ClockManager::SetKipData() {
|
||||
|
||||
CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, this->config->GetConfigValue(KipConfigValue_commonEmcMemVolt));
|
||||
CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock));
|
||||
CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock1, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock1));
|
||||
CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock2));
|
||||
CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock));
|
||||
CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, this->config->GetConfigValue(KipConfigValue_marikoEmcVddqVolt));
|
||||
CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, this->config->GetConfigValue(KipConfigValue_emcDvbShift));
|
||||
@@ -816,6 +1114,9 @@ void ClockManager::SetKipData() {
|
||||
table.eristaGpuVoltArray[i] = this->config->GetConfigValue((SysClkConfigValue)(KipConfigValue_g_volt_e_76800 + i));
|
||||
}
|
||||
|
||||
CUST_WRITE_FIELD_BATCH(&table, t6_tRTW_fine_tune, this->config->GetConfigValue(KipConfigValue_t6_tRTW_fine_tune));
|
||||
CUST_WRITE_FIELD_BATCH(&table, t7_tWTR_fine_tune, this->config->GetConfigValue(KipConfigValue_t7_tWTR_fine_tune));
|
||||
|
||||
if (!cust_write_table("sdmc:/atmosphere/kips/hoc.kip", &table)) {
|
||||
FileUtils::LogLine("[clock_manager] Failed to write KIP file");
|
||||
writeNotification("Horizon OC\nKip write failed");
|
||||
@@ -888,6 +1189,8 @@ void ClockManager::GetKipData() {
|
||||
|
||||
initialConfigValues[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table);
|
||||
initialConfigValues[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table);
|
||||
initialConfigValues[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table);
|
||||
initialConfigValues[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table);
|
||||
initialConfigValues[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table);
|
||||
initialConfigValues[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table);
|
||||
initialConfigValues[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table);
|
||||
@@ -908,7 +1211,6 @@ void ClockManager::GetKipData() {
|
||||
initialConfigValues[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table);
|
||||
initialConfigValues[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table);
|
||||
|
||||
|
||||
initialConfigValues[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table);
|
||||
initialConfigValues[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table);
|
||||
initialConfigValues[KipConfigValue_tableConf] = cust_get_table_conf(&table);
|
||||
@@ -926,6 +1228,8 @@ void ClockManager::GetKipData() {
|
||||
initialConfigValues[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table);
|
||||
initialConfigValues[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table);
|
||||
initialConfigValues[KipConfigValue_gpuSpeedo] = cust_get_gpu_speedo(&table);
|
||||
initialConfigValues[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table);
|
||||
initialConfigValues[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table);
|
||||
}
|
||||
|
||||
// configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table);
|
||||
@@ -933,6 +1237,8 @@ void ClockManager::GetKipData() {
|
||||
|
||||
configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table);
|
||||
configValues.values[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table);
|
||||
configValues.values[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table);
|
||||
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);
|
||||
@@ -982,6 +1288,9 @@ void ClockManager::GetKipData() {
|
||||
initialConfigValues[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_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);
|
||||
|
||||
// if(cust_get_cust_rev(&table) == KIP_CUST_REV)
|
||||
// return;
|
||||
|
||||
@@ -1000,75 +1309,4 @@ void ClockManager::GetKipData() {
|
||||
FileUtils::LogLine("[clock_manager] Config refresh error in GetKipData!");
|
||||
writeNotification("Horizon OC\nConfig refresh failed");
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::UpdateRamTimings() {
|
||||
u32 t1_tRCD = this->config->GetConfigValue(KipConfigValue_t1_tRCD);
|
||||
u32 t2_tRP = this->config->GetConfigValue(KipConfigValue_t2_tRP);
|
||||
u32 t3_tRAS = this->config->GetConfigValue(KipConfigValue_t3_tRAS);
|
||||
u32 t4_tRRD = this->config->GetConfigValue(KipConfigValue_t4_tRRD);
|
||||
u32 t5_tRFC = this->config->GetConfigValue(KipConfigValue_t5_tRFC);
|
||||
u32 t6_tRTW = this->config->GetConfigValue(KipConfigValue_t6_tRTW);
|
||||
u32 t7_tWTR = this->config->GetConfigValue(KipConfigValue_t7_tWTR);
|
||||
u32 t8_tREFI = this->config->GetConfigValue(KipConfigValue_t8_tREFI);
|
||||
bool hpMode = (bool)this->config->GetConfigValue(KipConfigValue_hpMode);
|
||||
|
||||
u64 ramFreq = initialConfigValues[KipConfigValue_marikoEmcMaxClock];
|
||||
u32 rlAdd = initialConfigValues[KipConfigValue_mem_burst_read_latency];
|
||||
u32 wlAdd = initialConfigValues[KipConfigValue_mem_burst_write_latency];
|
||||
|
||||
|
||||
Board::UpdateShadowRegs(t1_tRCD, t2_tRP, t3_tRAS, t4_tRRD, t5_tRFC, t6_tRTW, t7_tWTR, t8_tREFI, ramFreq, rlAdd, wlAdd, hpMode);
|
||||
}
|
||||
|
||||
unsigned int ramBrackets[][22] =
|
||||
{
|
||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }
|
||||
};
|
||||
|
||||
unsigned int gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||
|
||||
int ClockManager::GetSpeedoBracket (int speedo)
|
||||
{
|
||||
int speedoBracket = 3;
|
||||
if ((speedo < 1754) && (speedoBracket = 2, speedo < 1690)) {
|
||||
speedoBracket = !!(1625 < speedo);
|
||||
}
|
||||
|
||||
return speedoBracket;
|
||||
}
|
||||
|
||||
unsigned int ClockManager::GetGpuVoltage (unsigned int freq, int speedo)
|
||||
{
|
||||
long int loop;
|
||||
int bracket = GetSpeedoBracket(speedo);
|
||||
|
||||
if (freq < 1601)
|
||||
return 610;
|
||||
|
||||
loop = 0;
|
||||
do
|
||||
{
|
||||
if (freq <= ramBrackets[bracket][loop])
|
||||
return gpuDvfsArray[loop];
|
||||
|
||||
loop++;
|
||||
} while (loop != 22);
|
||||
|
||||
return 800;
|
||||
}
|
||||
|
||||
void ClockManager::calculateGpuVmin (void)
|
||||
{
|
||||
if(this->config->Refresh()) {
|
||||
SysClkConfigValueList configValues;
|
||||
this->config->GetConfigValues(&configValues);
|
||||
|
||||
int speedo = Board::getSpeedo(HorizonOCSpeedo_CPU), freq = this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock);
|
||||
configValues.values[KipConfigValue_marikoGpuVmin] = GetGpuVoltage(freq, speedo);
|
||||
this->config->SetConfigValues(&configValues, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,54 +23,166 @@
|
||||
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <sysclk.h>
|
||||
#include <switch.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "board.h"
|
||||
#include <nxExt/cpp/lockable_mutex.h>
|
||||
#include "integrations.h"
|
||||
void governorThread(void*);
|
||||
|
||||
class ReverseNXSync;
|
||||
|
||||
class SysDockIntegration;
|
||||
class ClockManager
|
||||
{
|
||||
public:
|
||||
static ClockManager* GetInstance();
|
||||
static void Initialize();
|
||||
static void Exit();
|
||||
|
||||
|
||||
ClockManager();
|
||||
virtual ~ClockManager();
|
||||
void FixCpuBug();
|
||||
|
||||
SysClkContext GetCurrentContext();
|
||||
Config* GetConfig();
|
||||
void SetRunning(bool running);
|
||||
bool Running();
|
||||
void GetFreqList(SysClkModule module, std::uint32_t* list, std::uint32_t maxCount, std::uint32_t* outCount);
|
||||
|
||||
/**
|
||||
* Handles safety features
|
||||
*
|
||||
*/
|
||||
void HandleSafetyFeatures();
|
||||
|
||||
/**
|
||||
* Handles misc features (currently only battery charge current).
|
||||
*
|
||||
*/
|
||||
void HandleMiscFeatures();
|
||||
|
||||
/**
|
||||
* Handles governor state resolution and applies CPU/GPU governor transitions.
|
||||
*
|
||||
* @param targetHz Governor override value for the current profile.
|
||||
*/
|
||||
void HandleGovernor(uint32_t targetHz);
|
||||
|
||||
/**
|
||||
* Handles DVFS logic before the frequency set
|
||||
*
|
||||
* @param targetHz Governor override value for the current profile.
|
||||
*/
|
||||
void DVFSBeforeSet(u32 targetHz);
|
||||
|
||||
/**
|
||||
* Handles DVFS logic after the frequency set
|
||||
*
|
||||
* @param targetHz Governor override value for the current profile.
|
||||
*/
|
||||
void DVFSAfterSet(u32 targetHz);
|
||||
|
||||
/**
|
||||
* Reset the GPU vMin
|
||||
*
|
||||
*/
|
||||
void DVFSReset();
|
||||
|
||||
/**
|
||||
* Handles the Live CPU UV Feature
|
||||
*
|
||||
*/
|
||||
void HandleCpuUv();
|
||||
|
||||
/**
|
||||
* Handles frequency resets
|
||||
*
|
||||
* @param module The module to reset frequency for
|
||||
* @param isBoost Is in boost mode
|
||||
*/
|
||||
void HandleFreqReset(SysClkModule module, bool isBoost);
|
||||
|
||||
/**
|
||||
* Sets clocks
|
||||
*
|
||||
* @param isBoost Is in boost mode
|
||||
*/
|
||||
void SetClocks(bool isBoost);
|
||||
|
||||
/**
|
||||
* Main function, runs every 5s in sleep mode, and a user specified amount when awake
|
||||
*
|
||||
*/
|
||||
void Tick();
|
||||
|
||||
/**
|
||||
* Reset CPU/GPU to stock values
|
||||
*
|
||||
*/
|
||||
void ResetToStockClocks();
|
||||
|
||||
/**
|
||||
* Wait for the next tick event
|
||||
*
|
||||
*/
|
||||
void WaitForNextTick();
|
||||
void SetRNXRTMode(ReverseNXMode mode);
|
||||
|
||||
/**
|
||||
* Set the data in the KIP
|
||||
*
|
||||
*/
|
||||
void SetKipData();
|
||||
|
||||
/**
|
||||
* Get the data from the KIP
|
||||
*
|
||||
*/
|
||||
void GetKipData();
|
||||
|
||||
/**
|
||||
* Runs the CPU Governor
|
||||
*
|
||||
* @param arg Cast to ClockManager* for context
|
||||
*/
|
||||
static void CpuGovernorThread(void* arg);
|
||||
|
||||
/**
|
||||
* Runs the GPU Governor
|
||||
*
|
||||
* @param arg Cast to ClockManager* for context
|
||||
*/
|
||||
static void GovernorThread(void* arg);
|
||||
void UpdateRamTimings();
|
||||
|
||||
/**
|
||||
* Gets the effective governor state from application/temporary override
|
||||
*
|
||||
* @param appState Governor state from app
|
||||
* @param tempState Governor state from temporary override
|
||||
*/
|
||||
GovernorState GetEffectiveGovernorState(GovernorState appState, GovernorState tempState);
|
||||
|
||||
/**
|
||||
* Frequency tables
|
||||
*
|
||||
*/
|
||||
struct {
|
||||
std::uint32_t count;
|
||||
std::uint32_t list[SYSCLK_FREQ_LIST_MAX];
|
||||
} freqTable[SysClkModule_EnumMax];
|
||||
|
||||
/**
|
||||
* Gets the current GPU speedo bracket
|
||||
*
|
||||
* @param speedo GPU Speedo
|
||||
*/
|
||||
int GetSpeedoBracket (int speedo);
|
||||
|
||||
/**
|
||||
* Gets the required vMin for a ram frequency for a speedo
|
||||
*
|
||||
* @param freq RAM Freq in MHz
|
||||
* @param speedo GPU Speedo
|
||||
*/
|
||||
unsigned int GetGpuVoltage (unsigned int freq, int speedo);
|
||||
void calculateGpuVmin(void);
|
||||
|
||||
protected:
|
||||
bool IsAssignableHz(SysClkModule module, std::uint32_t hz);
|
||||
inline std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile);
|
||||
@@ -78,9 +190,7 @@ class ClockManager
|
||||
bool ConfigIntervalTimeout(SysClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t* lastLogNs);
|
||||
void RefreshFreqTableRow(SysClkModule module);
|
||||
bool RefreshContext();
|
||||
|
||||
static ClockManager *instance;
|
||||
|
||||
std::atomic_bool running;
|
||||
LockableMutex contextMutex;
|
||||
Config* config;
|
||||
@@ -89,5 +199,5 @@ class ClockManager
|
||||
std::uint64_t lastFreqLogNs;
|
||||
std::uint64_t lastPowerLogNs;
|
||||
std::uint64_t lastCsvWriteNs;
|
||||
ReverseNXSync *rnxSync;
|
||||
};
|
||||
SysDockIntegration *sysDockIntegration;
|
||||
};
|
||||
@@ -17,68 +17,16 @@
|
||||
|
||||
|
||||
#include "integrations.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
ReverseNXSync::ReverseNXSync()
|
||||
: m_rt_mode(ReverseNX_NotFound), m_tool_mode(ReverseNX_NotFound) {
|
||||
FILE *fp = fopen("/atmosphere/contents/0000000000534C56/flags/boot2.flag", "r");
|
||||
m_tool_enabled = fp ? true : false;
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
SysDockIntegration::SysDockIntegration() {
|
||||
}
|
||||
|
||||
SysClkProfile ReverseNXSync::GetProfile(SysClkProfile real) {
|
||||
switch (this->GetMode()) {
|
||||
case ReverseNX_Docked:
|
||||
return SysClkProfile_Docked;
|
||||
case ReverseNX_Handheld:
|
||||
if (real == SysClkProfile_Docked)
|
||||
return SysClkProfile_HandheldChargingOfficial;
|
||||
default:
|
||||
return real;
|
||||
bool SysDockIntegration::getCurrentSysDockState() {
|
||||
struct stat st = {0};
|
||||
if (stat("sdmc:/atmosphere/contents/42000000000000A0", &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ReverseNXMode ReverseNXSync::GetMode() {
|
||||
if (!this->m_sync_enabled)
|
||||
return ReverseNX_NotFound;
|
||||
if (this->m_rt_mode)
|
||||
return this->m_rt_mode;
|
||||
return this->m_tool_mode;
|
||||
}
|
||||
|
||||
ReverseNXMode ReverseNXSync::GetToolModeFromPatch(const char* patch_path) {
|
||||
constexpr uint32_t DOCKED_MAGIC = 0x320003E0;
|
||||
constexpr uint32_t HANDHELD_MAGIC = 0x52A00000;
|
||||
FILE *fp = fopen(patch_path, "rb");
|
||||
if (fp) {
|
||||
uint32_t buf = 0;
|
||||
fread(&buf, sizeof(buf), 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
if (buf == DOCKED_MAGIC)
|
||||
return ReverseNX_Docked;
|
||||
if (buf == HANDHELD_MAGIC)
|
||||
return ReverseNX_Handheld;
|
||||
}
|
||||
|
||||
return ReverseNX_NotFound;
|
||||
}
|
||||
|
||||
ReverseNXMode ReverseNXSync::RecheckToolMode() {
|
||||
ReverseNXMode mode = ReverseNX_NotFound;
|
||||
if (this->m_tool_enabled) {
|
||||
const char* fileName = "_ZN2nn2oe18GetPerformanceModeEv.asm64"; // or _ZN2nn2oe18GetPerformanceModeEv.asm64
|
||||
const char* filePath = new char[72];
|
||||
SCOPE_EXIT { delete[] filePath; };
|
||||
/* Check per-game patch */
|
||||
snprintf((char*)filePath, 72, "/SaltySD/patches/%016lX/%s", this->m_app_id, fileName);
|
||||
mode = this->GetToolModeFromPatch(filePath);
|
||||
if (!mode) {
|
||||
/* Check global patch */
|
||||
snprintf((char*)filePath, 72, "/SaltySD/patches/%s", fileName);
|
||||
mode = this->GetToolModeFromPatch(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
@@ -29,25 +29,9 @@
|
||||
|
||||
#include "clock_manager.h"
|
||||
|
||||
class ReverseNXSync {
|
||||
class SysDockIntegration {
|
||||
public:
|
||||
ReverseNXSync ();
|
||||
SysDockIntegration();
|
||||
|
||||
void ToggleSync(bool enable) { m_sync_enabled = enable; };
|
||||
void Reset(uint64_t app_id) { m_app_id = app_id; SetRTMode(ReverseNX_NotFound); GetToolMode(); }
|
||||
ReverseNXMode GetRTMode() { return m_rt_mode; };
|
||||
void SetRTMode(ReverseNXMode mode) { m_rt_mode = mode; };
|
||||
ReverseNXMode GetToolMode() { return m_tool_mode = RecheckToolMode(); };
|
||||
SysClkProfile GetProfile(SysClkProfile real);
|
||||
ReverseNXMode GetMode();
|
||||
|
||||
protected:
|
||||
std::atomic<ReverseNXMode> m_rt_mode;
|
||||
ReverseNXMode m_tool_mode;
|
||||
uint64_t m_app_id = 0;
|
||||
bool m_tool_enabled;
|
||||
bool m_sync_enabled;
|
||||
|
||||
ReverseNXMode GetToolModeFromPatch(const char* patch_path);
|
||||
ReverseNXMode RecheckToolMode();
|
||||
bool getCurrentSysDockState();
|
||||
};
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -43,7 +43,7 @@ IpcService::IpcService(ClockManager* clockMgr)
|
||||
|
||||
this->running = false;
|
||||
this->clockMgr = clockMgr;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void IpcService::SetRunning(bool running)
|
||||
@@ -198,27 +198,11 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8*
|
||||
);
|
||||
}
|
||||
break;
|
||||
case SysClkIpcCmd_SetReverseNXRTMode:
|
||||
if (r->data.size >= sizeof(ReverseNXMode)) {
|
||||
ReverseNXMode mode = *((ReverseNXMode*)r->data.ptr);
|
||||
return ipcSrv->SetReverseNXRTMode(mode);
|
||||
}
|
||||
break;
|
||||
case HocClkIpcCmd_SetKipData:
|
||||
if (r->data.size >= 0) {
|
||||
return ipcSrv->SetKipData();
|
||||
}
|
||||
break;
|
||||
case HocClkIpcCmd_UpdateEmcRegs:
|
||||
if (r->data.size >= 0) {
|
||||
return ipcSrv->UpdateEmcRegs();
|
||||
}
|
||||
break;
|
||||
case HocClkIpcCmd_CalculateGpuVmin:
|
||||
if (r->data.size >= 0) {
|
||||
return ipcSrv->CalculateGPUVmin();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SYSCLK_ERROR(Generic);
|
||||
@@ -371,29 +355,14 @@ Result IpcService::GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t*
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::SetReverseNXRTMode(ReverseNXMode mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::SetKipData() {
|
||||
this->clockMgr->SetKipData();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetKipData() {
|
||||
this->clockMgr->GetKipData();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::UpdateEmcRegs() {
|
||||
this->clockMgr->UpdateRamTimings();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::CalculateGPUVmin() {
|
||||
this->clockMgr->calculateGpuVmin();
|
||||
return 0;
|
||||
}
|
||||
@@ -54,11 +54,8 @@ class IpcService
|
||||
Result GetConfigValues(SysClkConfigValueList* out_configValues);
|
||||
Result SetConfigValues(SysClkConfigValueList* configValues);
|
||||
Result GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count);
|
||||
Result SetReverseNXRTMode(ReverseNXMode mode);
|
||||
Result SetKipData();
|
||||
Result GetKipData();
|
||||
Result UpdateEmcRegs();
|
||||
Result CalculateGPUVmin();
|
||||
bool running;
|
||||
Thread thread;
|
||||
LockableMutex threadMutex;
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* 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>
|
||||
@@ -32,6 +32,8 @@ typedef struct {
|
||||
u32 hpMode;
|
||||
u32 commonEmcMemVolt;
|
||||
u32 eristaEmcMaxClock;
|
||||
u32 eristaEmcMaxClock1;
|
||||
u32 eristaEmcMaxClock2;
|
||||
u32 marikoEmcMaxClock;
|
||||
u32 marikoEmcVddqVolt;
|
||||
u32 emcDvbShift;
|
||||
@@ -77,7 +79,11 @@ typedef struct {
|
||||
|
||||
u32 eristaGpuVoltArray[27];
|
||||
u32 marikoGpuVoltArray[24];
|
||||
u32 reserved[64];
|
||||
|
||||
u32 t6_tRTW_fine_tune;
|
||||
u32 t7_tWTR_fine_tune;
|
||||
|
||||
u32 reserved[60];
|
||||
} CustomizeTable;
|
||||
|
||||
#pragma pack(pop)
|
||||
@@ -188,6 +194,8 @@ static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p,
|
||||
|
||||
static inline bool cust_set_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); }
|
||||
static inline bool cust_set_erista_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock, v); }
|
||||
static inline bool cust_set_erista_emc_max1(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock1, v); }
|
||||
static inline bool cust_set_erista_emc_max2(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock2, v); }
|
||||
static inline bool cust_set_mariko_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcMaxClock, v); }
|
||||
static inline bool cust_set_mariko_emc_vddq(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcVddqVolt, v); }
|
||||
static inline bool cust_set_emc_dvb_shift(const char* p, u32 v) { CUST_WRITE_FIELD(p, emcDvbShift, v); }
|
||||
@@ -200,6 +208,8 @@ static inline bool cust_set_tRFC(const char* p, u32 v) { CUST_WRITE_FIELD(p, t5_
|
||||
static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); }
|
||||
static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); }
|
||||
static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); }
|
||||
static inline bool cust_set_tRTW_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW_fine_tune, v); }
|
||||
static inline bool cust_set_tWTR_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR_fine_tune, v); }
|
||||
static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); }
|
||||
static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); }
|
||||
|
||||
@@ -255,6 +265,8 @@ static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FI
|
||||
|
||||
static inline u32 cust_get_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); }
|
||||
static inline u32 cust_get_erista_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock); }
|
||||
static inline u32 cust_get_erista_emc_max1(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock1); }
|
||||
static inline u32 cust_get_erista_emc_max2(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock2); }
|
||||
static inline u32 cust_get_mariko_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcMaxClock); }
|
||||
static inline u32 cust_get_mariko_emc_vddq(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcVddqVolt); }
|
||||
static inline u32 cust_get_emc_dvb_shift(const CustomizeTable* t) { return CUST_GET_FIELD(t, emcDvbShift); }
|
||||
@@ -267,6 +279,8 @@ static inline u32 cust_get_tRFC(const CustomizeTable* t) { return CUST_GET_FIELD
|
||||
static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); }
|
||||
static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); }
|
||||
static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); }
|
||||
static inline u32 cust_get_tRTW_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW_fine_tune); }
|
||||
static inline u32 cust_get_tWTR_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); }
|
||||
static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); }
|
||||
static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); }
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "process_management.h"
|
||||
#include "clock_manager.h"
|
||||
#include "ipc_service.h"
|
||||
#define INNER_HEAP_SIZE 0x30000
|
||||
#define INNER_HEAP_SIZE 0x40000
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -80,11 +80,11 @@ extern "C"
|
||||
hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro));
|
||||
setsysExit();
|
||||
}
|
||||
|
||||
|
||||
// rc = fanInitialize();
|
||||
// if (R_FAILED(rc))
|
||||
// diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||
|
||||
|
||||
rc = i2cInitialize();
|
||||
if (R_FAILED(rc))
|
||||
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||
@@ -96,7 +96,7 @@ extern "C"
|
||||
// fanExit();
|
||||
i2cExit();
|
||||
fsExit();
|
||||
fsdevUnmountAll();
|
||||
fsdevUnmountAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,6 @@ int main(int argc, char** argv)
|
||||
FileUtils::LogLine("Exit");
|
||||
svcSleepThread(1000000ULL);
|
||||
FileUtils::Exit();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
18
build.sh
18
build.sh
@@ -21,20 +21,4 @@ cd ../../
|
||||
|
||||
cd Source/Horizon-OC-Monitor/
|
||||
make -j"$(nproc)"
|
||||
cp Horizon-OC-Monitor.ovl ../../dist/switch/.overlays/Horizon-OC-Monitor.ovl
|
||||
|
||||
cd ../../
|
||||
|
||||
ROOT="build"
|
||||
PATCHES="Source/Atmosphere-Patches"
|
||||
|
||||
cp "$PATCHES/secmon_memory_layout.hpp" "$ROOT/libraries/libexosphere/include/exosphere/secmon/"
|
||||
cp "$PATCHES/secmon_emc_access_table_data.inc" "$ROOT/exosphere/program/source/smc/"
|
||||
cp "$PATCHES/secmon_define_emc_access_table.inc" "$ROOT/exosphere/program/source/smc/"
|
||||
cp "$PATCHES/secmon_smc_register_access.cpp" "$ROOT/exosphere/program/source/smc/"
|
||||
cd build/exosphere
|
||||
|
||||
make -j"$(nproc)"
|
||||
|
||||
cd out/nintendo_nx_arm64_armv8a/release
|
||||
cp "exosphere.bin" "../../../../../dist/"
|
||||
cp Horizon-OC-Monitor.ovl ../../dist/switch/.overlays/Horizon-OC-Monitor.ovl
|
||||
BIN
dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp
vendored
BIN
dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp
vendored
Binary file not shown.
BIN
dist/atmosphere/kips/hoc.kip
vendored
BIN
dist/atmosphere/kips/hoc.kip
vendored
Binary file not shown.
BIN
dist/exosphere.bin
vendored
BIN
dist/exosphere.bin
vendored
Binary file not shown.
BIN
dist/switch/.overlays/Horizon-OC-Monitor.ovl
vendored
BIN
dist/switch/.overlays/Horizon-OC-Monitor.ovl
vendored
Binary file not shown.
BIN
dist/switch/.overlays/horizon-oc-overlay.ovl
vendored
BIN
dist/switch/.overlays/horizon-oc-overlay.ovl
vendored
Binary file not shown.
Reference in New Issue
Block a user