132 Commits
2.0.1 ... 2.3.0

Author SHA1 Message Date
souldbminersmwc
f90ba2ca59 2.3.0 2026-05-11 19:07:44 -04:00
Lightos1
f97fdc9528 conversion script: fix 3200mhz 2026-05-11 21:34:01 +02:00
Lightos1
ed63a95488 conversion script: fix 3200mhz 2026-05-11 21:33:44 +02:00
Lightos1
e24512c9d6 raise vddq min validator to 400 2026-05-11 21:26:31 +02:00
Lightos1
1efd91d535 reaise vddq validator 2026-05-11 21:22:05 +02:00
Lightos1
3337738dcc conversion script: fix silly bugs 2026-05-11 19:58:08 +02:00
Lightos1
7f1f504c36 Merge branch 'main' of https://github.com/horizon-OC/Horizon-OC 2026-05-11 19:36:10 +02:00
Lightos1
2f21f23266 experimental: add improved dvb table (+ conversion script) 2026-05-11 19:35:48 +02:00
Lightos1
3c99ad0186 Update README.md 2026-05-11 17:22:54 +02:00
Lightos1
e4dd690ac9 Update README.md 2026-05-11 17:19:36 +02:00
Lightos1
9122768953 delete ams_patch.bat from the right branch 2026-05-10 22:44:32 +02:00
Lightos1
3539916cfd fix compilation errors 2026-05-10 22:36:29 +02:00
Lightos1
4bd776c8aa kip.cpp: improve version mismatch logging 2026-05-10 18:58:37 +02:00
souldbminersmwc
78cda43054 whoops i forgot code 2026-05-10 12:48:02 -04:00
souldbminersmwc
580db1f167 hocclk: fix gm20b driver 2026-05-10 12:47:49 -04:00
souldbminersmwc
ea9adbfa14 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-10 11:22:33 -04:00
souldbminersmwc
accfea86f1 hocmon: get real freqs from hocclk instead of clkrst 2026-05-10 11:22:31 -04:00
Lightos1
badf182529 build.sh: improve build process 2026-05-10 01:51:22 +02:00
souldbminersmwc
12f12c6b1e hocclk: fix cust rev detection 2026-05-09 19:13:05 -04:00
souldbminersmwc
dde723baee Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-09 19:04:44 -04:00
souldbminersmwc
27db54644e hocclk: fix 1267mhz clock voltage 2026-05-09 19:04:41 -04:00
Lightos1
138bcb6dc6 build.sh: alternatively I should consider not being stupid 2026-05-10 00:57:31 +02:00
Lightos1
05fa5034d3 Revert "build.sh: use make -j rather than -j8"
This reverts commit 8a98a57b4b.
Thansk to microslops amazing memory management, make -j sometimes runs
out of ram on my system when compiling libstratosphere. This can hang my
entire system and also corrupt ram??? WTF
2026-05-10 00:44:27 +02:00
Lightos1
8a98a57b4b build.sh: use make -j rather than -j8 2026-05-10 00:31:26 +02:00
souldbminersmwc
c12b0136f8 hocclk: add missing code and small change to overlay 2026-05-09 16:54:39 -04:00
souldbminersmwc
c4f7f0e713 hocclk: add mariko middle freq hack 2026-05-09 16:53:30 -04:00
Lightos1
935dd24129 move exosphere to /dist/Atmosphere/ 2026-05-09 22:51:57 +02:00
Lightos1
d72e05259a Update COMPILING.md 2026-05-09 22:46:33 +02:00
Lightos1
847ae19de9 add hoc notification icon -- thanks ppkantorski! 2026-05-09 22:44:35 +02:00
souldbminersmwc
8651e418ca Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-09 16:07:03 -04:00
souldbminersmwc
2e3ef0f3b0 add GM20B GPU clock driver 2026-05-09 16:06:57 -04:00
Lightos1
c018b10a7f soctherm: remove reduntant EnableSensor calls 2026-05-09 21:41:11 +02:00
souldbminersmwc
336ea0eddb hocclk: fix me being a idiot 2026-05-09 15:37:24 -04:00
Lightos1
d561c0e538 add speedo fuse reading and fix wafer coordinates 2026-05-09 14:20:43 +02:00
Lightos1
a7c1fe0d27 ldr: clean formating, fix tRC cap, map erista mtc indexes 2026-05-09 13:39:31 +02:00
Souldbminer
33582678c2 Update README.md 2026-05-08 22:44:06 -04:00
souldbminersmwc
3ca1f17e4d hocclk: major code refactor
move everything into its own directory, clean codebase up a lot
2026-05-08 22:43:14 -04:00
souldbminersmwc
65dfa8f48a Update board_fuse.cpp 2026-05-08 16:38:46 -04:00
souldbminersmwc
90ea18c881 hocclk: better HW info reading 2026-05-08 16:36:49 -04:00
souldbminersmwc
598136c64b hocclk: fixes and other stuff 2026-05-08 15:53:53 -04:00
Lightos1
848a788c5f add kip version detection + version mismatch warning 2026-05-08 20:44:28 +02:00
Lightos1
d443e069fd add more stable max index checks 2026-05-08 18:39:01 +02:00
Lightos1
b7e7f0f720 clarify stable struct 2026-05-08 18:18:32 +02:00
Lightos1
916e5c5ddf add stable max index checks 2026-05-08 18:10:32 +02:00
Lightos1
c766ab1569 add stable struct to HocClkContext 2026-05-08 17:58:27 +02:00
Lightos1
9ee4d79f77 Merge pull request #78 from dominatorul/patch-7
Enhance README with more MEM clock entries
2026-05-07 22:41:37 +02:00
Lightos1
d55d1ab319 Merge pull request #77 from th3-ne0undr5c0r/fr,-fr-CA
Add proper French support
2026-05-07 22:39:18 +02:00
Dominator
3be1eb6149 Enhance README with more MEM clock entries
Added additional memory clock values and clarified JEDEC standards.
2026-05-07 19:57:33 +03:00
th3-ne0undr5c0r
5e4f58975c Remove fr-ca support
remove French Canadian support as it is not supported.
2026-05-07 09:31:28 -06:00
th3-ne0undr5c0r
d0c257dbc0 Add proper French support
As title says, adds proper support for French. please keep in mind I have not yet tested/checked whether or not text clipping or formatting issues may be present.
2026-05-07 09:27:38 -06:00
Lightos1
ffb0ded210 Merge pull request #76 from redraz/patch-1
Update ru.json
2026-05-07 16:48:51 +02:00
redraz
396304c738 Update ru.json
I decided to make a proper translation into Russian
2026-05-07 17:04:22 +03:00
Lightos1
8c6baf9e2f add hocVersion to CustomizeTable in sysmodule 2026-05-06 08:56:25 +02:00
Lightos1
a24eec7256 add versioning to kip 2026-05-06 08:54:23 +02:00
Lightos1
77a45966da Revert cust change
This reverts commit 04d7e2f8e0.
2026-05-06 08:49:31 +02:00
Lightos1
04d7e2f8e0 Change cust rev
This now uses the minimum hoc-clk version the kip is compatible with.
2026-05-06 08:43:33 +02:00
souldbminersmwc
f5481d1c00 hocclk: dvfs bracket fix - thanks jotommy! 2026-05-05 15:41:42 -04:00
Lightos1
2e39421074 Refactor tsensor 2026-05-05 20:43:43 +02:00
souldbminersmwc
9cf901d487 Update aotag.hpp 2026-05-04 14:56:48 -04:00
souldbminersmwc
0cdc96f7f8 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-04 14:28:26 -04:00
souldbminersmwc
73fafa6337 aotag: fix nvidia Z
nvidia made a error with their driver somehow
2026-05-04 14:28:24 -04:00
Lightos1
cfae441656 fix boost mode exit 2026-05-04 18:33:38 +02:00
souldbminersmwc
bf6bfa3e57 aotag: calculate (hopefully) correct coeffs 2026-05-03 15:44:31 -04:00
souldbminersmwc
72f5e11c42 update aotag coeffs 2026-05-03 14:41:37 -04:00
souldbminersmwc
93b6974be5 Update aotag.cpp 2026-05-03 14:14:14 -04:00
th3-ne0undr5c0r
1f545a7030 Add French Canadian language support
As title says, adds support for French Canadian. please keep in mind I have not yet tested/checked whether or not text clipping or formatting issues may be present.
2026-05-02 23:13:51 -06:00
souldbminersmwc
73bcb384b5 add exosphere patch 2026-05-02 22:11:25 -04:00
souldbminersmwc
fab0b76a35 update binaries 2026-05-02 22:06:57 -04:00
souldbminersmwc
2f830bac53 hocclk: better aotag 2026-05-02 22:05:15 -04:00
souldbminersmwc
5bf7fdf60e Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-02 21:11:56 -04:00
souldbminersmwc
af4f00f682 hocclk: basic aotag support along with other changes 2026-05-02 21:11:54 -04:00
Lightos1
d4b09f147b add back emc data that I forgot 2026-05-02 16:17:09 +02:00
Lightos1
1b33e9982c update exosphere patches 2026-05-02 16:16:21 +02:00
souldbminersmwc
c998aa78ae hocclk: update credits 2026-05-02 10:12:42 -04:00
Souldbminer
2b5a27f86e Update README.md 2026-05-02 10:11:14 -04:00
Lightos1
52b1b8da81 fix gpu volt hijack logic 2026-05-01 22:49:19 +02:00
souldbminersmwc
f409f5b8c3 hocclk: dvfs logic refactor
make it a lot more stable
2026-04-30 19:58:48 -04:00
souldbminersmwc
77a7470149 fix clock reset bug
Co-Authored-By: ppkantorski <6467366+ppkantorski@users.noreply.github.com>
2026-04-30 19:36:10 -04:00
souldbminersmwc
1d9fa4c091 Update t210.c 2026-04-30 19:29:15 -04:00
souldbminersmwc
a16cf8a2ef hocclk: significantly reduce memory usage 2026-04-30 19:15:05 -04:00
souldbminersmwc
89418b7cd0 hocclk: some refactoring and commenting 2026-04-30 18:48:57 -04:00
Lightos1
00cf05d9c5 ldr: slightly clean up MemFreqMtcTable 2026-04-29 22:14:27 +02:00
Lightos1
39e7ba6b75 ldr: move R_SKIP after verifying mtc table to avoid triggering patch validations 2026-04-29 21:56:25 +02:00
Lightos1
d7f2cee3b1 Update README.md 2026-04-29 19:08:23 +02:00
Lightos1
3848bd7c83 Update README.md 2026-04-29 19:06:51 +02:00
Lightos1
693954930a remove oc_test 2026-04-29 18:55:14 +02:00
Lightos1
de89768c74 ldr:: panic::SmcError is now always included 2026-04-29 18:39:20 +02:00
Lightos1
8f243c8369 ldr: clean up includes 2026-04-29 18:35:42 +02:00
souldbminersmwc
fd91f376c4 bump version 2026-04-27 19:33:20 -04:00
souldbminersmwc
f0fe114303 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-27 19:23:47 -04:00
souldbminersmwc
1c64cf5db8 hocclk: add display color option for aula
this is very very subtle but can def make a difference to your experience
2026-04-27 19:23:44 -04:00
Lightos1
9eea39325d Update about_gui.cpp 2026-04-27 08:52:54 +02:00
Lightos1
9bb6b3383b Update README.md 2026-04-27 08:51:57 +02:00
Lightos1
fb3e976f2e ldr: fix 1333 latency max bug -- index 0 is a valid latency 2026-04-26 22:13:49 +02:00
Lightos1
ec4a1f974b variable should be lowercase 2026-04-25 23:15:39 +02:00
souldbminersmwc
fc4b3b8352 2.1.0 2026-04-25 16:40:55 -04:00
souldbminersmwc
5123f7b1de Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-25 16:39:31 -04:00
souldbminersmwc
3251d104c4 hocclk: rename UV tables to correct names 2026-04-25 16:30:10 -04:00
Lightos1
ea2d604c20 fix comment 2026-04-25 22:22:31 +02:00
souldbminersmwc
ae71cd447d ldr: add comment 2026-04-25 16:19:44 -04:00
souldbminersmwc
4261dd83f0 hoc: 133mhz step mode 2026-04-25 16:16:26 -04:00
souldbminersmwc
4dc01c024a hocclk: change capitilization 2026-04-25 15:59:05 -04:00
souldbminersmwc
9e26329173 hocclk: soc max volt dno side voltage 2026-04-25 15:57:37 -04:00
souldbminersmwc
36441e6dea add config support and update build script for soc vmax 2026-04-25 15:44:56 -04:00
Lightos1
cdf28607c9 move loader.json 2026-04-25 20:48:31 +02:00
Lightos1
b383fa7ec2 improve alignment 2026-04-25 20:30:46 +02:00
Lightos1
d7178ddd2c Add soc uncap 2026-04-25 20:22:23 +02:00
souldbminersmwc
9d149f0939 hocclk: fix trackbar reloading issues 2026-04-25 11:20:48 -04:00
souldbminersmwc
170dd79347 hocclk: cpu config rework 2026-04-25 11:06:22 -04:00
souldbminersmwc
d97d359ec2 hocclk: more configurator stuff 2026-04-24 17:00:59 -04:00
souldbminersmwc
9ff9e315a0 hocclk: improve kip saving mechanism 2026-04-24 16:42:59 -04:00
souldbminersmwc
cde560c4bd Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-24 16:35:25 -04:00
souldbminersmwc
a15860ba8d hocclk: make dram ti 2026-04-24 16:35:01 -04:00
Lightos1
76e6f1bd27 Merge pull request #71 from dominatorul/patch-4
Update README.md
2026-04-24 17:41:41 +02:00
Lightos1
2c1ad1b755 fix formating 2026-04-24 17:41:21 +02:00
Lightos1
2f2e5e9fb8 add new line 2026-04-24 17:38:28 +02:00
Lightos1
65b77a2d0b make step mode mariko only 2026-04-24 17:34:37 +02:00
Dominator
5d4812bde5 Update README.md
Updated clock specifications for MEM, CPU, and GPU with standardized terms.
2026-04-24 04:24:03 +03:00
souldbminersmwc
addd2de4d9 hocclk: add CPU LUT and add copyright 2026-04-23 18:50:51 -04:00
souldbminersmwc
0df8ce745f use original voltages 2026-04-22 18:06:27 -04:00
souldbminersmwc
62d055f163 hocclk: add missing -35mV step to configurator 2026-04-22 16:58:36 -04:00
souldbminersmwc
fa1510a40d Add B3's low ram freq DVFS
Co-Authored-By: halop <4215938+halop@users.noreply.github.com>
2026-04-22 16:56:09 -04:00
souldbminersmwc
e6942f95e7 hocclk: add BQ24193 temp driver 2026-04-22 16:40:51 -04:00
souldbminersmwc
94b63003ab hocclk: reorder options 2026-04-22 16:14:30 -04:00
souldbminersmwc
8aa20dc0cf hocclk: fix PLL ram mode and default to it 2026-04-22 15:49:07 -04:00
souldbminersmwc
db92c60cd2 hocclk: improve pll ram mode 2026-04-21 20:03:12 -04:00
souldbminersmwc
c8c7b233f5 hocclk: minor refactor 2026-04-21 19:52:31 -04:00
souldbminersmwc
5a9afcbb74 hocmon: rename tabs 2026-04-21 19:48:42 -04:00
souldbminersmwc
8127a0c3b7 hocclk: dram voltage color changes for mariko/erista 2026-04-21 19:48:27 -04:00
souldbminersmwc
7c5e746594 hocclk: ui changes 2026-04-21 19:46:21 -04:00
souldbminersmwc
7d30c4d384 bump version 2026-04-21 19:38:32 -04:00
souldbminersmwc
883b4fc3f4 hocclk: fix pointer dereference 2026-04-21 19:35:05 -04:00
156 changed files with 6156 additions and 2747 deletions

View File

@@ -1,12 +1,11 @@
Horizon OC Zeus Compilation Instructions Horizon OC Compilation Instructions
1. Install devkitpro (https://devkitpro.org/wiki/Getting_Started) with switch-dev 1. Install devkitpro (https://devkitpro.org/wiki/Getting_Started) with switch-dev
2. Set up a development enviorment for compiling Atmosphere (https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/building.md) 2. Set up a development enviorment for compiling Atmosphere (https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/building.md)
3. Install GNU make and ENSURE THAT YOUR ENVIORMENT HAS A PYTHON3 COMMAND AVAILABLE! 3. Install GNU make and ENSURE THAT YOUR ENVIORMENT HAS A PYTHON3 COMMAND AVAILABLE!
4. Git clone atmosphere (git clone https://github.com/Atmosphere-NX/Atmosphere.git) 4. Git clone atmosphere (git clone https://github.com/Atmosphere-NX/Atmosphere.git)
5. Clone the Horizon OC develop branch (git clone -b develop --single-branch https://github.com/Horizon-OC/Horizon-OC.git) 5. Clone the Horizon OC develop branch (git clone https://github.com/Horizon-OC/Horizon-OC.git --recurse-submodules)
6. Create a new folder named "build" in the horizon oc repo 6. Create a new folder named "build" in the horizon oc repo
7. Copy atmosphere files into that build folder 7. Copy atmosphere files into that build folder
8. Copy Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp to build/stratosphere/loader/source/ldr_process_creation.cpp, replacing any files if prompted 8. Copy Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp to build/stratosphere/loader/source/ldr_process_creation.cpp, replacing any files if prompted
9. Grab a copy of libultrahand (https://github.com/ppkantorski/libultrahand) and place it into Source/sys-clk/overlay/lib/libultrahand 9. Run ./build.sh in the root directory
10. Run ./build.sh in the root directory

View File

@@ -11,7 +11,7 @@
![VSCode](https://img.shields.io/badge/VSCode-0078D4?style=for-the-badge\&logo=visual%20studio%20code\&logoColor=white) ![VSCode](https://img.shields.io/badge/VSCode-0078D4?style=for-the-badge\&logo=visual%20studio%20code\&logoColor=white)
![Made with Notepad++](assets/np++.png?raw=true) ![Made with Notepad++](assets/np++.png?raw=true)
![C++](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge\&logo=c%2B%2B\&logoColor=white) ![C++](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge\&logo=c%2B%2B\&logoColor=white)
![Downloads](https://img.shields.io/github/downloads/souldbminersmwc/Horizon-OC/total.svg?style=for-the-badge) ![Downloads](https://img.shields.io/github/downloads/Horizon-OC/Horizon-OC/total.svg?style=for-the-badge)
--- ---
@@ -78,21 +78,64 @@ Refer to COMPILATION.md
--- ---
## Clock table ## Clock table
### MEM clocks ### MEM clocks (mhz)
* 3200 → max on mariko, JEDEC. * 3200 → max on mariko, JEDEC.
* 3166
* 3133
* 3100
* 3066
* 3033
* 3000
* 2966
* 2933 → JEDEC. * 2933 → JEDEC.
* 2900
* 2866
* 2833
* 2800
* 2766
* 2733
* 2700
* 2666 → JEDEC. * 2666 → JEDEC.
* 2633
* 2600
* 2566
* 2533
* 2500
* 2466
* 2433
* 2400 → max on erista, JEDEC. * 2400 → max on erista, JEDEC.
* 2133 → mariko safe max (4266 Modules), JEDEC. * 2366
* 1996 → JEDEC. * 2333
* 1866 → mariko safe max (3733 Modules), JEDEC. * 2300
* 1600 → official docked, boost mode, erista safe max, JEDEC. * 2266
* 2233
* 2200
* 2166
* 2133 → Mariko JEDEC standard max (4266 Modules)
* 2100
* 2066
* 2033
* 2000
* 1996 → JEDEC standard
* 1966
* 1933
* 1900
* 1866 → Mariko JEDEC standard max (3733 Modules)
* 1833
* 1800
* 1766
* 1733
* 1700
* 1666
* 1633
* 1600 → official docked, boost mode, Erista JEDEC standard max (3200 Modules), JEDEC.
* 1331 → official handheld, JEDEC. * 1331 → official handheld, JEDEC.
* 1065 * 1065
* 800 * 800
* 665 * 665
### CPU clocks ### CPU clocks (mhz)
* 2703 → mariko absolute max, dangerous * 2703 → mariko absolute max, dangerous
* 2601 → unsafe * 2601 → unsafe
* 2499 * 2499
@@ -115,17 +158,17 @@ Refer to COMPILATION.md
* 714 * 714
* 612 → sleep mode * 612 → sleep mode
### GPU clocks ### GPU clocks (mhz)
* 1536 → absolute max clock on mariko. very dangerous * 1536 → absolute max clock on mariko. very dangerous
* 1459 * 1459
* 1382 * 1382
* 1305 * 1305
* 1267 → NVIDIA T214 rating * 1267 → NVIDIA T214(mariko) rating
* 1228 → mariko HiOPT safe clock * 1228 → mariko High UV safe clock
* 1152 → mariko SLT max clock * 1152 → mariko hiOpt-15mV max clock
* 1075 → mariko no UV max clock. absolute max clock on erista. very dangerous * 1075 → mariko hiOpt max clock. absolute max clock on erista. very dangerous
* 998 → NVIDIA T210 rating * 998 → NVIDIA T210 (erista) rating
* 960 (erista only) → erista slt/hiopt safe max clock * 960 (erista only) → erista high uv/hiOpt-15mV safe max clock
* 921 → erista no UV max clock * 921 → erista no UV max clock
* 844 * 844
* 768 → official docked * 768 → official docked
@@ -142,31 +185,31 @@ Refer to COMPILATION.md
**Notes:** **Notes:**
1. On Erista, CPU in handheld is capped to 1581MHz 1. On Erista, CPU in handheld is capped to 1581MHz
2. GPU overclock is capped at 460MHz on erista in handheld 2. GPU overclock is capped at 460MHz on erista in handheld
3. On Mariko, cap with No uv is 614MHz, with SLT it is 691MHz and with HiOPT it's 768MHz 3. On Mariko, cap with hiOpt is 614MHz, with hiOpt-15mV it is 691MHz and with High UV it's 768MHz
4. Clocks higher than 768MHz on erista need the official charger is plugged in. 4. Clocks higher than 768MHz on erista need the official charger is plugged in.
5. On Mariko, cap with No uv is 844MHz, with SLT it is 921MHz and with HiOPT it's 998MHz
--- ---
## Credits ## Credits
* **Lightos's Cat** - Cat * **Lightos's Cat** - Cat
* **Souldbminer** - hoc-clk and loader development * **Souldbminer** - hoc-clk and loader development
* **Lightos** - Loader patches development, hoc-clk development, guides * **Lightos** - Loader patches development, hoc-clk development, guides
* **TDRR** - HOC Logo Design
* **tetetete-ctrl** - Website design
* **SciresM** - Atmosphere CFW * **SciresM** - Atmosphere CFW
* **CTCaer** - L4T, Hekate, proper RAM timings * **CTCaer** - L4T, Hekate, proper RAM timings
* **KazushiMe** - Switch OC Suite * **KazushiMe** - Switch OC Suite
* **Hanai3bi (Meha)** - Switch OC Suite, EOS, sys-clk-eos * **Hanai3bi (Meha)** - Switch OC Suite, EOS, sys-clk-eos
* **NaGaa95** - L4T-OC kernel, Status Monitor fork * **NaGaa95** - L4T-OC kernel, Status Monitor fork
* **B3711 (halop)** - EOS * **B3711 (halop)** - EOS, contributions
* **sys-clk team (m4xw, p-sam, natinusala)** - sys-clk * **sys-clk team (m4xw, p-sam, natinusala)** - sys-clk
* **Dominatorul** - Soctherm driver, guides, general help * **Dominatorul** - Soctherm driver, guides, general help
* **b0rd2death** - Ultrahand sys-clk & Status Monitor fork * **ppkantorski** - Ultrahand sys-clk & Status Monitor fork
* **MasaGratoR and ZachyCatGames** - General help * **MasaGratoR and ZachyCatGames** - General help
* **MasaGratoR** - Status Monitor & Display Refresh Rate driver * **MasaGratoR** - Status Monitor & Display Refresh Rate driver
* **Dominatorul, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh, frost, letum00, and Xenshen** - Testing * **Dominatorul, Samybigio, Arcdelta, Miki, Happy, Winnerboi77, Blaise, Alvise, agjeococh, frost, letum00, and Xenshen** - Testing
* **Samybigio2011, Miki** - Italian translations * **Samybigio2011, Miki** - Italian translations
* **angelblaster** - Korean translations * **angelblaster** - Korean translations
* **q1332348216-glitch** - Chinese translations * **q1332348216-glitch** - Chinese translations
* **th3-ne0undr5c0r** - French translations
* **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T * **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T

View File

@@ -14,9 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define __ACCESS_TABLE_NAME__ EmcAccessTable1 #define __ACCESS_TABLE_NAME__ RtcPmcAccessTable
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress() #define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceRtcPmc.GetAddress()
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc" #define __ACCESS_TABLE_INC__ "secmon_rtc_pmc_access_table_data.inc"
#include "secmon_define_access_table.inc" #include "secmon_define_access_table.inc"

File diff suppressed because it is too large Load Diff

View File

@@ -99,18 +99,16 @@ namespace ams::secmon::smc {
#include "secmon_define_pmc_access_table.inc" #include "secmon_define_pmc_access_table.inc"
#include "secmon_define_mc_access_table.inc" #include "secmon_define_mc_access_table.inc"
#include "secmon_define_emc_access_table.inc" #include "secmon_define_emc_access_table.inc"
#include "secmon_define_emc1_access_table.inc" #include "secmon_define_rtc_pmc_access_table.inc"
#include "secmon_define_emc2_access_table.inc"
#include "secmon_define_mc01_access_table.inc" #include "secmon_define_mc01_access_table.inc"
constexpr const AccessTableEntry AccessTables[] = { constexpr const AccessTableEntry AccessTables[] = {
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, }, { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, }, { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
{ EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, }, { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
{ EmcAccessTable1::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), EmcAccessTable1::Address, EmcAccessTable1::Size, }, { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::Size, },
{ EmcAccessTable2::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController2.GetAddress(), EmcAccessTable2::Address, EmcAccessTable2::Size, }, { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, }, { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
}; };
constexpr bool IsAccessAllowed(const AccessTableEntry &entry, uintptr_t address) { constexpr bool IsAccessAllowed(const AccessTableEntry &entry, uintptr_t address) {

View File

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

View File

@@ -1,51 +0,0 @@
TARGET_EXEC := test
BUILD_DIR := ./build
SRC_DIRS := ./
# CXX := clang++ g++-12
# Find all the C and C++ files we want to compile
# Note the single quotes around the * expressions. Make will incorrectly expand these otherwise.
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')
# String substitution for every C/C++ file.
# As an example, hello.cpp turns into ./build/hello.cpp.o
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
# String substitution (suffix version without %).
# As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d
DEPS := $(OBJS:.o=.d)
# Every folder in ./src will need to be passed to GCC so that it can find header files
INC_DIRS := $(shell find $(SRC_DIRS) -type d)
# Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CPPFLAGS := $(INC_FLAGS) -Wall -Werror -Wno-unused-result -std=c++20 -Og -g
# The final build step.
$(TARGET_EXEC): $(OBJS)
@echo "Linking $@"
@$(CXX) $(OBJS) -o $@ $(LDFLAGS)
# Build step for C source
$(BUILD_DIR)/%.c.o: %.c
@mkdir -p $(dir $@)
@echo "$<"
@$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
# Build step for C++ source
$(BUILD_DIR)/%.cpp.o: %.cpp
@mkdir -p $(dir $@)
@echo "$<"
@$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
.PHONY: clean
clean:
@rm -r $(BUILD_DIR) $(TARGET_EXEC)
# Include the .d makefiles. The - at the front suppresses the errors of missing
# Makefiles. Initially, all the .d files will be missing, and we don't want those
# errors to show up.
-include $(DEPS)

View File

@@ -40,24 +40,26 @@ volatile CustomizeTable C = {
.eristaEmcMaxClock1 = 1600000, .eristaEmcMaxClock1 = 1600000,
.eristaEmcMaxClock2 = 1600000, .eristaEmcMaxClock2 = 1600000,
/* Available: 66MHz step rate, 100MHz step rate and jedec. */ /* Available: 66MHz step rate, 100MHz step rate, 133MHz step rate and jedec. */
/* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */ /* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */
.stepMode = StepMode_66MHz, .stepMode = StepMode_66MHz,
.marikoEmcMaxClock = 2133000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */ .marikoEmcMaxClock = 2133000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.marikoEmcVddqVolt = 600000, .marikoEmcVddqVolt = 600000,
.emcDvbShift = 0,
// Primary .emcDvbShift = 0,
.t1_tRCD = 0, .marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */
.t2_tRP = 0,
.t3_tRAS = 0, /* Primary. */
// Secondary .t1_tRCD = 0,
.t4_tRRD = 0, .t2_tRP = 0,
.t5_tRFC = 0, .t3_tRAS = 0,
.t6_tRTW = 0, /* Secondary. */
.t7_tWTR = 0, .t4_tRRD = 0,
.t8_tREFI = 0, .t5_tRFC = 0,
.t6_tRTW = 0,
.t7_tWTR = 0,
.t8_tREFI = 0,
/* At 1333WL, for some reason (incorrect ram timing config in mtc table?), tRP causes crashes at high reductions - 2 seems to be the most common limit. */ /* At 1333WL, for some reason (incorrect ram timing config in mtc table?), tRP causes crashes at high reductions - 2 seems to be the most common limit. */
/* This is a lazy workaround until I find the issue... */ /* This is a lazy workaround until I find the issue... */
@@ -65,21 +67,21 @@ volatile CustomizeTable C = {
/* Frequency where non low timings gets used. */ /* Frequency where non low timings gets used. */
.timingEmcTbreak = DISABLED, .timingEmcTbreak = DISABLED,
.low_t6_tRTW = DISABLED, .low_t6_tRTW = 0,
.low_t7_tWTR = DISABLED, .low_t7_tWTR = 0,
.readLatency = { .readLatency = {
DISABLED, /* 1333 */ 0,
DISABLED, /* 1600 */ 0,
DISABLED, /* 1866 */ 0,
DISABLED, /* 2133 */ 0,
}, },
.writeLatency = { .writeLatency = {
DISABLED, /* 1333 */ 0,
DISABLED, /* 1600 */ 0,
DISABLED, /* 1866 */ 0,
DISABLED, /* 2133 */ 0,
}, },
/* You can mix and match different latencies if needed */ /* You can mix and match different latencies if needed */

View File

@@ -20,15 +20,14 @@
#pragma once #pragma once
#define CUST_REV 2 #define CUST_REV 3
#define KIP_VERSION 230
#include "oc_common.hpp" #include "oc_common.hpp"
#include "pcv/pcv_common.hpp" #include "pcv/pcv_common.hpp"
namespace ams::ldr::hoc { namespace ams::ldr::hoc {
#include "mtc_timing_table.hpp"
enum TableConfig: u32 { enum TableConfig: u32 {
DEFAULT_TABLE = 1, DEFAULT_TABLE = 1,
TBREAK_1581 = 2, TBREAK_1581 = 2,
@@ -40,6 +39,7 @@ enum StepMode: u32 {
StepMode_66MHz = 0, StepMode_66MHz = 0,
StepMode_100MHz = 1, StepMode_100MHz = 1,
StepMode_Jedec = 2, StepMode_Jedec = 2,
StepMode_133MHz = 3,
}; };
/* /*
@@ -77,11 +77,11 @@ static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(pcv::cvb_entry_t) * pcv::D
constexpr uint32_t ERISTA_MTC_MAGIC = 0x43544D45; // EMTC constexpr uint32_t ERISTA_MTC_MAGIC = 0x43544D45; // EMTC
constexpr uint32_t MARIKO_MTC_MAGIC = 0x43544D4D; // MMTC constexpr uint32_t MARIKO_MTC_MAGIC = 0x43544D4D; // MMTC
typedef struct CustomizeTable { struct CustomizeTable {
u8 cust[4] = {'C', 'U', 'S', 'T'}; u8 cust[4] = {'C', 'U', 'S', 'T'};
u32 custRev = CUST_REV; u32 custRev = CUST_REV;
u32 kipVersion = KIP_VERSION;
u32 placeholder;
u32 hpMode; u32 hpMode;
u32 commonEmcMemVolt; u32 commonEmcMemVolt;
@@ -92,7 +92,8 @@ typedef struct CustomizeTable {
StepMode stepMode; StepMode stepMode;
u32 marikoEmcMaxClock; u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt; u32 marikoEmcVddqVolt;
u32 emcDvbShift; s32 emcDvbShift;
u32 marikoSocVmax;
// advanced config // advanced config
u32 t1_tRCD; u32 t1_tRCD;
u32 t2_tRP; u32 t2_tRP;
@@ -167,7 +168,7 @@ typedef struct CustomizeTable {
CustomizeGpuDvfsTable marikoGpuDvfsTableSLT; CustomizeGpuDvfsTable marikoGpuDvfsTableSLT;
CustomizeGpuDvfsTable marikoGpuDvfsTableHiOPT; CustomizeGpuDvfsTable marikoGpuDvfsTableHiOPT;
} CustomizeTable; };
extern volatile CustomizeTable C; extern volatile CustomizeTable C;

View File

@@ -14,7 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stratosphere.hpp>
#include "../mtc_timing_value.hpp" #include "../mtc_timing_value.hpp"
namespace ams::ldr::hoc::pcv::erista { namespace ams::ldr::hoc::pcv::erista {

View File

@@ -26,16 +26,16 @@ namespace ams::ldr::hoc::pcv::mariko {
return; return;
} }
/* Fallback. */ /* > 3200 */
rext = 0x1A; rext = 0x1E;
} }
void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) { void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) {
latency += index * latencyStep; latency += index * latencyStep;
} }
static u32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) { static s32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) {
u32 maxIndex = 0; s32 maxIndex = -1;
for (u32 i = 0; i < latencySize; ++i) { for (u32 i = 0; i < latencySize; ++i) {
if (latencyArray[i]) { if (latencyArray[i]) {
maxIndex = i; maxIndex = i;
@@ -65,18 +65,18 @@ namespace ams::ldr::hoc::pcv::mariko {
} }
void HandleLatency(u32 freq) { void HandleLatency(u32 freq) {
static u32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency)); static s32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency));
static u32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency)); static s32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency));
constexpr u32 ReadLatencyStep = 4; constexpr u32 ReadLatencyStep = 4;
constexpr u32 WriteLatencyStep = 2; constexpr u32 WriteLatencyStep = 2;
bool autoLatencyRead = false, autoLatencyWrite = false; bool autoLatencyRead = false, autoLatencyWrite = false;
if (rlIndexMax == 0) { if (rlIndexMax == -1) {
AutoLatency(RL, freq, ReadLatencyStep); AutoLatency(RL, freq, ReadLatencyStep);
autoLatencyRead = true; autoLatencyRead = true;
} }
if (wlIndexMax == 0) { if (wlIndexMax == -1) {
AutoLatency(WL, freq, WriteLatencyStep); AutoLatency(WL, freq, WriteLatencyStep);
autoLatencyWrite = true; autoLatencyWrite = true;
} }
@@ -120,6 +120,7 @@ namespace ams::ldr::hoc::pcv::mariko {
} }
} }
/* DBI is always enabled. */
mrw2 = static_cast<u8>(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6))); mrw2 = static_cast<u8>(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6)));
} }
@@ -138,27 +139,27 @@ namespace ams::ldr::hoc::pcv::mariko {
tRPpbIndex = MIN(C.t2_tRP_cap, C.t2_tRP); tRPpbIndex = MIN(C.t2_tRP_cap, C.t2_tRP);
} }
tRCD = tRCD_values[C.t1_tRCD]; tRCD = tRCD_values[C.t1_tRCD];
tRPpb = tRP_values[tRPpbIndex]; tRPpb = tRP_values[tRPpbIndex];
tRAS = tRAS_values[C.t3_tRAS]; tRAS = tRAS_values[C.t3_tRAS];
tRRD = tRRD_values[C.t4_tRRD]; tRRD = tRRD_values[C.t4_tRRD];
tRFCpb = tRFC_values[C.t5_tRFC]; tRFCpb = tRFC_values[C.t5_tRFC];
u32 tRTW = C.t6_tRTW; u32 tRTW = C.t6_tRTW;
u32 tWTR = 10 - tWTR_values[C.t7_tWTR]; u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
if (freq < C.timingEmcTbreak) { if (freq < C.timingEmcTbreak) {
tRTW = C.low_t6_tRTW; tRTW = C.low_t6_tRTW;
tWTR = 10 - tWTR_values[C.low_t7_tWTR]; tWTR = 10 - tWTR_values[C.low_t7_tWTR];
} }
s32 finetRTW = C.fineTune_t6_tRTW; s32 finetRTW = C.fineTune_t6_tRTW;
s32 finetWTR = C.fineTune_t7_tWTR; s32 finetWTR = C.fineTune_t7_tWTR;
tRC = tRAS + tRPpb; tRC = tRAS + tRPpb;
tRFCab = tRFCpb * 2; tRFCab = tRFCpb * 2;
tXSR = static_cast<double>(tRFCab + 7.5); tXSR = static_cast<double>(tRFCab + 7.5);
tFAW = static_cast<u32>(tRRD * 4.0); tFAW = static_cast<u32>(tRRD * 4.0);
tRPab = tRPpb + 3; tRPab = tRPpb + 3;
tR2P = CEIL((RL * 0.426) - 2.0); tR2P = CEIL((RL * 0.426) - 2.0);
tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (tRTW * 3) + finetRTW; tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (tRTW * 3) + finetRTW;

