v4L2 soc-camera 分析 - soc_camera.c

本文详细解析了SOC Camera的驱动实现原理,包括平台设备的注册与探查流程、视频设备的创建与注册过程、关键函数的作用及调用路径等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2020 MediaTek Inc. */ #include <dt-bindings/clock/mt6878-clk.h> // #include "mediatek/chrome_regulator_wl2866d.dtsi" &seninf_top { seninf_csi_port_0: seninf-csi-port-0 { compatible = "mediatek,seninf"; csi-port = "0"; #if 0 nvmem-cells = <&csi_efuse0>; nvmem-cell-names = "rg_csi"; #endif port { seninf_csi_port_0_in: endpoint { remote-endpoint = <&sensor0_out>; }; }; }; seninf_csi_port_1: seninf-csi-port-1 { compatible = "mediatek,seninf"; csi-port = "1"; #if 0 nvmem-cells = <&csi_efuse1>; nvmem-cell-names = "rg_csi"; #endif port { seninf_csi_port_1_in: endpoint { remote-endpoint = <&sensor1_out>; }; }; }; seninf_csi_port_3: seninf-csi-port-3 { compatible = "mediatek,seninf"; csi-port = "3"; #if 0 nvmem-cells = <&csi_efuse3>; nvmem-cell-names = "rg_csi"; #endif port { seninf_csi_port_3_in: endpoint { remote-endpoint = <&sensor2_out>; }; }; }; }; /* CAMERA GPIO standardization */ &pio { camera_pins_cam0_mclk_off: camera-pins-cam0-mclk-off { pins-cmd-dat { pinmux = <PINMUX_GPIO94__FUNC_GPIO94>; drive-strength = <1>; }; }; camera_pins_cam0_mclk_2ma: camera-pins-cam0-mclk-2ma { pins-cmd-dat { pinmux = <PINMUX_GPIO94__FUNC_CMMCLK2>; drive-strength = <0>; }; }; camera_pins_cam0_mclk_4ma: camera-pins-cam0-mclk-4ma { pins-cmd-dat { pinmux = <PINMUX_GPIO94__FUNC_CMMCLK2>; drive-strength = <1>; }; }; camera_pins_cam0_mclk_6ma: camera-pins-cam0-mclk-6ma { pins-cmd-dat { pinmux = <PINMUX_GPIO94__FUNC_CMMCLK2>; drive-strength = <2>; }; }; camera_pins_cam0_mclk_8ma: camera-pins-cam0-mclk-8ma { pins-cmd-dat { pinmux = <PINMUX_GPIO94__FUNC_CMMCLK2>; drive-strength = <3>; }; }; camera_pins_cam0_rst_0: cam0@0 { pins-cmd-dat { pinmux = <PINMUX_GPIO25__FUNC_GPIO25>; slew-rate = <1>; output-low; }; }; camera_pins_cam0_rst_1: cam0@1 { pins-cmd-dat { pinmux = <PINMUX_GPIO25__FUNC_GPIO25>; slew-rate = <1>; output-high; }; }; camera_pins_cam0_avdd_0: cam0@2 { pins-cmd-dat { pinmux = <PINMUX_GPIO4__FUNC_GPIO4>; slew-rate = <1>; output-low; }; }; camera_pins_cam0_avdd_1: cam0@3 { pins-cmd-dat { pinmux = <PINMUX_GPIO4__FUNC_GPIO4>; slew-rate = <1>; output-high; }; }; camera_pins_cam0_dvdd_0: cam0@4 { pins-cmd-dat { pinmux = <PINMUX_GPIO42__FUNC_GPIO42>; slew-rate = <1>; output-low; }; }; camera_pins_cam0_dvdd_1: cam0@5 { pins-cmd-dat { pinmux = <PINMUX_GPIO42__FUNC_GPIO42>; slew-rate = <1>; output-high; }; }; camera_pins_cam0_dovdd_0: cam0@6 { pins-cmd-dat { pinmux = <PINMUX_GPIO193__FUNC_GPIO193>; slew-rate = <1>; output-low; }; }; camera_pins_cam0_dovdd_1: cam0@7 { pins-cmd-dat { pinmux = <PINMUX_GPIO193__FUNC_GPIO193>; slew-rate = <1>; output-high; }; }; camera_pins_cam0_afvdd_0: cam0@8 { pins-cmd-dat { pinmux = <PINMUX_GPIO22__FUNC_GPIO22>; slew-rate = <1>; output-low; }; }; camera_pins_cam0_afvdd_1: cam0@9 { pins-cmd-dat { pinmux = <PINMUX_GPIO22__FUNC_GPIO22>; slew-rate = <1>; output-high; }; }; camera_pins_cam1_mclk_off: camera-pins-cam1-mclk-off { pins-cmd-dat { pinmux = <PINMUX_GPIO96__FUNC_GPIO96>; drive-strength = <1>; }; }; camera_pins_cam1_mclk_2ma: camera-pins-cam1-mclk-2ma { pins-cmd-dat { pinmux = <PINMUX_GPIO96__FUNC_CMMCLK4>; drive-strength = <0>; }; }; camera_pins_cam1_mclk_4ma: camera-pins-cam1-mclk-4ma { pins-cmd-dat { pinmux = <PINMUX_GPIO96__FUNC_CMMCLK4>; drive-strength = <1>; }; }; camera_pins_cam1_mclk_6ma: camera-pins-cam1-mclk-6ma { pins-cmd-dat { pinmux = <PINMUX_GPIO96__FUNC_CMMCLK4>; drive-strength = <2>; }; }; camera_pins_cam1_mclk_8ma: camera-pins-cam1-mclk-8ma { pins-cmd-dat { pinmux = <PINMUX_GPIO96__FUNC_CMMCLK4>; drive-strength = <3>; }; }; camera_pins_cam1_rst_0: cam1@0 { pins-cmd-dat { pinmux = <PINMUX_GPIO28__FUNC_GPIO28>; slew-rate = <1>; output-low; }; }; camera_pins_cam1_rst_1: cam1@1 { pins-cmd-dat { pinmux = <PINMUX_GPIO28__FUNC_GPIO28>; slew-rate = <1>; output-high; }; }; camera_pins_cam1_dvdd_0: cam1@2 { pins-cmd-dat { pinmux = <PINMUX_GPIO23__FUNC_GPIO23>; slew-rate = <1>; output-low; }; }; camera_pins_cam1_dvdd_1: cam1@3 { pins-cmd-dat { pinmux = <PINMUX_GPIO23__FUNC_GPIO23>; slew-rate = <1>; output-high; }; }; camera_pins_cam1_avdd_0: cam1@4 { pins-cmd-dat { pinmux = <PINMUX_GPIO29__FUNC_GPIO29>; slew-rate = <1>; output-low; }; }; camera_pins_cam1_avdd_1: cam1@5 { pins-cmd-dat { pinmux = <PINMUX_GPIO29__FUNC_GPIO29>; slew-rate = <1>; output-high; }; }; camera_pins_cam1_dovdd_0: cam1@6 { pins-cmd-dat { pinmux = <PINMUX_GPIO193__FUNC_GPIO193>; slew-rate = <1>; output-low; }; }; camera_pins_cam1_dovdd_1: cam1@7 { pins-cmd-dat { pinmux = <PINMUX_GPIO193__FUNC_GPIO193>; slew-rate = <1>; output-high; }; }; camera_pins_default: camdefault { }; }; /* CAMERA GPIO end */ &mtk_composite_v4l2_2 { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; main_af_endpoint: endpoint { remote-endpoint = <&main_af>; }; }; }; &i2c8 { status = "okay"; clock-frequency = <1000000>; sensor0: sensor0@20 { compatible = "mediatek,imgsensor"; sensor-names = "chromemain_mipi_raw"; reg = <0x20>; #reindex-to = <0>; #cust-aov-csi-clk = <312>; #thermal-sensor-cells = <0>; pinctrl-names = "mclk_off", "mclk_2mA", "mclk_4mA", "mclk_6mA", "mclk_8mA", "rst_low", "rst_high", "avdd_off", "avdd_on", "dvdd_off", "dvdd_on", "dovdd_off", "dovdd_on", "afvdd_off", "afvdd_on", "pdn_low", "pdn_high"; pinctrl-0 = <&camera_pins_cam0_mclk_off>; pinctrl-1 = <&camera_pins_cam0_mclk_2ma>; pinctrl-2 = <&camera_pins_cam0_mclk_4ma>; pinctrl-3 = <&camera_pins_cam0_mclk_6ma>; pinctrl-4 = <&camera_pins_cam0_mclk_8ma>; pinctrl-5 = <&camera_pins_cam0_rst_0>; pinctrl-6 = <&camera_pins_cam0_rst_1>; pinctrl-7 = <&camera_pins_cam0_avdd_0>; pinctrl-8 = <&camera_pins_cam0_avdd_1>; pinctrl-9 = <&camera_pins_cam0_dvdd_0>; pinctrl-10 = <&camera_pins_cam0_dvdd_1>; pinctrl-11 = <&camera_pins_cam0_dovdd_0>; pinctrl-12 = <&camera_pins_cam0_dovdd_1>; pinctrl-13 = <&camera_pins_cam0_afvdd_0>; pinctrl-14 = <&camera_pins_cam0_afvdd_1>; clocks = <&topckgen_clk CLK_TOP_UVPLL192M_D32>, <&topckgen_clk CLK_TOP_UVPLL192M_D16>, <&topckgen_clk CLK_TOP_OSC_D20>, <&topckgen_clk CLK_TOP_UVPLL192M_D10>, <&topckgen_clk CLK_TOP_UVPLL192M_D8>, <&topckgen_clk CLK_TOP_TCK_26M_MX9>, <&topckgen_clk CLK_TOP_UNIVPLL_D6_D8>, <&topckgen_clk CLK_TOP_CAMTG5_SEL>; clock-names = "6", "12", "13", "19.2", "24", "26", "52", "mclk"; status = "okay"; port { sensor0_out: endpoint { remote-endpoint = <&seninf_csi_port_1_in>; }; }; }; camera_af_main@0c { compatible = "oplus,dw9800s_24678"; reg = <0x0c>; pinctrl-0 = <&camera_pins_cam0_afvdd_0>; pinctrl-1 = <&camera_pins_cam0_afvdd_1>; port { main_af: endpoint { remote-endpoint = <&main_af_endpoint>; }; }; }; mtk_camera_eeprom1:camera-eeprom1@54 { compatible = "mediatek,camera_eeprom"; reg = <0x54>; status = "okay"; }; }; &i2c2 { status = "okay"; clock-frequency = <1000000>; sensor1: sensor1@6c { compatible = "mediatek,imgsensor"; sensor-names = "chromefront_mipi_raw"; reg = <0x6c>; #thermal-sensor-cells = <0>; pinctrl-names = "mclk_off", "mclk_2mA", "mclk_4mA", "mclk_6mA", "mclk_8mA", "rst_low", "rst_high", "avdd_off", "avdd_on", "dvdd_off", "dvdd_on", "dovdd_off", "dovdd_on", "pdn_low", "pdn_high"; pinctrl-0 = <&camera_pins_cam1_mclk_off>; pinctrl-1 = <&camera_pins_cam1_mclk_2ma>; pinctrl-2 = <&camera_pins_cam1_mclk_4ma>; pinctrl-3 = <&camera_pins_cam1_mclk_6ma>; pinctrl-4 = <&camera_pins_cam1_mclk_8ma>; pinctrl-5 = <&camera_pins_cam1_rst_0>; pinctrl-6 = <&camera_pins_cam1_rst_1>; pinctrl-7 = <&camera_pins_cam1_avdd_0>; pinctrl-8 = <&camera_pins_cam1_avdd_1>; pinctrl-9 = <&camera_pins_cam1_dvdd_0>; pinctrl-10 = <&camera_pins_cam1_dvdd_1>; pinctrl-11 = <&camera_pins_cam1_dovdd_0>; pinctrl-12 = <&camera_pins_cam1_dovdd_1>; clocks = <&topckgen_clk CLK_TOP_UVPLL192M_D32>, <&topckgen_clk CLK_TOP_UVPLL192M_D16>, <&topckgen_clk CLK_TOP_OSC_D20>, <&topckgen_clk CLK_TOP_UVPLL192M_D10>, <&topckgen_clk CLK_TOP_UVPLL192M_D8>, <&topckgen_clk CLK_TOP_TCK_26M_MX9>, <&topckgen_clk CLK_TOP_UNIVPLL_D6_D8>, <&topckgen_clk CLK_TOP_CAMTG3_SEL>; clock-names = "6", "12", "13", "19.2", "24", "26", "52", "mclk"; status = "okay"; port { sensor1_out: endpoint { remote-endpoint = <&seninf_csi_port_0_in>; }; }; }; mtk_camera_eeprom0:camera-eeprom0@50 { compatible = "mediatek,camera_eeprom"; reg = <0x50>; status = "okay"; }; }; &i2c3 { clock-frequency = <400000>; #address-cells = <1>; #size-cells = <0>; aw36410:aw36410@63 { compatible = "oplus,aw36410_chrome"; #address-cells = <1>; #size-cells = <0>; reg = <0x63>; #cooling-cells = <2>; pinctrl-names = "default", "hwen-high", "hwen-low"; pinctrl-0 = <&aw36410_pins_default>; pinctrl-1 = <&aw36410_pins_hwen_high>; pinctrl-2 = <&aw36410_pins_hwen_low>; status = "okay"; flash@0{ reg = <0>; type = <0>; ct = <0>; part = <0>; port { fl_core_0: endpoint { remote-endpoint = <&flashlight_0>; }; }; }; }; }; &pio { aw36410_pins_default: default { }; aw36410_pins_hwen_high: hwen-high { pins_cmd_dat { pinmux = <PINMUX_GPIO1__FUNC_GPIO1>;// nobody use,just test slew-rate = <1>; output-high; }; }; aw36410_pins_hwen_low: hwen-low { pins_cmd_dat { pinmux = <PINMUX_GPIO1__FUNC_GPIO1>; slew-rate = <1>; output-low; }; }; }; &mtk_composite_v4l2_1 { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; flashlight_0: endpoint { remote-endpoint = <&fl_core_0>; }; }; };分析下这个文件的这个编译问题 DTC ../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/oplus6878_25683.dtb /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:6.40-18.5: ERROR (duplicate_label): /fragment@69/__overlay__/seninf-csi-port-1: Duplicate label 'seninf_csi_port_1' on /fragment@69/__overlay__/seninf-csi-port-1 and /fragment@3/__overlay__/seninf-csi-port-1 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:14.36-16.7: ERROR (duplicate_label): /fragment@69/__overlay__/seninf-csi-port-1/port/endpoint: Duplicate label 'seninf_csi_port_1_in' on /fragment@69/__overlay__/seninf-csi-port-1/port/endpoint and /fragment@3/__overlay__/seninf-csi-port-1/port/endpoint /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:34.40-46.5: ERROR (duplicate_label): /fragment@69/__overlay__/seninf-csi-port-3: Duplicate label 'seninf_csi_port_3' on /fragment@69/__overlay__/seninf-csi-port-3 and /fragment@3/__overlay__/seninf-csi-port-3 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:42.36-44.7: ERROR (duplicate_label): /fragment@69/__overlay__/seninf-csi-port-3/port/endpoint: Duplicate label 'seninf_csi_port_3_in' on /fragment@69/__overlay__/seninf-csi-port-3/port/endpoint and /fragment@3/__overlay__/seninf-csi-port-3/port/endpoint /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:51.55-56.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam0-mclk-off: Duplicate label 'camera_pins_cam0_mclk_off' on /fragment@70/__overlay__/camera-pins-cam0-mclk-off and /fragment@4/__overlay__/camera-pins-cam0-mclk-off /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:57.55-62.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam0-mclk-2ma: Duplicate label 'camera_pins_cam0_mclk_2ma' on /fragment@70/__overlay__/camera-pins-cam0-mclk-2ma and /fragment@4/__overlay__/camera-pins-cam0-mclk-2ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:63.55-68.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam0-mclk-4ma: Duplicate label 'camera_pins_cam0_mclk_4ma' on /fragment@70/__overlay__/camera-pins-cam0-mclk-4ma and /fragment@4/__overlay__/camera-pins-cam0-mclk-4ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:69.55-74.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam0-mclk-6ma: Duplicate label 'camera_pins_cam0_mclk_6ma' on /fragment@70/__overlay__/camera-pins-cam0-mclk-6ma and /fragment@4/__overlay__/camera-pins-cam0-mclk-6ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:75.55-80.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam0-mclk-8ma: Duplicate label 'camera_pins_cam0_mclk_8ma' on /fragment@70/__overlay__/camera-pins-cam0-mclk-8ma and /fragment@4/__overlay__/camera-pins-cam0-mclk-8ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:81.33-87.4: ERROR (duplicate_label): /fragment@70/__overlay__/cam0@0: Duplicate label 'camera_pins_cam0_rst_0' on /fragment@70/__overlay__/cam0@0 and /fragment@4/__overlay__/cam0@0 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:88.33-94.4: ERROR (duplicate_label): /fragment@70/__overlay__/cam0@1: Duplicate label 'camera_pins_cam0_rst_1' on /fragment@70/__overlay__/cam0@1 and /fragment@4/__overlay__/cam0@1 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:109.55-114.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam1-mclk-off: Duplicate label 'camera_pins_cam1_mclk_off' on /fragment@70/__overlay__/camera-pins-cam1-mclk-off and /fragment@4/__overlay__/camera-pins-cam1-mclk-off /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:115.55-120.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam1-mclk-2ma: Duplicate label 'camera_pins_cam1_mclk_2ma' on /fragment@70/__overlay__/camera-pins-cam1-mclk-2ma and /fragment@4/__overlay__/camera-pins-cam1-mclk-2ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:121.55-126.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam1-mclk-4ma: Duplicate label 'camera_pins_cam1_mclk_4ma' on /fragment@70/__overlay__/camera-pins-cam1-mclk-4ma and /fragment@4/__overlay__/camera-pins-cam1-mclk-4ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:127.55-132.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam1-mclk-6ma: Duplicate label 'camera_pins_cam1_mclk_6ma' on /fragment@70/__overlay__/camera-pins-cam1-mclk-6ma and /fragment@4/__overlay__/camera-pins-cam1-mclk-6ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:133.55-138.4: ERROR (duplicate_label): /fragment@70/__overlay__/camera-pins-cam1-mclk-8ma: Duplicate label 'camera_pins_cam1_mclk_8ma' on /fragment@70/__overlay__/camera-pins-cam1-mclk-8ma and /fragment@4/__overlay__/camera-pins-cam1-mclk-8ma /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:139.33-145.4: ERROR (duplicate_label): /fragment@70/__overlay__/cam1@0: Duplicate label 'camera_pins_cam1_rst_0' on /fragment@70/__overlay__/cam1@0 and /fragment@4/__overlay__/cam1@0 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:146.33-152.4: ERROR (duplicate_label): /fragment@70/__overlay__/cam1@1: Duplicate label 'camera_pins_cam1_rst_1' on /fragment@70/__overlay__/cam1@1 and /fragment@4/__overlay__/cam1@1 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:225.34-226.4: ERROR (duplicate_label): /fragment@70/__overlay__/camdefault: Duplicate label 'camera_pins_default' on /fragment@70/__overlay__/camdefault and /fragment@4/__overlay__/camdefault /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:252.30-254.5: ERROR (duplicate_label): /fragment@72/__overlay__/port@0/endpoint: Duplicate label 'main_af_endpoint' on /fragment@72/__overlay__/port@0/endpoint and /fragment@5/__overlay__/port@0/endpoint /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:268.22-317.4: ERROR (duplicate_label): /fragment@73/__overlay__/sensor1@10: Duplicate label 'sensor1' on /fragment@73/__overlay__/sensor1@10 and /fragment@7/__overlay__/sensor1@6c /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:313.26-315.6: ERROR (duplicate_label): /fragment@73/__overlay__/sensor1@10/port/endpoint: Duplicate label 'sensor1_out' on /fragment@73/__overlay__/sensor1@10/port/endpoint and /fragment@7/__overlay__/sensor1@6c/port/endpoint /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:318.42-322.4: ERROR (duplicate_label): /fragment@73/__overlay__/camera-eeprom1@54: Duplicate label 'mtk_camera_eeprom1' on /fragment@73/__overlay__/camera-eeprom1@54 and /fragment@6/__overlay__/camera-eeprom1@54 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:391.22-393.6: ERROR (duplicate_label): /fragment@74/__overlay__/camera_af_main@0c/port/endpoint: Duplicate label 'main_af' on /fragment@74/__overlay__/camera_af_main@0c/port/endpoint and /fragment@6/__overlay__/camera_af_main@0c/port/endpoint /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:406.22-455.4: ERROR (duplicate_label): /fragment@74/__overlay__/sensor0@1a: Duplicate label 'sensor0' on /fragment@74/__overlay__/sensor0@1a and /fragment@6/__overlay__/sensor0@20 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:451.26-453.6: ERROR (duplicate_label): /fragment@74/__overlay__/sensor0@1a/port/endpoint: Duplicate label 'sensor0_out' on /fragment@74/__overlay__/sensor0@1a/port/endpoint and /fragment@6/__overlay__/sensor0@20/port/endpoint /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:457.39-461.4: ERROR (duplicate_label): /fragment@74/__overlay__/camera-eeprom0@50: Duplicate label 'mtk_camera_eeprom0' on /fragment@74/__overlay__/camera-eeprom0@50 and /fragment@7/__overlay__/camera-eeprom0@50 /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:485.25-487.7: ERROR (duplicate_label): /fragment@75/__overlay__/aw36515_2led@63/flash@0/port/endpoint: Duplicate label 'fl_core_0' on /fragment@75/__overlay__/aw36515_2led@63/flash@0/port/endpoint and /fragment@8/__overlay__/aw36410@63/flash@0/port/endpoint /work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/cust_mt6878_casioy_camera_v4l2.dtsi:530.26-532.5: ERROR (duplicate_label): /fragment@77/__overlay__/port@0/endpoint: Duplicate label 'flashlight_0' on /fragment@77/__overlay__/port@0/endpoint and /fragment@10/__overlay__/port@0/endpoint ERROR: Input tree has errors, aborting (use -f to force output) make[3]: *** [/work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/scripts/Makefile.lib:422: ../kernel/kernel_device_modules-6.1/arch/arm64/boot/dts/mediatek/oplus6878_25683.dtb] Error 2 make[2]: *** [/work/oppo_V45875948/0623_20/source/vnd/kernel-6.1/Makefile:1524: oplus6878_25683.dtb] Error 2
最新发布
06-26
<think>我们正在解决设备树(DeviceTree)编译中出现的“Duplicatelabel”错误。根据引用内容,重复符号(duplicatesymbols)错误通常是因为重复定义了相同的标识符。在设备树中,这表现为标签(label)被重复使用。设备树标签用于引用节点,如果多个节点使用了相同的标签,就会导致重复标签错误。错误信息中提到的标签如`seninf_csi_port_1`、`sensor0`、`camera_pins`等,表明这些标签在设备树中被定义了多次。解决此问题的方法如下:1.**定位重复标签**:在设备树源文件(.dts或.dtsi)中搜索错误信息中提到的标签(例如`seninf_csi_port_1`、`sensor0`、`camera_pins`),找到所有定义这些标签的位置。2.**确保标签唯一性**:每个标签在整个设备树中必须是唯一的。因此,需要修改重复的标签,使其唯一。可以通过重命名其中一个标签来解决。3.**检查包含的文件**:设备树可能包含多个.dtsi文件。如果重复标签出现在不同的包含文件中,需要协调这些文件中的标签定义。可以修改其中一个文件中的标签,或者在不影响引用的情况下删除其中一个标签(如果不需要通过标签引用该节点)。4.**更新引用**:修改标签后,需要更新所有引用该标签的地方。设备树中引用标签的语法为`&label`,因此需要将相应的引用改为新的标签名。示例:假设在设备树中两处使用了标签`sensor0`:```sensor0:sensor@0{...};```在另一处:```sensor0:another-sensor@1{...};```需要将其中一个重命名,例如改为`sensor1`,并将所有引用`&sensor0`的地方(如果是指第二个节点)改为`&sensor1`。5.**重新编译**:修改后重新编译设备树,确保错误已解决。注意:在修改标签时,要确保不破坏设备树的结构和功能。通常,标签用于引用节点,尤其是在覆盖层(overlay)中。因此,修改标签名后,必须同步修改所有引用点。另外,根据引用[1]中的提示,重复符号错误也可能是因为将源文件(如.cpp)当作头文件包含进来。虽然设备树不是C++,但原理类似:避免多次包含同一个定义。在设备树中,这通常表现为多个节点使用同一标签。引用[2][3]提到Android中的权限重复问题,这与设备树标签重复问题不同,但原理相似:唯一性要求。因此,解决思路都是确保标识符的唯一性。**步骤总结**:1.搜索整个项目(包括所有.dts和.dtsi文件)中出现的重复标签。2.为重复的标签重新命名,确保每个标签只出现一次。3.更新所有引用这些标签的地方。4.重新编译并验证。如果重复标签出现在不同的设备树文件中(例如,一个在基文件,一个在覆盖层),需要评估哪个标签是需要的,或者是否可以通过调整文件包含结构来避免重复。相关问题:1.如何防止设备树中的标签重复?2.设备树标签的作用是什么?3.设备树编译中还有哪些常见错误?</think>### 解决设备树编译中的Duplicate Label错误 在设备树(Device Tree)编译过程中出现`Duplicate label`错误(如`seninf_csi_port_1`、`sensor0`、`camera_pins`等),通常是由于多个节点使用了相同的标签名称导致的。设备树标签(Label)本质上是节点的全局唯一标识符,必须保持唯一性。以下是系统性的解决方法: #### 错误原因分析 1. **标签重复定义** 同一设备树文件(`.dts/.dtsi`)或多个包含文件中定义了相同标签: ```dts // 文件A.dtsi seninf_csi_port_1: port@1 { ... }; // 文件B.dtsi seninf_csi_port_1: port@2 { ... }; // 重复标签! ``` 2. **包含文件冲突** 不同`.dtsi`文件包含相同标签(如多个摄像头驱动模块定义了`sensor0`)。 3. **标签作用域问题** 设备树标签是全局的,即使定义在不同文件中也会冲突[^1]。 #### 解决步骤 1. **定位重复标签** 在编译错误日志中定位重复标签名称(如示例中的`seninf_csi_port_1`)。 2. **搜索全局标签定义** 在项目所有设备树文件(`.dts`、`.dtsi`)中搜索该标签: ```bash grep -r "seninf_csi_port_1:" path/to/dts_files/ ``` 3. **修改冲突标签** 为重复标签添加硬件相关前缀或序号保持唯一性: ```diff // 修改前 - seninf_csi_port_1: port@1 {...}; // 修改后 + cam1_seninf_csi_port: port@1 {...}; // 添加硬件标识前缀 ``` 4. **更新标签引用** 同步修改所有引用该标签的地方(引用语法为`&label`): ```diff // 修改前 - &seninf_csi_port_1 // 修改后 + &cam1_seninf_csi_port ``` 5. **验证编译** 重新编译设备树: ```bash make dtbs ``` #### 预防措施 1. **命名规范** 采用`<硬件模块>_<功能>_<序号>`的命名规则(如`imx586_sensor_mipi0`)。 2. **模块化设计** 在`.dtsi`文件中使用宏定义避免冲突: ```dts #define CAMERA_LABEL(name) name##_sensor CAMERA_LABEL(imx586): camera@0 { ... }; ``` 3. **作用域控制** 非必要不定义标签,直接通过节点路径引用(如`/soc/camera`)。 #### 典型错误示例 ```log Error: duplicate label 'sensor0' at ./cam_v1.dtsi:10 and ./cam_v2.dtsi:15 ``` 说明两个摄像头驱动文件都定义了`sensor0`标签,需重命名为`cam0_sensor`和`cam1_sensor`。 > **关键原则**:设备树标签是全局符号表的一部分,其唯一性要求与编程中的函数命名类似[^1]。通过合理的命名规范和模块化设计可彻底避免此类问题。 --- ### 相关问题 1. 如何调试设备树中的语法错误? 2. 设备树覆盖层(Overlay)如何避免标签冲突? 3. 设备树编译错误与内核配置有何关联? 4. 如何验证修改后的设备树是否正确应用到硬件? [^1]: 设备树标签在编译时会被加入全局符号表,重复定义会导致符号冲突。 [^2]: Android系统对权限唯一性的要求与设备树标签冲突原理相似,均涉及全局标识符管理。 [^3]: 错误信息明确指向冲突的标签名和位置,是诊断的关键依据。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值