九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 3446|回复: 1
打印 上一主题 下一主题

v4L2 soc-camera 分析 - soc_camera.c

[复制链接]
跳转到指定楼层
楼主
发表于 2014-7-10 09:24:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
soc_camera.c

[cpp] view plaincopy

  • 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。这些平台设备可如下定义:
[cpp] view plaincopy

  • 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
[cpp] view plaincopy

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

[cpp] view plaincopy

  • 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函数
[cpp] view plaincopy

  • 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

[cpp] view plaincopy

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

[cpp] view plaincopy

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

  • 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 };  


[cpp] view plaincopy

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

[cpp] view plaincopy

  • 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这个循环
[cpp] view plaincopy

  • 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

[cpp] view plaincopy

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


[cpp] view plaincopy

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

[cpp] view plaincopy

  • 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。
[cpp] view plaincopy

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

[cpp] view plaincopy

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

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-11-23 16:55 , Processed in 0.020599 second(s), 17 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表