Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC
This commit is contained in:
@@ -35,8 +35,8 @@ volatile CustomizeTable C = {
|
||||
/* Disables RAM powerdown */
|
||||
.hpMode = DISABLED,
|
||||
|
||||
.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */
|
||||
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
|
||||
.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */
|
||||
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
|
||||
.eristaEmcMaxClock1 = 1600000,
|
||||
.eristaEmcMaxClock2 = 1600000,
|
||||
|
||||
@@ -47,7 +47,7 @@ volatile CustomizeTable C = {
|
||||
.marikoEmcMaxClock = 2133000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
|
||||
.marikoEmcVddqVolt = 600000,
|
||||
|
||||
.emcDvbShift = 0,
|
||||
.emcDvbShift = 0,
|
||||
.marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */
|
||||
|
||||
/* Primary. */
|
||||
@@ -86,35 +86,37 @@ volatile CustomizeTable C = {
|
||||
|
||||
/* You can mix and match different latencies if needed */
|
||||
/*
|
||||
* Read:
|
||||
* 2133RL = 40
|
||||
* 1866RL = 36
|
||||
* 1600RL = 32
|
||||
* 1331RL = 28
|
||||
* Write:
|
||||
* 2133WL = 18
|
||||
* 1866WL = 16
|
||||
* 1600WL = 14
|
||||
* 1331WL = 12
|
||||
* Read:
|
||||
* 2133RL = 40
|
||||
* 1866RL = 36
|
||||
* 1600RL = 32
|
||||
* 1331RL = 28
|
||||
* Write:
|
||||
* 2133WL = 18
|
||||
* 1866WL = 16
|
||||
* 1600WL = 14
|
||||
* 1331WL = 12
|
||||
*/
|
||||
|
||||
.mem_burst_read_latency = RL_1600,
|
||||
/* Erista only. */
|
||||
.mem_burst_read_latency = RL_1600,
|
||||
.mem_burst_write_latency = WL_1600,
|
||||
|
||||
.eristaCpuUV = 0,
|
||||
.eristaCpuVmin = 800,
|
||||
.eristaCpuUV = 0,
|
||||
.eristaCpuVmin = 800,
|
||||
.eristaCpuMaxVolt = 1200,
|
||||
/* Unlocks up to 2397 Mhz CPU, usage is not recommended. */
|
||||
.eristaCpuUnlock = DISABLED,
|
||||
.eristaCpuUnlock = DISABLED,
|
||||
|
||||
.marikoCpuUVLow = 0, // No undervolt
|
||||
.marikoCpuUVLow = 0, // No undervolt
|
||||
.marikoCpuUVHigh = 0, // No undervolt
|
||||
|
||||
.tableConf = TBREAK_1683,
|
||||
.marikoCpuLowVmin = 620,
|
||||
.tableConf = TBREAK_1683,
|
||||
.marikoCpuLowVmin = 620,
|
||||
.marikoCpuHighVmin = 750,
|
||||
|
||||
/* 1120mV is NVIDIA rating */
|
||||
.marikoCpuMaxVolt = 1120,
|
||||
.marikoCpuMaxVolt = 1120,
|
||||
|
||||
/* Supported values: 1963500, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000. */
|
||||
/* 1963500 is official rating of T214/Mariko, fully safe. */
|
||||
@@ -125,17 +127,15 @@ volatile CustomizeTable C = {
|
||||
/* 2703000 is potentially dangerous and not advised. */
|
||||
.marikoCpuMaxClock = 1963500,
|
||||
|
||||
.eristaCpuBoostClock = 1785000, // Default boost clock
|
||||
.marikoCpuBoostClock = 1963500, // Default boost clock
|
||||
.eristaCpuBoostClock = 1785000, /* Default boost clock */
|
||||
.marikoCpuBoostClock = 1963500, /* Default boost clock */
|
||||
|
||||
.eristaGpuUV = 0,
|
||||
.eristaGpuUV = 0,
|
||||
.eristaGpuVmin = 810,
|
||||
|
||||
.marikoGpuUV = 0,
|
||||
|
||||
/* Vmin past 795mV won't work due boot voltage being 800mV. */
|
||||
.marikoGpuVmin = 610,
|
||||
|
||||
.marikoGpuVmax = 800,
|
||||
|
||||
.commonGpuVoltOffset = 0,
|
||||
@@ -147,7 +147,6 @@ volatile CustomizeTable C = {
|
||||
/* AUTO: Voltage is optimally chosen; with commonGpuVoltOffset applied. */
|
||||
/* AUTO only works up to 1305 GPU on Mariko and 998 GPU on Erista (it is reccomended to manually set your 998MHz voltage though) */
|
||||
/* You can overwrite auto with any voltage (in mv) of your choice - offset will not be applied. */
|
||||
|
||||
.eristaGpuVoltArray = {
|
||||
AUTO /* 76 */,
|
||||
AUTO /* 115 */,
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace ams::ldr::hoc {
|
||||
|
||||
enum TableConfig: u32 {
|
||||
DEFAULT_TABLE = 1,
|
||||
TBREAK_1581 = 2,
|
||||
TBREAK_1683 = 3,
|
||||
TBREAK_1581 = 2,
|
||||
TBREAK_1683 = 3,
|
||||
EXTREME_TABLE = 4,
|
||||
};
|
||||
|
||||
@@ -42,19 +42,6 @@ enum StepMode: u32 {
|
||||
StepMode_133MHz = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* Read:
|
||||
* 2133RL = 40
|
||||
* 1866RL = 36
|
||||
* 1600RL = 32
|
||||
* 1331RL = 28
|
||||
* Write:
|
||||
* 2133WL = 18
|
||||
* 1866WL = 16
|
||||
* 1600WL = 14
|
||||
* 1331WL = 12
|
||||
*/
|
||||
|
||||
enum ReadLatency: u32 {
|
||||
RL_2133 = 40,
|
||||
RL_1866 = 36,
|
||||
@@ -74,11 +61,8 @@ using CustomizeGpuDvfsTable = pcv::cvb_entry_t[pcv::DvfsTableEntryLimit];
|
||||
static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(CustomizeGpuDvfsTable));
|
||||
static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(pcv::cvb_entry_t) * pcv::DvfsTableEntryLimit);
|
||||
|
||||
constexpr uint32_t ERISTA_MTC_MAGIC = 0x43544D45; // EMTC
|
||||
constexpr uint32_t MARIKO_MTC_MAGIC = 0x43544D4D; // MMTC
|
||||
|
||||
struct CustomizeTable {
|
||||
u8 cust[4] = {'C', 'U', 'S', 'T'};
|
||||
u8 cust[4] = {'C', 'U', 'S', 'T'};
|
||||
u32 custRev = CUST_REV;
|
||||
u32 kipVersion = KIP_VERSION;
|
||||
|
||||
|
||||
@@ -66,27 +66,32 @@ namespace ams::ldr::hoc {
|
||||
size_t maximum_patched_count = 0;
|
||||
patternFn pattern_search_fn = nullptr;
|
||||
Pointer value_search;
|
||||
|
||||
size_t patched_count = 0;
|
||||
|
||||
Result Apply(Pointer* ptr) {
|
||||
Result Apply(Pointer *ptr) {
|
||||
Result res = patcher_fn(ptr);
|
||||
if (R_SUCCEEDED(res))
|
||||
if (R_SUCCEEDED(res)) {
|
||||
patched_count++;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Result SearchAndApply(Pointer* ptr) {
|
||||
Result SearchAndApply(Pointer *ptr) {
|
||||
bool searchOk = false;
|
||||
if (pattern_search_fn) {
|
||||
if (pattern_search_fn(ptr)) searchOk = true;
|
||||
if (pattern_search_fn(ptr)) {
|
||||
searchOk = true;
|
||||
}
|
||||
} else {
|
||||
if (value_search == *(ptr)) searchOk = true;
|
||||
if (value_search == *(ptr)) {
|
||||
searchOk = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (searchOk)
|
||||
if (searchOk) {
|
||||
return Apply(ptr);
|
||||
}
|
||||
|
||||
R_THROW(ldr::ResultUnsuccessfulPatcher());
|
||||
}
|
||||
@@ -94,8 +99,9 @@ namespace ams::ldr::hoc {
|
||||
Result CheckResult() {
|
||||
R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher());
|
||||
|
||||
if (maximum_patched_count)
|
||||
if (maximum_patched_count) {
|
||||
R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher());
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
@@ -22,20 +22,20 @@
|
||||
|
||||
namespace ams::ldr::hoc::pcv {
|
||||
|
||||
Result MemFreqPllmLimit(u32* ptr) {
|
||||
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);
|
||||
Result MemFreqPllmLimit(u32 *ptr) {
|
||||
clk_pll_param *entry = reinterpret_cast<clk_pll_param *>(ptr);
|
||||
R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry());
|
||||
|
||||
// Double the max clk simply
|
||||
u32 max_clk = entry->freq * 2;
|
||||
entry->freq = max_clk;
|
||||
u32 max_clk = entry->freq * 2;
|
||||
entry->freq = max_clk;
|
||||
entry->vco_max = max_clk;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemVoltHandler(u32* ptr) {
|
||||
Result MemVoltHandler(u32 *ptr) {
|
||||
// ptr value might be default_uv or max_uv
|
||||
regulator* entries[2] = {
|
||||
regulator *entries[2] = {
|
||||
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.default_uv)),
|
||||
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.max_uv)),
|
||||
};
|
||||
@@ -44,16 +44,16 @@ namespace ams::ldr::hoc::pcv {
|
||||
constexpr u32 uv_min = 600'000;
|
||||
|
||||
auto validator = [](regulator* entry) {
|
||||
R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry());
|
||||
R_SUCCEED();
|
||||
};
|
||||
|
||||
regulator* entry = nullptr;
|
||||
for (auto& i : entries) {
|
||||
regulator *entry = nullptr;
|
||||
for (auto &i : entries) {
|
||||
if (R_SUCCEEDED(validator(i))) {
|
||||
entry = i;
|
||||
}
|
||||
@@ -76,24 +76,25 @@ namespace ams::ldr::hoc::pcv {
|
||||
}
|
||||
|
||||
void SafetyCheck() {
|
||||
// if (C.custRev != CUST_REV)
|
||||
// CRASH("Triggered");
|
||||
|
||||
struct sValidator {
|
||||
volatile u32 value;
|
||||
u32 min;
|
||||
u32 max;
|
||||
bool value_required = false;
|
||||
u32 panic;
|
||||
bool value_required = false;
|
||||
|
||||
Result check() {
|
||||
if (!value_required && !value)
|
||||
if (!value_required && !value) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
if (min && value < min)
|
||||
if (min && value < min) {
|
||||
R_THROW(ldr::ResultSafetyCheckFailure());
|
||||
if (max && value > max)
|
||||
}
|
||||
|
||||
if (max && value > max) {
|
||||
R_THROW(ldr::ResultSafetyCheckFailure());
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -102,28 +103,24 @@ namespace ams::ldr::hoc::pcv {
|
||||
u32 eristaCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq);
|
||||
u32 marikoCpuDvfsMaxFreq;
|
||||
if (C.marikoCpuUVHigh) {
|
||||
marikoCpuDvfsMaxFreq = static_cast<u32>(
|
||||
GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq
|
||||
);
|
||||
marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq);
|
||||
} else {
|
||||
marikoCpuDvfsMaxFreq = static_cast<u32>(
|
||||
GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq
|
||||
);
|
||||
marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq);
|
||||
}
|
||||
u32 eristaGpuDvfsMaxFreq;
|
||||
switch (C.eristaGpuUV) {
|
||||
case 0:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
||||
break;
|
||||
case 1:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq);
|
||||
break;
|
||||
case 2:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq);
|
||||
break;
|
||||
default:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
||||
break;
|
||||
case 0:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
||||
break;
|
||||
case 1:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq);
|
||||
break;
|
||||
case 2:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq);
|
||||
break;
|
||||
default:
|
||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
||||
break;
|
||||
}
|
||||
|
||||
u32 marikoGpuDvfsMaxFreq;
|
||||
@@ -142,22 +139,21 @@ namespace ams::ldr::hoc::pcv {
|
||||
break;
|
||||
}
|
||||
|
||||
using namespace ams::ldr::hoc::pcv;
|
||||
sValidator validators[] = {
|
||||
{ C.eristaCpuBoostClock, 1020'000, 2397'000, true, panic::Cpu },
|
||||
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true, panic::Cpu },
|
||||
{ C.eristaCpuMaxVolt, 1000, 1260, false, panic::Cpu },
|
||||
{ C.marikoCpuMaxVolt, 1000, 1200, false, panic::Cpu },
|
||||
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, false, panic::Cpu },
|
||||
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu },
|
||||
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
|
||||
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
|
||||
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc },
|
||||
{ C.marikoEmcVddqVolt, 400'000, 750'000, false, panic::Emc },
|
||||
{ C.marikoSocVmax, 1000, 1200, false, panic::Emc },
|
||||
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
|
||||
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu },
|
||||
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu },
|
||||
{ C.eristaCpuBoostClock, 1020'000, 2397'000, panic::Cpu, true },
|
||||
{ C.marikoCpuBoostClock, 1020'000, 2703'000, panic::Cpu, true },
|
||||
{ C.eristaCpuMaxVolt, 1000, 1260, panic::Cpu, },
|
||||
{ C.marikoCpuMaxVolt, 1000, 1200, panic::Cpu, },
|
||||
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, },
|
||||
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, panic::Cpu, },
|
||||
{ C.commonEmcMemVolt, 912'500, 1350'000, panic::Emc, }, /* Official vmax for the RAMs is 1400-1500mV */
|
||||
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, panic::Emc, },
|
||||
{ C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, },
|
||||
{ C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, },
|
||||
{ C.marikoSocVmax, 1000, 1200, panic::Emc, },
|
||||
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, panic::Gpu, },
|
||||
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, panic::Gpu, },
|
||||
{ C.marikoGpuVmax, 800, 960, panic::Gpu, },
|
||||
};
|
||||
|
||||
for (auto &v : validators) {
|
||||
|
||||
@@ -118,34 +118,34 @@ namespace ams::ldr::hoc::pcv {
|
||||
cvb_entry_t *customize_table;
|
||||
if (isMariko) {
|
||||
switch (C.marikoGpuUV) {
|
||||
case 0:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
break;
|
||||
case 1:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableSLT);
|
||||
break;
|
||||
case 2:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableHiOPT);
|
||||
break;
|
||||
default:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
break;
|
||||
case 1:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableSLT);
|
||||
break;
|
||||
case 2:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableHiOPT);
|
||||
break;
|
||||
default:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (C.eristaGpuUV) {
|
||||
case 0:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
|
||||
break;
|
||||
case 1:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableSLT);
|
||||
break;
|
||||
case 2:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableHiOPT);
|
||||
break;
|
||||
default:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
|
||||
break;
|
||||
case 1:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableSLT);
|
||||
break;
|
||||
case 2:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableHiOPT);
|
||||
break;
|
||||
default:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t default_entry_count = GetDvfsTableEntryCount(default_table);
|
||||
@@ -195,26 +195,6 @@ namespace ams::ldr::hoc::pcv {
|
||||
Result MemFreqPllmLimit(u32 *ptr);
|
||||
Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2
|
||||
|
||||
template <typename T>
|
||||
Result MemMtcCustomizeTable(T *dst, T *src) {
|
||||
constexpr u32 mtc_magic = std::is_same_v<T, MarikoMtcTable> ? MARIKO_MTC_MAGIC : ERISTA_MTC_MAGIC;
|
||||
R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic());
|
||||
|
||||
constexpr u32 ZERO_VAL = UINT32_MAX;
|
||||
// Skip params from dvfs_ver to clock_src;
|
||||
for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32)) {
|
||||
u32 *src_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(src) + offset);
|
||||
u32 *dst_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(dst) + offset);
|
||||
u32 src_val = *src_ent;
|
||||
|
||||
if (src_val){
|
||||
PATCH_OFFSET(dst_ent, src_val == ZERO_VAL ? 0 : src_val);
|
||||
}
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
};
|
||||
|
||||
void SafetyCheck();
|
||||
void Patch(uintptr_t mapped_nso, size_t nso_size);
|
||||
|
||||
|
||||
@@ -145,11 +145,11 @@ namespace ams::ldr::hoc::pcv {
|
||||
constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1;
|
||||
|
||||
template<typename T>
|
||||
size_t GetDvfsTableEntryCount(T* table_head) {
|
||||
size_t GetDvfsTableEntryCount(T *table_head) {
|
||||
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
|
||||
|
||||
auto is_empty = [](NT* entry) {
|
||||
uint8_t* m = reinterpret_cast<uint8_t *>(entry);
|
||||
u8 *m = reinterpret_cast<u8 *>(entry);
|
||||
for (size_t i = 0; i < sizeof(NT); i++) {
|
||||
if (*(m + i)) {
|
||||
return false;
|
||||
@@ -158,7 +158,7 @@ namespace ams::ldr::hoc::pcv {
|
||||
return true;
|
||||
};
|
||||
|
||||
NT* table = const_cast<NT *>(table_head);
|
||||
NT *table = const_cast<NT *>(table_head);
|
||||
size_t count = 0;
|
||||
while (count < DvfsTableEntryLimit) {
|
||||
if (is_empty(table++)) {
|
||||
@@ -170,10 +170,10 @@ namespace ams::ldr::hoc::pcv {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* GetDvfsTableLastEntry(T* table_head) {
|
||||
T *GetDvfsTableLastEntry(T *table_head) {
|
||||
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
|
||||
|
||||
NT* table = const_cast<NT *>(table_head);
|
||||
NT *table = const_cast<NT *>(table_head);
|
||||
size_t count = GetDvfsTableEntryCount(table_head);
|
||||
if (!count) {
|
||||
return nullptr;
|
||||
|
||||
@@ -136,17 +136,13 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
Result GpuFreqMaxAsm(u32 *ptr32) {
|
||||
// Check if both two instructions match the pattern
|
||||
u32 ins1 = *ptr32, ins2 = *(ptr32 + 1);
|
||||
if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1])))
|
||||
if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1]))) {
|
||||
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
|
||||
}
|
||||
|
||||
// Both instructions should operate on the same register
|
||||
u8 rd = asm_get_rd(ins1);
|
||||
if (rd != asm_get_rd(ins2))
|
||||
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
|
||||
|
||||
/* Verify the limit. */
|
||||
/* TODO: Make this a little bit cleaner at some point. */
|
||||
if (AsmGetImm16(ins1) != (GpuClkOsLimit & 0xFFFF) || AsmGetImm16(ins2) != (GpuClkOsLimit >> 16)) {
|
||||
if (rd != asm_get_rd(ins2)) {
|
||||
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
|
||||
}
|
||||
|
||||
@@ -165,6 +161,7 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
max_clock = GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq;
|
||||
break;
|
||||
}
|
||||
|
||||
u32 asm_patch[2] = {
|
||||
asm_set_rd(asm_set_imm16(GpuAsmPattern[0], max_clock), rd),
|
||||
asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd)
|
||||
@@ -279,22 +276,20 @@ namespace ams::ldr::hoc::pcv::erista {
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
|
||||
// ams::ldr::hoc::pcv::mariko::CalculateMrw2();
|
||||
// table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
|
||||
// table->dram_timings.rl = RL;
|
||||
|
||||
/* This needs some clean up. */
|
||||
constexpr double MC_ARB_DIV = 4.0;
|
||||
constexpr u32 MC_ARB_SFA = 2;
|
||||
|
||||
table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(tR2P / MC_ARB_DIV);
|
||||
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA;
|
||||
|
||||
|
||||
@@ -822,8 +822,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
auto DvbVolt = [&](s32 zero, s32 one, s32 two) {
|
||||
return std::array<s32, 3>{
|
||||
ClampVolt(zero, max0),
|
||||
ClampVolt(one, max1),
|
||||
ClampVolt(two, max2)
|
||||
ClampVolt(one, max1),
|
||||
ClampVolt(two, max2)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -832,16 +832,36 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
static_cast<u32>((v)[1]), \
|
||||
static_cast<u32>((v)[2])
|
||||
DvbEntry emcDvbOcTableBrackets[] = {
|
||||
{ 204000, { 637, 637, 637, }, },
|
||||
{ 1331200, { 650, 637, 637, }, },
|
||||
{ 1600000, { 675, 650, 637, }, },
|
||||
{ 1866000, { DVB(DvbVolt( 700, 675, 650)) }, },
|
||||
{ 2133000, { DVB(DvbVolt( 725, 700, 675)) }, },
|
||||
{ 2400000, { DVB(DvbVolt( 750, 725, 700)) }, },
|
||||
{ 2666000, { DVB(DvbVolt( 850, 825, 800)) }, },
|
||||
{ 2933000, { DVB(DvbVolt( 950, 925, 900)) }, },
|
||||
{ 3200000, { DVB(DvbVolt(1050, 1025, 1000)) }, },
|
||||
{ ~0u, { }, },
|
||||
{ 204000, { 637, 637, 637, }, },
|
||||
{ 1331200, { 650, 637, 637, }, },
|
||||
{ 1600000, { 675, 650, 637, }, },
|
||||
{ 1866000, { DVB(DvbVolt( 700, 675, 650)) }, },
|
||||
{ 2133000, { DVB(DvbVolt( 725, 700, 675)) }, },
|
||||
{ 2246000, { DVB(DvbVolt( 750, 725, 700)) }, },
|
||||
{ 2400000, { DVB(DvbVolt( 775, 750, 725)) }, },
|
||||
{ 2466000, { DVB(DvbVolt( 800, 775, 750)) }, },
|
||||
{ 2533000, { DVB(DvbVolt( 810, 785, 760)) }, },
|
||||
{ 2566000, { DVB(DvbVolt( 820, 795, 770)) }, },
|
||||
{ 2600000, { DVB(DvbVolt( 830, 805, 780)) }, },
|
||||
{ 2633000, { DVB(DvbVolt( 840, 815, 790)) }, },
|
||||
{ 2666000, { DVB(DvbVolt( 850, 825, 800)) }, },
|
||||
{ 2700000, { DVB(DvbVolt( 860, 835, 810)) }, },
|
||||
{ 2733000, { DVB(DvbVolt( 870, 845, 820)) }, },
|
||||
{ 2766000, { DVB(DvbVolt( 880, 855, 830)) }, },
|
||||
{ 2800000, { DVB(DvbVolt( 895, 865, 840)) }, },
|
||||
{ 2833000, { DVB(DvbVolt( 900, 875, 850)) }, },
|
||||
{ 2866000, { DVB(DvbVolt( 910, 885, 860)) }, },
|
||||
{ 2900000, { DVB(DvbVolt( 920, 895, 870)) }, },
|
||||
{ 2933000, { DVB(DvbVolt( 950, 905, 880)) }, },
|
||||
{ 2966000, { DVB(DvbVolt( 960, 915, 890)) }, },
|
||||
{ 3000000, { DVB(DvbVolt( 970, 925, 900)) }, },
|
||||
{ 3033000, { DVB(DvbVolt( 980, 940, 910)) }, },
|
||||
{ 3066000, { DVB(DvbVolt(1000, 955, 920)) }, },
|
||||
{ 3100000, { DVB(DvbVolt(1010, 990, 930)) }, },
|
||||
{ 3133000, { DVB(DvbVolt(1025, 1005, 940)) }, },
|
||||
{ 3166000, { DVB(DvbVolt(1035, 1015, 950)) }, },
|
||||
{ 3200000, { DVB(DvbVolt(1050, 1025, 960)) }, },
|
||||
{ ~0u, { }, },
|
||||
};
|
||||
#undef DVB
|
||||
DvbEntry emcDvbTableOc[newEmcList.size()];
|
||||
|
||||
Reference in New Issue
Block a user