这一篇和上一篇一样,基本属于临时抱佛脚的。
1 Camera的结构
大体上有这些部件。
核心部件就是Lens,VCM音圈马达,红外滤光片(IR-cut Filter),图像传感器(Sensor),最后是柔性电路板。
这里就不详细了,因为很多技术细节,对于bringup其实是没用的。或者说要到很深层次问题才会遇到。今天是短平快的文章,就不写那么多了。
2 Bringup的工作
用比较流行的IMX219为例,DataSheet是在:https://www.opensourceinstruments.com/Electronics/Data/IMX219PQ.pdf
实际的模块图是这样的,可以看到,一共有15个引脚。这里是双通道的MIPI。
引脚大概分为三组,需要做的工作如下:
1 MIPI,P1/N1 (Lane 1): 第一组差分数据对。P2/N2 (Lane 2): 第二组差分数据对。CP/CN (Clock): 差分时钟对。GND,穿插在差分对之间的地线,用于阻抗匹配和减少串扰。
这里的XCLK需要提供稳定的24MHz时钟。其它的还好。
2 I2C控制。(SDA, SCL)。
这边配置的内容最多,包括设备地址,各种命令寄存器,一开始的配置流程。相对来说是内容最多的部分。在Datasheet中篇幅也最多。
比如:
3 物理控制。包括了3.3~5V,GND,LDO-PW内部LDO供电,可起到RST作用,LED闪光灯。
这里就是确保供电稳定,然后供电的时序,通常需要先上电,延迟几毫秒,再给时钟,再发送命令这部分一定要精确控制。
比如:
3 高通平台的应用
目前手上没有高通的板子,所以这部分内容来自网络。
主要来自两个文章:https://bbs.huaweicloud.com/blogs/308120
https://blog.csdn.net/wanghz999/article/details/144322748,https://blog.csdn.net/wanghz999/article/details/144488973,https://blog.csdn.net/wanghz999/article/details/145816091?spm=1001.2014.3001.5502
需要配置的就是三个部分。DTS,应用层配置,模块E2PROM等。
3.1 驱动和设备树
设备树是kernel/arch/arm/boot/***-camera-sensor-cdp.dtsi
qcom,camera@20 {
compatible =“qcom,imx111”;
reg = <0x20>;
qcom,slave-id =<0x20 0x0 0x111>; //(slave id – 0x20, chip id address – 0x0, chip id –0x111)
qcom,csiphy-sd-index= <0>; //(Use CSIPHY subdev 0)
qcom,csid-sd-index= <0>; //(Use CSID subdev 0)
qcom,flash-src-index= <&led_flash0>; //(Use LED flash subdev 0)
qcom,mount-angle =<90>; //(mount angle 90 degree)
qcom,sensor-name =“imx111”;// (sensor name)
cam_vdig-supply =<&pm8941_l3>;// (Use L3 for VDIG)
cam_vana-supply =<&pm8941_l23>;// (Use L23 for VANA)
cam_vio-supply =<&pm8941_lvs2>; //(Use LVS3 for VIO)
cam_vaf-supply =<&pm8941_l17>; //(Use L17 for VAF)
qcom,cam-vreg-name= “cam_vdig”, “cam_vio”, “cam_vana”, “cam_vaf”;
qcom,cam-vreg-type= <0 1 0 0>; //(0 – LDO, 1 – LVS)
qcom,cam-vreg-min-voltage= <1225000 0 2850000 2850000>;// (min voltage)
qcom,cam-vreg-max-voltage= <1225000 0 2850000 2850000>;// (max voltage)
qcom,cam-vreg-op-mode= <105000 0 80000 100000>; //(Optimum mode)
qcom,gpio-no-mux =<0>;
gpios =<&msmgpio 15 0>, <&msmgpio 90 0>;
qcom,gpio-reset =<1>; //(Use gpio pin 90 for reset)
qcom,gpio-req-tbl-num= <0 1>; //(0 – pin 15, 1 – pin 90)
qcom,gpio-req-tbl-flags= <1 0>; //(0 – output gpio, 1 – input gpio)
qcom,gpio-req-tbl-label= “CAMIF_MCLK”, “CAM_RESET1”; //(gpio name)
qcom,gpio-set-tbl-num= <1 1>;// (1 – pin 90)
qcom,gpio-set-tbl-flags= <0 2>; //(0 – GPIOF_OUT_INIT_LOW, 2 -
GPIOF_OUT_INIT_HIGH)
qcom,gpio-set-tbl-delay= <1000 4000>; //(delay in micro sec)
qcom,csi-lane-assign= <0x4320>; //(Use 0x4320 for CSI lane assign)
qcom,csi-lane-mask= <0x1F>; //(Use 0x1F for lane mask)
qcom,sensor-position= <0>; //(0 – back camera, 1 – front camera)
qcom,sensor-mode =<1>;// (1 – 2D, 3 – 3D)
qcom,cci-master =<0>; //(0 – Master 0, 1 – Master 1)
status = “ok”;
};
可以看出,主要的配置内容就是设备地址,寄存器名称,供电引脚等。
配置完成后,有两个tips。
1 DTS是否编译进去
DTS编译完成后是生成DTB,可以用DTC工具反编译后验证。
adb root
adb pull /sys/firmware/fdt ./
dtc -I dtb -O dts fdt > neo.dts
2 供电是否配置正确
mount -t debugfs debugfs /sys/kernel/debug
cat /sys/kernel/debug/regulator_summary
当然,更直接的还是直接用万用表打。
3.2 驱动
这里一部分是XML文件,一部分是驱动代码kernel/drivers/media/platform/msm/camera_v2/sensor/imx111.c
这部分主要就是图像的属性。
输出分辨率与帧率
输入时钟(MCLK):一般情况Sensor的输入时钟是ISP提供,需要确认ISP支持那些时钟输出;一般是可以配置的,保险起见最好选择像24M这样的标准时钟。
输出格式:RAW/RGB/YUV
宽动态模式:线性/build-in/DCG/HDR
数据输出方式:MIPI/LVDS
Lane数量:1/2/4
输出最大传输速率限制:Sensor接不同的serders或者ISP芯片对最大传输速率限制各不相同;
RAW图的位数(8/10/12/14/16):线性模式下主要限制是传输;而宽动态模式下位数的限制主要是后端ISP能支持几位的数据处理,尤其是Sensor build-in模式下2帧合成和4帧合成输出ISP解压缩模块要求完全不同;
是否binning:高分辨率用作低分辨率时会用到binning,比如将800W像素,每2*2个像素合成一个;
镜像/翻转;
画面位置及裁剪,根据实际需求不同提需求;
该配置是否在其他平台上对接过?如果确定某配置是出图正常的,会让对接过程顺利不少;
如果有多个配置需求可以一起提出来,能节省时间。
camera 对应的chromatix library 和sensor library
这里配置的就是摄像的具体属性,主要就是I2C的寄存器。主要涉及到XML配置文件。
1)init, start, stop寄存器配置
2)coarse_int_time_addr 、global_gain_addr 寄存器地址
3)x_output 、y_output、line_length_pclk 、frame_length_lines 寄存器地址
4)full/half resolution 寄存器配置
5)配置每个every resolution 对应的Chromatix library
6)配置每个resolution 对应的sensor_out_info
大概如下:
...
<slaveInfo>
<!--Name of the sensor-->
<!--Sensor名字,与module文件中指定的需要完全对应上,如果有2颗一样是Sensor,推荐sensorName也有区分-->
<sensorName>ov13b10</sensorName>
<!--8-bit or 10-bit write slave address-->
<!-- Sensor的I2C地址,重要-->
<slaveAddress>0x6c</slaveAddress>
<!--Register address / data size in bytes -->
<regAddrType range="[1,4]">2</regAddrType>
<!--Register address / data size in bytes -->
<regDataType range="[1,4]">2</regDataType>
<!--Register address for sensor Id -->
<sensorIdRegAddr>0x300b</sensorIdRegAddr>
<!--Sensor Id-->
<!--在Sensor驱动加载时会去读取sensorId,如果读取的sensorId不对会直接导致驱动加载失败-->
<sensorId>0x0D42</sensorId>
...
CPP中主要配置Sensor曝光时间和增益变化相关的设置。
3.3 其它
多module。这部分主要是可能供应商来自不止一个,做了这个配置可以保证替换供应商后不用改代码。
EEPROM是存储校正参数,模组信息等。
最后就是multicamera,也是在XML中进行配置。。。