您的位置:首页 > 其它

深入浅出,camera v4l2理解(2)v4l2注册

2013-06-04 16:36 369 查看
正式步入v4l2_i2c_subdev_init
这个是什么呢,看代码:
这个是在v4l2-common里面:
[align=left]void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,[/align]
[align=left] const struct v4l2_subdev_ops *ops)[/align]
[align=left]{[/align]
[align=left] v4l2_subdev_init(sd, ops); //这个地方属于初始化,也就是申请相关空间[/align]
[align=left] sd->flags |= V4L2_SUBDEV_FL_IS_I2C; //说明这个是个i2c的[/align]
[align=left] /* the owner is the same as the i2c_client's driver owner */[/align]
[align=left] sd->owner = client->driver->driver.owner;[/align]
[align=left] /* i2c_client and v4l2_subdev point to one another */[/align]
[align=left] v4l2_set_subdevdata(sd, client); //相互保存数据[/align]
[align=left] i2c_set_clientdata(client, sd); //相互保存数据[/align]
[align=left] /* initialize name */[/align]
[align=left] snprintf(sd->name, sizeof(sd->name), "%s %d-%04x", //在这个地方这个name改变了,这里也就是注册mipi的时候用到的名字,每个mipi的每个线都要和这个名字对应,分别是name-所在的i2c总线-i2c的地址[/align]
[align=left] client->driver->driver.name, i2c_adapter_id(client->adapter),[/align]
[align=left] client->addr);[/align]
[align=left]}[/align]
[align=left]EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);[/align]

[align=left]这个函数主要起到保存参数的总用,后续调用更加的方便。[/align]

[align=left]在这个函数后,真正对v4l2配置的在下面这个函数:[/align]

[align=left]/* register a msm sensor into the msm device, which will probe the[/align]
[align=left] * sensor HW. if the HW exist then create a video device (/dev/videoX/)[/align]
[align=left] * to represent this sensor */[/align]

[align=left]一个v4l2的接口在/dev/videoX/每一个videoX对应一个v4l2的设备节点,从这个开始才是v4l2的重点:[/align]

[align=left]int msm_sensor_register(struct v4l2_subdev *sensor_sd)[/align]
[align=left]{[/align]
[align=left] int rc = -EINVAL;[/align]
[align=left] struct msm_camera_sensor_info *sdata;[/align]
[align=left] struct msm_cam_v4l2_device *pcam;[/align]
[align=left] struct msm_sensor_ctrl_t *s_ctrl;[/align]

[align=left] D("%s for %s\n", __func__, sensor_sd->name);[/align]

[align=left] /* allocate the memory for the camera device first */[/align]
[align=left] pcam = kzalloc(sizeof(*pcam), GFP_KERNEL);[/align]
[align=left] if (!pcam) {[/align]
[align=left] pr_err("%s: could not allocate mem for msm_cam_v4l2_device\n",[/align]
[align=left] __func__);[/align]
[align=left] return -ENOMEM;[/align]
[align=left] }[/align]

[align=left] pcam->sensor_sdev = sensor_sd; //这个sensor_sd,就是一个v4l2的name而已,里面的成员只做了赋值为0的初始化动作,后面会看到它的羽翼逐渐丰满。[/align]
[align=left] s_ctrl = get_sctrl(sensor_sd);[/align]
sdata = (struct msm_camera_sensor_info *) s_ctrl->sensordata;//这个很眼熟,不就是那个board中的msm_camera_sensor_info嘛!它包含了对sensor的很多信息,power啊reset啊
是否是有yuv的还是raw的,有没有对焦啊,什么都有!

[align=left] pcam->act_sdev = msm_actuator_probe(sdata->actuator_info);//这个地方看了对马达的probe了没,马达的i2c的probe就是从这个地方开始的[/align]
[align=left] pcam->eeprom_sdev = msm_eeprom_probe(sdata->eeprom_info); //这个地方对应board中的eeprom_info[/align]

[align=left] D("%s: pcam =0x%p\n", __func__, pcam);[/align]

[align=left] pcam->sdata = sdata; //msm_camera_sensor_info进去了[/align]

[align=left] /* init the user count and lock*/[/align]
[align=left] pcam->use_count = 0;[/align]
[align=left] mutex_init(&pcam->vid_lock);[/align]
[align=left] mutex_init(&pcam->mctl_node.dev_lock);[/align]

[align=left] /* Initialize the formats supported */[/align]
[align=left] rc = msm_mctl_init_user_formats(pcam);[/align]

[align=left]/**************************************************************************************************/[/align]

[align=left]这个函数主要是对camera输出的格式定义,这样v4l2才可以接受[/align]

int msm_mctl_init_user_formats(struct
msm_cam_v4l2_device *pcam)
[align=left]{[/align]
[align=left] struct v4l2_subdev *sd = pcam->sensor_sdev;[/align]
[align=left] enum v4l2_mbus_pixelcode pxlcode;[/align]
[align=left] int numfmt_sensor = 0;[/align]
[align=left] int numfmt = 0;[/align]
[align=left] int rc = 0;[/align]
[align=left] int i, j;[/align]

[align=left] D("%s\n", __func__);[/align]
[align=left] while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, numfmt_sensor, //别看了这个是用来判断是否存在pxlcode空指针的,用这个来判断你个v4l2支持多个格式[/align]
[align=left] &pxlcode))[/align]
[align=left] numfmt_sensor++; //格式的数量加加~[/align]

