soc-camera的作者之所以引入这个子系统,我想一个主要目的就是把camera驱动划分为camera host端,camera sensor端,这样同一个camera sensor驱动就可以方便的移植到多个camera host下,而无须做较多的改动。
本译文取自kernel文档:Documentation/video4linux/soc-camera.txt
术语
在阅读本文档前先明确几个术语:
soc-camera subsystem的目的
soc-camera 子系统在camera host驱动和camera sensor驱动间提供了统一的接口。子系统向上提供了V4L2接口,当前仅支持mmap method。
这个子系统连接SoC video capture接口和CMOS camera sensor chips,使得sensor驱动可以在其他的hosts驱动上复用。子系统在设计时也考虑到了多个camera host接口的存在,以及每个接口存在多个camera sensor,尽管在大部分情况下仅有一个camera sensor。
现存的驱动
在2.6.27-rc4中,主线内核有两个host 驱动:PXA27x的pxa_camera.c和SuperH SoCs的sh_mobile_ceu_camera.c,有四个sensor驱动:mt9m001.c,mt9v002.c以及一个通用的soc_camera_platform.c驱动。这个列表可能不是最新的,所以在你的源码树中查看,可能有更多的例子存在。
实际开发中,新的sensor驱动可以参照mt9m001.c和mt9v002.c这两个sensor驱动框架,根据项目所用的sensor稍加修改即可。
Camera host API
一个host camera driver使用soc_camera_host_register(struct soc_camera_host *)函数来注册。host object可以如下初始化
所有的方法都是通过struct soc_camera_host_ops
.add和 .remove方法是sensro接入host和从host卸载时调用,除了执行host内部的初始化工作,还会调用sensor的.init和.release方法。
.suspend和.resume方法实现host的电源管理功能, 他们要负责调用相应的sensor 方法。
.try_bus_param和.set_bus_param用来协商host和sensor间的物理连接参数。
.init_videobuf是当一个video-device被打开时调用,video-buffer管理的实现是完全依赖于特定的host
其余部分被V4L2的相应部分调用。
Camera API
Sensor drivers可以使用struct soc_camera_link,典型的由platform提供,用来代表sensor连接到的host总线,这个结构还提供了.power和.reset接口。本节所描述的代码和当前代码已经发生了很大的变化,所以暂时略过本节。
VIDIOC_S_CROP和VIDIOC_S_FMT调用的行为
VIDIOC_S_CROP:设置sensor窗口的位置和尺寸,单位是sensor的像素。改变sensor窗口尺寸时维持缩放因子没变,因此用户窗口尺寸也相应的变化了。
VIDIOC_S_FMT:设置用户窗口。通过修改缩放因子,尽可能的保持之前设置的窗口尺寸。如果sensor窗口无法保持不变,那么也可以修改。
soc-camera中有两个地方,可以进行缩放和剪切:camera sensor驱动,和camera host驱动。User ioctl首先发送到host dirver,然后再向下发送给camera driver。在camera sensor驱动执行缩放和剪切可能更有效,因为会节约camera总线带宽以及最大帧率(如果放大还成立吗,对于AD video芯片来说,缩放只能在host driver来做)。然而,如果camera sensor驱动无法实现要求的参数,那么host 驱动可以决定用它自己的缩放和剪切功能来满足用户需求。
Camera sensor驱动soc-camera core以及host驱动交互,完全是功能上的,不涉及任何数据传输。因而所有的camera sensor驱动应该用当前输出格式响应.g_fmt请求。这对于正确配置camera bus是必要的。s_fmt() 和try_fmt也不得不实现。sensor窗口和缩放因子也应该在camera sensor驱动内维护。按照V4L2 API,所有的capture驱动应该支持VIDIOC_CROPCAP ioctl,因此我们依赖于camera drivers实现.cropcap()。如果camera sensor驱动不支持cropping,那么可以选择不支持.s_crop,但是必须在camera host驱动实现cropping支持,起码g_crop方法必须支持。
用户设置的几何尺寸保存在struct soc_camera_device的.user_width和.user_height成员中,以供soc_camera core和host drivers使用。core在成功调用s_fmt后会修改这些成员,但是如果是在其他地方修改了他们,比如s_crop,那么host driver要负责更型他们。