exo/mariko fatal: perform display init, reboot on power button press

This commit is contained in:
Michael Scire 2020-11-20 01:05:45 -08:00 committed by SciresM
parent 45830472c1
commit 8ba1cdeef2
9 changed files with 1510 additions and 13 deletions

View file

@ -15,23 +15,439 @@
*/
#include <exosphere.hpp>
#include "fatal_device_page_table.hpp"
#include "fatal_registers_di.hpp"
namespace ams::secmon::fatal {
void InitializeDisplay() {
/* TODO */
AMS_SECMON_LOG("InitializeDisplay not yet implemented\n");
namespace {
#include "fatal_display_config.inc"
}
namespace {
/* Helpful defines. */
constexpr size_t FrameBufferHeight = 768;
constexpr size_t FrameBufferWidth = 1280;
constexpr size_t FrameBufferSize = FrameBufferHeight * FrameBufferWidth * sizeof(u32);
constexpr int DsiWaitForCommandMilliSecondsMax = 250;
constexpr int DsiWaitForCommandCompletionMilliSeconds = 5;
constexpr int DsiWaitForHostControlMilliSecondsMax = 150;
constexpr inline int I2cAddressMax77620Pmic = 0x3C;
constexpr size_t GPIO_PORT3_CNF_0 = 0x200;
constexpr size_t GPIO_PORT3_OE_0 = 0x210;
constexpr size_t GPIO_PORT3_OUT_0 = 0x220;
constexpr size_t GPIO_PORT6_CNF_1 = 0x504;
constexpr size_t GPIO_PORT6_OE_1 = 0x514;
constexpr size_t GPIO_PORT6_OUT_1 = 0x524;
/* Globals. */
constexpr inline const uintptr_t PMC = secmon::MemoryRegionVirtualDevicePmc .GetAddress();
constexpr inline const uintptr_t g_disp1_regs = secmon::MemoryRegionVirtualDeviceDisp1 .GetAddress();
constexpr inline const uintptr_t g_dsi_regs = secmon::MemoryRegionVirtualDeviceDsi .GetAddress();
constexpr inline const uintptr_t g_clk_rst_regs = secmon::MemoryRegionVirtualDeviceClkRst .GetAddress();
constexpr inline const uintptr_t g_gpio_regs = secmon::MemoryRegionVirtualDeviceGpio .GetAddress();
constexpr inline const uintptr_t g_apb_misc_regs = secmon::MemoryRegionVirtualDeviceApbMisc.GetAddress();
constexpr inline const uintptr_t g_mipi_cal_regs = secmon::MemoryRegionVirtualDeviceMipiCal.GetAddress();
constinit u32 *g_frame_buffer = nullptr;
inline void DoRegisterWrites(uintptr_t base_address, const RegisterWrite *reg_writes, size_t num_writes) {
for (size_t i = 0; i < num_writes; i++) {
reg::Write(base_address + reg_writes[i].offset, reg_writes[i].value);
}
}
inline void DoSocDependentRegisterWrites(uintptr_t base_address, const RegisterWrite *reg_writes_erista, size_t num_writes_erista, const RegisterWrite *reg_writes_mariko, size_t num_writes_mariko) {
switch (GetSocType()) {
case fuse::SocType_Erista: DoRegisterWrites(base_address, reg_writes_erista, num_writes_erista); break;
case fuse::SocType_Mariko: DoRegisterWrites(base_address, reg_writes_mariko, num_writes_mariko); break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
inline void DoSleepOrRegisterWrites(uintptr_t base_address, const SleepOrRegisterWrite *reg_writes, size_t num_writes) {
for (size_t i = 0; i < num_writes; i++) {
switch (reg_writes[i].kind) {
case SleepOrRegisterWriteKind_Write:
reg::Write(base_address + sizeof(u32) * reg_writes[i].offset, reg_writes[i].value);
break;
case SleepOrRegisterWriteKind_Sleep:
util::WaitMicroSeconds(reg_writes[i].offset * UINT64_C(1000));
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}
void WaitDsiTrigger() {
const u32 timeout = util::GetMicroSeconds() + (DsiWaitForCommandMilliSecondsMax * 1000u);
while (true) {
if (util::GetMicroSeconds() >= timeout) {
break;
}
if (reg::Read(g_dsi_regs + sizeof(u32) * DSI_TRIGGER) == 0) {
break;
}
}
util::WaitMicroSeconds(DsiWaitForCommandCompletionMilliSeconds * 1000u);
}
void WaitDsiHostControl() {
const u32 timeout = util::GetMicroSeconds() + (DsiWaitForHostControlMilliSecondsMax * 1000u);
while (true) {
if (util::GetMicroSeconds() >= timeout) {
break;
}
if ((reg::Read(g_dsi_regs + sizeof(u32) * DSI_HOST_CONTROL) & DSI_HOST_CONTROL_IMM_BTA) == 0) {
break;
}
}
}
void EnableBacklightForVendor2050ForHardwareTypeFive(int brightness) {
/* Enable FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_ENABLE, 2);
/* Configure DSI_LINE_TYPE as FOUR */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 9);
/* Set and wait for FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS, 2);
while ((reg::Read(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS) & 2) != 0) { /* ... */ }
/* Configure display brightness. */
const u32 brightness_val = ((0x7FF * brightness) / 100);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x339);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, (brightness_val & 0x700) | ((brightness_val & 0xFF) << 16) | 0x51);
/* Set and wait for FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS, 2);
while ((reg::Read(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS) & 2) != 0) { /* ... */ }
/* Set client sync point block reset. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_INCR_SYNCPT_CNTRL, 1);
util::WaitMicroSeconds(300'000ul);
/* Clear client sync point block resest. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_INCR_SYNCPT_CNTRL, 0);
util::WaitMicroSeconds(300'000ul);
/* Clear DSI_LINE_TYPE config. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 0);
/* Disable FRAME_END_INT */
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_ENABLE, 0);
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_INT_STATUS, 2);
}
void EnableBacklightForGeneric(int brightness) {
AMS_UNUSED(brightness);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x1);
}
#define DO_REGISTER_WRITES(base_address, writes) DoRegisterWrites(base_address, writes, util::size(writes))
#define DO_SOC_DEPENDENT_REGISTER_WRITES(base_address, writes) DoSocDependentRegisterWrites(base_address, writes##Erista, util::size(writes##Erista), writes##Mariko, util::size(writes##Mariko))
#define DO_SLEEP_OR_REGISTER_WRITES(base_address, writes) DoSleepOrRegisterWrites(base_address, writes, util::size(writes))
void InitializeFrameBuffer() {
if (g_frame_buffer != nullptr) {
std::memset(g_frame_buffer, 0, FrameBufferSize);
hw::FlushDataCache(g_frame_buffer, FrameBufferSize);
} else {
/* Clear the frame buffer. */
g_frame_buffer = secmon::MemoryRegionDramDcFramebuffer.GetPointer<u32>();
std::memset(g_frame_buffer, 0, FrameBufferSize);
hw::FlushDataCache(g_frame_buffer, FrameBufferSize);
/* Attach the frame buffer to DC. */
InitializeDevicePageTableForDc();
}
}
void FinalizeFrameBuffer() {
/* We don't actually support finalizing the framebuffer, so do nothing here. */
}
void ShowDisplay(const ams::impl::FatalErrorContext *f_ctx, const Result save_result) {
/* TODO */
AMS_UNUSED(f_ctx, save_result);
AMS_SECMON_LOG("ShowDisplay not yet implemented\n");
}
void FinalizeDisplay() {
FinalizeFrameBuffer();
/* TODO */
AMS_SECMON_LOG("FinalizeDisplay not yet implemented\n");
}
void InitializeDisplay() {
/* Ensure that the display is finalized. */
/* TODO */
/* Setup the framebuffer. */
InitializeFrameBuffer();
/* Get the hardware type. */
const auto hw_type = fuse::GetHardwareType();
/* Turn on DSI/voltage rail. */
{
if (GetSocType() == fuse::SocType_Mariko) {
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, 0x18, 0x3A);
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, 0x18, 0x3A);
}
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, 0x23, 0xD0);
}
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_H_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_H_CLR_CLR_MIPI_CAL_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_H_CLR_CLR_DSI_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_H_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_H_SET_SET_CLK_ENB_MIPI_CAL, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_H_SET_SET_CLK_ENB_DSI, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_L_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_L_CLR_CLR_HOST1X_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_L_CLR_CLR_DISP1_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_L_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_L_SET_SET_CLK_ENB_HOST1X, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_L_SET_SET_CLK_ENB_DISP1, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_X_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_X_SET_SET_CLK_ENB_UART_FST_MIPI_CAL, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_UART_FST_MIPI_CAL_UART_FST_MIPI_CAL_CLK_DIVISOR, 10),
CLK_RST_REG_BITS_ENUM (CLK_SOURCE_UART_FST_MIPI_CAL_UART_FST_MIPI_CAL_CLK_SRC, PLLP_OUT3));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_W_SET, CLK_RST_REG_BITS_ENUM(CLK_ENB_W_SET_SET_CLK_ENB_DSIA_LP, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_DSIA_LP_DSIA_LP_CLK_DIVISOR, 10),
CLK_RST_REG_BITS_ENUM (CLK_SOURCE_DSIA_LP_DSIA_LP_CLK_SRC, PLLP_OUT0));
/* Set IO_DPD_REQ to DPD_OFF. */
reg::ReadWrite(PMC + APBDEV_PMC_IO_DPD_REQ, PMC_REG_BITS_ENUM(IO_DPD_REQ_CODE, DPD_OFF));
reg::ReadWrite(PMC + APBDEV_PMC_IO_DPD2_REQ, PMC_REG_BITS_ENUM(IO_DPD2_REQ_CODE, DPD_OFF));
/* Configure LCD pinmux tristate + passthrough. */
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_INT, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_PWM, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_RST, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
if (hw_type == fuse::HardwareType_Five) {
/* Configure LCD backlight. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x4);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x4);
} else {
/* Configure LCD power, VDD. */
reg::SetBits(g_gpio_regs + GPIO_PORT3_CNF_0, 0x3);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OE_0, 0x3);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x1);
util::WaitMicroSeconds(10'000ul);
reg::SetBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x2);
util::WaitMicroSeconds(10'000ul);
/* Configure LCD backlight. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x7);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OE_1, 0x7);
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x2);
}
/* Configure display interface and display. */
reg::Write(g_mipi_cal_regs + MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0);
if (GetSocType() == fuse::SocType_Mariko) {
reg::Write(g_mipi_cal_regs + MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0);
reg::Write(g_apb_misc_regs + APB_MISC_GP_DSI_PAD_CONTROL, 0);
}
/* Execute configs. */
DO_SOC_DEPENDENT_REGISTER_WRITES(g_clk_rst_regs, DisplayConfigPlld01);
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigDc01);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init01);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init02);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init03);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init04);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init05);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsiPhyTiming);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init06);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsiPhyTiming);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init07);
util::WaitMicroSeconds(10'000ul);
/* Enable backlight reset. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x4);
util::WaitMicroSeconds(60'000ul);
if (hw_type == fuse::HardwareType_Five) {
reg::Write(g_dsi_regs + sizeof(u32) * DSI_BTA_TIMING, 0x40103);
} else {
reg::Write(g_dsi_regs + sizeof(u32) * DSI_BTA_TIMING, 0x50204);
}
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x337);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
WaitDsiTrigger();
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x406);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
WaitDsiTrigger();
reg::Write(g_dsi_regs + sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC);
WaitDsiHostControl();
util::WaitMicroSeconds(5'000ul);
/* Parse LCD vendor. */
{
u32 host_response[3];
for (size_t i = 0; i < util::size(host_response); i++) {
host_response[i] = reg::Read(g_dsi_regs + sizeof(u32) * DSI_RD_DATA);
}
/* The last word from host response is:
Bits 0-7: FAB
Bits 8-15: REV
Bits 16-23: Minor REV
*/
u32 lcd_vendor;
if ((host_response[2] & 0xFF) == 0x10) {
lcd_vendor = 0;
} else {
lcd_vendor = (host_response[2] >> 8) & 0xFF00;
}
lcd_vendor = (lcd_vendor & 0xFFFFFF00) | (host_response[2] & 0xFF);
AMS_ASSERT(lcd_vendor == GetLcdVendor());
}
/* LCD vendor specific configuration. */
switch (GetLcdVendor()) {
case 0x10: /* Japan Display Inc screens. */
DO_SLEEP_OR_REGISTER_WRITES(g_dsi_regs, DisplayConfigJdiSpecificInit01);
break;
case 0xF20: /* Innolux first revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(180'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x739);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x751548B1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x143209);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
case 0xF30: /* AUO first revision screens. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(180'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x439);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x9483FFB9);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x739);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x711148B1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x143209);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
case 0x2050: /* Unknown (hardware type 5) screen. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(180'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0xA015);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x205315);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x339);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x51);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(5'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
case 0x1020: /* Innolux second revision screen. */
case 0x1030: /* AUO second revision screen. */
case 0x1040: /* Unknown second revision screen. */
default:
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
util::WaitMicroSeconds(120'000ul);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
}
util::WaitMicroSeconds(20'000ul);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_clk_rst_regs, DisplayConfigPlld02);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init08);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsiPhyTiming);
DO_SLEEP_OR_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init09);
reg::Write(g_disp1_regs + sizeof(u32) * DC_DISP_DISP_CLOCK_CONTROL, SHIFT_CLK_DIVIDER(4));
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init10);
util::WaitMicroSeconds(10'000ul);
/* Configure MIPI CAL. */
DO_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal01);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal02);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init11);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal03);
DO_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal04);
if (GetSocType() == fuse::SocType_Mariko) {
/* On Mariko the above configurations are executed twice, for some reason. */
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal02);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init11);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal03);
DO_REGISTER_WRITES(g_mipi_cal_regs, DisplayConfigMipiCal04);
}
util::WaitMicroSeconds(10'000ul);
/* Write DISP1, FrameBuffer config. */
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigDc02);
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigFrameBuffer);
if (GetLcdVendor() != 0x2050) {
util::WaitMicroSeconds(35'000ul);
}
}
void ShowDisplay(const ams::impl::FatalErrorContext *f_ctx, const Result save_result) {
/* Draw the image to the screen. */
std::memset(g_frame_buffer, 0, FrameBufferSize);
{
/* TODO: Actually print the contents of the report. */
AMS_UNUSED(f_ctx, save_result);
for (size_t n = 0; n < 8; n++) {
const size_t x = n * (FrameBufferWidth / 8);
for (size_t cur_y = 0; cur_y < FrameBufferHeight; cur_y++) {
for (size_t cur_x = 0; cur_x < (FrameBufferWidth / 8); cur_x++) {
g_frame_buffer[(FrameBufferWidth - (x + cur_x)) * FrameBufferHeight + 0 + cur_y] = ((0x20 * n) | 0x1F);
}
}
}
}
hw::FlushDataCache(g_frame_buffer, FrameBufferSize);
/* Enable backlight. */
constexpr auto DisplayBrightness = 100;
if (GetLcdVendor() == 0x2050) {
EnableBacklightForVendor2050ForHardwareTypeFive(DisplayBrightness);
} else {
EnableBacklightForGeneric(DisplayBrightness);
}
}
}

