From 20878e3b7b6a2406da07e5c93cb0ac2fe03602a0 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Thu, 20 Nov 2025 14:07:33 +0800 Subject: [PATCH] feat(cam): support esp32p4 eco5 dvp cam --- .../dvp/include/esp_cam_ctlr_dvp.h | 29 +++++++++++++++++-- .../dvp/src/esp_cam_ctlr_dvp_cam.c | 18 +++++++++++- components/hal/cam_hal.c | 2 +- components/hal/include/hal/cam_hal.h | 2 ++ .../camera/dvp_dsi/main/dvp_dsi_main.c | 3 ++ .../camera/dvp_dsi/main/example_config.h | 1 - 6 files changed, 50 insertions(+), 5 deletions(-) diff --git a/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h b/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h index 032ab47a21..53cb812846 100644 --- a/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h +++ b/components/esp_driver_cam/dvp/include/esp_cam_ctlr_dvp.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -38,8 +38,33 @@ typedef struct esp_cam_ctlr_dvp_config { uint32_t h_res; /*!< Input horizontal resolution, i.e. the number of pixels in a line */ uint32_t v_res; /*!< Input vertical resolution, i.e. the number of lines in a frame */ cam_ctlr_color_t input_data_color_type; /*!< Input pixel format */ + uint32_t cam_data_width; /*!< Byte width, 8, 16 or 24 bit, default to 8 */ struct { - uint32_t byte_swap_en : 1; /*!< Enable byte swap */ + uint32_t bit_swap_en : 1; /*!< Enable bit swap */ + uint32_t byte_swap_en : 1; /*!< Enable byte swap + * + * GDMA Data Byte Order Table (input: B0,B1,B2,B3,B4,B5, addresses from low to high) + * + * | cam_data_width | bit_swap_en | byte_swap_en | Stage 1 Output Data Sequence | + * |----------------|-------------|--------------|------------------------------ | + * | 8-bit | 0 | 0 | {B0}{B1}{B2}{B3}{B4}{B5} | + * | 8-bit | 0 | 1 | {B1,B0}{B3,B2}{B5,B4} | + * | 8-bit | 1 | 0 | {B0'}{B1'}{B2'}{B3'}{B4'}{B5'} | + * | 8-bit | 1 | 1 | {B1',B0'}{B3',B2'}{B5',B4'} | + * + * | 16-bit | 0 | 0 | {B1,B0}{B3,B2}{B5,B4} | + * | 16-bit | 0 | 1 | {B0,B1}{B2,B3}{B4,B5} | + * | 16-bit | 1 | 0 | {B1',B0'}{B3',B2'}{B5',B4'} | + * | 16-bit | 1 | 1 | {B0',B1'}{B2',B3'}{B4',B5'} | + * + * | 24-bit | 0 | 0 | {B2,B1,B0}{B5,B4,B3} | + * | 24-bit | 0 | 1 | {B0,B1,B2}{B3,B4,B5} | + * | 24-bit | 1 | 0 | {B2',B1',B0'}{B5',B4',B3'} | + * | 24-bit | 1 | 1 | {B0',B1',B2'}{B3',B4',B5'} | + * + * Where B0' = bit-reversed B0,Bn'[7:0] = Bn[0:7] + * Each {} contains big-endian parallel data, {} are in serial relationship, output order is left to right + */ uint32_t bk_buffer_dis : 1; /*!< Disable backup buffer */ uint32_t pin_dont_init : 1; /*!< Don't initialize DVP pins if users have called "esp_cam_ctlr_dvp_init" before */ uint32_t pic_format_jpeg : 1; /*!< Input picture format is JPEG, if set this flag and "input_data_color_type" will be ignored */ diff --git a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c index 0d548f76a2..0a2096701a 100644 --- a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c +++ b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c @@ -790,7 +790,9 @@ static void *esp_cam_ctlr_dvp_cam_alloc_buffer(esp_cam_ctlr_t *handle, size_t si * @param cam_handle Camera controller handle * @param src_format Source format * @param dst_format Destination format - * @return ESP_OK on success, ESP_FAIL on failure + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG: Invalid argument */ esp_err_t esp_cam_ctlr_dvp_format_conversion(esp_cam_ctlr_handle_t cam_handle, const cam_ctlr_format_conv_config_t *config) @@ -803,6 +805,12 @@ esp_err_t esp_cam_ctlr_dvp_format_conversion(esp_cam_ctlr_handle_t cam_handle, ESP_LOGD(TAG, "Configure format conversion: %d -> %d", config->src_format, config->dst_format); +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 + if (config->src_format == CAM_CTLR_COLOR_YUV420) { + ESP_LOGE(TAG, "YUV420 is not allowed for source format"); + return ESP_ERR_INVALID_ARG; + } +#endif // Configure color format conversion cam_hal_color_format_convert(&ctlr->hal, config); @@ -868,9 +876,17 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_ cam_hal_config_t cam_hal_config = { .port = config->ctlr_id, + .cam_data_width = config->cam_data_width == 0 ? 8 : config->cam_data_width, + .bit_swap_en = config->bit_swap_en, .byte_swap_en = config->byte_swap_en, }; + ESP_RETURN_ON_FALSE(cam_hal_config.cam_data_width == 8 || cam_hal_config.cam_data_width == 16 || cam_hal_config.cam_data_width == 24, ESP_ERR_INVALID_ARG, TAG, "invalid argument: cam_data_width is not 8 or 16 or 24"); + +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 + ESP_RETURN_ON_FALSE(cam_hal_config.cam_data_width != 8 || cam_hal_config.byte_swap_en == 0, ESP_ERR_INVALID_ARG, TAG, "invalid argument: byte swap is not supported when cam_data_width is 8"); +#endif + if (!config->pin_dont_init) { // Initialzie DVP clock and GPIO internally ESP_GOTO_ON_ERROR(esp_cam_ctlr_dvp_init(config->ctlr_id, config->clk_src, config->pin), diff --git a/components/hal/cam_hal.c b/components/hal/cam_hal.c index c739f05d91..f4f8ee8577 100644 --- a/components/hal/cam_hal.c +++ b/components/hal/cam_hal.c @@ -74,7 +74,7 @@ void cam_hal_init(cam_hal_context_t *hal, const cam_hal_config_t *config) cam_ll_enable_stop_signal(hal->hw, 0); cam_ll_swap_dma_data_byte_order(hal->hw, config->byte_swap_en); - cam_ll_reverse_dma_data_bit_order(hal->hw, 0); + cam_ll_reverse_dma_data_bit_order(hal->hw, config->bit_swap_en); cam_ll_enable_vsync_generate_eof(hal->hw, 1); cam_hal_set_line_int_num(hal, 0); diff --git a/components/hal/include/hal/cam_hal.h b/components/hal/include/hal/cam_hal.h index e63e6440e5..79901c3ee6 100644 --- a/components/hal/include/hal/cam_hal.h +++ b/components/hal/include/hal/cam_hal.h @@ -28,6 +28,8 @@ typedef struct cam_hal_context { */ typedef struct cam_hal_config { int port; /*!< CAM port */ + uint32_t cam_data_width; /*!< CAM data width, 8 or 16 or 24 bit, default to 8 */ + bool bit_swap_en; /*!< CAM enable bit swap */ bool byte_swap_en; /*!< CAM enable byte swap */ } cam_hal_config_t; diff --git a/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c b/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c index 1b18668faf..0bf5d203cc 100644 --- a/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c +++ b/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c @@ -96,6 +96,9 @@ void app_main(void) .pin = &pin_cfg, .bk_buffer_dis = 1, .xclk_freq = EXAMPLE_DVP_CAM_XCLK_FREQ_HZ, + .cam_data_width = EXAMPLE_DVP_CAM_DATA_WIDTH, + .bit_swap_en = false, + .byte_swap_en = false, }; ret = esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle); diff --git a/examples/peripherals/camera/dvp_dsi/main/example_config.h b/examples/peripherals/camera/dvp_dsi/main/example_config.h index eb76ca211f..ab2b0e4c30 100644 --- a/examples/peripherals/camera/dvp_dsi/main/example_config.h +++ b/examples/peripherals/camera/dvp_dsi/main/example_config.h @@ -38,7 +38,6 @@ extern "C" { #define EXAMPLE_DVP_CAM_HSYNC_IO (-1) #else - #define EXAMPLE_DVP_CAM_SCCB_SCL_IO (33) #define EXAMPLE_DVP_CAM_SCCB_SDA_IO (32)