msm8996平台的 camera 框架笔记

msm8996平台的 camera 框架笔记

标签(空格分隔): camera


0 前言

本文档主要记录在msm8996平台下camera hal层框架。

1 kernel中的camera结构

qcom的camera driver采用v4l2框架。

1.1 qcom的v4l2节点结构

qcom_v4l2.jpg-675.7kB

qcom这里的操作有几点需要记录一下:

1、关于msm_cam设备
msm_cam设备在dts文件中被定义,从driver代码上来分析,该设备的定位是对所有qcom camera相关设备的管理。qcom把camera系统分为了camera和sensor两部分,camera这部分由msm_cam设备作为video设备与userspace进行交互,qcom自己的mipi、isp、cpp等硬件设备都属于camera部分,该部分目前理解为是qcom soc的片上ip core;sensor部分则为外部设备,例如一个感光sensor,每个sensor都作为一个subdev注册到msm_cam设备上,同时会创建一个对应的video设备。

2、关于s_init设备

目前来看,最主要的作用就是执行msm_sensor_driver_cmd()--->msm_sensor_driver_probe(),这里就是针对各sensor进行注册subdev和创建video的入口。

3、关于camera与sensor设备

这里的camera是指的一个video设备,sensor则是一个sensor设备。sensor设备作为subdev挂载在msm-cam设备下,在挂载每个sensor前会创建该sensor的一个video设备,一个video设备作为一个session通过v4l2接口与userspace交互数据,目前来看camera设备主要提供了一个v4l2的操作接口,实际执行过程都在别处执行。例如camera_v4l2_s_parm消息,camera设备通过video的消息接口收到该消息后直接是把这个消息以及参数又post event出去了,这里猜测在qcom camera的sensor driver的逻辑全部在hal层中,hal层收到camera post出来的set param event后根据param通过sensor对应的subdev去写sensor的寄存器,来完成对sensor的配置。这一点在sensor给v4l2提供的回调函数中可以看出一些踪迹,例如sensor给v4l2的一个回调:

msm_sensor_subdev_ioctl()--->
s_ctrl->func_tbl->sensor_config32(s_ctrl, argp)---> //(s_ctrl->func_tbl = &msm_sensor_func_tbl;)
msm_sensor_config32()--->
s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table()---> //s_ctrl->sensor_i2c_client->i2c_func_tbl =
				                                               //     &msm_sensor_qup_func_tbl;
msm_camera_qup_i2c_write_table()--->i2c_transfer()

所以这里认为创建sensor的video的目的是为了使hal层使用上更符合v4l2的接口习惯,为每个sensor分配一个video,hal层在操作camera时操作该设备对应的video就行了,但是这里由于qcom camera hal层框架的原因这里的video仅仅成为了一个接口,没有任何真正对硬件产生效果的逻辑操作。

这里试着分析一下qcom这样做的原因,可能有如下几点:
1、对自己的操作进行保护,因为hal层是不用提供源码的
2、从结构上来说,多个摄像头是公用vfe、cpp这些硬件资源的,所以这些硬件资源的管理不适合放到每个camera中去管理,所以就都挂到msm-cam设备下,每个硬件资源自己负责管理自己,并且自己解决多路复用的问题,这样这些逻辑就都放到了各个硬件自己的driver中(无论是在hal层还是kernel层)。
3、更好的架构一致性,所有的硬件资源的操作都由自己的subdev接口进行操作。

1.2 一个zsl的session和stream

v4l2的结构下图:

qcom_v4l2_bufs.jpg-448.5kB

一个zsl操作这里总共打开了6个stream,stream 5大概率是callback stream,有什么用暂时还不太清楚,但是启动之后stream 5立马就停了,所以这里未标出,stream 0好像是一个管理通道?这里也不太确定,但是从跟踪与分析来看跟数据流没什么关系,所以这里也未画出;stream 1的作用暂时不太清楚,猜测跟buf管理有关。

简单来说,一帧preview/viewfinder的数据经过如下部分:

