From f9ff748a9024b04764edc0d061573528ea186a9d Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Fri, 29 Nov 2024 12:43:48 +0100 Subject: [PATCH 1/3] refactor(core): extract framebuffer queue for reuse [no changelog] --- core/embed/io/display/fb_queue/fb_queue.c | 129 ++++++++++++++++++ core/embed/io/display/fb_queue/fb_queue.h | 73 ++++++++++ core/embed/io/display/st-7789/display_fb.c | 89 ++++-------- .../io/display/st-7789/display_internal.h | 32 +---- .../models/T3T1/trezor_t3t1_revE.py | 1 + 5 files changed, 227 insertions(+), 97 deletions(-) create mode 100644 core/embed/io/display/fb_queue/fb_queue.c create mode 100644 core/embed/io/display/fb_queue/fb_queue.h diff --git a/core/embed/io/display/fb_queue/fb_queue.c b/core/embed/io/display/fb_queue/fb_queue.c new file mode 100644 index 0000000000..a65e67e459 --- /dev/null +++ b/core/embed/io/display/fb_queue/fb_queue.c @@ -0,0 +1,129 @@ +#ifdef KERNEL_MODE +#include "fb_queue.h" + +int16_t fb_queue_get_for_copy(volatile frame_buffer_queue_t *queue) { + if (queue->entry[queue->wix] != FB_STATE_PREPARING) { + // No refresh needed as the frame buffer is not in + // the state to be copied to the display + return -1; + } + + return queue->wix; +} + +int16_t fb_queue_get_for_write(volatile frame_buffer_queue_t *queue) { + frame_buffer_state_t state; + + // We have to wait if the buffer was passed for copying + // to the interrupt handler + do { + state = queue->entry[queue->wix]; + } while (state == FB_STATE_READY || state == FB_STATE_COPYING); + + queue->entry[queue->wix] = FB_STATE_PREPARING; + + return queue->wix; +} + +int16_t fb_queue_get_for_transfer(volatile frame_buffer_queue_t *queue) { + if (queue->rix >= FRAME_BUFFER_COUNT) { + // This is an invalid state, and we should never get here + return -1; + } + + switch (queue->entry[queue->rix]) { + case FB_STATE_EMPTY: + case FB_STATE_PREPARING: + // No new frame queued + + case FB_STATE_COPYING: + // Currently we are copying a data to the display. + return -1; + break; + + case FB_STATE_READY: + // Now it's proper time to copy the data to the display + queue->entry[queue->rix] = FB_STATE_COPYING; + return queue->rix; + + // NOTE: when copying is done, this queue slot is marked empty + break; + + default: + // This is an invalid state, and we should never get here + return -1; + break; + } +} + +bool fb_queue_set_done(volatile frame_buffer_queue_t *queue) { + if (queue->rix >= FRAME_BUFFER_COUNT) { + // This is an invalid state, and we should never get here + return false; + } + + if (queue->entry[queue->rix] == FB_STATE_COPYING) { + queue->entry[queue->rix] = FB_STATE_EMPTY; + queue->rix = (queue->rix + 1) % FRAME_BUFFER_COUNT; + return true; + } + + return false; +} + +bool fb_queue_set_switched(volatile frame_buffer_queue_t *queue) { + if (queue->rix >= FRAME_BUFFER_COUNT) { + // This is an invalid state, and we should never get here + return false; + } + + if (queue->entry[queue->rix] == FB_STATE_COPYING) { + if (queue->aix >= 0) { + queue->entry[queue->aix] = FB_STATE_EMPTY; + } + queue->aix = queue->rix; + queue->rix = (queue->rix + 1) % FRAME_BUFFER_COUNT; + return true; + } + + return false; +} + +bool fb_queue_set_ready_for_transfer(volatile frame_buffer_queue_t *queue) { + if (queue->wix >= FRAME_BUFFER_COUNT) { + // This is an invalid state, and we should never get here + return false; + } + + if (queue->entry[queue->rix] == FB_STATE_PREPARING) { + queue->entry[queue->rix] = FB_STATE_READY; + queue->wix = (queue->wix + 1) % FRAME_BUFFER_COUNT; + return true; + } + + return false; +} + +void fb_queue_reset(volatile frame_buffer_queue_t *queue) { + // Reset the buffer queue so we can eventually continue + // safely in thread mode + queue->wix = 0; + queue->rix = 0; + for (int i = 0; i < FRAME_BUFFER_COUNT; i++) { + queue->entry[i] = FB_STATE_EMPTY; + } +} + +bool fb_queue_is_processed(volatile frame_buffer_queue_t *queue) { + for (int i = 0; i < FRAME_BUFFER_COUNT; i++) { + frame_buffer_state_t state = queue->entry[i]; + if (state == FB_STATE_READY || + (state == FB_STATE_COPYING && i != queue->aix)) { + return false; + } + } + + return true; +} + +#endif diff --git a/core/embed/io/display/fb_queue/fb_queue.h b/core/embed/io/display/fb_queue/fb_queue.h new file mode 100644 index 0000000000..53240f50ee --- /dev/null +++ b/core/embed/io/display/fb_queue/fb_queue.h @@ -0,0 +1,73 @@ +/* + * 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 . + */ + +#pragma once + +#include + +// Number of frame buffers used (1 or 2) +// If 1 buffer is selected, some animations may not +// be so smooth but the memory usage is lower. +#define FRAME_BUFFER_COUNT 2 + +// Each frame buffer can be in one of the following states: +typedef enum { + // The frame buffer is empty and can be written to + FB_STATE_EMPTY = 0, + // The frame buffer pass passed to application + FB_STATE_PREPARING = 1, + // The frame buffer was written to and is ready + // to be copied to the display + FB_STATE_READY = 2, + // The frame buffer is currently being copied to + // the display + FB_STATE_COPYING = 3, + +} frame_buffer_state_t; + +typedef struct { + // Queue entries + volatile frame_buffer_state_t entry[FRAME_BUFFER_COUNT]; + // Active index + // (accessed & updated in the context of the interrupt handlers + int16_t aix; + // Read index + // (accessed & updated in the context of the interrupt handlers + uint8_t rix; + // Write index + // (accessed & updated in context of the main thread) + uint8_t wix; + +} frame_buffer_queue_t; + +int16_t fb_queue_get_for_copy(volatile frame_buffer_queue_t *queue); + +int16_t fb_queue_get_for_write(volatile frame_buffer_queue_t *queue); + +int16_t fb_queue_get_for_transfer(volatile frame_buffer_queue_t *queue); + +bool fb_queue_set_done(volatile frame_buffer_queue_t *queue); + +bool fb_queue_set_switched(volatile frame_buffer_queue_t *queue); + +bool fb_queue_set_ready_for_transfer(volatile frame_buffer_queue_t *queue); + +void fb_queue_reset(volatile frame_buffer_queue_t *queue); + +bool fb_queue_is_processed(volatile frame_buffer_queue_t *queue); diff --git a/core/embed/io/display/st-7789/display_fb.c b/core/embed/io/display/st-7789/display_fb.c index a286dc188f..3532785301 100644 --- a/core/embed/io/display/st-7789/display_fb.c +++ b/core/embed/io/display/st-7789/display_fb.c @@ -120,13 +120,7 @@ void display_physical_fb_clear(void) { static void bg_copy_callback(void) { display_driver_t *drv = &g_display_driver; - if (drv->queue.rix >= FRAME_BUFFER_COUNT) { - // This is an invalid state and we should never get here - return; - } - - drv->queue.entry[drv->queue.rix] = FB_STATE_EMPTY; - drv->queue.rix = (drv->queue.rix + 1) % FRAME_BUFFER_COUNT; + fb_queue_set_done(&drv->queue); } // Interrupt routing handling TE signal @@ -135,37 +129,13 @@ static void display_te_interrupt_handler(void) { __HAL_GPIO_EXTI_CLEAR_FLAG(DISPLAY_TE_PIN); - if (drv->queue.rix >= FRAME_BUFFER_COUNT) { - // This is an invalid state and we should never get here - return; - } + int16_t fb_idx = fb_queue_get_for_transfer(&drv->queue); - switch (drv->queue.entry[drv->queue.rix]) { - case FB_STATE_EMPTY: - case FB_STATE_PREPARING: - // No new frame queued - break; - - case FB_STATE_COPYING: - // Currently we are copying a data to the display. - // We need to wait for the next TE interrupt. - break; - - case FB_STATE_READY: - // Now it's proper time to copy the data to the display - drv->queue.entry[drv->queue.rix] = FB_STATE_COPYING; - display_panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); - bg_copy_start_const_out_8(get_fb_ptr(drv->queue.rix), - (uint8_t *)DISPLAY_DATA_ADDRESS, - PHYSICAL_FRAME_BUFFER_SIZE, bg_copy_callback); - - // NOTE: when copying is done, this queue slot is marked empty - // (see bg_copy_callback()) - break; - - default: - // This is an invalid state and we should never get here - break; + if (fb_idx >= 0) { + display_panel_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); + bg_copy_start_const_out_8(get_fb_ptr(fb_idx), + (uint8_t *)DISPLAY_DATA_ADDRESS, + PHYSICAL_FRAME_BUFFER_SIZE, bg_copy_callback); } } @@ -187,17 +157,9 @@ bool display_get_frame_buffer(display_fb_info_t *fb) { return false; } - frame_buffer_state_t state; + uint8_t fb_idx = fb_queue_get_for_write(&drv->queue); - // We have to wait if the buffer was passed for copying - // to the interrupt handler - do { - state = drv->queue.entry[drv->queue.wix]; - } while (state == FB_STATE_READY || state == FB_STATE_COPYING); - - drv->queue.entry[drv->queue.wix] = FB_STATE_PREPARING; - - fb->ptr = get_fb_ptr(drv->queue.wix); + fb->ptr = get_fb_ptr(fb_idx); fb->stride = DISPLAY_RESX * sizeof(uint16_t); // Enable access to the frame buffer from the unprivileged code mpu_set_active_fb(fb->ptr, PHYSICAL_FRAME_BUFFER_SIZE); @@ -236,7 +198,9 @@ void display_refresh(void) { return; } - if (drv->queue.entry[drv->queue.wix] != FB_STATE_PREPARING) { + int16_t fb_idx = fb_queue_get_for_copy(&drv->queue); + + if (fb_idx < 0) { // No refresh needed as the frame buffer is not in // the state to be copied to the display return; @@ -255,26 +219,26 @@ void display_refresh(void) { // Stop any background copying even if it is not finished yet bg_copy_abort(); // Copy the frame buffer to the display manually - copy_fb_to_display(drv->queue.wix); + copy_fb_to_display(fb_idx); // Reset the buffer queue so we can eventually continue // safely in thread mode - drv->queue.wix = 0; - drv->queue.rix = 0; - for (int i = 0; i < FRAME_BUFFER_COUNT; i++) { - drv->queue.entry[i] = FB_STATE_EMPTY; - } + fb_queue_reset(&drv->queue); + // Enable normal processing again NVIC_EnableIRQ(DISPLAY_TE_INTERRUPT_NUM); } else { // Mark the buffer ready to switch to - drv->queue.entry[drv->queue.wix] = FB_STATE_READY; - drv->queue.wix = (drv->queue.wix + 1) % FRAME_BUFFER_COUNT; + fb_queue_set_ready_for_transfer(&drv->queue); } #else // BOARDLOADER wait_for_te_signal(); - copy_fb_to_display(drv->queue.wix); - drv->queue.entry[drv->queue.wix] = FB_STATE_EMPTY; + fb_queue_set_ready_for_transfer(&drv->queue); + fb_idx = fb_queue_get_for_transfer(&drv->queue); + if (fb_idx >= 0) { + copy_fb_to_display(fb_idx); + fb_queue_set_done(&drv->queue); + } #endif } @@ -293,14 +257,7 @@ void display_ensure_refreshed(void) { // so we can be sure there's not scheduled or pending // background copying do { - copy_pending = false; - for (int i = 0; i < FRAME_BUFFER_COUNT; i++) { - frame_buffer_state_t state = drv->queue.entry[i]; - if (state == FB_STATE_READY || state == FB_STATE_COPYING) { - copy_pending = true; - break; - } - } + copy_pending = !fb_queue_is_processed(&drv->queue); __WFI(); } while (copy_pending); diff --git a/core/embed/io/display/st-7789/display_internal.h b/core/embed/io/display/st-7789/display_internal.h index 19a4398669..7af7934ba1 100644 --- a/core/embed/io/display/st-7789/display_internal.h +++ b/core/embed/io/display/st-7789/display_internal.h @@ -6,37 +6,7 @@ #ifdef FRAMEBUFFER -// Number of frame buffers used (1 or 2) -// If 1 buffer is selected, some animations may not -// be so smooth but the memory usage is lower. -#define FRAME_BUFFER_COUNT 2 - -// Each frame buffer can be in one of the following states: -typedef enum { - // The frame buffer is empty and can be written to - FB_STATE_EMPTY = 0, - // The frame buffer pass passed to application - FB_STATE_PREPARING = 1, - // The frame buffer was written to and is ready - // to be copied to the display - FB_STATE_READY = 2, - // The frame buffer is currently being copied to - // the display - FB_STATE_COPYING = 3, - -} frame_buffer_state_t; - -typedef struct { - // Queue entries - volatile frame_buffer_state_t entry[FRAME_BUFFER_COUNT]; - // Read index - // (accessed & updated in the context of the interrupt handlers - uint8_t rix; - // Write index - // (accessed & updated in context of the main thread) - uint8_t wix; - -} frame_buffer_queue_t; +#include "../fb_queue/fb_queue.h" #endif // FRAMEBUFFER diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py index 0f52a08689..5229e2379a 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py @@ -47,6 +47,7 @@ def configure( sources += ["embed/io/display/st-7789/display_io.c"] sources += ["embed/io/display/st-7789/display_panel.c"] sources += ["embed/io/display/st-7789/panels/lx154a2482.c"] + sources += ["embed/io/display/fb_queue/fb_queue.c"] paths += ["embed/io/display/inc"] sources += ["embed/io/display/backlight/stm32/backlight_pwm.c"] From c52b026c373f470106b6f398e9dfb03df4a89cd8 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Mon, 25 Nov 2024 16:10:52 +0100 Subject: [PATCH 2/3] feat(core): display driver for T3W1 [no changelog] disp --- .../io/display/ltdc_dsi/display_driver.c | 404 ++++++++++++++++++ core/embed/io/display/ltdc_dsi/display_fb.c | 238 +++++++++++ .../io/display/ltdc_dsi/display_fb_rgb565.c | 64 +++ .../io/display/ltdc_dsi/display_fb_rgb888.c | 65 +++ .../io/display/ltdc_dsi/display_gfxmmu.c | 61 +++ .../io/display/ltdc_dsi/display_internal.h | 83 ++++ .../ltdc_dsi/panels/lx200d2406a/lx200d2406a.c | 166 +++++++ .../ltdc_dsi/panels/lx200d2406a/lx200d2406a.h | 49 +++ .../io/display/st7785ma/display_driver.c | 93 ---- .../models/T3W1/boards/trezor_t3w1_revA.h | 7 + .../models/T3W1/trezor_t3w1_revA.py | 6 +- 11 files changed, 1142 insertions(+), 94 deletions(-) create mode 100644 core/embed/io/display/ltdc_dsi/display_driver.c create mode 100644 core/embed/io/display/ltdc_dsi/display_fb.c create mode 100644 core/embed/io/display/ltdc_dsi/display_fb_rgb565.c create mode 100644 core/embed/io/display/ltdc_dsi/display_fb_rgb888.c create mode 100644 core/embed/io/display/ltdc_dsi/display_gfxmmu.c create mode 100644 core/embed/io/display/ltdc_dsi/display_internal.h create mode 100644 core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.c create mode 100644 core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.h delete mode 100644 core/embed/io/display/st7785ma/display_driver.c diff --git a/core/embed/io/display/ltdc_dsi/display_driver.c b/core/embed/io/display/ltdc_dsi/display_driver.c new file mode 100644 index 0000000000..ab45d30383 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/display_driver.c @@ -0,0 +1,404 @@ + +#include +#include +#include + +#include + +#ifdef KERNEL_MODE + +#include +#include +#include + +#ifdef USE_BACKLIGHT +#include "../backlight/backlight_pwm.h" +#endif + +#include "display_internal.h" + +display_driver_t g_display_driver = { + .initialized = false, +}; + +static void display_pll_init(void) { + RCC_PeriphCLKInitTypeDef PLL3InitPeriph = {0}; + + /* Start and configure PLL3 */ + /* HSE = 16/32MHZ */ + /* 16/32/(M=8) = 4MHz input (min) */ + /* 4*(N=125) = 500MHz VCO (almost max) */ + /* 500/(P=8) = 62.5 for DSI ie exactly the lane byte clock*/ + + PLL3InitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI | RCC_PERIPHCLK_LTDC; + PLL3InitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; + PLL3InitPeriph.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3; +#if HSE_VALUE == 32000000 + PLL3InitPeriph.PLL3.PLL3M = 8; +#elif HSE_VALUE == 16000000 + PLL3InitPeriph.PLL3.PLL3M = 4; +#endif + PLL3InitPeriph.PLL3.PLL3N = 125; + PLL3InitPeriph.PLL3.PLL3P = 8; + PLL3InitPeriph.PLL3.PLL3Q = 8; + PLL3InitPeriph.PLL3.PLL3R = 24; + PLL3InitPeriph.PLL3.PLL3FRACN = 0; + PLL3InitPeriph.PLL3.PLL3RGE = RCC_PLLVCIRANGE_0; + PLL3InitPeriph.PLL3.PLL3ClockOut = RCC_PLL3_DIVR | RCC_PLL3_DIVP; + PLL3InitPeriph.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; + (void)HAL_RCCEx_PeriphCLKConfig(&PLL3InitPeriph); +} + +static void display_dsi_init(void) { + display_driver_t *drv = &g_display_driver; + + RCC_PeriphCLKInitTypeDef DSIPHYInitPeriph = {0}; + DSI_PLLInitTypeDef PLLInit = {0}; + DSI_PHY_TimerTypeDef PhyTimers = {0}; + DSI_HOST_TimeoutTypeDef HostTimeouts = {0}; + + /* Enable DSI clock */ + __HAL_RCC_DSI_CLK_ENABLE(); + + /* Switch to D-PHY source clock */ + /* Enable the DSI host */ + drv->hlcd_dsi.Instance = DSI; + + __HAL_DSI_ENABLE(&drv->hlcd_dsi); + + /* Enable the DSI PLL */ + __HAL_DSI_PLL_ENABLE(&drv->hlcd_dsi); + + HAL_Delay(1); + + /* Enable the clock lane and the digital section of the D-PHY */ + drv->hlcd_dsi.Instance->PCTLR |= (DSI_PCTLR_CKE | DSI_PCTLR_DEN); + + /* Set the TX escape clock division factor */ + drv->hlcd_dsi.Instance->CCR = 4; + + HAL_Delay(1); + + /* Config DSI Clock to DSI PHY */ + DSIPHYInitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI; + DSIPHYInitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_DSIPHY; + + (void)HAL_RCCEx_PeriphCLKConfig(&DSIPHYInitPeriph); + + /* Reset the TX escape clock division factor */ + drv->hlcd_dsi.Instance->CCR &= ~DSI_CCR_TXECKDIV; + + /* Disable the DSI PLL */ + __HAL_DSI_PLL_DISABLE(&drv->hlcd_dsi); + + /* Disable the DSI host */ + __HAL_DSI_DISABLE(&drv->hlcd_dsi); + + /* DSI initialization */ + drv->hlcd_dsi.Instance = DSI; + drv->hlcd_dsi.Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE; + /* We have 1 data lane at 500Mbps => lane byte clock at 500/8 = 62,5 MHZ */ + /* We want TX escape clock at around 20MHz and under 20MHz so clock division + * is set to 4 */ + drv->hlcd_dsi.Init.TXEscapeCkdiv = 4; + drv->hlcd_dsi.Init.NumberOfLanes = PANEL_DSI_LANES; + drv->hlcd_dsi.Init.PHYFrequencyRange = DSI_DPHY_FRANGE_450MHZ_510MHZ; + drv->hlcd_dsi.Init.PHYLowPowerOffset = 0; + +#if HSE_VALUE == 32000000 + PLLInit.PLLNDIV = 62; +#elif HSE_VALUE == 16000000 + PLLInit.PLLNDIV = 125; +#endif + PLLInit.PLLIDF = 4; + PLLInit.PLLODF = 2; + PLLInit.PLLVCORange = DSI_DPHY_VCO_FRANGE_800MHZ_1GHZ; + PLLInit.PLLChargePump = DSI_PLL_CHARGE_PUMP_2000HZ_4400HZ; + PLLInit.PLLTuning = DSI_PLL_LOOP_FILTER_2000HZ_4400HZ; + + HAL_DSI_Init(&drv->hlcd_dsi, &PLLInit); + HAL_DSI_SetGenericVCID(&drv->hlcd_dsi, 0); + + /* Configure the DSI for Video mode */ + drv->DSIVidCfg.VirtualChannelID = 0; + drv->DSIVidCfg.HSPolarity = DSI_HSYNC_ACTIVE_HIGH; + drv->DSIVidCfg.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; + drv->DSIVidCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; + drv->DSIVidCfg.ColorCoding = DSI_RGB888; + drv->DSIVidCfg.Mode = PANEL_DSI_MODE; + drv->DSIVidCfg.PacketSize = LCD_WIDTH; + drv->DSIVidCfg.NullPacketSize = 0xFFFU; + drv->DSIVidCfg.HorizontalSyncActive = HSYNC * 3; + drv->DSIVidCfg.HorizontalBackPorch = HBP * 3; + drv->DSIVidCfg.HorizontalLine = (HACT + HSYNC + HBP + HFP) * 3; + drv->DSIVidCfg.VerticalSyncActive = VSYNC; + drv->DSIVidCfg.VerticalBackPorch = VBP; + drv->DSIVidCfg.VerticalFrontPorch = VFP; + drv->DSIVidCfg.VerticalActive = VACT; + drv->DSIVidCfg.LPCommandEnable = DSI_LP_COMMAND_ENABLE; + drv->DSIVidCfg.LPLargestPacketSize = 64; + /* Specify for each region of the video frame, if the transmission of command + * in LP mode is allowed in this region */ + /* while streaming is active in video mode */ + drv->DSIVidCfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE; + drv->DSIVidCfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE; + drv->DSIVidCfg.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE; + drv->DSIVidCfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE; + drv->DSIVidCfg.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE; + drv->DSIVidCfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; + drv->DSIVidCfg.FrameBTAAcknowledgeEnable = DSI_FBTAA_ENABLE; + drv->DSIVidCfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE; + + /* Drive the display */ + HAL_DSI_ConfigVideoMode(&drv->hlcd_dsi, &drv->DSIVidCfg); + + /*********************/ + /* LCD configuration */ + /*********************/ + PhyTimers.ClockLaneHS2LPTime = 11; + PhyTimers.ClockLaneLP2HSTime = 40; + PhyTimers.DataLaneHS2LPTime = 12; + PhyTimers.DataLaneLP2HSTime = 23; + PhyTimers.DataLaneMaxReadTime = 0; + PhyTimers.StopWaitTime = 7; + + HAL_DSI_ConfigPhyTimer(&drv->hlcd_dsi, &PhyTimers); + + HostTimeouts.TimeoutCkdiv = 1; + HostTimeouts.HighSpeedTransmissionTimeout = 0; + HostTimeouts.LowPowerReceptionTimeout = 0; + HostTimeouts.HighSpeedReadTimeout = 0; + HostTimeouts.LowPowerReadTimeout = 0; + HostTimeouts.HighSpeedWriteTimeout = 0; + HostTimeouts.HighSpeedWritePrespMode = 0; + HostTimeouts.LowPowerWriteTimeout = 0; + HostTimeouts.BTATimeout = 0; + + HAL_DSI_ConfigHostTimeouts(&drv->hlcd_dsi, &HostTimeouts); + HAL_DSI_ConfigFlowControl(&drv->hlcd_dsi, DSI_FLOW_CONTROL_BTA); + + /* Enable the DSI host */ + __HAL_DSI_ENABLE(&drv->hlcd_dsi); +} + +void display_ltdc_config_layer(LTDC_HandleTypeDef *hltdc, uint32_t fb_addr) { + LTDC_LayerCfgTypeDef LayerCfg = {0}; + + /* LTDC layer configuration */ + LayerCfg.WindowX0 = 0; + LayerCfg.WindowX1 = LCD_WIDTH; + LayerCfg.WindowY0 = LCD_Y_OFFSET; + LayerCfg.WindowY1 = LCD_HEIGHT + LCD_Y_OFFSET; + LayerCfg.PixelFormat = PANEL_LTDC_PIXEL_FORMAT; + LayerCfg.Alpha = 0xFF; /* NU default value */ + LayerCfg.Alpha0 = 0; /* NU default value */ + LayerCfg.BlendingFactor1 = + LTDC_BLENDING_FACTOR1_PAxCA; /* Not Used: default value */ + LayerCfg.BlendingFactor2 = + LTDC_BLENDING_FACTOR2_PAxCA; /* Not Used: default value */ + LayerCfg.FBStartAdress = fb_addr; + LayerCfg.ImageWidth = + FRAME_BUFFER_PIXELS_PER_LINE; /* Number of pixels per line in virtual + frame buffer */ + LayerCfg.ImageHeight = LCD_HEIGHT; + LayerCfg.Backcolor.Red = 0; /* Not Used: default value */ + LayerCfg.Backcolor.Green = 0; /* Not Used: default value */ + LayerCfg.Backcolor.Blue = 0; /* Not Used: default value */ + LayerCfg.Backcolor.Reserved = 0xFF; + HAL_LTDC_ConfigLayer(hltdc, &LayerCfg, LTDC_LAYER_1); +} + +void display_ltdc_init(void) { + display_driver_t *drv = &g_display_driver; + + __HAL_RCC_LTDC_CLK_ENABLE(); + + /* LTDC initialization */ + drv->hlcd_ltdc.Instance = LTDC; + drv->hlcd_ltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL; + drv->hlcd_ltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL; + drv->hlcd_ltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL; + drv->hlcd_ltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC; + drv->hlcd_ltdc.Init.HorizontalSync = HSYNC - 1; + drv->hlcd_ltdc.Init.AccumulatedHBP = HSYNC + HBP - 1; + drv->hlcd_ltdc.Init.AccumulatedActiveW = HACT + HBP + HSYNC - 1; + drv->hlcd_ltdc.Init.TotalWidth = HACT + HBP + HFP + HSYNC - 1; + drv->hlcd_ltdc.Init.Backcolor.Red = 0; /* Not used default value */ + drv->hlcd_ltdc.Init.Backcolor.Green = 0; /* Not used default value */ + drv->hlcd_ltdc.Init.Backcolor.Blue = 0; /* Not used default value */ + drv->hlcd_ltdc.Init.Backcolor.Reserved = 0xFF; + + HAL_LTDCEx_StructInitFromVideoConfig(&drv->hlcd_ltdc, &drv->DSIVidCfg); + + HAL_LTDC_Init(&drv->hlcd_ltdc); + + display_ltdc_config_layer(&drv->hlcd_ltdc, display_fb_get_initial_addr()); +} + +void display_set_fb(uint32_t fb_addr) { + display_driver_t *drv = &g_display_driver; + display_ltdc_config_layer(&drv->hlcd_ltdc, fb_addr); +} + +// Fully initializes the display controller. +void display_init(display_content_mode_t mode) { + display_driver_t *drv = &g_display_driver; + + GPIO_InitTypeDef GPIO_InitStructure = {0}; + + __HAL_RCC_DSI_FORCE_RESET(); + __HAL_RCC_LTDC_FORCE_RESET(); + +#ifdef DISPLAY_PWREN_PIN + DISPLAY_PWREN_CLK_ENA(); + HAL_GPIO_WritePin(DISPLAY_PWREN_PORT, DISPLAY_PWREN_PIN, GPIO_PIN_RESET); + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + GPIO_InitStructure.Pin = DISPLAY_PWREN_PIN; + HAL_GPIO_Init(DISPLAY_PWREN_PORT, &GPIO_InitStructure); +#endif + +#ifdef DISPLAY_RESET_PIN + DISPLAY_RESET_CLK_ENA(); + HAL_GPIO_WritePin(GPIOE, DISPLAY_RESET_PIN, GPIO_PIN_RESET); + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + GPIO_InitStructure.Pin = DISPLAY_RESET_PIN; + HAL_GPIO_Init(DISPLAY_RESET_PORT, &GPIO_InitStructure); + + systick_delay_ms(10); + HAL_GPIO_WritePin(DISPLAY_RESET_PORT, DISPLAY_RESET_PIN, GPIO_PIN_SET); + 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); +#endif + + display_fb_clear(); + + __HAL_RCC_LTDC_RELEASE_RESET(); + __HAL_RCC_DSI_RELEASE_RESET(); + +#ifdef DISPLAY_GFXMMU + display_gfxmmu_init(drv); +#endif + + display_pll_init(); + display_dsi_init(); + display_ltdc_init(); + + /* Start DSI */ + HAL_DSI_Start(&drv->hlcd_dsi); + + panel_init(drv); + + HAL_LTDC_ProgramLineEvent(&drv->hlcd_ltdc, LCD_HEIGHT); + + /* Enable LTDC interrupt */ + NVIC_SetPriority(LTDC_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(LTDC_IRQn); + + NVIC_SetPriority(LTDC_ER_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(LTDC_ER_IRQn); + + __HAL_LTDC_ENABLE_IT(&drv->hlcd_ltdc, LTDC_IT_LI | LTDC_IT_FU | LTDC_IT_TE); + + drv->initialized = true; +} + +int display_set_backlight(int level) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } + +#ifdef USE_BACKLIGHT + if (level > backlight_pwm_get()) { + display_ensure_refreshed(); + } + + return backlight_pwm_set(level); +#else + // Just emulation, not doing anything + drv->backlight_level = level; + return level; +#endif +} + +int display_get_backlight(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return 0; + } +#ifdef USE_BACKLIGHT + return backlight_pwm_get(); +#else + return drv->backlight_level; +#endif +} + +int display_set_orientation(int angle) { return angle; } + +int display_get_orientation(void) { return 0; } + +void LTDC_IRQHandler(void) { + IRQ_LOG_ENTER(); + mpu_mode_t mode = mpu_reconfig(MPU_MODE_DEFAULT); + + display_driver_t *drv = &g_display_driver; + + if (drv->hlcd_ltdc.State != HAL_LTDC_STATE_RESET) { + HAL_LTDC_IRQHandler(&drv->hlcd_ltdc); + } else { + LTDC->ICR = 0x3F; + } + + mpu_restore(mode); + IRQ_LOG_EXIT(); +} + +void LTDC_ER_IRQHandler(void) { + IRQ_LOG_ENTER(); + mpu_mode_t mode = mpu_reconfig(MPU_MODE_DEFAULT); + + display_driver_t *drv = &g_display_driver; + + if (drv->hlcd_ltdc.State != HAL_LTDC_STATE_RESET) { + HAL_LTDC_IRQHandler(&drv->hlcd_ltdc); + } else { + LTDC->ICR = 0x3F; + } + + mpu_restore(mode); + IRQ_LOG_EXIT(); +} + +void display_deinit(display_content_mode_t mode) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + + // todo + + NVIC_DisableIRQ(LTDC_IRQn); + NVIC_DisableIRQ(LTDC_ER_IRQn); +} + +#endif diff --git a/core/embed/io/display/ltdc_dsi/display_fb.c b/core/embed/io/display/ltdc_dsi/display_fb.c new file mode 100644 index 0000000000..63b490fc45 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/display_fb.c @@ -0,0 +1,238 @@ +/* + * 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 +#include + +#include "display_internal.h" + +#define ALIGNED_PHYSICAL_FRAME_BUFFER_SIZE \ + ALIGN_UP_CONST(PHYSICAL_FRAME_BUFFER_SIZE, PHYSICAL_FRAME_BUFFER_ALIGNMENT) + +// Physical frame buffers in internal SRAM memory. +// Both frame buffers layers in the fixed addresses that +// are shared between bootloaders and the firmware. +__attribute__((section(".fb1"), aligned(PHYSICAL_FRAME_BUFFER_ALIGNMENT))) +uint8_t physical_frame_buffer_0[ALIGNED_PHYSICAL_FRAME_BUFFER_SIZE]; + +#if (FRAME_BUFFER_COUNT > 1) +__attribute__((section(".fb2"), aligned(PHYSICAL_FRAME_BUFFER_ALIGNMENT))) +uint8_t physical_frame_buffer_1[ALIGNED_PHYSICAL_FRAME_BUFFER_SIZE]; +#endif + +#ifdef USE_TRUSTZONE +void display_set_unpriv_access(bool unpriv) { + // To allow unprivileged access both GFXMMU virtual buffers area and + // underlying SRAM region must be configured as unprivileged. + + // Order of GFXMMU and SRAM unprivileged access configuration is important + // to avoid the situation the virtual frame buffer has lower privileges + // than underlying frame buffer in physical memory so LTDC could not + // refresh the display properly. + +#ifdef DISPLAY_GFXMMU + if (!unpriv) { + tz_set_gfxmmu_unpriv(unpriv); + } +#endif + + tz_set_sram_unpriv((uint32_t)physical_frame_buffer_0, + PHYSICAL_FRAME_BUFFER_SIZE, unpriv); + + tz_set_sram_unpriv((uint32_t)physical_frame_buffer_1, + PHYSICAL_FRAME_BUFFER_SIZE, unpriv); + +#ifdef DISPLAY_GFXMMU + if (unpriv) { + tz_set_gfxmmu_unpriv(unpriv); + } +#endif + +#ifdef USE_DMA2D + tz_set_dma2d_unpriv(unpriv); +#endif +} +#endif // USE_TRUSTZONE + +// Returns the pointer to the physical frame buffer (0.. FRAME_BUFFER_COUNT-1) +// Returns NULL if the framebuffer index is out of range. +static uint8_t *get_fb_ptr(int16_t index) { +#ifdef DISPLAY_GFXMMU + if (index == 0) { + return (uint8_t *)GFXMMU_VIRTUAL_BUFFER0_BASE_S; +#if (FRAME_BUFFER_COUNT > 1) + } else if (index == 1) { + return (uint8_t *)GFXMMU_VIRTUAL_BUFFER1_BASE_S; +#endif +#else + if (index == 0) { + return physical_frame_buffer_0; +#if (FRAME_BUFFER_COUNT > 1) + } else if (index == 1) { + return physical_frame_buffer_1; +#endif +#endif + } else { + return NULL; + } +} + +bool display_get_frame_buffer(display_fb_info_t *fb_dest) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return false; + } + +#if PANEL_LTDC_PIXEL_FORMAT == LTDC_PIXEL_FORMAT_ARGB8888 +#define FB_PIXEL_SIZE 4 +#elif PANEL_LTDC_PIXEL_FORMAT == LTDC_PIXEL_FORMAT_RGB565 +#define FB_PIXEL_SIZE 2 +#endif + + int16_t fb_idx = fb_queue_get_for_write(&drv->queue); + + if (fb_idx < 0) { + fb_dest->ptr = NULL; + fb_dest->stride = 0; + return false; + } + + uintptr_t addr = (uintptr_t)get_fb_ptr(fb_idx); + + uint32_t fb_stride = FRAME_BUFFER_PIXELS_PER_LINE * FB_PIXEL_SIZE; + + // We may not utilize whole area of the display + addr += (LCD_HEIGHT - DISPLAY_RESY) / 2 * FB_PIXEL_SIZE; + addr += (LCD_WIDTH - DISPLAY_RESX) / 2 * fb_stride; + + display_fb_info_t fb = { + .ptr = (void *)addr, + .stride = fb_stride, + }; + + mpu_set_active_fb((void *)addr, VIRTUAL_FRAME_BUFFER_SIZE); + + memcpy(fb_dest, &fb, sizeof(display_fb_info_t)); + + return true; +} + +void display_refresh(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + + int16_t fb_idx = fb_queue_get_for_copy(&drv->queue); + + if (fb_idx < 0) { + // No refresh needed as the frame buffer is not in + // the state to be copied to the display + return; + } + + if (is_mode_exception()) { + // Disable scheduling of any new background copying + HAL_NVIC_DisableIRQ(LTDC_IRQn); + HAL_NVIC_DisableIRQ(LTDC_ER_IRQn); + + display_set_fb((uint32_t)get_fb_ptr(fb_idx)); + + // Reset the buffer queue so we can eventually continue + // safely in thread mode + fb_queue_reset(&drv->queue); + + // Enable normal processing again + HAL_NVIC_EnableIRQ(LTDC_IRQn); + HAL_NVIC_EnableIRQ(LTDC_ER_IRQn); + } else { + // Mark the buffer ready to switch to + fb_queue_set_ready_for_transfer(&drv->queue); + } +} + +void display_ensure_refreshed(void) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + + if (!is_mode_exception()) { + bool copy_pending; + + // Wait until all frame buffers are written to the display + // so we can be sure there's not scheduled or pending + // background copying + do { + copy_pending = !fb_queue_is_processed(&drv->queue); + __WFI(); + } while (copy_pending || drv->update_pending > 0); + } +} + +void display_fb_clear(void) { + mpu_set_active_fb(physical_frame_buffer_0, PHYSICAL_FRAME_BUFFER_SIZE); + memset(physical_frame_buffer_0, 0, PHYSICAL_FRAME_BUFFER_SIZE); + mpu_set_active_fb(physical_frame_buffer_1, PHYSICAL_FRAME_BUFFER_SIZE); + memset(physical_frame_buffer_1, 0, PHYSICAL_FRAME_BUFFER_SIZE); + mpu_set_active_fb(NULL, 0); +} + +uint32_t display_fb_get_initial_addr(void) { + display_fb_info_t fb_info; + + display_get_frame_buffer(&fb_info); + + fb_queue_set_ready_for_transfer(&g_display_driver.queue); + + fb_queue_get_for_transfer(&g_display_driver.queue); + + return (uint32_t)fb_info.ptr; +} + +void HAL_LTDC_LineEvenCallback(LTDC_HandleTypeDef *hltdc) { + display_driver_t *drv = &g_display_driver; + + if (!drv->initialized) { + return; + } + + if (drv->update_pending > 0) { + drv->update_pending--; + } + + int16_t fb_idx = fb_queue_get_for_transfer(&drv->queue); + if (fb_idx >= 0) { + fb_queue_set_switched(&drv->queue); + display_set_fb((uint32_t)get_fb_ptr(fb_idx)); + drv->update_pending = 3; + } + + HAL_LTDC_ProgramLineEvent(&drv->hlcd_ltdc, LCD_HEIGHT); +} + +#endif diff --git a/core/embed/io/display/ltdc_dsi/display_fb_rgb565.c b/core/embed/io/display/ltdc_dsi/display_fb_rgb565.c new file mode 100644 index 0000000000..cd6a98f2e5 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/display_fb_rgb565.c @@ -0,0 +1,64 @@ +#include +#include + +#include +#include + +#ifdef KERNEL_MODE +void display_copy_rgb565(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgb565_copy_rgb565(&bb_new); +} + +void display_fill(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgb565_fill(&bb_new); +} + +void display_copy_mono1p(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgb565_copy_mono1p(&bb_new); +} + +void display_copy_mono4(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgb565_copy_mono4(&bb_new); +} + +#endif diff --git a/core/embed/io/display/ltdc_dsi/display_fb_rgb888.c b/core/embed/io/display/ltdc_dsi/display_fb_rgb888.c new file mode 100644 index 0000000000..45cdb05243 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/display_fb_rgb888.c @@ -0,0 +1,65 @@ + +#ifdef KERNEL_MODE + +#include +#include + +#include +#include + +void display_fill(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgba8888_fill(&bb_new); +} + +void display_copy_rgb565(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgba8888_copy_rgb565(&bb_new); +} + +void display_copy_mono1p(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgba8888_copy_mono1p(&bb_new); +} + +void display_copy_mono4(const gfx_bitblt_t *bb) { + display_fb_info_t fb; + + if (!display_get_frame_buffer(&fb)) { + return; + } + + gfx_bitblt_t bb_new = *bb; + bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); + bb_new.dst_stride = fb.stride; + + gfx_rgba8888_copy_mono4(&bb_new); +} +#endif diff --git a/core/embed/io/display/ltdc_dsi/display_gfxmmu.c b/core/embed/io/display/ltdc_dsi/display_gfxmmu.c new file mode 100644 index 0000000000..926b9d57c5 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/display_gfxmmu.c @@ -0,0 +1,61 @@ +#ifdef KERNEL_MODE +#include + +#include + +#include "display_internal.h" + +extern uint8_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE]; +extern uint8_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE]; + +extern const uint32_t gfxmmu_lut_config[2 * GFXMMU_LUT_SIZE]; + +void display_gfxmmu_init(display_driver_t *drv) { + __HAL_RCC_GFXMMU_FORCE_RESET(); + __HAL_RCC_GFXMMU_RELEASE_RESET(); + + /* GFXMMU clock enable */ + __HAL_RCC_GFXMMU_CLK_ENABLE(); + + /* Enable GFXMMU interrupt */ + NVIC_SetPriority(GFXMMU_IRQn, IRQ_PRI_NORMAL); + NVIC_EnableIRQ(GFXMMU_IRQn); + + /* GFXMMU peripheral initialization */ + drv->hlcd_gfxmmu.Instance = GFXMMU; + drv->hlcd_gfxmmu.Init.BlocksPerLine = GFXMMU_192BLOCKS; + drv->hlcd_gfxmmu.Init.DefaultValue = 0xFFFFFFFFU; + drv->hlcd_gfxmmu.Init.Buffers.Buf0Address = (uint32_t)physical_frame_buffer_0; + drv->hlcd_gfxmmu.Init.Buffers.Buf1Address = (uint32_t)physical_frame_buffer_1; + drv->hlcd_gfxmmu.Init.Buffers.Buf2Address = 0; + drv->hlcd_gfxmmu.Init.Buffers.Buf3Address = 0; +#if defined(GFXMMU_CR_CE) + drv->hlcd_gfxmmu.Init.CachePrefetch.Activation = DISABLE; + drv->hlcd_gfxmmu.Init.CachePrefetch.CacheLock = GFXMMU_CACHE_LOCK_DISABLE; + drv->hlcd_gfxmmu.Init.CachePrefetch.CacheLockBuffer = + GFXMMU_CACHE_LOCK_BUFFER0; /* NU */ + drv->hlcd_gfxmmu.Init.CachePrefetch.CacheForce = + GFXMMU_CACHE_FORCE_ENABLE; /* NU */ + drv->hlcd_gfxmmu.Init.CachePrefetch.OutterBufferability = + GFXMMU_OUTTER_BUFFERABILITY_DISABLE; + drv->hlcd_gfxmmu.Init.CachePrefetch.OutterCachability = + GFXMMU_OUTTER_CACHABILITY_DISABLE; + drv->hlcd_gfxmmu.Init.CachePrefetch.Prefetch = GFXMMU_PREFETCH_DISABLE; +#endif /* GFXMMU_CR_CE */ +#if defined(GFXMMU_CR_ACE) + drv->hlcd_gfxmmu.Init.AddressCache.Activation = DISABLE; + drv->hlcd_gfxmmu.Init.AddressCache.AddressCacheLockBuffer = + GFXMMU_ADDRESSCACHE_LOCK_BUFFER0; +#endif /* GFXMMU_CR_ACE */ + drv->hlcd_gfxmmu.Init.Interrupts.Activation = DISABLE; + drv->hlcd_gfxmmu.Init.Interrupts.UsedInterrupts = + GFXMMU_AHB_MASTER_ERROR_IT; /* NU */ + HAL_GFXMMU_Init(&drv->hlcd_gfxmmu); + + /* Initialize LUT */ + HAL_GFXMMU_ConfigLut(&drv->hlcd_gfxmmu, 0, LCD_HEIGHT, + (uint32_t)&gfxmmu_lut_config); + + HAL_GFXMMU_DisableLutLines(&drv->hlcd_gfxmmu, LCD_HEIGHT, 1024 - LCD_HEIGHT); +} +#endif diff --git a/core/embed/io/display/ltdc_dsi/display_internal.h b/core/embed/io/display/ltdc_dsi/display_internal.h new file mode 100644 index 0000000000..bd48e14c25 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/display_internal.h @@ -0,0 +1,83 @@ +/* + * 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 . + */ + +#ifndef TREZOR_HAL_DISPLAY_INTERNAL_H +#define TREZOR_HAL_DISPLAY_INTERNAL_H + +#include +#include + +#include "../fb_queue/fb_queue.h" + +#ifdef DISPLAY_PANEL_LX200D2406A +#include "panels/lx200d2406a/lx200d2406a.h" +#elif defined DISPLAY_PANEL_STM32U5A9J_DK +#include "panels/stm32u5a9j-dk/stm32u5a9j-dk.h" +#endif + +// Hardware requires physical frame buffer alignment +#ifdef USE_TRUSTZONE +#define PHYSICAL_FRAME_BUFFER_ALIGNMENT TZ_SRAM_ALIGNMENT +#else +#define PHYSICAL_FRAME_BUFFER_ALIGNMENT 32 +#endif + +typedef struct { + bool initialized; + uint16_t update_pending; + frame_buffer_queue_t queue; + + // Current display orientation (0, 90, 180, 270) + int orientation_angle; + // Current backlight level ranging from 0 to 255 + int backlight_level; + // The current frame buffer selector + + DSI_HandleTypeDef hlcd_dsi; + LTDC_HandleTypeDef hlcd_ltdc; + DSI_VidCfgTypeDef DSIVidCfg; +#ifdef DISPLAY_GFXMMU + GFXMMU_HandleTypeDef hlcd_gfxmmu; +#endif + +} display_driver_t; + +extern display_driver_t g_display_driver; + +void display_set_fb(uint32_t fb_addr); + +void display_fb_clear(void); + +uint32_t display_fb_get_initial_addr(void); + +static inline uint32_t is_mode_exception(void) { + uint32_t isr_number = __get_IPSR() & IPSR_ISR_Msk; + // Check if the ISR number is not 0 (thread mode) or 11 (SVCall) + return (isr_number != 0) && (isr_number != 11); +} + +void display_ensure_refreshed(void); + +void panel_init(display_driver_t *drv); + +#ifdef DISPLAY_GFXMMU +void display_gfxmmu_init(display_driver_t *drv); +#endif + +#endif // TREZOR_HAL_DISPLAY_INTERNAL_H diff --git a/core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.c b/core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.c new file mode 100644 index 0000000000..fc81069a44 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.c @@ -0,0 +1,166 @@ + +#include +#include + +#include + +#include "lx200d2406a.h" + +#include "../../display_internal.h" + +// todo static assert resolution + +void panel_init(display_driver_t *drv) { + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x11, 0); + + systick_delay_ms(120); + + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x36, 0x00); + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x3A, 0x06); + + // mipi video mode + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xB0, 0x10); + + // Write(Command , 0xB2); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0C); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0C); + // Write(Parameter , 0x00); + // Write(Parameter , 0x00); + // Write(Parameter , 0x00); + // Write(Parameter , 0x33); + // Write(Parameter , 0x00); + // Write(Parameter , 0x33); + HAL_DSI_LongWrite( + &drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 10, 0xB2, + (uint8_t[]){0x00, 0x0c, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x33, 0x00, 0x33}); + + // Write(Command , 0xB7); + // Write(Parameter , 0x00); + // Write(Parameter , 0x06); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xB7, + (uint8_t[]){0x00, 0x06}); + + // Write(Command , 0xBB); + // Write(Parameter , 0x00); + // Write(Parameter , 0x1E); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xBB, + (uint8_t[]){0x00, 0x1E}); + + // Write(Command , 0xC0); + // Write(Parameter , 0x00); + // Write(Parameter , 0x2C); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xC0, + (uint8_t[]){0x00, 0x2C}); + + // Write(Command , 0xC2); + // Write(Parameter , 0x00); + // Write(Parameter , 0x01); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xC2, + (uint8_t[]){0x00, 0x01}); + + // Write(Command , 0xC3); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0F); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xC3, + (uint8_t[]){0x00, 0x0F}); + + // Write(Command , 0xC6); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0F); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xC6, + (uint8_t[]){0x00, 0x0F}); + + // Write(Command , 0xD0); + // Write(Parameter , 0x00); + // Write(Parameter , 0xA7); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xD0, + (uint8_t[]){0x00, 0xA7}); + + // Write(Command , 0xD0); + // Write(Parameter , 0x00); + // Write(Parameter , 0xA4); + // Write(Parameter , 0x00); + // Write(Parameter , 0xA1); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, 0xD0, + (uint8_t[]){0x00, 0xA4, 0x00, 0xA1}); + + // Write(Command , 0xD6); + // Write(Parameter , 0x00); + // Write(Parameter , 0xA1); + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, 0xD6, + (uint8_t[]){0x00, 0xA1}); + + // Write(Command , 0xE0); + // Write(Parameter , 0x00); + // Write(Parameter , 0xF0); + // Write(Parameter , 0x00); + // Write(Parameter , 0x06); + // Write(Parameter , 0x00); + // Write(Parameter , 0x11); + // Write(Parameter , 0x00); + // Write(Parameter , 0x09); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0A); + // Write(Parameter , 0x00); + // Write(Parameter , 0x28); + // Write(Parameter , 0x00); + // Write(Parameter , 0x37); + // Write(Parameter , 0x00); + // Write(Parameter , 0x44); + // Write(Parameter , 0x00); + // Write(Parameter , 0x4E); + // Write(Parameter , 0x00); + // Write(Parameter , 0x39); + // Write(Parameter , 0x00); + // Write(Parameter , 0x14); + // Write(Parameter , 0x00); + // Write(Parameter , 0x15); + // Write(Parameter , 0x00); + // Write(Parameter , 0x34); + // Write(Parameter , 0x00); + // Write(Parameter , 0x3A); + // HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 28, 0xE0, + // (uint8_t[]){0x00, 0xF0, 0x00, 0x06, 0x00, 0x11, 0x00, 0x09, 0x00, 0x0A, + // 0x00, 0x28, 0x00, 0x37, 0x00, 0x44, 0x00, 0x4E, 0x00, 0x39, 0x00, 0x14, + // 0x00, 0x15, 0x00, 0x34, 0x00, 0x3A}); + + // Write(Command , 0xE1); + // Write(Parameter , 0x00); + // Write(Parameter , 0xF0); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0E); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0F); + // Write(Parameter , 0x00); + // Write(Parameter , 0x0A); + // Write(Parameter , 0x00); + // Write(Parameter , 0x08); + // Write(Parameter , 0x00); + // Write(Parameter , 0x04); + // Write(Parameter , 0x00); + // Write(Parameter , 0x37); + // Write(Parameter , 0x00); + // Write(Parameter , 0x43); + // Write(Parameter , 0x00); + // Write(Parameter , 0x4D); + // Write(Parameter , 0x00); + // Write(Parameter , 0x35); + // Write(Parameter , 0x00); + // Write(Parameter , 0x12); + // Write(Parameter , 0x00); + // Write(Parameter , 0x13); + // Write(Parameter , 0x00); + // Write(Parameter , 0x32); + // Write(Parameter , 0x00); + // Write(Parameter , 0x39); + // HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 28, 0xE1, + // (uint8_t[]){0x00, 0xF0, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x0A, 0x00, 0x08, + // 0x00, 0x04, 0x00, 0x37, 0x00, 0x43, 0x00, 0x4D, 0x00, 0x35, 0x00, 0x12, + // 0x00, 0x13, 0x00, 0x32, 0x00, 0x39}); + + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x21, 0); + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x29, 0); + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x2C, 0); +} diff --git a/core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.h b/core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.h new file mode 100644 index 0000000000..b696dde2fe --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.h @@ -0,0 +1,49 @@ +/* + * 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 . + */ + +#pragma once + +#include + +#define VSYNC 4 +#define VBP 4 +#define VFP 660 +#define VACT 320 +#define HSYNC 30 +#define HBP 60 +#define HFP 60 +#define HACT 240 +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 + +#define LCD_Y_OFFSET 0 + +#define PANEL_DSI_MODE DSI_VID_MODE_NB_PULSES +#define PANEL_DSI_LANES DSI_ONE_DATA_LANE +#define PANEL_LTDC_PIXEL_FORMAT LTDC_PIXEL_FORMAT_RGB565 + +// Size of the physical frame buffer in bytes +// +// It's smaller than size of the virtual frame buffer +// due to used GFXMMU settings +#define PHYSICAL_FRAME_BUFFER_SIZE (240 * 320 * 2) +#define VIRTUAL_FRAME_BUFFER_SIZE PHYSICAL_FRAME_BUFFER_SIZE + +// Pitch (in pixels) of the virtual frame buffer +#define FRAME_BUFFER_PIXELS_PER_LINE 240 diff --git a/core/embed/io/display/st7785ma/display_driver.c b/core/embed/io/display/st7785ma/display_driver.c deleted file mode 100644 index 3036e03685..0000000000 --- a/core/embed/io/display/st7785ma/display_driver.c +++ /dev/null @@ -1,93 +0,0 @@ - -#include -#ifdef KERNEL_MODE - -#include -#include -#include - -#include -#include -#include -#include "../backlight/backlight_pwm.h" - -// Hardware requires physical frame buffer alignment -#ifdef USE_TRUSTZONE -#define PHYSICAL_FRAME_BUFFER_ALIGNMENT TZ_SRAM_ALIGNMENT -#else -#define PHYSICAL_FRAME_BUFFER_ALIGNMENT 32 -#endif - -// Size of the physical frame buffer in bytes -#define PHYSICAL_FRAME_BUFFER_SIZE \ - ALIGN_UP_CONST(DISPLAY_RESX *DISPLAY_RESY * 2, \ - PHYSICAL_FRAME_BUFFER_ALIGNMENT) - -static - __attribute__((section(".fb1"), aligned(PHYSICAL_FRAME_BUFFER_ALIGNMENT))) - uint8_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE]; - -#if (FRAME_BUFFER_COUNT > 1) -static - __attribute__((section(".fb2"), aligned(PHYSICAL_FRAME_BUFFER_ALIGNMENT))) - uint8_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE]; -#endif - -void display_init(display_content_mode_t mode) { - __HAL_RCC_GPIOE_CLK_ENABLE(); - - GPIO_InitTypeDef GPIO_InitStructure; - - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Alternate = 0; - GPIO_InitStructure.Pin = GPIO_PIN_2; - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET); - HAL_GPIO_Init(GPIOE, &GPIO_InitStructure); - - GPIO_InitStructure.Pin = GPIO_PIN_0; - // default to keeping display in reset - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_RESET); - HAL_GPIO_Init(GPIOE, &GPIO_InitStructure); - - hal_delay(100); - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET); - - backlight_pwm_init(mode); -} - -void display_deinit(display_content_mode_t mode) { backlight_pwm_deinit(mode); } - -void display_set_unpriv_access(bool unpriv) {} - -int display_set_backlight(int level) { - return 0; - // return backlight_pwm_set(level); -} - -int display_get_backlight(void) { return backlight_pwm_get(); } - -int display_set_orientation(int angle) { return angle; } -int display_get_orientation(void) { return 0; } - -// Returns the pointer to the physical frame buffer (0.. FRAME_BUFFER_COUNT-1) -// Returns NULL if the framebuffer index is out of range. -static uint8_t *get_fb_ptr(uint32_t index) { return physical_frame_buffer_0; } - -bool display_get_frame_buffer(display_fb_info_t *fb) { - fb->ptr = get_fb_ptr(0); - fb->stride = DISPLAY_RESX * sizeof(uint16_t); - // Enable access to the frame buffer from the unprivileged code - mpu_set_active_fb(fb->ptr, PHYSICAL_FRAME_BUFFER_SIZE); - - return true; -} - -void display_refresh(void) {} -void display_fill(const gfx_bitblt_t *bb) {} -void display_copy_rgb565(const gfx_bitblt_t *bb) {} -void display_copy_mono4(const gfx_bitblt_t *bb) {} -void display_copy_mono1p(const gfx_bitblt_t *bb) {} - -#endif diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h index 87e5edcc57..e2ca815e08 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h @@ -8,6 +8,13 @@ #define BTN_POWER_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE #define DISPLAY_COLOR_MODE DMA2D_OUTPUT_RGB565 +#define DISPLAY_PANEL_LX200D2406A +#define DISPLAY_RESET_PIN GPIO_PIN_2 +#define DISPLAY_RESET_PORT GPIOE +#define DISPLAY_RESET_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE +#define DISPLAY_PWREN_PIN GPIO_PIN_0 +#define DISPLAY_PWREN_PORT GPIOE +#define DISPLAY_PWREN_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE #define BACKLIGHT_PWM_FREQ 1000 #define BACKLIGHT_PWM_TIM TIM17 diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py index 19012a721a..6ad5f2fd94 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py @@ -39,7 +39,11 @@ def configure( ] sources += [ - "embed/io/display/st7785ma/display_driver.c", + "embed/io/display/ltdc_dsi/display_driver.c", + "embed/io/display/ltdc_dsi/panels/lx200d2406a/lx200d2406a.c", + "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", ] From ee77086f92ab8aa64331fca8eb7409482b60fc7e Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Mon, 2 Dec 2024 14:20:08 +0100 Subject: [PATCH 3/3] refactor(core): switch DISC2 display driver to universal LTDC DSI implementation [no changelog] --- .../panels/stm32u5a9j-dk/stm32u5a9j-dk.c} | 155 +- .../panels/stm32u5a9j-dk/stm32u5a9j-dk.h | 55 + .../io/display/stm32u5a9j-dk/display_driver.c | 226 --- .../io/display/stm32u5a9j-dk/display_fb.c | 124 -- .../display/stm32u5a9j-dk/display_internal.h | 88 - .../display/stm32u5a9j-dk/display_ltdc_dsi.c | 1559 ----------------- core/embed/models/D002/boards/stm32u5g9j-dk.h | 8 + core/site_scons/models/D002/discovery2.py | 9 +- 8 files changed, 184 insertions(+), 2040 deletions(-) rename core/embed/io/display/{stm32u5a9j-dk/display_gfxmmu_lut.h => ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.c} (86%) create mode 100644 core/embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.h delete mode 100644 core/embed/io/display/stm32u5a9j-dk/display_driver.c delete mode 100644 core/embed/io/display/stm32u5a9j-dk/display_fb.c delete mode 100644 core/embed/io/display/stm32u5a9j-dk/display_internal.h delete mode 100644 core/embed/io/display/stm32u5a9j-dk/display_ltdc_dsi.c diff --git a/core/embed/io/display/stm32u5a9j-dk/display_gfxmmu_lut.h b/core/embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.c similarity index 86% rename from core/embed/io/display/stm32u5a9j-dk/display_gfxmmu_lut.h rename to core/embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.c index ac502356d4..afb39c7ead 100644 --- a/core/embed/io/display/stm32u5a9j-dk/display_gfxmmu_lut.h +++ b/core/embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.c @@ -1,35 +1,9 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * File Name : gfxmmu_lut.h - * Description : header file for GFX MMU Configuration Table - ****************************************************************************** - * @attention - * - * Copyright (c) 2022 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __gfxmmu_lut_H -#define __gfxmmu_lut_H -#ifdef __cplusplus -extern "C" { -#endif -// GFX MMU Configuration Table +#ifdef KERNEL_MODE +#include -#define GFXMMU_FB_SIZE 733936 -#define GFXMMU_LUT_FIRST 0 -#define GFXMMU_LUT_LAST 479 -#define GFXMMU_LUT_SIZE 480 +#include "../../display_internal.h" -static const uint32_t gfxmmu_lut_config[2 * GFXMMU_LUT_SIZE] = { +const uint32_t gfxmmu_lut_config[2 * GFXMMU_LUT_SIZE] = { 0x00413601, // GFXMMU_LUT0L 0x003FFCA0, // GFXMMU_LUT0H 0x00433401, // GFXMMU_LUT1L @@ -992,15 +966,116 @@ static const uint32_t gfxmmu_lut_config[2 * GFXMMU_LUT_SIZE] = { 0x000B2ED0 // GFXMMU_LUT479H }; -#ifdef __cplusplus +void panel_init(display_driver_t* drv) { + /* CMD Mode */ + uint8_t InitParam1[3] = {0xFF, 0x83, 0x79}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 3, 0xB9, + InitParam1); + + /* SETPOWER */ + uint8_t InitParam2[16] = {0x44, 0x1C, 0x1C, 0x37, 0x57, 0x90, 0xD0, 0xE2, + 0x58, 0x80, 0x38, 0x38, 0xF8, 0x33, 0x34, 0x42}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 16, 0xB1, + InitParam2); + + /* SETDISP */ + uint8_t InitParam3[9] = {0x80, 0x14, 0x0C, 0x30, 0x20, + 0x50, 0x11, 0x42, 0x1D}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 9, 0xB2, + InitParam3); + + /* Set display cycle timing */ + uint8_t InitParam4[10] = {0x01, 0xAA, 0x01, 0xAF, 0x01, + 0xAF, 0x10, 0xEA, 0x1C, 0xEA}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 10, 0xB4, + InitParam4); + + /* SETVCOM */ + uint8_t InitParam5[4] = {00, 00, 00, 0xC0}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, 0xC7, + InitParam5); + + /* Set Panel Related Registers */ + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xCC, 0x02); + + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xD2, 0x77); + + uint8_t InitParam6[37] = {0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x32, + 0x10, 0x01, 0x00, 0x01, 0x03, 0x72, 0x03, 0x72, + 0x00, 0x08, 0x00, 0x08, 0x33, 0x33, 0x05, 0x05, + 0x37, 0x05, 0x05, 0x37, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x01, 0x00, 0x0E}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 37, 0xD3, + InitParam6); + + uint8_t InitParam7[34] = { + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x18, 0x18, + 0x18, 0x18, 0x19, 0x19, 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, + 0x23, 0x22, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 34, 0xD5, + InitParam7); + + uint8_t InitParam8[32] = {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x19, 0x19, 0x18, 0x18, 0x19, 0x19, 0x18, 0x18, + 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, + 0x20, 0x21, 0x22, 0x23, 0x18, 0x18, 0x18, 0x18}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 35, 0xD6, + InitParam8); + + /* SET GAMMA */ + uint8_t InitParam9[42] = { + 0x00, 0x16, 0x1B, 0x30, 0x36, 0x3F, 0x24, 0x40, 0x09, 0x0D, 0x0F, + 0x18, 0x0E, 0x11, 0x12, 0x11, 0x14, 0x07, 0x12, 0x13, 0x18, 0x00, + 0x17, 0x1C, 0x30, 0x36, 0x3F, 0x24, 0x40, 0x09, 0x0C, 0x0F, 0x18, + 0x0E, 0x11, 0x14, 0x11, 0x12, 0x07, 0x12, 0x14, 0x18}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xE0, + InitParam9); + + uint8_t InitParam10[3] = {0x2C, 0x2C, 00}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 3, 0xB6, + InitParam10); + + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, 0x00); + + uint8_t InitParam11[] = {0x01, 0x00, 0x07, 0x0F, 0x16, 0x1F, 0x27, 0x30, 0x38, + 0x40, 0x47, 0x4E, 0x56, 0x5D, 0x65, 0x6D, 0x74, 0x7D, + 0x84, 0x8A, 0x90, 0x99, 0xA1, 0xA9, 0xB0, 0xB6, 0xBD, + 0xC4, 0xCD, 0xD4, 0xDD, 0xE5, 0xEC, 0xF3, 0x36, 0x07, + 0x1C, 0xC0, 0x1B, 0x01, 0xF1, 0x34, 0x00}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, + InitParam11); + + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, 0x01); + + uint8_t InitParam12[] = {0x00, 0x08, 0x0F, 0x16, 0x1F, 0x28, 0x31, 0x39, 0x41, + 0x48, 0x51, 0x59, 0x60, 0x68, 0x70, 0x78, 0x7F, 0x87, + 0x8D, 0x94, 0x9C, 0xA3, 0xAB, 0xB3, 0xB9, 0xC1, 0xC8, + 0xD0, 0xD8, 0xE0, 0xE8, 0xEE, 0xF5, 0x3B, 0x1A, 0xB6, + 0xA0, 0x07, 0x45, 0xC5, 0x37, 0x00}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, + InitParam12); + + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, 0x02); + + uint8_t InitParam13[42] = { + 0x00, 0x09, 0x0F, 0x18, 0x21, 0x2A, 0x34, 0x3C, 0x45, 0x4C, 0x56, + 0x5E, 0x66, 0x6E, 0x76, 0x7E, 0x87, 0x8E, 0x95, 0x9D, 0xA6, 0xAF, + 0xB7, 0xBD, 0xC5, 0xCE, 0xD5, 0xDF, 0xE7, 0xEE, 0xF4, 0xFA, 0xFF, + 0x0C, 0x31, 0x83, 0x3C, 0x5B, 0x56, 0x1E, 0x5A, 0xFF}; + HAL_DSI_LongWrite(&drv->hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, + InitParam13); + + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, 0x00); + + /* Exit Sleep Mode*/ + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x11, 0x00); + + HAL_Delay(120); + + /* Display On */ + HAL_DSI_ShortWrite(&drv->hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, + DSI_SET_DISPLAY_ON, 0x00); + + HAL_Delay(120); } #endif -#endif /*__ gfxmmu_lut_H */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/core/embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.h b/core/embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.h new file mode 100644 index 0000000000..db27320de0 --- /dev/null +++ b/core/embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.h @@ -0,0 +1,55 @@ +/* + * 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 . + */ + +#pragma once + +#define VSYNC 1 +#define VBP 12 +#define VFP 50 +#define VACT 481 +#define HSYNC 2 +#define HBP 1 +#define HFP 1 +#define HACT 480 +#define LCD_WIDTH 480 +#define LCD_HEIGHT 480 + +#define LCD_Y_OFFSET 1 + +#define GFXMMU_FB_SIZE 733936 +#define GFXMMU_LUT_FIRST 0 +#define GFXMMU_LUT_LAST 479 +#define GFXMMU_LUT_SIZE 480 + +#define PANEL_DSI_MODE DSI_VID_MODE_BURST +#define PANEL_DSI_LANES DSI_TWO_DATA_LANES +#define PANEL_LTDC_PIXEL_FORMAT LTDC_PIXEL_FORMAT_ARGB8888 + +// Size of the physical frame buffer in bytes +// +// It's smaller than size of the virtual frame buffer +// due to used GFXMMU settings +#define PHYSICAL_FRAME_BUFFER_SIZE (184320 * 4) + +// Pitch (in pixels) of the virtual frame buffer +#define FRAME_BUFFER_PIXELS_PER_LINE 768 + +// Size of the virtual frame buffer in bytes +#define VIRTUAL_FRAME_BUFFER_SIZE \ + (FRAME_BUFFER_PIXELS_PER_LINE * LCD_HEIGHT * 4) diff --git a/core/embed/io/display/stm32u5a9j-dk/display_driver.c b/core/embed/io/display/stm32u5a9j-dk/display_driver.c deleted file mode 100644 index df8a2d2f22..0000000000 --- a/core/embed/io/display/stm32u5a9j-dk/display_driver.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 - -#include -#include - -#include "display_internal.h" - -#if (DISPLAY_RESX != 240) || (DISPLAY_RESY != 240) -#error "Incompatible display resolution" -#endif - -#ifdef KERNEL_MODE - -// Display driver instance -display_driver_t g_display_driver = { - .initialized = false, -}; - -void display_init(display_content_mode_t mode) { - display_driver_t *drv = &g_display_driver; - - if (drv->initialized) { - return; - } - - if (mode == DISPLAY_RESET_CONTENT) { - __HAL_RCC_DSI_FORCE_RESET(); - __HAL_RCC_LTDC_FORCE_RESET(); - __HAL_RCC_GFXMMU_FORCE_RESET(); - __HAL_RCC_DSI_RELEASE_RESET(); - __HAL_RCC_LTDC_RELEASE_RESET(); - __HAL_RCC_GFXMMU_RELEASE_RESET(); - - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - // Initializes the common periph clock - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI; - PeriphClkInit.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; - PeriphClkInit.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3; - PeriphClkInit.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; - PeriphClkInit.PLL3.PLL3M = 4; - PeriphClkInit.PLL3.PLL3N = 125; - PeriphClkInit.PLL3.PLL3P = 8; - PeriphClkInit.PLL3.PLL3Q = 2; - PeriphClkInit.PLL3.PLL3R = 24; - PeriphClkInit.PLL3.PLL3RGE = RCC_PLLVCIRANGE_0; - PeriphClkInit.PLL3.PLL3FRACN = 0; - PeriphClkInit.PLL3.PLL3ClockOut = RCC_PLL3_DIVP | RCC_PLL3_DIVR; - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); - - // Clear framebuffers - mpu_set_active_fb(physical_frame_buffer_0, PHYSICAL_FRAME_BUFFER_SIZE); - memset(physical_frame_buffer_0, 0x00, PHYSICAL_FRAME_BUFFER_SIZE); - - mpu_set_active_fb(physical_frame_buffer_1, PHYSICAL_FRAME_BUFFER_SIZE); - memset(physical_frame_buffer_1, 0x00, PHYSICAL_FRAME_BUFFER_SIZE); - - mpu_set_active_fb(NULL, 0); - - BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT); - BSP_LCD_SetBrightness(0, 100); - BSP_LCD_DisplayOn(0); - } else { - // Retain display content - BSP_LCD_Reinit(0); - if (drv->current_frame_buffer == 0) { - BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); - } else { - BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); - } - } - - drv->initialized = true; -} - -void display_deinit(display_content_mode_t mode) { - display_driver_t *drv = &g_display_driver; - - if (!drv->initialized) { - if (mode == DISPLAY_RESET_CONTENT) { - __HAL_RCC_DSI_FORCE_RESET(); - __HAL_RCC_LTDC_FORCE_RESET(); - __HAL_RCC_GFXMMU_FORCE_RESET(); - __HAL_RCC_DSI_RELEASE_RESET(); - __HAL_RCC_LTDC_RELEASE_RESET(); - __HAL_RCC_GFXMMU_RELEASE_RESET(); - } - return; - } - - if (mode == DISPLAY_RESET_CONTENT) { - BSP_LCD_DisplayOff(0); - BSP_LCD_SetBrightness(0, 0); - BSP_LCD_DeInit(0); - } - - mpu_set_active_fb(NULL, 0); - - drv->initialized = false; -} - -int display_set_backlight(int level) { - display_driver_t *drv = &g_display_driver; - - if (!drv->initialized) { - return 0; - } - - // Just emulation, not doing anything - drv->backlight_level = level; - return level; -} - -int display_get_backlight(void) { - display_driver_t *drv = &g_display_driver; - - if (!drv->initialized) { - return 0; - } - - return drv->orientation_angle; -} - -int display_set_orientation(int angle) { - display_driver_t *drv = &g_display_driver; - - if (!drv->initialized) { - return 0; - } - - if (angle == 0 || angle == 90 || angle == 180 || angle == 270) { - // Just emulation, not doing anything - drv->orientation_angle = angle; - } - - return drv->orientation_angle; -} - -int display_get_orientation(void) { - display_driver_t *drv = &g_display_driver; - - if (!drv->initialized) { - return 0; - } - - return drv->orientation_angle; -} - -void display_fill(const gfx_bitblt_t *bb) { - display_fb_info_t fb; - - if (!display_get_frame_buffer(&fb)) { - return; - } - - gfx_bitblt_t bb_new = *bb; - bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); - bb_new.dst_stride = fb.stride; - - gfx_rgba8888_fill(&bb_new); -} - -void display_copy_rgb565(const gfx_bitblt_t *bb) { - display_fb_info_t fb; - - if (!display_get_frame_buffer(&fb)) { - return; - } - - gfx_bitblt_t bb_new = *bb; - bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); - bb_new.dst_stride = fb.stride; - - gfx_rgba8888_copy_rgb565(&bb_new); -} - -void display_copy_mono1p(const gfx_bitblt_t *bb) { - display_fb_info_t fb; - - if (!display_get_frame_buffer(&fb)) { - return; - } - - gfx_bitblt_t bb_new = *bb; - bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); - bb_new.dst_stride = fb.stride; - - gfx_rgba8888_copy_mono1p(&bb_new); -} - -void display_copy_mono4(const gfx_bitblt_t *bb) { - display_fb_info_t fb; - - if (!display_get_frame_buffer(&fb)) { - return; - } - - gfx_bitblt_t bb_new = *bb; - bb_new.dst_row = (uint8_t *)fb.ptr + (fb.stride * bb_new.dst_y); - bb_new.dst_stride = fb.stride; - - gfx_rgba8888_copy_mono4(&bb_new); -} - -#endif diff --git a/core/embed/io/display/stm32u5a9j-dk/display_fb.c b/core/embed/io/display/stm32u5a9j-dk/display_fb.c deleted file mode 100644 index df599fa400..0000000000 --- a/core/embed/io/display/stm32u5a9j-dk/display_fb.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 - -#include -#include - -#include "display_internal.h" - -#ifdef USE_TRUSTZONE -#include -#endif - -#ifdef KERNEL_MODE - -// Physical frame buffers in internal SRAM memory -__attribute__((section(".fb1"), aligned(PHYSICAL_FRAME_BUFFER_ALIGNMENT))) -uint8_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE]; - -__attribute__((section(".fb2"), aligned(PHYSICAL_FRAME_BUFFER_ALIGNMENT))) -uint8_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE]; - -#ifdef USE_TRUSTZONE -void display_set_unpriv_access(bool unpriv) { - // To allow unprivileged access both GFXMMU virtual buffers area and - // underlying SRAM region must be configured as unprivileged. - - // Order of GFXMMU and SRAM unprivileged access configuration is important - // to avoid the situation the virtual frame buffer has lower privileges - // than underlying frame buffer in physical memory so LTDC could not - // refresh the display properly. - - if (!unpriv) { - tz_set_gfxmmu_unpriv(unpriv); - } - - tz_set_sram_unpriv((uint32_t)physical_frame_buffer_0, - PHYSICAL_FRAME_BUFFER_SIZE, unpriv); - - tz_set_sram_unpriv((uint32_t)physical_frame_buffer_1, - PHYSICAL_FRAME_BUFFER_SIZE, unpriv); - - if (unpriv) { - tz_set_gfxmmu_unpriv(unpriv); - } - -#ifdef USE_DMA2D - tz_set_dma2d_unpriv(unpriv); -#endif -} -#endif // USE_TRUSTZONE - -bool display_get_frame_buffer(display_fb_info_t *fb) { - display_driver_t *drv = &g_display_driver; - - if (!drv->initialized) { - fb->ptr = NULL; - fb->stride = 0; - return false; - } - - uintptr_t addr; - - if (drv->current_frame_buffer == 0) { - addr = GFXMMU_VIRTUAL_BUFFER1_BASE_S; - } else { - addr = GFXMMU_VIRTUAL_BUFFER0_BASE_S; - } - - uint32_t fb_stride = FRAME_BUFFER_PIXELS_PER_LINE * sizeof(uint32_t); - - // We do not utilize whole area of the display - // (discovery kit display is 480x480 and we need just 240x240) - addr += (480 - DISPLAY_RESY) / 2 * sizeof(uint32_t); - addr += (480 - DISPLAY_RESX) / 2 * fb_stride; - - fb->ptr = (void *)addr; - fb->stride = fb_stride; - - // Enable access to the frame buffer from the unprivileged code - mpu_set_active_fb(fb->ptr, VIRTUAL_FRAME_BUFFER_SIZE); - - return true; -} - -void display_refresh(void) { - display_driver_t *drv = &g_display_driver; - - if (!drv->initialized) { - return; - } - - // Disable access to the frame buffer from the unprivileged code - mpu_set_active_fb(NULL, 0); - - if (drv->current_frame_buffer == 0) { - drv->current_frame_buffer = 1; - BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER1_BASE_S); - } else { - drv->current_frame_buffer = 0; - BSP_LCD_SetFrameBuffer(0, GFXMMU_VIRTUAL_BUFFER0_BASE_S); - } -} - -#endif diff --git a/core/embed/io/display/stm32u5a9j-dk/display_internal.h b/core/embed/io/display/stm32u5a9j-dk/display_internal.h deleted file mode 100644 index d47aee47c9..0000000000 --- a/core/embed/io/display/stm32u5a9j-dk/display_internal.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 . - */ - -#ifndef TREZOR_HAL_DISPLAY_INTERNAL_H -#define TREZOR_HAL_DISPLAY_INTERNAL_H - -#include - -#include - -#ifdef USE_TRUSTZONE -#include -#endif - -// Display driver context. -typedef struct { - // Set if the driver is initialized - bool initialized; - // Current display orientation (0, 90, 180, 270) - int orientation_angle; - // Current backlight level ranging from 0 to 255 - int backlight_level; - // The current frame buffer selector - uint32_t current_frame_buffer; -} display_driver_t; - -// Display driver instance -extern display_driver_t g_display_driver; - -// Hardware requires physical frame buffer alignment -#ifdef USE_TRUSTZONE -#define PHYSICAL_FRAME_BUFFER_ALIGNMENT TZ_SRAM_ALIGNMENT -#else -#define PHYSICAL_FRAME_BUFFER_ALIGNMENT 32 -#endif - -// Size of the physical frame buffer in bytes -// -// It's smaller than size of the virtual frame buffer -// due to used GFXMMU settings -#define PHYSICAL_FRAME_BUFFER_SIZE \ - ALIGN_UP_CONST(184320 * 4, PHYSICAL_FRAME_BUFFER_ALIGNMENT) - -// Pitch (in pixels) of the virtual frame buffer -#define FRAME_BUFFER_PIXELS_PER_LINE 768 - -// Size of the virtual frame buffer in bytes -#define VIRTUAL_FRAME_BUFFER_SIZE \ - (FRAME_BUFFER_PIXELS_PER_LINE * DISPLAY_RESY * 4) - -// Physical frame buffers in internal SRAM memory -// -// Both frame buffers layers in the fixed addresses that -// are shared between bootloaders and the firmware. -extern uint8_t physical_frame_buffer_0[PHYSICAL_FRAME_BUFFER_SIZE]; -extern uint8_t physical_frame_buffer_1[PHYSICAL_FRAME_BUFFER_SIZE]; - -// LCD orientations -#define LCD_ORIENTATION_PORTRAIT 0U -#define LCD_ORIENTATION_LANDSCAPE 1U -#define LCD_ORIENTATION_PORTRAIT_ROT180 2U -#define LCD_ORIENTATION_LANDSCAPE_ROT180 3U - -int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation); -int32_t BSP_LCD_DeInit(uint32_t Instance); -int32_t BSP_LCD_Reinit(uint32_t Instance); -int32_t BSP_LCD_SetBrightness(uint32_t Instance, uint32_t Brightness); -int32_t BSP_LCD_DisplayOn(uint32_t Instance); -int32_t BSP_LCD_DisplayOff(uint32_t Instance); -int32_t BSP_LCD_SetFrameBuffer(uint32_t Instance, uint32_t fb_addr); - -#endif // TREZOR_HAL_DISPLAY_INTERNAL_H diff --git a/core/embed/io/display/stm32u5a9j-dk/display_ltdc_dsi.c b/core/embed/io/display/stm32u5a9j-dk/display_ltdc_dsi.c deleted file mode 100644 index f8df39bff1..0000000000 --- a/core/embed/io/display/stm32u5a9j-dk/display_ltdc_dsi.c +++ /dev/null @@ -1,1559 +0,0 @@ -/** - ****************************************************************************** - * @file stm32u5x9j_discovery_lcd.c - * @author MCD Application Team - * @brief This file includes the driver for Liquid Crystal Display (LCD) - module - * mounted on MB1829A board (ARGB8888 color format). - @verbatim - 1. How To use this driver: - -------------------------- - - This driver is used to drive directly in command mode a LCD TFT using the - DSI interface. - The following IPs are implied : DSI Host IP block working - in conjunction to the LTDC controller. - - This driver is linked by construction to LCD. - - 2. Driver description: - ---------------------- - + Initialization steps: - o Initialize the LCD using the BSP_LCD_Init() function. You can select - display orientation with "Orientation" parameter (portrait, landscape, - portrait with 180 degrees rotation or landscape with 180 degrees - rotation). - o Call BSP_LCD_GetXSize() and BSP_LCD_GetYsize() to get respectively - width and height in pixels of LCD in the current orientation. - o Call BSP_LCD_SetBrightness() and BSP_LCD_GetBrightness() to - respectively set and get LCD brightness. - o Call BSP_LCD_SetActiveLayer() to select the current active layer. - o Call BSP_LCD_GetFormat() to get LCD pixel format supported. - - + Display on LCD: - o Call BSP_LCD_DisplayOn() and BSP_LCD_DisplayOff() to respectively - switch on and switch off the LCD display. - o First, check that frame buffer is available using - BSP_LCD_IsFrameBufferAvailable(). o When frame buffer is available, modify it - using following functions: o Call BSP_LCD_WritePixel() and BSP_LCD_ReadPixel() - to respectively write and read a pixel. o Call BSP_LCD_DrawHLine() to draw a - horizontal line. o Call BSP_LCD_DrawVLine() to draw a vertical line. o Call - BSP_LCD_DrawBitmap() to draw a bitmap. o Call BSP_LCD_FillRect() to draw a - rectangle. o Call BSP_LCD_FillRGBRect() to draw a rectangle with RGB buffer. - o Call BSP_LCD_Refresh() to refresh LCD display. - - + De-initialization steps: - o De-initialize the LCD using the BSP_LCD_DeInit() function. - - @endverbatim - ****************************************************************************** - * @attention - * - * Copyright (c) 2023 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include -#include - -#include -#include "display_internal.h" - -#ifdef KERNEL_MODE - -/* Common Error codes */ -#define BSP_ERROR_NONE 0 -#define BSP_ERROR_NO_INIT -1 -#define BSP_ERROR_WRONG_PARAM -2 -#define BSP_ERROR_BUSY -3 -#define BSP_ERROR_PERIPH_FAILURE -4 -#define BSP_ERROR_COMPONENT_FAILURE -5 -#define BSP_ERROR_UNKNOWN_FAILURE -6 -#define BSP_ERROR_UNKNOWN_COMPONENT -7 -#define BSP_ERROR_BUS_FAILURE -8 -#define BSP_ERROR_CLOCK_FAILURE -9 -#define BSP_ERROR_MSP_FAILURE -10 -#define BSP_ERROR_FEATURE_NOT_SUPPORTED -11 - -#define BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE (-102) -/* Button user interrupt priority */ -#define BSP_BUTTON_USER_IT_PRIORITY \ - 0x0FUL /* Default is lowest priority level */ - -#define LCD_PIXEL_FORMAT_ARGB8888 \ - 0x00000000U /*!< ARGB8888 LTDC pixel format \ - */ -#define LCD_PIXEL_FORMAT_RGB888 0x00000001U /*!< RGB888 LTDC pixel format */ -#define LCD_PIXEL_FORMAT_RGB565 0x00000002U /*!< RGB565 LTDC pixel format */ -#define LCD_PIXEL_FORMAT_ARGB1555 \ - 0x00000003U /*!< ARGB1555 LTDC pixel format \ - */ -#define LCD_PIXEL_FORMAT_ARGB4444 \ - 0x00000004U /*!< ARGB4444 LTDC pixel format \ - */ -#define LCD_PIXEL_FORMAT_L8 0x00000005U /*!< L8 LTDC pixel format */ -#define LCD_PIXEL_FORMAT_AL44 0x00000006U /*!< AL44 LTDC pixel format */ -#define LCD_PIXEL_FORMAT_AL88 0x00000007U /*!< AL88 LTDC pixel format */ -/* LCD instances */ -#define LCD_INSTANCES_NBR 1U - -#define DSI_POWERON_GPIO_PORT GPIOI -#define DSI_POWERON_GPIO_PIN GPIO_PIN_5 -#define DSI_POWERON_GPIO_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() - -#define DSI_RESET_GPIO_PORT GPIOD -#define DSI_RESET_GPIO_PIN GPIO_PIN_5 -#define DSI_RESET_GPIO_CLOCK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE() - -#define VSYNC 1 -#define VBP 12 -#define VFP 50 -#define VACT 481 -#define HSYNC 2 -#define HBP 1 -#define HFP 1 -#define HACT 480 -#define LCD_WIDTH 480 -#define LCD_HEIGHT 480 - -#include "display_gfxmmu_lut.h" - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup STM32U5x9J_DISCOVERY - * @{ - */ - -/** @defgroup STM32U5x9J_DISCOVERY_LCD LCD - * @{ - */ - -/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_Defines LCD Private Constants - * @{ - */ - -/** - * @} - */ - -/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_Variables LCD Private Variables - * @{ - */ - -#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1) -static uint32_t LcdGfxmmu_IsMspCbValid[LCD_INSTANCES_NBR] = {0}; -#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1) */ - -#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) -static uint32_t LcdLtdc_IsMspCbValid[LCD_INSTANCES_NBR] = {0}; -#endif /* (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) */ - -#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) -static uint32_t LcdDsi_IsMspCbValid[LCD_INSTANCES_NBR] = {0}; -#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 1) */ - -GFXMMU_HandleTypeDef hlcd_gfxmmu = {0}; -LTDC_HandleTypeDef hlcd_ltdc = {0}; -DSI_HandleTypeDef hlcd_dsi = {0}; -static DSI_VidCfgTypeDef DSIVidCfg = {0}; - -/** - * @} - */ - -/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_FunctionPrototypes LCD Private - * Function Prototypes - * @{ - */ -static int32_t LCD_Init(void); -static int32_t LCD_DeInit(void); - -static void GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu); -static void GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu); -static void LTDC_MspInit(LTDC_HandleTypeDef *hltdc); -static void LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc); -static void DSI_MspInit(DSI_HandleTypeDef *hdsi); -static void DSI_MspDeInit(DSI_HandleTypeDef *hdsi); -#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) -static void DSI_EndOfRefreshCallback(DSI_HandleTypeDef *hdsi); -#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 1) */ -/** - * @} - */ - -/** @addtogroup STM32U5x9J_DISCOVERY_LCD_Exported_Functions - * @{ - */ -/** - * @brief Initialize the LCD. - * @param Instance LCD Instance. - * @param Orientation LCD_ORIENTATION_PORTRAIT, LCD_ORIENTATION_LANDSCAPE, - * LCD_ORIENTATION_PORTRAIT_ROT180 or - * LCD_ORIENTATION_LANDSCAPE_ROT180. - * @retval BSP status. - */ -int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation) { - memset(&hlcd_gfxmmu, 0, sizeof(hlcd_gfxmmu)); - memset(&hlcd_ltdc, 0, sizeof(hlcd_ltdc)); - memset(&hlcd_dsi, 0, sizeof(hlcd_dsi)); - memset(&DSIVidCfg, 0, sizeof(DSIVidCfg)); - - int32_t status = BSP_ERROR_NONE; - - if ((Instance >= LCD_INSTANCES_NBR) || - (Orientation > LCD_ORIENTATION_LANDSCAPE_ROT180)) { - status = BSP_ERROR_WRONG_PARAM; - } else if ((Orientation == LCD_ORIENTATION_LANDSCAPE) || - (Orientation == LCD_ORIENTATION_LANDSCAPE_ROT180)) { - status = BSP_ERROR_FEATURE_NOT_SUPPORTED; - } else { - if (LCD_Init() != 0) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } - - return status; -} - -/** - * @brief De-Initialize the LCD. - * @param Instance LCD Instance. - * @retval BSP status. - */ -int32_t BSP_LCD_DeInit(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - if (LCD_DeInit() != 0) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } - - return status; -} - -/** - * @brief Set the display on. - * @param Instance LCD Instance. - * @retval BSP status. - */ -int32_t BSP_LCD_DisplayOn(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - /* Set the display on */ - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, - DSI_SET_DISPLAY_ON, 0x00) != HAL_OK) { - status = BSP_ERROR_WRONG_PARAM; - } - } - - return status; -} - -/** - * @brief Set the display off. - * @param Instance LCD Instance. - * @retval BSP status. - */ -int32_t BSP_LCD_DisplayOff(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - /* Set the display off */ - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, - DSI_SET_DISPLAY_OFF, 0x00) != HAL_OK) { - status = BSP_ERROR_WRONG_PARAM; - } - } - - return status; -} - -/** - * @brief Set the display brightness. - * @param Instance LCD Instance. - * @param Brightness [00: Min (black), 100 Max]. - * @retval BSP status. - */ -int32_t BSP_LCD_SetBrightness(uint32_t Instance, uint32_t Brightness) { - int32_t status; - - if ((Instance >= LCD_INSTANCES_NBR) || (Brightness > 100U)) { - status = BSP_ERROR_WRONG_PARAM; - } else { - status = BSP_ERROR_FEATURE_NOT_SUPPORTED; - } - - return status; -} - -/** - * @brief Get the display brightness. - * @param Instance LCD Instance. - * @param Brightness [00: Min (black), 100 Max]. - * @retval BSP status. - */ -int32_t BSP_LCD_GetBrightness(uint32_t Instance, uint32_t *Brightness) { - int32_t status; - - if ((Instance >= LCD_INSTANCES_NBR) || (Brightness == NULL)) { - status = BSP_ERROR_WRONG_PARAM; - } else { - status = BSP_ERROR_FEATURE_NOT_SUPPORTED; - } - - return status; -} - -/** - * @brief Get the LCD X size. - * @param Instance LCD Instance. - * @param Xsize LCD X size. - * @retval BSP status. - */ -int32_t BSP_LCD_GetXSize(uint32_t Instance, uint32_t *Xsize) { - int32_t status = BSP_ERROR_NONE; - - if ((Instance >= LCD_INSTANCES_NBR) || (Xsize == NULL)) { - status = BSP_ERROR_WRONG_PARAM; - } else { - /* Get the display Xsize */ - *Xsize = LCD_WIDTH; - } - - return status; -} - -/** - * @brief Get the LCD Y size. - * @param Instance LCD Instance. - * @param Ysize LCD Y size. - * @retval BSP status. - */ -int32_t BSP_LCD_GetYSize(uint32_t Instance, uint32_t *Ysize) { - int32_t status = BSP_ERROR_NONE; - - if ((Instance >= LCD_INSTANCES_NBR) || (Ysize == NULL)) { - status = BSP_ERROR_WRONG_PARAM; - } else { - /* Get the display Ysize */ - *Ysize = LCD_HEIGHT; - } - - return status; -} - -/** - * @brief Set the LCD active layer. - * @param Instance LCD Instance. - * @param LayerIndex Active layer index. - * @retval BSP status. - */ -int32_t BSP_LCD_SetActiveLayer(uint32_t Instance, uint32_t LayerIndex) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - /* Nothing to do */ - UNUSED(LayerIndex); - } - - return status; -} - -/** - * @brief Get pixel format supported by LCD. - * @param Instance LCD Instance. - * @param Format Pointer on pixel format. - * @retval BSP status. - */ -int32_t BSP_LCD_GetFormat(uint32_t Instance, uint32_t *Format) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - /* Get pixel format supported by LCD */ - *Format = LCD_PIXEL_FORMAT_ARGB8888; - } - - return status; -} - -void MX_GFXMMU_Reinit(GFXMMU_HandleTypeDef *hgfxmmu) { - /* Initialize GFXMMU */ - hgfxmmu->Instance = GFXMMU; - hgfxmmu->Init.BlocksPerLine = GFXMMU_192BLOCKS; - hgfxmmu->Init.DefaultValue = 0xFFFFFFFFU; - hgfxmmu->Init.Buffers.Buf0Address = (uint32_t)physical_frame_buffer_0; - hgfxmmu->Init.Buffers.Buf1Address = (uint32_t)physical_frame_buffer_1; - hgfxmmu->Init.Buffers.Buf2Address = 0; - hgfxmmu->Init.Buffers.Buf3Address = 0; -#if defined(GFXMMU_CR_CE) - hgfxmmu->Init.CachePrefetch.Activation = DISABLE; - hgfxmmu->Init.CachePrefetch.CacheLock = GFXMMU_CACHE_LOCK_DISABLE; - hgfxmmu->Init.CachePrefetch.CacheLockBuffer = - GFXMMU_CACHE_LOCK_BUFFER0; /* NU */ - hgfxmmu->Init.CachePrefetch.CacheForce = GFXMMU_CACHE_FORCE_ENABLE; /* NU */ - hgfxmmu->Init.CachePrefetch.OutterBufferability = - GFXMMU_OUTTER_BUFFERABILITY_DISABLE; - hgfxmmu->Init.CachePrefetch.OutterCachability = - GFXMMU_OUTTER_CACHABILITY_DISABLE; - hgfxmmu->Init.CachePrefetch.Prefetch = GFXMMU_PREFETCH_DISABLE; -#endif /* GFXMMU_CR_CE */ -#if defined(GFXMMU_CR_ACE) - hgfxmmu->Init.AddressCache.Activation = DISABLE; - hgfxmmu->Init.AddressCache.AddressCacheLockBuffer = - GFXMMU_ADDRESSCACHE_LOCK_BUFFER0; -#endif /* GFXMMU_CR_ACE */ - hgfxmmu->Init.Interrupts.Activation = DISABLE; - hgfxmmu->Init.Interrupts.UsedInterrupts = GFXMMU_AHB_MASTER_ERROR_IT; /* NU */ -} - -/** - * @brief MX GFXMMU initialization. - * @param hgfxmmu GFXMMU handle. - * @retval HAL status. - */ -__weak HAL_StatusTypeDef MX_GFXMMU_Init(GFXMMU_HandleTypeDef *hgfxmmu) { - MX_GFXMMU_Reinit(hgfxmmu); - return HAL_GFXMMU_Init(hgfxmmu); -} - -/** - * @brief MX LTDC clock configuration. - * @param hltdc LTDC handle. - * @retval HAL status. - */ -__weak HAL_StatusTypeDef MX_LTDC_ClockConfig(LTDC_HandleTypeDef *hltdc) { - RCC_PeriphCLKInitTypeDef PLL3InitPeriph = {0}; - - /* Prevent unused argument(s) compilation warning */ - UNUSED(hltdc); - - /* Start and configurre PLL3 */ - /* HSE = 16MHZ */ - /* 16/(M=4) = 4MHz input (min) */ - /* 4*(N=125) = 500MHz VCO (almost max) */ - /* 500/(P=8) = 62.5 for DSI ie exactly the lane byte clock*/ - /* 500/(R=24) = 20.83 for LTDC exact match with DSI bandwidth */ - PLL3InitPeriph.PeriphClockSelection = RCC_PERIPHCLK_LTDC; - PLL3InitPeriph.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3; - PLL3InitPeriph.PLL3.PLL3M = 4; - PLL3InitPeriph.PLL3.PLL3N = 125; - PLL3InitPeriph.PLL3.PLL3P = 8; - PLL3InitPeriph.PLL3.PLL3Q = 8; - PLL3InitPeriph.PLL3.PLL3R = 24; - PLL3InitPeriph.PLL3.PLL3FRACN = 0; - PLL3InitPeriph.PLL3.PLL3RGE = RCC_PLLVCIRANGE_1; - PLL3InitPeriph.PLL3.PLL3ClockOut = RCC_PLL3_DIVR | RCC_PLL3_DIVP; - PLL3InitPeriph.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; - return HAL_RCCEx_PeriphCLKConfig(&PLL3InitPeriph); -} - -void MX_LTDC_Reinit(LTDC_HandleTypeDef *hltdc) { - /* LTDC initialization */ - hltdc->Instance = LTDC; - hltdc->Init.HSPolarity = LTDC_HSPOLARITY_AL; - hltdc->Init.VSPolarity = LTDC_VSPOLARITY_AL; - hltdc->Init.DEPolarity = LTDC_DEPOLARITY_AL; - hltdc->Init.PCPolarity = LTDC_PCPOLARITY_IPC; - hltdc->Init.HorizontalSync = HSYNC - 1; - hltdc->Init.AccumulatedHBP = HSYNC + HBP - 1; - hltdc->Init.AccumulatedActiveW = HACT + HBP + HSYNC - 1; - hltdc->Init.TotalWidth = HACT + HBP + HFP + HSYNC - 1; - hltdc->Init.Backcolor.Red = 0; /* Not used default value */ - hltdc->Init.Backcolor.Green = 0; /* Not used default value */ - hltdc->Init.Backcolor.Blue = 0; /* Not used default value */ - hltdc->Init.Backcolor.Reserved = 0xFF; - - HAL_LTDCEx_StructInitFromVideoConfig(&hlcd_ltdc, &DSIVidCfg); -} - -/** - * @brief MX LTDC initialization. - * @param hltdc LTDC handle. - * @retval HAL status. - */ -__weak HAL_StatusTypeDef MX_LTDC_Init(LTDC_HandleTypeDef *hltdc) { - MX_LTDC_Reinit(hltdc); - - return HAL_LTDC_Init(hltdc); -} - -// HAL_StatusTypeDef MX_LTDC_ReConfigLayer(LTDC_HandleTypeDef *hltdc, uint32_t -// LayerIndex) -//{ -// LTDC_LayerCfgTypeDef LayerCfg = {0}; -// -///* LTDC layer configuration */ -// LayerCfg.WindowX0 = 0; -// LayerCfg.WindowX1 = LCD_WIDTH; -// LayerCfg.WindowY0 = 1; -// LayerCfg.WindowY1 = (uint32_t)LCD_HEIGHT + 1UL; -// LayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888; -// LayerCfg.Alpha = 0xFF; /* NU default value */ -// LayerCfg.Alpha0 = 0; /* NU default value */ -// LayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA; /* Not Used: default -// value */ LayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; /* Not -// Used: default value */ LayerCfg.FBStartAdress = -// GFXMMU_VIRTUAL_BUFFER0_BASE; LayerCfg.ImageWidth = -// FRAME_BUFFER_PIXELS_PER_LINE; /* Number of pixels per line in virtual frame -// buffer */ LayerCfg.ImageHeight = LCD_HEIGHT; LayerCfg.Backcolor.Red = 0; -// /* Not Used: default value */ LayerCfg.Backcolor.Green = 0; /* Not Used: -// default value */ LayerCfg.Backcolor.Blue = 0; /* Not Used: default value */ -// LayerCfg.Bac -// return HAL_LTDC_ConfigLayer(hltdc, &LayerCfg, LayerIndex);kcolor.Reserved = -// 0xFF; -//} - -/** - * @brief MX LTDC layer configuration. - * @param hltdc LTDC handle. - * @param LayerIndex LTDC layer index. - * @retval HAL status. - */ -__weak HAL_StatusTypeDef MX_LTDC_ConfigLayer(LTDC_HandleTypeDef *hltdc, - uint32_t LayerIndex, - uint32_t fb_addr) { - LTDC_LayerCfgTypeDef LayerCfg = {0}; - - /* LTDC layer configuration */ - LayerCfg.WindowX0 = 0; - LayerCfg.WindowX1 = LCD_WIDTH; - LayerCfg.WindowY0 = 1; - LayerCfg.WindowY1 = (uint32_t)LCD_HEIGHT + 1UL; - LayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888; - LayerCfg.Alpha = 0xFF; /* NU default value */ - LayerCfg.Alpha0 = 0; /* NU default value */ - LayerCfg.BlendingFactor1 = - LTDC_BLENDING_FACTOR1_PAxCA; /* Not Used: default value */ - LayerCfg.BlendingFactor2 = - LTDC_BLENDING_FACTOR2_PAxCA; /* Not Used: default value */ - LayerCfg.FBStartAdress = fb_addr; - LayerCfg.ImageWidth = - FRAME_BUFFER_PIXELS_PER_LINE; /* Number of pixels per line in virtual - frame buffer */ - LayerCfg.ImageHeight = LCD_HEIGHT; - LayerCfg.Backcolor.Red = 0; /* Not Used: default value */ - LayerCfg.Backcolor.Green = 0; /* Not Used: default value */ - LayerCfg.Backcolor.Blue = 0; /* Not Used: default value */ - LayerCfg.Backcolor.Reserved = 0xFF; - return HAL_LTDC_ConfigLayer(hltdc, &LayerCfg, LayerIndex); -} - -/** - * @brief MX DSI initialization. - * @param hdsi DSI handle. - * @retval HAL status. - */ -HAL_StatusTypeDef MX_DSI_Reinit(DSI_HandleTypeDef *hdsi) { - /* DSI initialization */ - hdsi->Instance = DSI; - hdsi->Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE; - /* We have 1 data lane at 500Mbps => lane byte clock at 500/8 = 62,5 MHZ */ - /* We want TX escape clock at around 20MHz and under 20MHz so clock division - * is set to 4 */ - hdsi->Init.TXEscapeCkdiv = 4; - hdsi->Init.NumberOfLanes = DSI_TWO_DATA_LANES; - hdsi->Init.PHYFrequencyRange = DSI_DPHY_FRANGE_450MHZ_510MHZ; - hdsi->Init.PHYLowPowerOffset = 0; - - /* Configure the DSI for Video mode */ - DSIVidCfg.VirtualChannelID = 0; - DSIVidCfg.HSPolarity = DSI_HSYNC_ACTIVE_HIGH; - DSIVidCfg.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; - DSIVidCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; - DSIVidCfg.ColorCoding = DSI_RGB888; - DSIVidCfg.Mode = DSI_VID_MODE_BURST; - DSIVidCfg.PacketSize = LCD_WIDTH; - DSIVidCfg.NullPacketSize = 0xFFFU; - DSIVidCfg.HorizontalSyncActive = HSYNC * 3; - DSIVidCfg.HorizontalBackPorch = HBP * 3; - DSIVidCfg.HorizontalLine = (HACT + HSYNC + HBP + HFP) * 3; - DSIVidCfg.VerticalSyncActive = VSYNC; - DSIVidCfg.VerticalBackPorch = VBP; - DSIVidCfg.VerticalFrontPorch = VFP; - DSIVidCfg.VerticalActive = VACT; - DSIVidCfg.LPCommandEnable = DSI_LP_COMMAND_ENABLE; - DSIVidCfg.LPLargestPacketSize = 64; - /* Specify for each region of the video frame, if the transmission of command - * in LP mode is allowed in this region */ - /* while streaming is active in video mode */ - DSIVidCfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE; - DSIVidCfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE; - DSIVidCfg.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE; - DSIVidCfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE; - DSIVidCfg.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE; - DSIVidCfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; - DSIVidCfg.FrameBTAAcknowledgeEnable = DSI_FBTAA_ENABLE; - DSIVidCfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE; - - return HAL_OK; -} - -/** - * @brief MX DSI initialization. - * @param hdsi DSI handle. - * @retval HAL status. - */ -__weak HAL_StatusTypeDef MX_DSI_Init(DSI_HandleTypeDef *hdsi) { - DSI_PLLInitTypeDef PLLInit = {0}; - - /* DSI initialization */ - hdsi->Instance = DSI; - hdsi->Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE; - /* We have 1 data lane at 500Mbps => lane byte clock at 500/8 = 62,5 MHZ */ - /* We want TX escape clock at around 20MHz and under 20MHz so clock division - * is set to 4 */ - hdsi->Init.TXEscapeCkdiv = 4; - hdsi->Init.NumberOfLanes = DSI_TWO_DATA_LANES; - hdsi->Init.PHYFrequencyRange = DSI_DPHY_FRANGE_450MHZ_510MHZ; - hdsi->Init.PHYLowPowerOffset = 0; - - PLLInit.PLLNDIV = 125; - PLLInit.PLLIDF = 4; - PLLInit.PLLODF = 2; - PLLInit.PLLVCORange = DSI_DPHY_VCO_FRANGE_800MHZ_1GHZ; - PLLInit.PLLChargePump = DSI_PLL_CHARGE_PUMP_2000HZ_4400HZ; - PLLInit.PLLTuning = DSI_PLL_LOOP_FILTER_2000HZ_4400HZ; - - if (HAL_DSI_Init(hdsi, &PLLInit) != HAL_OK) { - return HAL_ERROR; - } - - if (HAL_DSI_SetGenericVCID(&hlcd_dsi, 0) != HAL_OK) { - return HAL_ERROR; - } - - /* Configure the DSI for Video mode */ - DSIVidCfg.VirtualChannelID = 0; - DSIVidCfg.HSPolarity = DSI_HSYNC_ACTIVE_HIGH; - DSIVidCfg.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; - DSIVidCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; - DSIVidCfg.ColorCoding = DSI_RGB888; - DSIVidCfg.Mode = DSI_VID_MODE_BURST; - DSIVidCfg.PacketSize = LCD_WIDTH; - DSIVidCfg.NullPacketSize = 0xFFFU; - DSIVidCfg.HorizontalSyncActive = HSYNC * 3; - DSIVidCfg.HorizontalBackPorch = HBP * 3; - DSIVidCfg.HorizontalLine = (HACT + HSYNC + HBP + HFP) * 3; - DSIVidCfg.VerticalSyncActive = VSYNC; - DSIVidCfg.VerticalBackPorch = VBP; - DSIVidCfg.VerticalFrontPorch = VFP; - DSIVidCfg.VerticalActive = VACT; - DSIVidCfg.LPCommandEnable = DSI_LP_COMMAND_ENABLE; - DSIVidCfg.LPLargestPacketSize = 64; - /* Specify for each region of the video frame, if the transmission of command - * in LP mode is allowed in this region */ - /* while streaming is active in video mode */ - DSIVidCfg.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE; - DSIVidCfg.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE; - DSIVidCfg.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE; - DSIVidCfg.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE; - DSIVidCfg.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE; - DSIVidCfg.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; - DSIVidCfg.FrameBTAAcknowledgeEnable = DSI_FBTAA_ENABLE; - DSIVidCfg.LooselyPacked = DSI_LOOSELY_PACKED_DISABLE; - - /* Drive the display */ - if (HAL_DSI_ConfigVideoMode(&hlcd_dsi, &DSIVidCfg) != HAL_OK) { - return HAL_ERROR; - } - - return HAL_OK; -} - -/** - * @brief MX DMA2D initialization. - * @param hdma2d DMA2D handle. - * @param Mode DMA2D transfer mode. - * @param OffLine DMA2D output offset. - * @retval HAL status. - */ -__weak HAL_StatusTypeDef MX_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d, - uint32_t Mode, uint32_t OffLine) { - /* Register to memory mode with ARGB8888 as color Mode */ - hdma2d->Instance = DMA2D; - hdma2d->Init.Mode = Mode; - hdma2d->Init.ColorMode = DMA2D_OUTPUT_ARGB8888; - hdma2d->Init.OutputOffset = OffLine; - hdma2d->Init.AlphaInverted = DMA2D_REGULAR_ALPHA; - hdma2d->Init.RedBlueSwap = DMA2D_RB_REGULAR; - hdma2d->Init.BytesSwap = DMA2D_BYTES_REGULAR; - hdma2d->Init.LineOffsetMode = DMA2D_LOM_PIXELS; - - /* DMA2D Initialization */ - return HAL_DMA2D_Init(hdma2d); -} - -#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 1) -/** - * @brief Register Default LCD GFXMMU Msp Callbacks - * @retval BSP status - */ -int32_t BSP_LCD_GFXMMU_RegisterDefaultMspCallbacks(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_GFXMMU_RESET_HANDLE_STATE(&hlcd_gfxmmu); - - /* Register default MspInit/MspDeInit Callback */ - if (HAL_GFXMMU_RegisterCallback(&hlcd_gfxmmu, HAL_GFXMMU_MSPINIT_CB_ID, - GFXMMU_MspInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_GFXMMU_RegisterCallback(&hlcd_gfxmmu, - HAL_GFXMMU_MSPDEINIT_CB_ID, - GFXMMU_MspDeInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdGfxmmu_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} - -/** - * @brief Register LCD GFXMMU Msp Callback - * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions - * @retval BSP status - */ -int32_t BSP_LCD_GFXMMU_RegisterMspCallbacks(uint32_t Instance, - BSP_LCD_GFXMMU_Cb_t *Callback) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_GFXMMU_RESET_HANDLE_STATE(&hlcd_gfxmmu); - - /* Register MspInit/MspDeInit Callbacks */ - if (HAL_GFXMMU_RegisterCallback(&hlcd_gfxmmu, HAL_GFXMMU_MSPINIT_CB_ID, - Callback->pMspGfxmmuInitCb) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_GFXMMU_RegisterCallback( - &hlcd_gfxmmu, HAL_GFXMMU_MSPDEINIT_CB_ID, - Callback->pMspGfxmmuDeInitCb) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdGfxmmu_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} -#endif /* USE_HAL_GFXMMU_REGISTER_CALLBACKS */ - -#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) -/** - * @brief Register Default LCD LTDC Msp Callbacks - * @retval BSP status - */ -int32_t BSP_LCD_LTDC_RegisterDefaultMspCallbacks(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_LTDC_RESET_HANDLE_STATE(&hlcd_ltdc); - - /* Register default MspInit/MspDeInit Callback */ - if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPINIT_CB_ID, - LTDC_MspInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPDEINIT_CB_ID, - LTDC_MspDeInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdLtdc_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} - -/** - * @brief Register LCD LTDC Msp Callback - * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions - * @retval BSP status - */ -int32_t BSP_LCD_LTDC_RegisterMspCallbacks(uint32_t Instance, - BSP_LCD_LTDC_Cb_t *Callback) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_LTDC_RESET_HANDLE_STATE(&hlcd_ltdc); - - /* Register MspInit/MspDeInit Callbacks */ - if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPINIT_CB_ID, - Callback->pMspLtdcInitCb) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_LTDC_RegisterCallback(&hlcd_ltdc, HAL_LTDC_MSPDEINIT_CB_ID, - Callback->pMspLtdcDeInitCb) != - HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdLtdc_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} -#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ - -#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) -/** - * @brief Register Default LCD DSI Msp Callbacks - * @retval BSP status - */ -int32_t BSP_LCD_DSI_RegisterDefaultMspCallbacks(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_DSI_RESET_HANDLE_STATE(&hlcd_dsi); - - /* Register default MspInit/MspDeInit Callback */ - if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPINIT_CB_ID, - DSI_MspInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPDEINIT_CB_ID, - DSI_MspDeInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdDsi_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} - -/** - * @brief Register LCD DSI Msp Callback - * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions - * @retval BSP status - */ -int32_t BSP_LCD_DSI_RegisterMspCallbacks(uint32_t Instance, - BSP_LCD_DSI_Cb_t *Callback) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_DSI_RESET_HANDLE_STATE(&hlcd_dsi); - - /* Register MspInit/MspDeInit Callbacks */ - if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPINIT_CB_ID, - Callback->pMspDsiInitCb) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_DSI_RegisterCallback(&hlcd_dsi, HAL_DSI_MSPDEINIT_CB_ID, - Callback->pMspDsiDeInitCb) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdDsi_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} -#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ - -#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) -/** - * @brief Register Default LCD DMA2D Msp Callbacks - * @retval BSP status - */ -int32_t BSP_LCD_DMA2D_RegisterDefaultMspCallbacks(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_DMA2D_RESET_HANDLE_STATE(&hlcd_dma2d); - - /* Register default MspInit/MspDeInit Callback */ - if (HAL_DMA2D_RegisterCallback(&hlcd_dma2d, HAL_DMA2D_MSPINIT_CB_ID, - DMA2D_MspInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_DMA2D_RegisterCallback(&hlcd_dma2d, - HAL_DMA2D_MSPDEINIT_CB_ID, - DMA2D_MspDeInit) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdDma2d_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} - -/** - * @brief Register LCD DMA2D Msp Callback - * @param Callbacks pointer to LCD MspInit/MspDeInit callback functions - * @retval BSP status - */ -int32_t BSP_LCD_DMA2D_RegisterMspCallbacks(uint32_t Instance, - BSP_LCD_DMA2D_Cb_t *Callback) { - int32_t status = BSP_ERROR_NONE; - - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - __HAL_DMA2D_RESET_HANDLE_STATE(&hlcd_dma2d); - - /* Register MspInit/MspDeInit Callbacks */ - if (HAL_DMA2D_RegisterCallback(&hlcd_dma2d, HAL_DMA2D_MSPINIT_CB_ID, - Callback->pMspDma2dInitCb) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else if (HAL_DMA2D_RegisterCallback( - &hlcd_dma2d, HAL_DMA2D_MSPDEINIT_CB_ID, - Callback->pMspDma2dDeInitCb) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - LcdDma2d_IsMspCbValid[Instance] = 1U; - } - } - - /* BSP status */ - return status; -} -#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ -/** - * @} - */ - -/** @defgroup STM32U5x9J_DISCOVERY_LCD_Private_Functions LCD Private Functions - * @{ - */ - -/** - * @brief Initialize LCD. - * @retval BSP status. - */ -static int32_t LCD_Init(void) { - int32_t status = BSP_ERROR_NONE; - uint32_t ErrorNumber = 0; - DSI_PHY_TimerTypeDef PhyTimers = {0}; - DSI_HOST_TimeoutTypeDef HostTimeouts = {0}; - - /***************/ - /* GFXMMU init */ - /***************/ -#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) - GFXMMU_MspInit(&hlcd_gfxmmu); -#else - /* Register the GFXMMU MSP Callbacks */ - if (LcdGfxmmu_IsMspCbValid[0] == 0U) { - if (BSP_LCD_GFXMMU_RegisterDefaultMspCallbacks(0) != BSP_ERROR_NONE) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } -#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) */ - - if (status == BSP_ERROR_NONE) { - /* GFXMMU peripheral initialization */ - if (MX_GFXMMU_Init(&hlcd_gfxmmu) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } - /* Initialize LUT */ - else if (HAL_GFXMMU_ConfigLut(&hlcd_gfxmmu, 0, LCD_WIDTH, - (uint32_t)&gfxmmu_lut_config) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - /* Disable non visible lines : from line 480 to 1023 */ - if (HAL_OK != HAL_GFXMMU_DisableLutLines(&hlcd_gfxmmu, LCD_WIDTH, 544)) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } - } - - /************/ - /* DSI init */ - /************/ - if (status == BSP_ERROR_NONE) { -#if (USE_HAL_DSI_REGISTER_CALLBACKS == 0) - DSI_MspInit(&hlcd_dsi); -#else - /* Register the DSI MSP Callbacks */ - if (LcdDsi_IsMspCbValid[0] == 0U) { - if (BSP_LCD_DSI_RegisterDefaultMspCallbacks(0) != BSP_ERROR_NONE) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } -#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 0) */ - - if (status == BSP_ERROR_NONE) { - /* DSI peripheral initialization */ - if (MX_DSI_Init(&hlcd_dsi) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } - } - - /*********************/ - /* LCD configuration */ - /*********************/ - if (status == BSP_ERROR_NONE) { - PhyTimers.ClockLaneHS2LPTime = 11; - PhyTimers.ClockLaneLP2HSTime = 40; - PhyTimers.DataLaneHS2LPTime = 12; - PhyTimers.DataLaneLP2HSTime = 23; - PhyTimers.DataLaneMaxReadTime = 0; - PhyTimers.StopWaitTime = 7; - - if (HAL_DSI_ConfigPhyTimer(&hlcd_dsi, &PhyTimers) != HAL_OK) { - return 6; - } - - HostTimeouts.TimeoutCkdiv = 1; - HostTimeouts.HighSpeedTransmissionTimeout = 0; - HostTimeouts.LowPowerReceptionTimeout = 0; - HostTimeouts.HighSpeedReadTimeout = 0; - HostTimeouts.LowPowerReadTimeout = 0; - HostTimeouts.HighSpeedWriteTimeout = 0; - HostTimeouts.HighSpeedWritePrespMode = 0; - HostTimeouts.LowPowerWriteTimeout = 0; - HostTimeouts.BTATimeout = 0; - - if (HAL_DSI_ConfigHostTimeouts(&hlcd_dsi, &HostTimeouts) != HAL_OK) { - return 7; - } - - if (HAL_DSI_ConfigFlowControl(&hlcd_dsi, DSI_FLOW_CONTROL_BTA) != HAL_OK) { - return 7; - } - - /* Enable the DSI host */ - __HAL_DSI_ENABLE(&hlcd_dsi); - - /*************/ - /* LTDC init */ - /*************/ - if (status == BSP_ERROR_NONE) { - if (MX_LTDC_ClockConfig(&hlcd_ltdc) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { -#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 0) - LTDC_MspInit(&hlcd_ltdc); -#else - /* Register the LTDC MSP Callbacks */ - if (LcdLtdc_IsMspCbValid[0] == 0U) { - if (BSP_LCD_LTDC_RegisterDefaultMspCallbacks(0) != BSP_ERROR_NONE) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } -#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) */ - - if (status == BSP_ERROR_NONE) { - /* LTDC peripheral initialization */ - if (MX_LTDC_Init(&hlcd_ltdc) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } else { - if (MX_LTDC_ConfigLayer(&hlcd_ltdc, LTDC_LAYER_1, - GFXMMU_VIRTUAL_BUFFER0_BASE_S) != HAL_OK) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } - } - } - } - - /* Start DSI */ - if (HAL_DSI_Start(&(hlcd_dsi)) != HAL_OK) { - return 8; - } - - /* CMD Mode */ - uint8_t InitParam1[3] = {0xFF, 0x83, 0x79}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 3, 0xB9, - InitParam1) != HAL_OK) { - ErrorNumber++; - } - - /* SETPOWER */ - uint8_t InitParam2[16] = {0x44, 0x1C, 0x1C, 0x37, 0x57, 0x90, 0xD0, 0xE2, - 0x58, 0x80, 0x38, 0x38, 0xF8, 0x33, 0x34, 0x42}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 16, 0xB1, - InitParam2) != HAL_OK) { - ErrorNumber++; - } - - /* SETDISP */ - uint8_t InitParam3[9] = {0x80, 0x14, 0x0C, 0x30, 0x20, - 0x50, 0x11, 0x42, 0x1D}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 9, 0xB2, - InitParam3) != HAL_OK) { - ErrorNumber++; - } - - /* Set display cycle timing */ - uint8_t InitParam4[10] = {0x01, 0xAA, 0x01, 0xAF, 0x01, - 0xAF, 0x10, 0xEA, 0x1C, 0xEA}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 10, 0xB4, - InitParam4) != HAL_OK) { - ErrorNumber++; - } - - /* SETVCOM */ - uint8_t InitParam5[4] = {00, 00, 00, 0xC0}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, 0xC7, - InitParam5) != HAL_OK) { - ErrorNumber++; - } - - /* Set Panel Related Registers */ - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xCC, - 0x02) != HAL_OK) { - ErrorNumber++; - } - - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xD2, - 0x77) != HAL_OK) { - ErrorNumber++; - } - - uint8_t InitParam6[37] = {0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x32, - 0x10, 0x01, 0x00, 0x01, 0x03, 0x72, 0x03, 0x72, - 0x00, 0x08, 0x00, 0x08, 0x33, 0x33, 0x05, 0x05, - 0x37, 0x05, 0x05, 0x37, 0x0A, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x01, 0x00, 0x0E}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 37, 0xD3, - InitParam6) != HAL_OK) { - ErrorNumber++; - } - - uint8_t InitParam7[34] = { - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x18, 0x18, - 0x18, 0x18, 0x19, 0x19, 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, - 0x23, 0x22, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 34, 0xD5, - InitParam7) != HAL_OK) { - ErrorNumber++; - } - - uint8_t InitParam8[32] = {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x19, 0x19, 0x18, 0x18, 0x19, 0x19, 0x18, 0x18, - 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, - 0x20, 0x21, 0x22, 0x23, 0x18, 0x18, 0x18, 0x18}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 35, 0xD6, - InitParam8) != HAL_OK) { - ErrorNumber++; - } - - /* SET GAMMA */ - uint8_t InitParam9[42] = { - 0x00, 0x16, 0x1B, 0x30, 0x36, 0x3F, 0x24, 0x40, 0x09, 0x0D, 0x0F, - 0x18, 0x0E, 0x11, 0x12, 0x11, 0x14, 0x07, 0x12, 0x13, 0x18, 0x00, - 0x17, 0x1C, 0x30, 0x36, 0x3F, 0x24, 0x40, 0x09, 0x0C, 0x0F, 0x18, - 0x0E, 0x11, 0x14, 0x11, 0x12, 0x07, 0x12, 0x14, 0x18}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xE0, - InitParam9) != HAL_OK) { - ErrorNumber++; - } - - uint8_t InitParam10[3] = {0x2C, 0x2C, 00}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 3, 0xB6, - InitParam10) != HAL_OK) { - ErrorNumber++; - } - - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, - 0x00) != HAL_OK) { - ErrorNumber++; - } - - uint8_t InitParam11[] = { - 0x01, 0x00, 0x07, 0x0F, 0x16, 0x1F, 0x27, 0x30, 0x38, 0x40, 0x47, - 0x4E, 0x56, 0x5D, 0x65, 0x6D, 0x74, 0x7D, 0x84, 0x8A, 0x90, 0x99, - 0xA1, 0xA9, 0xB0, 0xB6, 0xBD, 0xC4, 0xCD, 0xD4, 0xDD, 0xE5, 0xEC, - 0xF3, 0x36, 0x07, 0x1C, 0xC0, 0x1B, 0x01, 0xF1, 0x34, 0x00}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, - InitParam11) != HAL_OK) { - ErrorNumber++; - } - - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, - 0x01) != HAL_OK) { - ErrorNumber++; - } - - uint8_t InitParam12[] = { - 0x00, 0x08, 0x0F, 0x16, 0x1F, 0x28, 0x31, 0x39, 0x41, 0x48, 0x51, - 0x59, 0x60, 0x68, 0x70, 0x78, 0x7F, 0x87, 0x8D, 0x94, 0x9C, 0xA3, - 0xAB, 0xB3, 0xB9, 0xC1, 0xC8, 0xD0, 0xD8, 0xE0, 0xE8, 0xEE, 0xF5, - 0x3B, 0x1A, 0xB6, 0xA0, 0x07, 0x45, 0xC5, 0x37, 0x00}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, - InitParam12) != HAL_OK) { - ErrorNumber++; - } - - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, - 0x02) != HAL_OK) { - ErrorNumber++; - } - - uint8_t InitParam13[42] = { - 0x00, 0x09, 0x0F, 0x18, 0x21, 0x2A, 0x34, 0x3C, 0x45, 0x4C, 0x56, - 0x5E, 0x66, 0x6E, 0x76, 0x7E, 0x87, 0x8E, 0x95, 0x9D, 0xA6, 0xAF, - 0xB7, 0xBD, 0xC5, 0xCE, 0xD5, 0xDF, 0xE7, 0xEE, 0xF4, 0xFA, 0xFF, - 0x0C, 0x31, 0x83, 0x3C, 0x5B, 0x56, 0x1E, 0x5A, 0xFF}; - if (HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 42, 0xC1, - InitParam13) != HAL_OK) { - ErrorNumber++; - } - - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xBD, - 0x00) != HAL_OK) { - ErrorNumber++; - } - - /* Exit Sleep Mode*/ - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x11, - 0x00) != HAL_OK) { - ErrorNumber++; - } - - HAL_Delay(120); - - /* Display On */ - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x29, - 0x00) != HAL_OK) { - ErrorNumber++; - } - - HAL_Delay(120); - - if (ErrorNumber != 0U) { - status = BSP_ERROR_PERIPH_FAILURE; - } - } - - return status; -} - -/** - * @brief De-Initialize LCD. - * @retval BSP status. - */ -static int32_t LCD_DeInit(void) { - int32_t status = BSP_ERROR_NONE; - uint32_t ErrorNumber = 0; - - /* Disable DSI wrapper */ - __HAL_DSI_WRAPPER_DISABLE(&hlcd_dsi); - - /* Set display off */ - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, - DSI_SET_DISPLAY_OFF, 0x00) != HAL_OK) { - ErrorNumber++; - } - - /* Wait before entering in sleep mode */ - HAL_Delay(2000); - - /* Put LCD in sleep mode */ - if (HAL_DSI_ShortWrite(&hlcd_dsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, - DSI_ENTER_SLEEP_MODE, 0x0) != HAL_OK) { - ErrorNumber++; - } - - HAL_Delay(120); - - /* De-initialize DSI */ - if (HAL_DSI_DeInit(&hlcd_dsi) != HAL_OK) { - ErrorNumber++; - } -#if (USE_HAL_DSI_REGISTER_CALLBACKS == 0) - DSI_MspDeInit(&hlcd_dsi); -#endif /* (USE_HAL_DSI_REGISTER_CALLBACKS == 0) */ - - /* De-initialize LTDC */ - if (HAL_LTDC_DeInit(&hlcd_ltdc) != HAL_OK) { - ErrorNumber++; - } -#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 0) - LTDC_MspDeInit(&hlcd_ltdc); -#endif /* (USE_HAL_LTDC_REGISTER_CALLBACKS == 0) */ - - /* De-initialize GFXMMU */ - if (HAL_GFXMMU_DeInit(&hlcd_gfxmmu) != HAL_OK) { - ErrorNumber++; - } -#if (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) - GFXMMU_MspDeInit(&hlcd_gfxmmu); -#endif /* (USE_HAL_GFXMMU_REGISTER_CALLBACKS == 0) */ - - if (ErrorNumber != 0U) { - status = BSP_ERROR_PERIPH_FAILURE; - } - - return status; -} - -/** - * @brief Initialize GFXMMU MSP. - * @param hgfxmmu GFXMMU handle - * @retval None - */ -static void GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hgfxmmu); - - /* GFXMMU clock enable */ - __HAL_RCC_GFXMMU_CLK_ENABLE(); - - /* Enable GFXMMU interrupt */ - NVIC_SetPriority(GFXMMU_IRQn, IRQ_PRI_NORMAL); - NVIC_EnableIRQ(GFXMMU_IRQn); -} - -/** - * @brief De-Initialize GFXMMU MSP. - * @param hgfxmmu GFXMMU handle - * @retval None - */ -static void GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hgfxmmu); - - /* Disable GFXMMU interrupt */ - NVIC_DisableIRQ(GFXMMU_IRQn); - - /* GFXMMU clock disable */ - __HAL_RCC_GFXMMU_CLK_DISABLE(); -} - -/** - * @brief Initialize LTDC MSP. - * @param hltdc LTDC handle - * @retval None - */ -static void LTDC_MspInit(LTDC_HandleTypeDef *hltdc) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hltdc); - - /* Enable LCD clock */ - __HAL_RCC_LTDC_CLK_ENABLE(); - - /* Enable LTDC interrupt */ - NVIC_SetPriority(LTDC_IRQn, IRQ_PRI_NORMAL); - NVIC_EnableIRQ(LTDC_IRQn); - - NVIC_SetPriority(LTDC_ER_IRQn, IRQ_PRI_NORMAL); - NVIC_EnableIRQ(LTDC_ER_IRQn); -} - -/** - * @brief De-Initialize LTDC MSP. - * @param hltdc LTDC handle - * @retval None - */ -static void LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc) { - /* Prevent unused argument(s) compilation warning */ - UNUSED(hltdc); - - /* Disable LTDC interrupts */ - NVIC_DisableIRQ(LTDC_ER_IRQn); - NVIC_DisableIRQ(LTDC_IRQn); - - /* LTDC clock disable */ - __HAL_RCC_LTDC_CLK_DISABLE(); -} - -/** - * @brief Initialize DSI MSP. - * @param hdsi DSI handle - * @retval None - */ -static void DSI_MspInit(DSI_HandleTypeDef *hdsi) { - RCC_PeriphCLKInitTypeDef PLL3InitPeriph = {0}; - RCC_PeriphCLKInitTypeDef DSIPHYInitPeriph = {0}; - GPIO_InitTypeDef GPIO_InitStruct = {0}; - - UNUSED(hdsi); - - /* Enable GPIOI & GPIOD clocks */ - __HAL_RCC_GPIOD_CLK_ENABLE(); - __HAL_RCC_GPIOI_CLK_ENABLE(); - - /* Configure DSI Reset pin */ - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Pin = GPIO_PIN_5; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - - /* Configure LCD Backlight Pin */ - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Pin = GPIO_PIN_6; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); - - /* Enable DSI clock */ - __HAL_RCC_DSI_CLK_ENABLE(); - - /** ################ Set DSI clock to D-PHY source clock ################## - * **/ - - /* Start and configurre PLL3 */ - /* HSE = 16MHZ */ - /* 16/(M=4) = 4MHz input (min) */ - /* 4*(N=125) = 500MHz VCO (almost max) */ - /* 500/(P=8) = 62.5 for DSI ie exactly the lane byte clock*/ - - PLL3InitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI; - PLL3InitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; - PLL3InitPeriph.PLL3.PLL3M = 4; - PLL3InitPeriph.PLL3.PLL3N = 125; - PLL3InitPeriph.PLL3.PLL3P = 8; - PLL3InitPeriph.PLL3.PLL3Q = 8; - PLL3InitPeriph.PLL3.PLL3R = 24; - PLL3InitPeriph.PLL3.PLL3FRACN = 0; - PLL3InitPeriph.PLL3.PLL3RGE = RCC_PLLVCIRANGE_1; - PLL3InitPeriph.PLL3.PLL3ClockOut = RCC_PLL3_DIVR | RCC_PLL3_DIVP; - PLL3InitPeriph.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; - (void)HAL_RCCEx_PeriphCLKConfig(&PLL3InitPeriph); - - __HAL_RCC_DSI_CLK_ENABLE(); - - /* Switch to D-PHY source clock */ - /* Enable the DSI host */ - hlcd_dsi.Instance = DSI; - - __HAL_DSI_ENABLE(&hlcd_dsi); - - /* Enable the DSI PLL */ - __HAL_DSI_PLL_ENABLE(&hlcd_dsi); - - HAL_Delay(1); - - /* Enable the clock lane and the digital section of the D-PHY */ - hlcd_dsi.Instance->PCTLR |= (DSI_PCTLR_CKE | DSI_PCTLR_DEN); - - /* Set the TX escape clock division factor */ - hlcd_dsi.Instance->CCR = 4; - - HAL_Delay(1); - - /* Config DSI Clock to DSI PHY */ - DSIPHYInitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI; - DSIPHYInitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_DSIPHY; - - (void)HAL_RCCEx_PeriphCLKConfig(&DSIPHYInitPeriph); - - /* Reset */ - HAL_Delay(11); - HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_SET); - HAL_Delay(150); - - /* Reset the TX escape clock division factor */ - hlcd_dsi.Instance->CCR &= ~DSI_CCR_TXECKDIV; - - /* Disable the DSI PLL */ - __HAL_DSI_PLL_DISABLE(&hlcd_dsi); - - /* Disable the DSI host */ - __HAL_DSI_DISABLE(&hlcd_dsi); - - /** ######################################################################### - * **/ - - /* Enable DSI NVIC interrupt */ - /* Default is lowest priority level */ - NVIC_SetPriority(DSI_IRQn, IRQ_PRI_NORMAL); - NVIC_EnableIRQ(DSI_IRQn); -} - -/** - * @brief De-Initialize DSI MSP. - * @param hdsi DSI handle - * @retval None - */ -static void DSI_MspDeInit(DSI_HandleTypeDef *hdsi) { - RCC_PeriphCLKInitTypeDef PLL3InitPeriph = {0}; - - UNUSED(hdsi); - - /* Switch to PLL3 before Disable */ - PLL3InitPeriph.PeriphClockSelection = RCC_PERIPHCLK_DSI; - PLL3InitPeriph.DsiClockSelection = RCC_DSICLKSOURCE_PLL3; - PLL3InitPeriph.PLL3.PLL3M = 4; - PLL3InitPeriph.PLL3.PLL3N = 125; - PLL3InitPeriph.PLL3.PLL3P = 8; - PLL3InitPeriph.PLL3.PLL3Q = 8; - PLL3InitPeriph.PLL3.PLL3R = 24; - PLL3InitPeriph.PLL3.PLL3FRACN = 0; - PLL3InitPeriph.PLL3.PLL3RGE = RCC_PLLVCIRANGE_1; - PLL3InitPeriph.PLL3.PLL3ClockOut = RCC_PLL3_DIVR | RCC_PLL3_DIVP; - PLL3InitPeriph.PLL3.PLL3Source = RCC_PLLSOURCE_HSE; - (void)HAL_RCCEx_PeriphCLKConfig(&PLL3InitPeriph); - - /* DSI clock disable */ - __HAL_RCC_DSI_CLK_DISABLE(); - - /** @brief Toggle Sw reset of DSI IP */ - __HAL_RCC_DSI_FORCE_RESET(); - __HAL_RCC_DSI_RELEASE_RESET(); - - /* Disable DSI interrupts */ - NVIC_DisableIRQ(DSI_IRQn); -} - -int32_t BSP_LCD_SetFrameBuffer(uint32_t Instance, uint32_t fb_addr) { - int32_t status = BSP_ERROR_NONE; - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - MX_LTDC_ConfigLayer(&hlcd_ltdc, 0, fb_addr); - } - - return status; -} - -int32_t BSP_LCD_Reinit(uint32_t Instance) { - int32_t status = BSP_ERROR_NONE; - if (Instance >= LCD_INSTANCES_NBR) { - status = BSP_ERROR_WRONG_PARAM; - } else { - // Switch to D-PHY source clock - // Enable the DSI host - hlcd_dsi.Instance = DSI; - - MX_GFXMMU_Reinit(&hlcd_gfxmmu); - MX_DSI_Reinit(&hlcd_dsi); - MX_LTDC_Reinit(&hlcd_ltdc); - } - - return status; -} - -#endif diff --git a/core/embed/models/D002/boards/stm32u5g9j-dk.h b/core/embed/models/D002/boards/stm32u5g9j-dk.h index 3791696691..4ee0255c58 100644 --- a/core/embed/models/D002/boards/stm32u5g9j-dk.h +++ b/core/embed/models/D002/boards/stm32u5g9j-dk.h @@ -4,6 +4,14 @@ #define VDD_1V8 1 #define DISPLAY_COLOR_MODE DMA2D_OUTPUT_ARGB8888 +#define DISPLAY_PANEL_STM32U5A9J_DK +#define DISPLAY_GFXMMU 1 +#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 I2C_COUNT 1 #define I2C_INSTANCE_0 I2C5 diff --git a/core/site_scons/models/D002/discovery2.py b/core/site_scons/models/D002/discovery2.py index 4b953742e3..84fe59c14b 100644 --- a/core/site_scons/models/D002/discovery2.py +++ b/core/site_scons/models/D002/discovery2.py @@ -39,9 +39,12 @@ def configure( ] sources += [ - "embed/io/display/stm32u5a9j-dk/display_driver.c", - "embed/io/display/stm32u5a9j-dk/display_fb.c", - "embed/io/display/stm32u5a9j-dk/display_ltdc_dsi.c", + "embed/io/display/ltdc_dsi/display_driver.c", + "embed/io/display/ltdc_dsi/panels/stm32u5a9j-dk/stm32u5a9j-dk.c", + "embed/io/display/ltdc_dsi/display_fb.c", + "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", ] paths += ["embed/io/display/inc"]