sysclk: refactor governor settings gui

This commit is contained in:
souldbminersmwc
2026-03-19 19:13:39 -04:00
parent b5876ede0e
commit 4e0b54c1a8
8 changed files with 140 additions and 109 deletions

View File

@@ -30,7 +30,7 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <switch/types.h>
typedef enum
{
SysClkSocType_Erista = 0,
@@ -142,19 +142,12 @@ typedef enum {
GpuSchedulingOverrideMethod_NvService,
GpuSchedulingOverrideMethod_EnumMax,
} GpuSchedulingOverrideMethod;
typedef enum {
GovernorState_DoNotOverride = 0,
GovernorState_Disabled,
GovernorState_Enabled_CpuGpuVrr,
GovernorState_Enabled_CpuVrr,
GovernorState_Enabled_GpuVrr,
GovernorState_Enabled_CpuGpu,
GovernorState_Enabled_Cpu,
GovernorState_Enabled_Gpu,
GovernorState_Enabled_Vrr,
GovernorState_EnumMax,
} GovernorState;
ComponentGovernor_DoNotOverride = 0,
ComponentGovernor_Enabled = 1,
ComponentGovernor_Disabled = 2,
ComponentGovernor_EnumMax,
} ComponentGovernorState;
typedef enum {
RamDisplayMode_VDD2VDDQ = 0,
RamDisplayMode_VDD2Usage,
@@ -164,6 +157,25 @@ typedef enum {
#define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
// Packed u32
// Bits 0-7 - CPU
// Bits 8-15 - GPU
// Bits 16-23 - VRR
// Bits 24-32 - unused
inline u32 GovernorStatePack(u8 cpu, u8 gpu, u8 vrr) {
return (u32)cpu | ((u32)gpu << 8) | ((u32)vrr << 16);
}
inline u8 GovernorStateCpu(u32 p) {
return (u8)(p & 0xFF);
}
inline u8 GovernorStateGpu(u32 p) {
return (u8)((p >> 8) & 0xFF);
}
inline u8 GovernorStateVrr(u32 p) {
return (u8)((p >> 16) & 0xFF);
}
static inline const char* sysclkFormatModule(SysClkModule module, bool pretty)
{
switch(module)
@@ -177,7 +189,7 @@ static inline const char* sysclkFormatModule(SysClkModule module, bool pretty)
case HorizonOCModule_Display:
return pretty ? "Display" : "display";
case HorizonOCModule_Governor:
return pretty ? "Governor" : "gov";
return pretty ? "Governor" : "governor";
default:
return "null";
}

View File

@@ -277,6 +277,56 @@ void AppProfileGui::addModuleListItemValue(
this->listElement->addItem(listItem);
}
class GovernorProfileSubMenuGui : public BaseMenuGui {
uint64_t applicationId;
SysClkTitleProfileList* profileList;
SysClkProfile profile;
public:
GovernorProfileSubMenuGui(uint64_t appId, SysClkTitleProfileList* pList, SysClkProfile prof)
: applicationId(appId), profileList(pList), profile(prof) {}
void listUI() override {
this->listElement->addItem(new tsl::elm::CategoryHeader("Governor"));
static constexpr struct { const char* label; int shift; } kAll[] = {
{"CPU", 0}, {"GPU", 8}, {"VRR", 16}
};
int count = IsHoag() ? 2 : 3;
for (int i = 0; i < count; i++) {
u8 cur = (this->profileList->mhzMap[this->profile][HorizonOCModule_Governor] >> kAll[i].shift) & 0xFF;
auto* bar = new tsl::elm::NamedStepTrackBar(
"", {"Do Not Override", "Enabled", "Disabled"},
true, kAll[i].label
);
bar->setProgress(cur);
int shift = kAll[i].shift;
bar->setValueChangedListener([this, shift](u8 value) {
u32& packed = this->profileList->mhzMap[this->profile][HorizonOCModule_Governor];
packed = (packed & ~(0xFFu << shift)) | ((u32)value << shift);
Result rc = sysclkIpcSetProfiles(this->applicationId, this->profileList);
if (R_FAILED(rc)) FatalGui::openWithResultCode("sysclkIpcSetProfiles", rc);
});
this->listElement->addItem(bar);
}
}
};
void AppProfileGui::addGovernorSection(SysClkProfile profile) {
auto* item = new tsl::elm::ListItem("Governor");
item->setValue("\u2192"); // Right arrow
item->setClickListener([this, profile](u64 keys) {
if (keys & HidNpadButton_A) {
tsl::changeTo<GovernorProfileSubMenuGui>(
this->applicationId, this->profileList, profile
);
return true;
}
return false;
});
this->listElement->addItem(item);
}
void AppProfileGui::addProfileUI(SysClkProfile profile)
{
BaseMenuGui::refresh();
@@ -367,27 +417,7 @@ void AppProfileGui::addProfileUI(SysClkProfile profile)
}
}
#endif
std::vector<NamedValue> governorSettingsE = {
NamedValue("Do Not Override", GovernorState_DoNotOverride),
NamedValue("Disabled", GovernorState_Disabled),
NamedValue("CPU + GPU + VRR", GovernorState_Enabled_CpuGpuVrr),
NamedValue("CPU + VRR", GovernorState_Enabled_CpuVrr),
NamedValue("GPU + VRR", GovernorState_Enabled_GpuVrr),
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
NamedValue("CPU", GovernorState_Enabled_Cpu),
NamedValue("GPU", GovernorState_Enabled_Gpu),
NamedValue("VRR", GovernorState_Enabled_Vrr),
};
std::vector<NamedValue> governorSettingsH = {
NamedValue("Do Not Override", GovernorState_DoNotOverride),
NamedValue("Disabled", GovernorState_Disabled),
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
NamedValue("CPU", GovernorState_Enabled_Cpu),
NamedValue("GPU", GovernorState_Enabled_Gpu),
};
this->addModuleListItemValue(profile, HorizonOCModule_Governor, "Governor", 0, 0, 1, "", 1, 0, ValueThresholds(), IsHoag() ? governorSettingsH : governorSettingsE, false);
this->addGovernorSection(profile);
}
void AppProfileGui::listUI()