[align=left] D("%s, numfmt_sensor = %d\n", __func__, numfmt_sensor);[/align]
[align=left] if (!numfmt_sensor)[/align]
[align=left] return -ENXIO;[/align]

[align=left] pcam->usr_fmts = vmalloc(numfmt_sensor * ARRAY_SIZE(msm_isp_formats) * //知不知道v4l2对sensor输出格式的接受是有[/align]
[align=left] sizeof(struct msm_isp_color_fmt)); //明确的定义的?这个函数的意思是在所有的可以接受的格式先保存下来,很多十多组吧。[/align]
[align=left] if (!pcam->usr_fmts)[/align]
[align=left] return -ENOMEM;[/align]

[align=left] /* from sensor to ISP.. fill the data structure */[/align]
[align=left] for (i = 0; i < numfmt_sensor; i++) { //这里对每一个v4l2选择他对应的输出格式,有一个,配一个,可配置多个,也就是说一个sensor可能支持多个格式的输出嘛~[/align]
rc = v4l2_subdev_call(sd, video, enum_mbus_fmt, i, &pxlcode);
//循环取pxlcode空指针的,空了推出
[align=left] D("rc is %d\n", rc);[/align]
[align=left] if (rc < 0) {[/align]
[align=left] vfree(pcam->usr_fmts);[/align]
[align=left] return rc;[/align]
[align=left] }[/align]

[align=left] for (j = 0; j < ARRAY_SIZE(msm_isp_formats); j++) { //找一找pxlcode是否能匹配,不能换下一个pxlcode,一个sensor能提供多个pxlcode[/align]
[align=left] /* find the corresponding format */[/align]
[align=left] if (pxlcode == msm_isp_formats[j].pxlcode) {[/align]
[align=left] pcam->usr_fmts[numfmt] = msm_isp_formats[j];[/align]
[align=left] D("pcam->usr_fmts=0x%x\n", (u32)pcam->usr_fmts);[/align]
[align=left] D("format pxlcode 0x%x (0x%x) found\n",[/align]
[align=left] pcam->usr_fmts[numfmt].pxlcode,//如果你配置的参数在列表中有,恭喜你匹配成功,记录在pcam->usr_fmts[numfmt].pxlcode[/align]
[align=left] pcam->usr_fmts[numfmt].fourcc);////如果你配置的参数在列表中有,恭喜你匹配成功,记录在pcam->usr_fmts[numfmt].pxlcode[/align]
[align=left] numfmt++;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]

[align=left] pcam->num_fmts = numfmt; //你有多少个支持的格式啊?[/align]

[align=left] if (numfmt == 0) { //老子没有![/align]
[align=left] pr_err("%s: No supported formats.\n", __func__);[/align]
[align=left] vfree(pcam->usr_fmts);[/align]
[align=left] return -EINVAL; //滚粗![/align]
[align=left] }[/align]

[align=left] D("Found %d supported formats.\n", pcam->num_fmts);[/align]
[align=left] /* set the default pxlcode, in any case, it will be set through[/align]
[align=left] * setfmt */[/align]
[align=left] return 0;[/align]
[align=left]}[/align]

/**************************************************************************************************/

[align=left] if (rc < 0)[/align]
[align=left] goto failure;[/align]

[align=left] rc = msm_cam_dev_init(pcam);[/align]
[align=left] if (rc < 0)[/align]
[align=left] goto failure;[/align]

/*************************************************************************************************

static int msm_cam_dev_init(struct msm_cam_v4l2_device
*pcam)
[align=left]{[/align]
[align=left] int rc = -ENOMEM;[/align]
[align=left] struct video_device *pvdev = NULL;[/align]
struct i2c_client *client =v4l2_get_subdevdata(pcam->sensor_sdev);
//之前保存的现在拿出来用了
[align=left] D("%s\n", __func__);[/align]

[align=left] /* first register the v4l2 device */[/align]
[align=left] pcam->v4l2_dev.dev = &client->dev;[/align]
rc = v4l2_device_register(pcam->v4l2_dev.dev,
&pcam->v4l2_dev); //初始化参数用

[align=left] if (rc < 0)[/align]
[align=left] return -EINVAL;[/align]
[align=left] /*********************************************[/align]

int v4l2_device_register(struct device
*dev, struct v4l2_device *v4l2_dev)
[align=left] {[/align]
[align=left] if (v4l2_dev == NULL)[/align]
[align=left] return -EINVAL;[/align]

[align=left] INIT_LIST_HEAD(&v4l2_dev->subdevs);[/align]
[align=left] spin_lock_init(&v4l2_dev->lock);[/align]
[align=left] mutex_init(&v4l2_dev->ioctl_lock);[/align]
[align=left] v4l2_prio_init(&v4l2_dev->prio);[/align]
[align=left] kref_init(&v4l2_dev->ref);[/align]
[align=left] get_device(dev);[/align]
[align=left] v4l2_dev->dev = dev;[/align]
[align=left] if (dev == NULL) {[/align]
[align=left] /* If dev == NULL, then name must be filled in by the caller */[/align]
[align=left] WARN_ON(!v4l2_dev->name[0]);[/align]
[align=left] return 0;[/align]
[align=left] }[/align]

