diff --git a/core/embed/io/display/backlight/backlight_pwm.h b/core/embed/io/backlight/inc/io/backlight.h similarity index 87% rename from core/embed/io/display/backlight/backlight_pwm.h rename to core/embed/io/backlight/inc/io/backlight.h index 49f7c808c0e..c62d7fc7296 100644 --- a/core/embed/io/display/backlight/backlight_pwm.h +++ b/core/embed/io/backlight/inc/io/backlight.h @@ -17,8 +17,7 @@ * along with this program. If not, see . */ -#ifndef TREZORHAL_BACKLIGHT_H -#define TREZORHAL_BACKLIGHT_H +#pragma once // Action to be taken when initializing or // deinitializing the backlight driver @@ -32,7 +31,7 @@ typedef enum { // If the action is set to `BACKLIGHT_RESET`, the backlight level // is set to zero level. If the action is set to `BACKLIGHT_RETAIN`, // the backlight level is not changed (if possible). -void backlight_pwm_init(backlight_action_t action); +void backlight_init(backlight_action_t action); // Deinitialize the backlight driver // @@ -40,18 +39,16 @@ void backlight_pwm_init(backlight_action_t action); // is completely deinitialized. If the action is set to `BACKLIGHT_RETAIN`, // the driver is deinitialized as much as possible but the backlight // is kept on. -void backlight_pwm_deinit(backlight_action_t action); +void backlight_deinit(backlight_action_t action); // Sets the backlight level in range 0-255 and returns the actual level set. // // If the level is outside the range, the function has no effect // and just returns the actual level set. If the backlight driver // is not initialized, the function returns 0. -int backlight_pwm_set(int val); +int backlight_set(int val); // Gets the backlight level in range 0-255 // // Returns 0 if the backlight driver is not initialized. -int backlight_pwm_get(void); - -#endif // TREZORHAL_BACKLIGHT_H +int backlight_get(void); diff --git a/core/embed/io/backlight/stm32/backlight_pin.c b/core/embed/io/backlight/stm32/backlight_pin.c new file mode 100644 index 00000000000..1006c75f943 --- /dev/null +++ b/core/embed/io/backlight/stm32/backlight_pin.c @@ -0,0 +1,103 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 . + */ + +#include + +#include +#include + +typedef struct { + // Set if driver is initialized + bool initialized; + // Current backlight level in range 0-255 + int current_level; + +} backlight_driver_t; + +static backlight_driver_t g_backlight_driver = { + .initialized = false, +}; + +static void backlight_on(void) { + GPIO_InitTypeDef GPIO_InitStructure = {0}; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Pin = BACKLIGHT_PIN_PIN; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(BACKLIGHT_PIN_PORT, &GPIO_InitStructure); +} + +static void backlight_off(void) { + GPIO_InitTypeDef GPIO_InitStructure = {0}; + GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Pin = BACKLIGHT_PIN_PIN; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(BACKLIGHT_PIN_PORT, &GPIO_InitStructure); +} + +void backlight_init(backlight_action_t action) { + backlight_driver_t *drv = &g_backlight_driver; + + if (drv->initialized) { + return; + } + + BACKLIGHT_PIN_CLK_ENABLE(); + + if (action == BACKLIGHT_RESET) { + backlight_off(); + }; + + drv->initialized = true; +} + +void backlight_deinit(backlight_action_t action) { + backlight_driver_t *drv = &g_backlight_driver; + if (!drv->initialized) { + return; + } + + if (action == BACKLIGHT_RESET) { + backlight_off(); + } +} + +int backlight_set(int val) { + backlight_driver_t *drv = &g_backlight_driver; + if (!drv->initialized) { + return 0; + } + + if (val > 0) { + backlight_on(); + } else { + backlight_off(); + } + drv->current_level = val; + return val; +} + +int backlight_get(void) { + backlight_driver_t *drv = &g_backlight_driver; + if (!drv->initialized) { + return 0; + } + return drv->current_level; +} diff --git a/core/embed/io/display/backlight/stm32/backlight_pwm.c b/core/embed/io/backlight/stm32/tps61043.c similarity index 67% rename from core/embed/io/display/backlight/stm32/backlight_pwm.c rename to core/embed/io/backlight/stm32/tps61043.c index e5cd4df0633..1748acf4ed5 100644 --- a/core/embed/io/display/backlight/stm32/backlight_pwm.c +++ b/core/embed/io/backlight/stm32/tps61043.c @@ -22,14 +22,14 @@ #include -#include "../backlight/backlight_pwm.h" +#include // Requested PWM Timer clock frequency [Hz] #define TIM_FREQ 10000000 // Prescaler divider for the PWM Timer #define LED_PWM_PRESCALER (SystemCoreClock / TIM_FREQ - 1) // Period of the PWM Timer -#define LED_PWM_TIM_PERIOD (TIM_FREQ / BACKLIGHT_PWM_FREQ) +#define LED_PWM_TIM_PERIOD (TIM_FREQ / TPS61043_FREQ) // Backlight driver state typedef struct { @@ -45,7 +45,7 @@ static backlight_driver_t g_backlight_driver = { .initialized = false, }; -void backlight_pwm_init(backlight_action_t action) { +void backlight_init(backlight_action_t action) { backlight_driver_t *drv = &g_backlight_driver; if (drv->initialized) { @@ -57,10 +57,10 @@ void backlight_pwm_init(backlight_action_t action) { int initial_level = 0; if (action == BACKLIGHT_RETAIN) { - // We expect the BACKLIGHT_PWM_TIM to be already initialized + // We expect the TPS61043_TIM to be already initialized // (e.g. by the bootloader or boardloader) - uint32_t prev_arr = BACKLIGHT_PWM_TIM->ARR; - uint32_t prev_ccr1 = BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR; + uint32_t prev_arr = TPS61043_TIM->ARR; + uint32_t prev_ccr1 = TPS61043_TIM->TPS61043_TIM_CCR; initial_level = (prev_ccr1 * 255) / (prev_arr + 1); if (initial_level > 255) { @@ -69,20 +69,20 @@ void backlight_pwm_init(backlight_action_t action) { } // Initialize PWM GPIO - BACKLIGHT_PWM_PORT_CLK_EN(); + TPS61043_PORT_CLK_EN(); GPIO_InitTypeDef GPIO_InitStructure = {0}; GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = BACKLIGHT_PWM_TIM_AF; - GPIO_InitStructure.Pin = BACKLIGHT_PWM_PIN; - HAL_GPIO_Init(BACKLIGHT_PWM_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Alternate = TPS61043_TIM_AF; + GPIO_InitStructure.Pin = TPS61043_PIN; + HAL_GPIO_Init(TPS61043_PORT, &GPIO_InitStructure); // Initialize PWM timer - BACKLIGHT_PWM_TIM_FORCE_RESET(); - BACKLIGHT_PWM_TIM_RELEASE_RESET(); - BACKLIGHT_PWM_TIM_CLK_EN(); + TPS61043_TIM_FORCE_RESET(); + TPS61043_TIM_RELEASE_RESET(); + TPS61043_TIM_CLK_EN(); uint32_t tmpcr1 = 0; @@ -97,57 +97,57 @@ void backlight_pwm_init(backlight_action_t action) { tmpcr1 |= TIM_AUTORELOAD_PRELOAD_DISABLE; #endif - BACKLIGHT_PWM_TIM->CR1 = tmpcr1; + TPS61043_TIM->CR1 = tmpcr1; // Set the Autoreload value - BACKLIGHT_PWM_TIM->ARR = (uint32_t)LED_PWM_TIM_PERIOD - 1; + TPS61043_TIM->ARR = (uint32_t)LED_PWM_TIM_PERIOD - 1; // Set the Prescaler value - BACKLIGHT_PWM_TIM->PSC = LED_PWM_PRESCALER; + TPS61043_TIM->PSC = LED_PWM_PRESCALER; // Set the Repetition Counter value - BACKLIGHT_PWM_TIM->RCR = 0; + TPS61043_TIM->RCR = 0; // Generate an update event to reload the Prescaler // and the repetition counter (only for advanced timer) value immediately - BACKLIGHT_PWM_TIM->EGR = TIM_EGR_UG; + TPS61043_TIM->EGR = TIM_EGR_UG; // Set the Preload enable bit for channel1 - BACKLIGHT_PWM_TIM->CCMR1 |= TIM_CCMR1_OC1PE; + TPS61043_TIM->CCMR1 |= TIM_CCMR1_OC1PE; // Configure the Output Fast mode - BACKLIGHT_PWM_TIM->CCMR1 &= ~TIM_CCMR1_OC1FE; - BACKLIGHT_PWM_TIM->CCMR1 |= TIM_OCFAST_DISABLE; + TPS61043_TIM->CCMR1 &= ~TIM_CCMR1_OC1FE; + TPS61043_TIM->CCMR1 |= TIM_OCFAST_DISABLE; uint32_t tmpccmrx; uint32_t tmpccer; uint32_t tmpcr2; // Get the TIMx CCER register value - tmpccer = BACKLIGHT_PWM_TIM->CCER; + tmpccer = TPS61043_TIM->CCER; // Disable the Channel 1: Reset the CC1E Bit - BACKLIGHT_PWM_TIM->CCER &= ~TIM_CCER_CC1E; + TPS61043_TIM->CCER &= ~TIM_CCER_CC1E; tmpccer |= TIM_CCER_CC1E; // Get the TIMx CR2 register value - tmpcr2 = BACKLIGHT_PWM_TIM->CR2; + tmpcr2 = TPS61043_TIM->CR2; // Get the TIMx CCMR1 register value - tmpccmrx = BACKLIGHT_PWM_TIM->CCMR1; + tmpccmrx = TPS61043_TIM->CCMR1; // Reset the Output Compare Mode Bits tmpccmrx &= ~TIM_CCMR1_OC1M; tmpccmrx &= ~TIM_CCMR1_CC1S; // Select the Output Compare Mode - tmpccmrx |= BACKLIGHT_PWM_TIM_OCMODE; + tmpccmrx |= TPS61043_TIM_OCMODE; // Reset the Output Polarity level tmpccer &= ~TIM_CCER_CC1P; // Set the Output Compare Polarity tmpccer |= TIM_OCPOLARITY_HIGH; - if (IS_TIM_CCXN_INSTANCE(BACKLIGHT_PWM_TIM, TIM_CHANNEL_1)) { + if (IS_TIM_CCXN_INSTANCE(TPS61043_TIM, TIM_CHANNEL_1)) { // Check parameters assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); @@ -159,7 +159,7 @@ void backlight_pwm_init(backlight_action_t action) { tmpccer |= TIM_CCER_CC1NE; } - if (IS_TIM_BREAK_INSTANCE(BACKLIGHT_PWM_TIM)) { + if (IS_TIM_BREAK_INSTANCE(TPS61043_TIM)) { // Check parameters assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); @@ -174,23 +174,23 @@ void backlight_pwm_init(backlight_action_t action) { } // Write to TIMx CR2 - BACKLIGHT_PWM_TIM->CR2 = tmpcr2; + TPS61043_TIM->CR2 = tmpcr2; // Write to TIMx CCMR1 - BACKLIGHT_PWM_TIM->CCMR1 = tmpccmrx; + TPS61043_TIM->CCMR1 = tmpccmrx; // Set the Capture Compare Register value - BACKLIGHT_PWM_TIM->CCR1 = 0; + TPS61043_TIM->CCR1 = 0; // Write to TIMx CCER - BACKLIGHT_PWM_TIM->CCER = tmpccer; + TPS61043_TIM->CCER = tmpccer; - BACKLIGHT_PWM_TIM->BDTR |= TIM_BDTR_MOE; - BACKLIGHT_PWM_TIM->CR1 |= TIM_CR1_CEN; + TPS61043_TIM->BDTR |= TIM_BDTR_MOE; + TPS61043_TIM->CR1 |= TIM_CR1_CEN; drv->initialized = true; - backlight_pwm_set(initial_level); + backlight_set(initial_level); } -void backlight_pwm_deinit(backlight_action_t action) { +void backlight_deinit(backlight_action_t action) { backlight_driver_t *drv = &g_backlight_driver; if (!drv->initialized) { @@ -207,15 +207,15 @@ void backlight_pwm_deinit(backlight_action_t action) { #define LED_PWM_SLOW_TIM_PERIOD (10000) #define LED_PWM_PRESCALER_SLOW (SystemCoreClock / 1000000 - 1) // 1 MHz - BACKLIGHT_PWM_TIM->PSC = LED_PWM_PRESCALER_SLOW; - BACKLIGHT_PWM_TIM->CR1 |= TIM_CR1_ARPE; - BACKLIGHT_PWM_TIM->CR2 |= TIM_CR2_CCPC; - BACKLIGHT_PWM_TIM->ARR = LED_PWM_SLOW_TIM_PERIOD - 1; + TPS61043_TIM->PSC = LED_PWM_PRESCALER_SLOW; + TPS61043_TIM->CR1 |= TIM_CR1_ARPE; + TPS61043_TIM->CR2 |= TIM_CR2_CCPC; + TPS61043_TIM->ARR = LED_PWM_SLOW_TIM_PERIOD - 1; if (action == BACKLIGHT_RESET) { - BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; + TPS61043_TIM->TPS61043_TIM_CCR = 0; } else { // action == BACKLIGHT_RETAIN - BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = + TPS61043_TIM->TPS61043_TIM_CCR = (LED_PWM_SLOW_TIM_PERIOD * drv->current_level) / 255; } @@ -226,16 +226,16 @@ void backlight_pwm_deinit(backlight_action_t action) { GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = BACKLIGHT_PWM_PIN; - HAL_GPIO_Init(BACKLIGHT_PWM_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = TPS61043_PIN; + HAL_GPIO_Init(TPS61043_PORT, &GPIO_InitStructure); // Deinitialize PWM timer - BACKLIGHT_PWM_TIM_FORCE_RESET(); - BACKLIGHT_PWM_TIM_RELEASE_RESET(); - BACKLIGHT_PWM_TIM_CLK_DIS(); + TPS61043_TIM_FORCE_RESET(); + TPS61043_TIM_RELEASE_RESET(); + TPS61043_TIM_CLK_DIS(); } else { // action == BACKLIGHT_RETAIN - BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = + TPS61043_TIM->TPS61043_TIM_CCR = (LED_PWM_TIM_PERIOD * drv->current_level) / 255; } #endif @@ -244,28 +244,28 @@ void backlight_pwm_deinit(backlight_action_t action) { } // Generate a pulse on the backlight control pin to wake up the TPS61043 -static void backlight_pwm_wakeup_pulse(void) { +static void backlight_wakeup_pulse(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; - HAL_GPIO_WritePin(BACKLIGHT_PWM_PORT, BACKLIGHT_PWM_PIN, GPIO_PIN_SET); + HAL_GPIO_WritePin(TPS61043_PORT, TPS61043_PIN, GPIO_PIN_SET); GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Pin = BACKLIGHT_PWM_PIN; - HAL_GPIO_Init(BACKLIGHT_PWM_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = TPS61043_PIN; + HAL_GPIO_Init(TPS61043_PORT, &GPIO_InitStructure); hal_delay_us(500); GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = BACKLIGHT_PWM_TIM_AF; - GPIO_InitStructure.Pin = BACKLIGHT_PWM_PIN; - HAL_GPIO_Init(BACKLIGHT_PWM_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Alternate = TPS61043_TIM_AF; + GPIO_InitStructure.Pin = TPS61043_PIN; + HAL_GPIO_Init(TPS61043_PORT, &GPIO_InitStructure); } -int backlight_pwm_set(int level) { +int backlight_set(int level) { backlight_driver_t *drv = &g_backlight_driver; if (!drv->initialized) { @@ -276,11 +276,11 @@ int backlight_pwm_set(int level) { // TPS61043 goes to shutdown when duty cycle is 0 (after 32ms), // so we need to set GPIO to high for at least 500us // to wake it up. - if (BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR == 0 && level != 0) { - backlight_pwm_wakeup_pulse(); + if (TPS61043_TIM->TPS61043_TIM_CCR == 0 && level != 0) { + backlight_wakeup_pulse(); } - BACKLIGHT_PWM_TIM->CCR1 = (LED_PWM_TIM_PERIOD * level) / 255; + TPS61043_TIM->CCR1 = (LED_PWM_TIM_PERIOD * level) / 255; drv->current_level = level; } @@ -288,7 +288,7 @@ int backlight_pwm_set(int level) { return drv->current_level; } -int backlight_pwm_get(void) { +int backlight_get(void) { backlight_driver_t *drv = &g_backlight_driver; if (!drv->initialized) { diff --git a/core/embed/io/backlight/stm32u5/tps61062.c b/core/embed/io/backlight/stm32u5/tps61062.c new file mode 100644 index 00000000000..43c2af36b2b --- /dev/null +++ b/core/embed/io/backlight/stm32u5/tps61062.c @@ -0,0 +1,271 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 . + */ + +#ifdef KERNEL_MODE + +#include +#include +#include +#include + +#include + +#define BACKLIGHT_CONTROL_T_UP_US 30 // may be in range 1-75 +#define BACKLIGHT_CONTROL_T_DOWN_US 198 // may be in range 180-300 + +// unused - for reference +// #define BACKLIGHT_CONTROL_T_START_US 110 // may be in range 100-150 +// #define BACKLIGHT_CONTROL_T_D_US 2 +// #define BACKLIGHT_CONTROL_T_OFF_US 550 + +#define TIMER_PERIOD 32000 // 5 kHz @ 160MHz +#define MAX_PULSE_WIDTH_US 200 // 5kHz + +#define TIM_PULSE(width) \ + (TIMER_PERIOD - (width) * TIMER_PERIOD / MAX_PULSE_WIDTH_US) + +#define MAX_STEPS 32 +#define DEFAULT_STEP 16 // DAC value after reset + +// Backlight driver state +typedef struct { + // Set if driver is initialized + bool initialized; + // Level requested (0-255) + int current_level; + // Current step in range 0-32 + int current_step; + + DMA_HandleTypeDef dma; + TIM_HandleTypeDef tim; + + uint32_t pwm_data[MAX_STEPS + 2]; // max steps + 2 for start and end + +} backlight_driver_t; + +static backlight_driver_t g_backlight_driver = { + .initialized = false, +}; + +static void backlight_control_up(uint32_t *data, int steps); +static void backlight_control_down(uint32_t *data, int steps); +static void backlight_shutdown(); + +void backlight_init(backlight_action_t action) { + backlight_driver_t *drv = &g_backlight_driver; + + if (drv->initialized) { + return; + } + + memset(drv, 0, sizeof(backlight_driver_t)); + + TPS61062_ILED_CLK_ENA(); + TPS61062_EN_CLK_ENA(); + + // action = BACKLIGHT_RESET. + // action = BACKLIGHT_RETAIN is not implemented + + // Initialize EN GPIO + GPIO_InitTypeDef GPIO_EN_InitStructure = {0}; + GPIO_EN_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_EN_InitStructure.Pull = GPIO_NOPULL; + GPIO_EN_InitStructure.Speed = GPIO_SPEED_LOW; + GPIO_EN_InitStructure.Pin = TPS61062_EN_PIN; + HAL_GPIO_Init(TPS61062_EN_PORT, &GPIO_EN_InitStructure); + + HAL_GPIO_WritePin(TPS61062_EN_PORT, TPS61062_EN_PIN, GPIO_PIN_RESET); + + __HAL_RCC_TIM3_CLK_ENABLE(); + __HAL_RCC_TIM3_FORCE_RESET(); + __HAL_RCC_TIM3_RELEASE_RESET(); + drv->tim.State = HAL_TIM_STATE_RESET; + drv->tim.Instance = TIM3; + drv->tim.Init.Period = TIMER_PERIOD; + drv->tim.Init.Prescaler = 0; + drv->tim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + drv->tim.Init.CounterMode = TIM_COUNTERMODE_UP; + drv->tim.Init.RepetitionCounter = 0; + HAL_TIM_PWM_Init(&drv->tim); + + TIM_OC_InitTypeDef TIM_OC_InitStructure = {0}; + TIM_OC_InitStructure.Pulse = 0; + TIM_OC_InitStructure.OCMode = TIM_OCMODE_PWM1; + TIM_OC_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH; + TIM_OC_InitStructure.OCFastMode = TIM_OCFAST_DISABLE; + TIM_OC_InitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH; + TIM_OC_InitStructure.OCIdleState = TIM_OCIDLESTATE_RESET; + TIM_OC_InitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET; + HAL_TIM_PWM_ConfigChannel(&drv->tim, &TIM_OC_InitStructure, TIM_CHANNEL_1); + + // Initialize ILED GPIO + GPIO_InitTypeDef GPIO_ILED_InitStructure = {0}; + GPIO_ILED_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_ILED_InitStructure.Pull = GPIO_NOPULL; + GPIO_ILED_InitStructure.Speed = GPIO_SPEED_LOW; + GPIO_ILED_InitStructure.Pin = TPS61062_ILED_PIN; + GPIO_ILED_InitStructure.Alternate = GPIO_AF2_TIM3; + HAL_GPIO_Init(TPS61062_ILED_PORT, &GPIO_ILED_InitStructure); + + __HAL_RCC_GPDMA1_CLK_ENABLE(); + drv->dma.Instance = GPDMA1_Channel3; + drv->dma.Init.Direction = DMA_MEMORY_TO_PERIPH; + drv->dma.Init.Mode = DMA_NORMAL; + drv->dma.Init.Request = GPDMA1_REQUEST_TIM3_UP; + drv->dma.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST; + drv->dma.Init.SrcInc = DMA_SINC_INCREMENTED; + drv->dma.Init.DestInc = DMA_DINC_FIXED; + drv->dma.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD; + drv->dma.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD; + drv->dma.Init.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT; + drv->dma.Init.SrcBurstLength = 1; + drv->dma.Init.DestBurstLength = 1; + drv->dma.Init.TransferAllocatedPort = + DMA_SRC_ALLOCATED_PORT1 | DMA_DEST_ALLOCATED_PORT0; + drv->dma.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER; + + HAL_DMA_Init(&drv->dma); + HAL_DMA_ConfigChannelAttributes( + &drv->dma, DMA_CHANNEL_PRIV | DMA_CHANNEL_SEC | DMA_CHANNEL_SRC_SEC | + DMA_CHANNEL_DEST_SEC); + + __HAL_TIM_ENABLE_DMA(&drv->tim, TIM_DMA_UPDATE); + + HAL_TIM_Base_Start(&drv->tim); + HAL_TIM_PWM_Start(&drv->tim, TIM_CHANNEL_1); + + drv->initialized = true; +} + +void backlight_deinit(backlight_action_t action) { + backlight_driver_t *drv = &g_backlight_driver; + + if (!drv->initialized) { + return; + } + + if (HAL_DMA_GetState(&drv->dma) == HAL_DMA_STATE_BUSY) { + while (HAL_DMA_PollForTransfer(&drv->dma, HAL_DMA_FULL_TRANSFER, + HAL_MAX_DELAY) != HAL_OK) { + } + } + + if (action == BACKLIGHT_RESET) { + backlight_shutdown(); + HAL_GPIO_DeInit(TPS61062_ILED_PORT, TPS61062_ILED_PIN); + HAL_GPIO_DeInit(TPS61062_EN_PORT, TPS61062_EN_PIN); + + __HAL_RCC_TIM3_FORCE_RESET(); + __HAL_RCC_TIM3_RELEASE_RESET(); + __HAL_RCC_TIM3_CLK_DISABLE(); + } + + drv->initialized = false; +} + +int backlight_set(int val) { + backlight_driver_t *drv = &g_backlight_driver; + + if (!drv->initialized) { + return 0; + } + + if (val < 0 || val > 255) { + return drv->current_level; + } + + if (val == drv->current_level) { + return val; + } + + drv->current_level = val; + int set_step = MAX_STEPS * val / 255; + + if (set_step == 0) { + backlight_shutdown(); + drv->current_step = 0; + return drv->current_level; + } + + if (HAL_DMA_GetState(&drv->dma) == HAL_DMA_STATE_BUSY) { + while (HAL_DMA_PollForTransfer(&drv->dma, HAL_DMA_FULL_TRANSFER, + HAL_MAX_DELAY) != HAL_OK) { + } + } + + int pwm_data_idx = 0; + memset(drv->pwm_data, 0, sizeof(drv->pwm_data)); + + if (drv->current_step == 0) { + HAL_GPIO_WritePin(TPS61062_EN_PORT, TPS61062_EN_PIN, GPIO_PIN_SET); + // if brightness control is shutdown, start with initial pulse + drv->pwm_data[0] = TIMER_PERIOD; + pwm_data_idx++; + drv->current_step = DEFAULT_STEP; + } + + if (set_step > drv->current_step) { + int steps = set_step - drv->current_step; + backlight_control_up(&drv->pwm_data[pwm_data_idx], steps); + pwm_data_idx += steps; + + } else if (set_step < drv->current_step) { + int steps = drv->current_step - set_step; + backlight_control_down(&drv->pwm_data[pwm_data_idx], steps); + pwm_data_idx += steps; + } + + drv->pwm_data[pwm_data_idx] = TIMER_PERIOD; + + HAL_DMA_Start(&drv->dma, (uint32_t)drv->pwm_data, + (uint32_t)&drv->tim.Instance->CCR1, + (pwm_data_idx + 1) * sizeof(uint32_t)); + + drv->current_step = set_step; + + return drv->current_level; +} + +int backlight_get(void) { + backlight_driver_t *drv = &g_backlight_driver; + + if (!drv->initialized) { + return 0; + } + + 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); + } +} + +static void backlight_control_down(uint32_t *data, int steps) { + for (int i = 0; i < steps; i++) { + data[i] = TIM_PULSE(BACKLIGHT_CONTROL_T_DOWN_US); + } +} + +static void backlight_shutdown() { + HAL_GPIO_WritePin(TPS61062_EN_PORT, TPS61062_EN_PIN, GPIO_PIN_RESET); +} + +#endif diff --git a/core/embed/io/display/inc/io/display.h b/core/embed/io/display/inc/io/display.h index be0e474fc4e..4853980c0df 100644 --- a/core/embed/io/display/inc/io/display.h +++ b/core/embed/io/display/inc/io/display.h @@ -44,8 +44,6 @@ // MIPI - // - STM32U5A9J-DK Discovery Board -#ifdef KERNEL_MODE - // Specifies how display content should be handled during // initialization or deinitialization. typedef enum { @@ -55,6 +53,8 @@ typedef enum { DISPLAY_RETAIN_CONTENT } display_content_mode_t; +#ifdef KERNEL_MODE + // Initializes the display controller. // // If `mode` is `DISPLAY_RETAIN_CONTENT`, ensure the driver was previously diff --git a/core/embed/io/display/ltdc_dsi/display_driver.c b/core/embed/io/display/ltdc_dsi/display_driver.c index c7cfdf8784f..b07dea958c9 100644 --- a/core/embed/io/display/ltdc_dsi/display_driver.c +++ b/core/embed/io/display/ltdc_dsi/display_driver.c @@ -30,7 +30,7 @@ #include #ifdef USE_BACKLIGHT -#include "../backlight/backlight_pwm.h" +#include #endif #include "display_internal.h" @@ -356,18 +356,8 @@ bool display_init(display_content_mode_t mode) { systick_delay_ms(120); #endif -#ifdef DISPLAY_BACKLIGHT_PIN - DISPLAY_BACKLIGHT_CLK_ENABLE(); - /* Configure LCD Backlight Pin */ - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Pin = DISPLAY_BACKLIGHT_PIN; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(DISPLAY_BACKLIGHT_PORT, &GPIO_InitStructure); -#endif - #ifdef USE_BACKLIGHT - backlight_pwm_init(BACKLIGHT_RESET); + backlight_init(BACKLIGHT_RESET); #endif uint32_t fb_addr = display_fb_init(); @@ -430,16 +420,16 @@ void display_deinit(display_content_mode_t mode) { NVIC_DisableIRQ(LTDC_IRQn); NVIC_DisableIRQ(LTDC_ER_IRQn); -#ifdef DISPLAY_BACKLIGHT_PIN +#ifdef BACKLIGHT_PIN_PIN GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_LOW; - GPIO_InitStructure.Pin = DISPLAY_BACKLIGHT_PIN; - HAL_GPIO_Init(DISPLAY_BACKLIGHT_PORT, &GPIO_InitStructure); + GPIO_InitStructure.Pin = BACKLIGHT_PIN_PIN; + HAL_GPIO_Init(BACKLIGHT_PIN_PORT, &GPIO_InitStructure); #endif #ifdef USE_BACKLIGHT - backlight_pwm_deinit(BACKLIGHT_RESET); + backlight_deinit(BACKLIGHT_RESET); #endif display_dsi_deinit(drv); @@ -478,11 +468,11 @@ int display_set_backlight(int level) { } #ifdef USE_BACKLIGHT - if (level > backlight_pwm_get()) { + if (level > backlight_get()) { display_ensure_refreshed(); } - return backlight_pwm_set(level); + return backlight_set(level); #else // Just emulation, not doing anything drv->backlight_level = level; @@ -497,7 +487,7 @@ int display_get_backlight(void) { return 0; } #ifdef USE_BACKLIGHT - return backlight_pwm_get(); + return backlight_get(); #else return drv->backlight_level; #endif diff --git a/core/embed/io/display/st-7789/display_driver.c b/core/embed/io/display/st-7789/display_driver.c index 2c74c66c641..b6777f5bc97 100644 --- a/core/embed/io/display/st-7789/display_driver.c +++ b/core/embed/io/display/st-7789/display_driver.c @@ -27,7 +27,7 @@ #include "display_io.h" #include "display_panel.h" -#include "../backlight/backlight_pwm.h" +#include #ifndef BOARDLOADER #include "../bg_copy/bg_copy.h" @@ -71,7 +71,7 @@ bool display_init(display_content_mode_t mode) { display_io_init_fmc(); display_panel_init(); display_panel_set_little_endian(); - backlight_pwm_init(BACKLIGHT_RESET); + backlight_init(BACKLIGHT_RESET); } else { // Reinitialize FMC to set correct timing // We have to do this in reinit because boardloader is fixed. @@ -80,7 +80,7 @@ bool display_init(display_content_mode_t mode) { // Important for model T as this is not set in boardloader display_panel_set_little_endian(); display_panel_reinit(); - backlight_pwm_init(BACKLIGHT_RETAIN); + backlight_init(BACKLIGHT_RETAIN); } #ifdef FRAMEBUFFER @@ -116,8 +116,8 @@ void display_deinit(display_content_mode_t mode) { mpu_set_active_fb(NULL, 0); - backlight_pwm_deinit(mode == DISPLAY_RESET_CONTENT ? BACKLIGHT_RESET - : BACKLIGHT_RETAIN); + backlight_deinit(mode == DISPLAY_RESET_CONTENT ? BACKLIGHT_RESET + : BACKLIGHT_RETAIN); #ifdef TREZOR_MODEL_T2T1 // This ensures backward compatibility with legacy bootloader/firmware @@ -140,15 +140,15 @@ int display_set_backlight(int level) { #ifndef BOARDLOADER // if turning on the backlight, wait until the panel is refreshed - if (backlight_pwm_get() < level && !is_mode_exception()) { + if (backlight_get() < level && !is_mode_exception()) { display_ensure_refreshed(); } #endif - return backlight_pwm_set(level); + return backlight_set(level); } -int display_get_backlight(void) { return backlight_pwm_get(); } +int display_get_backlight(void) { return backlight_get(); } int display_set_orientation(int angle) { display_driver_t* drv = &g_display_driver; diff --git a/core/embed/models/D002/boards/stm32u5g9j-dk.h b/core/embed/models/D002/boards/stm32u5g9j-dk.h index 32ee4cb03d2..3d5857db100 100644 --- a/core/embed/models/D002/boards/stm32u5g9j-dk.h +++ b/core/embed/models/D002/boards/stm32u5g9j-dk.h @@ -9,9 +9,10 @@ #define DISPLAY_RESET_PIN GPIO_PIN_5 #define DISPLAY_RESET_PORT GPIOD #define DISPLAY_RESET_CLK_ENA __HAL_RCC_GPIOD_CLK_ENABLE -#define DISPLAY_BACKLIGHT_PIN GPIO_PIN_6 -#define DISPLAY_BACKLIGHT_PORT GPIOI -#define DISPLAY_BACKLIGHT_CLK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() + +#define BACKLIGHT_PIN_PIN GPIO_PIN_6 +#define BACKLIGHT_PIN_PORT GPIOI +#define BACKLIGHT_PIN_CLK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() #define I2C_COUNT 1 #define I2C_INSTANCE_0 I2C5 diff --git a/core/embed/models/T2T1/boards/trezor_t.h b/core/embed/models/T2T1/boards/trezor_t.h index fca04f62d5e..952a0ff6340 100644 --- a/core/embed/models/T2T1/boards/trezor_t.h +++ b/core/embed/models/T2T1/boards/trezor_t.h @@ -8,19 +8,19 @@ #define DISPLAY_TE_PIN GPIO_PIN_12 #define DISPLAY_I8080_8BIT_DW 1 -#define BACKLIGHT_PWM_FREQ 10000 -#define BACKLIGHT_PWM_TIM TIM1 -#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM1_CLK_ENABLE -#define BACKLIGHT_PWM_TIM_CLK_DIS __HAL_RCC_TIM1_CLK_DISABLE -#define BACKLIGHT_PWM_TIM_FORCE_RESET __HAL_RCC_TIM1_FORCE_RESET -#define BACKLIGHT_PWM_TIM_RELEASE_RESET __HAL_RCC_TIM1_RELEASE_RESET -#define BACKLIGHT_PWM_TIM_AF GPIO_AF1_TIM1 -#define BACKLIGHT_PWM_TIM_OCMODE TIM_OCMODE_PWM2 -#define BACKLIGHT_PWM_TIM_CHANNEL TIM_CHANNEL_1 -#define BACKLIGHT_PWM_TIM_CCR CCR1 -#define BACKLIGHT_PWM_PIN GPIO_PIN_7 -#define BACKLIGHT_PWM_PORT GPIOA -#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOA_CLK_ENABLE +#define TPS61043_FREQ 10000 +#define TPS61043_TIM TIM1 +#define TPS61043_TIM_CLK_EN __HAL_RCC_TIM1_CLK_ENABLE +#define TPS61043_TIM_CLK_DIS __HAL_RCC_TIM1_CLK_DISABLE +#define TPS61043_TIM_FORCE_RESET __HAL_RCC_TIM1_FORCE_RESET +#define TPS61043_TIM_RELEASE_RESET __HAL_RCC_TIM1_RELEASE_RESET +#define TPS61043_TIM_AF GPIO_AF1_TIM1 +#define TPS61043_TIM_OCMODE TIM_OCMODE_PWM2 +#define TPS61043_TIM_CHANNEL TIM_CHANNEL_1 +#define TPS61043_TIM_CCR CCR1 +#define TPS61043_PIN GPIO_PIN_7 +#define TPS61043_PORT GPIOA +#define TPS61043_PORT_CLK_EN __HAL_RCC_GPIOA_CLK_ENABLE #define I2C_COUNT 1 #define I2C_INSTANCE_0 I2C1 diff --git a/core/embed/models/T3T1/boards/trezor_t3t1_revE.h b/core/embed/models/T3T1/boards/trezor_t3t1_revE.h index fe191e079d8..eb5d894de07 100644 --- a/core/embed/models/T3T1/boards/trezor_t3t1_revE.h +++ b/core/embed/models/T3T1/boards/trezor_t3t1_revE.h @@ -15,19 +15,19 @@ #define DISPLAY_TE_INTERRUPT_GPIOSEL EXTI_GPIOD #define DISPLAY_TE_INTERRUPT_EXTI_LINE EXTI_LINE_12 -#define BACKLIGHT_PWM_FREQ 12500 -#define BACKLIGHT_PWM_TIM TIM17 -#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE -#define BACKLIGHT_PWM_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE -#define BACKLIGHT_PWM_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET -#define BACKLIGHT_PWM_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET -#define BACKLIGHT_PWM_TIM_AF GPIO_AF14_TIM17 -#define BACKLIGHT_PWM_TIM_OCMODE TIM_OCMODE_PWM1 -#define BACKLIGHT_PWM_TIM_CHANNEL TIM_CHANNEL_1 -#define BACKLIGHT_PWM_TIM_CCR CCR1 -#define BACKLIGHT_PWM_PIN GPIO_PIN_1 -#define BACKLIGHT_PWM_PORT GPIOE -#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOE_CLK_ENABLE +#define TPS61043_FREQ 12500 +#define TPS61043_TIM TIM17 +#define TPS61043_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE +#define TPS61043_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE +#define TPS61043_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET +#define TPS61043_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET +#define TPS61043_TIM_AF GPIO_AF14_TIM17 +#define TPS61043_TIM_OCMODE TIM_OCMODE_PWM1 +#define TPS61043_TIM_CHANNEL TIM_CHANNEL_1 +#define TPS61043_TIM_CCR CCR1 +#define TPS61043_PIN GPIO_PIN_1 +#define TPS61043_PORT GPIOE +#define TPS61043_PORT_CLK_EN __HAL_RCC_GPIOE_CLK_ENABLE #define I2C_COUNT 3 #define I2C_INSTANCE_0 I2C1 diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h index 302c0a7a95b..03201c74d48 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h @@ -23,19 +23,12 @@ #define DISPLAY_PWREN_PORT GPIOE #define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE -#define BACKLIGHT_PWM_FREQ 200 -#define BACKLIGHT_PWM_TIM TIM17 -#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE -#define BACKLIGHT_PWM_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE -#define BACKLIGHT_PWM_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET -#define BACKLIGHT_PWM_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET -#define BACKLIGHT_PWM_TIM_AF GPIO_AF14_TIM17 -#define BACKLIGHT_PWM_TIM_OCMODE TIM_OCMODE_PWM1 -#define BACKLIGHT_PWM_TIM_CHANNEL TIM_CHANNEL_1 -#define BACKLIGHT_PWM_TIM_CCR CCR1 -#define BACKLIGHT_PWM_PIN GPIO_PIN_9 -#define BACKLIGHT_PWM_PORT GPIOB -#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE +#define TPS61062_ILED_PIN GPIO_PIN_3 +#define TPS61062_ILED_PORT GPIOE +#define TPS61062_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE +#define TPS61062_EN_PIN GPIO_PIN_9 +#define TPS61062_EN_PORT GPIOB +#define TPS61062_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE #define NPM1300_I2C_INSTANCE 0 diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h index fe764385527..c305bbc9eb0 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h @@ -22,19 +22,12 @@ #define DISPLAY_PWREN_PORT GPIOE #define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE -#define BACKLIGHT_PWM_FREQ 200 -#define BACKLIGHT_PWM_TIM TIM17 -#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE -#define BACKLIGHT_PWM_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE -#define BACKLIGHT_PWM_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET -#define BACKLIGHT_PWM_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET -#define BACKLIGHT_PWM_TIM_AF GPIO_AF14_TIM17 -#define BACKLIGHT_PWM_TIM_OCMODE TIM_OCMODE_PWM1 -#define BACKLIGHT_PWM_TIM_CHANNEL TIM_CHANNEL_1 -#define BACKLIGHT_PWM_TIM_CCR CCR1 -#define BACKLIGHT_PWM_PIN GPIO_PIN_9 -#define BACKLIGHT_PWM_PORT GPIOB -#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE +#define TPS61062_ILED_PIN GPIO_PIN_3 +#define TPS61062_ILED_PORT GPIOE +#define TPS61062_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE +#define TPS61062_EN_PIN GPIO_PIN_9 +#define TPS61062_EN_PORT GPIOB +#define TPS61062_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE #define NPM1300_I2C_INSTANCE 0 diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h index 047b7ea02c5..8ce642c4128 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h @@ -23,19 +23,12 @@ #define DISPLAY_PWREN_PORT GPIOG #define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOG_CLK_ENABLE -#define BACKLIGHT_PWM_FREQ 200 -#define BACKLIGHT_PWM_TIM TIM17 -#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM17_CLK_ENABLE -#define BACKLIGHT_PWM_TIM_CLK_DIS __HAL_RCC_TIM17_CLK_DISABLE -#define BACKLIGHT_PWM_TIM_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET -#define BACKLIGHT_PWM_TIM_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET -#define BACKLIGHT_PWM_TIM_AF GPIO_AF14_TIM17 -#define BACKLIGHT_PWM_TIM_OCMODE TIM_OCMODE_PWM1 -#define BACKLIGHT_PWM_TIM_CHANNEL TIM_CHANNEL_1 -#define BACKLIGHT_PWM_TIM_CCR CCR1 -#define BACKLIGHT_PWM_PIN GPIO_PIN_9 -#define BACKLIGHT_PWM_PORT GPIOB -#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE +#define TPS61062_ILED_PIN GPIO_PIN_3 +#define TPS61062_ILED_PORT GPIOE +#define TPS61062_ILED_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE +#define TPS61062_EN_PIN GPIO_PIN_9 +#define TPS61062_EN_PORT GPIOB +#define TPS61062_EN_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE #define NPM1300_I2C_INSTANCE 0 diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c index 1a65b6796fb..5c865299408 100644 --- a/core/embed/projects/bootloader/main.c +++ b/core/embed/projects/bootloader/main.c @@ -377,6 +377,10 @@ void real_jump_to_firmware(void) { ui_screen_boot_stage_1(false); } + if (DISPLAY_JUMP_BEHAVIOR == DISPLAY_RESET_CONTENT) { + display_fade(display_get_backlight(), 0, 200); + } + drivers_deinit(); system_deinit(); diff --git a/core/embed/projects/firmware/main.c b/core/embed/projects/firmware/main.c index 39435894500..a91402fa5a8 100644 --- a/core/embed/projects/firmware/main.c +++ b/core/embed/projects/firmware/main.c @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#include #include #include "py/builtin.h" @@ -32,6 +33,7 @@ #include "ports/stm32/gccollect.h" #include "ports/stm32/pendsv.h" +#include #include #include #include @@ -49,7 +51,7 @@ int main(uint32_t cmd, void *arg) { system_exit(0); } - screen_boot_stage_2(); + screen_boot_stage_2(DISPLAY_JUMP_BEHAVIOR == DISPLAY_RESET_CONTENT); #ifdef USE_SECP256K1_ZKP ensure(sectrue * (zkp_context_init() == 0), NULL); diff --git a/core/embed/rust/rust_ui_common.h b/core/embed/rust/rust_ui_common.h index b3af726a141..c6a742d3e07 100644 --- a/core/embed/rust/rust_ui_common.h +++ b/core/embed/rust/rust_ui_common.h @@ -3,7 +3,7 @@ void display_rsod_rust(const char* title, const char* message, const char* footer); -void screen_boot_stage_2(void); +void screen_boot_stage_2(bool fade_in); void display_image(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen); void display_icon(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen, diff --git a/core/embed/rust/src/ui/api/common_c.rs b/core/embed/rust/src/ui/api/common_c.rs index 16c81443ce5..97d938294c6 100644 --- a/core/embed/rust/src/ui/api/common_c.rs +++ b/core/embed/rust/src/ui/api/common_c.rs @@ -29,6 +29,6 @@ extern "C" fn display_rsod_rust( } #[no_mangle] -extern "C" fn screen_boot_stage_2() { - ModelUI::screen_boot_stage_2(); +extern "C" fn screen_boot_stage_2(fade_in: bool) { + ModelUI::screen_boot_stage_2(fade_in); } diff --git a/core/embed/rust/src/ui/layout_bolt/mod.rs b/core/embed/rust/src/ui/layout_bolt/mod.rs index 64d5446320b..d2edf355406 100644 --- a/core/embed/rust/src/ui/layout_bolt/mod.rs +++ b/core/embed/rust/src/ui/layout_bolt/mod.rs @@ -68,8 +68,8 @@ impl CommonUI for UIBolt { show(&mut frame, false); } - fn screen_boot_stage_2() { + fn screen_boot_stage_2(fade_in: bool) { let mut frame = WelcomeScreen::new(false); - show(&mut frame, false); + show(&mut frame, fade_in); } } diff --git a/core/embed/rust/src/ui/layout_caesar/mod.rs b/core/embed/rust/src/ui/layout_caesar/mod.rs index 807ab172d8b..516764bbcdd 100644 --- a/core/embed/rust/src/ui/layout_caesar/mod.rs +++ b/core/embed/rust/src/ui/layout_caesar/mod.rs @@ -23,7 +23,7 @@ impl CommonUI for UICaesar { screens::screen_fatal_error(title, msg, footer); } - fn screen_boot_stage_2() { - screens::screen_boot_stage_2(); + fn screen_boot_stage_2(fade_in: bool) { + screens::screen_boot_stage_2(fade_in); } } diff --git a/core/embed/rust/src/ui/layout_caesar/screens.rs b/core/embed/rust/src/ui/layout_caesar/screens.rs index 70065304ba7..cbef8eafe3c 100644 --- a/core/embed/rust/src/ui/layout_caesar/screens.rs +++ b/core/embed/rust/src/ui/layout_caesar/screens.rs @@ -18,7 +18,7 @@ pub fn screen_fatal_error(title: &str, msg: &str, footer: &str) { display::refresh(); } -pub fn screen_boot_stage_2() { +pub fn screen_boot_stage_2(_fade_in: bool) { let mut frame = WelcomeScreen::new(false); frame.place(screen()); diff --git a/core/embed/rust/src/ui/layout_delizia/mod.rs b/core/embed/rust/src/ui/layout_delizia/mod.rs index 7541222d27a..f70f61437f8 100644 --- a/core/embed/rust/src/ui/layout_delizia/mod.rs +++ b/core/embed/rust/src/ui/layout_delizia/mod.rs @@ -65,7 +65,7 @@ impl CommonUI for UIDelizia { screens::screen_fatal_error(title, msg, footer); } - fn screen_boot_stage_2() { - screens::screen_boot_stage_2(); + fn screen_boot_stage_2(fade_in: bool) { + screens::screen_boot_stage_2(fade_in); } } diff --git a/core/embed/rust/src/ui/layout_delizia/screens.rs b/core/embed/rust/src/ui/layout_delizia/screens.rs index 86a62e6b2e7..3b194be83eb 100644 --- a/core/embed/rust/src/ui/layout_delizia/screens.rs +++ b/core/embed/rust/src/ui/layout_delizia/screens.rs @@ -18,7 +18,7 @@ pub fn screen_fatal_error(title: &str, msg: &str, footer: &str) { display::refresh(); } -pub fn screen_boot_stage_2() { +pub fn screen_boot_stage_2(_fade_in: bool) { let mut frame = WelcomeScreen::new(); frame.place(screen()); diff --git a/core/embed/rust/src/ui/ui_common.rs b/core/embed/rust/src/ui/ui_common.rs index 8bf6cf54806..e01fe817e3b 100644 --- a/core/embed/rust/src/ui/ui_common.rs +++ b/core/embed/rust/src/ui/ui_common.rs @@ -25,5 +25,5 @@ pub trait CommonUI { fn screen_fatal_error(title: &str, msg: &str, footer: &str); - fn screen_boot_stage_2(); + fn screen_boot_stage_2(fade_in: bool); } diff --git a/core/embed/sys/pvd/stm32/pvd.c b/core/embed/sys/pvd/stm32/pvd.c index bc6581a88e6..c66a6cc0b3c 100644 --- a/core/embed/sys/pvd/stm32/pvd.c +++ b/core/embed/sys/pvd/stm32/pvd.c @@ -24,6 +24,10 @@ #include #include +#ifdef USE_BACKLIGHT +#include +#endif + #if defined(KERNEL_MODE) && defined(USE_PVD) void pvd_init(void) { @@ -52,10 +56,11 @@ void PVD_PVM_IRQHandler(void) { void PVD_IRQHandler(void) { #endif mpu_reconfig(MPU_MODE_DEFAULT); -#ifdef BACKLIGHT_PWM_TIM - // Turn off display backlight - BACKLIGHT_PWM_TIM->BACKLIGHT_PWM_TIM_CCR = 0; + +#ifdef USE_BACKLIGHT + backlight_set(0); #endif + error_shutdown("PVD IRQ"); } diff --git a/core/site_scons/models/D002/discovery2.py b/core/site_scons/models/D002/discovery2.py index 51265b7e5d0..1a1bc8ea33a 100644 --- a/core/site_scons/models/D002/discovery2.py +++ b/core/site_scons/models/D002/discovery2.py @@ -48,6 +48,11 @@ def configure( ] paths += ["embed/io/display/inc"] + features_available.append("backlight") + defines += [("USE_BACKLIGHT", "1")] + sources += ["embed/io/backlight/stm32/backlight_pin.c"] + paths += ["embed/io/backlight/inc"] + if "input" in features_wanted: sources += ["embed/io/i2c_bus/stm32u5/i2c_bus.c"] sources += ["embed/io/touch/sitronix/sitronix.c"] diff --git a/core/site_scons/models/T2T1/trezor_t.py b/core/site_scons/models/T2T1/trezor_t.py index d64cb037553..901ecb0b44c 100644 --- a/core/site_scons/models/T2T1/trezor_t.py +++ b/core/site_scons/models/T2T1/trezor_t.py @@ -55,10 +55,10 @@ def configure( sources += ["embed/io/display/st-7789/panels/lx154a2422.c"] paths += ["embed/io/display/inc"] - sources += ["embed/io/display/backlight/stm32/backlight_pwm.c"] - features_available.append("backlight") defines += [("USE_BACKLIGHT", "1")] + sources += ["embed/io/backlight/stm32/tps61043.c"] + paths += ["embed/io/backlight/inc"] if "input" in features_wanted: sources += ["embed/io/i2c_bus/stm32f4/i2c_bus.c"] diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py index 709606b9e61..8fc439590e9 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py @@ -54,9 +54,10 @@ def configure( sources += ["embed/io/display/fb_queue/fb_queue.c"] paths += ["embed/io/display/inc"] - sources += ["embed/io/display/backlight/stm32/backlight_pwm.c"] features_available.append("backlight") defines += [("USE_BACKLIGHT", "1")] + sources += ["embed/io/backlight/stm32/tps61043.c"] + paths += ["embed/io/backlight/inc"] env_constraints = env.get("CONSTRAINTS") if not (env_constraints and "limited_util_s" in env_constraints): diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py index 7cdb2ce7e16..fdce74d8453 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py @@ -46,12 +46,13 @@ def configure( "embed/io/display/ltdc_dsi/display_fb_rgb888.c", "embed/io/display/ltdc_dsi/display_gfxmmu.c", "embed/io/display/fb_queue/fb_queue.c", - "embed/io/display/backlight/stm32/backlight_pwm.c", ] - paths += ["embed/io/display/inc"] + features_available.append("backlight") defines += [("USE_BACKLIGHT", "1")] + sources += ["embed/io/backlight/stm32u5/tps61062.c"] + paths += ["embed/io/backlight/inc"] if "input" in features_wanted: sources += ["embed/io/touch/ft6x36/ft6x36.c"] diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA0.py b/core/site_scons/models/T3W1/trezor_t3w1_revA0.py index 77c8e1fce9e..23c81d2af3d 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revA0.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revA0.py @@ -45,12 +45,13 @@ def configure( "embed/io/display/ltdc_dsi/display_fb.c", "embed/io/display/ltdc_dsi/display_fb_rgb565.c", "embed/io/display/fb_queue/fb_queue.c", - "embed/io/display/backlight/stm32/backlight_pwm.c", ] - paths += ["embed/io/display/inc"] + features_available.append("backlight") defines += [("USE_BACKLIGHT", "1")] + sources += ["embed/io/backlight/stm32u5/tps61062.c"] + paths += ["embed/io/backlight/inc"] if "input" in features_wanted: sources += ["embed/io/touch/ft6x36/ft6x36.c"] diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py index 4dffe290901..2a765279feb 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py @@ -46,12 +46,13 @@ def configure( "embed/io/display/ltdc_dsi/display_fb_rgb888.c", "embed/io/display/ltdc_dsi/display_gfxmmu.c", "embed/io/display/fb_queue/fb_queue.c", - "embed/io/display/backlight/stm32/backlight_pwm.c", ] - paths += ["embed/io/display/inc"] + features_available.append("backlight") defines += [("USE_BACKLIGHT", "1")] + sources += ["embed/io/backlight/stm32u5/tps61062.c"] + paths += ["embed/io/backlight/inc"] if "input" in features_wanted: sources += ["embed/io/touch/ft6x36/ft6x36.c"]