您的位置:首页 > 运维架构 > Linux

OMAP3430 sdp Linux camera driver 分析

2011-07-20 22:02 351 查看
一、文件: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函数*/
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: