From 67a470921a4d41074fe59d91a1441ccce08fb200 Mon Sep 17 00:00:00 2001 From: Kostas Missos Date: Wed, 19 Sep 2018 00:01:42 +0300 Subject: [PATCH] Add PWM backlight support + options - No eye blasting backlight - Option to choose the prefered brightness - Smooths transitions --- README.md | 7 ++-- bootloader/config/config.c | 72 ++++++++++++++++++++++++++++++++++++++ bootloader/config/config.h | 2 ++ bootloader/gfx/di.c | 44 +++++++++++++++++++++-- bootloader/gfx/di.h | 7 ++++ bootloader/gfx/tui.c | 4 +++ bootloader/main.c | 16 ++++----- bootloader/soc/clock.c | 12 +++++++ bootloader/soc/clock.h | 3 ++ bootloader/soc/t210.h | 2 ++ 10 files changed, 156 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 565a2de..abf0080 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,10 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti | Config option | Description | | ------------------ | ---------------------------------------------------------- | | 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. | | 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: @@ -49,7 +50,7 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti | kernel={SD path} | Replaces the kernel binary | | 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 | -| fullsvcperm=1 | Disables SVC verification | +| fullsvcperm=1 | Disables SVC verification (full services permission) | | debugmode=1 | Enables Debug mode | | atmosphere=1 | Enables Atmosphère patching | | 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) +If the main .ini is not found, it is created on the first hekate boot. + ``` hekate (C) 2018 naehrwert, st4rk diff --git a/bootloader/config/config.c b/bootloader/config/config.c index 32d9358..5234338 100644 --- a/bootloader/config/config.c +++ b/bootloader/config/config.c @@ -45,6 +45,7 @@ void set_default_configuration() h_cfg.verification = 2; h_cfg.se_keygen_done = 0; h_cfg.sbar_time_keeping = 0; + h_cfg.backlight = 100; } int create_config_entry() @@ -96,6 +97,9 @@ int create_config_entry() f_puts("\nverification=", &fp); itoa(h_cfg.verification, lbuf, 10); f_puts(lbuf, &fp); + f_puts("\nbacklight=", &fp); + itoa(h_cfg.backlight, lbuf, 10); + f_puts(lbuf, &fp); f_puts("\n", &fp); if (mainIniFound) @@ -562,3 +566,71 @@ void config_verification() return; 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(); +} diff --git a/bootloader/config/config.h b/bootloader/config/config.h index a50132a..0482f24 100644 --- a/bootloader/config/config.h +++ b/bootloader/config/config.h @@ -29,6 +29,7 @@ typedef struct _hekate_config // Global temporary config. int se_keygen_done; u32 sbar_time_keeping; + u32 backlight; } hekate_config; void set_default_configuration(); @@ -37,5 +38,6 @@ void config_autoboot(); void config_bootdelay(); void config_customlogo(); void config_verification(); +void config_backlight(); #endif /* _CONFIG_H_ */ diff --git a/bootloader/gfx/di.c b/bootloader/gfx/di.c index dd50cb1..8ff0293 100644 --- a/bootloader/gfx/di.c +++ b/bootloader/gfx/di.c @@ -137,14 +137,54 @@ void display_init() 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) { - 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() { - display_backlight(false); + display_backlight_brightness(0, 1000); DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1; DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; diff --git a/bootloader/gfx/di.h b/bootloader/gfx/di.h index 0e8b5e9..abd8197 100644 --- a/bootloader/gfx/di.h +++ b/bootloader/gfx/di.h @@ -161,6 +161,8 @@ #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 @@ -338,7 +340,11 @@ #define DSI_PAD_CONTROL_4 0x52 +/*! Display backlight related PWM registers. */ +#define PWM_CONTROLLER_PWM_CSR 0x00 + void display_init(); +void display_backlight_pwm_init(); void display_end(); /*! Show one single color on the display. */ @@ -346,6 +352,7 @@ void display_color_screen(u32 color); /*! Switches screen backlight ON/OFF. */ 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). */ u32 *display_init_framebuffer(); diff --git a/bootloader/gfx/tui.c b/bootloader/gfx/tui.c index 105d987..e12ac9d 100644 --- a/bootloader/gfx/tui.c +++ b/bootloader/gfx/tui.c @@ -20,6 +20,8 @@ #include "../config/config.h" #include "../power/max17050.h" #include "../utils/util.h" +#include "../config/config.h" +#include "di.h" #ifdef MENU_LOGO_ENABLE 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_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. u32 btn = btn_wait(); diff --git a/bootloader/main.c b/bootloader/main.c index b4183f3..60441a2 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -2209,7 +2209,6 @@ void auto_launch_firmware() }; struct _bmp_data bmpData; - bool backlightEnabled = false; bool bootlogoFound = false; char *bootlogoCustomEntry = NULL; @@ -2252,6 +2251,8 @@ void auto_launch_firmware() h_cfg.customlogo = atoi(kv->val); else if (!strcmp("verification", kv->key)) h_cfg.verification = atoi(kv->val); + else if (!strcmp("backlight", kv->key)) + h_cfg.backlight = atoi(kv->val); } boot_entry_id++; continue; @@ -2390,8 +2391,7 @@ void auto_launch_firmware() } free(BOOTLOGO); - display_backlight(true); - backlightEnabled = 1; + display_backlight_brightness(h_cfg.backlight, 1000); // Wait before booting. If VOL- is pressed go into bootloader menu. u32 btn = btn_wait_timeout(h_cfg.bootwait * 1000, BTN_VOL_DOWN); @@ -2432,9 +2432,6 @@ out: sd_unmount(); gfx_con.mute = false; - - if (!backlightEnabled) - display_backlight(true); } void toggle_autorcm(bool enable) @@ -3053,6 +3050,7 @@ ment_t ment_options[] = { MDEF_HANDLER("Auto boot", config_autoboot), MDEF_HANDLER("Boot time delay", config_bootdelay), MDEF_HANDLER("Custom boot logo", config_customlogo), + MDEF_HANDLER("Backlight", config_backlight), MDEF_END() }; @@ -3146,7 +3144,7 @@ menu_t menu_tools = { ment_t ment_top[] = { MDEF_HANDLER("Launch", launch_firmware), - MDEF_MENU("Launch options", &menu_options), + MDEF_MENU("Options", &menu_options), MDEF_CAPTION("---------------", 0xFF444444), MDEF_MENU("Tools", &menu_tools), MDEF_MENU("Console info", &menu_cinfo), @@ -3198,8 +3196,8 @@ void ipl_main() gfx_con_init(&gfx_con, &gfx_ctxt); - // Enable backlight after initializing gfx - //display_backlight(true); + display_backlight_pwm_init(); + //display_backlight_brightness(h_cfg.backlight, 1000); // Load saved configuration and auto boot if enabled. auto_launch_firmware(); diff --git a/bootloader/soc/clock.c b/bootloader/soc/clock.c index cb6133e..e745797 100644 --- a/bootloader/soc/clock.c +++ b/bootloader/soc/clock.c @@ -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_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) { // Put clock into reset. @@ -188,6 +190,16 @@ void clock_disable_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_SDMMC2_RST (1 << 9) #define L_SWR_SDMMC4_RST (1 << 15) diff --git a/bootloader/soc/clock.h b/bootloader/soc/clock.h index 45ef277..5b60329 100644 --- a/bootloader/soc/clock.h +++ b/bootloader/soc/clock.h @@ -47,6 +47,7 @@ #define CLK_RST_CONTROLLER_PLLE_MISC 0xEC #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8 #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_I2C5 0x128 #define CLK_RST_CONTROLLER_CLK_SOURCE_VI 0x148 @@ -153,6 +154,8 @@ void clock_enable_cl_dvfs(); void clock_disable_cl_dvfs(); void clock_enable_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_get_params(u32 *pout, u16 *pdivisor, u32 type); int clock_sdmmc_is_not_reset_and_enabled(u32 id); diff --git a/bootloader/soc/t210.h b/bootloader/soc/t210.h index a07d11b..39bf1b4 100644 --- a/bootloader/soc/t210.h +++ b/bootloader/soc/t210.h @@ -86,6 +86,7 @@ #define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off) #define APB_MISC(off) _REG(APB_MISC_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 PMC(off) _REG(PMC_BASE, off) #define SYSCTR0(off) _REG(SYSCTR0_BASE, off) @@ -101,6 +102,7 @@ /*! Misc registers. */ #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_RST_CFGPADCTRL 0xB68