zoukankan      html  css  js  c++  java
  • v4L2 soccamera 分析 soc_camera.c

    soc_camera.c

    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。这些平台设备可如下定义:

    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

    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时,就会把这个设备挂到这个总线上。


    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函数

    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


    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设备节点


    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后,所有可执行的操作,都是通过这两个入口进行的,下面是他们的定义。

    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 };  
    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可能没有被支持。


    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这个循环

    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


    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函数

    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的电源。


    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。

    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接口。

    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做初始化操作,否则,仅仅增加引用计数。

  • 相关阅读:
    16-面向对象之语法(1)
    4-编辑器IDE_for_python
    3-python入门学习路线
    2-学习方法心得
    1-语法基础
    NSMutableArray基本概念
    NSArray 与字符串
    NSArray文件读写
    NSArray排序
    NSArray 遍历
  • 原文地址:https://www.cnblogs.com/wangxianzhen/p/3014408.html
Copyright © 2011-2022 走看看