From 0e1ee38ae8b71842655177331d42efbd7563ea38 Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 15 Oct 2024 17:25:34 +0800 Subject: [PATCH 1/3] feat(isp): added lsc feature --- components/esp_driver_isp/CMakeLists.txt | 4 + .../esp_driver_isp/include/driver/isp.h | 1 + .../esp_driver_isp/include/driver/isp_core.h | 2 + .../esp_driver_isp/include/driver/isp_lsc.h | 90 ++++++++++++ .../include/esp_private/isp_private.h | 4 +- components/esp_driver_isp/src/isp_core.c | 2 + components/esp_driver_isp/src/isp_lsc.c | 101 +++++++++++++ components/hal/esp32p4/include/hal/isp_ll.h | 138 ++++++++++++++++-- components/hal/include/hal/color_types.h | 9 ++ components/hal/include/hal/isp_types.h | 25 ++++ .../esp32p4/include/soc/Kconfig.soc_caps.in | 16 ++ components/soc/esp32p4/include/soc/soc_caps.h | 4 + 12 files changed, 381 insertions(+), 15 deletions(-) create mode 100644 components/esp_driver_isp/include/driver/isp_lsc.h create mode 100644 components/esp_driver_isp/src/isp_lsc.c diff --git a/components/esp_driver_isp/CMakeLists.txt b/components/esp_driver_isp/CMakeLists.txt index 3cffb62c4c..ab7761edb6 100644 --- a/components/esp_driver_isp/CMakeLists.txt +++ b/components/esp_driver_isp/CMakeLists.txt @@ -34,6 +34,10 @@ if(CONFIG_SOC_ISP_COLOR_SUPPORTED) list(APPEND srcs "src/isp_color.c") endif() +if(CONFIG_SOC_ISP_LSC_SUPPORTED) + list(APPEND srcs "src/isp_lsc.c") +endif() + if(NOT ${target} STREQUAL "linux") list(APPEND requires esp_mm) endif() diff --git a/components/esp_driver_isp/include/driver/isp.h b/components/esp_driver_isp/include/driver/isp.h index 92370fb427..235aca350e 100644 --- a/components/esp_driver_isp/include/driver/isp.h +++ b/components/esp_driver_isp/include/driver/isp.h @@ -22,3 +22,4 @@ #include "driver/isp_hist.h" #include "driver/isp_sharpen.h" #include "driver/isp_color.h" +#include "driver/isp_lsc.h" diff --git a/components/esp_driver_isp/include/driver/isp_core.h b/components/esp_driver_isp/include/driver/isp_core.h index ef8307645c..c1f61928bf 100644 --- a/components/esp_driver_isp/include/driver/isp_core.h +++ b/components/esp_driver_isp/include/driver/isp_core.h @@ -10,6 +10,7 @@ #include #include "esp_err.h" #include "driver/isp_types.h" +#include "hal/color_types.h" #ifdef __cplusplus extern "C" { @@ -30,6 +31,7 @@ typedef struct { bool has_line_end_packet; ///< Enable line end packet 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 + color_raw_element_order_t bayer_order; ///< Bayer order int intr_priority; ///< The interrupt priority, range 0~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) } esp_isp_processor_cfg_t; diff --git a/components/esp_driver_isp/include/driver/isp_lsc.h b/components/esp_driver_isp/include/driver/isp_lsc.h new file mode 100644 index 0000000000..d4f7e6e30b --- /dev/null +++ b/components/esp_driver_isp/include/driver/isp_lsc.h @@ -0,0 +1,90 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/isp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LSC Gain array + */ +typedef struct { + isp_lsc_gain_t *gain_r; ///< Gain for R channel + isp_lsc_gain_t *gain_gr; ///< Gain for GR channel + isp_lsc_gain_t *gain_gb; ///< Gain for GB channel + isp_lsc_gain_t *gain_b; ///< Gain for B channel +} esp_isp_lsc_gain_array_t; + +/** + * @brief ISP LSC configurations + */ +typedef struct { + esp_isp_lsc_gain_array_t *gain_array; ///< Gain array +} esp_isp_lsc_config_t; + +/** + * @brief Helper function to allocate gain array for LSC + * + * @param[in] proc Processor handle + * @param[in] gain_array Gain array to be allocated + * @param[out] out_array_size_per_channel Array size + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_STATE Not allowed to be called under current state + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_lsc_gain_array_t *gain_array, size_t *out_array_size_per_channel); + +/** + * @brief ISP LSC configuration + * + * @note After calling this API, LSC doesn't take into effect until `esp_isp_lsc_enable` is called + * + * @param[in] proc Processor handle + * @param[in] config LSC configurations + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_STATE Not allowed to be called under current state + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid + */ +esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_config_t *config); + +/** + * @brief Enable ISP LSC function + * + * @param[in] proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_INVALID_STATE Driver state is invalid. + */ +esp_err_t esp_isp_lsc_enable(isp_proc_handle_t isp_proc); + +/** + * @brief Disable ISP LSC function + * + * @param[in] proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_INVALID_STATE Driver state is invalid. + */ +esp_err_t esp_isp_lsc_disable(isp_proc_handle_t isp_proc); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 1f96bea135..a0e6913ca5 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -64,6 +64,7 @@ typedef struct isp_processor_t { color_space_pixel_format_t out_color_format; uint32_t h_res; uint32_t v_res; + color_raw_element_order_t bayer_order; /* sub module contexts */ isp_af_ctlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS]; isp_awb_ctlr_t awb_ctlr; @@ -73,6 +74,7 @@ typedef struct isp_processor_t { isp_fsm_t demosaic_fsm; isp_fsm_t sharpen_fsm; isp_fsm_t color_fsm; + isp_fsm_t lsc_fsm; esp_isp_evt_cbs_t cbs; void *user_data; @@ -85,7 +87,7 @@ typedef struct isp_processor_t { uint32_t ae_isr_added: 1; uint32_t awb_isr_added: 1; uint32_t sharp_isr_added: 1; - uint32_t hist_isr_added: 1; + uint32_t hist_isr_added: 1; } isr_users; } isp_processor_t; diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index f3ff71e625..f964aaa1cc 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -139,6 +139,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ isp_ll_enable_line_end_packet_exist(proc->hal.hw, proc_config->has_line_end_packet); isp_ll_set_intput_data_h_pixel_num(proc->hal.hw, proc_config->h_res); isp_ll_set_intput_data_v_row_num(proc->hal.hw, proc_config->v_res); + isp_ll_set_bayer_mode(proc->hal.hw, proc_config->bayer_order); isp_ll_yuv_set_std(proc->hal.hw, proc_config->yuv_std); if (out_color_format.color_space == COLOR_SPACE_YUV) { isp_ll_yuv_set_range(proc->hal.hw, proc_config->yuv_range); @@ -148,6 +149,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ proc->out_color_format = out_color_format; proc->h_res = proc_config->h_res; proc->v_res = proc_config->v_res; + proc->bayer_order = proc_config->bayer_order; *ret_proc = proc; diff --git a/components/esp_driver_isp/src/isp_lsc.c b/components/esp_driver_isp/src/isp_lsc.c new file mode 100644 index 0000000000..97f7c576c9 --- /dev/null +++ b/components/esp_driver_isp/src/isp_lsc.c @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_check.h" +#include "freertos/FreeRTOS.h" +#include "driver/isp_core.h" +#include "driver/isp_bf.h" +#include "driver/isp_lsc.h" +#include "esp_private/isp_private.h" + +/*--------------------------------------------------------------- + LSC +---------------------------------------------------------------*/ +#define ISP_LSC_GET_GRIDS(res) (((res) - 1) / 2 / ISP_LL_LSC_GRID_HEIGHT + 2) + +static const char *TAG = "ISP_LSC"; + +esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_lsc_gain_array_t *gain_array, size_t *out_array_size_per_channel) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); + + int num_grids_x_max = ISP_LSC_GET_GRIDS(ISP_LL_HSIZE_MAX); + int num_grids_y_max = ISP_LSC_GET_GRIDS(ISP_LL_VSIZE_MAX); + int num_grids_x = ISP_LSC_GET_GRIDS(isp_proc->h_res); + int num_grids_y = ISP_LSC_GET_GRIDS(isp_proc->v_res); + ESP_LOGD(TAG, "num_grids_x_max: %d, num_grids_x: %d, num_grids_y_max: %d, num_grids_y: %d", num_grids_x_max, num_grids_y_max, num_grids_x, num_grids_y); + ESP_RETURN_ON_FALSE(num_grids_x <= num_grids_x_max && num_grids_y <= num_grids_y_max, ESP_ERR_INVALID_ARG, TAG, "invalid h_res or v_res"); + + gain_array->gain_r = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + gain_array->gain_gr = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + gain_array->gain_gb = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + gain_array->gain_b = (isp_lsc_gain_t *)heap_caps_calloc(1, num_grids_x * num_grids_y * sizeof(isp_lsc_gain_t), ISP_MEM_ALLOC_CAPS); + + if (!gain_array->gain_r || !gain_array->gain_gr || !gain_array->gain_gb || !gain_array->gain_b) { + ESP_LOGE(TAG, "no enough mem for gain arrays"); + return ESP_ERR_NO_MEM; + } + ESP_LOGD(TAG, "gain_array->gain_r: %p, gain_array->gain_gr: %p, gain_array->gain_gb: %p, gain_array->gain_b: %p", gain_array->gain_r, gain_array->gain_gr, gain_array->gain_gb, gain_array->gain_b); + *out_array_size_per_channel = num_grids_x * num_grids_y; + return ESP_OK; +} + +esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_config_t *config) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + + int num_grids_x_max = ISP_LSC_GET_GRIDS(ISP_LL_HSIZE_MAX); + int num_grids_y_max = ISP_LSC_GET_GRIDS(ISP_LL_VSIZE_MAX); + int num_grids_x = ISP_LSC_GET_GRIDS(isp_proc->h_res); + int num_grids_y = ISP_LSC_GET_GRIDS(isp_proc->v_res); + ESP_LOGD(TAG, "num_grids_x_max: %d, num_grids_x: %d, num_grids_y_max: %d, num_grids_y: %d", num_grids_x_max, num_grids_y_max, num_grids_x, num_grids_y); + ESP_RETURN_ON_FALSE(num_grids_x <= num_grids_x_max && num_grids_y <= num_grids_y_max, ESP_ERR_INVALID_ARG, TAG, "invalid h_res or v_res"); + ESP_RETURN_ON_FALSE(config->gain_array->gain_r && config->gain_array->gain_gr && config->gain_array->gain_gb && config->gain_array->gain_b, ESP_ERR_INVALID_ARG, TAG, "null pointer to gain arrays"); + + isp_ll_lsc_set_xtablesize(isp_proc->hal.hw, num_grids_x); + + for (int y = 0; y < num_grids_y; y++) { + for (int x = 0; x < num_grids_x; x++) { + int i = y * num_grids_x + x; + isp_ll_lut_set_wdata_r_gr(isp_proc->hal.hw, config->gain_array->gain_r[i], config->gain_array->gain_gr[i]); + isp_ll_lut_set_cmd(isp_proc->hal.hw, true, false, i, ISP_LL_LUT_LSC); + isp_ll_lut_set_wdata_gb_b(isp_proc->hal.hw, config->gain_array->gain_gb[i], config->gain_array->gain_b[i]); + isp_ll_lut_set_cmd(isp_proc->hal.hw, true, true, i, ISP_LL_LUT_LSC); + } + } + + return ESP_OK; +} + +esp_err_t esp_isp_lsc_enable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); + + isp_ll_lsc_clk_enable(isp_proc->hal.hw, true); + isp_ll_lsc_enable(isp_proc->hal.hw, true); + isp_proc->lsc_fsm = ISP_FSM_ENABLE; + + return ESP_OK; +} + +esp_err_t esp_isp_lsc_disable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "lsc isn't enabled yet"); + + isp_ll_lsc_enable(isp_proc->hal.hw, false); + isp_ll_lsc_clk_enable(isp_proc->hal.hw, false); + isp_proc->lsc_fsm = ISP_FSM_INIT; + + return ESP_OK; +} diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 9deb1b8781..00712b1256 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -22,7 +22,10 @@ extern "C" { #endif -#define ISP_LL_GET_HW(num) (((num) == 0) ? (&ISP) : NULL) +#define ISP_LL_GET_HW(num) (((num) == 0) ? (&ISP) : NULL) + +#define ISP_LL_HSIZE_MAX 1920 +#define ISP_LL_VSIZE_MAX 1080 /*--------------------------------------------------------------- Clock @@ -81,6 +84,14 @@ extern "C" { ---------------------------------------------------------------*/ #define ISP_LL_AE_WINDOW_MAX_RANGE ((1<<12) - 1) +/*--------------------------------------------------------------- + AWB +---------------------------------------------------------------*/ +#define ISP_LL_AWB_WINDOW_MAX_RANGE ((1<<12) - 1) +#define ISP_LL_AWB_LUM_MAX_RANGE ((1<<10) - 1) +#define ISP_LL_AWB_RGB_RATIO_INT_BITS (2) +#define ISP_LL_AWB_RGB_RATIO_FRAC_BITS (8) + /*--------------------------------------------------------------- BF ---------------------------------------------------------------*/ @@ -103,20 +114,10 @@ extern "C" { #define ISP_LL_COLOR_BRIGNTNESS_MAX 127 /*--------------------------------------------------------------- - AWB + LSC ---------------------------------------------------------------*/ -#define ISP_LL_AWB_WINDOW_MAX_RANGE ((1<<12) - 1) -#define ISP_LL_AWB_LUM_MAX_RANGE ((1<<10) - 1) -#define ISP_LL_AWB_RGB_RATIO_INT_BITS (2) -#define ISP_LL_AWB_RGB_RATIO_FRAC_BITS (8) - -typedef union { - struct { - uint32_t fraction: ISP_LL_AWB_RGB_RATIO_FRAC_BITS; - uint32_t integer: ISP_LL_AWB_RGB_RATIO_INT_BITS; - }; - uint32_t val; -} isp_ll_awb_rgb_ratio_t; +#define ISP_LL_LSC_GRID_HEIGHT 32 +#define ISP_LL_LSC_GRID_WIDTH 32 /*--------------------------------------------------------------- CCM @@ -150,6 +151,22 @@ typedef enum { ISP_LL_AF_EDGE_DETECTOR_MODE_MANUAL, ///< Manual set threshold } isp_ll_af_edge_detector_mode_t; +typedef union { + struct { + uint32_t fraction: ISP_LL_AWB_RGB_RATIO_FRAC_BITS; + uint32_t integer: ISP_LL_AWB_RGB_RATIO_INT_BITS; + }; + uint32_t val; +} isp_ll_awb_rgb_ratio_t; + +/** + * @brief ISP LUT + */ +typedef enum { + ISP_LL_LUT_LSC, ///< LUT for LSC + ISP_LL_LUT_DPC, ///< LUT for DPC +} isp_ll_lut_t; + /*--------------------------------------------------------------- Clock @@ -463,6 +480,17 @@ static inline bool isp_ll_is_rgb2yuv_enabled(isp_dev_t *hw) return hw->cntl.rgb2yuv_en; } +/** + * @brief Set bayer mode + * + * @param[in] hw Hardware instance address + * @param[in] bayer_order Bayer order + */ +static inline void isp_ll_set_bayer_mode(isp_dev_t *hw, color_raw_element_order_t bayer_order) +{ + hw->frame_cfg.bayer_mode = bayer_order; +} + /*--------------------------------------------------------------- AF ---------------------------------------------------------------*/ @@ -1153,6 +1181,88 @@ static inline void isp_ll_ae_env_detector_set_period(isp_dev_t *hw, uint32_t per hw->ae_monitor.ae_monitor_period = period; } +/*--------------------------------------------------------------- + LSC +---------------------------------------------------------------*/ +/** + * @brief Enable / Disable LSC clock + * + * @param[in] hw Hardware instance address + * @param[in] enable Enable / Disable + */ +static inline void isp_ll_lsc_clk_enable(isp_dev_t *hw, bool enable) +{ + hw->clk_en.clk_lsc_force_on = enable; +} + +/** + * @brief Enable / Disable Color + * + * @param[in] hw Hardware instance address + * @param[in] enable Enable / Disable + */ +static inline void isp_ll_lsc_enable(isp_dev_t *hw, bool enable) +{ + hw->cntl.lsc_en = enable; +} + +/** + * @brief Set xtable size + * + * @param[in] hw Hardware instance address + * @param[in] xtablesize xtablesize + */ +static inline void isp_ll_lsc_set_xtablesize(isp_dev_t *hw, uint8_t xtablesize) +{ + hw->lsc_tablesize.lsc_xtablesize = xtablesize; +} + +/*--------------------------------------------------------------- + LUT +---------------------------------------------------------------*/ +/** + * @brief Select ISP LUT + * + * @param[in] hw Hardware instance address + * @param[in] is_write Is write or not + * @param[in] is_gb_b Is gb_b or not + * @param[in] addr LUT addr + * @param[in] lut ISP LUT + */ +static inline void isp_ll_lut_set_cmd(isp_dev_t *hw, bool is_write, bool is_gb_b, uint32_t addr, isp_ll_lut_t lut) +{ + uint32_t val = 0; + val |= is_write ? (1 << 16) : 0; + val |= is_gb_b ? 0 : (1 << 10); + val |= addr & ((1 << 10) - 1); + val |= lut << 12; + hw->lut_cmd.val = val; +} + +/** + * @brief Set lut gb and b gain + * + * @param[in] hw Hardware instance address + * @param[in] gb_gain gb gain + * @param[in] b_gain b gain + */ +static inline void isp_ll_lut_set_wdata_gb_b(isp_dev_t *hw, isp_lsc_gain_t gb_gain, isp_lsc_gain_t b_gain) +{ + hw->lut_wdata.lut_wdata = (gb_gain.val & 0x3ff) << 10 | (b_gain.val & 0x3ff); +} + +/** + * @brief Set lut r and gr gain + * + * @param[in] hw Hardware instance address + * @param[in] r_gain r gain + * @param[in] gr_gain gr gain + */ +static inline void isp_ll_lut_set_wdata_r_gr(isp_dev_t *hw, isp_lsc_gain_t r_gain, isp_lsc_gain_t gr_gain) +{ + hw->lut_wdata.lut_wdata = (r_gain.val & 0x3ff) << 10 | (gr_gain.val & 0x3ff); +} + /*--------------------------------------------------------------- INTR ---------------------------------------------------------------*/ diff --git a/components/hal/include/hal/color_types.h b/components/hal/include/hal/color_types.h index 2cdd7d3310..ec61878d49 100644 --- a/components/hal/include/hal/color_types.h +++ b/components/hal/include/hal/color_types.h @@ -141,6 +141,15 @@ typedef enum { /*--------------------------------------------------------------- Color Endian ---------------------------------------------------------------*/ +/** + * @brief RAW element order + */ +typedef enum { + COLOR_RAW_ELEMENT_ORDER_BGGR, ///< BGGR order + COLOR_RAW_ELEMENT_ORDER_GBRG, ///< GBRG order + COLOR_RAW_ELEMENT_ORDER_GRBG, ///< GRBG order + COLOR_RAW_ELEMENT_ORDER_RGGB, ///< RGGB order +} color_raw_element_order_t; /** * @brief RGB element order diff --git a/components/hal/include/hal/isp_types.h b/components/hal/include/hal/isp_types.h index ae7d001f5b..974c5a3d35 100644 --- a/components/hal/include/hal/isp_types.h +++ b/components/hal/include/hal/isp_types.h @@ -393,6 +393,31 @@ typedef union { uint32_t val; ///< 32-bit color saturation value } isp_color_saturation_t; +/*--------------------------------------------------------------- + LSC +---------------------------------------------------------------*/ +#if SOC_ISP_LSC_SUPPORTED +#define ISP_LSC_GRAD_RATIO_INT_BITS SOC_ISP_LSC_GRAD_RATIO_INT_BITS +#define ISP_LSC_GRAD_RATIO_DEC_BITS SOC_ISP_LSC_GRAD_RATIO_DEC_BITS +#define ISP_LSC_GRAD_RATIO_RES_BITS SOC_ISP_LSC_GRAD_RATIO_RES_BITS +#else +#define ISP_LSC_GRAD_RATIO_INT_BITS 2 +#define ISP_LSC_GRAD_RATIO_DEC_BITS 8 +#define ISP_LSC_GRAD_RATIO_RES_BITS 22 +#endif + +/** + * @brief LSC gain + */ +typedef union { + struct { + uint32_t decimal:8; ///< Integer part + uint32_t integer:2; ///< Decimal part + uint32_t reserved:ISP_LSC_GRAD_RATIO_RES_BITS; ///< Reserved + }; + uint32_t val; ///< 32-bit gradient ratio value +} isp_lsc_gain_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 402a686f3e..a844aa197a 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -887,6 +887,10 @@ config SOC_ISP_COLOR_SUPPORTED bool default y +config SOC_ISP_LSC_SUPPORTED + bool + default y + config SOC_ISP_SHARE_CSI_BRG bool default y @@ -999,6 +1003,18 @@ config SOC_ISP_HIST_INTERVAL_NUMS int default 15 +config SOC_ISP_LSC_GRAD_RATIO_INT_BITS + int + default 2 + +config SOC_ISP_LSC_GRAD_RATIO_DEC_BITS + int + default 8 + +config SOC_ISP_LSC_GRAD_RATIO_RES_BITS + int + default 22 + config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 725d954dd4..cb5ea7dc6b 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -342,6 +342,7 @@ #define SOC_ISP_DVP_SUPPORTED 1 #define SOC_ISP_SHARPEN_SUPPORTED 1 #define SOC_ISP_COLOR_SUPPORTED 1 +#define SOC_ISP_LSC_SUPPORTED 1 #define SOC_ISP_SHARE_CSI_BRG 1 #define SOC_ISP_NUMS 1U @@ -371,6 +372,9 @@ #define SOC_ISP_HIST_BLOCK_Y_NUMS 5 #define SOC_ISP_HIST_SEGMENT_NUMS 16 #define SOC_ISP_HIST_INTERVAL_NUMS 15 +#define SOC_ISP_LSC_GRAD_RATIO_INT_BITS 2 +#define SOC_ISP_LSC_GRAD_RATIO_DEC_BITS 8 +#define SOC_ISP_LSC_GRAD_RATIO_RES_BITS 22 /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1) From 14f0f344eaf15966f1a576d1b129ebc7bf5f14cc Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 15 Oct 2024 17:26:55 +0800 Subject: [PATCH 2/3] feat(isp): lsc example --- .../components/dsi_init/Kconfig.projbuild | 4 ++-- .../peripherals/isp/multi_pipelines/README.md | 1 + .../isp/multi_pipelines/main/isp_dsi_main.c | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild b/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild index 6e81a71006..e433698706 100644 --- a/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild +++ b/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild @@ -13,7 +13,7 @@ menu "Example DSI Configuration" endchoice choice EXAMPLE_MIPI_DSI_DISP_HRES - bool "Set MIPI CSI horizontal resolution" + bool "Set MIPI DSI horizontal resolution" default EXAMPLE_MIPI_DSI_DISP_HRES_800 if EXAMPLE_LCD_PATTERN_ILI9881C default EXAMPLE_MIPI_DSI_DISP_HRES_1024 if EXAMPLE_LCD_PATTERN_EK79007 default EXAMPLE_MIPI_DSI_DISP_HRES_800 @@ -30,7 +30,7 @@ menu "Example DSI Configuration" default 1024 if EXAMPLE_MIPI_DSI_DISP_HRES_1024 choice EXAMPLE_MIPI_DSI_DISP_VRES - bool "Set MIPI CSI vertical resolution" + bool "Set MIPI DSI vertical resolution" default EXAMPLE_MIPI_DSI_DISP_VRES_1280 if EXAMPLE_LCD_PATTERN_ILI9881C default EXAMPLE_MIPI_DSI_DISP_VRES_600 if EXAMPLE_LCD_PATTERN_EK79007 default EXAMPLE_MIPI_DSI_DISP_VRES_1280 diff --git a/examples/peripherals/isp/multi_pipelines/README.md b/examples/peripherals/isp/multi_pipelines/README.md index 71139ba6b4..bfd80fbec1 100644 --- a/examples/peripherals/isp/multi_pipelines/README.md +++ b/examples/peripherals/isp/multi_pipelines/README.md @@ -14,6 +14,7 @@ This example demonstrates how to use the ISP (image signal processor) to work wi - ISP Demosaic feature - ISP GAMMA feature - ISP Color feature +- ISP LSC feature ## Usage diff --git a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c index 15a9289cf6..00e2dab0c8 100644 --- a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c +++ b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c @@ -347,6 +347,26 @@ void app_main(void) ESP_ERROR_CHECK(esp_isp_color_configure(isp_proc, &color_config)); ESP_ERROR_CHECK(esp_isp_color_enable(isp_proc)); + esp_isp_lsc_gain_array_t gain_array = {}; + esp_isp_lsc_config_t lsc_config = { + .gain_array = &gain_array, + }; + size_t gain_size = 0; + ESP_ERROR_CHECK(esp_isp_lsc_allocate_gain_array(isp_proc, &gain_array, &gain_size)); + + isp_lsc_gain_t gain_val = { + .decimal = 204, + .integer = 0, + }; + for (int i = 0; i < gain_size; i++) { + gain_array.gain_r[i].val = gain_val.val; + gain_array.gain_gr[i].val = gain_val.val; + gain_array.gain_gb[i].val = gain_val.val; + gain_array.gain_b[i].val = gain_val.val; + } + ESP_ERROR_CHECK(esp_isp_lsc_configure(isp_proc, &lsc_config)); + ESP_ERROR_CHECK(esp_isp_lsc_enable(isp_proc)); + typedef struct af_task_param_t { isp_proc_handle_t isp_proc; esp_sccb_io_handle_t dw9714_io_handle; From 7e02f87bc916c6c36727256e0b0277e18933025a Mon Sep 17 00:00:00 2001 From: Armando Date: Wed, 16 Oct 2024 15:05:01 +0800 Subject: [PATCH 3/3] change(isp): added eco2 check --- components/esp_driver_isp/include/driver/isp_lsc.h | 1 + components/esp_driver_isp/src/isp_lsc.c | 9 +++++++++ .../peripherals/isp/multi_pipelines/main/isp_dsi_main.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/components/esp_driver_isp/include/driver/isp_lsc.h b/components/esp_driver_isp/include/driver/isp_lsc.h index d4f7e6e30b..db32c74ff1 100644 --- a/components/esp_driver_isp/include/driver/isp_lsc.h +++ b/components/esp_driver_isp/include/driver/isp_lsc.h @@ -58,6 +58,7 @@ esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_ls * - ESP_OK On success * - ESP_ERR_INVALID_STATE Not allowed to be called under current state * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid + * - ESP_ERR_NOT_SUPPORTED Not supported */ esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_config_t *config); diff --git a/components/esp_driver_isp/src/isp_lsc.c b/components/esp_driver_isp/src/isp_lsc.c index 97f7c576c9..d8996e2905 100644 --- a/components/esp_driver_isp/src/isp_lsc.c +++ b/components/esp_driver_isp/src/isp_lsc.c @@ -15,6 +15,8 @@ #include "driver/isp_bf.h" #include "driver/isp_lsc.h" #include "esp_private/isp_private.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" /*--------------------------------------------------------------- LSC @@ -51,6 +53,13 @@ esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_ls esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_config_t *config) { +#if CONFIG_IDF_TARGET_ESP32P4 + unsigned chip_version = efuse_hal_chip_revision(); + if (!ESP_CHIP_REV_ABOVE(chip_version, 100)) { + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "LSC is not supported on ESP32P4 chips prior than ECO2"); + } +#endif + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); int num_grids_x_max = ISP_LSC_GET_GRIDS(ISP_LL_HSIZE_MAX); diff --git a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c index 00e2dab0c8..3f2db636db 100644 --- a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c +++ b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c @@ -347,6 +347,7 @@ void app_main(void) ESP_ERROR_CHECK(esp_isp_color_configure(isp_proc, &color_config)); ESP_ERROR_CHECK(esp_isp_color_enable(isp_proc)); +#if CONFIG_ESP32P4_REV_MIN_FULL >= 100 esp_isp_lsc_gain_array_t gain_array = {}; esp_isp_lsc_config_t lsc_config = { .gain_array = &gain_array, @@ -366,6 +367,7 @@ void app_main(void) } ESP_ERROR_CHECK(esp_isp_lsc_configure(isp_proc, &lsc_config)); ESP_ERROR_CHECK(esp_isp_lsc_enable(isp_proc)); +#endif typedef struct af_task_param_t { isp_proc_handle_t isp_proc;