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"]