hocclk: reduce ram usage and add display undervolt

This commit is contained in:
souldbminersmwc
2026-04-06 15:57:10 -04:00
parent 8faaaa58d9
commit 521e3c22dd
11 changed files with 105 additions and 82 deletions

View File

@@ -66,6 +66,7 @@ typedef enum {
HocClkConfigValue_RAMVoltDisplayMode, HocClkConfigValue_RAMVoltDisplayMode,
HocClkConfigValue_CpuGovernorMinimumFreq, HocClkConfigValue_CpuGovernorMinimumFreq,
HocClkConfigValue_DisplayVoltage,
KipConfigValue_custRev, KipConfigValue_custRev,
// KipConfigValue_mtcConf, // KipConfigValue_mtcConf,
@@ -252,6 +253,10 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
return pretty ? "RAM Voltage / Usage Display Mode" : "ram_volt_usage_display_mode"; return pretty ? "RAM Voltage / Usage Display Mode" : "ram_volt_usage_display_mode";
case HocClkConfigValue_CpuGovernorMinimumFreq: case HocClkConfigValue_CpuGovernorMinimumFreq:
return pretty ? "CPU Governor Minimum Frequency" : "cpu_gov_min_freq"; return pretty ? "CPU Governor Minimum Frequency" : "cpu_gov_min_freq";
case HocClkConfigValue_DisplayVoltage:
return pretty ? "Display Voltage" : "display_voltage";
// KIP config values // KIP config values
case KipConfigValue_custRev: case KipConfigValue_custRev:
return pretty ? "Custom Revision" : "kip_cust_rev"; return pretty ? "Custom Revision" : "kip_cust_rev";
@@ -453,6 +458,8 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val)
return 612000000ULL; // 612MHz return 612000000ULL; // 612MHz
case HocClkConfigValue_MaxDisplayClockH: case HocClkConfigValue_MaxDisplayClockH:
return 60ULL; return 60ULL;
case HocClkConfigValue_DisplayVoltage:
return 1200ULL; // Auto
default: default:
return 0ULL; return 0ULL;
} }
@@ -588,6 +595,9 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
return true; return true;
case HocClkConfigValue_BatteryChargeCurrent: case HocClkConfigValue_BatteryChargeCurrent:
return ((input >= 1024) && (input <= 3072)) || !input; return ((input >= 1024) && (input <= 3072)) || !input;
case HocClkConfigValue_DisplayVoltage:
return ((input >= 900) && (input <= 1325));
default: default:
return false; return false;
} }

View File

