首页 理论教育深入解析Linux内核与设备驱动中的TI芯片视频驱动实现

深入解析Linux内核与设备驱动中的TI芯片视频驱动实现

【摘要】:对视频驱动的具体实现,以DM3730 ISP驱动的设计与实现为例进行介绍。ISP驱动中使用isp_video作为以上单一矩形节点的抽象以及管理实体。可见实际的操作是由子设备完成的,子设备与具体功能相关。具体如下:这里操作的主要目的就是注册v4l2的子设备和I2C的设备,通过I2C总线适配将视频子设备与I2C的Camera Sensor关联起来,从而实现完整的驱动和设备连接。

对视频驱动的具体实现,以DM3730 ISP驱动的设计与实现为例进行介绍。首先来看一下ISP硬件框架,如图6-18所示。

978-7-111-49426-3-Chapter06-316.jpg

图6-18 DM3730 ISP硬件框架

从图6-18可见,ISP模块允许从多个通道读取数据,可以从CSI、CCP或者内存,而且硬件模块本身还可以屏蔽,另外其中内嵌MMU可以实现帧数据使用物理不连续的内存空间。从硬件看其功能十分强大,这就需要驱动软件支持这些特性,能够容易地设置不同的数据进出以及操作方式,从而更好地使用硬件功能。

1.整体框架及应用层接口

对这种需要灵活配置的设备,media controller是最适合的,在实际的驱动设计中也是采用了该方法进行驱动的架构设计。驱动的整体框架如图6-19所示。

978-7-111-49426-3-Chapter06-317.jpg

图6-19 DM3730 ISP驱动框架

从图6-19中可见,其中有很多的节点,每个多矩形组成的节点(如ISP CCDC)都是子设备是一个功能模块,实现具体的功能,而单一矩形的节点(包含/dev/video?)是video设备文件,这些设备文件是数据流的入口或者出口。

ISP驱动中使用isp_video作为以上单一矩形节点的抽象以及管理实体。细节如下:

978-7-111-49426-3-Chapter06-318.jpg

978-7-111-49426-3-Chapter06-319.jpg

对有数据输入或者输出的不同的模块会进行相应的注册工作,细节如下:

978-7-111-49426-3-Chapter06-320.jpg

978-7-111-49426-3-Chapter06-321.jpg

978-7-111-49426-3-Chapter06-322.jpg

这里只有初始化,而实际的注册由isp_video_register完成,细节如下:

978-7-111-49426-3-Chapter06-323.jpg

这样注册了实际的视频设备,相应应用层的操作就通过注册的接口进行了。通过一个例子来看看具体的接口是如何实现的。

978-7-111-49426-3-Chapter06-324.jpg

978-7-111-49426-3-Chapter06-325.jpg

可见实际的操作是由子设备完成的,子设备与具体功能相关。

2.子设备及连接管理

ISP驱动中每个功能节点都是一个subdev,而相应的连接也要进行管理,这些都要由具体功能模块来进行,以CCDC为例看看是如何实现的。

978-7-111-49426-3-Chapter06-326.jpg

978-7-111-49426-3-Chapter06-327.jpg

同样有注册操作:

978-7-111-49426-3-Chapter06-328.jpg

这样子设备以及连接就建立起来了。下面来看看连接media controller的操作:

978-7-111-49426-3-Chapter06-329.jpg

978-7-111-49426-3-Chapter06-330.jpg

978-7-111-49426-3-Chapter06-331.jpg

可见连接建立只是进行输入和输出子设备节点的状态记录,实际操作视频流streaming on是在子设备的s_stream操作中调用ccdc_configure来完成的,而相应的ccdc_configure则是根据ccdc_link_setup时的属性进行相应的寄存器设置。这样就可以完成连接框架到实际设备操作的流程。

3.视频数据流(www.chuimin.cn)

关于视频数据流,ISP驱动框架涉及两个管理实体,其一是isp_pipeline,表示流的物理pipeline路径。细节如下:

978-7-111-49426-3-Chapter06-332.jpg

978-7-111-49426-3-Chapter06-333.jpg

这里主要是各个设备文件所在的数据通道连接状况及其状态,这些会影响到模块的设置。这些状态信息会在电源管理中有相应的功能,比如系统从低功耗状态恢复执行时,需要恢复数据流传送,这时候就会从输入端进行恢复,需要保留这些信息。相应的属性设置在stream on操作中执行,相关代码详细内容如下:

978-7-111-49426-3-Chapter06-334.jpg

978-7-111-49426-3-Chapter06-335.jpg

通过分析可知,很多系统的设置就是通过pipeline的状态进行的,其中包括stream的操作,对stream的操作还要通过pipeline的操作完成,相应的接口是isp_pipeline_enable,详细内容如下:

978-7-111-49426-3-Chapter06-336.jpg

978-7-111-49426-3-Chapter06-337.jpg

978-7-111-49426-3-Chapter06-338.jpg

从中可见,pipeline就是遍历数据终点到起点的所有子设备,并进行相应的stream操作来保证pipeline中所有的模块正确工作。

另一个重要的管理实体是isp_video_queue,这里没有使用videobuf2架构是由于在相应驱动开发时内核还没有相关的架构,但是相应的queue可以看到videobuf2的影子。先来看看的isp_video_queue细节:

978-7-111-49426-3-Chapter06-339.jpg

这里的queue同样是应用层的接口队列,在isp_video中可以看到它的指针,而实际驱动操作的buffer形成以dmaqueue为列表头的列表。实际驱动提供的接口如下:

978-7-111-49426-3-Chapter06-340.jpg

978-7-111-49426-3-Chapter06-341.jpg

其中,isp_video_buffer_queue的工作就是将isp_video_queue中的buffer加入到驱动中进行操作,操作结束后,会在中断中根据具体的情况通过isp_video_buffer_next将buffer归还给isp_video_queue,以便完成应用的相关操作。层次关系与videobuf2是一致的,只是videobuf2细化了相关的接口,使用范围也更广。

这样就完成了数据流相关的操作。

4.camera sensor

还剩下一部分就是camera sensor的驱动,camera sensor实际上是通过I2C总线进行连接的外部设备,但是由于与主处理器的ISP绑定比较紧密,也为了系统移植的方便,将其做成subdev更合适,下面以mt9t111 sensor驱动进行说明。

从初始化开始了解:

978-7-111-49426-3-Chapter06-342.jpg

I2C设备自然需要相应的驱动,对应的匹配是通过ID table来完成的,后续介绍总线时会详细介绍。接下来就是具体的probe:

978-7-111-49426-3-Chapter06-343.jpg

978-7-111-49426-3-Chapter06-344.jpg

这样连接实体与子设备的操作实体都建立了,在应用中可以通过如下的代码将sensor与ISP进行连接:

978-7-111-49426-3-Chapter06-345.jpg

978-7-111-49426-3-Chapter06-346.jpg

由于后续操作的sensor在pipeline的连接中,就可以通过ISP pipeline的操作来遍历并调用相应子设备的接口,对于sensor子设备的接口这里就不进行详述,主要的操作还是通过I2C总线来完成的。

而设备信息的注册则是通过isp_subdev_i2c_board_info传入到ISP驱动中,并在初始化时,通过isp_register_subdev_group来完成。具体如下:

978-7-111-49426-3-Chapter06-347.jpg

978-7-111-49426-3-Chapter06-348.jpg

这里操作的主要目的就是注册v4l2的子设备和I2C的设备,通过I2C总线适配将视频子设备与I2C的Camera Sensor关联起来,从而实现完整的驱动和设备连接。