sensor ---> csiphy ---> csid ---> vfe ---> aix ---> hal ---> cpp ---> hal

2 hal层中的camera结构

qcom camera hal层的代码分为三部分:

一部分是cpp组成,以QCameraxxxx.cpp命名,例如QCamera2HWI.cpp,主要提供hal层的接口函数以及回调接口函数,主要负责hal层对aosp的接口适配以及qcom hal层接口框架逻辑。

另一部分代码以mm_xxx_xxx.c命名,例如mm_camera_stream.c,该部分是qcom hal层的硬件资源接口,主要是对camera硬件状态、硬件资源的管理以及对硬件操作的封装。

还有一部分是qcom闭源的,应该跟vfe、cpp等硬件的控制逻辑以及资源逻辑相关,该部分定义:

#define SHIMLAYER_LIB "/system/vendor/lib/libmmcamera2_mct_shimlayer.so"

推测这一部分与session的最终操作相关,一个session具体如何控制,具体需要哪些硬件协同工作都在这个so里面。

2.1 aosp的camera接口

boot_connect.jpg-334.9kB

这里主要分为两部分:
1、load
在cameraService被创建后会调用其OnFirstReg()函数,该函数加载QCamera的so文件,获得mModule句柄,同时获取其camera数量。

2、connect
当启动一个camera时camserver发起connect操作,这时会创建一个camera client并且为其填写mHardware数据,该数据是对硬件操作的入口,mHardware中的mDevice则是qcom cam返回的camera入口,mHardware的填充由openCamera()函数完成,具体过程如上图所示。

2.2 一个preview的启动过程

2.2.1 qcom hal层模型

cbNotifier.jpg-148.4kB

该图表示qcamera中Notifier的过程,一个notifier中有两个链表,一个cmd链表,一个data链表,一个notifier被触发都是cmdThread从cmd链表中取触发指令,然后执行相应的操作,如果操作内省是DO NEXT JOB,则会再从数据链表中取数据,然后调用数据处理的回调函数来对其进行处理。


mm_camera module.jpg-108.9kB

上图表示hal层mm_xxx.c相关的处理过程,中对该部分的操作全部是通过mm_camera_interface.c提供的接口来完成的,然后mm_camera.c根据操作类型以mm_xxx.c内部接口的标准将数据传送给最终处理的单元。

这里mm_camera_interface.c的作用是给外部提供调用接口,同时根据外部请求,来调用mm_camera.c中对应的操作;mm_camera.c的作用是响应外部请求,并翻译成mm_xxx.c内部接口模型。这里的内部接口模型主要是因为在每个模型中抽象了一个状态机模块,或者说每个内部模型都有一个状态机进行组合。

2.2.2 模型中的状态机

qcameraOps_stateMachine.jpg-180.4kB

状态机的创建是在openLegacy()被调用,new QCamera2HardwareInterface()时创建的,外部对qcom camera的所有操作都会以事件的方式来调用,最终由camera的状态机来决定消息的执行情况。

以上是QCameraxxx.cpp这一层的状态机,在mm_xxx.c这一层中,每个session和stream都有自己的状态机,工作机制与上述类似,详见上一节。。

2.2.3 start preview

startPreview.jpg-295.7kB

2.3 camera中的poll机制

camera_poll_system.jpg-236.6kB

这里的poll机制里面是嵌套了一个pipe机制在里面。
每次添加一个poll thread时,会给这个poll thread创建一个pipe,对于这个poll thread来说pipe也好open的dev也好,都是一个文件fd,都适用于poll,调用一次poll时可以传递给该函数一个fd数组,poll会去查看每一个fd,一旦哪个fd的poll有返回,则该poll thread就会对其进行处理。那么qcom这里期望做一个可以动态添加poll fd的机制,他们利用了了pipe,这个pipe就是fds[0],也就是每个poll thread自带fds[0],该fd响应添加新fd的操作,所以当open一个dev就可以把这个dev的fd通过write fds[0]添加进来。

2.4 关于callbacks

callbacks.jpg-454.5kB

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值