[align=left] /* Set name to driver name + device name if it is empty. */[/align]
[align=left] if (!v4l2_dev->name[0])[/align]
[align=left] snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",[/align]
[align=left] dev->driver->name, dev_name(dev));[/align]
[align=left] if (!dev_get_drvdata(dev))[/align]
[align=left] dev_set_drvdata(dev, v4l2_dev);[/align]
[align=left] return 0;[/align]
[align=left]}[/align]
[align=left]EXPORT_SYMBOL_GPL(v4l2_device_register);[/align]
[align=left]/**********************************************[/align]

[align=left] else[/align]
[align=left] pcam->v4l2_dev.notify = msm_cam_v4l2_subdev_notify;[/align]

[align=left] /* now setup video device */[/align]
[align=left] pvdev = video_device_alloc(); //申请一个video[/align]
[align=left] if (pvdev == NULL) {[/align]
[align=left] pr_err("%s: video_device_alloc failed\n", __func__);[/align]
[align=left] return rc;[/align]
[align=left] }[/align]

[align=left] strlcpy(pcam->media_dev.model, QCAMERA_NAME,[/align]
[align=left] sizeof(pcam->media_dev.model));[/align]
[align=left] pcam->media_dev.dev = &client->dev; [/align]
[align=left] rc = media_device_register(&pcam->media_dev); //注册一个media[/align]
[align=left] pvdev->v4l2_dev = &pcam->v4l2_dev;[/align]
[align=left] pcam->v4l2_dev.mdev = &pcam->media_dev; //注意这个v4l2_dev,包含了很多,很重要[/align]

