Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc committed 2025-11-09 16:14:52 -05:00
1 parent 22ec140738
commit 21a3f953d7
3804 files changed
+435 -570162

No files matched your search

@@ -1,210 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
namespace ams {
namespace {
constexpr inline dd::PhysicalAddress ClkRstRegistersPhysicalAddress = 0x60006000;
constexpr inline size_t ClkRstRegistersSize = 0x1000;
uintptr_t g_clkrst_registers = dd::QueryIoMapping(ClkRstRegistersPhysicalAddress, ClkRstRegistersSize);
struct ClkRstDefinition {
u32 clk_src_ofs;
u32 clk_en_ofs;
u32 rst_ofs;
u32 clk_en_index;
u32 rst_index;
u8 clk_src;
u8 clk_divisor;
};
constexpr inline const ClkRstDefinition Definitions[] = {
{ CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_ENB_I2C1_INDEX, CLK_RST_CONTROLLER_RST_I2C1_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 },
{ CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_ENB_I2C2_INDEX, CLK_RST_CONTROLLER_RST_I2C2_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 },
{ CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_ENB_I2C3_INDEX, CLK_RST_CONTROLLER_RST_I2C3_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 },
{ CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_ENB_I2C4_INDEX, CLK_RST_CONTROLLER_RST_I2C4_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 },
{ CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_ENB_I2C5_INDEX, CLK_RST_CONTROLLER_RST_I2C5_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 },
{ CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_ENB_I2C6_INDEX, CLK_RST_CONTROLLER_RST_I2C6_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 },
{ CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_ENB_PWM_INDEX, CLK_RST_CONTROLLER_RST_PWM_INDEX, 0x00 /* PLLP_OUT0 */, 0x10 },
};
constexpr inline const struct {
const ClkRstDefinition *definition;
DeviceCode device_code;
pcv::Module pcv_module;
} ClkRstDefinitionMap[] = {
{ std::addressof(Definitions[0]), i2c::DeviceCode_I2c1, pcv::Module_I2c1 },
{ std::addressof(Definitions[1]), i2c::DeviceCode_I2c2, pcv::Module_I2c2 },
{ std::addressof(Definitions[2]), i2c::DeviceCode_I2c3, pcv::Module_I2c3 },
{ std::addressof(Definitions[3]), i2c::DeviceCode_I2c4, pcv::Module_I2c4 },
{ std::addressof(Definitions[4]), i2c::DeviceCode_I2c5, pcv::Module_I2c5 },
{ std::addressof(Definitions[5]), i2c::DeviceCode_I2c6, pcv::Module_I2c6 },
{ std::addressof(Definitions[6]), pwm::DeviceCode_LcdBacklight, pcv::Module_Pwm },
};
ALWAYS_INLINE const ClkRstDefinition *GetDefinition(DeviceCode device_code) {
const ClkRstDefinition *def = nullptr;
for (const auto &entry : ClkRstDefinitionMap) {
if (entry.device_code == device_code) {
def = entry.definition;
break;
}
}
AMS_ABORT_UNLESS(def != nullptr);
return def;
}
ALWAYS_INLINE const ClkRstDefinition &GetDefinition(pcv::Module module) {
const ClkRstDefinition *def = nullptr;
for (const auto &entry : ClkRstDefinitionMap) {
if (entry.pcv_module == module) {
def = entry.definition;
break;
}
}
AMS_ABORT_UNLESS(def != nullptr);
return *def;
}
ALWAYS_INLINE const ClkRstDefinition &GetDefinition(clkrst::ClkRstSession *session) {
const ClkRstDefinition *def = nullptr;
for (const auto &entry : ClkRstDefinitionMap) {
if (session->_session == entry.definition) {
def = entry.definition;
break;
}
}
AMS_ABORT_UNLESS(def != nullptr);
return *def;
}
void SetResetEnabled(const ClkRstDefinition &def, bool en) {
/* Set or clear reset. */
reg::ReadWrite(g_clkrst_registers + def.rst_ofs, (en ? 1u : 0u) << def.rst_index, 1u << def.rst_index);
}
void SetClockEnabled(const ClkRstDefinition &def, bool en) {
/* Set or clear reset. */
reg::ReadWrite(g_clkrst_registers + def.clk_en_ofs, (en ? 1u : 0u) << def.clk_en_index, 1u << def.clk_en_index);
}
void SetClockRate(const ClkRstDefinition &def, u32 hz) {
AMS_UNUSED(hz);
/* Enable clock. */
reg::ReadWrite(g_clkrst_registers + def.clk_en_ofs, 1u << def.clk_en_index, 1u << def.clk_en_index);
/* Set the clock divisor. */
reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_DIVISOR, def.clk_divisor));
/* Wait for 2us for clock setting to take. */
os::SleepThread(TimeSpan::FromMicroSeconds(2));
/* Set the clock source. */
reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_SOURCE, def.clk_src));
/* Wait for 2us for clock setting to take. */
os::SleepThread(TimeSpan::FromMicroSeconds(2));
}
}
namespace clkrst {
void Initialize() {
/* ... */
}
void Finalize() {
/* ... */
}
Result OpenSession(ClkRstSession *out, DeviceCode device_code) {
/* Get the relevant definition. */
out->_session = const_cast<ClkRstDefinition *>(GetDefinition(device_code));
R_SUCCEED();
}
void CloseSession(ClkRstSession *session) {
/* Clear the session. */
session->_session = nullptr;
}
void SetResetAsserted(ClkRstSession *session) {
/* Assert reset. */
SetResetEnabled(GetDefinition(session), true);
}
void SetResetDeasserted(ClkRstSession *session) {
/* Assert reset. */
SetResetEnabled(GetDefinition(session), false);
}
void SetClockRate(ClkRstSession *session, u32 hz) {
/* Set the clock rate. */
SetClockRate(GetDefinition(session), hz);
}
void SetClockDisabled(ClkRstSession *session) {
AMS_UNUSED(session);
AMS_ABORT("SetClockDisabled not implemented for boot system module");
}
}
namespace pcv {
void Initialize() {
/* ... */
}
void Finalize() {
/* ... */
}
Result SetClockEnabled(Module module, bool en) {
/* Set clock. */
SetClockEnabled(GetDefinition(module), en);
R_SUCCEED();
}
Result SetClockRate(Module module, ClockHz hz) {
/* Set the clock rate. */
SetClockRate(GetDefinition(module), hz);
R_SUCCEED();
}
Result SetReset(Module module, bool en) {
/* Set reset. */
SetResetEnabled(GetDefinition(module), en);
R_SUCCEED();
}
}
}
@@ -1,52 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
namespace ams::regulator {
void Initialize() {
/* ... */
}
void Finalize() {
/* ... */
}
Result OpenSession(RegulatorSession *out, DeviceCode device_code) {
AMS_UNUSED(out, device_code);
R_SUCCEED();
}
void CloseSession(RegulatorSession *session) {
AMS_UNUSED(session);
}
bool GetVoltageEnabled(RegulatorSession *session) {
AMS_UNUSED(session);
return true;
}
Result SetVoltageEnabled(RegulatorSession *session, bool enabled) {
AMS_UNUSED(session, enabled);
R_SUCCEED();
}
Result SetVoltageValue(RegulatorSession *session, u32 micro_volts) {
AMS_UNUSED(session, micro_volts);
R_SUCCEED();
}
}
@@ -1,81 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
class BatteryDriver {
NON_COPYABLE(BatteryDriver);
NON_MOVEABLE(BatteryDriver);
private:
static constinit inline powctl::Session s_battery_session{powctl::Session::ConstantInitializeTag{}};
static constinit inline int s_reference_count{0};
public:
BatteryDriver() {
if ((s_reference_count++) == 0) {
R_ABORT_UNLESS(powctl::OpenSession(std::addressof(s_battery_session), powctl::DeviceCode_Max17050, ddsf::AccessMode_ReadWrite));
}
}
~BatteryDriver() {
if ((--s_reference_count) == 0) {
powctl::CloseSession(s_battery_session);
}
}
public:
Result IsBatteryRemoved(bool *out) {
bool present;
R_TRY(powctl::IsBatteryPresent(std::addressof(present), s_battery_session));
*out = !present;
R_SUCCEED();
}
Result GetChargePercentage(float *out) {
R_RETURN(powctl::GetBatteryChargePercentage(out, s_battery_session));
}
Result GetAverageVCell(int *out) {
R_RETURN(powctl::GetBatteryAverageVCell(out, s_battery_session));
}
Result GetVoltageFuelGaugePercentage(float *out) {
R_RETURN(powctl::GetBatteryVoltageFuelGaugePercentage(out, s_battery_session));
}
Result GetAverageCurrent(int *out) {
R_RETURN(powctl::GetBatteryAverageCurrent(out, s_battery_session));
}
Result GetCurrent(int *out) {
R_RETURN(powctl::GetBatteryCurrent(out, s_battery_session));
}
Result GetTemperature(float *out) {
R_RETURN(powctl::GetBatteryTemperature(out, s_battery_session));
}
Result IsI2cShutdownEnabled(bool *out) {
R_RETURN(powctl::IsBatteryI2cShutdownEnabled(out, s_battery_session));
}
Result SetI2cShutdownEnabled(bool en) {
R_RETURN(powctl::SetBatteryI2cShutdownEnabled(s_battery_session, en));
}
};
}
@@ -1,29 +0,0 @@
/*
* Copyright (c) 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/>.
*/
constexpr size_t ChargingBatteryX = 26;
constexpr size_t ChargingBatteryY = 28;
constexpr size_t ChargingBatteryW = 76;
constexpr size_t ChargingBatteryH = 28;
constexpr size_t ChargingBatteryMeterX = 7;
constexpr size_t ChargingBatteryMeterY = 8;
constexpr size_t ChargingBatteryMeterW = 31;
constexpr size_t ChargingBatteryMeterH = 12;
static_assert(ChargingBatteryMeterX + ChargingBatteryMeterW < ChargingBatteryW && ChargingBatteryMeterY + ChargingBatteryMeterH < ChargingBatteryH, "Incorrect ChargingBatteryMeter definition!");
constexpr u32 ChargingBattery[] = {0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF3D3D3D, 0xFFB2B2B2, 0xFFE6E6E6, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE6E6E6, 0xFFB2B2B2, 0xFF3D3D3D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF7A7A7A, 0xFFFEFEFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFDFDFD, 0xFF7A7A7A, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF3D3D3D, 0xFFFDFDFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFDFDFD, 0xFF3D3D3D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB2B2B2, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFB2B2B2, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF494949, 0xFFE2E2E2, 0xFFE3E3E3, 0xFF494949, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFE6E6E6, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF4A4A4A, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF0000Line truncated
static_assert(sizeof(ChargingBattery) == sizeof(u32) * ChargingBatteryW * ChargingBatteryH, "Incorrect ChargingBattery definition!");
@@ -1,29 +0,0 @@
/*
* Copyright (c) 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/>.
*/
constexpr size_t ChargingRedBatteryX = 26;
constexpr size_t ChargingRedBatteryY = 28;
constexpr size_t ChargingRedBatteryW = 76;
constexpr size_t ChargingRedBatteryH = 28;
constexpr size_t ChargingRedBatteryMeterX = 7;
constexpr size_t ChargingRedBatteryMeterY = 8;
constexpr size_t ChargingRedBatteryMeterW = 31;
constexpr size_t ChargingRedBatteryMeterH = 12;
static_assert(ChargingRedBatteryMeterX + ChargingRedBatteryMeterW < ChargingRedBatteryW && ChargingRedBatteryMeterY + ChargingRedBatteryMeterH < ChargingRedBatteryH, "Incorrect ChargingRedBatteryMeter definition!");
constexpr u32 ChargingRedBattery[] = {0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF3D3D3D, 0xFFB2B2B2, 0xFFE6E6E6, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE6E6E6, 0xFFB2B2B2, 0xFF3D3D3D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF7A7A7A, 0xFFFEFEFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFDFDFD, 0xFF7A7A7A, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF3D3D3D, 0xFFFDFDFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFDFDFD, 0xFF3D3D3D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB2B2B2, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFB2B2B2, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF494949, 0xFFE2E2E2, 0xFFE3E3E3, 0xFF494949, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFE6E6E6, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF4A4A4A, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF0Line truncated
static_assert(sizeof(ChargingRedBattery) == sizeof(u32) * ChargingRedBatteryW * ChargingRedBatteryH, "Incorrect ChargingRedBattery definition!");
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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/>.
*/
constexpr size_t LowBatteryX = 26;
constexpr size_t LowBatteryY = 28;
constexpr size_t LowBatteryW = 52;
constexpr size_t LowBatteryH = 28;
constexpr u32 LowBattery[] = {0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF3D3D3D, 0xFFB2B2B2, 0xFFE6E6E6, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE6E6E6, 0xFFB2B2B2, 0xFF3D3D3D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF7A7A7A, 0xFFFEFEFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFDFDFD, 0xFF7A7A7A, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF3D3D3D, 0xFFFDFDFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFDFDFD, 0xFF3D3D3D, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFB2B2B2, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFB2B2B2, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFE6E6E6, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF4A4A4A, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF4B4B4B, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE6E6E6, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0Line truncated
static_assert(sizeof(LowBattery) == sizeof(u32) * LowBatteryW * LowBatteryH, "Incorrect LowBattery definition!");
@@ -1,95 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_battery_icons.hpp"
#include "boot_display.hpp"
namespace ams::boot {
namespace {
/* Pull in icon definitions. */
#include "boot_battery_icon_low.inc"
#include "boot_battery_icon_charging.inc"
#include "boot_battery_icon_charging_red.inc"
/* Helpers. */
void FillBatteryMeter(u32 *icon, const size_t icon_w, const size_t icon_h, const size_t meter_x, const size_t meter_y, const size_t meter_w, const size_t meter_h, const size_t fill_w) {
const size_t fill_x = meter_x + meter_w - fill_w;
if (fill_x + fill_w > icon_w || meter_y + meter_h > icon_h || fill_x == 0) {
return;
}
u32 *cur_row = icon + meter_y * icon_w + fill_x;
for (size_t y = 0; y < meter_h; y++) {
/* Make last column of meter identical to first column of meter. */
cur_row[-1] = icon[(meter_y + y) * icon_w + meter_x];
/* Black out further pixels. */
for (size_t x = 0; x < fill_w; x++) {
cur_row[x] = 0xFF000000;
}
cur_row += icon_w;
}
}
}
void ShowLowBatteryIcon() {
InitializeDisplay();
{
/* Low battery icon is shown for 5 seconds. */
ShowDisplay(LowBatteryX, LowBatteryY, LowBatteryW, LowBatteryH, LowBattery);
os::SleepThread(TimeSpan::FromSeconds(5));
}
FinalizeDisplay();
}
void StartShowChargingIcon(int battery_percentage, bool wait) {
const bool is_red = battery_percentage <= 15;
const size_t IconX = is_red ? ChargingRedBatteryX : ChargingBatteryX;
const size_t IconY = is_red ? ChargingRedBatteryY : ChargingBatteryY;
const size_t IconW = is_red ? ChargingRedBatteryW : ChargingBatteryW;
const size_t IconH = is_red ? ChargingRedBatteryH : ChargingBatteryH;
const size_t IconMeterX = is_red ? ChargingRedBatteryMeterX : ChargingBatteryMeterX;
const size_t IconMeterY = is_red ? ChargingRedBatteryMeterY : ChargingBatteryMeterY;
const size_t IconMeterW = is_red ? ChargingRedBatteryMeterW : ChargingBatteryMeterW;
const size_t IconMeterH = is_red ? ChargingRedBatteryMeterH : ChargingBatteryMeterH;
const size_t MeterFillW = static_cast<size_t>(IconMeterW * (1.0 - (0.0404 + 0.0096 * static_cast<double>(battery_percentage))) + 0.5);
/* Create stack buffer, copy icon into it, draw fill meter, draw. */
{
u32 Icon[IconW * IconH];
std::memcpy(Icon, is_red ? ChargingRedBattery : ChargingBattery, sizeof(Icon));
FillBatteryMeter(Icon, IconW, IconH, IconMeterX, IconMeterY, IconMeterW, IconMeterH, MeterFillW);
InitializeDisplay();
ShowDisplay(IconX, IconY, IconW, IconH, Icon);
}
/* Wait for 2 seconds if we're supposed to. */
if (wait) {
os::SleepThread(TimeSpan::FromSeconds(2));
}
}
void EndShowChargingIcon() {
FinalizeDisplay();
}
}
@@ -1,35 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
#include "boot_display.hpp"
namespace ams::boot {
/* Battery Display utilities. */
void ShowLowBatteryIcon();
void StartShowChargingIcon(int battery_percentage, bool wait);
void EndShowChargingIcon();
inline void StartShowChargingIcon(int battery_percentage) {
return StartShowChargingIcon(battery_percentage, true);
}
inline void StartShowLowBatteryChargingIcon() {
return StartShowChargingIcon(1, false);
}
}
@@ -1,99 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_boot_reason.hpp"
#include "boot_pmic_driver.hpp"
#include "boot_rtc_driver.hpp"
namespace ams::boot {
namespace {
/* Globals. */
constinit spl::BootReason g_boot_reason = spl::BootReason_Unknown;
constinit bool g_detected_boot_reason = false;
/* Helpers. */
spl::BootReason DetectBootReason(u32 power_intr, u8 rtc_intr, u8 nv_erc, bool ac_ok) {
if (power_intr & 0x08) {
return spl::BootReason_OnKey;
}
if (rtc_intr & 0x02) {
return spl::BootReason_RtcAlarm1;
}
if (power_intr & 0x80) {
return spl::BootReason_AcOk;
}
if (rtc_intr & 0x04) {
if (nv_erc != 0x80 && !spl::IsRecoveryBoot()) {
return spl::BootReason_RtcAlarm2;
}
}
if ((nv_erc & 0x40) && ac_ok) {
return spl::BootReason_AcOk;
}
return spl::BootReason_Unknown;
}
}
void DetectBootReason() {
u8 power_intr;
u8 rtc_intr;
u8 rtc_intr_m;
u8 nv_erc;
bool ac_ok;
/* Get values from PMIC. */
{
PmicDriver pmic_driver;
R_ABORT_UNLESS(pmic_driver.GetOnOffIrq(std::addressof(power_intr)));
R_ABORT_UNLESS(pmic_driver.GetNvErc(std::addressof(nv_erc)));
R_ABORT_UNLESS(pmic_driver.GetAcOk(std::addressof(ac_ok)));
}
/* Get values from RTC. */
{
RtcDriver rtc_driver;
R_ABORT_UNLESS(rtc_driver.GetRtcIntr(std::addressof(rtc_intr)));
R_ABORT_UNLESS(rtc_driver.GetRtcIntrM(std::addressof(rtc_intr_m)));
}
/* Set global derived boot reason. */
g_boot_reason = DetectBootReason(power_intr, rtc_intr & ~rtc_intr_m, nv_erc, ac_ok);
/* Set boot reason for SPL. */
if (hos::GetVersion() >= hos::Version_3_0_0) {
/* Create the boot reason value. */
spl::BootReasonValue boot_reason_value = {};
boot_reason_value.power_intr = power_intr;
boot_reason_value.rtc_intr = rtc_intr & ~rtc_intr_m;
boot_reason_value.nv_erc = nv_erc;
boot_reason_value.boot_reason = g_boot_reason;
/* Set the boot reason value. */
R_ABORT_UNLESS(spl::SetBootReason(boot_reason_value));
}
g_detected_boot_reason = true;
}
spl::BootReason GetBootReason() {
AMS_ABORT_UNLESS(g_detected_boot_reason);
return g_boot_reason;
}
}
@@ -1,25 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
/* Boot Reason utilities. */
void DetectBootReason();
spl::BootReason GetBootReason();
}
@@ -1,45 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_change_voltage.hpp"
namespace ams::boot {
namespace {
/* Convenience definitions. */
constexpr u32 Sdmmc3VoltageBit = (1 << 13); /* SDMMC3 */
constexpr u32 AudioVoltageBit = (1 << 18); /* AUDIO_HV */
constexpr u32 GpioVoltageBit = (1 << 21); /* GPIO */
constexpr u32 SpiVoltageBit = (1 << 23); /* SPI_HV */
constexpr u32 VoltageChangeMask = SpiVoltageBit | GpioVoltageBit | AudioVoltageBit | Sdmmc3VoltageBit;
constexpr u32 PmcPwrDet = 0x7000E448;
constexpr u32 PmcPwrDetVal = 0x7000E4E4;
}
void ChangeGpioVoltageTo1_8v() {
/* Write mask to APBDEV_PMC_PWR_DET, then clear APBDEV_PMC_PWR_DET_VAL. */
dd::ReadModifyWriteIoRegister(PmcPwrDet, VoltageChangeMask, VoltageChangeMask);
dd::ReadModifyWriteIoRegister(PmcPwrDetVal, 0, VoltageChangeMask);
/* Sleep for 100 us. */
os::SleepThread(TimeSpan::FromMicroSeconds(100));
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void ChangeGpioVoltageTo1_8v();;
}
@@ -1,130 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
enum ChargerStatus {
ChargerStatus_Unknown = 0,
ChargerStatus_Charging = 1,
ChargerStatus_NotCharging = 2,
ChargerStatus_ChargeTerminationDone = 3,
};
class ChargerDriver {
private:
powctl::Session m_charger_session;
public:
ChargerDriver() : m_charger_session() {
R_ABORT_UNLESS(powctl::OpenSession(std::addressof(m_charger_session), powctl::DeviceCode_Bq24193, ddsf::AccessMode_ReadWrite));
}
~ChargerDriver() {
powctl::CloseSession(m_charger_session);
}
Result Initialize(bool set_input_current_limit) {
/* Configure PINMUX_AUX_CAM_FLASH_EN as tristate + passthrough. */
{
const uintptr_t apb_regs = dd::QueryIoMapping(0x70000000ul, os::MemoryPageSize);
reg::ClearBits(apb_regs + PINMUX_AUX_CAM_FLASH_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
}
/* Set input current limit to 500 ma. */
if (set_input_current_limit) {
R_TRY(powctl::SetChargerInputCurrentLimit(m_charger_session, 500));
}
/* Set boost mode current limit to 500 ma. */
R_TRY(powctl::SetChargerBoostModeCurrentLimit(m_charger_session, 500));
/* Disable hi-z mode. */
R_TRY(powctl::SetChargerHiZEnabled(m_charger_session, false));
/* Set configuration to charge battery. */
R_TRY(powctl::SetChargerChargerConfiguration(m_charger_session, powctl::ChargerConfiguration_ChargeBattery));
R_SUCCEED();
}
Result GetChargeCurrentState(powctl::ChargeCurrentState *out) {
R_RETURN(powctl::GetChargerChargeCurrentState(out, m_charger_session));
}
Result SetChargeCurrentState(powctl::ChargeCurrentState state) {
R_RETURN(powctl::SetChargerChargeCurrentState(m_charger_session, state));
}
Result GetInputCurrentLimit(int *out) {
R_RETURN(powctl::GetChargerInputCurrentLimit(out, m_charger_session));
}
Result SetChargerConfiguration(powctl::ChargerConfiguration cfg) {
R_RETURN(powctl::SetChargerChargerConfiguration(m_charger_session, cfg));
}
Result GetFastChargeCurrentLimit(int *out) {
R_RETURN(powctl::GetChargerFastChargeCurrentLimit(out, m_charger_session));
}
Result SetFastChargeCurrentLimit(int limit) {
R_RETURN(powctl::SetChargerFastChargeCurrentLimit(m_charger_session, limit));
}
Result GetChargeVoltageLimit(int *out) {
R_RETURN(powctl::GetChargerChargeVoltageLimit(out, m_charger_session));
}
Result SetChargeVoltageLimit(int limit) {
R_RETURN(powctl::SetChargerChargeVoltageLimit(m_charger_session, limit));
}
Result GetChargerStatus(boot::ChargerStatus *out) {
/* Default to unknown. */
*out = ChargerStatus_Unknown;
/* Get the powctl status. */
powctl::ChargerStatus powctl_status;
R_TRY(powctl::GetChargerChargerStatus(std::addressof(powctl_status), m_charger_session));
switch (powctl_status) {
case powctl::ChargerStatus_Charging: *out = boot::ChargerStatus_Charging; break;
case powctl::ChargerStatus_NotCharging: *out = boot::ChargerStatus_NotCharging; break;
case powctl::ChargerStatus_ChargeTerminationDone: *out = boot::ChargerStatus_ChargeTerminationDone; break;
}
R_SUCCEED();
}
Result GetBatteryCompensation(int *out) {
R_RETURN(powctl::GetChargerBatteryCompensation(out, m_charger_session));
}
Result SetBatteryCompensation(int v) {
R_RETURN(powctl::SetChargerBatteryCompensation(m_charger_session, v));
}
Result GetVoltageClamp(int *out) {
R_RETURN(powctl::GetChargerVoltageClamp(out, m_charger_session));
}
Result SetVoltageClamp(int v) {
R_RETURN(powctl::SetChargerVoltageClamp(m_charger_session, v));
}
};
}
@@ -1,529 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_check_battery.hpp"
#include "boot_battery_icons.hpp"
#include "boot_boot_reason.hpp"
#include "boot_pmic_driver.hpp"
#include "boot_battery_driver.hpp"
#include "boot_charger_driver.hpp"
#include "boot_power_utils.hpp"
namespace ams::boot {
namespace {
/* Value definitions. */
constexpr inline double BatteryLevelThresholdForBoot = 3.0;
constexpr inline double BatteryLevelThresholdForFullCharge = 99.0;
constexpr inline int BatteryVoltageThresholdConnected = 4000;
constexpr inline int BatteryVoltageThresholdDisconnected = 3650;
/* Types. */
enum class CheckBatteryResult {
Success,
Shutdown,
Reboot,
};
class BatteryChecker {
private:
boot::ChargerDriver &m_charger_driver;
boot::BatteryDriver &m_battery_driver;
const powctl::driver::impl::ChargeParameters &m_charge_parameters;
powctl::driver::impl::ChargeArbiter m_charge_arbiter;
powctl::ChargeCurrentState m_charge_current_state;
int m_fast_charge_current_limit;
int m_charge_voltage_limit;
int m_battery_compensation;
int m_voltage_clamp;
TimeSpan m_charging_done_interval;
bool m_has_start_time;
TimeSpan m_start_time;
private:
bool IsChargeDone();
void UpdateChargeDoneCurrent();
void ApplyArbiterRule();
void PrintBatteryStatus(float raw_charge, int voltage, int voltage_threshold);
CheckBatteryResult LoopCheckBattery(bool reboot_on_power_button_press, bool return_on_enough_battery, bool shutdown_on_full_battery, bool show_display, bool show_charging_display);
void UpdateStartTime() {
/* Update start time. */
m_start_time = os::ConvertToTimeSpan(os::GetSystemTick());
m_has_start_time = true;
}
public:
BatteryChecker(boot::ChargerDriver &cd, boot::BatteryDriver &bd, const powctl::driver::impl::ChargeParameters &cp, int cvl) : m_charger_driver(cd), m_battery_driver(bd), m_charge_parameters(cp), m_charge_arbiter(cp.rules, cp.num_rules, cvl), m_charging_done_interval(TimeSpan::FromSeconds(2)), m_has_start_time(false) {
/* Get parameters from charger. */
if (R_FAILED(m_charger_driver.GetChargeCurrentState(std::addressof(m_charge_current_state)))) {
boot::ShutdownSystem();
}
if (R_FAILED(m_charger_driver.GetFastChargeCurrentLimit(std::addressof(m_fast_charge_current_limit)))) {
boot::ShutdownSystem();
}
if (R_FAILED(m_charger_driver.GetChargeVoltageLimit(std::addressof(m_charge_voltage_limit)))) {
boot::ShutdownSystem();
}
if (R_FAILED(m_charger_driver.GetBatteryCompensation(std::addressof(m_battery_compensation)))) {
boot::ShutdownSystem();
}
if (R_FAILED(m_charger_driver.GetVoltageClamp(std::addressof(m_voltage_clamp)))) {
boot::ShutdownSystem();
}
/* Update start time. */
this->UpdateStartTime();
}
CheckBatteryResult LoopCheckBattery(spl::BootReason boot_reason) {
if (boot_reason == spl::BootReason_RtcAlarm2) {
/* RTC Alarm 2 boot (QuasiOff) */
return this->LoopCheckBattery(true, false, true, false, false);
} else if (boot_reason == spl::BootReason_AcOk) {
/* ACOK boot */
return this->LoopCheckBattery(true, true, false, true, true);
} else {
/* Normal boot */
return this->LoopCheckBattery(false, true, false, true, false);
}
}
void UpdateCharger();
};
void BatteryChecker::PrintBatteryStatus(float raw_charge, int voltage, int voltage_threshold) {
/* TODO: Print charge/voltage/threshold. */
AMS_UNUSED(raw_charge, voltage, voltage_threshold);
/* Get various battery metrics. */
int avg_current, current;
float temp, voltage_fuel_gauge_percentage;
if (R_FAILED(m_battery_driver.GetAverageCurrent(std::addressof(avg_current)))) {
return;
}
if (R_FAILED(m_battery_driver.GetCurrent(std::addressof(current)))) {
return;
}
if (R_FAILED(m_battery_driver.GetTemperature(std::addressof(temp)))) {
return;
}
if (R_FAILED(m_battery_driver.GetVoltageFuelGaugePercentage(std::addressof(voltage_fuel_gauge_percentage)))) {
return;
}
/* TODO: Print the things we just got. */
AMS_UNUSED(avg_current, current, temp, voltage_fuel_gauge_percentage);
}
bool BatteryChecker::IsChargeDone() {
/* Get the charger status. */
boot::ChargerStatus charger_status;
if (R_FAILED(m_charger_driver.GetChargerStatus(std::addressof(charger_status)))) {
boot::ShutdownSystem();
}
/* If charge status isn't done, we're not done. */
if (charger_status != boot::ChargerStatus_ChargeTerminationDone) {
return false;
}
/* Return whether a done current of zero is acceptable. */
return m_charge_arbiter.IsBatteryDoneCurrentAcceptable(0);
}
void BatteryChecker::UpdateChargeDoneCurrent() {
int done_current = 0;
if (m_has_start_time && (os::ConvertToTimeSpan(os::GetSystemTick()) - m_start_time) >= m_charging_done_interval) {
/* Get the current. */
if (R_FAILED(m_battery_driver.GetCurrent(std::addressof(done_current)))) {
boot::ShutdownSystem();
}
} else {
/* Get the charger status. */
boot::ChargerStatus charger_status;
if (R_FAILED(m_charger_driver.GetChargerStatus(std::addressof(charger_status)))) {
boot::ShutdownSystem();
}
/* If the charger status isn't done, don't update. */
if (charger_status != boot::ChargerStatus_ChargeTerminationDone) {
return;
}
}
/* Update done current. */
m_charge_arbiter.SetBatteryDoneCurrent(done_current);
}
void BatteryChecker::UpdateCharger() {
/* Get the battery temperature. */
float temp;
if (R_FAILED(m_battery_driver.GetTemperature(std::addressof(temp)))) {
boot::ShutdownSystem();
}
/* Update the temperature level. */
powctl::BatteryTemperatureLevel temp_level;
if (temp < static_cast<float>(m_charge_parameters.temp_min)) {
temp_level = powctl::BatteryTemperatureLevel::TooLow;
} else if (temp < static_cast<float>(m_charge_parameters.temp_low)) {
temp_level = powctl::BatteryTemperatureLevel::Low;
} else if (temp < static_cast<float>(m_charge_parameters.temp_high)) {
temp_level = powctl::BatteryTemperatureLevel::Medium;
} else if (temp < static_cast<float>(m_charge_parameters.temp_max)) {
temp_level = powctl::BatteryTemperatureLevel::High;
} else {
temp_level = powctl::BatteryTemperatureLevel::TooHigh;
}
m_charge_arbiter.SetBatteryTemperatureLevel(temp_level);
/* Update average voltage. */
int avg_v_cell;
if (R_FAILED(m_battery_driver.GetAverageVCell(std::addressof(avg_v_cell)))) {
boot::ShutdownSystem();
}
m_charge_arbiter.SetBatteryAverageVCell(avg_v_cell);
/* Update voltage fuel gauge percentage. */
float vfgp;
if (R_FAILED(m_battery_driver.GetVoltageFuelGaugePercentage(std::addressof(vfgp)))) {
boot::ShutdownSystem();
}
m_charge_arbiter.SetBatteryVoltageFuelGaugePercentage(vfgp);
/* Update charge done current. */
this->UpdateChargeDoneCurrent();
/* Update arbiter power state. */
m_charge_arbiter.SetPowerState(powctl::PowerState::ShutdownChargeMain);
/* Apply the newly selected rule. */
this->ApplyArbiterRule();
}
void BatteryChecker::ApplyArbiterRule() {
/* Get the selected rule. */
const auto *rule = m_charge_arbiter.GetSelectedRule();
AMS_ASSERT(rule != nullptr);
/* Check if we need to perform charger initialization. */
const bool reinit_charger = rule->reinitialize_charger;
const auto cur_charge_current_state = m_charge_current_state;
/* Set the charger to not charging while we make changes. */
if (!reinit_charger || cur_charge_current_state != powctl::ChargeCurrentState_NotCharging) {
if (R_FAILED(m_charger_driver.SetChargeCurrentState(powctl::ChargeCurrentState_NotCharging))) {
boot::ShutdownSystem();
}
m_charge_current_state = powctl::ChargeCurrentState_NotCharging;
/* Update start time. */
this->UpdateStartTime();
}
/* Process fast charge current limit when rule is smaller. */
const auto rule_fast_charge_current_limit = rule->fast_charge_current_limit;
const auto cur_fast_charge_current_limit = m_fast_charge_current_limit;
if (rule_fast_charge_current_limit < cur_fast_charge_current_limit) {
if (R_FAILED(m_charger_driver.SetFastChargeCurrentLimit(rule_fast_charge_current_limit))) {
boot::ShutdownSystem();
}
m_fast_charge_current_limit = rule_fast_charge_current_limit;
/* Update start time. */
this->UpdateStartTime();
}
/* Process charge voltage limit when rule is smaller. */
const auto rule_charge_voltage_limit = std::min(rule->charge_voltage_limit, m_charge_arbiter.GetChargeVoltageLimit());
const auto cur_charge_voltage_limit = m_charge_voltage_limit;
if (rule_charge_voltage_limit < cur_charge_voltage_limit) {
if (R_FAILED(m_charger_driver.SetChargeVoltageLimit(rule_charge_voltage_limit))) {
boot::ShutdownSystem();
}
m_charge_voltage_limit = rule_charge_voltage_limit;
/* Update start time. */
this->UpdateStartTime();
}
/* Process battery compensation when rule is smaller. */
const auto rule_battery_compensation = rule->battery_compensation;
const auto cur_battery_compensation = m_battery_compensation;
if (rule_battery_compensation < cur_battery_compensation) {
if (R_FAILED(m_charger_driver.SetBatteryCompensation(rule_battery_compensation))) {
boot::ShutdownSystem();
}
m_battery_compensation = rule_battery_compensation;
/* Update start time. */
this->UpdateStartTime();
}
/* Process voltage clamp when rule is smaller. */
const auto rule_voltage_clamp = rule->voltage_clamp;
const auto cur_voltage_clamp = m_voltage_clamp;
if (rule_voltage_clamp < cur_voltage_clamp) {
if (R_FAILED(m_charger_driver.SetVoltageClamp(rule_voltage_clamp))) {
boot::ShutdownSystem();
}
m_voltage_clamp = rule_voltage_clamp;
/* Update start time. */
this->UpdateStartTime();
}
/* Process voltage clamp when rule is larger. */
if (rule_voltage_clamp > cur_voltage_clamp) {
if (R_FAILED(m_charger_driver.SetVoltageClamp(rule_voltage_clamp))) {
boot::ShutdownSystem();
}
m_voltage_clamp = rule_voltage_clamp;
/* Update start time. */
this->UpdateStartTime();
}
/* Process battery compensation when rule is larger. */
if (rule_battery_compensation > cur_battery_compensation) {
if (R_FAILED(m_charger_driver.SetBatteryCompensation(rule_battery_compensation))) {
boot::ShutdownSystem();
}
m_battery_compensation = rule_battery_compensation;
/* Update start time. */
this->UpdateStartTime();
}
/* Process fast charge current limit when rule is larger. */
if (rule_fast_charge_current_limit > cur_fast_charge_current_limit) {
if (R_FAILED(m_charger_driver.SetFastChargeCurrentLimit(rule_fast_charge_current_limit))) {
boot::ShutdownSystem();
}
m_fast_charge_current_limit = rule_fast_charge_current_limit;
/* Update start time. */
this->UpdateStartTime();
}
/* Process charge voltage limit when rule is larger. */
if (rule_charge_voltage_limit > cur_charge_voltage_limit) {
if (R_FAILED(m_charger_driver.SetChargeVoltageLimit(rule_charge_voltage_limit))) {
boot::ShutdownSystem();
}
m_charge_voltage_limit = rule_charge_voltage_limit;
/* Update start time. */
this->UpdateStartTime();
}
/* If we're not charging and we expect to reinitialize the charger, do so. */
if (cur_charge_current_state != powctl::ChargeCurrentState_Charging && reinit_charger) {
if (R_FAILED(m_charger_driver.SetChargeCurrentState(powctl::ChargeCurrentState_Charging))) {
boot::ShutdownSystem();
}
m_charge_current_state = powctl::ChargeCurrentState_Charging;
/* Update start time. */
this->UpdateStartTime();
}
}
CheckBatteryResult BatteryChecker::LoopCheckBattery(bool reboot_on_power_button_press, bool return_on_enough_battery, bool shutdown_on_full_battery, bool show_display, bool show_charging_display) {
/* Ensure that if we show a charging icon, we stop showing it when we're done. */
bool is_showing_charging_icon = false;
ON_SCOPE_EXIT {
if (is_showing_charging_icon) {
boot::EndShowChargingIcon();
is_showing_charging_icon = false;
}
};
/* Show the charging display, if we should. */
if (show_charging_display) {
/* Get the raw battery charge. */
float raw_battery_charge;
if (R_FAILED(m_battery_driver.GetChargePercentage(std::addressof(raw_battery_charge)))) {
return CheckBatteryResult::Shutdown;
}
/* Display the battery with the appropriate percentage. */
const auto battery_charge = powctl::impl::ConvertBatteryChargePercentage(raw_battery_charge);
boot::StartShowChargingIcon(battery_charge);
is_showing_charging_icon = true;
}
/* Loop, checking the battery status. */
TimeSpan last_progress_time = TimeSpan(0);
while (true) {
/* Get the raw battery charge. */
float raw_battery_charge;
if (R_FAILED(m_battery_driver.GetChargePercentage(std::addressof(raw_battery_charge)))) {
return CheckBatteryResult::Shutdown;
}
/* Get the average vcell. */
int battery_voltage;
if (R_FAILED(m_battery_driver.GetAverageVCell(std::addressof(battery_voltage)))) {
return CheckBatteryResult::Shutdown;
}
/* Get whether we're connected to charger. */
bool ac_ok;
if (R_FAILED((boot::PmicDriver().GetAcOk(std::addressof(ac_ok))))) {
return CheckBatteryResult::Shutdown;
}
/* Decide on a battery voltage threshold. */
const auto battery_voltage_threshold = ac_ok ? BatteryVoltageThresholdConnected : BatteryVoltageThresholdDisconnected;
/* Check if we should return. */
if (return_on_enough_battery) {
if (raw_battery_charge >= BatteryLevelThresholdForBoot || battery_voltage >= battery_voltage_threshold) {
this->PrintBatteryStatus(raw_battery_charge, battery_voltage, battery_voltage_threshold);
return CheckBatteryResult::Success;
}
}
/* Otherwise, check if we should shut down. */
if (shutdown_on_full_battery) {
if (raw_battery_charge >= BatteryLevelThresholdForFullCharge || this->IsChargeDone()) {
return CheckBatteryResult::Shutdown;
}
}
/* Perform periodic printing. */
constexpr TimeSpan PrintProgressInterval = TimeSpan::FromSeconds(10);
const auto cur_time = os::ConvertToTimeSpan(os::GetSystemTick());
if ((cur_time - last_progress_time) >= PrintProgressInterval) {
last_progress_time = cur_time;
this->PrintBatteryStatus(raw_battery_charge, battery_voltage, battery_voltage_threshold);
}
/* If we've gotten to this point, we have insufficient battery to boot. If we aren't charging, show low battery and shutdown. */
if (!ac_ok) {
this->PrintBatteryStatus(raw_battery_charge, battery_voltage, battery_voltage_threshold);
if (show_display && !is_showing_charging_icon) {
boot::ShowLowBatteryIcon();
}
return CheckBatteryResult::Shutdown;
}
/* Check if we should reboot due to a power button press. */
if (reboot_on_power_button_press) {
/* Get the power button value. */
bool power_button_pressed;
if (R_FAILED((boot::PmicDriver().GetPowerButtonPressed(std::addressof(power_button_pressed))))) {
return CheckBatteryResult::Shutdown;
}
/* Handle the press (or not). */
if (power_button_pressed) {
return CheckBatteryResult::Reboot;
}
}
/* If we got to this point, we should show the low-battery charging screen. */
if (show_display && !is_showing_charging_icon) {
boot::StartShowLowBatteryChargingIcon();
is_showing_charging_icon = true;
}
/* Wait a bit before checking again. */
constexpr auto BatteryChargeCheckInterval = TimeSpan::FromMilliSeconds(20);
os::SleepThread(BatteryChargeCheckInterval);
/* Update the charger. */
this->UpdateCharger();
}
}
}
void CheckBatteryCharge() {
/* Open a sessions for the charger/battery. */
boot::ChargerDriver charger_driver;
boot::BatteryDriver battery_driver;
/* Check if the battery is removed. */
{
bool removed = false;
if (R_FAILED(battery_driver.IsBatteryRemoved(std::addressof(removed))) || removed) {
boot::ShutdownSystem();
}
}
/* Get the boot reason. */
const auto boot_reason = boot::GetBootReason();
/* Initialize the charger driver. */
if (R_FAILED(charger_driver.Initialize(boot_reason != spl::BootReason_RtcAlarm2)))
/* Check that the charger input limit is greater than 150 milli-amps. */
{
int input_current_limit_ma;
if (R_FAILED(charger_driver.GetInputCurrentLimit(std::addressof(input_current_limit_ma)))) {
boot::ShutdownSystem();
}
if (input_current_limit_ma <= 150) {
charger_driver.SetChargerConfiguration(powctl::ChargerConfiguration_ChargeDisable);
boot::ShutdownSystem();
}
}
/* Get the charge parameters. */
const auto &charge_parameters = powctl::driver::impl::GetChargeParameters();
/* Get the charge voltage limit. */
int charge_voltage_limit_mv;
if (boot_reason != spl::BootReason_RtcAlarm2 || charge_parameters.unknown_x_table == nullptr || charge_parameters.x_table_size == 0) {
charge_voltage_limit_mv = charge_parameters.default_charge_voltage_limit;
} else {
if (R_FAILED(charger_driver.GetChargeVoltageLimit(std::addressof(charge_voltage_limit_mv)))) {
boot::ShutdownSystem();
}
}
/* Create and update a battery checker. */
BatteryChecker battery_checker(charger_driver, battery_driver, charge_parameters, charge_voltage_limit_mv);
battery_checker.UpdateCharger();
/* Set the display brightness to 25%. */
boot::SetDisplayBrightness(25);
/* Check the battery. */
const CheckBatteryResult check_result = battery_checker.LoopCheckBattery(boot_reason);
/* Set the display brightness to 100%. */
boot::SetDisplayBrightness(100);
/* Handle the check result. */
switch (check_result) {
case CheckBatteryResult::Success:
break;
case CheckBatteryResult::Shutdown:
boot::ShutdownSystem();
break;
case CheckBatteryResult::Reboot:
boot::RebootSystem();
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void CheckBatteryCharge();
}
@@ -1,56 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_check_clock.hpp"
#include "boot_power_utils.hpp"
namespace ams::boot {
namespace {
/* Convenience definitions. */
constexpr u32 ExpectedPlluDivP = (1 << 16);
constexpr u32 ExpectedPlluDivN = (25 << 8);
constexpr u32 ExpectedPlluDivM = (2 << 0);
constexpr u32 ExpectedPlluVal = (ExpectedPlluDivP | ExpectedPlluDivN | ExpectedPlluDivM);
constexpr u32 ExpectedPlluMask = 0x1FFFFF;
constexpr u32 ExpectedUtmipDivN = (25 << 16);
constexpr u32 ExpectedUtmipDivM = (1 << 8);
constexpr u32 ExpectedUtmipVal = (ExpectedUtmipDivN | ExpectedUtmipDivM);
constexpr u32 ExpectedUtmipMask = 0xFFFF00;
/* Helpers. */
bool IsUsbClockValid() {
uintptr_t car_regs = dd::QueryIoMapping(0x60006000ul, os::MemoryPageSize);
AMS_ASSERT(car_regs != 0);
const u32 pllu = reg::Read(car_regs + 0xC0);
const u32 utmip = reg::Read(car_regs + 0x480);
return ((pllu & ExpectedPlluMask) == ExpectedPlluVal) && ((utmip & ExpectedUtmipMask) == ExpectedUtmipVal);
}
}
void CheckClock() {
if (!IsUsbClockValid()) {
/* Sleep for 1s, then reboot. */
os::SleepThread(TimeSpan::FromSeconds(1));
RebootSystem();
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void CheckClock();
}
@@ -1,37 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_clock_initial_configuration.hpp"
namespace ams::boot {
namespace {
constexpr inline dd::PhysicalAddress PmcBase = 0x7000E400;
/* Convenience definitions. */
constexpr u32 InitialClockOutMask1x = 0x00C4;
constexpr u32 InitialClockOutMask6x = 0xC4C4;
}
void SetInitialClockConfiguration() {
/* Write mask to APBDEV_PMC_PWR_DET, then clear APBDEV_PMC_PWR_DET_VAL. */
const u32 mask = hos::GetVersion() >= hos::Version_6_0_0 ? InitialClockOutMask6x : InitialClockOutMask1x;
dd::ReadModifyWriteIoRegister(PmcBase + APBDEV_PMC_CLK_OUT_CNTRL, mask, mask);
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void SetInitialClockConfiguration();
}
@@ -1,653 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_display.hpp"
#include "boot_i2c_utils.hpp"
#include "boot_registers_di.hpp"
namespace ams::boot {
/* Display configuration included into anonymous namespace. */
namespace {
#include "boot_display_config.inc"
}
namespace {
/* Helpful defines. */
constexpr size_t DeviceAddressSpaceAlignSize = 4_MB;
constexpr dd::DeviceVirtualAddress FrameBufferDeviceAddress = DisplayConfigFrameBufferAddress;
constexpr size_t FrameBufferWidth = 768;
constexpr size_t FrameBufferHeight = 1280;
constexpr size_t FrameBufferSize = FrameBufferHeight * FrameBufferWidth * sizeof(u32);
constexpr dd::PhysicalAddress PmcBase = 0x7000E400ul;
constexpr dd::PhysicalAddress Disp1Base = 0x54200000ul;
constexpr dd::PhysicalAddress DsiBase = 0x54300000ul;
constexpr dd::PhysicalAddress ClkRstBase = 0x60006000ul;
constexpr dd::PhysicalAddress GpioBase = 0x6000D000ul;
constexpr dd::PhysicalAddress ApbMiscBase = 0x70000000ul;
constexpr dd::PhysicalAddress MipiCalBase = 0x700E3000ul;
constexpr size_t Disp1Size = 3 * os::MemoryPageSize;
constexpr size_t DsiSize = os::MemoryPageSize;
constexpr size_t ClkRstSize = os::MemoryPageSize;
constexpr size_t GpioSize = os::MemoryPageSize;
constexpr size_t ApbMiscSize = os::MemoryPageSize;
constexpr size_t MipiCalSize = os::MemoryPageSize;
constexpr int DsiWaitForCommandMilliSecondsMax = 250;
constexpr int DsiWaitForCommandCompletionMilliSeconds = 5;
constexpr int DsiWaitForHostControlMilliSecondsMax = 150;
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. */
constinit bool g_is_display_intialized = false;
constinit spl::SocType g_soc_type = spl::SocType_Erista;
constinit u32 g_lcd_vendor = 0;
constinit int g_display_brightness = 100;
constinit dd::DeviceAddressSpaceType g_device_address_space;
constinit pwm::driver::ChannelSession g_lcd_backlight_session;
constinit u32 *g_frame_buffer = nullptr;
constinit u8 g_frame_buffer_storage[DeviceAddressSpaceAlignSize + FrameBufferSize];
constinit uintptr_t g_disp1_regs = 0;
constinit uintptr_t g_dsi_regs = 0;
constinit uintptr_t g_clk_rst_regs = 0;
constinit uintptr_t g_gpio_regs = 0;
constinit uintptr_t g_apb_misc_regs = 0;
constinit uintptr_t g_mipi_cal_regs = 0;
/* Helper functions. */
void InitializeRegisterVirtualAddresses() {
g_disp1_regs = dd::QueryIoMapping(Disp1Base, Disp1Size);
g_dsi_regs = dd::QueryIoMapping(DsiBase, DsiSize);
g_clk_rst_regs = dd::QueryIoMapping(ClkRstBase, ClkRstSize);
g_gpio_regs = dd::QueryIoMapping(GpioBase, GpioSize);
g_apb_misc_regs = dd::QueryIoMapping(ApbMiscBase, ApbMiscSize);
g_mipi_cal_regs = dd::QueryIoMapping(MipiCalBase, MipiCalSize);
AMS_ABORT_UNLESS(g_disp1_regs != 0);
AMS_ABORT_UNLESS(g_dsi_regs != 0);
AMS_ABORT_UNLESS(g_clk_rst_regs != 0);
AMS_ABORT_UNLESS(g_gpio_regs != 0);
AMS_ABORT_UNLESS(g_apb_misc_regs != 0);
AMS_ABORT_UNLESS(g_mipi_cal_regs != 0);
}
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 (g_soc_type) {
case spl::SocType_Erista: DoRegisterWrites(base_address, reg_writes_erista, num_writes_erista); break;
case spl::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:
os::SleepThread(TimeSpan::FromMilliSeconds(reg_writes[i].offset));
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}
#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, 0x00, FrameBufferSize);
dd::FlushDataCache(g_frame_buffer, FrameBufferSize);
} else {
const uintptr_t frame_buffer_aligned = util::AlignUp(reinterpret_cast<uintptr_t>(g_frame_buffer_storage), DeviceAddressSpaceAlignSize);
g_frame_buffer = reinterpret_cast<u32 *>(frame_buffer_aligned);
std::memset(g_frame_buffer, 0x00, FrameBufferSize);
dd::FlushDataCache(g_frame_buffer, FrameBufferSize);
/* Create Address Space. */
R_ABORT_UNLESS(dd::CreateDeviceAddressSpace(std::addressof(g_device_address_space), 0, (UINT64_C(1) << 32)));
/* Attach it to the DC. */
R_ABORT_UNLESS(dd::AttachDeviceAddressSpace(std::addressof(g_device_address_space), svc::DeviceName_Dc));
/* Map the framebuffer for the DC as read-only. */
R_ABORT_UNLESS(dd::MapDeviceAddressSpaceAligned(std::addressof(g_device_address_space), dd::GetCurrentProcessHandle(), frame_buffer_aligned, FrameBufferSize, FrameBufferDeviceAddress, dd::MemoryPermission_ReadOnly));
}
}
void FinalizeFrameBuffer() {
if (g_frame_buffer != nullptr) {
const uintptr_t frame_buffer_aligned = util::AlignUp(reinterpret_cast<uintptr_t>(g_frame_buffer_storage), DeviceAddressSpaceAlignSize);
/* Unmap the framebuffer from the DC. */
dd::UnmapDeviceAddressSpace(std::addressof(g_device_address_space), dd::GetCurrentProcessHandle(), frame_buffer_aligned, FrameBufferSize, FrameBufferDeviceAddress);
/* Detach address space from the DC. */
dd::DetachDeviceAddressSpace(std::addressof(g_device_address_space), svc::DeviceName_Dc);
/* Destroy the address space. */
dd::DestroyDeviceAddressSpace(std::addressof(g_device_address_space));
g_frame_buffer = nullptr;
}
}
void WaitDsiTrigger() {
os::Tick timeout = os::GetSystemTick() + os::ConvertToTick(TimeSpan::FromMilliSeconds(DsiWaitForCommandMilliSecondsMax));
while (true) {
if (os::GetSystemTick() >= timeout) {
break;
}
if (reg::Read(g_dsi_regs + sizeof(u32) * DSI_TRIGGER) == 0) {
break;
}
}
os::SleepThread(TimeSpan::FromMilliSeconds(DsiWaitForCommandCompletionMilliSeconds));
}
void WaitDsiHostControl() {
os::Tick timeout = os::GetSystemTick() + os::ConvertToTick(TimeSpan::FromMilliSeconds(DsiWaitForHostControlMilliSecondsMax));
while (true) {
if (os::GetSystemTick() >= timeout) {
break;
}
if ((reg::Read(g_dsi_regs + sizeof(u32) * DSI_HOST_CONTROL) & DSI_HOST_CONTROL_IMM_BTA) == 0) {
break;
}
}
}
void EnableBacklightForVendor2050ForAula(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);
os::SleepThread(TimeSpan::FromMilliSeconds(300));
/* Clear client sync point block resest. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_INCR_SYNCPT_CNTRL, 0);
os::SleepThread(TimeSpan::FromMilliSeconds(300));
/* 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) {
pwm::driver::SetScale(g_lcd_backlight_session, static_cast<double>(brightness));
pwm::driver::SetEnabled(g_lcd_backlight_session, true);
}
}
void InitializeDisplay() {
/* Setup globals. */
InitializeRegisterVirtualAddresses();
g_soc_type = spl::GetSocType();
InitializeFrameBuffer();
/* Get the hardware type. */
const auto hw_type = spl::GetHardwareType();
/* Turn on DSI/voltage rail. */
{
i2c::driver::I2cSession i2c_session;
R_ABORT_UNLESS(i2c::driver::OpenSession(std::addressof(i2c_session), i2c::DeviceCode_Max77620Pmic));
if (g_soc_type == spl::SocType_Mariko) {
WriteI2cRegister(i2c_session, 0x18, 0x3A);
WriteI2cRegister(i2c_session, 0x1F, 0x71);
}
WriteI2cRegister(i2c_session, 0x23, 0xD0);
i2c::driver::CloseSession(i2c_session);
}
/* 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. */
dd::WriteIoRegister(PmcBase + APBDEV_PMC_IO_DPD_REQ, reg::Encode(PMC_REG_BITS_ENUM(IO_DPD_REQ_CODE, DPD_OFF)));
dd::WriteIoRegister(PmcBase + APBDEV_PMC_IO_DPD2_REQ, reg::Encode(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 == spl::HardwareType::Aula) {
/* 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);
os::SleepThread(TimeSpan::FromMilliSeconds(10));
reg::SetBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x2);
os::SleepThread(TimeSpan::FromMilliSeconds(10));
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 (g_soc_type == spl::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);
os::SleepThread(TimeSpan::FromMilliSeconds(10));
/* Enable backlight reset. */
reg::SetBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x4);
os::SleepThread(TimeSpan::FromMilliSeconds(60));
if (hw_type == spl::HardwareType::Aula) {
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();
os::SleepThread(TimeSpan::FromMilliSeconds(5));
/* 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
*/
if ((host_response[2] & 0xFF) == 0x10) {
g_lcd_vendor = 0;
} else {
g_lcd_vendor = (host_response[2] >> 8) & 0xFF00;
}
g_lcd_vendor = (g_lcd_vendor & 0xFFFFFF00) | (host_response[2] & 0xFF);
}
/* LCD vendor specific configuration. */
if (g_lcd_vendor != 0x2050) {
/* Configure LCD backlight to use PWM. */
reg::ClearBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x1);
reg::Write(g_apb_misc_regs + PINMUX_AUX_LCD_BL_PWM, PINMUX_REG_BITS_ENUM(AUX_LCD_BL_PWM_PM, PWM0),
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN));
/* Configure LCD backlight. */
R_ABORT_UNLESS(pwm::driver::OpenSession(std::addressof(g_lcd_backlight_session), pwm::DeviceCode_LcdBacklight));
pwm::driver::SetPeriod(g_lcd_backlight_session, TimeSpan::FromNanoSeconds(33898));
switch (g_lcd_vendor) {
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);
os::SleepThread(TimeSpan::FromMilliSeconds(180));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(180));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(120));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
break;
}
} else {
/* LCD vendor 0x2050, unknown Aula (OLED) screen. */
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1105);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
os::SleepThread(TimeSpan::FromMilliSeconds(180));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x2905);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
}
os::SleepThread(TimeSpan::FromMilliSeconds(20));
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);
os::SleepThread(TimeSpan::FromMilliSeconds(10));
/* 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 (g_soc_type == spl::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);
}
os::SleepThread(TimeSpan::FromMilliSeconds(10));
/* Write DISP1, FrameBuffer config. */
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigDc02);
DO_SLEEP_OR_REGISTER_WRITES(g_disp1_regs, DisplayConfigFrameBuffer);
if (g_lcd_vendor != 0x2050) {
os::SleepThread(TimeSpan::FromMilliSeconds(35));
}
g_is_display_intialized = true;
}
void ShowDisplay(size_t x, size_t y, size_t width, size_t height, const u32 *img) {
if (!g_is_display_intialized) {
return;
}
/* Draw the image to the screen. */
std::memset(g_frame_buffer, 0, FrameBufferSize);
{
for (size_t cur_y = 0; cur_y < height; cur_y++) {
for (size_t cur_x = 0; cur_x < width; cur_x++) {
g_frame_buffer[(FrameBufferHeight - (x + cur_x)) * FrameBufferWidth + y + cur_y] = img[cur_y * width + cur_x];
}
}
}
dd::FlushDataCache(g_frame_buffer, FrameBufferSize);
/* Enable backlight. */
if (g_lcd_vendor == 0x2050) {
EnableBacklightForVendor2050ForAula(g_display_brightness);
} else {
EnableBacklightForGeneric(g_display_brightness);
}
}
void FinalizeDisplay() {
if (!g_is_display_intialized) {
return;
}
/* Disable backlight. */
if (g_lcd_vendor == 0x2050) {
EnableBacklightForVendor2050ForAula(0);
} else {
pwm::driver::SetEnabled(g_lcd_backlight_session, false);
pwm::driver::CloseSession(g_lcd_backlight_session);
}
reg::Write(g_disp1_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 1);
reg::Write(g_disp1_regs + sizeof(u32) * DSI_WR_DATA, 0x2805);
/* Nintendo waits 5 frames before continuing. */
{
const uintptr_t host1x_vaddr = dd::GetIoMapping(0x500030A4, 4);
const u32 start_val = reg::Read(host1x_vaddr);
while (reg::Read(host1x_vaddr) < start_val + 5) {
/* spinlock here. */
}
}
reg::Write(g_disp1_regs + sizeof(u32) * DC_CMD_STATE_ACCESS, (READ_MUX | WRITE_MUX));
reg::Write(g_disp1_regs + sizeof(u32) * DSI_VIDEO_MODE_CONTROL, 0);
DO_REGISTER_WRITES(g_disp1_regs, DisplayConfigDc01Fini01);
os::SleepThread(TimeSpan::FromMilliSeconds(40));
DO_SOC_DEPENDENT_REGISTER_WRITES(g_clk_rst_regs, DisplayConfigPlld01);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Fini01);
DO_SOC_DEPENDENT_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsiPhyTiming);
DO_REGISTER_WRITES(g_dsi_regs, DisplayConfigDsi01Fini02);
if (g_lcd_vendor != 0x2050) {
os::SleepThread(TimeSpan::FromMilliSeconds(10));
}
/* Vendor specific shutdown. */
switch (g_lcd_vendor) {
case 0x10: /* Japan Display Inc screens. */
DO_SLEEP_OR_REGISTER_WRITES(g_dsi_regs, DisplayConfigJdiSpecificFini01);
break;
case 0xF30: /* AUO first revision screens. */
DO_SLEEP_OR_REGISTER_WRITES(g_dsi_regs, DisplayConfigAuoRev1SpecificFini01);
break;
case 0x1020: /* Innolux second revision screens. */
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0xB39);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x751548B1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x71143209);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x115631);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
break;
case 0x1030: /* AUO second revision screens. */
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0xB39);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x711148B1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x71143209);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x114D31);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
break;
case 0x1040: /* Unknown second revision screens. */
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);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0xB39);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x731348B1);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x71243209);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x4C31);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
os::SleepThread(TimeSpan::FromMilliSeconds(5));
break;
default:
break;
}
reg::Write(g_dsi_regs + sizeof(u32) * DSI_WR_DATA, 0x1005);
reg::Write(g_dsi_regs + sizeof(u32) * DSI_TRIGGER, DSI_TRIGGER_HOST);
os::SleepThread(g_lcd_vendor == 0x2050 ? TimeSpan::FromMilliSeconds(120) : TimeSpan::FromMilliSeconds(50));
/* Disable backlight RST/Voltage. */
reg::ClearBits(g_gpio_regs + GPIO_PORT6_OUT_1, 0x4);
if (g_lcd_vendor == 0x2050) {
os::SleepThread(TimeSpan::FromMilliSeconds(30));
} else {
os::SleepThread(TimeSpan::FromMilliSeconds(10));
reg::ClearBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x2);
os::SleepThread(TimeSpan::FromMilliSeconds(10));
reg::ClearBits(g_gpio_regs + GPIO_PORT3_OUT_0, 0x1);
os::SleepThread(TimeSpan::FromMilliSeconds(10));
}
/* Cut clock to DSI. */
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_H_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_H_SET_SET_MIPI_CAL_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_H_SET_SET_DSI_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_H_CLR, CLK_RST_REG_BITS_ENUM(CLK_ENB_H_CLR_CLR_CLK_ENB_MIPI_CAL, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_H_CLR_CLR_CLK_ENB_DSI, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_RST_DEV_L_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_HOST1X_RST, ENABLE),
CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_DISP1_RST, ENABLE));
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_ENB_L_CLR, CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLR_CLR_CLK_ENB_HOST1X, ENABLE),
CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLR_CLR_CLK_ENB_DISP1, ENABLE));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_PAD_CONTROL_0, (DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF)));
reg::Write(g_dsi_regs + sizeof(u32) * DSI_POWER_CONTROL, 0);
/* Unmap framebuffer from DC virtual address space. */
FinalizeFrameBuffer();
g_is_display_intialized = false;
}
void SetDisplayBrightness(int percentage) {
g_display_brightness = percentage;
}
}
@@ -1,28 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
/* Splash Screen/Display utilities. */
void InitializeDisplay();
void ShowDisplay(size_t x, size_t y, size_t width, size_t height, const u32 *img);
void FinalizeDisplay();
void SetDisplayBrightness(int percentage);
}
@@ -1,683 +0,0 @@
/*
* Copyright (c) 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},
{sizeof(u32) * DSI_CONTROL, 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, 0},
{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},
};
@@ -1,70 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_driver_management.hpp"
namespace ams::boot {
void InitializeGpioDriverLibrary() {
/* Initialize the gpio client library with the server manager object. */
gpio::InitializeWith(gpio::server::GetServiceObject());
/* Initialize the board driver without enabling interrupt handlers. */
gpio::driver::board::Initialize(false);
/* Initialize the driver library. */
gpio::driver::Initialize();
}
void InitializeI2cDriverLibrary() {
/* Initialize the i2c client library with the server manager object. */
i2c::InitializeWith(i2c::server::GetServiceObject(), i2c::server::GetServiceObjectPowerBus());
/* Initialize the board driver. */
i2c::driver::board::Initialize();
/* Initialize the driver library. */
i2c::driver::Initialize();
/* Initialize the pwm client library with the server manager object. */
pwm::InitializeWith(pwm::server::GetServiceObject());
/* Initialize the pwm board driver. */
pwm::driver::board::Initialize();
/* Initialize the pwm driver library. */
pwm::driver::Initialize();
}
void FinalizeGpioDriverLibrary() {
/* Finalize the gpio client library. */
gpio::Finalize();
}
void FinalizeI2cDriverLibrary() {
/* Finalize the i2c driver library. */
i2c::driver::Finalize();
/* Finalize the i2c client library. */
i2c::Finalize();
/* NOTE: Unknown finalize function is called here by Nintendo. */
/* Finalize the pwm client library. */
pwm::Finalize();
}
}
@@ -1,27 +0,0 @@
/*
* Copyright (c) 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
namespace ams::boot {
void InitializeGpioDriverLibrary();
void InitializeI2cDriverLibrary();
void FinalizeGpioDriverLibrary();
void FinalizeI2cDriverLibrary();
}
@@ -1,30 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_fan_enable.hpp"
namespace ams::boot {
void SetFanPowerEnabled() {
if (spl::GetHardwareType() == spl::HardwareType::Copper) {
/* TODO */
/* boot::gpio::Configure(GpioPadName_FanEnable); */
/* boot::gpio::SetDirection(GpioPadName_FanEnable, GpioDirection_Output); */
/* boot::gpio::SetValue(GpioPadName_FanEnable, GpioValue_High); */
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void SetFanPowerEnabled();
}
@@ -1,72 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_i2c_utils.hpp"
namespace ams::boot {
namespace {
template<typename F>
constexpr Result RetryUntilSuccess(F f) {
constexpr auto Timeout = TimeSpan::FromSeconds(10);
constexpr auto RetryInterval = TimeSpan::FromMilliSeconds(20);
TimeSpan cur_time = TimeSpan(0);
while (true) {
const auto retry_result = f();
R_SUCCEED_IF(R_SUCCEEDED(retry_result));
cur_time += RetryInterval;
R_UNLESS(cur_time < Timeout, retry_result);
os::SleepThread(RetryInterval);
}
}
}
Result ReadI2cRegister(i2c::driver::I2cSession &session, u8 *dst, size_t dst_size, const u8 *cmd, size_t cmd_size) {
AMS_ABORT_UNLESS(dst != nullptr && dst_size > 0);
AMS_ABORT_UNLESS(cmd != nullptr && cmd_size > 0);
u8 cmd_list[i2c::CommandListLengthMax];
i2c::CommandListFormatter formatter(cmd_list, sizeof(cmd_list));
R_ABORT_UNLESS(formatter.EnqueueSendCommand(i2c::TransactionOption_StartCondition, cmd, cmd_size));
R_ABORT_UNLESS(formatter.EnqueueReceiveCommand(static_cast<i2c::TransactionOption>(i2c::TransactionOption_StartCondition | i2c::TransactionOption_StopCondition), dst_size));
R_RETURN(RetryUntilSuccess([&]() { R_RETURN(i2c::driver::ExecuteCommandList(dst, dst_size, session, cmd_list, formatter.GetCurrentLength())); }));
}
Result WriteI2cRegister(i2c::driver::I2cSession &session, const u8 *src, size_t src_size, const u8 *cmd, size_t cmd_size) {
AMS_ABORT_UNLESS(src != nullptr && src_size > 0);
AMS_ABORT_UNLESS(cmd != nullptr && cmd_size > 0);
u8 cmd_list[0x20];
/* N doesn't use a CommandListFormatter here... */
std::memcpy(cmd_list + 0, cmd, cmd_size);
std::memcpy(cmd_list + cmd_size, src, src_size);
R_RETURN(RetryUntilSuccess([&]() { R_RETURN(i2c::driver::Send(session, cmd_list, src_size + cmd_size, static_cast<i2c::TransactionOption>(i2c::TransactionOption_StartCondition | i2c::TransactionOption_StopCondition))); }));
}
Result WriteI2cRegister(i2c::driver::I2cSession &session, const u8 address, const u8 value) {
R_RETURN(WriteI2cRegister(session, std::addressof(value), sizeof(value), &address, sizeof(address)));
}
}
@@ -1,26 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
/* I2C Utilities. */
Result ReadI2cRegister(i2c::driver::I2cSession &session, u8 *dst, size_t dst_size, const u8 *cmd, size_t cmd_size);
Result WriteI2cRegister(i2c::driver::I2cSession &session, const u8 *src, size_t src_size, const u8 *cmd, size_t cmd_size);
Result WriteI2cRegister(i2c::driver::I2cSession &session, const u8 address, const u8 value);
}
@@ -1,224 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_boot_reason.hpp"
#include "boot_change_voltage.hpp"
#include "boot_check_battery.hpp"
#include "boot_check_clock.hpp"
#include "boot_clock_initial_configuration.hpp"
#include "boot_driver_management.hpp"
#include "boot_fan_enable.hpp"
#include "boot_pinmux_initial_configuration.hpp"
#include "boot_repair_boot_images.hpp"
#include "boot_splash_screen.hpp"
#include "boot_power_utils.hpp"
namespace ams {
namespace boot {
namespace {
constinit u8 g_exp_heap_memory[20_KB];
constinit u8 g_unit_heap_memory[5_KB];
constinit lmem::HeapHandle g_exp_heap_handle;
constinit lmem::HeapHandle g_unit_heap_handle;
constinit sf::ExpHeapMemoryResource g_exp_heap_memory_resource;
constinit sf::UnitHeapMemoryResource g_unit_heap_memory_resource;
void *Allocate(size_t size) {
void *mem = lmem::AllocateFromExpHeap(g_exp_heap_handle, size);
return mem;
}
void Deallocate(void *p, size_t size) {
AMS_UNUSED(size);
lmem::FreeToExpHeap(g_exp_heap_handle, p);
}
void InitializeHeaps() {
/* Create the heaps. */
g_exp_heap_handle = lmem::CreateExpHeap(g_exp_heap_memory, sizeof(g_exp_heap_memory), lmem::CreateOption_ThreadSafe);
g_unit_heap_handle = lmem::CreateUnitHeap(g_unit_heap_memory, sizeof(g_unit_heap_memory), sizeof(ddsf::DeviceCodeEntryHolder), lmem::CreateOption_ThreadSafe);
/* Attach the memory resources. */
g_exp_heap_memory_resource.Attach(g_exp_heap_handle);
g_unit_heap_memory_resource.Attach(g_unit_heap_handle);
/* Register with ddsf. */
ddsf::SetMemoryResource(std::addressof(g_exp_heap_memory_resource));
ddsf::SetDeviceCodeEntryHolderMemoryResource(std::addressof(g_unit_heap_memory_resource));
}
}
}
namespace hos {
void SetNonApproximateVersionInternal();
}
namespace init {
void InitializeSystemModule() {
/* Initialize heaps. */
boot::InitializeHeaps();
/* Connect to sm. */
R_ABORT_UNLESS(sm::Initialize());
/* Initialize fs. */
fs::InitializeForSystem();
fs::SetAllocator(boot::Allocate, boot::Deallocate);
fs::SetEnabledAutoAbort(false);
/* Initialize spl. */
spl::Initialize();
/* Set the true hos version. */
hos::SetNonApproximateVersionInternal();
/* Verify that we can sanely execute. */
ams::CheckApiVersion();
}
void FinalizeSystemModule() { /* ... */ }
void Startup() { /* ... */ }
}
void ExceptionHandler(FatalErrorContext *ctx) {
/* We're boot sysmodule, so manually reboot to fatal error. */
boot::RebootForFatalError(ctx);
}
void Main() {
/* Set thread name. */
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(boot, Main));
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(boot, Main));
/* Perform atmosphere-specific init. */
ams::InitializeForBoot();
/* Set the reboot payload with ams.mitm. */
boot::SetInitialRebootPayload();
/* Change voltage from 3.3v to 1.8v for select devices. */
boot::ChangeGpioVoltageTo1_8v();
/* Setup gpio. */
gpio::driver::SetInitialGpioConfig();
/* Initialize the gpio server library. */
boot::InitializeGpioDriverLibrary();
/* Initialize the i2c server library. */
boot::InitializeI2cDriverLibrary();
/* Get the hardware type. */
const auto hw_type = spl::GetHardwareType();
/* Initialize the power control library without interrupt event handling. */
if (hw_type != spl::HardwareType::Calcio) {
powctl::Initialize(false);
}
/* Check USB PLL/UTMIP clock. */
boot::CheckClock();
/* Talk to PMIC/RTC, set boot reason with SPL. */
boot::DetectBootReason();
/* Display the splash screen and check the battery charge. */
if (hw_type != spl::HardwareType::Calcio) {
/* Display splash screen for two seconds. */
boot::ShowSplashScreen();
/* Check that the battery has enough to boot. */
boot::CheckBatteryCharge();
}
/* Configure pinmux + drive pads. */
boot::SetInitialPinmuxConfiguration();
/* Configure the PMC wake pin settings. */
gpio::driver::SetInitialWakePinConfig();
/* Configure output clock. */
if (hw_type != spl::HardwareType::Calcio) {
boot::SetInitialClockConfiguration();
}
/* Set Fan enable config (Copper only). */
boot::SetFanPowerEnabled();
/* Repair boot partitions in NAND if needed. */
boot::CheckAndRepairBootImages();
/* Finalize the power control library. */
if (hw_type != spl::HardwareType::Calcio) {
powctl::Finalize();
}
/* Finalize the i2c server library. */
boot::FinalizeI2cDriverLibrary();
/* Finalize the gpio server library. */
boot::FinalizeGpioDriverLibrary();
/* Tell PM to start boot2. */
R_ABORT_UNLESS(pmshellInitialize());
R_ABORT_UNLESS(pmshellNotifyBootFinished());
}
}
/* Override operator new. */
void *operator new(size_t size) {
return ams::boot::Allocate(size);
}
void *operator new(size_t size, const std::nothrow_t &) {
return ams::boot::Allocate(size);
}
void operator delete(void *p) {
return ams::boot::Deallocate(p, 0);
}
void operator delete(void *p, size_t size) {
return ams::boot::Deallocate(p, size);
}
void *operator new[](size_t size) {
return ams::boot::Allocate(size);
}
void *operator new[](size_t size, const std::nothrow_t &) {
return ams::boot::Allocate(size);
}
void operator delete[](void *p) {
return ams::boot::Deallocate(p, 0);
}
void operator delete[](void *p, size_t size) {
return ams::boot::Deallocate(p, size);
}
@@ -1,28 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_pinmux_initial_configuration.hpp"
namespace ams::boot {
void SetInitialPinmuxConfiguration() {
pinmux::driver::Initialize();
pinmux::driver::SetInitialConfig();
pinmux::driver::SetInitialDrivePadConfig();
pinmux::driver::Finalize();
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void SetInitialPinmuxConfiguration();
}
@@ -1,123 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_i2c_utils.hpp"
#include "boot_pmic_driver.hpp"
namespace ams::boot {
void PmicDriver::ShutdownSystem() {
this->ShutdownSystem(false);
}
void PmicDriver::RebootSystem() {
this->ShutdownSystem(true);
}
Result PmicDriver::GetAcOk(bool *out) {
u8 power_status;
R_TRY(this->GetPowerStatus(std::addressof(power_status)));
*out = (power_status & 0x02) != 0;
R_SUCCEED();
}
Result PmicDriver::GetOnOffIrq(u8 *out) {
const u8 addr = 0x0B;
R_RETURN(ReadI2cRegister(m_i2c_session, out, sizeof(*out), std::addressof(addr), sizeof(addr)));
}
Result PmicDriver::GetPowerStatus(u8 *out) {
const u8 addr = 0x15;
R_RETURN(ReadI2cRegister(m_i2c_session, out, sizeof(*out), std::addressof(addr), sizeof(addr)));
}
Result PmicDriver::GetNvErc(u8 *out) {
const u8 addr = 0x0C;
R_RETURN(ReadI2cRegister(m_i2c_session, out, sizeof(*out), std::addressof(addr), sizeof(addr)));
}
Result PmicDriver::GetPowerButtonPressed(bool *out) {
u8 on_off_irq;
R_TRY(this->GetOnOffIrq(std::addressof(on_off_irq)));
*out = (on_off_irq & 0x08) != 0;
R_SUCCEED();
}
void PmicDriver::ShutdownSystem(bool reboot) {
const u8 on_off_1_addr = 0x41;
const u8 on_off_2_addr = 0x42;
/* Get value, set or clear software reset mask. */
u8 on_off_2_val = 0;
R_ABORT_UNLESS(ReadI2cRegister(m_i2c_session, std::addressof(on_off_2_val), sizeof(on_off_2_val), std::addressof(on_off_2_addr), sizeof(on_off_2_addr)));
if (reboot) {
on_off_2_val |= 0x80;
} else {
on_off_2_val &= ~0x80;
}
R_ABORT_UNLESS(WriteI2cRegister(m_i2c_session, std::addressof(on_off_2_val), sizeof(on_off_2_val), std::addressof(on_off_2_addr), sizeof(on_off_2_addr)));
/* Get value, set software reset mask. */
u8 on_off_1_val = 0;
R_ABORT_UNLESS(ReadI2cRegister(m_i2c_session, std::addressof(on_off_1_val), sizeof(on_off_1_val), std::addressof(on_off_1_addr), sizeof(on_off_1_addr)));
on_off_1_val |= 0x80;
/* Finalize the battery on non-Calcio. */
if (spl::GetHardwareType() != spl::HardwareType::Calcio) {
BatteryDriver battery_driver;
this->FinalizeBattery(battery_driver);
}
/* Actually write the value to trigger shutdown/reset. */
R_ABORT_UNLESS(WriteI2cRegister(m_i2c_session, std::addressof(on_off_1_val), sizeof(on_off_1_val), std::addressof(on_off_1_addr), sizeof(on_off_1_addr)));
/* Allow up to 5 seconds for shutdown/reboot to take place. */
os::SleepThread(TimeSpan::FromSeconds(5));
AMS_ABORT("Shutdown failed");
}
void PmicDriver::FinalizeBattery(BatteryDriver &battery_driver) {
/* Get whether shutdown is enabled. */
bool shutdown_enabled;
if (R_FAILED(battery_driver.IsI2cShutdownEnabled(std::addressof(shutdown_enabled)))) {
return;
}
/* On Hoag, we don't want to use the desired shutdown value when battery charged. */
bool use_desired_shutdown = true;
if (spl::GetHardwareType() == spl::HardwareType::Hoag) {
float battery_charge_raw;
if (R_FAILED(battery_driver.GetChargePercentage(std::addressof(battery_charge_raw))) || battery_charge_raw >= 80.0) {
use_desired_shutdown = false;
}
}
bool ac_ok;
bool desired_shutdown_enabled;
if (R_FAILED(this->GetAcOk(&ac_ok)) || ac_ok) {
desired_shutdown_enabled = false;
} else {
desired_shutdown_enabled = true;
}
desired_shutdown_enabled &= use_desired_shutdown;
if (shutdown_enabled != desired_shutdown_enabled) {
battery_driver.SetI2cShutdownEnabled(desired_shutdown_enabled);
}
}
}
@@ -1,47 +0,0 @@
/*
* Copyright (c) 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 "boot_battery_driver.hpp"
namespace ams::boot {
/* Driver object. */
class PmicDriver {
private:
i2c::driver::I2cSession m_i2c_session;
public:
PmicDriver() {
R_ABORT_UNLESS(i2c::driver::OpenSession(std::addressof(m_i2c_session), i2c::DeviceCode_Max77620Pmic));
}
~PmicDriver() {
i2c::driver::CloseSession(m_i2c_session);
}
private:
Result GetPowerStatus(u8 *out);
void ShutdownSystem(bool reboot);
void FinalizeBattery(BatteryDriver &battery_driver);
public:
void ShutdownSystem();
void RebootSystem();
Result GetAcOk(bool *out);
Result GetOnOffIrq(u8 *out);
Result GetNvErc(u8 *out);
Result GetPowerButtonPressed(bool *out);
};
}
@@ -1,106 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_power_utils.hpp"
#include "boot_pmic_driver.hpp"
namespace ams::boot {
namespace {
/* Convenience definitions. */
constexpr uintptr_t IramBase = 0x40000000ull;
constexpr uintptr_t IramPayloadBase = 0x40010000ull;
constexpr size_t IramSize = 0x40000;
constexpr size_t IramPayloadMaxSize = 0x24000;
constexpr size_t IramFatalErrorContextOffset = 0x2E000;
/* Globals. */
alignas(os::MemoryPageSize) u8 g_work_page[os::MemoryPageSize];
constexpr const u8 FuseeBin[] = {
#embed <fusee.bin>
};
/* Helpers. */
void ClearIram() {
/* Make page FFs. */
std::memset(g_work_page, 0xFF, sizeof(g_work_page));
/* Overwrite all of IRAM with FFs. */
for (size_t ofs = 0; ofs < IramSize; ofs += sizeof(g_work_page)) {
exosphere::CopyToIram(IramBase + ofs, g_work_page, sizeof(g_work_page));
}
}
void DoRebootToPayload() {
/* Ensure clean IRAM state. */
ClearIram();
/* Copy in payload. */
for (size_t ofs = 0; ofs < sizeof(FuseeBin); ofs += sizeof(g_work_page)) {
std::memcpy(g_work_page, FuseeBin + ofs, std::min(static_cast<size_t>(sizeof(FuseeBin) - ofs), sizeof(g_work_page)));
exosphere::CopyToIram(IramPayloadBase + ofs, g_work_page, sizeof(g_work_page));
}
exosphere::ForceRebootToIramPayload();
}
void DoRebootToFatalError(const ams::FatalErrorContext *ctx) {
/* Ensure clean IRAM state. */
ClearIram();
/* Copy in payload. */
for (size_t ofs = 0; ofs < sizeof(FuseeBin); ofs += sizeof(g_work_page)) {
std::memcpy(g_work_page, FuseeBin + ofs, std::min(static_cast<size_t>(sizeof(FuseeBin) - ofs), sizeof(g_work_page)));
exosphere::CopyToIram(IramPayloadBase + ofs, g_work_page, sizeof(g_work_page));
}
/* Copy in fatal error context, if relevant. */
if (ctx != nullptr) {
std::memset(g_work_page, 0xCC, sizeof(g_work_page));
std::memcpy(g_work_page, ctx, sizeof(*ctx));
exosphere::CopyToIram(IramPayloadBase + IramFatalErrorContextOffset, g_work_page, sizeof(g_work_page));
}
exosphere::ForceRebootToFatalError();
}
}
void RebootSystem() {
if (spl::GetSocType() == spl::SocType_Erista) {
DoRebootToPayload();
} else {
/* On Mariko, we can't reboot to payload, so we should just do a reboot. */
PmicDriver().RebootSystem();
}
}
void ShutdownSystem() {
PmicDriver().ShutdownSystem();
}
void SetInitialRebootPayload() {
::ams::SetInitialRebootPayload(FuseeBin, sizeof(FuseeBin));
}
void RebootForFatalError(ams::FatalErrorContext *ctx) {
DoRebootToFatalError(ctx);
}
}
@@ -1,29 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
/* Power utilities. */
void RebootSystem();
void ShutdownSystem();
/* Atmosphere power utilities. */
void SetInitialRebootPayload();
void RebootForFatalError(ams::FatalErrorContext *ctx);
}
@@ -1,352 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer
* Copyright (c) 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 <stratosphere.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
@@ -1,39 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_power_utils.hpp"
#include "boot_repair_boot_images.hpp"
namespace ams::boot {
namespace {
/* Globals. */
alignas(os::MemoryPageSize) u8 g_boot_image_work_buffer[0x10000];
}
void CheckAndRepairBootImages() {
const auto boot_image_update_type = updater::GetBootImageUpdateType(spl::GetHardwareType());
bool repaired_normal, repaired_safe;
if (R_SUCCEEDED(updater::VerifyBootImagesAndRepairIfNeeded(&repaired_normal, &repaired_safe, g_boot_image_work_buffer, sizeof(g_boot_image_work_buffer), boot_image_update_type)) && repaired_normal) {
/* Nintendo only performs a reboot on successful normal repair. */
RebootSystem();
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void CheckAndRepairBootImages();
}
@@ -1,39 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_rtc_driver.hpp"
namespace ams::boot {
Result RtcDriver::ReadRtcRegister(u8 *out, u8 address) {
const u8 update_addr = 0x04;
const u8 update_val = 0x10;
R_TRY(WriteI2cRegister(m_i2c_session, &update_val, sizeof(update_val), &update_addr, sizeof(update_addr)));
os::SleepThread(TimeSpan::FromMilliSeconds(16));
R_RETURN(ReadI2cRegister(m_i2c_session, out, sizeof(*out), &address, sizeof(address)));
}
Result RtcDriver::GetRtcIntr(u8 *out) {
const u8 addr = 0x00;
R_RETURN(ReadI2cRegister(m_i2c_session, out, sizeof(*out), &addr, sizeof(addr)));
}
Result RtcDriver::GetRtcIntrM(u8 *out) {
const u8 addr = 0x01;
R_RETURN(this->ReadRtcRegister(out, addr));
}
}
@@ -1,39 +0,0 @@
/*
* Copyright (c) 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 "boot_i2c_utils.hpp"
namespace ams::boot {
class RtcDriver {
private:
i2c::driver::I2cSession m_i2c_session;
public:
RtcDriver() {
R_ABORT_UNLESS(i2c::driver::OpenSession(std::addressof(m_i2c_session), i2c::DeviceCode_Max77620Rtc));
}
~RtcDriver() {
i2c::driver::CloseSession(m_i2c_session);
}
private:
Result ReadRtcRegister(u8 *out, u8 address);
public:
Result GetRtcIntr(u8 *out);
Result GetRtcIntrM(u8 *out);
};
}
@@ -1,47 +0,0 @@
/*
* Copyright (c) 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/>.
*/
#include <stratosphere.hpp>
#include "boot_boot_reason.hpp"
#include "boot_display.hpp"
#include "boot_splash_screen.hpp"
namespace ams::boot {
namespace {
/* Include splash screen into anonymous namespace. */
/* TODO: Compile-time switch for splash_screen_text.hpp? */
#include "boot_splash_screen_notext.inc"
}
void ShowSplashScreen() {
const auto boot_reason = GetBootReason();
if (boot_reason == spl::BootReason_AcOk || boot_reason == spl::BootReason_RtcAlarm2) {
return;
}
InitializeDisplay();
{
/* Splash screen is shown for 2 seconds. */
ShowDisplay(SplashScreenX, SplashScreenY, SplashScreenW, SplashScreenH, SplashScreen);
os::SleepThread(TimeSpan::FromSeconds(2));
}
FinalizeDisplay();
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (c) 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 <stratosphere.hpp>
namespace ams::boot {
void ShowSplashScreen();
}
@@ -1,22 +0,0 @@
/*
* Copyright (c) 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/>.
*/
constexpr size_t SplashScreenX = 535;
constexpr size_t SplashScreenY = 274;
constexpr size_t SplashScreenW = 210;
constexpr size_t SplashScreenH = 172;
constexpr u32 SplashScreen[] = {0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF202020, 0xFF404040, 0xFF666666, 0xFF666666, 0xFF707070, 0xFF666666, 0xFF666666, 0xFF404040, 0xFF333333, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF101010, 0xFF707070, 0xFFAFAFAF, 0xFFEFEFEF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFEFEFEF, 0xFFBFBFBF, 0xFF707070, 0xFF202020, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,Line truncated
static_assert(sizeof(SplashScreen) == sizeof(u32) * SplashScreenW * SplashScreenH, "Incorrect SplashScreen definition!");
@@ -1,22 +0,0 @@
/*
* Copyright (c) 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/>.
*/
constexpr size_t SplashScreenX = 464;
constexpr size_t SplashScreenY = 274;
constexpr size_t SplashScreenW = 351;
constexpr size_t SplashScreenH = 172;
constexpr u32 SplashScreen[] = {0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF202020, 0xFF202020, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,Line truncated
static_assert(sizeof(SplashScreen) == sizeof(u32) * SplashScreenW * SplashScreenH, "Incorrect SplashScreen definition!");