v4L2 soc-camera 分析 - soc_camera.c

soc_camera.c

[cpp]  view plain copy
  1. 1455 static struct platform_driver __refdata soc_camera_pdrv = {  
  2. 1456     .remove  = __devexit_p(soc_camera_pdrv_remove),  
  3. 1457     .driver  = {  
  4. 1458         .name   = "soc-camera-pdrv",  
  5. 1459         .owner  = THIS_MODULE,  
  6. 1460     },  
  7. 1461 };  
  8. 1462   
  9. 1463 static int __init soc_camera_init(void)  
  10. 1464 {  
  11. 1465     int ret = bus_register(&soc_camera_bus_type);  
  12. 1466     if (ret)  
  13. 1467         return ret;  
  14. 1468     ret = driver_register(&ic_drv);  
  15. 1469     if (ret)  
  16. 1470         goto edrvr;  
  17. 1471   
  18. 1472     ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);  
  19. 1473     if (ret)  
  20. 1474         goto epdr;  
  21. 1475   
  22. 1476     return 0;  
  23. 1477   
  24. 1478 epdr:  
  25. 1479     driver_unregister(&ic_drv);  
  26. 1480 edrvr:  
  27. 1481     bus_unregister(&soc_camera_bus_type);  
  28. 1482     return ret;  
  29. 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。这些平台设备可如下定义:

[cpp]  view plain copy
  1. struct platform_device your_mach_cameras[] = {  
  2.     {  
  3.         .name = "soc-camera-pdrv",  
  4.         .id = 0,  
  5.         .dev = {  
  6.             .platform_data = adv7180_link,  
  7.         },  
  8.     }, {  
  9.         .name = "soc-camera-pdrv",  
  10.         .id = 1,  
  11.         .dev = {  
  12.             .platform_data = tw9912_link,  
  13.         },  
  14.     }  
  15. };  

注意,这里假定系统的camera处理模块,接了两个camera sensor, adv7180_link和tw9912_link

[cpp]  view plain copy
  1. static struct i2c_board_info decoder_i2c_adv7180 = {  
  2.     I2C_BOARD_INFO("adv7180", (0x42 >> 1)),   
  3. };    
  4. struct soc_camera_link adv7180_link = {  
  5.     .bus_id     = 0,  
  6.     .board_info = &decoder_i2c_adv7180,  
  7.     .i2c_adapter_id = 0,  
  8. };    
soc_camera_link主要用来定义i2c地址,如果sensor不是通过i2c连接到host上,那么要定义add_device和del_device函数

1465 注册一条新的总线soc-camera,这样在scan_add_host中调用device_register时,就会把这个设备挂到这个总线上。


[cpp]  view plain copy
  1. 1135 struct bus_type soc_camera_bus_type = {  
  2. 1136     .name       = "soc-camera",  
  3. 1137     .probe      = soc_camera_probe,  
  4. 1138     .remove     = soc_camera_remove,  
  5. 1139     .suspend    = soc_camera_suspend,  
  6. 1140     .resume     = soc_camera_resume,  
  7. 1141 };  
  8. 1142 EXPORT_SYMBOL_GPL(soc_camera_bus_type);  

当一个soc-camera-device设备通过device_register注册设备时,就会调用soc_camera_probe函数

