1. V4L2框架概述与subdev基础
V4L2(Video4Linux2)是Linux内核中负责视频采集和输出的子系统框架,它为视频设备提供了一套标准化的接口。在复杂的视频处理系统中,通常需要将不同功能的硬件模块(如传感器、ISP、编码器等)组合起来工作,这时subdev(子设备)的概念就变得尤为重要。
subdev是V4L2框架中的核心组件之一,它代表了一个具有独立功能的视频处理单元。每个subdev可以有自己的输入输出pad(类似于端口),通过这些pad与其他subdev或主设备连接。这种架构设计使得复杂的视频处理流水线可以被清晰地模块化和组合。
1.1 subdev的基本结构
在Linux内核中,subdev通过struct v4l2_subdev结构体表示。这个结构体包含了subdev的所有属性和操作方法:
c复制struct v4l2_subdev {
struct media_entity entity;
struct list_head list;
struct module *owner;
u32 flags;
struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops;
const struct v4l2_subdev_internal_ops *internal_ops;
struct v4l2_ctrl_handler *ctrl_handler;
char name[52];
// ...其他成员
};
关键成员说明:
entity: 用于媒体控制器框架的实体表示ops: 包含subdev的各种操作方法(视频、音频、传感器等)internal_ops: subdev内部操作,如初始化、注册等ctrl_handler: 控制项处理程序
1.2 subdev的注册与初始化
注册一个subdev通常包括以下步骤:
- 分配并初始化v4l2_subdev结构体
- 设置subdev的操作方法集(v4l2_subdev_ops)
- 初始化媒体实体(media_entity)
- 调用v4l2_async_register_subdev()注册subdev
c复制struct v4l2_subdev *sd = devm_kzalloc(dev, sizeof(*sd), GFP_KERNEL);
v4l2_subdev_init(sd, &subdev_ops);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
v4l2_async_register_subdev(sd);
注意:在注册subdev之前,必须完成所有初始化工作,包括启用运行时电源管理。这是因为注册后subdev可能立即被访问。
2. subdev的异步注册与fwnode解析
在现代Linux视频驱动中,异步subdev注册机制变得越来越重要,特别是在基于设备树的系统中。这种机制允许subdev在它们依赖的资源可用之前就被注册,然后在所有资源就绪后自动完成初始化。
2.1 异步注册流程
异步注册的核心是v4l2_async_notifier结构体,它负责管理subdev的注册过程:
- 初始化notifier:
c复制struct v4l2_async_notifier *notifier = &sd->subdev_notifier;
v4l2
