Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"
This reverts commit 15b7df8ef1.
This commit is contained in:
1 parent
22ec140738
commit
21a3f953d7
3804 files changed
+435
-570162
No files matched your search
-210
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-52
@@ -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!");
|
||||
-29
@@ -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();
|
||||
|
||||
}
|
||||
-37
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
-23
@@ -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);
|
||||
}
|
||||
-28
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
-23
@@ -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!");
|
||||
Reference in new issue
Block a user