Sys-clk-OC: Fixed #41; Erista support added; Manager is deprecated

This commit is contained in:
KazushiM
2022-10-29 18:32:26 +08:00
parent a6dcf1da5c
commit 26c0bff4dd
24 changed files with 335 additions and 206 deletions

View File

@@ -13,7 +13,7 @@ Switch sysmodule allowing you to set cpu/gpu clocks according to the running app
* 2091 → max for Mariko (without overvolting capped at 1120 mV)
* 1963 → official max for Mariko
* 1887
* 1785 → official boost mode
* 1785 → official boost mode, OC max for Erista
* 1683
* 1581
* 1428
@@ -35,7 +35,7 @@ Switch sysmodule allowing you to set cpu/gpu clocks according to the running app
* 1152
* 1075
* 998
* 921 → official max for Erista
* 921 → OC max for Erista
* 844
* 768 → official docked
* 691
@@ -50,15 +50,13 @@ Switch sysmodule allowing you to set cpu/gpu clocks according to the running app
### MEM clocks
**Only 1600 and Max could be set in sys-clk-OC.**
From Hekate Minerva module [sys_sdrammtc.c](https://github.com/CTCaer/hekate/blob/197ed8c319bd4132e4d7571ce037d4a27f806bba/modules/hekate_libsys_minerva/sys_sdrammtc.c#L67)
- ????
- 2131 → NOT stable: max for Erista and official max for Mariko
- 2131 → max for Erista and official max for Mariko
- 2099
- 2064
- 1996 → stable for all
- 1996 → stable for Mariko
- 1932
- 1894
- 1862 → official max for Erista; Mariko without timing adjustment
@@ -74,6 +72,23 @@ From Hekate Minerva module [sys_sdrammtc.c](https://github.com/CTCaer/hekate/blo
To protect the battery from excessive strain, clocks requested from config may be capped before applying, depending on your current profile:
### Erista
| | Handheld | Charging (USB) | Charging (Official) | Docked |
|:-------:|:--------:|:--------------:|:-------------------:|:------:|
| **MEM** | - | - | - | - |
| **CPU** | - | - | - | - |
| **GPU** | 460 | 768 | - | - |
### Mariko (Safe)
| | Handheld | Charging (USB) | Charging (Official) | Docked |
|:-------:|:--------:|:--------------:|:-------------------:|:------:|
| **MEM** | - | - | - | - |
| **CPU** | 1963 | 1963 | 1963 | 1963 |
| **GPU** | 921 | 921 | 921 | 921 |
### Mariko (Unsafe allowed)
| | Handheld | Charging (USB) | Charging (Official) | Docked |
|:-------:|:--------:|:--------------:|:-------------------:|:------:|
| **MEM** | - | - | - | - |
@@ -181,8 +196,8 @@ The `[values]` section allows you to alter timings in sys-clk, you should not ne
| Key | Desc | Default |
|:------------------------:|-------------------------------------------------------------------------------|:---------:|
|**allow_unsafe_freq** | Allow unsafe frequencies (CPU > 1963.5 MHz, GPU > 921.6 MHz) | OFF |
|**auto_cpu_boost** | Auto-boost CPU when system Core #3 utilization ≥ 95% | ON |
|**allow_unsafe_freq** | (Mariko Only) Allow unsafe frequencies (CPU > 1963.5 MHz, GPU > 921.6 MHz) | OFF |
|**auto_cpu_boost** | (Mariko Only) Auto-boost CPU when system Core #3 utilization ≥ 95% | ON |
|**sync_reversenx_mode** | Sync nominal profile (mode) with ReverseNX (-Tool and -RT) | ON |
|**disable_fast_charging** | Disable fast charging (2000mA -> 500 mA) | OFF |
|**charging_limit_perc** | Charging limit (20% - 100%) | 100%(OFF) |

View File

@@ -31,6 +31,7 @@ Result sysclkIpcSetProfiles(u64 tid, SysClkTitleProfileList* profiles);
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues);
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues);
Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode);
Result sysclkIpcGetFrequencyTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table);
static inline Result sysclkIpcRemoveOverride(SysClkModule module)
{

View File

@@ -69,6 +69,8 @@ typedef struct
uint32_t boostCPUFreq;
} SysClkOcExtra;
uint32_t* GetTable(SysClkModule module);
typedef struct
{
union {
@@ -79,13 +81,10 @@ typedef struct
} SysClkTitleProfileList;
#define SYSCLK_GLOBAL_PROFILE_TID 0xA111111111111111
#define SYSCLK_CPU_SAFE_MAX_HZ 1963500000U
#define SYSCLK_GPU_HANDHELD_MAX_HZ 921600000U
#define SYSCLK_GPU_CHARGING_USB_MAX_HZ 1267200000U
extern uint32_t sysclk_g_freq_table_mem_hz[];
extern uint32_t sysclk_g_freq_table_cpu_hz[];
extern uint32_t sysclk_g_freq_table_gpu_hz[];
extern uint32_t g_freq_table_mem_hz[];
extern uint32_t g_freq_table_cpu_hz[];
extern uint32_t g_freq_table_gpu_hz[];
#define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)

View File

@@ -30,9 +30,9 @@ enum SysClkIpcCmd
SysClkIpcCmd_GetConfigValues = 9,
SysClkIpcCmd_SetConfigValues = 10,
SysClkIpcCmd_SetReverseNXRTMode = 11,
SysClkIpcCmd_GetFrequencyTable = 12,
};
typedef struct
{
uint64_t tid;
@@ -44,3 +44,10 @@ typedef struct
SysClkModule module;
uint32_t hz;
} SysClkIpc_SetOverride_Args;
typedef struct
{
SysClkModule module;
SysClkProfile profile;
size_t max_entry_num;
} SysClkIpc_GetFrequencyTable_Args;

