Add PWM backlight support + options

- No eye blasting backlight
- Option to choose the prefered brightness
- Smooths transitions
This commit is contained in:
Kostas Missos 2018-09-19 00:01:42 +03:00
parent 780736591e
commit 67a470921a
10 changed files with 156 additions and 13 deletions

View file

@ -34,9 +34,10 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
| Config option | Description | | Config option | Description |
| ------------------ | ---------------------------------------------------------- | | ------------------ | ---------------------------------------------------------- |
| autoboot=0 | 0: Disable, #: Boot entry number to auto boot. | | autoboot=0 | 0: Disable, #: Boot entry number to auto boot. |
| bootwait=3 | 0: Disable (Having VOL- pressed since injection goes to menu. It also disables bootlogo.), #: Time to wait for **VOL-** to enter menu. | | bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. |
| customlogo=0 | 0: Use default hekate bootlogo, 1: Use bootlogo.bmp. | | customlogo=0 | 0: Use default hekate bootlogo, 1: Use bootlogo.bmp. |
| verification=2 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and not 100% reliable), 2: Full (sha256 based, slow and 100% reliable). | | verification=2 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and not 100% reliable), 2: Full (sha256 based, slow and 100% reliable). |
| backlight=100 | Screen backlight level. 0-255. |
### Possible boot entry key/value combinations: ### Possible boot entry key/value combinations:
@ -49,7 +50,7 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
| kernel={SD path} | Replaces the kernel binary | | kernel={SD path} | Replaces the kernel binary |
| kip1={SD path} | Replaces/Adds kernel initial process. Multiple can be set. | | kip1={SD path} | Replaces/Adds kernel initial process. Multiple can be set. |
| kip1patch=patchname| Enables a kip1 patch. Specify with multiple lines and/or as CSV. Implemented patches right now are nosigchk,nogc | | kip1patch=patchname| Enables a kip1 patch. Specify with multiple lines and/or as CSV. Implemented patches right now are nosigchk,nogc |
| fullsvcperm=1 | Disables SVC verification | | fullsvcperm=1 | Disables SVC verification (full services permission) |
| debugmode=1 | Enables Debug mode | | debugmode=1 | Enables Debug mode |
| atmosphere=1 | Enables Atmosphère patching | | atmosphere=1 | Enables Atmosphère patching |
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. | | payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. |
@ -57,6 +58,8 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
You can find a template [Here](./res/hekate_ipl_template.ini) You can find a template [Here](./res/hekate_ipl_template.ini)
If the main .ini is not found, it is created on the first hekate boot.
``` ```
hekate (C) 2018 naehrwert, st4rk hekate (C) 2018 naehrwert, st4rk

View file

@ -45,6 +45,7 @@ void set_default_configuration()
h_cfg.verification = 2; h_cfg.verification = 2;
h_cfg.se_keygen_done = 0; h_cfg.se_keygen_done = 0;
h_cfg.sbar_time_keeping = 0; h_cfg.sbar_time_keeping = 0;
h_cfg.backlight = 100;
} }
int create_config_entry() int create_config_entry()
@ -96,6 +97,9 @@ int create_config_entry()
f_puts("\nverification=", &fp); f_puts("\nverification=", &fp);
itoa(h_cfg.verification, lbuf, 10); itoa(h_cfg.verification, lbuf, 10);
f_puts(lbuf, &fp); f_puts(lbuf, &fp);
f_puts("\nbacklight=", &fp);
itoa(h_cfg.backlight, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\n", &fp); f_puts("\n", &fp);
if (mainIniFound) if (mainIniFound)
@ -562,3 +566,71 @@ void config_verification()
return; return;
btn_wait(); btn_wait();
} }
void config_backlight()
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
u32 bri_entries = 11;
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (bri_entries + 3));
u32 *bri_values = (u32 *)malloc(sizeof(u32) * bri_entries);
char *bri_text = (char *)malloc(8 * bri_entries);
for (u32 j = 1; j < bri_entries; j++)
bri_values[j] = j * 10;
ments[0].type = MENT_BACK;
ments[0].caption = "Back";
ments[1].type = MENT_CHGLINE;
u32 i = 0;
for (i = 1; i < bri_entries; i++)
{
if ((h_cfg.backlight / 20) != i)
bri_text[i * 32] = ' ';
else
bri_text[i * 32] = '*';
if (i < 10)
{
bri_text[i * 32 + 1] = i + '0';
memcpy(bri_text + i * 32 + 2, "0%", 3);
}
else
memcpy(bri_text + i * 32 + 1, "100%", 5);
ments[i + 1].type = MENT_CHOICE;
ments[i + 1].caption = bri_text + i * 32;
ments[i + 1].data = &bri_values[i];
}
memset(&ments[i + 1], 0, sizeof(ment_t));
menu_t menu = {ments, "Backlight brightness", 0, 0};
u32 *temp_backlight = (u32 *)tui_do_menu(&gfx_con, &menu);
if (temp_backlight != NULL)
{
gfx_clear_grey(&gfx_ctxt, 0x1B);
gfx_con_setpos(&gfx_con, 0, 0);
h_cfg.backlight = (*(u32 *)temp_backlight) * 2;
//Save choice to ini file.
if (!create_config_entry())
gfx_puts(&gfx_con, "\nConfiguration was saved!\n");
else
EPRINTF("\nConfiguration saving failed!");
gfx_puts(&gfx_con, "\nPress any key...");
}
free(ments);
free(bri_values);
free(bri_text);
if (temp_backlight == NULL)
return;
btn_wait();
}

