diff --git a/k230_sdk_overlay/src/big/mpp/include/comm/k_sensor_comm.h b/k230_sdk_overlay/src/big/mpp/include/comm/k_sensor_comm.h index 8c2eba6..d6cbd18 100755 --- a/k230_sdk_overlay/src/big/mpp/include/comm/k_sensor_comm.h +++ b/k230_sdk_overlay/src/big/mpp/include/comm/k_sensor_comm.h @@ -98,7 +98,7 @@ typedef enum { OV_OV5647_MIPI_CSI1_1920X1080_30FPS_10BIT_LINEAR = 27, OV_OV5647_MIPI_CSI2_1920X1080_30FPS_10BIT_LINEAR = 28, - XS9922B_MIPI_CSI0_1280X720_30FPS_YUV422_DOL3 = 29, + // XS9922B_MIPI_CSI0_1280X720_30FPS_YUV422_DOL3 = 29, XS9950_MIPI_CSI0_1280X720_30FPS_YUV422 = 30, XS9950_MIPI_CSI1_1280X720_30FPS_YUV422 = 31, @@ -115,6 +115,17 @@ typedef enum { GC2053_MIPI_CSI0_1920X1080_30FPS_10BIT_LINEAR = 40, + OV_OV5647_MIPI_CSI1_640x480_90FPS_10BIT_LINEAR = 41, + OV_OV5647_MIPI_CSI1_1280X720_60FPS_10BIT_LINEAR = 42, + OV_OV5647_MIPI_CSI1_1280X960_60FPS_10BIT_LINEAR = 43, + + OV_OV5647_MIPI_CSI0_1280X720_60FPS_10BIT_LINEAR = 44, + OV_OV5647_MIPI_CSI0_1280X960_60FPS_10BIT_LINEAR = 45, + + OV_OV5647_MIPI_CSI2_640x480_90FPS_10BIT_LINEAR = 46, + OV_OV5647_MIPI_CSI2_1280X720_60FPS_10BIT_LINEAR = 47, + OV_OV5647_MIPI_CSI2_1280X960_60FPS_10BIT_LINEAR = 48, + SENSOR_TYPE_MAX, } k_vicap_sensor_type; diff --git a/k230_sdk_overlay/src/big/mpp/include/comm/k_vicap_comm.h b/k230_sdk_overlay/src/big/mpp/include/comm/k_vicap_comm.h index 0bd13de..3ea84f4 100755 --- a/k230_sdk_overlay/src/big/mpp/include/comm/k_vicap_comm.h +++ b/k230_sdk_overlay/src/big/mpp/include/comm/k_vicap_comm.h @@ -379,6 +379,7 @@ typedef struct { k_vicap_vi_flash_mode flash_mode; k_vicap_vi_first_frame_sel first_frame; k_u16 glitch_filter; + k_u16 fps; k_vicap_sensor_type sensor_type; } k_vicap_sensor_info; @@ -618,6 +619,11 @@ typedef struct k_video_frame_info info; } k_vicap_mcm_chn_vf_info; +typedef struct { + k_u32 adapt_id[16]; + k_u32 adapt_len; +}k_vicap_adapt_id; + #define K_ERR_VICAP_INVALID_DEVID K_DEF_ERR(K_ID_VICAP, K_ERR_LEVEL_ERROR, K_ERR_INVALID_DEVID) #define K_ERR_VICAP_INVALID_CHNID K_DEF_ERR(K_ID_VICAP, K_ERR_LEVEL_ERROR, K_ERR_INVALID_CHNID) #define K_ERR_VICAP_ILLEGAL_PARAM K_DEF_ERR(K_ID_VICAP, K_ERR_LEVEL_ERROR, K_ERR_ILLEGAL_PARAM) diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/gc2053.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/gc2053.c new file mode 100755 index 0000000..6fce9b1 --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/gc2053.c @@ -0,0 +1,989 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" +#include "io.h" +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#define pr_info(...) //rt_kprintf(__VA_ARGS__) +#define pr_debug(...) //rt_kprintf(__VA_ARGS__) +#define pr_warn(...) //rt_kprintf(__VA_ARGS__) +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define GC2053_REG_CHIP_ID_H 0xf0 +#define GC2053_REG_CHIP_ID_L 0xf1 + +#define GC2053_REG_EXP_TIME_H 0x03 +#define GC2053_REG_EXP_TIME_L 0x04 + +#define GC2053_REG_AGAIN_H 0xb1 +#define GC2053_REG_AGAIN_L 0xb2 + +#define GC2053_MIN_GAIN_STEP (1.0f/64.0f) + + + +static const k_sensor_reg gc2053_mipi4lane_1080p_30fps_linear[] = { + +#if 0 + {0xfe,0x80}, + {0xfe,0x80}, + {0xfe,0x80}, //pllmp_div = 128 + {0xfe,0x00}, + {0xf2,0x00}, + {0xf3,0x00}, + {0xf4,0x36}, //PLL_ldo_set = 3, spi_clk_div = 6 + {0xf5,0xc0}, + {0xf6,0x44}, //cp_clk_del = 0, cp_clk_div = 4 + {0xf7,0x01}, + {0xf8,0x63}, //pllmp_div = 99 + {0xf9,0x40}, //rpllckl_div = div4 + {0xfc,0x8e}, +/****CISCTL & ANALOG****/ + {0xfe,0x00}, + {0x87,0x18}, + {0xee,0x30}, + {0xd0,0xb7}, + {0x03,0x04}, //ET = 1120 + {0x04,0x60}, + {0x05,0x04}, //Line length = 1100 + {0x06,0x4c}, + {0x07,0x00}, //Vblank = 17 + {0x08,0x11}, + {0x09,0x00}, //Row start = 2 + {0x0a,0x02}, + {0x0b,0x00}, //Col Start = 2 + {0x0c,0x02}, + {0x0d,0x04}, //win_height = 1088, default win_width = 1936 + {0x0e,0x40}, + {0x12,0xe2}, + {0x13,0x16}, + {0x19,0x0a}, + {0x21,0x1c}, + {0x28,0x0a}, + {0x29,0x24}, + {0x2b,0x04}, + {0x32,0xf8}, + {0x37,0x03}, + {0x39,0x15}, + {0x43,0x07}, + {0x44,0x40}, + {0x46,0x0b}, + {0x4b,0x20}, + {0x4e,0x08}, + {0x55,0x20}, + {0x66,0x05}, + {0x67,0x05}, + {0x77,0x01}, + {0x78,0x00}, + {0x7c,0x93}, + {0x8c,0x12}, + {0x8d,0x92}, + {0x90,0x01}, + {0x9d,0x10}, + {0xce,0x7c}, + {0xd2,0x41}, + {0xd3,0xdc}, + {0xe6,0x50}, +/*gain*/ + {0xb6,0xc0}, + {0xb0,0x70}, + {0xb1,0x01}, //gain = 1.0x + {0xb2,0x00}, + {0xb3,0x00}, // + {0xb4,0x00}, + {0xb8,0x01}, //col_gain = 1.0x + {0xb9,0x00}, +/*blk*/ + {0x26,0x30}, + {0xfe,0x01}, + {0x40,0x23}, //black level & offset enable + {0x55,0x07}, + {0x60,0x40}, + {0xfe,0x04}, + {0x14,0x78}, + {0x15,0x78}, + {0x16,0x78}, + {0x17,0x78}, +/*window*/ + {0xfe,0x01}, + {0x92,0x00}, + {0x94,0x03}, + {0x95,0x04}, //out_win_height = 1080 + {0x96,0x38}, + {0x97,0x07}, //out_win_width = 1920 + {0x98,0x80}, +/*ISP*/ + {0xfe,0x01}, + {0x01,0x05}, + {0x02,0x89}, + {0x04,0x01}, + {0x07,0xa6}, + {0x08,0xa9}, + {0x09,0xa8}, + {0x0a,0xa7}, + {0x0b,0xff}, + {0x0c,0xff}, + {0x0f,0x00}, + {0x50,0x1c}, + {0x89,0x03}, + {0xfe,0x04}, + {0x28,0x86}, + {0x29,0x86}, + {0x2a,0x86}, + {0x2b,0x68}, + {0x2c,0x68}, + {0x2d,0x68}, + {0x2e,0x68}, + {0x2f,0x68}, + {0x30,0x4f}, + {0x31,0x68}, + {0x32,0x67}, + {0x33,0x66}, + {0x34,0x66}, + {0x35,0x66}, + {0x36,0x66}, + {0x37,0x66}, + {0x38,0x62}, + {0x39,0x62}, + {0x3a,0x62}, + {0x3b,0x62}, + {0x3c,0x62}, + {0x3d,0x62}, + {0x3e,0x62}, + {0x3f,0x62}, +/****DVP & MIPI****/ + {0xfe,0x01}, + {0x9a,0x06}, + {0xfe,0x00}, + {0x7b,0x2a}, + {0x23,0x2d}, + {0xfe,0x03}, + {0x01,0x27}, + {0x02,0x56}, + {0x03,0xb6}, + {0x12,0x80}, + {0x13,0x07}, + {0x15,0x12}, + {0xfe,0x00}, + {0x3e,0x91}, + +#else +/****system****/ + {0xfe, 0x80}, + {0xfe, 0x80}, + {0xfe, 0x80}, + {0xfe, 0x00}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x36}, + {0xf5, 0xc0}, + {0xf6, 0x44}, + {0xf7, 0x01}, + {0xf8, 0x63}, + {0xf9, 0x40}, + {0xfc, 0x8e}, + /****CISCTL & ANALOG****/ + {0xfe, 0x00}, //Page 0 + {0x87, 0x18}, + {0xee, 0x30}, + {0xd0, 0xb7}, + {0x03, 0x01}, //ET = 0x160 = 352 + {0x04, 0x60}, + {0x05, 0x04}, //line length = 1100 * 2 = 2200 + {0x06, 0x4c}, + {0x07, 0x00}, //Vblank = 0x11 = 17 + {0x08, 0x11}, + {0x09, 0x00}, //raw start = 0x02 + {0x0a, 0x02}, + {0x0b, 0x00}, //col start = 0x02 + {0x0c, 0x02}, + {0x0d, 0x04}, //win_height = 1088 + {0x0e, 0x40}, + {0x12, 0xe2}, + {0x13, 0x16}, + {0x19, 0x0a}, + {0x21, 0x1c}, + {0x28, 0x0a}, + {0x29, 0x24}, + {0x2b, 0x04}, + {0x32, 0xf8}, + {0x37, 0x03}, + {0x39, 0x15}, + {0x43, 0x07}, + {0x44, 0x40}, + {0x46, 0x0b}, + {0x4b, 0x20}, + {0x4e, 0x08}, + {0x55, 0x20}, + {0x66, 0x05}, + {0x67, 0x05}, + {0x77, 0x01}, + {0x78, 0x00}, + {0x7c, 0x93}, + {0x8c, 0x12}, + {0x8d, 0x92}, + {0x90, 0x01}, + {0x9d, 0x10}, + {0xce, 0x7c}, + {0xd2, 0x41}, + {0xd3, 0xdc}, + {0xe6, 0x50}, + /*gain*/ + {0xb6, 0xc0}, + {0xb0, 0x60}, + {0xb1, 0x01}, //gain: 1x + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0x00}, + {0xb8, 0x01}, + {0xb9, 0x00}, + /*blk*/ + {0x26, 0x30}, + {0xfe, 0x01}, + {0x40, 0x23}, + {0x55, 0x07}, + {0x60, 0x40}, + {0xfe, 0x04}, + {0x14, 0x78}, + {0x15, 0x78}, + {0x16, 0x78}, + {0x17, 0x78}, + /*window*/ + {0xfe, 0x01}, + {0x92, 0x00}, + {0x94, 0x03}, + {0x95, 0x04},//[10:0]win_out_height-1080 + {0x96, 0x38}, + {0x97, 0x07},//[11:0]win_out_width-1920 + {0x98, 0x80}, + /*ISP*/ + {0xfe, 0x01}, + {0x01, 0x05}, + {0x02, 0x89}, + {0x04, 0x01}, + {0x07, 0xa6}, + {0x08, 0xa9}, + {0x09, 0xa8}, + {0x0a, 0xa7}, + {0x0b, 0xff}, + {0x0c, 0xff}, + {0x0f, 0x00}, + {0x50, 0x1c}, + {0x89, 0x03}, + {0xfe, 0x04}, + {0x28, 0x86}, + {0x29, 0x86}, + {0x2a, 0x86}, + {0x2b, 0x68}, + {0x2c, 0x68}, + {0x2d, 0x68}, + {0x2e, 0x68}, + {0x2f, 0x68}, + {0x30, 0x4f}, + {0x31, 0x68}, + {0x32, 0x67}, + {0x33, 0x66}, + {0x34, 0x66}, + {0x35, 0x66}, + {0x36, 0x66}, + {0x37, 0x66}, + {0x38, 0x62}, + {0x39, 0x62}, + {0x3a, 0x62}, + {0x3b, 0x62}, + {0x3c, 0x62}, + {0x3d, 0x62}, + {0x3e, 0x62}, + {0x3f, 0x62}, + /****DVP & MIPI****/ + {0xfe, 0x01}, + {0x9a, 0x06}, + {0x99, 0x00}, + {0xfe, 0x00}, + {0x7b, 0x2a}, + {0x23, 0x2d}, + {0xfe, 0x03}, + {0x01, 0x27}, + {0x02, 0x56}, + {0x03, 0x8e}, + {0x12, 0x80}, + {0x13, 0x07}, + {0xfe, 0x00}, + {0x3e, 0x81}, + {0x3e, 0x91}, + + {REG_NULL, 0x00}, +#endif +}; + + +static k_sensor_mode gc2053_mode_info[] = { + { + .index = 0, + .sensor_type = GC2053_MIPI_CSI0_1920X1080_30FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1920, + .bounds_height = 1080, + .top = 0, + .left = 0, + .width = 1920, + .height = 1080, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 2, + .data_type = 0x2B, + }, + .reg_list = gc2053_mipi4lane_1080p_30fps_linear, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL1_CLK_DIV4, + .setting.mclk_div = 25, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, +}; + +static k_bool gc2053_init_flag = K_FALSE; +static k_sensor_mode *current_mode = NULL; + +static int gc2053_power_rest(k_s32 on) +{ + #define VICAP_GC2053_RST_GPIO (0) //24// + + kd_pin_mode(VICAP_GC2053_RST_GPIO, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(VICAP_GC2053_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_GC2053_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_GC2053_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(VICAP_GC2053_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + +static int gc2053_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + +static k_s32 gc2053_sensor_get_chip_id(void *ctx, k_u32 *chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter\n", __func__); + + kd_pin_mode(VICAP_GC2053_RST_GPIO, GPIO_DM_OUTPUT); + kd_pin_write(VICAP_GC2053_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + + gc2053_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, GC2053_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, GC2053_REG_CHIP_ID_L, &id_low); + if (ret) { + // pr_err("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + rt_kprintf("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + + +static k_s32 gc2053_sensor_power_on(void *ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + // if (!gc2053_init_flag) { + gc2053_power_rest(on); + gc2053_i2c_init(&dev->i2c_info); + // } + ret = gc2053_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + gc2053_init_flag = K_FALSE; + gc2053_power_rest(on); + } + + return ret; +} + + + +static k_s32 gc2053_sensor_init(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(gc2053_mode_info) / sizeof(k_sensor_mode); i++) { + if (gc2053_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(gc2053_mode_info[i]); + dev->sensor_mode = &(gc2053_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + case 0: + case 1: + case 2: + case 3: + case 6: + + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + + current_mode->ae_info.frame_length = 2200; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000015152;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.984375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR ; + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = GC2053_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.cur_frame_length - 1; //2.5ms //197; // 3ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length -1; + current_mode->ae_info.min_vs_integraion_line = 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + current_mode->ae_info.cur_again = 1.0; + current_mode->ae_info.cur_dgain = 1.0; + + current_mode->ae_info.cur_vs_again = 1.0; + current_mode->ae_info.cur_vs_dgain = 1.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.984375; + current_mode->ae_info.a_gain.step = (1.0f/64.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.984375; + current_mode->ae_info.a_vs_gain.step = (1.0f/64.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + + default: + break; + } + + k_u16 again_h; + k_u16 again_l; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + float again = 0, dgain = 0; + + ret = sensor_reg_read(&dev->i2c_info, GC2053_REG_AGAIN_H, &again_h); + ret = sensor_reg_read(&dev->i2c_info, GC2053_REG_AGAIN_L, &again_l); + again = (float)(again_l>>2)/64.0f + again_h; + + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + ret = sensor_reg_read(&dev->i2c_info, GC2053_REG_EXP_TIME_H, &exp_time_h); + ret = sensor_reg_read(&dev->i2c_info, GC2053_REG_EXP_TIME_L, &exp_time_l); + exp_time = ((exp_time_h & 0x3f) << 8) + exp_time_l; + + current_mode->ae_info.cur_integration_time = current_mode->ae_info.one_line_exp_time * exp_time; + gc2053_init_flag = K_TRUE; + + return ret; +} + + +static k_s32 gc2053_sensor_get_mode(void *ctx, k_sensor_mode *mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(gc2053_mode_info) / sizeof(k_sensor_mode); i++) { + if (gc2053_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &gc2053_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(gc2053_mode_info[i]); + return 0; + } + } + pr_info("%s, the mode not exit.\n", __func__); + + return ret; +} + +static k_s32 gc2053_sensor_set_mode(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 gc2053_sensor_enum_mode(void *ctx, k_sensor_enum_mode *enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(enum_mode, 0, sizeof(k_sensor_enum_mode)); + + return ret; +} + +static k_s32 gc2053_sensor_get_caps(void *ctx, k_sensor_caps *caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +static k_s32 gc2053_sensor_conn_check(void *ctx, k_s32 *conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +static k_s32 gc2053_sensor_set_stream(void *ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +static k_s32 gc2053_sensor_get_again(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 gc2053_sensor_set_again(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 again; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 64 + 0.5)<<2; + if(current_mode->sensor_again !=again) + { + ret = sensor_reg_write(&dev->i2c_info, GC2053_REG_AGAIN_H,(again>>8) & 0x0f); + ret |= sensor_reg_write(&dev->i2c_info, GC2053_REG_AGAIN_L, again & 0xfc); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/256.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 64 + 0.5)<<2; + if(current_mode->sensor_again !=again) + { + ret = sensor_reg_write(&dev->i2c_info, GC2053_REG_AGAIN_H,(again>>8) & 0x0f); + ret |= sensor_reg_write(&dev->i2c_info, GC2053_REG_AGAIN_L, again & 0xfc); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/256.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again*1000) ); + + return ret; +} + +static k_s32 gc2053_sensor_get_dgain(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 gc2053_sensor_set_dgain(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, GC2053_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, GC2053_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, GC2053_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, GC2053_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + //TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = (float)dgain/1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain*10000)); + + return ret; +} + +static k_s32 gc2053_sensor_get_intg_time(void *ctx, k_sensor_intg_time *time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 gc2053_sensor_set_intg_time(void *ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + float integraion_time = 0; + struct sensor_driver_dev *dev = ctx; + + k_u16 exp_reg = 0; + k_u16 exp_reg_l = 0; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + if (current_mode->et_line != exp_line) + { + ret |= sensor_reg_write(&dev->i2c_info, GC2053_REG_EXP_TIME_H, (exp_line >> 8) & 0x3f); + ret |= sensor_reg_write(&dev->i2c_info, GC2053_REG_EXP_TIME_L, (exp_line ) & 0xff); + current_mode->et_line = exp_line; + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n",\ + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +k_s32 gc2053_sensor_get_exp_parm(void *ctx, k_sensor_exposure_param *exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +k_s32 gc2053_sensor_set_exp_parm(void *ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 gc2053_sensor_get_fps(void *ctx, k_u32 *fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = 30000; + + return ret; +} + +k_s32 gc2053_sensor_set_fps(void *ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 gc2053_sensor_get_isp_status(void *ctx, k_sensor_isp_status *staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +k_s32 gc2053_sensor_set_blc(void *ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 gc2053_sensor_set_wb(void *ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 gc2053_sensor_get_tpg(void *ctx, k_sensor_test_pattern *tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +k_s32 gc2053_sensor_set_tpg(void *ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 gc2053_sensor_get_expand_curve(void *ctx, k_sensor_compand_curve *curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +k_s32 gc2053_sensor_get_otp_data(void *ctx, void *data) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(data, 0, sizeof(void *)); + + return ret; +} + +static k_s32 gc2053_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + + +struct sensor_driver_dev gc2053_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c3", //"i2c0", //"i2c3", + .slave_addr = 0x37, + .reg_addr_size = SENSOR_REG_VALUE_8BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "gc2053", + .sensor_func = { + .sensor_power = gc2053_sensor_power_on, + .sensor_init = gc2053_sensor_init, + .sensor_get_chip_id = gc2053_sensor_get_chip_id, + .sensor_get_mode = gc2053_sensor_get_mode, + .sensor_set_mode = gc2053_sensor_set_mode, + .sensor_enum_mode = gc2053_sensor_enum_mode, + .sensor_get_caps = gc2053_sensor_get_caps, + .sensor_conn_check = gc2053_sensor_conn_check, + .sensor_set_stream = gc2053_sensor_set_stream, + .sensor_get_again = gc2053_sensor_get_again, + .sensor_set_again = gc2053_sensor_set_again, + .sensor_get_dgain = gc2053_sensor_get_dgain, + .sensor_set_dgain = gc2053_sensor_set_dgain, + .sensor_get_intg_time = gc2053_sensor_get_intg_time, + .sensor_set_intg_time = gc2053_sensor_set_intg_time, + .sensor_get_exp_parm = gc2053_sensor_get_exp_parm, + .sensor_set_exp_parm = gc2053_sensor_set_exp_parm, + .sensor_get_fps = gc2053_sensor_get_fps, + .sensor_set_fps = gc2053_sensor_set_fps, + .sensor_get_isp_status = gc2053_sensor_get_isp_status, + .sensor_set_blc = gc2053_sensor_set_blc, + .sensor_set_wb = gc2053_sensor_set_wb, + .sensor_get_tpg = gc2053_sensor_get_tpg, + .sensor_set_tpg = gc2053_sensor_set_tpg, + .sensor_get_expand_curve = gc2053_sensor_get_expand_curve, + .sensor_get_otp_data = gc2053_sensor_get_otp_data, + .sensor_mirror_set = gc2053_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/imx335_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/imx335_drv.c index 8d4613e..60996e5 100755 --- a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/imx335_drv.c +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/imx335_drv.c @@ -891,6 +891,16 @@ static k_sensor_mode imx335_mode_info[] = { .data_type = 0x2C, }, .reg_list = imx335_mipi_2lane_raw12_1920x1080_30fps_mclk_74_25_regs, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL1_CLK_DIV4, + .setting.mclk_div = 8, + }, + {K_FALSE}, + {K_FALSE}, + }, }, { .index = 4, @@ -913,6 +923,16 @@ static k_sensor_mode imx335_mode_info[] = { .data_type = 0x2C, }, .reg_list = imx335_mipi_2lane_raw12_2592x1944_30fps_mclk_74_25_regs, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL1_CLK_DIV4, + .setting.mclk_div = 8, + }, + {K_FALSE}, + {K_FALSE}, + }, }, { .index = 5, @@ -935,6 +955,16 @@ static k_sensor_mode imx335_mode_info[] = { .data_type = 0x2C, }, .reg_list = imx335_mipi_4lane_raw12_2592x1944_30fps_mclk_74_25_regs, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL1_CLK_DIV4, + .setting.mclk_div = 8, + }, + {K_FALSE}, + {K_FALSE}, + }, }, { .index = 6, @@ -1034,10 +1064,15 @@ static k_s32 imx335_sensor_get_chip_id(void* ctx, k_u32* chip_id) struct sensor_driver_dev* dev = ctx; pr_info("%s enter\n", __func__); + kd_pin_mode(VICAP_IMX335_RST_GPIO, GPIO_DM_OUTPUT); + kd_pin_write(VICAP_IMX335_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_HIGH + + imx335_i2c_init(&dev->i2c_info); + ret = sensor_reg_read(&dev->i2c_info, IMX335_REG_ID, &id_high); ret |= sensor_reg_read(&dev->i2c_info, IMX335_REG_ID + 1, &id_low); if (ret) { - rt_kprintf("%s error\n", __func__); + // rt_kprintf("%s error\n", __func__); return -1; } @@ -1056,7 +1091,11 @@ static k_s32 imx335_sensor_power_on(void* ctx, k_s32 on) imx335_power_reset(0); imx335_i2c_init(&dev->i2c_info); imx335_power_reset(1); - imx335_sensor_get_chip_id(ctx, &chip_id); + ret = imx335_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } } else { imx335_power_reset(on); } @@ -1800,7 +1839,7 @@ static k_s32 imx335_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) struct sensor_driver_dev imx335_sensor_drv = { .i2c_info = { .i2c_bus = NULL, - .i2c_name = "i2c3", + .i2c_name = "i2c0", .slave_addr = 0x1a, .reg_addr_size = SENSOR_REG_VALUE_16BIT, .reg_val_size = SENSOR_REG_VALUE_8BIT, diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi1_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi1_drv.c index 0145bba..8afccb8 100755 --- a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi1_drv.c +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi1_drv.c @@ -277,57 +277,66 @@ static const k_sensor_reg ov5647_2592x1944_10bpp[] = { {REG_NULL, 0x00}, }; +//90 fps ok static const k_sensor_reg ov5647_640x480_10bpp[] = { - //pixel_rate = 55000000 - {0x0100, 0x00}, + //pixel_rate = 95833333 Hz, 1852 x 575 x 90fps {0x0103, 0x01}, - {0x3035, 0x11}, - {0x3036, 0x46}, + {0x0100, 0x00}, + {0x3034, 0x1a}, + {0x3035, 0x21}, + {0x3036, 0x73}, {0x303c, 0x11}, - {0x3821, 0x01}, - {0x3820, 0x41}, + {0x3106, 0xf5}, + {0x3820, 0x01}, //horizontal, bit1: mirror, bit0: bining + {0x3821, 0x03}, //verticall, bit1: flip, bit0: bining + {0x3827, 0xec}, {0x370c, 0x03}, {0x3612, 0x59}, {0x3618, 0x00}, {0x5000, 0x06}, - {0x5001, 0x00}, // set awb disble - {0x5002, 0x00}, + {0x5001, 0x00}, // set awb disble + {0x5002, 0x00}, //disable win, otp and awb gain {0x5003, 0x08}, {0x5a00, 0x08}, - {0x3000, 0xff}, - {0x3001, 0xff}, - {0x3002, 0xff}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, //2 lane, MIPI + {0x301c, 0xf8}, {0x301d, 0xf0}, - {0x3a18, 0x03}, - {0x3a19, 0xff}, + {0x3a18, 0x03}, //gain_celling, max gain value + {0x3a19, 0xff}, //gain_celling {0x3c01, 0x80}, {0x3b07, 0x0c}, - {0x380c, 0x07}, // 73c = 1852 + {0x380c, 0x07}, // HTS = 1852 {0x380d, 0x3c}, - - {0x380e, 0x01}, // v totle high - {0x380f, 0xf8}, // v totle lo 504 - - {0x3814, 0x35}, - {0x3815, 0x35}, + {0x380e, 0x02}, //VTS = 575 + {0x380f, 0x3f}, + {0x3814, 0x35}, //horizontal subsampling, 8/2 + {0x3815, 0x35}, //vertical subsampling, 8/2 {0x3708, 0x64}, {0x3709, 0x52}, - {0x3808, 0x02}, + {0x3808, 0x02}, // x output size: 640 {0x3809, 0x80}, - {0x380a, 0x01}, + {0x380a, 0x01}, // y output size: 480 {0x380b, 0xe0}, - {0x3800, 0x00}, + {0x3800, 0x00}, //x start = 0x10 = 16 {0x3801, 0x10}, - {0x3802, 0x00}, + {0x3802, 0x00}, //y start = 0 {0x3803, 0x00}, - {0x3804, 0x0a}, + {0x3804, 0x0a}, //x end = 0xa2f = 2607, x size = 2607 - 16 + 1 = 2592 (648 x 4) {0x3805, 0x2f}, - {0x3806, 0x07}, + {0x3806, 0x07}, //y end = 0x79f = 1951, y size = 1951 - 0 + 1 = 1952 (488 x 4) {0x3807, 0x9f}, + //{0x3811, 0x04}, //x offset: 4 + //{0x3813, 0x02}, //y offset: 2 {0x3630, 0x2e}, {0x3632, 0xe2}, {0x3633, 0x23}, {0x3634, 0x44}, + {0x3636, 0x06}, {0x3620, 0x64}, {0x3621, 0xe0}, {0x3600, 0x37}, @@ -341,10 +350,10 @@ static const k_sensor_reg ov5647_640x480_10bpp[] = { {0x3f05, 0x02}, {0x3f06, 0x10}, {0x3f01, 0x0a}, - {0x3a00, 0x00}, - {0x3a08, 0x01}, + {0x3a00, 0x00}, //AEC control, all disable + {0x3a08, 0x01}, //50Hz step {0x3a09, 0x2e}, - {0x3a0a, 0x00}, + {0x3a0a, 0x00}, //60Hz step {0x3a0b, 0xfb}, {0x3a0d, 0x02}, {0x3a0e, 0x01}, @@ -355,29 +364,18 @@ static const k_sensor_reg ov5647_640x480_10bpp[] = { {0x3a11, 0x60}, {0x3a1f, 0x28}, {0x4001, 0x02}, - {0x4004, 0x02}, + {0x4004, 0x02}, //blc line number {0x4000, 0x09}, - {0x3000, 0x00}, - {0x3001, 0x00}, - {0x3002, 0x00}, - {0x3017, 0xe0}, - {0x301c, 0xfc}, - {0x3636, 0x06}, - {0x3016, 0x08}, - {0x3827, 0xec}, - {0x3018, 0x44}, - {0x3035, 0x21}, - {0x3106, 0xf5}, - {0x3034, 0x1a}, - {0x301c, 0xf8}, + //{0x4837, 0x15}, {0x4800, 0x34}, + {0x3501, 0x02}, //ET = 42 lines + {0x3502, 0xa0}, {0x3503, 0x07}, //0x0f {0x350b, 0x10}, // gain - {0x0100, 0x01}, + //{0x0100, 0x01}, {REG_NULL, 0x00}, }; - static const k_sensor_reg ov5647_mipi2lane_1080p_30fps_flip_linear[] = { //pixel_rate = 81666700 {0x0103, 0x01}, @@ -476,6 +474,232 @@ static const k_sensor_reg ov5647_mipi2lane_1080p_30fps_flip_linear[] = { {REG_NULL, 0x00}, }; +// 60 fps binning ok +static const k_sensor_reg mode_1280x720_60fps[] = { + //PCLK = 95833333 Hz, 1796 x 886 x 60 + {0x0100, 0x00}, + {0x0103, 0x01}, + {0x3034, 0x1a}, + {0x3035, 0x21}, + {0x3036, 0x73}, //PLL multiplier + {0x303c, 0x11}, + {0x3106, 0xf5}, + {0x3820, 0x01}, //horizontal, bit1: mirror, bit0: bining + {0x3821, 0x03}, //verticall, bit1: flip, bit0: bining + {0x3827, 0xec}, + {0x370c, 0x03}, + {0x3612, 0x59}, + {0x3618, 0x00}, + {0x5000, 0x06}, //blc enable + {0x5001, 0x00}, // set awb disble + {0x5002, 0x00}, //disable win, otp and awb gain + {0x5003, 0x08}, + {0x5a00, 0x08}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, //2 lane, MIPI + {0x301c, 0xf8}, + {0x301d, 0xf0}, + {0x3a18, 0x03}, //gain_celling, max gain value + {0x3a19, 0xff}, //gain_celling + {0x3c01, 0x80}, + {0x3b07, 0x0c}, + + {0x380c, 0x07}, // HTS= 0x768 = 1896 - 100 --> 1796 = 0x704 + {0x380d, 0x04}, + {0x380e, 0x03}, // VTS= 0x7b0 = 1968 - 300 = 1,668 = 0x684 - 688 = 1000 = 0x3e8 - 150 = 850 = 0x352 + 36 = 886 = 0x376 + {0x380f, 0x76}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3808, 0x05}, // x output size: 1280, 1280 * 2 = 2,560 + {0x3809, 0x00}, + {0x380a, 0x02}, // y output size: 720, 720 * 2 = 1,440 + {0x380b, 0xd0}, + {0x3800, 0x00}, // x start = 32 + {0x3801, 0x20}, + {0x3802, 0x01}, // y start = 258 + {0x3803, 0x02}, + {0x3804, 0x0a}, // x end = 2623 + {0x3805, 0x3f}, + {0x3806, 0x07}, // y end = 0x73f + 52 = 1907 = 0x779 + {0x3807, 0x79}, + {0x3811, 0x0c}, //x offset: 4 + {0x3813, 0x06}, //y offset: 2 + + {0x3630, 0x2e}, + {0x3632, 0xe2}, + {0x3633, 0x23}, + {0x3634, 0x44}, + {0x3636, 0x06}, + {0x3620, 0x64}, + {0x3621, 0xe0}, + {0x3600, 0x37}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x3731, 0x02}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3f05, 0x02}, + {0x3f06, 0x10}, + {0x3f01, 0x0a}, + {0x3a00, 0x00}, //AEC control, all disable + {0x3a08, 0x01}, + {0x3a09, 0x28}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x08}, + {0x3a0e, 0x06}, + {0x3a0f, 0x58}, + {0x3a10, 0x50}, + {0x3a1b, 0x58}, + {0x3a1e, 0x50}, + {0x3a11, 0x60}, + {0x3a1f, 0x28}, + {0x4001, 0x02}, + {0x4004, 0x04}, //blc line number + {0x4000, 0x09}, + {0x4837, 0x16}, + {0x4800, 0x24}, + + {0x3501, 0x02}, //ET = 42 lines + {0x3502, 0xa0}, + {0x3503, 0x07}, //0x03 + {0x350b, 0x10}, + {0x3212, 0xa0}, + //{0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + +static const k_sensor_reg ov5647_1280x960p30_10bpp[] = { + {0x0100, 0x00}, + {0x0103, 0x01}, + {0x3034, 0x1a}, + + // {0x3035, 0x21}, + // {0x3036, 0x62}, + + {0x3035, 0x21}, + {0x3036, 0x73}, + + {0x303c, 0x11}, + {0x3106, 0xf5}, + {0x3827, 0xec}, + {0x370c, 0x03}, + {0x3612, 0x59}, + {0x3618, 0x00}, + {0x5000, 0x06}, + {0x5002, 0x41}, + {0x5003, 0x08}, + {0x5a00, 0x08}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, + {0x301c, 0xf8}, + {0x301d, 0xf0}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3c01, 0x80}, + {0x3b07, 0x0c}, + +#if 0 + {0x3800, 0x00}, // x start 0 + {0x3801, 0x00}, + + {0x3802, 0x00}, // y star 0 + {0x3803, 0x00}, + + {0x3804, 0x0a}, // x end 0xa3f + {0x3805, 0x3f}, + + {0x3806, 0x07}, // y end 0x7a3 + {0x3807, 0xa3}, +#else + + {0x3800, 0x00}, // x start 0 + {0x3801, 0x00}, + + {0x3802, 0x00}, // y star 0 + {0x3803, 0x00}, + + {0x3804, 0x0a}, // x end 0xa3f + {0x3805, 0x3f}, + + {0x3806, 0x07}, // y end 0x7a3 + {0x3807, 0xa3}, + +#endif + {0x3808, 0x05}, // x size 0x510 + {0x3809, 0x10}, + + {0x380a, 0x03}, // y size 0x3cc + {0x380b, 0xcc}, + + {0x380c, 0x07}, // x total 0x768 = 1896 + {0x380d, 0x68}, + + {0x380e, 0x05}, // v total 0x7b0 = 1968 -500 = 1468 = 0x5bc + {0x380f, 0xbc}, + + {0x3811, 0x0c}, + {0x3813, 0x06}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3630, 0x2e}, + {0x3632, 0xe2}, + {0x3633, 0x23}, + {0x3634, 0x44}, + {0x3636, 0x06}, + {0x3620, 0x64}, + {0x3621, 0xe0}, + {0x3600, 0x37}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x3731, 0x02}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3f05, 0x02}, + {0x3f06, 0x10}, + {0x3f01, 0x0a}, + {0x3a08, 0x01}, + {0x3a09, 0x28}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x08}, + {0x3a0e, 0x06}, + {0x3a0f, 0x58}, + {0x3a10, 0x50}, + {0x3a1b, 0x58}, + {0x3a1e, 0x50}, + {0x3a11, 0x60}, + {0x3a1f, 0x28}, + {0x4001, 0x02}, + {0x4004, 0x04}, + {0x4000, 0x09}, + {0x4837, 0x16}, + {0x4800, 0x24}, + {0x3503, 0x03}, + {0x3820, 0x41}, + {0x3821, 0x07}, + {0x350a, 0x00}, + {0x350b, 0x10}, + {0x3500, 0x00}, + {0x3501, 0x1a}, + {0x3502, 0xf0}, + {0x3212, 0xa0}, + {0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + static k_sensor_mode ov5647_mode_info[] = { { @@ -526,7 +750,7 @@ static k_sensor_mode ov5647_mode_info[] = { }, { .index = 2, - .sensor_type = OV_OV5647_MIPI_640x480_60FPS_10BIT_LINEAR, + .sensor_type = OV_OV5647_MIPI_CSI1_640x480_90FPS_10BIT_LINEAR, .size = { .bounds_width = 640, .bounds_height = 480, @@ -602,7 +826,52 @@ static k_sensor_mode ov5647_mode_info[] = { .reg_list = ov5647_mipi2lane_1080p_30fps_flip_linear, .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, }, - + { + .index = 5, + .sensor_type = OV_OV5647_MIPI_CSI1_1280X720_60FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 60000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_GBRG, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 2, + .data_type = 0x2B, //RAW10 + }, + .reg_list = mode_1280x720_60fps, //mode_1280x720_60fps, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 6, + .sensor_type = OV_OV5647_MIPI_CSI1_1280X960_60FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 960, + .top = 0, + .left = 0, + .width = 1280, + .height = 960, + }, + .fps = 60000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, //BAYER_PAT_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 2, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov5647_1280x960p30_10bpp, //mode_1280x720_60fps, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, }; static k_sensor_mode *current_mode = NULL; @@ -634,6 +903,19 @@ static int ov5647_power_rest(k_s32 on) return 0; } + +static int ov5647_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) { k_s32 ret = 0; @@ -642,10 +924,12 @@ static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) struct sensor_driver_dev *dev = ctx; pr_info("%s enter\n", __func__); + ov5647_i2c_init(&dev->i2c_info); + ret = sensor_reg_read(&dev->i2c_info, OV5647_REG_CHIP_ID_H, &id_high); ret |= sensor_reg_read(&dev->i2c_info, OV5647_REG_CHIP_ID_L, &id_low); if (ret) { - rt_kprintf("%s error\n", __func__);; + // rt_kprintf("%s error\n", __func__);; return -1; } @@ -656,17 +940,7 @@ static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) } -static int ov5647_i2c_init(k_sensor_i2c_info *i2c_info) -{ - i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); - if (i2c_info->i2c_bus == RT_NULL) - { - pr_err("can't find %s deivce", i2c_info->i2c_name); - return RT_ERROR; - } - return 0; -} static k_s32 ov5647_sensor_power_on(void *ctx, k_s32 on) { @@ -677,7 +951,11 @@ static k_s32 ov5647_sensor_power_on(void *ctx, k_s32 on) if (on) { ov5647_power_rest(on); ov5647_i2c_init(&dev->i2c_info); - ov5647_sensor_get_chip_id(ctx, &chip_id); + ret = ov5647_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } // write power on // ret = sensor_reg_list_write(&dev->i2c_info, sensor_oe_enable_regs); } else { @@ -939,6 +1217,219 @@ static k_s32 ov5647_sensor_init(void *ctx, k_sensor_mode mode) current_mode->ae_info.d_vs_gain.min = 1.0; current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f); + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + + case 5: //720P + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 886; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000027808;//0.00003025 + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + case 2: + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 575; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000027808;//0.00003025 + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + case 6: + // 960p + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 630; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000017636; + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + current_mode->ae_info.cur_fps = current_mode->fps; current_mode->sensor_again = 0; current_mode->et_line = 0; @@ -973,6 +1464,7 @@ static k_s32 ov5647_sensor_get_mode(void *ctx, k_sensor_mode *mode) k_s32 ret = -1; pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + // rt_kprintf("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); for (k_s32 i = 0; i < sizeof(ov5647_mode_info) / sizeof(k_sensor_mode); i++) { if (ov5647_mode_info[i].sensor_type == mode->sensor_type) { diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi2_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi2_drv.c index 0efdc35..bd96216 100755 --- a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi2_drv.c +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_csi2_drv.c @@ -277,57 +277,66 @@ static const k_sensor_reg ov5647_2592x1944_10bpp[] = { {REG_NULL, 0x00}, }; +//90 fps ok static const k_sensor_reg ov5647_640x480_10bpp[] = { - //pixel_rate = 55000000 - {0x0100, 0x00}, + //pixel_rate = 95833333 Hz, 1852 x 575 x 90fps {0x0103, 0x01}, - {0x3035, 0x11}, - {0x3036, 0x46}, + {0x0100, 0x00}, + {0x3034, 0x1a}, + {0x3035, 0x21}, + {0x3036, 0x73}, {0x303c, 0x11}, - {0x3821, 0x01}, - {0x3820, 0x41}, + {0x3106, 0xf5}, + {0x3820, 0x01}, //horizontal, bit1: mirror, bit0: bining + {0x3821, 0x03}, //verticall, bit1: flip, bit0: bining + {0x3827, 0xec}, {0x370c, 0x03}, {0x3612, 0x59}, {0x3618, 0x00}, {0x5000, 0x06}, - {0x5001, 0x00}, // set awb disble - {0x5002, 0x00}, + {0x5001, 0x00}, // set awb disble + {0x5002, 0x00}, //disable win, otp and awb gain {0x5003, 0x08}, {0x5a00, 0x08}, - {0x3000, 0xff}, - {0x3001, 0xff}, - {0x3002, 0xff}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, //2 lane, MIPI + {0x301c, 0xf8}, {0x301d, 0xf0}, - {0x3a18, 0x03}, - {0x3a19, 0xff}, + {0x3a18, 0x03}, //gain_celling, max gain value + {0x3a19, 0xff}, //gain_celling {0x3c01, 0x80}, {0x3b07, 0x0c}, - {0x380c, 0x07}, // 73c = 1852 + {0x380c, 0x07}, // HTS = 1852 {0x380d, 0x3c}, - - {0x380e, 0x01}, // v totle high - {0x380f, 0xf8}, // v totle lo 504 - - {0x3814, 0x35}, - {0x3815, 0x35}, + {0x380e, 0x02}, //VTS = 575 + {0x380f, 0x3f}, + {0x3814, 0x35}, //horizontal subsampling, 8/2 + {0x3815, 0x35}, //vertical subsampling, 8/2 {0x3708, 0x64}, {0x3709, 0x52}, - {0x3808, 0x02}, + {0x3808, 0x02}, // x output size: 640 {0x3809, 0x80}, - {0x380a, 0x01}, + {0x380a, 0x01}, // y output size: 480 {0x380b, 0xe0}, - {0x3800, 0x00}, + {0x3800, 0x00}, //x start = 0x10 = 16 {0x3801, 0x10}, - {0x3802, 0x00}, + {0x3802, 0x00}, //y start = 0 {0x3803, 0x00}, - {0x3804, 0x0a}, + {0x3804, 0x0a}, //x end = 0xa2f = 2607, x size = 2607 - 16 + 1 = 2592 (648 x 4) {0x3805, 0x2f}, - {0x3806, 0x07}, + {0x3806, 0x07}, //y end = 0x79f = 1951, y size = 1951 - 0 + 1 = 1952 (488 x 4) {0x3807, 0x9f}, + //{0x3811, 0x04}, //x offset: 4 + //{0x3813, 0x02}, //y offset: 2 {0x3630, 0x2e}, {0x3632, 0xe2}, {0x3633, 0x23}, {0x3634, 0x44}, + {0x3636, 0x06}, {0x3620, 0x64}, {0x3621, 0xe0}, {0x3600, 0x37}, @@ -341,10 +350,10 @@ static const k_sensor_reg ov5647_640x480_10bpp[] = { {0x3f05, 0x02}, {0x3f06, 0x10}, {0x3f01, 0x0a}, - {0x3a00, 0x00}, - {0x3a08, 0x01}, + {0x3a00, 0x00}, //AEC control, all disable + {0x3a08, 0x01}, //50Hz step {0x3a09, 0x2e}, - {0x3a0a, 0x00}, + {0x3a0a, 0x00}, //60Hz step {0x3a0b, 0xfb}, {0x3a0d, 0x02}, {0x3a0e, 0x01}, @@ -355,25 +364,15 @@ static const k_sensor_reg ov5647_640x480_10bpp[] = { {0x3a11, 0x60}, {0x3a1f, 0x28}, {0x4001, 0x02}, - {0x4004, 0x02}, + {0x4004, 0x02}, //blc line number {0x4000, 0x09}, - {0x3000, 0x00}, - {0x3001, 0x00}, - {0x3002, 0x00}, - {0x3017, 0xe0}, - {0x301c, 0xfc}, - {0x3636, 0x06}, - {0x3016, 0x08}, - {0x3827, 0xec}, - {0x3018, 0x44}, - {0x3035, 0x21}, - {0x3106, 0xf5}, - {0x3034, 0x1a}, - {0x301c, 0xf8}, + //{0x4837, 0x15}, {0x4800, 0x34}, + {0x3501, 0x02}, //ET = 42 lines + {0x3502, 0xa0}, {0x3503, 0x07}, //0x0f {0x350b, 0x10}, // gain - {0x0100, 0x01}, + //{0x0100, 0x01}, {REG_NULL, 0x00}, }; @@ -477,6 +476,216 @@ static const k_sensor_reg ov5647_mipi2lane_1080p_30fps_flip_linear[] = { }; +// 60 fps binning ok +static const k_sensor_reg mode_1280x720_60fps[] = { + //PCLK = 95833333 Hz, 1796 x 886 x 60 + {0x0100, 0x00}, + {0x0103, 0x01}, + {0x3034, 0x1a}, + {0x3035, 0x21}, + {0x3036, 0x73}, //PLL multiplier + {0x303c, 0x11}, + {0x3106, 0xf5}, + {0x3820, 0x01}, //horizontal, bit1: mirror, bit0: bining + {0x3821, 0x03}, //verticall, bit1: flip, bit0: bining + {0x3827, 0xec}, + {0x370c, 0x03}, + {0x3612, 0x59}, + {0x3618, 0x00}, + {0x5000, 0x06}, //blc enable + {0x5001, 0x00}, // set awb disble + {0x5002, 0x00}, //disable win, otp and awb gain + {0x5003, 0x08}, + {0x5a00, 0x08}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, //2 lane, MIPI + {0x301c, 0xf8}, + {0x301d, 0xf0}, + {0x3a18, 0x03}, //gain_celling, max gain value + {0x3a19, 0xff}, //gain_celling + {0x3c01, 0x80}, + {0x3b07, 0x0c}, + + {0x380c, 0x07}, // HTS= 0x768 = 1896 - 100 --> 1796 = 0x704 + {0x380d, 0x04}, + {0x380e, 0x03}, // VTS= 0x7b0 = 1968 - 300 = 1,668 = 0x684 - 688 = 1000 = 0x3e8 - 150 = 850 = 0x352 + 36 = 886 = 0x376 + {0x380f, 0x76}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3808, 0x05}, // x output size: 1280, 1280 * 2 = 2,560 + {0x3809, 0x00}, + {0x380a, 0x02}, // y output size: 720, 720 * 2 = 1,440 + {0x380b, 0xd0}, + {0x3800, 0x00}, // x start = 32 + {0x3801, 0x20}, + {0x3802, 0x01}, // y start = 258 + {0x3803, 0x02}, + {0x3804, 0x0a}, // x end = 2623 + {0x3805, 0x3f}, + {0x3806, 0x07}, // y end = 0x73f + 52 = 1907 = 0x779 + {0x3807, 0x79}, + {0x3811, 0x0c}, //x offset: 4 + {0x3813, 0x06}, //y offset: 2 + + {0x3630, 0x2e}, + {0x3632, 0xe2}, + {0x3633, 0x23}, + {0x3634, 0x44}, + {0x3636, 0x06}, + {0x3620, 0x64}, + {0x3621, 0xe0}, + {0x3600, 0x37}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x3731, 0x02}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3f05, 0x02}, + {0x3f06, 0x10}, + {0x3f01, 0x0a}, + {0x3a00, 0x00}, //AEC control, all disable + {0x3a08, 0x01}, + {0x3a09, 0x28}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x08}, + {0x3a0e, 0x06}, + {0x3a0f, 0x58}, + {0x3a10, 0x50}, + {0x3a1b, 0x58}, + {0x3a1e, 0x50}, + {0x3a11, 0x60}, + {0x3a1f, 0x28}, + {0x4001, 0x02}, + {0x4004, 0x04}, //blc line number + {0x4000, 0x09}, + {0x4837, 0x16}, + {0x4800, 0x24}, + + {0x3501, 0x02}, //ET = 42 lines + {0x3502, 0xa0}, + {0x3503, 0x07}, //0x03 + {0x350b, 0x10}, + {0x3212, 0xa0}, + //{0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + +// 960p60 10bpp +static const k_sensor_reg ov5647_1280x960p30_10bpp[] = { + {0x0100, 0x00}, + {0x0103, 0x01}, + {0x3034, 0x1a}, + + {0x3035, 0x21}, + {0x3036, 0x73}, + + {0x303c, 0x11}, + {0x3106, 0xf5}, + {0x3827, 0xec}, + {0x370c, 0x03}, + {0x3612, 0x59}, + {0x3618, 0x00}, + {0x5000, 0x06}, + {0x5002, 0x41}, + {0x5003, 0x08}, + {0x5a00, 0x08}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, + {0x301c, 0xf8}, + {0x301d, 0xf0}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3c01, 0x80}, + {0x3b07, 0x0c}, + + {0x3800, 0x00}, // x start 0 + {0x3801, 0x00}, + + {0x3802, 0x00}, // y star 0 + {0x3803, 0x00}, + + {0x3804, 0x0a}, // x end 0xa3f + {0x3805, 0x3f}, + + {0x3806, 0x07}, // y end 0x7a3 + {0x3807, 0xa3}, + + {0x3808, 0x05}, // x size 0x510 + {0x3809, 0x10}, + + {0x380a, 0x03}, // y size 0x3cc + {0x380b, 0xcc}, + + {0x380c, 0x07}, // x total 0x768 = 1896 + {0x380d, 0x68}, + + {0x380e, 0x05}, // v total 0x7b0 = 1968 -500 = 1468 = 0x5bc + {0x380f, 0xbc}, + + {0x3811, 0x0c}, + {0x3813, 0x06}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3630, 0x2e}, + {0x3632, 0xe2}, + {0x3633, 0x23}, + {0x3634, 0x44}, + {0x3636, 0x06}, + {0x3620, 0x64}, + {0x3621, 0xe0}, + {0x3600, 0x37}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x3731, 0x02}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3f05, 0x02}, + {0x3f06, 0x10}, + {0x3f01, 0x0a}, + {0x3a08, 0x01}, + {0x3a09, 0x28}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x08}, + {0x3a0e, 0x06}, + {0x3a0f, 0x58}, + {0x3a10, 0x50}, + {0x3a1b, 0x58}, + {0x3a1e, 0x50}, + {0x3a11, 0x60}, + {0x3a1f, 0x28}, + {0x4001, 0x02}, + {0x4004, 0x04}, + {0x4000, 0x09}, + {0x4837, 0x16}, + {0x4800, 0x24}, + {0x3503, 0x03}, + {0x3821, 0x01}, + {0x3820, 0x41}, + {0x350a, 0x00}, + {0x350b, 0x10}, + {0x3500, 0x00}, + {0x3501, 0x1a}, + {0x3502, 0xf0}, + {0x3212, 0xa0}, + {0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + + static k_sensor_mode ov5647_mode_info[] = { { .index = 0, @@ -526,7 +735,7 @@ static k_sensor_mode ov5647_mode_info[] = { }, { .index = 2, - .sensor_type = OV_OV5647_MIPI_640x480_60FPS_10BIT_LINEAR, + .sensor_type = OV_OV5647_MIPI_CSI2_640x480_90FPS_10BIT_LINEAR, .size = { .bounds_width = 640, .bounds_height = 480, @@ -535,7 +744,7 @@ static k_sensor_mode ov5647_mode_info[] = { .width = 640, .height = 480, }, - .fps = 60000, + .fps = 90000, .hdr_mode = SENSOR_MODE_LINEAR, .bit_width = 10, .bayer_pattern = BAYER_PAT_BGGR, @@ -622,6 +831,79 @@ static k_sensor_mode ov5647_mode_info[] = { {K_FALSE}, }, }, + { + .index = 5, + .sensor_type = OV_OV5647_MIPI_CSI2_1280X720_60FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 60000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_GBRG, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 2, + .data_type = 0x2B, //RAW10 + }, + .reg_list = mode_1280x720_60fps, //mode_1280x720_60fps, +#if defined(CONFIG_BOARD_K230_CANMV) + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, +#else + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, +#endif + }, + { + .index = 6, + .sensor_type = OV_OV5647_MIPI_CSI2_1280X960_60FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 960, + .top = 0, + .left = 0, + .width = 1280, + .height = 960, + }, + .fps = 60000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 2, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov5647_1280x960p30_10bpp, //mode_1280x720_60fps, +#if defined(CONFIG_BOARD_K230_CANMV) + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + +#else + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, +#endif + }, }; @@ -654,6 +936,18 @@ static int ov5647_power_rest(k_s32 on) return 0; } +static int ov5647_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) { k_s32 ret = 0; @@ -662,10 +956,15 @@ static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) struct sensor_driver_dev *dev = ctx; pr_info("%s enter\n", __func__); + ov5647_i2c_init(&dev->i2c_info); + + kd_pin_mode(OV5647_CAM_PIN_CSI2, GPIO_DM_OUTPUT); + kd_pin_write(OV5647_CAM_PIN_CSI2, GPIO_PV_HIGH); + ret = sensor_reg_read(&dev->i2c_info, OV5647_REG_CHIP_ID_H, &id_high); ret |= sensor_reg_read(&dev->i2c_info, OV5647_REG_CHIP_ID_L, &id_low); if (ret) { - rt_kprintf("%s error\n", __func__);; + // rt_kprintf("%s error\n", __func__);; return -1; } @@ -676,17 +975,7 @@ static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) } -static int ov5647_i2c_init(k_sensor_i2c_info *i2c_info) -{ - i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); - if (i2c_info->i2c_bus == RT_NULL) - { - pr_err("can't find %s deivce", i2c_info->i2c_name); - return RT_ERROR; - } - return 0; -} static k_s32 ov5647_sensor_power_on(void *ctx, k_s32 on) { @@ -699,7 +988,11 @@ static k_s32 ov5647_sensor_power_on(void *ctx, k_s32 on) if (on) { ov5647_power_rest(on); ov5647_i2c_init(&dev->i2c_info); - ov5647_sensor_get_chip_id(ctx, &chip_id); + ret = ov5647_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } // write power on // ret = sensor_reg_list_write(&dev->i2c_info, sensor_oe_enable_regs); } else { @@ -965,6 +1258,218 @@ static k_s32 ov5647_sensor_init(void *ctx, k_sensor_mode mode) current_mode->sensor_again = 0; current_mode->et_line = 0; break; + + case 2: + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 575; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000027808;//0.00003025 + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + case 6: + // 960p + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 630; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000017636; + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + case 5: //720P + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 886; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000027808;//0.00003025 + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; } k_u16 again_h, again_l; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_drv.c index 29fcd8b..1c63342 100755 --- a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_drv.c +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov5647_drv.c @@ -283,7 +283,7 @@ static const k_sensor_reg ov5647_2592x1944_10bpp[] = { {REG_NULL, 0x00}, }; -static const k_sensor_reg ov5647_640x480_10bpp[] = { +static const k_sensor_reg ov5647_640x480_60fps_10bpp[] = { //pixel_rate = 55000000 {0x0100, 0x00}, {0x0103, 0x01}, @@ -384,6 +384,105 @@ static const k_sensor_reg ov5647_640x480_10bpp[] = { }; +//90 fps ok +static const k_sensor_reg ov5647_640x480_10bpp[] = { + //pixel_rate = 95833333 Hz, 1852 x 575 x 90fps + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x3034, 0x1a}, + {0x3035, 0x21}, + {0x3036, 0x73}, + {0x303c, 0x11}, + {0x3106, 0xf5}, + {0x3820, 0x01}, //horizontal, bit1: mirror, bit0: bining + {0x3821, 0x03}, //verticall, bit1: flip, bit0: bining + {0x3827, 0xec}, + {0x370c, 0x03}, + {0x3612, 0x59}, + {0x3618, 0x00}, + {0x5000, 0x06}, + {0x5001, 0x00}, // set awb disble + {0x5002, 0x00}, //disable win, otp and awb gain + {0x5003, 0x08}, + {0x5a00, 0x08}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, //2 lane, MIPI + {0x301c, 0xf8}, + {0x301d, 0xf0}, + {0x3a18, 0x03}, //gain_celling, max gain value + {0x3a19, 0xff}, //gain_celling + {0x3c01, 0x80}, + {0x3b07, 0x0c}, + {0x380c, 0x07}, // HTS = 1852 + {0x380d, 0x3c}, + {0x380e, 0x02}, //VTS = 575 + {0x380f, 0x3f}, + {0x3814, 0x35}, //horizontal subsampling, 8/2 + {0x3815, 0x35}, //vertical subsampling, 8/2 + {0x3708, 0x64}, + {0x3709, 0x52}, + {0x3808, 0x02}, // x output size: 640 + {0x3809, 0x80}, + {0x380a, 0x01}, // y output size: 480 + {0x380b, 0xe0}, + {0x3800, 0x00}, //x start = 0x10 = 16 + {0x3801, 0x10}, + {0x3802, 0x00}, //y start = 0 + {0x3803, 0x00}, + {0x3804, 0x0a}, //x end = 0xa2f = 2607, x size = 2607 - 16 + 1 = 2592 (648 x 4) + {0x3805, 0x2f}, + {0x3806, 0x07}, //y end = 0x79f = 1951, y size = 1951 - 0 + 1 = 1952 (488 x 4) + {0x3807, 0x9f}, + //{0x3811, 0x04}, //x offset: 4 + //{0x3813, 0x02}, //y offset: 2 + {0x3630, 0x2e}, + {0x3632, 0xe2}, + {0x3633, 0x23}, + {0x3634, 0x44}, + {0x3636, 0x06}, + {0x3620, 0x64}, + {0x3621, 0xe0}, + {0x3600, 0x37}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x3731, 0x02}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3f05, 0x02}, + {0x3f06, 0x10}, + {0x3f01, 0x0a}, + {0x3a00, 0x00}, //AEC control, all disable + {0x3a08, 0x01}, //50Hz step + {0x3a09, 0x2e}, + {0x3a0a, 0x00}, //60Hz step + {0x3a0b, 0xfb}, + {0x3a0d, 0x02}, + {0x3a0e, 0x01}, + {0x3a0f, 0x58}, + {0x3a10, 0x50}, + {0x3a1b, 0x58}, + {0x3a1e, 0x50}, + {0x3a11, 0x60}, + {0x3a1f, 0x28}, + {0x4001, 0x02}, + {0x4004, 0x02}, //blc line number + {0x4000, 0x09}, + //{0x4837, 0x15}, + {0x4800, 0x34}, + {0x3501, 0x02}, //ET = 42 lines + {0x3502, 0xa0}, + {0x3503, 0x07}, //0x0f + {0x350b, 0x10}, // gain + //{0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + static const k_sensor_reg ov5647_mipi2lane_1080p_30fps_flip_linear[] = { //pixel_rate = 81666700 {0x0103, 0x01}, @@ -482,6 +581,214 @@ static const k_sensor_reg ov5647_mipi2lane_1080p_30fps_flip_linear[] = { {REG_NULL, 0x00}, }; +// 60 fps binning ok +static const k_sensor_reg mode_1280x720_60fps[] = { + //PCLK = 95833333 Hz, 1796 x 886 x 60 + {0x0100, 0x00}, + {0x0103, 0x01}, + {0x3034, 0x1a}, + {0x3035, 0x21}, + {0x3036, 0x73}, //PLL multiplier + {0x303c, 0x11}, + {0x3106, 0xf5}, + {0x3820, 0x01}, //horizontal, bit1: mirror, bit0: bining + {0x3821, 0x03}, //verticall, bit1: flip, bit0: bining + {0x3827, 0xec}, + {0x370c, 0x03}, + {0x3612, 0x59}, + {0x3618, 0x00}, + {0x5000, 0x06}, //blc enable + {0x5001, 0x00}, // set awb disble + {0x5002, 0x00}, //disable win, otp and awb gain + {0x5003, 0x08}, + {0x5a00, 0x08}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, //2 lane, MIPI + {0x301c, 0xf8}, + {0x301d, 0xf0}, + {0x3a18, 0x03}, //gain_celling, max gain value + {0x3a19, 0xff}, //gain_celling + {0x3c01, 0x80}, + {0x3b07, 0x0c}, + + {0x380c, 0x07}, // HTS= 0x768 = 1896 - 100 --> 1796 = 0x704 + {0x380d, 0x04}, + {0x380e, 0x03}, // VTS= 0x7b0 = 1968 - 300 = 1,668 = 0x684 - 688 = 1000 = 0x3e8 - 150 = 850 = 0x352 + 36 = 886 = 0x376 + {0x380f, 0x76}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3808, 0x05}, // x output size: 1280, 1280 * 2 = 2,560 + {0x3809, 0x00}, + {0x380a, 0x02}, // y output size: 720, 720 * 2 = 1,440 + {0x380b, 0xd0}, + {0x3800, 0x00}, // x start = 32 + {0x3801, 0x20}, + {0x3802, 0x01}, // y start = 258 + {0x3803, 0x02}, + {0x3804, 0x0a}, // x end = 2623 + {0x3805, 0x3f}, + {0x3806, 0x07}, // y end = 0x73f + 52 = 1907 = 0x779 + {0x3807, 0x79}, + {0x3811, 0x0c}, //x offset: 4 + {0x3813, 0x06}, //y offset: 2 + + {0x3630, 0x2e}, + {0x3632, 0xe2}, + {0x3633, 0x23}, + {0x3634, 0x44}, + {0x3636, 0x06}, + {0x3620, 0x64}, + {0x3621, 0xe0}, + {0x3600, 0x37}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x3731, 0x02}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3f05, 0x02}, + {0x3f06, 0x10}, + {0x3f01, 0x0a}, + {0x3a00, 0x00}, //AEC control, all disable + {0x3a08, 0x01}, + {0x3a09, 0x28}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x08}, + {0x3a0e, 0x06}, + {0x3a0f, 0x58}, + {0x3a10, 0x50}, + {0x3a1b, 0x58}, + {0x3a1e, 0x50}, + {0x3a11, 0x60}, + {0x3a1f, 0x28}, + {0x4001, 0x02}, + {0x4004, 0x04}, //blc line number + {0x4000, 0x09}, + {0x4837, 0x16}, + {0x4800, 0x24}, + + {0x3501, 0x02}, //ET = 42 lines + {0x3502, 0xa0}, + {0x3503, 0x07}, //0x03 + {0x350b, 0x10}, + {0x3212, 0xa0}, + //{0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + +// 960p60 10bpp +static const k_sensor_reg ov5647_1280x960p30_10bpp[] = { + {0x0100, 0x00}, + {0x0103, 0x01}, + {0x3034, 0x1a}, + + {0x3035, 0x21}, + {0x3036, 0x73}, + + {0x303c, 0x11}, + {0x3106, 0xf5}, + {0x3827, 0xec}, + {0x370c, 0x03}, + {0x3612, 0x59}, + {0x3618, 0x00}, + {0x5000, 0x06}, + {0x5002, 0x41}, + {0x5003, 0x08}, + {0x5a00, 0x08}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, + {0x301c, 0xf8}, + {0x301d, 0xf0}, + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + {0x3c01, 0x80}, + {0x3b07, 0x0c}, + + {0x3800, 0x00}, // x start 0 + {0x3801, 0x00}, + + {0x3802, 0x00}, // y star 0 + {0x3803, 0x00}, + + {0x3804, 0x0a}, // x end 0xa3f + {0x3805, 0x3f}, + + {0x3806, 0x07}, // y end 0x7a3 + {0x3807, 0xa3}, + + {0x3808, 0x05}, // x size 0x510 + {0x3809, 0x10}, + + {0x380a, 0x03}, // y size 0x3cc + {0x380b, 0xcc}, + + {0x380c, 0x07}, // x total 0x768 = 1896 + {0x380d, 0x68}, + + {0x380e, 0x05}, // v total 0x7b0 = 1968 -500 = 1468 = 0x5bc + {0x380f, 0xbc}, + + {0x3811, 0x0c}, + {0x3813, 0x06}, + {0x3814, 0x31}, + {0x3815, 0x31}, + {0x3630, 0x2e}, + {0x3632, 0xe2}, + {0x3633, 0x23}, + {0x3634, 0x44}, + {0x3636, 0x06}, + {0x3620, 0x64}, + {0x3621, 0xe0}, + {0x3600, 0x37}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x3731, 0x02}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3f05, 0x02}, + {0x3f06, 0x10}, + {0x3f01, 0x0a}, + {0x3a08, 0x01}, + {0x3a09, 0x28}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x08}, + {0x3a0e, 0x06}, + {0x3a0f, 0x58}, + {0x3a10, 0x50}, + {0x3a1b, 0x58}, + {0x3a1e, 0x50}, + {0x3a11, 0x60}, + {0x3a1f, 0x28}, + {0x4001, 0x02}, + {0x4004, 0x04}, + {0x4000, 0x09}, + {0x4837, 0x16}, + {0x4800, 0x24}, + {0x3503, 0x03}, + {0x3821, 0x01}, + {0x3820, 0x41}, + {0x350a, 0x00}, + {0x350b, 0x10}, + {0x3500, 0x00}, + {0x3501, 0x1a}, + {0x3502, 0xf0}, + {0x3212, 0xa0}, + {0x0100, 0x01}, + {REG_NULL, 0x00}, +}; static k_sensor_mode ov5647_mode_info[] = { { @@ -560,7 +867,20 @@ static k_sensor_mode ov5647_mode_info[] = { .data_type = 0x2B, //RAW10 }, .reg_list = ov5647_640x480_10bpp, +#if defined(CONFIG_BOARD_K230_CANMV) + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, +#else .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, +#endif }, { .index = 3, @@ -650,6 +970,79 @@ static k_sensor_mode ov5647_mode_info[] = { .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, }, + { + .index = 6, + .sensor_type = OV_OV5647_MIPI_CSI0_1280X720_60FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 60000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_GBRG, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 2, + .data_type = 0x2B, //RAW10 + }, + .reg_list = mode_1280x720_60fps, //mode_1280x720_60fps, +#if defined(CONFIG_BOARD_K230_CANMV) + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, +#else + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, +#endif + }, + { + .index = 7, + .sensor_type = OV_OV5647_MIPI_CSI0_1280X960_60FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 960, + .top = 0, + .left = 0, + .width = 1280, + .height = 960, + }, + .fps = 60000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 2, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov5647_1280x960p30_10bpp, //mode_1280x720_60fps, +#if defined(CONFIG_BOARD_K230_CANMV) + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, +#else + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, +#endif + }, + }; static k_sensor_mode *current_mode = NULL; @@ -661,7 +1054,6 @@ int ov5647_power_rest(k_s32 on) rt_kprintf("ov5647_power_rest OV5647_CAM_PIN is %d \n", OV5647_CAM_PIN); // rst kd_pin_mode(OV5647_CAM_PIN, GPIO_DM_OUTPUT); - kd_pin_write(OV5647_CAM_PIN, GPIO_PV_HIGH); if (on) @@ -681,6 +1073,19 @@ int ov5647_power_rest(k_s32 on) return 0; } + +static int ov5647_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) { k_s32 ret = 0; @@ -689,32 +1094,25 @@ static k_s32 ov5647_sensor_get_chip_id(void *ctx, k_u32 *chip_id) struct sensor_driver_dev *dev = ctx; pr_info("%s enter\n", __func__); + ov5647_i2c_init(&dev->i2c_info); + + kd_pin_mode(OV5647_CAM_PIN, GPIO_DM_OUTPUT); + kd_pin_write(OV5647_CAM_PIN, GPIO_PV_HIGH); + ret = sensor_reg_read(&dev->i2c_info, OV5647_REG_CHIP_ID_H, &id_high); ret |= sensor_reg_read(&dev->i2c_info, OV5647_REG_CHIP_ID_L, &id_low); if (ret) { - rt_kprintf("%s error\n", __func__);; + // rt_kprintf("%s error\n", __func__);; return -1; } *chip_id = (id_high << 8) | id_low; - pr_info("%s chip_id[0x%08X]\n", __func__, *chip_id); + // pr_info("%s chip_id[0x%08X]\n", __func__, *chip_id); return ret; } -static int ov5647_i2c_init(k_sensor_i2c_info *i2c_info) -{ - i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); - if (i2c_info->i2c_bus == RT_NULL) - { - pr_err("can't find %s deivce", i2c_info->i2c_name); - return RT_ERROR; - } - - return 0; -} - static k_s32 ov5647_sensor_power_on(void *ctx, k_s32 on) { k_s32 ret = 0; @@ -724,7 +1122,11 @@ static k_s32 ov5647_sensor_power_on(void *ctx, k_s32 on) if (on) { ov5647_power_rest(on); ov5647_i2c_init(&dev->i2c_info); - ov5647_sensor_get_chip_id(ctx, &chip_id); + ret = ov5647_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } // write power on // ret = sensor_reg_list_write(&dev->i2c_info, sensor_oe_enable_regs); } else { @@ -987,6 +1389,218 @@ static k_s32 ov5647_sensor_init(void *ctx, k_sensor_mode mode) current_mode->ae_info.d_vs_gain.min = 1.0; current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f); + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + case 6: //720P + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 886; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000027808;//0.00003025 + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + case 2: + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 575; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000027808;//0.00003025 + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + case 7: + // 960p + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 630; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000017636; + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 8.0;//63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = (1.0f/16.0f); + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_long_integraion_line = 2; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 12; + current_mode->ae_info.min_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 8.0; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 8.0; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + current_mode->ae_info.cur_fps = current_mode->fps; current_mode->sensor_again = 0; current_mode->et_line = 0; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov9286_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov9286_drv.c new file mode 100755 index 0000000..9c885b6 --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov9286_drv.c @@ -0,0 +1,1661 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" + +//#include +#include "io.h" + +// #include "gpio.h" +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#include "k_vicap_comm.h" + +#define pr_info(...) //rt_kprintf(__VA_ARGS__) +#define pr_debug(...) //rt_kprintf(__VA_ARGS__) +#define pr_warn(...) //rt_kprintf(__VA_ARGS__) +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define OV9286_REG_CHIP_ID_H 0x300a +#define OV9286_REG_CHIP_ID_L 0x300b + +#define OV9286_REG_LONG_EXP_TIME_H 0x3501 +#define OV9286_REG_LONG_EXP_TIME_L 0x3502 + +#define OV9286_REG_LONG_AGAIN 0x3509 +//#define OV9286_REG_LONG_AGAIN_H 0x350a +//#define OV9286_REG_LONG_AGAIN_L 0x350b + +#define OV9286_MIN_GAIN_STEP (1.0f/16.0f) + +static const k_sensor_reg ov9286_mipi2lane_720p_60fps_linear[] = { + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x3006, 0x06}, + {0x300f, 0xf4}, + {0x3011, 0x0a}, + {0x3013, 0x18}, + {0x302c, 0x00}, + {0x302f, 0x05}, + {0x3030, 0x10}, + {0x303f, 0x03}, + {0x31ff, 0x01}, + {0x3210, 0x04}, + {0x3503, 0x08}, + {0x3505, 0x8c}, + {0x3507, 0x03}, + {0x3508, 0x00}, + {0x3509, 0x10}, //gain + {0x350d, 0x07}, + {0x3510, 0x00}, + {0x3511, 0x00}, + {0x3512, 0x00}, + {0x3610, 0x80}, + {0x3611, 0xb8}, + {0x3612, 0x02}, + {0x3614, 0x80}, + {0x3620, 0x6e}, + {0x3632, 0x56}, + {0x3633, 0x78}, + {0x3662, 0x15}, + {0x3666, 0x70}, + {0x3670, 0x68}, + {0x3673, 0xe4}, + {0x3678, 0x00}, + {0x367e, 0x90}, + {0x3680, 0x84}, + {0x3707, 0x6c}, + {0x3712, 0x80}, + {0x372d, 0x22}, + {0x3731, 0x90}, + {0x3732, 0x30}, + {0x3778, 0x00}, + {0x377d, 0x22}, + {0x3788, 0x02}, + {0x3789, 0xa4}, + {0x378a, 0x00}, + {0x378b, 0x44}, + {0x3799, 0x20}, + {0x379b, 0x01}, + {0x379c, 0x10}, + {0x37a8, 0x42}, + {0x37aa, 0x52}, + {0x3803, 0xc8}, //y start: 200 + {0x3804, 0x05}, + {0x3805, 0x3f}, //x end: 1344 = 32 + 1280 +32 + {0x3806, 0x03}, + {0x3807, 0x9f}, //y end: 0x3a7 = 936, 0x39f = 928 + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x02}, + {0x380b, 0xd0}, + {0x380c, 0x02}, //HTS = 0x2b8 = 696 + {0x380d, 0xb8}, + {0x380e, 0x07}, //VTS = 0x77b = 1915 + {0x380f, 0x7b}, + {0x3810, 0x00}, + {0x3811, 0x20}, + {0x3816, 0x00}, + {0x3817, 0x01}, + {0x3818, 0x00}, + {0x3819, 0x05}, + {0x382b, 0x3a}, + {0x382c, 0x09}, + {0x382d, 0x9a}, + {0x3880, 0x10}, + {0x3881, 0x42}, + {0x3882, 0x01}, + {0x3883, 0xcc}, + {0x3885, 0x07}, + {0x389d, 0x03}, + {0x38a6, 0x00}, + {0x38a7, 0x01}, + {0x38b1, 0x00}, + {0x38b3, 0x07}, + {0x38e5, 0x02}, + {0x38e7, 0x00}, + + {0x4003, 0x10}, //black level target + {0x4008, 0x02}, + {0x4009, 0x09}, + {0x400a, 0x01}, + {0x400b, 0x30}, + {0x400c, 0x02}, + {0x400d, 0x09}, + {0x4010, 0xf0}, + {0x4016, 0x00}, + {0x4012, 0x08}, + {0x4017, 0x10}, + {0x4042, 0xd3}, + {0x4043, 0x60}, + {0x4045, 0x20}, + {0x404b, 0x20}, + {0x4307, 0x88}, + {0x4507, 0x40}, + {0x450b, 0x80}, + {0x450f, 0x00}, + {0x4600, 0x00}, + {0x4601, 0x01}, + {0x4603, 0x01}, + {0x4800, 0x60}, + {0x481f, 0x30}, + {0x4825, 0x35}, + {0x4837, 0x14}, + {0x4f00, 0x00}, + {0x4f07, 0x00}, + {0x4f08, 0x03}, + {0x4f09, 0x08}, + {0x4f0c, 0x04}, + {0x4f0d, 0xe4}, + {0x4f10, 0x00}, + {0x4f11, 0x00}, + {0x4f12, 0x0f}, + {0x4f13, 0xc4}, + {0x4f07, 0x00}, + {0x3880, 0x00}, + {0x4837, 0x1b}, + {0x3006, 0xea}, + {0x3210, 0x10}, + {0x3007, 0x02}, + {0x301c, 0x22}, + {0x3020, 0x20}, + {0x3025, 0x02}, + {0x382c, 0x07}, + {0x382d, 0xc0}, + {0x3920, 0xff}, + {0x3923, 0x00}, + {0x3924, 0x00}, + {0x3925, 0x00}, + {0x3928, 0x80}, + {0x392b, 0x00}, + {0x392c, 0x00}, + {0x392d, 0x03}, + {0x392e, 0xe0}, + {0x392f, 0xcb}, + {0x38b3, 0x07}, + {0x3885, 0x07}, + {0x382b, 0x5a}, + {0x3670, 0x68}, + {0x3006, 0xea}, + {0x3501, 0x11}, //ET = 287, 2.5ms + {0x3502, 0xf0}, // + {0x3927, 0x00}, //strobe width + {0x3928, 0x73}, + {0x3929, 0x07}, //strobe start point + {0x392a, 0x08}, // -7 : 01 + {0x3208, 0x10}, + {0x3208, 0xa0}, + {REG_NULL, 0x00}, +}; + +static const k_sensor_reg ov9286_mipi2lane_720p_30fps_linear[] = { + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x0300, 0x04}, //MIPI clock: 500Mbps, PLL1: 50MHz + {0x0302, 0x7d}, + {0x030a, 0x01}, + {0x030b, 0x02}, //PLL2(PCLK): 50MHz + {0x030d, 0x32}, + {0x030e, 0x06}, + {0x030f, 0x02}, + {0x0312, 0x0b}, + {0x0313, 0x02}, + {0x3006, 0x06}, + {0x300f, 0xf4}, + {0x3011, 0x0a}, + {0x3013, 0x18}, + {0x302c, 0x00}, + {0x302d, 0x0d}, + {0x302e, 0x6b}, + {0x302f, 0x2d}, + {0x3030, 0x10}, + {0x303f, 0x03}, + {0x31ff, 0x01}, + {0x3210, 0x04}, + {0x3500, 0x00}, + {0x3501, 0x6f}, //ET = 0x6f0 + {0x3502, 0x00}, // + {0x3503, 0x08}, + {0x3505, 0x8c}, + {0x3507, 0x03}, + {0x3508, 0x00}, + {0x3509, 0x10}, //sensor analog gain, 1x + {0x350d, 0x07}, + {0x3510, 0x00}, + {0x3511, 0x00}, + {0x3512, 0x00}, + {0x3610, 0x80}, + {0x3611, 0xb8}, + {0x3612, 0x02}, + {0x3614, 0x80}, + {0x3620, 0x6e}, + {0x3632, 0x56}, + {0x3633, 0x78}, + {0x3662, 0x15}, + {0x3666, 0x70}, + {0x3670, 0x68}, + {0x3673, 0xe4}, + {0x3678, 0x00}, + {0x367e, 0x90}, + {0x3680, 0x84}, + {0x3707, 0x6c}, + {0x3712, 0x80}, + {0x372d, 0x22}, + {0x3731, 0x90}, + {0x3732, 0x30}, + {0x3778, 0x00}, + {0x377d, 0x22}, + {0x3788, 0x02}, + {0x3789, 0xa4}, + {0x378a, 0x00}, + {0x378b, 0x44}, + {0x3799, 0x20}, + {0x379b, 0x01}, + {0x379c, 0x10}, + {0x37a8, 0x42}, + {0x37aa, 0x52}, + {0x37ab, 0x3c}, + {0x3802, 0x00}, + {0x3803, 0xc8}, + {0x3806, 0x03}, + {0x3807, 0xa7}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x02}, + {0x380b, 0xd0}, + {0x380c, 0x02}, //HTS = 760 + {0x380d, 0xf8}, + {0x380e, 0x08}, //VTS = 2193 + {0x380f, 0x91}, + {0x3810, 0x00}, + {0x3811, 0x20}, + {0x3817, 0x01}, + {0x3818, 0x00}, + {0x3819, 0x05}, + {0x382b, 0x3a}, + {0x382c, 0x09}, + {0x382d, 0x9a}, + {0x3880, 0x10}, + {0x3881, 0x42}, + {0x3882, 0x01}, + {0x3883, 0xcc}, + {0x3885, 0x07}, + {0x389d, 0x03}, + {0x38a6, 0x00}, + {0x38a7, 0x01}, + {0x38b1, 0x00}, + {0x38b3, 0x07}, + {0x38e5, 0x02}, + {0x38e7, 0x00}, + {0x4008, 0x02}, + {0x4009, 0x09}, + {0x400a, 0x01}, + {0x400b, 0x30}, + {0x400c, 0x02}, + {0x400d, 0x09}, + {0x4010, 0xf0}, + {0x4016, 0x00}, + {0x4012, 0x08}, + {0x4017, 0x10}, + {0x4042, 0xd3}, + {0x4043, 0x60}, + {0x4045, 0x20}, + {0x404b, 0x20}, + {0x4307, 0x88}, + {0x4507, 0x40}, + {0x450b, 0x80}, + {0x450f, 0x00}, + {0x4600, 0x00}, + {0x4601, 0x01}, + {0x4603, 0x01}, + {0x4800, 0x60}, + {0x481f, 0x30}, + {0x4825, 0x35}, + {0x4837, 0x35}, + {0x4f00, 0x00}, + {0x4f07, 0x00}, + {0x4f08, 0x03}, + {0x4f09, 0x08}, + {0x4f0c, 0x03}, + {0x4f0d, 0x54}, + {0x4f10, 0x00}, + {0x4f11, 0x00}, + {0x4f12, 0x0f}, + {0x4f13, 0xc4}, + {0x4f07, 0x00}, + {0x5000, 0x9f}, + {0x5e00, 0x00}, + {0x3006, 0xea}, + {0x3210, 0x10}, + {0x3007, 0x02}, + {0x301c, 0x22}, + {0x3020, 0x20}, + {0x3025, 0x02}, + {0x382c, 0x11}, + {0x382d, 0x70}, + {0x3920, 0xff}, + {0x3923, 0x00}, + {0x3924, 0x00}, + {0x3925, 0x00}, + {0x3926, 0x00}, + {0x3928, 0x80}, + {0x392b, 0x00}, + {0x392c, 0x00}, + {0x392d, 0x08}, + {0x392e, 0xb8}, + {0x392f, 0xcb}, + {0x38b3, 0x07}, + {0x3885, 0x07}, + {0x382b, 0x5a}, + {0x3670, 0x68}, + {0x3006, 0xea}, + {0x3501, 0x08}, // ET = 0x9c = 132 ET line (2ms) + {0x3502, 0x40}, + {0x3509, 0x10}, + {0x3927, 0x00}, //strobe width, 3ms + {0x3928, 0xc6}, + {0x3929, 0x07}, //strobe start point + {0x392a, 0xc4}, + {0x3208, 0x10}, + {0x3208, 0xa0}, + {REG_NULL, 0x00}, +}; + +static const k_sensor_reg ov9286_mipi2lane_720p_30fps_mclk_25m_linear[] = { + {0x0103, 0x01}, + {0x0100, 0x00}, + // {0x0300, 0x04}, //MIPI clock: 500Mbps, PLL1: 50MHz + // {0x0301, 0x00}, + // {0x0302, 0x7d}, + // {0x0303, 0x00}, + // {0x030a, 0x01}, + // {0x030b, 0x02}, //PLL2(PCLK): 50MHz + // {0x030d, 0x32}, + {0x0300, 0x00}, //MIPI clock: 500Mbps, PLL1: 50MHz + {0x0301, 0x00}, + {0x0302, 0x14}, + {0x0303, 0x00}, + {0x030a, 0x00}, + {0x030b, 0x00}, //PLL2(PCLK): 50MHz + {0x030d, 0x18}, + + {0x030e, 0x06}, + {0x030f, 0x02}, + {0x0312, 0x0b}, + {0x0313, 0x02}, + {0x3004, 0x00}, + {0x3006, 0x06}, + {0x300f, 0xf4}, + {0x3011, 0x0a}, + {0x3013, 0x18}, + {0x302c, 0x00}, + {0x302d, 0x0d}, + {0x302e, 0x6b}, + {0x302f, 0x2d}, + {0x3030, 0x10}, + {0x303f, 0x03}, + {0x31ff, 0x01}, + {0x3210, 0x04}, + {0x3500, 0x00}, + {0x3501, 0x6f}, //ET = 0x6f0 + {0x3502, 0x00}, // + {0x3503, 0x08}, + {0x3505, 0x8c}, + {0x3507, 0x03}, + {0x3508, 0x00}, + {0x3509, 0x10}, //sensor analog gain, 1x + {0x350d, 0x07}, + {0x3510, 0x00}, + {0x3511, 0x00}, + {0x3512, 0x00}, + {0x3610, 0x80}, + {0x3611, 0xb8}, + {0x3612, 0x02}, + {0x3614, 0x80}, + {0x3620, 0x6e}, + {0x3632, 0x56}, + {0x3633, 0x78}, + {0x3662, 0x15}, + {0x3666, 0x70}, + {0x3670, 0x68}, + {0x3673, 0xe4}, + {0x3678, 0x00}, + {0x367e, 0x90}, + {0x3680, 0x84}, + {0x3707, 0x6c}, + {0x3712, 0x80}, + {0x372d, 0x22}, + {0x3731, 0x90}, + {0x3732, 0x30}, + {0x3778, 0x00}, + {0x377d, 0x22}, + {0x3788, 0x02}, + {0x3789, 0xa4}, + {0x378a, 0x00}, + {0x378b, 0x44}, + {0x3799, 0x20}, + {0x379b, 0x01}, + {0x379c, 0x10}, + {0x37a8, 0x42}, + {0x37aa, 0x52}, + {0x37ab, 0x3c}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0xc8}, + {0x3804, 0x05}, + {0x3805, 0x3f}, + {0x3806, 0x03}, + {0x3807, 0xa7}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x02}, + {0x380b, 0xd0}, + {0x380c, 0x02}, //HTS = 760 + {0x380d, 0xf8}, + {0x380e, 0x08}, //VTS = 2193 + {0x380f, 0x91}, + {0x3810, 0x00}, + {0x3811, 0x20}, + {0x3812, 0x00}, + {0x3813, 0x08}, + {0x3814, 0x11}, + {0x3815, 0x11}, + {0x3816, 0x00}, + {0x3817, 0x01}, + {0x3818, 0x00}, + {0x3819, 0x05}, + {0x3820, 0x40}, + {0x3821, 0x00}, + {0x382b, 0x3a}, + {0x382c, 0x09}, + {0x382d, 0x9a}, + {0x3880, 0x10}, + {0x3881, 0x42}, + {0x3882, 0x01}, + {0x3883, 0xcc}, + {0x3885, 0x07}, + {0x389d, 0x03}, + {0x38a6, 0x00}, + {0x38a7, 0x01}, + {0x38a8, 0x00}, + {0x38a9, 0xf0}, + {0x38b1, 0x00}, + {0x38b3, 0x07}, + {0x38c4, 0x01}, + {0x38c5, 0x18}, + {0x38c6, 0x02}, + {0x38c7, 0xa8}, + {0x38e5, 0x02}, + {0x38e7, 0x00}, + {0x38e8, 0x00}, + {0x38ed, 0x00}, + {0x38ee, 0x00}, + {0x38ef, 0x00}, + {0x3920, 0xa5}, + {0x3921, 0x00}, + {0x3922, 0x00}, + {0x3923, 0x00}, + {0x3924, 0x05}, + {0x3925, 0x00}, + {0x3926, 0x00}, + {0x3927, 0x00}, + {0x3928, 0x1a}, + {0x3929, 0x01}, + {0x392a, 0xb4}, + {0x392b, 0x00}, + {0x392c, 0x10}, + {0x392f, 0x40}, + {0x393e, 0x00}, + {0x393f, 0x00}, + {0x4001, 0x00}, + {0x4003, 0x10}, + {0x4008, 0x02}, + {0x4009, 0x09}, + {0x400a, 0x01}, + {0x400b, 0x30}, + {0x400c, 0x02}, + {0x400d, 0x09}, + {0x4010, 0xf0}, + {0x4016, 0x00}, + {0x4012, 0x08}, + {0x4017, 0x10}, + {0x4042, 0xd3}, + {0x4043, 0x60}, + {0x4045, 0x20}, + {0x404b, 0x20}, + {0x4307, 0x88}, + {0x4507, 0x40}, + {0x450b, 0x80}, + {0x450f, 0x00}, + {0x4600, 0x00}, + {0x4601, 0x01}, + {0x4603, 0x01}, + {0x4800, 0x60}, + {0x481f, 0x30}, + {0x4825, 0x35}, + {0x4837, 0x35}, + {0x4f00, 0x00}, + {0x4f07, 0x00}, + {0x4f08, 0x03}, + {0x4f09, 0x08}, + {0x4f0c, 0x03}, + {0x4f0d, 0x54}, + {0x4f10, 0x00}, + {0x4f11, 0x00}, + {0x4f12, 0x0f}, + {0x4f13, 0xc4}, + {0x4f07, 0x00}, + {0x5000, 0x9f}, + {0x5e00, 0x00}, + {0x3006, 0xea}, + {0x3210, 0x10}, + {0x3007, 0x02}, + {0x301c, 0x22}, + {0x3020, 0x20}, + {0x3025, 0x02}, + {0x382c, 0x11}, + {0x382d, 0x70}, + {0x3920, 0xff}, + {0x3923, 0x00}, + {0x3924, 0x00}, + {0x3925, 0x00}, + {0x3926, 0x00}, + {0x3927, 0x00}, + {0x3928, 0x80}, + {0x392b, 0x00}, + {0x392c, 0x00}, + {0x392d, 0x08}, + {0x392e, 0xb8}, + {0x392f, 0xcb}, + {0x38b3, 0x07}, + {0x3885, 0x07}, + {0x382b, 0x5a}, + {0x3670, 0x68}, + {0x3006, 0xea}, + {0x3208, 0x00}, + // {0x3501, 0x09}, // ET = 0x9c = 156 ET line (2.371ms) + // {0x3502, 0xc0}, + {0x3501, 0x02}, // ET = 0x9c = 156 ET line (2.371ms) + {0x3502, 0xd0}, + {0x3509, 0x10}, + // {0x3927, 0x02}, // 20ms + // {0x3928, 0xcf}, // 20ms + {0x3927, 0x00}, // 20ms + {0x3928, 0x42}, // 20ms + // {0x3929, 0x04}, + // {0x392a, 0x9c}, + {0x3929, 0x08}, + {0x392a, 0x48}, + {0x3208, 0x10}, + {0x3208, 0xa0}, + //{0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + +static k_sensor_mode ov9286_mode_info[] = { + { + .index = 0, + .sensor_type = OV_OV9286_MIPI_1280X720_30FPS_10BIT_LINEAR_IR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_30fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 1, + .sensor_type = OV_OV9286_MIPI_1280X720_30FPS_10BIT_LINEAR_SPECKLE, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_30fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 2, + .sensor_type = OV_OV9286_MIPI_1280X720_30FPS_10BIT_MCLK_25M_LINEAR_SPECKLE, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_30fps_mclk_25m_linear, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, //32, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, + { + .index = 3, + .sensor_type = OV_OV9286_MIPI_1280X720_30FPS_10BIT_MCLK_25M_LINEAR_IR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_30fps_mclk_25m_linear, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, //32, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, + { + .index = 4, + .sensor_type = OV_OV9286_MIPI_1280X720_60FPS_10BIT_LINEAR_IR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_60fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 5, + .sensor_type = OV_OV9286_MIPI_1280X720_60FPS_10BIT_LINEAR_SPECKLE, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_60fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 6, + .sensor_type = OV_OV9286_MIPI_1280X720_30FPS_10BIT_LINEAR_IR_SPECKLE, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_30fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 7, + .sensor_type = OV_OV9286_MIPI_1280X720_60FPS_10BIT_LINEAR_IR_SPECKLE, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_60fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 8, + .sensor_type = OV_OV9286_MIPI_1280X720_30FPS_10BIT_MCLK_25M_LINEAR_SPECKLE_V2, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_30fps_mclk_25m_linear, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK2, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, //32, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, + { + .index = 9, + .sensor_type = OV_OV9286_MIPI_1280X720_30FPS_10BIT_MCLK_25M_LINEAR_IR_V2, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9286_mipi2lane_720p_30fps_mclk_25m_linear, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK2, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, //32, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, +}; + +static k_bool ov9286_init_flag = K_FALSE; +static k_sensor_mode *current_mode = NULL; + +static int ov9286_power_rest(k_s32 on) +{ + // #define OV9286_RST_PIN (49) + + kd_pin_mode(VICAP_OV9286_RST_GPIO, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(VICAP_OV9286_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(1); + kd_pin_write(VICAP_OV9286_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(1); + kd_pin_write(VICAP_OV9286_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(VICAP_OV9286_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + + +static int ov9286_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + + +static k_s32 ov9286_sensor_get_chip_id(void *ctx, k_u32 *chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter\n", __func__); + + ov9286_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, OV9286_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, OV9286_REG_CHIP_ID_L, &id_low); + if (ret) { + // pr_err("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + pr_info("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + + +static k_s32 ov9286_sensor_power_on(void *ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + if (!ov9286_init_flag) { + ov9286_power_rest(on); + ov9286_i2c_init(&dev->i2c_info); + } + ret = ov9286_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + ov9286_init_flag = K_FALSE; + ov9286_power_rest(on); + } + + return ret; +} + +static k_s32 ov9286_sensor_init(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(ov9286_mode_info) / sizeof(k_sensor_mode); i++) { + if (ov9286_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(ov9286_mode_info[i]); + dev->sensor_mode = &(ov9286_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + case 0: + case 1: + case 2: + case 3: + case 6: + case 8: + case 9: + if (!ov9286_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + } + + current_mode->ae_info.frame_length = 2193; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000152;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.0; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = OV9286_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 165; //2.5ms //197; // 3ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + current_mode->ae_info.cur_fps = current_mode->fps; + break; + + case 4: + case 5: + case 7: + if (!ov9286_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + } + + current_mode->ae_info.frame_length = 1915; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000087;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.2; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = OV9286_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 287; // 2.5ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + + default: + break; + } + + k_u16 again_h, again_l; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + float again = 0, dgain = 0; + + ret = sensor_reg_read(&dev->i2c_info, OV9286_REG_LONG_AGAIN, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, OV9286_REG_LONG_AGAIN_H, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, OV9286_REG_LONG_AGAIN_L, &again_l); + again = (float)again_h / 16.0f; + + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + ret = sensor_reg_read(&dev->i2c_info, OV9286_REG_LONG_EXP_TIME_H, &exp_time_h); + ret = sensor_reg_read(&dev->i2c_info, OV9286_REG_LONG_EXP_TIME_L, &exp_time_l); + exp_time = (exp_time_h << 4) | ((exp_time_l >> 4) & 0x0F); + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + ov9286_init_flag = K_TRUE; + + return ret; +} + + +k_s32 ov9286_sensor_get_mode(void *ctx, k_sensor_mode *mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(ov9286_mode_info) / sizeof(k_sensor_mode); i++) { + if (ov9286_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &ov9286_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(ov9286_mode_info[i]); + return 0; + } + } + pr_info("%s, the mode not exit.\n", __func__); + + return ret; +} + +k_s32 ov9286_sensor_set_mode(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9286_sensor_enum_mode(void *ctx, k_sensor_enum_mode *enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(enum_mode, 0, sizeof(k_sensor_enum_mode)); + + return ret; +} + +k_s32 ov9286_sensor_get_caps(void *ctx, k_sensor_caps *caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +k_s32 ov9286_sensor_conn_check(void *ctx, k_s32 *conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +k_s32 ov9286_sensor_set_stream(void *ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +k_s32 ov9286_sensor_get_again(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 ov9286_sensor_set_again(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 again; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 16 + 0.5); + //if(current_mode->sensor_again !=again) + { + ret = sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_AGAIN,(again & 0xff)); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/16.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_L_PARAS]* 16 + 0.5); + ret = sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_AGAIN,(again & 0xff)); + current_mode->ae_info.cur_again = (float)again/16.0f; + + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 16 + 0.5); + //TODO + current_mode->ae_info.cur_vs_again = (float)again/16.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again*1000) ); + + return ret; +} + +k_s32 ov9286_sensor_get_dgain(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 ov9286_sensor_set_dgain(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + //TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = (float)dgain/1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain*10000)); + + return ret; +} + +k_s32 ov9286_sensor_get_intg_time(void *ctx, k_sensor_intg_time *time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 ov9286_sensor_set_intg_time(void *ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + k_u16 Strobe_StartPoint = 0; + k_u16 Strobe_Width = 0; + float integraion_time = 0; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + //if (current_mode->et_line != exp_line) + { + ret |= sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_EXP_TIME_H, ( exp_line >> 4) & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, OV9286_REG_LONG_EXP_TIME_L, ( exp_line << 4) & 0xf0); + current_mode->et_line = exp_line; +/* //set strobe + Strobe_Width = (exp_line + 52)/3; + Strobe_StartPoint = Sensor_VTS - Strobe_Width - 7; + //Strobe_StartPoint = Sensor_VTS - Strobe_Width; + + ret |= sensor_reg_write(&dev->i2c_info, 0x3927, ( Strobe_Width >> 8) & 0xff); //strobe width + ret |= sensor_reg_write(&dev->i2c_info, 0x3928, Strobe_Width & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, 0x3929, ( Strobe_StartPoint >> 8) & 0xff); //strobe start point + ret |= sensor_reg_write(&dev->i2c_info, 0x392a, Strobe_StartPoint & 0xff);*/ + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n",\ + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +k_s32 ov9286_sensor_get_exp_parm(void *ctx, k_sensor_exposure_param *exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +k_s32 ov9286_sensor_set_exp_parm(void *ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9286_sensor_get_fps(void *ctx, k_u32 *fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = 30000; + + return ret; +} + +k_s32 ov9286_sensor_set_fps(void *ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9286_sensor_get_isp_status(void *ctx, k_sensor_isp_status *staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +k_s32 ov9286_sensor_set_blc(void *ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9286_sensor_set_wb(void *ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9286_sensor_get_tpg(void *ctx, k_sensor_test_pattern *tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +k_s32 ov9286_sensor_set_tpg(void *ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9286_sensor_get_expand_curve(void *ctx, k_sensor_compand_curve *curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +k_s32 ov9286_sensor_get_otp_data(void *ctx, void *data) +{ + struct sensor_driver_dev *dev = ctx; + k_s32 ret = 0; + k_sensor_otp_date otp_date; + k_u16 reg_data = 0; + rt_kprintf("%s enter\n", __func__); + + //get opt data + memcpy(&otp_date, data, sizeof(k_sensor_otp_date)); + //clear 0x3D00~0x3D1F 0 + for(int i = 0; i < 32; i++) + { + sensor_reg_write(&dev->i2c_info, 0x3d00 + i, 0x00); + } + sensor_reg_write(&dev->i2c_info, 0x3d81, 0x01); + rt_thread_mdelay(15); + + if(otp_date.otp_type == 1) + { + for(int i = 0; i < 17; i++) + { + ret = sensor_reg_read(&dev->i2c_info, 0x3d00 + i, ®_data); + otp_date.otp_date[i] = (k_u8)reg_data; + // rt_kprintf("read otp tpye is %d read reg(%d) val is %x \n", otp_date.otp_type, i, reg_data); + } + } + else + { + for(int i = 0; i < 15; i++) + { + ret = sensor_reg_read(&dev->i2c_info, 0x3d11 + i, ®_data); + otp_date.otp_date[i] = (k_u8)reg_data; + // rt_kprintf("read otp tpye is %d read reg(%d) val is %x \n", otp_date.otp_type, i, reg_data); + } + } + memcpy(data, &otp_date, sizeof(k_sensor_otp_date)); + + return ret; +} + +k_s32 ov9286_sensor_set_otp_data(void *ctx, void *data) +{ + struct sensor_driver_dev *dev = ctx; + k_s32 ret = 0; + k_sensor_otp_date otp_date; + k_sensor_otp_date read_otp_date; + k_u16 reg_data = 0; + k_u16 data_len = 0; + pr_info("%s enter\n", __func__); + + memset(&read_otp_date, 0, sizeof(k_sensor_otp_date)); + memcpy(&otp_date, data, sizeof(k_sensor_otp_date)); + + // for(int i = 0; i < 15; i++) + // { + // rt_kprintf("read otp tpye is %d read reg(%d) val is %x \n", otp_date.otp_type, i, otp_date.otp_date[i]); + // } + + rt_kprintf("read otp tpye char val is %s \n", otp_date.otp_date); +#if 1 + // clear otp blank + for(int i = 0; i < 32; i++) + { + sensor_reg_write(&dev->i2c_info, 0x3d00 + i, 0x00); + } + // write reg + data_len = strlen(otp_date.otp_date); + if(data_len > 15) + return -1; + for(int i = 0; i < data_len; i++) + { + sensor_reg_write(&dev->i2c_info, 0x3d11 + i, otp_date.otp_date[i]); + } + sensor_reg_write(&dev->i2c_info, 0x3d80, 0x01); + rt_thread_mdelay(30); + + // read opt date + read_otp_date.otp_type = 0; + ov9286_sensor_get_otp_data(ctx, &read_otp_date); + // compare date + for(int i = 0; i < data_len; i++) + { + if(read_otp_date.otp_date[i] != otp_date.otp_date[i]) + { + rt_kprintf("otp write failed read_otp_date is %x otp_date is %x i is %d K_ERR_VICAP_OPT_ALREADY_WRITE is %d \n", read_otp_date.otp_date[i], otp_date.otp_date[i], i, K_ERR_VICAP_OPT_ALREADY_WRITE); + ret = K_ERR_VICAP_OPT_ALREADY_WRITE; + } + } +#endif + + return ret; +} + + +static k_s32 ov9286_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev ov9286_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c0", + .slave_addr = 0x60, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "ov9286", + .sensor_func = { + .sensor_power = ov9286_sensor_power_on, + .sensor_init = ov9286_sensor_init, + .sensor_get_chip_id = ov9286_sensor_get_chip_id, + .sensor_get_mode = ov9286_sensor_get_mode, + .sensor_set_mode = ov9286_sensor_set_mode, + .sensor_enum_mode = ov9286_sensor_enum_mode, + .sensor_get_caps = ov9286_sensor_get_caps, + .sensor_conn_check = ov9286_sensor_conn_check, + .sensor_set_stream = ov9286_sensor_set_stream, + .sensor_get_again = ov9286_sensor_get_again, + .sensor_set_again = ov9286_sensor_set_again, + .sensor_get_dgain = ov9286_sensor_get_dgain, + .sensor_set_dgain = ov9286_sensor_set_dgain, + .sensor_get_intg_time = ov9286_sensor_get_intg_time, + .sensor_set_intg_time = ov9286_sensor_set_intg_time, + .sensor_get_exp_parm = ov9286_sensor_get_exp_parm, + .sensor_set_exp_parm = ov9286_sensor_set_exp_parm, + .sensor_get_fps = ov9286_sensor_get_fps, + .sensor_set_fps = ov9286_sensor_set_fps, + .sensor_get_isp_status = ov9286_sensor_get_isp_status, + .sensor_set_blc = ov9286_sensor_set_blc, + .sensor_set_wb = ov9286_sensor_set_wb, + .sensor_get_tpg = ov9286_sensor_get_tpg, + .sensor_set_tpg = ov9286_sensor_set_tpg, + .sensor_get_expand_curve = ov9286_sensor_get_expand_curve, + .sensor_get_otp_data = ov9286_sensor_get_otp_data, + .sensor_set_otp_data = ov9286_sensor_set_otp_data, + .sensor_mirror_set = ov9286_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov9732_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov9732_drv.c new file mode 100755 index 0000000..5a2ccd8 --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/ov9732_drv.c @@ -0,0 +1,1134 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" + +//#include +#include "io.h" +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#define pr_info(...) //rt_kprintf(__VA_ARGS__) +#define pr_debug(...) //rt_kprintf(__VA_ARGS__) +#define pr_warn(...) //rt_kprintf(__VA_ARGS__) +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define OV9732_REG_CHIP_ID_H 0x300a +#define OV9732_REG_CHIP_ID_L 0x300b + +#define OV9732_REG_LONG_EXP_TIME_H 0x3501 +#define OV9732_REG_LONG_EXP_TIME_L 0x3502 + +#define OV9732_REG_LONG_AGAIN_H 0x350a +#define OV9732_REG_LONG_AGAIN_L 0x350b + +#define OV9732_MIN_GAIN_STEP (1.0f/16.0f) + +#define DELAY_MS_SENSOR_DEFAULT 1 + +static const k_sensor_reg ov9732_mipi2lane_1080p_30fps_linear[] = { + {REG_NULL, 0x00}, +}; + +static const k_sensor_reg ov9732_mipi2lane_1080p_30fps_hdr[] = { + {REG_NULL, 0x00}, +}; + + +static const k_sensor_reg ov9732_mipi2lane_720p_30fps_linear[] = { + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3007, 0x1f}, + {0x3008, 0xff}, + {0x3009, 0x02}, + {0x3010, 0x00}, + {0x3011, 0x08}, + {0x3014, 0x22}, + {0x301e, 0x15}, + {0x3030, 0x19}, + {0x3080, 0x02}, + {0x3081, 0x3c}, + {0x3082, 0x04}, + {0x3083, 0x00}, + {0x3084, 0x02}, + {0x3085, 0x01}, + {0x3086, 0x01}, + {0x3089, 0x01}, + {0x308a, 0x00}, + {0x3103, 0x01}, + {0x3600, 0xf6}, + {0x3601, 0x72}, + {0x3605, 0x66}, + {0x3610, 0x0c}, + {0x3611, 0x60}, + {0x3612, 0x35}, + {0x3654, 0x10}, + {0x3655, 0x77}, + {0x3656, 0x77}, + {0x3657, 0x07}, + {0x3658, 0x22}, + {0x3659, 0x22}, + {0x365a, 0x02}, + {0x3700, 0x1f}, + {0x3701, 0x10}, + {0x3702, 0x0c}, + {0x3703, 0x0b}, + {0x3704, 0x3c}, + {0x3705, 0x51}, + {0x370d, 0x20}, + {0x3710, 0x0d}, + {0x3782, 0x58}, + {0x3783, 0x60}, + {0x3784, 0x05}, + {0x3785, 0x55}, + {0x37c0, 0x07}, + {0x3800, 0x00}, + {0x3801, 0x04}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3804, 0x05}, + {0x3805, 0x0b}, + {0x3806, 0x02}, + {0x3807, 0xdb}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x02}, + {0x380b, 0xd0}, + {0x380c, 0x05}, //HTS = 1467 + {0x380d, 0xbb}, + {0x380e, 0x03}, //VTS = 818 + {0x380f, 0x32}, + {0x3810, 0x00}, + {0x3811, 0x04}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x3816, 0x00}, + {0x3817, 0x00}, + {0x3818, 0x00}, + {0x3819, 0x04}, + {0x3820, 0x10}, + {0x3821, 0x00}, + {0x382c, 0x06}, + {0x3500, 0x00}, + {0x3501, 0x0c}, //ET = 204 ET line + {0x3502, 0xc0}, + {0x3503, 0x03}, //sensor gain delay 1 frame, 0x23/0x27 + {0x3504, 0x00}, //sensor SNR gain, 1x + {0x3505, 0x00}, + {0x3509, 0x10}, + {0x350a, 0x00}, + {0x350b, 0x10}, //sensor analog gain, 1x + {0x3d00, 0x00}, + {0x3d01, 0x00}, + {0x3d02, 0x00}, + {0x3d03, 0x00}, + {0x3d04, 0x00}, + {0x3d05, 0x00}, + {0x3d06, 0x00}, + {0x3d07, 0x00}, + {0x3d08, 0x00}, + {0x3d09, 0x00}, + {0x3d0a, 0x00}, + {0x3d0b, 0x00}, + {0x3d0c, 0x00}, + {0x3d0d, 0x00}, + {0x3d0e, 0x00}, + {0x3d0f, 0x00}, + {0x3d80, 0x00}, + {0x3d81, 0x00}, + {0x3d82, 0x38}, + {0x3d83, 0xa4}, + {0x3d84, 0x00}, + {0x3d85, 0x00}, + {0x3d86, 0x1f}, + {0x3d87, 0x03}, + {0x3d8b, 0x00}, + {0x3d8f, 0x00}, + {0x4001, 0xe0}, //black level auto mode + {0x4004, 0x00}, + {0x4005, 0x02}, + {0x4006, 0x01}, + {0x4007, 0x40}, + {0x4009, 0x0b}, + {0x4300, 0x03}, + {0x4301, 0xff}, + {0x4304, 0x00}, + {0x4305, 0x00}, + {0x4309, 0x00}, + {0x4600, 0x00}, + {0x4601, 0x04}, + {0x4800, 0x00}, + {0x4805, 0x00}, + {0x4821, 0x50}, + {0x4823, 0x50}, + {0x4837, 0x2d}, + {0x4a00, 0x00}, + {0x4f00, 0x80}, + {0x4f01, 0x10}, + {0x4f02, 0x00}, + {0x4f03, 0x00}, + {0x4f04, 0x00}, + {0x4f05, 0x00}, + {0x4f06, 0x00}, + {0x4f07, 0x00}, + {0x4f08, 0x00}, + {0x4f09, 0x00}, + {0x5000, 0x07}, //black level enable + {0x500c, 0x00}, + {0x500d, 0x00}, + {0x500e, 0x00}, + {0x500f, 0x00}, + {0x5010, 0x00}, + {0x5011, 0x00}, + {0x5012, 0x00}, + {0x5013, 0x00}, + {0x5014, 0x00}, + {0x5015, 0x00}, + {0x5016, 0x00}, + {0x5017, 0x00}, + {0x5080, 0x00}, + {0x5708, 0x06}, + {0x5781, 0x0e}, //dpc enable + {0x5783, 0x0f}, + {0x3603, 0x70}, + {0x3620, 0x1e}, + {0x400a, 0x01}, + {0x400b, 0xc0}, + //{0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + + +static const k_sensor_reg ov9732_mipi2lane_720p_30fps_mclk_16m_linear[] = { + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3007, 0x1f}, + {0x3008, 0xff}, + {0x3009, 0x02}, + {0x3010, 0x00}, + {0x3011, 0x08}, + {0x3014, 0x22}, + {0x301e, 0x15}, + {0x3030, 0x19}, + {0x3080, 0x02}, + // {0x3081, 0x3c}, + {0x3081, 0x5A}, + {0x3082, 0x04}, + {0x3083, 0x00}, + {0x3084, 0x02}, + {0x3085, 0x01}, + {0x3086, 0x01}, + {0x3089, 0x01}, + {0x308a, 0x00}, + {0x3103, 0x01}, + {0x3600, 0xf6}, + {0x3601, 0x72}, + {0x3605, 0x66}, + {0x3610, 0x0c}, + {0x3611, 0x60}, + {0x3612, 0x35}, + {0x3654, 0x10}, + {0x3655, 0x77}, + {0x3656, 0x77}, + {0x3657, 0x07}, + {0x3658, 0x22}, + {0x3659, 0x22}, + {0x365a, 0x02}, + {0x3700, 0x1f}, + {0x3701, 0x10}, + {0x3702, 0x0c}, + {0x3703, 0x0b}, + {0x3704, 0x3c}, + {0x3705, 0x51}, + {0x370d, 0x20}, + {0x3710, 0x0d}, + {0x3782, 0x58}, + {0x3783, 0x60}, + {0x3784, 0x05}, + {0x3785, 0x55}, + {0x37c0, 0x07}, + {0x3800, 0x00}, + {0x3801, 0x04}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3804, 0x05}, + {0x3805, 0x0b}, + {0x3806, 0x02}, + {0x3807, 0xdb}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x02}, + {0x380b, 0xd0}, + {0x380c, 0x05}, //HTS = 1467 + {0x380d, 0xbb}, + {0x380e, 0x03}, //VTS = 818 + {0x380f, 0x32}, + {0x3810, 0x00}, + {0x3811, 0x04}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x3816, 0x00}, + {0x3817, 0x00}, + {0x3818, 0x00}, + {0x3819, 0x04}, + {0x3820, 0x10}, + {0x3821, 0x00}, + {0x382c, 0x06}, + {0x3500, 0x00}, + {0x3501, 0x0c}, //ET = 204 ET line + {0x3502, 0xc0}, + {0x3503, 0x03}, //sensor gain delay 1 frame, 0x23/0x27 + {0x3504, 0x00}, //sensor SNR gain, 1x + {0x3505, 0x00}, + {0x3509, 0x10}, + {0x350a, 0x00}, + {0x350b, 0x10}, //sensor analog gain, 1x + {0x3d00, 0x00}, + {0x3d01, 0x00}, + {0x3d02, 0x00}, + {0x3d03, 0x00}, + {0x3d04, 0x00}, + {0x3d05, 0x00}, + {0x3d06, 0x00}, + {0x3d07, 0x00}, + {0x3d08, 0x00}, + {0x3d09, 0x00}, + {0x3d0a, 0x00}, + {0x3d0b, 0x00}, + {0x3d0c, 0x00}, + {0x3d0d, 0x00}, + {0x3d0e, 0x00}, + {0x3d0f, 0x00}, + {0x3d80, 0x00}, + {0x3d81, 0x00}, + {0x3d82, 0x38}, + {0x3d83, 0xa4}, + {0x3d84, 0x00}, + {0x3d85, 0x00}, + {0x3d86, 0x1f}, + {0x3d87, 0x03}, + {0x3d8b, 0x00}, + {0x3d8f, 0x00}, + {0x4001, 0xe0}, //black level auto mode + {0x4004, 0x00}, + {0x4005, 0x02}, + {0x4006, 0x01}, + {0x4007, 0x40}, + {0x4009, 0x0b}, + {0x4300, 0x03}, + {0x4301, 0xff}, + {0x4304, 0x00}, + {0x4305, 0x00}, + {0x4309, 0x00}, + {0x4600, 0x00}, + {0x4601, 0x04}, + {0x4800, 0x00}, + {0x4805, 0x00}, + {0x4821, 0x50}, + {0x4823, 0x50}, + {0x4837, 0x2d}, + {0x4a00, 0x00}, + {0x4f00, 0x80}, + {0x4f01, 0x10}, + {0x4f02, 0x00}, + {0x4f03, 0x00}, + {0x4f04, 0x00}, + {0x4f05, 0x00}, + {0x4f06, 0x00}, + {0x4f07, 0x00}, + {0x4f08, 0x00}, + {0x4f09, 0x00}, + {0x5000, 0x07}, //black level enable + {0x500c, 0x00}, + {0x500d, 0x00}, + {0x500e, 0x00}, + {0x500f, 0x00}, + {0x5010, 0x00}, + {0x5011, 0x00}, + {0x5012, 0x00}, + {0x5013, 0x00}, + {0x5014, 0x00}, + {0x5015, 0x00}, + {0x5016, 0x00}, + {0x5017, 0x00}, + {0x5080, 0x00}, + {0x5708, 0x06}, + {0x5781, 0x0e}, //dpc enable + {0x5783, 0x0f}, + {0x3603, 0x70}, + {0x3620, 0x1e}, + {0x400a, 0x01}, + {0x400b, 0xc0}, + //{0x0100, 0x01}, + {REG_NULL, 0x00}, +}; + +static k_sensor_mode ov9732_mode_info[] = { + { + .index = 0, + .sensor_type = OV_OV9732_MIPI_1280X720_30FPS_10BIT_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9732_mipi2lane_720p_30fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 1, + .sensor_type = OV_OV9732_MIPI_1280X720_30FPS_10BIT_MCLK_16M_LINEAR, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9732_mipi2lane_720p_30fps_mclk_16m_linear, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK1, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 25, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, + { + .index = 2, + .sensor_type = OV_OV9732_MIPI_1280X720_30FPS_10BIT_MCLK_16M_LINEAR_V2, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = ov9732_mipi2lane_720p_30fps_mclk_16m_linear, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK1, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 25, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, +}; + +static k_sensor_mode *current_mode = NULL; + +static int ov9732_power_rest(k_s32 on) +{ + // #define OV9732_RST_PIN (24)// (28) + + // rst + kd_pin_mode(OV9732_RST_PIN, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(OV9732_RST_PIN, GPIO_PV_HIGH); //GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(DELAY_MS_SENSOR_DEFAULT); + kd_pin_write(OV9732_RST_PIN, GPIO_PV_LOW); //GPIO_PV_LOW GPIO_PV_LOW + rt_thread_mdelay(DELAY_MS_SENSOR_DEFAULT); + kd_pin_write(OV9732_RST_PIN, GPIO_PV_HIGH); //GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(OV9732_RST_PIN, GPIO_PV_LOW); //GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(DELAY_MS_SENSOR_DEFAULT); + + return 0; +} + +static int ov9732_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + +static k_s32 ov9732_sensor_get_chip_id(void *ctx, k_u32 *chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter\n", __func__); + + ov9732_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, OV9732_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, OV9732_REG_CHIP_ID_L, &id_low); + if (ret) { + // rt_kprintf("%s error\n", __func__);; + return -1; + } + + *chip_id = (id_high << 8) | id_low; + pr_info("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + + +static k_s32 ov9732_sensor_power_on(void *ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + ov9732_power_rest(on); + ov9732_i2c_init(&dev->i2c_info); + ret = ov9732_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + ov9732_power_rest(on); + } + + return ret; +} + +static k_s32 ov9732_sensor_init(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(ov9732_mode_info) / sizeof(k_sensor_mode); i++) { + if (ov9732_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(ov9732_mode_info[i]); + dev->sensor_mode = &(ov9732_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + case 0: + case 1: + case 2: + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + +/////////////////// + current_mode->ae_info.frame_length = 818; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.00004075;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 63.9375; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + //current_mode->ae_info.ae_min_interval_frame = 2.5; + current_mode->ae_info.color_type = SENSOR_COLOR_IR; //color sensor without IR filter + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = OV9732_MIN_GAIN_STEP; + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_long_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 1; + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + //current_mode->ae_info.max_vvs_integraion_line = current_mode->ae_info.frame_length; + //current_mode->ae_info.min_vvs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + //current_mode->ae_info.max_vvs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vvs_integraion_line; + + //current_mode->ae_info.min_vvs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vvs_integraion_line; + + +///// + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + //current_mode->ae_info.cur_vvs_integration_time = 0.0; + +///// + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + //current_mode->ae_info.cur_vvs_again = 0.0; + //current_mode->ae_info.cur_vvs_dgain = 0.0; +///// + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 63.9375; + current_mode->ae_info.a_long_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 63.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 63.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f); + + //current_mode->ae_info.a_vvs_gain.max = 1.0; + //current_mode->ae_info.a_vvs_gain.min = 63.9375; + //current_mode->ae_info.a_vvs_gain.step = (1.0f/16.0f);// +///// + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f); + + //current_mode->ae_info.d_vvs_gain.max = 1.0;// + //current_mode->ae_info.d_vvs_gain.min = 1.0;// + //current_mode->ae_info.d_vvs_gain.step = (1.0f/1024.0f);// + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + default: + break; + } + + k_u16 again_h, again_l; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + float again = 0, dgain = 0; + + ret = sensor_reg_read(&dev->i2c_info, OV9732_REG_LONG_AGAIN_H, &again_h); + ret = sensor_reg_read(&dev->i2c_info, OV9732_REG_LONG_AGAIN_L, &again_l); + again = (float)(((again_h & 0x03) << 8) | again_l) / 16.0f; + + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + ret = sensor_reg_read(&dev->i2c_info, OV9732_REG_LONG_EXP_TIME_H, &exp_time_h); + ret = sensor_reg_read(&dev->i2c_info, OV9732_REG_LONG_EXP_TIME_L, &exp_time_l); + exp_time = (exp_time_h << 4) | ((exp_time_l >> 4) & 0x0F); + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + + return ret; +} + +k_s32 ov9732_sensor_get_mode(void *ctx, k_sensor_mode *mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(ov9732_mode_info) / sizeof(k_sensor_mode); i++) { + if (ov9732_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &ov9732_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(ov9732_mode_info[i]); + return 0; + } + } + pr_err("%s, the mode not exit.\n", __func__); + + return ret; +} + +k_s32 ov9732_sensor_set_mode(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9732_sensor_enum_mode(void *ctx, k_sensor_enum_mode *enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + if (enum_mode->index >= (sizeof(ov9732_mode_info) / sizeof(ov9732_mode_info[0]))) { + pr_err("%s, invalid mode index.\n", __func__); + return -1; + } + + for (k_s32 i = 0; i < sizeof(ov9732_mode_info) / sizeof(k_sensor_mode); i++) { + if (ov9732_mode_info[i].index == enum_mode->index) { + memcpy(&enum_mode->mode, &ov9732_mode_info[i], sizeof(k_sensor_mode)); + return 0; + } + } + return ret; +} + +k_s32 ov9732_sensor_get_caps(void *ctx, k_sensor_caps *caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +k_s32 ov9732_sensor_conn_check(void *ctx, k_s32 *conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +k_s32 ov9732_sensor_set_stream(void *ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +k_s32 ov9732_sensor_get_again(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 ov9732_sensor_set_again(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 again; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 16 + 0.5); + if(current_mode->sensor_again !=again) + { + ret = sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + ret |= sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/16.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 16 + 0.5); + ret = sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + ret |= sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_again = (float)again/16.0f; + + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 16 + 0.5); + //TODO + current_mode->ae_info.cur_vs_again = (float)again/16.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again*1000) ); + + return ret; +} + +k_s32 ov9732_sensor_get_dgain(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 ov9732_sensor_set_dgain(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + //TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = (float)dgain/1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain*10000)); + + return ret; +} + + +k_s32 ov9732_sensor_get_intg_time(void *ctx, k_sensor_intg_time *time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 ov9732_sensor_set_intg_time(void *ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + float integraion_time = 0; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + if (current_mode->et_line != exp_line) + { + ret |= sensor_reg_write(&dev->i2c_info, 0x3501, ( exp_line >> 4) & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, 0x3502, ( exp_line << 4) & 0xff); + current_mode->et_line = exp_line; + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n",\ + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +k_s32 ov9732_sensor_get_exp_parm(void *ctx, k_sensor_exposure_param *exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +k_s32 ov9732_sensor_set_exp_parm(void *ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9732_sensor_get_fps(void *ctx, k_u32 *fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = 30000; + + return ret; +} + +k_s32 ov9732_sensor_set_fps(void *ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9732_sensor_get_isp_status(void *ctx, k_sensor_isp_status *staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +k_s32 ov9732_sensor_set_blc(void *ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9732_sensor_set_wb(void *ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9732_sensor_get_tpg(void *ctx, k_sensor_test_pattern *tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +k_s32 ov9732_sensor_set_tpg(void *ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 ov9732_sensor_get_expand_curve(void *ctx, k_sensor_compand_curve *curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +k_s32 ov9732_sensor_get_otp_data(void *ctx, void *data) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(data, 0, sizeof(void *)); + + return ret; +} + +static k_s32 ov9732_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev ov9732_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c1", + .slave_addr = 0x36, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "ov9732", + .sensor_func = { + .sensor_power = ov9732_sensor_power_on, + .sensor_init = ov9732_sensor_init, + .sensor_get_chip_id = ov9732_sensor_get_chip_id, + .sensor_get_mode = ov9732_sensor_get_mode, + .sensor_set_mode = ov9732_sensor_set_mode, + .sensor_enum_mode = ov9732_sensor_enum_mode, + .sensor_get_caps = ov9732_sensor_get_caps, + .sensor_conn_check = ov9732_sensor_conn_check, + .sensor_set_stream = ov9732_sensor_set_stream, + .sensor_get_again = ov9732_sensor_get_again, + .sensor_set_again = ov9732_sensor_set_again, + .sensor_get_dgain = ov9732_sensor_get_dgain, + .sensor_set_dgain = ov9732_sensor_set_dgain, + .sensor_get_intg_time = ov9732_sensor_get_intg_time, + .sensor_set_intg_time = ov9732_sensor_set_intg_time, + .sensor_get_exp_parm = ov9732_sensor_get_exp_parm, + .sensor_set_exp_parm = ov9732_sensor_set_exp_parm, + .sensor_get_fps = ov9732_sensor_get_fps, + .sensor_set_fps = ov9732_sensor_set_fps, + .sensor_get_isp_status = ov9732_sensor_get_isp_status, + .sensor_set_blc = ov9732_sensor_set_blc, + .sensor_set_wb = ov9732_sensor_set_wb, + .sensor_get_tpg = ov9732_sensor_get_tpg, + .sensor_set_tpg = ov9732_sensor_set_tpg, + .sensor_get_expand_curve = ov9732_sensor_get_expand_curve, + .sensor_get_otp_data = ov9732_sensor_get_otp_data, + .sensor_mirror_set = ov9732_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sc035hgs_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sc035hgs_drv.c new file mode 100755 index 0000000..779ee53 --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sc035hgs_drv.c @@ -0,0 +1,1075 @@ + +#include "sensor_dev.h" +#include "io.h" +#include +#include "drv_gpio.h" + +#define pr_info(...) /*rt_kprintf(__VA_ARGS__)*/ +#define pr_debug(...) /*rt_kprintf(__VA_ARGS__)*/ +#define pr_warn(...) /*rt_kprintf(__VA_ARGS__)*/ +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define CHIP_ID 0x310b +#define SC035HGS_REG_CHIP_ID_H 0x3107 +#define SC035HGS_REG_CHIP_ID_L 0x3108 + +#define SC035HGS_LANES 1 +#define SC035HGS_BITS_PER_SAMPLE 10 +#define SC035HGS_LINK_FREQ_270MHZ 270000000 +#define SC035HGS_PIXEL_RATE \ + (SC035HGS_LINK_FREQ_270MHZ * 2 * SC035HGS_LANES / SC035HGS_BITS_PER_SAMPLE) +#define SC035HGS_XVCLK_FREQ 24000000 + +#define SC035HGS_REG_CTRL_MODE 0x0100 +#define SC035HGS_MODE_SW_STANDBY 0x0 +#define SC035HGS_MODE_STREAMING BIT(0) + +#define SC035HGS_REG_EXPOSURE 0x3e01 +#define SC035HGS_EXPOSURE_MIN 6 +#define SC035HGS_EXPOSURE_STEP 1 +#define SC035HGS_REG_VTS 0x320e +#define SC035HGS_REG_HTS 0x320f +#define SC035HGS_VTS_MAX 0xffff + +#define SC035HGS_REG_COARSE_DGAIN 0x3e06 +#define SC035HGS_REG_FINE_DGAIN 0x3e07 +#define SC035HGS_REG_COARSE_AGAIN 0x3e08 +#define SC035HGS_REG_FINE_AGAIN 0x3e09 +#define ANALOG_GAIN_MIN 0x10 +#define ANALOG_GAIN_MAX 0x7c0 +#define ANALOG_GAIN_STEP 1 +#define ANALOG_GAIN_DEFAULT 0x10 + +#define SC035HGS_REG_TEST_PATTERN 0x4501 +#define SC035HGS_TEST_PATTERN_ENABLE 0xcc +#define SC035HGS_TEST_PATTERN_DISABLE 0xc4 + +#define SC035HGS_REG_FLIP_MIRROR 0x3221 +#define SC035HGS_MIRROR_MASK 0x06 +#define SC035HGS_FLIP_MASK 0x60 + +#define SC035HGS_GROUP_HOLD 0x3812 +#define SC035HGS_GROUP_HOLD_START 0X00 +#define SC035HGS_GROUP_HOLD_LUNCH 0x30 + +#define SC035HGS_REG_VALUE_08BIT 1 +#define SC035HGS_REG_VALUE_16BIT 2 +#define SC035HGS_REG_VALUE_24BIT 3 + +#define SC035HGS_NAME "sc035hgs" +#if 0 +static k_sensor_reg sc035hgs_mipi_1lane_raw10_640x480_120fps_regs[] = { + { 0x0103, 0x01 }, + { 0x0100, 0x00 }, + { 0x36e9, 0x80 }, + { 0x36f9, 0x80 }, + { 0x3000, 0x00 }, + { 0x3001, 0x00 }, + { 0x300f, 0x0f }, + { 0x3018, 0x13 }, + { 0x3019, 0xfc }, + { 0x301c, 0x78 }, + { 0x301f, 0x87 }, + { 0x3031, 0x0a }, + { 0x3037, 0x20 }, + { 0x303f, 0x01 }, + { 0x320c, 0x03 }, // Line Length + { 0x320d, 0x54 }, + { 0x320e, 0x04 }, // Frame Length + { 0x320f, 0x20 }, + { 0x3217, 0x00 }, + { 0x3218, 0x00 }, + { 0x3220, 0x10 }, + { 0x3223, 0x48 }, + { 0x3226, 0x74 }, + { 0x3227, 0x07 }, + { 0x323b, 0x00 }, + { 0x3250, 0xf0 }, + { 0x3251, 0x02 }, + { 0x3252, 0x02 }, + { 0x3253, 0x08 }, + { 0x3254, 0x02 }, + { 0x3255, 0x07 }, + { 0x3304, 0x48 }, + { 0x3305, 0x00 }, + { 0x3306, 0x60 }, + { 0x3309, 0x50 }, + { 0x330a, 0x00 }, + { 0x330b, 0xc0 }, + { 0x330c, 0x18 }, + { 0x330f, 0x40 }, + { 0x3310, 0x10 }, + { 0x3314, 0x1e }, + { 0x3315, 0x30 }, + { 0x3316, 0x68 }, + { 0x3317, 0x1b }, + { 0x3329, 0x5c }, + { 0x332d, 0x5c }, + { 0x332f, 0x60 }, + { 0x3335, 0x64 }, + { 0x3344, 0x64 }, + { 0x335b, 0x80 }, + { 0x335f, 0x80 }, + { 0x3366, 0x06 }, + { 0x3385, 0x31 }, + { 0x3387, 0x39 }, + { 0x3389, 0x01 }, + { 0x33b1, 0x03 }, + { 0x33b2, 0x06 }, + { 0x33bd, 0xe0 }, + { 0x33bf, 0x10 }, + { 0x3621, 0xa4 }, + { 0x3622, 0x05 }, + { 0x3624, 0x47 }, + { 0x3630, 0x4a }, + { 0x3631, 0x58 }, + { 0x3633, 0x52 }, + { 0x3635, 0x03 }, + { 0x3636, 0x25 }, + { 0x3637, 0x8a }, + { 0x3638, 0x0f }, + { 0x3639, 0x08 }, + { 0x363a, 0x00 }, + { 0x363b, 0x48 }, + { 0x363c, 0x86 }, + { 0x363d, 0x10 }, + { 0x363e, 0xf8 }, + { 0x3640, 0x00 }, + { 0x3641, 0x01 }, + { 0x36ea, 0x37 }, + { 0x36eb, 0x0e }, + { 0x36ec, 0x0e }, + { 0x36ed, 0x23 }, + { 0x36fa, 0x37 }, + { 0x36fb, 0x00 }, + { 0x36fc, 0x02 }, + { 0x36fd, 0x03 }, + { 0x3908, 0x91 }, + { 0x391b, 0x81 }, + { 0x3d08, 0x01 }, + { 0x3e01, 0x14 }, // ET[7:0] + { 0x3e02, 0x80 }, // ET[7:4] + { 0x3e03, 0x2b }, + { 0x3e06, 0x0c }, + { 0x3e08, 0x00 }, // Coarse gain[4:2] + { 0x3e09, 0x10 }, // Fine gain [7:0] + { 0x3f04, 0x03 }, + { 0x3f05, 0x34 }, + { 0x4500, 0x59 }, + { 0x4501, 0xc4 }, + { 0x4603, 0x00 }, + { 0x4800, 0x64 }, + { 0x4809, 0x01 }, + { 0x4810, 0x00 }, + { 0x4811, 0x01 }, + { 0x4837, 0x13 }, + { 0x5011, 0x00 }, + { 0x5988, 0x02 }, + { 0x598e, 0x03 }, + { 0x598f, 0x10 }, + { 0x36e9, 0x24 }, + { 0x36f9, 0x20 }, + { REG_NULL, 0x00 } +}; +#else +static k_sensor_reg sc035hgs_mipi_1lane_raw10_640x480_120fps_regs[] = +{ + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x36e9, 0x80}, + {0x36f9, 0x80}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x300f, 0x0f}, + {0x3018, 0x13}, + {0x3019, 0xfc}, + {0x301c, 0x78}, + {0x301f, 0x87}, + {0x3031, 0x0a}, + {0x3037, 0x20}, + {0x303f, 0x01}, + {0x320c, 0x03}, //Line Length + {0x320d, 0x54}, + {0x320e, 0x04}, //Frame Length + {0x320f, 0x20}, + {0x3217, 0x00}, + {0x3218, 0x00}, + {0x3220, 0x10}, + {0x3223, 0x48}, + {0x3226, 0x74}, + {0x3227, 0x07}, + {0x323b, 0x00}, + {0x3250, 0xf0}, + {0x3251, 0x02}, + {0x3252, 0x02}, + {0x3253, 0x08}, + {0x3254, 0x02}, + {0x3255, 0x07}, + {0x3304, 0x48}, + {0x3305, 0x00}, + {0x3306, 0x60}, + {0x3309, 0x50}, + {0x330a, 0x00}, + {0x330b, 0xc0}, + {0x330c, 0x18}, + {0x330f, 0x40}, + {0x3310, 0x10}, + {0x3314, 0x1e}, + {0x3315, 0x30}, + {0x3316, 0x68}, + {0x3317, 0x1b}, + {0x3329, 0x5c}, + {0x332d, 0x5c}, + {0x332f, 0x60}, + {0x3335, 0x64}, + {0x3344, 0x64}, + {0x335b, 0x80}, + {0x335f, 0x80}, + {0x3366, 0x06}, + {0x3385, 0x31}, + {0x3387, 0x39}, + {0x3389, 0x01}, + {0x33b1, 0x03}, + {0x33b2, 0x06}, + {0x33bd, 0xe0}, + {0x33bf, 0x10}, + {0x3621, 0xa4}, + {0x3622, 0x05}, + {0x3624, 0x47}, + {0x3630, 0x4a}, + {0x3631, 0x58}, + {0x3633, 0x52}, + {0x3635, 0x03}, + {0x3636, 0x25}, + {0x3637, 0x8a}, + {0x3638, 0x0f}, + {0x3639, 0x08}, + {0x363a, 0x00}, + {0x363b, 0x48}, + {0x363c, 0x86}, + {0x363d, 0x10}, + {0x363e, 0xf8}, + {0x3640, 0x00}, + {0x3641, 0x01}, + {0x36ea, 0x37}, + {0x36eb, 0x0e}, + {0x36ec, 0x0e}, + {0x36ed, 0x23}, + {0x36fa, 0x37}, + {0x36fb, 0x00}, + {0x36fc, 0x02}, + {0x36fd, 0x03}, + {0x3908, 0x91}, + {0x391b, 0x81}, + {0x3d08, 0x01}, + {0x3e01, 0x14},//ET[7:0] + {0x3e02, 0x80},//ET[7:4] + {0x3e03, 0x2b}, + {0x3e06, 0x0c}, + {0x3e08, 0x00},//Coarse gain[4:2] + {0x3e09, 0x10},//Fine gain [7:0] + {0x3f04, 0x03}, + {0x3f05, 0x34}, + {0x4500, 0x59}, + {0x4501, 0xc4}, + {0x4603, 0x00}, + {0x4800, 0x64}, + {0x4809, 0x01}, + {0x4810, 0x00}, + {0x4811, 0x01}, + {0x4837, 0x13}, + {0x5011, 0x00}, + {0x5988, 0x02}, + {0x598e, 0x03}, + {0x598f, 0x10}, + {0x36e9, 0x24}, + {0x36f9, 0x20}, + {0x320e, 0x04}, + {0x320f, 0x20}, + // {0x0100, 0x01}, + {0x4418, 0x0a}, + {0x4419, 0x80}, +}; +#endif +static const k_sensor_reg sc035hgs_mipi_1lane_raw10_640x480_60fps_regs[] = { + { 0x320c, 0x03 }, // Line Length + { 0x320d, 0x54 }, + { 0x320e, 0x08 }, // Frame Length + { 0x320f, 0x40 }, + { REG_NULL, 0x00 } +}; + +static const k_sensor_reg sc035hgs_mipi_1lane_raw10_640x480_30fps_regs[] = { + { 0x320c, 0x03 }, // Line Length + { 0x320d, 0x54 }, + { 0x320e, 0x10 }, // Frame Length + { 0x320f, 0x80 }, + { REG_NULL, 0x00 } +}; + +static k_sensor_clk_info sc035hgs_clk_info[] = { + { + .mclk = 24000000, + .pclk = 108000000, + }, +}; + +// static k_sensor_mipi_info sc035hgs_mipi_info[] = { +// { +// .csi_id = 2, +// .mipi_lanes = 1, +// .data_type = 0x2B, //RAW10 +// }, +// }; + +static k_sensor_mode sc035hgs_mode_info[] = { + { + .index = 0, + .sensor_type = SC_SC035HGS_MIPI_1LANE_RAW10_640X480_120FPS_LINEAR, + .size = { + .bounds_width = 640, + .bounds_height = 480, + .top = 0, + .left = 0, + .width = 640, + .height = 480, + }, + .hdr_mode = SENSOR_MODE_LINEAR, + .bayer_pattern = BAYER_PAT_BGGR, + .bit_width = 10, + .fps = 120000, + .clk_info = sc035hgs_clk_info, + .mipi_info = { + .csi_id = 2, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = sc035hgs_mipi_1lane_raw10_640x480_120fps_regs, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 1, + .sensor_type = SC_SC035HGS_MIPI_1LANE_RAW10_640X480_60FPS_LINEAR, + .size = { + .bounds_width = 640, + .bounds_height = 480, + .top = 0, + .left = 0, + .width = 640, + .height = 480, + }, + .hdr_mode = SENSOR_MODE_LINEAR, + .bayer_pattern = BAYER_PAT_BGGR, + .bit_width = 10, + .fps = 60000, + .clk_info = sc035hgs_clk_info, + .mipi_info = { + .csi_id = 2, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = sc035hgs_mipi_1lane_raw10_640x480_60fps_regs, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, + { + .index = 2, + .sensor_type = SC_SC035HGS_MIPI_1LANE_RAW10_640X480_30FPS_LINEAR, + .size = { + .bounds_width = 640, + .bounds_height = 480, + .top = 0, + .left = 0, + .width = 640, + .height = 480, + }, + .hdr_mode = SENSOR_MODE_LINEAR, + .bayer_pattern = BAYER_PAT_BGGR, + .bit_width = 10, + .fps = 30000, + .clk_info = sc035hgs_clk_info, + .mipi_info = { + .csi_id = 2, + .mipi_lanes = 1, + .data_type = 0x2B, //RAW10 + }, + .reg_list = sc035hgs_mipi_1lane_raw10_640x480_30fps_regs, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, +}; + +static k_sensor_mode* current_mode = NULL; + +static int sc035hgs_power_reset(k_s32 on) +{ + #define SC035HGS_RST_PIN (43) + + kd_pin_mode(SC035HGS_RST_PIN, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(SC035HGS_RST_PIN, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(1); + kd_pin_write(SC035HGS_RST_PIN, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(1); + kd_pin_write(SC035HGS_RST_PIN, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(SC035HGS_RST_PIN, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + +static int sc035hgs_i2c_init(k_sensor_i2c_info* i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + return 0; +} + +static k_s32 sc035hgs_sensor_get_chip_id(void* ctx, k_u32* chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev* dev = ctx; + pr_info("%s enter\n", __func__); + + sc035hgs_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, SC035HGS_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, SC035HGS_REG_CHIP_ID_L, &id_low); + if (ret) { + // rt_kprintf("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + pr_info("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + +static k_s32 sc035hgs_sensor_power_on(void* ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev* dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + sc035hgs_power_reset(on); + sc035hgs_i2c_init(&dev->i2c_info); + ret = sc035hgs_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + sc035hgs_power_reset(on); + } + + return ret; +} + +static k_s32 sc035hgs_sensor_init(void* ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + k_u16 reg_msb = 0; + k_u16 reg_lsb = 0; + struct sensor_driver_dev* dev = ctx; + void *vi_addr = rt_ioremap((void *)0x90009000, 0x10000); + + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(sc035hgs_mode_info) / sizeof(k_sensor_mode); i++) { + if (sc035hgs_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(sc035hgs_mode_info[i]); + dev->sensor_mode = &(sc035hgs_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + rt_kprintf("%s enter, sensor mode %d -- max fps :%d\n", __func__, mode.index, mode.fps); + ret = sensor_reg_list_write(&dev->i2c_info, sc035hgs_mipi_1lane_raw10_640x480_120fps_regs); + +#define VI_CSI2_DIS_FRAME_M (0x8C) +#define VI_CSI2_DIS_FRAME_N (0x90) +#define VI_DIS_FRAME_EN (0x94) + + switch (current_mode->index) { + case 0: + /* todo fix, sc035hgs 120fps to 30fps */ + writel(1, vi_addr + VI_CSI2_DIS_FRAME_M); + writel(3, vi_addr + VI_CSI2_DIS_FRAME_N); + writel(4, vi_addr + VI_DIS_FRAME_EN); + break; + + case 1: + ret = sensor_reg_list_write(&dev->i2c_info, sc035hgs_mipi_1lane_raw10_640x480_60fps_regs); + /* todo fix, sc035hgs 60fps to 60fps */ + writel(1, vi_addr + VI_CSI2_DIS_FRAME_M); + writel(1, vi_addr + VI_CSI2_DIS_FRAME_N); + writel(4, vi_addr + VI_DIS_FRAME_EN); + + break; + + case 2: + ret = sensor_reg_list_write(&dev->i2c_info, sc035hgs_mipi_1lane_raw10_640x480_30fps_regs); + break; + + default: + return -1; + } + + + switch (current_mode->index) { + case 0: + + case 1: + + case 2: + + ret = sensor_reg_read(&dev->i2c_info, SC035HGS_REG_VTS, ®_msb); + ret = sensor_reg_read(&dev->i2c_info, SC035HGS_REG_VTS, ®_lsb); + current_mode->ae_info.frame_length = reg_msb << 8 | reg_lsb; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + + //exp + ret = sensor_reg_read(&dev->i2c_info, SC035HGS_REG_HTS, ®_msb); + ret = sensor_reg_read(&dev->i2c_info, SC035HGS_REG_HTS, ®_lsb); + current_mode->ae_info.one_line_exp_time = (reg_msb << 8 | reg_lsb) * 1000.0f / current_mode->clk_info->pclk ; // ms + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 6; + current_mode->ae_info.min_long_integraion_line = 2; + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 6; + current_mode->ae_info.min_integraion_line = 2; + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length -6; + current_mode->ae_info.min_vs_integraion_line = 2; + + current_mode->ae_info.max_long_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.max_long_integraion_line; + current_mode->ae_info.min_long_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.min_long_integraion_line; + current_mode->ae_info.max_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.max_integraion_line; + current_mode->ae_info.min_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.min_integraion_line; + current_mode->ae_info.max_vs_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.max_vs_integraion_line; + current_mode->ae_info.min_vs_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + //gain + current_mode->ae_info.gain_accuracy = 1024; + current_mode->ae_info.gain_increment = (1.0f / 16.0f); + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 120.125; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + //current_mode->ae_info.ae_min_interval_frame = 0.8; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_long_gain.max = 1.0; + current_mode->ae_info.a_long_gain.min = 63.9375; + current_mode->ae_info.a_long_gain.step = (1.0f / 16.0f); + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 63.9375; + current_mode->ae_info.a_gain.step = (1.0f / 16.0f); + current_mode->ae_info.a_vs_gain.max = 1.0; + current_mode->ae_info.a_vs_gain.min = 63.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f / 16.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f / 1024.0f); + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f / 1024.0f); + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f / 1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + + + default: + break; + } + + k_u16 exp_time; + float again = 0, dgain = 0; + again = 1.0; + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + // ret = sensor_reg_read(&dev->i2c_info, OV9732_REG_LONG_EXP_TIME_L, &exp_time_l); + exp_time = 1; + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + + return ret; +} + +static k_s32 sc035hgs_sensor_get_mode(void* ctx, k_sensor_mode* mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(sc035hgs_mode_info) / sizeof(k_sensor_mode); i++) { + if (sc035hgs_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &sc035hgs_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(sc035hgs_mode_info[i]); + return 0; + } + } + pr_err("%s, the mode not exit.\n", __func__); + + return ret; +} + +static k_s32 sc035hgs_sensor_set_mode(void* ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + struct sensor_driver_dev* dev = ctx; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc035hgs_sensor_enum_mode(void* ctx, k_sensor_enum_mode* enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + if (enum_mode->index >= (sizeof(sc035hgs_mode_info) / sizeof(k_sensor_mode))) { + pr_err("%s, invalid mode index.\n", __func__); + return -1; + } + + for (k_s32 i = 0; i < sizeof(sc035hgs_mode_info) / sizeof(k_sensor_mode); i++) { + if (sc035hgs_mode_info[i].index == enum_mode->index) { + memcpy(&enum_mode->mode, &sc035hgs_mode_info[i], sizeof(k_sensor_mode)); + return 0; + } + } + return ret; +} + +static k_s32 sc035hgs_sensor_get_caps(void* ctx, k_sensor_caps* caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +static k_s32 sc035hgs_sensor_conn_check(void* ctx, k_s32* conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +static k_s32 sc035hgs_sensor_set_stream(void* ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev* dev = ctx; + + rt_kprintf("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + rt_kprintf("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_again(void* ctx, k_sensor_gain* gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + // if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + // gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + // } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + // gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + // gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + // } else { + // pr_err("%s, unsupport exposure frame.\n", __func__); + // return -1; + // } + + return ret; +} + +static k_s32 sc035hgs_sensor_set_again(void* ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + // k_u16 again; + // k_u16 coarse; + // k_u16 fine; + // struct sensor_driver_dev* dev = ctx; + + // if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + // again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 16); + // ret = sensor_reg_read(&dev->i2c_info, SC035HGS_REG_COARSE_AGAIN, &coarse); + // coarse &= ~(0x07 << 2); // clear [4:2] bits for coarse gain + // if(again > 15.5 * 16) { + // again = 15.5 * 16; + // coarse |= 0x07 << 2; + // fine = 0x1f; + // } else if (again >= 8 << 4) { + // coarse |= 0x07 << 2; + // fine = again >> 3; + // } else if (again >= 4 << 4) { + // coarse |= 0x03 << 2; + // fine = again >> 2; + // } else if (again >= 2 << 4) { + // coarse |= 0x01 << 2; + // fine = again >> 1; + // } else if (again >= 1 << 4) { + // coarse |= 0x00 << 2; + // fine = again; + // } else { + // again = 1.0 * 16; + // coarse |= 0x00 << 2; + // fine = 0x10; + // } + // ret = sensor_reg_write(&dev->i2c_info, SC035HGS_REG_COARSE_AGAIN, coarse); + // ret |= sensor_reg_write(&dev->i2c_info, SC035HGS_REG_FINE_AGAIN, fine); + // current_mode->ae_info.cur_again = (float)again / 16.0f; + // } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + // again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 16); + // // ret = sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_H, (again & 0x0300) >> 8); + // // ret |= sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_L, (again & 0xff)); + // current_mode->ae_info.cur_again = (float)again / 16.0f; + + // again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 16); + // // TODO + // current_mode->ae_info.cur_vs_again = (float)again / 16.0f; + // } else { + // pr_err("%s, unsupport exposure frame.\n", __func__); + // return -1; + // } + // pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again * 1000)); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_dgain(void* ctx, k_sensor_gain* gain) +{ + k_s32 ret = 0; + + // pr_info("%s enter\n", __func__); + + // if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + // gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + // } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + // gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + // gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + // } else { + // pr_err("%s, unsupport exposure frame.\n", __func__); + // return -1; + // } + + return ret; +} + +static k_s32 sc035hgs_sensor_set_dgain(void* ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + // k_u32 dgain; + // k_u16 coarse; + // k_u16 fine; + // struct sensor_driver_dev* dev = ctx; + + // pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + // if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + // dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 128); + // ret = sensor_reg_read(&dev->i2c_info, SC035HGS_REG_COARSE_DGAIN, &coarse); + // coarse &= ~0x03; // clear [1:0] bits for coarse gain + // if(dgain > 7.96875 * 128) { + // dgain = 7.96875 * 128; + // coarse |= 0x03; + // fine = 0xff; + // } else if (dgain >= 4 * 128) { + // coarse |= 0x03; + // fine = dgain >> 2; + // } else if (dgain >= 2 * 128) { + // coarse |= 0x01; + // fine = dgain >> 1; + // } else if (dgain >= 1 * 128) { + // coarse |= 0x00; + // fine = dgain; + // } else { + // dgain = 128; + // coarse |= 0x00; + // fine = 0x80; + // } + // ret = sensor_reg_write(&dev->i2c_info, SC035HGS_REG_COARSE_DGAIN, coarse); + // ret |= sensor_reg_write(&dev->i2c_info, SC035HGS_REG_FINE_DGAIN, fine); + // current_mode->ae_info.cur_dgain = (float)dgain / 128.0f; + + // } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + // dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + // // ret = sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + // // ret |= sensor_reg_write(&dev->i2c_info, OV9732_REG_LONG_AGAIN_L,(again & 0xff)); + // current_mode->ae_info.cur_dgain = (float)dgain / 1024.0f; + + // dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + // // TODO wirte vs gain register + // current_mode->ae_info.cur_vs_dgain = (float)dgain / 1024.0f; + // } else { + // pr_err("%s, unsupport exposure frame.\n", __func__); + // return -1; + // } + // current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + // pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain * 10000)); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_intg_time(void* ctx, k_sensor_intg_time* time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 sc035hgs_sensor_set_intg_time(void* ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + float integraion_time = 0; + struct sensor_driver_dev* dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + // ret |= sensor_reg_write(&dev->i2c_info, 0x3501, (exp_line >> 4) & 0xff); + // ret |= sensor_reg_write(&dev->i2c_info, 0x3502, (exp_line << 4) & 0xff); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n", + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_exp_parm(void* ctx, k_sensor_exposure_param* exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +static k_s32 sc035hgs_sensor_set_exp_parm(void* ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_fps(void* ctx, k_u32* fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = current_mode->fps; + + return ret; +} + +static k_s32 sc035hgs_sensor_set_fps(void* ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_isp_status(void* ctx, k_sensor_isp_status* staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +static k_s32 sc035hgs_sensor_set_blc(void* ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc035hgs_sensor_set_wb(void* ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_tpg(void* ctx, k_sensor_test_pattern* tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +static k_s32 sc035hgs_sensor_set_tpg(void* ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_expand_curve(void* ctx, k_sensor_compand_curve* curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +static k_s32 sc035hgs_sensor_get_otp_data(void* ctx, void* data) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(data, 0, sizeof(void*)); + + return ret; +} + + +static k_s32 sc035hgs_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev sc035hgs_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c3", + .slave_addr = 0x30, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = SC035HGS_NAME, + .sensor_func = { + .sensor_power = sc035hgs_sensor_power_on, + .sensor_init = sc035hgs_sensor_init, + .sensor_get_chip_id = sc035hgs_sensor_get_chip_id, + .sensor_get_mode = sc035hgs_sensor_get_mode, + .sensor_set_mode = sc035hgs_sensor_set_mode, + .sensor_enum_mode = sc035hgs_sensor_enum_mode, + .sensor_get_caps = sc035hgs_sensor_get_caps, + .sensor_conn_check = sc035hgs_sensor_conn_check, + .sensor_set_stream = sc035hgs_sensor_set_stream, + .sensor_get_again = sc035hgs_sensor_get_again, + .sensor_set_again = sc035hgs_sensor_set_again, + .sensor_get_dgain = sc035hgs_sensor_get_dgain, + .sensor_set_dgain = sc035hgs_sensor_set_dgain, + .sensor_get_intg_time = sc035hgs_sensor_get_intg_time, + .sensor_set_intg_time = sc035hgs_sensor_set_intg_time, + .sensor_get_exp_parm = sc035hgs_sensor_get_exp_parm, + .sensor_set_exp_parm = sc035hgs_sensor_set_exp_parm, + .sensor_get_fps = sc035hgs_sensor_get_fps, + .sensor_set_fps = sc035hgs_sensor_set_fps, + .sensor_get_isp_status = sc035hgs_sensor_get_isp_status, + .sensor_set_blc = sc035hgs_sensor_set_blc, + .sensor_set_wb = sc035hgs_sensor_set_wb, + .sensor_get_tpg = sc035hgs_sensor_get_tpg, + .sensor_set_tpg = sc035hgs_sensor_set_tpg, + .sensor_get_expand_curve = sc035hgs_sensor_get_expand_curve, + .sensor_get_otp_data = sc035hgs_sensor_get_otp_data, + .sensor_mirror_set = sc035hgs_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sc201cs_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sc201cs_drv.c new file mode 100755 index 0000000..49ec5de --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sc201cs_drv.c @@ -0,0 +1,1008 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" +#include "io.h" +#include +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#define pr_info(...) /* rt_kprintf(__VA_ARGS__) */ +#define pr_debug(...) /*rt_kprintf(__VA_ARGS__)*/ +#define pr_warn(...) /*rt_kprintf(__VA_ARGS__)*/ +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +/* Streaming Mode */ +#define SC201CS_REG_MODE_SELECT 0x3000 +#define SC201CS_MODE_STANDBY 0x01 +#define SC201CS_MODE_STREAMING 0x00 + +/* Lines per frame */ +#define SC201CS_REG_LPFR 0x3030 + +/* Chip ID */ +#define SC201CS_REG_ID 0x3107 + +/* Exposure control */ +#define SC201CS_REG_EXP_TIME_H 0x3e01 +#define SC201CS_REG_EXP_TIME_L 0x3e02 +#define SC201CS_VMAX 1250//4500 + +/* Analog gain control */ +#define SC201CS_REG_AGAIN 0x3e09 +#define SC201CS_REG_DGAIN 0x3e07 +#define SC201CS_AGAIN_STEP (1.0f/64.0f) + +/* Group hold register */ +#define SC201CS_REG_HOLD 0x3001 + +/* Input clock rate */ +#define SC201CS_INCLK_RATE 24000000 + +/* CSI2 HW configuration */ +#define SC201CS_LINK_FREQ 594000000 +#define SC201CS_NUM_DATA_LANES 4 + +#define SC201CS_REG_MIN 0x00 +#define SC201CS_REG_MAX 0xfffff + + + +static const k_sensor_reg sc201cs_mipi_1lane_raw10_1600x1200_30fps_mclk_27m_regs[] = { + //MIPI clock 720Mbps, MCLK 72MHz + {0x0103,0x01}, + {0x0100,0x00}, + {0x36e9,0x80}, + {0x36ea,0xc8}, + {0x36eb,0x25}, + {0x36ec,0x00}, + {0x36ed,0x04}, + {0x36e9,0x41}, + {0x300b,0x44}, + {0x301f,0x31}, + //{0x320e,0x05}, //HTS:1920, VTS: 1500 + //{0x320f,0xdc}, //VTS default setting is 1250 + {0x3248,0x02}, + {0x3253,0x0a}, + {0x3301,0xff}, + {0x3302,0xff}, + {0x3303,0x10}, + {0x3306,0x28}, + {0x3307,0x02}, + {0x330a,0x00}, + {0x330b,0xb0}, + {0x3318,0x02}, + {0x3320,0x06}, + {0x3321,0x02}, + {0x3326,0x12}, + {0x3327,0x0e}, + {0x3328,0x03}, + {0x3329,0x0f}, + {0x3364,0x4f}, + {0x33b3,0x40}, + {0x33f9,0x2c}, + {0x33fb,0x38}, + {0x33fc,0x0f}, + {0x33fd,0x1f}, + {0x349f,0x03}, + {0x34a6,0x01}, + {0x34a7,0x1f}, + {0x34a8,0x40}, + {0x34a9,0x30}, + {0x34ab,0xa6}, + {0x34ad,0xa6}, + {0x3622,0x60}, + {0x3623,0x40}, + {0x3624,0x61}, + {0x3625,0x08}, + {0x3626,0x03}, + {0x3630,0xa8}, + {0x3631,0x84}, + {0x3632,0x90}, + {0x3633,0x43}, + {0x3634,0x09}, + {0x3635,0x82}, + {0x3636,0x48}, + {0x3637,0xe4}, + {0x3641,0x22}, + {0x3670,0x0f}, + {0x3674,0xc0}, + {0x3675,0xc0}, + {0x3676,0xc0}, + {0x3677,0x86}, + {0x3678,0x88}, + {0x3679,0x8c}, + {0x367c,0x01}, + {0x367d,0x0f}, + {0x367e,0x01}, + {0x367f,0x0f}, + {0x3690,0x63}, + {0x3691,0x63}, + {0x3692,0x73}, + {0x369c,0x01}, + {0x369d,0x1f}, + {0x369e,0x8a}, + {0x369f,0x9e}, + {0x36a0,0xda}, + {0x36a1,0x01}, + {0x36a2,0x03}, + {0x3900,0x0d}, + {0x3904,0x06}, + {0x3905,0x98}, + {0x3908,0x10}, //black level target + {0x391b,0x81}, + {0x391c,0x10}, + {0x391d,0x19}, + {0x3933,0x01}, + {0x3934,0x82}, + {0x3940,0x5d}, + {0x3942,0x01}, + {0x3943,0x82}, + {0x3949,0xc8}, + {0x394b,0x64}, + {0x3952,0x02}, + {0x3e00,0x00}, + {0x3e01,0x4d}, + {0x3e02,0xe0}, + {0x4502,0x34}, + {0x4509,0x30}, + {0x450a,0x71}, + // {0x0100,0x01} + { REG_NULL, 0x00 } +}; + +static const k_sensor_reg sc201cs_slave_mode_mipi_1lane_raw10_1600x1200_30fps_mclk_27m_regs[] = { + //MIPI clock 720Mbps, MCLK 72MHz + {0x0103,0x01}, + {0x0100,0x00}, + {0x36e9,0x80}, + {0x36ea,0xc8}, + {0x36eb,0x25}, + {0x36ec,0x00}, + {0x36ed,0x04}, + {0x36e9,0x41}, + {0x300b,0x40}, + {0x301f,0x32}, + //{0x320e,0x05}, //HTS:1920, VTS: 1500 + //{0x320f,0xdc}, + {0x3222,0x02}, + {0x3224,0x82}, + {0x322e,0x04},//0x04de = VTS - 4 = 1250 - 4 ? + {0x322f,0xde}, + {0x3248,0x02}, + {0x3253,0x0e}, + {0x3301,0xff}, + {0x3302,0xff}, + {0x3303,0x10}, + {0x3306,0x28}, + {0x3307,0x02}, + {0x330a,0x00}, + {0x330b,0xb0}, + {0x3318,0x02}, + {0x3320,0x06}, + {0x3321,0x02}, + {0x3326,0x12}, + {0x3327,0x0e}, + {0x3328,0x03}, + {0x3329,0x0f}, + {0x3364,0x4f}, + {0x33b3,0x40}, + {0x33f9,0x2c}, + {0x33fb,0x38}, + {0x33fc,0x0f}, + {0x33fd,0x1f}, + {0x349f,0x03}, + {0x34a6,0x01}, + {0x34a7,0x1f}, + {0x34a8,0x40}, + {0x34a9,0x30}, + {0x34ab,0xa6}, + {0x34ad,0xa6}, + {0x3622,0x60}, + {0x3623,0x40}, + {0x3624,0x61}, + {0x3625,0x08}, + {0x3626,0x03}, + {0x3630,0xa8}, + {0x3631,0x84}, + {0x3632,0x90}, + {0x3633,0x43}, + {0x3634,0x09}, + {0x3635,0x82}, + {0x3636,0x48}, + {0x3637,0xe4}, + {0x3641,0x22}, + {0x3670,0x0f}, + {0x3674,0xc0}, + {0x3675,0xc0}, + {0x3676,0xc0}, + {0x3677,0x86}, + {0x3678,0x88}, + {0x3679,0x8c}, + {0x367c,0x01}, + {0x367d,0x0f}, + {0x367e,0x01}, + {0x367f,0x0f}, + {0x3690,0x63}, + {0x3691,0x63}, + {0x3692,0x73}, + {0x369c,0x01}, + {0x369d,0x1f}, + {0x369e,0x8a}, + {0x369f,0x9e}, + {0x36a0,0xda}, + {0x36a1,0x01}, + {0x36a2,0x03}, + {0x3900,0x0d}, + {0x3904,0x06}, + {0x3905,0x98}, + {0x3908,0x10}, //black level target + {0x391b,0x81}, + {0x391c,0x10}, + {0x391d,0x19}, + {0x3933,0x01}, + {0x3934,0x82}, + {0x3940,0x5d}, + {0x3942,0x01}, + {0x3943,0x82}, + {0x3949,0xc8}, + {0x394b,0x64}, + {0x3952,0x02}, + {0x3e00,0x00}, + {0x3e01,0x4d}, + {0x3e02,0xe0}, + {0x4502,0x34}, + {0x4509,0x30}, + {0x450a,0x71}, + // {0x0100,0x01}, + { REG_NULL, 0x00 } +}; + +static k_sensor_mode sc201cs_mode_info[] = { + { + .index = 0, + .sensor_type = SC_SC201CS_MIPI_1LANE_RAW10_1600X1200_30FPS_LINEAR, + .size = { + .bounds_width = 1600, + .bounds_height = 1200, + .top = 0, + .left = 0, + .width = 1600, + .height = 1200, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR,//BAYER_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, + }, + .reg_list = sc201cs_mipi_1lane_raw10_1600x1200_30fps_mclk_27m_regs, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL1_CLK_DIV4, + .setting.mclk_div = 22, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, + { + .index = 1, + .sensor_type = SC_SC201CS_SLAVE_MODE_MIPI_1LANE_RAW10_1600X1200_30FPS_LINEAR, + .size = { + .bounds_width = 1600, + .bounds_height = 1200, + .top = 0, + .left = 0, + .width = 1600, + .height = 1200, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_LINEAR, + .bit_width = 10, + .bayer_pattern = BAYER_PAT_BGGR,//BAYER_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 1, + .data_type = 0x2B, + }, + .reg_list = sc201cs_slave_mode_mipi_1lane_raw10_1600x1200_30fps_mclk_27m_regs, + .mclk_setting = { + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL1_CLK_DIV4, + .setting.mclk_div = 22, + }, + { + .mclk_setting_en = K_TRUE, + .setting.id = SENSOR_MCLK1, + .setting.mclk_sel = SENSOR_PLL1_CLK_DIV4, + .setting.mclk_div = 22, + }, + {K_FALSE}, + }, + }, +}; + +static k_sensor_mode* current_mode = NULL; + +static int sc201cs_power_reset(k_s32 on) +{ + // #define SC201CS_RST_PIN 46 + // #define SC201CS_MASTER_PIN 28 + + k_u8 shutdown_gpio; + + shutdown_gpio = 49; + + kd_pin_mode(shutdown_gpio, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(shutdown_gpio, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(1); + kd_pin_write(shutdown_gpio, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(1); + kd_pin_write(shutdown_gpio, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(shutdown_gpio, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + +static int sc201cs_i2c_init(k_sensor_i2c_info* i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + +static k_s32 sc201cs_sensor_get_chip_id(void* ctx, k_u32* chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev* dev = ctx; + pr_info("%s enter\n", __func__); + + sc201cs_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, SC201CS_REG_ID, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, SC201CS_REG_ID + 1, &id_low); + if (ret) { + // rt_kprintf("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + pr_info("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + +static k_s32 sc201cs_sensor_power_on(void* ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev* dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter, %d\n", __func__, on); + if (on) { + sc201cs_power_reset(1); + sc201cs_i2c_init(&dev->i2c_info); + ret = sc201cs_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + sc201cs_power_reset(0); + } + + return ret; +} + +static k_s32 sc201cs_sensor_init(void* ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev* dev = ctx; + + if (current_mode == NULL) { + for (i = 0; i < sizeof(sc201cs_mode_info) / sizeof(k_sensor_mode); i++) { + if (sc201cs_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(sc201cs_mode_info[i]); + dev->sensor_mode = &(sc201cs_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + default: + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = SC201CS_VMAX; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.000026667; // s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 31.75; + + current_mode->ae_info.int_time_delay_frame = 2; + current_mode->ae_info.gain_delay_frame = 2; + //current_mode->ae_info.ae_min_interval_frame = 2.5; + current_mode->ae_info.color_type = SENSOR_COLOR; //color sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = SC201CS_AGAIN_STEP; + + current_mode->ae_info.max_long_integraion_line = current_mode->ae_info.frame_length - 6; + current_mode->ae_info.min_long_integraion_line = 1; + + current_mode->ae_info.max_integraion_line = current_mode->ae_info.frame_length - 6; + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length - 6; + current_mode->ae_info.min_vs_integraion_line = 1; + + current_mode->ae_info.max_long_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.max_long_integraion_line; + + current_mode->ae_info.min_long_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.min_long_integraion_line; + + current_mode->ae_info.max_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = current_mode->ae_info.integration_time_increment * current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_long_integration_time = 0.0; + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + current_mode->ae_info.cur_long_again = 0.0; + current_mode->ae_info.cur_long_dgain = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_long_gain.min = 1.0; + current_mode->ae_info.a_long_gain.max = 100.0; + current_mode->ae_info.a_long_gain.step = (1.0f / 256.0f); + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 100.0; + current_mode->ae_info.a_gain.step = (1.0f / 256.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 100.0; + current_mode->ae_info.a_vs_gain.step = (1.0f / 256.0f); + + current_mode->ae_info.d_long_gain.max = 1.0; + current_mode->ae_info.d_long_gain.min = 1.0; + current_mode->ae_info.d_long_gain.step = (1.0f / 1024.0f); + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f / 1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f / 1024.0f); + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + + break; + } + + k_u16 dgain, again; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + + + ret = sensor_reg_read(&dev->i2c_info, SC201CS_REG_DGAIN, &dgain); + ret = sensor_reg_read(&dev->i2c_info, SC201CS_REG_AGAIN, &again); + current_mode->ae_info.cur_gain = (float)((again+1) * dgain) / 128.0f; + + ret = sensor_reg_read(&dev->i2c_info, SC201CS_REG_EXP_TIME_H, &exp_time_h); + ret = sensor_reg_read(&dev->i2c_info, SC201CS_REG_EXP_TIME_L, &exp_time_l); + exp_time = (exp_time_h << 4) | ((exp_time_l >> 4) & 0x0F); + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + + //pr_info("%s exit, sensor_type:%d\n", __func__, mode.sensor_type); + return ret; +} + +static k_s32 sc201cs_sensor_get_mode(void* ctx, k_sensor_mode* mode) +{ + k_s32 ret = -1; + + for (k_s32 i = 0; i < sizeof(sc201cs_mode_info) / sizeof(k_sensor_mode); i++) { + if (sc201cs_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &sc201cs_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(sc201cs_mode_info[i]); + return 0; + } + } + pr_debug("%s, the mode not exit.\n", __func__); + + return ret; +} + +static k_s32 sc201cs_sensor_set_mode(void* ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc201cs_sensor_enum_mode(void* ctx, k_sensor_enum_mode* enum_mode) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + if (enum_mode->index >= (sizeof(sc201cs_mode_info) / sizeof(k_sensor_mode))) { + pr_err("%s, invalid mode index.\n", __func__); + return -1; + } + + for (k_s32 i = 0; i < sizeof(sc201cs_mode_info) / sizeof(k_sensor_mode); i++) { + if (sc201cs_mode_info[i].index == enum_mode->index) { + memcpy(&enum_mode->mode, &sc201cs_mode_info[i], sizeof(k_sensor_mode)); + return 0; + } + } + return ret; +} + +static k_s32 sc201cs_sensor_get_caps(void* ctx, k_sensor_caps* caps) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +static k_s32 sc201cs_sensor_conn_check(void* ctx, k_s32* conn) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +static k_s32 sc201cs_sensor_set_stream(void* ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev* dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +static k_s32 sc201cs_sensor_get_again(void* ctx, k_sensor_gain* gain) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 sc201cs_sensor_set_again(void* ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 SensorGain, again, dgain; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) + { + SensorGain = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 64 + 0.5)<<1; + if(current_mode->sensor_again !=SensorGain) + { + if(SensorGain>=2048) + { + again = 15; //16x + dgain = SensorGain>>4; + } + else if(SensorGain>=1024) + { + again = 7; //8x + dgain = SensorGain>>3; + } + else if(SensorGain>=512) + { + again = 3; //4x + dgain = SensorGain>>2; + } + else if(SensorGain>=256) + { + again = 1; //2x + dgain = SensorGain>>1; + } + else// if(SensorGain>=128) + { + again = 0; //1x + dgain = SensorGain; + } + + ret = sensor_reg_write(&dev->i2c_info, SC201CS_REG_AGAIN,again); + ret |= sensor_reg_write(&dev->i2c_info, SC201CS_REG_DGAIN,dgain); + current_mode->sensor_again = SensorGain; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/128.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + SensorGain = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 64 + 0.5)<<1; + if(current_mode->sensor_again !=SensorGain) + { + if(SensorGain>=2048) + { + again = 15; //16x + dgain = SensorGain>>4; + } + else if(SensorGain>=1024) + { + again = 7; //8x + dgain = SensorGain>>3; + } + else if(SensorGain>=512) + { + again = 3; //4x + dgain = SensorGain>>2; + } + else if(SensorGain>=256) + { + again = 1; //2x + dgain = SensorGain>>1; + } + else// if(SensorGain>=128) + { + again = 0; //1x + dgain = SensorGain; + } + + ret = sensor_reg_write(&dev->i2c_info, SC201CS_REG_AGAIN,again); + ret |= sensor_reg_write(&dev->i2c_info, SC201CS_REG_DGAIN,dgain); + current_mode->sensor_again = SensorGain; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/128.0f; + //TODO + current_mode->ae_info.cur_vs_again = (float)current_mode->sensor_again/128.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, exp_frame_type(%d), cur_again(%u)\n", __func__, gain.exp_frame_type, (k_u32)(current_mode->ae_info.cur_again * 1000)); + + return ret; +} + +static k_s32 sc201cs_sensor_get_dgain(void* ctx, k_sensor_gain* gain) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 sc201cs_sensor_set_dgain(void* ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev* dev = ctx; + + pr_debug("%s enter exp_frame_type(%d)\n", __func__, gain.exp_frame_type); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + current_mode->ae_info.cur_dgain = dgain / 1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + current_mode->ae_info.cur_dgain = dgain / 1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + // TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = dgain / 1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain * 10000)); + + return ret; +} + +static k_s32 sc201cs_sensor_get_intg_time(void* ctx, k_sensor_intg_time* time) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 sc201cs_sensor_set_intg_time(void* ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + float integraion_time = 0; + struct sensor_driver_dev* dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) + { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(current_mode->ae_info.min_integraion_line, exp_line)); + if (current_mode->et_line != exp_line) + { + ret |= sensor_reg_write(&dev->i2c_info, SC201CS_REG_EXP_TIME_H, ( exp_line >> 4) & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, SC201CS_REG_EXP_TIME_L, ( exp_line << 4) & 0xff); + current_mode->et_line = exp_line; + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(current_mode->ae_info.min_integraion_line, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(current_mode->ae_info.min_integraion_line, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s exp_frame_type(%d), exp_line(%d), integraion_time(%u)\n", + __func__, time.exp_frame_type, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +static k_s32 sc201cs_sensor_get_exp_parm(void* ctx, k_sensor_exposure_param* exp_parm) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +static k_s32 sc201cs_sensor_set_exp_parm(void* ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc201cs_sensor_get_fps(void* ctx, k_u32* fps) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + *fps = current_mode->fps; + + return ret; +} + +static k_s32 sc201cs_sensor_set_fps(void* ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc201cs_sensor_get_isp_status(void* ctx, k_sensor_isp_status* staus) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +static k_s32 sc201cs_sensor_set_blc(void* ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc201cs_sensor_set_wb(void* ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc201cs_sensor_get_tpg(void* ctx, k_sensor_test_pattern* tpg) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +static k_s32 sc201cs_sensor_set_tpg(void* ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + + return ret; +} + +static k_s32 sc201cs_sensor_get_expand_curve(void* ctx, k_sensor_compand_curve* curve) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +static k_s32 sc201cs_sensor_get_otp_data(void* ctx, void* data) +{ + k_s32 ret = 0; + + pr_debug("%s enter\n", __func__); + memset(data, 0, sizeof(void*)); + + return ret; +} + +static k_s32 sc201cs_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev sc201cs_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c1", + .slave_addr = 0x30, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "sc201cs", + .sensor_func = { + .sensor_power = sc201cs_sensor_power_on, + .sensor_init = sc201cs_sensor_init, + .sensor_get_chip_id = sc201cs_sensor_get_chip_id, + .sensor_get_mode = sc201cs_sensor_get_mode, + .sensor_set_mode = sc201cs_sensor_set_mode, + .sensor_enum_mode = sc201cs_sensor_enum_mode, + .sensor_get_caps = sc201cs_sensor_get_caps, + .sensor_conn_check = sc201cs_sensor_conn_check, + .sensor_set_stream = sc201cs_sensor_set_stream, + .sensor_get_again = sc201cs_sensor_get_again, + .sensor_set_again = sc201cs_sensor_set_again, + .sensor_get_dgain = sc201cs_sensor_get_dgain, + .sensor_set_dgain = sc201cs_sensor_set_dgain, + .sensor_get_intg_time = sc201cs_sensor_get_intg_time, + .sensor_set_intg_time = sc201cs_sensor_set_intg_time, + .sensor_get_exp_parm = sc201cs_sensor_get_exp_parm, + .sensor_set_exp_parm = sc201cs_sensor_set_exp_parm, + .sensor_get_fps = sc201cs_sensor_get_fps, + .sensor_set_fps = sc201cs_sensor_set_fps, + .sensor_get_isp_status = sc201cs_sensor_get_isp_status, + .sensor_set_blc = sc201cs_sensor_set_blc, + .sensor_set_wb = sc201cs_sensor_set_wb, + .sensor_get_tpg = sc201cs_sensor_get_tpg, + .sensor_set_tpg = sc201cs_sensor_set_tpg, + .sensor_get_expand_curve = sc201cs_sensor_get_expand_curve, + .sensor_get_otp_data = sc201cs_sensor_get_otp_data, + .sensor_mirror_set = sc201cs_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sensor_comm.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sensor_comm.c index 0c1e6ee..d3e972d 100755 --- a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sensor_comm.c +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/sensor_comm.c @@ -94,7 +94,7 @@ k_s32 sensor_reg_read(k_sensor_i2c_info *i2c_info, k_u16 reg_addr, k_u16 *buf) // rt_kprintf("sensor_reg_read: [0x%04x] = [0x%02x] i2c_info->size is %d \n", reg_addr, *buf, i2c_info->size); return RT_EOK; } - rt_kprintf("%s err.\n", __func__); + // rt_kprintf("%s err.\n", __func__); return RT_ERROR; } @@ -216,7 +216,7 @@ k_s32 sensor_priv_ioctl(struct sensor_driver_dev *dev, k_u32 cmd, void *args) } ret = dev->sensor_func.sensor_get_chip_id(dev, &chip_id); if (ret) { - rt_kprintf("%s (%s)sensor_get_chip_id err\n", __func__, dev->sensor_name); + // rt_kprintf("%s (%s)sensor_get_chip_id err\n", __func__, dev->sensor_name); return -1; } if (sizeof(chip_id) != lwp_put_to_user(args, &chip_id, sizeof(chip_id))){ @@ -237,7 +237,7 @@ k_s32 sensor_priv_ioctl(struct sensor_driver_dev *dev, k_u32 cmd, void *args) k_u16 reg_val; ret = sensor_reg_read(&dev->i2c_info, reg.addr, ®_val); if (ret) { - rt_kprintf("%s:%d sensor_reg_read err\n", __func__, __LINE__); + // rt_kprintf("%s:%d sensor_reg_read err\n", __func__, __LINE__); return -1; } reg.val = reg_val; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9922b_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9922b_drv.c new file mode 100755 index 0000000..b00884b --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9922b_drv.c @@ -0,0 +1,2017 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" + +//#include +#include "io.h" + +// #include "gpio.h" +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#define pr_info(...) rt_kprintf(__VA_ARGS__) +#define pr_debug(...) //rt_kprintf(__VA_ARGS__) +#define pr_warn(...) //rt_kprintf(__VA_ARGS__) +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define XS9922B_REG_CHIP_ID_H 0x40f0 +#define XS9922B_REG_CHIP_ID_L 0x40f1 + +#define XS9922B_REG_LONG_EXP_TIME_H 0x3501 +#define XS9922B_REG_LONG_EXP_TIME_L 0x3502 + +#define XS9922B_REG_LONG_AGAIN 0x3509 +//#define XS9922B_REG_LONG_AGAIN_H 0x350a +//#define XS9922B_REG_LONG_AGAIN_L 0x350b + +#define XS9922B_MIN_GAIN_STEP (1.0f/16.0f) + + +/* +iic : +slave addr : 0x30 +iic 电压: k230 1.8 , xs9922 : 3.3 + +mipi: +line num : 4 +mipi rate : 1.2G +mipi 连续模式: 连续模式 + +通道1: 手动模式(0x010c), default 关闭 (0x0e08) +通道2: 手动模式(0x110c), default 关闭 (0x1e08) +通道3: 手动模式(0x210c), default 关闭 (0x2e08) +通道4: 手动模式(0x310c), default 关闭 (0x3e08) + +彩条模式 : default : open 0x06。 不出彩条设置成0x0 + +帧号发送方式 : 1、 2、 3、 4轮流发送 +备注: +rst 需要拉低100ms,在拉高 +*/ +#if 1 +static const k_sensor_reg xs9922b_mipi4lane_720p_30fps_linear[] = { + + // {0x4082, 0x03}, iic burst模式 + {0x0e08, 0x00}, + {0x1e08, 0x00}, + {0x2e08, 0x00}, + {0x3e08, 0x00}, + //{0x4500, 0x02}, + {0x4f00, 0x01}, + {0x4030, 0x3f}, + {0x0e02, 0x00}, + {0x1e02, 0x00}, + {0x2e02, 0x00}, + {0x3e02, 0x00}, + {0x0803, 0x00}, + {0x1803, 0x00}, + {0x2803, 0x00}, + {0x3803, 0x00}, + {0x4020, 0x00}, + {0x080e, 0x00}, + {0x080e, 0x20}, + {0x080e, 0x28}, + {0x180e, 0x00}, + {0x180e, 0x20}, + {0x180e, 0x28}, + {0x280e, 0x00}, + {0x280e, 0x20}, + {0x280e, 0x28}, + {0x380e, 0x00}, + {0x380e, 0x20}, + {0x380e, 0x28}, + {0x4020, 0x03}, + {0x0803, 0x0f}, + {0x1803, 0x0f}, + {0x2803, 0x0f}, + {0x3803, 0x0f}, +#if RM_STRIPES + {0x0800, 0x16}, + {0x1800, 0x16}, + {0x2800, 0x16}, + {0x3800, 0x16}, + {0x4205, 0x36}, + {0x4215, 0x36}, + {0x4225, 0x36}, + {0x4235, 0x36},//wait(0.05) + {0x4205, 0x26}, + {0x4215, 0x26}, + {0x4225, 0x26}, + {0x4235, 0x26}, + {0x0800, 0x17}, + {0x1800, 0x17}, + {0x2800, 0x17}, + {0x3800, 0x17}, + #endif + {0x4340, 0x65}, + {0x4204, 0x02}, + {0x4214, 0x02}, + {0x4224, 0x02}, + {0x4234, 0x02}, + {0x4080, 0x07}, + {0x4119, 0x01}, + {0x0501, 0x84}, +#if USE_YUVGAIN + {0x010e, Y_GAIN}, + {0x010f, U_GAIN}, + {0x0110, V_GAIN}, +#endif + {0x0111, 0x40}, + {0x1501, 0x81}, +#if USE_YUVGAIN + {0x110e, Y_GAIN}, + {0x110f, U_GAIN}, + {0x1110, V_GAIN}, +#endif + {0x1111, 0x40}, + {0x2501, 0x8e}, +#if USE_YUVGAIN + {0x210e, Y_GAIN}, + {0x210f, U_GAIN}, + {0x2110, V_GAIN}, +#endif + {0x2111, 0x40}, + {0x3501, 0x8b}, +#if USE_YUVGAIN + {0x310e, Y_GAIN}, + {0x310f, U_GAIN}, + {0x3110, V_GAIN}, +#endif + {0x3111, 0x40}, + {0x4141, 0x22}, + {0x4140, 0x22}, + {0x413f, 0x22}, + {0x413e, 0x22}, + {0x030c, 0x03}, + {0x0300, 0x3f}, + {0x0333, 0x09}, + {0x0305, 0xe0}, + {0x011c, 0x32}, + {0x0105, 0xe1}, + //{0x0106, 0x80}, // contrast + //{0x0107, 0x00}, // brightness + //{0x0108, 0x80}, // staturation + //{0x0109, 0x00}, // hue + {0x01bf, 0x4e}, + {0x0b7c, 0x02}, + {0x0b55, 0x80}, + {0x0b56, 0x00}, + {0x0b59, 0x04}, + {0x0b5a, 0x01}, + {0x0b5c, 0x07}, + {0x0b5e, 0x05}, + {0x0b31, 0x18}, + {0x0b36, 0x40}, + {0x0b37, 0x1f}, + {0x0b4b, 0x10}, + {0x0b4e, 0x05}, + {0x0b51, 0x21}, + {0x0b15, 0x03}, + {0x0b16, 0x03}, + {0x0b17, 0x03}, + {0x0b07, 0x03}, + {0x0b08, 0x05}, + {0x0b1a, 0x10}, + {0x0b1e, 0xb8}, + {0x0b1f, 0x08}, + {0x0b5f, 0x64}, + {0x4200, 0x3f}, + {0x130c, 0x03}, + {0x1300, 0x3f}, + {0x1333, 0x09}, + {0x111c, 0x32}, + {0x11bf, 0x4e}, + {0x1b7c, 0x02}, + {0x1b55, 0x80}, + {0x1b56, 0x00}, + {0x1b59, 0x04}, + {0x1b5a, 0x01}, + {0x1b5c, 0x07}, + {0x1b5e, 0x05}, + {0x1b31, 0x18}, + {0x1b36, 0x40}, + {0x1b37, 0x1f}, + {0x1b4b, 0x10}, + {0x1b4e, 0x05}, + {0x1b51, 0x21}, + {0x1b15, 0x03}, + {0x1b16, 0x03}, + {0x1b17, 0x03}, + {0x1b07, 0x03}, + {0x1b08, 0x05}, + {0x1b1a, 0x10}, + {0x1b1e, 0xb8}, + {0x1b1f, 0x08}, + {0x1b5f, 0x64}, + {0x1105, 0xe1}, + //{0x1106, 0x80} + //{0x1107, 0x00}, + //{0x1108, 0x80}, + //{0x1109, 0x00}, + {0x4210, 0x33}, + {0x230c, 0x03}, + {0x2300, 0x3f}, + {0x2333, 0x09}, + {0x211c, 0x32}, + {0x21bf, 0x4e}, + {0x2b7c, 0x02}, + {0x2b55, 0x80}, + {0x2b56, 0x00}, + {0x2b59, 0x04}, + {0x2b5a, 0x01}, + {0x2b5c, 0x07}, + {0x2b5e, 0x05}, + {0x2b31, 0x18}, + {0x2b36, 0x40}, + {0x2b37, 0x1f}, + {0x2b4b, 0x10}, + {0x2b4e, 0x05}, + {0x2b51, 0x21}, + {0x2b15, 0x03}, + {0x2b16, 0x03}, + {0x2b17, 0x03}, + {0x2b07, 0x03}, + {0x2b08, 0x05}, + {0x2b1a, 0x10}, + {0x2b1e, 0xb8}, + {0x2b1f, 0x08}, + {0x2b5f, 0x64}, + {0x2105, 0xe1}, + //{0x2106, 0x80}, + //{0x2107, 0x00}, + //{0x2108, 0x80}, + //{0x2109, 0x00}, + {0x4220, 0x33}, + {0x330c, 0x03}, + {0x3300, 0x3f}, + {0x3333, 0x09}, + {0x311c, 0x32}, + {0x31bf, 0x4e}, + {0x3b7c, 0x02}, + {0x3b55, 0x80}, + {0x3b56, 0x00}, + {0x3b59, 0x04}, + {0x3b5a, 0x01}, + {0x3b5c, 0x07}, + {0x3b5e, 0x05}, + {0x3b31, 0x18}, + {0x3b36, 0x40}, + {0x3b37, 0x1f}, + {0x3b4b, 0x10}, + {0x3b4e, 0x05}, + {0x3b51, 0x21}, + {0x3b15, 0x03}, + {0x3b16, 0x03}, + {0x3b17, 0x03}, + {0x3b07, 0x03}, + {0x3b08, 0x05}, + {0x3b1a, 0x10}, + {0x3b1e, 0xb8}, + {0x3b1f, 0x08}, + {0x3b5f, 0x64}, + {0x3105, 0xe1}, + //{0x3106, 0x80}, + //{0x3107, 0x00}, + //{0x3108, 0x80}, + //{0x3109, 0x00}, + {0x4230, 0x33}, + {0x4800, 0x81}, + {0x4802, 0x01}, + {0x4030, 0x15}, + {0x50fc, 0x00}, + {0x50fd, 0x00}, + {0x50fe, 0x0d}, + {0x50ff, 0x59}, + {0x50e4, 0x00},//32位寄存器, 0x50e4是高字节, 0x50e7低8位字节 + {0x50e5, 0x00}, + {0x50e6, 0x2f}, + {0x50e7, 0x01},//0=1lane,1=2lane,2=3lane,3=4lane + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x32}, + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x00}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x44}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x36}, //0x78=1.5G,0x38 =1.4G,0x76=1.3G, 0x36=1.2G,0x34=1G,0x32=800M,0x2c=500M + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x30}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x40}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x50}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x80}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x90}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x20}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x45}, //0x45 + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, +#if MIPILANESWAP + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x55}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x01}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x85}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x01}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, +#endif + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x04}, + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x05}, + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x07}, + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01},//MIPI 1:连续模式 ,0:非连续模式 + {0x4801, 0x81}, + {0x4031, 0x01}, + {0x4138, 0x1e}, + {0x413b, 0x1e}, + {0x4135, 0x1e}, + {0x412f, 0x1e}, + {0x412c, 0x1e}, + {0x4126, 0x1e}, + {0x4129, 0x1e}, + {0x4123, 0x1e}, + {0x4f00, 0x01}, + //xs9922_720p_4lanes_25fps_1500M + {0x0803, 0x03}, /////////////////////////cam0 + {0x080e, 0x0f}, + {0x0803, 0x0f}, + {0x080e, 0x3f}, + {0x080e, 0x3f}, + {0x012d, 0x3f}, + {0x012f, 0xcc}, + {0x01e2, 0x03}, + {0x0158, 0x01}, + {0x0130, 0x10}, + {0x010c, 0x00},//通道0 1: 手动模式, 0: 自动模式 + {0x010d, 0x00},//40:AHD 720@25F 41:AHD 720@30F + {0x0805, 0x05}, + {0x0e11, 0x08},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x0e12, 0x01}, + {0x060b, 0x00}, + {0x0627, 0x14}, + {0x061c, 0x00}, + {0x061d, 0x5a}, + {0x061e, 0xa5}, + {0x0640, 0x04}, + {0x0616, 0x24}, + {0x0617, 0x00}, + {0x0618, 0x04}, + {0x060a, 0x07}, + {0x010a, 0x05}, + {0x0100, 0x30}, + {0x0104, 0x48}, + {0x0802, 0x21}, + {0x0502, 0x0c}, + {0x050e, 0x1c}, + {0x1803, 0x03}, ////////////////////////cam1 + {0x180e, 0x0f}, + {0x1803, 0x0f}, + {0x180e, 0x3f}, + {0x180e, 0x3f}, + {0x112d, 0x3f}, + {0x112f, 0xcc}, + {0x11e2, 0x03}, + {0x1158, 0x01}, + {0x1130, 0x10}, + {0x110c, 0x01},//通道1 1: 手动模式, 0: 自动模式 + {0x110d, 0x40},//40:AHD 720@25F 41:AHD 720@30F + {0x1805, 0x05}, + {0x1e11, 0x08},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x1e12, 0x01}, + {0x160b, 0x00}, + {0x1627, 0x14}, + {0x161c, 0x00}, + {0x161d, 0x5a}, + {0x161e, 0xa5}, + {0x1640, 0x04}, + {0x1616, 0x24}, + {0x1617, 0x00}, + {0x1618, 0x04}, + {0x160a, 0x07}, + {0x110a, 0x05}, + {0x1100, 0x30}, + {0x1104, 0x48}, + {0x1802, 0x21}, + {0x1502, 0x0d}, + {0x150e, 0x1d}, + {0x2803, 0x03}, ////////////////////////cam2 + {0x280e, 0x0f}, + {0x2803, 0x0f}, + {0x280e, 0x3f}, + {0x280e, 0x3f}, + {0x212d, 0x3f}, + {0x212f, 0xcc}, + {0x21e2, 0x03}, + {0x2158, 0x01}, + {0x2130, 0x10}, + {0x210c, 0x01},//通道2 1: 手动模式, 0: 自动模式 + {0x210d, 0x41},//40:AHD 720@25F 41:AHD 720@30F + {0x2805, 0x05}, + {0x2e11, 0x08},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x2e12, 0x01}, + {0x260b, 0x00}, + {0x2627, 0x14}, + {0x261c, 0x00}, + {0x261d, 0x5a}, + {0x261e, 0xa5}, + {0x2640, 0x04}, + {0x2616, 0x24}, + {0x2617, 0x00}, + {0x2618, 0x04}, + {0x260a, 0x07}, + {0x210a, 0x05}, + {0x2100, 0x30}, + {0x2104, 0x48}, + {0x2802, 0x21}, + {0x2502, 0x0e}, + {0x250e, 0x1e}, + {0x3803, 0x03}, ////////////////////////cam3 + {0x380e, 0x0f}, + {0x3803, 0x0f}, + {0x380e, 0x3f}, + {0x380e, 0x3f}, + {0x312d, 0x3f}, + {0x312f, 0xcc}, + {0x31e2, 0x03}, + {0x3158, 0x01}, + {0x3130, 0x10}, + {0x310c, 0x01},//通道3 1: 手动模式, 0: 自动模式 + {0x310d, 0x40},//40:AHD 720@25F 41:AHD 720@30F + {0x3805, 0x05}, + {0x3e11, 0x08},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x3e12, 0x01}, + {0x360b, 0x00}, + {0x3627, 0x14}, + {0x361c, 0x00}, + {0x361d, 0x5a}, + {0x361e, 0xa5}, + {0x3640, 0x04}, + {0x3616, 0x24}, + {0x3617, 0x00}, + {0x3618, 0x04}, + {0x360a, 0x07}, + {0x310a, 0x05}, + {0x3100, 0x38}, + {0x3104, 0x48}, + {0x3802, 0x21}, + {0x3502, 0x0f}, + {0x350e, 0x1f}, + //adc rst + {0x080e, 0x08}, + {0x0803, 0x0e}, + {0x0803, 0x0f}, + {0x080e, 0x28}, + {0x180e, 0x08}, + {0x1803, 0x0e}, + {0x1803, 0x0f}, + {0x180e, 0x28}, + {0x280e, 0x08}, + {0x2803, 0x0e}, + {0x2803, 0x0f}, + {0x280e, 0x28}, + {0x380e, 0x08}, + {0x3803, 0x0e}, + {0x3803, 0x0f}, + {0x380e, 0x28}, + {0x0e08, 0x01},//通道0 1: 开启, 0: 关闭 + {0x1e08, 0x00},//通道1 1: 开启, 0: 关闭 + {0x2e08, 0x00},//通道2 1: 开启, 0: 关闭 + {0x3e08, 0x00},//通道3 1: 开启, 0: 关闭 id == 3 + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x00}, + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, + + //adc rst ------------------- + {0x080e, 0x08}, + {0x0803, 0x0e}, + {0x0803, 0x0f}, + {0x080e, 0x28}, + //adc rst + {0x080e, 0x08}, + {0x0803, 0x0e}, + {0x0803, 0x0f}, + {0x080e, 0x28}, + + {REG_NULL, 0x0,}, +}; + +#else + +static const k_sensor_reg xs9922b_mipi4lane_720p_30fps_linear[] = { + + // {0x4082, 0x03}, iic burst模式 + {0x0e08, 0x01}, + {0x1e08, 0x00}, + {0x2e08, 0x00}, + {0x3e08, 0x00}, + //{0x4500, 0x02}, + {0x4f00, 0x01}, + {0x4030, 0x3f}, + {0x0e02, 0x00}, + {0x1e02, 0x00}, + {0x2e02, 0x00}, + {0x3e02, 0x00}, + {0x0803, 0x00}, + {0x1803, 0x00}, + {0x2803, 0x00}, + {0x3803, 0x00}, + {0x4020, 0x00}, + {0x080e, 0x00}, + {0x080e, 0x20}, + {0x080e, 0x28}, + {0x180e, 0x00}, + {0x180e, 0x20}, + {0x180e, 0x28}, + {0x280e, 0x00}, + {0x280e, 0x20}, + {0x280e, 0x28}, + {0x380e, 0x00}, + {0x380e, 0x20}, + {0x380e, 0x28}, + {0x4020, 0x03}, + {0x0803, 0x0f}, + {0x1803, 0x0f}, + {0x2803, 0x0f}, + {0x3803, 0x0f}, +#if RM_STRIPES + {0x0800, 0x16}, + {0x1800, 0x16}, + {0x2800, 0x16}, + {0x3800, 0x16}, + {0x4205, 0x36}, + {0x4215, 0x36}, + {0x4225, 0x36}, + {0x4235, 0x36},//wait(0.05) + {0x4205, 0x26}, + {0x4215, 0x26}, + {0x4225, 0x26}, + {0x4235, 0x26}, + {0x0800, 0x17}, + {0x1800, 0x17}, + {0x2800, 0x17}, + {0x3800, 0x17}, + #endif + {0x4340, 0x65}, + {0x4204, 0x02}, + {0x4214, 0x02}, + {0x4224, 0x02}, + {0x4234, 0x02}, + {0x4080, 0x07}, + {0x4119, 0x01}, + {0x0501, 0x84}, +#if USE_YUVGAIN + {0x010e, Y_GAIN}, + {0x010f, U_GAIN}, + {0x0110, V_GAIN}, +#endif + {0x0111, 0x40}, + {0x1501, 0x81}, +#if USE_YUVGAIN + {0x110e, Y_GAIN}, + {0x110f, U_GAIN}, + {0x1110, V_GAIN}, +#endif + {0x1111, 0x40}, + {0x2501, 0x8e}, +#if USE_YUVGAIN + {0x210e, Y_GAIN}, + {0x210f, U_GAIN}, + {0x2110, V_GAIN}, +#endif + {0x2111, 0x40}, + {0x3501, 0x8b}, +#if USE_YUVGAIN + {0x310e, Y_GAIN}, + {0x310f, U_GAIN}, + {0x3110, V_GAIN}, +#endif + {0x3111, 0x40}, + {0x4141, 0x22}, + {0x4140, 0x22}, + {0x413f, 0x22}, + {0x413e, 0x22}, + {0x030c, 0x03}, + {0x0300, 0x3f}, + {0x0333, 0x09}, + {0x0305, 0xe0}, + {0x011c, 0x32}, + {0x0105, 0xe1}, + //{0x0106, 0x80}, // contrast + //{0x0107, 0x00}, // brightness + //{0x0108, 0x80}, // staturation + //{0x0109, 0x00}, // hue + {0x01bf, 0x4e}, + {0x0b7c, 0x02}, + {0x0b55, 0x80}, + {0x0b56, 0x00}, + {0x0b59, 0x04}, + {0x0b5a, 0x01}, + {0x0b5c, 0x07}, + {0x0b5e, 0x05}, + {0x0b31, 0x18}, + {0x0b36, 0x40}, + {0x0b37, 0x1f}, + {0x0b4b, 0x10}, + {0x0b4e, 0x05}, + {0x0b51, 0x21}, + {0x0b15, 0x03}, + {0x0b16, 0x03}, + {0x0b17, 0x03}, + {0x0b07, 0x03}, + {0x0b08, 0x05}, + {0x0b1a, 0x10}, + {0x0b1e, 0xb8}, + {0x0b1f, 0x08}, + {0x0b5f, 0x64}, + {0x4200, 0x3f}, + {0x130c, 0x03}, + {0x1300, 0x3f}, + {0x1333, 0x09}, + {0x111c, 0x32}, + {0x11bf, 0x4e}, + {0x1b7c, 0x02}, + {0x1b55, 0x80}, + {0x1b56, 0x00}, + {0x1b59, 0x04}, + {0x1b5a, 0x01}, + {0x1b5c, 0x07}, + {0x1b5e, 0x05}, + {0x1b31, 0x18}, + {0x1b36, 0x40}, + {0x1b37, 0x1f}, + {0x1b4b, 0x10}, + {0x1b4e, 0x05}, + {0x1b51, 0x21}, + {0x1b15, 0x03}, + {0x1b16, 0x03}, + {0x1b17, 0x03}, + {0x1b07, 0x03}, + {0x1b08, 0x05}, + {0x1b1a, 0x10}, + {0x1b1e, 0xb8}, + {0x1b1f, 0x08}, + {0x1b5f, 0x64}, + {0x1105, 0xe1}, + //{0x1106, 0x80} + //{0x1107, 0x00}, + //{0x1108, 0x80}, + //{0x1109, 0x00}, + {0x4210, 0x33}, + {0x230c, 0x03}, + {0x2300, 0x3f}, + {0x2333, 0x09}, + {0x211c, 0x32}, + {0x21bf, 0x4e}, + {0x2b7c, 0x02}, + {0x2b55, 0x80}, + {0x2b56, 0x00}, + {0x2b59, 0x04}, + {0x2b5a, 0x01}, + {0x2b5c, 0x07}, + {0x2b5e, 0x05}, + {0x2b31, 0x18}, + {0x2b36, 0x40}, + {0x2b37, 0x1f}, + {0x2b4b, 0x10}, + {0x2b4e, 0x05}, + {0x2b51, 0x21}, + {0x2b15, 0x03}, + {0x2b16, 0x03}, + {0x2b17, 0x03}, + {0x2b07, 0x03}, + {0x2b08, 0x05}, + {0x2b1a, 0x10}, + {0x2b1e, 0xb8}, + {0x2b1f, 0x08}, + {0x2b5f, 0x64}, + {0x2105, 0xe1}, + //{0x2106, 0x80}, + //{0x2107, 0x00}, + //{0x2108, 0x80}, + //{0x2109, 0x00}, + {0x4220, 0x33}, + {0x330c, 0x03}, + {0x3300, 0x3f}, + {0x3333, 0x09}, + {0x311c, 0x32}, + {0x31bf, 0x4e}, + {0x3b7c, 0x02}, + {0x3b55, 0x80}, + {0x3b56, 0x00}, + {0x3b59, 0x04}, + {0x3b5a, 0x01}, + {0x3b5c, 0x07}, + {0x3b5e, 0x05}, + {0x3b31, 0x18}, + {0x3b36, 0x40}, + {0x3b37, 0x1f}, + {0x3b4b, 0x10}, + {0x3b4e, 0x05}, + {0x3b51, 0x21}, + {0x3b15, 0x03}, + {0x3b16, 0x03}, + {0x3b17, 0x03}, + {0x3b07, 0x03}, + {0x3b08, 0x05}, + {0x3b1a, 0x10}, + {0x3b1e, 0xb8}, + {0x3b1f, 0x08}, + {0x3b5f, 0x64}, + {0x3105, 0xe1}, + //{0x3106, 0x80}, + //{0x3107, 0x00}, + //{0x3108, 0x80}, + //{0x3109, 0x00}, + {0x4230, 0x33}, + {0x4800, 0x81}, + {0x4802, 0x01}, + {0x4030, 0x15}, + {0x50fc, 0x00}, + {0x50fd, 0x00}, + {0x50fe, 0x0d}, + {0x50ff, 0x59}, + {0x50e4, 0x00},//32位寄存器, 0x50e4是高字节, 0x50e7低8位字节 + {0x50e5, 0x00}, + {0x50e6, 0x2f}, + {0x50e7, 0x03},//0=1lane,1=2lane,2=3lane,3=4lane + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x32}, + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x00}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x44}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x78},//0x78=1.5G,0x38 =1.4G,0x76=1.3G, 0x36=1.2G,0x34=1G,0x32=800M,0x2c=500M + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x30}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x40}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x50}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x80}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x90}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x03}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x20}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x45}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + #if MIPILANESWAP + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x55}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x01}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + {0x5118, 0x00}, + {0x5119, 0x01}, + {0x511a, 0x00}, + {0x511b, 0x85}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x00}, + {0x5118, 0x00}, + {0x5119, 0x00}, + {0x511a, 0x00}, + {0x511b, 0x01}, + {0x5114, 0x00}, + {0x5115, 0x00}, + {0x5116, 0x00}, + {0x5117, 0x02}, + #endif + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x04}, + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x05}, + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x07}, + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01},//MIPI 1:连续模式 ,0:非连续模式 + {0x4801, 0x81}, + {0x4031, 0x01}, + {0x4138, 0x1e}, + {0x413b, 0x1e}, + {0x4135, 0x1e}, + {0x412f, 0x1e}, + {0x412c, 0x1e}, + {0x4126, 0x1e}, + {0x4129, 0x1e}, + {0x4123, 0x1e}, + {0x4f00, 0x01}, + //xs9922_720p_4lanes_25fps_1500M + {0x0803, 0x03}, /////////////////////////cam0 + {0x080e, 0x0f}, + {0x0803, 0x0f}, + {0x080e, 0x3f}, + {0x080e, 0x3f}, + {0x012d, 0x3f}, + {0x012f, 0xcc}, + {0x01e2, 0x03}, + {0x0158, 0x01}, + {0x0130, 0x10}, + {0x010c, 0x01},//通道0 1: 手动模式, 0: 自动模式 + {0x010d, 0x40},//40:AHD 720@25F 41:AHD 720@30F + {0x0805, 0x05}, + {0x0e11, 0x06},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x0e12, 0x01}, + {0x060b, 0x00}, + {0x0627, 0x14}, + {0x061c, 0x00}, + {0x061d, 0x5a}, + {0x061e, 0xa5}, + {0x0640, 0x04}, + {0x0616, 0x24}, + {0x0617, 0x00}, + {0x0618, 0x04}, + {0x060a, 0x07}, + {0x010a, 0x05}, + {0x0100, 0x30}, + {0x0104, 0x48}, + {0x0802, 0x21}, + {0x0502, 0x0c}, + {0x050e, 0x1c}, + {0x1803, 0x03}, ////////////////////////cam1 + {0x180e, 0x0f}, + {0x1803, 0x0f}, + {0x180e, 0x3f}, + {0x180e, 0x3f}, + {0x112d, 0x3f}, + {0x112f, 0xcc}, + {0x11e2, 0x03}, + {0x1158, 0x01}, + {0x1130, 0x10}, + {0x110c, 0x01},//通道1 1: 手动模式, 0: 自动模式 + {0x110d, 0x40},//40:AHD 720@25F 41:AHD 720@30F + {0x1805, 0x05}, + {0x1e11, 0x06},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x1e12, 0x01}, + {0x160b, 0x00}, + {0x1627, 0x14}, + {0x161c, 0x00}, + {0x161d, 0x5a}, + {0x161e, 0xa5}, + {0x1640, 0x04}, + {0x1616, 0x24}, + {0x1617, 0x00}, + {0x1618, 0x04}, + {0x160a, 0x07}, + {0x110a, 0x05}, + {0x1100, 0x30}, + {0x1104, 0x48}, + {0x1802, 0x21}, + {0x1502, 0x0d}, + {0x150e, 0x1d}, + {0x2803, 0x03}, ////////////////////////cam2 + {0x280e, 0x0f}, + {0x2803, 0x0f}, + {0x280e, 0x3f}, + {0x280e, 0x3f}, + {0x212d, 0x3f}, + {0x212f, 0xcc}, + {0x21e2, 0x03}, + {0x2158, 0x01}, + {0x2130, 0x10}, + {0x210c, 0x01},//通道2 1: 手动模式, 0: 自动模式 + {0x210d, 0x40},//40:AHD 720@25F 41:AHD 720@30F + {0x2805, 0x05}, + {0x2e11, 0x06},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x2e12, 0x01}, + {0x260b, 0x00}, + {0x2627, 0x14}, + {0x261c, 0x00}, + {0x261d, 0x5a}, + {0x261e, 0xa5}, + {0x2640, 0x04}, + {0x2616, 0x24}, + {0x2617, 0x00}, + {0x2618, 0x04}, + {0x260a, 0x07}, + {0x210a, 0x05}, + {0x2100, 0x30}, + {0x2104, 0x48}, + {0x2802, 0x21}, + {0x2502, 0x0e}, + {0x250e, 0x1e}, + {0x3803, 0x03}, ////////////////////////cam3 + {0x380e, 0x0f}, + {0x3803, 0x0f}, + {0x380e, 0x3f}, + {0x380e, 0x3f}, + {0x312d, 0x3f}, + {0x312f, 0xcc}, + {0x31e2, 0x03}, + {0x3158, 0x01}, + {0x3130, 0x10}, + {0x310c, 0x01},//通道3 1: 手动模式, 0: 自动模式 + {0x310d, 0x40},//40:AHD 720@25F 41:AHD 720@30F + {0x3805, 0x05}, + {0x3e11, 0x06},//彩条模式, 00-08, 白黄青绿粉红蓝黑彩条 + {0x3e12, 0x01}, + {0x360b, 0x00}, + {0x3627, 0x14}, + {0x361c, 0x00}, + {0x361d, 0x5a}, + {0x361e, 0xa5}, + {0x3640, 0x04}, + {0x3616, 0x24}, + {0x3617, 0x00}, + {0x3618, 0x04}, + {0x360a, 0x07}, + {0x310a, 0x05}, + {0x3100, 0x38}, + {0x3104, 0x48}, + {0x3802, 0x21}, + {0x3502, 0x0f}, + {0x350e, 0x1f}, + //adc rst + {0x080e, 0x08}, + {0x0803, 0x0e}, + {0x0803, 0x0f}, + {0x080e, 0x28}, + {0x180e, 0x08}, + {0x1803, 0x0e}, + {0x1803, 0x0f}, + {0x180e, 0x28}, + {0x280e, 0x08}, + {0x2803, 0x0e}, + {0x2803, 0x0f}, + {0x280e, 0x28}, + {0x380e, 0x08}, + {0x3803, 0x0e}, + {0x3803, 0x0f}, + {0x380e, 0x28}, + {0x0e08, 0x01},//通道0 1: 开启, 0: 关闭 + {0x1e08, 0x01},//通道1 1: 开启, 0: 关闭 + {0x2e08, 0x01},//通道2 1: 开启, 0: 关闭 + {0x3e08, 0x01},//通道3 1: 开启, 0: 关闭 + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x00}, + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, + + //adc rst ------------------- + {0x080e, 0x08}, + {0x0803, 0x0e}, + {0x0803, 0x0f}, + {0x080e, 0x28}, + //adc rst + {0x080e, 0x08}, + {0x0803, 0x0e}, + {0x0803, 0x0f}, + {0x080e, 0x28}, + + {REG_NULL, 0x0,}, +}; +#endif + + + +static k_sensor_mode xs9922b_mode_info[] = { + { + .index = 0, + .sensor_type = XS9950_MIPI_CSI2_1280X720_30FPS_YUV422, //XS9922B_MIPI_CSI0_1280X720_30FPS_YUV422_DOL3, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_HDR_STITCH, + .stitching_mode = SENSOR_STITCHING_3DOL, + .bit_width = 8, + .bayer_pattern = BAYER_PAT_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 4, + .data_type = 0x1e, + }, + .reg_list = xs9922b_mipi4lane_720p_30fps_linear, + .mclk_setting = {{K_FALSE}, {K_FALSE}, {K_FALSE}}, + }, +}; + +static k_bool xs9922b_init_flag = K_FALSE; +static k_sensor_mode *current_mode = NULL; + +static int xs9922b_power_rest(k_s32 on) +{ + #define VICAP_XS9922B_RST_GPIO (0) //24// + + kd_pin_mode(VICAP_XS9922B_RST_GPIO, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(VICAP_XS9922B_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9922B_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9922B_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(VICAP_XS9922B_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + + +static int xs9922b_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + + +static k_s32 xs9922b_sensor_get_chip_id(void *ctx, k_u32 *chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter\n", __func__); + + xs9922b_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, XS9922B_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, XS9922B_REG_CHIP_ID_L, &id_low); + if (ret) { + // pr_err("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + rt_kprintf("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + + +static k_s32 xs9922b_sensor_power_on(void *ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + // if (!xs9922b_init_flag) { + xs9922b_power_rest(on); + xs9922b_i2c_init(&dev->i2c_info); + // } + ret = xs9922b_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + xs9922b_init_flag = K_FALSE; + xs9922b_power_rest(on); + } + + return ret; +} + +static k_s32 xs9922b_sensor_init(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(xs9922b_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9922b_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(xs9922b_mode_info[i]); + dev->sensor_mode = &(xs9922b_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + case 0: + case 1: + case 2: + case 3: + case 6: + // if (!xs9922b_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + // } + k_u16 reg_val = 0; + k_u32 reg_adr = 0x511b; + ret = sensor_reg_read(&dev->i2c_info, reg_adr, ®_val); + printf("write reg success ----------0x511b----mipi rata is %x----------\n", reg_val); + + reg_adr = 0x0e08; + ret = sensor_reg_read(&dev->i2c_info, reg_adr, ®_val); + printf(" reg --0x0e08 is %x----------\n", reg_val); + + reg_adr = 0x0e02; + ret = sensor_reg_read(&dev->i2c_info, reg_adr, ®_val); + printf(" reg --0x0e02 is %x----------\n", reg_val); + + reg_adr = 0x1e02; + ret = sensor_reg_read(&dev->i2c_info, reg_adr, ®_val); + printf(" reg --0x1e02 is %x----------\n", reg_val); + + current_mode->ae_info.frame_length = 2193; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000152;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.0; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9922B_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 165; //2.5ms //197; // 3ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + current_mode->ae_info.cur_fps = current_mode->fps; + break; + + case 4: + case 5: + case 7: + if (!xs9922b_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + } + + + + current_mode->ae_info.frame_length = 1915; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000087;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.2; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9922B_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 287; // 2.5ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + + default: + break; + } + + k_u16 again_h; + k_u16 again_l; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + float again = 0, dgain = 0; + + // ret = sensor_reg_read(&dev->i2c_info, XS9922B_REG_LONG_AGAIN, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9922B_REG_LONG_AGAIN_H, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9922B_REG_LONG_AGAIN_L, &again_l); + again = 1.0;// (float)again_h / 16.0f; + + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + // ret = sensor_reg_read(&dev->i2c_info, XS9922B_REG_LONG_EXP_TIME_H, &exp_time_h); + // ret = sensor_reg_read(&dev->i2c_info, XS9922B_REG_LONG_EXP_TIME_L, &exp_time_l); + exp_time = (exp_time_h << 4) | ((exp_time_l >> 4) & 0x0F); + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + xs9922b_init_flag = K_TRUE; + + return ret; +} + + +k_s32 xs9922b_sensor_get_mode(void *ctx, k_sensor_mode *mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(xs9922b_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9922b_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &xs9922b_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(xs9922b_mode_info[i]); + return 0; + } + } + pr_info("%s, the mode not exit.\n", __func__); + + return ret; +} + +k_s32 xs9922b_sensor_set_mode(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 xs9922b_sensor_enum_mode(void *ctx, k_sensor_enum_mode *enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(enum_mode, 0, sizeof(k_sensor_enum_mode)); + + return ret; +} + +k_s32 xs9922b_sensor_get_caps(void *ctx, k_sensor_caps *caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +k_s32 xs9922b_sensor_conn_check(void *ctx, k_s32 *conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +k_s32 xs9922b_sensor_set_stream(void *ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +k_s32 xs9922b_sensor_get_again(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 xs9922b_sensor_set_again(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 again; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 16 + 0.5); + //if(current_mode->sensor_again !=again) + { + // ret = sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_AGAIN,(again & 0xff)); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/16.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_L_PARAS]* 16 + 0.5); + // ret = sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_AGAIN,(again & 0xff)); + current_mode->ae_info.cur_again = (float)again/16.0f; + + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 16 + 0.5); + //TODO + current_mode->ae_info.cur_vs_again = (float)again/16.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again*1000) ); + + return ret; +} + +k_s32 xs9922b_sensor_get_dgain(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 xs9922b_sensor_set_dgain(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + //TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = (float)dgain/1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain*10000)); + + return ret; +} + +k_s32 xs9922b_sensor_get_intg_time(void *ctx, k_sensor_intg_time *time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +k_s32 xs9922b_sensor_set_intg_time(void *ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + k_u16 Strobe_StartPoint = 0; + k_u16 Strobe_Width = 0; + float integraion_time = 0; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + //if (current_mode->et_line != exp_line) + { + // ret |= sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_EXP_TIME_H, ( exp_line >> 4) & 0xff); + // ret |= sensor_reg_write(&dev->i2c_info, XS9922B_REG_LONG_EXP_TIME_L, ( exp_line << 4) & 0xf0); + current_mode->et_line = exp_line; +/* //set strobe + Strobe_Width = (exp_line + 52)/3; + Strobe_StartPoint = Sensor_VTS - Strobe_Width - 7; + //Strobe_StartPoint = Sensor_VTS - Strobe_Width; + + ret |= sensor_reg_write(&dev->i2c_info, 0x3927, ( Strobe_Width >> 8) & 0xff); //strobe width + ret |= sensor_reg_write(&dev->i2c_info, 0x3928, Strobe_Width & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, 0x3929, ( Strobe_StartPoint >> 8) & 0xff); //strobe start point + ret |= sensor_reg_write(&dev->i2c_info, 0x392a, Strobe_StartPoint & 0xff);*/ + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n",\ + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +k_s32 xs9922b_sensor_get_exp_parm(void *ctx, k_sensor_exposure_param *exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +k_s32 xs9922b_sensor_set_exp_parm(void *ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 xs9922b_sensor_get_fps(void *ctx, k_u32 *fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = 30000; + + return ret; +} + +k_s32 xs9922b_sensor_set_fps(void *ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 xs9922b_sensor_get_isp_status(void *ctx, k_sensor_isp_status *staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +k_s32 xs9922b_sensor_set_blc(void *ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 xs9922b_sensor_set_wb(void *ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 xs9922b_sensor_get_tpg(void *ctx, k_sensor_test_pattern *tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +k_s32 xs9922b_sensor_set_tpg(void *ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +k_s32 xs9922b_sensor_get_expand_curve(void *ctx, k_sensor_compand_curve *curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +k_s32 xs9922b_sensor_get_otp_data(void *ctx, void *data) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(data, 0, sizeof(void *)); + + return ret; +} + +static k_s32 xs9922b_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev xs9922b_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c3", //"i2c0", //"i2c3", + .slave_addr = 0x30, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "xs9922b", + .sensor_func = { + .sensor_power = xs9922b_sensor_power_on, + .sensor_init = xs9922b_sensor_init, + .sensor_get_chip_id = xs9922b_sensor_get_chip_id, + .sensor_get_mode = xs9922b_sensor_get_mode, + .sensor_set_mode = xs9922b_sensor_set_mode, + .sensor_enum_mode = xs9922b_sensor_enum_mode, + .sensor_get_caps = xs9922b_sensor_get_caps, + .sensor_conn_check = xs9922b_sensor_conn_check, + .sensor_set_stream = xs9922b_sensor_set_stream, + .sensor_get_again = xs9922b_sensor_get_again, + .sensor_set_again = xs9922b_sensor_set_again, + .sensor_get_dgain = xs9922b_sensor_get_dgain, + .sensor_set_dgain = xs9922b_sensor_set_dgain, + .sensor_get_intg_time = xs9922b_sensor_get_intg_time, + .sensor_set_intg_time = xs9922b_sensor_set_intg_time, + .sensor_get_exp_parm = xs9922b_sensor_get_exp_parm, + .sensor_set_exp_parm = xs9922b_sensor_set_exp_parm, + .sensor_get_fps = xs9922b_sensor_get_fps, + .sensor_set_fps = xs9922b_sensor_set_fps, + .sensor_get_isp_status = xs9922b_sensor_get_isp_status, + .sensor_set_blc = xs9922b_sensor_set_blc, + .sensor_set_wb = xs9922b_sensor_set_wb, + .sensor_get_tpg = xs9922b_sensor_get_tpg, + .sensor_set_tpg = xs9922b_sensor_set_tpg, + .sensor_get_expand_curve = xs9922b_sensor_get_expand_curve, + .sensor_get_otp_data = xs9922b_sensor_get_otp_data, + .sensor_mirror_set = xs9922b_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi0_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi0_drv.c new file mode 100755 index 0000000..7b9a189 --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi0_drv.c @@ -0,0 +1,1755 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" + +//#include +#include "io.h" + +// #include "gpio.h" +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#define pr_info(...) //rt_kprintf(__VA_ARGS__) +#define pr_debug(...) //rt_kprintf(__VA_ARGS__) +#define pr_warn(...) //rt_kprintf(__VA_ARGS__) +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define XS9950_REG_CHIP_ID_H 0x40f0 +#define XS9950_REG_CHIP_ID_L 0x40f1 + +#define XS9950_REG_LONG_EXP_TIME_H 0x3501 +#define XS9950_REG_LONG_EXP_TIME_L 0x3502 + +#define XS9950_REG_LONG_AGAIN 0x3509 +//#define XS9950_REG_LONG_AGAIN_H 0x350a +//#define XS9950_REG_LONG_AGAIN_L 0x350b + +#define XS9950_MIN_GAIN_STEP (1.0f/16.0f) + +#define MIPI_LAN_RATA_800 +// #define MIPI_LAN_RATA_1000 +// #define MIPI_LAN_RATA_1500 + +/* +mipi clk = 71.53 x 2 , 没有数据 + +*/ + +static const k_sensor_reg xs9950_mipi4lane_720p_25fps_linear[] = { + //xs9950_mipi_init + {0x4300, 0x05}, + {0x4300, 0x15}, + {0x4080, 0x07}, + {0x4119, 0x01}, + {0x0803, 0x00}, + {0x4020, 0x00}, + {0x080e, 0x00}, + {0x080e, 0x20}, + {0x080e, 0x28}, + {0x4020, 0x03}, + {0x0803, 0x1f}, // zs default 0x0f + {0x0100, 0x35}, + {0x0104, 0x48}, + {0x0300, 0x3f}, + {0x0105, 0xe1}, + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, + {0x0333, 0x23}, //0x23 zs default 0x09 + {0x0336, 0x9e}, + {0x0337, 0xd9}, + {0x0338, 0x0a}, + {0x01bf, 0x4e}, + {0x010e, 0x78}, + {0x010f, 0x92}, + {0x0110, 0x70}, + {0x0111, 0x40}, + // {0x01e1, 0xff}, // zs default 0xff + {0x0314, 0x66}, + {0x0130, 0x10}, + {0x0315, 0x23}, + {0x0b64, 0x02}, + {0x01e2, 0x03}, + {0x0b55, 0x80}, + {0x0b56, 0x00}, + {0x0b59, 0x04}, + {0x0b5a, 0x01}, + {0x0b5c, 0x07}, + {0x0b5e, 0x05}, + {0x0b4b, 0x10}, + {0x0b4e, 0x05}, + {0x0b51, 0x21}, + {0x0b30, 0xbc}, + {0x0b31, 0x19}, + {0x0b15, 0x03}, + {0x0b16, 0x03}, + {0x0b17, 0x03}, + {0x0b07, 0x03}, + {0x0b08, 0x05}, + {0x0b1a, 0x10}, + {0x0158, 0x03}, + {0x0a88, 0x20}, + {0x0a61, 0x09}, + {0x0a62, 0x00}, + {0x0a63, 0x0e}, + {0x0a64, 0x00}, + {0x0a65, 0xfc}, + {0x0a67, 0xe5}, + {0x0a69, 0xef}, + {0x0a6b, 0x1b}, + {0x0a6d, 0x2f}, + {0x0a6f, 0x00}, + {0x0a71, 0xc2}, + {0x0a72, 0xff}, + {0x0a73, 0xd0}, + {0x0a74, 0xff}, + {0x0a75, 0x29}, + {0x0a77, 0x57}, + {0x0a78, 0x00}, + {0x0a79, 0x10}, + {0x0a7a, 0x00}, + {0x0a7b, 0xaa}, + {0x0a7d, 0xb2}, + {0x0a7f, 0x24}, + {0x0a80, 0x00}, + {0x0a81, 0x69}, + {0x0a82, 0x00}, + {0x0802, 0x02}, + {0x0501, 0x81}, + {0x0502, 0x0c}, //zs 0x0502 default 0x00 + {0x0b74, 0xfc}, + {0x01dc, 0x01}, + {0x0804, 0x04}, + {0x4018, 0x01}, + {0x0b56, 0x01}, + {0x0b73, 0x02}, + {0x4210, 0x0c}, + {0x420b, 0x2f}, // 上边是一样的 + + {0x0504, 0x89}, // bit[4:7] free_run颜色, 取值范围:[0, 8] + {0x0507, 0x13}, // color bar bit[0] 彩条滚动 + {0x0503, 0x00}, + {0x0502, 0x0c}, //这几个是读出来的然后在做的配置 zs + + {0x015a, 0x00}, // test pattern config + {0x015b, 0x24}, + {0x015c, 0x80}, + {0x015d, 0x16}, + {0x015e, 0xd0}, + {0x015f, 0x02}, + {0x0160, 0xee}, + {0x0161, 0x02}, + {0x0165, 0x00}, + {0x0166, 0x0f}, + + {0x4030, 0x15}, + {0x4134, 0x0a}, // zs default 0x06 + {0x0803, 0x0f}, + {0x4412, 0x00}, + {0x0803, 0x1f}, + {0x10e3, 0x01}, // mipi output en + {0x10eb, 0x04}, // clk datat lan en + + {0x50fc, 0x00}, + {0x50fd, 0x00}, + {0x50fe, 0x0d}, + {0x50ff, 0x59}, + + {0x50e4, 0x00}, // lan num 0 :1lna 1 ;2lan ???? + {0x50e5, 0x00}, + {0x50e6, 0x00}, + {0x50e7, 0x01}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x32}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x0f}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + {0x5048, 0x00}, + {0x5049, 0x00}, + {0x504a, 0x03}, + {0x504b, 0xff}, + + {0x5058, 0x00}, + {0x5059, 0x00}, + {0x505a, 0x00}, + {0x505b, 0x07}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x00}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x04}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x07}, +#ifdef MIPI_LAN_RATA_1500 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x6f}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_800 + {0x1003, 0x04}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0xed}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x4a}, // mipi pll clk +#endif + {0x1001, 0xe4}, + {0x1000, 0x4d}, + {0x1001, 0xe0}, + {0x1020, 0x1e}, + {0x1020, 0x1f}, +#ifdef MIPI_LAN_RATA_1500 + {0x1045, 0xcd}, + {0x1046, 0x0c}, + {0x1047, 0x36}, + {0x1048, 0x0f}, + {0x1049, 0x59}, + {0x104a, 0x07}, + {0x1050, 0xc4}, + {0x1065, 0xcd}, + {0x1066, 0x0c}, + {0x1067, 0x0e}, + {0x1068, 0x0f}, + {0x1069, 0x59}, + {0x106a, 0x07}, + {0x1070, 0xc4}, + {0x1085, 0xcd}, + {0x1086, 0x0c}, + {0x1087, 0x0e}, + {0x1088, 0x0f}, + {0x1089, 0x59}, + {0x108a, 0x07}, + {0x1090, 0xc4}, +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1045, 0xc5}, + {0x1046, 0x40}, + {0x1047, 0x20}, + {0x1048, 0x30}, + {0x1049, 0x4f}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x40}, + {0x1067, 0x09}, + {0x1068, 0x30}, + {0x1069, 0x4f}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x40}, + {0x1087, 0x09}, + {0x1088, 0x30}, + {0x1089, 0x4f}, + {0x108a, 0x0a}, + {0x1090, 0x04}, + +#endif + +#ifdef MIPI_LAN_RATA_800 + // mipi 800M + {0x1045, 0xc5}, + {0x1046, 0x70}, + {0x1047, 0x1f}, + {0x1048, 0x18}, + {0x1049, 0x4c}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x70}, + {0x1067, 0x09}, + {0x1068, 0x18}, + {0x1069, 0x4c}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x70}, + {0x1087, 0x09}, + {0x1088, 0x18}, + {0x1089, 0x4c}, + {0x108a, 0x0a}, + {0x1090, 0x04}, +#endif + {0x1040, 0x0a}, // lane clk pn swap + {0x1060, 0x0a}, // lane 0 pn swap + {0x1080, 0x0a}, // lane 1 pn swap + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + // {0x5004, 0x00}, // zs default 0x06 + // {0x5005, 0x00}, + + {0x0800, 0x03}, // zs default 0x05 + {0x0805, 0x07}, // zs default 0x05 + + {0x4200, 0x02}, // 0x4200=2:选择VINA,0x4200=0:选择VINB,0x4200=4:选择VINC,0x4200=6:选择VIND + // {0x0111, 0x68}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4202, 0x0e}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4203, 0x04}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x0100, 0x38}, // + // {0x01ce, 0x00}, // 调整自动曝光 + +#if 1 + // xs9950_AHD_720P_25f + {0x060b, 0x00}, + {0x0627, 0x14}, + {0x010c, 0x00}, + {0x0800, 0x05}, + {0x0805, 0x05}, + {0x0b50, 0x08}, + {0x0e08, 0x00}, + {0x010d, 0x40}, + {0x010c, 0x01}, + {0x0121, 0x7a}, + {0x0122, 0x6b}, + {0x0130, 0x10}, + {0x01a9, 0x00}, + {0x01aa, 0x04}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0105, 0xc1}, // AHD制式如发现颜色饱和度异常,可选择开关0x105的bit5 + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, // AHD制式如发现颜色饱和度异常,可选择打开0x105的bit5,并微调0x117 + {0x01e2, 0x03}, + {0x420b, 0x21}, + {0x0106, 0x80}, + {0x0107, 0x00}, + {0x0108, 0x80}, + {0x0109, 0x00}, + {0x010a, 0x20}, + {0x010b, 0x00}, + {0x011d, 0x17}, + {0x0e08, 0x01}, + {0x0a60, 0x04}, + {0x0a5c, 0xf6}, + {0x0a5d, 0xc0}, + {0x0a5e, 0x2d}, + {0x0a5f, 0x1b}, + {0x0156, 0x50}, + {0x0157, 0x07}, + {0x011d, 0x17}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0503, 0x00}, + {0x015a, 0x8b}, + {0x015b, 0x0e}, + {0x015c, 0x80}, + {0x015d, 0x16}, + {0x015e, 0xd0}, + {0x015f, 0x02}, + {0x0160, 0xee}, + {0x0161, 0x02}, + {0x0165, 0x40}, + {0x0166, 0x0f}, + {0x0A00, 0xFD}, + {0x0A01, 0xFF}, + {0x0A02, 0x00}, + {0x0A03, 0x00}, + {0x0A04, 0x04}, + {0x0A05, 0x00}, + {0x0A06, 0x01}, + {0x0A07, 0x00}, + {0x0A08, 0xFB}, + {0x0A09, 0xFF}, + {0x0A0A, 0xFE}, + {0x0A0B, 0xFF}, + {0x0A0C, 0x07}, + {0x0A0D, 0x00}, + {0x0A0E, 0x03}, + {0x0A0F, 0x00}, + {0x0A10, 0xF7}, + {0x0A11, 0xFF}, + {0x0A12, 0xFA}, + {0x0A13, 0xFF}, + {0x0A14, 0x0B}, + {0x0A15, 0x00}, + {0x0A16, 0x0A}, + {0x0A17, 0x00}, + {0x0A18, 0xF3}, + {0x0A19, 0xFF}, + {0x0A1A, 0xF1}, + {0x0A1B, 0xFF}, + {0x0A1C, 0x0F}, + {0x0A1D, 0x00}, + {0x0A1E, 0x18}, + {0x0A1F, 0x00}, + {0x0A20, 0xEE}, + {0x0A21, 0xFF}, + {0x0A22, 0xDC}, + {0x0A23, 0xFF}, + {0x0A24, 0x14}, + {0x0A25, 0x00}, + {0x0A26, 0x39}, + {0x0A27, 0x00}, + {0x0A28, 0xEB}, + {0x0A29, 0xFF}, + {0x0A2A, 0x98}, + {0x0A2B, 0xFF}, + {0x0A2C, 0x16}, + {0x0A2D, 0x00}, + {0x0A2E, 0x45}, + {0x0A2F, 0x01}, + {0x0A30, 0xEA}, + {0x0A31, 0x01}, + {0x0A60, 0x01}, + /*针对某些非标AHD72如下配置*/ + {0x0AA7, 0x7A}, + {0x0AA8, 0x18}, + {0x0AA9, 0xC0}, + {0x0AAA, 0x01}, + {0x0AAB, 0xC2}, + {0x0AAC, 0x01}, + {0x0AAD, 0x80}, + {0x0AAE, 0x43}, + {0x0AAF, 0x00}, + {0x0AB0, 0x70}, + {0x0AB1, 0x00}, + {0x0AB2, 0x1B}, + {0x0A88, 0x30}, + + //xs9950_mipi_reset_new + {0x0e08, 0x01}, + // {0x1e08, 0x01}, + // {0x2e08, 0x01}, + // {0x3e08, 0x01}, + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x00}, + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, +#endif + {REG_NULL, 0x0}, +}; + +static const k_sensor_reg xs9950_mipi4lane_1080p_25fps_linear[] = { + //xs9950_mipi_init + {0x4300, 0x05}, + {0x4300, 0x15}, + {0x4080, 0x07}, + {0x4119, 0x01}, + {0x0803, 0x00}, + {0x4020, 0x00}, + {0x080e, 0x00}, + {0x080e, 0x20}, + {0x080e, 0x28}, + {0x4020, 0x03}, + {0x0803, 0x1f}, // zs default 0x0f + {0x0100, 0x35}, + {0x0104, 0x48}, + {0x0300, 0x3f}, + {0x0105, 0xe1}, + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, + {0x0333, 0x23}, //0x23 zs default 0x09 + {0x0336, 0x9e}, + {0x0337, 0xd9}, + {0x0338, 0x0a}, + {0x01bf, 0x4e}, + {0x010e, 0x78}, + {0x010f, 0x92}, + {0x0110, 0x70}, + {0x0111, 0x40}, + // {0x01e1, 0xff}, // zs default 0xff + {0x0314, 0x66}, + {0x0130, 0x10}, + {0x0315, 0x23}, + {0x0b64, 0x02}, + {0x01e2, 0x03}, + {0x0b55, 0x80}, + {0x0b56, 0x00}, + {0x0b59, 0x04}, + {0x0b5a, 0x01}, + {0x0b5c, 0x07}, + {0x0b5e, 0x05}, + {0x0b4b, 0x10}, + {0x0b4e, 0x05}, + {0x0b51, 0x21}, + {0x0b30, 0xbc}, + {0x0b31, 0x19}, + {0x0b15, 0x03}, + {0x0b16, 0x03}, + {0x0b17, 0x03}, + {0x0b07, 0x03}, + {0x0b08, 0x05}, + {0x0b1a, 0x10}, + {0x0158, 0x03}, + {0x0a88, 0x20}, + {0x0a61, 0x09}, + {0x0a62, 0x00}, + {0x0a63, 0x0e}, + {0x0a64, 0x00}, + {0x0a65, 0xfc}, + {0x0a67, 0xe5}, + {0x0a69, 0xef}, + {0x0a6b, 0x1b}, + {0x0a6d, 0x2f}, + {0x0a6f, 0x00}, + {0x0a71, 0xc2}, + {0x0a72, 0xff}, + {0x0a73, 0xd0}, + {0x0a74, 0xff}, + {0x0a75, 0x29}, + {0x0a77, 0x57}, + {0x0a78, 0x00}, + {0x0a79, 0x10}, + {0x0a7a, 0x00}, + {0x0a7b, 0xaa}, + {0x0a7d, 0xb2}, + {0x0a7f, 0x24}, + {0x0a80, 0x00}, + {0x0a81, 0x69}, + {0x0a82, 0x00}, + {0x0802, 0x02}, + {0x0501, 0x81}, + {0x0502, 0x0c}, //zs 0x0502 default 0x00 + {0x0b74, 0xfc}, + {0x01dc, 0x01}, + {0x0804, 0x04}, + {0x4018, 0x01}, + {0x0b56, 0x01}, + {0x0b73, 0x02}, + {0x4210, 0x0c}, + {0x420b, 0x2f}, // 上边是一样的 + + {0x0504, 0x89}, // bit[4:7] free_run颜色, 取值范围:[0, 8] + {0x0507, 0x13}, // color bar bit[0] 彩条滚动 + {0x0503, 0x00}, + {0x0502, 0x0c}, //这几个是读出来的然后在做的配置 zs + + {0x015a, 0x00}, // test pattern config + {0x015b, 0x24}, + {0x015c, 0x80}, + {0x015d, 0x16}, + {0x015e, 0xd0}, + {0x015f, 0x02}, + {0x0160, 0xee}, + {0x0161, 0x02}, + {0x0165, 0x00}, + {0x0166, 0x0f}, + + {0x4030, 0x15}, + {0x4134, 0x0a}, // zs default 0x06 + {0x0803, 0x0f}, + {0x4412, 0x00}, + {0x0803, 0x1f}, + {0x10e3, 0x01}, // mipi output en + {0x10eb, 0x04}, // clk datat lan en + + {0x50fc, 0x00}, + {0x50fd, 0x00}, + {0x50fe, 0x0d}, + {0x50ff, 0x59}, + + {0x50e4, 0x00}, // lan num 0 :1lna 1 ;2lan ???? + {0x50e5, 0x00}, + {0x50e6, 0x00}, + {0x50e7, 0x01}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x32}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x0f}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + {0x5048, 0x00}, + {0x5049, 0x00}, + {0x504a, 0x03}, + {0x504b, 0xff}, + + {0x5058, 0x00}, + {0x5059, 0x00}, + {0x505a, 0x00}, + {0x505b, 0x07}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x00}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x04}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x07}, +#ifdef MIPI_LAN_RATA_1500 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x6f}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_800 + {0x1003, 0x04}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0xed}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x4a}, // mipi pll clk +#endif + {0x1001, 0xe4}, + {0x1000, 0x4d}, + {0x1001, 0xe0}, + {0x1020, 0x1e}, + {0x1020, 0x1f}, +#ifdef MIPI_LAN_RATA_1500 + {0x1045, 0xcd}, + {0x1046, 0x0c}, + {0x1047, 0x36}, + {0x1048, 0x0f}, + {0x1049, 0x59}, + {0x104a, 0x07}, + {0x1050, 0xc4}, + {0x1065, 0xcd}, + {0x1066, 0x0c}, + {0x1067, 0x0e}, + {0x1068, 0x0f}, + {0x1069, 0x59}, + {0x106a, 0x07}, + {0x1070, 0xc4}, + {0x1085, 0xcd}, + {0x1086, 0x0c}, + {0x1087, 0x0e}, + {0x1088, 0x0f}, + {0x1089, 0x59}, + {0x108a, 0x07}, + {0x1090, 0xc4}, +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1045, 0xc5}, + {0x1046, 0x40}, + {0x1047, 0x20}, + {0x1048, 0x30}, + {0x1049, 0x4f}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x40}, + {0x1067, 0x09}, + {0x1068, 0x30}, + {0x1069, 0x4f}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x40}, + {0x1087, 0x09}, + {0x1088, 0x30}, + {0x1089, 0x4f}, + {0x108a, 0x0a}, + {0x1090, 0x04}, + +#endif + +#ifdef MIPI_LAN_RATA_800 + // mipi 800M + {0x1045, 0xc5}, + {0x1046, 0x70}, + {0x1047, 0x1f}, + {0x1048, 0x18}, + {0x1049, 0x4c}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x70}, + {0x1067, 0x09}, + {0x1068, 0x18}, + {0x1069, 0x4c}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x70}, + {0x1087, 0x09}, + {0x1088, 0x18}, + {0x1089, 0x4c}, + {0x108a, 0x0a}, + {0x1090, 0x04}, +#endif + {0x1040, 0x0a}, // lane clk pn swap + {0x1060, 0x0a}, // lane 0 pn swap + {0x1080, 0x0a}, // lane 1 pn swap + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + // {0x5004, 0x00}, // zs default 0x06 + // {0x5005, 0x00}, + + {0x0800, 0x03}, // zs default 0x05 + {0x0805, 0x07}, // zs default 0x05 + + {0x4200, 0x02}, // 0x4200=2:选择VINA,0x4200=0:选择VINB,0x4200=4:选择VINC,0x4200=6:选择VIND + // {0x0111, 0x68}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4202, 0x0e}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4203, 0x04}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x0100, 0x38}, // + // {0x01ce, 0x00}, // 调整自动曝光 + +#if 1 + +#if 1 + //xs9950_AHD_1080P_25f + {0x060b, 0x00}, + {0x0627, 0x14}, + {0x010c, 0x00}, + {0x0800, 0x05}, + {0x0805, 0x05}, + {0x0b50, 0x08}, + {0x0e08, 0x00}, + {0x010d, 0x44}, + {0x010c, 0x01}, + {0x0121, 0x7a}, + {0x0122, 0x6b}, + {0x0130, 0x10}, + {0x01a9, 0x00}, + {0x01aa, 0x04}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0105, 0xc1}, + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, + {0x01e2, 0x03}, + {0x420b, 0x21}, + {0x0106, 0x80}, + {0x0107, 0x00}, + {0x0108, 0x80}, + {0x0109, 0x00}, + {0x010a, 0x1b}, + {0x010b, 0x01}, + {0x011d, 0x17}, + {0x0e08, 0x01}, + {0x0a60, 0x04}, + {0x0a5c, 0x56}, + {0x0a5d, 0x00}, + {0x0a5e, 0xe7}, + {0x0a5f, 0x38}, + {0x0156, 0x50}, + {0x0157, 0x07}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0503, 0x04}, + {0x015a, 0xd1}, + {0x015b, 0x15}, + {0x015c, 0x00}, + {0x015d, 0x0f}, + {0x015e, 0x38}, + {0x015f, 0x04}, + {0x0160, 0x65}, + {0x0161, 0x04}, + {0x0165, 0x44}, + {0x0166, 0x0f}, + {0x0A00, 0x00}, + {0x0A01, 0x00}, + {0x0A02, 0xFE}, + {0x0A03, 0xFF}, + {0x0A04, 0x04}, + {0x0A05, 0x00}, + {0x0A06, 0xFD}, + {0x0A07, 0xFF}, + {0x0A08, 0x00}, + {0x0A09, 0x00}, + {0x0A0A, 0x04}, + {0x0A0B, 0x00}, + {0x0A0C, 0xF9}, + {0x0A0D, 0xFF}, + {0x0A0E, 0x06}, + {0x0A0F, 0x00}, + {0x0A10, 0x00}, + {0x0A11, 0x00}, + {0x0A12, 0xF8}, + {0x0A13, 0xFF}, + {0x0A14, 0x0E}, + {0x0A15, 0x00}, + {0x0A16, 0xF5}, + {0x0A17, 0xFF}, + {0x0A18, 0x00}, + {0x0A19, 0x00}, + {0x0A1A, 0x0F}, + {0x0A1B, 0x00}, + {0x0A1C, 0xE7}, + {0x0A1D, 0xFF}, + {0x0A1E, 0x14}, + {0x0A1F, 0x00}, + {0x0A20, 0x00}, + {0x0A21, 0x00}, + {0x0A22, 0xE3}, + {0x0A23, 0xFF}, + {0x0A24, 0x31}, + {0x0A25, 0x00}, + {0x0A26, 0xD5}, + {0x0A27, 0xFF}, + {0x0A28, 0x00}, + {0x0A29, 0x00}, + {0x0A2A, 0x4B}, + {0x0A2B, 0x00}, + {0x0A2C, 0x5F}, + {0x0A2D, 0xFF}, + {0x0A2E, 0xE6}, + {0x0A2F, 0x00}, + {0x0A30, 0x00}, + {0x0A31, 0x03}, + {0x0A60, 0x01}, +#else + //xs9950_AHD_1080P_30f + {0x060b, 0x00}, + {0x0627, 0x14}, + {0x010c, 0x00}, + {0x0800, 0x05}, + {0x0805, 0x05}, + {0x0b50, 0x08}, + {0x0e08, 0x00}, + {0x010d, 0x45}, + {0x010c, 0x01}, + {0x0121, 0x7a}, + {0x0122, 0x6b}, + {0x0130, 0x10}, + {0x01a9, 0x00}, + {0x01aa, 0x04}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0105, 0xc1}, + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, + {0x01e2, 0x03}, + {0x420b, 0x21}, + {0x0106, 0x80}, + {0x0107, 0x00}, + {0x0108, 0x80}, + {0x0109, 0x00}, + {0x010a, 0x1b}, + {0x010b, 0x01}, + {0x011d, 0x17}, + {0x0e08, 0x01}, + {0x0a60, 0x04}, + {0x0a5c, 0x3c}, + {0x0a5d, 0x10}, + {0x0a5e, 0xec}, + {0x0a5f, 0x38}, + {0x0156, 0x50}, + {0x0157, 0x07}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0503, 0x05}, + {0x015a, 0xd1}, + {0x015b, 0x15}, + {0x015c, 0x80}, + {0x015d, 0x0c}, + {0x015e, 0x38}, + {0x015f, 0x04}, + {0x0160, 0x65}, + {0x0161, 0x04}, + {0x0165, 0x45}, + {0x0166, 0x0f}, + {0x0A00, 0x00}, + {0x0A01, 0x00}, + {0x0A02, 0xFE}, + {0x0A03, 0xFF}, + {0x0A04, 0x04}, + {0x0A05, 0x00}, + {0x0A06, 0xFD}, + {0x0A07, 0xFF}, + {0x0A08, 0x00}, + {0x0A09, 0x00}, + {0x0A0A, 0x04}, + {0x0A0B, 0x00}, + {0x0A0C, 0xF9}, + {0x0A0D, 0xFF}, + {0x0A0E, 0x06}, + {0x0A0F, 0x00}, + {0x0A10, 0x00}, + {0x0A11, 0x00}, + {0x0A12, 0xF8}, + {0x0A13, 0xFF}, + {0x0A14, 0x0E}, + {0x0A15, 0x00}, + {0x0A16, 0xF5}, + {0x0A17, 0xFF}, + {0x0A18, 0x00}, + {0x0A19, 0x00}, + {0x0A1A, 0x0F}, + {0x0A1B, 0x00}, + {0x0A1C, 0xE7}, + {0x0A1D, 0xFF}, + {0x0A1E, 0x14}, + {0x0A1F, 0x00}, + {0x0A20, 0x00}, + {0x0A21, 0x00}, + {0x0A22, 0xE3}, + {0x0A23, 0xFF}, + {0x0A24, 0x31}, + {0x0A25, 0x00}, + {0x0A26, 0xD5}, + {0x0A27, 0xFF}, + {0x0A28, 0x00}, + {0x0A29, 0x00}, + {0x0A2A, 0x4B}, + {0x0A2B, 0x00}, + {0x0A2C, 0x5F}, + {0x0A2D, 0xFF}, + {0x0A2E, 0xE6}, + {0x0A2F, 0x00}, + {0x0A30, 0x00}, + {0x0A31, 0x03}, + {0x0A60, 0x01}, + +#endif + //xs9950_mipi_reset_new + {0x0e08, 0x01}, + // {0x1e08, 0x01}, + // {0x2e08, 0x01}, + // {0x3e08, 0x01}, + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x00}, + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, +#endif + {REG_NULL, 0x0}, +}; + + +static k_sensor_mode xs9950_mode_info[] = { + { + .index = 0, + .sensor_type = XS9950_MIPI_CSI0_1280X720_30FPS_YUV422, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_HDR_STITCH, + .stitching_mode = SENSOR_STITCHING_3DOL, + .bit_width = 8, + .bayer_pattern = BAYER_PAT_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 4, + .data_type = 0x1e, + }, + .reg_list = xs9950_mipi4lane_720p_25fps_linear, + .mclk_setting = { + { + .mclk_setting_en = K_FALSE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, + + { + .index = 1, + .sensor_type = XS9950_MIPI_CSI0_1920X1080_30FPS_YUV422, + .size = { + .bounds_width = 1920, + .bounds_height = 1080, + .top = 0, + .left = 0, + .width = 1920, + .height = 1080, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_HDR_STITCH, + .stitching_mode = SENSOR_STITCHING_3DOL, + .bit_width = 8, + .bayer_pattern = BAYER_PAT_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 4, + .data_type = 0x1e, + }, + .reg_list = xs9950_mipi4lane_1080p_25fps_linear, + .mclk_setting = { + { + .mclk_setting_en = K_FALSE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, +}; + +static k_bool xs9950_init_flag = K_FALSE; +static k_sensor_mode *current_mode = NULL; + +static int xs9950_power_rest(k_s32 on) +{ + #define VICAP_XS9950_RST_GPIO (0) //24// + + kd_pin_mode(VICAP_XS9950_RST_GPIO, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + + +static int xs9950_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + +static k_s32 xs9950_sensor_get_chip_id(void *ctx, k_u32 *chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter\n", __func__); + + xs9950_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, XS9950_REG_CHIP_ID_L, &id_low); + if (ret) { + // pr_err("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + rt_kprintf("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + + + +static k_s32 xs9950_sensor_power_on(void *ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + // if (!xs9950_init_flag) { + xs9950_power_rest(on); + xs9950_i2c_init(&dev->i2c_info); + // } + ret = xs9950_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + xs9950_init_flag = K_FALSE; + xs9950_power_rest(on); + } + + return ret; +} + +static k_s32 xs9950_sensor_init(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(xs9950_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9950_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(xs9950_mode_info[i]); + dev->sensor_mode = &(xs9950_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + case 0: + case 1: + case 2: + case 3: + case 6: + + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + + current_mode->ae_info.frame_length = 2193; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000152;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.0; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9950_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 165; //2.5ms //197; // 3ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + current_mode->ae_info.cur_fps = current_mode->fps; + break; + + case 4: + case 5: + case 7: + if (!xs9950_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + } + + + + current_mode->ae_info.frame_length = 1915; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000087;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.2; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9950_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 287; // 2.5ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + + default: + break; + } + + k_u16 again_h; + k_u16 again_l; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + float again = 0, dgain = 0; + + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L, &again_l); + again = 1.0;// (float)again_h / 16.0f; + + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_H, &exp_time_h); + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_L, &exp_time_l); + exp_time = (exp_time_h << 4) | ((exp_time_l >> 4) & 0x0F); + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + xs9950_init_flag = K_TRUE; + + return ret; +} + + +static k_s32 xs9950_sensor_get_mode(void *ctx, k_sensor_mode *mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(xs9950_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9950_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &xs9950_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(xs9950_mode_info[i]); + return 0; + } + } + pr_info("%s, the mode not exit.\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_set_mode(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_enum_mode(void *ctx, k_sensor_enum_mode *enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(enum_mode, 0, sizeof(k_sensor_enum_mode)); + + return ret; +} + +static k_s32 xs9950_sensor_get_caps(void *ctx, k_sensor_caps *caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +static k_s32 xs9950_sensor_conn_check(void *ctx, k_s32 *conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +static k_s32 xs9950_sensor_set_stream(void *ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +static k_s32 xs9950_sensor_get_again(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_again(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 again; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 16 + 0.5); + //if(current_mode->sensor_again !=again) + { + // ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN,(again & 0xff)); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/16.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_L_PARAS]* 16 + 0.5); + // ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN,(again & 0xff)); + current_mode->ae_info.cur_again = (float)again/16.0f; + + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 16 + 0.5); + //TODO + current_mode->ae_info.cur_vs_again = (float)again/16.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again*1000) ); + + return ret; +} + +static k_s32 xs9950_sensor_get_dgain(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_dgain(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + //TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = (float)dgain/1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain*10000)); + + return ret; +} + +static k_s32 xs9950_sensor_get_intg_time(void *ctx, k_sensor_intg_time *time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_intg_time(void *ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + k_u16 Strobe_StartPoint = 0; + k_u16 Strobe_Width = 0; + float integraion_time = 0; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + //if (current_mode->et_line != exp_line) + { + // ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_H, ( exp_line >> 4) & 0xff); + // ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_L, ( exp_line << 4) & 0xf0); + current_mode->et_line = exp_line; +/* //set strobe + Strobe_Width = (exp_line + 52)/3; + Strobe_StartPoint = Sensor_VTS - Strobe_Width - 7; + //Strobe_StartPoint = Sensor_VTS - Strobe_Width; + + ret |= sensor_reg_write(&dev->i2c_info, 0x3927, ( Strobe_Width >> 8) & 0xff); //strobe width + ret |= sensor_reg_write(&dev->i2c_info, 0x3928, Strobe_Width & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, 0x3929, ( Strobe_StartPoint >> 8) & 0xff); //strobe start point + ret |= sensor_reg_write(&dev->i2c_info, 0x392a, Strobe_StartPoint & 0xff);*/ + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n",\ + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +static k_s32 xs9950_sensor_get_exp_parm(void *ctx, k_sensor_exposure_param *exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +static k_s32 xs9950_sensor_set_exp_parm(void *ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_fps(void *ctx, k_u32 *fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = 30000; + + return ret; +} + +static k_s32 xs9950_sensor_set_fps(void *ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_isp_status(void *ctx, k_sensor_isp_status *staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +static k_s32 xs9950_sensor_set_blc(void *ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_set_wb(void *ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_tpg(void *ctx, k_sensor_test_pattern *tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +static k_s32 xs9950_sensor_set_tpg(void *ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_expand_curve(void *ctx, k_sensor_compand_curve *curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +static k_s32 xs9950_sensor_get_otp_data(void *ctx, void *data) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(data, 0, sizeof(void *)); + + return ret; +} + +static k_s32 xs9950_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev xs9950_csi0_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c3", //"i2c0", //"i2c3", + .slave_addr = 0x30, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "xs9950_csi0", + .sensor_func = { + .sensor_power = xs9950_sensor_power_on, + .sensor_init = xs9950_sensor_init, + .sensor_get_chip_id = xs9950_sensor_get_chip_id, + .sensor_get_mode = xs9950_sensor_get_mode, + .sensor_set_mode = xs9950_sensor_set_mode, + .sensor_enum_mode = xs9950_sensor_enum_mode, + .sensor_get_caps = xs9950_sensor_get_caps, + .sensor_conn_check = xs9950_sensor_conn_check, + .sensor_set_stream = xs9950_sensor_set_stream, + .sensor_get_again = xs9950_sensor_get_again, + .sensor_set_again = xs9950_sensor_set_again, + .sensor_get_dgain = xs9950_sensor_get_dgain, + .sensor_set_dgain = xs9950_sensor_set_dgain, + .sensor_get_intg_time = xs9950_sensor_get_intg_time, + .sensor_set_intg_time = xs9950_sensor_set_intg_time, + .sensor_get_exp_parm = xs9950_sensor_get_exp_parm, + .sensor_set_exp_parm = xs9950_sensor_set_exp_parm, + .sensor_get_fps = xs9950_sensor_get_fps, + .sensor_set_fps = xs9950_sensor_set_fps, + .sensor_get_isp_status = xs9950_sensor_get_isp_status, + .sensor_set_blc = xs9950_sensor_set_blc, + .sensor_set_wb = xs9950_sensor_set_wb, + .sensor_get_tpg = xs9950_sensor_get_tpg, + .sensor_set_tpg = xs9950_sensor_set_tpg, + .sensor_get_expand_curve = xs9950_sensor_get_expand_curve, + .sensor_get_otp_data = xs9950_sensor_get_otp_data, + .sensor_mirror_set = xs9950_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi1_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi1_drv.c new file mode 100755 index 0000000..43ae6dc --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi1_drv.c @@ -0,0 +1,1208 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" + +//#include +#include "io.h" + +// #include "gpio.h" +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#define pr_info(...) //rt_kprintf(__VA_ARGS__) +#define pr_debug(...) //rt_kprintf(__VA_ARGS__) +#define pr_warn(...) //rt_kprintf(__VA_ARGS__) +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define XS9950_REG_CHIP_ID_H 0x40f0 +#define XS9950_REG_CHIP_ID_L 0x40f1 + +#define XS9950_REG_LONG_EXP_TIME_H 0x3501 +#define XS9950_REG_LONG_EXP_TIME_L 0x3502 + +#define XS9950_REG_LONG_AGAIN 0x3509 +//#define XS9950_REG_LONG_AGAIN_H 0x350a +//#define XS9950_REG_LONG_AGAIN_L 0x350b + +#define XS9950_MIN_GAIN_STEP (1.0f/16.0f) + +#define MIPI_LAN_RATA_800 +// #define MIPI_LAN_RATA_1000 +// #define MIPI_LAN_RATA_1500 + +/* +mipi clk = 71.53 x 2 , 没有数据 + +*/ + +static const k_sensor_reg xs9950_mipi4lane_720p_25fps_linear[] = { + //xs9950_mipi_init + {0x4300, 0x05}, + {0x4300, 0x15}, + {0x4080, 0x07}, + {0x4119, 0x01}, + {0x0803, 0x00}, + {0x4020, 0x00}, + {0x080e, 0x00}, + {0x080e, 0x20}, + {0x080e, 0x28}, + {0x4020, 0x03}, + {0x0803, 0x1f}, // zs default 0x0f + {0x0100, 0x35}, + {0x0104, 0x48}, + {0x0300, 0x3f}, + {0x0105, 0xe1}, + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, + {0x0333, 0x23}, //0x23 zs default 0x09 + {0x0336, 0x9e}, + {0x0337, 0xd9}, + {0x0338, 0x0a}, + {0x01bf, 0x4e}, + {0x010e, 0x78}, + {0x010f, 0x92}, + {0x0110, 0x70}, + {0x0111, 0x40}, + // {0x01e1, 0xff}, // zs default 0xff + {0x0314, 0x66}, + {0x0130, 0x10}, + {0x0315, 0x23}, + {0x0b64, 0x02}, + {0x01e2, 0x03}, + {0x0b55, 0x80}, + {0x0b56, 0x00}, + {0x0b59, 0x04}, + {0x0b5a, 0x01}, + {0x0b5c, 0x07}, + {0x0b5e, 0x05}, + {0x0b4b, 0x10}, + {0x0b4e, 0x05}, + {0x0b51, 0x21}, + {0x0b30, 0xbc}, + {0x0b31, 0x19}, + {0x0b15, 0x03}, + {0x0b16, 0x03}, + {0x0b17, 0x03}, + {0x0b07, 0x03}, + {0x0b08, 0x05}, + {0x0b1a, 0x10}, + {0x0158, 0x03}, + {0x0a88, 0x20}, + {0x0a61, 0x09}, + {0x0a62, 0x00}, + {0x0a63, 0x0e}, + {0x0a64, 0x00}, + {0x0a65, 0xfc}, + {0x0a67, 0xe5}, + {0x0a69, 0xef}, + {0x0a6b, 0x1b}, + {0x0a6d, 0x2f}, + {0x0a6f, 0x00}, + {0x0a71, 0xc2}, + {0x0a72, 0xff}, + {0x0a73, 0xd0}, + {0x0a74, 0xff}, + {0x0a75, 0x29}, + {0x0a77, 0x57}, + {0x0a78, 0x00}, + {0x0a79, 0x10}, + {0x0a7a, 0x00}, + {0x0a7b, 0xaa}, + {0x0a7d, 0xb2}, + {0x0a7f, 0x24}, + {0x0a80, 0x00}, + {0x0a81, 0x69}, + {0x0a82, 0x00}, + {0x0802, 0x02}, + {0x0501, 0x81}, + {0x0502, 0x0c}, //zs 0x0502 default 0x00 + {0x0b74, 0xfc}, + {0x01dc, 0x01}, + {0x0804, 0x04}, + {0x4018, 0x01}, + {0x0b56, 0x01}, + {0x0b73, 0x02}, + {0x4210, 0x0c}, + {0x420b, 0x2f}, // 上边是一样的 + + {0x0504, 0x89}, // bit[4:7] free_run颜色, 取值范围:[0, 8] + {0x0507, 0x13}, // color bar bit[0] 彩条滚动 + {0x0503, 0x00}, + {0x0502, 0x0c}, //这几个是读出来的然后在做的配置 zs + + {0x015a, 0x00}, // test pattern config + {0x015b, 0x24}, + {0x015c, 0x80}, + {0x015d, 0x16}, + {0x015e, 0xd0}, + {0x015f, 0x02}, + {0x0160, 0xee}, + {0x0161, 0x02}, + {0x0165, 0x00}, + {0x0166, 0x0f}, + + {0x4030, 0x15}, + {0x4134, 0x0a}, // zs default 0x06 + {0x0803, 0x0f}, + {0x4412, 0x00}, + {0x0803, 0x1f}, + {0x10e3, 0x01}, // mipi output en + {0x10eb, 0x04}, // clk datat lan en + + {0x50fc, 0x00}, + {0x50fd, 0x00}, + {0x50fe, 0x0d}, + {0x50ff, 0x59}, + + {0x50e4, 0x00}, // lan num 0 :1lna 1 ;2lan ???? + {0x50e5, 0x00}, + {0x50e6, 0x00}, + {0x50e7, 0x01}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x32}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x0f}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + {0x5048, 0x00}, + {0x5049, 0x00}, + {0x504a, 0x03}, + {0x504b, 0xff}, + + {0x5058, 0x00}, + {0x5059, 0x00}, + {0x505a, 0x00}, + {0x505b, 0x07}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x00}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x04}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x07}, +#ifdef MIPI_LAN_RATA_1500 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x6f}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_800 + {0x1003, 0x04}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0xed}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x4a}, // mipi pll clk +#endif + {0x1001, 0xe4}, + {0x1000, 0x4d}, + {0x1001, 0xe0}, + {0x1020, 0x1e}, + {0x1020, 0x1f}, +#ifdef MIPI_LAN_RATA_1500 + {0x1045, 0xcd}, + {0x1046, 0x0c}, + {0x1047, 0x36}, + {0x1048, 0x0f}, + {0x1049, 0x59}, + {0x104a, 0x07}, + {0x1050, 0xc4}, + {0x1065, 0xcd}, + {0x1066, 0x0c}, + {0x1067, 0x0e}, + {0x1068, 0x0f}, + {0x1069, 0x59}, + {0x106a, 0x07}, + {0x1070, 0xc4}, + {0x1085, 0xcd}, + {0x1086, 0x0c}, + {0x1087, 0x0e}, + {0x1088, 0x0f}, + {0x1089, 0x59}, + {0x108a, 0x07}, + {0x1090, 0xc4}, +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1045, 0xc5}, + {0x1046, 0x40}, + {0x1047, 0x20}, + {0x1048, 0x30}, + {0x1049, 0x4f}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x40}, + {0x1067, 0x09}, + {0x1068, 0x30}, + {0x1069, 0x4f}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x40}, + {0x1087, 0x09}, + {0x1088, 0x30}, + {0x1089, 0x4f}, + {0x108a, 0x0a}, + {0x1090, 0x04}, + +#endif + +#ifdef MIPI_LAN_RATA_800 + // mipi 800M + {0x1045, 0xc5}, + {0x1046, 0x70}, + {0x1047, 0x1f}, + {0x1048, 0x18}, + {0x1049, 0x4c}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x70}, + {0x1067, 0x09}, + {0x1068, 0x18}, + {0x1069, 0x4c}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x70}, + {0x1087, 0x09}, + {0x1088, 0x18}, + {0x1089, 0x4c}, + {0x108a, 0x0a}, + {0x1090, 0x04}, +#endif + {0x1040, 0x0a}, // lane clk pn swap + {0x1060, 0x0a}, // lane 0 pn swap + {0x1080, 0x0a}, // lane 1 pn swap + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + // {0x5004, 0x00}, // zs default 0x06 + // {0x5005, 0x00}, + + {0x0800, 0x03}, // zs default 0x05 + {0x0805, 0x07}, // zs default 0x05 + + {0x4200, 0x02}, // 0x4200=2:选择VINA,0x4200=0:选择VINB,0x4200=4:选择VINC,0x4200=6:选择VIND + // {0x0111, 0x68}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4202, 0x0e}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4203, 0x04}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x0100, 0x38}, // + // {0x01ce, 0x00}, // 调整自动曝光 + +#if 1 + // xs9950_AHD_720P_25f + {0x060b, 0x00}, + {0x0627, 0x14}, + {0x010c, 0x00}, + {0x0800, 0x05}, + {0x0805, 0x05}, + {0x0b50, 0x08}, + {0x0e08, 0x00}, + {0x010d, 0x40}, + {0x010c, 0x01}, + {0x0121, 0x7a}, + {0x0122, 0x6b}, + {0x0130, 0x10}, + {0x01a9, 0x00}, + {0x01aa, 0x04}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0105, 0xc1}, // AHD制式如发现颜色饱和度异常,可选择开关0x105的bit5 + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, // AHD制式如发现颜色饱和度异常,可选择打开0x105的bit5,并微调0x117 + {0x01e2, 0x03}, + {0x420b, 0x21}, + {0x0106, 0x80}, + {0x0107, 0x00}, + {0x0108, 0x80}, + {0x0109, 0x00}, + {0x010a, 0x20}, + {0x010b, 0x00}, + {0x011d, 0x17}, + {0x0e08, 0x01}, + {0x0a60, 0x04}, + {0x0a5c, 0xf6}, + {0x0a5d, 0xc0}, + {0x0a5e, 0x2d}, + {0x0a5f, 0x1b}, + {0x0156, 0x50}, + {0x0157, 0x07}, + {0x011d, 0x17}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0503, 0x00}, + {0x015a, 0x8b}, + {0x015b, 0x0e}, + {0x015c, 0x80}, + {0x015d, 0x16}, + {0x015e, 0xd0}, + {0x015f, 0x02}, + {0x0160, 0xee}, + {0x0161, 0x02}, + {0x0165, 0x40}, + {0x0166, 0x0f}, + {0x0A00, 0xFD}, + {0x0A01, 0xFF}, + {0x0A02, 0x00}, + {0x0A03, 0x00}, + {0x0A04, 0x04}, + {0x0A05, 0x00}, + {0x0A06, 0x01}, + {0x0A07, 0x00}, + {0x0A08, 0xFB}, + {0x0A09, 0xFF}, + {0x0A0A, 0xFE}, + {0x0A0B, 0xFF}, + {0x0A0C, 0x07}, + {0x0A0D, 0x00}, + {0x0A0E, 0x03}, + {0x0A0F, 0x00}, + {0x0A10, 0xF7}, + {0x0A11, 0xFF}, + {0x0A12, 0xFA}, + {0x0A13, 0xFF}, + {0x0A14, 0x0B}, + {0x0A15, 0x00}, + {0x0A16, 0x0A}, + {0x0A17, 0x00}, + {0x0A18, 0xF3}, + {0x0A19, 0xFF}, + {0x0A1A, 0xF1}, + {0x0A1B, 0xFF}, + {0x0A1C, 0x0F}, + {0x0A1D, 0x00}, + {0x0A1E, 0x18}, + {0x0A1F, 0x00}, + {0x0A20, 0xEE}, + {0x0A21, 0xFF}, + {0x0A22, 0xDC}, + {0x0A23, 0xFF}, + {0x0A24, 0x14}, + {0x0A25, 0x00}, + {0x0A26, 0x39}, + {0x0A27, 0x00}, + {0x0A28, 0xEB}, + {0x0A29, 0xFF}, + {0x0A2A, 0x98}, + {0x0A2B, 0xFF}, + {0x0A2C, 0x16}, + {0x0A2D, 0x00}, + {0x0A2E, 0x45}, + {0x0A2F, 0x01}, + {0x0A30, 0xEA}, + {0x0A31, 0x01}, + {0x0A60, 0x01}, + /*针对某些非标AHD72如下配置*/ + {0x0AA7, 0x7A}, + {0x0AA8, 0x18}, + {0x0AA9, 0xC0}, + {0x0AAA, 0x01}, + {0x0AAB, 0xC2}, + {0x0AAC, 0x01}, + {0x0AAD, 0x80}, + {0x0AAE, 0x43}, + {0x0AAF, 0x00}, + {0x0AB0, 0x70}, + {0x0AB1, 0x00}, + {0x0AB2, 0x1B}, + {0x0A88, 0x30}, + + //xs9950_mipi_reset_new + {0x0e08, 0x01}, + // {0x1e08, 0x01}, + // {0x2e08, 0x01}, + // {0x3e08, 0x01}, + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x00}, + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, +#endif + {REG_NULL, 0x0}, +}; + + +static k_sensor_mode xs9950_mode_info[] = { + { + .index = 0, + .sensor_type = XS9950_MIPI_CSI1_1280X720_30FPS_YUV422, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_HDR_STITCH, + .stitching_mode = SENSOR_STITCHING_3DOL, + .bit_width = 8, + .bayer_pattern = BAYER_PAT_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 4, + .data_type = 0x1e, + }, + .reg_list = xs9950_mipi4lane_720p_25fps_linear, + .mclk_setting = { + { + .mclk_setting_en = K_FALSE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, +}; + +static k_bool xs9950_init_flag = K_FALSE; +static k_sensor_mode *current_mode = NULL; + +static int xs9950_power_rest(k_s32 on) +{ + #define VICAP_XS9950_RST_GPIO (23) //24// + + kd_pin_mode(VICAP_XS9950_RST_GPIO, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + +static int xs9950_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + +static k_s32 xs9950_sensor_get_chip_id(void *ctx, k_u32 *chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter\n", __func__); + + xs9950_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, XS9950_REG_CHIP_ID_L, &id_low); + if (ret) { + // pr_err("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + rt_kprintf("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + + + + +static k_s32 xs9950_sensor_power_on(void *ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + // if (!xs9950_init_flag) { + xs9950_power_rest(on); + xs9950_i2c_init(&dev->i2c_info); + // } + ret = xs9950_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + xs9950_init_flag = K_FALSE; + xs9950_power_rest(on); + } + + return ret; +} + +static k_s32 xs9950_sensor_init(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(xs9950_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9950_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(xs9950_mode_info[i]); + dev->sensor_mode = &(xs9950_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + case 0: + case 1: + case 2: + case 3: + case 6: + // if (!xs9950_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + // } + + current_mode->ae_info.frame_length = 2193; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000152;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.0; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9950_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 165; //2.5ms //197; // 3ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + current_mode->ae_info.cur_fps = current_mode->fps; + break; + + case 4: + case 5: + case 7: + if (!xs9950_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + } + + + + current_mode->ae_info.frame_length = 1915; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000087;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.2; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9950_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 287; // 2.5ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + + default: + break; + } + + k_u16 again_h; + k_u16 again_l; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + float again = 0, dgain = 0; + + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L, &again_l); + again = 1.0;// (float)again_h / 16.0f; + + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_H, &exp_time_h); + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_L, &exp_time_l); + exp_time = (exp_time_h << 4) | ((exp_time_l >> 4) & 0x0F); + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + xs9950_init_flag = K_TRUE; + + return ret; +} + + +static k_s32 xs9950_sensor_get_mode(void *ctx, k_sensor_mode *mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(xs9950_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9950_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &xs9950_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(xs9950_mode_info[i]); + return 0; + } + } + pr_info("%s, the mode not exit.\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_set_mode(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_enum_mode(void *ctx, k_sensor_enum_mode *enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(enum_mode, 0, sizeof(k_sensor_enum_mode)); + + return ret; +} + +static k_s32 xs9950_sensor_get_caps(void *ctx, k_sensor_caps *caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +static k_s32 xs9950_sensor_conn_check(void *ctx, k_s32 *conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +static k_s32 xs9950_sensor_set_stream(void *ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +static k_s32 xs9950_sensor_get_again(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_again(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 again; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 16 + 0.5); + //if(current_mode->sensor_again !=again) + { + // ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN,(again & 0xff)); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/16.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_L_PARAS]* 16 + 0.5); + // ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN,(again & 0xff)); + current_mode->ae_info.cur_again = (float)again/16.0f; + + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 16 + 0.5); + //TODO + current_mode->ae_info.cur_vs_again = (float)again/16.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again*1000) ); + + return ret; +} + +static k_s32 xs9950_sensor_get_dgain(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_dgain(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + //TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = (float)dgain/1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain*10000)); + + return ret; +} + +static k_s32 xs9950_sensor_get_intg_time(void *ctx, k_sensor_intg_time *time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_intg_time(void *ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + k_u16 Strobe_StartPoint = 0; + k_u16 Strobe_Width = 0; + float integraion_time = 0; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + //if (current_mode->et_line != exp_line) + { + // ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_H, ( exp_line >> 4) & 0xff); + // ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_L, ( exp_line << 4) & 0xf0); + current_mode->et_line = exp_line; +/* //set strobe + Strobe_Width = (exp_line + 52)/3; + Strobe_StartPoint = Sensor_VTS - Strobe_Width - 7; + //Strobe_StartPoint = Sensor_VTS - Strobe_Width; + + ret |= sensor_reg_write(&dev->i2c_info, 0x3927, ( Strobe_Width >> 8) & 0xff); //strobe width + ret |= sensor_reg_write(&dev->i2c_info, 0x3928, Strobe_Width & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, 0x3929, ( Strobe_StartPoint >> 8) & 0xff); //strobe start point + ret |= sensor_reg_write(&dev->i2c_info, 0x392a, Strobe_StartPoint & 0xff);*/ + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n",\ + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +static k_s32 xs9950_sensor_get_exp_parm(void *ctx, k_sensor_exposure_param *exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +static k_s32 xs9950_sensor_set_exp_parm(void *ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_fps(void *ctx, k_u32 *fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = 30000; + + return ret; +} + +static k_s32 xs9950_sensor_set_fps(void *ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_isp_status(void *ctx, k_sensor_isp_status *staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +static k_s32 xs9950_sensor_set_blc(void *ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_set_wb(void *ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_tpg(void *ctx, k_sensor_test_pattern *tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +static k_s32 xs9950_sensor_set_tpg(void *ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_expand_curve(void *ctx, k_sensor_compand_curve *curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +static k_s32 xs9950_sensor_get_otp_data(void *ctx, void *data) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(data, 0, sizeof(void *)); + + return ret; +} + +static k_s32 xs9950_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev xs9950_csi1_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c0", //"i2c0", //"i2c3", + .slave_addr = 0x30, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "xs9950_csi1", + .sensor_func = { + .sensor_power = xs9950_sensor_power_on, + .sensor_init = xs9950_sensor_init, + .sensor_get_chip_id = xs9950_sensor_get_chip_id, + .sensor_get_mode = xs9950_sensor_get_mode, + .sensor_set_mode = xs9950_sensor_set_mode, + .sensor_enum_mode = xs9950_sensor_enum_mode, + .sensor_get_caps = xs9950_sensor_get_caps, + .sensor_conn_check = xs9950_sensor_conn_check, + .sensor_set_stream = xs9950_sensor_set_stream, + .sensor_get_again = xs9950_sensor_get_again, + .sensor_set_again = xs9950_sensor_set_again, + .sensor_get_dgain = xs9950_sensor_get_dgain, + .sensor_set_dgain = xs9950_sensor_set_dgain, + .sensor_get_intg_time = xs9950_sensor_get_intg_time, + .sensor_set_intg_time = xs9950_sensor_set_intg_time, + .sensor_get_exp_parm = xs9950_sensor_get_exp_parm, + .sensor_set_exp_parm = xs9950_sensor_set_exp_parm, + .sensor_get_fps = xs9950_sensor_get_fps, + .sensor_set_fps = xs9950_sensor_set_fps, + .sensor_get_isp_status = xs9950_sensor_get_isp_status, + .sensor_set_blc = xs9950_sensor_set_blc, + .sensor_set_wb = xs9950_sensor_set_wb, + .sensor_get_tpg = xs9950_sensor_get_tpg, + .sensor_set_tpg = xs9950_sensor_set_tpg, + .sensor_get_expand_curve = xs9950_sensor_get_expand_curve, + .sensor_get_otp_data = xs9950_sensor_get_otp_data, + .sensor_mirror_set = xs9950_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi2_drv.c b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi2_drv.c new file mode 100755 index 0000000..ce3e91a --- /dev/null +++ b/k230_sdk_overlay/src/big/mpp/kernel/sensor/src/xs9950_csi2_drv.c @@ -0,0 +1,1208 @@ +/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sensor_dev.h" + +//#include +#include "io.h" + +// #include "gpio.h" +#include "drv_gpio.h" + +#include "k_board_config_comm.h" + +#define pr_info(...) //rt_kprintf(__VA_ARGS__) +#define pr_debug(...) //rt_kprintf(__VA_ARGS__) +#define pr_warn(...) //rt_kprintf(__VA_ARGS__) +#define pr_err(...) rt_kprintf(__VA_ARGS__) + +#define XS9950_REG_CHIP_ID_H 0x40f0 +#define XS9950_REG_CHIP_ID_L 0x40f1 + +#define XS9950_REG_LONG_EXP_TIME_H 0x3501 +#define XS9950_REG_LONG_EXP_TIME_L 0x3502 + +#define XS9950_REG_LONG_AGAIN 0x3509 +//#define XS9950_REG_LONG_AGAIN_H 0x350a +//#define XS9950_REG_LONG_AGAIN_L 0x350b + +#define XS9950_MIN_GAIN_STEP (1.0f/16.0f) + +#define MIPI_LAN_RATA_800 +// #define MIPI_LAN_RATA_1000 +// #define MIPI_LAN_RATA_1500 + +/* +mipi clk = 71.53 x 2 , 没有数据 + +*/ + +static const k_sensor_reg xs9950_mipi4lane_720p_25fps_linear[] = { + //xs9950_mipi_init + {0x4300, 0x05}, + {0x4300, 0x15}, + {0x4080, 0x07}, + {0x4119, 0x01}, + {0x0803, 0x00}, + {0x4020, 0x00}, + {0x080e, 0x00}, + {0x080e, 0x20}, + {0x080e, 0x28}, + {0x4020, 0x03}, + {0x0803, 0x1f}, // zs default 0x0f + {0x0100, 0x35}, + {0x0104, 0x48}, + {0x0300, 0x3f}, + {0x0105, 0xe1}, + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, + {0x0333, 0x23}, //0x23 zs default 0x09 + {0x0336, 0x9e}, + {0x0337, 0xd9}, + {0x0338, 0x0a}, + {0x01bf, 0x4e}, + {0x010e, 0x78}, + {0x010f, 0x92}, + {0x0110, 0x70}, + {0x0111, 0x40}, + // {0x01e1, 0xff}, // zs default 0xff + {0x0314, 0x66}, + {0x0130, 0x10}, + {0x0315, 0x23}, + {0x0b64, 0x02}, + {0x01e2, 0x03}, + {0x0b55, 0x80}, + {0x0b56, 0x00}, + {0x0b59, 0x04}, + {0x0b5a, 0x01}, + {0x0b5c, 0x07}, + {0x0b5e, 0x05}, + {0x0b4b, 0x10}, + {0x0b4e, 0x05}, + {0x0b51, 0x21}, + {0x0b30, 0xbc}, + {0x0b31, 0x19}, + {0x0b15, 0x03}, + {0x0b16, 0x03}, + {0x0b17, 0x03}, + {0x0b07, 0x03}, + {0x0b08, 0x05}, + {0x0b1a, 0x10}, + {0x0158, 0x03}, + {0x0a88, 0x20}, + {0x0a61, 0x09}, + {0x0a62, 0x00}, + {0x0a63, 0x0e}, + {0x0a64, 0x00}, + {0x0a65, 0xfc}, + {0x0a67, 0xe5}, + {0x0a69, 0xef}, + {0x0a6b, 0x1b}, + {0x0a6d, 0x2f}, + {0x0a6f, 0x00}, + {0x0a71, 0xc2}, + {0x0a72, 0xff}, + {0x0a73, 0xd0}, + {0x0a74, 0xff}, + {0x0a75, 0x29}, + {0x0a77, 0x57}, + {0x0a78, 0x00}, + {0x0a79, 0x10}, + {0x0a7a, 0x00}, + {0x0a7b, 0xaa}, + {0x0a7d, 0xb2}, + {0x0a7f, 0x24}, + {0x0a80, 0x00}, + {0x0a81, 0x69}, + {0x0a82, 0x00}, + {0x0802, 0x02}, + {0x0501, 0x81}, + {0x0502, 0x0c}, //zs 0x0502 default 0x00 + {0x0b74, 0xfc}, + {0x01dc, 0x01}, + {0x0804, 0x04}, + {0x4018, 0x01}, + {0x0b56, 0x01}, + {0x0b73, 0x02}, + {0x4210, 0x0c}, + {0x420b, 0x2f}, // 上边是一样的 + + {0x0504, 0x89}, // bit[4:7] free_run颜色, 取值范围:[0, 8] + {0x0507, 0x13}, // color bar bit[0] 彩条滚动 + {0x0503, 0x00}, + {0x0502, 0x0c}, //这几个是读出来的然后在做的配置 zs + + {0x015a, 0x00}, // test pattern config + {0x015b, 0x24}, + {0x015c, 0x80}, + {0x015d, 0x16}, + {0x015e, 0xd0}, + {0x015f, 0x02}, + {0x0160, 0xee}, + {0x0161, 0x02}, + {0x0165, 0x00}, + {0x0166, 0x0f}, + + {0x4030, 0x15}, + {0x4134, 0x0a}, // zs default 0x06 + {0x0803, 0x0f}, + {0x4412, 0x00}, + {0x0803, 0x1f}, + {0x10e3, 0x01}, // mipi output en + {0x10eb, 0x04}, // clk datat lan en + + {0x50fc, 0x00}, + {0x50fd, 0x00}, + {0x50fe, 0x0d}, + {0x50ff, 0x59}, + + {0x50e4, 0x00}, // lan num 0 :1lna 1 ;2lan ???? + {0x50e5, 0x00}, + {0x50e6, 0x00}, + {0x50e7, 0x01}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x32}, + + {0x50f0, 0x00}, + {0x50f1, 0x00}, + {0x50f2, 0x00}, + {0x50f3, 0x0f}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + {0x5048, 0x00}, + {0x5049, 0x00}, + {0x504a, 0x03}, + {0x504b, 0xff}, + + {0x5058, 0x00}, + {0x5059, 0x00}, + {0x505a, 0x00}, + {0x505b, 0x07}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x00}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x04}, + + {0x50e0, 0x00}, + {0x50e1, 0x00}, + {0x50e2, 0x00}, + {0x50e3, 0x07}, +#ifdef MIPI_LAN_RATA_1500 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x6f}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_800 + {0x1003, 0x04}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0xed}, // mipi pll clk +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1003, 0x01}, // mipi pll clk 016f :1.5g 800: 4ed + {0x1004, 0x4a}, // mipi pll clk +#endif + {0x1001, 0xe4}, + {0x1000, 0x4d}, + {0x1001, 0xe0}, + {0x1020, 0x1e}, + {0x1020, 0x1f}, +#ifdef MIPI_LAN_RATA_1500 + {0x1045, 0xcd}, + {0x1046, 0x0c}, + {0x1047, 0x36}, + {0x1048, 0x0f}, + {0x1049, 0x59}, + {0x104a, 0x07}, + {0x1050, 0xc4}, + {0x1065, 0xcd}, + {0x1066, 0x0c}, + {0x1067, 0x0e}, + {0x1068, 0x0f}, + {0x1069, 0x59}, + {0x106a, 0x07}, + {0x1070, 0xc4}, + {0x1085, 0xcd}, + {0x1086, 0x0c}, + {0x1087, 0x0e}, + {0x1088, 0x0f}, + {0x1089, 0x59}, + {0x108a, 0x07}, + {0x1090, 0xc4}, +#endif + +#ifdef MIPI_LAN_RATA_1000 + {0x1045, 0xc5}, + {0x1046, 0x40}, + {0x1047, 0x20}, + {0x1048, 0x30}, + {0x1049, 0x4f}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x40}, + {0x1067, 0x09}, + {0x1068, 0x30}, + {0x1069, 0x4f}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x40}, + {0x1087, 0x09}, + {0x1088, 0x30}, + {0x1089, 0x4f}, + {0x108a, 0x0a}, + {0x1090, 0x04}, + +#endif + +#ifdef MIPI_LAN_RATA_800 + // mipi 800M + {0x1045, 0xc5}, + {0x1046, 0x70}, + {0x1047, 0x1f}, + {0x1048, 0x18}, + {0x1049, 0x4c}, + {0x104a, 0x0a}, + {0x1050, 0x04}, + {0x1065, 0xc5}, + {0x1066, 0x70}, + {0x1067, 0x09}, + {0x1068, 0x18}, + {0x1069, 0x4c}, + {0x106a, 0x0a}, + {0x1070, 0x04}, + {0x1085, 0xc5}, + {0x1086, 0x70}, + {0x1087, 0x09}, + {0x1088, 0x18}, + {0x1089, 0x4c}, + {0x108a, 0x0a}, + {0x1090, 0x04}, +#endif + {0x1040, 0x0a}, // lane clk pn swap + {0x1060, 0x0a}, // lane 0 pn swap + {0x1080, 0x0a}, // lane 1 pn swap + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, + + {0x50e8, 0x00}, + {0x50e9, 0x00}, + {0x50ea, 0x00}, + {0x50eb, 0x01}, + + // {0x5004, 0x00}, // zs default 0x06 + // {0x5005, 0x00}, + + {0x0800, 0x03}, // zs default 0x05 + {0x0805, 0x07}, // zs default 0x05 + + {0x4200, 0x02}, // 0x4200=2:选择VINA,0x4200=0:选择VINB,0x4200=4:选择VINC,0x4200=6:选择VIND + // {0x0111, 0x68}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4202, 0x0e}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x4203, 0x04}, // 适当调整这三个寄存器,也可增加清晰度和饱和度 + // {0x0100, 0x38}, // + // {0x01ce, 0x00}, // 调整自动曝光 + +#if 1 + // xs9950_AHD_720P_25f + {0x060b, 0x00}, + {0x0627, 0x14}, + {0x010c, 0x00}, + {0x0800, 0x05}, + {0x0805, 0x05}, + {0x0b50, 0x08}, + {0x0e08, 0x00}, + {0x010d, 0x40}, + {0x010c, 0x01}, + {0x0121, 0x7a}, + {0x0122, 0x6b}, + {0x0130, 0x10}, + {0x01a9, 0x00}, + {0x01aa, 0x04}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0105, 0xc1}, // AHD制式如发现颜色饱和度异常,可选择开关0x105的bit5 + {0x0101, 0x42}, + {0x0102, 0x40}, + {0x0116, 0x3c}, + {0x0117, 0x23}, // AHD制式如发现颜色饱和度异常,可选择打开0x105的bit5,并微调0x117 + {0x01e2, 0x03}, + {0x420b, 0x21}, + {0x0106, 0x80}, + {0x0107, 0x00}, + {0x0108, 0x80}, + {0x0109, 0x00}, + {0x010a, 0x20}, + {0x010b, 0x00}, + {0x011d, 0x17}, + {0x0e08, 0x01}, + {0x0a60, 0x04}, + {0x0a5c, 0xf6}, + {0x0a5d, 0xc0}, + {0x0a5e, 0x2d}, + {0x0a5f, 0x1b}, + {0x0156, 0x50}, + {0x0157, 0x07}, + {0x011d, 0x17}, + {0x0156, 0x00}, + {0x0157, 0x08}, + {0x0503, 0x00}, + {0x015a, 0x8b}, + {0x015b, 0x0e}, + {0x015c, 0x80}, + {0x015d, 0x16}, + {0x015e, 0xd0}, + {0x015f, 0x02}, + {0x0160, 0xee}, + {0x0161, 0x02}, + {0x0165, 0x40}, + {0x0166, 0x0f}, + {0x0A00, 0xFD}, + {0x0A01, 0xFF}, + {0x0A02, 0x00}, + {0x0A03, 0x00}, + {0x0A04, 0x04}, + {0x0A05, 0x00}, + {0x0A06, 0x01}, + {0x0A07, 0x00}, + {0x0A08, 0xFB}, + {0x0A09, 0xFF}, + {0x0A0A, 0xFE}, + {0x0A0B, 0xFF}, + {0x0A0C, 0x07}, + {0x0A0D, 0x00}, + {0x0A0E, 0x03}, + {0x0A0F, 0x00}, + {0x0A10, 0xF7}, + {0x0A11, 0xFF}, + {0x0A12, 0xFA}, + {0x0A13, 0xFF}, + {0x0A14, 0x0B}, + {0x0A15, 0x00}, + {0x0A16, 0x0A}, + {0x0A17, 0x00}, + {0x0A18, 0xF3}, + {0x0A19, 0xFF}, + {0x0A1A, 0xF1}, + {0x0A1B, 0xFF}, + {0x0A1C, 0x0F}, + {0x0A1D, 0x00}, + {0x0A1E, 0x18}, + {0x0A1F, 0x00}, + {0x0A20, 0xEE}, + {0x0A21, 0xFF}, + {0x0A22, 0xDC}, + {0x0A23, 0xFF}, + {0x0A24, 0x14}, + {0x0A25, 0x00}, + {0x0A26, 0x39}, + {0x0A27, 0x00}, + {0x0A28, 0xEB}, + {0x0A29, 0xFF}, + {0x0A2A, 0x98}, + {0x0A2B, 0xFF}, + {0x0A2C, 0x16}, + {0x0A2D, 0x00}, + {0x0A2E, 0x45}, + {0x0A2F, 0x01}, + {0x0A30, 0xEA}, + {0x0A31, 0x01}, + {0x0A60, 0x01}, + /*针对某些非标AHD72如下配置*/ + {0x0AA7, 0x7A}, + {0x0AA8, 0x18}, + {0x0AA9, 0xC0}, + {0x0AAA, 0x01}, + {0x0AAB, 0xC2}, + {0x0AAC, 0x01}, + {0x0AAD, 0x80}, + {0x0AAE, 0x43}, + {0x0AAF, 0x00}, + {0x0AB0, 0x70}, + {0x0AB1, 0x00}, + {0x0AB2, 0x1B}, + {0x0A88, 0x30}, + + //xs9950_mipi_reset_new + {0x0e08, 0x01}, + // {0x1e08, 0x01}, + // {0x2e08, 0x01}, + // {0x3e08, 0x01}, + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x00}, + + {0x5004, 0x00}, + {0x5005, 0x00}, + {0x5006, 0x00}, + {0x5007, 0x01}, +#endif + {REG_NULL, 0x0}, +}; + + +static k_sensor_mode xs9950_mode_info[] = { + { + .index = 0, + .sensor_type = XS9950_MIPI_CSI2_1280X720_30FPS_YUV422, + .size = { + .bounds_width = 1280, + .bounds_height = 720, + .top = 0, + .left = 0, + .width = 1280, + .height = 720, + }, + .fps = 30000, + .hdr_mode = SENSOR_MODE_HDR_STITCH, + .stitching_mode = SENSOR_STITCHING_3DOL, + .bit_width = 8, + .bayer_pattern = BAYER_PAT_RGGB, + .mipi_info = { + .csi_id = 0, + .mipi_lanes = 4, + .data_type = 0x1e, + }, + .reg_list = xs9950_mipi4lane_720p_25fps_linear, + .mclk_setting = { + { + .mclk_setting_en = K_FALSE, + .setting.id = SENSOR_MCLK0, + .setting.mclk_sel = SENSOR_PLL0_CLK_DIV4, + .setting.mclk_div = 16, + }, + {K_FALSE}, + {K_FALSE}, + }, + }, +}; + +static k_bool xs9950_init_flag = K_FALSE; +static k_sensor_mode *current_mode = NULL; + +static int xs9950_power_rest(k_s32 on) +{ + #define VICAP_XS9950_RST_GPIO (24) //24// + + kd_pin_mode(VICAP_XS9950_RST_GPIO, GPIO_DM_OUTPUT); + + if (on) { + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + rt_thread_mdelay(100); + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_HIGH); // GPIO_PV_LOW GPIO_PV_HIGH + } else { + kd_pin_write(VICAP_XS9950_RST_GPIO, GPIO_PV_LOW); // GPIO_PV_LOW GPIO_PV_HIGH + } + rt_thread_mdelay(1); + + return 0; +} + +static int xs9950_i2c_init(k_sensor_i2c_info *i2c_info) +{ + i2c_info->i2c_bus = rt_i2c_bus_device_find(i2c_info->i2c_name); + if (i2c_info->i2c_bus == RT_NULL) + { + pr_err("can't find %s deivce", i2c_info->i2c_name); + return RT_ERROR; + } + + return 0; +} + +static k_s32 xs9950_sensor_get_chip_id(void *ctx, k_u32 *chip_id) +{ + k_s32 ret = 0; + k_u16 id_high = 0; + k_u16 id_low = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter\n", __func__); + + xs9950_i2c_init(&dev->i2c_info); + + ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_CHIP_ID_H, &id_high); + ret |= sensor_reg_read(&dev->i2c_info, XS9950_REG_CHIP_ID_L, &id_low); + if (ret) { + // pr_err("%s error\n", __func__); + return -1; + } + + *chip_id = (id_high << 8) | id_low; + rt_kprintf("%s chip_id[0x%08X]\n", __func__, *chip_id); + return ret; +} + + + + +static k_s32 xs9950_sensor_power_on(void *ctx, k_s32 on) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + k_u32 chip_id = 0; + pr_info("%s enter\n", __func__); + if (on) { + // if (!xs9950_init_flag) { + xs9950_power_rest(on); + xs9950_i2c_init(&dev->i2c_info); + // } + ret = xs9950_sensor_get_chip_id(ctx, &chip_id); + if(ret < 0) + { + pr_err("%s, iic read chip id err \n", __func__); + } + } else { + xs9950_init_flag = K_FALSE; + xs9950_power_rest(on); + } + + return ret; +} + +static k_s32 xs9950_sensor_init(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + k_s32 i = 0; + struct sensor_driver_dev *dev = ctx; + pr_info("%s enter, sensor_type:%d\n", __func__, mode.sensor_type); + + if (current_mode == NULL) { + for (i = 0; i < sizeof(xs9950_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9950_mode_info[i].sensor_type == mode.sensor_type) { + current_mode = &(xs9950_mode_info[i]); + dev->sensor_mode = &(xs9950_mode_info[i]); + break; + } + } + } + + if (current_mode == NULL) { + pr_err("%s, current mode not exit.\n", __func__); + return -1; + } + + switch (current_mode->index) { + case 0: + case 1: + case 2: + case 3: + case 6: + // if (!xs9950_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + // } + + current_mode->ae_info.frame_length = 2193; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000152;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.0; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9950_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 165; //2.5ms //197; // 3ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + current_mode->ae_info.cur_fps = current_mode->fps; + break; + + case 4: + case 5: + case 7: + if (!xs9950_init_flag) { + ret = sensor_reg_list_write(&dev->i2c_info, current_mode->reg_list); + } + + + + current_mode->ae_info.frame_length = 1915; + current_mode->ae_info.cur_frame_length = current_mode->ae_info.frame_length; + current_mode->ae_info.one_line_exp_time = 0.0000087;//s + current_mode->ae_info.gain_accuracy = 1024; + + current_mode->ae_info.min_gain = 1.0; + current_mode->ae_info.max_gain = 15.9375; + + current_mode->ae_info.int_time_delay_frame = 0; + current_mode->ae_info.gain_delay_frame = 0; + //current_mode->ae_info.ae_min_interval_frame =1.2; + current_mode->ae_info.color_type = SENSOR_MONO; //mono sensor + + current_mode->ae_info.integration_time_increment = current_mode->ae_info.one_line_exp_time; + current_mode->ae_info.gain_increment = XS9950_MIN_GAIN_STEP; + + current_mode->ae_info.max_integraion_line = 287; // 2.5ms + current_mode->ae_info.min_integraion_line = 1; + + current_mode->ae_info.max_vs_integraion_line = current_mode->ae_info.frame_length; + current_mode->ae_info.min_vs_integraion_line = current_mode->ae_info.frame_length - 1; + + current_mode->ae_info.max_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_integraion_line; + + current_mode->ae_info.min_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_integraion_line; + + current_mode->ae_info.max_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.max_vs_integraion_line; + + current_mode->ae_info.min_vs_integraion_time = \ + current_mode->ae_info.integration_time_increment * \ + current_mode->ae_info.min_vs_integraion_line; + + current_mode->ae_info.cur_integration_time = 0.0; + current_mode->ae_info.cur_vs_integration_time = 0.0; + + current_mode->ae_info.cur_again = 0.0; + current_mode->ae_info.cur_dgain = 0.0; + + current_mode->ae_info.cur_vs_again = 0.0; + current_mode->ae_info.cur_vs_dgain = 0.0; + + current_mode->ae_info.a_gain.min = 1.0; + current_mode->ae_info.a_gain.max = 15.9375; + current_mode->ae_info.a_gain.step = (1.0f/16.0f); + + current_mode->ae_info.a_vs_gain.min = 1.0; + current_mode->ae_info.a_vs_gain.max = 15.9375; + current_mode->ae_info.a_vs_gain.step = (1.0f/16.0f);// + + current_mode->ae_info.d_gain.max = 1.0; + current_mode->ae_info.d_gain.min = 1.0; + current_mode->ae_info.d_gain.step = (1.0f/1024.0f); + + current_mode->ae_info.d_vs_gain.max = 1.0; + current_mode->ae_info.d_vs_gain.min = 1.0; + current_mode->ae_info.d_vs_gain.step = (1.0f/1024.0f);// + + current_mode->ae_info.cur_fps = current_mode->fps; + current_mode->sensor_again = 0; + current_mode->et_line = 0; + break; + + default: + break; + } + + k_u16 again_h; + k_u16 again_l; + k_u16 exp_time_h, exp_time_l; + k_u16 exp_time; + float again = 0, dgain = 0; + + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H, &again_h); + //ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L, &again_l); + again = 1.0;// (float)again_h / 16.0f; + + dgain = 1.0; + current_mode->ae_info.cur_gain = again * dgain; + current_mode->ae_info.cur_long_gain = current_mode->ae_info.cur_gain; + current_mode->ae_info.cur_vs_gain = current_mode->ae_info.cur_gain; + + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_H, &exp_time_h); + // ret = sensor_reg_read(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_L, &exp_time_l); + exp_time = (exp_time_h << 4) | ((exp_time_l >> 4) & 0x0F); + + current_mode->ae_info.cur_integration_time = exp_time * current_mode->ae_info.one_line_exp_time; + xs9950_init_flag = K_TRUE; + + return ret; +} + + +static k_s32 xs9950_sensor_get_mode(void *ctx, k_sensor_mode *mode) +{ + k_s32 ret = -1; + + pr_info("%s enter, sensor_type(%d)\n", __func__, mode->sensor_type); + + for (k_s32 i = 0; i < sizeof(xs9950_mode_info) / sizeof(k_sensor_mode); i++) { + if (xs9950_mode_info[i].sensor_type == mode->sensor_type) { + memcpy(mode, &xs9950_mode_info[i], sizeof(k_sensor_mode)); + current_mode = &(xs9950_mode_info[i]); + return 0; + } + } + pr_info("%s, the mode not exit.\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_set_mode(void *ctx, k_sensor_mode mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_enum_mode(void *ctx, k_sensor_enum_mode *enum_mode) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(enum_mode, 0, sizeof(k_sensor_enum_mode)); + + return ret; +} + +static k_s32 xs9950_sensor_get_caps(void *ctx, k_sensor_caps *caps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(caps, 0, sizeof(k_sensor_caps)); + caps->bit_width = current_mode->bit_width; + caps->bayer_pattern = current_mode->bayer_pattern; + caps->resolution.width = current_mode->size.width; + caps->resolution.height = current_mode->size.height; + + return ret; +} + +static k_s32 xs9950_sensor_conn_check(void *ctx, k_s32 *conn) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *conn = 1; + + return ret; +} + +static k_s32 xs9950_sensor_set_stream(void *ctx, k_s32 enable) +{ + k_s32 ret = 0; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter, enable(%d)\n", __func__, enable); + if (enable) { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x01); + } else { + // ret = sensor_reg_write(&dev->i2c_info, 0x0100, 0x00); + } + pr_info("%s exit, ret(%d)\n", __func__, ret); + + return ret; +} + +static k_s32 xs9950_sensor_get_again(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_again; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_again; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_again; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_again(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u16 again; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + again = (k_u16)(gain.gain[SENSOR_LINEAR_PARAS] * 16 + 0.5); + //if(current_mode->sensor_again !=again) + { + // ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN,(again & 0xff)); + current_mode->sensor_again = again; + } + current_mode->ae_info.cur_again = (float)current_mode->sensor_again/16.0f; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_L_PARAS]* 16 + 0.5); + // ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN,(again & 0xff)); + current_mode->ae_info.cur_again = (float)again/16.0f; + + again = (k_u16)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 16 + 0.5); + //TODO + current_mode->ae_info.cur_vs_again = (float)again/16.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s, hdr_mode(%d), cur_again(%u)\n", __func__, current_mode->hdr_mode, (k_u32)(current_mode->ae_info.cur_again*1000) ); + + return ret; +} + +static k_s32 xs9950_sensor_get_dgain(void *ctx, k_sensor_gain *gain) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + gain->gain[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_dgain; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + gain->gain[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_dgain; + gain->gain[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_dgain; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_dgain(void *ctx, k_sensor_gain gain) +{ + k_s32 ret = 0; + k_u32 dgain; + struct sensor_driver_dev *dev = ctx; + + pr_info("%s enter hdr_mode(%d)\n", __func__, current_mode->hdr_mode); + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + dgain = (k_u32)(gain.gain[SENSOR_LINEAR_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_L_PARAS] * 1024); + //ret = sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_H,(again & 0x0300)>>8); + //ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_AGAIN_L,(again & 0xff)); + current_mode->ae_info.cur_dgain = (float)dgain/1024.0f; + + dgain = (k_u32)(gain.gain[SENSOR_DUAL_EXP_S_PARAS] * 1024); + //TODO wirte vs gain register + current_mode->ae_info.cur_vs_dgain = (float)dgain/1024.0f; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + current_mode->ae_info.cur_gain = current_mode->ae_info.cur_again * current_mode->ae_info.cur_dgain; + pr_debug("%s,cur_gain(%d)\n", __func__, (k_u32)(current_mode->ae_info.cur_gain*10000)); + + return ret; +} + +static k_s32 xs9950_sensor_get_intg_time(void *ctx, k_sensor_intg_time *time) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + time->intg_time[SENSOR_LINEAR_PARAS] = current_mode->ae_info.cur_integration_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + time->intg_time[SENSOR_DUAL_EXP_L_PARAS] = current_mode->ae_info.cur_integration_time; + time->intg_time[SENSOR_DUAL_EXP_S_PARAS] = current_mode->ae_info.cur_vs_integration_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + + return ret; +} + +static k_s32 xs9950_sensor_set_intg_time(void *ctx, k_sensor_intg_time time) +{ + k_s32 ret = 0; + k_u16 exp_line = 0; + k_u16 Strobe_StartPoint = 0; + k_u16 Strobe_Width = 0; + float integraion_time = 0; + struct sensor_driver_dev *dev = ctx; + + if (current_mode->hdr_mode == SENSOR_MODE_LINEAR) { + integraion_time = time.intg_time[SENSOR_LINEAR_PARAS]; + + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + //if (current_mode->et_line != exp_line) + { + // ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_H, ( exp_line >> 4) & 0xff); + // ret |= sensor_reg_write(&dev->i2c_info, XS9950_REG_LONG_EXP_TIME_L, ( exp_line << 4) & 0xf0); + current_mode->et_line = exp_line; +/* //set strobe + Strobe_Width = (exp_line + 52)/3; + Strobe_StartPoint = Sensor_VTS - Strobe_Width - 7; + //Strobe_StartPoint = Sensor_VTS - Strobe_Width; + + ret |= sensor_reg_write(&dev->i2c_info, 0x3927, ( Strobe_Width >> 8) & 0xff); //strobe width + ret |= sensor_reg_write(&dev->i2c_info, 0x3928, Strobe_Width & 0xff); + ret |= sensor_reg_write(&dev->i2c_info, 0x3929, ( Strobe_StartPoint >> 8) & 0xff); //strobe start point + ret |= sensor_reg_write(&dev->i2c_info, 0x392a, Strobe_StartPoint & 0xff);*/ + } + current_mode->ae_info.cur_integration_time = (float)current_mode->et_line * current_mode->ae_info.one_line_exp_time; + } else if (current_mode->hdr_mode == SENSOR_MODE_HDR_STITCH) { + integraion_time = time.intg_time[SENSOR_DUAL_EXP_L_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + + integraion_time = time.intg_time[SENSOR_DUAL_EXP_S_PARAS]; + exp_line = integraion_time / current_mode->ae_info.one_line_exp_time; + exp_line = MIN(current_mode->ae_info.max_integraion_line, MAX(1, exp_line)); + + current_mode->ae_info.cur_vs_integration_time = (float)exp_line * current_mode->ae_info.one_line_exp_time; + } else { + pr_err("%s, unsupport exposure frame.\n", __func__); + return -1; + } + pr_debug("%s hdr_mode(%d), exp_line(%d), integraion_time(%u)\n",\ + __func__, current_mode->hdr_mode, exp_line, (k_u32)(integraion_time * 1000000000)); + + return ret; +} + +static k_s32 xs9950_sensor_get_exp_parm(void *ctx, k_sensor_exposure_param *exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(exp_parm, 0, sizeof(k_sensor_exposure_param)); + + return ret; +} + +static k_s32 xs9950_sensor_set_exp_parm(void *ctx, k_sensor_exposure_param exp_parm) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_fps(void *ctx, k_u32 *fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + *fps = 30000; + + return ret; +} + +static k_s32 xs9950_sensor_set_fps(void *ctx, k_u32 fps) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_isp_status(void *ctx, k_sensor_isp_status *staus) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(staus, 0, sizeof(k_sensor_isp_status)); + + return ret; +} + +static k_s32 xs9950_sensor_set_blc(void *ctx, k_sensor_blc blc) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_set_wb(void *ctx, k_sensor_white_balance wb) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_tpg(void *ctx, k_sensor_test_pattern *tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(tpg, 0, sizeof(k_sensor_test_pattern)); + + return ret; +} + +static k_s32 xs9950_sensor_set_tpg(void *ctx, k_sensor_test_pattern tpg) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + + return ret; +} + +static k_s32 xs9950_sensor_get_expand_curve(void *ctx, k_sensor_compand_curve *curve) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(curve, 0, sizeof(k_sensor_compand_curve)); + + return ret; +} + +static k_s32 xs9950_sensor_get_otp_data(void *ctx, void *data) +{ + k_s32 ret = 0; + + pr_info("%s enter\n", __func__); + memset(data, 0, sizeof(void *)); + + return ret; +} + +static k_s32 xs9950_sensor_mirror_set(void *ctx, k_vicap_mirror_mode mirror) +{ + return 0; +} + +struct sensor_driver_dev xs9950_csi2_sensor_drv = { + .i2c_info = { + .i2c_bus = NULL, + .i2c_name = "i2c1", //"i2c0", //"i2c3", + .slave_addr = 0x30, + .reg_addr_size = SENSOR_REG_VALUE_16BIT, + .reg_val_size = SENSOR_REG_VALUE_8BIT, + }, + .sensor_name = "xs9950_csi2", + .sensor_func = { + .sensor_power = xs9950_sensor_power_on, + .sensor_init = xs9950_sensor_init, + .sensor_get_chip_id = xs9950_sensor_get_chip_id, + .sensor_get_mode = xs9950_sensor_get_mode, + .sensor_set_mode = xs9950_sensor_set_mode, + .sensor_enum_mode = xs9950_sensor_enum_mode, + .sensor_get_caps = xs9950_sensor_get_caps, + .sensor_conn_check = xs9950_sensor_conn_check, + .sensor_set_stream = xs9950_sensor_set_stream, + .sensor_get_again = xs9950_sensor_get_again, + .sensor_set_again = xs9950_sensor_set_again, + .sensor_get_dgain = xs9950_sensor_get_dgain, + .sensor_set_dgain = xs9950_sensor_set_dgain, + .sensor_get_intg_time = xs9950_sensor_get_intg_time, + .sensor_set_intg_time = xs9950_sensor_set_intg_time, + .sensor_get_exp_parm = xs9950_sensor_get_exp_parm, + .sensor_set_exp_parm = xs9950_sensor_set_exp_parm, + .sensor_get_fps = xs9950_sensor_get_fps, + .sensor_set_fps = xs9950_sensor_set_fps, + .sensor_get_isp_status = xs9950_sensor_get_isp_status, + .sensor_set_blc = xs9950_sensor_set_blc, + .sensor_set_wb = xs9950_sensor_set_wb, + .sensor_get_tpg = xs9950_sensor_get_tpg, + .sensor_set_tpg = xs9950_sensor_set_tpg, + .sensor_get_expand_curve = xs9950_sensor_get_expand_curve, + .sensor_get_otp_data = xs9950_sensor_get_otp_data, + .sensor_mirror_set = xs9950_sensor_mirror_set, + }, +}; diff --git a/k230_sdk_overlay/src/big/mpp/userapps/api/mpi_sensor_api.h b/k230_sdk_overlay/src/big/mpp/userapps/api/mpi_sensor_api.h index e534c00..88a24cc 100755 --- a/k230_sdk_overlay/src/big/mpp/userapps/api/mpi_sensor_api.h +++ b/k230_sdk_overlay/src/big/mpp/userapps/api/mpi_sensor_api.h @@ -454,6 +454,9 @@ k_s32 kd_mpi_sensor_otpdata_set(k_s32 fd, void *ota_data); k_s32 kd_mpi_sensor_mirror_set(k_s32 fd, k_vicap_mirror_mode mirror); + +k_s32 kd_mpi_sensor_adapt_get(k_vicap_adapt_id *csi0_adapt_id, k_vicap_adapt_id *csi1_adapt_id, k_vicap_adapt_id *csi2_adapt_id); + /** @} */ /**