cmos摄像头-ov7740驱动

ov7740摄像头模块
cmos摄像头驱动基于I2C驱动框架实现,在probe函数里基于V4L2框架写摄像头驱动程序。
在这里插入图片描述
在这里插入图片描述

dev函数

设备地址:
写 – 0x42(01000010)
读 – 0x43(01000011)
8bit的地址 = 7bit设备地址 + 1bit的读/写控制位
设备地址 = 0100001 = 0x21

static struct i2c_board_info cmos_ov7740_info = {
   	
	I2C_BOARD_INFO("cmos_ov7740", 0x21),	//名字,设备地址
};

static struct i2c_client *cmos_ov7740_client;

static int cmos_ov7740_dev_init(void){
   
	struct i2c_adapter *i2c_adap;
	i2c_adap = i2c_get_adapter(0);	//获取适配器
	cmos_ov7740_client = i2c_new_device(i2c_adap, &cmos_ov7740_info);	//在该适配器下创建设备
	i2c_put_adapter(i2c_adap);
	return 0;
}

static void cmos_ov7740_dev_exit(void){
   
	i2c_unregister_device(cmos_ov7740_client);
}

module_init(cmos_ov7740_dev_init);
module_exit(cmos_ov7740_dev_exit);
MODULE_LICENSE("GPL");

drv函数

static const struct i2c_device_id cmos_ov7740_id_table[] = {
   
	{
    "cmos_ov7740", 0 },
	{
   }
};

/* 1.1. 分配、设置一个i2c_driver */
static struct i2c_driver cmos_ov7740_driver = {
   
	.driver	= {
   
		.name	= "cmos_ov7740",
		.owner	= THIS_MODULE,
	},
	.probe		= cmos_ov7740_probe,
	.remove		= __devexit_p(cmos_ov7740_remove),
	.id_table	= cmos_ov7740_id_table,	//用于匹配
};

static int cmos_ov7740_drv_init(void){
   
	/* 1.2.注册 */
	i2c_add_driver(&cmos_ov7740_driver);
	return 0;
}
static void cmos_ov7740_drv_exit(void){
   
	i2c_del_driver(&cmos_ov7740_driver);
}

module_init(cmos_ov7740_drv_init);
module_exit(cmos_ov7740_drv_exit);
MODULE_LICENSE("GPL");

与dev函数匹配会调用probe函数,卸载会调用remove函数。
在cmos_ov7740_probe函数里要做硬件相关的工作:映射相应寄存器,设置相应的GPIO引脚用于CAMIF,设置、使能时钟(使能HCLK,使能并设置CAMCLK = 24MHz),复位一下摄像头模块,通过IIC总线初始化摄像头模块,注册中断(每采集一帧的数据,摄像头控制器会触发一次中断)等。
问:为什么需要复位摄像头模块?
答:IIC能够正常操作CMOS摄像头模块内部的寄存器的前提是:
– 提供符合它需求的系统时钟(CAMCLK)
– 需要给它一个复位信号
问:怎样才能复位摄像头模块?
答:通过操作CAMIF控制器中相应的寄存器,让CAMRST发出复位信号,从而复位摄像头模 块,具体操作见驱动源码。

注册两个中断,编码通道和预览通道,每发出一帧数据,触发中断。

static int __devinit cmos_ov7740_probe(struct i2c_client *client,const struct i2c_device_id *id){
   
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

	/* 2.3 硬件相关 */
	/* 2.3.1 映射相应的寄存器 */
	GPJCON = ioremap(0x560000d0, 4);GPJDAT = ioremap(0x560000d4, 4);GPJUP = ioremap(0x560000d8, 4);
	CISRCFMT = ioremap(0x4F000000, 4);CIWDOFST = ioremap(0x4F000004, 4);CIGCTRL = ioremap(0x4F000008, 4);CIPRCLRSA1 = ioremap(0x4F00006C, 4);
	CIPRCLRSA2 = ioremap(0x4F000070, 4);CIPRCLRSA3 = ioremap(0x4F000074, 4);CIPRCLRSA4 = ioremap(0x4F000078, 4);CIPRTRGFMT = ioremap(0x4F00007C, 4);
	CIPRCTRL = ioremap(0x4F000080, 4);CIPRSCPRERATIO = ioremap(0x4F000084, 4);CIPRSCPREDST = ioremap(0x4F000088, 4);CIPRSCCTRL = ioremap(0x4F00008C, 4);CIPRTAREA = ioremap(0x4F000090, 4);
	CIIMGCPT = ioremap(0x4F0000A0, 4);
	SRCPND = ioremap(0X4A000000, 4);INTPND = ioremap(0X4A000010, 4);SUBSRCPND = ioremap(0X4A000018, 4);

	/* 2.3.2 设置相应的GPIO用于CAMIF */
	cmos_ov7740_gpio_cfg();
	/* 2.3.3 复位一下CAMIF控制器 */
	cmos_ov7740_camif_reset();
	/* 2.3.4 设置、使能时钟(使能HCLK、使能并设置CAMCLK = 24MHz) */
	cmos_ov7740_clk_cfg();
	/* 2.3.5 复位一下摄像头模块 */
	cmos_ov7740_reset();
	/* 2.3.6 通过IIC总线,初始化摄像头模块 */
	cmos_ov7740_client = client;
	cmos_ov7740_init();

	/* 2.3.7 注册中断 */
	if (request_irq(IRQ_S3C2440_CAM_C, cmos_ov7740_camif_irq_c, IRQF_DISABLED , "CAM_C", NULL))
		printk("%s:request_irq failed\n", __func__);	//编码通道:
	if (request_irq(IRQ_S3C2440_CAM_P,cmos_ov7740_camif_irq_p, IRQF_DISABLED , "CAM_P", NULL))
		printk("%s:request_irq failed\n", __func__);	//预览通道
		
	/* 2.2.注册 */
    if(video_register_device(&cmos_ov7740_vdev, VFL_TYPE_GRABBER, -1))	//注册video_device结构体
    	printk("unable to register video device\n");
	return 0;
}

static int __devexit cmos_ov7740_remove(struct i2c_client *client){
   
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

	iounmap(GPJCON);iounmap(GPJDAT);iounmap(GPJUP);
	iounmap(CISRCFMT);iounmap(CIWDOFST);iounmap(CIGCTRL);iounmap(CIPRCLRSA1);
	iounmap(CIPRCLRSA2);iounmap(CIPRCLRSA3);iounmap(CIPRCLRSA4);iounmap(CIPRTRGFMT);
	iounmap(CIPRCTRL);iounmap(CIPRSCPRERATIO);iounmap(CIPRSCPREDST);iounmap(CIPRSCCTRL);
	iounmap(CIPRTAREA);iounmap(CIIMGCPT);	
	iounmap(SRCPND);iounmap(INTPND);iounmap(SUBSRCPND);
	free_irq(IRQ_S3C2440_CAM_C, NULL)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值