From 37f9cef6ddf7b900cf53b9bd77b8130d8de04bd8 Mon Sep 17 00:00:00 2001 From: armando Date: Mon, 2 Feb 2026 15:17:59 +0800 Subject: [PATCH 1/2] feat(csi): support csi input bit swap --- .../csi/include/esp_cam_ctlr_csi.h | 8 +- .../esp_driver_cam/csi/src/esp_cam_ctlr_csi.c | 31 ++- .../esp32p4/include/hal/mipi_csi_brg_ll.h | 190 +++++++++++++++++- .../esp32p4/include/hal/mipi_csi_ll.h | 136 ------------- components/esp_hal_cam/mipi_csi_hal.c | 2 +- .../mipi_isp_dsi/sdkconfig.defaults.esp32p4 | 3 +- 6 files changed, 218 insertions(+), 152 deletions(-) diff --git a/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h b/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h index 7210ad15db2..5f638874152 100644 --- a/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h +++ b/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,8 +29,10 @@ typedef struct { cam_ctlr_color_t output_data_color_type; /*!< Output color type. */ int queue_items; /*!< Number of queue items. */ struct { - uint32_t byte_swap_en : 1; /*!< Set to 1 to enable byte swap. */ - uint32_t bk_buffer_dis : 1; /*!< Set to 1 to disable backup buffer. */ + uint32_t input_8bit_swap_en : 1; /*!< Set to 1 to enable input 8bit bit swap. [31:24] [23:16] [15:8] [7:0] -> [7:0] [15:8] [23:16] [31:24]*/ + uint32_t input_16bit_swap_en : 1; /*!< Set to 1 to enable input 16bit bit swap. [31:16] [15:0] -> [15:0] [31:16] */ + uint32_t byte_swap_en : 1; /*!< Set to 1 to enable output byte swap. */ + uint32_t bk_buffer_dis : 1; /*!< Set to 1 to disable backup buffer. */ }; /*!< Boolean flags. */ } esp_cam_ctlr_csi_config_t; diff --git a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c index 420c6029234..af61a130caf 100644 --- a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c +++ b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c @@ -106,6 +106,15 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ ESP_RETURN_ON_FALSE(config->input_data_color_type != 0, ESP_ERR_INVALID_ARG, TAG, "input_data_color_type must be specified"); ESP_RETURN_ON_FALSE(config->output_data_color_type != 0, ESP_ERR_INVALID_ARG, TAG, "output_data_color_type must be specified"); + bool is_less_v1 = false; //version 1 since P4 rev3 +#if CONFIG_IDF_TARGET_ESP32P4 + unsigned chip_version = efuse_hal_chip_revision(); + if (!ESP_CHIP_REV_ABOVE(chip_version, 300)) { + is_less_v1 = true; + } +#endif + ESP_RETURN_ON_FALSE(!(is_less_v1 && (config->input_8bit_swap_en || config->input_16bit_swap_en)), ESP_ERR_NOT_SUPPORTED, TAG, "input 8bit or 16bit swap is not supported on this chip"); + csi_controller_t *ctlr = heap_caps_calloc(1, sizeof(csi_controller_t), CSI_MEM_ALLOC_CAPS); ESP_RETURN_ON_FALSE(ctlr, ESP_ERR_NO_MEM, TAG, "no mem for csi controller context"); @@ -184,6 +193,19 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ mipi_csi_hal_init(&ctlr->hal, &hal_config); mipi_csi_brg_ll_set_burst_len(ctlr->hal.bridge_dev, 512); + cam_ctlr_format_conv_config_t format_conv_config = { + .src_format = config->input_data_color_type, + .dst_format = config->output_data_color_type, + }; + ESP_GOTO_ON_ERROR(s_csi_ctlr_format_conversion(&(ctlr->base), &format_conv_config), err, TAG, "failed to configure format conversion"); + + if (config->input_8bit_swap_en) { + mipi_csi_brg_ll_set_8bit_swap(ctlr->hal.bridge_dev, true); + } + if (config->input_16bit_swap_en) { + mipi_csi_brg_ll_set_16bit_swap(ctlr->hal.bridge_dev, true); + } + //---------------DWGDMA Init For CSI------------------// dw_gdma_channel_handle_t csi_dma_chan = NULL; dw_gdma_channel_alloc_config_t csi_dma_alloc_config = { @@ -219,12 +241,6 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "cam_csi_ctlr", &ctlr->pm_lock), err, TAG, "failed to create pm lock"); #endif //CONFIG_PM_ENABLE - cam_ctlr_format_conv_config_t format_conv_config = { - .src_format = config->input_data_color_type, - .dst_format = config->output_data_color_type, - }; - ESP_GOTO_ON_ERROR(s_csi_ctlr_format_conversion(&(ctlr->base), &format_conv_config), err, TAG, "failed to configure format conversion"); - ctlr->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; ctlr->csi_fsm = CSI_FSM_INIT; ctlr->base.del = s_ctlr_del; @@ -596,6 +612,8 @@ static esp_err_t s_csi_ctlr_format_conversion(esp_cam_ctlr_t *handle, const cam_ ESP_RETURN_ON_FALSE(handle && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); csi_controller_t *ctlr = __containerof(handle, csi_controller_t, base); + mipi_csi_brg_ll_enable_color_conversion(ctlr->hal.bridge_dev, true); + if (config->src_format == config->dst_format) { mipi_csi_brg_ll_set_color_mode_bypass(ctlr->hal.bridge_dev, true); return ESP_OK; @@ -614,7 +632,6 @@ static esp_err_t s_csi_ctlr_format_conversion(esp_cam_ctlr_t *handle, const cam_ mipi_csi_brg_ll_set_input_color_format(ctlr->hal.bridge_dev, config->src_format); mipi_csi_brg_ll_set_output_color_format(ctlr->hal.bridge_dev, config->dst_format); mipi_csi_brg_ll_set_color_mode_bypass(ctlr->hal.bridge_dev, false); - mipi_csi_brg_ll_enable_color_conversion(ctlr->hal.bridge_dev, true); } ctlr->in_color_format = config->src_format; ctlr->out_color_format = config->dst_format; diff --git a/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_brg_ll.h b/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_brg_ll.h index dd19cc6a92a..3efee66b57e 100644 --- a/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_brg_ll.h +++ b/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_brg_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "hal/misc.h" #include "hal/assert.h" #include "hal/hal_utils.h" +#include "hal/config.h" #include "hal/mipi_csi_types.h" #include "hal/color_types.h" #include "hal/cam_ctlr_types.h" @@ -137,16 +138,199 @@ static inline void mipi_csi_brg_ll_set_dma_req_interval(csi_brg_dev_t *dev, uint } /** - * @brief Set the data endianness order in bytes + * @brief Set the output data endianness order in bytes * * @param dev Pointer to the CSI bridge controller register base address * @param byte_swap_en byte swap enable or not */ -static inline void mipi_csi_brg_ll_set_byte_endian(csi_brg_dev_t *dev, bool byte_swap_en) +static inline void mipi_csi_brg_ll_set_output_byte_endian(csi_brg_dev_t *dev, bool byte_swap_en) { dev->endian_mode.byte_endian_order = byte_swap_en; } +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + +/** + * @brief Set RGB element order for input color data + * + * @param dev Pointer to the CSI bridge controller register base address + * @param rgb_format RGB element order: 0=RGB, 1=BGR, 2=RBG, 3=BRG, 4=GRB, 5=GBR + * + */ +static inline void mipi_csi_brg_ll_set_input_rgb_format(csi_brg_dev_t *dev, uint32_t rgb_format) +{ + dev->host_cm_ctrl.csi_host_cm_rx_rgb_format = rgb_format; +} + +/** + * @brief Set the color format for the input color data + * + * @param dev Pointer to the CSI bridge controller register base address + * @param color_format Camera controller color format + */ +static inline void mipi_csi_brg_ll_set_input_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) +{ + // Set format type + if (color_format == CAM_CTLR_COLOR_RGB888) { + dev->host_cm_ctrl.csi_host_cm_rx = 0; + mipi_csi_brg_ll_set_input_rgb_format(dev, 0); // Default: RGB order + } else if (color_format == CAM_CTLR_COLOR_RGB565) { + dev->host_cm_ctrl.csi_host_cm_rx = 1; + mipi_csi_brg_ll_set_input_rgb_format(dev, 0); // Default: RGB order + } else if (color_format == CAM_CTLR_COLOR_YUV420) { + dev->host_cm_ctrl.csi_host_cm_rx = 3; + } else if (color_format == CAM_CTLR_COLOR_YUV422_YVYU || + color_format == CAM_CTLR_COLOR_YUV422_YUYV || + color_format == CAM_CTLR_COLOR_YUV422_UYVY || + color_format == CAM_CTLR_COLOR_YUV422_VYUY) { + dev->host_cm_ctrl.csi_host_cm_rx = 2; + // Set YUV422 packing order: YVYU=0, YUYV=1, VYUY=2, UYVY=3 + if (color_format == CAM_CTLR_COLOR_YUV422_YVYU) { + dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 0; + } else if (color_format == CAM_CTLR_COLOR_YUV422_YUYV) { + dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 1; + } else if (color_format == CAM_CTLR_COLOR_YUV422_VYUY) { + dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 2; + } else if (color_format == CAM_CTLR_COLOR_YUV422_UYVY) { + dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 3; + } + } else { + HAL_ASSERT(false && "Unsupported input color format"); + } +} + +/** + * @brief Enable or disable color mode conversion output + * + * @param dev Pointer to the CSI bridge controller register base address + * @param en true to enable, false to disable + * + */ +static inline void mipi_csi_brg_ll_enable_color_conversion(csi_brg_dev_t *dev, bool en) +{ + dev->host_cm_ctrl.csi_host_cm_en = en; +} + +/** + * @brief Enable or disable color mode conversion bypass + * + * @param dev Pointer to the CSI bridge controller regihost_cm_ctrlster base address + * @param bypass true to bypass (input directly to output), false to enable conversion + * + */ +static inline void mipi_csi_brg_ll_set_color_mode_bypass(csi_brg_dev_t *dev, bool bypass) +{ + dev->host_cm_ctrl.csi_host_cm_bypass = bypass; +} + +/** + * @brief Set the color format for the output color data + * + * @param dev Pointer to the CSI bridge controller register base address + * @param color_format Camera controller color format + */ +static inline void mipi_csi_brg_ll_set_output_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) +{ + if (color_format == CAM_CTLR_COLOR_RGB888) { + dev->host_cm_ctrl.csi_host_cm_tx = 0; + } else if (color_format == CAM_CTLR_COLOR_RGB565) { + dev->host_cm_ctrl.csi_host_cm_tx = 1; + } else if (color_format == CAM_CTLR_COLOR_YUV420) { + dev->host_cm_ctrl.csi_host_cm_tx = 3; + } else if (color_format == CAM_CTLR_COLOR_YUV422_YVYU || + color_format == CAM_CTLR_COLOR_YUV422_YUYV || + color_format == CAM_CTLR_COLOR_YUV422_UYVY || + color_format == CAM_CTLR_COLOR_YUV422_VYUY) { + dev->host_cm_ctrl.csi_host_cm_tx = 2; + } else { + HAL_ASSERT(false && "Unsupported output color format"); + } +} + +/* + * @brief Set the 16-bit swap + * + * @note + * [31:16] [15:0] + * -> + * [15:0] [31:16] + * + * @param dev Pointer to the CSI bridge controller register base address + * @param swap true to swap, false to not swap + */ +static inline void mipi_csi_brg_ll_set_16bit_swap(csi_brg_dev_t *dev, bool swap) +{ + dev->host_cm_ctrl.csi_host_cm_16bit_swap = swap; +} + +/** + * @brief Set the 8-bit swap + * + * @note + * [31:24] [23:16] [15:8] [7:0] + * -> + * [7:0] [15:8] [23:16] [31:24] + * + * @param dev Pointer to the CSI bridge controller register base address + * @param swap true to swap, false to not swap + */ +static inline void mipi_csi_brg_ll_set_8bit_swap(csi_brg_dev_t *dev, bool swap) +{ + dev->host_cm_ctrl.csi_host_cm_8bit_swap = swap; +} + +#else +static inline void mipi_csi_brg_ll_set_input_rgb_format(csi_brg_dev_t *dev, uint32_t rgb_format) +{ + //for compatibility + (void)dev; + (void)rgb_format; +} + +static inline void mipi_csi_brg_ll_set_input_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) +{ + //for compatibility + (void)dev; + (void)color_format; +} + +static inline void mipi_csi_brg_ll_enable_color_conversion(csi_brg_dev_t *dev, bool en) +{ + //for compatibility + (void)dev; + (void)en; +} + +static inline void mipi_csi_brg_ll_set_color_mode_bypass(csi_brg_dev_t *dev, bool bypass) +{ + //for compatibility + (void)dev; + (void)bypass; +} + +static inline void mipi_csi_brg_ll_set_output_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) +{ + //for compatibility + (void)dev; + (void)color_format; +} + +static inline void mipi_csi_brg_ll_set_16bit_swap(csi_brg_dev_t *dev, bool swap) +{ + //for compatibility + (void)dev; + (void)swap; +} + +static inline void mipi_csi_brg_ll_set_8bit_swap(csi_brg_dev_t *dev, bool swap) +{ + //for compatibility + (void)dev; + (void)swap; +} + +#endif // HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_ll.h b/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_ll.h index 6d3612023a5..b2bcbb11a8b 100644 --- a/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_ll.h +++ b/components/esp_hal_cam/esp32p4/include/hal/mipi_csi_ll.h @@ -14,7 +14,6 @@ #include "hal/mipi_csi_brg_ll.h" #include "hal/mipi_csi_phy_ll.h" #include "hal/mipi_csi_host_ll.h" -#include "hal/config.h" #include "soc/hp_sys_clkrst_struct.h" #ifdef __cplusplus @@ -156,141 +155,6 @@ static inline void mipi_csi_ll_reset_host_clock(int group_id) mipi_csi_ll_reset_host_clock(__VA_ARGS__); \ } while(0) -#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 - -/** - * @brief Set RGB element order for input color data - * - * @param dev Pointer to the CSI bridge controller register base address - * @param rgb_format RGB element order: 0=RGB, 1=BGR, 2=RBG, 3=BRG, 4=GRB, 5=GBR - * - */ -static inline void mipi_csi_brg_ll_set_input_rgb_format(csi_brg_dev_t *dev, uint32_t rgb_format) -{ - dev->host_cm_ctrl.csi_host_cm_rx_rgb_format = rgb_format; -} - -/** - * @brief Set the color format for the input color data - * - * @param dev Pointer to the CSI bridge controller register base address - * @param color_format Camera controller color format - */ -static inline void mipi_csi_brg_ll_set_input_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) -{ - // Set format type - if (color_format == CAM_CTLR_COLOR_RGB888) { - dev->host_cm_ctrl.csi_host_cm_rx = 0; - mipi_csi_brg_ll_set_input_rgb_format(dev, 0); // Default: RGB order - } else if (color_format == CAM_CTLR_COLOR_RGB565) { - dev->host_cm_ctrl.csi_host_cm_rx = 1; - mipi_csi_brg_ll_set_input_rgb_format(dev, 0); // Default: RGB order - } else if (color_format == CAM_CTLR_COLOR_YUV420) { - dev->host_cm_ctrl.csi_host_cm_rx = 3; - } else if (color_format == CAM_CTLR_COLOR_YUV422_YVYU || - color_format == CAM_CTLR_COLOR_YUV422_YUYV || - color_format == CAM_CTLR_COLOR_YUV422_UYVY || - color_format == CAM_CTLR_COLOR_YUV422_VYUY) { - dev->host_cm_ctrl.csi_host_cm_rx = 2; - // Set YUV422 packing order: YVYU=0, YUYV=1, VYUY=2, UYVY=3 - if (color_format == CAM_CTLR_COLOR_YUV422_YVYU) { - dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 0; - } else if (color_format == CAM_CTLR_COLOR_YUV422_YUYV) { - dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 1; - } else if (color_format == CAM_CTLR_COLOR_YUV422_VYUY) { - dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 2; - } else if (color_format == CAM_CTLR_COLOR_YUV422_UYVY) { - dev->host_cm_ctrl.csi_host_cm_rx_yuv422_format = 3; - } - } else { - HAL_ASSERT(false && "Unsupported input color format"); - } -} - -/** - * @brief Enable or disable color mode conversion output - * - * @param dev Pointer to the CSI bridge controller register base address - * @param en true to enable, false to disable - * - */ -static inline void mipi_csi_brg_ll_enable_color_conversion(csi_brg_dev_t *dev, bool en) -{ - dev->host_cm_ctrl.csi_host_cm_en = en; -} - -/** - * @brief Enable or disable color mode conversion bypass - * - * @param dev Pointer to the CSI bridge controller regihost_cm_ctrlster base address - * @param bypass true to bypass (input directly to output), false to enable conversion - * - */ -static inline void mipi_csi_brg_ll_set_color_mode_bypass(csi_brg_dev_t *dev, bool bypass) -{ - dev->host_cm_ctrl.csi_host_cm_bypass = bypass; -} - -/** - * @brief Set the color format for the output color data - * - * @param dev Pointer to the CSI bridge controller register base address - * @param color_format Camera controller color format - */ -static inline void mipi_csi_brg_ll_set_output_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) -{ - if (color_format == CAM_CTLR_COLOR_RGB888) { - dev->host_cm_ctrl.csi_host_cm_tx = 0; - } else if (color_format == CAM_CTLR_COLOR_RGB565) { - dev->host_cm_ctrl.csi_host_cm_tx = 1; - } else if (color_format == CAM_CTLR_COLOR_YUV420) { - dev->host_cm_ctrl.csi_host_cm_tx = 3; - } else if (color_format == CAM_CTLR_COLOR_YUV422_YVYU || - color_format == CAM_CTLR_COLOR_YUV422_YUYV || - color_format == CAM_CTLR_COLOR_YUV422_UYVY || - color_format == CAM_CTLR_COLOR_YUV422_VYUY) { - dev->host_cm_ctrl.csi_host_cm_tx = 2; - } else { - HAL_ASSERT(false && "Unsupported output color format"); - } -} -#else -static inline void mipi_csi_brg_ll_set_input_rgb_format(csi_brg_dev_t *dev, uint32_t rgb_format) -{ - //for compatibility - (void)dev; - (void)rgb_format; -} - -static inline void mipi_csi_brg_ll_set_input_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) -{ - //for compatibility - (void)dev; - (void)color_format; -} - -static inline void mipi_csi_brg_ll_enable_color_conversion(csi_brg_dev_t *dev, bool en) -{ - //for compatibility - (void)dev; - (void)en; -} - -static inline void mipi_csi_brg_ll_set_color_mode_bypass(csi_brg_dev_t *dev, bool bypass) -{ - //for compatibility - (void)dev; - (void)bypass; -} - -static inline void mipi_csi_brg_ll_set_output_color_format(csi_brg_dev_t *dev, cam_ctlr_color_t color_format) -{ - //for compatibility - (void)dev; - (void)color_format; -} -#endif // HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 - #ifdef __cplusplus } #endif diff --git a/components/esp_hal_cam/mipi_csi_hal.c b/components/esp_hal_cam/mipi_csi_hal.c index 3f8aaba0338..b7fd34c242b 100644 --- a/components/esp_hal_cam/mipi_csi_hal.c +++ b/components/esp_hal_cam/mipi_csi_hal.c @@ -73,5 +73,5 @@ void mipi_csi_hal_init(mipi_csi_hal_context_t *hal, const mipi_csi_hal_config_t mipi_csi_brg_ll_set_flow_ctl_buf_afull_thrd(hal->bridge_dev, 960); mipi_csi_brg_ll_set_data_type_min(hal->bridge_dev, 0x12); mipi_csi_brg_ll_set_data_type_max(hal->bridge_dev, 0x2f); - mipi_csi_brg_ll_set_byte_endian(hal->bridge_dev, config->byte_swap_en); + mipi_csi_brg_ll_set_output_byte_endian(hal->bridge_dev, config->byte_swap_en); } diff --git a/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 index 2c02a3b7ee1..9956837cc20 100644 --- a/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 +++ b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 @@ -1,3 +1,2 @@ -CONFIG_IDF_EXPERIMENTAL_FEATURES=y CONFIG_SPIRAM=y -CONFIG_SPIRAM_SPEED_200M=y +CONFIG_SPIRAM_SPEED_250M=y From 34ad02e811a3dc9f1703d13fd41e89b8c43fcb63 Mon Sep 17 00:00:00 2001 From: armando Date: Thu, 12 Feb 2026 15:29:40 +0800 Subject: [PATCH 2/2] feat(csi): support custom data type --- .../csi/include/esp_cam_ctlr_csi.h | 42 ++++++++++------ .../esp_driver_cam/csi/src/esp_cam_ctlr_csi.c | 48 +++++++++++++------ .../csi/src/esp_cam_ctlr_csi_internal.h | 1 + .../esp_hal_cam/include/hal/mipi_csi_types.h | 3 ++ components/esp_hal_cam/mipi_csi_hal.c | 2 - 5 files changed, 65 insertions(+), 31 deletions(-) diff --git a/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h b/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h index 5f638874152..ee3c61477b0 100644 --- a/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h +++ b/components/esp_driver_cam/csi/include/esp_cam_ctlr_csi.h @@ -15,25 +15,39 @@ extern "C" { #endif +/** + * @brief CSI customized data type configuration. + * + * @note By default (by setting this structure to 0), embedded data and standard data type will be supported. + * Under most conditions, you don't need to set this and can keep these to 0. + * Set this if you want to use customized data type. + */ +typedef struct { + uint32_t bits_per_pixel; /*!< Bits per pixel, by default it's 0, embedded data and standard data type will be supported */ + uint32_t data_type_min; /*!< Data type, by default it's 0, embedded data and standard data type will be supported */ + uint32_t data_type_max; /*!< Data type, by default it's 0, embedded data and standard data type will be supported */ +} esp_cam_ctlr_csi_data_type_t; + /** * @brief ESP CAM CSI controller configurations. */ typedef struct { - int ctlr_id; /*!< CSI controller ID. */ - mipi_csi_phy_clock_source_t clk_src; /*!< CSI PHY clock source. */ - uint32_t h_res; /*!< Input horizontal resolution. Measurement unit: pixels per line. */ - uint32_t v_res; /*!< Input vertical resolution. Measurement unit: lines per frame. */ - uint8_t data_lane_num; /*!< Number of data lanes. */ - int lane_bit_rate_mbps; /*!< Lane bit rate. Measurement unit: Mbps. */ - cam_ctlr_color_t input_data_color_type; /*!< Input color type. */ - cam_ctlr_color_t output_data_color_type; /*!< Output color type. */ - int queue_items; /*!< Number of queue items. */ + int ctlr_id; /*!< CSI controller ID. */ + mipi_csi_phy_clock_source_t clk_src; /*!< CSI PHY clock source. */ + uint32_t h_res; /*!< Input horizontal resolution. Measurement unit: pixels per line. */ + uint32_t v_res; /*!< Input vertical resolution. Measurement unit: lines per frame. */ + uint8_t data_lane_num; /*!< Number of data lanes. */ + int lane_bit_rate_mbps; /*!< Lane bit rate. Measurement unit: Mbps. */ + cam_ctlr_color_t input_data_color_type; /*!< Input color type. */ + cam_ctlr_color_t output_data_color_type; /*!< Output color type. */ + esp_cam_ctlr_csi_data_type_t data_type; /*!< Data type configuration. */ + int queue_items; /*!< Number of queue items. */ struct { - uint32_t input_8bit_swap_en : 1; /*!< Set to 1 to enable input 8bit bit swap. [31:24] [23:16] [15:8] [7:0] -> [7:0] [15:8] [23:16] [31:24]*/ - uint32_t input_16bit_swap_en : 1; /*!< Set to 1 to enable input 16bit bit swap. [31:16] [15:0] -> [15:0] [31:16] */ - uint32_t byte_swap_en : 1; /*!< Set to 1 to enable output byte swap. */ - uint32_t bk_buffer_dis : 1; /*!< Set to 1 to disable backup buffer. */ - }; /*!< Boolean flags. */ + uint32_t input_8bit_swap_en : 1; /*!< Set to 1 to enable input 8bit bit swap. [31:24] [23:16] [15:8] [7:0] -> [7:0] [15:8] [23:16] [31:24]*/ + uint32_t input_16bit_swap_en : 1; /*!< Set to 1 to enable input 16bit bit swap. [31:16] [15:0] -> [15:0] [31:16] */ + uint32_t byte_swap_en : 1; /*!< Set to 1 to enable output byte swap. */ + uint32_t bk_buffer_dis : 1; /*!< Set to 1 to disable backup buffer. */ + }; /*!< Boolean flags. */ } esp_cam_ctlr_csi_config_t; /** diff --git a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c index af61a130caf..fea9748a9b1 100644 --- a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c +++ b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c @@ -103,8 +103,10 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ esp_err_t ret = ESP_FAIL; ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(config->data_lane_num <= MIPI_CSI_HOST_LL_LANE_NUM_MAX, ESP_ERR_INVALID_ARG, TAG, "lane num should be equal or smaller than %d", MIPI_CSI_HOST_LL_LANE_NUM_MAX); - ESP_RETURN_ON_FALSE(config->input_data_color_type != 0, ESP_ERR_INVALID_ARG, TAG, "input_data_color_type must be specified"); - ESP_RETURN_ON_FALSE(config->output_data_color_type != 0, ESP_ERR_INVALID_ARG, TAG, "output_data_color_type must be specified"); + if (!config->data_type.bits_per_pixel) { + ESP_RETURN_ON_FALSE(config->input_data_color_type != 0, ESP_ERR_INVALID_ARG, TAG, "input_data_color_type must be specified"); + ESP_RETURN_ON_FALSE(config->output_data_color_type != 0, ESP_ERR_INVALID_ARG, TAG, "output_data_color_type must be specified"); + } bool is_less_v1 = false; //version 1 since P4 rev3 #if CONFIG_IDF_TARGET_ESP32P4 @@ -149,23 +151,32 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ ESP_LOGD(TAG, "ctlr->h_res: 0d %"PRId32, ctlr->h_res); ESP_LOGD(TAG, "ctlr->v_res: 0d %"PRId32, ctlr->v_res); + ctlr->custom_data_depth = config->data_type.bits_per_pixel; //in color type - int in_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(config->input_data_color_type); - ESP_GOTO_ON_FALSE(in_bits_per_pixel != 0, ESP_ERR_INVALID_ARG, err, TAG, "unsupported input color format"); - ctlr->in_color_format = config->input_data_color_type; - ctlr->in_bpp = in_bits_per_pixel; + if (!config->data_type.bits_per_pixel) { + int in_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(config->input_data_color_type); + ESP_GOTO_ON_FALSE(in_bits_per_pixel != 0, ESP_ERR_INVALID_ARG, err, TAG, "unsupported input color format"); + ctlr->in_color_format = config->input_data_color_type; + ctlr->in_bpp = in_bits_per_pixel; + } else { + ctlr->in_bpp = config->data_type.bits_per_pixel; + } ESP_LOGD(TAG, "ctlr->in_bpp: 0d %d", ctlr->in_bpp); - //out color type - int out_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(config->output_data_color_type); + if (!config->data_type.bits_per_pixel) { + //out color type + int out_bits_per_pixel = color_hal_pixel_format_fourcc_get_bit_depth(config->output_data_color_type); - ESP_GOTO_ON_FALSE(out_bits_per_pixel != 0, ESP_ERR_INVALID_ARG, err, TAG, "unsupported output color format"); - ctlr->out_color_format = config->output_data_color_type; - ctlr->out_bpp = out_bits_per_pixel; + ESP_GOTO_ON_FALSE(out_bits_per_pixel != 0, ESP_ERR_INVALID_ARG, err, TAG, "unsupported output color format"); + ctlr->out_color_format = config->output_data_color_type; + ctlr->out_bpp = out_bits_per_pixel; + } else { + ctlr->out_bpp = config->data_type.bits_per_pixel; + } ESP_LOGD(TAG, "ctlr->out_bpp: 0d %d", ctlr->out_bpp); // Note: Width * Height * BitsPerPixel must be divisible by 8 - int fb_size_in_bits = config->v_res * config->h_res * out_bits_per_pixel; + int fb_size_in_bits = config->v_res * config->h_res * ctlr->out_bpp; ESP_GOTO_ON_FALSE((fb_size_in_bits % 8 == 0), ESP_ERR_INVALID_ARG, err, TAG, "framesize not 8bit aligned"); ctlr->fb_size_in_bytes = fb_size_in_bits / 8; ESP_LOGD(TAG, "ctlr->fb_size_in_bytes=%d", ctlr->fb_size_in_bytes); @@ -192,6 +203,15 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ hal_config.byte_swap_en = config->byte_swap_en; mipi_csi_hal_init(&ctlr->hal, &hal_config); mipi_csi_brg_ll_set_burst_len(ctlr->hal.bridge_dev, 512); + if (!config->data_type.bits_per_pixel) { + //for yuv, rgb and raw + mipi_csi_brg_ll_set_data_type_min(ctlr->hal.bridge_dev, 0x12); + mipi_csi_brg_ll_set_data_type_max(ctlr->hal.bridge_dev, 0x2f); + } else { + mipi_csi_brg_ll_set_data_type_min(ctlr->hal.bridge_dev, config->data_type.data_type_min); + mipi_csi_brg_ll_set_data_type_max(ctlr->hal.bridge_dev, config->data_type.data_type_max); + } + mipi_csi_brg_ll_enable_color_conversion(ctlr->hal.bridge_dev, true); cam_ctlr_format_conv_config_t format_conv_config = { .src_format = config->input_data_color_type, @@ -612,9 +632,7 @@ static esp_err_t s_csi_ctlr_format_conversion(esp_cam_ctlr_t *handle, const cam_ ESP_RETURN_ON_FALSE(handle && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); csi_controller_t *ctlr = __containerof(handle, csi_controller_t, base); - mipi_csi_brg_ll_enable_color_conversion(ctlr->hal.bridge_dev, true); - - if (config->src_format == config->dst_format) { + if (ctlr->custom_data_depth || config->src_format == config->dst_format) { mipi_csi_brg_ll_set_color_mode_bypass(ctlr->hal.bridge_dev, true); return ESP_OK; } else { diff --git a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi_internal.h b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi_internal.h index 7c15c81f82c..2e6dd05a333 100644 --- a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi_internal.h +++ b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi_internal.h @@ -52,6 +52,7 @@ struct csi_controller_t { portMUX_TYPE spinlock; //spinlock cam_ctlr_color_t in_color_format; //input color format cam_ctlr_color_t out_color_format; //output color format + uint32_t custom_data_depth; //custom data depth, bits per pixel uint32_t h_res; //input horizontal resolution uint32_t v_res; //input vertical resolution int in_bpp; //input data type, bit per pixel diff --git a/components/esp_hal_cam/include/hal/mipi_csi_types.h b/components/esp_hal_cam/include/hal/mipi_csi_types.h index 9458bc6ddb7..29052ae90f5 100644 --- a/components/esp_hal_cam/include/hal/mipi_csi_types.h +++ b/components/esp_hal_cam/include/hal/mipi_csi_types.h @@ -16,6 +16,9 @@ extern "C" { #endif +#define MIPI_CSI_CUSTOM_DATA_TYPE_MIN 0x30 +#define MIPI_CSI_CUSTOM_DATA_TYPE_MAX 0x37 + #if SOC_MIPI_CSI_SUPPORTED /** * @brief MIPI CSI PHY clock source diff --git a/components/esp_hal_cam/mipi_csi_hal.c b/components/esp_hal_cam/mipi_csi_hal.c index b7fd34c242b..bdec1ad41eb 100644 --- a/components/esp_hal_cam/mipi_csi_hal.c +++ b/components/esp_hal_cam/mipi_csi_hal.c @@ -71,7 +71,5 @@ void mipi_csi_hal_init(mipi_csi_hal_context_t *hal, const mipi_csi_hal_config_t mipi_csi_brg_ll_set_intput_data_h_pixel_num(hal->bridge_dev, config->frame_height); mipi_csi_brg_ll_set_intput_data_v_row_num(hal->bridge_dev, config->frame_width); mipi_csi_brg_ll_set_flow_ctl_buf_afull_thrd(hal->bridge_dev, 960); - mipi_csi_brg_ll_set_data_type_min(hal->bridge_dev, 0x12); - mipi_csi_brg_ll_set_data_type_max(hal->bridge_dev, 0x2f); mipi_csi_brg_ll_set_output_byte_endian(hal->bridge_dev, config->byte_swap_en); }