[cpp]  view plain copy
  1. 1402 static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)  
  2. 1403 {  
  3. 1404     struct soc_camera_link *icl = pdev->dev.platform_data;  
  4. 1405     struct soc_camera_device *icd;  
  5. 1406     int ret;  
  6. 1407   
  7. 1408     if (!icl)  
  8. 1409         return -EINVAL;  
  9. 1410   
  10. 1411     icd = kzalloc(sizeof(*icd), GFP_KERNEL);  
  11. 1412     if (!icd)  
  12. 1413         return -ENOMEM;  
  13. 1414           
  14. 1415     icd->iface = icl->bus_id;  
  15. 1416     icd->pdev = &pdev->dev;  
  16. 1417     platform_set_drvdata(pdev, icd);  
  17. 1418       
  18. 1419     ret = soc_camera_device_register(icd);  
  19. 1420     if (ret < 0)  
  20. 1421         goto escdevreg;  
  21. 1422           
  22. 1423     soc_camera_device_init(&icd->dev, icl);  
  23. 1424       
  24. 1425     icd->user_width     = DEFAULT_WIDTH;  
  25. 1426     icd->user_height    = DEFAULT_HEIGHT;  
  26. 1427       
  27. 1428     return 0;  
  28. 1429       
  29. 1430 escdevreg:  
  30. 1431     kfree(icd);  
  31. 1432       
  32. 1433     return ret;  
  33. 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


[cpp]  view plain copy
  1. 1374 /* 
  2. 1375  * Called from soc_camera_probe() above (with .video_lock held???) 
  3. 1376  */  
  4. 1377 static int soc_camera_video_start(struct soc_camera_device *icd)  
  5. 1378 {  
  6. 1379     struct device_type *type = icd->vdev->dev.type;  
  7. 1380     int ret;  
  8. 1381   
  9. 1382     if (!icd->dev.parent)  
  10. 1383         return -ENODEV;  
  11. 1384   
  12. 1385     if (!icd->ops ||  
  13. 1386         !icd->ops->query_bus_param ||  
  14. 1387         !icd->ops->set_bus_param)  
  15. 1388         return -EINVAL;  
  16. 1389   
  17. 1390     ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1);  
  18. 1391     if (ret < 0) {  
  19. 1392         dev_err(&icd->dev, "video_register_device failed: %d\n", ret);  
  20. 1393         return ret;  
  21. 1394     }  
  22. 1395   
  23. 1396     /* Restore device type, possibly set by the subdevice driver */  
  24. 1397     icd->vdev->dev.type = type;  
  25. 1398   
  26. 1399     return 0;  
  27. 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设备节点


[cpp]  view plain copy
  1. 1352 static int video_dev_create(struct soc_camera_device *icd)  
  2. 1353 {    
  3. 1354     struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);  
  4. 1355     struct video_device *vdev = video_device_alloc();  
  5. 1356   
  6. 1357     if (!vdev)  
  7. 1358         return -ENOMEM;  
  8. 1359      
  9. 1360     strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));  
  10. 1361   
  11. 1362     vdev->parent        = &icd->dev;  
  12. 1363     vdev->current_norm  = V4L2_STD_UNKNOWN;  
  13. 1364     vdev->fops      = &soc_camera_fops;  
  14. 1365     vdev->ioctl_ops     = &soc_camera_ioctl_ops;  
  15. 1366     vdev->release       = video_device_release;  
  16. 1367     vdev->tvnorms       = V4L2_STD_UNKNOWN;  
  17. 1368   
  18. 1369     icd->vdev = vdev;  
  19. 1370   
  20. 1371     return 0;  
  21. 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后,所有可执行的操作,都是通过这两个入口进行的,下面是他们的定义。

[cpp]  view plain copy
  1. 549 static struct v4l2_file_operations soc_camera_fops = {  
  2. 550     .owner      = THIS_MODULE,  
  3. 551     .open       = soc_camera_open,  
  4. 552     .release    = soc_camera_close,  
  5. 553     .unlocked_ioctl = video_ioctl2,  
  6. 554     .read       = soc_camera_read,  
  7. 555     .mmap       = soc_camera_mmap,  
  8. 556     .poll       = soc_camera_poll,  
  9. 557 };  

