您的位置:首页 > 运维架构 > 网站架构

ov9650摄像头驱动之——linux内核v4l2架构分析1

2016-06-15 17:08 603 查看
http://www.cnblogs.com/liugf05/archive/2012/12/11/2812997.html


ov9650摄像头驱动之——linux内核v4l2架构分析1

 本系列准备分为3-4篇来讲,因为说的太多会比较乱
 
v4l2视频驱动主要涉及几个知识点:

    摄像头方面的知识(摄像头厂家提供的芯片手册可以查看
要了解选用的摄像头的特性,包括访问控制方法、各种参数的配置方法、信号输出类型等。
    Camera解码器、控制器(主控芯片的芯片手册里面有摄像头相关的寄存器设置,比如2410里,里面主要是设置相关控制功能使能,芯片内部自己的架构
如果摄像头是模拟量输出的,要熟悉解码器的配置。最后数字视频信号进入camera控制器后,还要熟悉camera控制器的操作。
    V4L2的API和数据结构控制(主要是用户空间需要的一些v4l2的操作,然后针对这些操作必须在底层实现相应的驱动
编写驱动前要熟悉应用程序访问V4L2的方法及设计到的数据结构。
    V4L2的驱动架构(这个是在底层写驱动,为用户空间提供相应的访问接口,可以参照内核里面的/drivers/media/video//zc301/zc301_core.c 中的ZC301视频驱动代码
它是内核提供的非常完善的v4l2架构的例子,基本上都可以在它的基础上进行修改!
最后编写出符合V4L2规范的视频驱动。
 
NO.1 摄像头方面的知识
 
ov9650摄像头,暂时先不说,先了解一下camera解码器、控制器,不同的主控芯片的camera控制器都差不多
 

  
 
上面是需要顺序写ov9650的寄存器的地址和写入的数值(采用I2C子系统传输)
I2C子系统传输已经分析过,平台设备的资源可以在板文件中初始化:
 
1.修改vi drivers/i2c/busses/Kconfig
 
修改
config I2C_S3C2410
tristate "S3C2410 I2C Driver"
depends on ARCH_S3C2410 || ARCH_S3C64XX
help
  Say Y here to include support for I2C controller in the
  Samsung S3C2410 based System-on-Chip devices.
 
为:
config I2C_S3C2410
tristate "S3C2410 I2C Driver"
depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100
help
  Say Y here to include support for I2C controller in the
  Samsung S3C2410 based System-on-Chip devices.
2.内核配置并重新编译内核
$ make menuconfig
Device Drivers  --->
<*> I2C support  --->
<*>   I2C device interface
I2C Hardware Bus support  --->
<*> S3C2410 I2C Driver
3.修改vi arch/arm/mach-s5pc100/mach-smdkc100.c
 
查看原理图可以知道摄像头是接在I2C-0或1上,假设在1上,根据原理图修改i2c_devs1添加ov9650的内容,主要是ov9650的地址,这个在芯片手册上可以查到是0x60
而下面为什么是0x30呢?在我的另外一篇I2C子系统分析里面讲过。给个链接解释
修改:
static struct i2c_board_info i2c_devs1[] __initdata = {
};
 
为:
static struct i2c_board_info i2c_devs1[] __initdata = {
{
I2C_BOARD_INFO("ov9650", 0x30),
},
};
 
添加s5pc100 摄像头控制器平台设备相关内容,这些内容我们可以通过查看S5PC100的芯片手册查到
static struct resource s3c_camif_resource[] = {
[0] = {
.start = 0xEE200000,
.end   = 0xEE200000 + SZ_1M - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_FIMC0,
.end   = IRQ_FIMC0,
.flags = IORESOURCE_IRQ,
}
 
};
 
static u64 s3c_device_camif_dmamask = 0xffffffffUL;
 
struct platform_device s3c_device_camif = {
.name  = "s5pc100-camif",
.id  = 0,
.num_resources  = ARRAY_SIZE(s3c_camif_resource),
.resource  = s3c_camif_resource,
.dev              = {
.dma_mask = &s3c_device_camif_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};
 
EXPORT_SYMBOL(s3c_device_camif);
 
注册摄像头控制平台设备:
在smdkc100_devices中添加s3c_device_camif
 
static struct platform_device *smdkc100_devices[] __initdata = {
&s3c_device_camif,  //添加内容
};
 
4. 添加驱动(video)
Make menuconfig
Device Drivers  --->  
 <*> Multimedia support  --->
 <*>   Video For Linux 
[*]     Enable Video For Linux API 1 (DEPRECATED) (NEW)
[*]   Video capture adapters (NEW)  --->
[*]   V4L USB devices (NEW)  ---> 
<*>   USB Video Class (UVC) 
[*]     UVC input events device support (NEW)
 <*>   USB ZC0301[P] webcam support (DEPRECATED)
 
这样device已经注册好了!
 
/* write a register */
static int ov9650_reg_write(struct i2c_client *client,
u8 reg, u8 val)
{
int ret;
u8 _val;
unsigned char data[2] = { reg, val };
struct i2c_msg msg = {
.addr= client->addr,
.flags= 0,
.len= 2,
.buf= data,
};
//构建i2c_msg 
ret = i2c_transfer(client->adapter, &msg, 1);  //I2C适配器和I2C设备之间的一组消息的交换
return 0;
}
 
 
 
static void ov9650_init_regs(void)
{
int i;
for (i=0; i<ARRAY_SIZE(regs); i++)
 
{
if (regs[i].subaddr == 0xff) 
{
mdelay(regs[i].value);
continue;
}
ov9650_reg_write(ov9650_client, regs[i].subaddr, regs[i].value);
}
}
 至此,通过I2C总线已经将摄像头的寄存器初始化好了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: