1        Vpif的V4L2 linux驱动程序框架

在linux中,使用V4L2框架来管理视频采集设备。V4L2框架主要包括两层:V4L2Device和V4L2 Subdevice,其中V4L2 Device是虚拟的设备,用以管理V4L2 Subdevice,而Subdevice才是真正的物理设备,例如各种视频AD芯片和sensor等。

在DM6467使用的linux内核中,使用VPIFcapture来管理一些子设备,包括TVP5150、TVP7002、THS7353和OV5642等,其驱动结构如下图所示。

  

从上图可以看出,对于ov5642的驱动程序编写有两种方式,一种是直接将ov5642作为video_device,另一种是将其作为subdevice供上一层调用。考虑到如果将ov5642直接作为video_device来编写驱动程序的话,那需要自己处理一些内存管理的问题,这比较复杂,所以我们采用第二种方法。

2        编写ov5642驱动程序

由于Linux中已经有了用于视频设备驱动程序的V4L2框架,在编写ov5642驱动程序时,主要功能就是对其进行初始化以及编写一些API函数。

首先,作为V4L2 subdevice,在ov5642的驱动程序中的以下函数是必须实现的。

 

函数名

功能

__init int ov5642_mod_init()

模块初始化

__exit void ov5642_mod_exit()

模块退出时清理内存

ov5642_probe()

注册时对设备进行探测

ov5642_remove()

移除设备时运行

 

然后,由于vpif要调用ov5642驱动程序,这过程中又会使用到另外一些函数,主要包括以下部分。

 

函数名

功能

ov5642_querystd()

查询ov5642支持的视频格式

ov5642_s_stream()

使能/关闭ov5642输出

ov5642_cropcap()

获取视频的裁剪功能

ov5642_s_std()

设置ov5642输出的视频格式

 

另外,由于ov5642是使用SCCB(可与I2C兼容)总线访问其寄存器,所以还需要编写寄存器访问函数,主要包括以下部分。

 

函数名

功能

reg_read()

读ov5642寄存器

reg_write()

写ov5642寄存器

ov5642_write_array()

向ov5642写一系列寄存器

reg_write16()

写16位寄存器

 

编写完所有基本API函数之后,使用以下代码将这些API函数传递给一些结构体,然后就可以实现内核的统一管理所有驱动程序。

 

// v4l2 子设备的视频操作函数

static const struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {

         .querystd = ov5642_querystd,

         .s_stream = ov5642_s_stream,

         .cropcap  = ov5642_cropcap,

};

// v4l2子设备的核心操作函数

static const struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {

         .s_std        = ov5642_s_std,

         .g_chip_ident = ov5642_g_chip_ident,

};

// v4l2子设备的所有API

static const struct v4l2_subdev_ops ov5642_subdev_ops = {

         .core         = &ov5642_subdev_core_ops,

         .video        = &ov5642_subdev_video_ops,

};

 

// 用于I2C驱动程序的结构体,定义ov5642的I2C设备ID,并添加到I2C设备表

static const struct i2c_device_id ov5642_id[] = {

         { "ov5642", 0 },

         { }

};

MODULE_DEVICE_TABLE(i2c, ov5642_id);

// I2C设备的驱动程序函数

static struct i2c_driver ov5642_i2c_driver = {

         .driver = {

                   .owner = THIS_MODULE,

                   .name = "ov5642",

         },

         .probe                = ov5642_probe,

         .remove            = ov5642_remove,

         .id_table  = ov5642_id,

};

// 定义模块初始化和退出时运行的函数

module_init(ov5642_mod_init);

module_exit(ov5642_mod_exit);

 

系统上电时,内核在内存中解压并运行,这时首先会调用ov5642驱动程序中的初始化函数ov5642_mod_init(),添加I2C设备及I2C设备驱动程序,然后VPIF驱动程序初始化时会调用ov5642驱动程序中的ov5642_probe()函数,对ov5642进行一系列的初始化,并且注册为V4L2子设备。下图是Linux启动时的输出信息,从中可以看出驱动程序的运行过程。

 

现在已经实现的ov5642驱动程序的API函数还太少,还缺比如设置各种参数的函数,而且不能改变分辨率,只能是VGA,这在以后还需要修改。

Logo

更多推荐