/* 应用程序通过读的方式读取摄像头的数据 */
static ssize_t cmos_ov7740_read(struct file *filep, char __user *buf, size_t count, loff_t *pos)
{
size_t end;
int i;
end = min_t(size_t, buf_size, count);
wait_event_interruptible(cam_wait_queue, ev_cam);
for(i=0; i<4; i++)
{
if(copy_to_user(buf, (void *)img_buff[i].virt_base, end))
return -EFAULT;
}
ev_cam = 0;
return end;
}
static const struct v4l2_file_operations cmos_ov7740_fops = {
.owner = THIS_MODULE,
.open = cmos_ov7740_open,
.release = cmos_ov7740_close,
.unlocked_ioctl = video_ioctl2,
.read = cmos_ov7740_read,
};
/*
注意:
该函数是必须的,否则在insmod的时候,会出错
*/
static void cmos_ov7740_release(struct video_device *vdev)
{
unsigned int order;
order = get_order(buf_size);
free_pages(img_buff[0].virt_base, order);
img_buff[0].phy_base = (unsigned long)NULL;
free_pages(img_buff[1].virt_base, order);
img_buff[1].phy_base = (unsigned long)NULL;
free_pages(img_buff[2].virt_base, order);
img_buff[2].phy_base = (unsigned long)NULL;
free_pages(img_buff[3].virt_base, order);
img_buff[3].phy_base = (unsigned long)NULL;
}
/* 2.1. 分配、设置一个video_device结构体 */
static struct video_device cmos_ov7740_vdev = {
.fops = &cmos_ov7740_fops,
.ioctl_ops = &cmos_ov7740_ioctl_ops,
.release = cmos_ov7740_release,
.name = "cmos_ov7740",
};
static void cmos_ov7740_gpio_cfg(void)
{
/* 设置相应的GPIO用于CAMIF */
*GPJCON = 0x2aaaaaa;
*GPJDAT = 0;
/* 使能上拉电阻 */
*GPJUP = 0;
}
static void cmos_ov7740_camif_reset(void)
{
/* 传输方式为BT601 */
*CISRCFMT |= (1<<31);
/* 复位CAMIF控制器 */
*CIGCTRL |= (1<<31);
mdelay(10);
*CIGCTRL &= ~(1<<31);
mdelay(10);
}
static void cmos_ov7740_clk_cfg(void)
{
struct clk *camif_clk;
struct clk *camif_upll_clk;
/* 使能CAMIF的时钟源 */
camif_clk = clk_get(NULL, "camif");
if(!camif_clk || IS_ERR(camif_clk))
{
printk(KERN_INFO "failed to get CAMIF clock source\n");
}
clk_enable(camif_clk);
/* 使能并设置CAMCLK = 24MHz */
camif_upll_clk = clk_get(NULL, "camif-upll");
clk_set_rate(camif_upll_clk, 24000000);
mdelay(100);
}
/*
注意:
1.S3C2440提供的复位时序(CAMRST)为:0->1->0(0:表示正常工作的电平、1:表示复位电平)
但是,实验证明,该复位时序与我们的OV7740需要的复位时序(1->0->1)不符合。
2.因此,我们就应该结合OV7740的具体复位时序,来设置相应的寄存器。
*/
static void cmos_ov7740_reset(void)
{
*CIGCTRL |= (1<<30);
mdelay(30);
*CIGCTRL &= ~(1<<30);
mdelay(30);
*CIGCTRL |= (1<<30);
mdelay(30);
}
static void cmos_ov7740_init(void)
{
unsigned int mid;
int i;
/* 读 */
mid = i2c_smbus_read_byte_data(cmos_ov7740_client, 0x0a)<<8;
mid |= i2c_smbus_read_byte_data(cmos_ov7740_client, 0x0b);
printk("manufacture ID = 0x%4x\n", mid);
/* 写 */
for(i = 0; i < OV7740_INIT_REGS_SIZE; i++)
{
i2c_smbus_write_byte_data(cmos_ov7740_client, ov7740_setting_30fps_VGA_640_480[i].regaddr, ov7740_setting_30fps_VGA_640_480[i].value);
mdelay(2);
}
}