OMAP3430 sdp Linux camera driver 分析

 

一、文件:arch/arm/mach-omap2/board-3430sdp.c line1274

(1)、/*定义I2C 的相关信息*/

static struct i2c_board_info __initdata sdp3430_i2c_boardinfo_2[] = {

#ifdefined(CONFIG_VIDEO_MT9P012)|| defined(CONFIG_VIDEO_MT9P012_MODULE)

       {

              I2C_BOARD_INFO("mt9p012", MT9P012_I2C_ADDR),

              .platform_data = &sdp3430_mt9p012_platform_data,

       },

#ifdef CONFIG_VIDEO_DW9710

       {

              I2C_BOARD_INFO(DW9710_NAME, DW9710_AF_I2C_ADDR),

              .platform_data = &sdp3430_dw9710_platform_data,

       },

#endif

#endif

#ifdefined(CONFIG_VIDEO_OV3640)|| defined(CONFIG_VIDEO_OV3640_MODULE)

       {

              I2C_BOARD_INFO("ov3640", OV3640_I2C_ADDR),

              .platform_data = &sdp3430_ov3640_platform_data,

       },

#endif

#ifdefined(CONFIG_VIDEO_IMX046)|| defined(CONFIG_VIDEO_IMX046_MODULE)

       {

              I2C_BOARD_INFO("imx046", IMX046_I2C_ADDR),

              .platform_data = &sdp3430_imx046_platform_data,

       },

#endif

       {

              I2C_BOARD_INFO("isp1301_host", ISP1301_I2C_ADDR1),

              .type             = "isp1301_host",

       },

       {

              I2C_BOARD_INFO("isp1301_host", ISP1301_I2C_ADDR2),

              .type             = "isp1301_host",

       },

};


(2)、platform 数据,有I2c注册时传入驱动程序

static struct mt9p012_platform_data sdp3430_mt9p012_platform_data = {

       .power_set      = mt9p012_sensor_power_set,

       .priv_data_set = mt9p012_sensor_set_prv_data,

       .default_regs   = NULL,

};

 

二、文件:drivers/media/video/mt9p012.c

Camera sensor作为v4l2的slave设备,必须和master设备配对使用.

(1)、/*定义IOCTL函数*/

static struct v4l2_int_ioctl_desc mt9p012_ioctl_desc[] = {

       { .num = vidioc_int_enum_framesizes_num,

         .func = (v4l2_int_ioctl_func *)ioctl_enum_framesizes },

       { .num = vidioc_int_enum_frameintervals_num,

         .func = (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },

       { .num = vidioc_int_dev_init_num,

         .func = (v4l2_int_ioctl_func *)ioctl_dev_init },

       { .num = vidioc_int_dev_exit_num,

         .func = (v4l2_int_ioctl_func *)ioctl_dev_exit },

       { .num = vidioc_int_s_power_num,

         .func = (v4l2_int_ioctl_func *)ioctl_s_power },

       { .num = vidioc_int_g_priv_num,

         .func = (v4l2_int_ioctl_func *)ioctl_g_priv },

       { .num = vidioc_int_init_num,

         .func = (v4l2_int_ioctl_func *)ioctl_init },

       { .num = vidioc_int_enum_fmt_cap_num,

         .func = (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },

       { .num = vidioc_int_try_fmt_cap_num,

         .func = (v4l2_int_ioctl_func *)ioctl_try_fmt_cap },

       { .num = vidioc_int_g_fmt_cap_num,

         .func = (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },

       { .num = vidioc_int_s_fmt_cap_num,

         .func = (v4l2_int_ioctl_func *)ioctl_s_fmt_cap },

       { .num = vidioc_int_g_parm_num,

         .func = (v4l2_int_ioctl_func *)ioctl_g_parm },

       { .num = vidioc_int_s_parm_num,

         .func = (v4l2_int_ioctl_func *)ioctl_s_parm },

       { .num = vidioc_int_queryctrl_num,

         .func = (v4l2_int_ioctl_func *)ioctl_queryctrl },

       { .num = vidioc_int_g_ctrl_num,

         .func = (v4l2_int_ioctl_func *)ioctl_g_ctrl },

       { .num = vidioc_int_s_ctrl_num,

         .func = (v4l2_int_ioctl_func *)ioctl_s_ctrl },

};


static struct v4l2_int_slave mt9p012_slave = {

       .ioctls = mt9p012_ioctl_desc,

       .num_ioctls = ARRAY_SIZE(mt9p012_ioctl_desc),

};


static struct v4l2_int_device mt9p012_int_device = {

       .module = THIS_MODULE,

       .name = DRIVER_NAME,

       .priv = &mt9p012,

       .type = v4l2_int_type_slave,

       .u = {

              .slave = &mt9p012_slave,

       },

};


(2)、数据结构说明

struct v4l2_int_device {

       /* Don't touch head. */

       struct list_head head;/*双向链表*/

       struct module *module;

       char name[V4L2NAMESIZE];

       enum v4l2_int_type type;

       union {

              struct v4l2_int_master *master;/*sensor控制器,例如omap3430等*/

              struct v4l2_int_slave *slave; /*sensor,例如mt9p012,mt9p113等*/

       } u;

       void *priv;

};


(3)、注册mt9p012 camera sensor

static int

mt9p012_probe(struct i2c_client *client, const struct i2c_device_id *id)

{

       struct mt9p012_sensor *sensor = &mt9p012;

       int err;

       if (i2c_get_clientdata(client))

              return -EBUSY;

       sensor->pdata = client->dev.platform_data;

       if (!sensor->pdata) {

              dev_err(&client->dev, "no platform data?\n");

              return -ENODEV;

       }


       sensor->v4l2_int_device = &mt9p012_int_device;

       sensor->i2c_client = client;

       i2c_set_clientdata(client, sensor);

       /* Make the default capture format QCIF V4L2_PIX_FMT_SGRBG10 */

       sensor->pix.width = VIDEO_WIDTH_4X_BINN_SCALED;

       sensor->pix.height = VIDEO_HEIGHT_4X_BINN_SCALED;

       sensor->pix.pixelformat = V4L2_PIX_FMT_SGRBG10;

       err = v4l2_int_device_register(sensor->v4l2_int_device);/*注册V4L2 的IOCTL*/

       if (err)

              i2c_set_clientdata(client, NULL);

       return err;

}


三、drivers/media/video/omap34Xxcamera.c

(1)、定义sensor master的attach和detach函数,和slave配对时调用

static struct v4l2_int_master omap34xxcam_master = {

       .attach = omap34xxcam_device_register,

       .detach = omap34xxcam_device_unregister,

};

(2)、在probe函数中再次调用v4l2_int_device_register函数注册master设备

static int omap34xxcam_probe(struct platform_device *pdev)

{

       struct omap34xxcam_device *cam;

       struct resource *mem;

       struct isp_sysc isp_sysconfig;

       int irq;

       int i;

       cam = kzalloc(sizeof(*cam), GFP_KERNEL);

       if (!cam) {

              dev_err(&pdev->dev, "could not allocate memory\n");

              goto err;

       }

       platform_set_drvdata(pdev, cam);

       cam->dev = &pdev->dev;

       /* request the mem region for the camera registers */

       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);

       if (!mem) {

              dev_err(cam->dev, "no mem resource?\n");

              goto err;

       }

       if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,

                            pdev->name)) {

              dev_err(cam->dev,

                     "cannot reserve camera register I/O region\n");

              goto err;

       }

