add on the fly gpu volt table

This commit is contained in:
Lightos1
2026-07-04 18:18:51 +02:00
parent cb0ffbcd29
commit 7766481ff6
10 changed files with 351 additions and 205 deletions

View File

@@ -50,7 +50,7 @@ Result hocclkIpcSetConfigValues(HocClkConfigValueList* configValues);
Result hocclkIpcGetFreqList(HocClkModule module, u32* list, u32 maxCount, u32* outCount);
Result hocClkIpcSetKipData();
Result hocClkIpcGetKipData();
Result hocClkIpcRequestGpuVoltage(u32 voltage);
Result hocClkIpcRequestGpuVoltage(u32 voltage, u32 hz);
static inline Result hocclkIpcRemoveOverride(HocClkModule module)
{

View File

@@ -69,4 +69,9 @@ typedef struct
{
HocClkModule module;
uint32_t maxCount;
} HocClkIpc_GetFreqList_Args;
} HocClkIpc_GetFreqList_Args;
typedef struct {
u32 voltage;
u32 hz;
} HocClkIpc_RequestGpuVoltage_Args;

View File

@@ -168,6 +168,11 @@ Result hocClkIpcGetKipData()
return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_GetKipData, temp);
}
Result hocClkIpcRequestGpuVoltage(u32 voltage) {
return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_RequestGpuVoltage, voltage);
Result hocClkIpcRequestGpuVoltage(u32 voltage, u32 hz) {
const HocClkIpc_RequestGpuVoltage_Args args = {
.voltage = voltage,
.hz = hz,
};
return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_RequestGpuVoltage, args);
}

View File