View File

@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../mtc_timing_value.hpp" #include "../oc_common.hpp"
#include "timing_tables.hpp" #include "timing_tables.hpp"
namespace ams::ldr::hoc::pcv::mariko { namespace ams::ldr::hoc::pcv::mariko {

View File

@@ -15,7 +15,7 @@
*/ */
#pragma once #pragma once
#include "../mtc_timing_value.hpp" #include <stratosphere.hpp>
namespace ams::ldr::hoc::pcv::mariko { namespace ams::ldr::hoc::pcv::mariko {

View File

@@ -18,17 +18,16 @@
#pragma once #pragma once
#ifdef ATMOSPHERE_IS_STRATOSPHERE #include <stratosphere.hpp>
#include <stratosphere.hpp> #include <vapours/results/results_common.hpp>
#include <vapours/results/results_common.hpp> #define LOGGING(fmt, ...) ((void)0)
#define LOGGING(fmt, ...) ((void)0) #define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); }
#define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); }
#else
#include "oc_test.hpp"
#endif
#include "customize.hpp" #include "customize.hpp"
#include "oc_log.hpp"
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
#include "oc_log.hpp"
#endif
#define PATCH_OFFSET(offset, value) \ #define PATCH_OFFSET(offset, value) \
static_assert(sizeof(__typeof__(offset)) <= sizeof(u64)); \ static_assert(sizeof(__typeof__(offset)) <= sizeof(u64)); \
@@ -52,6 +51,8 @@ namespace ams::ldr {
R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014); R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014);
R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015); R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015);
R_DEFINE_ERROR_RESULT(InvalidMtcTablePattern, 1016); R_DEFINE_ERROR_RESULT(InvalidMtcTablePattern, 1016);
R_DEFINE_ERROR_RESULT(InvalidSocVoltPattern, 1017);
R_DEFINE_ERROR_RESULT(InvalidSocVoltLimit, 1018);
} }
namespace ams::ldr::hoc { namespace ams::ldr::hoc {
@@ -91,9 +92,7 @@ namespace ams::ldr::hoc {
} }
Result CheckResult() { Result CheckResult() {
#ifndef ATMOSPHERE_IS_STRATOSPHERE
R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher()); R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher());
#endif
if (maximum_patched_count) if (maximum_patched_count)
R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher()); R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher());

View File