[cpp]  view plain copy
  1. 1321 static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {  
  2. 1322     .vidioc_querycap     = soc_camera_querycap,  
  3. 1323     .vidioc_g_fmt_vid_cap    = soc_camera_g_fmt_vid_cap,  
  4. 1324     .vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap,  
  5. 1325     .vidioc_s_fmt_vid_cap    = soc_camera_s_fmt_vid_cap,  
  6. 1326     .vidioc_enum_input   = soc_camera_enum_input,  
  7. 1327     .vidioc_g_input      = soc_camera_g_input,  
  8. 1328     .vidioc_s_input      = soc_camera_s_input,  
  9. 1329     .vidioc_s_std        = soc_camera_s_std,  
  10. 1330     .vidioc_reqbufs      = soc_camera_reqbufs,  
  11. 1331     .vidioc_try_fmt_vid_cap  = soc_camera_try_fmt_vid_cap,  
  12. 1332     .vidioc_querybuf     = soc_camera_querybuf,  
  13. 1333     .vidioc_qbuf         = soc_camera_qbuf,  
  14. 1334     .vidioc_dqbuf        = soc_camera_dqbuf,  
  15. 1335     .vidioc_streamon     = soc_camera_streamon,  
  16. 1336     .vidioc_streamoff    = soc_camera_streamoff,  
  17. 1337     .vidioc_queryctrl    = soc_camera_queryctrl,  
  18. 1338     .vidioc_g_ctrl       = soc_camera_g_ctrl,  
  19. 1339     .vidioc_s_ctrl       = soc_camera_s_ctrl,  
  20. 1340     .vidioc_cropcap      = soc_camera_cropcap,  
  21. 1341     .vidioc_g_crop       = soc_camera_g_crop,  
  22. 1342     .vidioc_s_crop       = soc_camera_s_crop,  
  23. 1343     .vidioc_g_parm       = soc_camera_g_parm,  
  24. 1344     .vidioc_s_parm       = soc_camera_s_parm,  
  25. 1345     .vidioc_g_chip_ident     = soc_camera_g_chip_ident,  
  26. 1346 #ifdef CONFIG_VIDEO_ADV_DEBUG  
  27. 1347     .vidioc_g_register   = soc_camera_g_register,  
  28. 1348     .vidioc_s_register   = soc_camera_s_register,  
  29. 1349 #endif  
  30. 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可能没有被支持。


[cpp]  view plain copy
  1. 1281 /* Image capture device */  
  2. 1282 static int soc_camera_device_register(struct soc_camera_device *icd)  
  3. 1283 {  
  4. 1284     struct soc_camera_device *ix;  
  5. 1285     int num = -1, i;  
  6. 1286   
  7. 1287     for (i = 0; i < 256 && num < 0; i++) {  
  8. 1288         num = i;  
  9. 1289         /* Check if this index is available on this interface */  
  10. 1290         list_for_each_entry(ix, &devices, list) {  
  11. 1291             if (ix->iface == icd->iface && ix->devnum == i) {  
  12. 1292                 num = -1;  
  13. 1293                 break;  
  14. 1294             }  
  15. 1295         }  
  16. 1296     }  
  17. 1297   
  18. 1298     if (num < 0)  
  19. 1299         /* 
  20. 1300          * ok, we have 256 cameras on this host... 
  21. 1301          * man, stay reasonable... 
  22. 1302          */  
  23. 1303         return -ENOMEM;  
  24. 1304   
  25. 1305     icd->devnum     = num;  
  26. 1306     icd->use_count      = 0;  
  27. 1307     icd->host_priv      = NULL;  
  28. 1308     mutex_init(&icd->video_lock);  
  29. 1309   
  30. 1310     list_add_tail(&icd->list, &devices);  
  31. 1311   
  32. 1312     return 0;  
  33. 1313 }   

把给定的@icd加到全局soc camera device列表中

1290~1294 @devices是一个全局soc camera device列表,这段代码相当拗口,注意1293行是break 1290这个循环

[cpp]  view plain copy
  1. 1194 int soc_camera_host_register(struct soc_camera_host *ici)  
  2. 1195 {  
  3. 1196     struct soc_camera_host *ix;  
  4. 1197     int ret;  
  5. 1198   
  6. 1199     if (!ici || !ici->ops ||  
  7. 1200         !ici->ops->try_fmt ||  
  8. 1201         !ici->ops->set_fmt ||  
  9. 1202         !ici->ops->set_bus_param ||  
  10. 1203         !ici->ops->querycap ||  
  11. 1204         !ici->ops->init_videobuf ||  
  12. 1205         !ici->ops->reqbufs ||  
  13. 1206         !ici->ops->add ||  
  14. 1207         !ici->ops->remove ||  
  15. 1208         !ici->ops->poll ||  
  16. 1209         !ici->v4l2_dev.dev)  
  17. 1210         return -EINVAL;  
  18. 1211   
  19. 1212     if (!ici->ops->set_crop)  
  20. 1213         ici->ops->set_crop = default_s_crop;  
  21. 1214     if (!ici->ops->get_crop)  
  22. 1215         ici->ops->get_crop = default_g_crop;  
  23. 1216     if (!ici->ops->cropcap)  
  24. 1217         ici->ops->cropcap = default_cropcap;  
  25. 1218     if (!ici->ops->set_parm)  
  26. 1219         ici->ops->set_parm = default_s_parm;  
  27. 1220     if (!ici->ops->get_parm)  
  28. 1221         ici->ops->get_parm = default_g_parm;  
  29. 1222   
  30. 1223     mutex_lock(&list_lock);  
  31. 1224     list_for_each_entry(ix, &hosts, list) {  
  32. 1225         if (ix->nr == ici->nr) {  
  33. 1226             ret = -EBUSY;  
  34. 1227             goto edevreg;  
  35. 1228         }  
  36. 1229     }  
  37. 1230   
  38. 1231     ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev);  
  39. 1232     if (ret < 0)  
  40. 1233         goto edevreg;  
  41. 1234   
  42. 1235     list_add_tail(&ici->list, &hosts);  
  43. 1236     mutex_unlock(&list_lock);  
  44. 1237   
  45. 1238     scan_add_host(ici);  
  46. 1239   
  47. 1240     return 0;  
  48. 1241   
  49. 1242 edevreg:  
  50. 1243     mutex_unlock(&list_lock);  
  51. 1244     return ret;  
  52. 1245 }  
  53. 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


[cpp]  view plain copy
  1. 1135 struct bus_type soc_camera_bus_type = {  
  2. 1136     .name       = "soc-camera",  
  3. 1137     .probe      = soc_camera_probe,  
  4. 1138     .remove     = soc_camera_remove,  
  5. 1139     .suspend    = soc_camera_suspend,  
  6. 1140     .resume     = soc_camera_resume,  
  7. 1141 };  
  8. 1142 EXPORT_SYMBOL_GPL(soc_camera_bus_type);  

soc camera总线代码,当调用device_register注册一个新设备时,会调用probe函数

[cpp]  view plain copy
  1.  947 static int soc_camera_probe(struct device *dev)  
  2.  948 {  
  3.  949     struct soc_camera_device *icd = to_soc_camera_dev(dev);  
  4.  950     struct soc_camera_host *ici = to_soc_camera_host(dev->parent);  
  5.  951     struct soc_camera_link *icl = to_soc_camera_link(icd);  
  6.  952     struct device *control = NULL;  
  7.  953     struct v4l2_subdev *sd;  
  8.  954     struct v4l2_mbus_framefmt mf;  
  9.  955     int ret;  
  10.  956   
  11.  957     dev_info(dev, "Probing %s\n", dev_name(dev));  
  12.  958   
  13.  959     ret = regulator_bulk_get(icd->pdev, icl->num_regulators,  
  14.  960                  icl->regulators);  
  15.  961     if (ret < 0)  
  16.  962         goto ereg;  
  17.  963   
  18.  964     ret = soc_camera_power_set(icd, icl, 1);  
  19.  965     if (ret < 0)  
  20.  966         goto epower;  
  21.  967   
  22.  968     /* The camera could have been already on, try to reset */  
  23.  969     if (icl->reset)  
  24.  970         icl->reset(icd->pdev);  
  25.  971   
  26.  972     ret = ici->ops->add(icd);  
  27.  973     if (ret < 0)  
  28.  974         goto eadd;  
  29.  975   
  30.  976     /* Must have icd->vdev before registering the device */  
  31.  977     ret = video_dev_create(icd);  
  32.  978     if (ret < 0)  
  33.  979         goto evdc;  
  34.  980   
  35.  981     /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */  
  36.  982     if (icl->board_info) {  
  37.  983         ret = soc_camera_init_i2c(icd, icl);  
  38.  984         if (ret < 0) {  
  39.  985             goto eadddev;  
  40.  986         }  
  41.  987     } else if (!icl->add_device || !icl->del_device) {  
  42.  988         ret = -EINVAL;  
  43.  989         goto eadddev;  
  44.  990     } else {  
  45.  991         if (icl->module_name)  
  46.  992             ret = request_module(icl->module_name);  
  47.  993   
  48.  994         ret = icl->add_device(icl, &icd->dev);  
  49.  995         if (ret < 0)  
  50.  996             goto eadddev;  
  51.  997   
  52.  998         /* 
  53.  999          * FIXME: this is racy, have to use driver-binding notification, 
  54. 1000          * when it is available 
  55. 1001          */  
  56. 1002         control = to_soc_camera_control(icd);  
  57. 1003         if (!control || !control->driver || !dev_get_drvdata(control) ||  
  58. 1004             !try_module_get(control->driver->owner)) {  
  59. 1005             icl->del_device(icl);  
  60. 1006             goto enodrv;  
  61. 1007         }  
  62. 1008     }  
  63. 1009   
  64. 1010     /* At this point client .probe() should have run already */  
  65. 1011     ret = soc_camera_init_user_formats(icd);  
  66. 1012     if (ret < 0)  
  67. 1013         goto eiufmt;  
  68. 1014   
  69. 1015     icd->field = V4L2_FIELD_ANY;  
  70. 1016   
  71. 1017     icd->vdev->lock = &icd->video_lock;  
  72. 1018   
  73. 1019     /* 
  74. 1020      * ..._video_start() will create a device node, video_register_device() 
  75. 1021      * itself is protected against concurrent open() calls, but we also have 
  76. 1022      * to protect our data. 
  77. 1023      */  
  78. 1024     mutex_lock(&icd->video_lock);  
  79. 1025   
  80. 1026     ret = soc_camera_video_start(icd);  
  81. 1027     if (ret < 0)  
  82. 1028         goto evidstart;  
  83. 1029   
  84. 1030     /* Try to improve our guess of a reasonable window format */  
  85. 1031     sd = soc_camera_to_subdev(icd);  
  86. 1032     if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {  
  87. 1033         icd->user_width     = mf.width;  
  88. 1034         icd->user_height    = mf.height;  
  89. 1035         icd->colorspace     = mf.colorspace;  
  90. 1036         icd->field      = mf.field;  
  91. 1037     }  
  92. 1038   
  93. 1039     /* Do we have to sysfs_remove_link() before device_unregister()? */  
  94. 1040     if (sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj,  
  95. 1041                   "control"))  
  96. 1042         dev_warn(&icd->dev, "Failed creating the control symlink\n");  
  97. 1043   
  98. 1044     ici->ops->remove(icd);  
  99. 1045   
  100. 1046     soc_camera_power_set(icd, icl, 0);  
  101. 1047   
  102. 1048     mutex_unlock(&icd->video_lock);  
  103. 1049   
  104. 1050     return 0;  
  105. 1051   
  106. 1052 evidstart:  
  107. 1053     mutex_unlock(&icd->video_lock);  
  108. 1054     soc_camera_free_user_formats(icd);  
  109. 1055 eiufmt:  
  110. 1056     if (icl->board_info) {  
  111. 1057         soc_camera_free_i2c(icd);  
  112. 1058     } else {  
  113. 1059         icl->del_device(icl);  
  114. 1060         module_put(control->driver->owner);  
  115. 1061     }  
  116. 1062 enodrv:  
  117. 1063 eadddev:  
  118. 1064     video_device_release(icd->vdev);  
  119. 1065 evdc:  
  120. 1066     ici->ops->remove(icd);  
  121. 1067 eadd:  
  122. 1068     soc_camera_power_set(icd, icl, 0);  
  123. 1069 epower:  
  124. 1070     regulator_bulk_free(icl->num_regulators, icl->regulators);  
  125. 1071 ereg:  
  126. 1072     return ret;  
  127. 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的电源。


