原文网址(转载请注明出处):
源码基于:Android Q
展锐平台sl8541移植OV8858进行详细讲解。
1.硬件
1.1.OV8858 结构图(连接器)

1.2.开发板MIPI原理图


1.3.Camera引脚编号介绍

引脚编号 引脚名称 其他
83 CAM_I2C_SCL SCL1
84 CAM_I2C_SDA SDA1
基于MIPI CSI标准,M1710U模块摄像头接口默认支持1路2-lane CSI1+ 1 路 1-lane CSI0,最高速率达 1.5Gbps/lane。可支持 2 路摄像头:前摄使用 1-lane MIPI,可最大支持 2 MP 拍照;后摄使用 2-lane MIPI,可最大支持 8 MP 拍照。摄像和照相质量由摄像头传感器、镜头规格参数等多种因素决定。
如上所述,模块的 CSI0 默认为 1-lane,但能最大扩展为 4-lane,另外3 组数据 lane 信息在模块硬件设计手册中未作体现,客户可以通过下文了解关于模块 4-lane CSI0 的详细信息,以满足最大 13 MP 像素摄像头的应用需求。
开发板现在支持情况:
- 前摄:5M(500万像素)
- 后摄:8M(800万像素)
1.4.OV8858 datesheet


1.5.camera主要硬件介绍
主要由如下五部分组成,协同工作:
(1)三路电压AVDD/DVDD/IOVDD:
AVDD模拟电源,主要给感光区和ADC供电,要求比较干净;
DVDD数字电源,主要是给ISP供电;
IOVDD数字I0电源,给I2C和DVP供电。
(2) PDN/RST:
RST:用来reset sensor; RESET- 般是低电平有效,当脉冲为低电平时,reset sensor, 而正常工作时,应该设置为高电平。
复位时序时序通常是:高->低->高,根据硬件需要加一定的延时;
电源实测数据如下:
开发板电压状态:
打开摄像头: MCAM_VAAM_2V8 129 2.8V MCAM_IOVDD 125 1.8V
关闭摄像头 MCAM_VAAM_2V8 129 0V MCAM_IOVDD 125 1.8V
1.6.上电时序