@@ -22,6 +22,7 @@ const u8 MAX17050_CURRENT_REG = 0x0A;
// Buck Converter // Buck Converter
typedef enum I2c_BuckConverter_Reg { typedef enum I2c_BuckConverter_Reg {
I2c_Max77620_SD1VOLT_REG = 0x17, // Used for Erista DDR VDDQ+VDD2 / Mariko VDD2 I2c_Max77620_SD1VOLT_REG = 0x17, // Used for Erista DDR VDDQ+VDD2 / Mariko VDD2
I2c_Max77620_LDO0VOLT_REG = 0x23, // Used for Erista DDR VDDQ+VDD2 / Mariko VDD2
I2c_Max77621_VOLT_REG = 0x00, I2c_Max77621_VOLT_REG = 0x00,
I2c_Max77812_CPUVOLT_REG = 0x26, I2c_Max77812_CPUVOLT_REG = 0x26,
I2c_Max77812_GPUVOLT_REG = 0x23, I2c_Max77812_GPUVOLT_REG = 0x23,
@@ -40,7 +41,8 @@ typedef struct I2c_BuckConverter_Domain {
const I2c_BuckConverter_Domain I2c_Erista_CPU = { I2cDevice_Max77621Cpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, }; const I2c_BuckConverter_Domain I2c_Erista_CPU = { I2cDevice_Max77621Cpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, };
const I2c_BuckConverter_Domain I2c_Erista_GPU = { I2cDevice_Max77621Gpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, }; const I2c_BuckConverter_Domain I2c_Erista_GPU = { I2cDevice_Max77621Gpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, };
const I2c_BuckConverter_Domain I2c_Erista_DRAM = { I2cDevice_Max77620Pmic, I2c_Max77620_SD1VOLT_REG, 0x7F, 12500, 600000, 1250000, }; const I2c_BuckConverter_Domain I2c_Erista_DRAM = { I2cDevice_Max77620Pmic, I2c_Max77620_SD1VOLT_REG, 0x3F, 12500, 600000, 1250000, };
const I2c_BuckConverter_Domain I2c_Display = { I2cDevice_Max77620Pmic, I2c_Max77620_LDO0VOLT_REG, 0x7F, 25000, 800000, 1325000, };
const I2c_BuckConverter_Domain I2c_Mariko_CPU = { I2cDevice_Max77812_2, I2c_Max77812_CPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 }; const I2c_BuckConverter_Domain I2c_Mariko_CPU = { I2cDevice_Max77812_2, I2c_Max77812_CPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 };
const I2c_BuckConverter_Domain I2c_Mariko_GPU = { I2cDevice_Max77812_2, I2c_Max77812_GPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 }; const I2c_BuckConverter_Domain I2c_Mariko_GPU = { I2cDevice_Max77812_2, I2c_Max77812_GPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 };
const I2c_BuckConverter_Domain I2c_Mariko_DRAM_VDDQ = { I2cDevice_Max77812_2, I2c_Max77812_MEMVOLT_REG, 0xFF, 5000, 250000, 700000, 0x78 }; const I2c_BuckConverter_Domain I2c_Mariko_DRAM_VDDQ = { I2cDevice_Max77812_2, I2c_Max77812_MEMVOLT_REG, 0xFF, 5000, 250000, 700000, 0x78 };

View File

@@ -31,6 +31,7 @@ tsl::elm::ListItem* RETROStatusItem = NULL;
tsl::elm::ListItem* waferCordsItem = NULL; tsl::elm::ListItem* waferCordsItem = NULL;
tsl::elm::ListItem* ramVoltItem = NULL; tsl::elm::ListItem* ramVoltItem = NULL;
tsl::elm::ListItem* eristaPLLXItem = NULL; tsl::elm::ListItem* eristaPLLXItem = NULL;
tsl::elm::ListItem* dispVoltItem = NULL;
ImageElement* CatImage = NULL; ImageElement* CatImage = NULL;
HideableCategoryHeader* CatHeader = NULL; HideableCategoryHeader* CatHeader = NULL;
@@ -56,6 +57,10 @@ void AboutGui::listUI()
new tsl::elm::ListItem("RAM Voltage:"); new tsl::elm::ListItem("RAM Voltage:");
this->listElement->addItem(ramVoltItem); this->listElement->addItem(ramVoltItem);
dispVoltItem =
new tsl::elm::ListItem("Display Voltage:");
this->listElement->addItem(dispVoltItem);
eristaPLLXItem = eristaPLLXItem =
new tsl::elm::ListItem("PLLX Temp:"); new tsl::elm::ListItem("PLLX Temp:");
if(IsErista()) { if(IsErista()) {
@@ -327,5 +332,8 @@ void AboutGui::refresh()
sprintf(strings[4], "%u.%u / %u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ] / 1000); sprintf(strings[4], "%u.%u / %u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ] / 1000);
ramVoltItem->setValue(strings[4]); ramVoltItem->setValue(strings[4]);
sprintf(strings[5], "%u.%u mV", context->voltages[HocClkVoltage_Display] / 1000U, (context->voltages[HocClkVoltage_Display] % 1000U) / 100U);
dispVoltItem->setValue(strings[5]);
} }

View File

@@ -621,6 +621,8 @@ public:
protected: protected:
void listUI() override { void listUI() override {
ValueThresholds thresholdsDisabled(0, 0);
BaseMenuGui::refresh(); // get latest context BaseMenuGui::refresh(); // get latest context
if(!this->context) if(!this->context)
return; return;
@@ -649,6 +651,16 @@ protected:
false false
); );
} }
addConfigButton(
HocClkConfigValue_DisplayVoltage,
"Display Voltage",
ValueRange(900, 1200, 25, " mV", 1),
"Display Voltage",
&thresholdsDisabled,
{},
{},
false
);
} }
}; };

View File