[cpp]  view plain copy
  1. 869 /* So far this function cannot fail */  
  2. 870 static void scan_add_host(struct soc_camera_host *ici)  
  3. 871 {  
  4. 872     struct soc_camera_device *icd;  
  5. 873   
  6. 874     mutex_lock(&list_lock);  
  7. 875   
  8. 876     list_for_each_entry(icd, &devices, list) {  
  9. 877         if (icd->iface == ici->nr) {  
  10. 878             int ret;  
  11. 879             icd->dev.parent = ici->v4l2_dev.dev;  
  12. 880             dev_set_name(&icd->dev, "%u-%u", icd->iface,  
  13. 881                      icd->devnum);  
  14. 882             ret = device_register(&icd->dev);  
  15. 883             if (ret < 0) {  
  16. 884                 icd->dev.parent = NULL;  
  17. 885                 dev_err(&icd->dev,  
  18. 886                     "Cannot register device: %d\n", ret);  
  19. 887             }  
  20. 888         }  
  21. 889     }  
  22. 890   
  23. 891     mutex_unlock(&list_lock);  
  24. 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。

[cpp]  view plain copy
  1. 178 static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)  
  2. 179 {  
  3. 180     int ret;  
  4. 181     struct soc_camera_device *icd = file->private_data;  
  5. 182     struct v4l2_subdev *sd = soc_camera_to_subdev(icd);  
  6. 183   
  7. 184     /* call s_routing to select the input of camera sensor */  
  8. 185     ret = v4l2_subdev_call(sd, video, s_routing, i, 0, 0);  
  9. 186   
  10. 187     return ret;  
  11. 188 }  
