From a472bfbb69480264e62b09fca551a55ff3284f0a Mon Sep 17 00:00:00 2001 From: armando Date: Thu, 12 Feb 2026 15:29:40 +0800 Subject: [PATCH] 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 5f63887415..ee3c61477b 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 af61a130ca..fea9748a9b 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 7c15c81f82..2e6dd05a33 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 9458bc6ddb..29052ae90f 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 b7fd34c242..bdec1ad41e 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); }