1. 以 sensor 为例在 sensor 的probe()函数中注册流程为ov5645_probe()│ ▼devm_kzalloc()// 分配ov5645结构体内存│ ▼ov5645_parse()// 通过devm_gpiod_get、devm_pinctrl_get、devm_clk_get_optional等 api 在 dts 中获取 gpio、clock、pinctrl等信息│ ▼v4l2_ctrl_handler_init()// 初始化菜单后面通过v4l2_ctrl_new_std设置饱和度、白平衡等菜单│ ▼v4l2_i2c_subdev_init()// 初始化sudev绑定core、video、pad操作函数集│ ▼media_entity_pads_init()// 把pad数组挂到sensor的entity上并初始化每个pad所属的entity和索引│ ▼ov5645_power_on()// 开启MCLK设置pwdn、reset、power给sensor上电│ ▼ov5645_read_reg()// 上电之后一般先检测能否读到chip id│ ▼v4l2_async_register_subdev()// 把自己加入到全局subdev_list中v4l2_i2c_subdev_init(sd, client, ov5645_subdev_ops)把 subdev 和 i2c 的 client 关联起来media_entity_pads_init(sd-entity, OV5645_SD_PAD_MAX_NUM, ov5645-pad)告诉entity有哪些padv4l2_async_register_subdev(sd)非常重要的函数把subdev-async_list插入到 全局subdev_list中在我的博客异步注册中有详细讲解2. 以 DMA 为例csi_dma_probe()│ ▼devm_kzalloc()│ ▼dma_set_mask_and_coherent()// 设置 dma_alloc_coherent() 所返回地址的可用范围│ ▼v4l2_device_register()// 注册 v4l2_device│ ▼media_device_init()// 初始化 Media Graph 的链表│ ▼media_device_register()// 注册media_device│ ▼media_entity_pads_init()// 告诉entity有哪些pad│ ▼video_register_device()// 注册video_device│ ▼v4l2_async_nf_init()// 初始化notifier将notifier与v4l2_device关联│ ▼v4l2_async_nf_parse_fwnode_endpoints()// 通过设备树的endpoint将上游的fwnode加入waiting_list中│ ▼v4l2_async_nf_register()// 注册notifierdma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))告诉DMA 子系统DMA 设备能使用 64 位 DMA 地址设置dma_alloc_coherent()所返回地址的可用范围v4l2_device_register(dev, csi_dma-v4l2_dev)注册v4l2_device初始化subdev管理链表看似只初始化了一个subdevs链表实际上在后面注册notifier的时候会检查有没有这个v4l2_device没有的话不会注册 subdevv4l2_device相当于根没有根这个框架就无法运作。media_device_init(csi_dma-media_dev)这个函数很简单初始化 Media Graph 的链表(entity、pad、link)等media_device_register(csi_dma-media_dev)注册media_device创建 dev/meidaX 节点用户可以查询有哪些entity/pad/link以及整条 Media Graph 拓扑;为后续注册video_device时其内部会调用media_device_register_entity把vdev-entity加入到mdev-entities中;在异步匹配后会调用v4l2_device_register_subdev注册subdev在该函数内容同样调用media_device_register_entity把每个sd-entity和pad注册到v4l2_dev-mdev;在bound函数中会调用media_create_pad_link把link也加入Media Graphvideo_register_device(vdev, VFL_TYPE_VIDEO, dma_cap-id)注册video_device创建dev/videoX节点把entity和pad加入Media Graphvideo_register_device()└──video_register_media_controller()// 注册entity└──media_device_register_entity()// 把vdev-entity加入到mdev-entities中v4l2_async_nf_init(ntf, csi_dma-v4l2_dev)v4l2_async_nf_parse_fwnode_endpoints(csi_dma-dev, ntf, sizeof(v4l2_async_subdev), NULL)遍历 dts 中 DMA 的 endpoint沿remote-endpoint找到上游设备把该设备的 fwnode 匹配条目加入 notifier 的waiting_list。v4l2_async_nf_register(ntf)触发bound()、complete()、v4l2_device_register_subdev()等在异步注册流程中有详解。