185 soc_camera驱动并没有实现这句话,而是直接  return 0,这就导致当前的soc camera子系统不支持S_INPUT接口。

[cpp]  view plain copy
  1. 384 static int soc_camera_open(struct file *file)  
  2.  385 {  
  3.  386     struct video_device *vdev = video_devdata(file);  
  4.  387     struct soc_camera_device *icd = container_of(vdev->parent,  
  5.  388                              struct soc_camera_device,  
  6.  389                              dev);  
  7.  390     struct soc_camera_link *icl = to_soc_camera_link(icd);  
  8.  391     struct soc_camera_host *ici;  
  9.  392     int ret;  
  10.  393   
  11.  394     if (!icd->ops)  
  12.  395         /* No device driver attached */  
  13.  396         return -ENODEV;  
  14.  397   
  15.  398     ici = to_soc_camera_host(icd->dev.parent);  
  16.  399   
  17.  400     if (!try_module_get(ici->ops->owner)) {  
  18.  401         dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");  
  19.  402         return -EINVAL;  
  20.  403     }  
  21.  404   
  22.  405     icd->use_count++;  
  23.  406   
  24.  407     /* Now we really have to activate the camera */  
  25.  408     if (icd->use_count == 1) {  
  26.  409         /* Restore parameters before the last close() per V4L2 API */  
  27.  410         struct v4l2_format f = {  
  28.  411             .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,  
  29.  412             .fmt.pix = {  
  30.  413                 .width      = icd->user_width,  
  31.  414                 .height     = icd->user_height,  
  32.  415                 .field      = icd->field,  
  33.  416                 .colorspace = icd->colorspace,  
  34.  417                 .pixelformat    =  
  35.  418                     icd->current_fmt->host_fmt->fourcc,  
  36.  419             },  
  37.  420         };  
  38.  421   
  39.  422         ret = soc_camera_power_set(icd, icl, 1);  
  40.  423         if (ret < 0)  
  41.  424             goto epower;  
  42.  425   
  43.  426         /* The camera could have been already on, try to reset */  
  44.  427         if (icl->reset)  
  45.  428             icl->reset(icd->pdev);  
  46.  429   
  47.  430         ret = ici->ops->add(icd);  
  48.  431         if (ret < 0) {  
  49.  432             dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);  
  50.  433             goto eiciadd;  
  51.  434         }  
  52.  435   
  53.  436         pm_runtime_enable(&icd->vdev->dev);  
  54.  437         ret = pm_runtime_resume(&icd->vdev->dev);  
  55.  438         if (ret < 0 && ret != -ENOSYS)  
  56.  439             goto eresume;  
  57.  440   
  58.  441         /* 
  59.  442          * Try to configure with default parameters. Notice: this is the 
  60.  443          * very first open, so, we cannot race against other calls, 
  61.  444          * apart from someone else calling open() simultaneously, but 
  62.  445          * .video_lock is protecting us against it. 
  63.  446          */  
  64.  447         ret = soc_camera_set_fmt(icd, &f);  
  65.  448         if (ret < 0)  
  66.  449             goto esfmt;  
  67.  450   
  68.  451         ici->ops->init_videobuf(&icd->vb_vidq, icd);  
  69.  452     }  
  70.  453   
  71.  454     file->private_data = icd;  
  72.  455     dev_dbg(&icd->dev, "camera device open\n");  
  73.  456   
  74.  457     return 0;  
  75.  458   
  76.  459     /* 
  77.  460      * First four errors are entered with the .video_lock held 
  78.  461      * and use_count == 1 
  79.  462      */  
  80.  463 esfmt:  
  81.  464     pm_runtime_disable(&icd->vdev->dev);  
  82.  465 eresume:  
  83.  466     ici->ops->remove(icd);  
  84.  467 eiciadd:  
  85.  468     soc_camera_power_set(icd, icl, 0);  
  86.  469 epower:  
  87.  470     icd->use_count--;  
  88.  471     module_put(ici->ops->owner);  
  89.  472   
  90.  473     return ret;  
  91.  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做初始化操作,否则,仅仅增加引用计数。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值