@@ -87,7 +87,7 @@ namespace ams::ldr::hoc {
static bool initDone = false; static bool initDone = false;
log_ctx_t *log_ctx = (log_ctx_t*)working_buf; log_ctx_t *log_ctx = (log_ctx_t*)working_buf;
SmcCopyFromIram(working_buf, IRAM_LOG_CTX_ADDR, sizeof(working_buf)); R_DISCARD(SmcCopyFromIram(working_buf, IRAM_LOG_CTX_ADDR, sizeof(working_buf)));
if (!initDone) { if (!initDone) {
initDone = true; initDone = true;
@@ -103,21 +103,25 @@ namespace ams::ldr::hoc {
va_end(args); va_end(args);
if (res < 0 || res >= (static_cast<s32>(max_log_sz - log_ctx->end))) { if (res < 0 || res >= (static_cast<s32>(max_log_sz - log_ctx->end))) {
SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf)); R_DISCARD(SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf)));
return; return;
} }
log_ctx->end += res; log_ctx->end += res;
SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf)); R_DISCARD(SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf)));
} }
#endif #endif
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) #if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
void ViewLog() { void ViewLog() {
if (spl::GetSocType() == spl::SocType_Mariko) {
return;
}
constexpr size_t PageSize = 4096; constexpr size_t PageSize = 4096;
for (size_t ofs = 0; ofs < fatal_handler_bin_size; ofs += PageSize) { for (size_t ofs = 0; ofs < fatal_handler_bin_size; ofs += PageSize) {
memcpy(&working_buf, fatal_handler_bin + ofs, std::min(fatal_handler_bin_size - ofs, PageSize)); memcpy(&working_buf, fatal_handler_bin + ofs, std::min(fatal_handler_bin_size - ofs, PageSize));
SmcCopyToIram(ATMOSPHERE_IRAM_PAYLOAD_BASE + ofs, &working_buf, std::min(fatal_handler_bin_size - ofs, PageSize)); R_DISCARD(SmcCopyToIram(ATMOSPHERE_IRAM_PAYLOAD_BASE + ofs, &working_buf, std::min(fatal_handler_bin_size - ofs, PageSize)));
} }
SmcRebootToIramPayload(); SmcRebootToIramPayload();

View File

@@ -1,214 +0,0 @@
/*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ATMOSPHERE_IS_STRATOSPHERE
#include "oc_test.hpp"
#include "oc_loader.hpp"
void* loadExec(const char* file_loc, size_t* out_size) {
FILE* fp = fopen(file_loc, "rb");
if (!fp) {
fprintf(stderr, "Cannot open file: \"%s\"\n", file_loc);
exit(-1);
}
if (fseek(fp, 0, SEEK_END) < 0) {
fprintf(stderr, "fseek error\n");
exit(-1);
}
long size = ftell(fp);
if (size == -1L) {
fprintf(stderr, "\"%s\" is a directory", file_loc);
exit(-1);
}
fseek(fp, 0, SEEK_SET);
void* buf = malloc(size);
fread(buf, size, 1, fp);
fclose(fp);
if (size < 8192) {
fprintf(stderr, "File is too small to process: \"%s\" (%ld B)\n", file_loc, size);
exit(-1);
}
*out_size = size;
return buf;
}
void saveExec(const char* file_loc, const void* buf, size_t size) {
FILE* fp = fopen(file_loc, "wb");
if (!fp) {
fprintf(stderr, "Cannot write to \"%s\"\n", file_loc);
exit(-1);
}
printf("Saving to \"%s\"...\n", file_loc);
fwrite(buf, size, 1, fp);
fclose(fp);
}
Result Test_PcvDvfsTable() {
using namespace ams::ldr::hoc::pcv;
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&mariko::CpuCvbTableDefault)) == 18);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&erista::CpuCvbTableDefault)) == 16);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&mariko::GpuCvbTableDefault)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&erista::GpuCvbTableDefault)) == 12);
cvb_entry_t last_mariko_cpu_cvb_entry_default = { 1963500, { 1675751, -38635, 27 }, { 1120000 } };
assert(memcmp(GetDvfsTableLastEntry((cvb_entry_t *)(&mariko::CpuCvbTableDefault)), (void *)&last_mariko_cpu_cvb_entry_default, sizeof(last_mariko_cpu_cvb_entry_default)) == 0);
assert(GetDvfsTableLastEntry((cvb_entry_t *)(&erista::GpuCvbTableDefault))->freq == 921600);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTableSLT)) == 25);
// Customized table default
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.eristaCpuDvfsTable)) == 19);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTable)) == 21);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTableSLT)) == 22);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.eristaGpuDvfsTable)) == 12);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTable)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTableSLT)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTableHiOPT)) == 17);
constexpr size_t limit = ams::ldr::hoc::pcv::DvfsTableEntryLimit;
cvb_entry_t customized_table[limit] = {};
for (size_t i = 0; i < limit; i++) {
assert(GetDvfsTableEntryCount(customized_table) == i);
auto p = GetDvfsTableLastEntry(customized_table);
if (p)
assert(p->freq == i);
customized_table[i].freq = i + 1;
}
R_SUCCEED();
}
void unitTest() {
UnitTest test[] = {
{ "PCV DVFS Table", &Test_PcvDvfsTable }
};
for (auto &t : test) {
t.Test();
}
}
int main(int argc, char** argv) {
unitTest();
const char* pcv_opt = "pcv";
const char* ptm_opt = "ptm";
const char* save_opt = "-s";
const char* mariko_ext = ".mariko";
const char* erista_ext = ".erista";
enum EXE_OPTION {
EXE_PCV,
EXE_PTM,
UNKNOWN
};
EXE_OPTION exe_opt = UNKNOWN;
if (argc > 2) {
if (!strcmp(argv[1], pcv_opt))
exe_opt = EXE_PCV;
if (!strcmp(argv[1], ptm_opt))
exe_opt = EXE_PTM;
}
if ((argc != 3 && argc != 4) || exe_opt == UNKNOWN) {
fprintf(stderr, "Usage:\n"\
" %s %s | %s [%s] <exec_path>\n\n"\
" %s : Save patched executable with extension \"%s\" / \"%s\"\n"
, argv[0], pcv_opt, ptm_opt, save_opt
, save_opt, mariko_ext, erista_ext);
return -1;
}
bool save_patched = false;
char* exec_path = argv[2];
if (argc == 4 && !strcmp(argv[2], save_opt)) {
save_patched = true;
exec_path = argv[3];
}
size_t file_size;
void* file_buffer = loadExec(exec_path, &file_size);
size_t exec_path_len = strlen(reinterpret_cast<const char *>(exec_path));
size_t exec_path_patched_len = exec_path_len + std::max(strlen(mariko_ext), strlen(erista_ext)) + 1;
if (exe_opt == EXE_PCV) {
ams::ldr::hoc::pcv::SafetyCheck();
{
void* erista_buf = malloc(file_size);
std::memcpy(erista_buf, file_buffer, file_size);
printf("Patching %s for Erista...\n", pcv_opt);
ams::ldr::hoc::pcv::erista::Patch(reinterpret_cast<uintptr_t>(erista_buf), file_size);
if (save_patched) {
char* exec_path_erista = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_erista, exec_path, exec_path_patched_len);
strncat(exec_path_erista, erista_ext, exec_path_patched_len);
saveExec(exec_path_erista, erista_buf, file_size);
free(exec_path_erista);
}
free(erista_buf);
}
{
void* mariko_buf = malloc(file_size);
std::memcpy(mariko_buf, file_buffer, file_size);
printf("Patching %s for Mariko...\n", pcv_opt);
ams::ldr::hoc::pcv::mariko::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
if (save_patched) {
char* exec_path_mariko = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_mariko, exec_path, exec_path_patched_len);
strncat(exec_path_mariko, mariko_ext, exec_path_patched_len);
saveExec(exec_path_mariko, mariko_buf, file_size);
free(exec_path_mariko);
}
free(mariko_buf);
}
}
if (exe_opt == EXE_PTM) {
void* mariko_buf = malloc(file_size);
std::memcpy(mariko_buf, file_buffer, file_size);
printf("Patching %s (Mariko Only)...\n", ptm_opt);
ams::ldr::hoc::ptm::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
if (save_patched) {
char* exec_path_mariko = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_mariko, exec_path, exec_path_patched_len);
strncat(exec_path_mariko, mariko_ext, exec_path_patched_len);
saveExec(exec_path_mariko, mariko_buf, file_size);
free(exec_path_mariko);
}
free(mariko_buf);
}
free(file_buffer);
printf("Passed!\n\n");
return 0;
}
#endif

View File

@@ -1,81 +0,0 @@
/*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef ATMOSPHERE_IS_STRATOSPHERE
#include <cassert>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef int32_t s32;
typedef uint64_t u64;
typedef int Result;
#define R_SUCCEEDED(arg) (arg == 0)
#define R_FAILED(arg) (arg != 0)
#define LOGGING(fmt, ...) { printf(fmt "\n", ##__VA_ARGS__); }
#define CRASH(msg, ...) { fprintf(stderr, "%s\nFailed in %s!\n", msg, __PRETTY_FUNCTION__); exit(-1); }
#define R_SUCCEED() { return 0; }
#define R_THROW(err) { return err; }
#define R_TRY(expr) { Result _rc = (expr); if (R_FAILED(_rc)) { return _rc; } }
#define R_UNLESS(expr, rc) { if (!(expr)) { return rc; } }
#define R_DEFINE_ERROR_RESULT(name, rc) \
inline Result Result##name() { return rc; }
#define HEXDUMP(ptr, len) \
{ \
const uint8_t* p = reinterpret_cast<const uint8_t *>(ptr); \
size_t i, j; \
for (i = 0; i < len; i += 16) { \
printf("%06zx: ", i); \
for (j = 0; j < 16 && i + j < len; j++) \
printf("%02x ", p[i + j]); \
for (; j < 16; j++) \
printf(" "); \
for (j = 0; j < 16 && i + j < len; j++) \
printf("%c", isprint(p[i + j]) ? p[i + j] : '.'); \
printf("\n"); \
} \
} \
typedef struct UnitTest {
using Func = Result(*)();
const char* description;
Func fun = nullptr;
void Test() {
Result res = fun();
if (R_FAILED(res)) {
CRASH(description);
}
}
} UnitTest;
#endif

View File

@@ -153,7 +153,8 @@ namespace ams::ldr::hoc::pcv {
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV { C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc }, { GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc }, { C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc },
{ C.marikoEmcVddqVolt, 250'000, 700'000, false, panic::Emc }, { C.marikoEmcVddqVolt, 400'000, 750'000, false, panic::Emc },
{ C.marikoSocVmax, 1000, 1200, false, panic::Emc },
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu }, { eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu }, { marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu },
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu }, { C.marikoGpuVmax, 800, 960, false, panic::Gpu },
@@ -161,17 +162,13 @@ namespace ams::ldr::hoc::pcv {
for (auto &v : validators) { for (auto &v : validators) {
if (R_FAILED(v.check())) { if (R_FAILED(v.check())) {
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) panic::SmcError(v.panic);
panic::SmcError(v.panic);
#endif
CRASH("Validation FAIL"); CRASH("Validation FAIL");
} }
} }
} }
void Patch(uintptr_t mapped_nso, size_t nso_size) { void Patch(uintptr_t mapped_nso, size_t nso_size) {
#ifdef ATMOSPHERE_IS_STRATOSPHERE
SafetyCheck(); SafetyCheck();
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
@@ -180,8 +177,6 @@ namespace ams::ldr::hoc::pcv {
} else { } else {
erista::Patch(mapped_nso, nso_size); erista::Patch(mapped_nso, nso_size);
} }
#endif
} }
} }

View File

@@ -24,7 +24,6 @@
#include "pcv_common.hpp" #include "pcv_common.hpp"
#include "pcv_erista.hpp" #include "pcv_erista.hpp"
#include "pcv_mariko.hpp" #include "pcv_mariko.hpp"
#include "pcv_asm.hpp"
namespace ams::ldr::hoc::pcv { namespace ams::ldr::hoc::pcv {

View File

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

View File

@@ -18,25 +18,27 @@
#pragma once #pragma once
#include "../mtc_timing_table.hpp"
namespace ams::ldr::hoc::pcv { namespace ams::ldr::hoc::pcv {
typedef struct cvb_coefficients { struct cvb_coefficients {
s32 c0 = 0; s32 c0 = 0;
s32 c1 = 0; s32 c1 = 0;
s32 c2 = 0; s32 c2 = 0;
s32 c3 = 0; s32 c3 = 0;
s32 c4 = 0; s32 c4 = 0;
s32 c5 = 0; s32 c5 = 0;
} cvb_coefficients; };
typedef struct cvb_entry_t { struct cvb_entry_t {
u64 freq; u64 freq;
cvb_coefficients cvb_dfll_param; cvb_coefficients cvb_dfll_param;
cvb_coefficients cvb_pll_param; cvb_coefficients cvb_pll_param;
} cvb_entry_t; };
static_assert(sizeof(cvb_entry_t) == 0x38); static_assert(sizeof(cvb_entry_t) == 0x38);
typedef struct cvb_cpu_dfll_data { struct cvb_cpu_dfll_data {
u32 tune0_low; u32 tune0_low;
u32 tune0_high; u32 tune0_high;
u32 tune1_low; u32 tune1_low;
@@ -44,9 +46,9 @@ namespace ams::ldr::hoc::pcv {
unsigned int tune_high_min_millivolts; unsigned int tune_high_min_millivolts;
unsigned int tune_high_margin_millivolts; unsigned int tune_high_margin_millivolts;
unsigned long dvco_calibration_max; unsigned long dvco_calibration_max;
} cvb_cpu_dfll_data; };
typedef struct __attribute__((packed)) div_nmp { struct __attribute__((packed)) div_nmp {
u8 divn_shift; u8 divn_shift;
u8 divn_width; u8 divn_width;
u8 divm_shift; u8 divm_shift;
@@ -56,9 +58,9 @@ namespace ams::ldr::hoc::pcv {
u8 override_divn_shift; u8 override_divn_shift;
u8 override_divm_shift; u8 override_divm_shift;
u8 override_divp_shift; u8 override_divp_shift;
} div_nmp; };
typedef struct __attribute__((packed)) clk_pll_param { struct __attribute__((packed)) clk_pll_param {
u32 freq; u32 freq;
u32 input_min; u32 input_min;
u32 input_max; u32 input_max;
@@ -72,9 +74,9 @@ namespace ams::ldr::hoc::pcv {
struct div_nmp *div_nmp; struct div_nmp *div_nmp;
u32 unk_1[4]; u32 unk_1[4];
void (*unk_fn)(u64* unk_struct); // set_defaults? void (*unk_fn)(u64* unk_struct); // set_defaults?
} clk_pll_param; };
typedef struct __attribute__((packed)) dvfs_rail { struct __attribute__((packed)) dvfs_rail {
u32 id; u32 id;
u32 unk_0[5]; u32 unk_0[5];
u32 freq; u32 freq;
@@ -84,9 +86,9 @@ namespace ams::ldr::hoc::pcv {
u32 step_mv; u32 step_mv;
u32 max_mv; u32 max_mv;
u32 unk_2[11]; u32 unk_2[11];
} dvfs_rail; };
typedef struct __attribute__((packed)) regulator { struct __attribute__((packed)) regulator {
u64 id; u64 id;
const char* name; const char* name;
u32 type; u32 type;
@@ -110,7 +112,7 @@ namespace ams::ldr::hoc::pcv {
} type_2_3; } type_2_3;
}; };
u32 unk_x[60]; u32 unk_x[60];
} regulator; };
static_assert(sizeof(regulator) == 0x120); static_assert(sizeof(regulator) == 0x120);
constexpr u32 CpuClkOSLimit = 1785'000; constexpr u32 CpuClkOSLimit = 1785'000;

View File

@@ -216,7 +216,7 @@ namespace ams::ldr::hoc::pcv::erista {
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); 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_wr_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8))); WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB9)));
WRITE_PARAM_ALL_REG(table, emc_ras, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F))); WRITE_PARAM_ALL_REG(table, emc_ras, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F)));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD)); WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb)); WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
@@ -357,15 +357,11 @@ namespace ams::ldr::hoc::pcv::erista {
table->dram_timings.t_rp = tRFCpb; table->dram_timings.t_rp = tRFCpb;
table->dram_timings.t_rfc = tRFCab; table->dram_timings.t_rfc = tRFCab;
table->emc_cfg_2 = 0x11083D; table->emc_cfg_2 = 0x11083D;
table->min_volt = std::min(static_cast<u32>(1050), 900 + C.emcDvbShift * 25); table->min_volt = (u32)std::min(static_cast<s32>(1050), 900 + C.emcDvbShift * 25);
} }
/* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */ /* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */
Result MemFreqMtcTable(u32 *ptr) { Result MemFreqMtcTable(u32 *ptr) {
if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) {
R_SKIP();
}
u32 khz_list[] = { 40800, 68000, 102000, 204000, 408000, 665600, 800000, 1065600, 1331200, 1600000 }; u32 khz_list[] = { 40800, 68000, 102000, 204000, 408000, 665600, 800000, 1065600, 1331200, 1600000 };
std::sort(maxEmcClocks, maxEmcClocks + std::size(maxEmcClocks)); std::sort(maxEmcClocks, maxEmcClocks + std::size(maxEmcClocks));
u32 khz_list_size = std::size(khz_list); u32 khz_list_size = std::size(khz_list);
@@ -380,6 +376,10 @@ namespace ams::ldr::hoc::pcv::erista {
R_UNLESS(table_list[mtcIndex]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable()); R_UNLESS(table_list[mtcIndex]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
} }
if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) {
R_SKIP();
}
/* If we oc ram at all, tables are always shifted by at least 1. */ /* If we oc ram at all, tables are always shifted by at least 1. */
u32 tableShifts = 1; u32 tableShifts = 1;
for (u32 i = 0; i < std::size(maxEmcClocks) - 1; ++i) { for (u32 i = 0; i < std::size(maxEmcClocks) - 1; ++i) {
@@ -451,21 +451,24 @@ namespace ams::ldr::hoc::pcv::erista {
// } // }
void Patch(uintptr_t mapped_nso, size_t nso_size) { void Patch(uintptr_t mapped_nso, size_t nso_size) {
u32 CpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq);
u32 GpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq);
PatcherEntry<u32> patches[] = { PatcherEntry<u32> patches[] = {
{"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq)}, {"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, CpuCvbDefaultMaxFreq },
{"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial}, {"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial },
{"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial}, {"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial },
{"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF}, {"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, CpuTune0Low },
{"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial}, {"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial },
{"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial}, {"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial },
{"GPU Freq Table", GpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq)}, {"GPU Freq Table", GpuFreqCvbTable<false>, 1, nullptr, GpuCvbDefaultMaxFreq },
{"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn}, {"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn },
{"GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax}, {"GPU PLL Max", & GpuFreqPllMax, 1, nullptr, GpuClkPllMax },
// {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit}, // {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit },
{"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit}, {"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit },
{"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit}, {"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit },
{"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit}, {"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit },
{"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS}, {"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS },
}; };
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(EristaMtcTable); ptr += sizeof(u32)) { for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(EristaMtcTable); ptr += sizeof(u32)) {
@@ -480,9 +483,7 @@ namespace ams::ldr::hoc::pcv::erista {
for (auto &entry : patches) { for (auto &entry : patches) {
LOGGING("%s Count: %zu", entry.description, entry.patched_count); LOGGING("%s Count: %zu", entry.description, entry.patched_count);
if (R_FAILED(entry.CheckResult())) { if (R_FAILED(entry.CheckResult())) {
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) panic::SmcError(panic::Patch);
panic::SmcError(panic::Patch);
#endif
CRASH(entry.description); CRASH(entry.description);
} }

View File

@@ -51,16 +51,16 @@ namespace ams::ldr::hoc::pcv::erista {
}; };
constexpr u32 CpuVoltOfficial = 1227; constexpr u32 CpuVoltOfficial = 1227;
constexpr u32 CpuVminOfficial = 825; constexpr u32 CpuVminOfficial = 825;
constexpr u32 CpuTune0Low = 0xFFEAD0FF;
constexpr u32 CpuVoltL4T = 1257'000; constexpr u32 CpuVoltL4T = 1257'000;
static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 }; static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 };
static_assert(sizeof(cpuVoltDvfsPattern) == 0x14, "invalid cpuVoltDvfsPattern size"); static_assert(sizeof(cpuVoltDvfsPattern) == 0x14, "Invalid cpuVoltDvfsPattern size");
static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 }; static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 };
static_assert(sizeof(cpuVoltageThermalPattern) == 0x3c, "invalid cpuVoltageThermalPattern size"); static_assert(sizeof(cpuVoltageThermalPattern) == 0x3c, "Invalid cpuVoltageThermalPattern size");
constexpr u32 GpuClkPllLimit = 2'600'000; constexpr u32 GpuClkPllLimit = 2'600'000;
constexpr u32 GpuClkPllMax = 921'600'000; constexpr u32 GpuClkPllMax = 921'600'000;
@@ -72,7 +72,7 @@ namespace ams::ldr::hoc::pcv::erista {
static_assert(sizeof(gpuVoltDvfsPattern) == (sizeof(u32) * 6), "Invalid gpuVoltDvfsPattern"); static_assert(sizeof(gpuVoltDvfsPattern) == (sizeof(u32) * 6), "Invalid gpuVoltDvfsPattern");
static const u32 gpuVoltThermalPattern[] = { 950, 1132, 0, 810, 1132, 15000, 810, 1132, 30000, 810, 1132, 50000, 810, 1132, 70000, 810, 1132, 105000 }; static const u32 gpuVoltThermalPattern[] = { 950, 1132, 0, 810, 1132, 15000, 810, 1132, 30000, 810, 1132, 50000, 810, 1132, 70000, 810, 1132, 105000 };
static_assert(sizeof(gpuVoltThermalPattern) == 0x48, "invalid gpuVoltageThermalPattern size"); static_assert(sizeof(gpuVoltThermalPattern) == 0x48, "Invalid gpuVoltageThermalPattern size");
/* GPU Max Clock asm Pattern: /* GPU Max Clock asm Pattern:
* *
@@ -109,8 +109,8 @@ namespace ams::ldr::hoc::pcv::erista {
{ }, { },
}; };
constexpr u32 MemVoltHOS = 1125'000; constexpr u32 MemVoltHOS = 1125'000;
constexpr u32 EmcClkMinFreq = 40800; /* 40.8 MHz table only exists on erista. */ constexpr u32 EmcClkMinFreq = 40800; /* 40.8 MHz table only exists on erista. */
constexpr u32 EmcClkPllmLimit = 1866'000'000; constexpr u32 EmcClkPllmLimit = 1866'000'000;
constexpr u32 MTC_TABLE_REV = 7; constexpr u32 MTC_TABLE_REV = 7;
@@ -123,13 +123,13 @@ namespace ams::ldr::hoc::pcv::erista {
enum DramId { enum DramId {
ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC = 2, /* This doesn't have a table in pcv? Wtf? */ ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC = 2,
ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7, /* No table, but expected */ ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7,
}; };
enum MtcTableIndex { enum MtcTableIndex {
T210SdevEmcDvfsTableS4gb01 = 0, /* HB-MGCH */ T210SdevEmcDvfsTableS4gb01 = 0, /* HB-MGCH, WT:C */
T210SdevEmcDvfsTableS6gb01 = 1, /* HM-MGCH */ T210SdevEmcDvfsTableS6gb01 = 1, /* HM-MGCH */
T210SdevEmcDvfsTableH4gb01 = 2, /* HR-NLE */ T210SdevEmcDvfsTableH4gb01 = 2, /* HR-NLE */
MtcTableIndex_Invalid = 3, MtcTableIndex_Invalid = 3,
@@ -141,9 +141,10 @@ namespace ams::ldr::hoc::pcv::erista {
}; };
constexpr MtcDramIndex mtcIndexTable[] = { constexpr MtcDramIndex mtcIndexTable[] = {
{ ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH, T210SdevEmcDvfsTableS4gb01, }, { ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH, T210SdevEmcDvfsTableS6gb01, }, { ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE, T210SdevEmcDvfsTableH4gb01, }, { ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH, T210SdevEmcDvfsTableS6gb01, },
{ ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE, T210SdevEmcDvfsTableH4gb01, },
}; };
void Patch(uintptr_t mapped_nso, size_t nso_size); void Patch(uintptr_t mapped_nso, size_t nso_size);

View File

@@ -79,16 +79,17 @@ namespace ams::ldr::hoc::pcv::mariko {
Result CpuFreqVdd(u32 *ptr) { Result CpuFreqVdd(u32 *ptr) {
dvfs_rail *entry = reinterpret_cast<dvfs_rail *>(reinterpret_cast<u8 *>(ptr) - offsetof(dvfs_rail, freq)); dvfs_rail *entry = reinterpret_cast<dvfs_rail *>(reinterpret_cast<u8 *>(ptr) - offsetof(dvfs_rail, freq));
R_UNLESS(entry->id == 1, ldr::ResultInvalidCpuFreqVddEntry()); R_UNLESS(entry->id == 1, ldr::ResultInvalidCpuFreqVddEntry());
R_UNLESS(entry->min_mv == 250'000, ldr::ResultInvalidCpuFreqVddEntry()); R_UNLESS(entry->min_mv == 250'000, ldr::ResultInvalidCpuFreqVddEntry());
R_UNLESS(entry->step_mv == 5000, ldr::ResultInvalidCpuFreqVddEntry()); R_UNLESS(entry->step_mv == 5000, ldr::ResultInvalidCpuFreqVddEntry());
R_UNLESS(entry->max_mv == 1525'000, ldr::ResultInvalidCpuFreqVddEntry()); R_UNLESS(entry->max_mv == 1525'000, ldr::ResultInvalidCpuFreqVddEntry());
if (C.marikoCpuUVHigh) { if (C.marikoCpuUVHigh) {
PATCH_OFFSET(ptr, CapCpuClock()); PATCH_OFFSET(ptr, CapCpuClock());
} else { } else {
PATCH_OFFSET(ptr, GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq); PATCH_OFFSET(ptr, GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq);
} }
R_SUCCEED(); R_SUCCEED();
} }
@@ -279,12 +280,6 @@ namespace ams::ldr::hoc::pcv::mariko {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
} }
/* Verify the limit. */
/* TODO: Make this a little bit cleaner at some point. */
if (AsmGetImm16(ins1) != (GpuClkOsLimit & 0xFFFF) || AsmGetImm16(ins2) != (GpuClkOsLimit >> 16)) {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
u32 max_clock; u32 max_clock;
switch (C.marikoGpuUV) { switch (C.marikoGpuUV) {
case 0: case 0:
@@ -379,7 +374,7 @@ namespace ams::ldr::hoc::pcv::mariko {
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); 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_wr_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8))); WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB9)));
WRITE_PARAM_ALL_REG(table, emc_ras, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F))); WRITE_PARAM_ALL_REG(table, emc_ras, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F)));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD)); WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb)); WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
@@ -438,22 +433,21 @@ namespace ams::ldr::hoc::pcv::mariko {
WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv); 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_rdv_mask, rdv + 2);
WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv); WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
/* TODO: Check this out again at some point. */
WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_2, 0x24); WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_2, 0x24);
WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_3, 0x24); WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_3, 0x24);
/* This needs some clean up. */ /* This needs some clean up. */
constexpr double MC_ARB_DIV = 4.0; constexpr double MC_ARB_DIV = 4.0;
constexpr u32 MC_ARB_SFA = 2; constexpr u32 MC_ARB_SFA = 2;
table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV; table->burst_mc_regs.mc_emem_arb_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_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_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(tR2P / MC_ARB_DIV); table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(tR2P / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA; table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA;
@@ -526,12 +520,12 @@ namespace ams::ldr::hoc::pcv::mariko {
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_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_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1;
table->dram_timings.t_rp = tRFCpb; table->dram_timings.t_rp = tRFCpb;
table->dram_timings.t_rfc = tRFCab; table->dram_timings.t_rfc = tRFCab;
table->dram_timings.rl = RL; table->dram_timings.rl = RL;
table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2); table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
table->emc_cfg_2 = 0x11083D; table->emc_cfg_2 = 0x11083D;
} }
void MemMtcPllmbDivisor(MarikoMtcTable *table) { void MemMtcPllmbDivisor(MarikoMtcTable *table) {
@@ -544,11 +538,11 @@ namespace ams::ldr::hoc::pcv::mariko {
bool remainder_check = (table->rate_khz - PllOscInKHz * (table->rate_khz / PllOscInKHz)) > (table->rate_khz - PllOscHalfKHz * divm_candidate_half) && static_cast<int>(((target_freq_d / PllOscHalfKHz - divm_candidate_half - 0.5) * 8192.0)) != 0; bool remainder_check = (table->rate_khz - PllOscInKHz * (table->rate_khz / PllOscInKHz)) > (table->rate_khz - PllOscHalfKHz * divm_candidate_half) && static_cast<int>(((target_freq_d / PllOscHalfKHz - divm_candidate_half - 0.5) * 8192.0)) != 0;
u32 divm_final = remainder_check + 1; u32 divm_final = remainder_check + 1;
table->pllmb_divm = divm_final; table->pllmb_divm = divm_final;
double div_step_d = static_cast<double>(PllOscInKHz) / divm_final; double div_step_d = static_cast<double>(PllOscInKHz) / divm_final;
s32 divn_integer = static_cast<u8>(table->rate_khz / div_step_d); s32 divn_integer = static_cast<u8>(table->rate_khz / div_step_d);
table->pllmb_divn = divn_integer; table->pllmb_divn = divn_integer;
u32 divn_fraction = static_cast<s32>((target_freq_d / div_step_d - divn_integer - 0.5) * 8192.0); u32 divn_fraction = static_cast<s32>((target_freq_d / div_step_d - divn_integer - 0.5) * 8192.0);
@@ -559,34 +553,34 @@ namespace ams::ldr::hoc::pcv::mariko {
s32 divn_fraction_ssc = static_cast<s32>((actual_freq_khz * 0.997 / div_step_d - divn_integer - 0.5) * 8192.0); s32 divn_fraction_ssc = static_cast<s32>((actual_freq_khz * 0.997 / div_step_d - divn_integer - 0.5) * 8192.0);
double delta_scaled = (0.3 / div_step_d + 0.3 / div_step_d) * (divn_fraction - divn_fraction_ssc); double delta_scaled = (0.3 / div_step_d + 0.3 / div_step_d) * (divn_fraction - divn_fraction_ssc);
s32 delta_int = static_cast<s32>(delta_scaled); s32 delta_int = static_cast<s32>(delta_scaled);
double delta_frac = delta_scaled - delta_int; double delta_frac = delta_scaled - delta_int;
u32 setup_value = 0; u32 setup_value = 0;
if (delta_frac <= 0.5) { if (delta_frac <= 0.5) {
double round_val = (delta_int + ROUND(delta_frac + delta_frac)) ? 0.5 : 0.0; double round_val = (delta_int + ROUND(delta_frac + delta_frac)) ? 0.5 : 0.0;
setup_value = ROUND(delta_frac + delta_frac) ? static_cast<u32>(round_val + round_val) | 0x1000 : static_cast<u32>(round_val); setup_value = ROUND(delta_frac + delta_frac) ? static_cast<u32>(round_val + round_val) | 0x1000 : static_cast<u32>(round_val);
} else { } else {
s32 frac_doubled = ROUND(delta_frac - 0.5 + delta_frac - 0.5); s32 frac_doubled = ROUND(delta_frac - 0.5 + delta_frac - 0.5);
double round_val = 1.0; double round_val = 1.0;
setup_value = frac_doubled ? static_cast<u32>(round_val) : static_cast<u32>(round_val + round_val) | 0x1000; setup_value = frac_doubled ? static_cast<u32>(round_val) : static_cast<u32>(round_val + round_val) | 0x1000;
} }
u32 ctrl1 = static_cast<u16>(divn_fraction_ssc) | (static_cast<u16>(divn_fraction) << 16); u32 ctrl1 = static_cast<u16>(divn_fraction_ssc) | (static_cast<u16>(divn_fraction) << 16);
u32 ctrl2 = static_cast<u16>(divn_fraction) | (static_cast<u16>(setup_value) << 16); u32 ctrl2 = static_cast<u16>(divn_fraction) | (static_cast<u16>(setup_value) << 16);
table->pllm_ss_ctrl1 = ctrl1; table->pllm_ss_ctrl1 = ctrl1;
table->pllm_ss_ctrl2 = ctrl2; table->pllm_ss_ctrl2 = ctrl2;
table->pllmb_ss_ctrl1 = ctrl1; table->pllmb_ss_ctrl1 = ctrl1;
table->pllmb_ss_ctrl2 = ctrl2; table->pllmb_ss_ctrl2 = ctrl2;
} else { } else {
table->pllm_ss_cfg &= 0xBFFFFFFF; table->pllm_ss_cfg &= 0xBFFFFFFF;
table->pllmb_ss_cfg &= 0xBFFFFFFF; table->pllmb_ss_cfg &= 0xBFFFFFFF;
u64 pair = (static_cast<u64>(divn_fraction) << 32) | static_cast<u64>(table->rate_khz); u64 pair = (static_cast<u64>(divn_fraction) << 32) | static_cast<u64>(table->rate_khz);
u32 pll_misc = (table->pllm_ss_ctrl2 & 0xFFFF0000) | static_cast<u32>((pair - actual_freq_khz) >> 32); u32 pll_misc = (table->pllm_ss_ctrl2 & 0xFFFF0000) | static_cast<u32>((pair - actual_freq_khz) >> 32);
table->pllm_ss_ctrl2 = pll_misc; table->pllm_ss_ctrl2 = pll_misc;
table->pllmb_ss_ctrl2 = pll_misc; table->pllmb_ss_ctrl2 = pll_misc;
} }
} }
@@ -615,6 +609,25 @@ namespace ams::ldr::hoc::pcv::mariko {
newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit)); newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit));
} }
void MtcGenerate133StepTable() {
const u32 stepFreqs133[] = { 1733000, 1866000, 2000000, 2133000, 2266000, 2400000, 2533000, 2666000, 2800000, 2933000, 3066000, 3200000, 3333000, 3466000, }; // Avoid rounding issues
constexpr u32 StepFreqs133Size = std::size(stepFreqs133);
for (u32 i = 0; i < StepFreqs133Size; ++i) {
if (stepFreqs133[i] <= C.marikoEmcMaxClock) {
newEmcList.push_back(stepFreqs133[i]);
} else {
break;
}
}
if (newEmcList.back() != C.marikoEmcMaxClock) {
newEmcList.push_back(static_cast<u32>(C.marikoEmcMaxClock));
}
newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit));
}
void MtcGenerateFreqTables() { void MtcGenerateFreqTables() {
if (C.marikoEmcMaxClock <= EmcClkOSLimit) { if (C.marikoEmcMaxClock <= EmcClkOSLimit) {
return; return;
@@ -635,6 +648,9 @@ namespace ams::ldr::hoc::pcv::mariko {
case StepMode_Jedec: case StepMode_Jedec:
MtcGenerateJedecTable(); MtcGenerateJedecTable();
return; return;
case StepMode_133MHz:
MtcGenerate133StepTable();
return;
default: default:
stepRate = 66667; stepRate = 66667;
break; break;
@@ -665,7 +681,7 @@ namespace ams::ldr::hoc::pcv::mariko {
Result MtcValidateAllTables(MarikoMtcTable *tableStart, const u32 *validationList, u32 tableCount) { Result MtcValidateAllTables(MarikoMtcTable *tableStart, const u32 *validationList, u32 tableCount) {
for (u32 i = 0; i < tableCount; ++i) { for (u32 i = 0; i < tableCount; ++i) {
R_UNLESS(R_SUCCEEDED(VerifyMtcTable(&tableStart[i], validationList[i])), ldr::ResultInvalidMtcTable()); R_TRY(VerifyMtcTable(&tableStart[i], validationList[i]));
} }
R_SUCCEED(); R_SUCCEED();
@@ -687,9 +703,9 @@ namespace ams::ldr::hoc::pcv::mariko {
return MtcTableIndex_Invalid; return MtcTableIndex_Invalid;
} }
NORETURN void AbortInvalidDramId() { NORETURN void AbortInvalidMtc(const char *crashMsg) {
panic::SmcError(panic::Emc); panic::SmcError(panic::Emc);
CRASH("Invalid dram id\n"); CRASH(crashMsg);
} }
u32 GetMtcOffset(MtcTableIndex index) { u32 GetMtcOffset(MtcTableIndex index) {
@@ -718,12 +734,7 @@ namespace ams::ldr::hoc::pcv::mariko {
} }
} }
bool patchedMtc = false;
Result MemFreqMtcTable(u32 *ptr) { Result MemFreqMtcTable(u32 *ptr) {
if (C.marikoEmcMaxClock <= EmcClkOSLimit || patchedMtc) {
R_SKIP();
}
static const DramId dramId = [] { static const DramId dramId = [] {
DramId id = GetDramId(); DramId id = GetDramId();
return id; return id;
@@ -733,7 +744,7 @@ namespace ams::ldr::hoc::pcv::mariko {
MtcTableIndex idx = GetMtcDramIndex(dramId); MtcTableIndex idx = GetMtcDramIndex(dramId);
/* If for some reason this happens, there is no chance of recovering this. */ /* If for some reason this happens, there is no chance of recovering this. */
if (idx == MtcTableIndex_Invalid) { if (idx == MtcTableIndex_Invalid) {
AbortInvalidDramId(); AbortInvalidMtc("Invalid dramId");
} }
return idx; return idx;
}(); }();
@@ -742,22 +753,26 @@ namespace ams::ldr::hoc::pcv::mariko {
static const u32 mtcOffset = GetMtcOffset(mtcIndex); static const u32 mtcOffset = GetMtcOffset(mtcIndex);
/* Offset from 1600MHz pointer to 204Mhz table start. */ /* Offset from 1600MHz pointer to 204Mhz table start. */
constexpr u32 StartAdjustment = offsetof(MarikoMtcTable, rate_khz) + sizeof(MarikoMtcTable) * 2; constexpr u32 StartAdjustment = offsetof(MarikoMtcTable, rate_khz) + sizeof(MarikoMtcTable) * (mariko::MtcTableCountDefault - 1);
u8 *startPtr = reinterpret_cast<u8 *>(ptr) - StartAdjustment; u8 *startPtr = reinterpret_cast<u8 *>(ptr) - StartAdjustment;
MarikoMtcTable *table = reinterpret_cast<MarikoMtcTable *>(startPtr + mtcOffset); MarikoMtcTable *table = reinterpret_cast<MarikoMtcTable *>(startPtr + mtcOffset);
R_UNLESS(R_SUCCEEDED(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault)), ldr::ResultInvalidMtcTable()); R_TRY(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault));
if (C.marikoEmcMaxClock <= EmcClkOSLimit) {
R_SKIP();
}
PrepareMtcMemoryRegion(startPtr, table); PrepareMtcMemoryRegion(startPtr, table);
table = reinterpret_cast<MarikoMtcTable *>(startPtr); table = reinterpret_cast<MarikoMtcTable *>(startPtr);
if (R_FAILED(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault))) { if (R_FAILED(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault))) {
panic::SmcError(panic::Emc); AbortInvalidMtc("Failed mtc validation");
} }
MtcExtendTables(table); MtcExtendTables(table);
if (R_FAILED(MtcValidateAllTables(table, newEmcList.data(), newEmcList.size()))) { if (R_FAILED(MtcValidateAllTables(table, newEmcList.data(), newEmcList.size()))) {
panic::SmcError(panic::Emc); AbortInvalidMtc("Failed mtc validation");
} }
for (u32 i = mariko::MtcTableCountDefault; i < newEmcList.size(); ++i) { for (u32 i = mariko::MtcTableCountDefault; i < newEmcList.size(); ++i) {
@@ -765,7 +780,6 @@ namespace ams::ldr::hoc::pcv::mariko {
MemMtcPllmbDivisor(&table[i]); MemMtcPllmbDivisor(&table[i]);
} }
patchedMtc = true;
R_SUCCEED(); R_SUCCEED();
} }
@@ -782,21 +796,43 @@ namespace ams::ldr::hoc::pcv::mariko {
R_SKIP(); R_SKIP();
} }
u32 max0 = 1050;
u32 max1 = 1025;
u32 max2 = 1000;
s32 voltAdd = 25 * C.emcDvbShift; s32 voltAdd = 25 * C.emcDvbShift;
#define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000),
DvbEntry emcDvbTableNew[] = { if (C.marikoSocVmax && C.marikoSocVmax > 1000) {
{ 204000, { 637, 637, 637, } }, max0 = C.marikoSocVmax;
{ 1331200, { 650, 637, 637, } }, max1 = C.marikoSocVmax;
{ 1600000, { 675, 650, 637, } }, max2 = C.marikoSocVmax;
{ 1866000, { DVB_VOLT(700, 675, 650) } }, }
{ 2133000, { DVB_VOLT(725, 700, 675) } },
{ 2400000, { DVB_VOLT(750, 725, 700) } }, auto DvbVolt = [&](u32 zero, u32 one, u32 two) {
{ 2666000, { DVB_VOLT(775, 750, 725) } }, return std::array<u32, 3>{
{ 2933000, { DVB_VOLT(800, 775, 750) } }, std::min((u32)((s32)zero + voltAdd), max0),
{ 3200000, { DVB_VOLT(800, 800, 775) } }, std::min((u32)((s32)one + voltAdd), max1),
{ 0xFFFFFFFF, { } }, std::min((u32)((s32)two + voltAdd), max2)
};
}; };
#define DVB(v) \
static_cast<u32>((v)[0]), \
static_cast<u32>((v)[1]), \
static_cast<u32>((v)[2])
DvbEntry emcDvbTableNew[] = {
{ 204000, { 637, 637, 637, }, },
{ 1331200, { 650, 637, 637, }, },
{ 1600000, { 675, 650, 637, }, },
{ 1866000, { DVB(DvbVolt( 700, 675, 650)) }, },
{ 2133000, { DVB(DvbVolt( 725, 700, 675)) }, },
{ 2400000, { DVB(DvbVolt( 750, 725, 700)) }, },
{ 2666000, { DVB(DvbVolt( 850, 825, 800)) }, },
{ 2933000, { DVB(DvbVolt( 950, 925, 900)) }, },
{ 3200000, { DVB(DvbVolt(1050, 1025, 1000)) }, },
{ 0xFFFFFFFF, { }, },
};
#undef DVB
u32 j = MtcTableCountDefault; u32 j = MtcTableCountDefault;
for (u32 i = MtcTableCountDefault; i < newEmcList.size(); ++i) { for (u32 i = MtcTableCountDefault; i < newEmcList.size(); ++i) {
if (newEmcList[i] >= emcDvbTableNew[j].freq && newEmcList[i] < emcDvbTableNew[j + 1].freq) { if (newEmcList[i] >= emcDvbTableNew[j].freq && newEmcList[i] < emcDvbTableNew[j + 1].freq) {
@@ -849,7 +885,7 @@ namespace ams::ldr::hoc::pcv::mariko {
regulator *entry = reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_2_3.default_uv)); regulator *entry = reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_2_3.default_uv));
constexpr u32 uv_step = 5'000; constexpr u32 uv_step = 5'000;
constexpr u32 uv_min = 250'000; constexpr u32 uv_min = 250'000;
auto validator = [entry]() { auto validator = [entry]() {
R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry());
@@ -909,8 +945,127 @@ namespace ams::ldr::hoc::pcv::mariko {
u8 movRd = asm_get_rd(mov); u8 movRd = asm_get_rd(mov);
u32 movCountPatch = asm_set_rd(asm_set_imm16(MtcMovAsm, newEmcList.size()), movRd); u32 movCountPatch = asm_set_rd(asm_set_imm16(MtcMovAsm, newEmcList.size()), movRd);
PATCH_OFFSET(ptr - BrOffset, NopIns); PATCH_OFFSET(ptr - BrOffset, NopIns);
PATCH_OFFSET(ptr - MovOffset, movCountPatch); PATCH_OFFSET(ptr - MovOffset, movCountPatch);
R_SUCCEED();
}
Result GetSocSpeedo(u32 &socSpeedo) {
constexpr u64 FusePhysicalAddress = 0x7000F000;
u64 virtualAddress = 0;
constexpr u64 Size = 0x1000;
u64 outSize;
/* TODO: use svc::QueryMemoryMapping instead. */
R_TRY(svcQueryMemoryMapping(&virtualAddress, &outSize, FusePhysicalAddress, Size));
constexpr u32 FuseOffset = 2048;
constexpr u32 SocSpeedoOffset = 308;
socSpeedo = *reinterpret_cast<u32 *>(virtualAddress + FuseOffset + SocSpeedoOffset);
R_SUCCEED();
}
u32 GetSocProcessId(u32 socSpeedo) {
if (socSpeedo <= 1597) {
return 0;
}
if (socSpeedo <= 1708) {
return 1;
}
/* >= 1709. */
return 2;
}
Result SocVoltAsm(u32 *compareSpeedos) {
constexpr u32 VoltageScanLimit = 10;
/* Might actually be speedo id. */
u32 *writeProcessId = ScanAssembly(compareSpeedos, VoltageScanLimit, SocVoltWriteProcessIdAsm, asm_compare_no_rd);
R_UNLESS(writeProcessId != nullptr, ldr::ResultInvalidSocVoltPattern());
u8 writeProcessIdRd = asm_get_rd(*writeProcessId);
/* This writes 1050mV. */
u32 *writeVoltage = ScanAssembly(writeProcessId, VoltageScanLimit, SocVoltWriteVoltageAsm, asm_compare_no_rd);
R_UNLESS(writeVoltage != nullptr, ldr::ResultInvalidSocVoltPattern());
u8 writeVoltageRd = asm_get_rd(*writeVoltage);
/* A csel instruction is used to select the soc voltage limit register. */
/* We care about its destination register since that is used for verification. */
constexpr u32 VoltageSelectScanLimit = 24;
u32 *selectVoltage = ScanAssembly(writeVoltage, VoltageSelectScanLimit, SocVoltSelectRegisterAsm, AsmCompareCselNoReg);
R_UNLESS(selectVoltage != nullptr, ldr::ResultInvalidSocVoltPattern());
/* Todo: check rm and rn? */
u8 selectVoltageRd = asm_get_rd(*selectVoltage);
/* rdCsel is then multiplied by 1000 to convert to uV. */
/* This is pretty far down the function. */
constexpr u32 MultiplierScanLimit = 200;
u32 *multiplier = ScanAssembly(selectVoltage, MultiplierScanLimit, SocVoltMultiplyVoltsAsm, AsmCompareMullNoReg);
R_UNLESS(multiplier != nullptr, ldr::ResultInvalidSocVoltPattern());
u8 multiplierRn = AsmGetMullRn(*multiplier);
u8 multiplierRm = AsmGetMullRm(*multiplier);
/* One of the two registers has to be rdCsel. */
R_UNLESS((multiplierRn == selectVoltageRd) || (multiplierRm == selectVoltageRd), ldr::ResultInvalidSocVoltPattern());
u8 multiplierRd = asm_get_rd(*multiplier);
/* Subs instruction is then used to verify against absolute limit. */
u32 limitValidationPattern = AsmSubsSetRn(SocVoltValidateLimitAsm, multiplierRd);
u32 *limitValidation = ScanAssembly(multiplier, VoltageScanLimit, limitValidationPattern, AsmSubsCompareNoReg);
R_UNLESS(limitValidation != nullptr, ldr::ResultInvalidSocVoltPattern());
/* There is a b.gt instruction right after (checks for socVoltageCap < socVoltageMax). */
u32 *branchToAbort = limitValidation + 1;
R_UNLESS(AsmCompareBrConNoImm19(*branchToAbort, SocVoltBranchToAbortAsm), ldr::ResultInvalidSocVoltPattern());
if (!C.marikoSocVmax || C.marikoSocVmax <= 1000) {
R_SKIP();
}
/* Adjust 1598 speedo minimum to ensure it always goes down process id 0 branch. */
/* 2200 should be high enough :D */
u32 compareSpeedosPatch = AsmSubsSetImm12(*compareSpeedos, 2200);
PATCH_OFFSET(compareSpeedos, compareSpeedosPatch);
u32 socSpeedo = 0;
R_TRY(GetSocSpeedo(socSpeedo));
/* Adjust processId from 0 to [process id of switch booting this]. */
/* We're overwriting the orr instruction entirly. */
u32 processId = GetSocProcessId(socSpeedo);
u32 writeProcessIdPatch = asm_set_rd(asm_set_imm16(SocVoltWriteVoltageAsm, processId), writeProcessIdRd);
PATCH_OFFSET(writeProcessId, writeProcessIdPatch);
/* Adjust voltage limit. */
u32 voltageLimitPatch = asm_set_rd(asm_set_imm16(SocVoltWriteVoltageAsm, C.marikoSocVmax), writeVoltageRd);
PATCH_OFFSET(writeVoltage, voltageLimitPatch);
/* Branches to an abort if limits are invalid -- we patch the branch instruction with NOP. */
PATCH_OFFSET(branchToAbort, NopIns);
R_SUCCEED();
}
Result SocVoltLimit(u32 *ptr) {
R_UNLESS(!std::memcmp(ptr - SocVoltLimitMaxDefaultIndex, socVoltLimitArray, sizeof(socVoltLimitArray)), ldr::ResultInvalidSocVoltLimit());
if (!C.marikoSocVmax || C.marikoSocVmax <= SocVoltLimitOfficial) {
R_SKIP();
}
constexpr u32 Step = 25;
u32 maxVolt = C.marikoSocVmax;
if (maxVolt % Step) {
maxVolt = maxVolt / Step * Step; /* Round. */
}
u32 volt = SocVoltLimitOfficial;
for (u32 i = 1; i < DvfsTableEntryCount - SocVoltLimitMaxDefaultIndex && volt < maxVolt; ++i) {
volt += Step;
PATCH_OFFSET(ptr + i, volt);
}
R_SUCCEED(); R_SUCCEED();
} }
@@ -932,13 +1087,15 @@ namespace ams::ldr::hoc::pcv::mariko {
{ "GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn }, { "GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn },
{ "GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax }, { "GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax },
{ "GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit }, { "GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit },
{ "MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit }, { "MEM Freq Mtc", &MemFreqMtcTable, 1, nullptr, EmcClkOSLimit },
{ "MEM Freq Dvb", &MemFreqDvbTable, 1, nullptr, EmcClkOSLimit }, { "MEM Freq Dvb", &MemFreqDvbTable, 1, nullptr, EmcClkOSLimit },
{ "MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit }, { "MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit },
{ "MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit }, { "MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit },
{ "MEM Vddq", &EmcVddqVolt, 2, nullptr, EmcVddqDefault }, { "MEM Vddq", &EmcVddqVolt, 2, nullptr, EmcVddqDefault },
{ "MEM Vdd2", &MemVoltHandler, 2, nullptr, MemVdd2Default }, { "MEM Vdd2", &MemVoltHandler, 2, nullptr, MemVdd2Default },
{ "Mem Table Asm", &MemMtcTableAsm, 0, &MemMtcGetGetTablePatternFn }, { "MEM Table Asm", &MemMtcTableAsm, 1, &MemMtcGetGetTablePatternFn },
{ "SOC Volt Asm", &SocVoltAsm, 1, &SocVoltPatternFn },
{ "SOC Volt Limit", &SocVoltLimit, 1, nullptr, SocVoltLimitOfficial },
}; };
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(MarikoMtcTable); ptr += sizeof(u32)) { for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(MarikoMtcTable); ptr += sizeof(u32)) {
@@ -953,9 +1110,7 @@ namespace ams::ldr::hoc::pcv::mariko {
for (auto &entry : patches) { for (auto &entry : patches) {
LOGGING("%s Count: %zu", entry.description, entry.patched_count); LOGGING("%s Count: %zu", entry.description, entry.patched_count);
if (R_FAILED(entry.CheckResult())) { if (R_FAILED(entry.CheckResult())) {
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) panic::SmcError(panic::Patch);
panic::SmcError(panic::Patch);
#endif
CRASH(entry.description); CRASH(entry.description);
} }

View File

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

View File

@@ -21,11 +21,7 @@
namespace ams::ldr::hoc::ptm { namespace ams::ldr::hoc::ptm {
Result CpuPtmBoost(perf_conf_entry* entry) { Result CpuPtmBoost(perf_conf_entry* entry) {
#ifdef ATMOSPHERE_IS_STRATOSPHERE
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
#else
bool isMariko = true;
#endif
if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) { if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) {
R_SUCCEED(); R_SUCCEED();
@@ -76,11 +72,7 @@ namespace ams::ldr::hoc::ptm {
PatcherEntry<perf_conf_entry> cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, }; PatcherEntry<perf_conf_entry> cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, };
PatcherEntry<perf_conf_entry> memPtmPatch = { "MEM Ptm", &MemPtm, 16, }; PatcherEntry<perf_conf_entry> memPtmPatch = { "MEM Ptm", &MemPtm, 16, };
#ifdef ATMOSPHERE_IS_STRATOSPHERE
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
#else
bool isMariko = true;
#endif
for (u32 i = 0; i < entryCnt; i++) { for (u32 i = 0; i < entryCnt; i++) {
perf_conf_entry *entry = confTable + i; perf_conf_entry *entry = confTable + i;

View File

@@ -69,9 +69,7 @@ MmuRequest nvencRequest;
MmuRequest nvjpgRequest; MmuRequest nvjpgRequest;
//Checks //Checks
Result clkrstCheck = 1;
Result nvCheck = 1; Result nvCheck = 1;
Result pcvCheck = 1;
Result i2cCheck = 1; Result i2cCheck = 1;
Result pwmCheck = 1; Result pwmCheck = 1;
Result tcCheck = 1; Result tcCheck = 1;
@@ -554,28 +552,6 @@ void Misc(void*) {
do { do {
mutexLock(&mutex_Misc); mutexLock(&mutex_Misc);
// CPU, GPU and RAM Frequency
if (R_SUCCEEDED(clkrstCheck)) {
ClkrstSession clkSession;
if (R_SUCCEEDED(clkrstOpenSession(&clkSession, PcvModuleId_CpuBus, 3))) {
clkrstGetClockRate(&clkSession, &CPU_Hz);
clkrstCloseSession(&clkSession);
}
if (R_SUCCEEDED(clkrstOpenSession(&clkSession, PcvModuleId_GPU, 3))) {
clkrstGetClockRate(&clkSession, &GPU_Hz);
clkrstCloseSession(&clkSession);
}
if (R_SUCCEEDED(clkrstOpenSession(&clkSession, PcvModuleId_EMC, 3))) {
clkrstGetClockRate(&clkSession, &RAM_Hz);
clkrstCloseSession(&clkSession);
}
}
else if (R_SUCCEEDED(pcvCheck)) {
pcvGetClockRate(PcvModule_CpuBus, &CPU_Hz);
pcvGetClockRate(PcvModule_GPU, &GPU_Hz);
pcvGetClockRate(PcvModule_EMC, &RAM_Hz);
}
// Get sys-clk data // Get sys-clk data
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
HocClkContext hocclkCTX; HocClkContext hocclkCTX;
@@ -599,6 +575,9 @@ void Misc(void*) {
realSOC_mV = hocclkCTX.voltages[HocClkVoltage_SOC]; realSOC_mV = hocclkCTX.voltages[HocClkVoltage_SOC];
realVDD2_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDD2]; realVDD2_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDD2];
realVDDQ_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDDQ]; realVDDQ_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDDQ];
CPU_Hz = hocclkCTX.freqs[HocClkModule_CPU];
GPU_Hz = hocclkCTX.freqs[HocClkModule_GPU];
RAM_Hz = hocclkCTX.freqs[HocClkModule_MEM];
} }
} }

View File

@@ -419,8 +419,6 @@ public:
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize();
@@ -473,8 +471,6 @@ public:
} }
shmemClose(&_sharedmemory); shmemClose(&_sharedmemory);
//Exit services //Exit services
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -502,8 +498,6 @@ public:
//Initialize services //Initialize services
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -556,8 +550,6 @@ public:
hocclkIpcExit(); hocclkIpcExit();
} }
//Exit services //Exit services
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -589,8 +581,6 @@ public:
// Same serviceinit as before // Same serviceinit as before
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -644,8 +634,6 @@ public:
hocclkIpcExit(); hocclkIpcExit();
} }
// Exit services // Exit services
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -679,8 +667,6 @@ public:
virtual void initServices() override { virtual void initServices() override {
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -732,8 +718,6 @@ public:
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
hocclkIpcExit(); hocclkIpcExit();
} }
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -762,8 +746,6 @@ public:
virtual void initServices() override { virtual void initServices() override {
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -815,8 +797,6 @@ public:
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
hocclkIpcExit(); hocclkIpcExit();
} }
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -845,8 +825,6 @@ public:
virtual void initServices() override { virtual void initServices() override {
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -898,8 +876,6 @@ public:
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
hocclkIpcExit(); hocclkIpcExit();
} }
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);

View File

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

View File

@@ -125,7 +125,7 @@ public:
//Print strings //Print strings
///CPU ///CPU
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) { if (1) {
uint32_t height_offset = 155; uint32_t height_offset = 155;
if (realCPU_Hz && settings.showRealFreqs) { if (realCPU_Hz && settings.showRealFreqs) {
@@ -173,7 +173,7 @@ public:
} }
///GPU ///GPU
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck) || R_SUCCEEDED(nvCheck)) { if (R_SUCCEEDED(nvCheck)) {
uint32_t height_offset = 320-8; uint32_t height_offset = 320-8;
if (realGPU_Hz && settings.showRealFreqs) { if (realGPU_Hz && settings.showRealFreqs) {
@@ -181,7 +181,7 @@ public:
} }
renderer->drawString("GPU Usage", false, COMMON_MARGIN, 285-8, 20, (settings.catColor1)); renderer->drawString("GPU Usage", false, COMMON_MARGIN, 285-8, 20, (settings.catColor1));
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) { if (1) {
if (settings.showTargetFreqs) { if (settings.showTargetFreqs) {
//static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first; //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first;
renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2)); renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2));
@@ -213,7 +213,7 @@ public:
static std::vector<std::string> specialChars = {""}; static std::vector<std::string> specialChars = {""};
///RAM ///RAM
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck) || R_SUCCEEDED(Hinted)) { if (R_SUCCEEDED(Hinted)) {
uint32_t height_offset = 410; uint32_t height_offset = 410;
if (realRAM_Hz && settings.showRealFreqs) { if (realRAM_Hz && settings.showRealFreqs) {
@@ -221,7 +221,7 @@ public:
} }
renderer->drawString("RAM Usage", false, COMMON_MARGIN, 375, 20, (settings.catColor1)); renderer->drawString("RAM Usage", false, COMMON_MARGIN, 375, 20, (settings.catColor1));
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) { if (1) {
if (settings.showTargetFreqs) { if (settings.showTargetFreqs) {
//static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first; //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first;
renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2)); renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2));

View File

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

View File

@@ -1,6 +1,5 @@
# hoc-clk # hoc-clk
Switch sysmodule allowing you to set cpu/gpu/mem clocks according to the running application and docked state. Overclocking suite for Nintendo Switch.
Modified for Horizon OC
Support is only provided for FW 16.0.0+. This MAY work on older firmwares but support is NOT guaranteed Support is only provided for FW 17.0.0+. This MAY work on older firmwares but support is NOT guaranteed

Binary file not shown.

View File

@@ -9,10 +9,8 @@ if [[ -n "$1" ]]; then
DIST_DIR="$1" DIST_DIR="$1"
fi fi
echo "DIST_DIR: $DIST_DIR" echo
echo "CORES: $CORES" echo "*** Compiling hoc-clk ***"
echo "*** sysmodule ***"
TITLE_ID="$(grep -oP '"title_id":\s*"0x\K(\w+)' "$ROOT_DIR/sysmodule/perms.json")" TITLE_ID="$(grep -oP '"title_id":\s*"0x\K(\w+)' "$ROOT_DIR/sysmodule/perms.json")"
pushd "$ROOT_DIR/sysmodule" pushd "$ROOT_DIR/sysmodule"
@@ -24,18 +22,23 @@ cp -vf "$ROOT_DIR/sysmodule/out/hoc-clk.nsp" "$DIST_DIR/atmosphere/contents/$TIT
>"$DIST_DIR/atmosphere/contents/$TITLE_ID/flags/boot2.flag" >"$DIST_DIR/atmosphere/contents/$TITLE_ID/flags/boot2.flag"
cp -vf "$ROOT_DIR/sysmodule/toolbox.json" "$DIST_DIR/atmosphere/contents/$TITLE_ID/toolbox.json" cp -vf "$ROOT_DIR/sysmodule/toolbox.json" "$DIST_DIR/atmosphere/contents/$TITLE_ID/toolbox.json"
echo "*** overlay ***" echo
echo "*** Compiling hoc-clk-overlay ***"
pushd "$ROOT_DIR/overlay" pushd "$ROOT_DIR/overlay"
make -j$CORES make -j$CORES
popd > /dev/null popd > /dev/null
mkdir -p "$DIST_DIR/switch/.overlays" mkdir -p "$DIST_DIR/switch/.overlays"
cp -vf "$ROOT_DIR/overlay/out/horizon-oc-overlay.ovl" "$DIST_DIR/switch/.overlays/horizon-oc-overlay.ovl" cp -vf "$ROOT_DIR/overlay/out/horizon-oc-overlay.ovl" "$DIST_DIR/switch/.overlays/horizon-oc-overlay.ovl"
echo
echo "*** assets ***" echo "*** Copying assets ***"
mkdir -p "$DIST_DIR/config/horizon-oc" 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/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template"
cp -vf "$ROOT_DIR/../../README.md" "$DIST_DIR/README.md" mkdir -p "$DIST_DIR/config/ultrahand/assets/notifications"
cp -vf "$ROOT_DIR/assets/hoc.rgba" "$DIST_DIR/config/ultrahand/assets/notifications/hoc.rgba"
echo "*** lang ***" echo
cp -r "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/" echo "*** Copying lang ***"
cp -vr "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/"
echo

View File

@@ -48,7 +48,7 @@ extern "C" {
#include "hocclk/apm.h" #include "hocclk/apm.h"
#include "hocclk/config.h" #include "hocclk/config.h"
#include "hocclk/errors.h" #include "hocclk/errors.h"
#include "hocclk/psm_ext.h" #include "hocclk/result.hpp"
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -42,22 +42,20 @@ typedef enum
typedef enum typedef enum
{ {
HocClkConsoleType_Icosa = 0, // V1 HocClkConsoleType_Icosa = 0, // V1
HocClkConsoleType_Copper, // Unreleased Erista
HocClkConsoleType_Hoag, // Lite
HocClkConsoleType_Iowa, // V2 HocClkConsoleType_Iowa, // V2
HocClkConsoleType_Calcio, // Unreleased Mariko HocClkConsoleType_Hoag, // Lite
HocClkConsoleType_Aula, // OLED HocClkConsoleType_Aula, // OLED
HocClkConsoleType_EnumMax, HocClkConsoleType_EnumMax,
} HocClkConsoleType; } HocClkConsoleType;
typedef enum { typedef enum {
HocClkVoltage_SOC = 0, HocClkVoltage_SOC = 0, // VDD_SOC rail.
HocClkVoltage_EMCVDD2, HocClkVoltage_EMCVDD2, // DRAM VDD2 rail
HocClkVoltage_CPU, HocClkVoltage_CPU, // CPU rail
HocClkVoltage_GPU, HocClkVoltage_GPU, // GPU rail
HocClkVoltage_EMCVDDQ, // Returns VDD2 on Erista HocClkVoltage_EMCVDDQ, // DRAM VDDQ rail
HocClkVoltage_Display, HocClkVoltage_Display, // Display rail
HocClkVoltage_Battery, HocClkVoltage_Battery, // Battery voltage
HocClkVoltage_EnumMax, HocClkVoltage_EnumMax,
} HocClkVoltage; } HocClkVoltage;
@@ -73,7 +71,7 @@ typedef enum
typedef enum typedef enum
{ {
HocClkModule_CPU = 0, HocClkModule_CPU = 0,
HocClkModule_GPU, HocClkModule_GPU,
HocClkModule_MEM, HocClkModule_MEM,
HocClkModule_Governor, HocClkModule_Governor,
@@ -83,15 +81,17 @@ typedef enum
typedef enum typedef enum
{ {
HocClkThermalSensor_SOC = 0, HocClkThermalSensor_SOC = 0, // SoC temperature in millicelcius
HocClkThermalSensor_PCB, HocClkThermalSensor_PCB, // PCB temperature in millicelcius
HocClkThermalSensor_Skin, HocClkThermalSensor_Skin, // "Skin" temperature in millicelcius
HocClkThermalSensor_Battery, HocClkThermalSensor_Battery, // Battery temperature in millicelcius
HocClkThermalSensor_PMIC, // Always return 50.0C, as thats the only reasonable value the PMIC sensor can generate HocClkThermalSensor_PMIC, // Always return 50.0C, as thats the only reasonable value the PMIC sensor can generate
HocClkThermalSensor_CPU, HocClkThermalSensor_CPU, // CPU temperature in millicelcius
HocClkThermalSensor_GPU, HocClkThermalSensor_GPU, // GPU temperature in millicelcius
HocClkThermalSensor_MEM, // Returns the PLLX sensor value on Mariko HocClkThermalSensor_MEM, // MEM temperature in millicelcius. Returns the PLLX sensor value on Mariko
HocClkThermalSensor_PLLX, HocClkThermalSensor_PLLX, // PLLX temperature in millicelcius
HocClkThermalSensor_AO, // AOTAG
HocClkThermalSensor_BQ24193, // BQ24193 temperature. Refer to BQ24193Temp for returned values
HocClkThermalSensor_EnumMax HocClkThermalSensor_EnumMax
} HocClkThermalSensor; } HocClkThermalSensor;
@@ -113,7 +113,7 @@ typedef enum
HocClkPartLoad_RamBWAll, HocClkPartLoad_RamBWAll,
HocClkPartLoad_RamBWCpu, HocClkPartLoad_RamBWCpu,
HocClkPartLoad_RamBWGpu, HocClkPartLoad_RamBWGpu,
HocClkPartLoad_RamBWPeak, HocClkPartLoad_RamBWPeak, // Maximum possible RAM bandwidth
HocClkPartLoad_EnumMax HocClkPartLoad_EnumMax
} HocClkPartLoad; } HocClkPartLoad;
@@ -125,15 +125,15 @@ typedef enum {
} HocClkSpeedo; } HocClkSpeedo;
typedef enum { typedef enum {
GPUUVLevel_NoUV = 0, GPUUVLevel_HiOPT = 0,
GPUUVLevel_SLT, GPUUVLevel_HiOPT15,
GPUUVLevel_HiOPT, GPUUVLevel_HighUV,
GPUUVLevel_EnumMax, GPUUVLevel_EnumMax,
} GPUUndervoltLevel; } GPUUndervoltLevel;
enum { enum {
DVFSMode_Disabled = 0, DVFSMode_Disabled = 0,
DVFSMode_Hijack, DVFSMode_Hijack, // PCV hijack dvfs
// DVFSMode_OfficialService, // DVFSMode_OfficialService,
// DVFSMode_Hack, // DVFSMode_Hack,
DVFSMode_EnumMax, DVFSMode_EnumMax,
@@ -164,8 +164,8 @@ typedef enum {
} RamDisplayMode; } RamDisplayMode;
typedef enum { typedef enum {
MemoryFrequencyMeasurementMode_Actmon = 0, MemoryFrequencyMeasurementMode_PLL = 0,
MemoryFrequencyMeasurementMode_PLL, MemoryFrequencyMeasurementMode_Actmon,
MemoryFrequencyMeasurementMode_EnumMax, MemoryFrequencyMeasurementMode_EnumMax,
} MemoryFrequencyMeasurementMode; } MemoryFrequencyMeasurementMode;
@@ -175,6 +175,51 @@ typedef enum {
RamDisplayUnit_MHzMTs, RamDisplayUnit_MHzMTs,
RamDisplayUnit_EnumMax, RamDisplayUnit_EnumMax,
} RamDisplayUnit; } RamDisplayUnit;
typedef enum {
BQ24193Temp_Normal = 0,
BQ24193Temp_Warm,
BQ24193Temp_Hot,
BQ24193Temp_Overheat,
BQ24193Temp_EnumMax
} BQ24193Temp;
typedef enum AulaColorMode {
AulaDisplayColorMode_DoNotOverride = 0xFF,
AulaDisplayColorMode_Saturated = 0x0,
AulaDisplayColorMode_Washed = 0x45,
AulaDisplayColorMode_Basic = 0x03, // Default
AulaDisplayColorMode_PowerReset = 0x20, // Reset to on power on
AulaDisplayColorMode_Natural = 0x23,
AulaDisplayColorMode_Vivid = 0x65,
AulaDisplayColorMode_Night0 = 0x43,
AulaDisplayColorMode_Night1 = 0x15,
AulaDisplayColorMode_Night2 = 0x35,
AulaDisplayColorMode_Night3 = 0x75,
} AulaColorMode;
// typedef enum {
// PANEL_JDI_XXX062M = 0x10,
// PANEL_JDI_LAM062M109A = 0x0910, // SI.
// PANEL_JDI_LPM062M326A = 0x2610, // LTPS.
// PANEL_INL_P062CCA_AZ1 = 0x0F20,
// PANEL_AUO_A062TAN01 = 0x0F30,
// PANEL_INL_2J055IA_27A = 0x1020,
// PANEL_AUO_A055TAN01 = 0x1030,
// PANEL_SHP_LQ055T1SW10 = 0x1040,
// PANEL_SAM_AMS699VC01 = 0x2050,
// PANEL_RR_SUPER5_OLED_V1 = 0x10E0,
// PANEL_RR_SUPER5_OLED_HD_V1 = 0x10E1,
// PANEL_RR_SUPER7_IPS_V1 = 0x0FE0,
// PANEL_RR_SUPER7_IPS_HD_V1 = 0x0FE1
// // Found on 6/2" clones. Unknown markings. Clone of AUO A062TAN01.
// // Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F]. Sometimes reports [30] 94 [0F]. Both IDs have correct CRC16.
// PANEL_OEM_CLONE_6_2 = 0x0F83,
// // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
// PANEL_OEM_CLONE_5_5 = 0x00B3,
// // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
// PANEL_OEM_CLONE = 0x0000
// //0x0F40 [40] 94 [0F], 5.5" clone
// } HocClkDisplayPanel;
#define HOCCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax) #define HOCCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
@@ -237,6 +282,10 @@ static inline const char* hocclkFormatThermalSensor(HocClkThermalSensor thermSen
return pretty ? "MEM" : "mem"; return pretty ? "MEM" : "mem";
case HocClkThermalSensor_PLLX: case HocClkThermalSensor_PLLX:
return pretty ? "PLLX" : "pllx"; return pretty ? "PLLX" : "pllx";
case HocClkThermalSensor_AO:
return pretty ? "AO" : "ao";
case HocClkThermalSensor_BQ24193:
return pretty ? "BQ24193" : "bq24193";
default: default:
return "unknown"; return "unknown";
} }
@@ -284,7 +333,7 @@ static inline const char* hocClkFormatVoltage(HocClkVoltage voltage, bool pretty
case HocClkVoltage_GPU: case HocClkVoltage_GPU:
return pretty ? "GPU" : "gpu"; return pretty ? "GPU" : "gpu";
case HocClkVoltage_EMCVDD2: case HocClkVoltage_EMCVDD2:
return pretty ? "VDD2" : "emcvdd2"; return pretty ? "VDD2" : "vdd2";
case HocClkVoltage_EMCVDDQ: case HocClkVoltage_EMCVDDQ:
return pretty ? "VDDQ" : "vddq"; return pretty ? "VDDQ" : "vddq";
case HocClkVoltage_SOC: case HocClkVoltage_SOC:
@@ -295,3 +344,61 @@ static inline const char* hocClkFormatVoltage(HocClkVoltage voltage, bool pretty
return "unknown"; return "unknown";
} }
} }
static inline const char* hocClkFormatConsoleType(HocClkConsoleType consoleType, bool pretty)
{
switch(consoleType)
{
case HocClkConsoleType_Icosa:
return pretty ? "Icosa (V1)" : "icosa";
case HocClkConsoleType_Iowa:
return pretty ? "Iowa (V2)" : "iowa";
case HocClkConsoleType_Hoag:
return pretty ? "Hoag (Lite)" : "hoag";
case HocClkConsoleType_Aula:
return pretty ? "Aula (OLED)" : "aula";
default:
return "unknown";
}
}
// static inline const char* hocClkFormatPanel(HocClkDisplayPanel panel, bool pretty)
// {
// switch(panel)
// {
// case PANEL_JDI_XXX062M:
// return pretty ? "JDI XXX062M" : "jdi_xxx062m";
// case PANEL_JDI_LAM062M109A:
// return pretty ? "JDI LAM062M109A" : "jdi_lam062m109a";
// case PANEL_JDI_LPM062M326A:
// return pretty ? "JDI LPM062M326A" : "jdi_lpm062m326a";
// case PANEL_INL_P062CCA_AZ1:
// return pretty ? "INL P062CCA-AZ1" : "inl_p062cca_az1";
// case PANEL_AUO_A062TAN01:
// return pretty ? "AUO A062TAN01" : "auo_a062tan01";
// case PANEL_INL_2J055IA_27A:
// return pretty ? "INL 2J055IA-27A" : "inl_2j055ia_27a";
// case PANEL_AUO_A055TAN01:
// return pretty ? "AUO A055TAN01" : "auo_a055tan01";
// case PANEL_SHP_LQ055T1SW10:
// return pretty ? "SHP LQ055T1SW10" : "shp_lq055t1sw10";
// case PANEL_SAM_AMS699VC01:
// return pretty ? "SAM AMS699VC01" : "sam_ams699vc01";
// case PANEL_RR_SUPER5_OLED_V1:
// return pretty ? "SUPER5 OLED" : "rr_super5_oled_v1";
// case PANEL_RR_SUPER5_OLED_HD_V1:
// return pretty ? "SUPER5 OLED HD" : "rr_super5_oled_hd_v1";
// case PANEL_RR_SUPER7_IPS_V1:
// return pretty ? "SUPER7 IPS" : "rr_super7_ips_v1";
// case PANEL_RR_SUPER7_IPS_HD_V1:
// return pretty ? "RR Super7 IPS HD V1" : "rr_super7_ips_hd_v1";
// case PANEL_OEM_CLONE_6_2:
// return pretty ? "OEM Clone 6.2" : "oem_clone_6_2";
// case PANEL_OEM_CLONE_5_5:
// return pretty ? "OEM Clone 5.5" : "oem_clone_5_5";
// case PANEL_OEM_CLONE:
// return pretty ? "OEM Clone" : "oem_clone";
// default:
// return "unknown";
// }
// }

