feat(csi): support csi input bit swap

This commit is contained in:
armando
2026-02-02 15:17:59 +08:00
committed by Armando (Dou Yiwen)
parent f2635f98d9
commit 303da81075
6 changed files with 218 additions and 152 deletions
@@ -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;
@@ -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;
@@ -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
@@ -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
+1 -1
View File
@@ -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);
}
@@ -1,3 +1,2 @@
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_SPIRAM_SPEED_250M=y