[RAM@2131.2MHz] Add DRAM timing adjusment, 2131.2 MHz should work for all ram chips and achieves higher bandwidth;

[Fix] Revert to permanent RAM clock (ptm-patch);
No longer actively maintained next year.
This commit is contained in:
KazushiM
2021-12-05 21:01:49 +08:00
parent c66c836ae3
commit 46c0cb88c3
26 changed files with 67 additions and 82 deletions

View File

@@ -256,8 +256,8 @@ namespace pcv {
// Mariko mtc tables starting from rev, see mtc_timing_table.hpp for parameters.
// All mariko mtc tables will be patched to simplify the procedure.
constexpr u32 MtcTable_1600[13] = {
0x1012D8, 0x11C63C, 0x11F8A0, 0x122B04, 0x125D68, 0x128FCC, 0x12C230, 0x12F494, 0x1326F8, 0x13595C, 0x138BC0, 0x13BE24, 0x13F088
constexpr u32 MtcTable_1600[][13] = {
{ 0x1012D8, 0x11C63C, 0x11F8A0, 0x122B04, 0x125D68, 0x128FCC, 0x12C230, 0x12F494, 0x1326F8, 0x13595C, 0x138BC0, 0x13BE24, 0x13F088 }, // 13.x
};
constexpr u32 MtcTableOffset = 0x10CC;

View File

@@ -15,7 +15,7 @@
*/
#include <stratosphere.hpp>
#include "ldr_patcher.hpp"
//#define ADJUST_TIMING
#define ADJUST_TIMING
namespace ams::ldr {
@@ -68,10 +68,11 @@ namespace ams::ldr {
}
u32 GetEmcClock() {
// RAM freqs to choose: 1600000, 1728000, 1795200, 1862400, 1894400, 1932800, 1996800, 2064000, 2099200, 2131200
// RAM overclock could be UNSTABLE on some RAM without bumping up voltage,
// and therefore show graphical glitches, hang randomly or even worse, corrupt your NAND
return 1862400;
// RAM freqs from Hekate:
// 1600000, 1728000, 1795200, 1862400, 1894400, 1932800, 1996800, 2064000, 2099200, 2131200
// Other values might work as well
// RAM overclock could be UNSTABLE and generate graphical glitches / instabilities / NAND corruption
return 2131200;
}
u32 GetCpuBoostClock() {
@@ -185,8 +186,8 @@ namespace ams::ldr {
}
#ifdef ADJUST_TIMING
/* Adjust timing parameters in 1600MHz mtc tables */
u32 param_1331, param_1600;
#define ADJUST_PROPORTIONAL(TARGET_TABLE, REF_TABLE, PARAM) \
param_1331 = REF_TABLE->PARAM; \
param_1600 = TARGET_TABLE->PARAM; \
@@ -207,10 +208,10 @@ namespace ams::ldr {
divn = divn * 2 + 1;
}
if (i == 2) {
for (u32 j = 0; j < sizeof(pcv::MtcTable_1600)/sizeof(u32); j++) {
pcv::MarikoMtcTable* mtc_table_1600 = reinterpret_cast<pcv::MarikoMtcTable *>(mapped_nso + pcv::MtcTable_1600[j]);
pcv::MarikoMtcTable* mtc_table_1331 = reinterpret_cast<pcv::MarikoMtcTable *>(mapped_nso + pcv::MtcTable_1600[j] - pcv::MtcTableOffset);
if (i >= 2) {
for (u32 j = 0; j < sizeof(pcv::MtcTable_1600[i-2])/sizeof(u32); j++) {
pcv::MarikoMtcTable* mtc_table_1600 = reinterpret_cast<pcv::MarikoMtcTable *>(mapped_nso + pcv::MtcTable_1600[i-2][j]);
pcv::MarikoMtcTable* mtc_table_1331 = reinterpret_cast<pcv::MarikoMtcTable *>(mapped_nso + pcv::MtcTable_1600[i-2][j] - pcv::MtcTableOffset);
/* Patch parameters that seem like timings */
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rc);
@@ -228,27 +229,17 @@ namespace ams::ldr {
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rd_rcd);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_wr_rcd);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rrd);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_wdv);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_wsv);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_wev);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_wdv_mask); //?
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_quse);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_quse_width);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_einput);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_einput_duration);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_qsafe);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rdv);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rdv_mask); //?
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rdv_early);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rdv_early_mask); //?
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_refresh);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_pre_refresh_req_cnt);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_pdex2wr);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_pdex2rd);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_act2pden);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_rw2pden);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_cke2pden);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_pdex2mrr);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_txsr);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_txsrdll);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_tcke);
@@ -258,15 +249,11 @@ namespace ams::ldr {
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_trpab);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_tclkstop);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_trefbw);
//ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_pmacro_ddll_long_cmd_4); //?
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_pmacro_dll_cfg_2);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_qpop);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_tr_rdv);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_tr_qpop);
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_tr_rdv_mask); //?
ADJUST_PROP_WITHIN_ALL_REG(mtc_table_1600, mtc_table_1331, emc_tr_qsafe);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, dram_timings.rl);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, burst_mc_regs.mc_emem_arb_timing_rcd);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, burst_mc_regs.mc_emem_arb_timing_rp);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, burst_mc_regs.mc_emem_arb_timing_rc);
@@ -276,7 +263,10 @@ namespace ams::ldr {
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, burst_mc_regs.mc_emem_arb_timing_r2w);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, burst_mc_regs.mc_emem_arb_timing_w2r);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, burst_mc_regs.mc_emem_arb_timing_rfcpb);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, la_scale_regs.mc_mll_mpcorer_ptsa_rate);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, la_scale_regs.mc_ptsa_grant_decrement);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, min_mrs_wait);
ADJUST_PROPORTIONAL(mtc_table_1600, mtc_table_1331, latency);
@@ -289,16 +279,16 @@ namespace ams::ldr {
}
}
// u32 PtmEmcClock = GetEmcClock() * 1000;
u32 PtmEmcClock = GetEmcClock() * 1000;
u32 CpuBoostClock = GetCpuBoostClock() * 1000;
for (u32 i = 0; i < sizeof(PtmModuleId)/sizeof(ro::ModuleId); i++) {
if (std::memcmp(std::addressof(PtmModuleId[i]), std::addressof(module_id), sizeof(module_id)) == 0) {
// for (u32 j = 0; j < 16; j++) {
// std::memcpy(reinterpret_cast<void *>(mapped_nso + ptm::EmcOffsetStart[i] + ptm::OffsetInterval * j), &PtmEmcClock, sizeof(PtmEmcClock));
// std::memcpy(reinterpret_cast<void *>(mapped_nso + ptm::EmcOffsetStart[i] + ptm::OffsetInterval * j + 0x4), &PtmEmcClock, sizeof(PtmEmcClock));
// }
for (u32 j = 0; j < 16; j++) {
std::memcpy(reinterpret_cast<void *>(mapped_nso + ptm::EmcOffsetStart[i] + ptm::OffsetInterval * j), &PtmEmcClock, sizeof(PtmEmcClock));
std::memcpy(reinterpret_cast<void *>(mapped_nso + ptm::EmcOffsetStart[i] + ptm::OffsetInterval * j + 0x4), &PtmEmcClock, sizeof(PtmEmcClock));
}
for (u32 j = 0; j < 2; j++) {
std::memcpy(reinterpret_cast<void *>(mapped_nso + ptm::EmcOffsetStart[i] + ptm::CpuBoostOffset + ptm::OffsetInterval * j), &CpuBoostClock, sizeof(CpuBoostClock));
std::memcpy(reinterpret_cast<void *>(mapped_nso + ptm::EmcOffsetStart[i] + ptm::CpuBoostOffset + ptm::OffsetInterval * j + 0x4), &CpuBoostClock, sizeof(CpuBoostClock));

View File

@@ -65,7 +65,7 @@ From Hekate Minerva module [sys_sdrammtc.c](https://github.com/CTCaer/hekate/blo
- 1996
- 1932
- 1894
- 1862 → official max for Erista; Mariko (stable on most DRAM chips except Hynix ones) (with timings for 1600MHz and no overvolting capped at 600 mV)
- 1862 → official max for Erista; Mariko without timing adjustment (stable on most DRAM chips except Hynix ones)
- 1795
- 1728
- 1600 → official docked & official boost mode
@@ -131,19 +131,14 @@ Presets can be customized by adding them to the ini config file located at `/con
[Application Title ID]
docked_cpu=
docked_gpu=
docked_mem=
handheld_charging_cpu=
handheld_charging_gpu=
handheld_charging_mem=
handheld_charging_usb_cpu=
handheld_charging_usb_gpu=
handheld_charging_usb_mem=
handheld_charging_official_cpu=
handheld_charging_official_gpu=
handheld_charging_official_mem=
handheld_cpu=
handheld_gpu=
handheld_mem=
```
* Replace `Application Title ID` with the title id of the game/application you're interested in customizing.
@@ -165,7 +160,6 @@ Leads to a smoother framerate overall (ex: in the korok forest)
[01007EF00011E000]
docked_cpu=1224
handheld_charging_cpu=1224
handheld_mem=1600
```
### Example 2: Picross

View File

@@ -77,7 +77,7 @@ AdvancedSettingsTab::AdvancedSettingsTab()
});
// MEM
brls::SelectListItem *memFreqListItem = createFreqListItem(SysClkModule_MEM, context.overrideFreqs[SysClkModule_MEM] / 1000000);
/*brls::SelectListItem *memFreqListItem = createFreqListItem(SysClkModule_MEM, context.overrideFreqs[SysClkModule_MEM] / 1000000);
memFreqListItem->getValueSelectedEvent()->subscribe([](int result)
{
Result rc = result == 0 ?
@@ -90,7 +90,7 @@ AdvancedSettingsTab::AdvancedSettingsTab()
errorResult(result == 0 ? "sysclkIpcRemoveOverride" : "sysclkIpcSetOverride", rc);
// TODO: Reset selected value
}
});
});*/
this->addView(cpuFreqListItem);
this->addView(gpuFreqListItem);

View File

@@ -116,7 +116,7 @@ void AppProfileFrame::addFreqs(brls::List* list, SysClkProfile profile)
list->addView(gpuListItem);
// MEM
brls::SelectListItem* memListItem = createFreqListItem(SysClkModule_MEM, this->profiles.mhzMap[profile][SysClkModule_MEM]);
/*brls::SelectListItem* memListItem = createFreqListItem(SysClkModule_MEM, this->profiles.mhzMap[profile][SysClkModule_MEM]);
this->profiles.mhzMap[profile][SysClkModule_MEM] *= 1000000;
@@ -126,7 +126,7 @@ void AppProfileFrame::addFreqs(brls::List* list, SysClkProfile profile)
brls::Logger::debug("Caching freq for module %d and profile %d to %" PRIu32, SysClkModule_MEM, profile, this->profiles.mhzMap[profile][SysClkModule_MEM]);
});
list->addView(memListItem);
list->addView(memListItem);*/
}
void AppProfileFrame::onProfileChanged()

View File

@@ -110,10 +110,7 @@ brls::SelectListItem* createFreqListItem(SysClkModule module, uint32_t selectedF
selected = i + 1;
char clock[16];
if (freq == 1600000000)
snprintf(clock, sizeof(clock), "Max MHz");
else
snprintf(clock, sizeof(clock), "%d MHz", freq / 1000000);
snprintf(clock, sizeof(clock), "%d MHz", freq / 1000000);
clocks.push_back(std::string(clock));

View File

@@ -20,10 +20,6 @@ static inline std::string formatListFreqMhz(std::uint32_t mhz)
{
return FREQ_DEFAULT_TEXT;
}
else if (mhz == 1600)
{
return "Max MHz";
}
char buf[10];
return std::string(buf, snprintf(buf, sizeof(buf), "%u MHz", mhz));

View File

@@ -62,7 +62,7 @@ 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_MEM, &sysclk_g_freq_table_mem_hz[0]);
}
void AppProfileGui::listUI()

View File

@@ -62,7 +62,7 @@ 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_MEM, &sysclk_g_freq_table_mem_hz[0]);
}
void GlobalOverrideGui::refresh()

View File

@@ -247,10 +247,6 @@ void ClockManager::Tick()
if (hz)
{
hz = Clocks::GetNearestHz((SysClkModule)module, isEnabledReverseNX ? RealProfile : this->context->profile, hz);
if (module == SysClkModule_MEM && hz == 1600'000'000 && this->context->freqs[module] >= hz)
{
continue;
}
if (hz != this->context->freqs[module] && this->context->enabled)
{
@@ -446,6 +442,13 @@ bool ClockManager::RefreshContext()
{
hz = Clocks::GetCurrentHz((SysClkModule)module);
// Skip MEM freq check
if (module == SysClkModule_MEM)
{
this->context->freqs[module] = hz;
break;
}
// Round to MHz
uint32_t cur_mhz = hz/1000'000;
uint32_t be4_mhz = this->context->freqs[module]/1000'000;

View File

@@ -179,10 +179,10 @@ void Clocks::ResetToStock(unsigned int module)
{
Clocks::SetHz(SysClkModule_GPU, apmConfiguration->gpu_hz);
}
if (module == SysClkModule_EnumMax || module == SysClkModule_MEM)
{
Clocks::SetHz(SysClkModule_MEM, apmConfiguration->mem_hz);
}
// if (module == SysClkModule_EnumMax || module == SysClkModule_MEM)
// {
// Clocks::SetHz(SysClkModule_MEM, apmConfiguration->mem_hz);
// }
}
else
{
@@ -225,6 +225,9 @@ SysClkProfile Clocks::GetCurrentProfile()
void Clocks::SetHz(SysClkModule module, std::uint32_t hz)
{
if (module == SysClkModule_MEM)
return;
Result rc = 0;
if(hosversionAtLeast(8,0,0))