View File

@@ -13,6 +13,7 @@
#include <switch.h>
#include <string.h>
#include <stdatomic.h>
#include <stdlib.h>
static Service g_sysclkSrv;
static atomic_size_t g_refCnt;
@@ -119,3 +120,29 @@ Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode)
{
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_SetReverseNXRTMode, mode);
}
Result sysclkIpcGetFrequencyTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table)
{
SysClkIpc_GetFrequencyTable_Args args = {
.module = module,
.profile = profile,
.max_entry_num = max_entry_num
};
size_t table_size = sizeof(uint32_t) * max_entry_num;
uint32_t* table = malloc(table_size);
memset(table, 0, table_size);
SfDispatchParams disp;
Result rc = serviceDispatchImpl(
&g_sysclkSrv, SysClkIpcCmd_GetFrequencyTable,
&args, sizeof(args),
table, table_size, disp);
if (R_FAILED(rc))
return rc;
memcpy(out_table, table, table_size);
free(table);
return 0;
}

View File

@@ -9,13 +9,14 @@
*/
#include <stdint.h>
#include <sysclk/clocks.h>
uint32_t sysclk_g_freq_table_mem_hz[] = {
uint32_t g_freq_table_mem_hz[] = {
// From Hekate Minerva module
// 665600000,
// 800000000,
// 1065600000,
// 1331200000,
665600000,
800000000,
1065600000,
1331200000,
1600000000,
// 1728000000,
// 1795200000,
@@ -29,7 +30,7 @@ uint32_t sysclk_g_freq_table_mem_hz[] = {
0,
};
uint32_t sysclk_g_freq_table_cpu_hz[] = {
uint32_t g_freq_table_cpu_hz[] = {
612000000,
714000000,
816000000,
@@ -51,7 +52,7 @@ uint32_t sysclk_g_freq_table_cpu_hz[] = {
0,
};
uint32_t sysclk_g_freq_table_gpu_hz[] = {
uint32_t g_freq_table_gpu_hz[] = {
76800000,
153600000,
230400000,
@@ -72,3 +73,16 @@ uint32_t sysclk_g_freq_table_gpu_hz[] = {
1305600000,
0,
};
uint32_t* GetTable(SysClkModule module) {
switch (module) {
case SysClkModule_CPU:
return &g_freq_table_cpu_hz[0];
case SysClkModule_GPU:
return &g_freq_table_gpu_hz[0];
case SysClkModule_MEM:
return &g_freq_table_mem_hz[0];
default:
return NULL;
}
}

View File

@@ -32,7 +32,7 @@ NO_ICON := 1
#---------------------------------------------------------------------------------
# version control constants
#---------------------------------------------------------------------------------
TARGET_VERSION := OC-$$(date +%Y/%m/%d)
TARGET_VERSION := $$(date +%Y/%m/%d)
APP_VERSION := $(TARGET_VERSION)
#---------------------------------------------------------------------------------

View File

@@ -17,13 +17,9 @@
static inline std::string formatListFreqMhz(std::uint32_t mhz)
{
if(mhz == 0)
{
return FREQ_DEFAULT_TEXT;
}
else if (mhz == 1862)
{
if(mhz == 1862) // MEM
return "Maximum";
}
char buf[10];
return std::string(buf, snprintf(buf, sizeof(buf), "%u MHz", mhz));

View File

@@ -24,10 +24,10 @@ AppProfileGui::~AppProfileGui()
delete this->profileList;
}
void AppProfileGui::openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module, std::uint32_t* hzList)
void AppProfileGui::openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module)
{
tsl::changeTo<FreqChoiceGui>(this->profileList->mhzMap[profile][module] * 1000000, hzList, [this, listItem, profile, module](std::uint32_t hz) {
this->profileList->mhzMap[profile][module] = hz / 1000000;
tsl::changeTo<FreqChoiceGui>(this->profileList->mhzMap[profile][module], module, profile, [this, listItem, profile, module](std::uint32_t mhz) {
this->profileList->mhzMap[profile][module] = mhz;
listItem->setValue(formatListFreqMhz(this->profileList->mhzMap[profile][module]));
Result rc = sysclkIpcSetProfiles(this->applicationId, this->profileList);
if(R_FAILED(rc))
@@ -40,14 +40,14 @@ void AppProfileGui::openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfil
});
}
void AppProfileGui::addModuleListItem(SysClkProfile profile, SysClkModule module, std::uint32_t* hzList)
void AppProfileGui::addModuleListItem(SysClkProfile profile, SysClkModule module)
{
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(sysclkFormatModule(module, true));
listItem->setValue(formatListFreqMhz(this->profileList->mhzMap[profile][module]));
listItem->setClickListener([this, listItem, profile, module, hzList](u64 keys) {
listItem->setClickListener([this, listItem, profile, module](u64 keys) {
if((keys & HidNpadButton_A) == HidNpadButton_A)
{
this->openFreqChoiceGui(listItem, profile, module, hzList);
this->openFreqChoiceGui(listItem, profile, module);
return true;
}
@@ -60,9 +60,9 @@ void AppProfileGui::addModuleListItem(SysClkProfile profile, SysClkModule module
void AppProfileGui::addProfileUI(SysClkProfile profile)
{
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true)));
this->addModuleListItem(profile, SysClkModule_CPU, &sysclk_g_freq_table_cpu_hz[0]);
this->addModuleListItem(profile, SysClkModule_GPU, &sysclk_g_freq_table_gpu_hz[0]);
this->addModuleListItem(profile, SysClkModule_MEM, &sysclk_g_freq_table_mem_hz[0]);
this->addModuleListItem(profile, SysClkModule_CPU);
this->addModuleListItem(profile, SysClkModule_GPU);
this->addModuleListItem(profile, SysClkModule_MEM);
}
void AppProfileGui::listUI()

View File

@@ -20,8 +20,8 @@ class AppProfileGui : public BaseMenuGui
std::uint64_t applicationId;
SysClkTitleProfileList* profileList;
void openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module, std::uint32_t* hzList);
void addModuleListItem(SysClkProfile profile, SysClkModule module, std::uint32_t* hzList);
void openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module);
void addModuleListItem(SysClkProfile profile, SysClkModule module);
void addProfileUI(SysClkProfile profile);
public:

View File

@@ -11,23 +11,33 @@
#include "freq_choice_gui.h"
#include "../format.h"
#include "fatal_gui.h"
FreqChoiceGui::FreqChoiceGui(std::uint32_t selectedHz, std::uint32_t* hzList, FreqChoiceListener listener)
FreqChoiceGui::FreqChoiceGui(std::uint32_t selectedMHz, SysClkModule module, SysClkProfile profile, FreqChoiceListener listener)
{
this->selectedHz = selectedHz;
this->hzList = hzList;
this->hzTable = new uint32_t[MAX_ENTRIES];
Result rc = sysclkIpcGetFrequencyTable(module, profile, MAX_ENTRIES, hzTable);
if (R_FAILED(rc)) {
FatalGui::openWithResultCode("sysclkIpcGetFrequencyTable", rc);
}
this->selectedMHz = selectedMHz;
this->listener = listener;
}
tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool selected)
FreqChoiceGui::~FreqChoiceGui() {
delete[] this->hzTable;
}
tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t mhz, bool selected)
{
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(formatListFreqHz(hz));
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(formatListFreqMhz(mhz));
listItem->setValue(selected ? "\uE14B" : "");
listItem->setClickListener([this, hz](u64 keys) {
listItem->setClickListener([this, mhz](u64 keys) {
if((keys & HidNpadButton_A) == HidNpadButton_A && this->listener)
{
if(this->listener(hz))
if(this->listener(mhz))
{
tsl::goBack();
}
@@ -42,11 +52,13 @@ tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool sel
void FreqChoiceGui::listUI()
{
std::uint32_t* hzPtr = this->hzList;
this->listElement->addItem(this->createFreqListItem(0, this->selectedHz == 0));
while(*hzPtr)
this->listElement->addItem(this->createFreqListItem(0, this->selectedMHz == 0));
uint32_t* p = this->hzTable;
while(*p)
{
this->listElement->addItem(this->createFreqListItem(*hzPtr, (*hzPtr / 1000000) == (this->selectedHz / 1000000)));
hzPtr++;
uint32_t mhz = *p / 1000'000;
this->listElement->addItem(this->createFreqListItem(mhz, mhz == this->selectedMHz));
p++;
}
}

View File

@@ -14,20 +14,21 @@
#include "base_menu_gui.h"
using FreqChoiceListener = std::function<bool(std::uint32_t hz)>;
using FreqChoiceListener = std::function<bool(std::uint32_t mhz)>;
#define FREQ_DEFAULT_TEXT "Do not override"
class FreqChoiceGui : public BaseMenuGui
{
protected:
std::uint32_t selectedHz;
std::uint32_t* hzList;
std::uint32_t selectedMHz;
static constexpr size_t MAX_ENTRIES = 20;
std::uint32_t* hzTable;
FreqChoiceListener listener;
tsl::elm::ListItem* createFreqListItem(std::uint32_t hz, bool selected);
tsl::elm::ListItem* createFreqListItem(std::uint32_t mhz, bool selected);
public:
FreqChoiceGui(std::uint32_t selectedHz, std::uint32_t* hzList, FreqChoiceListener listener);
~FreqChoiceGui() {}
FreqChoiceGui(std::uint32_t selectedMHz, SysClkModule module, SysClkProfile profile, FreqChoiceListener listener);
~FreqChoiceGui();
void listUI() override;
};

View File

@@ -22,10 +22,10 @@ GlobalOverrideGui::GlobalOverrideGui()
}
}
void GlobalOverrideGui::openFreqChoiceGui(SysClkModule module, std::uint32_t* hzList)
void GlobalOverrideGui::openFreqChoiceGui(SysClkModule module)
{
tsl::changeTo<FreqChoiceGui>(this->context->overrideFreqs[module], hzList, [this, module](std::uint32_t hz) {
Result rc = sysclkIpcSetOverride(module, hz);
tsl::changeTo<FreqChoiceGui>(this->context->overrideFreqs[module] / 1000'000, module, SysClkProfile_EnumMax, [this, module](std::uint32_t mhz) {
Result rc = sysclkIpcSetOverride(module, mhz * 1000'000);
if(R_FAILED(rc))
{
FatalGui::openWithResultCode("sysclkIpcSetOverride", rc);
@@ -33,21 +33,21 @@ void GlobalOverrideGui::openFreqChoiceGui(SysClkModule module, std::uint32_t* hz
}
this->lastContextUpdate = armGetSystemTick();
this->context->overrideFreqs[module] = hz;
this->context->overrideFreqs[module] = mhz * 1000'000;
return true;
});
}
void GlobalOverrideGui::addModuleListItem(SysClkModule module, std::uint32_t* hzList)
void GlobalOverrideGui::addModuleListItem(SysClkModule module)
{
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(sysclkFormatModule(module, true));
listItem->setValue(formatListFreqMhz(0));
listItem->setClickListener([this, module, hzList](u64 keys) {
listItem->setClickListener([this, module](u64 keys) {
if((keys & HidNpadButton_A) == HidNpadButton_A)
{
this->openFreqChoiceGui(module, hzList);
this->openFreqChoiceGui(module);
return true;
}
@@ -60,9 +60,9 @@ void GlobalOverrideGui::addModuleListItem(SysClkModule module, std::uint32_t* hz
void GlobalOverrideGui::listUI()
{
this->addModuleListItem(SysClkModule_CPU, &sysclk_g_freq_table_cpu_hz[0]);
this->addModuleListItem(SysClkModule_GPU, &sysclk_g_freq_table_gpu_hz[0]);
this->addModuleListItem(SysClkModule_MEM, &sysclk_g_freq_table_mem_hz[0]);
this->addModuleListItem(SysClkModule_CPU);
this->addModuleListItem(SysClkModule_GPU);
this->addModuleListItem(SysClkModule_MEM);
}
void GlobalOverrideGui::refresh()

View File

@@ -20,8 +20,8 @@ class GlobalOverrideGui : public BaseMenuGui
tsl::elm::ListItem* listItems[SysClkModule_EnumMax];
std::uint32_t listHz[SysClkModule_EnumMax];
void openFreqChoiceGui(SysClkModule module, std::uint32_t* hzList);
void addModuleListItem(SysClkModule module, std::uint32_t* hzList);
void openFreqChoiceGui(SysClkModule module);
void addModuleListItem(SysClkModule module);
public:
GlobalOverrideGui();

View File

@@ -17,6 +17,24 @@ MiscGui::MiscGui()
this->configList = new SysClkConfigValueList {};
this->chargeInfo = new PsmChargeInfo {};
this->i2cInfo = new I2cInfo {};
u64 hardware_type = 0;
splInitialize();
splGetConfig(SplConfigItem_HardwareType, &hardware_type);
splExit();
switch (hardware_type) {
case 1: //Icosa
case 2: //Copper
this->isMariko = false;
break;
// case 3: // Iowa
// case 4: // Hoag
// case 5: // Aula
default:
this->isMariko = true;
break;
}
}
MiscGui::~MiscGui()
@@ -24,9 +42,10 @@ MiscGui::~MiscGui()
delete this->configList;
delete this->chargeInfo;
delete this->i2cInfo;
this->configToggles.clear();
}
tsl::elm::ToggleListItem* MiscGui::addConfigToggle(SysClkConfigValue configVal) {
void MiscGui::addConfigToggle(SysClkConfigValue configVal) {
const char* configName = sysclkFormatConfigValue(configVal, true);
tsl::elm::ToggleListItem* toggle = new tsl::elm::ToggleListItem(configName, this->configList->values[configVal]);
toggle->setStateChangedListener([this, configVal](bool state) {
@@ -38,33 +57,28 @@ tsl::elm::ToggleListItem* MiscGui::addConfigToggle(SysClkConfigValue configVal)
this->lastContextUpdate = armGetSystemTick();
});
this->listElement->addItem(toggle);
return toggle;
this->configToggles[configVal] = toggle;
}
void MiscGui::updateConfigToggle(tsl::elm::ToggleListItem *toggle, SysClkConfigValue configVal) {
if (toggle != nullptr) {
toggle->setState(this->configList->values[configVal]);
void MiscGui::updateConfigToggles() {
for (const auto& [value, toggle] : this->configToggles) {
if (toggle != nullptr)
toggle->setState(this->configList->values[value]);
}
}
void MiscGui::listUI()
{
this->listElement->addItem(new tsl::elm::CategoryHeader("Temporary toggles"));
this->backlightToggle = new tsl::elm::ToggleListItem("Screen Backlight", false);
backlightToggle->setStateChangedListener([this](bool state) {
LblUpdate(true);
});
this->listElement->addItem(this->backlightToggle);
sysclkIpcGetConfigValues(this->configList);
this->listElement->addItem(new tsl::elm::CategoryHeader("Config"));
this->unsafeFreqToggle = addConfigToggle(SysClkConfigValue_AllowUnsafeFrequencies);
this->cpuBoostToggle = addConfigToggle(SysClkConfigValue_AutoCPUBoost);
this->syncModeToggle = addConfigToggle(SysClkConfigValue_SyncReverseNXMode);
this->fastChargingToggle = addConfigToggle(SysClkConfigValue_DisableFastCharging);
this->governorToggle = addConfigToggle(SysClkConfigValue_GovernorExperimental);
if (this->isMariko) {
addConfigToggle(SysClkConfigValue_AllowUnsafeFrequencies);
addConfigToggle(SysClkConfigValue_AutoCPUBoost);
}
addConfigToggle(SysClkConfigValue_SyncReverseNXMode);
addConfigToggle(SysClkConfigValue_DisableFastCharging);
addConfigToggle(SysClkConfigValue_GovernorExperimental);
this->chargingLimitHeader = new tsl::elm::CategoryHeader("");
this->listElement->addItem(this->chargingLimitHeader);
@@ -92,11 +106,20 @@ void MiscGui::listUI()
renderer->drawString("\uE016 Long-term use may render the battery gauge \ninaccurate!", false, x, y + 20, SMALL_TEXT_SIZE, DESC_COLOR);
}), SMALL_TEXT_SIZE * 2 + 20);
this->listElement->addItem(new tsl::elm::CategoryHeader("Info"));
this->listElement->addItem(new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString(this->infoNames, false, x, y + 20, SMALL_TEXT_SIZE, DESC_COLOR);
renderer->drawString(this->infoVals, false, x + 120, y + 20, SMALL_TEXT_SIZE, VALUE_COLOR);
}), SMALL_TEXT_SIZE * 12 + 20);
this->listElement->addItem(new tsl::elm::CategoryHeader("Temporary toggles"));
this->backlightToggle = new tsl::elm::ToggleListItem("Screen Backlight", false);
backlightToggle->setStateChangedListener([this](bool state) {
LblUpdate(true);
});
this->listElement->addItem(this->backlightToggle);
if (this->isMariko) {
this->listElement->addItem(new tsl::elm::CategoryHeader("Info"));
this->listElement->addItem(new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString(this->infoNames, false, x, y + 20, SMALL_TEXT_SIZE, DESC_COLOR);
renderer->drawString(this->infoVals, false, x + 120, y + 20, SMALL_TEXT_SIZE, VALUE_COLOR);
}), SMALL_TEXT_SIZE * 12 + 20);
}
}
void MiscGui::refresh() {
@@ -106,10 +129,7 @@ void MiscGui::refresh() {
{
frameCounter = 0;
sysclkIpcGetConfigValues(this->configList);
updateConfigToggle(this->unsafeFreqToggle, SysClkConfigValue_AllowUnsafeFrequencies);
updateConfigToggle(this->cpuBoostToggle, SysClkConfigValue_AutoCPUBoost);
updateConfigToggle(this->syncModeToggle, SysClkConfigValue_SyncReverseNXMode);
updateConfigToggle(this->fastChargingToggle, SysClkConfigValue_DisableFastCharging);
updateConfigToggles();
this->chargingLimitBar->setProgress(this->configList->values[SysClkConfigValue_ChargingLimitPercentage]);
snprintf(chargingLimitBarDesc, 30, "Battery Charging Limit: %lu%%", this->configList->values[SysClkConfigValue_ChargingLimitPercentage]);
@@ -121,7 +141,9 @@ void MiscGui::refresh() {
LblUpdate();
this->backlightToggle->setState(lblstatus);
I2cGetInfo(this->i2cInfo);
UpdateInfo(this->infoVals, sizeof(this->infoVals));
if (this->isMariko) {
I2cGetInfo(this->i2cInfo);
UpdateInfo(this->infoVals, sizeof(this->infoVals));
}
}
}

View File

@@ -69,15 +69,13 @@ class MiscGui : public BaseMenuGui
cmd.reg = reg;
res = i2csessionSendAuto(&_session, &cmd, sizeof(cmd), I2cTransactionOption_All);
if (res)
{
if (res) {
i2csessionClose(&_session);
return res;
}
res = i2csessionReceiveAuto(&_session, &rec, sizeof(rec), I2cTransactionOption_All);
if (res)
{
if (res) {
i2csessionClose(&_session);
return res;
}
@@ -100,15 +98,13 @@ class MiscGui : public BaseMenuGui
cmd.reg = reg;
res = i2csessionSendAuto(&_session, &cmd, sizeof(cmd), I2cTransactionOption_All);
if (res)
{
if (res) {
i2csessionClose(&_session);
return res;
}
res = i2csessionReceiveAuto(&_session, &rec, sizeof(rec), I2cTransactionOption_All);
if (res)
{
if (res) {
i2csessionClose(&_session);
return res;
}
@@ -133,8 +129,7 @@ class MiscGui : public BaseMenuGui
if (R_SUCCEEDED(I2cRead_OutU16(Max17050Reg_Current, I2cDevice_Max17050, &tmp)))
i2cInfo->batCurrent = (s16)tmp * (1.5625 / (SenseResistor * CGain));
auto I2cRead_Max77812_M_VOUT = [this](u8 reg)
{
auto I2cRead_Max77812_M_VOUT = [this](u8 reg) {
constexpr u32 MIN_MV = 250;
constexpr u32 MV_STEP = 5;
constexpr u8 RESET_VAL = 0x78;
@@ -229,19 +224,24 @@ class MiscGui : public BaseMenuGui
{
smInitialize();
lblInitialize();
lblGetBacklightSwitchStatus(&lblstatus);
if (shouldSwitch)
lblstatus ? lblSwitchBacklightOff(0) : lblSwitchBacklightOn(0);
lblExit();
smExit();
}
tsl::elm::ToggleListItem* addConfigToggle(SysClkConfigValue);
void updateConfigToggle(tsl::elm::ToggleListItem*, SysClkConfigValue);
bool isMariko = false;
tsl::elm::ToggleListItem *backlightToggle, *unsafeFreqToggle, *cpuBoostToggle, *syncModeToggle, *fastChargingToggle, *governorToggle;
tsl::elm::CategoryHeader *chargingLimitHeader;
StepTrackBarIcon *chargingLimitBar;
std::map<SysClkConfigValue, tsl::elm::ToggleListItem*> configToggles;
void addConfigToggle(SysClkConfigValue);
void updateConfigToggles();
tsl::elm::ToggleListItem* backlightToggle;
tsl::elm::CategoryHeader* chargingLimitHeader;
StepTrackBarIcon* chargingLimitBar;
SysClkConfigValueList* configList;
PsmChargeInfo* chargeInfo;

View File

@@ -17,7 +17,7 @@ include $(DEVKITPRO)/libnx/switch_rules
# INCLUDES is a list of directories containing header files
# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm".
#---------------------------------------------------------------------------------
TARGET := sys-clk
TARGET := sys-clk-OC
BUILD := build
OUTDIR := out
RESOURCES := res
@@ -30,7 +30,7 @@ LIBNAMES := minIni nxExt
#---------------------------------------------------------------------------------
# version control constants
#---------------------------------------------------------------------------------
TARGET_VERSION := OC-$$(date +%Y/%m/%d)
TARGET_VERSION := $$(date +%Y/%m/%d)
#---------------------------------------------------------------------------------
# options for code generation

View File

@@ -58,7 +58,6 @@ ClockManager::ClockManager()
this->oc = new SysClkOcExtra;
this->oc->systemCoreBoostCPU = false;
this->oc->allowUnsafeFreq = false;
this->oc->governor = false;
this->oc->realProfile = SysClkProfile_Handheld;
this->oc->maxMEMFreq = 0;
@@ -138,7 +137,7 @@ uint32_t ClockManager::GetHz(SysClkModule module)
if (hz)
{
/* Considering realProfile frequency limit */
hz = Clocks::GetNearestHz(module, this->oc->realProfile, hz, this->oc->allowUnsafeFreq);
hz = Clocks::GetNearestHz(module, this->oc->realProfile, hz);
if (module == SysClkModule_MEM && hz == MAX_MEM_CLOCK)
{
@@ -244,7 +243,8 @@ bool ClockManager::RefreshContext()
bool hasChanged = this->config->Refresh();
if (hasChanged) {
this->rnxSync->ToggleSync(this->GetConfig()->GetConfigValue(SysClkConfigValue_SyncReverseNXMode));
this->oc->allowUnsafeFreq = this->GetConfig()->GetConfigValue(SysClkConfigValue_AllowUnsafeFrequencies);
bool allowUnsafe = this->GetConfig()->GetConfigValue(SysClkConfigValue_AllowUnsafeFrequencies);
Clocks::SetAllowUnsafe(allowUnsafe);
}
bool enabled = this->GetConfig()->Enabled();
@@ -255,14 +255,6 @@ bool ClockManager::RefreshContext()
hasChanged = true;
}
bool governor = this->GetConfig()->GetConfigValue(SysClkConfigValue_GovernorExperimental);
if (governor != this->oc->governor)
{
this->oc->governor = governor;
FileUtils::LogLine("[mgr] Governor status: %s", governor ? "enabled" : "disabled");
hasChanged = true;
}
std::uint64_t applicationId = ProcessManagement::GetCurrentApplicationId();
if (applicationId != this->context->applicationId)
{
@@ -274,8 +266,17 @@ bool ClockManager::RefreshContext()
this->rnxSync->Reset(applicationId);
}
bool governor = this->GetConfig()->GetConfigValue(SysClkConfigValue_GovernorExperimental);
governor &= !this->GetConfig()->GetTitleGovernorDisabled(applicationId);
if (governor != this->oc->governor)
{
this->oc->governor = governor;
FileUtils::LogLine("[mgr] Governor status: %s", governor ? "enabled" : "disabled");
hasChanged = true;
}
if (hasChanged) {
if (enabled && governor && !this->GetConfig()->GetTitleGovernorDisabled(applicationId))
if (enabled && governor)
this->governor->Start();
else
this->governor->Stop();

View File

@@ -8,27 +8,70 @@
* --------------------------------------------------------------------------
*/
#include <cstring>
#include <nxExt.h>
#include "clocks.h"
#include "errors.h"
void Clocks::GetList(SysClkModule module, std::uint32_t **outClocks)
void Clocks::GetRange(SysClkModule module, SysClkProfile profile, uint32_t** min, uint32_t** max)
{
switch(module)
{
case SysClkModule_CPU:
*outClocks = sysclk_g_freq_table_cpu_hz;
break;
case SysClkModule_GPU:
*outClocks = sysclk_g_freq_table_gpu_hz;
break;
case SysClkModule_MEM:
*outClocks = sysclk_g_freq_table_mem_hz;
break;
default:
*outClocks = NULL;
ERROR_THROW("No such PcvModule: %u", module);
if (module == SysClkModule_MEM) {
*min = isMariko ? &g_freq_table_mem_hz[4] : &g_freq_table_mem_hz[0]; // 1600 / 665
*max = &g_freq_table_mem_hz[5]; // 1862 - Max
return;
}
if (module == SysClkModule_CPU) {
*min = &g_freq_table_cpu_hz[0];
if (!isMariko)
*max = &g_freq_table_cpu_hz[11]; // 1785
else {
if (allowUnsafe)
*max = &g_freq_table_cpu_hz[17]; // 2397
else
*max = &g_freq_table_cpu_hz[13]; // 1963
}
return;
}
if (module == SysClkModule_GPU) {
*min = &g_freq_table_gpu_hz[0];
if (isMariko && !allowUnsafe) {
*max = &g_freq_table_gpu_hz[11]; // 921
return;
}
switch (profile) {
case SysClkProfile_Handheld:
*max = isMariko ? &g_freq_table_gpu_hz[11] : &g_freq_table_gpu_hz[5]; // 921 / 460
break;
case SysClkProfile_HandheldChargingUSB:
*max = isMariko ? &g_freq_table_gpu_hz[16] : &g_freq_table_gpu_hz[9]; // 1267 / 768
break;
default:
*max = isMariko ? &g_freq_table_gpu_hz[17] : &g_freq_table_gpu_hz[11]; // 1305 / 921
break;
}
return;
}
ERROR_THROW("No such PcvModule: %u", module);
}
Result Clocks::GetTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table) {
uint32_t* min = NULL;
uint32_t* max = NULL;
memset(out_table, 0, max_entry_num * sizeof(uint32_t));
GetRange(module, profile, &min, &max);
if (!min || !max || (max - min) / sizeof(uint32_t) >= max_entry_num)
return 1;
uint32_t* p = min;
size_t idx = 0;
while(p <= max)
out_table[idx++] = *p++;
return 0;
}
void Clocks::Initialize()
@@ -42,9 +85,17 @@ void Clocks::Initialize()
splExit();
switch (hardware_type) {
case 0: //Icosa
case 1: //Copper
ERROR_THROW("[!] Erista is not supported!");
case 1: //Icosa
case 2: //Copper
isMariko = false;
break;
case 3: // Iowa
case 4: // Hoag
case 5: // Aula
isMariko = true;
break;
default:
ERROR_THROW("Unknown hardware type: 0x%X!", hardware_type);
return;
}
@@ -303,63 +354,25 @@ std::uint32_t Clocks::GetCurrentHz(SysClkModule module)
return hz;
}
std::uint32_t Clocks::GetNearestHz(SysClkModule module, SysClkProfile profile, std::uint32_t inHz, bool allowUnsafe)
std::uint32_t Clocks::GetNearestHz(SysClkModule module, SysClkProfile profile, std::uint32_t inHz)
{
std::uint32_t hz = GetNearestHz(module, inHz);
std::uint32_t maxHz = GetMaxAllowedHz(module, profile, allowUnsafe);
uint32_t* min = NULL;
uint32_t* max = NULL;
GetRange(module, profile, &min, &max);
if(maxHz != 0)
{
hz = std::min(hz, maxHz);
}
return hz;
}
std::uint32_t Clocks::GetMaxAllowedHz(SysClkModule module, SysClkProfile profile, bool allowUnsafe)
{
switch (module) {
case SysClkModule_CPU:
if (!allowUnsafe)
return SYSCLK_CPU_SAFE_MAX_HZ;
break;
case SysClkModule_GPU:
if (profile == SysClkProfile_Handheld || !allowUnsafe)
return SYSCLK_GPU_HANDHELD_MAX_HZ;
if (profile == SysClkProfile_HandheldChargingUSB)
return SYSCLK_GPU_CHARGING_USB_MAX_HZ;
break;
default:
break;
}
return 0;
}
std::uint32_t Clocks::GetNearestHz(SysClkModule module, std::uint32_t inHz)
{
std::uint32_t *clockTable = NULL;
GetList(module, &clockTable);
if (!clockTable || !clockTable[0])
{
if (!min || !max)
ERROR_THROW("table lookup failed for SysClkModule: %u", module);
uint32_t inMHz = inHz / 1000000U;
uint32_t* p = min;
while(p <= max) {
if (inMHz == *p / 1000000U)
return *p;
p++;
}
int i = 0;
while(clockTable[i])
{
// if (inHz <= (clockTable[i] + clockTable[i + 1]) / 2)
if ((inHz / 1000'000) == (clockTable[i] / 1000'000))
{
return clockTable[i];
}
i++;
}
/* Freq not found in the table, return inHz regardlessly */
return inHz;
return *max;
}
std::int32_t Clocks::GetTsTemperatureMilli(TsLocation location)

View File

@@ -18,6 +18,10 @@
class Clocks
{
public:
static void GetRange(SysClkModule module, SysClkProfile profile, uint32_t** min, uint32_t** max);
static Result GetTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table);
static void SetAllowUnsafe(bool allow) { allowUnsafe = allow; };
static bool GetIsMariko() { return isMariko; };
static void Exit();
static void Initialize();
static SysClkApmConfiguration* GetEmbeddedApmConfig(uint32_t confId);
@@ -29,14 +33,14 @@ class Clocks
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 std::uint32_t GetNearestHz(SysClkModule module, SysClkProfile profile, std::uint32_t inHz, bool allowUnsafe);
static std::uint32_t GetNearestHz(SysClkModule module, SysClkProfile profile, std::uint32_t inHz);
static std::uint32_t GetTemperatureMilli(SysClkThermalSensor sensor);
static void GetList(SysClkModule module, std::uint32_t **outClocks);
protected:
static inline bool allowUnsafe;
static inline bool isMariko;
static std::int32_t GetTsTemperatureMilli(TsLocation location);
static PcvModule GetPcvModule(SysClkModule sysclkModule);
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
static std::uint32_t GetNearestHz(SysClkModule module, std::uint32_t inHz);
static std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile, bool allowUnsafe);
static std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile);
};

View File

@@ -16,6 +16,7 @@
#include <algorithm>
#include <cstring>
#include "errors.h"
#include "clocks.h"
#include "file_utils.h"
Config::Config(std::string path)
@@ -64,6 +65,12 @@ void Config::Load()
FileUtils::LogLine("[cfg] Error loading file");
}
// Erista: Disable Mariko only features
if (!Clocks::GetIsMariko()) {
this->configValues[SysClkConfigValue_AllowUnsafeFrequencies] = 0;
this->configValues[SysClkConfigValue_AutoCPUBoost] = 0;
}
this->loaded = true;
}

View File

@@ -160,6 +160,14 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8*
return ipcSrv->SetReverseNXRTMode(mode);
}
break;
case SysClkIpcCmd_GetFrequencyTable:
if(r->data.size >= sizeof(SysClkIpc_GetFrequencyTable_Args))
{
SysClkIpc_GetFrequencyTable_Args* in_args = (SysClkIpc_GetFrequencyTable_Args*)r->data.ptr;
*out_dataSize = sizeof(uint32_t) * in_args->max_entry_num;
return ipcSrv->GetFrequencyTable(in_args, (uint32_t*)out_data);
}
break;
}
return SYSCLK_ERROR(Generic);
@@ -301,3 +309,7 @@ Result IpcService::SetReverseNXRTMode(ReverseNXMode mode) {
ClockManager::GetInstance()->SetRNXRTMode(mode);
return 0;
}
Result IpcService::GetFrequencyTable(SysClkIpc_GetFrequencyTable_Args* args, uint32_t* out_table) {
return Clocks::GetTable(args->module, args->profile, args->max_entry_num, out_table);
}

View File

@@ -37,6 +37,7 @@ class IpcService
Result GetConfigValues(SysClkConfigValueList* out_configValues);
Result SetConfigValues(SysClkConfigValueList* configValues);
Result SetReverseNXRTMode(ReverseNXMode mode);
Result GetFrequencyTable(SysClkIpc_GetFrequencyTable_Args* args, uint32_t* out_table);
bool running;
Thread thread;

View File

@@ -135,11 +135,8 @@ Governor::Governor() {
m_cpu_freq.module = SysClkModule_CPU;
m_gpu_freq.module = SysClkModule_GPU;
uint32_t* list = NULL;
Clocks::GetList(SysClkModule_CPU, &list);
m_cpu_freq.hz_list = list;
Clocks::GetList(SysClkModule_GPU, &list);
m_gpu_freq.hz_list = list;
m_cpu_freq.hz_list = &g_freq_table_cpu_hz[0];
m_gpu_freq.hz_list = &g_freq_table_cpu_hz[0];
m_cpu_freq.boost_hz = 1785'000'000;
m_cpu_freq.utilref_hz = 2397'000'000;