[align=left] /* init video device's driver interface */ //接口和操作[/align]
[align=left] D("sensor name = %s, sizeof(pvdev->name)=%d\n",[/align]
[align=left] pcam->sensor_sdev->name, sizeof(pvdev->name));[/align]

[align=left] /* device info - strlcpy is safer than strncpy but[/align]
[align=left] only if architecture supports*/[/align]
[align=left] strlcpy(pvdev->name, pcam->sensor_sdev->name, sizeof(pvdev->name));[/align]

[align=left] pvdev->release = video_device_release;[/align]
[align=left] pvdev->fops = &g_msm_fops;[/align]
[align=left] pvdev->ioctl_ops = &g_msm_ioctl_ops;[/align]
[align=left] pvdev->minor = -1;[/align]
[align=left] pvdev->vfl_type = 1;[/align]

[align=left] media_entity_init(&pvdev->entity, 0, NULL, 0);[/align]
[align=left] pvdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;[/align]
[align=left] pvdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;[/align]

[align=left] /* register v4l2 video device to kernel as /dev/videoXX */[/align]
[align=left] D("video_register_device\n");[/align]
[align=left] rc = video_register_device(pvdev,[/align]
[align=left] VFL_TYPE_GRABBER,[/align]
[align=left] msm_camera_v4l2_nr);[/align]
[align=left] if (rc) {[/align]
[align=left] pr_err("%s: video_register_device failed\n", __func__);[/align]
[align=left] goto reg_fail;[/align]
[align=left] }[/align]
[align=left] pvdev->entity.name = video_device_node_name(pvdev);[/align]
[align=left] D("%s: video device registered as /dev/video%d\n",[/align]
[align=left] __func__, pvdev->num);[/align]

[align=left] /* connect pcam and video dev to each other */[/align]
[align=left] pcam->pvdev = pvdev;[/align]
[align=left] video_set_drvdata(pcam->pvdev, pcam);[/align]

[align=left] /* If isp HW registeration is successful,[/align]
[align=left] * then create event queue to[/align]
[align=left] * receievent event froms HW[/align]
[align=left] */[/align]
[align=left] /* yyan: no global - each sensor will[/align]
[align=left] * create a new vidoe node! */[/align]
[align=left] /* g_pmsm_camera_v4l2_dev = pmsm_camera_v4l2_dev; */[/align]
[align=left] /* g_pmsm_camera_v4l2_dev->pvdev = pvdev; */[/align]

[align=left] return rc ;[/align]

[align=left]reg_fail:[/align]
[align=left] video_device_release(pvdev);[/align]
[align=left] v4l2_device_unregister(&pcam->v4l2_dev);[/align]
[align=left] pcam->v4l2_dev.dev = NULL;[/align]
[align=left] return rc;[/align]
[align=left]}[/align]