View File

@@ -30,21 +30,41 @@
#include <stdint.h> #include <stdint.h>
#include "board.h" #include "board.h"
typedef struct typedef struct {
{
/*
* This "stable struct" must never be modified. It provides a fixed memory layout so external clients can safely read the expected fields even
* if HocClkContext changes in newer versions and the client is not recompiled.
*/
struct {
#define HocClkModuleStable_EnumMax 5
#define HocClkThermalSensorStable_EnumMax 11
#define HocClkPowerSensorStable_EnumMax 2
#define HocClkPartLoadStable_EnumMax 10
#define HocClkVoltageStable_EnumMax 7
u32 freqs[HocClkModuleStable_EnumMax];
u32 realFreqs[HocClkModuleStable_EnumMax];
u32 overrideFreqs[HocClkModuleStable_EnumMax];
s32 temps[HocClkThermalSensorStable_EnumMax];
s32 power[HocClkPowerSensorStable_EnumMax];
u32 partLoad[HocClkPartLoadStable_EnumMax];
u32 voltages[HocClkVoltageStable_EnumMax];
} stable;
uint64_t applicationId; uint64_t applicationId;
HocClkProfile profile; HocClkProfile profile;
uint32_t freqs[HocClkModule_EnumMax]; uint32_t freqs[HocClkModule_EnumMax];
uint32_t realFreqs[HocClkModule_EnumMax]; uint32_t realFreqs[HocClkModule_EnumMax];
uint32_t overrideFreqs[HocClkModule_EnumMax]; uint32_t overrideFreqs[HocClkModule_EnumMax];
uint32_t temps[HocClkThermalSensor_EnumMax]; int32_t temps[HocClkThermalSensor_EnumMax];
int32_t power[HocClkPowerSensor_EnumMax]; int32_t power[HocClkPowerSensor_EnumMax];
uint32_t partLoad[HocClkPartLoad_EnumMax]; uint32_t partLoad[HocClkPartLoad_EnumMax];
uint32_t voltages[HocClkVoltage_EnumMax]; uint32_t voltages[HocClkVoltage_EnumMax];
u16 speedos[HocClkSpeedo_EnumMax]; u16 speedos[HocClkSpeedo_EnumMax];
u16 iddq[HocClkSpeedo_EnumMax]; u16 iddq[HocClkSpeedo_EnumMax];
u16 waferX; s16 waferX;
u16 waferY; s16 waferY;
// Misc stuff // Misc stuff
GpuSchedulingMode gpuSchedulingMode; GpuSchedulingMode gpuSchedulingMode;
@@ -54,13 +74,16 @@ typedef struct
u8 maxDisplayFreq; u8 maxDisplayFreq;
u8 dramID; u8 dramID;
bool isDram8GB; bool isDram8GB;
HocClkConsoleType consoleType;
// FPS / Resolution // FPS / Resolution
u8 fps; u8 fps;
u16 resolutionHeight; u16 resolutionHeight;
u8 custRev;
u16 kipVersion;
// Reserved for future use // Reserved for future use
u8 reserved[0x428]; u8 reserved[0x35B];
} HocClkContext; } HocClkContext;
typedef struct typedef struct
@@ -71,8 +94,8 @@ typedef struct
}; };
} HocClkTitleProfileList; } HocClkTitleProfileList;
#define HOCCLK_FREQ_LIST_MAX 32 #define HOCCLK_FREQ_LIST_MAX 48
#define GLOBAL_PROFILE_ID 0xA111111111111111 #define HOCCLK_GLOBAL_PROFILE_TID 0xA111111111111111
static_assert(sizeof(HocClkContext) == 0x500); static_assert(sizeof(HocClkContext) == 0x500);

View File

@@ -72,6 +72,9 @@ typedef enum {
HocClkConfigValue_RamDisplayUnit, HocClkConfigValue_RamDisplayUnit,
HocClkConfigValue_IsFirstLoad, HocClkConfigValue_IsFirstLoad,
HocClkConfigValue_AulaDisplayColorPreset,
HocClkConfigValue_MarikoMiddleFreqs,
KipConfigValue_custRev, KipConfigValue_custRev,
// KipConfigValue_mtcConf, // KipConfigValue_mtcConf,
KipConfigValue_hpMode, KipConfigValue_hpMode,
@@ -85,6 +88,7 @@ typedef enum {
KipConfigValue_marikoEmcMaxClock, KipConfigValue_marikoEmcMaxClock,
KipConfigValue_marikoEmcVddqVolt, KipConfigValue_marikoEmcVddqVolt,
KipConfigValue_emcDvbShift, KipConfigValue_emcDvbShift,
KipConfigValue_marikoSocVmax,
KipConfigValue_t1_tRCD, KipConfigValue_t1_tRCD,
KipConfigValue_t2_tRP, KipConfigValue_t2_tRP,
@@ -284,7 +288,10 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
case HocClkConfigValue_RamDisplayUnit: case HocClkConfigValue_RamDisplayUnit:
return pretty ? "RAM Frequency Display Unit" : "RAM_display_unit"; return pretty ? "RAM Frequency Display Unit" : "RAM_display_unit";
case HocClkConfigValue_AulaDisplayColorPreset:
return pretty ? "Aula Display Color Preset" : "aula_color_preset";
case HocClkConfigValue_MarikoMiddleFreqs:
return pretty ? "Mariko Middle Clocks" : "mariko_middle_freqs";
// KIP config values // KIP config values
case KipConfigValue_custRev: case KipConfigValue_custRev:
return pretty ? "Custom Revision" : "kip_cust_rev"; return pretty ? "Custom Revision" : "kip_cust_rev";
@@ -310,7 +317,8 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
return pretty ? "Mariko EMC VDDQ Voltage" : "mariko_emc_vddq_volt"; return pretty ? "Mariko EMC VDDQ Voltage" : "mariko_emc_vddq_volt";
case KipConfigValue_emcDvbShift: case KipConfigValue_emcDvbShift:
return pretty ? "EMC DVB Shift" : "emc_dvb_shift"; return pretty ? "EMC DVB Shift" : "emc_dvb_shift";
case KipConfigValue_marikoSocVmax:
return pretty ? "SOC Vmax" : "soc_vmax";
// Memory timings // Memory timings
case KipConfigValue_t1_tRCD: case KipConfigValue_t1_tRCD:
return pretty ? "t1 - tRCD" : "t1_trcd"; return pretty ? "t1 - tRCD" : "t1_trcd";
@@ -496,6 +504,7 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val)
case HocClkConfigValue_LiveCpuUv: case HocClkConfigValue_LiveCpuUv:
case HocClkConfigValue_GPUSchedulingMethod: case HocClkConfigValue_GPUSchedulingMethod:
case HocClkConfigValue_MemoryFrequencyMeasurementMode: case HocClkConfigValue_MemoryFrequencyMeasurementMode:
case HocClkConfigValue_MarikoMiddleFreqs:
return 0ULL; return 0ULL;
case HocClkConfigValue_RamDisplayUnit: case HocClkConfigValue_RamDisplayUnit:
return (uint64_t)RamDisplayUnit_MHz; return (uint64_t)RamDisplayUnit_MHz;
@@ -522,6 +531,8 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val)
return 60ULL; return 60ULL;
case HocClkConfigValue_DisplayVoltage: case HocClkConfigValue_DisplayVoltage:
return 1200ULL; // Auto return 1200ULL; // Auto
case HocClkConfigValue_AulaDisplayColorPreset:
return AulaDisplayColorMode_DoNotOverride;
default: default:
return 0ULL; return 0ULL;
} }
@@ -553,6 +564,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case HocClkConfigValue_EnableExperimentalSettings: case HocClkConfigValue_EnableExperimentalSettings:
case HocClkConfigValue_LiveCpuUv: case HocClkConfigValue_LiveCpuUv:
case HocClkConfigValue_GPUSchedulingMethod: case HocClkConfigValue_GPUSchedulingMethod:
case HocClkConfigValue_MarikoMiddleFreqs:
return (input & 0x1) == input; return (input & 0x1) == input;
case KipConfigValue_custRev: case KipConfigValue_custRev:
@@ -566,6 +578,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_marikoEmcMaxClock: case KipConfigValue_marikoEmcMaxClock:
case KipConfigValue_marikoEmcVddqVolt: case KipConfigValue_marikoEmcVddqVolt:
case KipConfigValue_emcDvbShift: case KipConfigValue_emcDvbShift:
case KipConfigValue_marikoSocVmax:
case KipConfigValue_t1_tRCD: case KipConfigValue_t1_tRCD:
case KipConfigValue_t2_tRP: case KipConfigValue_t2_tRP:
case KipConfigValue_t3_tRAS: case KipConfigValue_t3_tRAS:
@@ -669,6 +682,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case HocClkConfigValue_CpuGovernorMinimumFreq: case HocClkConfigValue_CpuGovernorMinimumFreq:
case HocClkConfigValue_MemoryFrequencyMeasurementMode: case HocClkConfigValue_MemoryFrequencyMeasurementMode:
case HocClkConfigValue_RamDisplayUnit: case HocClkConfigValue_RamDisplayUnit:
case HocClkConfigValue_AulaDisplayColorPreset:
return true; return true;
case HocClkConfigValue_BatteryChargeCurrent: case HocClkConfigValue_BatteryChargeCurrent:
return ((input >= 1024) && (input <= 3072)) || !input; return ((input >= 1024) && (input <= 3072)) || !input;

View File

@@ -0,0 +1,11 @@
#pragma once
#include <switch.h>
#define R_UNLESS(rc) \
do { \
if (R_FAILED(rc)) { \
return; \
} \
} while (0)
/* TODO: Add more Result macros. */

View File

@@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk
# version control constants # version control constants
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
#TARGET_VERSION := $(shell git describe --dirty --always --tags) #TARGET_VERSION := $(shell git describe --dirty --always --tags)
APP_VERSION := 2.0.1 APP_VERSION := 2.3.0 # ensure to set KIP_VERSION and CUST_REV in sysmodule Makefile when updating this
TARGET_VERSION := $(APP_VERSION) TARGET_VERSION := $(APP_VERSION)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

View File

@@ -1,11 +1,11 @@
{ {
"Information": "Informations", "Information": "Informations",
"IDDQ:": "IDDQ :", "IDDQ:": "IDDQ :",
"Module: ": "Module :", "Module: ": "Module :",
"sys-dock status:": "état du dock système :", "sys-dock status:": "Statut de sys-dock :",
"SaltyNX status:": "Statut SaltyNX :", "SaltyNX status:": "Statut de SaltyNX :",
"RR Display status:": "Etat d'affichage RR :", "RR Display status:": "Statut de l'affichage RR :",
"Wafer Position:": "Position de la plaquette :", "Wafer Position:": "Position du wafer :",
"Credits": "Crédits", "Credits": "Crédits",
"Developers": "Développeurs", "Developers": "Développeurs",
"Contributors": "Contributeurs", "Contributors": "Contributeurs",
@@ -15,127 +15,127 @@
"Installed": "Installé", "Installed": "Installé",
"Not Installed": "Non installé", "Not Installed": "Non installé",
"X: %u Y: %u": "X : %u Y : %u", "X: %u Y: %u": "X : %u Y : %u",
"THE BEER-WARE LICENSE": "LA LICENCE DE LA BIÈRE", "THE BEER-WARE LICENSE": "LA LICENCE BEER-WARE",
"Default": "Par défaut", "Default": "Par défaut",
"Do Not Override": "Ne pas remplacer", "Do Not Override": "Ne pas remplacer",
"Disabled": "Désactivé", "Disabled": "Désactivé",
"Enabled": "Activé", "Enabled": "Activé",
" \\ue0e3 Reset": "\\ue0e3 Réinitialiser", " \\ue0e3 Reset": "\\ue0e3 Réinitialiser",
"Display": "Affichage", "Display": "Écran",
"Application changed\\n\\n": "Application modifiée\\n\\n", "Application changed\\n\\n": "Application modifiée\\n\\n",
"The running application changed\\n\\n": "L'application en cours d'exécution a changé\\n\\n", "The running application changed\\n\\n": "L'application en cours d'exécution a changé\\n\\n",
"while editing was going on.": "pendant le montage.", "while editing was going on.": "pendant la modification.",
"Board": "Conseil", "Board": "Carte",
"%u.%u%u mV": "%u.%u%u mV", "%u.%u%u mV": "%u.%u%u mV",
"Could not connect to hoc-clk sysmodule.\\n\\n": "Impossible de se connecter au module système hoc-clk.\\n\\n", "Could not connect to hoc-clk sysmodule.\\n\\n": "Impossible de se connecter au sysmodule hoc-clk.\\n\\n",
"Please make sure everything is\\n\\n": "Veuillez vous assurer que tout est\\n\\n", "Please make sure everything is\\n\\n": "Veuillez vous assurer que tout est\\n\\n",
"correctly installed and enabled.": "correctement installé et activé.", "correctly installed and enabled.": "correctement installé et activé.",
"Fatal error": "Erreur fatale", "Fatal error": "Erreur fatale",
"Temporary Overrides ": "Remplacements temporaires", "Temporary Overrides ": "Forçages temporaires ",
"Sleep Mode": "Mode veille", "Sleep Mode": "Mode veille",
"Stock": "Actions", "Stock": "D'origine",
"Dev OC": "Développeur OC", "Dev OC": "OC Développeur",
"Boost Mode": "Mode Boost", "Boost Mode": "Mode Boost",
"Safe Max": "Coffre-fort maximum", "Safe Max": "Max sûr",
"Unsafe Max": "Dangereux Max", "Unsafe Max": "Max non sûr",
"Absolute Max": "Max absolu", "Absolute Max": "Max absolu",
"Handheld Safe Max": "Coffre-fort portatif Max", "Handheld Safe Max": "Max sûr (mode portable)",
"Enable": "Activer", "Enable": "Activer",
"Edit App Profile": "Modifier le profil de l'application", "Edit App Profile": "Modifier le profil de l'app",
"Edit Global Profile": "Modifier le profil global", "Edit Global Profile": "Modifier le profil global",
"Temporary Overrides": "Remplacements temporaires", "Temporary Overrides": "Forçages temporaires",
"Settings": "Paramètres", "Settings": "Paramètres",
"About": "À propos", "About": "À propos",
"Compiling with minimal features": "Compilation avec des fonctionnalités minimales", "Compiling with minimal features": "Compilation avec fonctionnalités minimales",
"General Settings": "Paramètres généraux", "General Settings": "Paramètres généraux",
"Governor Settings": "Paramètres du gouverneur", "Governor Settings": "Paramètres du gouverneur",
"Safety Settings": "Paramètres de sécurité", "Safety Settings": "Paramètres de sécurité",
"Save KIP Settings": "Enregistrer les paramètres KIP", "Save KIP Settings": "Enregistrer les paramètres KIP",
"RAM Settings": "Paramètres de la RAM", "RAM Settings": "Paramètres RAM",
"CPU Settings": "Paramètres du processeur", "CPU Settings": "Paramètres CPU",
"GPU Settings": "Paramètres du processeur graphique", "GPU Settings": "Paramètres GPU",
"Display Settings": "Paramètres d'affichage", "Display Settings": "Paramètres d'affichage",
"Experimental": "Expérimental", "Experimental": "Expérimental",
"GPU Scheduling Override Method": "Méthode de remplacement de la planification GPU", "GPU Scheduling Override Method": "Méthode de Forçage de l'ordonnancement GPU",
"can be dangerous and may cause": "peut être dangereux et provoquer", "can be dangerous and may cause": "peut être dangereux et causer des",
"damage to your battery or charger!": "dommages à votre batterie ou à votre chargeur !", "damage to your battery or charger!": "dommages à votre batterie ou chargeur !",
"Charge Current Override": "Remplacement du courant de charge", "Charge Current Override": "Forçage du courant de charge",
"RAM Voltage Display Mode": "Mode d'affichage de la tension de la RAM", "RAM Voltage Display Mode": "Mode d'affichage de la tension RAM",
"Polling Interval": "Intervalle d'interrogation", "Polling Interval": "Intervalle d'interrogation",
"CPU Governor Minimum Frequency": "Fréquence minimale du gouverneur du processeur", "CPU Governor Minimum Frequency": "Fréquence minimale du gouverneur CPU",
"refresh rates may cause stress": "les taux de rafraîchissement peuvent causer du stress", "refresh rates may cause stress": "les taux de rafraîchissement peuvent stresser",
"or damage to your display! ": "ou endommager votre écran !", "or damage to your display! ": "ou endommager votre écran !",
"Proceed at your own risk!": "Procédez à vos propres risques !", "Proceed at your own risk!": "À utiliser à vos propres risques !",
"Max Handheld Display": "Affichage portable maximum", "Max Handheld Display": "Affichage portable max",
"Display Clock": "Affichage de l'horloge", "Display Clock": "Fréquence d'affichage",
"Official Rating": "Classement officiel", "Official Rating": "Classement officiel",
"TDP Threshold": "Seuil TDP", "TDP Threshold": "Seuil TDP",
"Power": "Puissance", "Power": "Alimentation",
"Thermal Throttle Limit": "Limite d'accélérateur thermique", "Thermal Throttle Limit": "Limite d'étranglement thermique",
"HP Mode": "Mode HP", "HP Mode": "Mode HP",
"Default (Mariko)": "Par défaut (Mariko)", "Default (Mariko)": "Par défaut (Mariko)",
"Default (Erista)": "Par défaut (Erista)", "Default (Erista)": "Par défaut (Erista)",
"Rating": "Note", "Rating": "Évaluation",
"Safe Max (Mariko)": "Coffre-fort Max (Mariko)", "Safe Max (Mariko)": "Max sûr (Mariko)",
"Safe Max (Erista)": "Coffre-fort Max (Erista)", "Safe Max (Erista)": "Max sûr (Erista)",
"RAM VDD2 Voltage": "Tension de la RAM VDD2", "RAM VDD2 Voltage": "Tension RAM VDD2",
"Voltage": "Tension", "Voltage": "Tension",
"RAM VDDQ Voltage": "Tension VDDQ de la RAM", "RAM VDDQ Voltage": "Tension RAM VDDQ",
"RAM Frequency Editor": "Éditeur de fréquence RAM", "RAM Frequency Editor": "Éditeur de fréquence RAM",
"JEDEC.": "JEDEC.", "JEDEC.": "JEDEC.",
"High speedo needed!": "Besoin d'un speedo haut !", "High speedo needed!": "Speedo élevé requis !",
"3333MHz (Needs extreme Speedo/PLL)": "3333 MHz (nécessite un Speedo/PLL extrême)", "3333MHz (Needs extreme Speedo/PLL)": "3333 MHz (nécessite Speedo/PLL extrême)",
"3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (nécessite un Speedo/PLL extrême)", "3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (nécessite Speedo/PLL extrême)",
"3400MHz (Needs extreme Speedo/PLL)": "3400 MHz (nécessite un Speedo/PLL extrême)", "3400MHz (Needs extreme Speedo/PLL)": "3400 MHz (nécessite Speedo/PLL extrême)",
"3433MHz (Needs ridiculous Speedo/PLL)": "3433 MHz (nécessite un Speedo/PLL ridicule)", "3433MHz (Needs ridiculous Speedo/PLL)": "3433 MHz (nécessite Speedo/PLL ridicule)",
"3466MHz (Needs ridiculous Speedo/PLL)": "3466 MHz (nécessite un Speedo/PLL ridicule)", "3466MHz (Needs ridiculous Speedo/PLL)": "3466 MHz (nécessite Speedo/PLL ridicule)",
"3500MHz (Needs ridiculous Speedo/PLL)": "3500 MHz (nécessite un Speedo/PLL ridicule)", "3500MHz (Needs ridiculous Speedo/PLL)": "3500 MHz (nécessite Speedo/PLL ridicule)",
"Ram Max Clock": "Ram Max Horloge", "Ram Max Clock": "Fréquence RAM max",
"RAM Latency Editor": "Éditeur de latence RAM", "RAM Latency Editor": "Éditeur de latence RAM",
"RAM Timing Reductions": "Réductions de synchronisation de la RAM", "RAM Timing Reductions": "Réductions des timings RAM",
"Memory Timings": "Horaires de mémoire", "Memory Timings": "Timings mémoire",
"Advanced": "Avancé", "Advanced": "Avancé",
"t6 tRTW Fine Tune": "t6 tRTW réglage fin", "t6 tRTW Fine Tune": "Ajustement précis t6 tRTW",
"tRTW Fine Tune": "tRTW Réglage fin", "tRTW Fine Tune": "Ajustement précis tRTW",
"t7 tWTR Fine Tune": "t7 tWTR réglage fin", "t7 tWTR Fine Tune": "Ajustement précis t7 tWTR",
"tWTR Fine Tune": "Réglage fin du tWTR", "tWTR Fine Tune": "Ajustement précis tWTR",
"Memory Latencies": "Latences de mémoire", "Memory Latencies": "Latences mémoire",
"Read Latency": "Latence de lecture", "Read Latency": "Latence de lecture",
"Write Latency": "Latence d'écriture", "Write Latency": "Latence d'écriture",
"CPU Boost Clock": "Horloge d'augmentation du processeur", "CPU Boost Clock": "Fréquence Boost CPU",
"CPU UV": "UV du processeur", "CPU UV": "UV CPU",
"CPU Unlock": "Déverrouillage du processeur", "CPU Unlock": "Déverrouillage CPU",
"CPU VMIN": "CPU VMIN", "CPU VMIN": "CPU VMIN",
"CPU Max Voltage": "Tension maximale du processeur", "CPU Max Voltage": "Tension CPU max",
"CPU Max Clock": "Horloge maximale du processeur", "CPU Max Clock": "Fréquence CPU max",
"Extreme UV Table": "Table UV Extrême", "Extreme UV Table": "Table d'UV extrême",
"CPU UV Table": "Tableau UV du processeur", "CPU UV Table": "Table d'UV CPU",
"CPU Low UV": "CPU faible UV", "CPU Low UV": "UV CPU faible",
"CPU High UV": "CPU UV élevé", "CPU High UV": "UV CPU élevé",
"CPU Low VMIN": "CPU faible VMIN", "CPU Low VMIN": "VMIN CPU faible",
"CPU High VMIN": "Processeur VMIN élevé", "CPU High VMIN": "VMIN CPU élevé",
"No Undervolt": "Pas de sous-tension", "No Undervolt": "Aucun Undervolt",
"SLT Table": "Tableau SLT", "SLT Table": "Table SLT",
"HiOPT Table": "Tableau HiOPT", "HiOPT Table": "Table HiOPT",
"GPU Undervolt Table": "Tableau de sous-tension GPU", "GPU Undervolt Table": "Table d'undervolt GPU",
"GPU Minimum Voltage": "Tension minimale du GPU", "GPU Minimum Voltage": "Tension GPU minimale",
"Calculate GPU Vmin": "Calculer la Vmin du GPU", "Calculate GPU Vmin": "Calculer Vmin GPU",
"GPU VMIN": "GPU VMIN", "GPU VMIN": "GPU VMIN",
"GPU Maximum Voltage": "Tension maximale du GPU", "GPU Maximum Voltage": "Tension GPU maximale",
"GPU Voltage Offset": "Décalage de tension du GPU", "GPU Voltage Offset": "Offset de tension GPU",
"Do not override": "Ne remplacez pas", "Do not override": "Ne pas remplacer",
"Enabled (Default)": "Activé (par défaut)", "Enabled (Default)": "Activé (par défaut)",
"96.6% limit": "Limite de 96,6 %", "96.6% limit": "Limite de 96,6 %",
"99.7% limit": "Limite de 99,7 %", "99.7% limit": "Limite de 99,7 %",
"GPU Scheduling Override": "Remplacement de la planification GPU", "GPU Scheduling Override": "Forçage de l'ordonnancement GPU",
"Official Service": "Service officiel", "Official Service": "Service officiel",
"GPU DVFS Mode": "Mode GPU DVFS", "GPU DVFS Mode": "Mode GPU DVFS",
"GPU DVFS Offset": "Décalage GPU DVFS", "GPU DVFS Offset": "Offset GPU DVFS",
"GPU Voltage Table": "Tableau de tension du GPU", "GPU Voltage Table": "Table de tension GPU",
"GPU Custom Table (mV)": "Tableau personnalisé GPU (mV)", "GPU Custom Table (mV)": "Table de GPU personnalisée (mV)",
"1075MHz without UV, 1152MHz on SLT": "1075 MHz sans UV, 1152 MHz sur SLT", "1075MHz without UV, 1152MHz on SLT": "1075 MHz sans UV, 1152 MHz sur SLT",
"or 1228MHz on HiOPT can cause ": "ou 1228 MHz sur HiOPT peut provoquer", "or 1228MHz on HiOPT can cause ": "ou 1228 MHz sur HiOPT peut causer des",
"permanent damage to your Switch!": "dommages permanents à votre Switch !", "permanent damage to your Switch!": "dommages permanents à votre Switch !",
"921MHz without UV and 960MHz on": "921 MHz sans UV et 960 MHz activé", "921MHz without UV and 960MHz on": "921 MHz sans UV et 960 MHz sur",
"SLT or HiOPT can cause ": "SLT ou HiOPT peuvent provoquer" "SLT or HiOPT can cause ": "SLT ou HiOPT peuvent causer des"
} }