View File

@@ -70,6 +70,7 @@ class AppProfileGui : public BaseMenuGui
std::vector<NamedValue> namedValues = {},
bool showDefaultValue = true
);
void addGovernorSection(SysClkProfile profile);
void addProfileUI(SysClkProfile profile);
public:
AppProfileGui(std::uint64_t applicationId, SysClkTitleProfileList* profileList);

View File

@@ -15,11 +15,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "../format.h"
#include "fatal_gui.h"
#include "global_override_gui.h"
#include "value_choice_gui.h"
#include "labels.h"
GlobalOverrideGui::GlobalOverrideGui()
{
for (std::uint16_t m = 0; m < SysClkModule_EnumMax; m++) {
@@ -291,25 +293,51 @@ void GlobalOverrideGui::addModuleToggleItem(SysClkModule module)
this->listItems[module] = toggle;
}
std::vector<NamedValue> governorSettingsE = {
NamedValue("Do Not Override", GovernorState_DoNotOverride),
NamedValue("Disabled", GovernorState_Disabled),
NamedValue("CPU + GPU + VRR", GovernorState_Enabled_CpuGpuVrr),
NamedValue("CPU + VRR", GovernorState_Enabled_CpuVrr),
NamedValue("GPU + VRR", GovernorState_Enabled_GpuVrr),
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
NamedValue("CPU", GovernorState_Enabled_Cpu),
NamedValue("GPU", GovernorState_Enabled_Gpu),
NamedValue("VRR", GovernorState_Enabled_Vrr),
class GovernorOverrideSubMenuGui : public BaseMenuGui {
u32 packed;
public:
GovernorOverrideSubMenuGui(u32 initialPacked) : packed(initialPacked) {}
void listUI() override {
this->listElement->addItem(new tsl::elm::CategoryHeader("Governor"));
static constexpr struct { const char* label; int shift; } kAll[] = {
{"CPU", 0}, {"GPU", 8}, {"VRR", 16}
};
int count = IsHoag() ? 2 : 3;
for (int i = 0; i < count; i++) {
u8 cur = (this->packed >> kAll[i].shift) & 0xFF;
auto* bar = new tsl::elm::NamedStepTrackBar(
"", {"Do Not Override", "Enabled", "Disabled"},
true, kAll[i].label
);
bar->setProgress(cur);
int shift = kAll[i].shift;
bar->setValueChangedListener([this, shift](u8 value) {
this->packed = (this->packed & ~(0xFFu << shift)) | ((u32)value << shift);
Result rc = sysclkIpcSetOverride(HorizonOCModule_Governor, this->packed);
if (R_FAILED(rc)) FatalGui::openWithResultCode("sysclkIpcSetOverride", rc);
this->lastContextUpdate = armGetSystemTick();
});
this->listElement->addItem(bar);
}
}
};
std::vector<NamedValue> governorSettingsH = {
NamedValue("Do Not Override", GovernorState_DoNotOverride),
NamedValue("Disabled", GovernorState_Disabled),
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
NamedValue("CPU", GovernorState_Enabled_Cpu),
NamedValue("GPU", GovernorState_Enabled_Gpu),
};
void GlobalOverrideGui::addGovernorSection() {
auto* item = new tsl::elm::ListItem("Governor");
item->setValue("\u2192"); // right arrow
item->setClickListener([this](u64 keys) {
if (keys & HidNpadButton_A) {
u32 packed = this->context ? this->context->overrideFreqs[HorizonOCModule_Governor] : 0;
tsl::changeTo<GovernorOverrideSubMenuGui>(packed);
return true;
}
return false;
});
this->listElement->addItem(item);
}
void GlobalOverrideGui::listUI()
{
@@ -330,7 +358,7 @@ void GlobalOverrideGui::listUI()
this->addModuleListItemValue(HorizonOCModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
#endif
this->addModuleListItemValue(HorizonOCModule_Governor, "Governor", 0, 0, 1, "", 1, 0, ValueThresholds(), IsHoag() ? governorSettingsH : governorSettingsE, false);
this->addGovernorSection();
}
void GlobalOverrideGui::refresh()
@@ -342,23 +370,7 @@ void GlobalOverrideGui::refresh()
for (std::uint16_t m = 0; m < SysClkModule_EnumMax; m++) {
if (m == HorizonOCModule_Governor) {
if (this->listItems[m] != nullptr &&
this->listHz[m] != this->context->overrideFreqs[m]) {
std::string displayText = FREQ_DEFAULT_TEXT;
std::uint32_t currentValue = this->context->overrideFreqs[m];
for (const auto& setting : governorSettingsE) {
if (setting.value == currentValue) {
displayText = setting.name;
break;
}
}
this->listItems[m]->setValue(displayText);
this->listHz[m] = currentValue;
}
this->listHz[m] = this->context->overrideFreqs[m];
continue;
}

View File

@@ -36,8 +36,8 @@ class GlobalOverrideGui : public BaseMenuGui
std::map<SysClkModule, std::tuple<std::string, std::uint32_t, int>> customFormatModules;
tsl::elm::ListItem* listItems[SysClkModule_EnumMax];
std::uint32_t listHz[SysClkModule_EnumMax];
bool isGovernorEnabled;
void openFreqChoiceGui(SysClkModule module);
void addGovernorSection();
void addModuleListItem(SysClkModule module);
void addModuleToggleItem(SysClkModule module);
void openValueChoiceGui(

View File

@@ -30,6 +30,7 @@
#define A_BTN "\ue0e0"
#define R_ARROW "\u2192"
class GeneralSettingsSubMenuGui;
class GovernorSettingsSubMenuGui;
class DisplaySubMenuGui;

View File

@@ -566,18 +566,6 @@ void ClockManager::VRRThread(void* arg) {
}
GovernorState ClockManager::GetEffectiveGovernorState(GovernorState appState, GovernorState tempState)
{
if (tempState == GovernorState_Disabled)
{
return GovernorState_Disabled;
}
if (tempState != GovernorState_DoNotOverride)
{
return tempState;
}
return appState;
}
void ClockManager::HandleSafetyFeatures() {
AppletOperationMode opMode = appletGetOperationMode();
@@ -608,37 +596,32 @@ void ClockManager::HandleMiscFeatures() {
}
void ClockManager::HandleGovernor(uint32_t targetHz) {
GovernorState appGovernorState = (GovernorState)targetHz;
u32 tempTargetHz = this->context->overrideFreqs[HorizonOCModule_Governor];
if (!tempTargetHz)
{
tempTargetHz = this->config->GetAutoClockHz(this->context->applicationId, HorizonOCModule_Governor, this->context->profile, true);
if(!tempTargetHz)
if (!tempTargetHz)
tempTargetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Governor, this->context->profile, true);
}
GovernorState tempGovernorState = (GovernorState)tempTargetHz;
GovernorState effectiveState = this->GetEffectiveGovernorState(appGovernorState, tempGovernorState);
auto resolve = [](u8 app, u8 temp) -> u8 {
if (temp == ComponentGovernor_Disabled) return ComponentGovernor_Disabled;
if (temp != ComponentGovernor_DoNotOverride) return temp;
return app;
};
bool newCpuGovernorState = (effectiveState == GovernorState_Enabled_CpuGpuVrr ||
effectiveState == GovernorState_Enabled_CpuVrr ||
effectiveState == GovernorState_Enabled_CpuGpu ||
effectiveState == GovernorState_Enabled_Cpu);
u8 effectiveCpu = resolve(GovernorStateCpu(targetHz), GovernorStateCpu(tempTargetHz));
u8 effectiveGpu = resolve(GovernorStateGpu(targetHz), GovernorStateGpu(tempTargetHz));
u8 effectiveVrr = resolve(GovernorStateVrr(targetHz), GovernorStateVrr(tempTargetHz));
bool newGpuGovernorState = (effectiveState == GovernorState_Enabled_CpuGpuVrr ||
effectiveState == GovernorState_Enabled_GpuVrr ||
effectiveState == GovernorState_Enabled_CpuGpu ||
effectiveState == GovernorState_Enabled_Gpu);
bool newVrrGovernorState = (effectiveState == GovernorState_Enabled_CpuGpuVrr ||
effectiveState == GovernorState_Enabled_CpuVrr ||
effectiveState == GovernorState_Enabled_GpuVrr ||
effectiveState == GovernorState_Enabled_Vrr);
bool newCpuGovernorState = (effectiveCpu == ComponentGovernor_Enabled);
bool newGpuGovernorState = (effectiveGpu == ComponentGovernor_Enabled);
bool newVrrGovernorState = (effectiveVrr == ComponentGovernor_Enabled);
isCpuGovernorEnabled = newCpuGovernorState;
isGpuGovernorEnabled = newGpuGovernorState;
isVRREnabled = newVrrGovernorState;
if(newCpuGovernorState == false && lastCpuGovernorState == true) {
svcSleepThread(50'000'000); // thread syncing. probably a cleaner way to do this but hey, it works!
Board::ResetToStockCpu();

View File

@@ -192,14 +192,6 @@ class ClockManager
*/
static void VRRThread(void* arg);
/**
* Gets the effective governor state from application/temporary override
*
* @param appState Governor state from app
* @param tempState Governor state from temporary override
*/
GovernorState GetEffectiveGovernorState(GovernorState appState, GovernorState tempState);
/**
* Frequency table
*