Start hoc-clk rewrite
This commit is contained in:
39
Source/rewrite-hoc-clk/sysmodule/src/board/board.hpp
Normal file
39
Source/rewrite-hoc-clk/sysmodule/src/board/board.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 <switch.h>
|
||||
|
||||
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
|
||||
#define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0))
|
||||
|
||||
namespace board {
|
||||
|
||||
void Initialize();
|
||||
void Exit();
|
||||
|
||||
}
|
||||
120
Source/rewrite-hoc-clk/sysmodule/src/board/board_fuse.cpp
Normal file
120
Source/rewrite-hoc-clk/sysmodule/src/board/board_fuse.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include "board_fuse.hpp"
|
||||
|
||||
namespace board {
|
||||
|
||||
namespace {
|
||||
constexpr u32 FuseCpuSpeedoCalib = 0x114;
|
||||
// constexpr u32 FuseCpuSpeedo1Calib = 0x12C;
|
||||
constexpr u32 FuseGpuSpeedoCalib = 0x130;
|
||||
|
||||
constexpr u32 FuseSocSpeedoCalib = 0x134;
|
||||
// constexpr u32 FuseSocSpeedo1Calib = 0x138;
|
||||
// constexpr u32 FuseSocSpeedo2Calib = 0x13C;
|
||||
|
||||
constexpr u32 FuseCpuIddqCalib = 0x118;
|
||||
constexpr u32 FuseSocIddqCalib = 0x140;
|
||||
constexpr u32 FuseGpuIddqCalib = 0x228;
|
||||
}
|
||||
|
||||
void SetGpuBracket(u8 speedo, u8 &gpuBracket) {
|
||||
if (speedo <= 1624) {
|
||||
gpuBracket = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (speedo <= 1689) {
|
||||
gpuBracket = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (speedo <= 1753) {
|
||||
gpuBracket = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
/* >= 1754 */
|
||||
gpuBracket = 3;
|
||||
}
|
||||
|
||||
FuseReadSpeedo(FuseSpeedoData &speedo) {
|
||||
u64 pid = 0;
|
||||
constexpr u64 UsbID = 0x0100000000000006;
|
||||
if (R_FAILED(pmdmntGetProcessId(&pid, UsbID))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Handle debug;
|
||||
if (R_FAILED(svcDebugActiveProcess(&debug, pid))) {
|
||||
return;
|
||||
}
|
||||
|
||||
MemoryInfo mem_info = {};
|
||||
u32 pageinfo = 0;
|
||||
u64 addr = 0;
|
||||
|
||||
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 + FuseCpuSpeedoCalib);
|
||||
speedo.gpuSpeedo = *reinterpret_cast<u16*>(dump + FuseGpuSpeedoCalib);
|
||||
speedo.socSpeedo = *reinterpret_cast<u16*>(dump + FuseSocSpeedoCalib);
|
||||
speedo.cpuIDDQ = *reinterpret_cast<u16*>(dump + FuseCpuIddqCalib);
|
||||
speedo.gpuIDDQ = *reinterpret_cast<u16*>(dump + FuseSocIddqCalib);
|
||||
speedo.socIDDQ = *reinterpret_cast<u16*>(dump + FUSE_GPU_IDDQ_CALIB);
|
||||
|
||||
svcCloseHandle(debug);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addr = mem_info.addr + mem_info.size;
|
||||
}
|
||||
|
||||
svcCloseHandle(debug);
|
||||
}
|
||||
|
||||
}
|
||||
44
Source/rewrite-hoc-clk/sysmodule/src/board/board_fuse.hpp
Normal file
44
Source/rewrite-hoc-clk/sysmodule/src/board/board_fuse.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace board {
|
||||
|
||||
struct FuseSpeedoData {
|
||||
u16 cpuSpeedo;
|
||||
u16 gpuSpeedo;
|
||||
u16 socSpeedo;
|
||||
|
||||
u16 cpuIDDQ;
|
||||
u16 gpuIDDQ;
|
||||
u16 socIDDQ;
|
||||
};
|
||||
|
||||
FuseReadSpeedo(FuseSpeedoData speedo);
|
||||
FuseSetGpuBracket(u8 gpuSpeedo, u8 &gpuBracket);
|
||||
|
||||
}
|
||||
195
Source/rewrite-hoc-clk/sysmodule/src/board/board_init.cpp
Normal file
195
Source/rewrite-hoc-clk/sysmodule/src/board/board_init.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <nxExt.h>
|
||||
#include <sysclk.h>
|
||||
#include <switch.h>
|
||||
#include <pwm.h>
|
||||
|
||||
#include "board.hpp"
|
||||
#include "board_fuse.hpp"
|
||||
#include "board_load.hpp"
|
||||
|
||||
namespace board {
|
||||
|
||||
SysClkSocType gSocType;
|
||||
u8 gDramID;
|
||||
HorizonOCConsoleType gConsoleType = HorizonOCConsoleType_Iowa;
|
||||
FuseSpeedoData gSpeedos;
|
||||
u8 speedoBracket;
|
||||
Result nvCheck = 1;
|
||||
u23 fd = 0, fd2 = 0;
|
||||
|
||||
void FetchHardwareInfos() {
|
||||
FuseReadSpeedos(gSpeedos);
|
||||
FuseSetGpuBracket(gSpeedos.gpuSpeedo, speedoBracket);
|
||||
|
||||
u64 sku = 0, dramID = 0;
|
||||
Result rc = splInitialize();
|
||||
ASSERT_RESULT_OK(rc, "splInitialize");
|
||||
|
||||
rc = splGetConfig(SplConfigItem_HardwareType, &sku);
|
||||
ASSERT_RESULT_OK(rc, "splGetConfig");
|
||||
|
||||
rc = splGetConfig(SplConfigItem_DramId, &dramID);
|
||||
ASSERT_RESULT_OK(rc, "splGetConfig");
|
||||
gDramID = dramID;
|
||||
splExit();
|
||||
|
||||
switch(sku) {
|
||||
case 2 ... 5:
|
||||
gSocType = SysClkSocType_Mariko;
|
||||
break;
|
||||
default:
|
||||
gSocType = SysClkSocType_Erista;
|
||||
}
|
||||
|
||||
if (gSocType == SysClkSocType_Mariko) {
|
||||
CacheDvfsTable();
|
||||
}
|
||||
|
||||
gConsoleType = static_cast<HorizonOCConsoleType> sku;
|
||||
g_dramID = dramID;
|
||||
}
|
||||
|
||||
/* TODO: Check for config */
|
||||
void Initialize() {
|
||||
Result rc = 0;
|
||||
|
||||
if (HOSSVC_HAS_CLKRST) {
|
||||
rc = clkrstInitialize();
|
||||
ASSERT_RESULT_OK(rc, "clkrstInitialize");
|
||||
} else {
|
||||
rc = pcvInitialize();
|
||||
ASSERT_RESULT_OK(rc, "pcvInitialize");
|
||||
}
|
||||
|
||||
if(HOSSVC_HAS_TC) {
|
||||
rc = tcInitialize();
|
||||
ASSERT_RESULT_OK(rc, "tcInitialize");
|
||||
}
|
||||
|
||||
rc = max17050Initialize();
|
||||
ASSERT_RESULT_OK(rc, "max17050Initialize");
|
||||
|
||||
rc = tmp451Initialize();
|
||||
ASSERT_RESULT_OK(rc, "tmp451Initialize");
|
||||
|
||||
nvInitialize_rc = nvInitialize();
|
||||
if (R_SUCCEEDED(nvInitialize_rc)) {
|
||||
nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
|
||||
nvCheck_sched = nvOpen(&fd2, "/dev/nvsched-ctrl");
|
||||
}
|
||||
|
||||
rc = rgltrInitialize();
|
||||
ASSERT_RESULT_OK(rc, "rgltrInitialize");
|
||||
|
||||
rc = pmdmntInitialize();
|
||||
ASSERT_RESULT_OK(rc, "pmdmntInitialize");
|
||||
|
||||
StartGpuLoad(nvCheck, fd);
|
||||
|
||||
leventClear(&threadexit);
|
||||
threadCreate(&cpuCore0Thread, CheckCore, &idletick0, NULL, 0x1000, 0x10, 0);
|
||||
threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1);
|
||||
threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2);
|
||||
// threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3);
|
||||
threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x10, 3);
|
||||
|
||||
threadStart(&cpuCore0Thread);
|
||||
threadStart(&cpuCore1Thread);
|
||||
threadStart(&cpuCore2Thread);
|
||||
// threadStart(&cpuCore3Thread);
|
||||
|
||||
threadStart(&miscThread);
|
||||
batteryInfoInitialize();
|
||||
FetchHardwareInfos();
|
||||
|
||||
if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) {
|
||||
pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001);
|
||||
}
|
||||
|
||||
if (gConsoleType != HorizonOCConsoleType_Hoag) {
|
||||
u64 clkVirtAddr, dsiVirtAddr, outsize;
|
||||
|
||||
rc = svcQueryMemoryMapping(&clkVirtAddr, &outsize, 0x60006000, 0x1000);
|
||||
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (clk)");
|
||||
|
||||
rc = svcQueryMemoryMapping(&dsiVirtAddr, &outsize, 0x54300000, 0x40000);
|
||||
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (dsi)");
|
||||
|
||||
DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr};
|
||||
DisplayRefresh_Initialize(&cfg);
|
||||
}
|
||||
|
||||
// rc = svcQueryMemoryMapping(&cldvfs, &cldvfs_temp, CLDVFS_REGION_BASE, CLDVFS_REGION_SIZE);
|
||||
// ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (cldvfs)");
|
||||
|
||||
// if (socType == SysClkSocType_Erista) {
|
||||
// cachedEristaUvLowTune0 = *(u32*) (cldvfs + CL_DVFS_TUNE0_0);
|
||||
// cachedEristaUvLowTune1 = *(u32*) (cldvfs + CL_DVFS_TUNE1_0);
|
||||
// } else {
|
||||
// SetHz(SysClkModule_CPU, 1785000000);
|
||||
// cachedMarikoUvHighTune0 = *(u32*) (cldvfs + CL_DVFS_TUNE0_0);
|
||||
// ResetToStockCpu();
|
||||
// }
|
||||
}
|
||||
|
||||
void Exit() {
|
||||
if (HOSSVC_HAS_CLKRST) {
|
||||
clkrstExit();
|
||||
} else {
|
||||
pcvExit();
|
||||
}
|
||||
|
||||
apmExtExit();
|
||||
psmExit();
|
||||
|
||||
if (HOSSVC_HAS_TC) {
|
||||
tcExit();
|
||||
}
|
||||
|
||||
max17050Exit();
|
||||
tmp451Exit();
|
||||
|
||||
ExitLoad();
|
||||
|
||||
// threadClose(&cpuCore3Thread);
|
||||
threadClose(&miscThread);
|
||||
|
||||
pwmChannelSessionClose(&g_ICon);
|
||||
pwmExit();
|
||||
rgltrExit();
|
||||
batteryInfoExit();
|
||||
pmdmntExit();
|
||||
nvExit();
|
||||
|
||||
if (gConsoleType != HorizonOCConsoleType_Hoag) {
|
||||
DisplayRefresh_Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
66
Source/rewrite-hoc-clk/sysmodule/src/board/board_load.cpp
Normal file
66
Source/rewrite-hoc-clk/sysmodule/src/board/board_load.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace board {
|
||||
|
||||
Thread gpuThread;
|
||||
u32 gpuLoad;
|
||||
u32 _fd;
|
||||
|
||||
void GpuLoadThread(Result *nvCheck) {
|
||||
constexpr u32 GpuSamples = 8;
|
||||
u32 gpu_load_array[GpuSamples] = {};
|
||||
size_t i = 0;
|
||||
constexpr u32 NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD = 0x80044715;
|
||||
|
||||
if (R_SUCCEEDED(nvCheck)) do {
|
||||
u32 temp;
|
||||
if (R_SUCCEEDED(nvIoctl(_fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &temp))) {
|
||||
gpu_load_array[i++ % gpu_samples_average] = temp;
|
||||
gpuLoad = std::accumulate(&gpu_load_array[0], &gpu_load_array[gpu_samples_average], 0) / gpu_samples_average;
|
||||
}
|
||||
svcSleepThread(16'666'000); // wait a bit (this is the perfect amount of time to keep the reading accurate)
|
||||
} while(true);
|
||||
}
|
||||
|
||||
void StartGpuLoad(Result nvCheck, u32 fd) {
|
||||
_fd = fd;
|
||||
|
||||
threadCreate(&gpuThread, GpuLoadThread, &nvCheck, NULL, 0x1000, 0x3F, -2);
|
||||
threadStart(&gpuThread);
|
||||
}
|
||||
|
||||
void ExitLoad() {
|
||||
threadClose(gpuThread);
|
||||
}
|
||||
|
||||
void StartCpuLoad() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
35
Source/rewrite-hoc-clk/sysmodule/src/board/board_load.hpp
Normal file
35
Source/rewrite-hoc-clk/sysmodule/src/board/board_load.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace board {
|
||||
|
||||
void StartGpuLoad(Result nvCheck, u32 fd);
|
||||
void StartCpuLoad();
|
||||
void ExitLoad();
|
||||
|
||||
}
|
||||
1299
Source/rewrite-hoc-clk/sysmodule/src/clock_manager.cpp
Normal file
1299
Source/rewrite-hoc-clk/sysmodule/src/clock_manager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
261
Source/rewrite-hoc-clk/sysmodule/src/clock_manager.h
Normal file
261
Source/rewrite-hoc-clk/sysmodule/src/clock_manager.h
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* 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 <atomic>
|
||||
#include <sysclk.h>
|
||||
#include <switch.h>
|
||||
#include "config.h"
|
||||
#include "board.h"
|
||||
#include <nxExt/cpp/lockable_mutex.h>
|
||||
#include "integrations.h"
|
||||
|
||||
class SysDockIntegration;
|
||||
class SaltyNXIntegration;
|
||||
class ClockManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get instance
|
||||
* @return Pointer to a ClockManager instance
|
||||
*/
|
||||
static ClockManager* GetInstance();
|
||||
static void Initialize();
|
||||
static void Exit();
|
||||
ClockManager();
|
||||
virtual ~ClockManager();
|
||||
|
||||
/**
|
||||
* Get context object
|
||||
* @return Context instance
|
||||
*/
|
||||
SysClkContext GetCurrentContext();
|
||||
|
||||
/**
|
||||
* Get config object
|
||||
* @return Pointer to a config instance
|
||||
*/
|
||||
Config* GetConfig();
|
||||
|
||||
/**
|
||||
* Set clock manager running
|
||||
* @param running Is running or not?
|
||||
*/
|
||||
void SetRunning(bool running);
|
||||
|
||||
/**
|
||||
* Is clock manager running
|
||||
* @return running or not?
|
||||
*/
|
||||
bool Running();
|
||||
|
||||
/**
|
||||
* Get frequency list from clkrst
|
||||
*
|
||||
* @param module Module to get frequency list for
|
||||
* @param list List of frequencies
|
||||
* @param maxCount How many entries to expect in list. Usually 32
|
||||
* @param outCount How many entries were retrived
|
||||
*/
|
||||
void GetFreqList(SysClkModule module, std::uint32_t* list, std::uint32_t maxCount, std::uint32_t* outCount);
|
||||
|
||||
/**
|
||||
* Handles safety features
|
||||
*
|
||||
*/
|
||||
void HandleSafetyFeatures();
|
||||
|
||||
/**
|
||||
* Handles misc features (currently only battery charge current).
|
||||
*
|
||||
*/
|
||||
void HandleMiscFeatures();
|
||||
|
||||
/**
|
||||
* Handles governor state resolution and applies CPU/GPU governor transitions.
|
||||
*
|
||||
* @param targetHz Governor override value for the current profile.
|
||||
*/
|
||||
void HandleGovernor(uint32_t targetHz);
|
||||
|
||||
/**
|
||||
* Handles DVFS logic before the frequency set
|
||||
*
|
||||
* @param targetHz Governor override value for the current profile.
|
||||
*/
|
||||
void DVFSBeforeSet(u32 targetHz);
|
||||
|
||||
/**
|
||||
* Handles DVFS logic after the frequency set
|
||||
*
|
||||
* @param targetHz Governor override value for the current profile.
|
||||
*/
|
||||
void DVFSAfterSet(u32 targetHz);
|
||||
|
||||
/**
|
||||
* Reset the GPU vMin
|
||||
*
|
||||
*/
|
||||
void DVFSReset();
|
||||
|
||||
/**
|
||||
* Handles the Live CPU UV Feature
|
||||
*
|
||||
*/
|
||||
void HandleCpuUv();
|
||||
|
||||
/**
|
||||
* Handles frequency resets
|
||||
*
|
||||
* @param module The module to reset frequency for
|
||||
* @param isBoost Is in boost mode
|
||||
*/
|
||||
void HandleFreqReset(SysClkModule module, bool isBoost);
|
||||
|
||||
/**
|
||||
* Sets clocks
|
||||
*
|
||||
* @param isBoost Is in boost mode
|
||||
*/
|
||||
void SetClocks(bool isBoost);
|
||||
|
||||
/**
|
||||
* Main function, runs every 5s in sleep mode, and a user specified amount when awake
|
||||
*
|
||||
*/
|
||||
void Tick();
|
||||
|
||||
/**
|
||||
* Reset CPU/GPU to stock values
|
||||
*
|
||||
*/
|
||||
void ResetToStockClocks();
|
||||
|
||||
/**
|
||||
* Wait for the next tick event
|
||||
*
|
||||
*/
|
||||
void WaitForNextTick();
|
||||
|
||||
/**
|
||||
* Set the data in the KIP
|
||||
*
|
||||
*/
|
||||
void SetKipData();
|
||||
|
||||
/**
|
||||
* Get the data from the KIP
|
||||
*
|
||||
*/
|
||||
void GetKipData();
|
||||
|
||||
/**
|
||||
* Runs the CPU Governor
|
||||
*
|
||||
* @param arg Cast to ClockManager* for context
|
||||
*/
|
||||
static void CpuGovernorThread(void* arg);
|
||||
|
||||
/**
|
||||
* Runs the GPU Governor
|
||||
*
|
||||
* @param arg Cast to ClockManager* for context
|
||||
*/
|
||||
static void GovernorThread(void* arg);
|
||||
|
||||
/**
|
||||
* Runs the VRR Algorithm
|
||||
*
|
||||
* @param arg Cast to ClockManager* for context
|
||||
*/
|
||||
static void VRRThread(void* arg);
|
||||
|
||||
/**
|
||||
* Frequency table
|
||||
*
|
||||
*/
|
||||
struct FreqTable {
|
||||
std::uint32_t count;
|
||||
std::uint32_t list[SYSCLK_FREQ_LIST_MAX];
|
||||
} freqTable[SysClkModule_EnumMax];
|
||||
|
||||
/**
|
||||
* Gets the current GPU speedo bracket
|
||||
*
|
||||
* @param speedo GPU Speedo
|
||||
*/
|
||||
int GetSpeedoBracket (int speedo);
|
||||
|
||||
/**
|
||||
* Gets the required vMin for a ram frequency for a speedo
|
||||
*
|
||||
* @param freq RAM Freq in MHz
|
||||
* @param speedo GPU Speedo
|
||||
*/
|
||||
unsigned int GetGpuVoltage (unsigned int freq, int speedo);
|
||||
|
||||
/**
|
||||
* Gets the required vMin for a ram frequency for a speedo
|
||||
*
|
||||
* @param util Utilization in percentile
|
||||
* @param tableMaxHz Table Max Hz
|
||||
*/
|
||||
static u32 SchedutilTargetHz(u32 util, u32 tableMaxHz);
|
||||
|
||||
/**
|
||||
* Gets the required vMin for a ram frequency for a speedo
|
||||
*
|
||||
* @param table FreqTable for module
|
||||
* @param targetHz Hz to search for
|
||||
*/
|
||||
static u32 TableIndexForHz(const FreqTable& table, u32 targetHz);
|
||||
|
||||
/**
|
||||
* Gets the required vMin for a ram frequency for a speedo
|
||||
*
|
||||
* @param mgr ClockManager instance (runs in a thread so must be passed)
|
||||
* @param module Module for which to resolve target Hz
|
||||
*/
|
||||
static u32 ResolveTargetHz(ClockManager* mgr, SysClkModule module);
|
||||
|
||||
protected:
|
||||
bool IsAssignableHz(SysClkModule module, std::uint32_t hz);
|
||||
inline std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile);
|
||||
std::uint32_t GetNearestHz(SysClkModule module, std::uint32_t inHz, std::uint32_t maxHz);
|
||||
bool ConfigIntervalTimeout(SysClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t* lastLogNs);
|
||||
void RefreshFreqTableRow(SysClkModule module);
|
||||
bool RefreshContext();
|
||||
static ClockManager *instance;
|
||||
std::atomic_bool running;
|
||||
LockableMutex contextMutex;
|
||||
Config* config;
|
||||
SysClkContext* context;
|
||||
std::uint64_t lastTempLogNs;
|
||||
std::uint64_t lastFreqLogNs;
|
||||
std::uint64_t lastPowerLogNs;
|
||||
std::uint64_t lastCsvWriteNs;
|
||||
SysDockIntegration *sysDockIntegration;
|
||||
SaltyNXIntegration *saltyNXIntegration;
|
||||
};
|
||||
520
Source/rewrite-hoc-clk/sysmodule/src/config.cpp
Normal file
520
Source/rewrite-hoc-clk/sysmodule/src/config.cpp
Normal file
@@ -0,0 +1,520 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include "errors.h"
|
||||
#include "file_utils.h"
|
||||
|
||||
Config::Config(std::string path)
|
||||
{
|
||||
this->path = path;
|
||||
this->loaded = false;
|
||||
this->profileMHzMap = std::map<std::tuple<std::uint64_t, SysClkProfile, SysClkModule>, std::uint32_t>();
|
||||
this->profileCountMap = std::map<std::uint64_t, std::uint8_t>();
|
||||
this->mtime = 0;
|
||||
this->enabled = false;
|
||||
for(unsigned int i = 0; i < SysClkModule_EnumMax; i++)
|
||||
{
|
||||
this->overrideFreqs[i] = 0;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < SysClkConfigValue_EnumMax; i++)
|
||||
{
|
||||
this->configValues[i] = sysclkDefaultConfigValue((SysClkConfigValue)i);
|
||||
}
|
||||
}
|
||||
|
||||
Config::~Config()
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
this->Close();
|
||||
}
|
||||
|
||||
Config* Config::CreateDefault()
|
||||
{
|
||||
return new Config(FILE_CONFIG_DIR "/config.ini");
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
FileUtils::LogLine("[cfg] Reading %s", this->path.c_str());
|
||||
|
||||
this->Close();
|
||||
this->mtime = this->CheckModificationTime();
|
||||
if(!this->mtime)
|
||||
{
|
||||
FileUtils::LogLine("[cfg] Error finding file");
|
||||
}
|
||||
else if (!ini_browse(&BrowseIniFunc, this, this->path.c_str()))
|
||||
{
|
||||
FileUtils::LogLine("[cfg] Error loading file");
|
||||
}
|
||||
|
||||
this->loaded = true;
|
||||
}
|
||||
|
||||
void Config::Close()
|
||||
{
|
||||
this->loaded = false;
|
||||
this->profileMHzMap.clear();
|
||||
this->profileCountMap.clear();
|
||||
|
||||
for(unsigned int i = 0; i < SysClkConfigValue_EnumMax; i++)
|
||||
{
|
||||
this->configValues[i] = sysclkDefaultConfigValue((SysClkConfigValue)i);
|
||||
}
|
||||
}
|
||||
|
||||
bool Config::Refresh()
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
if (!this->loaded || this->mtime != this->CheckModificationTime())
|
||||
{
|
||||
this->Load();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Config::HasProfilesLoaded()
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
return this->loaded;
|
||||
}
|
||||
|
||||
time_t Config::CheckModificationTime()
|
||||
{
|
||||
time_t mtime = 0;
|
||||
struct stat st;
|
||||
if (stat(this->path.c_str(), &st) == 0)
|
||||
{
|
||||
mtime = st.st_mtime;
|
||||
}
|
||||
|
||||
return mtime;
|
||||
}
|
||||
|
||||
std::uint32_t Config::FindClockMHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile)
|
||||
{
|
||||
if (this->loaded)
|
||||
{
|
||||
std::map<std::tuple<std::uint64_t, SysClkProfile, SysClkModule>, std::uint32_t>::const_iterator it = this->profileMHzMap.find(std::make_tuple(tid, profile, module));
|
||||
if (it != this->profileMHzMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::uint32_t Config::FindClockHzFromProfiles(std::uint64_t tid, SysClkModule module, std::initializer_list<SysClkProfile> profiles, u32 mhzMultiplier)
|
||||
{
|
||||
std::uint32_t mhz = 0;
|
||||
|
||||
if (this->loaded)
|
||||
{
|
||||
for(auto profile: profiles)
|
||||
{
|
||||
mhz = FindClockMHz(tid, module, profile);
|
||||
|
||||
if(mhz)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::max((std::uint32_t)0, mhz * mhzMultiplier);
|
||||
}
|
||||
|
||||
std::uint32_t Config::GetAutoClockHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile, bool returnRaw)
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
switch(profile)
|
||||
{
|
||||
case SysClkProfile_Handheld:
|
||||
return FindClockHzFromProfiles(tid, module, {SysClkProfile_Handheld}, returnRaw ? 1 : 1000000);
|
||||
case SysClkProfile_HandheldCharging:
|
||||
case SysClkProfile_HandheldChargingUSB:
|
||||
return FindClockHzFromProfiles(tid, module, {SysClkProfile_HandheldChargingUSB, SysClkProfile_HandheldCharging, SysClkProfile_Handheld}, returnRaw ? 1 : 1000000);
|
||||
case SysClkProfile_HandheldChargingOfficial:
|
||||
return FindClockHzFromProfiles(tid, module, {SysClkProfile_HandheldChargingOfficial, SysClkProfile_HandheldCharging, SysClkProfile_Handheld}, returnRaw ? 1 : 1000000);
|
||||
case SysClkProfile_Docked:
|
||||
return FindClockHzFromProfiles(tid, module, {SysClkProfile_Docked}, returnRaw ? 1 : 1000000);
|
||||
default:
|
||||
ERROR_THROW("Unhandled SysClkProfile: %u", profile);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Config::GetProfiles(std::uint64_t tid, SysClkTitleProfileList* out_profiles)
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
|
||||
for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++)
|
||||
{
|
||||
for(unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
out_profiles->mhzMap[profile][module] = FindClockMHz(tid, (SysClkModule)module, (SysClkProfile)profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Config::SetProfiles(std::uint64_t tid, SysClkTitleProfileList* profiles, bool immediate)
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
uint8_t numProfiles = 0;
|
||||
|
||||
char section[17] = {0};
|
||||
snprintf(section, sizeof(section), "%016lX", tid);
|
||||
|
||||
std::vector<std::string> keys;
|
||||
std::vector<std::string> values;
|
||||
keys.reserve(SysClkProfile_EnumMax * SysClkModule_EnumMax);
|
||||
values.reserve(SysClkProfile_EnumMax * SysClkModule_EnumMax);
|
||||
|
||||
std::uint32_t* mhz = &profiles->mhz[0];
|
||||
|
||||
for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++)
|
||||
{
|
||||
for(unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
if(*mhz)
|
||||
{
|
||||
numProfiles++;
|
||||
|
||||
std::string key = std::string(Board::GetProfileName((SysClkProfile)profile, false)) +
|
||||
"_" +
|
||||
Board::GetModuleName((SysClkModule)module, false);
|
||||
std::string value = std::to_string(*mhz);
|
||||
|
||||
keys.push_back(key);
|
||||
values.push_back(value);
|
||||
}
|
||||
mhz++;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const char*> keyPointers;
|
||||
std::vector<const char*> valuePointers;
|
||||
keyPointers.reserve(keys.size() + 1);
|
||||
valuePointers.reserve(values.size() + 1);
|
||||
|
||||
for(size_t i = 0; i < keys.size(); i++) {
|
||||
keyPointers.push_back(keys[i].c_str());
|
||||
valuePointers.push_back(values[i].c_str());
|
||||
}
|
||||
keyPointers.push_back(NULL);
|
||||
valuePointers.push_back(NULL);
|
||||
|
||||
if(!ini_putsection(section, keyPointers.data(), valuePointers.data(), this->path.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(immediate)
|
||||
{
|
||||
mhz = &profiles->mhz[0];
|
||||
this->profileCountMap[tid] = numProfiles;
|
||||
for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++)
|
||||
{
|
||||
for(unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
if(*mhz)
|
||||
{
|
||||
this->profileMHzMap[std::make_tuple(tid, (SysClkProfile)profile, (SysClkModule)module)] = *mhz;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->profileMHzMap.erase(std::make_tuple(tid, (SysClkProfile)profile, (SysClkModule)module));
|
||||
}
|
||||
mhz++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::uint8_t Config::GetProfileCount(std::uint64_t tid)
|
||||
{
|
||||
std::map<std::uint64_t, std::uint8_t>::iterator it = this->profileCountMap.find(tid);
|
||||
if (it == this->profileCountMap.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int Config::BrowseIniFunc(const char* section, const char* key, const char* value, void* userdata)
|
||||
{
|
||||
Config* config = (Config*)userdata;
|
||||
std::uint64_t input;
|
||||
if(!strcmp(section, CONFIG_VAL_SECTION))
|
||||
{
|
||||
for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++)
|
||||
{
|
||||
if(!strcmp(key, sysclkFormatConfigValue((SysClkConfigValue)kval, false)))
|
||||
{
|
||||
input = strtoul(value, NULL, 0);
|
||||
if(!sysclkValidConfigValue((SysClkConfigValue)kval, input))
|
||||
{
|
||||
input = sysclkDefaultConfigValue((SysClkConfigValue)kval);
|
||||
FileUtils::LogLine("[cfg] Invalid value for key '%s' in section '%s': using default %d", key, section, input);
|
||||
}
|
||||
config->configValues[kval] = input;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized config value", key, section);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::uint64_t tid = strtoul(section, NULL, 16);
|
||||
|
||||
if(!tid || strlen(section) != 16)
|
||||
{
|
||||
FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid TitleID", key, section);
|
||||
return 1;
|
||||
}
|
||||
|
||||
SysClkProfile parsedProfile = SysClkProfile_EnumMax;
|
||||
SysClkModule parsedModule = SysClkModule_EnumMax;
|
||||
|
||||
for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++)
|
||||
{
|
||||
const char* profileCode = Board::GetProfileName((SysClkProfile)profile, false);
|
||||
size_t profileCodeLen = strlen(profileCode);
|
||||
|
||||
if(!strncmp(key, profileCode, profileCodeLen) && key[profileCodeLen] == '_')
|
||||
{
|
||||
const char* subkey = key + profileCodeLen + 1;
|
||||
|
||||
for(unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
const char* moduleCode = Board::GetModuleName((SysClkModule)module, false);
|
||||
size_t moduleCodeLen = strlen(moduleCode);
|
||||
if(!strncmp(subkey, moduleCode, moduleCodeLen) && subkey[moduleCodeLen] == '\0')
|
||||
{
|
||||
parsedProfile = (SysClkProfile)profile;
|
||||
parsedModule = (SysClkModule)module;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(parsedModule == SysClkModule_EnumMax || parsedProfile == SysClkProfile_EnumMax)
|
||||
{
|
||||
FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized key", key, section);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::uint32_t mhz = strtoul(value, NULL, 10);
|
||||
if(!mhz)
|
||||
{
|
||||
FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid value", key, section);
|
||||
return 1;
|
||||
}
|
||||
|
||||
config->profileMHzMap[std::make_tuple(tid, parsedProfile, parsedModule)] = mhz;
|
||||
std::map<std::uint64_t, std::uint8_t>::iterator it = config->profileCountMap.find(tid);
|
||||
if (it == config->profileCountMap.end())
|
||||
{
|
||||
config->profileCountMap[tid] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Config::SetEnabled(bool enabled)
|
||||
{
|
||||
this->enabled = enabled;
|
||||
}
|
||||
|
||||
bool Config::Enabled()
|
||||
{
|
||||
return this->enabled;
|
||||
}
|
||||
|
||||
void Config::SetOverrideHz(SysClkModule module, std::uint32_t hz)
|
||||
{
|
||||
ASSERT_ENUM_VALID(SysClkModule, module);
|
||||
|
||||
std::scoped_lock lock{this->overrideMutex};
|
||||
|
||||
this->overrideFreqs[module] = hz;
|
||||
}
|
||||
|
||||
std::uint32_t Config::GetOverrideHz(SysClkModule module)
|
||||
{
|
||||
ASSERT_ENUM_VALID(SysClkModule, module);
|
||||
|
||||
std::scoped_lock lock{this->overrideMutex};
|
||||
|
||||
return this->overrideFreqs[module];
|
||||
}
|
||||
|
||||
std::uint64_t Config::GetConfigValue(SysClkConfigValue kval)
|
||||
{
|
||||
ASSERT_ENUM_VALID(SysClkConfigValue, kval);
|
||||
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
|
||||
return this->configValues[kval];
|
||||
}
|
||||
|
||||
const char* Config::GetConfigValueName(SysClkConfigValue kval, bool pretty)
|
||||
{
|
||||
ASSERT_ENUM_VALID(SysClkConfigValue, kval);
|
||||
|
||||
const char* result = sysclkFormatConfigValue(kval, pretty);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Config::GetConfigValues(SysClkConfigValueList* out_configValues)
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
|
||||
for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++)
|
||||
{
|
||||
out_configValues->values[kval] = this->configValues[kval];
|
||||
}
|
||||
}
|
||||
|
||||
bool Config::SetConfigValues(SysClkConfigValueList* configValues, bool immediate)
|
||||
{
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
|
||||
std::vector<const char*> iniKeys;
|
||||
std::vector<std::string> iniValues;
|
||||
|
||||
iniKeys.reserve(SysClkConfigValue_EnumMax + 1);
|
||||
iniValues.reserve(SysClkConfigValue_EnumMax);
|
||||
|
||||
for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++)
|
||||
{
|
||||
if(!sysclkValidConfigValue((SysClkConfigValue)kval, configValues->values[kval]) ||
|
||||
configValues->values[kval] == sysclkDefaultConfigValue((SysClkConfigValue)kval))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
iniValues.push_back(std::to_string(configValues->values[kval]));
|
||||
iniKeys.push_back(sysclkFormatConfigValue((SysClkConfigValue)kval, false));
|
||||
}
|
||||
|
||||
// Null terminate
|
||||
iniKeys.push_back(NULL);
|
||||
|
||||
// Build pointer array for ini function
|
||||
std::vector<const char*> valuePointers;
|
||||
valuePointers.reserve(iniValues.size() + 1);
|
||||
for(const auto& val : iniValues) {
|
||||
valuePointers.push_back(val.c_str());
|
||||
}
|
||||
valuePointers.push_back(NULL);
|
||||
|
||||
if(!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), this->path.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only actually apply changes in memory after a successful save
|
||||
if(immediate)
|
||||
{
|
||||
for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++)
|
||||
{
|
||||
if(sysclkValidConfigValue((SysClkConfigValue)kval, configValues->values[kval]))
|
||||
{
|
||||
this->configValues[kval] = configValues->values[kval];
|
||||
}
|
||||
else
|
||||
{
|
||||
this->configValues[kval] = sysclkDefaultConfigValue((SysClkConfigValue)kval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Config::ResetConfigValue(SysClkConfigValue kval)
|
||||
{
|
||||
if (!SYSCLK_ENUM_VALID(SysClkConfigValue, kval)) {
|
||||
FileUtils::LogLine("[cfg] Invalid SysClkConfigValue: %u", kval);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::scoped_lock lock{this->configMutex};
|
||||
|
||||
std::uint64_t defaultValue = sysclkDefaultConfigValue(kval);
|
||||
|
||||
std::vector<const char*> iniKeys;
|
||||
std::vector<std::string> iniValues;
|
||||
|
||||
iniKeys.reserve(2);
|
||||
iniValues.reserve(1);
|
||||
|
||||
const char* keyStr = sysclkFormatConfigValue(kval, false);
|
||||
|
||||
iniKeys.push_back(keyStr);
|
||||
iniValues.push_back("");
|
||||
|
||||
iniKeys.push_back(NULL);
|
||||
|
||||
std::vector<const char*> valuePointers;
|
||||
valuePointers.reserve(iniValues.size() + 1);
|
||||
for (const auto& val : iniValues) {
|
||||
valuePointers.push_back(val.c_str());
|
||||
}
|
||||
valuePointers.push_back(NULL);
|
||||
|
||||
if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), this->path.c_str())) {
|
||||
FileUtils::LogLine("[cfg] Failed to reset config value %u in INI", kval);
|
||||
return false;
|
||||
}
|
||||
|
||||
this->configValues[kval] = defaultValue;
|
||||
FileUtils::LogLine("[cfg] Reset config value %u to default: %llu", kval, defaultValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
91
Source/rewrite-hoc-clk/sysmodule/src/config.h
Normal file
91
Source/rewrite-hoc-clk/sysmodule/src/config.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 <atomic>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <switch.h>
|
||||
#include <minIni.h>
|
||||
#include <nxExt.h>
|
||||
#include "board.h"
|
||||
|
||||
#define CONFIG_VAL_SECTION "values"
|
||||
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
Config(std::string path);
|
||||
virtual ~Config();
|
||||
|
||||
static Config* CreateDefault();
|
||||
|
||||
bool Refresh();
|
||||
|
||||
bool HasProfilesLoaded();
|
||||
|
||||
std::uint8_t GetProfileCount(std::uint64_t tid);
|
||||
void GetProfiles(std::uint64_t tid, SysClkTitleProfileList* out_profiles);
|
||||
bool SetProfiles(std::uint64_t tid, SysClkTitleProfileList* profiles, bool immediate);
|
||||
std::uint32_t GetAutoClockHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile, bool returnRaw);
|
||||
|
||||
void SetEnabled(bool enabled);
|
||||
bool Enabled();
|
||||
void SetOverrideHz(SysClkModule module, std::uint32_t hz);
|
||||
std::uint32_t GetOverrideHz(SysClkModule module);
|
||||
|
||||
std::uint64_t GetConfigValue(SysClkConfigValue val);
|
||||
const char* GetConfigValueName(SysClkConfigValue val, bool pretty);
|
||||
void GetConfigValues(SysClkConfigValueList* out_configValues);
|
||||
bool SetConfigValues(SysClkConfigValueList* configValues, bool immediate);
|
||||
bool ResetConfigValue(SysClkConfigValue kval);
|
||||
bool SetInternalValues(bool immediate);
|
||||
bool SetConfigValue(SysClkConfigValue kval, std::uint64_t value, bool immediate = true);
|
||||
|
||||
uint64_t configValues[SysClkConfigValue_EnumMax];
|
||||
protected:
|
||||
void Load();
|
||||
void Close();
|
||||
bool kipOverride[SysClkConfigValue_EnumMax];
|
||||
time_t CheckModificationTime();
|
||||
std::uint32_t FindClockMHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile);
|
||||
std::uint32_t FindClockHzFromProfiles(std::uint64_t tid, SysClkModule module, std::initializer_list<SysClkProfile> profiles, u32 mhzMultiplier = 1000000);
|
||||
static int BrowseIniFunc(const char* section, const char* key, const char* value, void* userdata);
|
||||
|
||||
std::map<std::tuple<std::uint64_t, SysClkProfile, SysClkModule>, std::uint32_t> profileMHzMap;
|
||||
std::map<std::uint64_t, std::uint8_t> profileCountMap;
|
||||
bool loaded;
|
||||
std::string path;
|
||||
time_t mtime;
|
||||
LockableMutex configMutex;
|
||||
LockableMutex overrideMutex;
|
||||
std::atomic_bool enabled;
|
||||
std::uint32_t overrideFreqs[SysClkModule_EnumMax];
|
||||
};
|
||||
54
Source/rewrite-hoc-clk/sysmodule/src/errors.cpp
Normal file
54
Source/rewrite-hoc-clk/sysmodule/src/errors.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "errors.h"
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include "file_utils.h"
|
||||
void Errors::ThrowException(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
const char* msg = Errors::FormatMessage(format, args);
|
||||
va_end(args);
|
||||
FileUtils::LogLine(format, args);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
const char* Errors::FormatMessage(const char* format, va_list args)
|
||||
{
|
||||
size_t len = vsnprintf(NULL, 0, format, args) * sizeof(char);
|
||||
char* buf = (char*)malloc(len + 1);
|
||||
if (buf == NULL)
|
||||
{
|
||||
return format;
|
||||
}
|
||||
|
||||
vsnprintf(buf, len + 1, format, args);
|
||||
|
||||
return buf;
|
||||
}
|
||||
52
Source/rewrite-hoc-clk/sysmodule/src/errors.h
Normal file
52
Source/rewrite-hoc-clk/sysmodule/src/errors.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 <switch.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#define ERROR_THROW(format, ...) Errors::ThrowException(format "\n in %s:%u", ##__VA_ARGS__, __FILE__, __LINE__)
|
||||
#define ERROR_RESULT_THROW(rc, format, ...) ERROR_THROW(format "\n RC: [0x%x] %04d-%04d", ##__VA_ARGS__, rc, R_MODULE(rc), R_DESCRIPTION(rc))
|
||||
#define ASSERT_RESULT_OK(rc, format, ...) \
|
||||
if (R_FAILED(rc)) \
|
||||
{ \
|
||||
ERROR_RESULT_THROW(rc, "ASSERT_RESULT_OK: " format, ##__VA_ARGS__); \
|
||||
}
|
||||
#define ASSERT_ENUM_VALID(n, v) \
|
||||
if(!SYSCLK_ENUM_VALID(n, v)) { \
|
||||
ERROR_THROW("No such %s: %u", #n, v); \
|
||||
}
|
||||
|
||||
class Errors
|
||||
{
|
||||
public:
|
||||
static void ThrowException(const char* format, ...);
|
||||
|
||||
protected:
|
||||
static const char* FormatMessage(const char* format, va_list args);
|
||||
};
|
||||
217
Source/rewrite-hoc-clk/sysmodule/src/file_utils.cpp
Normal file
217
Source/rewrite-hoc-clk/sysmodule/src/file_utils.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "file_utils.h"
|
||||
#include <nxExt.h>
|
||||
|
||||
static LockableMutex g_log_mutex;
|
||||
static LockableMutex g_csv_mutex;
|
||||
static std::atomic_bool g_has_initialized = false;
|
||||
static bool g_log_enabled = false;
|
||||
static std::uint64_t g_last_flag_check = 0;
|
||||
|
||||
extern "C" void __libnx_init_time(void);
|
||||
|
||||
static void _FileUtils_InitializeThreadFunc(void* args)
|
||||
{
|
||||
FileUtils::Initialize();
|
||||
}
|
||||
|
||||
bool FileUtils::IsInitialized()
|
||||
{
|
||||
return g_has_initialized;
|
||||
}
|
||||
|
||||
void FileUtils::LogLine(const char* format, ...)
|
||||
{
|
||||
std::scoped_lock lock{g_log_mutex};
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
if (g_has_initialized)
|
||||
{
|
||||
FileUtils::RefreshFlags(false);
|
||||
|
||||
if(g_log_enabled)
|
||||
{
|
||||
FILE* file = fopen(FILE_LOG_FILE_PATH, "a");
|
||||
|
||||
if (file)
|
||||
{
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
struct tm* nowTm = localtime(&now.tv_sec);
|
||||
|
||||
fprintf(file, "[%04d-%02d-%02d %02d:%02d:%02d.%03ld] ", nowTm->tm_year+1900, nowTm->tm_mon+1, nowTm->tm_mday, nowTm->tm_hour, nowTm->tm_min, nowTm->tm_sec, now.tv_nsec / 1000000UL);
|
||||
vfprintf(file, format, args);
|
||||
fprintf(file, "\n");
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void FileUtils::WriteContextToCsv(const SysClkContext* context)
|
||||
{
|
||||
std::scoped_lock lock{g_csv_mutex};
|
||||
|
||||
FILE* file = fopen(FILE_CONTEXT_CSV_PATH, "a");
|
||||
|
||||
if (file)
|
||||
{
|
||||
// Print header
|
||||
if(!ftell(file))
|
||||
{
|
||||
fprintf(file, "timestamp,profile,app_tid");
|
||||
|
||||
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
fprintf(file, ",%s_hz", sysclkFormatModule((SysClkModule)module, false));
|
||||
}
|
||||
|
||||
for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++)
|
||||
{
|
||||
fprintf(file, ",%s_milliC", sysclkFormatThermalSensor((SysClkThermalSensor)sensor, false));
|
||||
}
|
||||
|
||||
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
fprintf(file, ",%s_real_hz", sysclkFormatModule((SysClkModule)module, false));
|
||||
}
|
||||
|
||||
for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++)
|
||||
{
|
||||
fprintf(file, ",%s_mw", sysclkFormatPowerSensor((SysClkPowerSensor)sensor, false));
|
||||
}
|
||||
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
|
||||
fprintf(file, "%ld%03ld,%s,%016lx", now.tv_sec, now.tv_nsec / 1000000UL, sysclkFormatProfile(context->profile, false), context->applicationId);
|
||||
|
||||
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
fprintf(file, ",%d", context->freqs[module]);
|
||||
}
|
||||
|
||||
for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++)
|
||||
{
|
||||
fprintf(file, ",%d", context->temps[sensor]);
|
||||
}
|
||||
|
||||
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
fprintf(file, ",%d", context->realFreqs[module]);
|
||||
}
|
||||
|
||||
for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++)
|
||||
{
|
||||
fprintf(file, ",%d", context->power[sensor]);
|
||||
}
|
||||
|
||||
fprintf(file, "\n");
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
void FileUtils::RefreshFlags(bool force)
|
||||
{
|
||||
std::uint64_t now = armTicksToNs(armGetSystemTick());
|
||||
if(!force && (now - g_last_flag_check) < FILE_FLAG_CHECK_INTERVAL_NS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE* file = fopen(FILE_LOG_FLAG_PATH, "r");
|
||||
if (file)
|
||||
{
|
||||
g_log_enabled = true;
|
||||
fclose(file);
|
||||
} else {
|
||||
g_log_enabled = false;
|
||||
}
|
||||
|
||||
g_last_flag_check = now;
|
||||
}
|
||||
|
||||
void FileUtils::InitializeAsync()
|
||||
{
|
||||
Thread initThread = {0};
|
||||
threadCreate(&initThread, _FileUtils_InitializeThreadFunc, NULL, NULL, 0x4000, 0x15, 0);
|
||||
threadStart(&initThread);
|
||||
}
|
||||
|
||||
Result FileUtils::Initialize()
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
{
|
||||
rc = timeInitialize();
|
||||
}
|
||||
|
||||
__libnx_init_time();
|
||||
timeExit();
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
{
|
||||
rc = fsInitialize();
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
{
|
||||
rc = fsdevMountSdmc();
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
{
|
||||
FileUtils::RefreshFlags(true);
|
||||
g_has_initialized = true;
|
||||
FileUtils::LogLine("=== hoc-clk " TARGET_VERSION " ===");
|
||||
FileUtils::LogLine("by m4xw, natinusala, p-sam, Souldbminer and Lightos_");
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void FileUtils::Exit()
|
||||
{
|
||||
if (!g_has_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_has_initialized = false;
|
||||
g_log_enabled = false;
|
||||
|
||||
fsdevUnmountAll();
|
||||
fsExit();
|
||||
}
|
||||
55
Source/rewrite-hoc-clk/sysmodule/src/file_utils.h
Normal file
55
Source/rewrite-hoc-clk/sysmodule/src/file_utils.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 <switch.h>
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
#include <cstdarg>
|
||||
#include <sysclk.h>
|
||||
|
||||
#define FILE_CONFIG_DIR "/config/" TARGET
|
||||
#define FILE_FLAG_CHECK_INTERVAL_NS (10000ULL * 1000000000ULL)
|
||||
#define FILE_CONTEXT_CSV_PATH FILE_CONFIG_DIR "/context.csv"
|
||||
#define FILE_LOG_FLAG_PATH FILE_CONFIG_DIR "/log.flag"
|
||||
#define FILE_LOG_FILE_PATH FILE_CONFIG_DIR "/log.txt"
|
||||
|
||||
class FileUtils
|
||||
{
|
||||
public:
|
||||
static void Exit();
|
||||
static Result Initialize();
|
||||
static bool IsInitialized();
|
||||
static bool IsLogEnabled();
|
||||
static void InitializeAsync();
|
||||
static void LogLine(const char* format, ...);
|
||||
static void WriteContextToCsv(const SysClkContext* context);
|
||||
protected:
|
||||
static void RefreshFlags(bool force);
|
||||
};
|
||||
137
Source/rewrite-hoc-clk/sysmodule/src/integrations.cpp
Normal file
137
Source/rewrite-hoc-clk/sysmodule/src/integrations.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "integrations.h"
|
||||
#include <sys/stat.h>
|
||||
#include <SaltyNX.h>
|
||||
#include "process_management.h"
|
||||
|
||||
SysDockIntegration::SysDockIntegration() {
|
||||
}
|
||||
|
||||
bool SysDockIntegration::getCurrentSysDockState() {
|
||||
struct stat st = {0};
|
||||
return stat("sdmc:/atmosphere/contents/42000000000000A0/flags/boot2.flag", &st) == 0;
|
||||
}
|
||||
|
||||
SaltyNXIntegration::SaltyNXIntegration() {
|
||||
}
|
||||
|
||||
void SaltyNXIntegration::LoadSaltyNX() {
|
||||
if (!CheckPort())
|
||||
return;
|
||||
LoadSharedMemory();
|
||||
}
|
||||
|
||||
bool SaltyNXIntegration::getCurrentSaltyNXState() {
|
||||
struct stat st = {0};
|
||||
return stat("sdmc:/atmosphere/contents/0000000000534C56/flags/boot2.flag", &st) == 0;
|
||||
}
|
||||
|
||||
bool SaltyNXIntegration::CheckPort() {
|
||||
Handle saltysd;
|
||||
|
||||
for (int i = 0; i < 67; i++) {
|
||||
if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) {
|
||||
svcCloseHandle(saltysd);
|
||||
break;
|
||||
}
|
||||
if (i == 66) return false;
|
||||
svcSleepThread(1'000'000);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 67; i++) {
|
||||
if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) {
|
||||
svcCloseHandle(saltysd);
|
||||
return true;
|
||||
}
|
||||
svcSleepThread(1'000'000);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SaltyNXIntegration::LoadSharedMemory() {
|
||||
if (SaltySD_Connect())
|
||||
return;
|
||||
SaltySD_GetSharedMemoryHandle(&remoteSharedMemory);
|
||||
SaltySD_Term();
|
||||
shmemLoadRemote(&_sharedmemory, remoteSharedMemory, 0x1000, Perm_Rw);
|
||||
if (!shmemMap(&_sharedmemory))
|
||||
SharedMemoryUsed = true;
|
||||
}
|
||||
|
||||
void SaltyNXIntegration::searchSharedMemoryBlock(uintptr_t base) {
|
||||
ptrdiff_t search_offset = 0;
|
||||
while (search_offset < 0x1000) {
|
||||
NxFps = (NxFpsSharedBlock*)(base + search_offset);
|
||||
if (NxFps->MAGIC == 0x465053)
|
||||
return;
|
||||
search_offset += 4;
|
||||
}
|
||||
NxFps = 0;
|
||||
}
|
||||
|
||||
u64 prevTid = 0;
|
||||
|
||||
u8 SaltyNXIntegration::GetFPS() {
|
||||
if (!SharedMemoryUsed)
|
||||
return 254;
|
||||
|
||||
u64 tid = ProcessManagement::GetCurrentApplicationId();
|
||||
if (tid == 0)
|
||||
return 254;
|
||||
|
||||
if (prevTid != tid) {
|
||||
NxFps = 0;
|
||||
prevTid = tid;
|
||||
}
|
||||
|
||||
if (!NxFps) {
|
||||
uintptr_t base = (uintptr_t)shmemGetAddr(&_sharedmemory);
|
||||
searchSharedMemoryBlock(base);
|
||||
}
|
||||
|
||||
return NxFps ? NxFps->FPS : 254;
|
||||
}
|
||||
|
||||
u16 SaltyNXIntegration::GetResolutionHeight() {
|
||||
if (!SharedMemoryUsed)
|
||||
return 0;
|
||||
|
||||
u64 tid = ProcessManagement::GetCurrentApplicationId();
|
||||
if (tid == 0)
|
||||
return 0;
|
||||
|
||||
if (prevTid != tid) {
|
||||
NxFps = 0;
|
||||
prevTid = tid;
|
||||
}
|
||||
|
||||
if (!NxFps) {
|
||||
uintptr_t base = (uintptr_t)shmemGetAddr(&_sharedmemory);
|
||||
searchSharedMemoryBlock(base);
|
||||
}
|
||||
if(NxFps) {
|
||||
NxFps->renderCalls[0].calls = 0xFFFF;
|
||||
svcSleepThread(10*1000);
|
||||
|
||||
return NxFps->renderCalls[0].height == 0 ? NxFps->viewportCalls[0].height : NxFps->renderCalls[0].height;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
94
Source/rewrite-hoc-clk/sysmodule/src/integrations.h
Normal file
94
Source/rewrite-hoc-clk/sysmodule/src/integrations.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <nxExt.h>
|
||||
#include <sysclk.h>
|
||||
#include <switch.h>
|
||||
#include "errors.h"
|
||||
#include "file_utils.h"
|
||||
|
||||
#include "clock_manager.h"
|
||||
|
||||
class SysDockIntegration {
|
||||
public:
|
||||
SysDockIntegration();
|
||||
|
||||
bool getCurrentSysDockState();
|
||||
};
|
||||
|
||||
class SaltyNXIntegration {
|
||||
public:
|
||||
struct resolutionCalls {
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t calls;
|
||||
};
|
||||
|
||||
struct NxFpsSharedBlock {
|
||||
uint32_t MAGIC;
|
||||
uint8_t FPS;
|
||||
float FPSavg;
|
||||
bool pluginActive;
|
||||
uint8_t FPSlocked;
|
||||
uint8_t FPSmode;
|
||||
uint8_t ZeroSync;
|
||||
uint8_t patchApplied;
|
||||
uint8_t API;
|
||||
uint32_t FPSticks[10];
|
||||
uint8_t Buffers;
|
||||
uint8_t SetBuffers;
|
||||
uint8_t ActiveBuffers;
|
||||
uint8_t SetActiveBuffers;
|
||||
union {
|
||||
struct {
|
||||
bool handheld: 1;
|
||||
bool docked: 1;
|
||||
unsigned int reserved: 6;
|
||||
} NX_PACKED ds;
|
||||
uint8_t general;
|
||||
} displaySync;
|
||||
resolutionCalls renderCalls[8];
|
||||
resolutionCalls viewportCalls[8];
|
||||
bool forceOriginalRefreshRate;
|
||||
bool dontForce60InDocked;
|
||||
bool forceSuspend;
|
||||
uint8_t currentRefreshRate;
|
||||
float readSpeedPerSecond;
|
||||
uint8_t FPSlockedDocked;
|
||||
uint64_t frameNumber;
|
||||
} NX_PACKED;
|
||||
|
||||
NxFpsSharedBlock* NxFps = 0;
|
||||
SharedMemory _sharedmemory = {};
|
||||
bool SharedMemoryUsed = false;
|
||||
Handle remoteSharedMemory = 1;
|
||||
SaltyNXIntegration();
|
||||
void LoadSaltyNX();
|
||||
bool getCurrentSaltyNXState();
|
||||
|
||||
bool CheckPort();
|
||||
void LoadSharedMemory();
|
||||
void searchSharedMemoryBlock(uintptr_t base);
|
||||
u8 GetFPS();
|
||||
u16 GetResolutionHeight();
|
||||
};
|
||||
374
Source/rewrite-hoc-clk/sysmodule/src/ipc_service.cpp
Normal file
374
Source/rewrite-hoc-clk/sysmodule/src/ipc_service.cpp
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "ipc_service.h"
|
||||
#include <cstring>
|
||||
#include <switch.h>
|
||||
#include "file_utils.h"
|
||||
#include "errors.h"
|
||||
#include "clock_manager.h"
|
||||
IpcService::IpcService(ClockManager* clockMgr)
|
||||
{
|
||||
std::int32_t priority;
|
||||
Result rc = svcGetThreadPriority(&priority, CUR_THREAD_HANDLE);
|
||||
ASSERT_RESULT_OK(rc, "svcGetThreadPriority");
|
||||
rc = ipcServerInit(&this->server, SYSCLK_IPC_SERVICE_NAME, 42);
|
||||
ASSERT_RESULT_OK(rc, "ipcServerInit");
|
||||
rc = threadCreate(&this->thread, &IpcService::ProcessThreadFunc, this, NULL, 0x2000, priority, -2);
|
||||
ASSERT_RESULT_OK(rc, "threadCreate");
|
||||
|
||||
this->running = false;
|
||||
this->clockMgr = clockMgr;
|
||||
|
||||
}
|
||||
|
||||
void IpcService::SetRunning(bool running)
|
||||
{
|
||||
std::scoped_lock lock{this->threadMutex};
|
||||
if(this->running == running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->running = running;
|
||||
|
||||
if(running)
|
||||
{
|
||||
Result rc = threadStart(&this->thread);
|
||||
ASSERT_RESULT_OK(rc, "threadStart");
|
||||
}
|
||||
else
|
||||
{
|
||||
svcCancelSynchronization(this->thread.handle);
|
||||
threadWaitForExit(&this->thread);
|
||||
}
|
||||
}
|
||||
|
||||
IpcService::~IpcService()
|
||||
{
|
||||
this->SetRunning(false);
|
||||
Result rc = threadClose(&this->thread);
|
||||
ASSERT_RESULT_OK(rc, "threadClose");
|
||||
rc = ipcServerExit(&this->server);
|
||||
ASSERT_RESULT_OK(rc, "ipcServerExit");
|
||||
}
|
||||
|
||||
void IpcService::ProcessThreadFunc(void* arg)
|
||||
{
|
||||
Result rc;
|
||||
IpcService* ipcSrv = (IpcService*)arg;
|
||||
while(true)
|
||||
{
|
||||
rc = ipcServerProcess(&ipcSrv->server, &IpcService::ServiceHandlerFunc, arg);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
if(rc == KERNELRESULT(Cancelled))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(rc != KERNELRESULT(ConnectionClosed))
|
||||
{
|
||||
FileUtils::LogLine("[ipc] ipcServerProcess: [0x%x] %04d-%04d", rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8* out_data, size_t* out_dataSize)
|
||||
{
|
||||
IpcService* ipcSrv = (IpcService*)arg;
|
||||
|
||||
switch(r->data.cmdId)
|
||||
{
|
||||
case SysClkIpcCmd_GetApiVersion:
|
||||
*out_dataSize = sizeof(u32);
|
||||
return ipcSrv->GetApiVersion((u32*)out_data);
|
||||
|
||||
case SysClkIpcCmd_GetVersionString:
|
||||
if(r->hipc.meta.num_recv_buffers >= 1)
|
||||
{
|
||||
return ipcSrv->GetVersionString(
|
||||
(char*)hipcGetBufferAddress(r->hipc.data.recv_buffers),
|
||||
hipcGetBufferSize(r->hipc.data.recv_buffers)
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case SysClkIpcCmd_GetCurrentContext:
|
||||
if(r->data.size >= sizeof(std::uint64_t) && r->hipc.meta.num_recv_buffers >= 1)
|
||||
{
|
||||
size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers);
|
||||
if(bufSize >= sizeof(SysClkContext))
|
||||
{
|
||||
return ipcSrv->GetCurrentContext((SysClkContext*)hipcGetBufferAddress(r->hipc.data.recv_buffers));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SysClkIpcCmd_Exit:
|
||||
return ipcSrv->Exit();
|
||||
|
||||
case SysClkIpcCmd_GetProfileCount:
|
||||
if(r->data.size >= sizeof(std::uint64_t))
|
||||
{
|
||||
*out_dataSize = sizeof(std::uint8_t);
|
||||
return ipcSrv->GetProfileCount((std::uint64_t*)r->data.ptr, (std::uint8_t*)out_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case SysClkIpcCmd_GetProfiles:
|
||||
if(r->data.size >= sizeof(std::uint64_t) && r->hipc.meta.num_recv_buffers >= 1)
|
||||
{
|
||||
size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers);
|
||||
if(bufSize >= sizeof(SysClkTitleProfileList))
|
||||
{
|
||||
return ipcSrv->GetProfiles((std::uint64_t*)r->data.ptr, (SysClkTitleProfileList*)hipcGetBufferAddress(r->hipc.data.recv_buffers));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SysClkIpcCmd_SetProfiles:
|
||||
if(r->data.size >= sizeof(SysClkIpc_SetProfiles_Args))
|
||||
{
|
||||
return ipcSrv->SetProfiles((SysClkIpc_SetProfiles_Args*)r->data.ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
case SysClkIpcCmd_SetEnabled:
|
||||
if(r->data.size >= sizeof(std::uint8_t))
|
||||
{
|
||||
return ipcSrv->SetEnabled((std::uint8_t*)r->data.ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
case SysClkIpcCmd_SetOverride:
|
||||
if(r->data.size >= sizeof(SysClkIpc_SetOverride_Args))
|
||||
{
|
||||
return ipcSrv->SetOverride((SysClkIpc_SetOverride_Args*)r->data.ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
case SysClkIpcCmd_GetConfigValues:
|
||||
if(r->hipc.meta.num_recv_buffers >= 1)
|
||||
{
|
||||
size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers);
|
||||
if(bufSize >= sizeof(SysClkConfigValueList))
|
||||
{
|
||||
return ipcSrv->GetConfigValues((SysClkConfigValueList*)hipcGetBufferAddress(r->hipc.data.recv_buffers));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SysClkIpcCmd_SetConfigValues:
|
||||
if(r->hipc.meta.num_send_buffers >= 1)
|
||||
{
|
||||
size_t bufSize = hipcGetBufferSize(r->hipc.data.send_buffers);
|
||||
if(bufSize >= sizeof(SysClkConfigValueList))
|
||||
{
|
||||
return ipcSrv->SetConfigValues((SysClkConfigValueList*)hipcGetBufferAddress(r->hipc.data.send_buffers));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SysClkIpcCmd_GetFreqList:
|
||||
if(r->data.size >= sizeof(SysClkIpc_GetFreqList_Args) && r->hipc.meta.num_recv_buffers >= 1)
|
||||
{
|
||||
*out_dataSize = sizeof(std::uint32_t);
|
||||
return ipcSrv->GetFreqList(
|
||||
(SysClkIpc_GetFreqList_Args*)r->data.ptr,
|
||||
(std::uint32_t*)hipcGetBufferAddress(r->hipc.data.recv_buffers),
|
||||
hipcGetBufferSize(r->hipc.data.recv_buffers),
|
||||
(std::uint32_t*)out_data
|
||||
);
|
||||
}
|
||||
break;
|
||||
case HocClkIpcCmd_SetKipData:
|
||||
if (r->data.size >= 0) {
|
||||
return ipcSrv->SetKipData();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SYSCLK_ERROR(Generic);
|
||||
}
|
||||
|
||||
Result IpcService::GetApiVersion(u32* out_version)
|
||||
{
|
||||
*out_version = SYSCLK_IPC_API_VERSION;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetVersionString(char* out_buf, size_t bufSize)
|
||||
{
|
||||
if(bufSize)
|
||||
{
|
||||
strncpy(out_buf, TARGET_VERSION, bufSize-1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetCurrentContext(SysClkContext* out_ctx)
|
||||
{
|
||||
*out_ctx = this->clockMgr->GetCurrentContext();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::Exit()
|
||||
{
|
||||
this->clockMgr->SetRunning(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetProfileCount(std::uint64_t* tid, std::uint8_t* out_count)
|
||||
{
|
||||
Config* config = this->clockMgr->GetConfig();
|
||||
if(!config->HasProfilesLoaded())
|
||||
{
|
||||
return SYSCLK_ERROR(ConfigNotLoaded);
|
||||
}
|
||||
|
||||
*out_count = config->GetProfileCount(*tid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetProfiles(std::uint64_t* tid, SysClkTitleProfileList* out_profiles)
|
||||
{
|
||||
Config* config = this->clockMgr->GetConfig();
|
||||
if(!config->HasProfilesLoaded())
|
||||
{
|
||||
return SYSCLK_ERROR(ConfigNotLoaded);
|
||||
}
|
||||
|
||||
config->GetProfiles(*tid, out_profiles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::SetProfiles(SysClkIpc_SetProfiles_Args* args)
|
||||
{
|
||||
Config* config = this->clockMgr->GetConfig();
|
||||
if(!config->HasProfilesLoaded())
|
||||
{
|
||||
return SYSCLK_ERROR(ConfigNotLoaded);
|
||||
}
|
||||
|
||||
SysClkTitleProfileList profiles = args->profiles;
|
||||
|
||||
if(!config->SetProfiles(args->tid, &profiles, true))
|
||||
{
|
||||
return SYSCLK_ERROR(ConfigSaveFailed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::SetEnabled(std::uint8_t* enabled)
|
||||
{
|
||||
Config* config = this->clockMgr->GetConfig();
|
||||
config->SetEnabled(*enabled);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::SetOverride(SysClkIpc_SetOverride_Args* args)
|
||||
{
|
||||
SysClkModule module = args->module;
|
||||
std::uint32_t hz = args->hz;
|
||||
|
||||
if(!SYSCLK_ENUM_VALID(SysClkModule, args->module))
|
||||
{
|
||||
return SYSCLK_ERROR(Generic);
|
||||
}
|
||||
|
||||
Config* config = this->clockMgr->GetConfig();
|
||||
config->SetOverrideHz(module, hz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetConfigValues(SysClkConfigValueList* out_configValues)
|
||||
{
|
||||
Config* config = this->clockMgr->GetConfig();
|
||||
if(!config->HasProfilesLoaded())
|
||||
{
|
||||
return SYSCLK_ERROR(ConfigNotLoaded);
|
||||
}
|
||||
|
||||
config->GetConfigValues(out_configValues);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::SetConfigValues(SysClkConfigValueList* configValues)
|
||||
{
|
||||
Config* config = this->clockMgr->GetConfig();
|
||||
if(!config->HasProfilesLoaded())
|
||||
{
|
||||
return SYSCLK_ERROR(ConfigNotLoaded);
|
||||
}
|
||||
|
||||
SysClkConfigValueList configValuesCopy = *configValues;
|
||||
|
||||
if(!config->SetConfigValues(&configValuesCopy, true))
|
||||
{
|
||||
return SYSCLK_ERROR(ConfigSaveFailed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count)
|
||||
{
|
||||
if(!SYSCLK_ENUM_VALID(SysClkModule, args->module))
|
||||
{
|
||||
return SYSCLK_ERROR(Generic);
|
||||
}
|
||||
|
||||
if(args->maxCount != size/sizeof(*out_list))
|
||||
{
|
||||
return SYSCLK_ERROR(Generic);
|
||||
}
|
||||
|
||||
this->clockMgr->GetFreqList(args->module, out_list, args->maxCount, out_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::SetKipData() {
|
||||
this->clockMgr->SetKipData();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetKipData() {
|
||||
this->clockMgr->GetKipData();
|
||||
|
||||
return 0;
|
||||
}
|
||||
66
Source/rewrite-hoc-clk/sysmodule/src/ipc_service.h
Normal file
66
Source/rewrite-hoc-clk/sysmodule/src/ipc_service.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 <atomic>
|
||||
#include <nxExt.h>
|
||||
#include <sysclk.h>
|
||||
#include "clock_manager.h"
|
||||
|
||||
class IpcService
|
||||
{
|
||||
public:
|
||||
|
||||
IpcService(ClockManager* clockMgr);
|
||||
virtual ~IpcService();
|
||||
void SetRunning(bool running);
|
||||
static void ProcessThreadFunc(void* arg);
|
||||
static Result ServiceHandlerFunc(void* arg, const IpcServerRequest* r, std::uint8_t* out_data, size_t* out_dataSize);
|
||||
|
||||
Result GetApiVersion(u32* out_version);
|
||||
Result GetVersionString(char* out_buf, size_t bufSize);
|
||||
Result GetCurrentContext(SysClkContext* out_ctx);
|
||||
Result Exit();
|
||||
Result GetProfileCount(std::uint64_t* tid, std::uint8_t* out_count);
|
||||
Result GetProfiles(std::uint64_t* tid, SysClkTitleProfileList* out_profiles);
|
||||
Result SetProfiles(SysClkIpc_SetProfiles_Args* args);
|
||||
Result SetEnabled(std::uint8_t* enabled);
|
||||
Result SetOverride(SysClkIpc_SetOverride_Args* args);
|
||||
Result GetConfigValues(SysClkConfigValueList* out_configValues);
|
||||
Result SetConfigValues(SysClkConfigValueList* configValues);
|
||||
Result GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count);
|
||||
Result SetKipData();
|
||||
Result GetKipData();
|
||||
bool running;
|
||||
Thread thread;
|
||||
LockableMutex threadMutex;
|
||||
IpcServer server;
|
||||
ClockManager* clockMgr;
|
||||
protected:
|
||||
|
||||
};
|
||||
450
Source/rewrite-hoc-clk/sysmodule/src/kip.h
Normal file
450
Source/rewrite-hoc-clk/sysmodule/src/kip.h
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct {
|
||||
u8 cust[4];
|
||||
u32 custRev;
|
||||
u32 placeholder;
|
||||
u32 hpMode;
|
||||
u32 commonEmcMemVolt;
|
||||
u32 eristaEmcMaxClock;
|
||||
u32 eristaEmcMaxClock1;
|
||||
u32 eristaEmcMaxClock2;
|
||||
u32 marikoEmcMaxClock;
|
||||
u32 marikoEmcVddqVolt;
|
||||
u32 emcDvbShift;
|
||||
// advanced config
|
||||
u32 t1_tRCD;
|
||||
u32 t2_tRP;
|
||||
u32 t3_tRAS;
|
||||
u32 t4_tRRD;
|
||||
u32 t5_tRFC;
|
||||
u32 t6_tRTW;
|
||||
u32 t7_tWTR;
|
||||
u32 t8_tREFI;
|
||||
|
||||
u32 mem_burst_read_latency;
|
||||
u32 mem_burst_write_latency;
|
||||
|
||||
u32 eristaCpuUV;
|
||||
u32 eristaCpuVmin;
|
||||
u32 eristaCpuMaxVolt;
|
||||
u32 eristaCpuUnlock;
|
||||
|
||||
u32 marikoCpuUVLow;
|
||||
u32 marikoCpuUVHigh;
|
||||
u32 tableConf;
|
||||
u32 marikoCpuLowVmin;
|
||||
u32 marikoCpuHighVmin;
|
||||
u32 marikoCpuMaxVolt;
|
||||
u32 marikoCpuMaxClock;
|
||||
|
||||
u32 eristaCpuBoostClock;
|
||||
u32 marikoCpuBoostClock;
|
||||
|
||||
u32 eristaGpuUV;
|
||||
u32 eristaGpuVmin;
|
||||
|
||||
u32 marikoGpuUV;
|
||||
u32 marikoGpuVmin;
|
||||
u32 marikoGpuVmax;
|
||||
|
||||
u32 commonGpuVoltOffset;
|
||||
|
||||
u32 gpuSpeedo;
|
||||
|
||||
u32 eristaGpuVoltArray[27];
|
||||
u32 marikoGpuVoltArray[24];
|
||||
|
||||
u32 t6_tRTW_fine_tune;
|
||||
u32 t7_tWTR_fine_tune;
|
||||
|
||||
u32 reserved[60];
|
||||
} CustomizeTable;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define CUST_MAGIC "CUST"
|
||||
#define CUST_MAGIC_LEN 4
|
||||
|
||||
typedef struct {
|
||||
FILE* file;
|
||||
long offset;
|
||||
CustomizeTable cached_table;
|
||||
bool has_cache;
|
||||
} CustHandle;
|
||||
|
||||
static inline bool cust_find_offset(FILE* f, long* out_offset) {
|
||||
u8 buf[512];
|
||||
long pos = 0;
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
while (1) {
|
||||
size_t r = fread(buf, 1, sizeof(buf), f);
|
||||
if (r < CUST_MAGIC_LEN) break;
|
||||
|
||||
for (size_t i = 0; i <= r - CUST_MAGIC_LEN; i++) {
|
||||
if (memcmp(&buf[i], CUST_MAGIC, CUST_MAGIC_LEN) == 0) {
|
||||
*out_offset = pos + (long)i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pos += (long)(r - (CUST_MAGIC_LEN - 1));
|
||||
fseek(f, pos, SEEK_SET);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool cust_read_table(const char* path, CustomizeTable* out) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
if (!f) return false;
|
||||
|
||||
long off;
|
||||
if (!cust_find_offset(f, &off)) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
|
||||
if (off + (long)sizeof(CustomizeTable) > size) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(f, off, SEEK_SET);
|
||||
bool ok = fread(out, 1, sizeof(CustomizeTable), f) == sizeof(CustomizeTable);
|
||||
fclose(f);
|
||||
|
||||
return ok && memcmp(out->cust, CUST_MAGIC, CUST_MAGIC_LEN) == 0;
|
||||
}
|
||||
|
||||
static inline bool cust_write_table(const char* path, const CustomizeTable* in) {
|
||||
FILE* f = fopen(path, "r+b");
|
||||
if (!f) return false;
|
||||
|
||||
long off;
|
||||
if (!cust_find_offset(f, &off)) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
|
||||
if (off + (long)sizeof(CustomizeTable) > size) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(f, off, SEEK_SET);
|
||||
bool ok = fwrite(in, 1, sizeof(CustomizeTable), f) == sizeof(CustomizeTable);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
static inline bool cust_read_and_cache(const char* path, CustomizeTable* out) {
|
||||
return cust_read_table(path, out);
|
||||
}
|
||||
|
||||
#define CUST_WRITE_FIELD_BATCH(table, field, val) \
|
||||
do { \
|
||||
(table)->field = (val); \
|
||||
} while (0)
|
||||
|
||||
#define CUST_WRITE_FIELD(path, field, val) \
|
||||
do { \
|
||||
CustomizeTable t; \
|
||||
if (!cust_read_table(path, &t)) return false; \
|
||||
t.field = (val); \
|
||||
return cust_write_table(path, &t); \
|
||||
} 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_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_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); }
|
||||
static inline bool cust_set_erista_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock, v); }
|
||||
static inline bool cust_set_erista_emc_max1(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock1, v); }
|
||||
static inline bool cust_set_erista_emc_max2(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock2, v); }
|
||||
static inline bool cust_set_mariko_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcMaxClock, v); }
|
||||
static inline bool cust_set_mariko_emc_vddq(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcVddqVolt, v); }
|
||||
static inline bool cust_set_emc_dvb_shift(const char* p, u32 v) { CUST_WRITE_FIELD(p, emcDvbShift, v); }
|
||||
|
||||
static inline bool cust_set_tRCD(const char* p, u32 v) { CUST_WRITE_FIELD(p, t1_tRCD, v); }
|
||||
static inline bool cust_set_tRP(const char* p, u32 v) { CUST_WRITE_FIELD(p, t2_tRP, v); }
|
||||
static inline bool cust_set_tRAS(const char* p, u32 v) { CUST_WRITE_FIELD(p, t3_tRAS, v); }
|
||||
static inline bool cust_set_tRRD(const char* p, u32 v) { CUST_WRITE_FIELD(p, t4_tRRD, v); }
|
||||
static inline bool cust_set_tRFC(const char* p, u32 v) { CUST_WRITE_FIELD(p, t5_tRFC, v); }
|
||||
static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); }
|
||||
static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); }
|
||||
static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); }
|
||||
static inline bool cust_set_tRTW_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW_fine_tune, v); }
|
||||
static inline bool cust_set_tWTR_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR_fine_tune, v); }
|
||||
static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); }
|
||||
static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); }
|
||||
|
||||
static inline bool cust_set_erista_cpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuUV, v); }
|
||||
static inline bool cust_set_eristaCpuVmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuVmin, v); }
|
||||
static inline bool cust_set_erista_cpu_max_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuMaxVolt, v); }
|
||||
static inline bool cust_set_eristaCpuUnlock(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuUnlock, v); }
|
||||
|
||||
static inline bool cust_set_mariko_cpu_uv_low(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuUVLow, v); }
|
||||
static inline bool cust_set_mariko_cpu_uv_high(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuUVHigh, v); }
|
||||
static inline bool cust_set_mariko_cpu_low_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuLowVmin, v); }
|
||||
static inline bool cust_set_mariko_cpu_high_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuHighVmin, v); }
|
||||
static inline bool cust_set_mariko_cpu_max_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxVolt, v); }
|
||||
static inline bool cust_set_erista_cpu_boost(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuBoostClock, v); }
|
||||
static inline bool cust_set_mariko_cpu_boost(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuBoostClock, v); }
|
||||
|
||||
static inline bool cust_set_erista_gpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaGpuUV, v); }
|
||||
static inline bool cust_set_erista_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaGpuVmin, v); }
|
||||
static inline bool cust_set_mariko_gpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuUV, v); }
|
||||
static inline bool cust_set_mariko_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmin, v); }
|
||||
static inline bool cust_set_mariko_gpu_vmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmax, v); }
|
||||
static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); }
|
||||
static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); }
|
||||
static inline bool cust_set_marikoCpuMaxClock(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxClock, v); }
|
||||
|
||||
/* GPU VOLT ARRAY HELPERS */
|
||||
static inline bool cust_set_erista_gpu_volt(const char* p, int idx, u32 v) {
|
||||
if (idx < 0 || idx >= 27) return false;
|
||||
CustomizeTable t;
|
||||
if (!cust_read_table(p, &t)) return false;
|
||||
t.eristaGpuVoltArray[idx] = v;
|
||||
return cust_write_table(p, &t);
|
||||
}
|
||||
|
||||
static inline bool cust_set_mariko_gpu_volt(const char* p, int idx, u32 v) {
|
||||
if (idx < 0 || idx >= 24) return false;
|
||||
CustomizeTable t;
|
||||
if (!cust_read_table(p, &t)) return false;
|
||||
t.marikoGpuVoltArray[idx] = v;
|
||||
return cust_write_table(p, &t);
|
||||
}
|
||||
|
||||
static inline u32 cust_get_field(const CustomizeTable* t, u32 offset) {
|
||||
if (!t) return 0;
|
||||
return *(u32*)((u8*)t + offset);
|
||||
}
|
||||
|
||||
#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_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_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); }
|
||||
static inline u32 cust_get_erista_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock); }
|
||||
static inline u32 cust_get_erista_emc_max1(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock1); }
|
||||
static inline u32 cust_get_erista_emc_max2(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock2); }
|
||||
static inline u32 cust_get_mariko_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcMaxClock); }
|
||||
static inline u32 cust_get_mariko_emc_vddq(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcVddqVolt); }
|
||||
static inline u32 cust_get_emc_dvb_shift(const CustomizeTable* t) { return CUST_GET_FIELD(t, emcDvbShift); }
|
||||
|
||||
static inline u32 cust_get_tRCD(const CustomizeTable* t) { return CUST_GET_FIELD(t, t1_tRCD); }
|
||||
static inline u32 cust_get_tRP(const CustomizeTable* t) { return CUST_GET_FIELD(t, t2_tRP); }
|
||||
static inline u32 cust_get_tRAS(const CustomizeTable* t) { return CUST_GET_FIELD(t, t3_tRAS); }
|
||||
static inline u32 cust_get_tRRD(const CustomizeTable* t) { return CUST_GET_FIELD(t, t4_tRRD); }
|
||||
static inline u32 cust_get_tRFC(const CustomizeTable* t) { return CUST_GET_FIELD(t, t5_tRFC); }
|
||||
static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); }
|
||||
static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); }
|
||||
static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); }
|
||||
static inline u32 cust_get_tRTW_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW_fine_tune); }
|
||||
static inline u32 cust_get_tWTR_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); }
|
||||
static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); }
|
||||
static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); }
|
||||
|
||||
static inline u32 cust_get_erista_cpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuUV); }
|
||||
static inline u32 cust_get_eristaCpuVmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuVmin); }
|
||||
static inline u32 cust_get_erista_cpu_max_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuMaxVolt); }
|
||||
static inline u32 cust_get_eristaCpuUnlock(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuUnlock); }
|
||||
|
||||
static inline u32 cust_get_mariko_cpu_uv_low(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuUVLow); }
|
||||
static inline u32 cust_get_mariko_cpu_uv_high(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuUVHigh); }
|
||||
static inline u32 cust_get_mariko_cpu_low_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuLowVmin); }
|
||||
static inline u32 cust_get_mariko_cpu_high_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuHighVmin); }
|
||||
static inline u32 cust_get_mariko_cpu_max_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxVolt); }
|
||||
static inline u32 cust_get_erista_cpu_boost(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuBoostClock); }
|
||||
static inline u32 cust_get_mariko_cpu_boost(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuBoostClock); }
|
||||
static inline u32 cust_get_table_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, tableConf); }
|
||||
|
||||
static inline u32 cust_get_erista_gpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaGpuUV); }
|
||||
static inline u32 cust_get_erista_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaGpuVmin); }
|
||||
static inline u32 cust_get_mariko_gpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuUV); }
|
||||
static inline u32 cust_get_mariko_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmin); }
|
||||
static inline u32 cust_get_mariko_gpu_vmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmax); }
|
||||
static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); }
|
||||
static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); }
|
||||
static inline u32 cust_get_marikoCpuMaxClock(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxClock); }
|
||||
|
||||
static inline u32 cust_get_erista_gpu_volt(const CustomizeTable* t, int idx) {
|
||||
if (!t || idx < 0 || idx >= 27) return 0;
|
||||
return t->eristaGpuVoltArray[idx];
|
||||
}
|
||||
|
||||
static inline u32 cust_get_mariko_gpu_volt(const CustomizeTable* t, int idx) {
|
||||
if (!t || idx < 0 || idx >= 24) return 0;
|
||||
return t->marikoGpuVoltArray[idx];
|
||||
}
|
||||
|
||||
#define DECL_ERISTA_GPU_VOLT_HELPER(freq, idx) \
|
||||
static inline bool cust_set_erista_gpu_volt_##freq( \
|
||||
const char* p, u32 v) { \
|
||||
return cust_set_erista_gpu_volt(p, idx, v); \
|
||||
}
|
||||
|
||||
#define DECL_MARIKO_GPU_VOLT_HELPER(freq, idx) \
|
||||
static inline bool cust_set_mariko_gpu_volt_##freq( \
|
||||
const char* p, u32 v) { \
|
||||
return cust_set_mariko_gpu_volt(p, idx, v); \
|
||||
}
|
||||
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(76800, 0)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(115200, 1)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(153600, 2)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(192000, 3)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(230400, 4)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(268800, 5)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(307200, 6)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(345600, 7)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(384000, 8)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(422400, 9)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(460800, 10)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(499200, 11)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(537600, 12)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(576000, 13)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(614400, 14)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(652800, 15)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(691200, 16)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(729600, 17)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(768000, 18)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(806400, 19)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(844800, 20)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(883200, 21)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(921600, 22)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(960000, 23)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(998400, 24)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(1036800, 25)
|
||||
DECL_ERISTA_GPU_VOLT_HELPER(1075200, 26)
|
||||
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(76800, 0)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(153600, 1)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(230400, 2)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(307200, 3)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(384000, 4)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(460800, 5)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(537600, 6)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(614400, 7)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(691200, 8)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(768000, 9)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(844800, 10)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(921600, 11)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(998400, 12)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1075200, 13)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1152000, 14)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1228800, 15)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1267200, 16)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1305600, 17)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1344000, 18)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1382400, 19)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1420800, 20)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1459200, 21)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1497600, 22)
|
||||
DECL_MARIKO_GPU_VOLT_HELPER(1536000, 23)
|
||||
|
||||
|
||||
#define DECL_ERISTA_GPU_VOLT_GET(freq, idx) \
|
||||
static inline u32 cust_get_erista_gpu_volt_##freq##_val(const char* p) { \
|
||||
CustomizeTable t; \
|
||||
if (!cust_read_table(p, &t)) return 0; \
|
||||
return cust_get_erista_gpu_volt(&t, idx); \
|
||||
}
|
||||
#define DECL_MARIKO_GPU_VOLT_GET(freq, idx) \
|
||||
static inline u32 cust_get_mariko_gpu_volt_##freq##_val(const char* p) { \
|
||||
CustomizeTable t; \
|
||||
if (!cust_read_table(p, &t)) return 0; \
|
||||
return cust_get_mariko_gpu_volt(&t, idx); \
|
||||
}
|
||||
|
||||
DECL_ERISTA_GPU_VOLT_GET(76800, 0)
|
||||
DECL_ERISTA_GPU_VOLT_GET(115200, 1)
|
||||
DECL_ERISTA_GPU_VOLT_GET(153600, 2)
|
||||
DECL_ERISTA_GPU_VOLT_GET(192000, 3)
|
||||
DECL_ERISTA_GPU_VOLT_GET(230400, 4)
|
||||
DECL_ERISTA_GPU_VOLT_GET(268800, 5)
|
||||
DECL_ERISTA_GPU_VOLT_GET(307200, 6)
|
||||
DECL_ERISTA_GPU_VOLT_GET(345600, 7)
|
||||
DECL_ERISTA_GPU_VOLT_GET(384000, 8)
|
||||
DECL_ERISTA_GPU_VOLT_GET(422400, 9)
|
||||
DECL_ERISTA_GPU_VOLT_GET(460800, 10)
|
||||
DECL_ERISTA_GPU_VOLT_GET(499200, 11)
|
||||
DECL_ERISTA_GPU_VOLT_GET(537600, 12)
|
||||
DECL_ERISTA_GPU_VOLT_GET(576000, 13)
|
||||
DECL_ERISTA_GPU_VOLT_GET(614400, 14)
|
||||
DECL_ERISTA_GPU_VOLT_GET(652800, 15)
|
||||
DECL_ERISTA_GPU_VOLT_GET(691200, 16)
|
||||
DECL_ERISTA_GPU_VOLT_GET(729600, 17)
|
||||
DECL_ERISTA_GPU_VOLT_GET(768000, 18)
|
||||
DECL_ERISTA_GPU_VOLT_GET(806400, 19)
|
||||
DECL_ERISTA_GPU_VOLT_GET(844800, 20)
|
||||
DECL_ERISTA_GPU_VOLT_GET(883200, 21)
|
||||
DECL_ERISTA_GPU_VOLT_GET(921600, 22)
|
||||
DECL_ERISTA_GPU_VOLT_GET(960000, 23)
|
||||
DECL_ERISTA_GPU_VOLT_GET(998400, 24)
|
||||
DECL_ERISTA_GPU_VOLT_GET(1036800, 25)
|
||||
DECL_ERISTA_GPU_VOLT_GET(1075200, 26)
|
||||
|
||||
DECL_MARIKO_GPU_VOLT_GET(76800, 0)
|
||||
DECL_MARIKO_GPU_VOLT_GET(153600, 1)
|
||||
DECL_MARIKO_GPU_VOLT_GET(230400, 2)
|
||||
DECL_MARIKO_GPU_VOLT_GET(307200, 3)
|
||||
DECL_MARIKO_GPU_VOLT_GET(384000, 4)
|
||||
DECL_MARIKO_GPU_VOLT_GET(460800, 5)
|
||||
DECL_MARIKO_GPU_VOLT_GET(537600, 6)
|
||||
DECL_MARIKO_GPU_VOLT_GET(614400, 7)
|
||||
DECL_MARIKO_GPU_VOLT_GET(691200, 8)
|
||||
DECL_MARIKO_GPU_VOLT_GET(768000, 9)
|
||||
DECL_MARIKO_GPU_VOLT_GET(844800, 10)
|
||||
DECL_MARIKO_GPU_VOLT_GET(921600, 11)
|
||||
DECL_MARIKO_GPU_VOLT_GET(998400, 12)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1075200, 13)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1152000, 14)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1228800, 15)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1267200, 16)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1305600, 17)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1344000, 18)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1382400, 19)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1420800, 20)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1459200, 21)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1497600, 22)
|
||||
DECL_MARIKO_GPU_VOLT_GET(1536000, 23)
|
||||
168
Source/rewrite-hoc-clk/sysmodule/src/main.cpp
Normal file
168
Source/rewrite-hoc-clk/sysmodule/src/main.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
#include "errors.h"
|
||||
#include "file_utils.h"
|
||||
#include "board.h"
|
||||
#include "process_management.h"
|
||||
#include "clock_manager.h"
|
||||
#include "ipc_service.h"
|
||||
#define INNER_HEAP_SIZE 0x40000
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void virtmemSetup(void);
|
||||
|
||||
extern std::uint32_t __start__;
|
||||
|
||||
std::uint32_t __nx_applet_type = AppletType_None;
|
||||
TimeServiceType __nx_time_service_type = TimeServiceType_System;
|
||||
std::uint32_t __nx_fs_num_sessions = 1;
|
||||
u32 __nx_nv_transfermem_size = 0x8000;
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
NvServiceType __nx_nv_service_type = NvServiceType_Factory;
|
||||
|
||||
|
||||
void __libnx_initheap(void)
|
||||
{
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib Heap Management */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
virtmemSetup();
|
||||
}
|
||||
|
||||
void __appInit(void)
|
||||
{
|
||||
if (R_FAILED(smInitialize()))
|
||||
{
|
||||
fatalThrow(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM));
|
||||
}
|
||||
|
||||
Result rc = setsysInitialize();
|
||||
if (R_SUCCEEDED(rc))
|
||||
{
|
||||
SetSysFirmwareVersion fw;
|
||||
rc = setsysGetFirmwareVersion(&fw);
|
||||
if (R_SUCCEEDED(rc))
|
||||
hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro));
|
||||
setsysExit();
|
||||
}
|
||||
|
||||
// rc = fanInitialize();
|
||||
// if (R_FAILED(rc))
|
||||
// diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||
|
||||
rc = i2cInitialize();
|
||||
if (R_FAILED(rc))
|
||||
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||
rc = appletInitialize();
|
||||
if (R_FAILED(rc))
|
||||
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||
}
|
||||
|
||||
void __appExit(void)
|
||||
{
|
||||
// CloseFanControllerThread();
|
||||
// fanExit();
|
||||
i2cExit();
|
||||
fsExit();
|
||||
fsdevUnmountAll();
|
||||
appletExit();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Result rc = FileUtils::Initialize();
|
||||
if (R_FAILED(rc))
|
||||
{
|
||||
fatalThrow(rc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Board::Initialize();
|
||||
ProcessManagement::Initialize();
|
||||
|
||||
ProcessManagement::WaitForQLaunch();
|
||||
|
||||
ClockManager* clockMgr = new ClockManager();
|
||||
IpcService* ipcSrv = new IpcService(clockMgr);
|
||||
|
||||
FileUtils::LogLine("Ready");
|
||||
|
||||
clockMgr->SetRunning(true);
|
||||
clockMgr->GetConfig()->SetEnabled(true);
|
||||
ipcSrv->SetRunning(true);
|
||||
// TemperaturePoint *table;
|
||||
// ReadConfigFile(&table);
|
||||
// InitFanController(table);
|
||||
// StartFanControllerThread();
|
||||
|
||||
while (clockMgr->Running())
|
||||
{
|
||||
clockMgr->Tick();
|
||||
clockMgr->WaitForNextTick();
|
||||
}
|
||||
|
||||
ipcSrv->SetRunning(false);
|
||||
delete ipcSrv;
|
||||
delete clockMgr;
|
||||
ProcessManagement::Exit();
|
||||
Board::Exit();
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
FileUtils::LogLine("[!] %s", ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::exception_ptr p = std::current_exception();
|
||||
FileUtils::LogLine("[!?] %s", p ? p.__cxa_exception_type()->name() : "...");
|
||||
}
|
||||
|
||||
FileUtils::LogLine("Exit");
|
||||
svcSleepThread(1000000ULL);
|
||||
FileUtils::Exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
1329
Source/rewrite-hoc-clk/sysmodule/src/old_board.cpp
Normal file
1329
Source/rewrite-hoc-clk/sysmodule/src/old_board.cpp
Normal file
File diff suppressed because it is too large
Load Diff
80
Source/rewrite-hoc-clk/sysmodule/src/old_board.h
Normal file
80
Source/rewrite-hoc-clk/sysmodule/src/old_board.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <switch.h>
|
||||
#include <sysclk.h>
|
||||
|
||||
class Board
|
||||
{
|
||||
public:
|
||||
static void PcvHijackDvfs(u32 vmin);
|
||||
static u32 GetMinimumGpuVoltage(u32 freqMhz);
|
||||
static void fuseReadSpeedos();
|
||||
static u16 getSpeedo(HorizonOCSpeedo speedoType);
|
||||
static u16 getIDDQ(HorizonOCSpeedo speedoType);
|
||||
static const char* GetProfileName(SysClkProfile profile, bool pretty);
|
||||
static const char* GetModuleName(SysClkModule module, bool pretty);
|
||||
static const char* GetThermalSensorName(SysClkThermalSensor sensor, bool pretty);
|
||||
static const char* GetPowerSensorName(SysClkPowerSensor sensor, bool pretty);
|
||||
static void Initialize();
|
||||
static void Exit();
|
||||
static void ResetToStock();
|
||||
static void ResetToStockCpu();
|
||||
static void ResetToStockMem();
|
||||
static void ResetToStockGpu();
|
||||
static void ResetToStockDisplay();
|
||||
static u8 GetHighestDockedDisplayRate();
|
||||
static SysClkProfile GetProfile();
|
||||
static void SetHz(SysClkModule module, std::uint32_t hz);
|
||||
static std::uint32_t GetHz(SysClkModule module);
|
||||
static std::uint32_t GetRealHz(SysClkModule module);
|
||||
static void GetFreqList(SysClkModule module, std::uint32_t* outList, std::uint32_t maxCount, std::uint32_t* outCount);
|
||||
static std::uint32_t GetTemperatureMilli(SysClkThermalSensor sensor);
|
||||
static std::int32_t GetPowerMw(SysClkPowerSensor sensor);
|
||||
static std::uint32_t GetPartLoad(SysClkPartLoad load);
|
||||
static SysClkSocType GetSocType();
|
||||
static HorizonOCConsoleType GetConsoleType();
|
||||
static std::uint32_t GetVoltage(HocClkVoltage voltage);
|
||||
static u8 GetFanRotationLevel();
|
||||
static u8 GetDramID();
|
||||
static bool IsDram8GB();
|
||||
static void SetGpuSchedulingMode(GpuSchedulingMode mode, GpuSchedulingOverrideMethod method);
|
||||
static void SetDisplayRefreshDockedState(bool docked);
|
||||
static void SetCpuUvLevel(u32 levelLow, u32 levelHigh, u32 tbreakPoint);
|
||||
static u32 CalculateTbreak(u32 table);
|
||||
static bool IsHoag();
|
||||
protected:
|
||||
static void FetchHardwareInfos();
|
||||
static PcvModule GetPcvModule(SysClkModule sysclkModule);
|
||||
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
|
||||
private:
|
||||
static void SetSpeedoBracket();
|
||||
static void CacheDvfsTable();
|
||||
static Handle GetPcvHandle();
|
||||
};
|
||||
85
Source/rewrite-hoc-clk/sysmodule/src/process_management.cpp
Normal file
85
Source/rewrite-hoc-clk/sysmodule/src/process_management.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "process_management.h"
|
||||
#include "file_utils.h"
|
||||
#include "errors.h"
|
||||
#define IS_QLAUNCH 0x20f
|
||||
|
||||
void ProcessManagement::Initialize()
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
rc = pmdmntInitialize();
|
||||
ASSERT_RESULT_OK(rc, "pmdmntInitialize");
|
||||
|
||||
rc = pminfoInitialize();
|
||||
ASSERT_RESULT_OK(rc, "pminfoInitialize");
|
||||
}
|
||||
|
||||
void ProcessManagement::WaitForQLaunch()
|
||||
{
|
||||
Result rc = 0;
|
||||
std::uint64_t pid = 0;
|
||||
do
|
||||
{
|
||||
rc = pmdmntGetProcessId(&pid, PROCESS_MANAGEMENT_QLAUNCH_TID);
|
||||
svcSleepThread(50 * 1000000ULL); // 50ms
|
||||
} while (R_FAILED(rc));
|
||||
}
|
||||
|
||||
std::uint64_t ProcessManagement::GetCurrentApplicationId()
|
||||
{
|
||||
Result rc = 0;
|
||||
std::uint64_t pid = 0;
|
||||
std::uint64_t tid = 0;
|
||||
rc = pmdmntGetApplicationProcessId(&pid);
|
||||
|
||||
if (rc == IS_QLAUNCH)
|
||||
{
|
||||
return PROCESS_MANAGEMENT_QLAUNCH_TID;
|
||||
}
|
||||
|
||||
ASSERT_RESULT_OK(rc, "pmdmntGetApplicationProcessId");
|
||||
|
||||
rc = pminfoGetProgramId(&tid, pid);
|
||||
|
||||
if (rc == IS_QLAUNCH)
|
||||
{
|
||||
return PROCESS_MANAGEMENT_QLAUNCH_TID;
|
||||
}
|
||||
|
||||
ASSERT_RESULT_OK(rc, "pminfoGetProgramId");
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
void ProcessManagement::Exit()
|
||||
{
|
||||
pmdmntExit();
|
||||
pminfoExit();
|
||||
}
|
||||
41
Source/rewrite-hoc-clk/sysmodule/src/process_management.h
Normal file
41
Source/rewrite-hoc-clk/sysmodule/src/process_management.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 <switch.h>
|
||||
#include <cstdint>
|
||||
|
||||
#define PROCESS_MANAGEMENT_QLAUNCH_TID 0x0100000000001000ULL
|
||||
|
||||
class ProcessManagement
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
static void WaitForQLaunch();
|
||||
static std::uint64_t GetCurrentApplicationId();
|
||||
static void Exit();
|
||||
};
|
||||
Reference in New Issue
Block a user