View file

@ -29,6 +29,7 @@ typedef struct _hekate_config
// Global temporary config. // Global temporary config.
int se_keygen_done; int se_keygen_done;
u32 sbar_time_keeping; u32 sbar_time_keeping;
u32 backlight;
} hekate_config; } hekate_config;
void set_default_configuration(); void set_default_configuration();
@ -37,5 +38,6 @@ void config_autoboot();
void config_bootdelay(); void config_bootdelay();
void config_customlogo(); void config_customlogo();
void config_verification(); void config_verification();
void config_backlight();
#endif /* _CONFIG_H_ */ #endif /* _CONFIG_H_ */

View file

@ -137,14 +137,54 @@ void display_init()
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
} }
void display_backlight_pwm_init()
{
clock_enable_pwm();
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31); // Enable PWM
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; // PWM clock source.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
}
void display_backlight(bool enable) void display_backlight(bool enable)
{ {
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM. gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM GPIO.
}
void display_backlight_brightness(u32 brightness, u32 step_delay)
{
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR) >> 16) & 0xFF;
if (brightness == old_value)
return;
if (brightness > 255)
brightness = 255;
if (old_value < brightness)
{
for (u32 i = old_value; i < brightness + 1; i++)
{
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31) | (i << 16); // Enable PWM
usleep(step_delay);
}
}
else
{
for (u32 i = old_value; i > brightness; i--)
{
PWM(PWM_CONTROLLER_PWM_CSR) = (1 << 31) | (i << 16); // Enable PWM
usleep(step_delay);
}
}
if (!brightness)
PWM(PWM_CONTROLLER_PWM_CSR) = 0;
} }
void display_end() void display_end()
{ {
display_backlight(false); display_backlight_brightness(0, 1000);
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1; DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1;
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; DSI(_DSIREG(DSI_WR_DATA)) = 0x2805;

View file

@ -161,6 +161,8 @@
#define DE_CONTROL_ACTIVE_BLANK (4 << 2) #define DE_CONTROL_ACTIVE_BLANK (4 << 2)
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480 #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_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_WIN_CSC_YOF 0x611 #define DC_WIN_CSC_YOF 0x611
@ -338,7 +340,11 @@
#define DSI_PAD_CONTROL_4 0x52 #define DSI_PAD_CONTROL_4 0x52
/*! Display backlight related PWM registers. */
#define PWM_CONTROLLER_PWM_CSR 0x00
void display_init(); void display_init();
void display_backlight_pwm_init();
void display_end(); void display_end();
/*! Show one single color on the display. */ /*! Show one single color on the display. */
@ -346,6 +352,7 @@ void display_color_screen(u32 color);
/*! Switches screen backlight ON/OFF. */ /*! Switches screen backlight ON/OFF. */
void display_backlight(bool enable); void display_backlight(bool enable);
void display_backlight_brightness(u32 brightness, u32 step_delay);
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ /*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
u32 *display_init_framebuffer(); u32 *display_init_framebuffer();

View file

@ -20,6 +20,8 @@
#include "../config/config.h" #include "../config/config.h"
#include "../power/max17050.h" #include "../power/max17050.h"
#include "../utils/util.h" #include "../utils/util.h"
#include "../config/config.h"
#include "di.h"
#ifdef MENU_LOGO_ENABLE #ifdef MENU_LOGO_ENABLE
extern u8 *Kc_MENU_LOGO; extern u8 *Kc_MENU_LOGO;
@ -161,6 +163,8 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
gfx_con_setpos(con, 0, 1191); gfx_con_setpos(con, 0, 1191);
gfx_printf(con, "%k VOL: Move up/down\n PWR: Select option%k", 0xFF555555, 0xFFCCCCCC); gfx_printf(con, "%k VOL: Move up/down\n PWR: Select option%k", 0xFF555555, 0xFFCCCCCC);
display_backlight_brightness(h_cfg.backlight, 1000);
// Wait for user command. // Wait for user command.
u32 btn = btn_wait(); u32 btn = btn_wait();

View file

@ -2209,7 +2209,6 @@ void auto_launch_firmware()
}; };
struct _bmp_data bmpData; struct _bmp_data bmpData;
bool backlightEnabled = false;
bool bootlogoFound = false; bool bootlogoFound = false;
char *bootlogoCustomEntry = NULL; char *bootlogoCustomEntry = NULL;
@ -2252,6 +2251,8 @@ void auto_launch_firmware()
h_cfg.customlogo = atoi(kv->val); h_cfg.customlogo = atoi(kv->val);
else if (!strcmp("verification", kv->key)) else if (!strcmp("verification", kv->key))
h_cfg.verification = atoi(kv->val); h_cfg.verification = atoi(kv->val);
else if (!strcmp("backlight", kv->key))
h_cfg.backlight = atoi(kv->val);
} }
boot_entry_id++; boot_entry_id++;
continue; continue;
@ -2390,8 +2391,7 @@ void auto_launch_firmware()
} }
free(BOOTLOGO); free(BOOTLOGO);
display_backlight(true); display_backlight_brightness(h_cfg.backlight, 1000);
backlightEnabled = 1;
// Wait before booting. If VOL- is pressed go into bootloader menu. // Wait before booting. If VOL- is pressed go into bootloader menu.
u32 btn = btn_wait_timeout(h_cfg.bootwait * 1000, BTN_VOL_DOWN); u32 btn = btn_wait_timeout(h_cfg.bootwait * 1000, BTN_VOL_DOWN);
@ -2432,9 +2432,6 @@ out:
sd_unmount(); sd_unmount();
gfx_con.mute = false; gfx_con.mute = false;
if (!backlightEnabled)
display_backlight(true);
} }
void toggle_autorcm(bool enable) void toggle_autorcm(bool enable)
@ -3053,6 +3050,7 @@ ment_t ment_options[] = {
MDEF_HANDLER("Auto boot", config_autoboot), MDEF_HANDLER("Auto boot", config_autoboot),
MDEF_HANDLER("Boot time delay", config_bootdelay), MDEF_HANDLER("Boot time delay", config_bootdelay),
MDEF_HANDLER("Custom boot logo", config_customlogo), MDEF_HANDLER("Custom boot logo", config_customlogo),
MDEF_HANDLER("Backlight", config_backlight),
MDEF_END() MDEF_END()
}; };
@ -3146,7 +3144,7 @@ menu_t menu_tools = {
ment_t ment_top[] = { ment_t ment_top[] = {
MDEF_HANDLER("Launch", launch_firmware), MDEF_HANDLER("Launch", launch_firmware),
MDEF_MENU("Launch options", &menu_options), MDEF_MENU("Options", &menu_options),
MDEF_CAPTION("---------------", 0xFF444444), MDEF_CAPTION("---------------", 0xFF444444),
MDEF_MENU("Tools", &menu_tools), MDEF_MENU("Tools", &menu_tools),
MDEF_MENU("Console info", &menu_cinfo), MDEF_MENU("Console info", &menu_cinfo),
@ -3198,8 +3196,8 @@ void ipl_main()
gfx_con_init(&gfx_con, &gfx_ctxt); gfx_con_init(&gfx_con, &gfx_ctxt);
// Enable backlight after initializing gfx display_backlight_pwm_init();
//display_backlight(true); //display_backlight_brightness(h_cfg.backlight, 1000);
// Load saved configuration and auto boot if enabled. // Load saved configuration and auto boot if enabled.
auto_launch_firmware(); auto_launch_firmware();

View file

@ -49,6 +49,8 @@ static clock_t _clock_kfuse = { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTRO
static clock_t _clock_cl_dvfs = { CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_RST_CONTROLLER_RST_SOURCE, 0x1B, 0, 0 }; static clock_t _clock_cl_dvfs = { CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_RST_CONTROLLER_RST_SOURCE, 0x1B, 0, 0 };
static clock_t _clock_coresight = { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, 9, 0, 4}; static clock_t _clock_coresight = { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, 9, 0, 4};
static clock_t _clock_pwm = { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 0x11, 6, 4};
void clock_enable(const clock_t *clk) void clock_enable(const clock_t *clk)
{ {
// Put clock into reset. // Put clock into reset.
@ -188,6 +190,16 @@ void clock_disable_coresight()
clock_disable(&_clock_coresight); clock_disable(&_clock_coresight);
} }
void clock_enable_pwm()
{
clock_enable(&_clock_pwm);
}
void clock_disable_pwm()
{
clock_disable(&_clock_pwm);
}
#define L_SWR_SDMMC1_RST (1 << 14) #define L_SWR_SDMMC1_RST (1 << 14)
#define L_SWR_SDMMC2_RST (1 << 9) #define L_SWR_SDMMC2_RST (1 << 9)
#define L_SWR_SDMMC4_RST (1 << 15) #define L_SWR_SDMMC4_RST (1 << 15)

View file

@ -47,6 +47,7 @@
#define CLK_RST_CONTROLLER_PLLE_MISC 0xEC #define CLK_RST_CONTROLLER_PLLE_MISC 0xEC
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8 #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB 0xFC #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB 0xFC
#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM 0x110
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124 #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128 #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128
#define CLK_RST_CONTROLLER_CLK_SOURCE_VI 0x148 #define CLK_RST_CONTROLLER_CLK_SOURCE_VI 0x148
@ -153,6 +154,8 @@ void clock_enable_cl_dvfs();
void clock_disable_cl_dvfs(); void clock_disable_cl_dvfs();
void clock_enable_coresight(); void clock_enable_coresight();
void clock_disable_coresight(); void clock_disable_coresight();
void clock_enable_pwm();
void clock_disable_pwm();
void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val); void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val);
void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type); void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type);
int clock_sdmmc_is_not_reset_and_enabled(u32 id); int clock_sdmmc_is_not_reset_and_enabled(u32 id);

View file

@ -86,6 +86,7 @@
#define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off) #define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off)
#define APB_MISC(off) _REG(APB_MISC_BASE, off) #define APB_MISC(off) _REG(APB_MISC_BASE, off)
#define PINMUX_AUX(off) _REG(PINMUX_AUX_BASE, off) #define PINMUX_AUX(off) _REG(PINMUX_AUX_BASE, off)
#define PWM(off) _REG(PWM_BASE, off)
#define RTC(off) _REG(RTC_BASE, off) #define RTC(off) _REG(RTC_BASE, off)
#define PMC(off) _REG(PMC_BASE, off) #define PMC(off) _REG(PMC_BASE, off)
#define SYSCTR0(off) _REG(SYSCTR0_BASE, off) #define SYSCTR0(off) _REG(SYSCTR0_BASE, off)
@ -101,6 +102,7 @@
/*! Misc registers. */ /*! Misc registers. */
#define APB_MISC_PP_PINMUX_GLOBAL 0x40 #define APB_MISC_PP_PINMUX_GLOBAL 0x40
#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64 #define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68 #define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68