View File

@@ -1,141 +1,179 @@
{ {
"Information": "Информация", "Information": "Информация",
"IDDQ:": "ИДДК:", "IDDQ:": "IDDQ:",
"Module: ": "Модуль:", "Module: ": "Module:",
"sys-dock status:": "Статус системной док-станции:", "sys-dock status:": "Статус sys-dock:",
"SaltyNX status:": "Статус SaltyNX:", "SaltyNX status:": "Статус SaltyNX:",
"RR Display status:": "Статус отображения RR:", "RR Display status:": "Статус RR Display:",
"Wafer Position:": "Позиция вафли:", "Wafer Position:": "Wafer Position:",
"Credits": "Кредиты", "Credits": "Благодарности",
"Developers": "Разработчики", "Developers": "Разработчики",
"Contributors": "Авторы", "Contributors": "Внесли вклад",
"Testers": "Тестеры", "Testers": "Тестеры",
"Special Thanks": "Особая благодарность", "Special Thanks": "Особая благодарность",
"Unknown": "Неизвестно", "Unknown": "Неизвестно",
"Installed": "Установлено", "Installed": "Установлено",
"Not Installed": "Не установлено", "Not Installed": "Не установлено",
"X: %u Y: %u": "X: %u Y: %u", "X: %u Y: %u": "X: %u Y: %u",
"THE BEER-WARE LICENSE": "ЛИЦЕНЗИЯ НА ПРОДАЖУ ПИВА", "THE BEER-WARE LICENSE": "BEER-WARE LICENSE",
"Default": "По умолчанию", "Default": "По умолчанию",
"Do Not Override": "Не переопределять", "Do Not Override": "Не менять",
"Disabled": "Отключено", "Disabled": "Отключено",
"Enabled": "Включено", "Enabled": "Включено",
"Auto": "Авто",
" \\ue0e3 Reset": "\\ue0e3 Сброс", " \\ue0e3 Reset": "\\ue0e3 Сброс",
"Display": "Дисплей", "Display": "Дисплей",
"Application changed\\n\\n": "Приложение изменено\\n\\n", "Application changed\\n\\n": "Приложение изменено\\n\\n",
"The running application changed\\n\\n": "Запущенное приложение изменилось\\n\\n", "The running application changed\\n\\n": "Запущенное приложение изменилось\\n\\n",
"while editing was going on.": "пока шло редактирование.", "while editing was going on.": "пока шло редактирование.",
"Board": "Совет", "Board": "Board",
"%u.%u%u mV": "%u.%u%u мВ", "%u.%u%u mV": "%u.%u%u мВ",
"Could not connect to hoc-clk sysmodule.\\n\\n": "Не удалось подключиться к системному модулю hoc-clk.\\n\\n", "Could not connect to hoc-clk sysmodule.\\n\\n": "Не удалось подключиться к сис-модулю hoc-clk.\\n\\n",
"Please make sure everything is\\n\\n": "Пожалуйста, убедитесь, что все в порядке\\n\\n", "Please make sure everything is\\n\\n": "Пожалуйста, убедитесь, что все\\n\\n",
"correctly installed and enabled.": "правильно установлен и включен.", "correctly installed and enabled.": "правильно установлено и включено.",
"Fatal error": "Неустранимая ошибка", "Fatal error": "Фатальная ошибка",
"Temporary Overrides ": "Временные переопределения", "Temporary Overrides ": "Временный профиль",
"Sleep Mode": "Спящий режим", "Sleep Mode": "Спящий режим",
"Stock": "Акции", "Stock": "Стандарт",
"Dev OC": "Разработчик OC", "Dev OC": "Разгон dev-кита",
"Boost Mode": "Режим повышения", "Boost Mode": "Режим буста",
"Safe Max": "Сейф Макс", "Safe Max": "Безопасный макс.",
"Unsafe Max": "Небезопасный Макс", "Unsafe Max": "Опасный макс.",
"Absolute Max": "Абсолютный Макс", "Absolute Max": "Абсолютный макс.",
"Handheld Safe Max": "Ручной сейф Макс", "Handheld Safe Max": "Портативный безопасный макс.",
"Enable": "Включить", "Enable": "Включено",
"Edit App Profile": "Редактировать профиль приложения", "Edit App Profile": "Профиль приложения",
"Edit Global Profile": "Редактировать глобальный профиль", "Edit Global Profile": "Глобальный профиль",
"Temporary Overrides": "Временные переопределения", "Temporary Overrides": "Временный профиль",
"Settings": "Настройки", "Settings": "Настройки",
"About": "О", "About": "Сведения",
"Compiling with minimal features": "Компиляция с минимальными возможностями", "Compiling with minimal features": "Собрано с урезанием функций",
"General Settings": "Общие настройки", "\uE150 Settings marked in blue": "Настройки помеченные синим",
"Governor Settings": "Настройки губернатора", "don't require a reboot to apply!": "Синие настройки применяются сразу!",
"General Settings": "Основные настройки",
"Governor Settings": "Настройки говернора",
"Safety Settings": "Настройки безопасности", "Safety Settings": "Настройки безопасности",
"Save KIP Settings": "Сохранить настройки КИП", "Save KIP Settings": "Сохранить настройки KIP",
"RAM Settings": "Настройки ОЗУ", "RAM Settings": "Настройки RAM",
"CPU Settings": "Настройки процессора", "CPU Settings": "Настройки CPU",
"GPU Settings": "Настройки графического процессора", "GPU Settings": "Настройки GPU",
"Display Settings": "Настройки дисплея", "Display Settings": "Настройки дисплея",
"Experimental": "Экспериментальный", "Experimental": "Экспериментальный",
"GPU Scheduling Override Method": "Метод переопределения планирования графического процессора", "Enable Experimental Settings": "Экспериментальные настройки",
"can be dangerous and may cause": "может быть опасным и может вызвать", "\uE150 Experimental Settings are incomplete ": "Экспериментальные настройки не закончены",
"damage to your battery or charger!": "повреждение аккумулятора или зарядного устройства!", "and may not work correctly or at all!": "Экспериментальные настройки не",
"Charge Current Override": "Блокировка зарядного тока", "Here be dragons!": "закончены и могут не работать!",
"RAM Voltage Display Mode": "Режим отображения напряжения ОЗУ", "Experimental Settings": "Экспериментальные",
"Live CPU Undervolt": "Мгновенный андервольт CPU",
"GPU Scheduling Override Method": "Метод перезаписи планировщика GPU",
"Memory Frequency Measurement Mode": "Режим измерения частоты RAM",
"\uE150 Overriding the charge current": "Перезапись зарядного тока может",
"can be dangerous and may cause": "Перезапись зарядного тока может",
"damage to your battery or charger!": "повреждить аккумулятор или зарядку!",
"Charge Current Override": "Перезапись зарядного тока",
"RAM Voltage Display Mode": "Показ вольтажа RAM",
"RAM Display Unit": "Показ единицы измерения RAM",
"Polling Interval": "Интервал опроса", "Polling Interval": "Интервал опроса",
"CPU Governor Minimum Frequency": "Минимальная частота регулятора ЦП", "CPU Governor Minimum Frequency": "Минимальная частота говернора CPU",
"refresh rates may cause stress": "частота обновления может вызвать стресс", "\uE150 Usage of unsafe display": "\uE150 Использование не безопасной",
"or damage to your display! ": "или повреждение дисплея!", "refresh rates may cause stress": "Не безопасная частота",
"or damage to your display! ": "может повредить ваш экран",
"Proceed at your own risk!": "Действуйте на свой страх и риск!", "Proceed at your own risk!": "Действуйте на свой страх и риск!",
"Max Handheld Display": "Макс. портативный дисплей", "Max Handheld Display Hz": "Макс. в портативе",
"Display Clock": "Дисплей Часы", "Display Clock": "Частота экрана",
"Official Rating": "Официальный рейтинг", "Official Rating": "Официальный рейтинг",
"TDP Threshold": "Порог TDP", "TDP Threshold": "Порог TDP",
"Power": "Мощность", "Power": "Мощность",
"Thermal Throttle Limit": "Температурный предел дроссельной заслонки", "Thermal Throttle Limit": "Предел троттлинга",
"HP Mode": "Режим HP", "HP Mode": "Режим HP",
"Default (Mariko)": "По умолчанию (Марико)", "Default (Mariko)": "По умолчанию (M)",
"Default (Erista)": "По умолчанию (Эриста)", "Default (Erista)": "По умолчанию (E)",
"Rating": "Рейтинг", "Rating": "Рейтинг",
"Safe Max (Mariko)": "Сейф Макс (Марико)", "Safe Max (Mariko)": "Сейф Макс (M)",
"Safe Max (Erista)": "Сейф Макс (Эриста)", "Safe Max (Erista)": "Сейф Макс (E)",
"RAM VDD2 Voltage": "Напряжение ОЗУ VDD2", "RAM VDD2 Voltage": "Вольтаж VDD2",
"Voltage": "Напряжение", "Voltage": "Вольтаж",
"RAM VDDQ Voltage": "Напряжение ОЗУ VDDQ", "RAM VDDQ Voltage": "Вольтаж VDDQ",
"RAM Frequency Editor": "Редактор частоты оперативной памяти", "Step Mode": "Частотный шаг",
"JEDEC.": "ДЖЕДЕК.", "RAM Frequency Editor": "Редактор частоты",
"High speedo needed!": "Нужен высокий спидометр!", "JEDEC.": "JEDEC.",
"3333MHz (Needs extreme Speedo/PLL)": "3333 МГц (требуется экстремальный спидометр/PLL)", "High speedo needed!": "Для высоких speedo",
"3366MHz (Needs extreme Speedo/PLL)": "3366 МГц (требуется экстремальный спидометр/PLL)", "3333MHz (Needs extreme Speedo/PLL)": "3333 MHz (нужны невероятные speedo/PLL)",
"3400MHz (Needs extreme Speedo/PLL)": "3400 МГц (требуется экстремальный спидометр/PLL)", "3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (нужны невероятные speedo/PLL)",
"3433MHz (Needs ridiculous Speedo/PLL)": "3433 МГц (нужен нелепый спидометр/PLL)", "3400MHz (Needs extreme Speedo/PLL)": "3400 MHz (нужны невероятные speedo/PLL)",
"3466MHz (Needs ridiculous Speedo/PLL)": "3466 МГц (нужен нелепый спидометр/PLL)", "3433MHz (Needs ridiculous Speedo/PLL)": "3433 MHz (нужны безумные speedo/PLL)",
"3500MHz (Needs ridiculous Speedo/PLL)": "3500 МГц (нужен нелепый спидометр/PLL)", "3466MHz (Needs ridiculous Speedo/PLL)": "3466 MHz (нужны безумные speedo/PLL)",
"Ram Max Clock": "Рам Макс Часы", "3500MHz (Needs ridiculous Speedo/PLL)": "3500 MHz (нужны безумные speedo/PLL)",
"RAM Latency Editor": "Редактор задержки оперативной памяти", "Ram Max Clock": "Макс. частота",
"RAM Timing Reductions": "Сокращение таймингов ОЗУ", "RAM Latency Editor": "Редактор задержек",
"Memory Timings": "Тайминги памяти", "1333 Latency Max": "1333 задержка",
"Advanced": "Расширенный", "1600 Latency Max": "1600 задержка",
"t6 tRTW Fine Tune": "t6 tRTW Точная настройка", "1866 Latency Max": "1866 задержка",
"tRTW Fine Tune": "tRTW Точная настройка", "2133 Latency Max": "2133 задержка",
"t7 tWTR Fine Tune": "t7 tWTR Тонкая настройка", "RAM Timing Reductions": "Настройка таймингов",
"tWTR Fine Tune": "tWTR Тонкая настройка", "Memory Timings": "Тайминги RAM",
"RAM-Timing tBreak": "Разбитие таблицы таймингов",
"Memory": "RAM",
"mem": "RAM",
"MEM": "RAM",
"Profile": "Профиль",
"Governor": "Говернор",
"Advanced": "Расширенные",
"Docked": "В доке",
"Handheld": "Портатив",
"Charging": "На зарядке",
"USB Charger": "USB Зарядка",
"PD Charger": "PD Зарядка",
"Handheld TDP": "TPD в портативе",
"Thermal Throttle": "Троттлинг",
"Uncapped Clocks": "Максимальные частоты",
"SoC DVB Shift": "SoC DVB сдвиг",
"SoC Max Volt": "Макс. вольт SoC",
"Overwrite Boost Mode": "Перезапись буста",
"Display Refresh Rate Changing": "Изменение частоты экрана",
"Low t6 tRTW": "Нижний t6 tRTW",
"Low t7 tWTR": "Нижний t7 tWTR",
"1333WL t2 RP Cap": "Предел 1333WL t2 RP",
"t6 tRTW Fine Tune": " Точная настройка t6 tRTW",
"tRTW Fine Tune": " Точная настройка tRTW",
"t7 tWTR Fine Tune": " Точная настройка t7 tWTR",
"tWTR Fine Tune": " Точная настройка tWTR",
"Memory Latencies": "Задержки памяти", "Memory Latencies": "Задержки памяти",
"Read Latency": "Задержка чтения", "Read Latency": "Задержка чтения",
"Write Latency": "Задержка записи", "Write Latency": "Задержка записи",
"CPU Boost Clock": "Тактовая частота процессора", "CPU Boost Clock": "Частота буста",
"CPU UV": "УФ процессора", "CPU UV": "Андервольт CPU",
"CPU Unlock": "Разблокировка процессора", "CPU Unlock": "Разблокировка CPU",
"CPU VMIN": "ЦП VMIN", "CPU VMIN": "Мин. вольтаж",
"CPU Max Voltage": "Максимальное напряжение процессора", "CPU Max Voltage": "Макс. вольтаж",
"CPU Max Clock": "Максимальная частота процессора", "CPU Max Clock": "Макс. частота",
"Extreme UV Table": "Стол для экстремального УФ-излучения", "Extreme UV Table": "Экстримальная",
"CPU UV Table": "UV-таблица процессора", "CPU UV Table": "Таблица андервольта",
"CPU Low UV": "ЦП с низким УФ-излучением", "CPU Low UV": "Андервольт нижних частот",
"CPU High UV": "Процессор с высоким УФ", "CPU High UV": "Андервольт верхних частот",
"CPU Low VMIN": "Низкий VMIN процессора", "CPU Low VMIN": "Мин. вольт. нижних частот",
"CPU High VMIN": "Высокий VMIN процессора", "CPU High VMIN": "Мин. вольт. верхних частот",
"No Undervolt": "Нет Андервольта", "No Undervolt": "Без андервольта",
"SLT Table": "Таблица ТА", "SLT Table": "Таблица SLT",
"HiOPT Table": "Таблица HiOPT", "HiOPT Table": "Таблица HiOPT",
"GPU Undervolt Table": "Таблица пониженного напряжения графического процессора", "GPU Undervolt Table": "Таблица андервольта",
"GPU Minimum Voltage": "Минимальное напряжение графического процессора", "GPU Minimum Voltage": "Мин. вольтаж",
"Calculate GPU Vmin": "Рассчитать Vmin графического процессора", "Calculate GPU Vmin": "Вычисление мин. вольтаж",
"GPU VMIN": "Вмин графического процессора", "GPU VMIN": "Мин. вольтаж",
"GPU Maximum Voltage": "Максимальное напряжение графического процессора", "GPU Maximum Voltage": "Макс. вольтаж",
"GPU Voltage Offset": "Смещение напряжения графического процессора", "GPU Voltage Offset": "Смещение вольтажа",
"Do not override": "Не переопределять", "Do not override": "Не менять",
"Enabled (Default)": "Включено (по умолчанию)", "Enabled (Default)": "Включено (По умолчанию)",
"96.6% limit": "Предел 96,6%", "96.6% limit": "96,6%",
"99.7% limit": "лимит 99,7%", "99.7% limit": "99,7%",
"GPU Scheduling Override": "Переопределение планирования графического процессора", "GPU Scheduling Override": "Перезапись планировщика",
"Official Service": "Официальная служба", "Official Service": "Официальная служба",
"GPU DVFS Mode": "Режим графического процессора DVFS", "GPU DVFS Mode": "Режим DVFS",
"GPU DVFS Offset": "Смещение DVFS графического процессора", "GPU DVFS Offset": "Смещение DVFS",
"GPU Voltage Table": "Таблица напряжений графического процессора", "GPU Voltage Table": "Таблица вольтажей",
"GPU Custom Table (mV)": "Пользовательская таблица графического процессора (мВ)", "GPU Custom Table (mV)": "Ручная таблица (мВ)",
"1075MHz without UV, 1152MHz on SLT": "1075 МГц без УФ, 1152 МГц на SLT", "\uE150 Setting GPU Clocks past": "\uE150 Установка частот GPU выше",
"or 1228MHz on HiOPT can cause ": "или 1228 МГц на HiOPT может привести к", "1228MHz without a proper undervolt": "Установка частот GPU выше 1228 МГц",
"permanent damage to your Switch!": "необратимое повреждение вашего коммутатора!", "can cause degradation or damage": "без хорошего андервольта может",
"921MHz without UV and 960MHz on": "921 МГц без УФ и 960 МГц с включенным", "to your console!": "повредить вашу консоль!"
"SLT or HiOPT can cause ": "SLT или HiOPT могут вызвать"
} }

View File

