diff --git a/core/embed/io/backlight/inc/io/backlight.h b/core/embed/io/backlight/inc/io/backlight.h index c62d7fc729..42c7580eb7 100644 --- a/core/embed/io/backlight/inc/io/backlight.h +++ b/core/embed/io/backlight/inc/io/backlight.h @@ -19,6 +19,9 @@ #pragma once +#define BACKLIGHT_MAX_LEVEL 255 +#define BACKLIGHT_MIN_LEVEL 0 + // Action to be taken when initializing or // deinitializing the backlight driver typedef enum { @@ -41,7 +44,8 @@ void backlight_init(backlight_action_t action); // is kept on. void backlight_deinit(backlight_action_t action); -// Sets the backlight level in range 0-255 and returns the actual level set. +// Request the backlight level in range 0-255 and returns the actual level set. +// The requested level may be limited if its above the max_level limit. // // If the level is outside the range, the function has no effect // and just returns the actual level set. If the backlight driver @@ -52,3 +56,8 @@ int backlight_set(int val); // // Returns 0 if the backlight driver is not initialized. int backlight_get(void); + +// Set maximal backlight limit, limits the requested level to max_level value. +// +// Returns 0 if the backlight driver is not initialized. +int backlight_set_max_level(int max_level); diff --git a/core/embed/io/backlight/stm32u5/tps61062.c b/core/embed/io/backlight/stm32u5/tps61062.c index 43c2af36b2..0fd3ae26ae 100644 --- a/core/embed/io/backlight/stm32u5/tps61062.c +++ b/core/embed/io/backlight/stm32u5/tps61062.c @@ -47,11 +47,17 @@ typedef struct { // Set if driver is initialized bool initialized; + // Level requested (0-255) + int requested_level; int current_level; + // Current step in range 0-32 int current_step; + // Max backlight level + int max_level; + DMA_HandleTypeDef dma; TIM_HandleTypeDef tim; @@ -150,6 +156,10 @@ void backlight_init(backlight_action_t action) { HAL_TIM_Base_Start(&drv->tim); HAL_TIM_PWM_Start(&drv->tim, TIM_CHANNEL_1); + // Default no backlight max_level limit + drv->max_level = BACKLIGHT_MAX_LEVEL; + drv->requested_level = BACKLIGHT_MIN_LEVEL; + drv->initialized = true; } @@ -186,16 +196,28 @@ int backlight_set(int val) { return 0; } - if (val < 0 || val > 255) { + // Requested level out of range + if (val < BACKLIGHT_MIN_LEVEL || val > BACKLIGHT_MAX_LEVEL) { return drv->current_level; } - if (val == drv->current_level) { - return val; + // Capture requested level. + drv->requested_level = val; + + int requested_level_limited = drv->requested_level; + if (drv->requested_level > drv->max_level) { + requested_level_limited = drv->max_level; } - drv->current_level = val; - int set_step = MAX_STEPS * val / 255; + // No action required + if (requested_level_limited == drv->current_level) { + return drv->current_level; + } + + // New backlight level + drv->current_level = requested_level_limited; + + int set_step = MAX_STEPS * drv->current_level / BACKLIGHT_MAX_LEVEL; if (set_step == 0) { backlight_shutdown(); @@ -252,6 +274,28 @@ int backlight_get(void) { return drv->current_level; } +// Set maximal backlight level +int backlight_set_max_level(int max_level) { + backlight_driver_t *drv = &g_backlight_driver; + + if (!drv->initialized) { + return 0; + } + + if (max_level < BACKLIGHT_MIN_LEVEL) { + max_level = BACKLIGHT_MIN_LEVEL; + } + + if (max_level > BACKLIGHT_MAX_LEVEL) { + max_level = BACKLIGHT_MAX_LEVEL; + } + + drv->max_level = max_level; + backlight_set(drv->requested_level); + + return drv->current_level; +} + static void backlight_control_up(uint32_t *data, int steps) { for (int i = 0; i < steps; i++) { data[i] = TIM_PULSE(BACKLIGHT_CONTROL_T_UP_US);