高通camera驱动分析
./qcom/proprietary/mm-still/codec_v1/omx/jpeg_encoder/Android.mk:15:CHROMATIX_VERSION := 0309
这个定义用那个版本,这个就是用0309的版本
在调试的时候发现不能点亮,发现是pdaf关掉就可以了。 is_pdaf_support =0;
在调试代码的时候发现, 内核部分只有配置电压和始终的代码,初始化部分都在 vendor下, 通过名字匹配。af也是一样。
sensor_init.c 里可以添加 支持的sensor类型,可以支持多颗sensor ,能够自动识。
OV8865
1、kernel部分:
A、kernel_driver:
把驱动文件ov8865_qtech_f8865ac.c 放到kernel/drivers/media/platform/msm/camera_v2/sensor/目录下
B、kernel_dtsi:
把如下板级信息加到kernel/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi文件中
actuator1: qcom,actuator@18 {
cell-index = <4>;
reg = <0x18>;
compatible = "qcom,actuator";
qcom,cci-master = <0>;
};
eeprom0:qom,eeprom@2b{
cell-index = <0>;
reg = <0x2b 0x0>;
...
...
};
qcom,camera@7f {
compatible = "qcom,ov8865_qtech";
reg = <0x7f>;
qcom,slave-id = <0x6c 0x300b 0x8865>;
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator1>;
qcom,eeprom-src = <&eeprom0>;
qcom,led-flash-src = <&led_flash0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov8865_qtech";
cam_vdig-supply = <&pm8110_l7>;
cam_vana-supply = <&pm8110_l19>;
cam_vio-supply = <&pm8110_l14>;
qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
qcom,cam-vreg-type = <0 0 0>;
qcom,cam-vreg-min-voltage = <1500000 1800000 2850000>;
qcom,cam-vreg-max-voltage = <1500000 1800000 2850000>;
qcom,cam-vreg-op-mode = <200000 200000 100000>;
qcom,gpio-no-mux = <0>;
gpios = <&msmgpio 13 0>,
<&msmgpio 21 0>,
<&msmgpio 20 0>,
<&pm8110_gpios 2 0>;
qcom,gpio-reset = <1>;
qcom,gpio-standby = <2>;
qcom,gpio-vdig = <3>;
qcom,gpio-req-tbl-num = <0 1 2 3>;
qcom,gpio-req-tbl-flags = <1 0 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK",
"CAM_RESET1",
"CAM_STANDBY",
"CAM_VDIG";
qcom,csi-lane-assign = <0xe4>;
qcom,csi-lane-mask = <0x3>;
qcom,sensor-position = <0>;
qcom,sensor-mode = <1>;
qcom,cci-master = <0>;
};
C、kernel-clock:
这部分主要是针对 B 的,增加一些I2C地址
如下代码断:
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3033,6 +3033,7 @@ static struct clk_lookup msm_clocks_8610[] = {
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-0020"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006a"),
CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "6-0048"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006c"), //front camera ismclk1_clk_src.c back camera ismclk0_clk_src.c
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006f"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-0034"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-007d"),
@@ -3042,6 +3043,7 @@ static struct clk_lookup msm_clocks_8610[] = {
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-0020"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006a"),
CLK_LOOKUP("cam_clk", mclk1_clk.c, "6-0048"),
+ CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006c"),
D、把C文件加到Makefile
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -22,3 +22,4 @@ obj-y += gc2035.o
#obj-$(CONFIG_SP1628) += sp1628.o
obj-$(CONFIG_GC0339) += gc0339.o
obj-$(CONFIG_HM1090) += HM1090.o
+obj-y +=ov8865_qtech_f8865ac.o
kernel部分就这么多了,此时可以先编译一个bootimage看看能不能编译过。
2、vendor部分
这一部分主要包括:效果(chromatix)、马达AF驱动(actuators)、库文件(sensor_libs)
A、效果(chromatix):把chromatix_ov8865_qtech_f8865ac整个文件夹放到vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/chromatix/0301/libchromatix/下
B、马达AF驱动(actuators) :把af_main_cam_camcorder_6.h、af_main_cam_camera_6.h AF头文件放到vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/actuators/0301/目录下。
同时做如下工作:
--- a/mm-camera/mm-camera2/media-controller/modules/sensors/actuators/actuator.c
+++ b/mm-camera/mm-camera2/media-controller/modules/sensors/actuators/actuator.c
@@ -13,7 +14,7 @@
-static actuator_ctrl_t actuators[ACTUATOR_CAM_MODE_MAX][6] = {
+static actuator_ctrl_t actuators[ACTUATOR_CAM_MODE_MAX][7] = {
@@ -21,6 +22,7 @@ static actuator_ctrl_t actuators[ACTUATOR_CAM_MODE_MAX][6] = {
#include "af_main_cam_camera_2.h"
#include "af_main_cam_camera_3.h"
#include "af_main_cam_camera_4.h"
#include "af_main_cam_camera_5.h"
+ #include "af_main_cam_camera_6.h"
@@ -29,6 +31,7 @@ static actuator_ctrl_t actuators[ACTUATOR_CAM_MODE_MAX][6] = {
#include "af_main_cam_camcorder_2.h"
#include "af_main_cam_camcorder_3.h"
#include "af_main_cam_camcorder_4.h"
#include "af_main_cam_camcorder_5.h"
+ #include "af_main_cam_camcorder_6.h"
}
};
在af_main_cam_camcorder_6.h中会有af_header_info_t:
如下:
/* af_header_info_t */
{
/* header_version */
0x301,
/* cam_name */
ACTUATOR_MAIN_CAM_6,
/* module_name */
"ov8865",
/* actuator_name */
"BU64243GWZ",
}, /* af_header_info_t */
其中ACTUATOR_MAIN_CAM_6这个需要在kernel中定义,在kernel/include/media/msm_cam_sensor.h文件中添加ACTUATOR_MAIN_CAM_6
enum af_camera_name {
ACTUATOR_MAIN_CAM_0,
ACTUATOR_MAIN_CAM_1,
ACTUATOR_MAIN_CAM_2,
ACTUATOR_MAIN_CAM_3,
ACTUATOR_MAIN_CAM_4,
ACTUATOR_MAIN_CAM_5,
ACTUATOR_MAIN_CAM_6
ACTUATOR_WEB_CAM_0,
ACTUATOR_WEB_CAM_1,
ACTUATOR_WEB_CAM_2,
};
C、库文件(sensor_libs) :把ov8865_qtech_f8865ac整个文件夹放到vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor_libs/目录下
D、把相关文件添加到config中,如下:
--- a/common/config/device-vendor.mk
+++ b/common/config/device-vendor.mk
@@ -526,6 +526,7 @@ MM_CAMERA += libmmcamera_s5k3l1yx
+MM_CAMERA += libmmcamera_ov8865_qtech //库文件
MM_CAMERA += libmmcamera_SKUAA_ST_gc0339
@@ -617,6 +618,10 @@ MM_CAMERA += libchromatix_ov8825_7853f_snapshot
MM_CAMERA += libchromatix_ov8825_7853f_zsl
+MM_CAMERA += libchromatix_ov8865_qtech_f8865ac_snapshot //效果文件
+MM_CAMERA += libchromatix_ov8865_qtech_f8865ac_preview
+MM_CAMERA += libchromatix_ov8865_qtech_f8865ac_common
+MM_CAMERA += libchromatix_ov8865_qtech_f8865ac_default_video
MM_CAMERA += libchromatix_SKUAA_ST_gc0339_common
@@ -640,6 +645,7 @@ MM_CAMERA += libchromatix_skuf_ov5648_p5v23c_preview
MM_CAMERA += libmmcamera_truly_cm7700_eeprom
+MM_CAMERA += libmmcamera_qtech_f8865ac_eeprom //e2prom文件
MM_CAMERA += libmmcamera_sunny_p12v01m_eeprom
编systemimage.img验证
1camera基本代码架构
高通平台对于camera的代码组织,大体上还是遵循Android的框架:即上层应用和HAL层交互,高通平台在HAL层里面实现自己的一套管理策略;在kernel中实现sensor的底层驱动。但是,对于最核心的sensor端的底层设置、ISP效果相关等代码则是单独进行了抽离,放在了一个daemon进程中进行管理:
由于高通把大部分具体的设置及参数放到了daemon进程中,所以在kernel部分只是进行了V4L2的设备注册、IIC设备注册等简单的动作:
如上图,camera在kernel层的主文件为msm.c,负责设备的具体注册及相关方法的填充;在msm_sensor.c文件中,主要维护高通自己的一个sensor相关结构体—msm_sensor_ctrl_t,同时把dts文件中的配置信息读取出来;kernel层对于不同的sensor对应自己的一个驱动文件—xxsensor.c,主要是把powersetting的设定填充到msm_sensor_ctrl_t中。
在vendor目录下,高通把各个sensor实质性的代码放置在此。一部分代码是高通自己实现的daemon进程和kernel层及HAL层进行通讯的框架代码;另一部分则是和sensor相关的chromatix效果代码和sensorlib部分代码(initsetting、lensinfo、outputinfo)。
如上图,高通平台通过一个函数指针数组sub_module_init来管理sensor相关的组件;其中重要的是sensor_sub_module_init和chromatix_sub_module_init模块,对于sensor模块需要对应填充sensor_lib_t下的接口,对于chromatix模块则是通过高通的chromatix工具生成。
从更高的层次来看,sensor部分的代码只是camera子系统的一部分。打开高通vendor下面关于camera的源码也可以看到,/mm-camera2/media-controller/modules目录下面,sensors只是modules文件下面其中的一个子目录。
2主要移植步骤
2.1kernel层代码移植
对于kernel层的代码移植,实际上对dts文件的移植。因为kernel层驱动代码基本已经被高通的框架以及vendor下代码架空,只剩下一个上电的列表。具体步骤为:
1.在目录kernel/arch/arm/boot/dts/下的对应dtsi文件中新增camera节点,主要关注节点中的IIC地址、sensro的ID信息、电压设定信息:
2.在目录kernel/drivers/media/platform/msm/camera_v2/sensor/目录新增xxsensor.c文件,主要填充msm_sensor_power_setting结构体:sensor上电的包含的引脚设定和电压设定,具体格式可以参考同目录下的其他文件。
3.kernel下面的相关mk文件:
其他:如果sensor中带有eeprom,需要在dts文件中增加eeprom的节点信息;同样,sensor带有对焦功能,需要在dts文件中增加actuator节点信息;对于带eeprom的sensor,还需要配置eeprom的时钟控制代码(有待研究)。
2.2vendor下代码移植
Vendor下面的代码主要是两部分,一个是sensor_libs目录下的sensor具体设定、配置文件,另一个是chromatix下面的ISP效果文件。具体为:
1.sensor_libs目录下文件:包括一个Android.mk文件和一个.c文件。其中Android.mk文件参考同目录下其他.mk文件修改和对应sensor有关设定即可;.c文件中需要填充的为一个sensor_lib_t类型的结构体:
2.chromatix目录下相关文件,在对应sensor目录下包含4个目录和一个Android文件,总共13个文件,这些文件都会由chromatix调试工具生成。下面为IMX179文件实例:
3.vendor下还有eeprom文件,模组自带的eeprom数据处理相关;AF相关文件,调试工具生成的关于AF的效果文件;配置文件,把需要编译的模块填进配置文件中。
1、Sensor slave配置
结构体msm_camera_sensor_slave_info定义在media/msm_cam_sensor.h中:
struct msm_camera_sensor_slave_info {
char
sensor_name[32];
//sensor名称
char
eeprom_name[32];
//eeprom名称
char
actuator_name[32];
//actuator名称
enum msm_sensor_camera_id_t
camera_id;
//camera id号
uint16_t
slave_addr;
//从地址
enum msm_camera_i2c_reg_addr_type addr_type;
//camera i2c寄存器地址类型
struct msm_sensor_id_info_t
sensor_id_info;
//sensor 芯片id信息
struct msm_sensor_power_setting_array power_setting_array;
//上电序列
uint8_t
is_init_params_vaild; //初始化参数是否有效
struct msm_sensor_init_params
sensor_init_params;
//sensor初始化参数
};
1.1、枚举类型msm_sensor_camera_id_t的定义如下:
enum msm_sensor_camera_id_t {
CAMERA_0,
//camera id 号0
CAMERA_1,
//camera id 号1
CAMERA_2,
//camera id 号2
CAMERA_3,
//camera id 号3
MAX_CAMERAS,
//支持的最大id号
};
1.2、枚举类型msm_camera_i2c_reg_addr_type的定义如下:
enum msm_camera_i2c_reg_addr_type{
MSM_CAMERA_I2C_BYTE_ADDR = 1,
//1字节型
MSM_CAMERA_I2C_WORD_ADDR,
//2字型
MSM_CAMERA_I2C_3B_ADDR,
//3字节型
};
1.3、结构体msm_sensor_id_info_t的定义如下:
struct msm_sensor_id_info_t{
uint16_t
sensor_id_reg_addr;
//对应sensor id号的寄存器地址
uint16_t
sensor_id;
//sensor id号
};
1.4、结构体 msm_sensor_power_setting_array的定义如下:
enum msm_sensor_power_seq_type_t{
SENSOR_CLK,
SENSOR_GPIO,
SENSOR_VREG,
SENSOR_I2C_MUX,
};
struct msm_sensor_power_setting{ //上电序列
enum msm_sensor_power_seq_type
seq_type;
uint16_t
seq_val;
long
config_val;
uint16_t
delay;
void
*data[10];
};
struct msm_sensor_power_setting_array{
struct msm_sensor_power_setting
*power_setting;
uint16_t
size;
struct
msm_sensor_power_setting
*power_down_setting;
uint16_t
size_down;
};
1.5、结构体msm_sensor_init_params的定义如下:
enum camb_position_t{
BACK_CAMERA_B,
//后摄
FRONT_CAMERA_B,
//前摄
INVALID_CAMERA_B,
//非法
}
struct msm_sensor_init_params{
/* mask of modes supported: 2D, 3D */
int
modes_supported;
//支持camera的模式
/* sensor position: front, back */
enum camb_position_t
position;
//sensor的位置
/* sensor mount angle
*/
uint32_t
sensor_mount_angle;
//sensor安装的角度
};
举例:
以下是imx230_lib.c中对sensor初始化参数的设置。
支持模式的值是在枚举类型camerab_mode_t中:
enum camerab_mode_t{
CAMERA_MODE_2D_B = (1<<0),
//2D
CAMERA_MODE_3D_B = (1<<1),
//3D
CAMERA_MODE_INVALID = (1<<2),
//非法
};
2D模式:平面图像模式。
3D模式:拍照出使裸眼观看就具有立体感的图像的模式,需要使用双摄像头。
sensor安装角度的值是宏定义,在sensor_lib.h中:
/*MOUNT ANGLE >= to this value is considered invalid in sensor lib */
#define SENSOR_MOUNTANGLE_360
360
//360度
/* Sensor mount angle. */
#define SENSOR_MOUNTANGLE_0
0
//0度
#define SENSOR_MOUNTANGLE_90
90
//90度
#define SENSOR_MOUNTANGLE_180
180
//180度
#define SENSOR_MOUNTANGLE_270270 //270度
2.、Sensor 输出设置
2.1 、Sensor输出格式设置
输出格式:Bayer/YUV.
连接模式:parallel/MIPI. msm8974只支持MIPI.
Raw图格式:8/10/12 bits.
imx230分别设置为Bayer、MIPI、10bit。
结构体sensor_output_t 定义在sensor_lib.h中:
typedef struct{
sensor_output_format_t
output_format;
//输出格式
sensor_connection_mode_t
connection_mode;
//连接模式
sensor_raw_output_t
raw_output;
//raw图格式
}sensor_output_t;
其中sensor_output_format_t, sensor_connection_mode_t, sensor_raw_output_t为枚举类型,定义如下:
typedef enum{
SENSOR_BAYER,
//Bayer格式
SENSOR_YCBCR
//YUV格式(Y,Cb,Cr)
}sensor_output_format_t;
typedef enum{
SENSOR_PARALLEL,
//并行
SENSOR_MIPI_CSI,
//MIPI CSI
SENSOR_MIPI_CSI_1,
//CSI1
SENSOR_MIPI_CSI_2,
//CSI2
}sensor_connection_mode_t;
typedef enum{
SENSOR_8_BIT_DIRECT,
//8-bit
SENSOR_10_BIT_DIRECT,
//10-bit
SENSOR_12_BIT_DIRECT,
//12-bit
}sensor_raw_output_t;
10-bit RAW图数据是通过数据包的格式进行传输的,打包之后的数据格式为8-bit。下表是对RAW10数据包格式限制条件的说明,每一个数据包的长度必须是表中数值的整数倍,bit位传输顺序服从CSI-2规则,LSB优先。
2.2 、Sensor像素格式信息
结构体sensor_pix_fmt_info_t定义在sensor_lib.h中:
struct sensor_pix_fmt_info_t {
uint32_t
fourcc;
};
像素格式的值V4L2_PIX_FMT_SRGGB10是宏定义在linux/videodev2.h中,如下:
/* __u32为unsigned int 型 */
#define v4l2_fourcc(a,b,c,d) \
((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)
//为什么这么做?
/* www.siliconimaging.com/RGB%20Bayer.htm */
#define V4L2_PIX_FMT_SBGGR8
v4l2_fourcc('B','A','8','1')
//BGGR 8bit
#define V4L2_PIX_FMT_SGBRG8
v4l2_fourcc('G','B','R','G')
//GBRG 8bit
#define V4L2_PIX_FMT_SGRBG8
v4l2_fourcc('G','R','B','G')
//GRBG 8bit
#define V4L2_PIX_FMT_SRGGB8
v4l2_fourcc('R','G','G','B')
//RGGB 8bit
#define V4L2_PIX_FMT_SBGGR10
v4l2_fourcc('B','G','1','0')
//BGGR 10bit
#define V4L2_PIX_FMT_SGBRG10
v4l2_fourcc('G','B','1','0')
//GBRG 10bit
#define V4L2_PIX_FMT_SGRBG10
v4l2_fourcc('B','A','1','0')
//GRBG 10bit
#define V4L2_PIX_FMT_SRGGB10
v4l2_fourcc('R','G','1','0')
//RGGB 10bit
#define V4L2_PIX_FMT_SBGGR12
v4l2_fourcc('B','G','1','2')
//BGGR 12bit
#define V4L2_PIX_FMT_SGBRG12
v4l2_fourcc('G','B','1','2')
//GBRG 12bit
#define V4L2_PIX_FMT_SGRBG12
v4l2_fourcc('B','A','1','2')
//GRBG 12bit
#define V4L2_PIX_FMT_SRGGB12
v4l2_fourcc('R','G','1','2')
//RGGB 12bit
像素格式的值MSM_V4L2_PIX_FMT_META是宏定义在media/msm_cam_sensor.h中:
#define MSM_V4L2_PIX_FMT_META
v4l2_fourcc('M','E','T','A')
2.3 、Sensor输出尺寸设置
结构体sensor_lib_out_info_t用于保存sensor所支持的不同分辨率的信息。imx230_lib.c中使用结构体sensor_lib_out_info_t定义了一个sensor_out_info[]。sensor_out_info[0]保存最大分辨率信息,sensor_out_info[1]保存1/4最大分辨率的信息。
2.3.1、 各参数含义解释
结构体sensor_lib_out_info_t的定义如下:
struct sensor_lib_out_info_t {
uint16_t
x_output;
//sensor 输出宽度(pixels)
uint16_t
y_output;
//sensor输出高度(pixels)
uint16_t
line_lenth_pclk;
//每一帧每一行多少个pixels
uint16_t
frame_length_lines;
//每一帧多少行
uint32_t
vt_pixel_clk;
//sensor 扫描速率(pixels per sec)
uint32_t
op_pixel_clk;
//sensor实际输出速率(pixels per sec)
uint16_t
bining_factor;
/*?: 1 if average is taken, >1 if sum is
taken(applies only for if this resolution has binnig) */
float
min_fps;
//sensor支持的最小帧率
float
max_fps;
//sensor支持的最大帧率
uint32_t
mode;
//分辨率所对应的模式
};
使用Chromatix软件进行tuning设置Image Width和Image Height的值时分别参考此处x_output和y_output。
line_length_pckl 和frame_length_lines 是指包含blanking的宽度值和高度值。
line_lenth_pclk和frame_length_lines决定帧的大小。
什么是blanking?
每一帧图像的每一行输出是遵循CSI2的通用帧格式。每一行的行尾(Packet Footer,PF)到下一行行头(Packet Header,PH)的期间称为“line blanking”。同样的,每一帧的帧尾(Frame End,FE)到下一帧帧头(Frame Start,FS)的期间称为“frame blanking”。
vt_pixel_clk时钟用于内部图像处理,计算曝光时间和帧率等。
曝光时间计算见4.1。
帧率:frame rate = vt_pixel_clk / (line_lenth_pclk * frame_length_lines).
op_pixel_clk = (sensor 输出实际比特率)/bits-per-pixel.
比如,如果 MIPI DDR 时钟值 (sensor MIPI 的时钟 lane 频率) 为 300Mhz, 同时 sensor 使用4 个 lane 传输数据, 每一个 lane 的数据率是 300*2 = 600Mhz. 因此, 总数据率为 600*4= 2400Mhz. 对于 10bit 的 bayer sensor, op_pixel_clk 值可设置为 2400/10 = 240Mhz.这些值可以从 sensor 的寄存器设置中计算出来。
其中的mode的值是宏定义的,如下:
/* HFR模式不用于常规的camera,camcorder */
#define SENSOR_DEFAULT_MODE (1 << 0)
//默认模式
#define SENSOR_HFR_MODE (1 << 1)
//高帧率模式,用于捕捉慢动作视频
#define SENSOR_HDR_MODE (1 << 2)
//高动态范围图像模式
结构体sensor_lib_out_info_array的定义如下:
struct sensor_lib_out_info_array {
struct sensor_lib_out_info_t
*out_info;
//指向sensor_lib_out_info_t结构体的指针
uint16_t
size;
//sensor_lib_out_info_t结构体数组长度
};
ARRAY_SIZE的宏定义如下:
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
//获取数组长度。
2.3.2 、x_output & y_output参数设置
x_output和y_output是sensor输出图像的重要参数,分别代表了图像的宽度和高度,单位是pixel。上层camera app最终就是从这里获取的sensor输出图像的宽度和高度信息,然后根据此信息裁剪出各种尺寸的图片。
Camera app照相所支持的图片尺寸在mct_pipeline.c(路径:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/pipeline)中定义,如下图:
因此imx230的x_output和y_output参数设置是不能小于上图中的最大尺寸,同时要与实际sensor输出图像的尺寸一致。
Imx230中控制sensor输出图像尺寸的寄存器关系如下图:
由关系图可以看出,最终控制sensor图像输出尺寸的是寄存器X_OUT_SIZE和Y_OUT_SIZE,所以x_output和y_output的值要与这两个寄存器的值一致。
一般sensor提供商所提供的这些寄存器的设置,都是由寄存器X_ADD_STA ,Y_ADD_STA, X_ADD_END和Y_ADD_END所确定的尺寸就是sensor最后输出的尺寸,这样后面的bining、sub-sampling、digtal crop、scaling 处理都可以省去以节约拍照时间。
2.4 、Sensor输出寄存器地址设置
结构体 msm_sensor_output_reg_addr_t的定义如下:
struct msm_sensor_output_reg_addr_t {
uint16_t
x_output;
//寄存器X_OUT_SIZE地址
uint16_t
y_output;
//寄存器Y_OUT_SIZE地址
uint16_t
line_length_pclk;
//寄存器LIN_LENGTH_PCK地址
uint16_t
frame_length_lines;
//寄存器FRM_LENGTH_LINES地址
};
2.5、 图像裁剪设置
图像裁剪设置主要用到的结构体为sensor_crop_parms_t和sensor_crop_params_arry, sensor_crop_params_t用于保存裁剪的位置信息。定义在sensor_lib.h中:
struct sensor_crop_parms_t {
uint16_t
top_crop;
//距离顶部的距离
uint16_t
bottom_crop;
//距离底部的距离
uint16_t
left_crop;
//距离左侧的距离
uint16_t
right_crop; //距离右侧的距离
} ;
struct sensor_lib_crop_params_array{
struct sensor_crop_parms_t
*crop_params;
//结构体指针
uint16_t
size;
//结构数组长度
};
imx230对于2种分辨率的图像不裁剪。
2.6 、分辨率切换设置
imx230使用2种分辨率,枚举类型sensor_res_cfg_type_t说明了进行分辨率切换时所需要进行的操作,在sensor_lib.h中定义如下:
typedef enum {
SENSOR_SET_STOP_STREAM,
//停止数据传输
SENSOR_SET_START_STREAM,
//开始数据传输
SENSOR_SET_NEW_RESOLUTION,
//设置新的分辨率
SENSOR_SEND_EVENT,
//发送事件
SENSOR_SET_CSIPHY_CFG,
//CSIPHY参数设置
SENSOR_SET_CSID_CFG,
//CSID参数设置
SENSOR_LOAD_CHROMATIX,
//加载chromatix参数
} sensor_res_cfg_type_t;
imx230_res_cfg[]数组序列对应着切换分辨率的操作顺序:
停止数据传输 ----> 设置新的分辨率 ----> CSIPHY参数设置 ----> CSID参数设置
----> 加载chromatix参数 ----> 发送事件 ----> 开始数据传输.
3、Camera I2C寄存器设置
I2C寄存器的设置都会用到这两种结构体:msm_camera_i2c_reg_array 和msm_camera_i2c_reg_setting。其定义在media/msm_camera.h中:
struct msm_camera_i2c_reg_array {
uint16_t
reg_addr;
//寄存器地址
uint16_t
reg_data;
//寄存器数据
};
struct msm_camera_i2c_reg_setting {
struct msm_camera_i2c_reg_array
*reg_setting;
//结构体指针
uint16_t
size;
//结构数组长度
enum msm_camera_i2c_reg_addr_type
addr_type;
//地址类型
enum msm_camera_i2c_data_type
data_type;
//数据类型
uint16_t
dalay;
//延时
};
其中枚举类型msm_camera_i2c_reg_addr_type在1.2中已经作过介绍了。 msm_camera_i2c_data_type的定义如下:
enum msm_camera_i2c_data_type {
MSM_CAMERA_I2C_BYTE_DATA = 1,
MSM_CAMERA_I2C_WORD_DATA,
MSM_CAMERA_I2C_SET_BYTE_MASK,
MSM_CAMERA_I2C_UNSET_BYTE_MASK,
MSM_CAMERA_I2C_SET_WORD_MASK,
MSM_CAMERA_I2C_UNSET_WORD_MASK,
MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
};
3.1、寄存器初始化设置
表现为在相机启动时一组一次性写入的寄存器。init_reg_array[],res0_reg_array[]和res1_reg_arry[]定义在头文imx230_lib.h中。分别对应excel表RegisterSetting中的全局设置和不同分辨率设置的数据。
寄存器初始化流程为:
上电 —> 外部时钟输入 —> XCLR关闭—> 外部时钟寄存器设置 —> 全局寄存器设置 —> Load Setting
之后寄存器设置根据不同分辨率具有不同的设置。
Load Setting —> 模式设置 —> 输出格式设置 —> 时钟设置 —> Data rate设置 —> 曝光时间设置 —> Gain值设置 —> HDR设置 —> DPC2D设置 —> LSC设? —> Stats 设置
3.2 、Grouphold on设置
sensor工作时更新曝光设定需要操作许多寄存器(曝光时间,每帧行数,增益),这些必须在同一帧完成更新。这些寄存器都有双buffer,并具有按组更新的功能。表现为所有相关寄存器一起完成更新。
地址0x0104就是寄存器GRP_PARAM_HOLD的地址,当其寄存器的值设为1时,写入的寄存器数据被暂存的buffer寄存器中。
3.3 、Grouphold off设置
当寄存器GRP_PARAM_HOLD的值为0时,所需要寄存器的值会被同时更新,参数的变化会在同一帧生效。
3.4、 启动输出设置
MIPI数据包必须以在SoT(Start of Transmission)和EoT(End of Transmission)之间发送。根据参考手册7.1,在正确的时间设定寄存器MODE_SEL(地址0x0100)为1时,开始进行数据输出。
启动数据输出流程分为两种情况:
情况1:在上电之后
(1)准备上电序列时序
(2)PLL锁相环参数设置
(3)初始化设置
(4)设置读取模式(起始/结束位置,大小,曝光时间,gain值)
(5)设置MIPI接口参数
(6)设置寄存器MODE_SEL的值为1,准备数据输出
在经过MIPI唤醒时间和初始化时间之后,开始输出第一帧图像数据。
情况2:在经过一次数据输出之后
(1)设置寄存器MODE_SEL的值为0,进入待命状态
(2)等待MIPI的FE package
(3)设置下一次数据输出模式
(4)设置寄存器MODE_SEL的值为1,准备数据输出
在经过MIPI唤醒时间和初始化时间之后,开始输出第一帧图像数据。
3.5、停止输出配置
在正确的时间设定MODE_SEL为0时,结束数据传输。
4、曝光设置
4.1 、曝光寄存器地址
结构体msm_sensor_exp_gain_info_t定义在sensor_lib.c中:
struct msm_sensor_exp_gain_info_t {
uint16_t
coarse_int_time_addr;
//粗曝光时间寄存器地址
uint16_t
global_gain_addr;
//模拟增益寄存器地址
uint16_t
vert_offset;
//曝光行偏置
};
粗曝光时间单位为lines,用于计算曝光时间,计算关系如下:
Tsh = Tline * (COARSE_INTEG_TIME + FINE_INTEG_TIME / LINE_LENGTH_PCK)
其中细曝光时间单位为pixels,是定值,其寄存器为只读寄存器。Tline为行曝光时间,为时间单位。计算如下:
Tline = LINE_LENGTH_PCK * VTPXCK_period
曝光行偏置用于设定以下关系:
COARSE_INTEG_TIME ≤ frame_length_lines – vert_offset
4.2、 AEC参数设置
结构体sensor_aec_data_t定义在sensor_lib.h中:
typedef enum {
SENSOR_MODE_SNAPSHOT,
//快照模式
SENSOR_MODE_RAW_SNAPSHOT,
//raw图快照模式
SENSOR_MODE_PREVIEW,
//预览模式
SENSOR_MODE_VIDEO,
//视频录像模式
SENSOR_MODE_VIDEO_HD,
//高清视频录像模式
SENSOR_MODE_HFR_60FPS,
//60帧率HFR模式
SENSOR_MODE_HFR_90FPS,
//90帧率 HFR模式
SENSOR_MODE_HFR_120FPS,
//120帧率HFR模式
SENSOR_MODE_HFR_150FPS,
//150帧率HFR模式
SENSOR_MODE_ZSL,
//零秒快拍
SENSOR_MODE_INVALID,
//非法
} sensor_mode_t;
typedef struct {
sensor_mode_t
op_mode;
//sensor 模式
uint32_t
pixels_per_line;
//每一帧每一行多少个pixels
uint32_t
lines_per_frame;
//每一帧多少行
uint32_t
pclk;
//vt_pixel_clk
uint32_t
max_fps;
//最大帧率
float
digital_gain;
//数字增益
float
stored_digital_gain;
float
max_gain;
//最大数字增益
uint32_t
max_linecount;
//最大曝光行数
} sensor_aec_data_t;
4.3 、曝光增益gain值设置
AEC算法中模拟增益gain用于曝光计算,实际上必须把gain转换成寄存器gain去设置sensor。以下是imx230的gain转换函数:
模拟增益real_gain值的范围是1至8, 对应到reg_gain的范围为0到448。real_gain与reg_gain的关系为:
real_gain = 512 / (512 - reg_gain)
结构体sensor_exposure_info_t定义在sensor_lib.h中:
typedef struct {
uint16_t
reg_gain;
//寄存器gain值
uint16_t
line_count;
//曝光行数
float
digital_gain;
float
sensor_real_gain;
//sensor的模拟gain值
float
sensor_digital_gain;
//sensor的数字gain值
} sensor_exposure_info_t;
5、镜头参数设置
结构体sensor_lens_info_t定义在sensor_lib.c中:
typedef struct {
float
focal_length;
//焦距
float
pix_size;
//像素大小
float
f_number;
//光圈
float
total_f_dist;
float
hor_view_angle;
//水平视角
float
ver_view_angle;
//垂直视角
} sensor_lens_info_t;
6、Chromatix参数
每一种分辨率都必须有对应的chromatix库文件。这里对应2种分辨率,设置的是相应的库文件名称。
结构体sensor_lib_chromatix_t定义在sensor_lib.h中:
struct sensor_lib_chromatix_t {
char
*common_chromatix;
char
*camera_preview_chromatix;
char
*camera_snapshot_chromatix;
char
*camcorder_chromatix;
char
*liveshot_chromatix;
};
其数据成员都是字符型指针,用来记录不同分辨率下不同模式的库文件名称。
7. MIPI接收器配置
7.1 、CSI lane参数配置
结构体 csi_lane_params_t定义在media/msm_camera.h中:
struct csi_lane_params_t {
uint16_t
csi_lane_assign;
//端口映射设置
uint8_t
csi_lane_mask;
//标识哪一个lane被使用
uint8_t
csi_if;
//未使用
uint8_t
csid_core[2];
//csid硬件选择
uint8_t
csi_phy_sel;
//csi-phy设备选择
};
csi_lane_assign —— 有时候用户的MIPI lanes可能使用不同与MSM参考设置的端口映射。比如,sensor的lane0连接到MSM的数据lane4等。对于这种情况,csi_lane_assign参数能设置正确的端口映射。csi_lane_assign是一个16bit的值,每位的含义参见下表。lane1用于MIPI时钟,客户不可用它来映射到任何数据lane。
csi_lane_mask —— 用于表示哪些lane被使用,这是一个8位值,每一位含义如下:
Bit position
Represents
7:5
保留
4
数据lane4是否使用:
- 0 :不
- 1 :是
3
数据lane3是否使用:
- 0 :不
- 1 :是
2
数据lane2是否使用:
- 0 :不
- 1 :是
1
数据lane1是否使用:
- 0 :不
- 1 :是
注意:该位必须设置为1
0
数据lane0是否使用:
- 0 :不
- 1 :是
比如0x1F表示4条数据lane和时钟都被使用。
csi_if —— 暂不使用。
csid_core —— 设置哪个CSID硬件被该sensor使用。两个并发的sensor不能使用同一个CSID硬件。
csi_phy_sel —— 设置哪个CSI-PHY硬件被该sensor使用。对于每一个sensor来说必须是独一无二的,除非有额外的MIPI桥连接两个sensor到同一个PHY接口上。
7.2 、虚拟通道设置
CSI2传输的数据包包头部分的起始1byte为数据标志符(Data Identifier, DI),由VC[7:6](Virtual Channel)和DT[5;0](Data Type)组成。通过不同的VC和DT值来标志不同的数据流,占2个bit位的虚拟通道VC允许最多4个数据流交叉传输,其取值范围为0~3.
下表表示不同的TD的取值及对应的数据格式。
结构体 msm_camera_csid_vc_cfg用于保存虚拟通道的设置信息,在media/msm_camera.h中定义:
struct msm_camera_csid_vc_cfg {
uint8_t
cid;
//通道号
uint8_t
dt;
//数据类型
uint8_t
decode_format;
//解码格式
};
imx230的设置如下:
其数据类型和解码格式的值是宏定义的,其中数据类型的宏定义是根据上述DT表得来的。如下:
#define CSI_EMBED_DATA
0x12
#define CSI_RESERVED_DATA_0
0x13
#define CSI_YUV422_8
0x1E
#define CSI_RAW8
0x2A
#define CSI_RAW10
0x2B
#define CSI_RAW12
0x2C
#define CSI_DECODE_6BIT
0
#define CSI_DECODE_8BIT
1
#define CSI_DECODE_10BIT
2
#define CSI_DECODE_DPCM_10_8_10
5
7.3 、数据流设置
typedef struct _sensor_stream_info_t {
uint16_t
vc_cfg_size;
struct msm_camera_csid_vc_cfg
*vc_cfg;
//虚拟通道设置
struct sensor_pix_fmt_info_t
*pix_fmt_fourcc;//像素格式
} sensor_stream_info_t;
typedef struct _sensor_stream_info_array_t {
sensor_stream_info_t
*sensor_stream_info;
uint16_t
size;
} sensor_stream_info_array_t;
7.4、 CSID和CSI-PHY参数设置
struct msm_camera_csid_lut_params {
uint8_t
num_cid;
//虚拟通道个数
struct msm_camera_csid_vc_cfg
*vc_cfg;
//虚拟通道参数
};
struct msm_camera_csid_params {
uint8_t
lane_cnt;
//使用lane的数目
uint16_t
lane_assign;
uint8_t
phy_sel;
struct msm_camera_csid_lut_params lut_params;
};
struct msm_camera_csiphy_params {
uint8_t
lane_cnt;
uint8_t
settle_cnt;
uint16_t
lane_mask;
uint8_t
combo_mode;
uint8_t
csid_core;
};
struct msm_camera_csi2_params {
struct msm_camera_csid_params
csid_params;
//CSID参数
struct msm_camera_csiphy_params
csiphy_params;
//CSI-PHY参数
};
lane_cnt ——有多少数据 lane 用于数据传输. 该值必须在 sensor 最大能力范围内,而且sensor 寄存器设置必须与该 lane 数匹配.
settle_cnt ——该值须和 sensor 的特性匹配, 保证 sensor 的 MIPI 传输和 MSM 的 MIPI 接收能同步.
客户可以对不同的分辨率模式使用不同CSI 参数设置。imx230采用两种分辨率,但是使用相同的CSI设置。
8、imx230_ofilm_open_lib
在imx230_lib.c中,最后将所有的参数设置都放入sensor_lib_t类型的结构体sensor_lib_ptr中,定义函数imx230_ofilm_open_lib()来返回sensor_lib_ptr的地址,供外界调用。
结构体sensor_lib_t涵盖了关于camera设置的几乎全部信息。如下:
typedef struct {
/* sensor slave info */
struct msm_camera_sensor_slave_info *sensor_slave_info;
/* sensor info */
struct msm_sensor_init_params *sensor_init_params;
/* name of the AF actuator (if any)*/
char* actuator_name;
/* name of the eeprom (if any)*/
char* eeprom_name;
/* sensor output settings */
sensor_output_t *sensor_output;
/* sensor output register address */
struct msm_sensor_output_reg_addr_t *output_reg_addr;
/* sensor exposure gain register address */
struct msm_sensor_exp_gain_info_t *exp_gain_info;
/* sensor aec info */
sensor_aec_data_t *aec_info;
/* sensor snapshot exposure wait frames info */
uint16_t snapshot_exp_wait_frames;
/* number of frames to skip after start stream info */
uint16_t sensor_num_frame_skip;
/* number of frames to skip after start HDR stream info */
uint16_t sensor_num_HDR_frame_skip;
/* sensor pipeline delay */
uint32_t sensor_max_pipeline_frame_delay;
/* sensor exposure table size */
uint16_t exposure_table_size;
/* sensor lens info */
sensor_lens_info_t *default_lens_info;
/* csi lane params */
struct csi_lane_params_t *csi_lane_params;
/* csi cid params */
struct msm_camera_csid_vc_cfg *csi_cid_params;
/* sensor port info that consists of cid mask and fourcc mapaping */
sensor_stream_info_array_t *sensor_stream_info_array;
/* csi cid params size */
uint16_t csi_cid_params_size;
/* init settings */
struct sensor_lib_reg_settings_array *init_settings_array;
/* start settings */
struct msm_camera_i2c_reg_setting *start_settings;
/* stop settings */
struct msm_camera_i2c_reg_setting *stop_settings;
/* group on settings */
struct msm_camera_i2c_reg_setting *groupon_settings;
/* group off settings */
struct msm_camera_i2c_reg_setting *groupoff_settings;
/* resolution config table */
struct sensor_res_cfg_table_t *sensor_res_cfg_table;
/* resolution settings */
struct sensor_lib_reg_settings_array *res_settings_array;
struct sensor_lib_out_info_array *out_info_array;
struct sensor_lib_csi_params_array *csi_params_array;
struct sensor_lib_crop_params_array *crop_params_array;
struct sensor_lib_chromatix_array *chromatix_array;
/* video_hdr mode info*/
struct sensor_lib_meta_data_info_array *meta_data_out_info_array;
/* exposure funtion table */
sensor_exposure_table_t *exposure_func_table;
/* exposure info */
sensor_exposure_info_t exposure_info;
/* flag to sync exp and gain */
uint8_t sync_exp_gain;
/* video hdr func table */
sensor_video_hdr_table_t *video_hdr_awb_lsc_func_table;
/* scale size tbl count*/
uint8_t scale_tbl_cnt;
/* function to get scale size tbl*/
int32_t (*get_scale_tbl)(msm_sensor_dimension_t *);
/* supported Scene mode */
uint32_t *sensor_supported_scene_mode;
/* supported effect mode */
uint32_t *sensor_supported_effect_mode;
/* sensor pipeline immediate delay */
uint32_t sensor_max_immediate_frame_delay;
/* library specific data */
void *data;
} sensor_lib_t;