View file

@ -0,0 +1,682 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
struct RegisterWrite {
u32 offset;
u32 value;
};
enum SleepOrRegisterWriteKind : u16 {
SleepOrRegisterWriteKind_Write = 0,
SleepOrRegisterWriteKind_Sleep = 1,
};
struct SleepOrRegisterWrite {
SleepOrRegisterWriteKind kind;
u16 offset;
u32 value;
};
constexpr const RegisterWrite DisplayConfigPlld01Erista[] = {
{CLK_RST_CONTROLLER_CLK_SOURCE_DISP1, 0x40000000},
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4830A001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000020},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002D0AAA},
};
constexpr const RegisterWrite DisplayConfigPlld01Mariko[] = {
{CLK_RST_CONTROLLER_CLK_SOURCE_DISP1, 0x40000000},
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4830A001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000000},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002DFC00},
};
constexpr const SleepOrRegisterWrite DisplayConfigDc01[] = {
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_REG_ACT_CONTROL, 0x54},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_DISP_DC_MCCIF_FIFOCTRL, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_MEM_HIGH_PRIORITY, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE},
{SleepOrRegisterWriteKind_Write, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL},
{SleepOrRegisterWriteKind_Write, DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9}, // 9: SYNCPT
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{SleepOrRegisterWriteKind_Write, 0x4E4, 0},
{SleepOrRegisterWriteKind_Write, DC_COM_CRC_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}
};
constexpr const RegisterWrite DisplayConfigDsi01Init01[] = {
{sizeof(u32) * DSI_WR_DATA, 0x0},
{sizeof(u32) * DSI_INT_ENABLE, 0x0},
{sizeof(u32) * DSI_INT_STATUS, 0x0},
{sizeof(u32) * DSI_INT_MASK, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_0, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_1, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_2, 0x0},
{sizeof(u32) * DSI_INIT_SEQ_DATA_3, 0x0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init02Erista[] = {
{sizeof(u32) * DSI_INIT_SEQ_DATA_15, 0x0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init02Mariko[] = {
{sizeof(u32) * DSI_INIT_SEQ_DATA_15_MARIKO, 0x0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init03[] = {
{sizeof(u32) * DSI_DCS_CMDS, 0},
{sizeof(u32) * DSI_PKT_SEQ_0_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_1_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_2_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_3_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_4_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_5_LO, 0},
{sizeof(u32) * DSI_PKT_SEQ_0_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_1_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_2_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_3_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_4_HI, 0},
{sizeof(u32) * DSI_PKT_SEQ_5_HI, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init04Erista[] = {
/* No register writes. */
};
constexpr const RegisterWrite DisplayConfigDsi01Init04Mariko[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
{sizeof(u32) * DSI_PAD_CONTROL_2, 0},
{sizeof(u32) * DSI_PAD_CONTROL_3, 0},
{sizeof(u32) * DSI_PAD_CONTROL_4, 0},
{sizeof(u32) * DSI_PAD_CONTROL_5_MARIKO, 0},
{sizeof(u32) * DSI_PAD_CONTROL_6_MARIKO, 0},
{sizeof(u32) * DSI_PAD_CONTROL_7_MARIKO, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init05[] = {
{sizeof(u32) * DSI_PAD_CONTROL_CD, 0},
{sizeof(u32) * DSI_SOL_DELAY, 0x18},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x1E0},
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_INIT_SEQ_CONTROL, 0},
{sizeof(u32) * DSI_PKT_LEN_0_1, 0},
{sizeof(u32) * DSI_PKT_LEN_2_3, 0},
{sizeof(u32) * DSI_PKT_LEN_4_5, 0},
{sizeof(u32) * DSI_PKT_LEN_6_7, 0},
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init06[] = {
{sizeof(u32) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(u32) * DSI_PHY_TIMING_2, 0x30109},
{sizeof(u32) * DSI_BTA_TIMING, 0x190A14},
{sizeof(u32) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{sizeof(u32) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(u32) * DSI_TO_TALLY, 0},
{sizeof(u32) * DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, 0},
{sizeof(u32) * DSI_POWER_CONTROL, 0},
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init07[] = {
{sizeof(u32) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(u32) * DSI_PHY_TIMING_2, 0x30118},
{sizeof(u32) * DSI_BTA_TIMING, 0x190A14},
{sizeof(u32) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{sizeof(u32) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(u32) * DSI_TO_TALLY, 0},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x40},
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_TX_CRC, 0},
{sizeof(u32) * DSI_INIT_SEQ_CONTROL, 0}
};
constexpr const RegisterWrite DisplayConfigDsiPhyTimingErista[] = {
{sizeof(u32) * DSI_PHY_TIMING_0, 0x6070601},
};
constexpr const RegisterWrite DisplayConfigDsiPhyTimingMariko[] = {
{sizeof(u32) * DSI_PHY_TIMING_0, 0x6070603},
};
constexpr const SleepOrRegisterWrite DisplayConfigJdiSpecificInit01[] = {
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x9483FFB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xBD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x1939},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAD8},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAEB},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAEBAAAA},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAAA},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAAAAAEB},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAAEBAAAA},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xAA},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x1BD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2739},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFD8},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2BD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xF39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFD8},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xFFFFFF},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xBD15},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x6D915},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x1105},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Sleep, 180, 0},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2905},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
constexpr const RegisterWrite DisplayConfigPlld02Erista[] = {
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4810c001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000020},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002D0AAA},
};
constexpr const RegisterWrite DisplayConfigPlld02Mariko[] = {
{CLK_RST_CONTROLLER_PLLD_BASE, 0x4810c001},
{CLK_RST_CONTROLLER_PLLD_MISC1, 0x00000000},
{CLK_RST_CONTROLLER_PLLD_MISC, 0x002DFC00},
};
constexpr const RegisterWrite DisplayConfigDsi01Init08[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const SleepOrRegisterWrite DisplayConfigDsi01Init09[] = {
{SleepOrRegisterWriteKind_Write, DSI_PHY_TIMING_1, 0x40A0E05},
{SleepOrRegisterWriteKind_Write, DSI_PHY_TIMING_2, 0x30172},
{SleepOrRegisterWriteKind_Write, DSI_BTA_TIMING, 0x190A14},
{SleepOrRegisterWriteKind_Write, DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)},
{SleepOrRegisterWriteKind_Write, DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)},
{SleepOrRegisterWriteKind_Write, DSI_TO_TALLY, 0},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_0_LO, 0x40000208},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_2_LO, 0x40000308},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_4_LO, 0x40000308},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_1_LO, 0x40000308},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_3_LO, 0x3F3B2B08},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_3_HI, 0x2CC},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_5_LO, 0x3F3B2B08},
{SleepOrRegisterWriteKind_Write, DSI_PKT_SEQ_5_HI, 0x2CC},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_0_1, 0xCE0000},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_2_3, 0x87001A2},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_4_5, 0x190},
{SleepOrRegisterWriteKind_Write, DSI_PKT_LEN_6_7, 0x190},
{SleepOrRegisterWriteKind_Write, DSI_HOST_CONTROL, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Init10[] = {
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_CONTROL, 0},
{sizeof(u32) * DSI_SOL_DELAY, 6},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x1E0},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}
};
constexpr const RegisterWrite DisplayConfigDsi01Init11Erista[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
{sizeof(u32) * DSI_PAD_CONTROL_2, 0},
{sizeof(u32) * DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
{sizeof(u32) * DSI_PAD_CONTROL_4, 0}
};
constexpr const RegisterWrite DisplayConfigDsi01Init11Mariko[] = {
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
{sizeof(u32) * DSI_PAD_CONTROL_2, 0},
{sizeof(u32) * DSI_PAD_CONTROL_3, 0},
{sizeof(u32) * DSI_PAD_CONTROL_4, 0x77777},
{sizeof(u32) * DSI_PAD_CONTROL_5_MARIKO, 0x77777},
{sizeof(u32) * DSI_PAD_CONTROL_6_MARIKO, DSI_PAD_PREEMP_PD_CLK(0x1) | DSI_PAD_PREEMP_PU_CLK(0x1) | DSI_PAD_PREEMP_PD(0x01) | DSI_PAD_PREEMP_PU(0x1)},
{sizeof(u32) * DSI_PAD_CONTROL_7_MARIKO, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal01[] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 1},
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal02Erista[] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0x300},
};
constexpr const RegisterWrite DisplayConfigMipiCal02Mariko[] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal03Erista[] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal03Mariko[] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
};
constexpr const RegisterWrite DisplayConfigMipiCal04[] = {
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILD_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILE_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILF_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001},
};
constexpr const SleepOrRegisterWrite DisplayConfigDc02[] = {
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_DV_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_YOF, 0xF0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KYRGB, 0x12A},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUR, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVR, 0x198},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUG, 0x39B},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVG, 0x32F},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KUB, 0x204},
{SleepOrRegisterWriteKind_Write, DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{SleepOrRegisterWriteKind_Write, 0x4E4, 0},
{SleepOrRegisterWriteKind_Write, DC_COM_CRC_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, 0x716, 0x10000FF},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
/* Set Display timings */
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_TIMING_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_REF_TO_SYNC, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1.
{SleepOrRegisterWriteKind_Write, DC_DISP_SYNC_WIDTH, 0x10048},
{SleepOrRegisterWriteKind_Write, DC_DISP_BACK_PORCH, 0x90048},
{SleepOrRegisterWriteKind_Write, DC_DISP_ACTIVE, 0x50002D0},
{SleepOrRegisterWriteKind_Write, DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd.
/* End of Display timings */
{SleepOrRegisterWriteKind_Write, DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
{SleepOrRegisterWriteKind_Write, DC_COM_PIN_OUTPUT_ENABLE(1), 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_CLOCK_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX},
{SleepOrRegisterWriteKind_Write, DC_DISP_FRONT_PORCH, 0xA0088},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{SleepOrRegisterWriteKind_Write, DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_ACCESS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND_OPTION0, 0}
};
constexpr u32 DisplayConfigFrameBufferAddress = 0xC0000000;
constexpr const SleepOrRegisterWrite DisplayConfigFrameBuffer[] = {
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C.
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B.
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A.
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_POSITION, 0}, //(0,0)
{SleepOrRegisterWriteKind_Write, DC_WIN_H_INITIAL_DDA, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_V_INITIAL_DDA, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes.
{SleepOrRegisterWriteKind_Write, DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)},
{SleepOrRegisterWriteKind_Write, DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels.
{SleepOrRegisterWriteKind_Write, DC_WIN_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{SleepOrRegisterWriteKind_Write, DC_WIN_BUFFER_CONTROL, 0},
{SleepOrRegisterWriteKind_Write, DC_WINBUF_SURFACE_KIND, 0}, //Regular surface.
{SleepOrRegisterWriteKind_Write, DC_WINBUF_START_ADDR, DisplayConfigFrameBufferAddress}, //Framebuffer address.
{SleepOrRegisterWriteKind_Write, DC_WINBUF_ADDR_H_OFFSET, 0},
{SleepOrRegisterWriteKind_Write, DC_WINBUF_ADDR_V_OFFSET, 0},
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, 0},
{SleepOrRegisterWriteKind_Write, DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{SleepOrRegisterWriteKind_Write, DC_WIN_WIN_OPTIONS, WIN_ENABLE}, //Enable window AD.
{SleepOrRegisterWriteKind_Write, DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display.
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update.
{SleepOrRegisterWriteKind_Write, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request.
};
constexpr const RegisterWrite DisplayConfigDc01Fini01[] = {
{sizeof(u32) * DC_DISP_FRONT_PORCH, 0xA0088},
{sizeof(u32) * DC_CMD_INT_MASK, 0},
{sizeof(u32) * DC_CMD_STATE_ACCESS, 0},
{sizeof(u32) * DC_CMD_INT_ENABLE, 0},
{sizeof(u32) * DC_CMD_CONT_SYNCPT_VSYNC, 0},
{sizeof(u32) * DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(u32) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(u32) * DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{sizeof(u32) * DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
};
constexpr const RegisterWrite DisplayConfigDsi01Fini01[] = {
{sizeof(u32) * DSI_POWER_CONTROL, 0},
{sizeof(u32) * DSI_PAD_CONTROL_1, 0},
};
constexpr const RegisterWrite DisplayConfigDsi01Fini02[] = {
{sizeof(u32) * DSI_PHY_TIMING_1, 0x40A0E05},
{sizeof(u32) * DSI_PHY_TIMING_2, 0x30118},
{sizeof(u32) * DSI_BTA_TIMING, 0x190A14},
{sizeof(u32) * DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
{sizeof(u32) * DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{sizeof(u32) * DSI_TO_TALLY, 0},
{sizeof(u32) * DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{sizeof(u32) * DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{sizeof(u32) * DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{sizeof(u32) * DSI_MAX_THRESHOLD, 0x40},
{sizeof(u32) * DSI_TRIGGER, 0},
{sizeof(u32) * DSI_TX_CRC, 0},
{sizeof(u32) * DSI_INIT_SEQ_CONTROL, 0}
};
constexpr const SleepOrRegisterWrite DisplayConfigJdiSpecificFini01[] = {
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x9483FFB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2139},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x191919D5},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x4F0F41B1},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xF179A433},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2D81},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
};
constexpr const SleepOrRegisterWrite DisplayConfigAuoRev1SpecificFini01[] = {
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x9483FFB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2C39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x191919D5},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x2C39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x191919D6},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x19191919},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB39},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x711148B1},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x71143209},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x114D31},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0x439},
{SleepOrRegisterWriteKind_Write, DSI_WR_DATA, 0xB9},
{SleepOrRegisterWriteKind_Write, DSI_TRIGGER, DSI_TRIGGER_HOST},
{SleepOrRegisterWriteKind_Sleep, 5, 0},
};

