1、 CFG_WRITE(SIO_D); High(SIO_C); High(SIO_D); WAIT_STABLE(); return 0;由上面的图可以看出,CLK高电平时,DATA拉低,即为STARTstatic void _inline_ sccb_start(void) Low(SIO_D);使用到一个信号量static DECLARE_MUTEX(bus_lock);void sccb_write(u8 IdAddr, u8 SubAddr, u8 data) down(&bus_lock); sccb_start(); sccb_write_byte(IdAddr); sccb_wr
2、ite_byte(SubAddr); sccb_write_byte(data); sccb_stop(); up (&首先把信号量数值降低,表示自己使用,如果此时信号量不大于0,表示bus正在使用,驱动会在此等待,知道信号量大于0,然后,将其减1,此时bus对外界不可用。最后再把信号量加1,表示bus可用。%摄像头接口初始化:/* * camif_init() */static int _init camif_init(void)配置CAMIF的GPIO接口功能 /* set gpio-j to camera mode. */ s3c2410_gpio_cfgpin(S3C2440_GPJ0
3、, S3C2440_GPJ0_CAMDATA0); s3c2410_gpio_cfgpin(S3C2440_GPJ1, S3C2440_GPJ1_CAMDATA1); s3c2410_gpio_cfgpin(S3C2440_GPJ2, S3C2440_GPJ2_CAMDATA2); s3c2410_gpio_cfgpin(S3C2440_GPJ3, S3C2440_GPJ3_CAMDATA3); s3c2410_gpio_cfgpin(S3C2440_GPJ4, S3C2440_GPJ4_CAMDATA4); s3c2410_gpio_cfgpin(S3C2440_GPJ5, S3C2440_
4、GPJ5_CAMDATA5); s3c2410_gpio_cfgpin(S3C2440_GPJ6, S3C2440_GPJ6_CAMDATA6); s3c2410_gpio_cfgpin(S3C2440_GPJ7, S3C2440_GPJ7_CAMDATA7); s3c2410_gpio_cfgpin(S3C2440_GPJ8, S3C2440_GPJ8_CAMPCLK); s3c2410_gpio_cfgpin(S3C2440_GPJ9, S3C2440_GPJ9_CAMVSYNC); s3c2410_gpio_cfgpin(S3C2440_GPJ10, S3C2440_GPJ10_CAMH
5、REF); s3c2410_gpio_cfgpin(S3C2440_GPJ11, S3C2440_GPJ11_CAMCLKOUT); s3c2410_gpio_cfgpin(S3C2440_GPJ12, S3C2440_GPJ12_CAMRESET);申请CAMIF的寄存器区域,由于OS的系统统一管理,所以,需要确定,该寄存器区域没有被别的进程获取,所以要申请。 /* init cameras virtual memory. */ if (!request_mem_region(unsigned long)S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF, CARD_NAM
6、E) ret = -EBUSY; goto error1; 申请到了寄存器区域,相当于物理地址可用,然后,再将该物理地址映射到虚拟地址。 /* remap the virtual memory. */ camif_base_addr = (unsigned long)ioremap_nocache(unsigned long)S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF); if (camif_base_addr = (unsigned long)NULL) goto error2;获取CAMIF的时钟,使用24M /* init camera clock. */ pd
7、ev-clk = clk_get(NULL, camif); if (IS_ERR(pdev-clk) ret = -ENOENT; goto error3; clk_enable(pdev-clk); camif_upll_clk = clk_get(NULL, camif-upll clk_set_rate(camif_upll_clk, ); mdelay(100);初始化CAMIF的状态 /* init camif state and its lock. */state = CAMIF_STATE_FREE;CAMIF DEV的状态:/* for s3c2440camif_dev-st
8、ate field. */enum CAMIF_STATE_FREE = 0, / not openned CAMIF_STATE_READY = 1, / openned, but standby CAMIF_STATE_PREVIEWING = 2, / in previewing CAMIF_STATE_CODECING = 3 / in capturing;注册杂项设备: /* register to videodev layer. */ if (misc_register(&misc) 0) goto error4; printk(KERN_ALERTs3c2440 camif in
9、it donen初始化SCCB接口,Serial Camera Control Bus,其实是I2C接口 sccb_init();硬件复位CAMIF hw_reset_camif();其实是软件复位,对CIGCTRL寄存器配置软件复位/* software reset camera interface. */static void _inline_ hw_reset_camif(void) u32 cigctrl; cigctrl = (130)|(1= 0; s3c2410_gpio_setpin(S3C2410_GPG4, 1);OV9650的初始化:int s3c2440_ov9650_
10、init(void)Loading OV9650 driver.n /* power on. */ ov9650_poweron(); /* check device. */ if (ov9650_check() = 0 & ov9650_check() = 0) printk(KERN_ERRNo OV9650 found!n return -ENODEV; show_ov9650_product_id(); ov9650_init_regs(); printk(ov9650 init done!OV9650上电,这里对GPG12设置为输出,这里使用的虽然是中断引脚,但似乎没有用中断,这是一
11、个电源控制引脚,PWDN,0:power on,1:power downstatic void _inline_ ov9650_poweron(void) s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_OUTP); s3c2410_gpio_setpin(S3C2410_GPG12, 0); mdelay(20);OV9650检测,读取OV9650的Manu IDstatic int _inline_ ov9650_check(void) u32 mid; mid = sccb_read(OV9650_SCCB_ADDR, 0x1c)stat
12、e = CAMIF_STATE_READY; init_camif_config(fh); 对CAMIF进行配置,最后更新一下配置/* config camif when master-open camera.*/static void init_camif_config(struct s3c2440camif_fh * fh) struct s3c2440camif_dev * pdev; pdev = fh-dev;input = 0; / FIXME, the default input image format, see inputs for detail. /* the source
13、 image size (input from external camera). */srcHsize = 1280; / FIXME, the OV9650s horizontal output pixels.srcVsize = 1024;s verical output pixels. /* the windowed image size. */wndHsize = 1280;wndVsize = 1024; /* codec-path target(output) image size. */coTargetHsize = pdev-wndHsize;coTargetVsize =
14、pdev-wndVsize; /* preview-path target(preview) image size. */preTargetHsize = 640;preTargetVsize = 512; update_camif_config(fh, CAMIF_CMD_STOP); 由于设备状态是CAMIF_STATE_READY所以,直接更新寄存器。/* update camera interface with the new config. */static void update_camif_config (struct s3c2440camif_fh * fh, u32 cmdc
15、ode) switch (pdev-state) case CAMIF_STATE_READY: update_camif_regs(fh-dev); / config the regs directly. break; case CAMIF_STATE_PREVIEWING: /* camif is previewing image. */ disable_irq(IRQ_S3C2440_CAM_P); / disable cam-preview irq. /* source image format. */ if (cmdcode & CAMIF_CMD_SFMT) / ignore it
16、, nothing to do now. /* target image format. */ CAMIF_CMD_TFMT) /* change target image format only. */ pdev-cmdcode |= CAMIF_CMD_TFMT; 不知为什么要等待VSYNC为L?然后对寄存器进行配置。/* update camif registers, called only when camif ready, or ISR. */static void _inline_ update_camif_regs(struct s3c2440camif_dev * pdev)i
17、n_irq() while(1) / wait until VSYNC is L barrier(); if (ioread32(S3C244X_CICOSTATUS)&(1 size2)?size1:size2; order = get_order(size); /获取需要分配字节的2的阶数,内存按页分配 img_buff0.order = order; img_buff0.virt_base = _get_free_pages(GFP_KERNEL|GFP_DMA, img_buff0.order); if (img_buff0.virt_base = (unsigned long)NUL
18、L) goto error0; img_buff0.phy_base = img_buff0.virt_base - PAGE_OFFSET + PHYS_OFFSET; / the DMA address.申请中断,分别为Codec的中断和Preview的中断 request_irq(IRQ_S3C2440_CAM_C, on_camif_irq_c, IRQF_DISABLED, CAM_C, pdev); request_irq(IRQ_S3C2440_CAM_P, on_camif_irq_p, IRQF_DISABLED, CAM_P使能时钟,软件复位,更新CAMIF的配置。 / a
19、nd enable camif clock. soft_reset_camif(); file-private_data = fh; fh-dev = pdev; update_camif_config(fh, 0);摄像头接口读取函数:static ssize_t camif_read(struct file *file, char _user *data, size_t count, loff_t *ppos) int i; struct s3c2440camif_fh * fh; fh = file-private_data; if (start_capture(pdev, 0) !=
20、0) /此处是捕获一张图片,所以会阻塞在此,直至中断发生。 return -ERESTARTSYS;/中断已经发生,数据已经更新。 disable_irq(IRQ_S3C2440_CAM_C); disable_irq(IRQ_S3C2440_CAM_P); for (i = 0; i 4; i+) if (img_buffi.state != CAMIF_BUFF_INVALID) /如果数据已经更新,移动数据 copy_to_user(data, (void *)img_buffi.virt_base, count); img_buffi.state = CAMIF_BUFF_INVALID; /设置数据无效 enable_irq(IRQ_S3C2440_CAM_P); /重新使能中断 enable_irq(IRQ_S3C2440_CAM_C); return count; 开始捕获函数,设置window offset/* start image capture. * * param stream means capture pictures streamly
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1