@@ -41,7 +41,7 @@ DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_V
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -Os -ffunction-sections \ CFLAGS := -g -Wall -Os -ffunction-sections \
$(ARCH) $(DEFINES) $(ARCH) $(DEFINES) -ffast-math
CFLAGS += $(INCLUDE) -D__SWITCH__ CFLAGS += $(INCLUDE) -D__SWITCH__

View File

@@ -3,13 +3,14 @@
"title_id": "0x00FF0000636C6BFF", "title_id": "0x00FF0000636C6BFF",
"title_id_range_min": "0x00FF0000636C6BFF", "title_id_range_min": "0x00FF0000636C6BFF",
"title_id_range_max": "0x00FF0000636C6BFF", "title_id_range_max": "0x00FF0000636C6BFF",
"main_thread_stack_size": "0x0000C000", "main_thread_stack_size": "0x0000D000",
"main_thread_priority": 16, "main_thread_priority": 16,
"default_cpu_id": 3, "default_cpu_id": 3,
"process_category": 1, "process_category": 1,
"is_retail": true, "is_retail": true,
"pool_partition": 2, "pool_partition": 2,
"is_64_bit": true, "is_64_bit": true,
"optimize_memory_allocation": true,
"address_space_type": 3, "address_space_type": 3,
"filesystem_access": { "filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF" "permissions": "0xFFFFFFFFFFFFFFFF"

View File

@@ -217,8 +217,13 @@ namespace clockManager {
void HandleMiscFeatures() void HandleMiscFeatures()
{ {
if (config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)) { static u32 tick = 0;
I2c_Bq24193_SetFastChargeCurrentLimit(config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)); if(++tick > 10) {
if (config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)) {
I2c_Bq24193_SetFastChargeCurrentLimit(config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent));
}
tick = 0;
I2c_BuckConverter_SetMvOut(&I2c_Display, config::GetConfigValue(HocClkConfigValue_DisplayVoltage));
} }
} }
@@ -560,12 +565,12 @@ namespace clockManager {
board::FuseData *fuse = board::GetFuseData(); board::FuseData *fuse = board::GetFuseData();
gContext.speedos[0] = fuse->cpuSpeedo; gContext.speedos[HocClkSpeedo_CPU] = fuse->cpuSpeedo;
gContext.speedos[1] = fuse->gpuSpeedo; gContext.speedos[HocClkSpeedo_GPU] = fuse->gpuSpeedo;
gContext.speedos[2] = fuse->socSpeedo; gContext.speedos[HocClkSpeedo_SOC] = fuse->socSpeedo;
gContext.iddq[0] = fuse->cpuIDDQ; gContext.iddq[HocClkSpeedo_CPU] = fuse->cpuIDDQ;
gContext.iddq[1] = fuse->gpuIDDQ; gContext.iddq[HocClkSpeedo_GPU] = fuse->gpuIDDQ;
gContext.iddq[2] = fuse->socIDDQ; gContext.iddq[HocClkSpeedo_SOC] = fuse->socIDDQ;
gContext.waferX = fuse->waferX; gContext.waferX = fuse->waferX;
gContext.waferY = fuse->waferY; gContext.waferY = fuse->waferY;
@@ -625,9 +630,9 @@ namespace clockManager {
bool isBoost = apmExtIsBoostMode(mode); bool isBoost = apmExtIsBoostMode(mode);
HandleSafetyFeatures(); HandleSafetyFeatures();
HandleMiscFeatures();
if (RefreshContext() || config::Refresh()) { if (RefreshContext() || config::Refresh()) {
HandleMiscFeatures();
SetClocks(isBoost); SetClocks(isBoost);
} }
} }

View File

@@ -30,28 +30,12 @@
#include <cstring> #include <cstring>
namespace errors { namespace errors {
namespace {
const char* 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;
}
}
void ThrowException(const char* format, ...) { void ThrowException(const char* format, ...) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
const char* msg = FormatMessage(format, args);
va_end(args);
fileUtils::LogLine(format, args); fileUtils::LogLine(format, args);
throw std::runtime_error(msg); va_end(args);
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
// throw std::runtime_error(msg);
} }
} }

View File