View file

@ -22,6 +22,8 @@ namespace ams::secmon::fatal {
namespace {
constexpr inline int I2cAddressMax77620Pmic = 0x3C;
ALWAYS_INLINE const ams::impl::FatalErrorContext *GetFatalErrorContext() {
return MemoryRegionVirtualTzramMarikoProgramFatalErrorContext.GetPointer<ams::impl::FatalErrorContext>();
}
@ -58,6 +60,10 @@ namespace ams::secmon::fatal {
AMS_SECMON_LOG("Failed to save fatal error context: %08x\n", result.GetValue());
}
/* Ensure that i2c-5 is usable for communicating with the pmic. */
clkrst::EnableI2c5Clock();
i2c::Initialize(i2c::Port_5);
/* Display the fatal error. */
{
AMS_SECMON_LOG("Showing Display, LCD Vendor = %04x\n", GetLcdVendor());
@ -69,7 +75,15 @@ namespace ams::secmon::fatal {
/* Ensure we have nothing waiting to be logged. */
AMS_LOG_FLUSH();
/* TODO: Wait for a button press, then reboot. */
/* Wait for power button to be pressed. */
while (!pmic::IsPowerButtonPressed()) {
util::WaitMicroSeconds(100);
}
/* Reboot. */
pmic::ShutdownSystem(true);
/* Wait for our reboot to complete. */
AMS_INFINITE_LOOP();
}

View file

@ -0,0 +1,352 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <exosphere.hpp>
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
#define SYNCPT_CNTRL_NO_STALL (1 << 8)
#define SYNCPT_CNTRL_SOFT_RESET (1 << 0)
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
#define SYNCPT_VSYNC_ENABLE (1 << 8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
#define DC_CMD_DISPLAY_COMMAND 0x32
#define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
#define DISP_CTRL_MODE_MASK (3 << 5)
#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
#define PW0_ENABLE (1 << 0)
#define PW1_ENABLE (1 << 2)
#define PW2_ENABLE (1 << 4)
#define PW3_ENABLE (1 << 6)
#define PW4_ENABLE (1 << 8)
#define PM0_ENABLE (1 << 16)
#define PM1_ENABLE (1 << 18)
#define DC_CMD_INT_STATUS 0x37
#define DC_CMD_INT_MASK 0x38
#define DC_CMD_INT_ENABLE 0x39
#define DC_CMD_STATE_ACCESS 0x40
#define READ_MUX (1 << 0)
#define WRITE_MUX (1 << 2)
#define DC_CMD_STATE_CONTROL 0x41
#define GENERAL_ACT_REQ (1 << 0)
#define WIN_A_ACT_REQ (1 << 1)
#define WIN_B_ACT_REQ (1 << 2)
#define WIN_C_ACT_REQ (1 << 3)
#define CURSOR_ACT_REQ (1 << 7)
#define GENERAL_UPDATE (1 << 8)
#define WIN_A_UPDATE (1 << 9)
#define WIN_B_UPDATE (1 << 10)
#define WIN_C_UPDATE (1 << 11)
#define CURSOR_UPDATE (1 << 15)
#define NC_HOST_TRIG (1 << 24)
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
#define WINDOW_A_SELECT (1 << 4)
#define WINDOW_B_SELECT (1 << 5)
#define WINDOW_C_SELECT (1 << 6)
#define DC_CMD_REG_ACT_CONTROL 0x043
#define DC_COM_CRC_CONTROL 0x300
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define DC_COM_DSC_TOP_CTL 0x33E
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE (1 << 29)
#define SOR1_TIMING_CYA (1 << 27)
#define SOR1_ENABLE (1 << 26)
#define SOR_ENABLE (1 << 25)
#define CURSOR_ENABLE (1 << 16)
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
#define DC_DISP_REF_TO_SYNC 0x406
#define DC_DISP_SYNC_WIDTH 0x407
#define DC_DISP_BACK_PORCH 0x408
#define DC_DISP_ACTIVE 0x409
#define DC_DISP_FRONT_PORCH 0x40A
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
#define DISP_DATA_FORMAT_DF2S (4 << 0)
#define DISP_DATA_FORMAT_DF3S (5 << 0)
#define DISP_DATA_FORMAT_DFSPI (6 << 0)
#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
#define DISP_ALIGNMENT_MSB (0 << 8)
#define DISP_ALIGNMENT_LSB (1 << 8)
#define DISP_ORDER_RED_BLUE (0 << 9)
#define DISP_ORDER_BLUE_RED (1 << 9)
#define DC_DISP_DISP_COLOR_CONTROL 0x430
#define DITHER_CONTROL_MASK (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
#define BASE_COLOR_SIZE_MASK (0xf << 0)
#define BASE_COLOR_SIZE_666 (0 << 0)
#define BASE_COLOR_SIZE_111 (1 << 0)
#define BASE_COLOR_SIZE_222 (2 << 0)
#define BASE_COLOR_SIZE_333 (3 << 0)
#define BASE_COLOR_SIZE_444 (4 << 0)
#define BASE_COLOR_SIZE_555 (5 << 0)
#define BASE_COLOR_SIZE_565 (6 << 0)
#define BASE_COLOR_SIZE_332 (7 << 0)
#define BASE_COLOR_SIZE_888 (8 << 0)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC1_H_QUALIFIER_NONE (1 << 16)
#define SC0_H_QUALIFIER_NONE (1 << 0)
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
#define DE_SELECT_ACTIVE (1 << 0)
#define DE_SELECT_ACTIVE_IS (2 << 0)
#define DE_CONTROL_ONECLK (0 << 2)
#define DE_CONTROL_NORMAL (1 << 2)
#define DE_CONTROL_EARLY_EXT (2 << 2)
#define DE_CONTROL_EARLY (3 << 2)
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
#define DC_DISP_SD_BL_PARAMETERS 0x4D7
#define DC_DISP_SD_BL_CONTROL 0x4DC
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_WIN_CSC_YOF 0x611
#define DC_WIN_CSC_KYRGB 0x612
#define DC_WIN_CSC_KUR 0x613
#define DC_WIN_CSC_KVR 0x614
#define DC_WIN_CSC_KUG 0x615
#define DC_WIN_CSC_KVG 0x616
#define DC_WIN_CSC_KUB 0x617
#define DC_WIN_CSC_KVB 0x618
#define DC_WIN_AD_WIN_OPTIONS 0xB80
#define DC_WIN_BD_WIN_OPTIONS 0xD80
#define DC_WIN_CD_WIN_OPTIONS 0xF80
// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION (1 << 0)
#define V_DIRECTION (1 << 2)
#define SCAN_COLUMN (1 << 4)
#define COLOR_EXPAND (1 << 6)
#define CSC_ENABLE (1 << 18)
#define WIN_ENABLE (1 << 30)
#define DC_WIN_COLOR_DEPTH 0x703
#define WIN_COLOR_DEPTH_P1 0x0
#define WIN_COLOR_DEPTH_P2 0x1
#define WIN_COLOR_DEPTH_P4 0x2
#define WIN_COLOR_DEPTH_P8 0x3
#define WIN_COLOR_DEPTH_B4G4R4A4 0x4
#define WIN_COLOR_DEPTH_B5G5R5A 0x5
#define WIN_COLOR_DEPTH_B5G6R5 0x6
#define WIN_COLOR_DEPTH_AB5G5R5 0x7
#define WIN_COLOR_DEPTH_B8G8R8A8 0xC
#define WIN_COLOR_DEPTH_R8G8B8A8 0xD
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE
#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF
#define WIN_COLOR_DEPTH_YCbCr422 0x10
#define WIN_COLOR_DEPTH_YUV422 0x11
#define WIN_COLOR_DEPTH_YCbCr420P 0x12
#define WIN_COLOR_DEPTH_YUV420P 0x13
#define WIN_COLOR_DEPTH_YCbCr422P 0x14
#define WIN_COLOR_DEPTH_YUV422P 0x15
#define WIN_COLOR_DEPTH_YCbCr422R 0x16
#define WIN_COLOR_DEPTH_YUV422R 0x17
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
#define WIN_COLOR_DEPTH_YUV422RA 0x19
#define DC_WIN_BUFFER_CONTROL 0x702
#define DC_WIN_POSITION 0x704
#define DC_WIN_SIZE 0x705
#define H_SIZE(x) (((x) & 0x1fff) << 0)
#define V_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_PRESCALED_SIZE 0x706
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_H_INITIAL_DDA 0x707
#define DC_WIN_V_INITIAL_DDA 0x708
#define DC_WIN_DDA_INC 0x709
#define H_DDA_INC(x) (((x) & 0xffff) << 0)
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
#define DC_WIN_DV_CONTROL 0x70E
// The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808
#define DC_WINBUF_SURFACE_KIND 0x80B
#define PITCH (0 << 0)
#define TILED (1 << 0)
#define BLOCK (2 << 0)
#define BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
/*! Display serial interface registers. */
#define _DSIREG(reg) ((reg) * 4)
#define DSI_INCR_SYNCPT_CNTRL 0x1
#define DSI_RD_DATA 0x9
#define DSI_WR_DATA 0xA
#define DSI_POWER_CONTROL 0xB
#define DSI_POWER_CONTROL_ENABLE 1
#define DSI_INT_ENABLE 0xC
#define DSI_INT_STATUS 0xD
#define DSI_INT_MASK 0xE
#define DSI_HOST_CONTROL 0xF
#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21)
#define DSI_HOST_CONTROL_CRC_RESET (1 << 20)
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
#define DSI_HOST_CONTROL_RAW (1 << 6)
#define DSI_HOST_CONTROL_HS (1 << 5)
#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4)
#define DSI_HOST_CONTROL_IMM_BTA (1 << 3)
#define DSI_HOST_CONTROL_PKT_BTA (1 << 2)
#define DSI_HOST_CONTROL_CS (1 << 1)
#define DSI_HOST_CONTROL_ECC (1 << 0)
#define DSI_CONTROL 0x10
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
#define DSI_SOL_DELAY 0x11
#define DSI_MAX_THRESHOLD 0x12
#define DSI_TRIGGER 0x13
#define DSI_TRIGGER_HOST (1 << 1)
#define DSI_TRIGGER_VIDEO (1 << 0)
#define DSI_TX_CRC 0x14
#define DSI_STATUS 0x15
#define DSI_INIT_SEQ_CONTROL 0x1A
#define DSI_INIT_SEQ_DATA_0 0x1B
#define DSI_INIT_SEQ_DATA_1 0x1C
#define DSI_INIT_SEQ_DATA_2 0x1D
#define DSI_INIT_SEQ_DATA_3 0x1E
#define DSI_PKT_SEQ_0_LO 0x23
#define DSI_PKT_SEQ_0_HI 0x24
#define DSI_PKT_SEQ_1_LO 0x25
#define DSI_PKT_SEQ_1_HI 0x26
#define DSI_PKT_SEQ_2_LO 0x27
#define DSI_PKT_SEQ_2_HI 0x28
#define DSI_PKT_SEQ_3_LO 0x29
#define DSI_PKT_SEQ_3_HI 0x2A
#define DSI_PKT_SEQ_4_LO 0x2B
#define DSI_PKT_SEQ_4_HI 0x2C
#define DSI_PKT_SEQ_5_LO 0x2D
#define DSI_PKT_SEQ_5_HI 0x2E
#define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37
#define DSI_PHY_TIMING_0 0x3C
#define DSI_PHY_TIMING_1 0x3D
#define DSI_PHY_TIMING_2 0x3E
#define DSI_BTA_TIMING 0x3F
#define DSI_TIMEOUT_0 0x44
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
#define DSI_TIMEOUT_1 0x45
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
#define DSI_TO_TALLY 0x46
#define DSI_PAD_CONTROL_0 0x4B
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
#define DSI_PAD_CONTROL_CD 0x4c
#define DSI_VIDEO_MODE_CONTROL 0x4E
#define DSI_PAD_CONTROL_1 0x4F
#define DSI_PAD_CONTROL_2 0x50
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
#define DSI_PAD_CONTROL_4 0x52
#define DSI_PAD_CONTROL_5_MARIKO 0x53
#define DSI_PAD_CONTROL_6_MARIKO 0x54
#define DSI_PAD_CONTROL_7_MARIKO 0x55
#define DSI_INIT_SEQ_DATA_15 0x5F
#define DSI_INIT_SEQ_DATA_15_MARIKO 0x62

View file

@ -42,7 +42,6 @@ namespace ams::secmon {
/* If not all cores have received the fatal, we need to trigger the interrupt on other cores. */
if (g_fatal_error_mask != (1u << NumCores) - 1) {
/* Configure and send the interrupt to the next core. */
const auto next_core = __builtin_ctz(~g_fatal_error_mask);
gic::SetSpiTargetCpu(MarikoFatalErrorInterruptId, (1u << next_core));

View file

@ -32,6 +32,8 @@ namespace ams::pmic {
void DisableVddCpu(Regulator regulator);
void EnableSleep();
void PowerOff();
void ShutdownSystem(bool reboot);
bool IsAcOk();
bool IsPowerButtonPressed();
}

View file

@ -149,7 +149,10 @@ namespace ams::secmon {
HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__)
HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__)
#define DEFINE_DEVICE_REGION(_NAME_, _PREV_, _ADDRESS_, _SIZE_, _SECURE_) \
constexpr inline const MemoryRegion MemoryRegionVirtualDevice##_NAME_ = MemoryRegion(MemoryRegionVirtualDevice##_PREV_.GetEndAddress() + 0x1000, _SIZE_); \

View file

@ -176,8 +176,40 @@ namespace ams::pmic {
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, Max77620RegisterOnOffCnfg1, MAX77620_ONOFFCNFG1_PWR_OFF);
}
void ShutdownSystem(bool reboot) {
/* Get value, set or clear software reset mask. */
u8 on_off_2_val = i2c::QueryByte(i2c::Port_5, I2cAddressMax77620Pmic, MAX77620_REG_ONOFFCNFG2);
if (reboot) {
on_off_2_val |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
} else {
on_off_2_val &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK);
}
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, MAX77620_REG_ONOFFCNFG2, on_off_2_val);
/* Get value, set software reset mask. */
u8 on_off_1_val = i2c::QueryByte(i2c::Port_5, I2cAddressMax77620Pmic, MAX77620_REG_ONOFFCNFG1);
on_off_1_val |= MAX77620_ONOFFCNFG1_SFT_RST;
/* NOTE: Here, userland finalizes the battery on non-Calcio. */
if (fuse::GetHardwareType() != fuse::HardwareType_Calcio) {
/* ... */
}
/* Actually write the value to trigger shutdown/reset. */
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, MAX77620_REG_ONOFFCNFG1, on_off_1_val);
/* Allow up to 5 seconds for shutdown/reboot to take place. */
util::WaitMicroSeconds(5'000'000ul);
AMS_ABORT("Shutdown failed");
}
bool IsAcOk() {
return (GetPmicOnOffStat() & (1 << 1)) != 0;
}
bool IsPowerButtonPressed() {
return (GetPmicOnOffStat() & (1 << 2)) != 0;
}
}

View file

@ -344,9 +344,6 @@ namespace ams::boot {
DO_SOC_DEPENDENT_REGISTER_WRITES(g_clk_rst_regs, DisplayConfigPlld01);
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigDc01);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init01);
/* NOTE: Nintendo bug here. */
/* As of 8.0.0, Nintendo writes this list to CAR instead of DSI */
/* This results in them zeroing CLK_SOURCE_UARTA... */
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init02);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init03);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Init04);