       cam->mmio_base_phys = mem->start;

       cam->mmio_size = (mem->end - mem->start) + 1;

       /* map the region */

       cam->mmio_base = (unsigned long)

                     ioremap_nocache(cam->mmio_base_phys, cam->mmio_size);

       if (!cam->mmio_base) {

              dev_err(cam->dev, "cannot map camera register I/O region\n");

              goto err;

       }

       irq = platform_get_irq(pdev, 0);

       if (irq <= 0) {

              dev_err(cam->dev, "no irq for camera?\n");

              goto err;

       }

       isp_get();

       isp_sysconfig.reset = 0;

       isp_sysconfig.idle_mode = 1;

       isp_power_settings(isp_sysconfig);

       isp_put();

       for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {

              struct omap34xxcam_videodev *vdev = &cam->vdevs[i];

              struct v4l2_int_device *m = &vdev->master;

              m->module       = THIS_MODULE;

              strlcpy(m->name, CAM_NAME, sizeof(m->name));

              m->type         = v4l2_int_type_master;

              m->u.master     = &omap34xxcam_master;/赋值master和slave配对调用函数/

              m->priv        = vdev;

              mutex_init(&vdev->mutex);

              vdev->index             = i;

              vdev->cam               = cam;

              if (v4l2_int_device_register(m))/*注册*/

                     goto err;

       }

       omap34xxcam = cam;

#ifdef CONFIG_OMAP3_PM

       if (system_rev >= OMAP3430_REV_ES2_0) {

              /* Getting constraint for VDD1 and VDD2 */

              co_opp_camera_latency = constraint_get("omap34xxcam",

                                                        &cnstr_id_latency);

              co_opp_camera_vdd1 = constraint_get("omap34xxcam", &cnstr_id_vdd1);

              co_opp_camera_vdd2 = constraint_get("omap34xxcam", &cnstr_id_vdd2);

       }

#endif

       return 0;

err:

       omap34xxcam_remove(pdev);

       return -ENODEV;

}

四、文件:arch/arm/mach-omap2/devices.c

(1)、注册平台设备包含camera

static int __init omap2_init_devices(void)

{

       /* please keep these calls, and their implementations above,

        * in alphabetical order so they're easier to sort through.

        */

       omap_init_camera();

       omap_init_mbox();

       omap_init_mcspi();

       omap_hdq_init();

       omap_init_sti();

       omap_init_sha1_md5();

       return 0;

}

arch_initcall(omap2_init_devices);

(2)、camera平台设备定义

#elifdefined(CONFIG_VIDEO_OMAP3)|| defined(CONFIG_VIDEO_OMAP3_MODULE)


static struct resource cam_resources[] = {

       {

              .start            = OMAP34XX_CAMERA_BASE,

              .end              = OMAP34XX_CAMERA_BASE + 0x1B70,

              .flags            = IORESOURCE_MEM,

       },

       {

              .start            = INT_34XX_CAM_IRQ,

              .flags            = IORESOURCE_IRQ,

       }

};

static struct platform_device omap_cam_device = {

       .name           = "omap34xxcam",

       .id          = -1,

       .num_resources = ARRAY_SIZE(cam_resources),

       .resource      = cam_resources,

};

static inline void omap_init_camera(void)

{

       platform_device_register(&omap_cam_device);/*注册成功调用probe函数*/

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值