/************************************************************************************************

[align=left] rc = msm_setup_mctl_node(pcam);[/align]
[align=left] if (rc < 0) {[/align]
[align=left] pr_err("%s:failed to create mctl device: %d\n",[/align]
[align=left] __func__, rc);[/align]
[align=left] goto failure;[/align]
[align=left] }[/align]

[align=left] g_server_dev.camera_info.video_dev_name[/align]
[align=left] [g_server_dev.camera_info.num_cameras][/align]
[align=left] = video_device_node_name(pcam->pvdev);[/align]
[align=left] D("%s Connected video device %s\n", __func__,[/align]
[align=left] g_server_dev.camera_info.video_dev_name[/align]
[align=left] [g_server_dev.camera_info.num_cameras]);[/align]

[align=left] g_server_dev.camera_info.s_mount_angle[/align]
[align=left] [g_server_dev.camera_info.num_cameras][/align]
[align=left] = sdata->sensor_platform_info->mount_angle;[/align]

[align=left] g_server_dev.camera_info.is_internal_cam[/align]
[align=left] [g_server_dev.camera_info.num_cameras][/align]
[align=left] = sdata->camera_type;[/align]

[align=left] g_server_dev.mctl_node_info.mctl_node_name[/align]
[align=left] [g_server_dev.mctl_node_info.num_mctl_nodes][/align]
[align=left] = video_device_node_name(pcam->mctl_node.pvdev);[/align]

[align=left] pr_info("%s mctl_node_name[%d] = %s\n", __func__,[/align]
[align=left] g_server_dev.mctl_node_info.num_mctl_nodes,[/align]
[align=left] g_server_dev.mctl_node_info.mctl_node_name[/align]
[align=left] [g_server_dev.mctl_node_info.num_mctl_nodes]);[/align]

[align=left] /*Temporary solution to store info in media device structure[/align]
[align=left] until we can expand media device structure to support more[/align]
[align=left] device info*/[/align]
[align=left] snprintf(pcam->media_dev.serial,[/align]
[align=left] sizeof(pcam->media_dev.serial),[/align]
[align=left] "%s-%d-%d", QCAMERA_NAME,[/align]
[align=left] sdata->sensor_platform_info->mount_angle,[/align]
[align=left] sdata->camera_type);[/align]

[align=left] g_server_dev.camera_info.num_cameras++;[/align]
[align=left] g_server_dev.mctl_node_info.num_mctl_nodes++;[/align]

[align=left] D("%s done, rc = %d\n", __func__, rc);[/align]
[align=left] D("%s number of sensors connected is %d\n", __func__,[/align]
[align=left] g_server_dev.camera_info.num_cameras);[/align]

[align=left] /* register the subdevice, must be done for callbacks */[/align]
[align=left] rc = msm_cam_register_subdev_node(sensor_sd, SENSOR_DEV, vnode_count);[/align]
[align=left] if (rc < 0) {[/align]
[align=left] D("%s sensor sub device register failed\n",[/align]
[align=left] __func__);[/align]
[align=left] goto failure;[/align]
[align=left] }[/align]

[align=left] if (pcam->act_sdev) {[/align]
[align=left] rc = v4l2_device_register_subdev(&pcam->v4l2_dev,[/align]
[align=left] pcam->act_sdev);[/align]
[align=left] if (rc < 0) {[/align]
[align=left] D("%s actuator sub device register failed\n",[/align]
[align=left] __func__);[/align]
[align=left] goto failure;[/align]
[align=left] }[/align]
[align=left] }[/align]

[align=left] if (pcam->eeprom_sdev) {[/align]
[align=left] rc = v4l2_device_register_subdev(&pcam->v4l2_dev,[/align]
[align=left] pcam->eeprom_sdev);[/align]
[align=left] if (rc < 0) {[/align]
[align=left] D("%s eeprom sub device register failed\n", __func__);[/align]
[align=left] goto failure;[/align]
[align=left] }[/align]
[align=left] }[/align]

[align=left] pcam->vnode_id = vnode_count++;[/align]
[align=left] return rc;[/align]

[align=left]failure:[/align]
[align=left] kzfree(pcam);[/align]
[align=left] return rc;[/align]
[align=left]}[/align]

[align=left]EXPORT_SYMBOL(msm_sensor_register);[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: