S5PC100平台上Linux Camera驱动开发详解(7)

现在ov9650驱动里的probe和s_config函数的调用时间和功能都已经清楚了,还剩下一个ov9650_init函数还没有被调用。其实我们可以在任何希望调用它的时候利用v4l2_subdev_call来调用这init方法。不过在摄像头控制器的驱动里面已经有相应的地方调用了,就是在fimc_capture.c里面,有一个静态函数fimc_init_camera,这里会调用:

178        /* subdev call for init */
        179        ret = v4l2_subdev_call(cam->sd, core, init, 0);
        180        if (ret == -ENOIOCTLCMD) {
        181                fimc_err("%s: init subdev api not supported\n", __func__);
        182                return ret;
        183        }

这时ov9650.c里的ov9650_init就会被调到了。Ov9650_init做的工作其实就是初始化摄像头的寄存器,初始化可以有两种方法,一个是通过sccb.c里面提供的方法(gpio模拟i2c),另一个就是直接利用内核提供的i2c总线数据读写方法来操作,我们的代码里两种方法都实现了,不过用sccb更稳妥一些,因为不知道什么原因,直接操作i2c总线有时候会失败,这个问题仍需解决。fimc_init_camera这个函数可能会在fimc_s_input或者fimc_streamon_capture两个函数中被调用。也就是当应用程序中调用ioctl( v4l2_fd, VIDIOC_S_INPUT, &index )或者ioctl(v4l2_fd, VIDIOC_STREAMON, &type)时都有可能调用到fimc_init_camera。,当然它只会被调用一次。

还有最后一个问题就是何时给摄像头发送复位信号(原理图上第4管脚,CAM_RST),因为摄像头只有接到复位信号(高电平或者低电平)才能正常工作。我们这里是在打开v4l2设备的时候,也就是open(“/dev/video0”, RD_WR)时复位的,具体就是在fimc_dev.c里对应得v4l2的open方法:fimc_open:

653        if (pdata->hw_ver == 0x40)
        654                fimc_hw_reset_camera(ctrl);

这个fimc_hw_reset_camera就是复位函数,定义在fimc40_reg.c中:

1113 int fimc_hw_reset_camera(struct fimc_control *ctrl)
        1114 {
        1115        u32 cfg;
        1116
        1117 #ifdef CONFIG_VIDEO_OV9650
        1118        /* high reset */
        1119        cfg = readl(ctrl->regs + S3C_CIGCTRL);
        1120        cfg |= S3C_CIGCTRL_CAMRST_A;
        1121        writel(cfg, ctrl->regs + S3C_CIGCTRL);
        1122        mdelay(20);
        1123
        1124        cfg = readl(ctrl->regs + S3C_CIGCTRL);
        1125        cfg &= ~S3C_CIGCTRL_CAMRST_A;
        1126        writel(cfg, ctrl->regs + S3C_CIGCTRL);
        1127        udelay(2000);
        1128 #endif
        1129 #ifdef CONFIG_VIDEO_OV9655
        1130        /* low reset */
        1131        cfg = readl(ctrl->regs + S3C_CIGCTRL);
        1132        cfg &= ~S3C_CIGCTRL_CAMRST_A;
        1133        writel(cfg, ctrl->regs + S3C_CIGCTRL);
        1134        mdelay(20);
        1135
        1136        cfg = readl(ctrl->regs + S3C_CIGCTRL);
        1137        cfg |= S3C_CIGCTRL_CAMRST_A;
        1138        writel(cfg, ctrl->regs + S3C_CIGCTRL);
        1139        udelay(2000);
        }

因为ov9650是高电平复位,ov9655是低电平复位,所以需要分开来写。

5. 应用程序如何操作摄像头

细节请参考代码:ov9650_v4l2.c

操作摄像头需要符合v4l2的标准接口,接口描述及示例请参考v4l2官网

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/7ef92923623d14e8d9f2bdca4c92469b.html