diff --git a/components/esp_lcd/Kconfig b/components/esp_lcd/Kconfig index 0cc7d93381..21c8cd279b 100644 --- a/components/esp_lcd/Kconfig +++ b/components/esp_lcd/Kconfig @@ -1,10 +1,4 @@ menu "ESP-Driver:LCD Controller Configurations" - config LCD_ENABLE_DEBUG_LOG - bool "Enable debug log" - default n - help - whether to enable the debug log message for LCD driver. - Note that, this option only controls the LCD driver log, won't affect other drivers. if SOC_LCD_RGB_SUPPORTED config LCD_RGB_ISR_IRAM_SAFE @@ -28,14 +22,37 @@ menu "ESP-Driver:LCD Controller Configurations" endif # SOC_LCD_RGB_SUPPORTED if SOC_MIPI_DSI_SUPPORTED - config LCD_DSI_ISR_IRAM_SAFE - bool "DSI LCD ISR IRAM-Safe" - default n - select DW_GDMA_ISR_IRAM_SAFE # relies on DW_GDMA Full trans done interrupt + config LCD_DSI_ISR_HANDLER_IN_IRAM + bool "Place DSI ISR handler in IRAM to reduce latency" + default y + select LCD_DSI_OBJ_FORCE_INTERNAL help - Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be - executable when the cache is disabled (e.g. SPI Flash write). - If you want the LCD driver to keep flushing the screen even when cache ops disabled, - you can enable this option. Note, this will also increase the IRAM usage. + Place DSI ISR handler in IRAM to reduce latency caused by cache miss. + + config LCD_DSI_ISR_CACHE_SAFE + bool "Allow DSI ISR to execute when cache is disabled" if !SPI_FLASH_AUTO_SUSPEND + select LCD_DSI_ISR_HANDLER_IN_IRAM + select DW_GDMA_ISR_IRAM_SAFE # relies on DW_GDMA Full trans done interrupt + default n + help + Enable this option to allow the DSI Interrupt Service Routine (ISR) + to execute even when the cache is disabled. This can be useful in scenarios where the cache + might be turned off, but the DSI functionality is still required to operate correctly. + + config LCD_DSI_OBJ_FORCE_INTERNAL + bool + default n + help + This will ensure the DSI driver object will always be allocated in internal RAM. endif # SOC_MIPI_DSI_SUPPORTED + + config LCD_ENABLE_DEBUG_LOG + bool "Force enable debug log" + default n + help + If enabled, LCD driver component will: + 1. ignore the global logging settings + 2. compile all log messages into the binary + 3. set the runtime log level to VERBOSE + Please enable this option by caution, as it will increase the binary size. endmenu diff --git a/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c b/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c index 1c188b3ffb..3a52c5bd1e 100644 --- a/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c +++ b/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c @@ -1,19 +1,12 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "soc/soc_caps.h" -#include "esp_check.h" #include "esp_lcd_mipi_dsi.h" #include "esp_clk_tree.h" -#include "esp_private/esp_clk_tree_common.h" #include "mipi_dsi_priv.h" -static const char *TAG = "lcd.dsi.bus"; - #define MIPI_DSI_DEFAULT_TIMEOUT_CLOCK_FREQ_MHZ 10 // TxClkEsc frequency must be configured between 2 and 20 MHz #define MIPI_DSI_DEFAULT_ESCAPE_CLOCK_FREQ_MHZ 18 @@ -38,25 +31,31 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc dsi_bus->bus_id = bus_id; // Enable the APB clock for accessing the DSI host and bridge registers - DSI_RCC_ATOMIC() { + PERIPH_RCC_ATOMIC() { mipi_dsi_ll_enable_bus_clock(bus_id, true); mipi_dsi_ll_reset_register(bus_id); } // if the clock source is not assigned, fallback to the default clock source - mipi_dsi_phy_clock_source_t phy_clk_src = bus_config->phy_clk_src; + mipi_dsi_phy_pllref_clock_source_t phy_clk_src = bus_config->phy_clk_src; if (phy_clk_src == 0) { - phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT; +#if SOC_IS(ESP32P4) && HAL_CONFIG(CHIP_SUPPORT_MIN_REV) < 300 + phy_clk_src = MIPI_DSI_PHY_PLLREF_CLK_SRC_DEFAULT_LEGACY; +#else + phy_clk_src = MIPI_DSI_PHY_PLLREF_CLK_SRC_DEFAULT; +#endif } ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)phy_clk_src, true), err, TAG, "clock source enable failed"); // enable the clock source for DSI PHY - DSI_CLOCK_SRC_ATOMIC() { - // set clock source for DSI PHY - mipi_dsi_ll_set_phy_clock_source(bus_id, phy_clk_src); + PERIPH_RCC_ATOMIC() { + // set the DSI PHY configuration clock // the configuration clock is used for all modes except the shutdown mode + mipi_dsi_ll_set_phy_config_clock_source(bus_id, MIPI_DSI_PHY_CFG_CLK_SRC_DEFAULT); mipi_dsi_ll_enable_phy_config_clock(bus_id, true); - // enable the clock for generating the serial clock - mipi_dsi_ll_enable_phy_reference_clock(bus_id, true); + // set the DSI PHY PLL reference clock + mipi_dsi_ll_set_phy_pllref_clock_source(bus_id, phy_clk_src); + mipi_dsi_ll_set_phy_pll_ref_clock_div(bus_id, 1); // no division + mipi_dsi_ll_enable_phy_pllref_clock(bus_id, true); } #if CONFIG_PM_ENABLE @@ -135,12 +134,12 @@ esp_err_t esp_lcd_del_dsi_bus(esp_lcd_dsi_bus_handle_t bus) ESP_RETURN_ON_FALSE(bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); int bus_id = bus->bus_id; // disable the clock source for DSI PHY - DSI_CLOCK_SRC_ATOMIC() { - mipi_dsi_ll_enable_phy_reference_clock(bus_id, false); + PERIPH_RCC_ATOMIC() { + mipi_dsi_ll_enable_phy_pllref_clock(bus_id, false); mipi_dsi_ll_enable_phy_config_clock(bus_id, false); } // disable the APB clock for accessing the DSI peripheral registers - DSI_RCC_ATOMIC() { + PERIPH_RCC_ATOMIC() { mipi_dsi_ll_enable_bus_clock(bus_id, false); } #if CONFIG_PM_ENABLE @@ -152,3 +151,11 @@ esp_err_t esp_lcd_del_dsi_bus(esp_lcd_dsi_bus_handle_t bus) free(bus); return ESP_OK; } + +#if CONFIG_LCD_ENABLE_DEBUG_LOG +__attribute__((constructor)) +static void mipi_dsi_override_default_log_level(void) +{ + esp_log_level_set(TAG, ESP_LOG_VERBOSE); +} +#endif diff --git a/components/esp_lcd/dsi/esp_lcd_panel_dpi.c b/components/esp_lcd/dsi/esp_lcd_panel_dpi.c index e71800d0c1..de46cbb589 100644 --- a/components/esp_lcd/dsi/esp_lcd_panel_dpi.c +++ b/components/esp_lcd/dsi/esp_lcd_panel_dpi.c @@ -4,11 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "soc/soc_caps.h" -#include "esp_check.h" #include "esp_lcd_panel_interface.h" #include "esp_lcd_mipi_dsi.h" #include "esp_clk_tree.h" @@ -17,13 +12,8 @@ #include "esp_async_fbcpy.h" #include "esp_memory_utils.h" #include "esp_private/dw_gdma.h" -#include "esp_private/esp_clk_tree_common.h" -#include "hal/cache_hal.h" -#include "hal/cache_ll.h" #include "hal/color_hal.h" -static const char *TAG = "lcd.dsi.dpi"; - typedef struct esp_lcd_dpi_panel_t esp_lcd_dpi_panel_t; static esp_err_t dpi_panel_del(esp_lcd_panel_t *panel); @@ -77,8 +67,7 @@ static bool async_fbcpy_done_cb(esp_async_fbcpy_handle_t mcp, esp_async_fbcpy_ev return need_yield; } -IRAM_ATTR -static bool dma_trans_done_cb(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data) +bool mipi_dsi_dma_trans_done_cb(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data) { bool yield_needed = false; esp_lcd_dpi_panel_t *dpi_panel = (esp_lcd_dpi_panel_t *)user_data; @@ -152,7 +141,7 @@ static esp_err_t dpi_panel_create_dma_link(esp_lcd_dpi_panel_t *dpi_panel) // register DMA ISR callbacks dw_gdma_event_callbacks_t dsi_dma_cbs = { - .on_full_trans_done = dma_trans_done_cb, + .on_full_trans_done = mipi_dsi_dma_trans_done_cb, }; ESP_RETURN_ON_ERROR(dw_gdma_channel_register_event_callbacks(dma_chan, &dsi_dma_cbs, dpi_panel), TAG, "register DMA callbacks failed"); @@ -232,20 +221,16 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ dpi_panel->num_fbs = num_fbs; // allocate frame buffer from PSRAM - uint32_t cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); - // DMA doesn't have requirement on the buffer alignment, but the cache does - uint32_t alignment = cache_line_size; size_t fb_size = panel_config->video_timing.h_size * panel_config->video_timing.v_size * bits_per_pixel / 8; - uint8_t *frame_buffer = NULL; for (int i = 0; i < num_fbs; i++) { - frame_buffer = heap_caps_aligned_calloc(alignment, 1, fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + uint8_t *frame_buffer = heap_caps_calloc(1, fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); ESP_GOTO_ON_FALSE(frame_buffer, ESP_ERR_NO_MEM, err, TAG, "no memory for frame buffer"); dpi_panel->fbs[i] = frame_buffer; ESP_LOGD(TAG, "fb[%d] @%p", i, frame_buffer); // preset the frame buffer with black color - // the frame buffer address alignment is ensured by `heap_caps_aligned_calloc` + // the frame buffer address alignment is ensured by `heap_caps_calloc` // while the value of the fb_size may not be aligned to the cache line size - // but that's not a problem because the `heap_caps_aligned_calloc` internally allocated a buffer whose size is aligned up to the cache line size + // but that's not a problem because the `heap_caps_calloc` internally allocated a buffer whose size is aligned up to the cache line size ESP_GOTO_ON_ERROR(esp_cache_msync(frame_buffer, fb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED), err, TAG, "cache write back failed"); } @@ -278,7 +263,7 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ uint32_t dpi_div = mipi_dsi_hal_host_dpi_calculate_divider(hal, dpi_clk_src_freq_hz / 1000 / 1000, panel_config->dpi_clock_freq_mhz); ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)dpi_clk_src, true), err, TAG, "clock source enable failed"); // set the clock source, set the divider, and enable the dpi clock - DSI_CLOCK_SRC_ATOMIC() { + PERIPH_RCC_ATOMIC() { mipi_dsi_ll_set_dpi_clock_source(bus_id, dpi_clk_src); mipi_dsi_ll_set_dpi_clock_div(bus_id, dpi_div); mipi_dsi_ll_enable_dpi_clock(bus_id, true); @@ -297,7 +282,7 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ ESP_GOTO_ON_ERROR(dpi_panel_create_dma_link(dpi_panel), err, TAG, "initialize DMA link failed"); mipi_dsi_host_ll_dpi_set_vcid(hal->host, panel_config->virtual_channel); - mipi_dsi_hal_host_dpi_set_color_coding(hal, out_color_format, 0); + mipi_dsi_host_ll_dpi_set_color_coding(hal->host, out_color_format, 0); // these signals define how the DPI interface interacts with the controller mipi_dsi_host_ll_dpi_set_timing_polarity(hal->host, false, false, false, false, false); @@ -335,8 +320,9 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ panel_config->video_timing.vsync_front_porch); mipi_dsi_brg_ll_set_num_pixel_bits(hal->bridge, panel_config->video_timing.h_size * panel_config->video_timing.v_size * bits_per_pixel); mipi_dsi_brg_ll_set_underrun_discard_count(hal->bridge, panel_config->video_timing.h_size); - // set input color space - mipi_dsi_brg_ll_set_input_color_space(hal->bridge, COLOR_SPACE_TYPE(in_color_format)); + // set the in/out color formats in the DSI bridge + mipi_dsi_brg_ll_set_input_color_format(hal->bridge, in_color_format); + mipi_dsi_brg_ll_set_output_color_format(hal->bridge, out_color_format, 0); // use the DW_GDMA as the flow controller mipi_dsi_brg_ll_set_flow_controller(hal->bridge, MIPI_DSI_LL_FLOW_CONTROLLER_DMA); mipi_dsi_brg_ll_set_multi_block_number(hal->bridge, DPI_PANEL_MIN_DMA_NODES_PER_LINK); @@ -366,7 +352,7 @@ static esp_err_t dpi_panel_del(esp_lcd_panel_t *panel) int bus_id = bus->bus_id; mipi_dsi_hal_context_t *hal = &bus->hal; // disable the DPI clock - DSI_CLOCK_SRC_ATOMIC() { + PERIPH_RCC_ATOMIC() { mipi_dsi_ll_enable_dpi_clock(bus_id, false); } // disable the DSI bridge @@ -588,6 +574,7 @@ esp_err_t esp_lcd_dpi_panel_set_color_conversion(esp_lcd_panel_handle_t panel, c if (dpi_panel->in_color_format == COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422) && COLOR_SPACE_TYPE(dpi_panel->out_color_format) == LCD_COLOR_SPACE_RGB) { // YUV422->RGB + mipi_dsi_brg_ll_set_input_color_range(hal->bridge, config->in_color_range); mipi_dsi_brg_ll_set_yuv_convert_std(hal->bridge, config->spec.yuv.conv_std); mipi_dsi_brg_ll_set_yuv422_pack_order(hal->bridge, config->spec.yuv.yuv422.in_pack_order); } else { @@ -625,7 +612,7 @@ esp_err_t esp_lcd_dpi_panel_register_event_callbacks(esp_lcd_panel_handle_t pane { ESP_RETURN_ON_FALSE(panel && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); esp_lcd_dpi_panel_t *dpi_panel = __containerof(panel, esp_lcd_dpi_panel_t, base); -#if CONFIG_LCD_DSI_ISR_IRAM_SAFE +#if CONFIG_LCD_DSI_ISR_HANDLER_IN_IRAM if (cbs->on_color_trans_done) { ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_color_trans_done), ESP_ERR_INVALID_ARG, TAG, "on_color_trans_done callback not in IRAM"); } @@ -635,7 +622,7 @@ esp_err_t esp_lcd_dpi_panel_register_event_callbacks(esp_lcd_panel_handle_t pane if (user_ctx) { ESP_RETURN_ON_FALSE(esp_ptr_internal(user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM"); } -#endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE +#endif // CONFIG_LCD_DSI_ISR_HANDLER_IN_IRAM dpi_panel->on_color_trans_done = cbs->on_color_trans_done; dpi_panel->on_refresh_done = cbs->on_refresh_done; dpi_panel->user_ctx = user_ctx; diff --git a/components/esp_lcd/dsi/esp_lcd_panel_io_dbi.c b/components/esp_lcd/dsi/esp_lcd_panel_io_dbi.c index 369776958d..9ad7782af5 100644 --- a/components/esp_lcd/dsi/esp_lcd_panel_io_dbi.c +++ b/components/esp_lcd/dsi/esp_lcd_panel_io_dbi.c @@ -1,18 +1,12 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "soc/soc_caps.h" -#include "esp_check.h" #include "esp_lcd_panel_io_interface.h" #include "esp_lcd_mipi_dsi.h" #include "mipi_dsi_priv.h" -static const char *TAG = "lcd.dsi.dbi"; - typedef struct esp_lcd_dbi_io_t esp_lcd_dbi_io_t; struct esp_lcd_dbi_io_t { diff --git a/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h b/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h index 1cae1edf42..f8d2c89c36 100644 --- a/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h +++ b/components/esp_lcd/dsi/include/esp_lcd_mipi_dsi.h @@ -23,7 +23,7 @@ extern "C" { typedef struct { int bus_id; /*!< Select which DSI controller, index from 0 */ uint8_t num_data_lanes; /*!< Number of data lanes, if set to 0, the driver will fallback to use maximum number of lanes */ - mipi_dsi_phy_clock_source_t phy_clk_src; /*!< MIPI DSI PHY clock source */ + mipi_dsi_phy_pllref_clock_source_t phy_clk_src; /*!< The clock source for the PHY PLL */ uint32_t lane_bit_rate_mbps; /*!< Lane bit rate in Mbps */ } esp_lcd_dsi_bus_config_t; diff --git a/components/esp_lcd/dsi/mipi_dsi_priv.h b/components/esp_lcd/dsi/mipi_dsi_priv.h index 7014cd2422..9e107eb649 100644 --- a/components/esp_lcd/dsi/mipi_dsi_priv.h +++ b/components/esp_lcd/dsi/mipi_dsi_priv.h @@ -1,29 +1,33 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once -#include "hal/mipi_dsi_hal.h" -#include "hal/mipi_dsi_ll.h" +#include +#include "sdkconfig.h" +#if CONFIG_LCD_ENABLE_DEBUG_LOG +// The local log level must be defined before including esp_log.h +// Set the maximum log level for gptimer driver +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE +#endif +#include "soc/soc_caps_full.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_attr.h" #include "esp_heap_caps.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_pm.h" +#include "hal/mipi_dsi_hal.h" +#include "hal/mipi_dsi_ll.h" -#if SOC_PERIPH_CLK_CTRL_SHARED -#define DSI_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() -#else -#define DSI_CLOCK_SRC_ATOMIC() -#endif - -#if !SOC_RCC_IS_INDEPENDENT -#define DSI_RCC_ATOMIC() PERIPH_RCC_ATOMIC() -#else -#define DSI_RCC_ATOMIC() -#endif - -#if CONFIG_LCD_DSI_ISR_IRAM_SAFE +#if CONFIG_LCD_DSI_OBJ_FORCE_INTERNAL #define DSI_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else #define DSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT @@ -32,6 +36,9 @@ #define DPI_PANEL_MAX_FB_NUM 3 // maximum number of frame buffers that can be maintained by the driver #define DPI_PANEL_MIN_DMA_NODES_PER_LINK 1 // NOTE: we assume 1 DMA link item can carry the WHOLE image +///!< Logging settings +#define TAG "lcd.dsi" + #ifdef __cplusplus extern "C" { #endif diff --git a/components/esp_lcd/linker.lf b/components/esp_lcd/linker.lf index f66d088f22..301f385da5 100644 --- a/components/esp_lcd/linker.lf +++ b/components/esp_lcd/linker.lf @@ -1,17 +1,28 @@ -[mapping:esp_lcd_gdma] +[mapping:esp_lcd_dsi] +archive: libesp_lcd.a +entries: + if LCD_DSI_ISR_HANDLER_IN_IRAM = y: + esp_lcd_panel_dpi: mipi_dsi_dma_trans_done_cb (noflash) + +[mapping:esp_lcd_dsi_dma] +archive: libesp_hw_support.a +entries: + if LCD_DSI_ISR_HANDLER_IN_IRAM = y: + # Control dw_gdma function placement granularly + dw_gdma: dw_gdma_link_list_get_item (noflash) + dw_gdma: dw_gdma_lli_set_block_markers (noflash) + dw_gdma: dw_gdma_channel_use_link_list (noflash) + dw_gdma: dw_gdma_channel_enable_ctrl (noflash) + +[mapping:esp_lcd_rgb_dma] archive: libesp_hw_support.a entries: if LCD_RGB_ISR_IRAM_SAFE = y: gdma: gdma_reset (noflash) gdma: gdma_start (noflash) gdma_link: gdma_link_get_head_addr (noflash) - if LCD_DSI_ISR_IRAM_SAFE = y: - dw_gdma: dw_gdma_link_list_get_item (noflash) - dw_gdma: dw_gdma_lli_set_block_markers (noflash) - dw_gdma: dw_gdma_channel_use_link_list (noflash) - dw_gdma: dw_gdma_channel_enable_ctrl (noflash) -[mapping:esp_lcd_hal] +[mapping:esp_lcd_rgb_hal] archive: libhal.a entries: if LCD_RGB_ISR_IRAM_SAFE = y: diff --git a/components/esp_lcd/sdkconfig.rename b/components/esp_lcd/sdkconfig.rename new file mode 100644 index 0000000000..789cff053a --- /dev/null +++ b/components/esp_lcd/sdkconfig.rename @@ -0,0 +1,4 @@ +# sdkconfig replacement configurations for deprecated options formatted as +# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION + +CONFIG_LCD_DSI_ISR_IRAM_SAFE CONFIG_LCD_DSI_ISR_CACHE_SAFE diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/CMakeLists.txt b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/CMakeLists.txt index 8ee501adae..842c50afd0 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/CMakeLists.txt +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/CMakeLists.txt @@ -2,7 +2,7 @@ set(srcs "test_app_main.c" "test_mipi_dsi_board.c" "test_mipi_dsi_panel.c") -if(CONFIG_LCD_DSI_ISR_IRAM_SAFE) +if(CONFIG_LCD_DSI_ISR_CACHE_SAFE) list(APPEND srcs "test_mipi_dsi_iram.c") endif() diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c index 51299acb8c..724fd369b1 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_iram.c @@ -46,7 +46,6 @@ TEST_CASE("MIPI DSI draw bitmap (EK79007) IRAM Safe", "[mipi_dsi]") esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, .num_data_lanes = 2, - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, .lane_bit_rate_mbps = 1000, // 1000 Mbps }; TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c index aa5579c0d3..8034cabc2b 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/main/test_mipi_dsi_panel.c @@ -28,7 +28,6 @@ TEST_CASE("MIPI DSI Pattern Generator (EK79007)", "[mipi_dsi]") esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, .num_data_lanes = 2, - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, .lane_bit_rate_mbps = 1000, // 1000 Mbps }; TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); @@ -103,7 +102,6 @@ TEST_CASE("MIPI DSI draw bitmap (EK79007)", "[mipi_dsi]") esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, .num_data_lanes = 2, - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, .lane_bit_rate_mbps = 1000, // 1000 Mbps }; TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); @@ -175,7 +173,6 @@ TEST_CASE("MIPI DSI with multiple frame buffers (EK79007)", "[mipi_dsi]") esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, .num_data_lanes = 2, - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, .lane_bit_rate_mbps = 1000, // 1000 Mbps }; TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); @@ -258,7 +255,6 @@ TEST_CASE("MIPI DSI draw YUV422 (EK79007)", "[mipi_dsi]") esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, .num_data_lanes = 2, - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, .lane_bit_rate_mbps = 1000, // 1000 Mbps }; TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py b/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py index 04f1620759..85d7d3fb62 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/pytest_mipi_dsi_lcd.py @@ -9,7 +9,7 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.parametrize( 'config', [ - 'iram_safe', + 'cache_safe', 'release', ], indirect=True, diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/sdkconfig.ci.iram_safe b/components/esp_lcd/test_apps/mipi_dsi_lcd/sdkconfig.ci.cache_safe similarity index 69% rename from components/esp_lcd/test_apps/mipi_dsi_lcd/sdkconfig.ci.iram_safe rename to components/esp_lcd/test_apps/mipi_dsi_lcd/sdkconfig.ci.cache_safe index 17fbfe207f..66ef31174d 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/sdkconfig.ci.iram_safe +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/sdkconfig.ci.cache_safe @@ -1,6 +1,8 @@ CONFIG_COMPILER_DUMP_RTL_FILES=y +CONFIG_LCD_DSI_ISR_CACHE_SAFE=y CONFIG_COMPILER_OPTIMIZATION_NONE=y # silent the error check, as the error string are stored in rodata, causing RTL check failure CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y -CONFIG_LCD_DSI_ISR_IRAM_SAFE=y +CONFIG_HAL_ASSERTION_SILENT=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y diff --git a/components/hal/esp32p4/include/hal/dw_gdma_ll.h b/components/hal/esp32p4/include/hal/dw_gdma_ll.h index 60e5032dde..0295fee38c 100644 --- a/components/hal/esp32p4/include/hal/dw_gdma_ll.h +++ b/components/hal/esp32p4/include/hal/dw_gdma_ll.h @@ -300,6 +300,7 @@ static inline void dw_gdma_ll_channel_clear_intr(dw_gdma_dev_t *dev, uint8_t cha * @param channel Channel number * @param en True to enable, false to disable */ +__attribute__((always_inline)) static inline void dw_gdma_ll_channel_enable(dw_gdma_dev_t *dev, uint8_t channel, bool en) { if (en) { @@ -818,6 +819,7 @@ static inline void dw_gdma_ll_channel_set_dst_outstanding_limit(dw_gdma_dev_t *d * @param channel Channel number * @param addr Address of the first link list item, it must be aligned 64 bytes */ +__attribute__((always_inline)) static inline void dw_gdma_ll_channel_set_link_list_head_addr(dw_gdma_dev_t *dev, uint8_t channel, uint32_t addr) { dev->ch[channel].llp0.loc0 = addr >> 6; @@ -846,6 +848,7 @@ static inline intptr_t dw_gdma_ll_channel_get_current_link_list_item_addr(dw_gdm * @param channel Channel number * @param port Master port */ +__attribute__((always_inline)) static inline void dw_gdma_ll_channel_set_link_list_master_port(dw_gdma_dev_t *dev, uint8_t channel, uint32_t port) { dev->ch[channel].llp0.lms = port; diff --git a/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h b/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h index 3d086af34b..63a54071ca 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h @@ -16,6 +16,7 @@ #define MIPI_DSI_LL_GET_BRG(bus_id) (bus_id == 0 ? &MIPI_DSI_BRIDGE : NULL) #define MIPI_DSI_LL_EVENT_UNDERRUN (1 << 0) +#define MIPI_DSI_LL_EVENT_VSYNC (1 << 1) #ifdef __cplusplus extern "C" { @@ -167,78 +168,6 @@ static inline void mipi_dsi_brg_ll_credit_reset(dsi_brg_dev_t *dev) dev->raw_buf_credit_ctl.credit_reset = 1; } -/** - * @brief Set the color coding for the bridge controller - * - * @param dev Pointer to the DSI bridge controller register base address - * @param color_coding Color coding value - * @param sub_config Sub configuration - */ -#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 -static inline void mipi_dsi_brg_ll_set_pixel_format(dsi_brg_dev_t *dev, lcd_color_format_t color_coding, uint32_t sub_config) -{ - switch (color_coding) { - case LCD_COLOR_FMT_RGB565: - dev->pixel_type.raw_type = 2; - dev->pixel_type.dpi_type = 2; - break; - case LCD_COLOR_FMT_RGB666: - dev->pixel_type.raw_type = 1; - dev->pixel_type.dpi_type = 1; - break; - case LCD_COLOR_FMT_RGB888: - dev->pixel_type.raw_type = 0; - dev->pixel_type.dpi_type = 0; - break; - default: - // MIPI DSI host can only accept RGB data, no YUV data - HAL_ASSERT(false); - break; - } - dev->pixel_type.dpi_config = sub_config; -} -#else -static inline void mipi_dsi_brg_ll_set_pixel_format(dsi_brg_dev_t *dev, lcd_color_format_t color_coding, uint32_t sub_config) -{ - switch (color_coding) { - case LCD_COLOR_FMT_RGB565: - dev->pixel_type.raw_type = 2; - break; - case LCD_COLOR_FMT_RGB666: - dev->pixel_type.raw_type = 1; - break; - case LCD_COLOR_FMT_RGB888: - dev->pixel_type.raw_type = 0; - break; - default: - // MIPI DSI host can only accept RGB data, no YUV data - HAL_ASSERT(false); - break; - } - dev->pixel_type.dpi_config = sub_config; -} -#endif - -/** - * @brief Set the color space for input color data - * - * @param dev Pointer to the DSI bridge controller register base address - * @param color_space Color space type - */ -static inline void mipi_dsi_brg_ll_set_input_color_space(dsi_brg_dev_t *dev, lcd_color_space_t color_space) -{ - switch (color_space) { - case LCD_COLOR_SPACE_RGB: - dev->pixel_type.data_in_type = 0; - break; - case LCD_COLOR_SPACE_YUV: - dev->pixel_type.data_in_type = 1; - break; - default: - abort(); - } -} - /** * @brief Set the vertical timing parameters for the bridge controller * @@ -402,6 +331,157 @@ static inline void mipi_dsi_brg_ll_set_yuv422_pack_order(dsi_brg_dev_t *dev, lcd } } +/**********************************************************************************************************************/ +/************************ The following functions behave differently based on the chip revision ***********************/ +/**********************************************************************************************************************/ + +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +/** + * @brief Set the color format for the input color data + * + * @param dev Pointer to the DSI bridge controller register base address + * @param color_format Color format + */ +static inline void mipi_dsi_brg_ll_set_input_color_format(dsi_brg_dev_t *dev, lcd_color_format_t color_format) +{ + switch (color_format) { + case LCD_COLOR_FMT_RGB888: + dev->pixel_type.raw_type = 0; + dev->pixel_type.data_in_type = 0; + break; + case LCD_COLOR_FMT_RGB666: + dev->pixel_type.raw_type = 1; + dev->pixel_type.data_in_type = 0; + break; + case LCD_COLOR_FMT_RGB565: + dev->pixel_type.raw_type = 2; + dev->pixel_type.data_in_type = 0; + break; + case LCD_COLOR_FMT_YUV422: + dev->pixel_type.raw_type = 9; + dev->pixel_type.data_in_type = 1; + break; + default: + abort(); + } +} + +/** + * @brief Set the color space for output color data + * + * @param dev Pointer to the DSI bridge controller register base address + * @param color_format Color format + */ +static inline void mipi_dsi_brg_ll_set_output_color_format(dsi_brg_dev_t *dev, lcd_color_format_t color_format, uint32_t sub_config) +{ + switch (color_format) { + case LCD_COLOR_FMT_RGB888: + dev->pixel_type.dpi_type = 0; + break; + case LCD_COLOR_FMT_RGB666: + dev->pixel_type.dpi_type = 1; + break; + case LCD_COLOR_FMT_RGB565: + dev->pixel_type.dpi_type = 2; + break; + default: + abort(); + } + dev->pixel_type.dpi_config = sub_config; +} + +/** + * @brief Reset the DSI bridge module + * + * @param dev Pointer to the DSI bridge controller register base address + */ +static inline void mipi_dsi_brg_ll_reset(dsi_brg_dev_t *dev) +{ + dev->en.dsi_brig_rst = 1; + dev->en.dsi_brig_rst = 0; +} + +/** + * @brief Set the color range of input data + * + * @param dev LCD register base address + * @param range Color range + */ +static inline void mipi_dsi_brg_ll_set_input_color_range(dsi_brg_dev_t *dev, lcd_color_range_t range) +{ + if (range == LCD_COLOR_RANGE_LIMIT) { + dev->yuv_cfg.yuv_range = 0; + } else if (range == LCD_COLOR_RANGE_FULL) { + dev->yuv_cfg.yuv_range = 1; + } +} + +#else + +/** + * @brief Set the color format for the input color data + * + * @param dev Pointer to the DSI bridge controller register base address + * @param color_format Color format + */ +static inline void mipi_dsi_brg_ll_set_input_color_format(dsi_brg_dev_t *dev, lcd_color_format_t color_format) +{ + switch (color_format) { + case LCD_COLOR_FMT_RGB888: + dev->pixel_type.raw_type = 0; + dev->pixel_type.data_in_type = 0; + break; + case LCD_COLOR_FMT_RGB666: + dev->pixel_type.raw_type = 1; + dev->pixel_type.data_in_type = 0; + break; + case LCD_COLOR_FMT_RGB565: + dev->pixel_type.raw_type = 2; + dev->pixel_type.data_in_type = 0; + break; + case LCD_COLOR_FMT_YUV422: + dev->pixel_type.data_in_type = 1; + break; + default: + abort(); + } +} + +/** + * @brief Set the color space for output color data + * + * @param dev Pointer to the DSI bridge controller register base address + * @param color_format Color format + */ +static inline void mipi_dsi_brg_ll_set_output_color_format(dsi_brg_dev_t *dev, lcd_color_format_t color_format, uint32_t sub_config) +{ + switch (color_format) { + case LCD_COLOR_FMT_RGB565: + dev->pixel_type.raw_type = 2; + break; + case LCD_COLOR_FMT_RGB666: + dev->pixel_type.raw_type = 1; + break; + case LCD_COLOR_FMT_RGB888: + dev->pixel_type.raw_type = 0; + break; + default: + abort(); + } + dev->pixel_type.dpi_config = sub_config; +} + +static inline void mipi_dsi_brg_ll_reset(dsi_brg_dev_t *dev) +{ + // Not supported +} + +static inline void mipi_dsi_brg_ll_set_input_color_range(dsi_brg_dev_t *dev, lcd_color_range_t range) +{ + // Not supported +} +#endif + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/mipi_dsi_ll.h b/components/hal/esp32p4/include/hal/mipi_dsi_ll.h index d735a543e3..af27b2c332 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_ll.h @@ -10,6 +10,7 @@ #include #include "soc/hp_sys_clkrst_struct.h" #include "hal/misc.h" +#include "hal/config.h" #include "hal/mipi_dsi_host_ll.h" #include "hal/mipi_dsi_brg_ll.h" #include "hal/mipi_dsi_phy_ll.h" @@ -91,11 +92,14 @@ static inline void mipi_dsi_ll_set_dpi_clock_source(int group_id, mipi_dsi_dpi_c case MIPI_DSI_DPI_CLK_SRC_XTAL: HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dpiclk_src_sel = 0; break; + case MIPI_DSI_DPI_CLK_SRC_PLL_F240M: + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dpiclk_src_sel = 1; + break; case MIPI_DSI_DPI_CLK_SRC_PLL_F160M: HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dpiclk_src_sel = 2; break; - case MIPI_DSI_DPI_CLK_SRC_PLL_F240M: - HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dpiclk_src_sel = 1; + case MIPI_DSI_DPI_CLK_SRC_APLL: + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dpiclk_src_sel = 3; break; default: abort(); @@ -148,41 +152,22 @@ static inline void mipi_dsi_ll_enable_phy_config_clock(int group_id, bool enable } while(0) /** - * @brief Enable MIPI DSI PHY PLL reference clock - * - * @param group_id Group ID - * @param enable true to enable, false to disable - */ -static inline void mipi_dsi_ll_enable_phy_reference_clock(int group_id, bool enable) -{ - (void)group_id; - HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dphy_pll_refclk_en = enable; -} - -/// use a macro to wrap the function, force the caller to use it in a critical section -/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define mipi_dsi_ll_enable_phy_reference_clock(...) do { \ - (void)__DECLARE_RCC_ATOMIC_ENV; \ - mipi_dsi_ll_enable_phy_reference_clock(__VA_ARGS__); \ - } while(0) - -/** - * @brief Set the clock source for the DSI PHY interface + * @brief Set the clock source for the DSI PHY configuration interface * * @param group_id Group ID * @param source Clock source */ -static inline void mipi_dsi_ll_set_phy_clock_source(int group_id, mipi_dsi_phy_clock_source_t source) +static inline void _mipi_dsi_ll_set_phy_config_clock_source(int group_id, soc_periph_mipi_dsi_phy_cfg_clk_src_t source) { (void)group_id; switch (source) { - case MIPI_DSI_PHY_CLK_SRC_PLL_F20M: + case MIPI_DSI_PHY_CFG_CLK_SRC_PLL_F20M: HP_SYS_CLKRST.peri_clk_ctrl02.reg_mipi_dsi_dphy_clk_src_sel = 0; break; - case MIPI_DSI_PHY_CLK_SRC_RC_FAST: + case MIPI_DSI_PHY_CFG_CLK_SRC_RC_FAST: HP_SYS_CLKRST.peri_clk_ctrl02.reg_mipi_dsi_dphy_clk_src_sel = 1; break; - case MIPI_DSI_PHY_CLK_SRC_PLL_F25M: + case MIPI_DSI_PHY_CFG_CLK_SRC_PLL_F25M: HP_SYS_CLKRST.peri_clk_ctrl02.reg_mipi_dsi_dphy_clk_src_sel = 2; break; default: @@ -192,11 +177,136 @@ static inline void mipi_dsi_ll_set_phy_clock_source(int group_id, mipi_dsi_phy_c /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define mipi_dsi_ll_set_phy_clock_source(...) do { \ - (void)__DECLARE_RCC_ATOMIC_ENV; \ - mipi_dsi_ll_set_phy_clock_source(__VA_ARGS__); \ +#define mipi_dsi_ll_set_phy_config_clock_source(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _mipi_dsi_ll_set_phy_config_clock_source(__VA_ARGS__); \ } while(0) +/** + * @brief Enable MIPI DSI PHY PLL reference clock + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void mipi_dsi_ll_enable_phy_pllref_clock(int group_id, bool enable) +{ + (void)group_id; + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dphy_pll_refclk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define mipi_dsi_ll_enable_phy_pllref_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + mipi_dsi_ll_enable_phy_pllref_clock(__VA_ARGS__); \ + } while(0) + +/**********************************************************************************************************************/ +/************************ The following functions behave differently based on the chip revision ***********************/ +/**********************************************************************************************************************/ + +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + +/** + * @brief Set the clock source for the DSI PHY PLL reference clock + * + * @param group_id Group ID + * @param source Clock source + */ +static inline void _mipi_dsi_ll_set_phy_pllref_clock_source(int group_id, mipi_dsi_phy_pllref_clock_source_t source) +{ + (void)group_id; + switch (source) { + case MIPI_DSI_PHY_PLLREF_CLK_SRC_XTAL: + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dphy_pll_refclk_src_sel = 0; + break; + case MIPI_DSI_PHY_PLLREF_CLK_SRC_APLL: + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dphy_pll_refclk_src_sel = 1; + break; + case MIPI_DSI_PHY_PLLREF_CLK_SRC_CPLL: + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dphy_pll_refclk_src_sel = 2; + break; + case MIPI_DSI_PHY_PLLREF_CLK_SRC_SPLL: + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dphy_pll_refclk_src_sel = 3; + break; + case MIPI_DSI_PHY_PLLREF_CLK_SRC_MPLL: + HP_SYS_CLKRST.peri_clk_ctrl03.reg_mipi_dsi_dphy_pll_refclk_src_sel = 4; + break; + default: + abort(); + } +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define mipi_dsi_ll_set_phy_pllref_clock_source(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _mipi_dsi_ll_set_phy_pllref_clock_source(__VA_ARGS__); \ + } while(0) + +/** + * @brief Set the clock division factor for the DSI PHY clock source + * + * @param group_id Group ID + * @param div Division factor + */ +static inline void _mipi_dsi_ll_set_phy_pll_ref_clock_div(int group_id, uint32_t div) +{ + (void) group_id; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl03, reg_mipi_dsi_dphy_pll_refclk_div_num, div - 1); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define mipi_dsi_ll_set_phy_pll_ref_clock_div(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _mipi_dsi_ll_set_phy_pll_ref_clock_div(__VA_ARGS__);\ + } while (0) + +#else + +/** + * @brief Set the clock source for the DSI PHY PLL reference clock + * + * @note The PHY PLL reference clock source is same as PHY configuration clock source + * + * @param group_id Group ID + * @param source Clock source + */ +static inline void _mipi_dsi_ll_set_phy_pllref_clock_source(int group_id, mipi_dsi_phy_pllref_clock_source_t source) +{ + (void)group_id; + switch (source) { + case MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F20M: + HP_SYS_CLKRST.peri_clk_ctrl02.reg_mipi_dsi_dphy_clk_src_sel = 0; + break; + case MIPI_DSI_PHY_PLLREF_CLK_SRC_RC_FAST: + HP_SYS_CLKRST.peri_clk_ctrl02.reg_mipi_dsi_dphy_clk_src_sel = 1; + break; + case MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F25M: + HP_SYS_CLKRST.peri_clk_ctrl02.reg_mipi_dsi_dphy_clk_src_sel = 2; + break; + default: + abort(); + } +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define mipi_dsi_ll_set_phy_pllref_clock_source(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _mipi_dsi_ll_set_phy_pllref_clock_source(__VA_ARGS__); \ + } while(0) + +static inline void mipi_dsi_ll_set_phy_pll_ref_clock_div(int group_id, uint32_t div) +{ + // not supported + (void)group_id; + (void)div; +} + +#endif + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/mipi_dsi_hal.h b/components/hal/include/hal/mipi_dsi_hal.h index e3e43b2b3b..d7f3737f52 100644 --- a/components/hal/include/hal/mipi_dsi_hal.h +++ b/components/hal/include/hal/mipi_dsi_hal.h @@ -143,15 +143,6 @@ void mipi_dsi_hal_host_gen_write_short_packet(mipi_dsi_hal_context_t *hal, uint8 void mipi_dsi_hal_host_gen_read_short_packet(mipi_dsi_hal_context_t *hal, uint8_t vc, mipi_dsi_data_type_t dt, uint16_t header_data, void *ret_buffer, uint16_t buffer_size); -/** - * @brief Set DPI color coding - * - * @param hal Pointer to the HAL driver context - * @param color_coding Color coding - * @param sub_config Sub configuration - */ -void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_format_t color_coding, uint32_t sub_config); - /** * @brief Set horizontal timing parameters for DPI * diff --git a/components/hal/include/hal/mipi_dsi_types.h b/components/hal/include/hal/mipi_dsi_types.h index 8c2a880a7e..3d5078bd4b 100644 --- a/components/hal/include/hal/mipi_dsi_types.h +++ b/components/hal/include/hal/mipi_dsi_types.h @@ -9,6 +9,7 @@ #include #include "soc/clk_tree_defs.h" #include "esp_assert.h" +#include "soc/soc_caps.h" #ifdef __cplusplus extern "C" { @@ -58,17 +59,25 @@ typedef enum { } mipi_dsi_pattern_type_t; #if SOC_MIPI_DSI_SUPPORTED + /** - * @brief MIPI DSI PHY clock source + * @brief MIPI DSI PHY PLL reference clock source */ -typedef soc_periph_mipi_dsi_phy_clk_src_t mipi_dsi_phy_clock_source_t; +typedef soc_periph_mipi_dsi_phy_pllref_clk_src_t mipi_dsi_phy_pllref_clock_source_t; /** * @brief MIPI DSI DPI clock source */ typedef soc_periph_mipi_dsi_dpi_clk_src_t mipi_dsi_dpi_clock_source_t; + +/** + * @brief For backward compatibility + */ +typedef mipi_dsi_phy_pllref_clock_source_t mipi_dsi_phy_clock_source_t; + #else -typedef int mipi_dsi_phy_clock_source_t; + +typedef int mipi_dsi_phy_pllref_clock_source_t; typedef int mipi_dsi_dpi_clock_source_t; #endif // SOC_MIPI_DSI_SUPPORTED diff --git a/components/hal/mipi_dsi_hal.c b/components/hal/mipi_dsi_hal.c index 9ca4b6f71e..8e57fab191 100644 --- a/components/hal/mipi_dsi_hal.c +++ b/components/hal/mipi_dsi_hal.c @@ -25,6 +25,8 @@ void mipi_dsi_hal_init(mipi_dsi_hal_context_t *hal, const mipi_dsi_hal_config_t mipi_dsi_phy_ll_reset(hal->host); mipi_dsi_phy_ll_enable_clock_lane(hal->host, true); mipi_dsi_phy_ll_force_pll(hal->host, true); + // reset the dsi bridge + mipi_dsi_brg_ll_reset(hal->bridge); } void mipi_dsi_hal_deinit(mipi_dsi_hal_context_t *hal) @@ -227,12 +229,6 @@ void mipi_dsi_hal_host_gen_read_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t mipi_dsi_hal_host_gen_read_short_packet(hal, vc, MIPI_DSI_DT_DCS_READ_0, header_data, ret_param, param_buf_size); } -void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_color_format_t color_coding, uint32_t sub_config) -{ - mipi_dsi_host_ll_dpi_set_color_coding(hal->host, color_coding, sub_config); - mipi_dsi_brg_ll_set_pixel_format(hal->bridge, color_coding, sub_config); -} - void mipi_dsi_hal_host_dpi_set_horizontal_timing(mipi_dsi_hal_context_t *hal, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp) { float dpi2lane_clk_ratio = (float)hal->lane_bit_rate_mbps / hal->dpi_clock_freq_mhz / 8; diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 80864fd0a8..38b9b6aeb4 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -413,7 +413,7 @@ typedef enum { CAM_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */ } soc_periph_cam_clk_src_t; -/////////////////////////////////////////////////MIPI/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////MIPI CSI/////////////////////////////////////////////////////////////// /** * @brief Array initializer for all supported clock sources of MIPI CSI PHY interface @@ -430,10 +430,12 @@ typedef enum { MIPI_CSI_PHY_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F20M, /*!< Select PLL_F20M as default clock */ } soc_periph_mipi_csi_phy_clk_src_t; +/////////////////////////////////////////////////MIPI DSI/////////////////////////////////////////////////////////////// + /** * @brief Array initializer for all supported clock sources of MIPI DSI DPI interface */ -#define SOC_MIPI_DSI_DPI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_PLL_F240M} +#define SOC_MIPI_DSI_DPI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_PLL_F240M, SOC_MOD_CLK_APLL} /** * @brief Type of MIPI DSI DPI clock source @@ -442,23 +444,46 @@ typedef enum { MIPI_DSI_DPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as MIPI DSI DPI source clock */ MIPI_DSI_DPI_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as MIPI DSI DPI source clock */ MIPI_DSI_DPI_CLK_SRC_PLL_F240M = SOC_MOD_CLK_PLL_F240M, /*!< Select PLL_F240M as MIPI DSI DPI source clock */ + MIPI_DSI_DPI_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as MIPI DSI DPI source clock */ MIPI_DSI_DPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F240M, /*!< Select PLL_F240M as default clock */ } soc_periph_mipi_dsi_dpi_clk_src_t; /** - * @brief Array initializer for all supported clock sources of MIPI DSI PHY interface - */ -#define SOC_MIPI_DSI_PHY_CLKS {SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_PLL_F25M, SOC_MOD_CLK_PLL_F20M} - -/** - * @brief Type of MIPI DSI PHY clock source + * @brief Type of MIPI DSI PHY configuration clock source */ typedef enum { - MIPI_DSI_PHY_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as MIPI DSI PHY source clock */ - MIPI_DSI_PHY_CLK_SRC_PLL_F25M = SOC_MOD_CLK_PLL_F25M, /*!< Select PLL_F25M as MIPI DSI PHY source clock */ - MIPI_DSI_PHY_CLK_SRC_PLL_F20M = SOC_MOD_CLK_PLL_F20M, /*!< Select PLL_F20M as MIPI DSI PHY source clock */ - MIPI_DSI_PHY_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F20M, /*!< Select PLL_F20M as default clock */ -} soc_periph_mipi_dsi_phy_clk_src_t; + MIPI_DSI_PHY_CFG_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as MIPI DSI PHY configuration source clock */ + MIPI_DSI_PHY_CFG_CLK_SRC_PLL_F25M = SOC_MOD_CLK_PLL_F25M, /*!< Select PLL_F25M as MIPI DSI PHY configuration source clock */ + MIPI_DSI_PHY_CFG_CLK_SRC_PLL_F20M = SOC_MOD_CLK_PLL_F20M, /*!< Select PLL_F20M as MIPI DSI PHY configuration source clock */ + MIPI_DSI_PHY_CFG_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F20M, /*!< Select PLL_F20M as default clock */ +} soc_periph_mipi_dsi_phy_cfg_clk_src_t; + +/** + * @brief Type of MIPI DSI PHY PLL reference clock source + */ +typedef enum { + // only available on esp32p4 version < 3.0 + MIPI_DSI_PHY_PLLREF_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F25M = SOC_MOD_CLK_PLL_F25M, /*!< Select PLL_F25M as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F20M = SOC_MOD_CLK_PLL_F20M, /*!< Select PLL_F20M as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_DEFAULT_LEGACY = SOC_MOD_CLK_PLL_F20M, /*!< Select PLL_F20M as default clock */ + + // only available on esp32p4 version >= 3.0 + MIPI_DSI_PHY_PLLREF_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_CPLL = SOC_MOD_CLK_CPLL, /*!< Select CPLL as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_SPLL = SOC_MOD_CLK_SPLL, /*!< Select SPLL as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_MPLL = SOC_MOD_CLK_MPLL, /*!< Select MPLL as MIPI DSI PHY PLL reference clock */ + MIPI_DSI_PHY_PLLREF_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as default clock */ +} soc_periph_mipi_dsi_phy_pllref_clk_src_t; + +/** + * @brief For backward compatibility, old macro definitions are kept. Remove it in the next major release (esp-idf v7.0) + */ +#define MIPI_DSI_PHY_CLK_SRC_RC_FAST SOC_MOD_CLK_RC_FAST +#define MIPI_DSI_PHY_CLK_SRC_PLL_F25M SOC_MOD_CLK_PLL_F25M +#define MIPI_DSI_PHY_CLK_SRC_PLL_F20M SOC_MOD_CLK_PLL_F20M +#define MIPI_DSI_PHY_CLK_SRC_DEFAULT SOC_MOD_CLK_PLL_F20M /////////////////////////////////////////////////I2C//////////////////////////////////////////////////////////////////// diff --git a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst index d24da8cecb..3b1b56ff09 100644 --- a/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/en/api-reference/peripherals/lcd/dsi_lcd.rst @@ -11,7 +11,6 @@ MIPI DSI Interfaced LCD esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, // index from 0, specify the DSI host to use .num_data_lanes = 2, // Number of data lanes to use, can't set a value that exceeds the chip's capability - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, // Clock source for the DPHY .lane_bit_rate_mbps = EXAMPLE_MIPI_DSI_LANE_BITRATE_MBPS, // Bit rate of the data lanes, in Mbps }; ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); diff --git a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst index 4bbba0e0cb..47058f9d46 100644 --- a/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst +++ b/docs/zh_CN/api-reference/peripherals/lcd/dsi_lcd.rst @@ -11,7 +11,6 @@ MIPI DSI 接口的 LCD esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, // 从 0 开始编号,指定要使用的 DSI 主机 .num_data_lanes = 2, // 要使用的数据通道数,不能超过芯片支持的数量 - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, // DPHY 的时钟源 .lane_bit_rate_mbps = EXAMPLE_MIPI_DSI_LANE_BITRATE_MBPS, // 数据通道的比特率 (Mbps) }; ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); diff --git a/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c b/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c index 3cd506cfc0..3b2413b988 100644 --- a/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c +++ b/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c @@ -21,7 +21,6 @@ void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_ esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, .num_data_lanes = 2, - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, .lane_bit_rate_mbps = 1000, // 1000 Mbps }; ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, mipi_dsi_bus)); diff --git a/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c b/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c index a51828a783..01cf4f7dfe 100644 --- a/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c +++ b/examples/peripherals/lcd/mipi_dsi/main/mipi_dsi_lcd_example_main.c @@ -197,7 +197,6 @@ void app_main(void) esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, .num_data_lanes = EXAMPLE_MIPI_DSI_LANE_NUM, - .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, .lane_bit_rate_mbps = EXAMPLE_MIPI_DSI_LANE_BITRATE_MBPS, }; ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));