您的位置:首页 > 其它

v4L2 soc-camera 分析 - soc_camera.c

2013-04-11 14:08 459 查看
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做初始化操作,否则,仅仅增加引用计数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: