v4L2 soc-camera 分析 - soc_camera.c
soc_camera.c
- 1455 static struct platform_driver __refdata soc_camera_pdrv = {
- 1456 .remove = __devexit_p(soc_camera_pdrv_remove),
- 1457 .driver = {
- 1458 .name = "soc-camera-pdrv",
- 1459 .owner = THIS_MODULE,
- 1460 },
- 1461 };
- 1462
- 1463 static int __init soc_camera_init(void)
- 1464 {
- 1465 int ret = bus_register(&soc_camera_bus_type);
- 1466 if (ret)
- 1467 return ret;
- 1468 ret = driver_register(&ic_drv);
- 1469 if (ret)
- 1470 goto edrvr;
- 1471
- 1472 ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
- 1473 if (ret)
- 1474 goto epdr;
- 1475
- 1476 return 0;
- 1477
- 1478 epdr:
- 1479 driver_unregister(&ic_drv);
- 1480 edrvr:
- 1481 bus_unregister(&soc_camera_bus_type);
- 1482 return ret;
- 1483 }
1472 platform_driver_probe和platform_driver_register的区别:前者功能上和 platform_driver_register是一样的,但是在内核启动完成后,这个函数就不能再执行了,这样可以释放函数 soc_camera_pdrv_probe所占的空间。
soc_camera_pdrv_probe会probe系统内名称为"soc-camera-pdrv"的平台设备,系统内有几个这样的平台设备,那么就会创建几个soc_camera_device。这些平台设备可如下定义:
- struct platform_device your_mach_cameras[] = {
- {
- .name = "soc-camera-pdrv",
- .id = 0,
- .dev = {
- .platform_data = adv7180_link,
- },
- }, {
- .name = "soc-camera-pdrv",
- .id = 1,
- .dev = {
- .platform_data = tw9912_link,
- },
- }
- };
注意,这里假定系统的camera处理模块,接了两个camera sensor, adv7180_link和tw9912_link
- static struct i2c_board_info decoder_i2c_adv7180 = {
- I2C_BOARD_INFO("adv7180", (0x42 >> 1)),
- };
- struct soc_camera_link adv7180_link = {
- .bus_id = 0,
- .board_info = &decoder_i2c_adv7180,
- .i2c_adapter_id = 0,
- };
soc_camera_link主要用来定义i2c地址,如果sensor不是通过i2c连接到host上,那么要定义add_device和del_device函数
1465 注册一条新的总线soc-camera,这样在scan_add_host中调用device_register时,就会把这个设备挂到这个总线上。
- 1135 struct bus_type soc_camera_bus_type = {
- 1136 .name = "soc-camera",
- 1137 .probe = soc_camera_probe,
- 1138 .remove = soc_camera_remove,
- 1139 .suspend = soc_camera_suspend,
- 1140 .resume = soc_camera_resume,
- 1141 };
- 1142 EXPORT_SYMBOL_GPL(soc_camera_bus_type);
当一个soc-camera-device设备通过device_register注册设备时,就会调用soc_camera_probe函数
- 1402 static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
- 1403 {
- 1404 struct soc_camera_link *icl = pdev->dev.platform_data;
- 1405 struct soc_camera_device *icd;
- 1406 int ret;
- 1407
- 1408 if (!icl)
- 1409 return -EINVAL;
- 1410
- 1411 icd = kzalloc(sizeof(*icd), GFP_KERNEL);
- 1412 if (!icd)
- 1413 return -ENOMEM;
- 1414
- 1415 icd->iface = icl->bus_id;
- 1416 icd->pdev = &pdev->dev;
- 1417 platform_set_drvdata(pdev, icd);
- 1418
- 1419 ret = soc_camera_device_register(icd);
- 1420 if (ret < 0)
- 1421 goto escdevreg;
- 1422
- 1423 soc_camera_device_init(&icd->dev, icl);
- 1424
- 1425 icd->user_width = DEFAULT_WIDTH;
- 1426 icd->user_height = DEFAULT_HEIGHT;
- 1427
- 1428 return 0;
- 1429
- 1430 escdevreg:
- 1431 kfree(icd);
- 1432
- 1433 return ret;
- 1434 }
查找匹配名为soc-camera-pdrv的platform device时,调用该函数。
1419 调用soc_camera_device_register,把这个soc_camera_device加到全局camera device链表@devices上,并且为它分配设备号,做一些必要的初始化
1423 设置soc_came_device对应device的bus为soc_camera_bus_type,这样当我们注册设备时,就会调用soc_camera_probe
- 1374 /*
- 1375 * Called from soc_camera_probe() above (with .video_lock held???)
- 1376 */
- 1377 static int soc_camera_video_start(struct soc_camera_device *icd)
- 1378 {
- 1379 struct device_type *type = icd->vdev->dev.type;
- 1380 int ret;
- 1381
- 1382 if (!icd->dev.parent)
- 1383 return -ENODEV;
- 1384
- 1385 if (!icd->ops ||
- 1386 !icd->ops->query_bus_param ||
- 1387 !icd->ops->set_bus_param)
- 1388 return -EINVAL;
- 1389
- 1390 ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1);
- 1391 if (ret < 0) {
- 1392 dev_err(&icd->dev, "video_register_device failed: %d\n", ret);
- 1393 return ret;
- 1394 }
- 1395
- 1396 /* Restore device type, possibly set by the subdevice driver */
- 1397 icd->vdev->dev.type = type;
- 1398
- 1399 return 0;
- 1400 }
在当前的上下文,soc_camera_video_start的调用路径如下
soc_camera_host_register ==> scan_add_host ==> device_register
==> bus_probe_device ==> soc_camera_bus_type.probe ==>
soc_camera_video_start
1390 我们可以看出,系统为每一个soc-camera-device创建了一个video device设备节点
- 1352 static int video_dev_create(struct soc_camera_device *icd)
- 1353 {
- 1354 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- 1355 struct video_device *vdev = video_device_alloc();
- 1356
- 1357 if (!vdev)
- 1358 return -ENOMEM;
- 1359
- 1360 strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
- 1361
- 1362 vdev->parent = &icd->dev;
- 1363 vdev->current_norm = V4L2_STD_UNKNOWN;
- 1364 vdev->fops = &soc_camera_fops;
- 1365 vdev->ioctl_ops = &soc_camera_ioctl_ops;
- 1366 vdev->release = video_device_release;
- 1367 vdev->tvnorms = V4L2_STD_UNKNOWN;
- 1368
- 1369 icd->vdev = vdev;
- 1370
- 1371 return 0;
- 1372 }
当前的上下文,video_dev_create的调用路径如下
soc_camera_host_register ==> scan_add_host ==> device_register ==> bus_probe_device ==> soc_camera_bus_type.probe ==> soc_camera_video_start
这里面设置了video_device的两个非常重要的参数:soc_camera_ioctl_ops和soc_camera_fops,当user space打开video device后,所有可执行的操作,都是通过这两个入口进行的,下面是他们的定义。
- 549 static struct v4l2_file_operations soc_camera_fops = {
- 550 .owner = THIS_MODULE,
- 551 .open = soc_camera_open,
- 552 .release = soc_camera_close,
- 553 .unlocked_ioctl = video_ioctl2,
- 554 .read = soc_camera_read,
- 555 .mmap = soc_camera_mmap,
- 556 .poll = soc_camera_poll,
- 557 };
- 1321 static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
- 1322 .vidioc_querycap = soc_camera_querycap,
- 1323 .vidioc_g_fmt_vid_cap = soc_camera_g_fmt_vid_cap,
- 1324 .vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap,
- 1325 .vidioc_s_fmt_vid_cap = soc_camera_s_fmt_vid_cap,
- 1326 .vidioc_enum_input = soc_camera_enum_input,
- 1327 .vidioc_g_input = soc_camera_g_input,
- 1328 .vidioc_s_input = soc_camera_s_input,
- 1329 .vidioc_s_std = soc_camera_s_std,
- 1330 .vidioc_reqbufs = soc_camera_reqbufs,
- 1331 .vidioc_try_fmt_vid_cap = soc_camera_try_fmt_vid_cap,
- 1332 .vidioc_querybuf = soc_camera_querybuf,
- 1333 .vidioc_qbuf = soc_camera_qbuf,
- 1334 .vidioc_dqbuf = soc_camera_dqbuf,
- 1335 .vidioc_streamon = soc_camera_streamon,
- 1336 .vidioc_streamoff = soc_camera_streamoff,
- 1337 .vidioc_queryctrl = soc_camera_queryctrl,
- 1338 .vidioc_g_ctrl = soc_camera_g_ctrl,
- 1339 .vidioc_s_ctrl = soc_camera_s_ctrl,
- 1340 .vidioc_cropcap = soc_camera_cropcap,
- 1341 .vidioc_g_crop = soc_camera_g_crop,
- 1342 .vidioc_s_crop = soc_camera_s_crop,
- 1343 .vidioc_g_parm = soc_camera_g_parm,
- 1344 .vidioc_s_parm = soc_camera_s_parm,
- 1345 .vidioc_g_chip_ident = soc_camera_g_chip_ident,
- 1346 #ifdef CONFIG_VIDEO_ADV_DEBUG
- 1347 .vidioc_g_register = soc_camera_g_register,
- 1348 .vidioc_s_register = soc_camera_s_register,
- 1349 #endif
- 1350 };
soc_camera_ops 不支持read操作,因此如果使用了soc camera子系统,那么应用层就无法再使用read操作获取camera 数据,而只能选择使用mmap方式。不支持read操作没什么关系,大部分camera操作都是使用mmap方式进行的。samsung的s5pv210 不支持read操作,而freescale mxc系列则支持read操作获取camera数据。
soc_camera_ioctl_ops也仅仅支持了v4l2_ioctl_ops的一个子集,这就意味着应用程序的作者需要考虑ioctl可能没有被支持。
- 1281 /* Image capture device */
- 1282 static int soc_camera_device_register(struct soc_camera_device *icd)
- 1283 {
- 1284 struct soc_camera_device *ix;
- 1285 int num = -1, i;
- 1286
- 1287 for (i = 0; i < 256 && num < 0; i++) {
- 1288 num = i;
- 1289 /* Check if this index is available on this interface */
- 1290 list_for_each_entry(ix, &devices, list) {
- 1291 if (ix->iface == icd->iface && ix->devnum == i) {
- 1292 num = -1;
- 1293 break;
- 1294 }
- 1295 }
- 1296 }
- 1297
- 1298 if (num < 0)
- 1299 /*
- 1300 * ok, we have 256 cameras on this host...
- 1301 * man, stay reasonable...
- 1302 */
- 1303 return -ENOMEM;
- 1304
- 1305 icd->devnum = num;
- 1306 icd->use_count = 0;
- 1307 icd->host_priv = NULL;
- 1308 mutex_init(&icd->video_lock);
- 1309
- 1310 list_add_tail(&icd->list, &devices);
- 1311
- 1312 return 0;
- 1313 }
把给定的@icd加到全局soc camera device列表中
1290~1294 @devices是一个全局soc camera device列表,这段代码相当拗口,注意1293行是break 1290这个循环
- 1194 int soc_camera_host_register(struct soc_camera_host *ici)
- 1195 {
- 1196 struct soc_camera_host *ix;
- 1197 int ret;
- 1198
- 1199 if (!ici || !ici->ops ||
- 1200 !ici->ops->try_fmt ||
- 1201 !ici->ops->set_fmt ||
- 1202 !ici->ops->set_bus_param ||
- 1203 !ici->ops->querycap ||
- 1204 !ici->ops->init_videobuf ||
- 1205 !ici->ops->reqbufs ||
- 1206 !ici->ops->add ||
- 1207 !ici->ops->remove ||
- 1208 !ici->ops->poll ||
- 1209 !ici->v4l2_dev.dev)
- 1210 return -EINVAL;
- 1211
- 1212 if (!ici->ops->set_crop)
- 1213 ici->ops->set_crop = default_s_crop;
- 1214 if (!ici->ops->get_crop)
- 1215 ici->ops->get_crop = default_g_crop;
- 1216 if (!ici->ops->cropcap)
- 1217 ici->ops->cropcap = default_cropcap;
- 1218 if (!ici->ops->set_parm)
- 1219 ici->ops->set_parm = default_s_parm;
- 1220 if (!ici->ops->get_parm)
- 1221 ici->ops->get_parm = default_g_parm;
- 1222
- 1223 mutex_lock(&list_lock);
- 1224 list_for_each_entry(ix, &hosts, list) {
- 1225 if (ix->nr == ici->nr) {
- 1226 ret = -EBUSY;
- 1227 goto edevreg;
- 1228 }
- 1229 }
- 1230
- 1231 ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev);
- 1232 if (ret < 0)
- 1233 goto edevreg;
- 1234
- 1235 list_add_tail(&ici->list, &hosts);
- 1236 mutex_unlock(&list_lock);
- 1237
- 1238 scan_add_host(ici);
- 1239
- 1240 return 0;
- 1241
- 1242 edevreg:
- 1243 mutex_unlock(&list_lock);
- 1244 return ret;
- 1245 }
- 1246 EXPORT_SYMBOL(soc_camera_host_register);
1231 每个camera host对应一个v4l2 device(注意不是video device),host上device对应的才是video device
1235 @host是一个全局camera host 链表
1238 scan_add_host 关联系统内属于这个host的video device
- 1135 struct bus_type soc_camera_bus_type = {
- 1136 .name = "soc-camera",
- 1137 .probe = soc_camera_probe,
- 1138 .remove = soc_camera_remove,
- 1139 .suspend = soc_camera_suspend,
- 1140 .resume = soc_camera_resume,
- 1141 };
- 1142 EXPORT_SYMBOL_GPL(soc_camera_bus_type);
soc camera总线代码,当调用device_register注册一个新设备时,会调用probe函数
- 947 static int soc_camera_probe(struct device *dev)
- 948 {
- 949 struct soc_camera_device *icd = to_soc_camera_dev(dev);
- 950 struct soc_camera_host *ici = to_soc_camera_host(dev->parent);
- 951 struct soc_camera_link *icl = to_soc_camera_link(icd);
- 952 struct device *control = NULL;
- 953 struct v4l2_subdev *sd;
- 954 struct v4l2_mbus_framefmt mf;
- 955 int ret;
- 956
- 957 dev_info(dev, "Probing %s\n", dev_name(dev));
- 958
- 959 ret = regulator_bulk_get(icd->pdev, icl->num_regulators,
- 960 icl->regulators);
- 961 if (ret < 0)
- 962 goto ereg;
- 963
- 964 ret = soc_camera_power_set(icd, icl, 1);
- 965 if (ret < 0)
- 966 goto epower;
- 967
- 968 /* The camera could have been already on, try to reset */
- 969 if (icl->reset)
- 970 icl->reset(icd->pdev);
- 971
- 972 ret = ici->ops->add(icd);
- 973 if (ret < 0)
- 974 goto eadd;
- 975
- 976 /* Must have icd->vdev before registering the device */
- 977 ret = video_dev_create(icd);
- 978 if (ret < 0)
- 979 goto evdc;
- 980
- 981 /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */
- 982 if (icl->board_info) {
- 983 ret = soc_camera_init_i2c(icd, icl);
- 984 if (ret < 0) {
- 985 goto eadddev;
- 986 }
- 987 } else if (!icl->add_device || !icl->del_device) {
- 988 ret = -EINVAL;
- 989 goto eadddev;
- 990 } else {
- 991 if (icl->module_name)
- 992 ret = request_module(icl->module_name);
- 993
- 994 ret = icl->add_device(icl, &icd->dev);
- 995 if (ret < 0)
- 996 goto eadddev;
- 997
- 998 /*
- 999 * FIXME: this is racy, have to use driver-binding notification,
- 1000 * when it is available
- 1001 */
- 1002 control = to_soc_camera_control(icd);
- 1003 if (!control || !control->driver || !dev_get_drvdata(control) ||
- 1004 !try_module_get(control->driver->owner)) {
- 1005 icl->del_device(icl);
- 1006 goto enodrv;
- 1007 }
- 1008 }
- 1009
- 1010 /* At this point client .probe() should have run already */
- 1011 ret = soc_camera_init_user_formats(icd);
- 1012 if (ret < 0)
- 1013 goto eiufmt;
- 1014
- 1015 icd->field = V4L2_FIELD_ANY;
- 1016
- 1017 icd->vdev->lock = &icd->video_lock;
- 1018
- 1019 /*
- 1020 * ..._video_start() will create a device node, video_register_device()
- 1021 * itself is protected against concurrent open() calls, but we also have
- 1022 * to protect our data.
- 1023 */
- 1024 mutex_lock(&icd->video_lock);
- 1025
- 1026 ret = soc_camera_video_start(icd);
- 1027 if (ret < 0)
- 1028 goto evidstart;
- 1029
- 1030 /* Try to improve our guess of a reasonable window format */
- 1031 sd = soc_camera_to_subdev(icd);
- 1032 if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
- 1033 icd->user_width = mf.width;
- 1034 icd->user_height = mf.height;
- 1035 icd->colorspace = mf.colorspace;
- 1036 icd->field = mf.field;
- 1037 }
- 1038
- 1039 /* Do we have to sysfs_remove_link() before device_unregister()? */
- 1040 if (sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj,
- 1041 "control"))
- 1042 dev_warn(&icd->dev, "Failed creating the control symlink\n");
- 1043
- 1044 ici->ops->remove(icd);
- 1045
- 1046 soc_camera_power_set(icd, icl, 0);
- 1047
- 1048 mutex_unlock(&icd->video_lock);
- 1049
- 1050 return 0;
- 1051
- 1052 evidstart:
- 1053 mutex_unlock(&icd->video_lock);
- 1054 soc_camera_free_user_formats(icd);
- 1055 eiufmt:
- 1056 if (icl->board_info) {
- 1057 soc_camera_free_i2c(icd);
- 1058 } else {
- 1059 icl->del_device(icl);
- 1060 module_put(control->driver->owner);
- 1061 }
- 1062 enodrv:
- 1063 eadddev:
- 1064 video_device_release(icd->vdev);
- 1065 evdc:
- 1066 ici->ops->remove(icd);
- 1067 eadd:
- 1068 soc_camera_power_set(icd, icl, 0);
- 1069 epower:
- 1070 regulator_bulk_free(icl->num_regulators, icl->regulators);
- 1071 ereg:
- 1072 return ret;
- 1073 }
在host-driver probe函数中调用,soc_camera_host_register ==> scan_add_host ==> device_register ==> bus_probe_device ==> soc_camera_probe
972 调用camera host驱动的add函数,比如pxa平台的pxa_camera_add_device
977 在调用video_device_register之前,要先创建video_device
982~1008 如果是i2c camera,那么调用soc_camera_init_i2c来初始华i2c,否则就调用add_device增加设备。 soc_camera_init_i2c会调用到芯片驱动i2c_driver.probe,对于我们的项目,则是adv7180_probe
1010~1013 初始化client format,调用soc_camera_init_user_format之前,已经执行了芯片的probe函数,已经可以对芯片进一步的操作。
1026 调用soc_camera_video_start注册一个video device
1031 每一个soc camera device都一一对应一个v4l2 subdev
1044 ~ 1046 已经获取了soc camera device必要的信息后,调用remove_device关闭soc camera device,然后调用soc_camera_power_set关闭soc camera device的电源。
- 869 /* So far this function cannot fail */
- 870 static void scan_add_host(struct soc_camera_host *ici)
- 871 {
- 872 struct soc_camera_device *icd;
- 873
- 874 mutex_lock(&list_lock);
- 875
- 876 list_for_each_entry(icd, &devices, list) {
- 877 if (icd->iface == ici->nr) {
- 878 int ret;
- 879 icd->dev.parent = ici->v4l2_dev.dev;
- 880 dev_set_name(&icd->dev, "%u-%u", icd->iface,
- 881 icd->devnum);
- 882 ret = device_register(&icd->dev);
- 883 if (ret < 0) {
- 884 icd->dev.parent = NULL;
- 885 dev_err(&icd->dev,
- 886 "Cannot register device: %d\n", ret);
- 887 }
- 888 }
- 889 }
- 890
- 891 mutex_unlock(&list_lock);
- 892 }
这个函数只被soc_camera_host_register调用。扫描系统所有的camera device,把属于这个camera host(参数@ici指定)的所有camera device注册到系统中。
876 系统所有的camera device,在没有被camera host注册前,这些camera device仅保存在@devices链表中
877 比较camera device的host number是否等于这个camera host
882 device_register 注册一个设备到系统中,这个函数会调用bus_probe_device,而bus_probe_device则会调用 soc_camera_bus_type.probe,也就是soc_camera_probe。这样soc_camera_host_register 就会注册所有属于这个host的camera device到系统中,并且创建了相应的设备节点/dev/videoX,整个设备的注册过程全部结束了,从现在开始,可以在设备节点/dev /videoX上调用open read write ioctl以及poll。
- 178 static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
- 179 {
- 180 int ret;
- 181 struct soc_camera_device *icd = file->private_data;
- 182 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- 183
- 184 /* call s_routing to select the input of camera sensor */
- 185 ret = v4l2_subdev_call(sd, video, s_routing, i, 0, 0);
- 186
- 187 return ret;
- 188 }
185 soc_camera驱动并没有实现这句话,而是直接 return 0,这就导致当前的soc camera子系统不支持S_INPUT接口。
- 384 static int soc_camera_open(struct file *file)
- 385 {
- 386 struct video_device *vdev = video_devdata(file);
- 387 struct soc_camera_device *icd = container_of(vdev->parent,
- 388 struct soc_camera_device,
- 389 dev);
- 390 struct soc_camera_link *icl = to_soc_camera_link(icd);
- 391 struct soc_camera_host *ici;
- 392 int ret;
- 393
- 394 if (!icd->ops)
- 395 /* No device driver attached */
- 396 return -ENODEV;
- 397
- 398 ici = to_soc_camera_host(icd->dev.parent);
- 399
- 400 if (!try_module_get(ici->ops->owner)) {
- 401 dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
- 402 return -EINVAL;
- 403 }
- 404
- 405 icd->use_count++;
- 406
- 407 /* Now we really have to activate the camera */
- 408 if (icd->use_count == 1) {
- 409 /* Restore parameters before the last close() per V4L2 API */
- 410 struct v4l2_format f = {
- 411 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- 412 .fmt.pix = {
- 413 .width = icd->user_width,
- 414 .height = icd->user_height,
- 415 .field = icd->field,
- 416 .colorspace = icd->colorspace,
- 417 .pixelformat =
- 418 icd->current_fmt->host_fmt->fourcc,
- 419 },
- 420 };
- 421
- 422 ret = soc_camera_power_set(icd, icl, 1);
- 423 if (ret < 0)
- 424 goto epower;
- 425
- 426 /* The camera could have been already on, try to reset */
- 427 if (icl->reset)
- 428 icl->reset(icd->pdev);
- 429
- 430 ret = ici->ops->add(icd);
- 431 if (ret < 0) {
- 432 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
- 433 goto eiciadd;
- 434 }
- 435
- 436 pm_runtime_enable(&icd->vdev->dev);
- 437 ret = pm_runtime_resume(&icd->vdev->dev);
- 438 if (ret < 0 && ret != -ENOSYS)
- 439 goto eresume;
- 440
- 441 /*
- 442 * Try to configure with default parameters. Notice: this is the
- 443 * very first open, so, we cannot race against other calls,
- 444 * apart from someone else calling open() simultaneously, but
- 445 * .video_lock is protecting us against it.
- 446 */
- 447 ret = soc_camera_set_fmt(icd, &f);
- 448 if (ret < 0)
- 449 goto esfmt;
- 450
- 451 ici->ops->init_videobuf(&icd->vb_vidq, icd);
- 452 }
- 453
- 454 file->private_data = icd;
- 455 dev_dbg(&icd->dev, "camera device open\n");
- 456
- 457 return 0;
- 458
- 459 /*
- 460 * First four errors are entered with the .video_lock held
- 461 * and use_count == 1
- 462 */
- 463 esfmt:
- 464 pm_runtime_disable(&icd->vdev->dev);
- 465 eresume:
- 466 ici->ops->remove(icd);
- 467 eiciadd:
- 468 soc_camera_power_set(icd, icl, 0);
- 469 epower:
- 470 icd->use_count--;
- 471 module_put(ici->ops->owner);
- 472
- 473 return ret;
- 474 }
当应用通过open系统调用,打开设备节点/dev/videoX时,会调用soc_camera_open
430 ici->ops->add 不仅要执行host内部的初始化,还会调用camera sensor(参数icd指定)的init
447 配置camera sensor缺省的格式参数,从我个人理解,一切合理的fmt都应该在调用S_INPUT之后进行设置。当然,这需要应用程序编程时先调用S_INPUT再进行S_FMT。
405~408 仅在第一次打开时,才对camera host和camera sensor做初始化操作,否则,仅仅增加引用计数。