@@ -84,9 +84,8 @@ namespace fileUtils {
if (file) { if (file) {
struct timespec now; struct timespec now;
clock_gettime(CLOCK_REALTIME, &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); fprintf(file, "[%lu] ", armGetSystemTick());
vfprintf(file, format, args); vfprintf(file, format, args);
fprintf(file, "\n"); fprintf(file, "\n");
fclose(file); fclose(file);

View File

@@ -38,7 +38,5 @@ namespace governor {
void startThreads(); void startThreads();
void exitThreads(); void exitThreads();
void HandleGovernor(uint32_t targetHz); void HandleGovernor(uint32_t targetHz);
void CpuGovernorThread(void* arg);
void GovernorThread(void* arg); void GovernorThread(void* arg);
void VRRThread(void* arg);
} }

View File

@@ -37,8 +37,8 @@
#include "clock_manager.hpp" #include "clock_manager.hpp"
#include "ipc_service.hpp" #include "ipc_service.hpp"
#include "config.hpp" #include "config.hpp"
#define INNER_HEAP_SIZE 0x45000
#define INNER_HEAP_SIZE 0x45000
extern "C" extern "C"
{ {
@@ -54,6 +54,23 @@ extern "C"
char nx_inner_heap[INNER_HEAP_SIZE]; char nx_inner_heap[INNER_HEAP_SIZE];
NvServiceType __nx_nv_service_type = NvServiceType_Factory; NvServiceType __nx_nv_service_type = NvServiceType_Factory;
// Ty to MasaGratoR for this!
//This is done to save some space as they have no practical use in our case
void* __real___cxa_throw(void *thrown_exception, void *pvar, void (*dest)(void *));
void* __real__Unwind_Resume();
void* __real___gxx_personality_v0();
void __wrap___cxa_throw(void *thrown_exception, void *pvar, void (*dest)(void *)) {
abort();
}
void __wrap__Unwind_Resume() {
return;
}
void __wrap___gxx_personality_v0() {
return;
}
void __libnx_initheap(void) void __libnx_initheap(void)
{ {
@@ -94,20 +111,19 @@ extern "C"
rc = i2cInitialize(); rc = i2cInitialize();
if (R_FAILED(rc)) if (R_FAILED(rc))
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
rc = appletInitialize();
if (R_FAILED(rc)) }
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
}
void __appExit(void) void __appExit(void)
{ {
// CloseFanControllerThread(); // CloseFanControllerThread();
// fanExit(); // fanExit();
i2cExit(); i2cExit();
fsExit(); setsysExit();
fsdevUnmountAll(); fsdevUnmountAll();
appletExit(); fsExit();
} smExit();
}
} }
int main(int argc, char** argv) int main(int argc, char** argv)
@@ -119,48 +135,36 @@ int main(int argc, char** argv)
return 1; return 1;
} }
try board::Initialize();
processManagement::Initialize();
processManagement::WaitForQLaunch();
clockManager::Initialize();
ipcService::Initialize();
fileUtils::LogLine("Ready");
clockManager::SetRunning(true);
config::SetEnabled(true);
ipcService::SetRunning(true);
// TemperaturePoint *table;
// ReadConfigFile(&table);
// InitFanController(table);
// StartFanControllerThread();
while (clockManager::Running())
{ {
board::Initialize(); clockManager::Tick();
processManagement::Initialize(); clockManager::WaitForNextTick();
processManagement::WaitForQLaunch();
clockManager::Initialize();
ipcService::Initialize();
fileUtils::LogLine("Ready");
clockManager::SetRunning(true);
config::SetEnabled(true);
ipcService::SetRunning(true);
// TemperaturePoint *table;
// ReadConfigFile(&table);
// InitFanController(table);
// StartFanControllerThread();
while (clockManager::Running())
{
clockManager::Tick();
clockManager::WaitForNextTick();
}
ipcService::SetRunning(false);
ipcService::Exit();
clockManager::Exit();
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() : "...");
} }
ipcService::SetRunning(false);
ipcService::Exit();
clockManager::Exit();
processManagement::Exit();
board::Exit();
fileUtils::LogLine("Exit"); fileUtils::LogLine("Exit");
svcSleepThread(1000000ULL); svcSleepThread(1000000ULL);
fileUtils::Exit(); fileUtils::Exit();