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


你可能感兴趣的:(v4L2 soc-camera 分析 - soc_camera.c)