重要:
这里需要注意的是,XSHUTDN就是reset引脚,低电平复位,正常工作的时候,应该是高电平
PWDNB是和复位脚差不多功能的,给寄存器复位,所以这两个,比较关键,我这里是使用了DOVDD和XSHUTDN连接的情况,所以驱动中power_on处理的时候,拉高reset以后,不延时,直接拉高pwdn,然后延时,才能让模块上电
dvdd avdd iovdd上电时序其实要求并不严格,之前我一直读取不到模块id,就是因为我们分开供电XSHUYDN和PWDNB,而驱动中是先拉低reset然后拉高延时2Ms再拉高pwdn,所以导致系统一直没有工作起来,去读i2c的时候返回-5
这里rk也有案例
实际上很简单,驱动中probe以后,就开始检测获dts配置,然后就power_on执行上电流程,上电以后,第一步就是check_id,也就是读取摄像头id,如果i2c通信异常,那么久无法进行下面的工作,直接return
经过一番折腾,i2c正常读取id,解决了前面最关键的一步
切记:如果i2c读取不到,确保硬件电压,时钟正常,然后基本上就是时序了
如果硬件都没问题,但是读取的时候没有一直错,可能先考虑给一个for循环,循环发送0x00-0xff,看看有没有回应,避免因为地址错误这种低级错误
2.Camera软件移植
2.1.dts移植
vddcamio: LDO_VDDCAMIO {
regulator-name = "vddcamio";
regulator-min-microvolt = <1400000>;//调节器最小微伏
regulator-max-microvolt = <2187500>;//调节器最大微伏
regulator-ramp-delay = <25000>;
};
vddcama: LDO_VDDCAMA {
regulator-name = "vddcama";
regulator-min-microvolt = <1612500>;//调节器最小微伏
regulator-max-microvolt = <3200000>;//调节器最大微伏
regulator-ramp-delay = <25000>;
};
&i2c1 {//使用的i2c总线
status = "okay";//okay 才会进行匹配
clock-frequency = <100000>;//数据传输频率
sensor_main: sensor-main@40 {//主摄
compatible = "sprd,sensor-main";
reg = <0x40>;//主摄寄存器地址
clock-names = "clk_src","sensor_eb",
"clk_96m","clk_76m8",
"clk_48m","clk_26m";//代表所使用的mclk
clocks = <&mm_clk CLK_SENSOR0>, <&mm_gate CLK_SENSOR0_EB>,
<&pll CLK_TWPLL_96M>,<&pll CLK_TWPLL_76M8>,
<&pll CLK_TWPLL_48M>,<&ext_26m>;
vddio-supply = <&vddcamio>;//所使用的avdd,dvdd,iovdd
//vddcama-supply = <&vddcama>;
//vddcamd-supply = <&vddcamd>;
vddcammot-supply = <&vddcama>;//所使用的avdd,dvdd,iovdd
sprd,phyid = <2>;//phyid是硬件上mipi上连接的方式有关系,1lane,2lane,4lane,4lane phyid设为0
csi = <&csi0>;//选择的CSI总线
reset-gpios = <&ap_gpio 44 0>;//复位引脚
//power-down-gpios = <&ap_gpio 46 0>;
dvdd-gpios = <&ap_gpio 32 0>;//dvdd电源控制引脚
avdd-gpios = <&ap_gpio 8 0>;//avdd电源控制引脚
};
DTS冒号前都是别名,引用用&符号。如上:vddcama是别名,应用则是&vddcamio。
2.2.源码定位
sl8541e_1h10wifi5g_32b_Natv$ find . -name "*ov8858*"
./bsp/kernel/kernel4.14/drivers/staging/media/atomisp/i2c/ov8858_btns.h
./bsp/kernel/kernel4.14/drivers/staging/media/atomisp/i2c/ov8858.c
./bsp/kernel/kernel4.14/drivers/staging/media/atomisp/i2c/ov8858.h
./vendor/sprd/modules/libcamera/sensor/otp_drv/driver/ov8858_cmk
./vendor/sprd/modules/libcamera/sensor/otp_drv/driver/ov8858_cmk/ov8858_cmk_otp_drv.c
./vendor/sprd/modules/libcamera/sensor/otp_drv/driver/ov8858_cmk/ov8858_cmk_golden_otp.h
./vendor/sprd/modules/libcamera/sensor/otp_drv/driver/ov8858_cmk/ov8858_cmk_otp_drv.h
./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858
./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.c
./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.h
./out/target/product/sl8541e_1h10wifi5g_32b/obj/SHARED_LIBRARIES/libsensor_ov8858_intermediates
./out/target/product/sl8541e_1h10wifi5g_32b/obj/SHARED_LIBRARIES/libsensor_ov8858_intermediates/libsensor_ov8858.so
./out/target/product/sl8541e_1h10wifi5g_32b/obj/SHARED_LIBRARIES/libsensor_ov8858_intermediates/sensor_ov8858_mipi_raw.o
./out/target/product/sl8541e_1h10wifi5g_32b/obj/SHARED_LIBRARIES/libsensor_ov8858_intermediates/LINKED/libsensor_ov8858.so
./out/target/product/sl8541e_1h10wifi5g_32b/obj/SHARED_LIBRARIES/libsensor_ov8858_intermediates/sensor_ov8858_mipi_raw.d
./out/target/product/sl8541e_1h10wifi5g_32b/obj/SHARED_LIBRARIES/libsensor_ov8858_intermediates/libsensor_ov8858.so.d
./out/target/product/sl8541e_1h10wifi5g_32b/obj/PACKAGING/target_files_intermediates/sl8541e_1h10wifi5g_32b_Natv-target_files-20230519.163824/VENDOR/lib/libsensor_ov8858.so
./out/target/product/sl8541e_1h10wifi5g_32b/archive_symbols/symbols.vendor/vendor/lib/libsensor_ov8858.so
./out/target/product/sl8541e_1h10wifi5g_32b/symbols/vendor/lib/libsensor_ov8858.so
./out/target/product/sl8541e_1h10wifi5g_32b/vendor/lib/libsensor_ov8858.so
源码定位在:
./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858
./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.c
./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.h
$ ls ./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858
Android.mk(编译ov8858脚本) sensor_ov8858_mipi_raw.c sensor_ov8858_mipi_raw.h
sensor的操作函数为ops,在sensor_ov8858_mipi_raw.c 中查到ops函数为s_ov8858_ops_tab
//sensor_ov8858_mipi_raw.c
/*==============================================================================
* Description:
* 所有ioctl函数
* 您可以从sensor_drv_u.h中添加引用SENSOR_IOCTL_FUNC_TAB_T的函数
*
* 像这样添加ioctl函数:
* .power = ov8858_power_on,
*============================================================================*/
static struct sensor_ic_ops s_ov8858_ops_tab = {
.create_handle = ,
.delete_handle = ov8858_drv_handle_delete,
.get_data = ov8858_drv_get_private_data,
/*---------------------------------------*/
.power = ov8858_drv_power_on,//上电
.identify = ov8858_drv_identify,//识别传感器id
.ex_write_exp = ov8858_drv_write_exposure,//将曝光写入传感器寄存器并获得当前快门,请注意帧长,如有必要请勿更改此功能
.write_gain_value = ov8858_drv_write_gain_value,//写入增益值传感器,你可以改变这个功能,如果它是必要的
.read_aec_info = ov8858_drv_read_aec_info,
.ext_ops = {
[SENSOR_IOCTL_BEFORE_SNAPSHOT].ops = ov8858_drv_before_snapshot,//在快照之前,您可以根据需要更改此功能
[SENSOR_IOCTL_STREAM_ON].ops = ov8858_drv_stream_on,//请根据您的规格修改此功能
[SENSOR_IOCTL_STREAM_OFF].ops = ov8858_drv_stream_off,//请根据您的规格修改此功能
/** 展开界面,如果你想添加你的子CMD ,
* 你可以在enum中添加它{@SENSOR_IOCTL_VAL_TYPE}
*/
[SENSOR_IOCTL_ACCESS_VAL].ops = ov8858_drv_access_val,//CFG otp设置请根据您的规格修改此功能
}};
sl8541e_1h10wifi5g_32b_Natv$ cgrep -r "s_ov8858_ops_tab" ./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.c:905:static struct sensor_ic_ops s_ov8858_ops_tab = { ./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.h:1083:static struct sensor_ic_ops s_ov8858_ops_tab; ./vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.h:1117: .sns_ops = &s_ov8858_ops_tab,
2.3. ov8858_mipi_raw_info
//vendor/sprd/modules/libcamera/sensor/sensor_drv/classic/OmniVision/ov8858/sensor_ov8858_mipi_raw.h
//模块基本信息
static struct sensor_module_info s_ov8858_module_info_tab[VENDOR_NUM] = {
{.module_id = MODULE_SUNNY,
.module_info = {.major_i2c_addr = I2C_SLAVE_ADDR >> 1,
.minor_i2c_addr = 0x20 >> 1,
.reg_addr_value_bits = SENSOR_I2C_REG_16BIT |
SENSOR_I2C_VAL_8BIT |
SENSOR_I2C_FREQ_400,
.avdd_val = SENSOR_AVDD_2800MV, //模拟电源,主要给感光区和ADC供电
.iovdd_val = SENSOR_AVDD_1800MV, //数字电源,主要是给ISP供电;
.dvdd_val = SENSOR_AVDD_1200MV, //数字I0电源,给I2C和DVP供电。
.image_pattern = SENSOR_IMAGE_PATTERN_RAWRGB_B,
.preview_skip_num = 1, //预览前跳过帧数
.capture_skip_num = 3, //在捕获之前跳过帧数
.flash_capture_skip_num = 6, //闪光捕捉跳过帧数
.mipi_cap_skip_num = 0, //mipi cap跳过帧数
.preview_deci_num = 0, //预览期间的十进制帧数
.video_preview_deci_num = 0, //视频预览期间的十进制帧数
.threshold_eb = 0,
.threshold_mode = 0,
.threshold_start = 0,
.threshold_end = 0,
.sensor_interface =
{
.type = SENSOR_INTERFACE_TYPE_CSI2,
.bus_width = LANE_NUM, //连接的lane数 #define LANE_NUM 2
.pixel_width = RAW_BITS, //camera sensor输出格式 #define RAW_BITS 10
.is_loose = 0,
},
.change_setting_skip_num = 1,
.horizontal_view_angle = 35,
.vertical_view_angle = 35}}
/*If there are multiple modules,please add here*/
};
static struct sensor_ic_ops s_ov8858_ops_tab;
struct sensor_raw_info *s_ov8858_mipi_raw_info_ptr = PNULL;
SENSOR_INFO_T g_ov8858_mipi_raw_info = {
.hw_signal_polarity = SENSOR_HW_SIGNAL_PCLK_P | SENSOR_HW_SIGNAL_VSYNC_P |
SENSOR_HW_SIGNAL_HSYNC_P,
.environment_mode = SENSOR_ENVIROMENT_NORMAL | SENSOR_ENVIROMENT_NIGHT,
.image_effect = SENSOR_IMAGE_EFFECT_NORMAL |
SENSOR_IMAGE_EFFECT_BLACKWHITE | SENSOR_IMAGE_EFFECT_RED |
SENSOR_IMAGE_EFFECT_GREEN | SENSOR_IMAGE_EFFECT_BLUE |
SENSOR_IMAGE_EFFECT_YELLOW | SENSOR_IMAGE_EFFECT_NEGATIVE |
SENSOR_IMAGE_EFFECT_CANVAS,
.wb_mode = 0,
.step_count = 7,
.reset_pulse_level = SENSOR_LOW_PULSE_RESET,
.reset_pulse_width = 50,
.power_down_level = SENSOR_LOW_LEVEL_PWDN,
.identify_count = 1,
.identify_code =
{
{.reg_addr = ov8858_PID_ADDR, .reg_value = ov8858_PID_VALUE},
{.reg_addr = ov8858_VER_ADDR, .reg_value = ov8858_VER_VALUE},
},
.source_width_max = SNAPSHOT_WIDTH,
.source_height_max = SNAPSHOT_HEIGHT,
.name = (cmr_s8 *)SENSOR_NAME,
.image_format = SENSOR_IMAGE_FORMAT_RAW, //原数据格式
.module_info_tab = s_ov8858_module_info_tab, //sensor信息表
.module_info_tab_size = ARRAY_SIZE(s_ov8858_module_info_tab),
.resolution_tab_info_ptr = s_ov8858_resolution_tab_raw, //摄像头图形分辨率表
.sns_ops = &s_ov8858_ops_tab, //ops函数操作集合
.raw_info_ptr = &s_ov8858_mipi_raw_info_ptr,
.video_tab_info_ptr = NULL,
.sensor_version_info = (cmr_s8 *)"ov8858v1",
};
2.4.重要函数
2.4.1.ov8858_drv_power_on
static cmr_int ov8858_drv_power_on()
{
define BOOLEAN unsigned int
/* 1: high level valid; 0: low level valid */
cmr_u32 power_down_level;
SENSOR_AVDD_VAL_E dvdd_val = module_info->dvdd_val;
SENSOR_AVDD_VAL_E avdd_val = module_info->avdd_val;
SENSOR_AVDD_VAL_E iovdd_val = module_info->iovdd_val;
BOOLEAN power_down = MIPI_RAW_INFO.power_down_level;
BOOLEAN reset_level = MIPI_RAW_INFO.reset_pulse_level;
...
if (SENSOR_TRUE == power_on)
{
//断电
hw_sensor_power_down(sns_drv_cxt->hw_handle, power_down);
hw_sensor_set_reset_level(sns_drv_cxt->hw_handle, reset_level);
hw_sensor_set_mclk(sns_drv_cxt->hw_handle, SENSOR_DISABLE_MCLK);
hw_sensor_set_avdd_val(sns_drv_cxt->hw_handle, SENSOR_AVDD_CLOSED);
hw_sensor_set_dvdd_val(sns_drv_cxt->hw_handle, SENSOR_AVDD_CLOSED);
hw_sensor_set_iovdd_val(sns_drv_cxt->hw_handle, SENSOR_AVDD_CLOSED);
usleep(1 * 1000);
//上电
hw_sensor_set_iovdd_val(sns_drv_cxt->hw_handle, iovdd_val);
hw_sensor_set_avdd_val(sns_drv_cxt->hw_handle, avdd_val);
hw_sensor_set_dvdd_val(sns_drv_cxt->hw_handle, dvdd_val);
usleep(1 * 1000);
hw_sensor_set_mclk(sns_drv_cxt->hw_handle, EX_MCLK);
hw_sensor_power_down(sns_drv_cxt->hw_handle, !power_down);
hw_sensor_set_reset_level(sns_drv_cxt->hw_handle, !reset_level);
hw_sensor_set_mipi_level(sns_drv_cxt->hw_handle, 0);
usleep(1 * 1000);
}
else
{
// hw_sensor_set_mclk(sns_drv_cxt->hw_handle, SENSOR_DISABLE_MCLK);
usleep(500);
hw_sensor_set_mipi_level(sns_drv_cxt->hw_handle, 1);
hw_sensor_set_reset_level(sns_drv_cxt->hw_handle, reset_level);
hw_sensor_power_down(sns_drv_cxt->hw_handle, power_down);
hw_sensor_set_mclk(sns_drv_cxt->hw_handle, SENSOR_DISABLE_MCLK);
usleep(200);
hw_sensor_set_dvdd_val(sns_drv_cxt->hw_handle, SENSOR_AVDD_CLOSED);
hw_sensor_set_avdd_val(sns_drv_cxt->hw_handle, SENSOR_AVDD_CLOSED);
hw_sensor_set_iovdd_val(sns_drv_cxt->hw_handle, SENSOR_AVDD_CLOSED);
}
}
2.4.2ov8858_drv_identify
/*==============================================================================
* Description:
* 识别传感器id
* 请根据您的规格修改此功能
*============================================================================*/
static cmr_int ov8858_drv_identify(cmr_handle handle, cmr_uint param) {
cmr_u16 pid_value = 0x00;
cmr_u16 ver_value = 0x00;
cmr_int ret_value = SENSOR_FAIL;
SENSOR_IC_CHECK_HANDLE(handle);
struct sensor_ic_drv_cxt *sns_drv_cxt = (struct sensor_ic_drv_cxt *)handle;
SENSOR_LOGI("mipi raw identify");
//IIC 传感器IC读寄存器接口
pid_value = hw_sensor_read_reg(sns_drv_cxt->hw_handle, ov8858_PID_ADDR);//#define ov8858_PID_ADDR 0x300B
if (ov8858_PID_VALUE == pid_value) { //#define ov8858_PID_VALUE 0x88
ver_value = hw_sensor_read_reg(sns_drv_cxt->hw_handle, ov8858_VER_ADDR);//#define ov8858_VER_ADDR 0x300C
SENSOR_LOGI("Identify: PID = %x, VER = %x", pid_value, ver_value);
if (ov8858_VER_VALUE == ver_value) { //#define ov8858_VER_VALUE 0x58
SENSOR_LOGI("this is ov8858 sensor");
// ov8858_drv_init_fps_info(handle);
ret_value = SENSOR_SUCCESS;
} else {
SENSOR_LOGI("Identify this is %x%x sensor", pid_value, ver_value);
}
} else {
SENSOR_LOGE("sensor identify fail, pid_value = %x", pid_value);
}
return ret_value;
}
2.5.sensor cfg介绍
//vendor/sprd/modules/libcamera/sensor/sensor_cfg.c
#ifdef OV8858
extern SENSOR_INFO_T g_ov8858_mipi_raw_info;
#endif
const SENSOR_MATCH_T back_sensor_infor_tab[] = {
...
#ifdef OV8858
{MODULE_SUNNY, "ov8858", &g_ov8858_mipi_raw_info, {&dw9763a_drv_entry, 0}, {&general_otp_entry, 0xB0, DUAL_CAM_ONE_EEPROM, 8192}},
#endif
...
#ifdef OV8858
{MODULE_SUNNY, "ov8858", &g_ov8858_mipi_raw_info, {&dw9763a_drv_entry, 0}, {&ov8858_cmk_drv_entry, 0xB0, DUAL_CAM_ONE_EEPROM, 8192}},
#endif
2.6.sensor 模组属性配置
<!-- device/sprd/sharkle/sl8541e_1h10wifi5g_32b/camera/sensor_config.xml -->
<CameraModuleCfg>
<SlotId>0</SlotId>
<SensorName>ov8858</SensorName>
<Facing>BACK</Facing>
<Orientation>90</Orientation>
<Resource_cost>50</Resource_cost>
<TuningParameter>
<TuningName>hi846_160</TuningName>
</TuningParameter>
</CameraModuleCfg>
<CameraModuleCfg>
<SlotId>0</SlotId>
<SensorName>gc02m1b_js_1</SensorName>
<Facing>BACK</Facing>
<Orientation>90</Orientation>
<Resource_cost>50</Resource_cost>
<TuningParameter>
<TuningName>hi846_160</TuningName>
</TuningParameter>
</CameraModuleCfg>
2.7.sensor_config xml配置文件
<!-- device/sprd/sharkle/sl8541e_1h10wifi5g_32b/camera/sensor_config.xml -->
<root>
<!-->
sensor id 0
<-->
<CameraModuleCfg>
<SlotId>0</SlotId>
<SensorName>ov64b40</SensorName><!-->与sensor驱动文件夹名称相同<-->
<Facing>BACK</Facing><!-->Sensor朝向<-->
<Orientation>90</Orientation><!-->Sensor安装角度<-->
<Resource_cost>50</Resource_cost><!-->该sensor资源占用比例,0-100<-->
<OTP>
<E2prom>
<OtpName>ov64b40_085</OtpName><!-->与OTP驱动文件夹名称相同<-->
<I2cAddr>0xa0</I2cAddr><!-->E2prom I2C地址<-->
<E2promNum>1</E2promNum><!-->E2prom数量及存放方式<-->
<E2promSize>2542</E2promSize><!-->E2prom大小,单位byte<-->
</E2prom>
</OTP>
<VCM>
<AfName>dw9800</AfName><!-->与AF驱动文件夹名称相同<-->
<Mode>0</Mode><!-->AF工作模式,默认为0<-->
</VCM>
<TuningParameter>
<TuningName>ov64b40</TuningName><!-->tuning参数的名称<-->
</TuningParameter>
</CameraModuleCfg>
...
<!-->
sensor id 1
3.mk文件配置
3.1.BoardConfig.mk
修改对应的 camera 的对应像素信息配置,根据camera 规格书配置。
#camera sensor support list
#example
#CAMERA_SENSOR_TYPE_BACK :="ov8856,ov8858"
CAMERA_SENSOR_TYPE_BACK := "s5k4h7_wifi5g"
CAMERA_SENSOR_TYPE_FRONT := "gc2385_wifi5g"
CAMERA_SENSOR_TYPE_BACK_EXT := ""
CAMERA_SENSOR_TYPE_FRONT_EXT :=
#tuning param support list
TUNING_PARAM_LIST := "s5k4h7_front_main_wifi5g,gc2385_wifi5g"
追踪 CAMERA_SENSOR_TYPE_BACK
//vendor/sprd/modules/libcamera/sensor/sensor_cfg.c
char *sensor_get_name_list(cmr_u32 sensor_id) {
char *sensor_name_list_ptr = NULL;
switch (sensor_id) {
case SENSOR_MAIN:
sensor_name_list_ptr = (char *)CAMERA_SENSOR_TYPE_BACK;
break;
...
return (char *)sensor_name_list_ptr;
}
//sensor_get_name_list
cmr_int sensor_check_name(cmr_u32 sensor_id, SENSOR_MATCH_T *reg_tab_ptr) {
cmr_int ret = SENSOR_SUCCESS;
const char *delimiters = ",";
char *sns_name_list_ptr = sensor_get_name_list(sensor_id);
char sns_name_str[MAX_SENSOR_NAME_LEN] = {0};
char *token;
memcpy(sns_name_str, sns_name_list_ptr,
MIN(strlen(sns_name_list_ptr), MAX_SENSOR_NAME_LEN));
for (token = strtok(sns_name_str, delimiters); token != NULL;
token = strtok(NULL, delimiters)) {
if (strcasecmp(reg_tab_ptr->sn_name, token) == 0) {
SENSOR_LOGI("%s name match succesful\n", token);
return ret;
}
}
return SENSOR_FAIL;
}
//sensor_check_name
//未被调用
M1710U/sl8541e_1h10wifi5g_32b_Natv/out/target/product/sl8541e_1h10wifi5g_32b$ find . -name "*sensor_cfg*"
./obj/SHARED_LIBRARIES/libcamsensor_intermediates/sensor_cfg.o
./obj/SHARED_LIBRARIES/libcamsensor_intermediates/sensor_cfg.d
3.2.Android.mk
#vendor/sprd/modules/libcamera/sensor/Android.mk
LOCAL_SRC_FILES += \
sensor_cfg.c \
LOCAL_MODULE := libcamsensor #生成libcamsensor库
编译的so库
sl8541e_1h10wifi5g_32b_Natv/out/target/product/sl8541e_1h10wifi5g_32b$ find . -name "libcamsensor.*"
./obj/SHARED_LIBRARIES/libcamsensor_intermediates/libcamsensor.so
./obj/SHARED_LIBRARIES/libcamsensor_intermediates/LINKED/libcamsensor.so
./obj/SHARED_LIBRARIES/libcamsensor_intermediates/libcamsensor.so.toc
./obj/SHARED_LIBRARIES/libcamsensor_intermediates/libcamsensor.so.d
./obj/PACKAGING/target_files_intermediates/sl8541e_1h10wifi5g_32b_Natv-target_files-20230519.163824/VENDOR/lib/libcamsensor.so
./archive_symbols/symbols.vendor/vendor/lib/libcamsensor.so
./symbols/vendor/lib/libcamsensor.so
./vendor/lib/libcamsensor.so
4.平台OTP驱动
OTP:一次编程的可编程只读存储器
文件路径:vendor/sprd/modules/libcamera/sensor/otp_drv/driver
按照平台OTP规范烧录,数据存储在E2PROM中,可以在该目录下添加驱动,可以参考general驱动。
5.AF驱动移植
AF:自动对焦技术
文件路径:vendor/sprd/modules/libcamera/sensor/af_drv
在该目录下添加AF的驱动,然后在vcm_lib_cfg.mk中添加AF驱动编译关系。
6.闪光灯驱动移植
文件路径:
bsp/modules/common/camera/flash_bsp/kernel/kernel4.14/arch/arm/boot/dts/M1710U_Q/sl8541e-1h10wifi5g_32b.dts
在bsp/modules/common/camera/flash下添加驱动文件夹,并在dts文件中对flash进行设置
flash_ic: flash-ic@63 {
compatible = "sprd,flash-aw36518";
reg = <0x63>;
sprd,flash-ic = <36518>;
sprd,torch = <1>;
sprd,preflash = <1>;
sprd,highlight = <1>;
sprd,torch-level = <128>;
sprd,preflash-level = <128>;
sprd,highlight-level = <128>;
sprd,lvfm-enable = <1>;
flash-torch-en-gpios = <&ap_gpio 88 0>;
flash-chip-en-gpios = <&ap_gpio 89 0>;
flash-sync-gpios = <&ap_gpio 141 0>;
};
7.问题
7.1.Camera读取不到ID
打印log .
dev_ err(dev, “Unexpected sensor id(%06x), ret(%d)n”, id, ret);
os04a10 1-0036- 1: Unexpected sensor id(000000), ret(-5)
i2c不通,在读取id之前_os04a10_ power_ on(os04a10);会上电,
所以操作都在这个函数里,确定在这里面供电,clk,各管脚都正常了。仔细量了。
如果是其他摄像头要确定
i2c 地址正常
挂在哪个i2c通道下面
dts 里面都是7位地址
注意不要写错了。
建议i2c的问题客户自己查,这种,只要是_ os04a10 power_ _on 操作对了就不会有问题。
参考:
https://www.cnblogs.com/ChenChangXiong/p/14919931.html
https://blog.csdn.net/lovemengx/article/details/105166764
3526

被折叠的 条评论
为什么被折叠?



