sys-clk-OC
This commit is contained in:
454
Source/sys-clk-OC/sysmodule/src/clocks.cpp
Normal file
454
Source/sys-clk-OC/sysmodule/src/clocks.cpp
Normal file
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
* wrote this file. As long as you retain this notice you can do whatever you
|
||||
* want with this stuff. If you meet any of us some day, and you think this
|
||||
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <nxExt.h>
|
||||
#include "clocks.h"
|
||||
#include "errors.h"
|
||||
|
||||
bool Clocks::isMariko = false;
|
||||
|
||||
void Clocks::GetList(SysClkModule module, std::uint32_t **outClocks)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void Clocks::Initialize()
|
||||
{
|
||||
Result rc = 0;
|
||||
|
||||
if(hosversionAtLeast(8,0,0))
|
||||
{
|
||||
rc = clkrstInitialize();
|
||||
ASSERT_RESULT_OK(rc, "pcvInitialize");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = pcvInitialize();
|
||||
ASSERT_RESULT_OK(rc, "pcvInitialize");
|
||||
}
|
||||
|
||||
rc = apmExtInitialize();
|
||||
ASSERT_RESULT_OK(rc, "apmExtInitialize");
|
||||
|
||||
rc = psmInitialize();
|
||||
ASSERT_RESULT_OK(rc, "psmInitialize");
|
||||
|
||||
rc = tsInitialize();
|
||||
ASSERT_RESULT_OK(rc, "tsInitialize");
|
||||
|
||||
if(hosversionAtLeast(5,0,0))
|
||||
{
|
||||
rc = tcInitialize();
|
||||
ASSERT_RESULT_OK(rc, "tcInitialize");
|
||||
}
|
||||
|
||||
// Check if it's Mariko
|
||||
u64 hardware_type = 0;
|
||||
splInitialize();
|
||||
splGetConfig(SplConfigItem_HardwareType, &hardware_type);
|
||||
splExit();
|
||||
|
||||
switch(hardware_type) {
|
||||
case 0: //Icosa
|
||||
case 1: //Copper
|
||||
break;
|
||||
case 2: //Hoag
|
||||
case 3: //Iowa
|
||||
case 4: //Calcio
|
||||
case 5: //Aula
|
||||
isMariko = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Clocks::Exit()
|
||||
{
|
||||
if(hosversionAtLeast(8,0,0))
|
||||
{
|
||||
pcvExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
clkrstExit();
|
||||
}
|
||||
|
||||
apmExtExit();
|
||||
psmExit();
|
||||
tsExit();
|
||||
|
||||
if(hosversionAtLeast(5,0,0))
|
||||
{
|
||||
tcExit();
|
||||
}
|
||||
}
|
||||
|
||||
const char* Clocks::GetModuleName(SysClkModule module, bool pretty)
|
||||
{
|
||||
const char* result = sysclkFormatModule(module, pretty);
|
||||
|
||||
if(!result)
|
||||
{
|
||||
ERROR_THROW("No such SysClkModule: %u", module);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* Clocks::GetProfileName(SysClkProfile profile, bool pretty)
|
||||
{
|
||||
const char* result = sysclkFormatProfile(profile, pretty);
|
||||
|
||||
if(!result)
|
||||
{
|
||||
ERROR_THROW("No such SysClkProfile: %u", profile);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* Clocks::GetThermalSensorName(SysClkThermalSensor sensor, bool pretty)
|
||||
{
|
||||
const char* result = sysclkFormatThermalSensor(sensor, pretty);
|
||||
|
||||
if(!result)
|
||||
{
|
||||
ERROR_THROW("No such SysClkThermalSensor: %u", sensor);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PcvModule Clocks::GetPcvModule(SysClkModule sysclkModule)
|
||||
{
|
||||
switch(sysclkModule)
|
||||
{
|
||||
case SysClkModule_CPU:
|
||||
return PcvModule_CpuBus;
|
||||
case SysClkModule_GPU:
|
||||
return PcvModule_GPU;
|
||||
case SysClkModule_MEM:
|
||||
return PcvModule_EMC;
|
||||
default:
|
||||
ERROR_THROW("No such SysClkModule: %u", sysclkModule);
|
||||
}
|
||||
|
||||
return (PcvModule)0;
|
||||
}
|
||||
|
||||
PcvModuleId Clocks::GetPcvModuleId(SysClkModule sysclkModule)
|
||||
{
|
||||
PcvModuleId pcvModuleId;
|
||||
Result rc = pcvGetModuleId(&pcvModuleId, GetPcvModule(sysclkModule));
|
||||
ASSERT_RESULT_OK(rc, "pcvGetModuleId");
|
||||
|
||||
return pcvModuleId;
|
||||
}
|
||||
|
||||
void Clocks::ResetToStock()
|
||||
{
|
||||
Result rc = 0;
|
||||
if(hosversionAtLeast(9,0,0))
|
||||
{
|
||||
std::uint32_t confId = 0;
|
||||
rc = apmExtGetCurrentPerformanceConfiguration(&confId);
|
||||
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
|
||||
|
||||
SysClkApmConfiguration* apmConfiguration = NULL;
|
||||
for(size_t i = 0; sysclk_g_apm_configurations[i].id; i++)
|
||||
{
|
||||
if(sysclk_g_apm_configurations[i].id == confId)
|
||||
{
|
||||
apmConfiguration = &sysclk_g_apm_configurations[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!apmConfiguration)
|
||||
{
|
||||
ERROR_THROW("Unknown apm configuration: %x", confId);
|
||||
}
|
||||
|
||||
Clocks::SetHz(SysClkModule_CPU, apmConfiguration->cpu_hz);
|
||||
Clocks::SetHz(SysClkModule_GPU, apmConfiguration->gpu_hz);
|
||||
// We don't need to set MEM freqs any more
|
||||
//Clocks::SetHz(SysClkModule_MEM, apmConfiguration->mem_hz);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::uint32_t mode = 0;
|
||||
rc = apmExtGetPerformanceMode(&mode);
|
||||
ASSERT_RESULT_OK(rc, "apmExtGetPerformanceMode");
|
||||
|
||||
rc = apmExtSysRequestPerformanceMode(mode);
|
||||
ASSERT_RESULT_OK(rc, "apmExtSysRequestPerformanceMode");
|
||||
}
|
||||
}
|
||||
|
||||
SysClkProfile Clocks::GetCurrentProfile()
|
||||
{
|
||||
std::uint32_t mode = 0;
|
||||
Result rc = apmExtGetPerformanceMode(&mode);
|
||||
ASSERT_RESULT_OK(rc, "apmExtGetPerformanceMode");
|
||||
|
||||
if(mode)
|
||||
{
|
||||
return SysClkProfile_Docked;
|
||||
}
|
||||
|
||||
PsmChargerType chargerType;
|
||||
|
||||
rc = psmGetChargerType(&chargerType);
|
||||
ASSERT_RESULT_OK(rc, "psmGetChargerType");
|
||||
|
||||
if(chargerType == PsmChargerType_EnoughPower)
|
||||
{
|
||||
return SysClkProfile_HandheldChargingOfficial;
|
||||
}
|
||||
else if(chargerType == PsmChargerType_LowPower || chargerType == PsmChargerType_NotSupported)
|
||||
{
|
||||
return SysClkProfile_HandheldChargingUSB;
|
||||
}
|
||||
|
||||
return SysClkProfile_Handheld;
|
||||
}
|
||||
|
||||
void Clocks::SetHz(SysClkModule module, std::uint32_t hz)
|
||||
{
|
||||
// We don't need to set MEM freqs any more
|
||||
if (module == SysClkModule_MEM)
|
||||
return;
|
||||
|
||||
Result rc = 0;
|
||||
|
||||
if(hosversionAtLeast(8,0,0))
|
||||
{
|
||||
ClkrstSession session = {0};
|
||||
|
||||
rc = clkrstOpenSession(&session, Clocks::GetPcvModuleId(module), 3);
|
||||
ASSERT_RESULT_OK(rc, "clkrstOpenSession");
|
||||
rc = clkrstSetClockRate(&session, hz);
|
||||
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
||||
|
||||
clkrstCloseSession(&session);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = pcvSetClockRate(Clocks::GetPcvModule(module), hz);
|
||||
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t Clocks::GetCurrentHz(SysClkModule module)
|
||||
{
|
||||
Result rc = 0;
|
||||
std::uint32_t hz = 0;
|
||||
|
||||
if(hosversionAtLeast(8,0,0))
|
||||
{
|
||||
ClkrstSession session = {0};
|
||||
|
||||
rc = clkrstOpenSession(&session, Clocks::GetPcvModuleId(module), 3);
|
||||
ASSERT_RESULT_OK(rc, "clkrstOpenSession");
|
||||
|
||||
rc = clkrstGetClockRate(&session, &hz);
|
||||
ASSERT_RESULT_OK(rc, "clkrstGetClockRate");
|
||||
|
||||
clkrstCloseSession(&session);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = pcvGetClockRate(Clocks::GetPcvModule(module), &hz);
|
||||
ASSERT_RESULT_OK(rc, "pcvGetClockRate");
|
||||
}
|
||||
|
||||
return hz;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if(maxHz != 0)
|
||||
{
|
||||
hz = std::min(hz, maxHz);
|
||||
}
|
||||
|
||||
return hz;
|
||||
}
|
||||
|
||||
std::uint32_t Clocks::GetMaxAllowedHz(SysClkModule module, SysClkProfile profile)
|
||||
{
|
||||
if(module == SysClkModule_GPU)
|
||||
{
|
||||
if(profile < SysClkProfile_HandheldCharging)
|
||||
{
|
||||
return isMariko ? 1536000000 : SYSCLK_GPU_HANDHELD_MAX_HZ;
|
||||
}
|
||||
else if(profile <= SysClkProfile_HandheldChargingUSB)
|
||||
{
|
||||
return isMariko ? 1536000000 : SYSCLK_GPU_UNOFFICIAL_CHARGER_MAX_HZ;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::uint32_t Clocks::GetNearestHz(SysClkModule module, std::uint32_t inHz)
|
||||
{
|
||||
// Hardcoded values to return, I don't know why it will bump to max when excessive OC
|
||||
if(module == SysClkModule_MEM)
|
||||
{
|
||||
switch(inHz)
|
||||
{
|
||||
// From Hekate Minerva module
|
||||
case 1331000000:
|
||||
return 1331200000;
|
||||
case 1795000000:
|
||||
return 1795200000;
|
||||
case 1862000000:
|
||||
return 1862400000;
|
||||
case 1894000000:
|
||||
return 1894400000;
|
||||
case 1932000000:
|
||||
return 1932800000;
|
||||
case 1996000000:
|
||||
return 1996800000;
|
||||
case 2099000000:
|
||||
return 2099200000;
|
||||
case 2131000000:
|
||||
return 2131200000;
|
||||
default:
|
||||
return inHz;
|
||||
}
|
||||
}
|
||||
|
||||
if(module == SysClkModule_CPU)
|
||||
{
|
||||
switch(inHz)
|
||||
{
|
||||
case 1963000000:
|
||||
return 1963500000;
|
||||
default:
|
||||
return inHz;
|
||||
}
|
||||
}
|
||||
|
||||
if(module == SysClkModule_GPU)
|
||||
{
|
||||
switch(inHz)
|
||||
{
|
||||
case 76000000:
|
||||
return 76800000;
|
||||
case 153000000:
|
||||
return 153600000;
|
||||
case 230000000:
|
||||
return 230400000;
|
||||
case 307000000:
|
||||
return 307200000;
|
||||
case 460000000:
|
||||
return 460800000;
|
||||
case 537000000:
|
||||
return 537600000;
|
||||
case 614000000:
|
||||
return 614400000;
|
||||
case 691000000:
|
||||
return 691200000;
|
||||
case 844000000:
|
||||
return 844800000;
|
||||
case 921000000:
|
||||
return 921600000;
|
||||
case 998000000:
|
||||
return 998400000;
|
||||
case 1075000000:
|
||||
return 1075200000;
|
||||
case 1228000000:
|
||||
return 1228800000;
|
||||
case 1267000000:
|
||||
return 1267200000;
|
||||
case 1305000000:
|
||||
return 1305600000;
|
||||
case 1382000000:
|
||||
return 1382400000;
|
||||
case 1420000000:
|
||||
return 1420800000;
|
||||
default:
|
||||
return inHz;
|
||||
}
|
||||
}
|
||||
|
||||
return inHz;
|
||||
std::uint32_t *clockTable = NULL;
|
||||
GetList(module, &clockTable);
|
||||
|
||||
if (!clockTable || !clockTable[0])
|
||||
{
|
||||
ERROR_THROW("table lookup failed for SysClkModule: %u", module);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while(clockTable[i + 1])
|
||||
{
|
||||
if (inHz <= (clockTable[i] + clockTable[i + 1]) / 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return clockTable[i];
|
||||
}
|
||||
|
||||
std::uint32_t Clocks::GetTemperatureMilli(SysClkThermalSensor sensor)
|
||||
{
|
||||
Result rc;
|
||||
std::int32_t millis = 0;
|
||||
|
||||
if(sensor == SysClkThermalSensor_SOC)
|
||||
{
|
||||
rc = tsGetTemperatureMilliC(TsLocation_External, &millis);
|
||||
ASSERT_RESULT_OK(rc, "tsGetTemperatureMilliC");
|
||||
}
|
||||
else if(sensor == SysClkThermalSensor_PCB)
|
||||
{
|
||||
rc = tsGetTemperatureMilliC(TsLocation_Internal, &millis);
|
||||
ASSERT_RESULT_OK(rc, "tsGetTemperatureMilliC");
|
||||
}
|
||||
else if(sensor == SysClkThermalSensor_Skin)
|
||||
{
|
||||
if(hosversionAtLeast(5,0,0))
|
||||
{
|
||||
rc = tcGetSkinTemperatureMilliC(&millis);
|
||||
ASSERT_RESULT_OK(rc, "tcGetSkinTemperatureMilliC");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_THROW("No such SysClkThermalSensor: %u", sensor);
|
||||
}
|
||||
|
||||
return std::max(0, millis);
|
||||
}
|
||||
Reference in New Issue
Block a user