@@ -29,7 +29,6 @@
#include <tesla.hpp> #include <tesla.hpp>
#include "ui/gui/fatal_gui.h" #include "ui/gui/fatal_gui.h"
#include "ui/gui/main_gui.h" #include "ui/gui/main_gui.h"
#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc.
class AppOverlay : public tsl::Overlay class AppOverlay : public tsl::Overlay
{ {
@@ -42,7 +41,6 @@ class AppOverlay : public tsl::Overlay
//} //}
virtual void exitServices() override { virtual void exitServices() override {
rgltrExit();
hocclkIpcExit(); hocclkIpcExit();
} }

View File

@@ -22,6 +22,8 @@
#include "cat.h" #include "cat.h"
#include "ult_ext.h" #include "ult_ext.h"
// tsl::elm::ListItem* custRevItem = NULL;
tsl::elm::ListItem* kipVersionItem = NULL;
tsl::elm::ListItem* SpeedoItem = NULL; tsl::elm::ListItem* SpeedoItem = NULL;
tsl::elm::ListItem* IddqItem = NULL; tsl::elm::ListItem* IddqItem = NULL;
tsl::elm::ListItem* DramModule = NULL; tsl::elm::ListItem* DramModule = NULL;
@@ -36,6 +38,9 @@ tsl::elm::ListItem* ramBWItemAll = NULL;
tsl::elm::ListItem* ramBWItemCpu = NULL; tsl::elm::ListItem* ramBWItemCpu = NULL;
tsl::elm::ListItem* ramBWItemGpu = NULL; tsl::elm::ListItem* ramBWItemGpu = NULL;
tsl::elm::ListItem* ramBWItemMax = NULL; tsl::elm::ListItem* ramBWItemMax = NULL;
tsl::elm::ListItem* bqtempitem = NULL;
tsl::elm::ListItem* aotagTempItem = NULL;
tsl::elm::ListItem* cTypeItem = NULL;
ImageElement* CatImage = NULL; ImageElement* CatImage = NULL;
HideableCategoryHeader* CatHeader = NULL; HideableCategoryHeader* CatHeader = NULL;
@@ -53,13 +58,18 @@ AboutGui::~AboutGui()
void AboutGui::listUI() void AboutGui::listUI()
{ {
BaseMenuGui::refresh();
if (!this->context)
return;
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::CategoryHeader("Voltages and Temps") new tsl::elm::CategoryHeader("Voltages")
); );
ramVoltItem = ramVoltItem =
new tsl::elm::ListItem("RAM Voltage:"); new tsl::elm::ListItem("RAM Voltage:");
if(IsMariko()) { if(IsMariko()) {
this->listElement->addItem(ramVoltItem); this->listElement->addItem(ramVoltItem);
} }
@@ -67,12 +77,23 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Display Voltage:"); new tsl::elm::ListItem("Display Voltage:");
this->listElement->addItem(dispVoltItem); this->listElement->addItem(dispVoltItem);
this->listElement->addItem(
new tsl::elm::CategoryHeader("Temperatures")
);
eristaPLLXItem = eristaPLLXItem =
new tsl::elm::ListItem("PLLX Temp:"); new tsl::elm::ListItem("PLLX Temp:");
if(IsErista()) { if(this->context->temps[HocClkThermalSensor_AO] > 0) { // Only show if the value is valid (not -126, which means not patched)
this->listElement->addItem(eristaPLLXItem); this->listElement->addItem(eristaPLLXItem);
} }
aotagTempItem =
new tsl::elm::ListItem("AOTAG Temp:");
this->listElement->addItem(aotagTempItem);
bqtempitem =
new tsl::elm::ListItem("BQ24193 Temp:");
this->listElement->addItem(bqtempitem);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::CategoryHeader("RAM Bandwidth") new tsl::elm::CategoryHeader("RAM Bandwidth")
); );
@@ -88,15 +109,20 @@ void AboutGui::listUI()
ramBWItemCpu = ramBWItemCpu =
new tsl::elm::ListItem("RAM BW (CPU):"); new tsl::elm::ListItem("RAM BW (CPU):");
this->listElement->addItem(ramBWItemCpu); this->listElement->addItem(ramBWItemCpu);
ramBWItemGpu = ramBWItemGpu =
new tsl::elm::ListItem("RAM BW (GPU):"); new tsl::elm::ListItem("RAM BW (GPU):");
this->listElement->addItem(ramBWItemGpu); this->listElement->addItem(ramBWItemGpu);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::CategoryHeader("HW Info") new tsl::elm::CategoryHeader("Hardware Info")
); );
cTypeItem =
new tsl::elm::ListItem("Console Type:");
this->listElement->addItem(cTypeItem);
SpeedoItem = SpeedoItem =
new tsl::elm::ListItem("Speedo:"); new tsl::elm::ListItem("Speedo:");
this->listElement->addItem(SpeedoItem); this->listElement->addItem(SpeedoItem);
@@ -106,7 +132,7 @@ void AboutGui::listUI()
this->listElement->addItem(IddqItem); this->listElement->addItem(IddqItem);
DramModule = DramModule =
new tsl::elm::ListItem("Module: "); new tsl::elm::ListItem("DRAM Module: ");
this->listElement->addItem(DramModule); this->listElement->addItem(DramModule);
waferCordsItem = waferCordsItem =
@@ -123,6 +149,12 @@ void AboutGui::listUI()
new tsl::elm::CategoryHeader("Software Info") new tsl::elm::CategoryHeader("Software Info")
); );
// custRevItem = new tsl::elm::ListItem("CUST revision:");
// this->listElement->addItem(custRevItem);
kipVersionItem = new tsl::elm::ListItem("KIP version:");
this->listElement->addItem(kipVersionItem);
if(!IsHoag()) { if(!IsHoag()) {
sysdockStatusItem = sysdockStatusItem =
new tsl::elm::ListItem("sys-dock status:"); new tsl::elm::ListItem("sys-dock status:");
@@ -174,13 +206,25 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Blaise25") new tsl::elm::ListItem("Blaise25")
); );
// ---- Testers ----
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::CategoryHeader("Testers") new tsl::elm::ListItem("tetetete-ctrl")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("Dom") new tsl::elm::ListItem("B3711")
);
this->listElement->addItem(
new tsl::elm::ListItem("TDRR")
);
this->listElement->addItem(
new tsl::elm::ListItem("MasaGratoR")
);
// ---- Testers ----
this->listElement->addItem(
new tsl::elm::CategoryHeader("Testers")
); );
this->listElement->addItem( this->listElement->addItem(
@@ -188,7 +232,7 @@ void AboutGui::listUI()
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("Delta") new tsl::elm::ListItem("arcdelta")
); );
this->listElement->addItem( this->listElement->addItem(
@@ -199,10 +243,6 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Happy") new tsl::elm::ListItem("Happy")
); );
this->listElement->addItem(
new tsl::elm::ListItem("Flopsider")
);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("Winnerboi77") new tsl::elm::ListItem("Winnerboi77")
); );
@@ -219,10 +259,6 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Alvise") new tsl::elm::ListItem("Alvise")
); );
this->listElement->addItem(
new tsl::elm::ListItem("TDRR")
);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("agjeococh") new tsl::elm::ListItem("agjeococh")
); );
@@ -241,7 +277,7 @@ void AboutGui::listUI()
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("ScriesM - Atmosphere CFW") new tsl::elm::ListItem("SciresM - Atmosphere CFW")
); );
this->listElement->addItem( this->listElement->addItem(
@@ -249,27 +285,23 @@ void AboutGui::listUI()
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("hanai3bi - Switch OC Suite & EOS") new tsl::elm::ListItem("hanai3Bi - Switch OC Suite & EOS")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("NaGaa95 - L4T-OC-Kernel") new tsl::elm::ListItem("NaGaa95 - L4T-OC-Kernel")
); );
this->listElement->addItem(
new tsl::elm::ListItem("B3711 - EOS")
);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("RetroNX - sys-clk") new tsl::elm::ListItem("RetroNX - sys-clk")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("b0rd2death - Ultrahand") new tsl::elm::ListItem("ppkantorski - Ultrahand")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("MasaGratoR - Status Monitor") new tsl::elm::ListItem("CtCaer - Hekate, L4T and Proper Timings")
); );
// Create cat elements but hide them initially // Create cat elements but hide them initially
@@ -337,7 +369,7 @@ void AboutGui::update()
void AboutGui::refresh() void AboutGui::refresh()
{ {
BaseMenuGui::refresh(); BaseMenuGui::refresh();
if (!this->context) if (!this->context)
return; return;
// Format strings once per refresh // Format strings once per refresh
@@ -347,26 +379,38 @@ void AboutGui::refresh()
SpeedoItem->setValue(strings[0]); SpeedoItem->setValue(strings[0]);
IddqItem->setValue(strings[1]); IddqItem->setValue(strings[1]);
DramModule->setValue(formatRamModule()); DramModule->setValue(formatRamModule());
// custRevItem->setValue(std::to_string(this->context->custRev));
kipVersionItem->setValue(std::to_string((this->context->kipVersion / 100) % 10) + "." + std::to_string((this->context->kipVersion / 10) % 10) + "." + std::to_string( this->context->kipVersion % 10) + " (Cust Rev " + std::to_string(this->context->custRev) + ")");
if(!IsHoag()) if(!IsHoag())
sysdockStatusItem->setValue(this->context->isSysDockInstalled ? "Installed" : "Not Installed"); sysdockStatusItem->setValue(this->context->isSysDockInstalled ? "Installed" : "Not Installed");
saltyNXStatusItem->setValue(this->context->isSaltyNXInstalled ? "Installed" : "Not Installed"); saltyNXStatusItem->setValue(this->context->isSaltyNXInstalled ? "Installed" : "Not Installed");
if(IsHoag()) if(IsHoag())
RETROStatusItem->setValue(this->context->isUsingRetroSuper ? "Installed" : "Not Installed"); RETROStatusItem->setValue(this->context->isUsingRetroSuper ? "Installed" : "Not Installed");
sprintf(strings[2], "X: %u Y: %u", this->context->waferX, this->context->waferY); sprintf(strings[2], "X: %d Y: %d", this->context->waferX, this->context->waferY);
waferCordsItem->setValue(strings[2]); waferCordsItem->setValue(strings[2]);
if(IsErista()) { s32 millis = context->temps[HocClkThermalSensor_PLLX];
u32 millis = context->temps[HocClkThermalSensor_PLLX]; sprintf(strings[3], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
sprintf(strings[3], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); eristaPLLXItem->setValue(strings[3]);
eristaPLLXItem->setValue(strings[3]);
millis = context->temps[HocClkThermalSensor_AO];
if(millis > 0) {
sprintf(strings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
} else if (millis == -125) {
sprintf(strings[11], "Invalid");
} else if (millis == -126) {
sprintf(strings[11], "Not Patched");
} }
aotagTempItem->setValue(strings[11]);
sprintf(strings[4], "%u.%u / %u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ] / 1000); sprintf(strings[4], "%u.%u / %u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ] / 1000);
ramVoltItem->setValue(strings[4]); ramVoltItem->setValue(strings[4]);
sprintf(strings[5], "%u.%u mV", context->voltages[HocClkVoltage_Display] / 1000U, (context->voltages[HocClkVoltage_Display] % 1000U) / 100U); sprintf(strings[5], "%u.%u mV", context->voltages[HocClkVoltage_Display] / 1000U, (context->voltages[HocClkVoltage_Display] % 1000U) / 100U);
dispVoltItem->setValue(strings[5]); dispVoltItem->setValue(strings[5]);
@@ -382,4 +426,25 @@ void AboutGui::refresh()
sprintf(strings[9], "%u MB/s", context->partLoad[HocClkPartLoad_RamBWPeak]); sprintf(strings[9], "%u MB/s", context->partLoad[HocClkPartLoad_RamBWPeak]);
ramBWItemMax->setValue(strings[9]); ramBWItemMax->setValue(strings[9]);
switch(context->temps[HocClkThermalSensor_BQ24193]) {
case BQ24193Temp_Normal:
strcpy(strings[10], "Normal");
break;
case BQ24193Temp_Warm:
strcpy(strings[10], "Warm");
break;
case BQ24193Temp_Hot:
strcpy(strings[10], "Hot");
break;
case BQ24193Temp_Overheat:
strcpy(strings[10], "Overheat");
break;
default:
strcpy(strings[10], "Unknown");
}
bqtempitem->setValue(strings[10]);
cTypeItem->setValue(hocClkFormatConsoleType(this->context->consoleType, true));
} }

View File

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

View File

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

View File

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

View File

@@ -87,7 +87,9 @@ std::map<uint32_t, std::string> gpu_freq_label_e_uv = {
std::map<uint32_t, std::string> gpu_freq_label_m = { std::map<uint32_t, std::string> gpu_freq_label_m = {
{76800000, "Boost Mode"}, {76800000, "Boost Mode"},
{307200000, "Handheld"}, {307200000, "Handheld"},
{345600000, "Handheld"},
{384000000, "Handheld"}, {384000000, "Handheld"},
{422400000, "Handheld"},
{460800000, "Handheld"}, {460800000, "Handheld"},
{614400000, "Handheld Safe Max"}, {614400000, "Handheld Safe Max"},
{768000000, "Docked"}, {768000000, "Docked"},

View File

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

View File

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

View File

@@ -22,21 +22,20 @@ CONFIG_DIR := horizon-oc
BUILD := build BUILD := build
OUTDIR := out OUTDIR := out
RESOURCES := res RESOURCES := res
SOURCES := src src/nx/ipc ../common/src src/board SOURCES := src src/hos src/i2c src/ipc src/board src/display src/tsensor src/mgr src/file src/soc src/mapping src/pwr src/util
DATA := data DATA := data
INCLUDES := ../common/include INCLUDES := ../common/include src/hos src/soc src/i2c src/util src/pwr src/ipc
EXEFS_SRC := exefs_src EXEFS_SRC := exefs_src
LIBNAMES := minIni nxExt LIBNAMES := minIni
# major minor patch
#--------------------------------------------------------------------------------- TARGET_VERSION := 2.3.0
# version control constants KIP_VERSION := 230
#--------------------------------------------------------------------------------- CUST_REV := 3
TARGET_VERSION := $(shell git describe --dirty --always --tags)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # options for code generation
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_VERSION)\"" -DCONFIG_DIR="\"$(CONFIG_DIR)\"" DEFINES := -DDISABLE_IPC -DKIP_VERSION=$(KIP_VERSION) -DCUST_REV=$(CUST_REV) -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_VERSION)\"" -DCONFIG_DIR="\"$(CONFIG_DIR)\""
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE

View File

@@ -1,13 +0,0 @@
# Editor files
*.swp
*~
# Objects
*.o
*.a
*.so
# Lib
lib
release
debug

View File

@@ -1,132 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
SOURCES := src
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec
CFLAGS := -g -Wall -Werror \
-ffunction-sections \
-fdata-sections \
$(ARCH) \
$(BUILD_CFLAGS)
CFLAGS += $(INCLUDE) -std=gnu11
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
.PHONY: clean all lib/lib$(TARGET).a lib/lib$(TARGET)d.a
#---------------------------------------------------------------------------------
all: lib/lib$(TARGET).a lib/lib$(TARGET)d.a
lib:
@[ -d $@ ] || mkdir -p $@
release:
@[ -d $@ ] || mkdir -p $@
debug:
@[ -d $@ ] || mkdir -p $@
lib/lib$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
DEPSDIR=$(CURDIR)/release \
--no-print-directory -C release \
-f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr release debug lib
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(OFILES_SRC) : $(HFILES)
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
* wrote this file. As long as you retain this notice you can do whatever you
* want with this stuff. If you meet any of us some day, and you think this
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
* --------------------------------------------------------------------------
*/
#pragma once
#include "nxExt/apm_ext.h"
#include "nxExt/i2c.h"
#include "nxExt/t210.h"
#include "nxExt/max17050.h"
#include "nxExt/tmp451.h"
#include "nxExt/ipc_server.h"
#include "nxExt/cpp/lockable_mutex.h"

View File

@@ -3,7 +3,7 @@
"title_id": "0x00FF0000636C6BFF", "title_id": "0x00FF0000636C6BFF",
"title_id_range_min": "0x00FF0000636C6BFF", "title_id_range_min": "0x00FF0000636C6BFF",
"title_id_range_max": "0x00FF0000636C6BFF", "title_id_range_max": "0x00FF0000636C6BFF",
"main_thread_stack_size": "0x0000F000", "main_thread_stack_size": "0x0000C000",
"main_thread_priority": 16, "main_thread_priority": 16,
"default_cpu_id": 3, "default_cpu_id": 3,
"process_category": 1, "process_category": 1,
@@ -31,6 +31,14 @@
"highest_cpu_id": 3 "highest_cpu_id": 3
} }
}, { }, {
"type": "map",
"value": {
"address": "0x70000000",
"is_ro": false,
"size": "0x00001000",
"is_io": true
}
}, {
"type": "map", "type": "map",
"value": { "value": {
"address": "0x60006000", "address": "0x60006000",

View File

@@ -24,13 +24,19 @@
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include <hocclk.h> #include <hocclk.h>
#include <switch.h> #include <switch.h>
#include <pwm.h> #include <pwm.h>
#include <registers.h> #include <registers.h>
#include <battery.h> #include <battery.h>
#include "display_refresh_rate.hpp" #include "../display/display_refresh_rate.hpp"
#include <rgltr.h> #include <rgltr.h>
#include <notification.h> #include <notification.h>
@@ -39,51 +45,65 @@
#include "board_load.hpp" #include "board_load.hpp"
#include "board_volt.hpp" #include "board_volt.hpp"
#include "board_misc.hpp" #include "board_misc.hpp"
#include "../soctherm.hpp" #include "../tsensor/soctherm.hpp"
#include "../integrations.hpp" #include "../tsensor/aotag.hpp"
#include "../file_utils.hpp" #include "../hos/integrations.hpp"
#include "../file/file_utils.hpp"
namespace board { namespace board {
u64 clkVirtAddr, dsiVirtAddr; u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr;
HocClkSocType gSocType; HocClkSocType gSocType;
u8 gDramID; u8 gDramID;
HocClkConsoleType gConsoleType = HocClkConsoleType_Iowa; HocClkConsoleType gConsoleType = HocClkConsoleType_Icosa;
FuseData fuseData; FuseData fuseData;
u8 speedoBracket; u8 speedoBracket;
PwmChannelSession iCon; PwmChannelSession iCon;
u32 fd = 0, fd2 = 0; u32 fd = 0, fd2 = 0;
#define PMC_BASE 0x7000E400
#define APB_MISC_GP_HIDREV 0x804
#define GP_HIDREV_MAJOR_T210 0x1
#define GP_HIDREV_MAJOR_T210B01 0x2
#define APB_BASE 0x70000000
#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x))
#define FUSE_OFFSET 0x800
void FetchHardwareInfos() { void FetchHardwareInfos() {
ReadFuses(fuseData); ReadFuses(fuseData, fuseVirtAddr);
SetGpuBracket(fuseData.gpuSpeedo, speedoBracket); SetGpuBracket(fuseData.gpuSpeedo, speedoBracket);
u64 sku = 0, dramID = 0; u32 hidrev = *(u32*)(apbVirtAddr + APB_MISC_GP_HIDREV);
Result rc = splInitialize(); if (((hidrev >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01) {
ASSERT_RESULT_OK(rc, "splInitialize"); gSocType = HocClkSocType_Mariko;
CacheGpuVoltTable();
rc = splGetConfig(SplConfigItem_HardwareType, &sku); } else {
ASSERT_RESULT_OK(rc, "splGetConfig"); gSocType = HocClkSocType_Erista;
rc = splGetConfig(SplConfigItem_DramId, &dramID);
ASSERT_RESULT_OK(rc, "splGetConfig");
gDramID = dramID;
splExit();
switch(sku) {
case 2 ... 5:
gSocType = HocClkSocType_Mariko;
break;
default:
gSocType = HocClkSocType_Erista;
} }
u32 odm4 = *(u32*)(fuseVirtAddr + FUSE_OFFSET + FUSE_RESERVED_ODMX(4));
if (gSocType == HocClkSocType_Mariko) { if (gSocType == HocClkSocType_Mariko) {
CacheGpuVoltTable(); switch ((odm4 & 0xF0000) >> 16) {
case 2:
gConsoleType = HocClkConsoleType_Hoag;
break;
case 4:
gConsoleType = HocClkConsoleType_Aula;
break;
case 1:
default:
gConsoleType = HocClkConsoleType_Iowa;
}
} else {
gConsoleType = HocClkConsoleType_Icosa;
} }
gConsoleType = static_cast<HocClkConsoleType>(sku); gDramID = (odm4 & 0xF8) >> 3;
// Get extended dram id info.
if (gSocType == HocClkSocType_Mariko) {
gDramID |= (odm4 & 0x7000) >> 7;
}
} }
/* TODO: Check for config */ /* TODO: Check for config */
@@ -115,6 +135,26 @@ namespace board {
rc = tmp451Initialize(); rc = tmp451Initialize();
ASSERT_RESULT_OK(rc, "tmp451Initialize"); ASSERT_RESULT_OK(rc, "tmp451Initialize");
rc = rgltrInitialize();
ASSERT_RESULT_OK(rc, "rgltrInitialize");
rc = pmdmntInitialize();
ASSERT_RESULT_OK(rc, "pmdmntInitialize");
rc = QueryMemoryMapping(&clkVirtAddr, 0x60006000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (clk)");
rc = QueryMemoryMapping(&dsiVirtAddr, 0x54300000, 0x40000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (dsi)");
rc = QueryMemoryMapping(&apbVirtAddr, 0x70000000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (apb)");
rc = QueryMemoryMapping(&fuseVirtAddr, 0x7000F000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (fuse)");
FetchHardwareInfos();
Result nvCheck = 1; Result nvCheck = 1;
if (R_SUCCEEDED(nvInitialize())) { if (R_SUCCEEDED(nvInitialize())) {
nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -127,18 +167,21 @@ namespace board {
} }
} }
rc = rgltrInitialize();
ASSERT_RESULT_OK(rc, "rgltrInitialize");
rc = pmdmntInitialize();
ASSERT_RESULT_OK(rc, "pmdmntInitialize");
StartLoad(nvCheck, fd); StartLoad(nvCheck, fd);
batteryInfoInitialize(); batteryInfoInitialize();
FetchHardwareInfos();
soctherm::Initialize(); tsensor::InitializeSoctherm(); // SOCTHERM must be init before AOTAG
// PMC exosphere check
SecmonArgs args = {};
args.X[0] = 0xF0000002;
args.X[1] = PMC_BASE;
svcCallSecureMonitor(&args);
if (args.X[1] != PMC_BASE) { // if param 1 is identical read failed
tsensor::InitializeAotag(GetSocType() == HocClkSocType_Mariko);
}
Result pwmCheck = 1; Result pwmCheck = 1;
if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) {
@@ -147,12 +190,6 @@ namespace board {
StartMiscThread(pwmCheck, &iCon); StartMiscThread(pwmCheck, &iCon);
rc = QueryMemoryMapping(&clkVirtAddr, 0x60006000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (clk)");
rc = QueryMemoryMapping(&dsiVirtAddr, 0x54300000, 0x40000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (dsi)");
display::DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr, .isLite = (GetConsoleType() == HocClkConsoleType_Hoag), .isRetroSUPER = integrations::GetRETROSuperStatus()}; display::DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr, .isLite = (GetConsoleType() == HocClkConsoleType_Hoag), .isRetroSUPER = integrations::GetRETROSuperStatus()};
display::Initialize(&cfg); display::Initialize(&cfg);
@@ -175,6 +212,7 @@ namespace board {
max17050Exit(); max17050Exit();
tmp451Exit(); tmp451Exit();
display::Shutdown();
ExitLoad(); ExitLoad();
@@ -185,7 +223,6 @@ namespace board {
rgltrExit(); rgltrExit();
batteryInfoExit(); batteryInfoExit();
pmdmntExit(); pmdmntExit();
display::Shutdown();
nvExit(); nvExit();
} }

View File

@@ -35,12 +35,18 @@
#include "board_sensor.hpp" #include "board_sensor.hpp"
#include "board_volt.hpp" #include "board_volt.hpp"
#include "board_profile.hpp" #include "board_profile.hpp"
#include "../mem_map.hpp" #include "../mapping/mem_map.hpp"
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0)) #define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
#define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0)) #define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0))
namespace board { namespace board {
extern u64 clkVirtAddr, dsiVirtAddr; extern u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr;
extern HocClkSocType gSocType;
extern u8 gDramID;
extern HocClkConsoleType gConsoleType;
extern FuseData fuseData;
extern u8 speedoBracket;
void Initialize(); void Initialize();
void Exit(); void Exit();
HocClkSocType GetSocType(); HocClkSocType GetSocType();

View File

@@ -26,15 +26,24 @@
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include "display_refresh_rate.hpp" #include <i2c.h>
#include "../i2c/i2cDrv.h"
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include "../display/display_refresh_rate.hpp"
#include "board.hpp" #include "board.hpp"
#include "board_name.hpp" #include "board_name.hpp"
#include "../errors.hpp" #include "../file/errors.hpp"
#include "pllmb.hpp" #include "../soc/pllmb.hpp"
#include "../config.hpp" #include "../file/config.hpp"
#include "../soc/gm20b.hpp"
namespace board { namespace board {
#define MIDDLE_FREQ_TABLE_START_POINT 1228800000
static u32 currentInjectedHz = 0;
PcvModule GetPcvModule(HocClkModule hocclkModule) { PcvModule GetPcvModule(HocClkModule hocclkModule) {
switch (hocclkModule) { switch (hocclkModule) {
case HocClkModule_CPU: case HocClkModule_CPU:
@@ -70,7 +79,6 @@ namespace board {
Result rc = 0; Result rc = 0;
bool usesGovenor = module > HocClkModule_MEM; bool usesGovenor = module > HocClkModule_MEM;
if (module == HocClkModule_Display) { if (module == HocClkModule_Display) {
display::SetRate(hz); display::SetRate(hz);
return; return;
@@ -80,27 +88,39 @@ namespace board {
return; return;
} }
bool useGm20b = (module == HocClkModule_GPU) && (GetSocType() == HocClkSocType_Mariko) && (hz % 38400000 == 0) && (hz % 76800000 != 0) && hz < MIDDLE_FREQ_TABLE_START_POINT;
u32 pcvHz = useGm20b ? ((hz + 76800000 - 1) / 76800000) * 76800000 : hz;
if (module == HocClkModule_GPU)
currentInjectedHz = 0;
if (HOSSVC_HAS_CLKRST) { if (HOSSVC_HAS_CLKRST) {
ClkrstSession session = {}; ClkrstSession session = {};
rc = clkrstOpenSession(&session, GetPcvModuleId(module), 3); rc = clkrstOpenSession(&session, GetPcvModuleId(module), 3);
ASSERT_RESULT_OK(rc, "clkrstOpenSession"); ASSERT_RESULT_OK(rc, "clkrstOpenSession");
ClkrstSetHz(session, hz); ClkrstSetHz(session, pcvHz);
/* Voltage bug workaround. */ /* Voltage bug workaround. */
if (module == HocClkModule_CPU) { if (module == HocClkModule_CPU) {
svcSleepThread(300'000); svcSleepThread(300'000);
ClkrstSetHz(session, hz); ClkrstSetHz(session, pcvHz);
} }
clkrstCloseSession(&session); clkrstCloseSession(&session);
} else { } else {
PcvSetHz(GetPcvModule(module), hz); PcvSetHz(GetPcvModule(module), pcvHz);
if (module == HocClkModule_CPU) { if (module == HocClkModule_CPU) {
svcSleepThread(300'000); svcSleepThread(300'000);
PcvSetHz(GetPcvModule(module), hz); PcvSetHz(GetPcvModule(module), pcvHz);
} }
} }
if (useGm20b) {
gm20b::setClock(hz / 1000);
currentInjectedHz = hz;
}
} }
u32 GetDisplayRate(u32 hz) { u32 GetDisplayRate(u32 hz) {
@@ -116,6 +136,10 @@ namespace board {
return GetDisplayRate(hz); return GetDisplayRate(hz);
} }
if (module == HocClkModule_GPU && currentInjectedHz != 0) {
return currentInjectedHz;
}
if (HOSSVC_HAS_CLKRST) { if (HOSSVC_HAS_CLKRST) {
ClkrstSession session = {}; ClkrstSession session = {};

View File

@@ -27,8 +27,14 @@
#pragma once #pragma once
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include "../errors.hpp" #include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include "../file/errors.hpp"
namespace board { namespace board {

View File

@@ -42,61 +42,19 @@ namespace board {
gpuBracket = 3; gpuBracket = 3;
} }
void ReadFuses(FuseData &speedo) { void ReadFuses(FuseData &speedo, u64 fuseVa) {
u64 pid = 0; constexpr u32 FuseOffset = 0x800;
constexpr u64 UsbID = 0x0100000000000006; u8 *fusePtr = reinterpret_cast<u8 *>(fuseVa) + FuseOffset;
if (R_FAILED(pmdmntGetProcessId(&pid, UsbID))) {
return;
}
Handle debug; speedo.cpuSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_SPEEDO_0_CALIB);
if (R_FAILED(svcDebugActiveProcess(&debug, pid))) { speedo.gpuSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_SPEEDO_2_CALIB);
return; speedo.socSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_SOC_SPEEDO_0_CALIB);
} speedo.cpuIDDQ = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_IDDQ_CALIB) * 4;
speedo.gpuIDDQ = *reinterpret_cast<u16 *>(fusePtr + FUSE_GPU_IDDQ_CALIB) * 5;
MemoryInfo mem_info = {}; speedo.socIDDQ = *reinterpret_cast<u16 *>(fusePtr + FUSE_SOC_IDDQ_CALIB) * 4;
u32 pageinfo = 0; speedo.waferX = *reinterpret_cast<s16 *>(fusePtr + FUSE_OPT_X_COORDINATE);
u64 addr = 0; speedo.waferY = *reinterpret_cast<s16 *>(fusePtr + FUSE_OPT_Y_COORDINATE);
speedo.waferX = (speedo.waferX & BIT(8)) ? (speedo.waferX - 512) : speedo.waferX;
u8 stack[0x10] = {};
const u8 compare[0x10] = {};
u8 dump[0x400] = {};
constexpr u64 PageSize = 0x1000;
while (true) {
if (R_FAILED(svcQueryDebugProcessMemory(&mem_info, &pageinfo, debug, addr)) || mem_info.addr < addr) {
break;
}
if (mem_info.type == MemType_Io && mem_info.size == PageSize) {
if (R_FAILED(svcReadDebugProcessMemory(stack, debug, mem_info.addr, sizeof(stack)))) {
break;
}
if (memcmp(stack, compare, sizeof(stack)) == 0) {
if (R_FAILED(svcReadDebugProcessMemory(dump, debug, mem_info.addr + 0x800, sizeof(dump)))) {
break;
}
speedo.cpuSpeedo = *reinterpret_cast<u16*>(dump + FUSE_CPU_SPEEDO_0_CALIB);
speedo.gpuSpeedo = *reinterpret_cast<u16*>(dump + FUSE_CPU_SPEEDO_2_CALIB);
speedo.socSpeedo = *reinterpret_cast<u16*>(dump + FUSE_SOC_SPEEDO_0_CALIB);
speedo.cpuIDDQ = *reinterpret_cast<u16*>(dump + FUSE_CPU_IDDQ_CALIB) * 4;
speedo.gpuIDDQ = *reinterpret_cast<u16*>(dump + FUSE_GPU_IDDQ_CALIB) * 5;
speedo.socIDDQ = *reinterpret_cast<u16*>(dump + FUSE_SOC_IDDQ_CALIB) * 4;
speedo.waferX = *reinterpret_cast<u16*>(dump + FUSE_OPT_X_COORDINATE);
speedo.waferY = *reinterpret_cast<u16*>(dump + FUSE_OPT_Y_COORDINATE);
svcCloseHandle(debug);
return;
}
}
addr = mem_info.addr + mem_info.size;
}
svcCloseHandle(debug);
} }
} }

View File

@@ -30,11 +30,11 @@ namespace board {
u16 gpuIDDQ; u16 gpuIDDQ;
u16 socIDDQ; u16 socIDDQ;
u16 waferX; s16 waferX;
u16 waferY; s16 waferY;
}; };
void ReadFuses(FuseData &speedo); void ReadFuses(FuseData &speedo, u64 fuseVa);
void SetGpuBracket(u16 gpuSpeedo, u8 &gpuBracket); void SetGpuBracket(u16 gpuSpeedo, u8 &gpuBracket);
} }

View File

@@ -26,7 +26,13 @@
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include <algorithm> #include <algorithm>
#include <math.h> #include <math.h>
#include <numeric> #include <numeric>

View File

@@ -26,7 +26,13 @@
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include "board.hpp" #include "board.hpp"
namespace board { namespace board {

View File

@@ -26,12 +26,22 @@
#include <hocclk.h> #include <hocclk.h>
#include <switch.h> #include <switch.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include "../i2c/i2cDrv.h"
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include <cmath> #include <cmath>
#include <battery.h> #include <battery.h>
#include <pwm.h> #include <pwm.h>
#include "board.hpp" #include "board.hpp"
#include "../soctherm.hpp" #include "../tsensor/soctherm.hpp"
#include "../tsensor/aotag.hpp"
#include "../tsensor/bq24193.hpp"
#include "../file/config.hpp"
namespace board { namespace board {
@@ -39,8 +49,8 @@ namespace board {
s32 millis = 0; s32 millis = 0;
BatteryChargeInfo info; BatteryChargeInfo info;
soctherm::TSensorTemps temps = {}; tsensor::TSensorTemps temps = {};
soctherm::ReadSensors(temps); tsensor::ReadTSensors(temps);
switch(sensor) { switch(sensor) {
case HocClkThermalSensor_SOC: { case HocClkThermalSensor_SOC: {
@@ -77,11 +87,24 @@ namespace board {
break; break;
} }
case HocClkThermalSensor_MEM: { case HocClkThermalSensor_MEM: {
millis = board::GetSocType() == HocClkSocType_Mariko ? temps.pllx : temps.mem; if (board::GetSocType() == HocClkSocType_Mariko && tsensor::IsInitialized() && tsensor::ReadAotag() > 0) {
millis = (temps.pllx * 0.10f) + (tsensor::ReadAotag() * 0.90f);
} else {
millis = board::GetSocType() == HocClkSocType_Mariko ? temps.pllx : temps.mem;
}
break; break;
} }
case HocClkThermalSensor_PLLX: { case HocClkThermalSensor_PLLX: {
millis = temps.pllx; millis = temps.pllx;
break;
}
case HocClkThermalSensor_BQ24193: {
millis = bq24193::getBQTemp();
break;
}
case HocClkThermalSensor_AO: {
millis = tsensor::ReadAotag();
break;
} }
default: { default: {
ASSERT_ENUM_VALID(HocClkThermalSensor, sensor); ASSERT_ENUM_VALID(HocClkThermalSensor, sensor);

View File

@@ -1,6 +1,8 @@
/* /*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
* *
* Copyright (c) B3711
*
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation. * version 2, as published by the Free Software Foundation.
@@ -25,11 +27,12 @@
#include "board.hpp" #include "board.hpp"
#include "board_freq.hpp" #include "board_freq.hpp"
#include "board_volt.hpp" #include "board_volt.hpp"
#include "../file_utils.hpp" #include "../file/file_utils.hpp"
namespace board { namespace board {
GpuVoltData voltData = {}; GpuVoltData voltData = {};
u32 cpuVoltTable[32] = {}; // 32LUT
u64 cldvfs; u64 cldvfs;
CpuDfllData cachedTune; CpuDfllData cachedTune;
@@ -257,7 +260,7 @@ namespace board {
rgltrGetVoltage(&session, &out); rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session); rgltrCloseSession(&session);
} else { } else {
out = GetVoltage(HocClkVoltage_EMCVDD2); out = GetVoltage(HocClkVoltage_EMCVDD2); // VDD2 and VDDQ are always connected to the same rail on Erista
} }
break; break;
case HocClkVoltage_Display: case HocClkVoltage_Display:
@@ -318,6 +321,7 @@ namespace board {
} }
void CacheGpuVoltTable() { void CacheGpuVoltTable() {
// Likely CPU regulator?
UnkRegulator reg = { UnkRegulator reg = {
.voltageMin = 600000, .voltageMin = 600000,
.voltageStep = 12500, .voltageStep = 12500,
@@ -371,14 +375,26 @@ namespace board {
/* Assuming mariko. */ /* Assuming mariko. */
const u32 vmax = 800; const u32 vmax = 800;
constexpr u32 VoltageTableOffset = 312; constexpr u32 GpuVoltageTableOffset = 312;
if (!std::memcmp(&buffer[index + VoltageTableOffset], &vmax, sizeof(vmax))) { if (!std::memcmp(&buffer[index + GpuVoltageTableOffset], &vmax, sizeof(vmax))) {
std::memcpy(voltData.voltTable, &buffer[index + VoltageTableOffset], sizeof(voltData.voltTable)); std::memcpy(voltData.voltTable, &buffer[index + GpuVoltageTableOffset], sizeof(voltData.voltTable));
voltData.voltTableAddress = base + memoryInfo.addr + VoltageTableOffset + index; voltData.voltTableAddress = base + memoryInfo.addr + GpuVoltageTableOffset + index;
} }
constexpr u32 CpuVoltageTableOffset = 0xB8;
std::memcpy(cpuVoltTable, &buffer[index + CpuVoltageTableOffset], sizeof(cpuVoltTable)); // TODO: verify the CPU table
svcCloseHandle(handle); svcCloseHandle(handle);
handle = INVALID_HANDLE; handle = INVALID_HANDLE;
// Print info AFTER we exit the handle to avoid hangs
for(int i = 0; i < (int)std::size(cpuVoltTable); ++i) {
fileUtils::LogLine("[dvfs] cpu volt %d: %u mV", i, cpuVoltTable[i]);
}
for(int i = 0; i < (int)std::size(voltData.voltTable); ++i) {
fileUtils::LogLine("[dvfs] gpu volt %d: %u mV", i, voltData.voltTable[i]);
}
return; return;
} }
} }
@@ -421,25 +437,42 @@ namespace board {
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) { u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) {
static const u32 ramTable[][22] = { static const u32 ramTable[][22] = {
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, }, { 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, }, // Bracket 0
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, }, { 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, }, // Bracket 1
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, }, { 2433, 2466, 2533, 2566, 2600, 2666, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, }, // Bracket 2
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }, { 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }, // Bracket 3
}; };
static const u32 gpuVoltArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, }; static const u32 gpuVoltArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, };
if (freqMhz <= 1600) { if (freqMhz <= 1600) return 0; // DVFS doesnt work below 1600MHz, it will just use vMin
return 0; if (bracket >= std::size(ramTable)) bracket = 0;
u32 bracketStart = ramTable[bracket][0];
u32 rampStartVolt = (bracket == 0) ? 535 : 525; // Do not touch!
u32 rampSpan = 590 - rampStartVolt;
if (freqMhz >= 1633 && freqMhz < bracketStart) {
u32 raw = rampStartVolt + ((freqMhz - 1633) * rampSpan) / (bracketStart - 1633);
u32 volt = ((raw + 2) / 5) * 5;
if (volt < rampStartVolt) volt = rampStartVolt;
if (volt > 590) volt = 590;
return volt;
} }
u32 baseVolt = gpuVoltArray[std::size(gpuVoltArray) - 1];
for (u32 i = 0; i < std::size(gpuVoltArray); ++i) { for (u32 i = 0; i < std::size(gpuVoltArray); ++i) {
if (freqMhz <= ramTable[bracket][i]) { if (freqMhz <= ramTable[bracket][i]) {
return gpuVoltArray[i]; baseVolt = gpuVoltArray[i];
break;
} }
} }
return gpuVoltArray[std::size(gpuVoltArray) - 1]; return baseVolt;
} }
} }

View File

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

View File

@@ -1,132 +0,0 @@
#include "pllmb.hpp"
namespace pllmb {
static const u8 qlin_hw_to_pdiv[17] = {
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 30, 32
};
enum pdiv_type {
PDIV_QLIN,
PDIV_POW2
};
struct pll_desc_t {
u32 base_offset;
u8 divm_shift;
u8 divm_width;
u8 divn_shift;
u8 divn_width;
u8 divp_shift;
u8 divp_width;
pdiv_type ptype;
};
static const pll_desc_t pll_table[] = {
{ PLLM_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLMB_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLP_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ PLLA_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ PLLU_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ _PLLD_BASE, 0, 8, 8, 8, 20, 5, PDIV_POW2 },
{ PLLX_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLA1_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLDP_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLD2_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLC4_BASE, 0, 8, 8, 8, 20, 5, PDIV_QLIN },
{ PLLRE_BASE, 0, 8, 8, 8, 16, 4, PDIV_QLIN },
{ PLLC_BASE, 0, 8, 10, 8, 20, 5, PDIV_QLIN },
{ PLLC2_BASE, 0, 8, 10, 8, 20, 5, PDIV_QLIN },
{ PLLC3_BASE, 0, 8, 10, 8, 20, 5, PDIV_QLIN },
};
static inline u32 clk_read32(u32 offset)
{
return *(volatile u32 *)(uintptr_t)(board::clkVirtAddr + offset);
}
static inline u32 extract(u32 val, u8 shift, u8 width)
{
return (val >> shift) & ((1u << width) - 1u);
}
static u64 pll_rate_from_desc(const pll_desc_t &pll, u64 osc_hz,
bool undivided)
{
u32 base = clk_read32(pll.base_offset);
u32 divm = extract(base, pll.divm_shift, pll.divm_width);
u32 divn = extract(base, pll.divn_shift, pll.divn_width);
if (divm == 0 || divn == 0)
return 0;
u64 vco = osc_hz * divn / divm;
if (undivided)
return vco;
u32 hw_p = extract(base, pll.divp_shift, pll.divp_width);
u32 pdiv;
if (pll.ptype == PDIV_QLIN)
pdiv = (hw_p < 17) ? qlin_hw_to_pdiv[hw_p] : 1;
else
pdiv = 1u << hw_p;
return vco / pdiv;
}
static u64 pll_rate_by_offset(u32 base_offset, u64 osc_hz,
bool undivided)
{
for (const auto &pll : pll_table) {
if (pll.base_offset == base_offset)
return pll_rate_from_desc(pll, osc_hz, undivided);
}
return 0;
}
u64 getRamClockRatePLLMB()
{
u32 clk_src = clk_read32(CLK_SOURCE_EMC);
u32 src = (clk_src >> 29) & 0x7;
u32 div = (clk_src >> 0) & 0xff;
u32 pll_off;
bool undivided = false;
switch (src) {
case EMC_SRC_PLLM:
pll_off = PLLM_BASE;
break;
case EMC_SRC_PLLM_UD:
pll_off = PLLM_BASE;
undivided = true;
break;
case EMC_SRC_PLLMB:
pll_off = PLLMB_BASE;
break;
case EMC_SRC_PLLMB_UD:
pll_off = PLLMB_BASE;
undivided = true;
break;
case EMC_SRC_PLLP:
pll_off = PLLP_BASE;
break;
case EMC_SRC_PLLP_UD:
pll_off = PLLP_BASE;
undivided = true;
break;
case EMC_SRC_PLLC:
pll_off = PLLC_BASE;
break;
case EMC_SRC_CLK_M:
return OSC_HZ;
default:
return 0;
}
u64 pll_hz = pll_rate_by_offset(pll_off, OSC_HZ, undivided);
return pll_hz / (div + 2) * 2;
}
}

View File

@@ -1,21 +0,0 @@
#pragma once
#include <cstdint>
#include <switch.h>
#include <hocclk.h>
#include "board.hpp"
#include <registers.h>
namespace pllmb {
typedef enum PLLSource {
EMC_SRC_PLLM = 0,
EMC_SRC_PLLC = 1,
EMC_SRC_PLLP = 2,
EMC_SRC_CLK_M = 3,
EMC_SRC_PLLM_UD = 4,
EMC_SRC_PLLMB_UD = 5,
EMC_SRC_PLLMB = 6,
EMC_SRC_PLLP_UD = 7
} PLLSource;
u64 getRamClockRatePLLMB();
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) Souldbminer
*
* Copyright (c) CtCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "aula.hpp"
#include "common.hpp"
// I *think* HOS changes this in some ways, so look into it more
namespace AulaDisplay {
#define MMIO_REG32(base, off) *(vu32 *)((base) + (off))
#define DSI(off) MMIO_REG32(board::dsiVirtAddr, (off) << 2u)
#define DSI_WR_DATA 0xA
#define DSI_TRIGGER 0x13
void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait) {
DSI(DSI_WR_DATA) = (param << 8) | cmd;
DSI(DSI_TRIGGER) = DSI_TRIGGER_HOST;
if (wait)
svcSleepThread(wait * 1000); // usleep-equivalant
}
void SetDisplayColorMode(AulaColorMode mode) {
if(mode == AulaDisplayColorMode_DoNotOverride)
return;
// send display command to change color mode.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM,
MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (mode << 8), 0);
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) Atmosphère-NX * Copyright (c) Souldbminer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -12,14 +12,12 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/ */
#define __ACCESS_TABLE_NAME__ EmcAccessTable2
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController2.GetAddress()
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc"
#include "secmon_define_access_table.inc" #include "../board/board.hpp"
#undef __ACCESS_TABLE_INC__ namespace AulaDisplay {
#undef __ACCESS_TABLE_ADDRESS__ void SetDisplayColorMode(AulaColorMode mode);
#undef __ACCESS_TABLE_NAME__ }

View File

@@ -0,0 +1,890 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DI_H_
#define _DI_H_
#define DSI_VIDEO_DISABLED 0
#define DSI_VIDEO_ENABLED 1
#define WINDOW_A 0
#define WINDOW_B 1
#define WINDOW_C 2
#define WINDOW_D 3
#ifndef BIT
#define BIT(n) (1U<<(n))
#endif
/*! Display registers. */
// All Display/DSI/MIPI register defines and macros are index based (not offset).
// DC_CMD/DC_COM/WINC Non-shadowed. DC_DISP/DC_WIN/DC_WINBUF Shadowed.
// Display controller scratch registers.
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_0 0xED
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_1 0xEE
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_0 0x16D
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_1 0x16E
#define DC_COM_SCRATCH_REGISTER_A 0x325
#define DC_COM_SCRATCH_REGISTER_B 0x326
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_0 0xBED
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_1 0xBEE
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_0 0xDED
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_1 0xDEE
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_0 0xFED
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_1 0xFEE
// DC_CMD non-shadowed command/sync registers.
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
#define SYNCPT_GENERAL_INDX(x) (((x) & 0xFF) << 0)
#define SYNCPT_GENERAL_COND(x) (((x) & 0xFF) << 8)
#define COND_REG_WR_SAFE 3
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
#define SYNCPT_CNTRL_SOFT_RESET BIT(0)
#define SYNCPT_CNTRL_NO_STALL BIT(8)
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
#define SYNCPT_VSYNC_INDX(x) (((x) & 0xFF) << 0)
#define SYNCPT_VSYNC_ENABLE BIT(8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
#define DC_CMD_DISPLAY_COMMAND 0x32
#define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
#define DISP_CTRL_MODE_MASK (3 << 5)
#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
#define PW0_ENABLE BIT(0)
#define PW1_ENABLE BIT(2)
#define PW2_ENABLE BIT(4)
#define PW3_ENABLE BIT(6)
#define PW4_ENABLE BIT(8)
#define PM0_ENABLE BIT(16)
#define PM1_ENABLE BIT(18)
#define DC_CMD_INT_STATUS 0x37
#define DC_CMD_INT_MASK 0x38
#define DC_CMD_INT_ENABLE 0x39
#define DC_CMD_INT_FRAME_END_INT BIT(1)
#define DC_CMD_INT_V_BLANK_INT BIT(2)
#define DC_CMD_INT_POLARITY 0x3B
#define DC_CMD_STATE_ACCESS 0x40
#define READ_MUX_ASSEMBLY 0x0
#define WRITE_MUX_ASSEMBLY 0x0
#define READ_MUX_ACTIVE BIT(0)
#define WRITE_MUX_ACTIVE BIT(2)
#define DC_CMD_STATE_CONTROL 0x41
#define GENERAL_ACT_REQ BIT(0)
#define WIN_ACT_REQ 1
#define WIN_A_ACT_REQ BIT(1)
#define WIN_B_ACT_REQ BIT(2)
#define WIN_C_ACT_REQ BIT(3)
#define WIN_D_ACT_REQ BIT(4)
#define CURSOR_ACT_REQ BIT(7)
#define GENERAL_UPDATE BIT(8)
#define WIN_UPDATE 9
#define WIN_A_UPDATE BIT(9)
#define WIN_B_UPDATE BIT(10)
#define WIN_C_UPDATE BIT(11)
#define WIN_D_UPDATE BIT(12)
#define CURSOR_UPDATE BIT(15)
#define NC_HOST_TRIG BIT(24)
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
#define WINDOW_SELECT 4
#define WINDOW_A_SELECT BIT(4)
#define WINDOW_B_SELECT BIT(5)
#define WINDOW_C_SELECT BIT(6)
#define WINDOW_D_SELECT BIT(7)
#define DC_CMD_REG_ACT_CONTROL 0x43
#define GENERAL_ACT_HCNTR_SEL BIT(0)
#define WIN_A_ACT_HCNTR_SEL BIT(2)
#define WIN_B_ACT_HCNTR_SEL BIT(4)
#define WIN_C_ACT_HCNTR_SEL BIT(6)
#define CURSOR_ACT_HCNTR_SEL BIT(7)
#define WIN_D_ACT_HCNTR_SEL BIT(10)
// DC_D_WIN_DD window D instance of DC_WIN
#define DC_D_WIN_DD_WIN_OPTIONS 0x80
#define DC_D_WIN_DD_COLOR_DEPTH 0x83
#define DC_D_WIN_DD_POSITION 0x84
#define DC_D_WIN_DD_SIZE 0x85
#define DC_D_WIN_DD_LINE_STRIDE 0x8A
#define DC_D_WIN_DD_BLEND_LAYER_CONTROL 0x96
#define DC_D_WIN_DD_BLEND_MATCH_SELECT 0x97
#define DC_D_WIN_DD_BLEND_ALPHA_1BIT 0x99
// DC_D_WINBUF_DD window D instance of DC_WINBUF
#define DC_D_WINBUF_DD_START_ADDR 0xC0
#define DC_D_WINBUF_DD_ADDR_H_OFFSET 0xC6
#define DC_D_WINBUF_DD_ADDR_V_OFFSET 0xC8
#define DC_D_WINBUF_DD_START_ADDR_HI 0xCD
#define DC_D_WINBUF_DD_MEMFETCH_CONTROL 0xEB
// DC_T_WIN_TD macro for using DD defines.
#define _DC_T(reg) ((reg) + 0x80)
// DC_COM non-shadowed registers.
#define DC_COM_CRC_CONTROL 0x300
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define LSC0_OUTPUT_POLARITY_LOW BIT(24)
// CMU registers.
#define DC_COM_CMU_CSC_KRR 0x32A
#define DC_COM_CMU_CSC_KGR 0x32B
#define DC_COM_CMU_CSC_KBR 0x32C
#define DC_COM_CMU_CSC_KRG 0x32D
#define DC_COM_CMU_CSC_KGG 0x32E
#define DC_COM_CMU_CSC_KBG 0x32F
#define DC_COM_CMU_CSC_KRB 0x330
#define DC_COM_CMU_CSC_KGB 0x331
#define DC_COM_CMU_CSC_KBB 0x332
#define DC_COM_CMU_LUT1 0x336
#define LUT1_ADDR(x) ((x) & 0xFF)
#define LUT1_DATA(x) (((x) & 0xFFF) << 16)
#define LUT1_READ_DATA(x) (((x) >> 16) & 0xFFF)
#define DC_COM_CMU_LUT2 0x337
#define LUT2_ADDR(x) ((x) & 0x3FF)
#define LUT2_DATA(x) (((x) & 0xFF) << 16)
#define LUT2_READ_DATA(x) (((x) >> 16) & 0xFF)
#define DC_COM_CMU_LUT1_READ 0x338
#define LUT1_READ_ADDR(x) (((x) & 0xFF) << 8)
#define LUT1_READ_EN BIT(0)
#define DC_COM_CMU_LUT2_READ 0x339
#define LUT2_READ_ADDR(x) (((x) & 0x3FF) << 8)
#define LUT2_READ_EN BIT(0)
#define DC_COM_DSC_TOP_CTL 0x33E
// DC_DISP shadowed registers.
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define CURSOR_ENABLE BIT(16)
#define SOR_ENABLE BIT(25)
#define SOR1_ENABLE BIT(26)
#define SOR1_TIMING_CYA BIT(27)
#define DSI_ENABLE BIT(29)
#define HDMI_ENABLE BIT(30)
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
#define VSYNC_H_POSITION(x) (((x) & 0x1FFF) << 0)
#define DC_DISP_REF_TO_SYNC 0x406
#define H_REF_TO_SYNC(x) (((x) & 0x1FFF) << 0) // Min 0 pixel clock.
#define V_REF_TO_SYNC(x) (((x) & 0x1FFF) << 16) // Min 1 line clock.
#define DC_DISP_SYNC_WIDTH 0x407
#define H_SYNC_WIDTH(x) (((x) & 0x1FFF) << 0) // Min 1 pixel clock.
#define V_SYNC_WIDTH(x) (((x) & 0x1FFF) << 16) // Min 1 line clock.
#define DC_DISP_BACK_PORCH 0x408
#define H_BACK_PORCH(x) (((x) & 0x1FFF) << 0)
#define V_BACK_PORCH(x) (((x) & 0x1FFF) << 16)
#define DC_DISP_ACTIVE 0x409
#define H_DISP_ACTIVE(x) (((x) & 0x1FFF) << 0) // Min 16 pixel clock.
#define V_DISP_ACTIVE(x) (((x) & 0x1FFF) << 16) // Min 16 line clock.
#define DC_DISP_FRONT_PORCH 0x40A
#define H_FRONT_PORCH(x) (((x) & 0x1FFF) << 0) // Min -=PS_=-H_REF_TO_SYNC + 1
#define V_FRONT_PORCH(x) (((x) & 0x1FFF) << 16) // Min -=PS_=-V_REF_TO_SYNC + 1
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xFF)
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
#define DISP_DATA_FORMAT_DF2S (4 << 0)
#define DISP_DATA_FORMAT_DF3S (5 << 0)
#define DISP_DATA_FORMAT_DFSPI (6 << 0)
#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
#define DISP_ALIGNMENT_MSB (0 << 8)
#define DISP_ALIGNMENT_LSB (1 << 8)
#define DISP_ORDER_RED_BLUE (0 << 9)
#define DISP_ORDER_BLUE_RED (1 << 9)
#define DC_DISP_DISP_COLOR_CONTROL 0x430
#define BASE_COLOR_SIZE_MASK (0xF << 0)
#define BASE_COLOR_SIZE_666 (0 << 0)
#define BASE_COLOR_SIZE_111 (1 << 0)
#define BASE_COLOR_SIZE_222 (2 << 0)
#define BASE_COLOR_SIZE_333 (3 << 0)
#define BASE_COLOR_SIZE_444 (4 << 0)
#define BASE_COLOR_SIZE_555 (5 << 0)
#define BASE_COLOR_SIZE_565 (6 << 0)
#define BASE_COLOR_SIZE_332 (7 << 0)
#define BASE_COLOR_SIZE_888 (8 << 0)
#define DITHER_CONTROL_MASK (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
#define DISP_COLOR_SWAP BIT(16)
#define BLANK_COLOR_WHITE BIT(17)
#define CMU_ENABLE BIT(20)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC0_H_QUALIFIER_NONE BIT(0)
#define SC1_H_QUALIFIER_NONE BIT(16)
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
#define DE_SELECT_ACTIVE (1 << 0)
#define DE_SELECT_ACTIVE_IS (2 << 0)
#define DE_CONTROL_ONECLK (0 << 2)
#define DE_CONTROL_NORMAL (1 << 2)
#define DE_CONTROL_EARLY_EXT (2 << 2)
#define DE_CONTROL_EARLY (3 << 2)
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
// Cursor configuration registers.
#define DC_DISP_CURSOR_FOREGROUND 0x43C
#define DC_DISP_CURSOR_BACKGROUND 0x43D
#define CURSOR_COLOR(r,g,b) (((r) & 0xFF) | (((g) & 0xFF) << 8) | (((b) & 0xFF) << 16))
#define DC_DISP_CURSOR_START_ADDR 0x43E
#define DC_DISP_CURSOR_START_ADDR_NS 0x43F
#define CURSOR_CLIPPING(w) ((w) << 28)
#define CURSOR_CLIP_WIN_A 1
#define CURSOR_CLIP_WIN_B 2
#define CURSOR_CLIP_WIN_C 3
#define CURSOR_SIZE_32 (0 << 24)
#define CURSOR_SIZE_64 (1 << 24)
#define CURSOR_SIZE_128 (2 << 24)
#define CURSOR_SIZE_256 (3 << 24)
#define DC_DISP_CURSOR_POSITION 0x440
#define DC_DISP_CURSOR_START_ADDR_HI 0x4EC
#define DC_DISP_CURSOR_START_ADDR_HI_NS 0x4ED
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4F1
#define CURSOR_BLEND_2BIT (0 << 24)
#define CURSOR_BLEND_R8G8B8A8 (1 << 24)
#define CURSOR_BLEND_SRC_FACTOR(n) ((n) << 8)
#define CURSOR_BLEND_DST_FACTOR(n) ((n) << 16)
#define CURSOR_BLEND_ZRO 0
#define CURSOR_BLEND_K1 1
#define CURSOR_BLEND_NK1 2
// End of cursor cfg regs.
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
#define DC_DISP_SD_BL_PARAMETERS 0x4D7
#define DC_DISP_SD_BL_CONTROL 0x4DC
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_DISP_DISPLAY_SPARE0 0x4F7 // Used by SW/HW.
#define DC_DISP_DISPLAY_SPARE1 0x4F8
#define DC_WINC_COLOR_PALETTE 0x500
#define COLOR_PALETTE_IDX(off) (DC_WINC_COLOR_PALETTE + (off))
#define COLOR_PALETTE_RGB(rgb) (byte_swap_32(rgb) >> 8)
#define DC_WINC_PALETTE_COLOR_EXT 0x600
#define DC_WINC_H_FILTER_P(p) (0x601 + (p))
#define DC_WINC_V_FILTER_P(p) (0x619 + (p))
#define DC_WINC_H_FILTER_HI_P(p) (0x629 + (p))
#define DC_WINC_CSC_YOF 0x611
#define DC_WINC_CSC_KYRGB 0x612
#define DC_WINC_CSC_KUR 0x613
#define DC_WINC_CSC_KVR 0x614
#define DC_WINC_CSC_KUG 0x615
#define DC_WINC_CSC_KVG 0x616
#define DC_WINC_CSC_KUB 0x617
#define DC_WINC_CSC_KVB 0x618
#define DC_WIN_AD_WIN_OPTIONS 0xB80
#define DC_WIN_BD_WIN_OPTIONS 0xD80
#define DC_WIN_CD_WIN_OPTIONS 0xF80
// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION BIT(0)
#define V_DIRECTION BIT(2)
#define SCAN_COLUMN BIT(4)
#define COLOR_EXPAND BIT(6)
#define H_FILTER_ENABLE BIT(8)
#define V_FILTER_ENABLE BIT(10)
#define COLOR_PALETTE_ENABLE BIT(16)
#define CSC_ENABLE BIT(18)
#define DV_ENABLE BIT(20)
#define WIN_ENABLE BIT(30)
#define H_FILTER_EXPAND BIT(31)
#define DC_WIN_BUFFER_CONTROL 0x702
#define BUFFER_CONTROL_HOST 0
#define BUFFER_CONTROL_VI 1
#define BUFFER_CONTROL_SB2D 4
#define DC_WIN_COLOR_DEPTH 0x703
#define WIN_COLOR_DEPTH_P1 0x0
#define WIN_COLOR_DEPTH_P2 0x1
#define WIN_COLOR_DEPTH_P4 0x2
#define WIN_COLOR_DEPTH_P8 0x3
#define WIN_COLOR_DEPTH_B4G4R4A4 0x4
#define WIN_COLOR_DEPTH_B5G5R5A 0x5
#define WIN_COLOR_DEPTH_B5G6R5 0x6
#define WIN_COLOR_DEPTH_AB5G5R5 0x7
#define WIN_COLOR_DEPTH_B8G8R8A8 0xC
#define WIN_COLOR_DEPTH_R8G8B8A8 0xD
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE
#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF
#define WIN_COLOR_DEPTH_YCbCr422 0x10
#define WIN_COLOR_DEPTH_YUV422 0x11
#define WIN_COLOR_DEPTH_YCbCr420P 0x12
#define WIN_COLOR_DEPTH_YUV420P 0x13
#define WIN_COLOR_DEPTH_YCbCr422P 0x14
#define WIN_COLOR_DEPTH_YUV422P 0x15
#define WIN_COLOR_DEPTH_YCbCr422R 0x16
#define WIN_COLOR_DEPTH_YUV422R 0x17
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
#define WIN_COLOR_DEPTH_YUV422RA 0x19
#define WIN_COLOR_DEPTH_X1R5G5B5 0x1E
#define WIN_COLOR_DEPTH_R5G5B5X1 0x1F
#define WIN_COLOR_DEPTH_X1B5G5R5 0x20
#define WIN_COLOR_DEPTH_B5G5R5X1 0x21
#define WIN_COLOR_DEPTH_YCbCr444P 0x29
#define WIN_COLOR_DEPTH_YCrCb420SP 0x2A
#define WIN_COLOR_DEPTH_YCbCr420SP 0x2B
#define WIN_COLOR_DEPTH_YCrCb422SP 0x2C
#define WIN_COLOR_DEPTH_YCbCr422SP 0x2D
#define WIN_COLOR_DEPTH_YUV444P 0x34
#define WIN_COLOR_DEPTH_YVU420SP 0x35
#define WIN_COLOR_DEPTH_YUV420SP 0x36
#define WIN_COLOR_DEPTH_YVU422SP 0x37
#define WIN_COLOR_DEPTH_YUV422SP 0x38
#define WIN_COLOR_DEPTH_YVU444SP 0x3B
#define WIN_COLOR_DEPTH_YUV444SP 0x3C
#define DC_WIN_POSITION 0x704
#define H_POSITION(x) (((x) & 0xFFFF) << 0) // Support negative.
#define V_POSITION(x) (((x) & 0xFFFF) << 16) // Support negative.
#define DC_WIN_SIZE 0x705
#define H_SIZE(x) (((x) & 0x1FFF) << 0)
#define V_SIZE(x) (((x) & 0x1FFF) << 16)
#define DC_WIN_PRESCALED_SIZE 0x706
#define H_PRESCALED_SIZE(x) (((x) & 0x7FFF) << 0)
#define V_PRESCALED_SIZE(x) (((x) & 0x1FFF) << 16)
#define DC_WIN_H_INITIAL_DDA 0x707
#define DC_WIN_V_INITIAL_DDA 0x708
#define DC_WIN_DDA_INC 0x709
#define H_DDA_INC(x) (((x) & 0xFFFF) << 0)
#define V_DDA_INC(x) (((x) & 0xFFFF) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xFFFF) << 16)
#define DC_WIN_DV_CONTROL 0x70E
#define DV_CTRL_R(r) (((r) & 7) << 16)
#define DV_CTRL_G(g) (((g) & 7) << 8)
#define DV_CTRL_B(b) (((b) & 7) << 0)
#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
#define WIN_BLEND_DEPTH(x) (((x) & 0xFF) << 0)
#define WIN_K1(x) (((x) & 0xFF) << 8)
#define WIN_K2(x) (((x) & 0xFF) << 16)
#define WIN_BLEND_ENABLE (0 << 24)
#define WIN_BLEND_BYPASS (1 << 24)
#define DC_WINBUF_BLEND_MATCH_SELECT 0x717
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ZERO (0 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ONE (1 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 (2 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_DST (3 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (4 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_SRC (5 << 0)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ZERO (0 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ONE (1 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1 (2 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K2 (3 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1_TIMES_DST (4 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (5 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_SRC (6 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1 (7 << 4)
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_ZERO (0 << 8)
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K1 (1 << 8)
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 (2 << 8)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO (0 << 12)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ONE (1 << 12)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_NEG_K1_TIMES_SRC (2 << 12)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_K2 (3 << 12)
#define DC_WINBUF_BLEND_ALPHA_1BIT 0x719
#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xFF) << 0)
#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xFF) << 8)
/*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
#define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808
#define DC_WINBUF_SURFACE_KIND 0x80B
#define PITCH (0 << 0)
#define TILED (1 << 0)
#define BLOCK (2 << 0)
#define BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
#define DC_WINBUF_MEMFETCH_CONTROL 0x82B
/* Scratch register to store DCS backlight level (custom). */
#define DC_DCS_BACKLIGHT_LEVEL DC_COM_SCRATCH_REGISTER_B
/*! Display serial interface registers. */
#define DSI_INCR_SYNCPT_CNTRL 0x1
#define DSI_INCR_SYNCPT_SOFT_RESET BIT(0)
#define DSI_INCR_SYNCPT_NO_STALL BIT(8)
#define DSI_RD_DATA 0x9
#define DSI_WR_DATA 0xA
#define DSI_POWER_CONTROL 0xB
#define DSI_POWER_CONTROL_ENABLE 1
#define DSI_INT_ENABLE 0xC
#define DSI_INT_STATUS 0xD
#define DSI_INT_MASK 0xE
#define DSI_HOST_CONTROL 0xF
#define DSI_HOST_CONTROL_ECC BIT(0)
#define DSI_HOST_CONTROL_CS BIT(1)
#define DSI_HOST_CONTROL_PKT_BTA BIT(2)
#define DSI_HOST_CONTROL_IMM_BTA BIT(3)
#define DSI_HOST_CONTROL_FIFO_SEL BIT(4)
#define DSI_HOST_CONTROL_HS BIT(5)
#define DSI_HOST_CONTROL_RAW BIT(6)
#define DSI_HOST_CONTROL_TX_TRIG_MASK (3 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
#define DSI_HOST_CONTROL_CRC_RESET BIT(20)
#define DSI_HOST_CONTROL_FIFO_RESET BIT(21)
#define DSI_CONTROL 0x10
#define DSI_CONTROL_HOST_ENABLE BIT(0)
#define DSI_CONTROL_VIDEO_ENABLE BIT(1)
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
#define DSI_CONTROL_DCS_ENABLE BIT(3)
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
#define DSI_CONTROL_HS_CLK_CTRL BIT(20)
#define DSI_SOL_DELAY 0x11
#define DSI_MAX_THRESHOLD 0x12
#define DSI_TRIGGER 0x13
#define DSI_TRIGGER_VIDEO BIT(0)
#define DSI_TRIGGER_HOST BIT(1)
#define DSI_TX_CRC 0x14
#define DSI_STATUS 0x15
#define DSI_STATUS_RX_FIFO_SIZE 0x1F
#define DSI_STATUS_TX_FIFO_SIZE 0x20 // Actual depth is 64.
#define DSI_INIT_SEQ_CONTROL 0x1A
#define DSI_INIT_SEQ_DATA_0 0x1B
#define DSI_INIT_SEQ_DATA_1 0x1C
#define DSI_INIT_SEQ_DATA_2 0x1D
#define DSI_INIT_SEQ_DATA_3 0x1E
#define DSI_PKT_SEQ_0_LO 0x23
#define DSI_PKT_SEQ_0_HI 0x24
#define DSI_PKT_SEQ_1_LO 0x25
#define DSI_PKT_SEQ_1_HI 0x26
#define DSI_PKT_SEQ_2_LO 0x27
#define DSI_PKT_SEQ_2_HI 0x28
#define DSI_PKT_SEQ_3_LO 0x29
#define DSI_PKT_SEQ_3_HI 0x2A
#define DSI_PKT_SEQ_4_LO 0x2B
#define DSI_PKT_SEQ_4_HI 0x2C
#define DSI_PKT_SEQ_5_LO 0x2D
#define DSI_PKT_SEQ_5_HI 0x2E
#define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37
#define PKT0_LEN(x) (((x) & 0xFFFF) << 0)
#define PKT1_LEN(x) (((x) & 0xFFFF) << 16)
#define DSI_PHY_TIMING_0 0x3C
#define DSI_PHY_TIMING_1 0x3D
#define DSI_PHY_TIMING_2 0x3E
#define DSI_BTA_TIMING 0x3F
#define DSI_TIMEOUT_0 0x44
#define DSI_TIMEOUT_HTX(x) (((x) & 0xFFFF) << 0)
#define DSI_TIMEOUT_LRX(x) (((x) & 0xFFFF) << 16)
#define DSI_TIMEOUT_1 0x45
#define DSI_TIMEOUT_TA(x) (((x) & 0xFFFF) << 0)
#define DSI_TIMEOUT_PR(x) (((x) & 0xFFFF) << 16)
#define DSI_TO_TALLY 0x46
#define DSI_PAD_CONTROL_0 0x4B
#define DSI_PAD_CONTROL_VS1_PDIO_CLK BIT(8)
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xF) << 0)
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK BIT(24)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xF) << 16)
#define DSI_PAD_CONTROL_CD 0x4C
#define DSI_VIDEO_MODE_CONTROL 0x4E
#define DSI_CMD_PKT_VID_ENABLE 1
#define DSI_DSI_LINE_TYPE(x) ((x) << 1)
#define DSI_PAD_CONTROL_1 0x4F
#define DSI_PAD_CONTROL_2 0x50
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_CONTROL_4 0x52
#define DSI_PAD_CONTROL_5_B01 0x53
#define DSI_PAD_CONTROL_6_B01 0x54
#define DSI_PAD_CONTROL_7_B01 0x55
#define DSI_INIT_SEQ_DATA_15 0x5F
#define DSI_INIT_SEQ_DATA_15_B01 0x62
/*! DSI packet defines */
#define DSI_ESCAPE_CMD 0x87
#define DSI_ACK_NO_ERR 0x84
#define ACK_ERROR_RES 0x02
#define GEN_LONG_RD_RES 0x1A
#define DCS_LONG_RD_RES 0x1C
#define GEN_1_BYTE_SHORT_RD_RES 0x11
#define DCS_1_BYTE_SHORT_RD_RES 0x21
#define GEN_2_BYTE_SHORT_RD_RES 0x12
#define DCS_2_BYTE_SHORT_RD_RES 0x22
/*! MIPI registers. */
#define MIPI_CAL_MIPI_CAL_CTRL (0x00 / 0x4)
#define MIPI_CAL_CIL_MIPI_CAL_STATUS (0x08 / 0x4)
#define MIPI_CAL_CILA_MIPI_CAL_CONFIG (0x14 / 0x4)
#define MIPI_CAL_CILB_MIPI_CAL_CONFIG (0x18 / 0x4)
#define MIPI_CAL_CILC_MIPI_CAL_CONFIG (0x1C / 0x4)
#define MIPI_CAL_CILD_MIPI_CAL_CONFIG (0x20 / 0x4)
#define MIPI_CAL_CILE_MIPI_CAL_CONFIG (0x24 / 0x4)
#define MIPI_CAL_CILF_MIPI_CAL_CONFIG (0x28 / 0x4)
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG (0x38 / 0x4)
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG (0x3C / 0x4)
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG (0x40 / 0x4)
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG (0x44 / 0x4)
#define MIPI_CAL_MIPI_BIAS_PAD_CFG0 (0x58 / 0x4)
#define MIPI_CAL_MIPI_BIAS_PAD_CFG1 (0x5C / 0x4)
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 (0x60 / 0x4)
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2 (0x64 / 0x4)
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2 (0x68 / 0x4)
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2 (0x70 / 0x4)
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG_2 (0x74 / 0x4)
/*! MIPI CMDs. */
#define MIPI_DSI_V_SYNC_START 0x01
#define MIPI_DSI_COLOR_MODE_OFF 0x02
#define MIPI_DSI_END_OF_TRANSMISSION 0x08
#define MIPI_DSI_NULL_PACKET 0x09
#define MIPI_DSI_V_SYNC_END 0x11
#define MIPI_DSI_COLOR_MODE_ON 0x12
#define MIPI_DSI_BLANKING_PACKET 0x19
#define MIPI_DSI_H_SYNC_START 0x21
#define MIPI_DSI_SHUTDOWN_PERIPHERAL 0x22
#define MIPI_DSI_H_SYNC_END 0x31
#define MIPI_DSI_TURN_ON_PERIPHERAL 0x32
#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37
#define MIPI_DSI_DCS_SHORT_WRITE 0x05
#define MIPI_DSI_DCS_READ 0x06
#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15
#define MIPI_DSI_DCS_LONG_WRITE 0x39
#define MIPI_DSI_GENERIC_LONG_WRITE 0x29
#define MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM 0x03
#define MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM 0x13
#define MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23
#define MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM 0x04
#define MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM 0x14
#define MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM 0x24
/*! MIPI DCS CMDs. */
#define MIPI_DCS_NOP 0x00
#define MIPI_DCS_SOFT_RESET 0x01
#define MIPI_DCS_GET_COMPRESSION_MODE 0x03
#define MIPI_DCS_GET_DISPLAY_ID 0x04
#define MIPI_DCS_GET_DISPLAY_ID1 0xDA // GET_DISPLAY_ID Byte0, Module Manufacturer ID.
#define MIPI_DCS_GET_DISPLAY_ID2 0xDB // GET_DISPLAY_ID Byte1, Module/Driver Version ID.
#define MIPI_DCS_GET_DISPLAY_ID3 0xDC // GET_DISPLAY_ID Byte2, Module/Driver ID.
#define MIPI_DCS_GET_NUM_ERRORS 0x05 // 1 byte.
#define MIPI_DCS_GET_RED_CHANNEL 0x06
#define MIPI_DCS_GET_GREEN_CHANNEL 0x07
#define MIPI_DCS_GET_BLUE_CHANNEL 0x08
#define MIPI_DCS_GET_DISPLAY_STATUS 0x09 // 4 bytes.
#define MIPI_DCS_GET_POWER_MODE 0x0A // 1 byte. 2: DISON, 3: NORON, 4: SLPOUT, 7: BSTON.
#define MIPI_DCS_GET_ADDRESS_MODE 0x0B // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
#define MIPI_DCS_GET_PIXEL_FORMAT 0x0C // 1 byte. 4-6: DPI.
#define MIPI_DCS_GET_DISPLAY_MODE 0x0D // 1 byte. 0-2: GCS, 3: ALLPOFF, 4: ALLPON, 5: INVON.
#define MIPI_DCS_GET_SIGNAL_MODE 0x0E // 1 byte. 0: EODSI, 2: DEON, 3: PCLKON, 4: VSON, 5: HSON, 7: TEON.
#define MIPI_DCS_GET_DIAGNOSTIC_RESULT 0x0F // 1 byte. 6: FUNDT, 7: REGLD.
#define MIPI_DCS_ENTER_SLEEP_MODE 0x10
#define MIPI_DCS_EXIT_SLEEP_MODE 0x11
#define MIPI_DCS_ENTER_PARTIAL_MODE 0x12
#define MIPI_DCS_ENTER_NORMAL_MODE 0x13
#define MIPI_DCS_EXIT_INVERT_MODE 0x20
#define MIPI_DCS_ENTER_INVERT_MODE 0x21
#define MIPI_DCS_ALL_PIXELS_OFF 0x22
#define MIPI_DCS_ALL_PIXELS_ON 0x23
#define MIPI_DCS_SET_CONTRAST 0x25 // VCON in 40mV steps. 7-bit integer.
#define MIPI_DCS_SET_GAMMA_CURVE 0x26 // 1 byte. 0-7: GC.
#define MIPI_DCS_SET_DISPLAY_OFF 0x28
#define MIPI_DCS_SET_DISPLAY_ON 0x29
#define MIPI_DCS_SET_COLUMN_ADDRESS 0x2A
#define MIPI_DCS_SET_PAGE_ADDRESS 0x2B
#define MIPI_DCS_WRITE_MEMORY_START 0x2C
#define MIPI_DCS_WRITE_LUT 0x2D // 24-bit: 192 bytes.
#define MIPI_DCS_READ_MEMORY_START 0x2E
#define MIPI_DCS_SET_PARTIAL_ROWS 0x30
#define MIPI_DCS_SET_PARTIAL_COLUMNS 0x31
#define MIPI_DCS_SET_SCROLL_AREA 0x33
#define MIPI_DCS_SET_TEAR_OFF 0x34
#define MIPI_DCS_SET_TEAR_ON 0x35
#define MIPI_DCS_SET_ADDRESS_MODE 0x36 // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
#define MIPI_DCS_SET_SCROLL_START 0x37
#define MIPI_DCS_EXIT_IDLE_MODE 0x38
#define MIPI_DCS_ENTER_IDLE_MODE 0x39
#define MIPI_DCS_SET_PIXEL_FORMAT 0x3A // 1 byte. 4-6: DPI.
#define MIPI_DCS_WRITE_MEMORY_CONTINUE 0x3C
#define MIPI_DCS_READ_MEMORY_CONTINUE 0x3E
#define MIPI_DCS_GET_3D_CONTROL 0x3F
#define MIPI_DCS_SET_VSYNC_TIMING 0x40
#define MIPI_DCS_SET_TEAR_SCANLINE 0x44
#define MIPI_DCS_GET_SCANLINE 0x45
#define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46
#define MIPI_DCS_GET_SCANLINE_WIDTH 0x47
#define MIPI_DSI_AREA_COLOR_MODE 0x4C
#define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. 1 byte. 0-7: DBV.
#define MIPI_DCS_GET_BRIGHTNESS 0x52 // 1 byte. 0-7: DBV.
#define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
#define MIPI_DCS_GET_CONTROL_DISPLAY 0x54 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
#define MIPI_DCS_SET_CABC_VALUE 0x55 // 1 byte. 0-32: C, 4-7: C.
#define MIPI_DCS_GET_CABC_VALUE 0x56 // 1 byte. 0-32: C, 4-7: C.
#define MIPI_DCS_SET_CABC_MIN_BRI 0x5E // 1 byte. 0-7: CMB.
#define MIPI_DCS_GET_CABC_MIN_BRI 0x5F // 1 byte. 0-7: CMB.
#define MIPI_DCS_GET_AUTO_BRI_DIAG_RES 0x68 // 1 byte. 6-7: D.
#define MIPI_DCS_READ_DDB_START 0xA1
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
/*! MIPI DCS Panel Private CMDs. */
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0 // 43 bytes.
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0
#define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 // OLED backlight tuning. Byte7: PWM transition time in frames.
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
#define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands.
#define MIPI_DCS_PRIV_UNK_BD 0xBD
#define MIPI_DCS_PRIV_UNK_D5 0xD5
#define MIPI_DCS_PRIV_UNK_D6 0xD6
#define MIPI_DCS_PRIV_UNK_D8 0xD8
#define MIPI_DCS_PRIV_UNK_D9 0xD9
#define MIPI_DCS_PRIV_SM_DISPLAY_ID 0xDD
// LVL1 LVL2 LVL3 UNK0 UNK1
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Lock/Unlock: A5/5A. LVL1 group is normal registers.
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
#define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE.
/*! MIPI DCS Panel Private CMDs PAGE 1. */
#define MIPI_DCS_PRIV_GET_DISPLAY_ID4 0x00
#define MIPI_DCS_PRIV_GET_DISPLAY_ID5 0x01
#define MIPI_DCS_PRIV_GET_DISPLAY_ID6 0x02
/*! MIPI DCS CMD Defines. */
#define DCS_POWER_MODE_DISPLAY_ON BIT(2)
#define DCS_POWER_MODE_NORMAL_MODE BIT(3)
#define DCS_POWER_MODE_SLEEP_MODE BIT(4)
#define DCS_POWER_MODE_PARTIAL_MODE BIT(5)
#define DCS_POWER_MODE_IDLE_MODE BIT(6)
#define DCS_ADDRESS_MODE_V_FLIP BIT(0)
#define DCS_ADDRESS_MODE_H_FLIP BIT(1)
#define DCS_ADDRESS_MODE_LATCH_RL BIT(2) // Latch Data Order.
#define DCS_ADDRESS_MODE_BGR_COLOR BIT(3)
#define DCS_ADDRESS_MODE_LINE_ORDER BIT(4) // Line Refresh Order.
#define DCS_ADDRESS_MODE_SWAP_XY BIT(5) // Page/Column Addressing Reverse Order.
#define DCS_ADDRESS_MODE_MIRROR_X BIT(6) // Column Address Order.
#define DCS_ADDRESS_MODE_MIRROR_Y BIT(7) // Page Address Order.
#define DCS_ADDRESS_MODE_ROTATION_MASK (0xF << 4)
#define DCS_ADDRESS_MODE_ROTATION_90 (DCS_ADDRESS_MODE_SWAP_XY | DCS_ADDRESS_MODE_LINE_ORDER)
#define DCS_ADDRESS_MODE_ROTATION_180 (DCS_ADDRESS_MODE_MIRROR_X | DCS_ADDRESS_MODE_LINE_ORDER)
#define DCS_ADDRESS_MODE_ROTATION_270 (DCS_ADDRESS_MODE_SWAP_XY)
#define DCS_GAMMA_CURVE_NONE 0
#define DCS_GAMMA_CURVE_GC0_1_8 BIT(0)
#define DCS_GAMMA_CURVE_GC1_2_5 BIT(1)
#define DCS_GAMMA_CURVE_GC2_1_0 BIT(2)
#define DCS_GAMMA_CURVE_GC3_1_0 BIT(3) // Are there more?
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2)
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) // Transition fading.
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
#define DCS_CONTROL_DISPLAY_HBM_CTRL0 BIT(6)
#define DCS_CONTROL_DISPLAY_HBM_CTRL1 BIT(7)
#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Based on Vivid but over-saturated.
#define DCS_SM_COLOR_MODE_WASHED 0x45
#define DCS_SM_COLOR_MODE_BASIC 0x03 // Real natural profile.
#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on.
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural.. Extra saturation.
#define DCS_SM_COLOR_MODE_VIVID 0x65 // Saturated.
#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on Washed Out.
#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on Basic.
#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on Natural.
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on Vivid.
#define DCS_SM_COLOR_MODE_ENABLE BIT(0)
#define PANEL_SM_BL_CANDELA_MAX 2047
/* Switch Panels:
*
* 6.2" panels for Icosa and Iowa SKUs:
* [10] 81 [26]: JDI LPM062M326A
* [10] 96 [09]: JDI LAM062M109A
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
* [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
* [20] 96 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
* [20] 97 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
* [20] 98 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
* [20] 99 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
* [30] 93 [0F]: AUO A062TAN00 (59.06A33.000)
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
* [30] 97 [0F]: AUO A062TAN02 (59.06A33.002) [From photo of assumed same panel]
* [30] 98 [0F]: AUO A062TAN0? [UNCONFIRMED MODEL]
* [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID]
*
*
* 5.5" panels for Hoag SKU:
* [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1) (6203B001P4000)
* [20] 95 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV]
* [20] 96 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV]
* [30] 93 [10]: AUO A055TAN01 (59.05A30.001)
* [30] 94 [10]: AUO A055TAN02 (59.05A30.002)
* [30] 95 [10]: AUO A055TAN03 (59.05A30.003)
* [40] 94 [10]: Sharp LQ055T1SW10 (Rev P)
*
*
* 7.0" OLED panels for Aula SKU:
* [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
*/
/* Display ID Decoding:
*
* byte0: Vendor
* byte1: Model
* byte2: Board
*
* Vendors:
* 10h: Japan Display Inc.
* 20h: InnoLux Corporation
* 30h: AU Optronics
* 40h: Sharp
* 50h: Samsung
*
* Boards, Panel Size:
* 0Fh: Icosa/Iowa, 6.2"
* 10h: Hoag, 5.5"
* 20h: Aula, 7.0"
*/
// void display_init();
// void display_backlight_pwm_init();
// void display_end();
// /*! Interrupt management. */
// void display_enable_interrupt(u32 intr);
// void display_disable_interrupt(u32 intr);
// void display_wait_interrupt(u32 intr);
// /*! Get/Set Display panel ID. */
// u32 display_get_verbose_panel_id();
// u16 display_get_decoded_panel_id();
// void display_set_decoded_panel_id(u32 id);
// /*! MIPI DCS register management */
// int display_dsi_read(u8 cmd, u32 len, void *data);
// int display_dsi_vblank_read(u8 cmd, u32 len, void *data);
// void display_dsi_write(u8 cmd, u32 len, void *data);
// void display_dsi_vblank_write(u8 cmd, u32 len, void *data);
// /*! Show one single color on the display. */
// void display_color_screen(u32 color);
// /*! Screen backlight ON/OFF or set via duty and fading. */
// void display_backlight(bool enable);
// void display_backlight_brightness(u32 brightness, u32 step_delay);
// u32 *display_init_window_a_pitch();
// u32 *display_init_window_a_pitch_vic();
// u32 *display_init_window_a_pitch_inv();
// u32 *display_init_window_a_block();
// u32 *display_init_window_d_console();
// void display_window_disable(u32 window);
// void display_set_framebuffer(u32 window, void *fb);
// void display_move_framebuffer(u32 window, void *fb);
// void display_window_d_console_enable();
// void display_window_d_console_disable();
// void display_cursor_init(void *crs_fb, u32 size);
// void display_cursor_set_pos(u32 x, u32 y);
// void display_cursor_deinit();
#endif

View File

@@ -37,8 +37,14 @@
#include <atomic> #include <atomic>
#include <initializer_list> #include <initializer_list>
#include <minIni.h> #include <minIni.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include "board/board.hpp" #include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include "../board/board.hpp"
#include "errors.hpp" #include "errors.hpp"
#include "file_utils.hpp" #include "file_utils.hpp"

View File

@@ -25,7 +25,13 @@
*/ */
#include "file_utils.hpp" #include "file_utils.hpp"
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
extern "C" void __libnx_init_time(void); extern "C" void __libnx_init_time(void);

View File

@@ -16,10 +16,11 @@
*/ */
#include "kip.hpp" #include "kip.hpp"
#include "board/board.hpp" #include "../i2c/i2cDrv.h"
#include "../board/board.hpp"
#include "file_utils.hpp" #include "file_utils.hpp"
#include "../mgr/clock_manager.hpp"
#define CUST_REV 2
namespace kip { namespace kip {
bool kipAvailable = false; bool kipAvailable = false;
@@ -52,13 +53,20 @@ namespace kip {
return; return;
} }
// if(cust_get_cust_rev(&table) != CUST_REV) { u32 custRev = cust_get_cust_rev(&table);
// fileUtils::LogLine("Revision: %u", cust_get_cust_rev(&table)); u32 kipVersion = cust_get_kip_version(&table);
// notification::writeNotification("Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC"); if (custRev < CUST_REV || kipVersion < KIP_VERSION) {
// return; notification::writeNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC");
// } fileUtils::LogLine("Cust revision: %u", custRev);
fileUtils::LogLine("Kip version: %u", kipVersion);
return;
} else if (custRev > CUST_REV || kipVersion > KIP_VERSION) {
notification::writeNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC");
fileUtils::LogLine("Cust revision: %u", custRev);
fileUtils::LogLine("Kip version: %u", kipVersion);
return;
}
CUST_WRITE_FIELD_BATCH(&table, custRev, config::GetConfigValue(KipConfigValue_custRev));
// CUST_WRITE_FIELD_BATCH(&table, mtcConf, config::GetConfigValue(KipConfigValue_mtcConf)); // CUST_WRITE_FIELD_BATCH(&table, mtcConf, config::GetConfigValue(KipConfigValue_mtcConf));
CUST_WRITE_FIELD_BATCH(&table, hpMode, config::GetConfigValue(KipConfigValue_hpMode)); CUST_WRITE_FIELD_BATCH(&table, hpMode, config::GetConfigValue(KipConfigValue_hpMode));
@@ -68,7 +76,8 @@ namespace kip {
CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock2)); CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock2));
CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, config::GetConfigValue(KipConfigValue_marikoEmcMaxClock)); CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, config::GetConfigValue(KipConfigValue_marikoEmcMaxClock));
CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt)); CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt));
CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, config::GetConfigValue(KipConfigValue_emcDvbShift)); CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, config::GetConfigValue(KipConfigValue_emcDvbShift) > 8 && config::GetConfigValue(KipConfigValue_emcDvbShift) <= 16 ? 8 : config::GetConfigValue(KipConfigValue_emcDvbShift)); // 2.2.0 -> 2.3.0 compat
CUST_WRITE_FIELD_BATCH(&table, marikoSocVmax, config::GetConfigValue(KipConfigValue_marikoSocVmax));
CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, config::GetConfigValue(KipConfigValue_t1_tRCD)); CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, config::GetConfigValue(KipConfigValue_t1_tRCD));
CUST_WRITE_FIELD_BATCH(&table, t2_tRP, config::GetConfigValue(KipConfigValue_t2_tRP)); CUST_WRITE_FIELD_BATCH(&table, t2_tRP, config::GetConfigValue(KipConfigValue_t2_tRP));
@@ -160,139 +169,149 @@ namespace kip {
void GetKipData() void GetKipData()
{ {
FILE* fp; FILE* fp;
if (config::Refresh()) { fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r");
fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r");
if (fp == NULL) { if (fp == NULL) {
notification::writeNotification("Horizon OC\nKip opening failed"); notification::writeNotification("Horizon OC\nKip opening failed");
kipAvailable = false; kipAvailable = false;
return; return;
} else { } else {
kipAvailable = true; kipAvailable = true;
fclose(fp); fclose(fp);
} }
HocClkConfigValueList configValues; HocClkConfigValueList configValues;
config::GetConfigValues(&configValues); config::GetConfigValues(&configValues);
CustomizeTable table; CustomizeTable table;
if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) { if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) {
fileUtils::LogLine("[kip] Failed to read KIP file for GetKipData"); fileUtils::LogLine("[kip] Failed to read KIP file for GetKipData");
notification::writeNotification("Horizon OC\nKip read failed"); notification::writeNotification("Horizon OC\nKip read failed");
return; return;
} }
// if(cust_get_cust_rev(&table) != CUST_REV) { // if(cust_get_cust_rev(&table) != CUST_REV) {
// notification::writeNotification("Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC"); // notification::writeNotification("Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC");
// return; // return;
// } // }
if ((u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip") != config::GetConfigValue(KipCrc32) && !config::GetConfigValue(HocClkConfigValue_IsFirstLoad)) { if ((u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip") != config::GetConfigValue(KipCrc32) && !config::GetConfigValue(HocClkConfigValue_IsFirstLoad)) {
SetKipData(); SetKipData();
notification::writeNotification("Horizon OC\nKIP has been updated\nPlease reboot your console"); notification::writeNotification("Horizon OC\nKIP has been updated\nPlease reboot your console");
return; return;
} }
if (config::GetConfigValue(HocClkConfigValue_IsFirstLoad) == true) { if (config::GetConfigValue(HocClkConfigValue_IsFirstLoad) == true) {
configValues.values[HocClkConfigValue_IsFirstLoad] = (u64)false; configValues.values[HocClkConfigValue_IsFirstLoad] = (u64)false;
notification::writeNotification("Horizon OC has been installed"); notification::writeNotification("Horizon OC has been installed");
} }
configValues.values[KipCrc32] = (u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum configValues.values[KipCrc32] = (u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum
// configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table); // configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table);
configValues.values[KipConfigValue_hpMode] = cust_get_hp_mode(&table); clockManager::gContext.custRev = cust_get_cust_rev(&table);
configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table); u32 custRev = cust_get_cust_rev(&table);
configValues.values[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table); u32 kipVersion = cust_get_kip_version(&table);
configValues.values[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table); if (custRev < CUST_REV || kipVersion < KIP_VERSION) {
configValues.values[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table); notification::writeNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC");
configValues.values[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table); fileUtils::LogLine("Cust revision: %u", custRev);
configValues.values[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table); fileUtils::LogLine("Kip version: %u", kipVersion);
configValues.values[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table); return;
} else if (custRev > CUST_REV || kipVersion > KIP_VERSION) {
notification::writeNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC");
fileUtils::LogLine("Cust revision: %u", custRev);
fileUtils::LogLine("Kip version: %u", kipVersion);
return;
}
configValues.values[KipConfigValue_t1_tRCD] = cust_get_tRCD(&table); clockManager::gContext.kipVersion = kipVersion;
configValues.values[KipConfigValue_t2_tRP] = cust_get_tRP(&table); configValues.values[KipConfigValue_custRev] = cust_get_cust_rev(&table);
configValues.values[KipConfigValue_t3_tRAS] = cust_get_tRAS(&table); configValues.values[KipConfigValue_hpMode] = cust_get_hp_mode(&table);
configValues.values[KipConfigValue_t4_tRRD] = cust_get_tRRD(&table);
configValues.values[KipConfigValue_t5_tRFC] = cust_get_tRFC(&table);
configValues.values[KipConfigValue_t6_tRTW] = cust_get_tRTW(&table);
configValues.values[KipConfigValue_t7_tWTR] = cust_get_tWTR(&table);
configValues.values[KipConfigValue_t8_tREFI] = cust_get_tREFI(&table);
configValues.values[KipConfigValue_stepMode] = cust_get_step_mode(&table);
configValues.values[KipConfigValue_timingEmcTbreak] = cust_get_timing_emc_tbreak(&table); configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table);
configValues.values[KipConfigValue_low_t6_tRTW] = cust_get_low_t6_tRTW(&table); configValues.values[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table);
configValues.values[KipConfigValue_low_t7_tWTR] = cust_get_low_t7_tWTR(&table); configValues.values[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table);
configValues.values[KipConfigValue_t2_tRP_cap] = cust_get_tRP_cap(&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) > 8 && cust_get_emc_dvb_shift(&table) <= 16 ? 8 : cust_get_emc_dvb_shift(&table); // 2.2.0 -> 2.3.0 compat
configValues.values[KipConfigValue_marikoSocVmax] = cust_get_marikoSocVmax(&table);
configValues.values[KipConfigValue_read_latency_1333] = cust_get_read_latency_1333(&table); configValues.values[KipConfigValue_t1_tRCD] = cust_get_tRCD(&table);
configValues.values[KipConfigValue_read_latency_1600] = cust_get_read_latency_1600(&table); configValues.values[KipConfigValue_t2_tRP] = cust_get_tRP(&table);
configValues.values[KipConfigValue_read_latency_1866] = cust_get_read_latency_1866(&table); configValues.values[KipConfigValue_t3_tRAS] = cust_get_tRAS(&table);
configValues.values[KipConfigValue_read_latency_2133] = cust_get_read_latency_2133(&table); configValues.values[KipConfigValue_t4_tRRD] = cust_get_tRRD(&table);
configValues.values[KipConfigValue_t5_tRFC] = cust_get_tRFC(&table);
configValues.values[KipConfigValue_t6_tRTW] = cust_get_tRTW(&table);
configValues.values[KipConfigValue_t7_tWTR] = cust_get_tWTR(&table);
configValues.values[KipConfigValue_t8_tREFI] = cust_get_tREFI(&table);
configValues.values[KipConfigValue_stepMode] = cust_get_step_mode(&table);
configValues.values[KipConfigValue_write_latency_1333] = cust_get_write_latency_1333(&table); configValues.values[KipConfigValue_timingEmcTbreak] = cust_get_timing_emc_tbreak(&table);
configValues.values[KipConfigValue_write_latency_1600] = cust_get_write_latency_1600(&table); configValues.values[KipConfigValue_low_t6_tRTW] = cust_get_low_t6_tRTW(&table);
configValues.values[KipConfigValue_write_latency_1866] = cust_get_write_latency_1866(&table); configValues.values[KipConfigValue_low_t7_tWTR] = cust_get_low_t7_tWTR(&table);
configValues.values[KipConfigValue_write_latency_2133] = cust_get_write_latency_2133(&table); configValues.values[KipConfigValue_t2_tRP_cap] = cust_get_tRP_cap(&table);
configValues.values[KipConfigValue_mem_burst_read_latency] = cust_get_burst_read_lat(&table); configValues.values[KipConfigValue_read_latency_1333] = cust_get_read_latency_1333(&table);
configValues.values[KipConfigValue_mem_burst_write_latency] = cust_get_burst_write_lat(&table); configValues.values[KipConfigValue_read_latency_1600] = cust_get_read_latency_1600(&table);
configValues.values[KipConfigValue_read_latency_1866] = cust_get_read_latency_1866(&table);
configValues.values[KipConfigValue_read_latency_2133] = cust_get_read_latency_2133(&table);
configValues.values[KipConfigValue_eristaCpuUV] = cust_get_erista_cpu_uv(&table); configValues.values[KipConfigValue_write_latency_1333] = cust_get_write_latency_1333(&table);
configValues.values[KipConfigValue_eristaCpuVmin] = cust_get_eristaCpuVmin(&table); configValues.values[KipConfigValue_write_latency_1600] = cust_get_write_latency_1600(&table);
configValues.values[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table); configValues.values[KipConfigValue_write_latency_1866] = cust_get_write_latency_1866(&table);
configValues.values[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table); configValues.values[KipConfigValue_write_latency_2133] = cust_get_write_latency_2133(&table);
configValues.values[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table); configValues.values[KipConfigValue_mem_burst_read_latency] = cust_get_burst_read_lat(&table);
configValues.values[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table); configValues.values[KipConfigValue_mem_burst_write_latency] = cust_get_burst_write_lat(&table);
configValues.values[KipConfigValue_tableConf] = cust_get_table_conf(&table);
configValues.values[KipConfigValue_marikoCpuLowVmin] = cust_get_mariko_cpu_low_vmin(&table);
configValues.values[KipConfigValue_marikoCpuHighVmin] = cust_get_mariko_cpu_high_vmin(&table);
configValues.values[KipConfigValue_marikoCpuMaxVolt] = cust_get_mariko_cpu_max_volt(&table);
configValues.values[KipConfigValue_marikoCpuMaxClock] = cust_get_marikoCpuMaxClock(&table);
configValues.values[KipConfigValue_eristaCpuBoostClock] = cust_get_erista_cpu_boost(&table);
configValues.values[KipConfigValue_marikoCpuBoostClock] = cust_get_mariko_cpu_boost(&table);
configValues.values[KipConfigValue_eristaGpuUV] = cust_get_erista_gpu_uv(&table); configValues.values[KipConfigValue_eristaCpuUV] = cust_get_erista_cpu_uv(&table);
configValues.values[KipConfigValue_eristaGpuVmin] = cust_get_erista_gpu_vmin(&table); configValues.values[KipConfigValue_eristaCpuVmin] = cust_get_eristaCpuVmin(&table);
configValues.values[KipConfigValue_marikoGpuUV] = cust_get_mariko_gpu_uv(&table); configValues.values[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table);
configValues.values[KipConfigValue_marikoGpuVmin] = cust_get_mariko_gpu_vmin(&table); configValues.values[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table);
configValues.values[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table);
configValues.values[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table);
configValues.values[KipConfigValue_gpuSpeedo] = board::GetFuseData()->gpuSpeedo; // cust_get_gpu_speedo(&table);
for (int i = 0; i < 24; i++) { configValues.values[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table);
configValues.values[KipConfigValue_g_volt_76800 + i] = cust_get_mariko_gpu_volt(&table, i); configValues.values[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table);
} configValues.values[KipConfigValue_tableConf] = cust_get_table_conf(&table);
configValues.values[KipConfigValue_marikoCpuLowVmin] = cust_get_mariko_cpu_low_vmin(&table);
configValues.values[KipConfigValue_marikoCpuHighVmin] = cust_get_mariko_cpu_high_vmin(&table);
configValues.values[KipConfigValue_marikoCpuMaxVolt] = cust_get_mariko_cpu_max_volt(&table);
configValues.values[KipConfigValue_marikoCpuMaxClock] = cust_get_marikoCpuMaxClock(&table);
configValues.values[KipConfigValue_eristaCpuBoostClock] = cust_get_erista_cpu_boost(&table);
configValues.values[KipConfigValue_marikoCpuBoostClock] = cust_get_mariko_cpu_boost(&table);
for (int i = 0; i < 27; i++) { configValues.values[KipConfigValue_eristaGpuUV] = cust_get_erista_gpu_uv(&table);
configValues.values[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i); configValues.values[KipConfigValue_eristaGpuVmin] = cust_get_erista_gpu_vmin(&table);
} configValues.values[KipConfigValue_marikoGpuUV] = cust_get_mariko_gpu_uv(&table);
configValues.values[KipConfigValue_marikoGpuVmin] = cust_get_mariko_gpu_vmin(&table);
configValues.values[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table);
configValues.values[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table);
configValues.values[KipConfigValue_gpuSpeedo] = board::GetFuseData()->gpuSpeedo; // cust_get_gpu_speedo(&table);
configValues.values[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table); for (int i = 0; i < 24; i++) {
configValues.values[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table); configValues.values[KipConfigValue_g_volt_76800 + i] = cust_get_mariko_gpu_volt(&table, i);
}
for (int i = 0; i < 27; i++) {
configValues.values[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) if (sizeof(HocClkConfigValueList) <= sizeof(configValues)) {
// return; if (config::SetConfigValues(&configValues, false)) {
fileUtils::LogLine("[kip] KIP loaded. CRC32: %ld (Cust Rev %ld)", configValues.values[KipCrc32], configValues.values[KipConfigValue_custRev]);
if (sizeof(HocClkConfigValueList) <= sizeof(configValues)) { for (u64 i = KipConfigValue_hpMode; i < HocClkConfigValue_EnumMax; i++) {
if (config::SetConfigValues(&configValues, false)) { fileUtils::LogLine("%s: %ld", hocclkFormatConfigValue((HocClkConfigValue)i, false), configValues.values[i]);
fileUtils::LogLine("[kip] KIP loaded. CRC32: %ld (Cust Rev %ld)", configValues.values[KipCrc32], configValues.values[KipConfigValue_custRev]);
for (u64 i = KipConfigValue_hpMode; i < HocClkConfigValue_EnumMax; i++) {
fileUtils::LogLine("%s: %ld", hocclkFormatConfigValue((HocClkConfigValue)i, false), configValues.values[i]);
}
} else {
fileUtils::LogLine("[kip] Warning: Failed to set config values from KIP");
notification::writeNotification("Horizon OC\nKip config set failed");
} }
} else { } else {
fileUtils::LogLine("[kip] Error: Config value list buffer size mismatch"); fileUtils::LogLine("[kip] Warning: Failed to set config values from KIP");
notification::writeNotification("Horizon OC\nConfig Buffer Mismatch"); notification::writeNotification("Horizon OC\nKip config set failed");
} }
} else { } else {
fileUtils::LogLine("[kip] Config refresh error in GetKipData!"); fileUtils::LogLine("[kip] Error: Config value list buffer size mismatch");
notification::writeNotification("Horizon OC\nConfig refresh failed"); notification::writeNotification("Horizon OC\nConfig Buffer Mismatch");
} }
} }
} }