@@ -482,6 +482,116 @@ void MiscGui::addFreqButton(HocClkConfigValue configVal, const char *altName, Ho
this->configRanges[configVal] = ValueRange(0, 0, 0, "MHz", 1);
}
void MiscGui::addGpuFreqVoltageButton(HocClkConfigValue configVal, const char *altName, uint32_t freqHz, const ValueRange &range,
const std::string &categoryName, const ValueThresholds *thresholds,
const std::map<uint32_t, std::string> &labels, const std::vector<NamedValue> &namedValues,
bool showDefaultValue, bool kip) {
const char *configName = altName ? altName : hocclkFormatConfigValue(configVal, true);
auto infoStrings = ConfigInfoStrings(configVal, IsMariko(), IsHoag());
tsl::elm::ListItem *listItem = new tsl::elm::ListItem(configName);
if (!kip)
listItem->setTextColor(tsl::Color(120, 235, 255, 255));
uint64_t currentValue = this->configList->values[configVal];
char valueText[32];
if (currentValue == 0 && showDefaultValue) {
snprintf(valueText, sizeof(valueText), "%s", VALUE_DEFAULT_TEXT);
} else {
bool foundNamedValue = false;
for (const auto &namedValue : namedValues) {
if (currentValue == namedValue.value) {
snprintf(valueText, sizeof(valueText), "%s", namedValue.name.c_str());
foundNamedValue = true;
break;
}
}
if (!foundNamedValue) {
uint64_t displayValue = currentValue / range.divisor;
if (!range.suffix.empty()) {
snprintf(valueText, sizeof(valueText), "%lu %s", displayValue, range.suffix.c_str());
} else {
snprintf(valueText, sizeof(valueText), "%lu", displayValue);
}
}
}
listItem->setValue(valueText);
ValueThresholds thresholdsCopy = (thresholds ? *thresholds : ValueThresholds{});
listItem->setClickListener([this, configVal, range, categoryName, thresholdsCopy, labels, showDefaultValue, kip, freqHz,
infoStrings = std::move(infoStrings), configName = std::string(configName)](u64 keys) {
if (!infoStrings.empty() && (keys & HidNpadButton_Y) && !(keys & ~HidNpadButton_Y)) {
tsl::changeTo<InfoGui>(configName, infoStrings);
return true;
}
if ((keys & HidNpadButton_X) && !(keys & ~HidNpadButton_X)) {
if (!this->configList->values[HocClkConfigValue_LiveGpuVoltage])
return false;
uint32_t voltageMv = (uint32_t)this->configList->values[configVal];
Result rc = hocClkIpcRequestGpuVoltage(voltageMv, freqHz);
if (R_FAILED(rc)) {
FatalGui::openWithResultCode("hocClkIpcRequestGpuVoltage", rc);
return false;
}
return true;
}
if ((keys & HidNpadButton_A) == 0)
return false;
std::uint32_t currentValue = this->configList->values[configVal];
auto nvIt = this->configNamedValues.find(configVal);
const std::vector<NamedValue> &liveNamedValues = (nvIt != this->configNamedValues.end()) ? nvIt->second : std::vector<NamedValue>();
if (thresholdsCopy.warning != 0 || thresholdsCopy.danger != 0) {
tsl::changeTo<ValueChoiceGui>(
currentValue, range, categoryName,
[this, configVal, kip](std::uint32_t value) {
this->configList->values[configVal] = value;
Result rc = hocclkIpcSetConfigValues(this->configList);
if (R_FAILED(rc)) {
FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc);
return false;
}
if (kip) {
shouldSaveKip = true;
}
this->lastContextUpdate = armGetSystemTick();
return true;
},
thresholdsCopy, true, labels, liveNamedValues, showDefaultValue);
} else {
tsl::changeTo<ValueChoiceGui>(
currentValue, range, categoryName,
[this, configVal, kip](std::uint32_t value) {
this->configList->values[configVal] = value;
Result rc = hocclkIpcSetConfigValues(this->configList);
if (R_FAILED(rc)) {
FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc);
return false;
}
if (kip) {
shouldSaveKip = true;
}
this->lastContextUpdate = armGetSystemTick();
return true;
},
ValueThresholds(), false, labels, liveNamedValues, showDefaultValue);
}
return true;
});
this->listElement->addItem(listItem);
this->configButtons[configVal] = listItem;
this->configRanges[configVal] = range;
this->configNamedValues[configVal] = namedValues;
}
void MiscGui::listUI() {
Result rc = hocclkIpcGetConfigValues(configList);
if (R_FAILED(rc)) [[unlikely]] {
@@ -2129,41 +2239,6 @@ class GpuSubmenuGui : public MiscGui {
addConfigButton(HocClkConfigValue_DVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {},
dvfsOffset, false);
if (this->configList->values[HocClkConfigValue_LiveGpuVoltage]) {
std::vector<NamedValue> gpuVoltRequestValues = {
NamedValue("Reset", 0),
};
for (u32 mv = IsMariko() ? 420 : 700; mv <= 1050; mv += 5) {
gpuVoltRequestValues.push_back(NamedValue(std::to_string(mv) + "mV", mv));
}
tsl::elm::ListItem *gpuVoltRequestBtn = new tsl::elm::ListItem("GPU Volt Request");
gpuVoltRequestBtn->setTextColor(tsl::Color(120, 235, 255, 255));
gpuVoltRequestBtn->setValue("Request");
gpuVoltRequestBtn->setClickListener([gpuVoltRequestValues](u64 keys) {
if ((keys & HidNpadButton_A) == 0)
return false;
tsl::changeTo<ValueChoiceGui>(
0, ValueRange(0, 0, 1, "", 1), "GPU Volt Request",
[](u32 value) {
Result rc = hocClkIpcRequestGpuVoltage(value);
if (R_FAILED(rc)) {
FatalGui::openWithResultCode("hocClkIpcRequestGpuVoltage", rc);
return false;
}
return true;
},
ValueThresholds(), false, std::map<u32, std::string>{}, gpuVoltRequestValues, false, false);
return true;
});
this->listElement->addItem(gpuVoltRequestBtn);
}
tsl::elm::ListItem *customTableSubmenu = new tsl::elm::ListItem("GPU Voltage Table");
customTableSubmenu->setClickListener([](u64 keys) {
if (keys & HidNpadButton_A) {
@@ -2276,7 +2351,6 @@ class GpuCustomTableSubmenuGui : public MiscGui {
};
if (IsMariko()) {
tsl::elm::CustomDrawer *warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString("\uE150 Setting GPU Clocks past", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
renderer->drawString("1305MHz without a proper undervolt", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
@@ -2287,61 +2361,61 @@ class GpuCustomTableSubmenuGui : public MiscGui {
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 130);
this->listElement->addItem(warningText);
addConfigButton(KipConfigValue_g_volt_76800, "76.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts, false,
true);
addConfigButton(KipConfigValue_g_volt_153600, "153.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_230400, "230.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_307200, "307.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_384000, "384.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_460800, "460.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_537600, "537.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_614400, "614.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_691200, "691.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_768000, "768.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_844800, "844.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_921600, "921.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_998400, "998.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts,
false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_76800, "76.8MHz", 76'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_153600, "153.6MHz", 153'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_230400, "230.4MHz", 230'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_307200, "307.2MHz", 307'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_384000, "384.0MHz", 384'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_460800, "460.8MHz", 460'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_537600, "537.6MHz", 537'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_614400, "614.4MHz", 614'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_691200, "691.2MHz", 691'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_768000, "768.0MHz", 768'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_844800, "844.8MHz", 844'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_921600, "921.6MHz", 921'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_998400, "998.4MHz", 998'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
if (this->configList->values[KipConfigValue_marikoGpuUV] >= GPUUVLevel_SLT) {
addConfigButton(KipConfigValue_g_volt_1075200, "1075.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1075200, "1075.2MHz", 1'075'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
if (this->configList->values[KipConfigValue_marikoGpuUV] >= GPUUVLevel_HiOPT)
addConfigButton(KipConfigValue_g_volt_1152000, "1152.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1152000, "1152.0MHz", 1'152'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
if (this->configList->values[KipConfigValue_marikoGpuUV] >= GPUUVLevel_HighUV) {
addConfigButton(KipConfigValue_g_volt_1228800, "1228.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_1267200, "1267.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_1305600, "1305.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_1344000, "1344.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts_noAuto, false, true);
addConfigButton(KipConfigValue_g_volt_1382400, "1382.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts_noAuto, false, true);
addConfigButton(KipConfigValue_g_volt_1420800, "1420.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts_noAuto, false, true);
addConfigButton(KipConfigValue_g_volt_1459200, "1459.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts_noAuto, false, true);
addConfigButton(KipConfigValue_g_volt_1497600, "1497.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts_noAuto, false, true);
addConfigButton(KipConfigValue_g_volt_1536000, "1536.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {},
mGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1228800, "1228.8MHz", 1'228'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1267200, "1267.2MHz", 1'267'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1305600, "1305.6MHz", 1'305'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1344000, "1344.0MHz", 1'344'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1382400, "1382.4MHz", 1'382'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1420800, "1420.8MHz", 1'420'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1459200, "1459.2MHz", 1'459'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1497600, "1497.6MHz", 1'497'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_1536000, "1536.0MHz", 1'536'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true);
}
}
} else {
tsl::elm::CustomDrawer *warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
renderer->drawString("\uE150 Setting GPU Clocks past", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
renderer->drawString("921MHz without a proper undervolt", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
@@ -2352,62 +2426,63 @@ class GpuCustomTableSubmenuGui : public MiscGui {
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 130);
this->listElement->addItem(warningText);
addConfigButton(KipConfigValue_g_volt_e_76800, "76.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_115200, "115.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_153600, "153.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_192000, "192.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_230400, "230.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_268800, "268.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_307200, "307.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_345600, "345.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_384000, "384.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_422400, "422.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_460800, "460.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_499200, "499.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_537600, "537.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_576000, "576.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_614400, "614.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_652800, "652.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_691200, "691.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_729600, "729.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_768000, "768.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_806400, "806.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_844800, "844.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_883200, "883.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addConfigButton(KipConfigValue_g_volt_e_921600, "921.6MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {}, eGpuVolts,
false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_76800, "76.8MHz", 76'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_115200, "115.2MHz", 115'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_153600, "153.6MHz", 153'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_192000, "192.0MHz", 192'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_230400, "230.4MHz", 230'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_268800, "268.8MHz", 268'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_307200, "307.2MHz", 307'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_345600, "345.6MHz", 345'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_384000, "384.0MHz", 384'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_422400, "422.4MHz", 422'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_460800, "460.8MHz", 460'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_499200, "499.2MHz", 499'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_537600, "537.6MHz", 537'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_576000, "576.0MHz", 576'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_614400, "614.4MHz", 614'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_652800, "652.8MHz", 652'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_691200, "691.2MHz", 691'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_729600, "729.6MHz", 729'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_768000, "768.0MHz", 768'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_806400, "806.4MHz", 806'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_844800, "844.8MHz", 844'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_883200, "883.2MHz", 883'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_921600, "921.6MHz", 921'600'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
if (this->configList->values[KipConfigValue_eristaGpuUV] >= GPUUVLevel_SLT)
addConfigButton(KipConfigValue_g_volt_e_960000, "960.0MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {},
eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_960000, "960.0MHz", 960'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
if (this->configList->values[KipConfigValue_eristaGpuUV] >= GPUUVLevel_HiOPT) {
addConfigButton(KipConfigValue_g_volt_e_998400, "998.4MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {},
eGpuVolts, false, true);
addConfigButton(KipConfigValue_g_volt_e_1036800, "1036.8MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {},
eGpuVolts_noAuto, false, true);
addConfigButton(KipConfigValue_g_volt_e_1075200, "1075.2MHz", ValueRange(0, 0, 0, "0", 1), "Voltage", &EgpuVmaxThresholds, {},
eGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_998400, "998.4MHz", 998'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_1036800, "1036.8MHz", 1'036'800'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts_noAuto, false, true);
addGpuFreqVoltageButton(KipConfigValue_g_volt_e_1075200, "1075.2MHz", 1'075'200'000, ValueRange(0, 0, 0, "0", 1), "Voltage",
&EgpuVmaxThresholds, {}, eGpuVolts_noAuto, false, true);
}
}
}

View File

@@ -58,6 +58,10 @@ class MiscGui : public BaseMenuGui {
const std::vector<NamedValue> &namedValues = {}, bool showDefaultValue = true, const char *subText = nullptr,
bool kip = false);
void addFreqButton(HocClkConfigValue configVal, const char *altName, HocClkModule module, const std::map<uint32_t, std::string> &labels = {});
void addGpuFreqVoltageButton(HocClkConfigValue configVal, const char *altName, uint32_t freqHz, const ValueRange &range,
const std::string &categoryName, const ValueThresholds *thresholds,
const std::map<uint32_t, std::string> &labels, const std::vector<NamedValue> &namedValues,
bool showDefaultValue, bool kip);
void updateConfigToggles();
tsl::elm::ToggleListItem *enabledToggle;

View File

@@ -281,6 +281,16 @@ namespace board {
return INVALID_HANDLE;
}
bool ValidateHandle(Handle handle) {
if (handle == INVALID_HANDLE) {
fileUtils::LogLine("Invalid handle!");
return false;
}
return true;
}
void CacheGpuVoltTable() {
// Likely CPU regulator?
UnkRegulator reg = {
@@ -290,8 +300,7 @@ namespace board {
};
Handle handle = GetPcvHandle();
if (handle == INVALID_HANDLE) {
fileUtils::LogLine("[dvfs] Invalid handle!");
if (!ValidateHandle(handle)) {
return;
}
@@ -338,13 +347,13 @@ namespace board {
u32 bootVoltage = GetSocType() == HocClkSocType_Mariko ? 800 : 950;
constexpr u32 GpuVoltageTableOffset = 312;
if (!std::memcmp(&buffer[index + GpuVoltageTableOffset], &bootVoltage, sizeof(bootVoltage))) {
std::memcpy(voltData.voltTable, &buffer[index + GpuVoltageTableOffset], sizeof(voltData.voltTable));
std::memcpy(voltData.voltTableStock, &buffer[index + GpuVoltageTableOffset], sizeof(voltData.voltTableStock));
std::memcpy(voltData.voltTableLive, voltData.voltTableStock, sizeof(voltData.voltTableStock));
voltData.voltTableAddress = base + memoryInfo.addr + GpuVoltageTableOffset + index;
}
constexpr u32 CpuVoltageTableOffset = 0xB8;
std::memcpy(cpuVoltTable, &buffer[index + CpuVoltageTableOffset], sizeof(cpuVoltTable)); // TODO: verify the CPU table
svcCloseHandle(handle);
handle = INVALID_HANDLE;
@@ -353,8 +362,8 @@ namespace board {
fileUtils::LogLine("[dvfs] cpu volt %d: %u mV", i, cpuVoltTable[i]);
}
for (int i = 0; i < (int)std::size(voltData.voltTable); ++i) {
fileUtils::LogLine("[dvfs] gpu volt %d: %u mV", i, voltData.voltTable[0][i]);
for (int i = 0; i < (int)std::size(voltData.voltTableStock); ++i) {
fileUtils::LogLine("[dvfs] gpu volt %d: %u mV", i, voltData.voltTableStock[0][i]);
}
return;
}
@@ -365,53 +374,88 @@ namespace board {
return;
}
void PcvHijackGpuVolts(u32 vmin, bool forceOverwrite) {
u32 table[192];
static_assert(sizeof(table) == sizeof(voltData.voltTable), "Invalid gpu voltage table size!");
std::memcpy(table, voltData.voltTable, sizeof(voltData.voltTable));
/* forceOverwrite needs to be handled regardless. */
if (voltData.ramVmin == vmin && !forceOverwrite) {
return;
}
/* Skip adjusting table if vmin is zero (voltage reset), unless forced. */
if (vmin != 0 || forceOverwrite) {
/* Only apply forced voltage override if it's safe to do so. */
if (forceOverwrite && vmin < voltData.ramVmin) {
vmin = voltData.ramVmin;
}
if (vmin != 0) {
for (u32 i = 0; i < std::size(table); ++i) {
if (!table[i]) {
continue;
}
const bool raiseVoltageRamOc = table[i] <= vmin && !forceOverwrite;
if (raiseVoltageRamOc || forceOverwrite) {
table[i] = vmin;
}
}
}
}
// Result ReadGpuVoltTable(u32 *table) {
// Handle handle = GetPcvHandle();
// if (!ValidateHandle(handle)) {
// return 1;
// }
//
// Result rc = svcReadDebugProcessMemory(table, handle, voltData.voltTableAddress, sizeof(voltData.voltTableStock));
// svcCloseHandle(handle);
// return rc;
// }
Result WriteGpuVoltTable(u32 *table) {
Handle handle = GetPcvHandle();
if (handle == INVALID_HANDLE) {
fileUtils::LogLine("Invalid handle!");
if (!ValidateHandle(handle)) {
return 1;
}
Result rc = svcWriteDebugProcessMemory(handle, table, voltData.voltTableAddress, sizeof(voltData.voltTableStock));
svcCloseHandle(handle);
return rc;
}
void PcvHijackGpuVolts(u32 vmin) {
u32 table[GpuVoltTableSize];
std::memcpy(table, voltData.voltTableLive, sizeof(voltData.voltTableLive));
if (voltData.ramVmin == vmin) {
return;
}
Result rc = svcWriteDebugProcessMemory(handle, table, voltData.voltTableAddress, sizeof(table));
if (R_SUCCEEDED(rc) && !forceOverwrite) {
voltData.ramVmin = vmin;
for (u32 i = 0; i < std::size(table); ++i) {
if (table[i] && table[i] <= vmin) {
table[i] = vmin;
}
}
svcCloseHandle(handle);
ASSERT_RESULT_OK(WriteGpuVoltTable(table), "WriteGpuVoltTable");
voltData.ramVmin = vmin;
fileUtils::LogLine("[dvfs] voltage set to %u mV", vmin);
}
u32 GetGpuFreqIndex(u32 hz) {
u32 list[HOCCLK_FREQ_LIST_MAX];
u32 count;
GetFreqList(HocClkModule_GPU, list, HOCCLK_FREQ_LIST_MAX, &count);
for (u32 i = 0; i < count; ++i) {
if (list[i] == hz) {
return i;
}
}
return HOCCLK_FREQ_LIST_MAX;
}
void PcvHijackGpuFrequency(u32 voltage, u32 hz) {
u32 freqIndex = GetGpuFreqIndex(hz);
if (freqIndex == HOCCLK_FREQ_LIST_MAX) {
return;
}
bool voltageReset = (voltage == 0);
for (u32 i = 0; i < GpuVoltTableTempCount; ++i) {
if (voltageReset) {
voltage = voltData.voltTableStock[i][freqIndex];
}
voltData.voltTableLive[i][freqIndex] = voltage;
}
if (voltageReset) {
voltage = voltData.voltTableStock[GpuVoltTableTempCount - 2 /* 70C */][freqIndex];
}
if (voltage >= voltData.ramVmin) {
/* Only update the table if it's safe to do so. */
ASSERT_RESULT_OK(WriteGpuVoltTable(reinterpret_cast<u32 *>(voltData.voltTableLive)), "WriteGpuVoltTable");
}
}
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) {
u32 baseVolt = 800;
if (GetSocType() == HocClkSocType_Mariko) {

View File

@@ -22,11 +22,19 @@
namespace board {
constexpr u32 GpuVoltTableTempCount = 6;
constexpr u32 GpuVoltFreqTempCount = 32;
constexpr size_t GpuVoltTableSize = GpuVoltTableTempCount * GpuVoltFreqTempCount;
struct GpuVoltData {
u32 voltTable[6][32] = {};
u32 voltTableStock[GpuVoltTableTempCount][GpuVoltFreqTempCount] = {};
u32 voltTableRamOc[GpuVoltTableTempCount][GpuVoltFreqTempCount] = {};
u32 voltTableLive[GpuVoltTableTempCount][GpuVoltFreqTempCount] = {};
u64 voltTableAddress;
u32 ramVmin;
};
struct UnkRegulator {
u32 voltageMin;
u32 voltageStep;
@@ -48,7 +56,8 @@ namespace board {
u32 CalculateTbreak(u32 table);
u32 GetVoltage(HocClkVoltage voltage);
void CacheGpuVoltTable();
void PcvHijackGpuVolts(u32 vmin, bool forceOverwrite);
void PcvHijackGpuVolts(u32 vmin);
void PcvHijackGpuFrequency(u32 voltage, u32 hz);
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket);
} // namespace board

View File

@@ -141,6 +141,11 @@ namespace ipcService {
return 0;
}
Result RequestGpuVoltage(HocClkIpc_RequestGpuVoltage_Args *args) {
clockManager::ApplyGpuFreqVoltRequest(args->voltage, args->hz);
return 0;
}
Result ServiceHandlerFunc(void *arg, const IpcServerRequest *r, u8 *out_data, size_t *out_dataSize) {
(void)arg;
switch (r->data.cmdId) {
@@ -237,11 +242,8 @@ namespace ipcService {
break;
case HocClkIpcCmd_RequestGpuVoltage:
if (r->data.size >= sizeof(u32)) {
u32 voltage;
memcpy(&voltage, r->data.ptr, sizeof(u32));
clockManager::ApplyGpuVoltageRequest(voltage);
return 0;
if (r->data.size >= sizeof(HocClkIpc_RequestGpuVoltage_Args)) {
return RequestGpuVoltage((HocClkIpc_RequestGpuVoltage_Args *)r->data.ptr);
}
break;
}

View File

@@ -333,8 +333,8 @@ namespace clockManager {
}
u32 ClampGpuVoltage(u32 voltage) {
constexpr u32 MaxGpuVoltage = 960;
return std::min(voltage, MaxGpuVoltage);
static const u32 maxGpuVoltage = board::GetSocType() == HocClkSocType_Mariko ? 960 : 995;
return std::min(voltage, maxGpuVoltage);
}
u32 GetCurrentNearestGpuFrequency() {
@@ -343,15 +343,17 @@ namespace clockManager {
return GetNearestHz(HocClkModule_GPU, gpuHz, maxHz);
}
void ApplyGpuVoltageRequest(u32 voltage) {
fileUtils::LogLine("Unclamped voltage request: %u", voltage);
void ApplyGpuFreqVoltRequest(u32 voltage, u32 hz) {
voltage = ClampGpuVoltage(voltage);
fileUtils::LogLine("Actual voltage: %u", voltage);
board::PcvHijackGpuVolts(voltage, true);
u32 currentFreq = GetCurrentNearestGpuFrequency();
/* If not freq was provided, use the current freq. */
if (hz == 0) {
hz = currentFreq;
}
board::PcvHijackGpuFrequency(voltage, hz);
/* Update the voltage using the currently nearest valid gpu frequency. */
board::SetHz(HocClkModule_GPU, GetCurrentNearestGpuFrequency());
board::SetHz(HocClkModule_GPU, currentFreq);
}
void ApplyGpuDvfs(u32 targetHz) {
@@ -367,7 +369,7 @@ namespace clockManager {
vmin = ClampGpuVoltage(vmin);
/* Hijack gpu volt table. */
board::PcvHijackGpuVolts(vmin, false);
board::PcvHijackGpuVolts(vmin);
/* Update gpu frequency to actually use the voltage. */
if (targetHz) {
@@ -380,7 +382,7 @@ namespace clockManager {
void DVFSReset() {
if (config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) {
board::PcvHijackGpuVolts(0, false); // Reset to vMin
board::PcvHijackGpuVolts(0); // Reset to vMin
u32 targetHz = gContext.overrideFreqs[HocClkModule_GPU];
if (!targetHz) {
@@ -578,7 +580,7 @@ namespace clockManager {
if (hasChanged) {
board::ResetToStock();
if (config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) {
board::PcvHijackGpuVolts(0, false);
board::PcvHijackGpuVolts(0);
board::ResetToStockGpu();
}
WaitForNextTick();

View File

@@ -63,7 +63,7 @@ namespace clockManager {
void GetFreqList(HocClkModule module, std::uint32_t *list, std::uint32_t maxCount, std::uint32_t *outCount);
void ApplyGpuVoltageRequest(u32 voltage);
void ApplyGpuFreqVoltRequest(u32 voltage, u32 hz);
void Tick();
void WaitForNextTick();