高通camera模块的启动过程
Camera驱动Vendor sensor部分启动初始化过程
mm-qcamera-daemon进程:
vendor\qcom\proprietary\mm-camera\mm-camera2\server-imagingserver.c的int main(int argc __unused, char *argv[] __unused)函数:
1.查找server节点:查找mdev_info.model=="msm_config"的/dev/media0-x节点,找到挂在它下面entity.type == MEDIA_ENT_T_DEVNODE_V4L &&
entity.group_id == QCAMERA_VNODE_GROUP_ID)的entity,这个entity.name就是server节点名称,一般是/dev/video0;它的注册是在msm.c中的msm_probe()函数
2.初始化驱动的六大模块:”sensor”,”iface”,”isp”,”stats”,”pproc”,”imglib”
函数server_process_module_init():每个模块采用同样的结构体和函数集合, 通过每个模块的mct_module_init_name_t->init_mod函数获取mct_module_t的实例,之后要对某个模块操作就通过调用mct_module_t的实例的函数集合。在sensor模块的mct_module_init_name_t->init_mod函数中就会执行sensor的查找匹配等操作。
3.往kernel的sensor节点设置probe完成的标志
4.while代码处理时间
Sensor模块的启动过程
vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\module\module_sensor.c:
步骤大概分为eebin, sensor, eeprom
1创建mct_module_t的实例并对函数集合赋值:
s_module->set_mod = module_sensor_set_mod;
s_module->query_mod = module_sensor_query_mod;
s_module->start_session = module_sensor_start_session;
s_module->stop_session = module_sensor_stop_session;
s_module->set_session_data = module_sensor_set_session_data;
s_module->get_session_data = module_sensor_get_session_data;
2eebin_interface_control():
- qcom,cmm-data-support - Camera MultiModule data capability flag.
- qcom,cmm-data-compressed - Camera MultiModule data compression flag.
- qcom,cmm-data-offset - Camera MultiModule data start offset.
- qcom,cmm-data-size - Camera MultiModule data size
3.. sensor_init_probe():
找到entity.group_id == MSM_CAMERA_SUBDEV_SENSOR_INIT的节点,这个节点在kernel中的msm_sensor_init.c节点注册。
最重要的函数sensor_init_xml_probe(module_sensor_ctrl_t *module_ctrl, int32_t sd_fd) :读取/vendor/etc/camera/camera_config.xml并解析
2
ov2680
ov2680_chromatix
1
FRONT
90
1
0x3
0x4320
0
1.98
2.4
1.2
68.0
51.0
0.1
1) 根据sensorname,导入对应的驱动库例如libmmcamera_s5k4h8.so,调用sensor_open_lib获取该sensor的信息和函数集合,然后往kernel的sensor init的节点发送VIDIOC_MSM_SENSOR_INIT_CFG命令,这个命令在kernel的msm_sensor_driver.c的msm_sensor_driver_probe()执行,vendor传下来的camera id变成底下的g_sctrl[slave_info->camera_id](如果有一二供兼容,这块的架构可能要改);另外会去关联eeprom、actuator、ois、flash的cell-index;s_ctrl->func_tbl->sensor_power_up上电的时候会去读id,id判断成功则会调用msm_sensor_driver_create_v4l_subdev生成需要的各种节点(video, subdev),返回给vendor的session id就是注册/dev/videox生成的device node number
2) sensor_create_sbundle():创建该模组对应的module_sensor_ctrl_t实例。
4子设备节点的查找:
module_sensor_find_other_subdev()
(entity.type == MEDIA_ENT_T_V4L2_SUBDEV &&
(entity.group_id == MSM_CAMERA_SUBDEV_ACTUATOR ||
entity.group_id == MSM_CAMERA_SUBDEV_EEPROM ||
entity.group_id == MSM_CAMERA_SUBDEV_FLASH ||
entity.group_id == MSM_CAMERA_SUBDEV_STROBE_FLASH ||
entity.group_id == MSM_CAMERA_SUBDEV_CSIPHY ||
entity.group_id == MSM_CAMERA_SUBDEV_CSID ||
entity.group_id == MSM_CAMERA_SUBDEV_OIS ||
entity.group_id == MSM_CAMERA_SUBDEV_EXT))
5 每个sensor模组的子设备函数表的初始化
module_sensors_subinit()
typedef struct {
int32_t (*open)(void **, void *);
int32_t (*process)(void *, sensor_submodule_event_type_t, void *);
int32_t (*close)(void *);
} sensor_func_tbl_t;
6枚举并创建每个模组的mct_port,链接到s_module-> srcports上。
port_sensor_create()
获取每个模组的驱动中sensor_stream_info_array数据,里面包含几个port以及 每个port下多少个channel,然后创建mct_port,挂到整个sensor module的srcports上
.sensor_stream_info_array =
{
.sensor_stream_info =
{
{
.vc_cfg_size = 1,
.vc_cfg =
{
{
.cid = 0,
.dt = CSI_RAW10,
.decode_format = CSI_DECODE_10BIT
},
},
.pix_data_fmt =
{
SENSOR_BAYER,
},
},
},
.size = 1,
},
7.对每个sensor获取eeprom数据
module_sensor_init_eeprom()初始化、读取、格式化eeprom数据
8对每个sensor的chromatix数据导入、eeprom数据应用
module_sensor_init_chromatix():调用cm_create();
这个函数会将s5k4h8_chromatix.xml中的common、resolution 0-x下的各种场景(isp、cpp、a3)配置导入到hash表中;
其中chromatix_info是在sensor_util_xml.c的sensor_xml_util_parse_chromatix_name()下赋值的,时间sensor_bundle创建的时候;
rc = addLib(cm, chromatix_name->isp_common, EEPROM_CALIBRATE_LSC);功能是导入isp_common的库,并用EEPROM中的lsc数据替换导入的该部分数据。在导入库的函数addLib_getSymbol()的过程中,会调用int32_t load_chromatix(const char *name, const char *path, void **handle, void **symbol),这个函数的实现是在chromatix_sub_module.c中,在这个实现中会去调用path对应的库的void *load_chromatix(void)。还会调用(cm->eeprom_func))->process( cm->eeprom_ctrl, cal_type, data_sym)去替换cal_type对应的数据。
Camera驱动vendor sensor start session过程
module_sensor_start_session():
sensor_thread_create():处理SET_AUTOFOCUS和OFFLOAD_FUNC(降低主线程负载)两个事件
module_sensor_init_session():
1) 初始化s_bundle->frame_ctrl.frame_ctrl_q;
2) 对每个sub dev调用open函数
3) SUB_MODULE_CHROMATIX处理CHROMATIX_SET_CM事件
4) SUB_MODULE_ACTUATOR处理ACTUATOR_SET_EEBIN_DATA
5) module_sensor_offload_init_config():SUB_MODULE_SENSOR处理SENSOR_INIT事件,处理各种初始化变量
6) SUB_MODULE_SENSOR处理SENSOR_SET_FORMATTED_CAL_DATA事件
管道
分为无名管道(父母兄弟进程)和命名管道
Int pipe(int fd[2]): fd[0]:用于读出数据; fd[1]:用于写入数据
struct pollfd pollfds={
pollfds.fd = fd[0]
pollfds.events = POLLIN|POLLPRI;
};
Int ready = Poll(&pollfds, 1, -1);
Int read_bytes = read(pollfds.fd, &event, sizeof(isp_trigger_thread_event_t));
write(fd[1], &trigger_thread_event, sizeof(trigger_thread_event));