View File

@@ -34,7 +34,7 @@ namespace kip {
typedef struct { typedef struct {
u8 cust[4]; u8 cust[4];
u32 custRev; u32 custRev;
u32 placeholder; u32 kipVersion;
u32 hpMode; u32 hpMode;
u32 commonEmcMemVolt; u32 commonEmcMemVolt;
u32 eristaEmcMaxClock; u32 eristaEmcMaxClock;
@@ -44,6 +44,8 @@ namespace kip {
u32 marikoEmcMaxClock; u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt; u32 marikoEmcVddqVolt;
u32 emcDvbShift; u32 emcDvbShift;
u32 marikoSocVmax;
// advanced config // advanced config
u32 t1_tRCD; u32 t1_tRCD;
u32 t2_tRP; u32 t2_tRP;
@@ -204,7 +206,7 @@ namespace kip {
return cust_write_table(path, &t); \ return cust_write_table(path, &t); \
} while (0) } while (0)
static inline bool cust_set_cust_rev(const char* p, u32 v) { CUST_WRITE_FIELD(p, custRev, v); } // static inline bool cust_set_cust_rev(const char* p, u32 v) { CUST_WRITE_FIELD(p, custRev, v); }
// static inline bool cust_set_mtc_conf(const char* p, u32 v) { CUST_WRITE_FIELD(p, mtcConf, v); } // static inline bool cust_set_mtc_conf(const char* p, u32 v) { CUST_WRITE_FIELD(p, mtcConf, v); }
static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p, hpMode, v); } static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p, hpMode, v); }
@@ -266,6 +268,7 @@ namespace kip {
static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); } static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); }
static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); } static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); }
static inline bool cust_set_marikoCpuMaxClock(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxClock, v); } static inline bool cust_set_marikoCpuMaxClock(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxClock, v); }
static inline bool cust_set_marikoSocVmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoSocVmax, v); }
/* GPU VOLT ARRAY HELPERS */ /* GPU VOLT ARRAY HELPERS */
static inline bool cust_set_erista_gpu_volt(const char* p, int idx, u32 v) { static inline bool cust_set_erista_gpu_volt(const char* p, int idx, u32 v) {
@@ -292,6 +295,7 @@ namespace kip {
#define CUST_GET_FIELD(table, field) ((table) ? (table)->field : 0) #define CUST_GET_FIELD(table, field) ((table) ? (table)->field : 0)
static inline u32 cust_get_cust_rev(const CustomizeTable* t) { return CUST_GET_FIELD(t, custRev); } static inline u32 cust_get_cust_rev(const CustomizeTable* t) { return CUST_GET_FIELD(t, custRev); }
static inline u32 cust_get_kip_version(const CustomizeTable* t) { return CUST_GET_FIELD(t, kipVersion); }
// static inline u32 cust_get_mtc_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, mtcConf); } // static inline u32 cust_get_mtc_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, mtcConf); }
static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FIELD(t, hpMode); } static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FIELD(t, hpMode); }
@@ -354,6 +358,7 @@ namespace kip {
static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); } static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); }
static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); } static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); }
static inline u32 cust_get_marikoCpuMaxClock(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxClock); } static inline u32 cust_get_marikoCpuMaxClock(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxClock); }
static inline u32 cust_get_marikoSocVmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoSocVmax); }
static inline u32 cust_get_erista_gpu_volt(const CustomizeTable* t, int idx) { static inline u32 cust_get_erista_gpu_volt(const CustomizeTable* t, int idx) {
if (!t || idx < 0 || idx >= 27) return 0; if (!t || idx < 0 || idx >= 27) return 0;

View File

@@ -1,381 +0,0 @@
/*
* Copyright (c) Souldbminer and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "governor.hpp"
#include "process_management.hpp"
namespace governor {
#define POLL_NS 5'000'000 // 5 ms governor poll rate
#define DOWN_HOLD_TICKS 10 // 50 ms how long to in POLL_NS to hold while ramping down
#define STEP_UTIL 900 // multiplier for step calculations
bool isGpuGovernorEnabled = false;
bool isCpuGovernorEnabled = false;
bool lastGpuGovernorState = false;
bool lastCpuGovernorState = false;
bool lastVrrGovernorState = false;
bool hasChanged = true;
bool isCpuGovernorInBoostMode = false;
bool isVRREnabled = false;
// thread handles
Thread cpuGovernorTHREAD;
Thread gpuGovernorTHREAD;
Thread vrrTHREAD;
void HandleGovernor(uint32_t targetHz)
{
u32 tempTargetHz = clockManager::gContext.overrideFreqs[HocClkModule_Governor];
if (!tempTargetHz) {
tempTargetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HocClkModule_Governor, clockManager::gContext.profile, true);
if (!tempTargetHz)
tempTargetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HocClkModule_Governor, clockManager::gContext.profile, true);
}
auto resolve = [](u8 app, u8 temp) -> u8 {
if (temp == ComponentGovernor_Disabled) return ComponentGovernor_Disabled;
if (temp != ComponentGovernor_DoNotOverride) return temp;
return app;
};
u8 effectiveCpu = resolve(GovernorStateCpu(targetHz), GovernorStateCpu(tempTargetHz));
u8 effectiveGpu = resolve(GovernorStateGpu(targetHz), GovernorStateGpu(tempTargetHz));
u8 effectiveVrr = resolve(GovernorStateVrr(targetHz), GovernorStateVrr(tempTargetHz));
bool newCpuGovernorState = (effectiveCpu == ComponentGovernor_Enabled);
bool newGpuGovernorState = (effectiveGpu == ComponentGovernor_Enabled);
bool newVrrGovernorState = (effectiveVrr == ComponentGovernor_Enabled);
isCpuGovernorEnabled = newCpuGovernorState;
isGpuGovernorEnabled = newGpuGovernorState;
isVRREnabled = newVrrGovernorState;
if (newCpuGovernorState == false && lastCpuGovernorState == true) {
svcSleepThread(100'000'000); // thread syncing. probably a cleaner way to do this but hey, it works!
board::ResetToStockCpu();
}
if (newGpuGovernorState == false && lastGpuGovernorState == true) {
svcSleepThread(100'000'000);
board::ResetToStockGpu();
}
if (newVrrGovernorState == false && lastVrrGovernorState == true) {
svcSleepThread(100'000'000);
board::ResetToStockDisplay();
}
if (newCpuGovernorState != lastCpuGovernorState || newGpuGovernorState != lastGpuGovernorState || newVrrGovernorState != lastVrrGovernorState) {
fileUtils::LogLine("[mgr] Governor state changed: CPU %s, GPU %s, VRR %s", newCpuGovernorState ? "enabled" : "disabled", newGpuGovernorState ? "enabled" : "disabled", newVrrGovernorState ? "enabled" : "disabled");
lastCpuGovernorState = newCpuGovernorState;
lastGpuGovernorState = newGpuGovernorState;
lastVrrGovernorState = newVrrGovernorState;
}
}
u32 SchedutilTargetHz(u32 util, u32 tableMaxHz)
{
u64 hz = (u64)tableMaxHz * util / STEP_UTIL;
return (u32)(std::min(hz, static_cast<u64>(tableMaxHz)));
}
u32 TableIndexForHz(const clockManager::FreqTable& table, u32 targetHz)
{
for (u32 i = 0; i < table.count; i++)
if (table.list[i] >= targetHz)
return i;
return table.count - 1;
}
u32 ResolveTargetHz(HocClkModule module)
{
u32 hz = clockManager::gContext.overrideFreqs[module];
if (!hz)
hz = config::GetAutoClockHz(
clockManager::gContext.applicationId, module,
clockManager::gContext.profile, false);
if (!hz)
hz = config::GetAutoClockHz(
GLOBAL_PROFILE_ID, module,
clockManager::gContext.profile, false);
return hz;
}
void CpuGovernorThread(void* arg)
{
(void)arg;
u32 downHoldRemaining = 0;
u32 lastHz = 0;
u32 minHz = 612;
u32 tick = 0;
for (;;) {
if (!clockManager::gRunning || !isCpuGovernorEnabled) {
downHoldRemaining = 0;
lastHz = 0;
svcSleepThread(POLL_NS);
continue;
}
u32 mode = 0;
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
if (R_SUCCEEDED(rc) && apmExtIsBoostMode(mode)) {
isCpuGovernorInBoostMode = true;
downHoldRemaining = 0;
lastHz = 0;
continue; // TODO: figure out a way to get boost clock easily and set it instead of just skipping the governor
} else if (!apmExtIsBoostMode(mode)) {
isCpuGovernorInBoostMode = false;
}
auto& table = clockManager::gFreqTable[HocClkModule_CPU];
if (table.count == 0)
continue;
std::scoped_lock lock{clockManager::gContextMutex};
u32 cpuLoad = board::GetPartLoad(HocClkPartLoad_CPUMax);
u32 tableMaxHz = table.list[table.count - 1];
u32 desiredHz = SchedutilTargetHz(cpuLoad, tableMaxHz);
u32 targetHz = ResolveTargetHz(HocClkModule_CPU);
u32 maxHz = clockManager::GetMaxAllowedHz(HocClkModule_CPU, clockManager::gContext.profile);
if (targetHz && desiredHz > targetHz)
desiredHz = targetHz;
if (maxHz && desiredHz > maxHz)
desiredHz = maxHz;
u32 newHz = table.list[TableIndexForHz(table, desiredHz)];
// ramp up fast, go down slow
bool goingDown = (lastHz != 0) && (newHz < lastHz);
if (!goingDown)
downHoldRemaining = 0;
else if (downHoldRemaining == 0)
downHoldRemaining = DOWN_HOLD_TICKS;
if (downHoldRemaining > 0)
downHoldRemaining--;
if (++tick > 50) {
minHz = config::GetConfigValue(HocClkConfigValue_CpuGovernorMinimumFreq);
tick = 0;
}
if (newHz < minHz)
newHz = minHz;
if ((!goingDown || (downHoldRemaining == 0)) && clockManager::IsAssignableHz(HocClkModule_CPU, newHz)) {
board::SetHz(HocClkModule_CPU, newHz);
clockManager::gContext.freqs[HocClkModule_CPU] = newHz;
lastHz = newHz;
}
svcSleepThread(POLL_NS);
}
}
void GovernorThread(void* arg)
{
(void)arg;
u32 downHoldRemaining = 0;
u32 lastHz = 0;
for (;;) {
if (!clockManager::gRunning || !isGpuGovernorEnabled) {
downHoldRemaining = 0;
lastHz = 0;
svcSleepThread(POLL_NS);
continue;
}
auto& table = clockManager::gFreqTable[HocClkModule_GPU];
if (table.count == 0)
continue;
std::scoped_lock lock{clockManager::gContextMutex};
u32 gpuLoad = board::GetPartLoad(HocClkPartLoad_GPU);
u32 tableMaxHz = table.list[table.count - 1];
u32 desiredHz = SchedutilTargetHz(gpuLoad, tableMaxHz);
u32 targetHz = ResolveTargetHz(HocClkModule_GPU);
u32 maxHz = clockManager::GetMaxAllowedHz(HocClkModule_GPU, clockManager::gContext.profile);
if (targetHz && desiredHz > targetHz)
desiredHz = targetHz;
if (maxHz && desiredHz > maxHz)
desiredHz = maxHz;
u32 newHz = table.list[TableIndexForHz(table, desiredHz)];
bool goingDown = (lastHz != 0) && (newHz < lastHz);
if (!goingDown)
downHoldRemaining = 0;
else if (downHoldRemaining == 0)
downHoldRemaining = DOWN_HOLD_TICKS;
if (downHoldRemaining > 0)
downHoldRemaining--;
if ((!goingDown || (downHoldRemaining == 0)) && clockManager::IsAssignableHz(HocClkModule_GPU, newHz)) {
board::SetHz(HocClkModule_GPU, newHz);
clockManager::gContext.freqs[HocClkModule_GPU] = newHz;
lastHz = newHz;
}
svcSleepThread(POLL_NS);
}
}
void VRRThread(void* arg)
{
(void)arg;
u8 tick = 0, tick2 = 0;
for (;;) {
if (!clockManager::gRunning || clockManager::gContext.profile == HocClkProfile_Docked || !isVRREnabled) {
svcSleepThread(POLL_NS);
continue;
}
std::scoped_lock lock{clockManager::gContextMutex};
if(++tick2 > 100) {
bool isApplicationOutOfFocus = false;
Result rc = processManagement::isApplicationOutOfFocus(&isApplicationOutOfFocus);
if(R_FAILED(rc)) {
svcSleepThread(POLL_NS);
continue;
}
if(isApplicationOutOfFocus) {
board::ResetToStockDisplay();
svcSleepThread(POLL_NS);
continue;
}
}
u8 fps;
if (clockManager::gContext.isSaltyNXInstalled) {
fps = integrations::GetSaltyNXFPS();
} else {
svcSleepThread(~0ULL); // effectively disable the thread if SaltyNX isn't installed, as there's no point in it running
continue;
}
if (fps == 254) {
svcSleepThread(POLL_NS);
continue;
}
// if(appletGetFocusState() != AppletFocusState_InFocus) {
// board::ResetToStockDisplay();
// continue;
// }
u32 targetHz = clockManager::gContext.overrideFreqs[HocClkModule_Display];
if (!targetHz) {
targetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HocClkModule_Display, clockManager::gContext.profile, false);
if (!targetHz)
targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HocClkModule_Display, clockManager::gContext.profile, false);
}
u8 maxDisplay;
if (targetHz) {
maxDisplay = targetHz;
} else {
maxDisplay = 60; // don't assume display stuff!
}
u8 minDisplay = board::GetConsoleType() == HocClkConsoleType_Aula ? 45 : 40;
if (maxDisplay == minDisplay)
continue;
if (fps >= minDisplay && fps <= maxDisplay) {
board::SetHz(HocClkModule_Display, fps);
clockManager::gContext.freqs[HocClkModule_Display] = fps;
clockManager::gContext.realFreqs[HocClkModule_Display] = fps;
} else {
for (u32 i = 0; i < 10; i++) {
u32 compareHz = fps * i;
if (compareHz >= minDisplay && compareHz <= maxDisplay) {
board::SetHz(HocClkModule_Display, compareHz);
clockManager::gContext.freqs[HocClkModule_Display] = compareHz;
clockManager::gContext.realFreqs[HocClkModule_Display] = compareHz;
break;
}
}
}
if (++tick > 50) {
board::SetHz(HocClkModule_Display, maxDisplay);
tick = 0;
svcSleepThread(50'000'000);
}
svcSleepThread(POLL_NS);
}
}
void startThreads() {
threadCreate(
&cpuGovernorTHREAD,
CpuGovernorThread,
nullptr,
NULL,
0x2000,
0x3F,
-2
);
threadCreate(
&gpuGovernorTHREAD,
GovernorThread,
nullptr,
NULL,
0x2000,
0x3F,
-2
);
threadCreate(
&vrrTHREAD,
VRRThread,
nullptr,
NULL,
0x2000,
0x3F,
-2
);
threadStart(&cpuGovernorTHREAD);
threadStart(&gpuGovernorTHREAD);
threadStart(&vrrTHREAD);
}
void exitThreads() {
threadClose(&cpuGovernorTHREAD);
threadClose(&gpuGovernorTHREAD);
threadClose(&vrrTHREAD);
}
}

View File

@@ -25,7 +25,7 @@
*/ */
#include "nxExt/apm_ext.h" #include "apm_ext.h"
#include <stdatomic.h> #include <stdatomic.h>

View File

@@ -12,7 +12,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -28,7 +28,7 @@ namespace notification {
} }
fclose(flagFile); fclose(flagFile);
std::string filename = "Horizon OC -" + std::to_string(std::time(nullptr)) + ".notify"; std::string filename = "hoc-" + std::to_string(std::time(nullptr)) + ".notify";
std::string fullPath = "sdmc:/config/ultrahand/notifications/" + filename; std::string fullPath = "sdmc:/config/ultrahand/notifications/" + filename;
FILE* file = fopen(fullPath.c_str(), "w"); FILE* file = fopen(fullPath.c_str(), "w");

View File

@@ -26,8 +26,8 @@
#include "process_management.hpp" #include "process_management.hpp"
#include "file_utils.hpp" #include "../file/file_utils.hpp"
#include "errors.hpp" #include "../file/errors.hpp"
#include <cstring> #include <cstring>
namespace processManagement { namespace processManagement {

View File

@@ -15,7 +15,7 @@
* *
*/ */
#include <hocclk/psm_ext.h> #include "psm_ext.h"
const char* PsmPowerRoleToStr(PsmPowerRole role) { const char* PsmPowerRoleToStr(PsmPowerRole role) {
switch (role) { switch (role) {

View File

@@ -17,7 +17,7 @@
#define NX_SERVICE_ASSUME_NON_DOMAIN #define NX_SERVICE_ASSUME_NON_DOMAIN
#include <switch.h> #include <switch.h>
#include "service_guard.h" #include "../util/service_guard.h"
#include "pwm.h" #include "pwm.h"
static Service g_pwmSrv; static Service g_pwmSrv;

View File

@@ -25,7 +25,7 @@
*/ */
#include "nxExt/i2c.h" #include "i2c.h"
#define I2C_CMD_SND 0 #define I2C_CMD_SND 0
#define I2C_CMD_RCV 1 #define I2C_CMD_RCV 1

Some files were not shown because too many files have changed in this diff Show More