diff --git a/components/esp_lcd/CMakeLists.txt b/components/esp_lcd/CMakeLists.txt index d748393fab..bffe85979f 100644 --- a/components/esp_lcd/CMakeLists.txt +++ b/components/esp_lcd/CMakeLists.txt @@ -6,27 +6,34 @@ endif() set(srcs "src/esp_lcd_common.c" "src/esp_lcd_panel_io.c" - "src/esp_lcd_panel_io_i2c_v1.c" - "src/esp_lcd_panel_io_i2c_v2.c" - "src/esp_lcd_panel_io_spi.c" "src/esp_lcd_panel_nt35510.c" "src/esp_lcd_panel_ssd1306.c" "src/esp_lcd_panel_st7789.c" "src/esp_lcd_panel_ops.c") set(includes "include" "interface") -set(priv_requires "esp_mm" "esp_psram") +set(priv_requires "esp_mm" "esp_psram" "esp_pm" "esp_driver_spi" "esp_driver_i2s") +set(public_requires "driver" "esp_driver_gpio" "esp_driver_i2c") + +if(CONFIG_SOC_I2C_SUPPORTED) + list(APPEND srcs "i2c/esp_lcd_panel_io_i2c_v1.c" "i2c/esp_lcd_panel_io_i2c_v2.c") +endif() + +if(CONFIG_SOC_GPSPI_SUPPORTED) + list(APPEND srcs "spi/esp_lcd_panel_io_spi.c") +endif() if(CONFIG_SOC_I2S_LCD_I80_VARIANT) - list(APPEND srcs "src/esp_lcd_panel_io_i2s.c") - list(APPEND priv_requires "esp_driver_i2s") + list(APPEND srcs "i80/esp_lcd_panel_io_i2s.c") endif() if(CONFIG_SOC_LCDCAM_SUPPORTED) - list(APPEND srcs "src/esp_lcd_panel_io_i80.c" "src/esp_lcd_panel_rgb.c") + list(APPEND includes "rgb/include") + list(APPEND srcs "i80/esp_lcd_panel_io_i80.c" "rgb/esp_lcd_panel_rgb.c") endif() idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${includes} + PRIV_INCLUDE_DIRS "priv_include" PRIV_REQUIRES ${priv_requires} - REQUIRES driver esp_driver_gpio esp_driver_spi esp_driver_i2c + REQUIRES ${public_requires} LDFRAGMENTS linker.lf) diff --git a/components/esp_lcd/Kconfig b/components/esp_lcd/Kconfig index 25a77c8376..b72408b5ed 100644 --- a/components/esp_lcd/Kconfig +++ b/components/esp_lcd/Kconfig @@ -3,6 +3,7 @@ menu "LCD and Touch Panel" menu "LCD Peripheral Configuration" config LCD_PANEL_IO_FORMAT_BUF_SIZE + depends on SOC_LCD_I80_SUPPORTED int "LCD panel io format buffer size" default 32 help diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c b/components/esp_lcd/i2c/esp_lcd_panel_io_i2c_v1.c similarity index 100% rename from components/esp_lcd/src/esp_lcd_panel_io_i2c_v1.c rename to components/esp_lcd/i2c/esp_lcd_panel_io_i2c_v1.c diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c b/components/esp_lcd/i2c/esp_lcd_panel_io_i2c_v2.c similarity index 100% rename from components/esp_lcd/src/esp_lcd_panel_io_i2c_v2.c rename to components/esp_lcd/i2c/esp_lcd_panel_io_i2c_v2.c diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2s.c b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c similarity index 100% rename from components/esp_lcd/src/esp_lcd_panel_io_i2s.c rename to components/esp_lcd/i80/esp_lcd_panel_io_i2s.c diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c similarity index 100% rename from components/esp_lcd/src/esp_lcd_panel_io_i80.c rename to components/esp_lcd/i80/esp_lcd_panel_io_i80.c diff --git a/components/esp_lcd/src/esp_lcd_common.h b/components/esp_lcd/priv_include/esp_lcd_common.h similarity index 100% rename from components/esp_lcd/src/esp_lcd_common.h rename to components/esp_lcd/priv_include/esp_lcd_common.h diff --git a/components/esp_lcd/src/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c similarity index 100% rename from components/esp_lcd/src/esp_lcd_panel_rgb.c rename to components/esp_lcd/rgb/esp_lcd_panel_rgb.c diff --git a/components/esp_lcd/include/esp_lcd_panel_rgb.h b/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h similarity index 100% rename from components/esp_lcd/include/esp_lcd_panel_rgb.h rename to components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h diff --git a/components/esp_lcd/src/esp_lcd_panel_io_spi.c b/components/esp_lcd/spi/esp_lcd_panel_io_spi.c similarity index 100% rename from components/esp_lcd/src/esp_lcd_panel_io_spi.c rename to components/esp_lcd/spi/esp_lcd_panel_io_spi.c diff --git a/components/esp_lcd/src/esp_lcd_panel_nt35510.c b/components/esp_lcd/src/esp_lcd_panel_nt35510.c index 7fbe7ab37d..aa2a472b23 100644 --- a/components/esp_lcd/src/esp_lcd_panel_nt35510.c +++ b/components/esp_lcd/src/esp_lcd_panel_nt35510.c @@ -80,7 +80,7 @@ esp_lcd_new_panel_nt35510(const esp_lcd_panel_io_handle_t io, const esp_lcd_pane nt35510->madctl_val |= LCD_CMD_BGR_BIT; break; default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space"); + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported RGB element order"); break; } diff --git a/components/esp_lcd/src/esp_lcd_panel_ops.c b/components/esp_lcd/src/esp_lcd_panel_ops.c index 1e03be92d2..acef06ce4e 100644 --- a/components/esp_lcd/src/esp_lcd_panel_ops.c +++ b/components/esp_lcd/src/esp_lcd_panel_ops.c @@ -31,6 +31,7 @@ esp_err_t esp_lcd_panel_del(esp_lcd_panel_handle_t panel) esp_err_t esp_lcd_panel_draw_bitmap(esp_lcd_panel_handle_t panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) { ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid panel handle"); + ESP_RETURN_ON_FALSE(panel->draw_bitmap, ESP_ERR_NOT_SUPPORTED, TAG, "draw_bitmap is not supported by this panel"); return panel->draw_bitmap(panel, x_start, y_start, x_end, y_end, color_data); } diff --git a/components/esp_lcd/src/esp_lcd_panel_st7789.c b/components/esp_lcd/src/esp_lcd_panel_st7789.c index fc43f91582..e6cd329d13 100644 --- a/components/esp_lcd/src/esp_lcd_panel_st7789.c +++ b/components/esp_lcd/src/esp_lcd_panel_st7789.c @@ -85,7 +85,7 @@ esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel st7789->madctl_val |= LCD_CMD_BGR_BIT; break; default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space"); + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported RGB element order"); break; } diff --git a/components/esp_lcd/test_apps/i2c_lcd/main/CMakeLists.txt b/components/esp_lcd/test_apps/i2c_lcd/main/CMakeLists.txt index aa4f3147a3..1b5ee568b6 100644 --- a/components/esp_lcd/test_apps/i2c_lcd/main/CMakeLists.txt +++ b/components/esp_lcd/test_apps/i2c_lcd/main/CMakeLists.txt @@ -4,5 +4,5 @@ set(srcs "test_app_main.c" # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - PRIV_REQUIRES esp_lcd unity driver + PRIV_REQUIRES esp_lcd unity esp_driver_i2c WHOLE_ARCHIVE) diff --git a/components/esp_lcd/test_apps/spi_lcd/main/CMakeLists.txt b/components/esp_lcd/test_apps/spi_lcd/main/CMakeLists.txt index 72a8ae1d4a..77a57a2cc4 100644 --- a/components/esp_lcd/test_apps/spi_lcd/main/CMakeLists.txt +++ b/components/esp_lcd/test_apps/spi_lcd/main/CMakeLists.txt @@ -4,5 +4,5 @@ set(srcs "test_app_main.c" # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - PRIV_REQUIRES esp_lcd unity driver + PRIV_REQUIRES esp_lcd unity esp_driver_spi WHOLE_ARCHIVE) 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 19aed7fb43..7c399550bb 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_brg_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,8 @@ #include "hal/mipi_dsi_types.h" #include "hal/lcd_types.h" +#define MIPI_DSI_LL_GET_BRG(bus_id) (bus_id == 0 ? &MIPI_DSI_BRIDGE : NULL) + #ifdef __cplusplus extern "C" { #endif @@ -46,6 +48,19 @@ static inline void mipi_dsi_brg_ll_set_burst_len(dsi_brg_dev_t *dev, uint32_t bu dev->dma_req_cfg.dma_burst_len = burst_len; } +/** + * @brief Set the fifo empty threshold + * + * @note valid only when dsi_bridge is the flow controller + * + * @param dev Pointer to the DSI bridge controller register base address + * @param threshold Threshold value + */ +static inline void mipi_dsi_brg_ll_set_empty_threshold(dsi_brg_dev_t *dev, uint32_t threshold) +{ + dev->raw_buf_almost_empty_thrd.dsi_raw_buf_almost_empty_thrd = threshold; +} + /** * @brief Set the number of pixel bits in total * @@ -201,11 +216,11 @@ static inline void mipi_dsi_brg_ll_enable_dpi_output(dsi_brg_dev_t *dev, bool en } /** - * @brief Update the configuration of DSI bridge + * @brief Update the DPI configuration of DSI bridge * * @param dev Pointer to the DSI bridge controller register base address */ -static inline void mipi_dsi_brg_ll_update_config(dsi_brg_dev_t *dev) +static inline void mipi_dsi_brg_ll_update_dpi_config(dsi_brg_dev_t *dev) { dev->dpi_config_update.dpi_config_update = 1; } diff --git a/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h b/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h index a76bbb3134..999f7d3226 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_host_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,8 @@ #include "hal/mipi_dsi_types.h" #include "hal/lcd_types.h" +#define MIPI_DSI_LL_GET_HOST(bus_id) (bus_id == 0 ? &MIPI_DSI_HOST : NULL) + #define MIPI_DSI_LL_MAX_DPI_CLK_DIV 256 #ifdef __cplusplus @@ -28,6 +30,15 @@ typedef enum { MIPI_DSI_LL_TRANS_SPEED_LP, /*!< Low power transmission */ } mipi_dsi_ll_trans_speed_mode_t; +/** + * @brief MIPI DSI clock lane state + */ +typedef enum { + MIPI_DSI_LL_CLOCK_LANE_STATE_AUTO, /*!< Clock lane state is automatic controlled by the DSI host */ + MIPI_DSI_LL_CLOCK_LANE_STATE_HS, /*!< Clock lane state is in high speed */ + MIPI_DSI_LL_CLOCK_LANE_STATE_LP, /*!< Clock lane state is in low power */ +} mipi_dsi_ll_clock_lane_state_t; + /** * @brief Color coding type (depth and pixel configuration) */ @@ -40,15 +51,6 @@ typedef enum { MIPI_DSI_LL_COLOR_CODE_24BIT = 5, // 24-bit } mipi_dsi_ll_color_coding_t; -/** - * @brief The kind of test pattern that can be generated by the DSI Host controller - */ -typedef enum { - MIPI_DSI_LL_PATTERN_BAR_VERTICAL, // Vertical bar pattern - MIPI_DSI_LL_PATTERN_BAR_HORIZONTAL, // Horizontal bar pattern - MIPI_DSI_LL_PATTERN_BER_VERTICAL, // Vertical ber pattern -} mipi_dsi_ll_pattern_type_t; - /** * @brief MIPI DSI Video mode burst type */ @@ -120,25 +122,43 @@ static inline void mipi_dsi_host_ll_set_timeout_count(dsi_host_dev_t *dev, uint3 } /** - * @brief Enable the automatic mechanism to stop providing clock in the clock lane when time allows + * @brief Set the state of the clock lane * * @param dev Pointer to the DSI Host controller register base address - * @param enable True to enable, False to disable + * @param state Clock lane state */ -static inline void mipi_dsi_host_ll_enable_non_continuous_clock(dsi_host_dev_t *dev, bool enable) +static inline void mipi_dsi_host_ll_set_clock_lane_state(dsi_host_dev_t *dev, mipi_dsi_ll_clock_lane_state_t state) { - dev->lpclk_ctrl.auto_clklane_ctrl = enable; + switch (state) { + case MIPI_DSI_LL_CLOCK_LANE_STATE_AUTO: + dev->lpclk_ctrl.auto_clklane_ctrl = 1; + dev->lpclk_ctrl.phy_txrequestclkhs = 1; + break; + case MIPI_DSI_LL_CLOCK_LANE_STATE_HS: + dev->lpclk_ctrl.auto_clklane_ctrl = 0; + dev->lpclk_ctrl.phy_txrequestclkhs = 1; + break; + case MIPI_DSI_LL_CLOCK_LANE_STATE_LP: + dev->lpclk_ctrl.auto_clklane_ctrl = 0; + dev->lpclk_ctrl.phy_txrequestclkhs = 0; + break; + default: + HAL_ASSERT(false); + break; + } } /** - * @brief Request the PHY module to start transmission of high speed clock + * @brief Enable / Disable video mode + * + * @note Commands can still be sent by the generic interface while in video mode * * @param dev Pointer to the DSI Host controller register base address - * @param enable True to enable, False to disable + * @param en True to enable, False to disable */ -static inline void mipi_dsi_host_ll_enable_hs_clock(dsi_host_dev_t *dev, bool enable) +static inline void mipi_dsi_host_ll_enable_video_mode(dsi_host_dev_t *dev, bool en) { - dev->lpclk_ctrl.phy_txrequestclkhs = enable; + dev->mode_cfg.cmd_video_mode = !en; } ////////////////////////////////////////////DPI Interface/////////////////////////////// @@ -278,20 +298,26 @@ static inline void mipi_dsi_host_ll_dpi_set_video_burst_type(dsi_host_dev_t *dev * @param dev Pointer to the DSI Host controller register base address * @param type Pattern type */ -static inline void mipi_dsi_host_ll_dpi_set_pattern_type(dsi_host_dev_t *dev, mipi_dsi_ll_pattern_type_t type) +static inline void mipi_dsi_host_ll_dpi_set_pattern_type(dsi_host_dev_t *dev, mipi_dsi_pattern_type_t type) { switch (type) { - case MIPI_DSI_LL_PATTERN_BAR_HORIZONTAL: + case MIPI_DSI_PATTERN_BAR_HORIZONTAL: dev->vid_mode_cfg.vpg_mode = 0; dev->vid_mode_cfg.vpg_orientation = 1; + dev->vid_mode_cfg.vpg_en = 1; break; - case MIPI_DSI_LL_PATTERN_BAR_VERTICAL: + case MIPI_DSI_PATTERN_BAR_VERTICAL: dev->vid_mode_cfg.vpg_mode = 0; dev->vid_mode_cfg.vpg_orientation = 0; + dev->vid_mode_cfg.vpg_en = 1; break; - case MIPI_DSI_LL_PATTERN_BER_VERTICAL: + case MIPI_DSI_PATTERN_BER_VERTICAL: dev->vid_mode_cfg.vpg_mode = 1; dev->vid_mode_cfg.vpg_orientation = 0; + dev->vid_mode_cfg.vpg_en = 1; + break; + case MIPI_DSI_PATTERN_NONE: + dev->vid_mode_cfg.vpg_en = 0; break; default: HAL_ASSERT(false); @@ -299,30 +325,6 @@ static inline void mipi_dsi_host_ll_dpi_set_pattern_type(dsi_host_dev_t *dev, mi } } -/** - * @brief Enable pattern generation - * - * @param dev Pointer to the DSI Host controller register base address - * @param enable True to enable, False to disable - */ -static inline void mipi_dsi_host_ll_dpi_enable_pattern(dsi_host_dev_t *dev, bool enable) -{ - dev->vid_mode_cfg.vpg_en = enable; -} - -/** - * @brief Enable / Disable DPI video mode - * - * @note Commands can still be sent by the generic interface while in video mode - * - * @param dev Pointer to the DSI Host controller register base address - * @param en True to enable, False to disable - */ -static inline void mipi_dsi_host_ll_dpi_enable_video_mode(dsi_host_dev_t *dev, bool en) -{ - dev->mode_cfg.cmd_video_mode = !en; -} - /** * @brief Set the number of bytes inside a null packet * @@ -412,7 +414,7 @@ static inline void mipi_dsi_host_ll_enable_te_ack(dsi_host_dev_t *dev, bool en) } /** - * @brief Enable the acknowledge request after each packet transmission + * @brief Enable to request an acknowledgement from the DSI device after sending a command or data packet * * @param dev Pointer to the DSI Host controller register base address * @param enable True to enable, False to disable diff --git a/components/hal/esp32p4/include/hal/mipi_dsi_ll.h b/components/hal/esp32p4/include/hal/mipi_dsi_ll.h index 9bf9b42d1c..6c37ea589b 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,8 @@ #include "hal/mipi_dsi_brg_ll.h" #include "hal/mipi_dsi_phy_ll.h" +#define MIPI_DSI_LL_NUM_BUS 1 // 1 MIPI DSI bus + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/esp32p4/include/hal/mipi_dsi_phy_ll.h b/components/hal/esp32p4/include/hal/mipi_dsi_phy_ll.h index c5de472eb0..a38ce30747 100644 --- a/components/hal/esp32p4/include/hal/mipi_dsi_phy_ll.h +++ b/components/hal/esp32p4/include/hal/mipi_dsi_phy_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,9 @@ #include "soc/mipi_dsi_host_struct.h" #include "hal/mipi_dsi_types.h" +#define MIPI_DSI_LL_MIN_PHY_MBPS 80 +#define MIPI_DSI_LL_MAX_PHY_MBPS 1500 + #ifdef __cplusplus extern "C" { #endif @@ -32,7 +35,6 @@ static inline void mipi_dsi_phy_ll_enable_clock_lane(dsi_host_dev_t *dev, bool e * @brief Reset the digital section of the PHY * * @param dev Pointer to the DSI Host controller register base address - * @param enable True to place the PHY in the reset state, False to release the reset */ static inline void mipi_dsi_phy_ll_reset(dsi_host_dev_t *dev) { @@ -76,14 +78,16 @@ static inline bool mipi_dsi_phy_ll_is_pll_locked(dsi_host_dev_t *dev) } /** - * @brief Check if the Lane0 in stop state + * @brief Check if the all active lanes are in the stop state * * @param dev Pointer to the DSI Host controller register base address - * @return True if the Lane0 in stop state, False otherwise + * @return True if the lanes are all in stop state, False otherwise */ -static inline bool mipi_dsi_phy_ll_is_lane0_stoped(dsi_host_dev_t *dev) +static inline bool mipi_dsi_phy_ll_are_lanes_stoped(dsi_host_dev_t *dev) { - return dev->phy_status.phy_stopstate0lane; + uint32_t status = dev->phy_status.val; + const uint32_t mask = 1 << 2 | 1 << 4 | 1 << 7; + return (status & mask) == mask; } /** diff --git a/components/hal/include/hal/mipi_dsi_hal.h b/components/hal/include/hal/mipi_dsi_hal.h index 41005971ab..7ec69da23e 100644 --- a/components/hal/include/hal/mipi_dsi_hal.h +++ b/components/hal/include/hal/mipi_dsi_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,15 +30,17 @@ typedef struct dsi_brg_dev_t *mipi_dsi_bridge_soc_handle_t; typedef struct { mipi_dsi_host_soc_handle_t host; /*!< Pointer to the host controller registers */ mipi_dsi_bridge_soc_handle_t bridge; /*!< Pointer to the bridge controller registers */ - float dpi2lane_clk_ratio; /*!< Ratio between DPI clock and lane byte clock */ + uint32_t lane_bit_rate_mbps; /*!< Lane bit rate in Mbps */ + uint32_t dpi_clock_freq_mhz; /*!< DPI clock frequency in MHz */ } mipi_dsi_hal_context_t; /** * @brief MIPI DSI HAL driver configuration */ typedef struct { - uint32_t lane_byte_clk_hz; /*!< Lane byte clock frequency */ - uint32_t dpi_clk_hz; /*!< DPI clock frequency */ + int bus_id; /*!< MIPI DSI bus ID, index from 0 */ + uint32_t lane_bit_rate_mbps; /*!< Lane bit rate in Mbps */ + uint8_t num_data_lanes; /*!< Number of data lanes */ } mipi_dsi_hal_config_t; /** @@ -51,6 +53,22 @@ typedef struct { */ void mipi_dsi_hal_init(mipi_dsi_hal_context_t *hal, const mipi_dsi_hal_config_t *config); +/** + * @brief Deinitialize MIPI DSI Hal driver context + * + * @param hal Pointer to the HAL driver context + */ +void mipi_dsi_hal_deinit(mipi_dsi_hal_context_t *hal); + +/** + * @brief Configure the PHY PLL + * + * @param hal Pointer to the HAL driver context + * @param phy_clk_src_freq_hz PHY clock source frequency in Hz + * @param lane_bit_rate_mbps Lane bit rate in Mbps + */ +void mipi_dsi_hal_configure_phy_pll(mipi_dsi_hal_context_t *hal, uint32_t phy_clk_src_freq_hz, uint32_t lane_bit_rate_mbps); + /** * @brief Write a value to a PHY register via internal bus (so-called test interface) * @@ -74,7 +92,7 @@ void mipi_dsi_hal_phy_write_register(mipi_dsi_hal_context_t *hal, uint8_t reg_ad * @param param_size Number of bytes of the parameters */ void mipi_dsi_hal_host_gen_write_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t vc, - uint32_t command, uint32_t command_bytes, const void *param, uint16_t param_size); + uint32_t command, uint32_t command_bytes, const void *param, uint16_t param_size); /** * @brief Send a DCS command and return the associated parameters via the generic interface @@ -86,7 +104,8 @@ void mipi_dsi_hal_host_gen_write_dcs_command(mipi_dsi_hal_context_t *hal, uint8_ * @param ret_param Pointer to the buffer to store the returned parameters * @param param_buf_size Size of the buffer to store the returned parameters */ -void mipi_dsi_hal_host_gen_read_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t vc, uint32_t command, uint32_t command_bytes, void *ret_param, uint16_t param_buf_size); +void mipi_dsi_hal_host_gen_read_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t vc, + uint32_t command, uint32_t command_bytes, void *ret_param, uint16_t param_buf_size); /** * @brief Send a long packet via the generic interface @@ -97,7 +116,8 @@ void mipi_dsi_hal_host_gen_read_dcs_command(mipi_dsi_hal_context_t *hal, uint8_t * @param buffer Pointer to the buffer * @param buffer_size Number of bytes to be sent */ -void mipi_dsi_hal_host_gen_write_long_packet(mipi_dsi_hal_context_t *hal, uint8_t vc, mipi_dsi_data_type_t dt, const void *buffer, uint16_t buffer_size); +void mipi_dsi_hal_host_gen_write_long_packet(mipi_dsi_hal_context_t *hal, uint8_t vc, + mipi_dsi_data_type_t dt, const void *buffer, uint16_t buffer_size); /** * @brief Send a short packet via the generic interface @@ -107,7 +127,8 @@ void mipi_dsi_hal_host_gen_write_long_packet(mipi_dsi_hal_context_t *hal, uint8_ * @param dt Data type * @param header_data Data to be sent, filled into the DSI packet header */ -void mipi_dsi_hal_host_gen_write_short_packet(mipi_dsi_hal_context_t *hal, uint8_t vc, mipi_dsi_data_type_t dt, uint16_t header_data); +void mipi_dsi_hal_host_gen_write_short_packet(mipi_dsi_hal_context_t *hal, uint8_t vc, + mipi_dsi_data_type_t dt, uint16_t header_data); /** * @brief Send a short packet via the generic interface and return the associated data @@ -119,7 +140,8 @@ void mipi_dsi_hal_host_gen_write_short_packet(mipi_dsi_hal_context_t *hal, uint8 * @param ret_buffer Pointer to the buffer to store the returned data * @param buffer_size Size of the buffer to store the returned data */ -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); +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 @@ -152,6 +174,18 @@ void mipi_dsi_hal_host_dpi_set_horizontal_timing(mipi_dsi_hal_context_t *hal, ui */ void mipi_dsi_hal_host_dpi_set_vertical_timing(mipi_dsi_hal_context_t *hal, uint32_t vsw, uint32_t vbp, uint32_t active_height, uint32_t vfp); +/** + * @brief Calculate the divider for DPI clock + * + * @note This function will also update the real DPI clock frequency in the HAL context + * + * @param hal Pointer to the HAL driver context + * @param clk_src_mhz Clock source frequency in MHz + * @param expect_dpi_clk_mhz Expected DPI clock frequency in MHz + * @return Divider value + */ +uint32_t mipi_dsi_hal_host_dpi_calculate_divider(mipi_dsi_hal_context_t *hal, uint32_t clk_src_mhz, uint32_t expect_dpi_clk_mhz); + #ifdef __cplusplus } diff --git a/components/hal/include/hal/mipi_dsi_types.h b/components/hal/include/hal/mipi_dsi_types.h index 68c666ad21..8c2a880a7e 100644 --- a/components/hal/include/hal/mipi_dsi_types.h +++ b/components/hal/include/hal/mipi_dsi_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,20 +48,14 @@ typedef enum { } __attribute__((packed)) mipi_dsi_data_type_t; /** - * @brief MIPI DSI packet + * @brief The kind of test pattern that can be generated by the DSI Host controller */ -typedef struct { - mipi_dsi_data_type_t dt: 6; /*!< Data Type */ - uint8_t vc: 2; /*!< Virtual Channel */ - union { - uint16_t word_count; /*!< Word count, in bytes */ - uint8_t data[2]; /*!< Data of short packet */ - }; - uint8_t ecc; /*!< ECC */ - uint8_t payload[0]; /*!< Payload of long packet */ -} __attribute__((packed)) mipi_dsi_packet_t; - -ESP_STATIC_ASSERT(sizeof(mipi_dsi_packet_t) == 4, "Invalid size of mipi_dsi_packet_t structure"); +typedef enum { + MIPI_DSI_PATTERN_NONE, /*!< No pattern */ + MIPI_DSI_PATTERN_BAR_VERTICAL, /*!< Vertical BAR pattern, with different colors */ + MIPI_DSI_PATTERN_BAR_HORIZONTAL, /*!< Horizontal BAR pattern, with different colors */ + MIPI_DSI_PATTERN_BER_VERTICAL, /*!< Vertical Bit Error Rate(BER) pattern */ +} mipi_dsi_pattern_type_t; #if SOC_MIPI_DSI_SUPPORTED /** diff --git a/components/hal/mipi_dsi_hal.c b/components/hal/mipi_dsi_hal.c index 74a677f4b3..9320923cc4 100644 --- a/components/hal/mipi_dsi_hal.c +++ b/components/hal/mipi_dsi_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,12 +8,76 @@ #include #include "hal/mipi_dsi_hal.h" #include "hal/mipi_dsi_ll.h" +#include "hal/assert.h" +#include "hal/log.h" +#include "soc/mipi_dsi_periph.h" void mipi_dsi_hal_init(mipi_dsi_hal_context_t *hal, const mipi_dsi_hal_config_t *config) { - hal->host = &MIPI_DSI_HOST; - hal->bridge = &MIPI_DSI_BRIDGE; - hal->dpi2lane_clk_ratio = ((float)config->lane_byte_clk_hz) / config->dpi_clk_hz; + hal->host = MIPI_DSI_LL_GET_HOST(config->bus_id); + hal->bridge = MIPI_DSI_LL_GET_BRG(config->bus_id); + // set the data lane number + mipi_dsi_phy_ll_set_data_lane_number(hal->host, config->num_data_lanes); + // power on the host controller and PHY + mipi_dsi_host_ll_power_on_off(hal->host, true); + mipi_dsi_phy_ll_power_on_off(hal->host, true); + // reset the PHY and then enable the clock lane + 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); +} + +void mipi_dsi_hal_deinit(mipi_dsi_hal_context_t *hal) +{ + // power off the host controller and PHY + mipi_dsi_phy_ll_power_on_off(hal->host, false); + mipi_dsi_host_ll_power_on_off(hal->host, false); + hal->host = NULL; + hal->bridge = NULL; +} + +void mipi_dsi_hal_configure_phy_pll(mipi_dsi_hal_context_t *hal, uint32_t phy_clk_src_freq_hz, uint32_t lane_bit_rate_mbps) +{ + // Formula: f_vco = M/N * f_ref + // where the M is Feedback Multiplication Ratio, N is Input Frequency Division Ratio + uint32_t ref_freq_mhz = phy_clk_src_freq_hz / 1000 / 1000; + uint32_t vco_freq_mhz = lane_bit_rate_mbps; + uint8_t pll_N = 1; + uint16_t pll_M = 0; + // 5MHz <= f_ref/N <= 40MHz + uint8_t min_N = MAX(1, ref_freq_mhz / 40); + uint8_t max_N = ref_freq_mhz / 5; + for (uint8_t n = min_N; n <= max_N; n++) { + uint16_t m = vco_freq_mhz * n / ref_freq_mhz; + // M must be even number + if ((m & 0x01) == 0) { + pll_M = m; + pll_N = n; + break; + } + } + HAL_ASSERT(pll_M && pll_N); + + // search for the best PLL range + uint8_t hs_freq_sel = 0; + for (size_t i = 0; i < num_of_soc_mipi_dsi_phy_pll_ranges; i++) { + if (lane_bit_rate_mbps >= soc_mipi_dsi_phy_pll_ranges[i].start_mbps && + lane_bit_rate_mbps <= soc_mipi_dsi_phy_pll_ranges[i].end_mbps) { + hs_freq_sel = soc_mipi_dsi_phy_pll_ranges[i].hs_freq_range_sel; + break; + } + } + + mipi_dsi_hal_phy_write_register(hal, 0x44, hs_freq_sel << 1); + // make use of the N and M factors that configured in the 0x17 and 0x18 + mipi_dsi_hal_phy_write_register(hal, 0x19, 0x30); + mipi_dsi_hal_phy_write_register(hal, 0x17, pll_N - 1); + mipi_dsi_hal_phy_write_register(hal, 0x18, ((pll_M - 1) & 0x1F)); + mipi_dsi_hal_phy_write_register(hal, 0x18, 0x80 | (((pll_M - 1) >> 5) & 0x0F)); + // update the real lane bit rate + hal->lane_bit_rate_mbps = ref_freq_mhz * pll_M / pll_N; + HAL_LOGD("dsi_hal", "phy pll: ref=%luHz, lane_bit_rate=%luMbps, M=%d, N=%d, hsfreqrange=%d", + phy_clk_src_freq_hz, hal->lane_bit_rate_mbps, pll_M, pll_N, hs_freq_sel); } void mipi_dsi_hal_phy_write_register(mipi_dsi_hal_context_t *hal, uint8_t reg_addr, uint8_t reg_val) @@ -110,7 +174,7 @@ void mipi_dsi_hal_host_gen_read_short_packet(mipi_dsi_hal_context_t *hal, uint8_ // set the maximum returned data size, it should equal to the parameter size of the read command mipi_dsi_hal_host_gen_write_short_packet(hal, vc, MIPI_DSI_DT_SET_MAXIMUM_RETURN_PKT, buffer_size); // make sure command mode is on - mipi_dsi_host_ll_dpi_enable_video_mode(hal->host, false); + mipi_dsi_host_ll_enable_video_mode(hal->host, false); // make sure receiving is enabled mipi_dsi_host_ll_enable_bta(hal->host, true); // listen to the same virtual channel as the one sent to @@ -142,23 +206,28 @@ void mipi_dsi_hal_host_dpi_set_color_coding(mipi_dsi_hal_context_t *hal, lcd_col { 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); - // please note, we need to call bridge_update to make the new configuration take effect } 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; mipi_dsi_host_ll_dpi_set_horizontal_timing(hal->host, - hsw * hal->dpi2lane_clk_ratio, - hbp * hal->dpi2lane_clk_ratio, - active_width * hal->dpi2lane_clk_ratio, - hfp * hal->dpi2lane_clk_ratio); + hsw * dpi2lane_clk_ratio, + hbp * dpi2lane_clk_ratio, + active_width * dpi2lane_clk_ratio, + hfp * dpi2lane_clk_ratio); mipi_dsi_brg_ll_set_horizontal_timing(hal->bridge, hsw, hbp, active_width, hfp); - // please note, we need to call bridge_update to make the new configuration take effect } void mipi_dsi_hal_host_dpi_set_vertical_timing(mipi_dsi_hal_context_t *hal, uint32_t vsw, uint32_t vbp, uint32_t active_height, uint32_t vfp) { mipi_dsi_host_ll_dpi_set_vertical_timing(hal->host, vsw, vbp, active_height, vfp); mipi_dsi_brg_ll_set_vertical_timing(hal->bridge, vsw, vbp, active_height, vfp); - // please note, we need to call bridge_update to make the new configuration take effect +} + +uint32_t mipi_dsi_hal_host_dpi_calculate_divider(mipi_dsi_hal_context_t *hal, uint32_t clk_src_mhz, uint32_t expect_dpi_clk_mhz) +{ + uint32_t div = clk_src_mhz / expect_dpi_clk_mhz; + hal->dpi_clock_freq_mhz = clk_src_mhz / div; + return div; } diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index cb0f27e409..f8c1dc5930 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -75,6 +75,10 @@ if(CONFIG_SOC_LCDCAM_SUPPORTED OR CONFIG_SOC_LCD_I80_SUPPORTED) list(APPEND srcs "${target}/lcd_periph.c") endif() +if(CONFIG_SOC_MIPI_DSI_SUPPORTED) + list(APPEND srcs "${target}/mipi_dsi_periph.c") +endif() + if(CONFIG_SOC_PARLIO_SUPPORTED) list(APPEND srcs "${target}/parlio_periph.c") endif() diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index f1deb519c9..b192eac7a2 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -375,7 +375,7 @@ 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_F25M, /*!< Select PLL_F25M as default 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; /////////////////////////////////////////////////I2C//////////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32p4/mipi_dsi_periph.c b/components/soc/esp32p4/mipi_dsi_periph.c new file mode 100644 index 0000000000..ca2eb57f00 --- /dev/null +++ b/components/soc/esp32p4/mipi_dsi_periph.c @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/mipi_dsi_periph.h" + +const soc_mipi_dsi_phy_pll_freq_range_t soc_mipi_dsi_phy_pll_ranges[] = { + {80, 89, 0x00}, // [80,90) Mbps + {90, 99, 0x10}, // [90,100) Mbps + {100, 109, 0x20}, // [100,110) Mbps + {110, 129, 0x01}, // [110,130) Mbps + {130, 139, 0x11}, // [130,140) Mbps + {140, 149, 0x21}, // [140,150) Mbps + {150, 169, 0x02}, // [150,170) Mbps + {170, 179, 0x12}, // [170,180) Mbps + {180, 199, 0x22}, // [180,200) Mbps + {200, 219, 0x03}, // [200,220) Mbps + {220, 239, 0x13}, // [220,240) Mbps + {240, 249, 0x23}, // [240,250) Mbps + {250, 269, 0x04}, // [250,270) Mbps + {270, 299, 0x14}, // [270,300) Mbps + {300, 329, 0x05}, // [300,330) Mbps + {330, 359, 0x15}, // [330,360) Mbps + {360, 399, 0x25}, // [360,400) Mbps + {400, 449, 0x06}, // [400,450) Mbps + {450, 499, 0x16}, // [450,500) Mbps + {500, 549, 0x07}, // [500,550) Mbps + {550, 599, 0x17}, // [550,600) Mbps + {600, 649, 0x08}, // [600,650) Mbps + {650, 699, 0x18}, // [650,700) Mbps + {700, 749, 0x09}, // [700,750) Mbps + {750, 799, 0x19}, // [750,800) Mbps + {800, 849, 0x29}, // [800,850) Mbps + {850, 899, 0x39}, // [850,900) Mbps + {900, 949, 0x0A}, // [900,950) Mbps + {950, 999, 0x1A}, // [950,1000) Mbps + {1000, 1049, 0x2A}, // [1000,1050) Mbps + {1050, 1099, 0x3A}, // [1050,1100) Mbps + {1100, 1149, 0x0B}, // [1100,1150) Mbps + {1150, 1199, 0x1B}, // [1150,1200) Mbps + {1200, 1249, 0x2B}, // [1200,1250) Mbps + {1250, 1299, 0x3B}, // [1250,1300) Mbps + {1300, 1349, 0x0C}, // [1300,1350) Mbps + {1350, 1399, 0x1C}, // [1350,1400) Mbps + {1400, 1449, 0x2C}, // [1400,1450) Mbps + {1450, 1500, 0x3C}, // [1450,1500] Mbps +}; + +const size_t num_of_soc_mipi_dsi_phy_pll_ranges = sizeof(soc_mipi_dsi_phy_pll_ranges) / sizeof(soc_mipi_dsi_phy_pll_freq_range_t); diff --git a/components/soc/include/soc/mipi_dsi_periph.h b/components/soc/include/soc/mipi_dsi_periph.h new file mode 100644 index 0000000000..1264c517b6 --- /dev/null +++ b/components/soc/include/soc/mipi_dsi_periph.h @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief MIPI DSI PHY PLL frequency range + */ +typedef struct { + uint32_t start_mbps; /*!< Start frequency of the range (included) */ + uint32_t end_mbps; /*!< End frequency of the range (included) */ + uint8_t hs_freq_range_sel; /*!< HS operating frequency range selection */ +} soc_mipi_dsi_phy_pll_freq_range_t; + +extern const soc_mipi_dsi_phy_pll_freq_range_t soc_mipi_dsi_phy_pll_ranges[]; +extern const size_t num_of_soc_mipi_dsi_phy_pll_ranges; + +#ifdef __cplusplus +} +#endif diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index d60e0ec0c5..e99f39df8c 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -174,7 +174,6 @@ INPUT = \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_sleep.h \ $(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_io.h \ $(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_ops.h \ - $(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_rgb.h \ $(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_vendor.h \ $(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_dev.h \ $(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_ssd1306.h \ diff --git a/docs/doxygen/Doxyfile_esp32s3 b/docs/doxygen/Doxyfile_esp32s3 index 2f77282841..5671ce1fae 100644 --- a/docs/doxygen/Doxyfile_esp32s3 +++ b/docs/doxygen/Doxyfile_esp32s3 @@ -1,5 +1,6 @@ INPUT += \ $(PROJECT_PATH)/components/driver/touch_sensor/$(IDF_TARGET)/include/driver/touch_sensor.h \ + $(PROJECT_PATH)/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ $(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \ $(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \ diff --git a/docs/en/api-reference/peripherals/lcd.rst b/docs/en/api-reference/peripherals/lcd.rst index 20f48d148a..674ab3525c 100644 --- a/docs/en/api-reference/peripherals/lcd.rst +++ b/docs/en/api-reference/peripherals/lcd.rst @@ -498,5 +498,8 @@ API Reference .. include-build-file:: inc/esp_lcd_types.inc .. include-build-file:: inc/esp_lcd_panel_io.inc .. include-build-file:: inc/esp_lcd_panel_ops.inc -.. include-build-file:: inc/esp_lcd_panel_rgb.inc .. include-build-file:: inc/esp_lcd_panel_vendor.inc + +.. only:: SOC_LCD_RGB_SUPPORTED + + .. include-build-file:: inc/esp_lcd_panel_rgb.inc