2.7. V4L2 子设备¶
许多驱动程序需要与子设备通信。这些设备可以执行各种任务,但最常见的是处理音频和/或视频的混合、编码或解码。对于网络摄像头,常见的子设备是传感器和摄像头控制器。
通常这些是 I2C 设备,但不一定。为了为驱动程序提供与这些子设备一致的接口,创建了 v4l2_subdev
结构体 (v4l2-subdev.h)。
每个子设备驱动程序都必须有一个 v4l2_subdev
结构体。对于简单的子设备,此结构体可以是独立的,如果需要存储更多状态信息,则可以嵌入到更大的结构体中。通常有一个低级设备结构体(例如 i2c_client
),其中包含内核设置的设备数据。建议使用 v4l2_set_subdevdata()
将该指针存储在 v4l2_subdev
的私有数据中。这样可以轻松地从 v4l2_subdev
转到实际的低级总线特定设备数据。
您还需要一种从低级结构体转到 v4l2_subdev
的方法。对于常见的 i2c_client 结构体,使用 i2c_set_clientdata() 调用来存储 v4l2_subdev
指针,对于其他总线,您可能需要使用其他方法。
桥接器可能还需要存储每个子设备的私有数据,例如指向桥接器特定的每个子设备的私有数据的指针。v4l2_subdev
结构体为此目的提供了主机私有数据,可以使用 v4l2_get_subdev_hostdata()
和 v4l2_set_subdev_hostdata()
访问。
从桥接器驱动程序的角度来看,您加载子设备模块,并以某种方式获取 v4l2_subdev
指针。对于 i2c 设备,这很容易:您调用 i2c_get_clientdata()
。对于其他总线,需要执行类似的操作。存在用于 I2C 总线上的子设备的辅助函数,可以为您完成大部分棘手的工作。
每个 v4l2_subdev
包含子设备驱动程序可以实现的函数指针(或者如果不适用,则保留为 NULL
)。由于子设备可以做很多不同的事情,并且您不希望最终得到一个庞大的 ops 结构体,其中只有少数 ops 被普遍实现,因此函数指针按照类别排序,每个类别都有自己的 ops 结构体。
顶层 ops 结构体包含指向类别 ops 结构体的指针,如果 subdev 驱动程序不支持该类别中的任何内容,则该指针可能为 NULL。
它看起来像这样
struct v4l2_subdev_core_ops {
int (*log_status)(struct v4l2_subdev *sd);
int (*init)(struct v4l2_subdev *sd, u32 val);
...
};
struct v4l2_subdev_tuner_ops {
...
};
struct v4l2_subdev_audio_ops {
...
};
struct v4l2_subdev_video_ops {
...
};
struct v4l2_subdev_pad_ops {
...
};
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_pad_ops *video;
};
核心 ops 对所有 subdevs 都是通用的,其他类别根据子设备实现。例如,视频设备不太可能支持音频 ops,反之亦然。
此设置限制了函数指针的数量,同时仍然可以轻松添加新的 ops 和类别。
子设备驱动程序使用以下命令初始化 v4l2_subdev
结构体
v4l2_subdev_init
(sd
, &ops
)。
之后,您需要使用唯一的名称初始化 sd
->name 并设置模块所有者。如果您使用 i2c 辅助函数,则会自动为您完成此操作。
如果需要与媒体框架集成,则必须通过调用 media_entity_pads_init()
来初始化嵌入在 v4l2_subdev
结构体(实体字段)中的 media_entity
结构体,如果实体有 pad
struct media_pad *pads = &my_sd->pads;
int err;
err = media_entity_pads_init(&sd->entity, npads, pads);
pads 数组必须已事先初始化。无需手动设置 struct media_entity
函数和名称字段,但如果需要,则必须初始化修订字段。
当子设备设备节点(如果有)打开/关闭时,将自动获取/释放对实体的引用。
不要忘记在子设备销毁之前清理媒体实体
media_entity_cleanup(&sd->entity);
如果子设备驱动程序实现接收器 pad,则 subdev 驱动程序可以在 v4l2_subdev_pad_ops
中设置 link_validate 字段以提供自己的链接验证函数。对于管道中的每个链接,都会调用链接的接收器端的 link_validate pad 操作。在这两种情况下,驱动程序仍然负责验证子设备和视频节点之间的格式配置的正确性。
如果未设置 link_validate op,则使用默认函数 v4l2_subdev_link_validate_default()
。此函数确保链接的源和接收器上的宽度、高度和媒体总线像素代码相等。除了他们自己的检查之外,Subdev 驱动程序还可以自由地使用此功能来执行上述检查。
2.7.1. Subdev 注册¶
目前有两种方法可以将子设备注册到 V4L2 核心。第一种(传统)可能性是由桥接器驱动程序注册子设备。当桥接器驱动程序具有有关连接到它的子设备的完整信息,并且确切知道何时注册它们时,可以执行此操作。这通常是内部子设备的情况,例如 SoC 或复杂 PCI(e) 板内的视频数据处理单元、USB 摄像头中的摄像头传感器或连接到 SoC,它们通常在其平台数据中将有关它们的信息传递给桥接器驱动程序。
但是,在某些情况下,子设备必须异步地注册到桥接器设备。这种配置的一个示例是基于设备树的系统,其中有关子设备的信息独立于桥接器设备提供给系统,例如,当子设备在 DT 中定义为 I2C 设备节点时。第二种情况中使用的 API 在下面进一步描述。
使用一种或另一种注册方法只会影响探测过程,在两种情况下,运行时桥接器-子设备交互是相同的。
2.7.1.1. 注册同步子设备¶
在同步情况下,设备(桥接器)驱动程序需要使用 v4l2_device 注册 v4l2_subdev
如果 subdev 模块在注册之前消失,则此操作可能会失败。成功调用此函数后,subdev->dev 字段指向 v4l2_device
。
如果 v4l2_device 父设备具有非 NULL mdev 字段,则子设备实体将自动注册到媒体设备。
您可以使用以下命令注销子设备
之后,可以卸载 subdev 模块,并且 sd
->dev == NULL
。
2.7.1.2. 注册异步子设备¶
在异步情况下,可以独立于桥接器驱动程序的可用性来调用子设备探测。然后,子设备驱动程序必须验证是否满足成功探测的所有要求。这可以包括检查主时钟的可用性。如果任何条件未满足,驱动程序可能会决定返回 -EPROBE_DEFER
以请求进一步的重新探测尝试。一旦满足所有条件,应使用 v4l2_async_register_subdev()
函数注册子设备。注销使用 v4l2_async_unregister_subdev()
调用执行。以这种方式注册的子设备存储在子设备的全局列表中,准备好被桥接器驱动程序拾取。
驱动程序必须在使能够运行时 PM 之前,在使用 v4l2_async_register_subdev()
注册子设备之前完成子设备的所有初始化。这是因为子设备在注册后立即变得可访问。
2.7.1.3. 异步子设备通知器¶
反过来,桥接器驱动程序必须注册一个通知器对象。这是使用 v4l2_async_nf_register()
调用执行的。要注销通知器,驱动程序必须调用 v4l2_async_nf_unregister()
。在释放未注册通知器的内存之前,必须通过调用 v4l2_async_nf_cleanup()
来清理它。
在注册通知器之前,桥接器驱动程序必须做两件事:首先,必须使用 v4l2_async_nf_init()
初始化通知器。其次,桥接器驱动程序可以开始形成桥接器设备运行所需的异步连接描述符列表。v4l2_async_nf_add_fwnode()
、v4l2_async_nf_add_fwnode_remote()
和 v4l2_async_nf_add_i2c()
异步连接描述符描述了与外部子设备的连接,这些子设备的驱动程序尚未被探测。基于异步连接,当相关的子设备可用时,可能会创建一个媒体数据或辅助链接。可能有一个或多个到给定子设备的异步连接,但这在将连接添加到通知器时是未知的。异步连接在找到匹配的异步子设备时,逐个绑定。
2.7.1.4. 子设备的异步子设备通知器¶
注册异步子设备的驱动程序也可以注册异步通知器。这称为异步子设备通知器,该过程与桥接器驱动程序的过程类似,不同之处在于使用 v4l2_async_subdev_nf_init()
初始化通知器。只有在 V4L2 设备可用后,即存在通过异步子设备和通知器到非异步子设备通知器的路径时,子设备通知器才能完成。
2.7.1.5. 摄像头传感器驱动程序的异步子设备注册助手¶
v4l2_async_register_subdev_sensor()
是传感器驱动程序注册自己的异步连接的辅助函数,但它也注册一个通知器,并进一步注册固件中找到的镜头和闪光设备的异步连接。子设备的通知器使用 v4l2_async_unregister_subdev()
注销并与异步子设备一起清理。
2.7.1.6. 异步子设备通知器示例¶
这些函数分配一个异步连接描述符,该描述符是类型结构体 v4l2_async_connection
嵌入到驱动程序特定的结构体中。&struct v4l2_async_connection
应是此结构体的第一个成员
struct my_async_connection {
struct v4l2_async_connection asc;
...
};
struct my_async_connection *my_asc;
struct fwnode_handle *ep;
...
my_asc = v4l2_async_nf_add_fwnode_remote(¬ifier, ep,
struct my_async_connection);
fwnode_handle_put(ep);
if (IS_ERR(my_asc))
return PTR_ERR(my_asc);
2.7.1.7. 异步子设备通知器回调¶
然后,V4L2 核心将使用这些连接描述符将异步注册的子设备与它们匹配。如果检测到匹配,则调用 .bound()
通知器回调。在绑定所有连接后,调用 .complete() 回调。当从系统中删除连接时,调用 .unbind()
方法。所有三个回调都是可选的。
驱动程序可以在其驱动程序特定的 v4l2_async_connection
包装器中存储任何类型的自定义数据。如果在释放结构体时任何数据需要特殊处理,则驱动程序必须实现 .destroy()
通知器回调。框架将在释放 v4l2_async_connection
之前立即调用它。
2.7.2. 调用 subdev 操作¶
使用 v4l2_subdev
的优点是它是一个通用结构体,不包含有关底层硬件的任何知识。因此,驱动程序可能包含多个使用 I2C 总线的 subdev,但也可能包含一个通过 GPIO 引脚控制的 subdev。这种区别仅在设置设备时才相关,但一旦注册 subdev,它就完全透明。
注册 subdev 后,您可以直接调用 ops 函数
err = sd->ops->core->g_std(sd, &norm);
但最好且更容易使用此宏
err = v4l2_subdev_call(sd, core, g_std, &norm);
该宏将执行正确的 NULL
指针检查,如果 sd
是 NULL
,则返回 -ENODEV
,如果 sd
->core 或 sd
->core->g_std 是 NULL
,则返回 -ENOIOCTLCMD
,否则返回 sd
->ops->core->g_std ops 的实际结果。
也可以调用所有或部分子设备
v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm);
任何不支持此 ops 的 subdev 都会被跳过,并且错误结果会被忽略。如果要检查错误,请使用此命令
err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm);
除了 -ENOIOCTLCMD
之外的任何错误都将以该错误退出循环。如果没有发生错误(除了 -ENOIOCTLCMD
),则返回 0。
两次调用的第二个参数是一个组 ID。如果为 0,则调用所有 subdev。如果为非零值,则仅调用那些组 ID 与该值匹配的 subdev。在桥接器驱动程序注册 subdev 之前,它可以将 sd
->grp_id 设置为它想要的任何值(默认为 0)。此值归桥接器驱动程序所有,子设备驱动程序永远不会修改或使用它。
组 ID 使桥接器驱动程序可以更好地控制如何调用回调。例如,一个板上可能有多个音频芯片,每个芯片都能够改变音量。但是,通常在用户想要更改音量时,只会实际使用一个。您可以将该 subdev 的组 ID 设置为例如 AUDIO_CONTROLLER,并在调用 v4l2_device_call_all()
时将其指定为组 ID 值。这确保它只会转到需要的 subdev。
如果子设备需要将其 v4l2_device 父设备通知事件,则它可以调用 v4l2_subdev_notify(sd, notification, arg)
。此宏检查是否定义了 notify()
回调,如果未定义,则返回 -ENODEV
。否则,将返回 notify()
调用的结果。
2.8. V4L2 子设备用户空间 API¶
传统上,桥接器驱动程序向用户空间公开一个或多个视频节点,并通过 v4l2_subdev_ops
操作来控制子设备,以响应视频节点操作。这向应用程序隐藏了底层硬件的复杂性。对于复杂的设备,可能需要比视频节点提供的更精细的设备控制。在这些情况下,实现 媒体控制器 API 的桥接器驱动程序可以选择直接从用户空间访问子设备操作。
可以在 /dev
中创建名为 v4l-subdev
X 的设备节点以直接访问子设备。如果子设备支持直接用户空间配置,则必须在注册之前设置 V4L2_SUBDEV_FL_HAS_DEVNODE
标志。
注册子设备后,v4l2_device
驱动程序可以为所有标记有 V4L2_SUBDEV_FL_HAS_DEVNODE
的已注册子设备创建设备节点,方法是调用 v4l2_device_register_subdev_nodes()
。当注销子设备时,这些设备节点将被自动删除。
设备节点处理 V4L2 API 的子集。
VIDIOC_QUERYCTRL
、VIDIOC_QUERYMENU
、VIDIOC_G_CTRL
、VIDIOC_S_CTRL
、VIDIOC_G_EXT_CTRLS
、VIDIOC_S_EXT_CTRLS
和 VIDIOC_TRY_EXT_CTRLS
控件 ioctl 与 V4L2 中定义的相同。它们的行为相同,唯一的例外是它们仅处理在子设备中实现的控件。根据驱动程序,也可以通过一个(或多个)V4L2 设备节点访问这些控件。
VIDIOC_DQEVENT
、VIDIOC_SUBSCRIBE_EVENT
和 VIDIOC_UNSUBSCRIBE_EVENT
事件 ioctl 与 V4L2 中定义的相同。它们的行为相同,唯一的例外是它们仅处理由子设备生成的事件。根据驱动程序,也可以通过一个(或多个)V4L2 设备节点报告这些事件。
想要使用事件的子设备驱动程序需要在注册子设备之前设置
V4L2_SUBDEV_FL_HAS_EVENTS
v4l2_subdev
.flags。注册后,事件可以像往常一样在v4l2_subdev
.devnode 设备节点上排队。为了正确支持事件,还实现了
poll()
文件操作。
私有 ioctl
上面列表中未包含的所有 ioctl 都通过 core::ioctl 操作直接传递给子设备驱动程序。
2.9. 只读子设备用户空间 API¶
桥接驱动程序通过直接调用由 v4l2_subdev_ops
结构实现的内核 API 来控制其连接的子设备,通常不希望用户空间能够通过子设备设备节点更改相同的参数,因此通常不注册任何内容。
有时通过只读 API 向用户空间报告当前子设备配置很有用,该 API 不允许应用程序更改设备参数,但允许与子设备设备节点交互以检查它们。
例如,为了实现基于计算摄影的相机,用户空间需要了解每个支持的输出分辨率的详细相机传感器配置(在跳过、合并、裁剪和缩放方面)。为了支持此类用例,桥接驱动程序可以通过只读 API 将子设备操作公开给用户空间。
要为所有注册了 V4L2_SUBDEV_FL_HAS_DEVNODE
的子设备创建只读设备节点,v4l2_device
驱动程序应调用 v4l2_device_register_ro_subdev_nodes()
。
对于使用 v4l2_device_register_ro_subdev_nodes()
注册的子设备设备节点,用户空间应用程序对以下 ioctl 的访问受到限制。
VIDIOC_SUBDEV_S_FMT
、VIDIOC_SUBDEV_S_CROP
、VIDIOC_SUBDEV_S_SELECTION
这些 ioctl 仅允许在只读子设备设备节点上用于 V4L2_SUBDEV_FORMAT_TRY 格式和选择矩形。
VIDIOC_SUBDEV_S_FRAME_INTERVAL
、VIDIOC_SUBDEV_S_DV_TIMINGS
、VIDIOC_SUBDEV_S_STD
这些 ioctl 不允许在只读子设备节点上使用。
如果 ioctl 不允许,或者要修改的格式设置为 V4L2_SUBDEV_FORMAT_ACTIVE
,则核心将返回一个负错误代码,并且 errno 变量设置为 -EPERM
。
2.10. I2C 子设备驱动程序¶
由于这些驱动程序非常常见,因此可以使用特殊的辅助函数来简化这些驱动程序的使用 (v4l2-common.h
)。
将 v4l2_subdev
支持添加到 I2C 驱动程序的推荐方法是将 v4l2_subdev
结构嵌入到为每个 I2C 设备实例创建的状态结构中。非常简单的设备没有状态结构,在这种情况下,您可以直接创建一个 v4l2_subdev
。
典型的状态结构如下所示(其中 “chipname” 替换为芯片的名称)
struct chipname_state {
struct v4l2_subdev sd;
... /* additional state fields */
};
按如下方式初始化 v4l2_subdev
结构
v4l2_i2c_subdev_init(&state->sd, client, subdev_ops);
此函数将填写 v4l2_subdev
的所有字段,确保 v4l2_subdev
和 i2c_client 都相互指向。
您还应该添加一个辅助内联函数,以从 v4l2_subdev
指针转到 chipname_state 结构
static inline struct chipname_state *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct chipname_state, sd);
}
使用此函数从 v4l2_subdev
结构转到 i2c_client
结构
struct i2c_client *client = v4l2_get_subdevdata(sd);
使用此函数从 i2c_client
转到 v4l2_subdev
结构
struct v4l2_subdev *sd = i2c_get_clientdata(client);
确保在调用 remove()
回调时调用 v4l2_device_unregister_subdev()
(sd
)。这将从桥接驱动程序中注销子设备。即使从未注册子设备,也可以安全地调用此函数。
您需要这样做,因为当桥接驱动程序销毁 i2c 适配器时,会调用该适配器上的 i2c 设备的 remove()
回调。之后,相应的 v4l2_subdev 结构将无效,因此必须首先注销它们。从 remove()
回调调用 v4l2_device_unregister_subdev()
(sd
) 可确保始终正确地完成此操作。
桥接驱动程序还有一些可以使用的辅助函数
struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter,
"module_foo", "chipid", 0x36, NULL);
这将加载给定的模块(如果没有模块需要加载,则可以为 NULL
),并使用给定的 i2c_adapter
和芯片/地址参数调用 i2c_new_client_device()
。如果一切顺利,它将向 v4l2_device 注册子设备。
您还可以使用 v4l2_i2c_new_subdev()
的最后一个参数来传递它应该探测的可能的 I2C 地址数组。仅当上一个参数为 0 时才使用这些探测地址。非零参数意味着您知道确切的 i2c 地址,因此在这种情况下不会进行探测。
如果出现问题,这两个函数都返回 NULL
。
请注意,您传递给 v4l2_i2c_new_subdev()
的 chipid 通常与模块名称相同。它允许您指定芯片变体,例如 “saa7114” 或 “saa7115”。但总的来说,i2c 驱动程序会自动检测到这一点。chipid 的使用需要在以后更仔细地研究。它在 i2c 驱动程序之间有所不同,因此可能会造成混淆。要查看支持哪些芯片变体,您可以查看 i2c 驱动程序代码中的 i2c_device_id 表。这列出了所有可能性。
还有一个辅助函数
v4l2_i2c_new_subdev_board()
使用传递给 i2c 驱动程序的 i2c_board_info
结构,并替换 irq、platform_data 和 addr 参数。
如果子设备支持 s_config core ops,则在设置子设备后使用 irq 和 platform_data 参数调用该 op。
v4l2_i2c_new_subdev()
函数将调用 v4l2_i2c_new_subdev_board()
,在内部使用 client_type
和 addr
填充 i2c_board_info
结构。
2.11. 集中管理的子设备活动状态¶
传统上,V4L2 子设备驱动程序维护活动设备配置的内部状态。这通常实现为例如 struct v4l2_mbus_framefmt
数组,每个 pad 一个条目,对于裁剪和合成矩形也是如此。
除了活动配置之外,每个子设备文件句柄都有一个由 V4L2 核心管理的 struct v4l2_subdev_state
,其中包含尝试配置。
为了简化子设备驱动程序,V4L2 子设备 API 现在可以选择性地支持由 v4l2_subdev_state
表示的集中管理的活动配置。一个状态实例(包含活动设备配置)作为 v4l2_subdev
结构的一部分存储在子设备本身中,而核心将一个尝试状态与每个打开的文件句柄相关联,以存储与该文件句柄相关的尝试配置。
子设备驱动程序可以选择使用状态来管理其活动配置,方法是在注册子设备之前调用 v4l2_subdev_init_finalize()
初始化子设备状态。它们还必须调用 v4l2_subdev_cleanup()
以释放所有已分配的资源,然后才能注销子设备。核心自动为每个打开的文件句柄分配和初始化一个状态,以存储尝试配置,并在关闭文件句柄时释放它。
V4L2 子设备操作使用 ACTIVE 和 TRY 格式,通过 “状态” 参数接收要操作的正确状态。状态必须由调用者通过调用 v4l2_subdev_lock_state()
和 v4l2_subdev_unlock_state()
来锁定和解锁。调用者可以通过调用 v4l2_subdev_call_state_active()
宏来执行此操作。
不接收状态参数的操作隐式地对子设备活动状态进行操作,驱动程序可以通过调用 v4l2_subdev_lock_and_get_active_state()
来独占访问该状态。子设备活动状态也必须通过调用 v4l2_subdev_unlock_state()
来释放。
驱动程序绝不能手动访问存储在 v4l2_subdev
或文件句柄中的状态,而不使用指定的辅助函数。
虽然 V4L2 核心将正确的尝试或活动状态传递给子设备操作,但许多现有设备驱动程序在调用 v4l2_subdev_call()
的操作时传递 NULL 状态。这种遗留结构导致子设备驱动程序出现问题,这些驱动程序让 V4L2 核心管理活动状态,因为它们期望接收适当的状态作为参数。为了帮助将子设备驱动程序转换为托管活动状态,而无需同时转换所有调用者,v4l2_subdev_call()
中添加了一个额外的包装器层,它通过使用 v4l2_subdev_lock_and_get_active_state()
获取和锁定被调用者的活动状态来处理 NULL 情况,并在调用后解锁状态。
整个子设备状态实际上分为三个部分:v4l2_subdev_state、子设备控件和子设备驱动程序的内部状态。将来,这些部分应该合并为一个状态。目前,我们需要一种方法来处理这些部分的锁定。这可以通过共享锁来完成。v4l2_ctrl_handler 已经通过其 “lock” 指针支持这一点,并且相同的模型也用于状态。驱动程序可以在调用 v4l2_subdev_init_finalize()
之前执行以下操作
sd->ctrl_handler->lock = &priv->mutex;
sd->state_lock = &priv->mutex;
这在控件和状态之间共享驱动程序的私有互斥锁。
2.12. 流、多路复用媒体 pad 和内部路由¶
子设备驱动程序可以通过设置 V4L2_SUBDEV_FL_STREAMS 子设备标志并实现对集中管理的子设备活动状态、路由和基于流的配置的支持来实现对多路复用流的支持。
2.13. V4L2 子设备函数和数据结构¶
-
struct v4l2_decode_vbi_line¶
用于 decode_vbi_line
定义:
struct v4l2_decode_vbi_line {
u32 is_second_field;
u8 *p;
u32 line;
u32 type;
};
成员
is_second_field
对于第一个(奇数)场,设置为 0;对于第二个(偶数)场,设置为 1。
p
指向解码器中切片的 VBI 数据的指针。退出时,指向有效负载的开始。
line
切片的 VBI 数据的行号 (1-23)
type
VBI 服务类型 (V4L2_SLICED_*)。如果未找到服务,则为 0
-
enum v4l2_subdev_io_pin_bits¶
子设备外部 IO 引脚配置位
常量
V4L2_SUBDEV_IO_PIN_DISABLE
禁用引脚配置。假定启用。
V4L2_SUBDEV_IO_PIN_OUTPUT
如果引脚是输出,则设置它。
V4L2_SUBDEV_IO_PIN_INPUT
如果引脚是输入,则设置它。
V4L2_SUBDEV_IO_PIN_SET_VALUE
通过
struct v4l2_subdev_io_pin_config
->value 设置输出值。V4L2_SUBDEV_IO_PIN_ACTIVE_LOW
引脚活动为位 0。否则,假定为 ACTIVE HIGH。
-
struct v4l2_subdev_io_pin_config¶
子设备外部 IO 引脚配置
定义:
struct v4l2_subdev_io_pin_config {
u32 flags;
u8 pin;
u8 function;
u8 value;
u8 strength;
};
成员
flags
此引脚配置的标志位掩码,其位由
enum v4l2_subdev_io_pin_bits
定义。pin
要配置的芯片外部 IO 引脚
function
要路由到 IO 引脚的内部信号 pad/函数
value
引脚的初始值 - 例如 GPIO 输出值
strength
引脚驱动强度
-
struct v4l2_subdev_core_ops¶
为子设备定义核心 ops 回调
定义:
struct v4l2_subdev_core_ops {
int (*log_status)(struct v4l2_subdev *sd);
int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n, struct v4l2_subdev_io_pin_config *pincfg);
int (*init)(struct v4l2_subdev *sd, u32 val);
int (*load_fw)(struct v4l2_subdev *sd);
int (*reset)(struct v4l2_subdev *sd, u32 val);
int (*s_gpio)(struct v4l2_subdev *sd, u32 val);
long (*command)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#ifdef CONFIG_COMPAT;
long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg);
#endif;
#ifdef CONFIG_VIDEO_ADV_DEBUG;
int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
int (*s_register)(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg);
#endif;
int (*s_power)(struct v4l2_subdev *sd, int on);
int (*interrupt_service_routine)(struct v4l2_subdev *sd, u32 status, bool *handled);
int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub);
int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub);
};
成员
log_status
用于 VIDIOC_LOG_STATUS() ioctl 处理程序代码的回调。
s_io_pin_config
为芯片配置一个或多个芯片 I/O 引脚,这些芯片将不同的内部信号 pad 多路复用到 IO 引脚。此函数采用指向 “n” 个引脚配置条目数组的指针,每个引脚配置一个条目。此函数可以在子设备初始化之外的其他时间调用。
init
将传感器寄存器初始化为某种合理的默认值。不要用于新的驱动程序,应在现有驱动程序中删除。
load_fw
加载固件。
reset
通用重置命令。该参数选择要重置的子系统。传递 0 将始终重置整个芯片。没有在 linux-media 邮件列表中首先讨论这一点,不要用于新的驱动程序。通常没有理由重置设备。
s_gpio
设置 GPIO 引脚。现在很简单,如果需要,可能需要用方向参数进行扩展。
command
由内核驱动程序调用,以便调用子设备驱动程序内部的具有单独回调的函数驱动程序。
ioctl
在 V4L2 核心的 ioctl() 系统调用处理程序的末尾调用。用于提供对驱动程序上使用的私有 ioctl 的支持。
compat_ioctl32
当 32 位应用程序使用 64 位内核时调用,以便修复从/到用户空间传递的数据。
g_register
用于 VIDIOC_DBG_G_REGISTER() ioctl 处理程序代码的回调。
s_register
用于 VIDIOC_DBG_S_REGISTER() ioctl 处理程序代码的回调。
s_power
将子设备置于省电模式(on == 0)或正常操作模式(on == 1)。已弃用。请参阅 编写相机传感器驱动程序。pre_streamon 和 post_streamoff 回调可以用于例如在调用 s_stream 之前将总线设置为 LP-11 模式。
interrupt_service_routine
当由于此子设备而引发中断状态时,由桥接芯片的中断服务处理程序调用,以便此子设备可以处理详细信息。它可能会安排稍后执行的工作。它不得睡眠。从 IRQ 上下文中调用。
subscribe_event
驱动程序使用它来请求控件框架,以便在控件值更改时收到警告。
unsubscribe_event
从控件框架中删除事件订阅。
-
struct v4l2_subdev_tuner_ops¶
在无线电模式下打开 v4l 设备时使用的回调。
定义:
struct v4l2_subdev_tuner_ops {
int (*standby)(struct v4l2_subdev *sd);
int (*s_radio)(struct v4l2_subdev *sd);
int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq);
int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
int (*enum_freq_bands)(struct v4l2_subdev *sd, struct v4l2_frequency_band *band);
int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
int (*s_tuner)(struct v4l2_subdev *sd, const struct v4l2_tuner *vt);
int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
int (*s_modulator)(struct v4l2_subdev *sd, const struct v4l2_modulator *vm);
int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config);
};
成员
standby
将调谐器置于待机模式。下次使用它时,它将自动唤醒。
s_radio
将调谐器切换到无线电模式的回调。驱动程序应在无线电模式下操作调谐器 ops 时显式调用它,然后才能处理它。用于同时具有 AM/FM 无线电接收器和 TV 的设备。
s_frequency
用于 VIDIOC_S_FREQUENCY() ioctl 处理程序代码的回调。
g_frequency
用于 VIDIOC_G_FREQUENCY() ioctl 处理程序代码的回调。必须填写 freq->type。通常由
video_ioctl2()
或桥接驱动程序完成。enum_freq_bands
用于 VIDIOC_ENUM_FREQ_BANDS() ioctl 处理程序代码的回调。
g_tuner
用于 VIDIOC_G_TUNER() ioctl 处理程序代码的回调。
s_tuner
用于 VIDIOC_S_TUNER() ioctl 处理程序代码的回调。必须填写 vt->type。通常由 video_ioctl2 或桥接驱动程序完成。
g_modulator
用于 VIDIOC_G_MODULATOR() ioctl 处理程序代码的回调。
s_modulator
用于 VIDIOC_S_MODULATOR() ioctl 处理程序代码的回调。
s_type_addr
设置调谐器类型及其 I2C 地址。
s_config
设置 tda9887 特定内容,如 port1、port2 和 qss
描述
注意
在同时具有 AM/FM 和 TV 的设备上,由驱动程序显式调用 s_radio,以便在处理其他需要它的 struct v4l2_subdev_tuner_ops
之前将调谐器切换到无线电模式。此类用法的示例是
static void s_frequency(void *priv, const struct v4l2_frequency *f)
{
...
if (f.type == V4L2_TUNER_RADIO)
v4l2_device_call_all(v4l2_dev, 0, tuner, s_radio);
...
v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency);
}
-
struct v4l2_subdev_audio_ops¶
用于音频相关设置的回调
定义:
struct v4l2_subdev_audio_ops {
int (*s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_i2s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
};
成员
s_clock_freq
设置音频时钟输出的频率(以 Hz 为单位)。用于将音频处理器与视频解码器连接起来,确保音频和视频保持同步。频率的常用值为 48000、44100 或 32000 Hz。如果不支持该频率,则返回 -EINVAL。
s_i2s_clock_freq
以 bps 为单位设置 I2S 速度。这用于提供一种标准方法来选择某些板设计中用于驱动数字音频流的 I2S 时钟。频率的常用值为 1024000 和 2048000。如果不支持该频率,则返回
-EINVAL
。s_routing
用于定义音频芯片的输入和/或输出引脚,以及任何其他配置数据。切勿尝试在此级别使用用户级别的输入 ID(例如复合、S-Video、调谐器)。i2c 设备不应该知道输入引脚是否连接到复合连接器,因为在另一个板或平台上,它可能连接到完全不同的东西。调用驱动程序负责将用户级别的输入映射到 i2c 设备上的正确引脚。
s_stream
用于通知音频代码流将开始或已停止。
-
struct v4l2_mbus_frame_desc_entry_csi2¶
定义:
struct v4l2_mbus_frame_desc_entry_csi2 {
u8 vc;
u8 dt;
};
成员
vc
CSI-2 虚拟通道
dt
CSI-2 数据类型 ID
-
enum v4l2_mbus_frame_desc_flags¶
媒体总线帧描述标志
常量
V4L2_MBUS_FRAME_DESC_FL_LEN_MAX
指示
struct v4l2_mbus_frame_desc_entry
->length 字段指定最大数据长度。V4L2_MBUS_FRAME_DESC_FL_BLOB
指示格式没有行偏移量,即接收器应使用 1D DMA。
-
struct v4l2_mbus_frame_desc_entry¶
媒体总线帧描述结构
定义:
struct v4l2_mbus_frame_desc_entry {
enum v4l2_mbus_frame_desc_flags flags;
u32 stream;
u32 pixelcode;
u32 length;
union {
struct v4l2_mbus_frame_desc_entry_csi2 csi2;
} bus;
};
成员
flags
位掩码标志,由
enum v4l2_mbus_frame_desc_flags
定义。stream
路由配置中的流
pixelcode
媒体总线像素代码,如果未设置 flags
FRAME_DESC_FL_BLOB
,则有效。length
每帧的八位字节数,如果设置了 flags
V4L2_MBUS_FRAME_DESC_FL_LEN_MAX
,则有效。bus
总线特定帧描述符参数
bus.csi2
CSI-2 特定总线配置
-
enum v4l2_mbus_frame_desc_type¶
媒体总线帧描述类型
常量
V4L2_MBUS_FRAME_DESC_TYPE_UNDEFINED
未定义的帧描述类型。驱动程序不应使用此类型,它用于向后兼容。
V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL
并行媒体总线。
V4L2_MBUS_FRAME_DESC_TYPE_CSI2
CSI-2 媒体总线。帧描述参数必须在
struct v4l2_mbus_frame_desc_entry
->csi2 中设置。
-
struct v4l2_mbus_frame_desc¶
媒体总线数据帧描述
定义:
struct v4l2_mbus_frame_desc {
enum v4l2_mbus_frame_desc_type type;
struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
unsigned short num_entries;
};
成员
type
entry
帧描述符数组
num_entries
entry 数组中的条目数
-
enum v4l2_subdev_pre_streamon_flags¶
用于 pre_streamon 子设备核心 op 的标志
常量
V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP
在调用 s_stream() 之前,将发射器设置为 LP-11 或 LP-111 模式。
-
struct v4l2_subdev_video_ops¶
在视频模式下打开 v4l 设备时使用的回调。
定义:
struct v4l2_subdev_video_ops {
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags);
int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
int (*g_std_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
int (*g_pixelaspect)(struct v4l2_subdev *sd, struct v4l2_fract *aspect);
int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf, unsigned int *size);
int (*pre_streamon)(struct v4l2_subdev *sd, u32 flags);
int (*post_streamoff)(struct v4l2_subdev *sd);
};
成员
s_routing
请参阅 audio_ops 中的 s_routing,除了此版本适用于视频设备。
s_crystal_freq
以 Hz 为单位设置用于生成时钟的晶体频率。一个额外的标志字段允许设备进行特定的配置,例如时钟分频器等。如果未使用,则将标志设置为 0。如果不支持该频率,则返回 -EINVAL。
g_std
用于 VIDIOC_G_STD() ioctl 处理程序代码的回调。
s_std
用于 VIDIOC_S_STD() ioctl 处理程序代码的回调。
s_std_output
为视频输出设备设置 v4l2_std_id。视频输入设备会忽略此设置。
g_std_output
获取视频输出设备当前的制式标准。视频输入设备会忽略此设置。
querystd
用于 VIDIOC_QUERYSTD() ioctl 处理程序代码的回调。
g_tvnorms
获取视频采集设备支持的所有制式的
v4l2_std_id
。视频输出设备会忽略此设置。g_tvnorms_output
获取视频输出设备支持的所有制式的 v4l2_std_id。视频采集设备会忽略此设置。
g_input_status
获取输入状态。与
struct v4l2_input
中的 status 字段相同。s_stream
启动(enabled == 1)或停止(enabled == 0)子设备上的流传输。停止失败将移除流传输启动时获取的任何资源,但驱动程序仍会返回错误代码。调用者应跟踪子设备状态,不应启动或停止已启动或停止的子设备。另请参见 v4l2-subdev.c 中的 call_s_stream 包装器。
此回调已弃用。新的驱动程序应改为实现
v4l2_subdev_pad_ops.enable_streams
和v4l2_subdev_pad_ops.disable_streams
操作,并为v4l2_subdev_video_ops.s_stream
操作使用 v4l2_subdev_s_stream_helper 以支持旧版用户。驱动程序也不应直接调用 .s_stream() 子设备操作,而应使用
v4l2_subdev_enable_streams()
和v4l2_subdev_disable_streams()
辅助函数。g_pixelaspect
返回像素宽高比的回调。
s_rx_buffer
为子设备设置主机分配的内存缓冲区。子设备可以将 size 调整为较低的值,并且从 data 开始,写入缓冲区的数据不得超过 size 的原始值。
pre_streamon
可以在实际开始流传输之前调用,以帮助初始化总线。当前的用法是在流传输之前将 CSI-2 发射器设置为 LP-11 或 LP-111 模式。请参见
enum v4l2_subdev_pre_streamon_flags
。如果 pre_streamon 无法执行标志参数指示的操作,则应返回错误。特别是,-EACCES 表示不支持该操作。对于每次成功调用 pre_streamon,调用者都应调用 post_streamoff。
post_streamoff
在停止流传输后调用,但仅当之前调用过 pre_streamon 时才调用。
-
struct v4l2_subdev_vbi_ops¶
通过 vbi 设备节点以视频模式打开 v4l 设备时使用的回调。
定义:
struct v4l2_subdev_vbi_ops {
int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);
int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);
int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);
int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);
int (*s_raw_fmt)(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
int (*g_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
int (*s_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
};
成员
decode_vbi_line
支持分片 VBI 的视频解码器需要实现此 ioctl。
struct v4l2_decode_vbi_line
的字段 p 设置为解码器生成的 VBI 数据的开始位置。然后,驱动程序解析分片 VBI 数据并相应地设置结构中的其他字段。指针 p 更新为指向有效负载的开始位置,可以逐字复制到struct v4l2_sliced_vbi_data
的 data 字段中。如果没有找到有效的 VBI 数据,则在返回时将 type 字段设置为 0。s_vbi_data
用于在视频信号上生成 VBI 信号。
struct v4l2_sliced_vbi_data
填充了应该输出的数据包。请注意,如果将 line 字段设置为 0,则会禁用该 VBI 信号。如果没有找到有效的 VBI 数据,则在返回时将 type 字段设置为 0。g_vbi_data
用于从读取回寄存器获取分片 VBI 数据包。并非所有视频解码器都支持此功能。如果由于读取回寄存器包含无效或错误数据而没有可用数据,则返回
-EIO
。请注意,您必须填写“id”成员和“field”成员(以确定应获取来自第一个还是第二个字段的 CC 数据)。g_sliced_vbi_cap
用于 VIDIOC_G_SLICED_VBI_CAP() ioctl 处理程序代码的回调。
s_raw_fmt
为原始 VBI 设置视频编码器/解码器。
g_sliced_fmt
检索当前的分片 VBI 设置。
s_sliced_fmt
设置分片 VBI 设置。
-
struct v4l2_subdev_sensor_ops¶
v4l2-subdev 传感器操作
定义:
struct v4l2_subdev_sensor_ops {
int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames);
};
成员
g_skip_top_lines
要跳过的图像顶部行数。某些传感器需要此设置,这些传感器总是会损坏输出图像的几个顶部行,或者在这些行中发送其元数据。
g_skip_frames
流开始时要跳过的帧数。对于一些有缺陷的传感器,在打开时会生成错误的帧,因此需要此设置。
-
enum v4l2_subdev_ir_mode¶
描述了支持的 IR 类型
常量
V4L2_SUBDEV_IR_MODE_PULSE_WIDTH
IR 使用 struct ir_raw_event 记录
-
struct v4l2_subdev_ir_parameters¶
用于 IR TX 或 TX 的参数
定义:
struct v4l2_subdev_ir_parameters {
unsigned int bytes_per_data_element;
enum v4l2_subdev_ir_mode mode;
bool enable;
bool interrupt_enable;
bool shutdown;
bool modulation;
u32 max_pulse_width;
unsigned int carrier_freq;
unsigned int duty_cycle;
bool invert_level;
bool invert_carrier_sense;
u32 noise_filter_min_width;
unsigned int carrier_range_lower;
unsigned int carrier_range_upper;
u32 resolution;
};
成员
bytes_per_data_element
读取或写入调用中每个数据元素占用的字节数。
mode
由
enum v4l2_subdev_ir_mode
定义的 IR 模式。enable
如果为 true,则设备处于活动状态
interrupt_enable
如果为 true,则启用 IR 中断
shutdown
如果为 true:将硬件设置为低/无功耗模式;false:正常模式
modulation
如果为 true,则使用载波;如果为 false,则使用基带
max_pulse_width
最大脉冲宽度,以纳秒为单位,仅对基带信号有效
carrier_freq
载波频率,以赫兹为单位,仅对调制信号有效
duty_cycle
占空比百分比,仅对调制信号有效
invert_level
反转信号电平
invert_carrier_sense
将 0/space 作为载波突发发送。仅在 TX 中使用。
noise_filter_min_width
有效脉冲的最小时间,以纳秒为单位。仅用于 RX。
carrier_range_lower
较低的载波范围,以赫兹为单位,仅对调制信号有效。仅用于 RX。
carrier_range_upper
较高的载波范围,以赫兹为单位,仅对调制信号有效。仅用于 RX。
resolution
接收分辨率,以纳秒为单位。仅用于 RX。
-
struct v4l2_subdev_ir_ops¶
用于 IR 子设备的操作
定义:
struct v4l2_subdev_ir_ops {
int (*rx_read)(struct v4l2_subdev *sd, u8 *buf, size_t count, ssize_t *num);
int (*rx_g_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*rx_s_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*tx_write)(struct v4l2_subdev *sd, u8 *buf, size_t count, ssize_t *num);
int (*tx_g_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*tx_s_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
};
成员
rx_read
读取接收到的代码或脉冲宽度数据。语义与非阻塞 read() 调用类似。
rx_g_parameters
获取 IR 接收器的当前操作参数和状态。
rx_s_parameters
设置 IR 接收器的当前操作参数和状态。建议首先调用 [rt]x_g_parameters 来填写当前状态,然后只更改需要更改的字段。返回时,将返回实际的设备操作参数和状态。请注意,硬件限制可能会阻止实际设置与请求的设置匹配 - 例如,当请求 36,000 Hz 时,实际载波设置为 35,904 Hz。例外情况是 shutdown 参数为 true。将返回上次使用的操作参数,但硬件的实际状态可能不同,以最大限度地减少功耗和处理(当 shutdown 为 true 时)。
tx_write
写入代码或脉冲宽度数据以进行传输。语义与非阻塞 write() 调用类似。
tx_g_parameters
获取 IR 发射器的当前操作参数和状态。
tx_s_parameters
设置 IR 发射器的当前操作参数和状态。建议首先调用 [rt]x_g_parameters 来填写当前状态,然后只更改需要更改的字段。返回时,将返回实际的设备操作参数和状态。请注意,硬件限制可能会阻止实际设置与请求的设置匹配 - 例如,当请求 36,000 Hz 时,实际载波设置为 35,904 Hz。例外情况是 shutdown 参数为 true。将返回上次使用的操作参数,但硬件的实际状态可能不同,以最大限度地减少功耗和处理(当 shutdown 为 true 时)。
-
struct v4l2_subdev_pad_config¶
用于存储 subdev pad 信息。
定义:
struct v4l2_subdev_pad_config {
struct v4l2_mbus_framefmt format;
struct v4l2_rect crop;
struct v4l2_rect compose;
struct v4l2_fract interval;
};
成员
format
crop
用于裁剪的
struct v4l2_rect
compose
用于合成的
struct v4l2_rect
interval
帧间隔
-
struct v4l2_subdev_stream_config¶
用于存储流配置。
定义:
struct v4l2_subdev_stream_config {
u32 pad;
u32 stream;
bool enabled;
struct v4l2_mbus_framefmt fmt;
struct v4l2_rect crop;
struct v4l2_rect compose;
struct v4l2_fract interval;
};
成员
pad
pad 编号
stream
stream number
enabled
是否已使用
v4l2_subdev_enable_streams()
启用流fmt
crop
用于裁剪的
struct v4l2_rect
compose
用于合成的
struct v4l2_rect
interval
帧间隔
描述
此结构存储流的配置。
-
struct v4l2_subdev_stream_configs¶
流配置的集合。
定义:
struct v4l2_subdev_stream_configs {
u32 num_configs;
struct v4l2_subdev_stream_config *configs;
};
成员
num_configs
config 中的条目数。
configs
-
struct v4l2_subdev_krouting¶
subdev 路由表
定义:
struct v4l2_subdev_krouting {
unsigned int len_routes;
unsigned int num_routes;
struct v4l2_subdev_route *routes;
};
成员
len_routes
routes 数组的长度,以路由为单位
num_routes
路由数
routes
struct v4l2_subdev_route
描述
此结构包含子设备的路由表。
-
struct v4l2_subdev_state¶
用于存储 subdev 状态信息。
定义:
struct v4l2_subdev_state {
struct mutex _lock;
struct mutex *lock;
struct v4l2_subdev *sd;
struct v4l2_subdev_pad_config *pads;
struct v4l2_subdev_krouting routing;
struct v4l2_subdev_stream_configs stream_configs;
};
成员
_lock
“锁”的默认值
lock
状态的互斥锁。可以由用户替换。
sd
状态相关的子设备
pads
routing
子设备的路由表
stream_configs
流配置(仅适用于 V4L2_SUBDEV_FL_STREAMS)
描述
只有在主参数的“which”字段设置为 V4L2_SUBDEV_FORMAT_TRY
时,才需要将此结构传递给 pad 操作。对于 V4L2_SUBDEV_FORMAT_ACTIVE
,传递 NULL
是安全的。
-
struct v4l2_subdev_pad_ops¶
v4l2-subdev pad 级别操作
定义:
struct v4l2_subdev_pad_ops {
int (*enum_mbus_code)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code);
int (*enum_frame_size)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse);
int (*enum_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval_enum *fie);
int (*get_fmt)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_format *format);
int (*set_fmt)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_format *format);
int (*get_selection)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel);
int (*set_selection)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel);
int (*get_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *interval);
int (*set_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *interval);
int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*s_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*g_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*query_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*dv_timings_cap)(struct v4l2_subdev *sd, struct v4l2_dv_timings_cap *cap);
int (*enum_dv_timings)(struct v4l2_subdev *sd, struct v4l2_enum_dv_timings *timings);
#ifdef CONFIG_MEDIA_CONTROLLER;
int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt);
#endif ;
int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd);
int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd);
int (*get_mbus_config)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_config *config);
int (*set_routing)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state,enum v4l2_subdev_format_whence which, struct v4l2_subdev_krouting *route);
int (*enable_streams)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, u32 pad, u64 streams_mask);
int (*disable_streams)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, u32 pad, u64 streams_mask);
};
成员
enum_mbus_code
用于 VIDIOC_SUBDEV_ENUM_MBUS_CODE() ioctl 处理程序代码的回调。
enum_frame_size
用于 VIDIOC_SUBDEV_ENUM_FRAME_SIZE() ioctl 处理程序代码的回调。
enum_frame_interval
用于 VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL() ioctl 处理程序代码的回调。
get_fmt
用于 VIDIOC_SUBDEV_G_FMT() ioctl 处理程序代码的回调。
set_fmt
用于 VIDIOC_SUBDEV_S_FMT() ioctl 处理程序代码的回调。
get_selection
用于 VIDIOC_SUBDEV_G_SELECTION() ioctl 处理程序代码的回调。
set_selection
用于 VIDIOC_SUBDEV_S_SELECTION() ioctl 处理程序代码的回调。
get_frame_interval
用于 VIDIOC_SUBDEV_G_FRAME_INTERVAL() ioctl 处理程序代码的回调。
set_frame_interval
用于 VIDIOC_SUBDEV_S_FRAME_INTERVAL() ioctl 处理程序代码的回调。
get_edid
用于 VIDIOC_SUBDEV_G_EDID() ioctl 处理程序代码的回调。
set_edid
用于 VIDIOC_SUBDEV_S_EDID() ioctl 处理程序代码的回调。
s_dv_timings
在子设备中设置自定义 dv 时序。当子设备能够在硬件中设置详细的时序信息以生成/检测视频信号时,将使用此功能。
g_dv_timings
在子设备中获取自定义 dv 时序。
query_dv_timings
用于 VIDIOC_QUERY_DV_TIMINGS() ioctl 处理程序代码的回调。
dv_timings_cap
用于 VIDIOC_SUBDEV_DV_TIMINGS_CAP() ioctl 处理程序代码的回调。
enum_dv_timings
用于 VIDIOC_SUBDEV_ENUM_DV_TIMINGS() ioctl 处理程序代码的回调。
link_validate
由媒体控制器代码使用,以检查属于管道的链接是否可用于流传输。
get_frame_desc
获取当前的低级别媒体总线帧参数。
set_frame_desc
设置低级别媒体总线帧参数,fd 数组可以由 subdev 驱动程序调整到设备功能。
get_mbus_config
获取远程子设备的媒体总线配置。媒体总线配置通常在子设备探测时从固件接口检索,立即应用于硬件,并最终由驱动程序调整。远程子设备(通常是视频接收器)应使用此操作来查询发送端总线配置,以便相应地调整自己的总线配置。调用者应确保他们从远程端获取尽可能最新的配置,可能会尽可能接近流传输时间调用此操作。如果已调用的 pad 索引无效或发生不可恢复的故障,则该操作将失败。在调用操作之前,已将 config 参数 memset 为 0。
set_routing
启用或禁用子设备路由表中描述的数据连接路由。实现此操作的 Subdevs 必须设置 V4L2_SUBDEV_FL_STREAMS 标志。
enable_streams
在给定的源 pad 上启用 streams_mask 中定义的流。实现此操作的 Subdevs 必须使用 subdev 核心提供的活动状态管理(通过在初始化时调用
v4l2_subdev_init_finalize()
启用)。不要直接调用,请改用v4l2_subdev_enable_streams()
。如果驱动程序仅支持单个流而不设置 V4L2_SUBDEV_CAP_STREAMS 子设备功能标志,则可以忽略 mask 参数。
disable_streams
在给定的源 pad 上禁用 streams_mask 中定义的流。实现此操作的 Subdevs 必须使用 subdev 核心提供的活动状态管理(通过在初始化时调用
v4l2_subdev_init_finalize()
启用)。不要直接调用,请改用v4l2_subdev_disable_streams()
。如果驱动程序仅支持单个流而不设置 V4L2_SUBDEV_CAP_STREAMS 子设备功能标志,则可以忽略 mask 参数。
-
struct v4l2_subdev_ops¶
Subdev 操作
定义:
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor;
const struct v4l2_subdev_pad_ops *pad;
};
成员
core
指向
struct v4l2_subdev_core_ops
的指针。可以为NULL
tuner
指向
struct v4l2_subdev_tuner_ops
的指针。可以为NULL
audio
指向
struct v4l2_subdev_audio_ops
的指针。可以为NULL
video
指向
struct v4l2_subdev_video_ops
的指针。可以为NULL
vbi
指向
struct v4l2_subdev_vbi_ops
的指针。可以为NULL
ir
指向
struct v4l2_subdev_ir_ops
的指针。可以为NULL
sensor
指向
struct v4l2_subdev_sensor_ops
的指针。可以为NULL
pad
指向
struct v4l2_subdev_pad_ops
的指针。可以为NULL
-
struct v4l2_subdev_internal_ops¶
V4L2 subdev 内部操作
定义:
struct v4l2_subdev_internal_ops {
int (*init_state)(struct v4l2_subdev *sd, struct v4l2_subdev_state *state);
int (*registered)(struct v4l2_subdev *sd);
void (*unregistered)(struct v4l2_subdev *sd);
int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
void (*release)(struct v4l2_subdev *sd);
};
成员
init_state
将 subdev 状态初始化为默认值
registered
在此 subdev 注册时调用。调用时,v4l2_dev 字段设置为正确的 v4l2_device。
unregistered
在此 subdev 注销时调用。调用时,v4l2_dev 字段仍设置为正确的 v4l2_device。
open
当应用程序打开 subdev 设备节点时调用。
close
当 subdev 设备节点关闭时调用。请注意,可能在 unregistered 之后调用 close!
release
当 subdev 设备的最后一个用户消失时调用。这发生在 unregistered 回调之后,并且当 v4l-subdevX 设备节点的最后一个打开的文件句柄关闭时。如果没有为此子设备创建设备节点,则在 unregistered 回调之后立即调用 release 回调。release 回调通常用于释放包含 v4l2_subdev 结构的内存。对于设置 V4L2_SUBDEV_FL_HAS_DEVNODE 标志的任何子设备,几乎肯定需要此回调。
描述
注意
永远不要从驱动程序中调用此函数,只有 v4l2 框架可以调用这些操作。
-
struct v4l2_subdev_platform_data¶
regulators 配置结构
定义:
struct v4l2_subdev_platform_data {
struct regulator_bulk_data *regulators;
int num_regulators;
void *host_priv;
};
成员
regulators
用于打开/关闭 subdevice 的可选 regulators
num_regulators
Regululators 的数量
host_priv
每个子设备的数据,特定于某个视频主机设备
-
struct v4l2_subdev¶
描述 V4L2 子设备
定义:
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER);
struct media_entity entity;
#endif;
struct list_head list;
struct module *owner;
bool owner_v4l2_dev;
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];
u32 grp_id;
void *dev_priv;
void *host_priv;
struct video_device *devnode;
struct device *dev;
struct fwnode_handle *fwnode;
struct list_head async_list;
struct list_head async_subdev_endpoint_list;
struct v4l2_async_notifier *subdev_notifier;
struct list_head asc_list;
struct v4l2_subdev_platform_data *pdata;
struct mutex *state_lock;
struct led_classdev *privacy_led;
struct v4l2_subdev_state *active_state;
u64 enabled_pads;
bool s_stream_enabled;
};
成员
entity
指向
struct media_entity
的指针list
子设备列表
owner
所有者与驱动程序的
struct device
所有者相同。owner_v4l2_dev
如果
sd->owner
与 v4l2_dev->dev 所有者的所有者匹配,则为 true。由v4l2_device_register_subdev()
初始化。flags
subdev 标志。可以是:
V4L2_SUBDEV_FL_IS_I2C
- 如果此 subdev 是 i2c 设备,则设置此标志;V4L2_SUBDEV_FL_IS_SPI
- 如果此 subdev 是 spi 设备,则设置此标志;V4L2_SUBDEV_FL_HAS_DEVNODE
- 如果此 subdev 需要设备节点,则设置此标志;V4L2_SUBDEV_FL_HAS_EVENTS
- 如果此 subdev 生成事件,则设置此标志。v4l2_dev
指向 struct
v4l2_device
的指针ops
指向 struct
v4l2_subdev_ops
的指针internal_ops
指向 struct
v4l2_subdev_internal_ops
的指针。永远不要从驱动程序中调用这些内部操作!ctrl_handler
此 subdev 的控制处理程序。可以为 NULL。
name
Sub-device 的名称。请注意,名称必须是唯一的。
grp_id
可用于对类似的 subdevs 进行分组。值是特定于驱动程序的
dev_priv
指向私有数据的指针
host_priv
指向设备附加的 subdev 使用的私有数据的指针。
devnode
subdev 设备节点
dev
指向物理设备的指针(如果有)
fwnode
subdev 的 fwnode_handle,通常与 dev->of_node->fwnode 或 dev->fwnode 相同(以非 NULL 者为准)。
async_list
将此 subdev 链接到全局 subdev_list 或 notifier->done_list 列表。
async_subdev_endpoint_list
struct v4l2_async_subdev_endpoint
的 async_subdev_endpoint_entry 中的列表条目。subdev_notifier
使用
v4l2_async_register_subdev_sensor()
为 sub- device 隐式注册的子设备通知程序。asc_list
异步连接列表,
struct v4l2_async_connection
.subdev_entry。pdata
subdevice 平台数据的公共部分
state_lock
指向用于所有 subdev 状态的锁的指针,由驱动程序设置。这是可选的。如果为 NULL,则每个状态实例将获得自己的锁。
privacy_led
指向传感器隐私 LED 的 LED classdev 的可选指针。
active_state
subdev 的活动状态(对于内部跟踪状态的 subdevs,为 NULL)。通过调用
v4l2_subdev_init_finalize()
初始化。enabled_pads
由
v4l2_subdev_enable_streams()
和v4l2_subdev_disable_streams()
辅助函数(用于回退情况)使用的已启用 pads 的位掩码。s_stream_enabled
跟踪是否已使用 s_stream 启用流传输。这仅用于 call_s_stream() 内部使用。
描述
subdev 驱动程序的每个实例都应创建此结构,无论是独立的还是嵌入在更大的结构中。
此结构应由 v4l2_subdev_init()
或其变体之一初始化:v4l2_spi_subdev_init()
、v4l2_i2c_subdev_init()
。
-
media_entity_to_v4l2_subdev¶
media_entity_to_v4l2_subdev (ent)
从嵌入的
struct media_entity
返回struct v4l2_subdev
。
Parameters
ent
指向
struct media_entity
的指针。
-
vdev_to_v4l2_subdev¶
vdev_to_v4l2_subdev (vdev)
从嵌入它的
struct video_device
返回struct v4l2_subdev
。
Parameters
vdev
指向
struct video_device
的指针
-
struct v4l2_subdev_fh¶
用于存储每个文件句柄的 subdev 信息
定义:
struct v4l2_subdev_fh {
struct v4l2_fh vfh;
struct module *owner;
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API);
struct v4l2_subdev_state *state;
u64 client_caps;
#endif;
};
成员
vfh
指向
struct v4l2_fh
的指针owner
指向此文件句柄所有者的模块指针
state
指向
struct v4l2_subdev_state
的指针client_caps
V4L2_SUBDEV_CLIENT_CAP_*
的位掩码
-
to_v4l2_subdev_fh¶
to_v4l2_subdev_fh (fh)
从嵌入它的
struct v4l2_fh
返回struct v4l2_subdev_fh
。
Parameters
fh
指向
struct v4l2_fh
的指针
-
void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)¶
设置 V4L2 dev 私有设备数据
Parameters
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针void *p
指向要存储的私有设备数据的指针。
-
void *v4l2_get_subdevdata(const struct v4l2_subdev *sd)¶
获取 V4L2 dev 私有设备数据
-
void v4l2_set_subdev_hostdata(struct v4l2_subdev *sd, void *p)¶
设置 V4L2 dev 私有主机数据
Parameters
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针void *p
指向要存储的私有数据的指针。
-
void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)¶
获取 V4L2 dev 私有数据
-
int v4l2_subdev_get_fwnode_pad_1_to_1(struct media_entity *entity, struct fwnode_endpoint *endpoint)¶
从 subdev fwnode 端点获取 pad 编号,假设 1:1 端口:pad
Parameters
struct media_entity *entity
指向 subdev 实体的指针
struct fwnode_endpoint *endpoint
指向已解析的 fwnode 端点的指针
描述
对于将端口号和 pad 索引 1:1 映射的子设备,此函数可以用作 .get_fwnode_pad 操作。 如果端点由子设备拥有,则该函数返回端点端口号。
成功时返回端点端口号,否则返回负错误代码。
-
int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, struct media_link *link, struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt)¶
验证媒体链接
Parameters
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针struct media_link *link
指向
struct media_link
的指针struct v4l2_subdev_format *source_fmt
指向
struct v4l2_subdev_format
的指针struct v4l2_subdev_format *sink_fmt
指向
struct v4l2_subdev_format
的指针
描述
此函数确保链接的源和目标上的宽度、高度和媒体总线像素代码相等。
-
int v4l2_subdev_link_validate(struct media_link *link)¶
验证媒体链接
Parameters
struct media_link *link
指向
struct media_link
的指针
描述
此函数调用 subdev 的 link_validate ops 来验证媒体链接是否对流式传输有效。 它还在内部调用 v4l2_subdev_link_validate_default()
以确保链接的源和目标上的宽度、高度和媒体总线像素代码相等。
该函数可用作 v4l2_subdev 实例的直接 media_entity_ops.link_validate
实现。 它支持子设备之间的所有链接,以及子设备和视频设备之间的链接,前提是视频设备也实现了它们的 media_entity_ops.link_validate
操作。
-
bool v4l2_subdev_has_pad_interdep(struct media_entity *entity, unsigned int pad0, unsigned int pad1)¶
子设备的 MC has_pad_interdep 实现
Parameters
struct media_entity *entity
指向
struct media_entity
的指针unsigned int pad0
第一个 pad 的 pad 编号
unsigned int pad1
第二个 pad 的 pad 编号
描述
此函数是 media_entity_operations.has_pad_interdep 操作的实现,适用于实现多路复用流 API 的子设备(如 V4L2_SUBDEV_FL_STREAMS 子设备标志所示)。
如果 pad0 和 pad1 之间存在活动路由,则它认为两个 pad 是相互依赖的。
-
struct v4l2_subdev_state *__v4l2_subdev_state_alloc(struct v4l2_subdev *sd, const char *lock_name, struct lock_class_key *key)¶
分配 v4l2_subdev_state
Parameters
struct v4l2_subdev *sd
指向
struct v4l2_subdev
的指针,为其分配状态。const char *lock_name
状态锁的名称
struct lock_class_key *key
锁的 lock_class_key
描述
当不再需要状态时,必须调用 __v4l2_subdev_state_free()
。
不要由驱动程序直接调用。
-
void __v4l2_subdev_state_free(struct v4l2_subdev_state *state)¶
释放 v4l2_subdev_state
Parameters
struct v4l2_subdev_state *state
要释放的 v4l2_subdev_state。
描述
不要由驱动程序直接调用。
-
v4l2_subdev_init_finalize¶
v4l2_subdev_init_finalize (sd)
完成子设备的初始化
Parameters
sd
子设备
描述
此函数完成子设备的初始化,包括为子设备分配活动状态。
在使用集中式活动状态的子设备驱动程序初始化 subdev struct 并调用 media_entity_pads_init()
之后,但在注册 subdev 之前,必须调用此函数。
在删除子设备时,用户必须调用 v4l2_subdev_cleanup()
。
-
void v4l2_subdev_cleanup(struct v4l2_subdev *sd)¶
释放子设备分配的资源
Parameters
struct v4l2_subdev *sd
子设备
描述
清除 V4L2 异步子设备。 如果资源已使用 v4l2_async_subdev_endpoint_add()
或 v4l2_subdev_init_finalize()
与之关联,则必须在释放子设备时调用此函数。
-
v4l2_subdev_state_get_format¶
v4l2_subdev_state_get_format (state, pad, ...)
获取指向流格式的指针
Parameters
state
子设备状态
pad
pad id
...
流 id(可选参数)
描述
这会为子设备状态中给定的 pad + 流返回指向 struct v4l2_mbus_framefmt
的指针。
对于不知道流的驱动程序,会返回相应 pad 的格式。 如果 pad 不存在,则返回 NULL。
-
v4l2_subdev_state_get_crop¶
v4l2_subdev_state_get_crop (state, pad, ...)
获取指向流裁剪矩形的指针
Parameters
state
子设备状态
pad
pad id
...
流 id(可选参数)
描述
这会为子设备状态中给定的 pad + 流返回指向裁剪矩形的指针。
对于不知道流的驱动程序,会返回相应 pad 的裁剪矩形。 如果 pad 不存在,则返回 NULL。
-
v4l2_subdev_state_get_compose¶
v4l2_subdev_state_get_compose (state, pad, ...)
获取指向流合成矩形的指针
Parameters
state
子设备状态
pad
pad id
...
流 id(可选参数)
描述
这会为子设备状态中给定的 pad + 流返回指向合成矩形的指针。
对于不知道流的驱动程序,会返回相应 pad 的合成矩形。 如果 pad 不存在,则返回 NULL。
-
v4l2_subdev_state_get_interval¶
v4l2_subdev_state_get_interval (state, pad, ...)
获取指向流帧间隔的指针
Parameters
state
子设备状态
pad
pad id
...
流 id(可选参数)
描述
这会为子设备状态中给定的 pad + 流返回指向帧间隔的指针。
对于不知道流的驱动程序,会返回相应 pad 的帧间隔。 如果 pad 不存在,则返回 NULL。
-
int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_format *format)¶
基于状态填充格式
Parameters
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
struct v4l2_subdev_format *format
指向
struct v4l2_subdev_format
的指针
描述
基于 format 结构中的信息填充 format->format 字段。
如果 subdev 驱动程序不需要在其 get_fmt op 中执行任何特殊操作,则支持活动状态的 subdev 驱动程序可以使用此函数来实现 v4l2_subdev_pad_ops.get_fmt。
成功时返回 0,否则返回错误值。
-
int v4l2_subdev_get_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *fi)¶
基于状态填充帧间隔
Parameters
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
struct v4l2_subdev_frame_interval *fi
指向
struct v4l2_subdev_frame_interval
的指针
描述
基于 fi 结构中的信息填充 fi->interval 字段。
如果 subdev 驱动程序不需要在其 get_frame_interval op 中执行任何特殊操作,则支持活动状态的 subdev 驱动程序可以使用此函数来实现 v4l2_subdev_pad_ops.get_frame_interval。
成功时返回 0,否则返回错误值。
-
int v4l2_subdev_set_routing(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, const struct v4l2_subdev_krouting *routing)¶
将给定路由设置为 subdev 状态
Parameters
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
const struct v4l2_subdev_krouting *routing
将复制到 subdev 状态的路由
描述
这将从状态中释放旧路由表(如果存在),为给定路由分配足够的空间,并复制路由。
这可以从 subdev 驱动程序的 set_routing op 中使用,在验证路由之后。
-
for_each_active_route¶
for_each_active_route (routing, route)
迭代路由表的所有活动路由
Parameters
routing
路由表
route
路由迭代器
-
int v4l2_subdev_set_routing_with_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, const struct v4l2_subdev_krouting *routing, const struct v4l2_mbus_framefmt *fmt)¶
将给定的路由和格式设置为 subdev 状态
Parameters
struct v4l2_subdev *sd
子设备
struct v4l2_subdev_state *state
子设备状态
const struct v4l2_subdev_krouting *routing
将复制到 subdev 状态的路由
const struct v4l2_mbus_framefmt *fmt
用于初始化所有流的格式
描述
这与 v4l2_subdev_set_routing 相同,但还会使用给定的格式初始化所有流。
-
int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing, u32 pad, u32 stream, u32 *other_pad, u32 *other_stream)¶
查找相反的流
Parameters
const struct v4l2_subdev_krouting *routing
用于查找另一侧的路由
u32 pad
pad id
u32 stream
流 id
u32 *other_pad
用于返回相反 pad 的指针
u32 *other_stream
用于返回相反流的指针
描述
此函数使用路由表查找与给定 pad + 流相反的 pad + 流。
如果调用方不需要该值,则 other_pad 和/或 other_stream 可以为 NULL。
成功时返回 0,如果未找到匹配的路由,则返回 -EINVAL。
-
struct v4l2_mbus_framefmt *v4l2_subdev_state_get_opposite_stream_format(struct v4l2_subdev_state *state, u32 pad, u32 stream)¶
获取指向相反流格式的指针
Parameters
struct v4l2_subdev_state *state
子设备状态
u32 pad
pad id
u32 stream
流 id
描述
这会为子设备状态中与给定 pad + 流相反的 pad + 流返回指向 struct v4l2_mbus_framefmt
的指针。
如果状态不包含给定的 pad + 流,则返回 NULL。
-
u64 v4l2_subdev_state_xlate_streams(const struct v4l2_subdev_state *state, u32 pad0, u32 pad1, u64 *streams)¶
将流从一个 pad 转换为另一个 pad
Parameters
const struct v4l2_subdev_state *state
子设备状态
u32 pad0
第一个 pad
u32 pad1
第二个 pad
u64 *streams
第一个 pad 上的流位掩码
描述
subdev 的 sink pad 上的流根据 subdev 状态路由表中的表达式路由到源 pad。 流编号在路由的 sink 和源侧不一定匹配。 此函数使用 state 中的路由表将 pad0 上的流(表示为 streams 中的位掩码)转换为 pad1 上的相应流。 它返回 pad1 上的流掩码,并使用在路由表中找到的流更新 streams。
pad0 和 pad1 必须是 sink 和源,顺序不限。
返回
路由到 pad0 上的 streams 的 pad1 的流的位掩码。
-
enum v4l2_subdev_routing_restriction¶
子设备内部路由限制
常量
V4L2_SUBDEV_ROUTING_NO_1_TO_N
输入流不应路由到多个输出流(流重复)
V4L2_SUBDEV_ROUTING_NO_N_TO_1
多个输入流不应路由到同一个输出流(流合并)
V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX
来自 sink pad 的所有流必须路由到单个源 pad
V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX
源 pad 上的所有流必须源自单个 sink pad
V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING
sink pad 不应包含多路复用流
V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING
源 pad 不应包含多路复用流
V4L2_SUBDEV_ROUTING_ONLY_1_TO_1
仅允许非重叠的 1 对 1 流路由(V4L2_SUBDEV_ROUTING_NO_1_TO_N 和 V4L2_SUBDEV_ROUTING_NO_N_TO_1 的组合)
V4L2_SUBDEV_ROUTING_NO_STREAM_MIX
来自 sink pad 的所有流必须路由到单个源 pad,并且该源 pad 不应从任何其他 sink pad 获取路由(V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX 和 V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX 的组合)
V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING
在源端或 sink 端都不允许使用多路复用流。
-
int v4l2_subdev_routing_validate(struct v4l2_subdev *sd, const struct v4l2_subdev_krouting *routing, enum v4l2_subdev_routing_restriction disallow)¶
验证路由是否符合驱动程序约束
Parameters
struct v4l2_subdev *sd
子设备
const struct v4l2_subdev_krouting *routing
要验证的路由
enum v4l2_subdev_routing_restriction disallow
路由限制
描述
这会验证给定的路由是否符合 disallow 约束。
成功时返回 0,否则返回错误值。
-
int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad, u64 streams_mask)¶
在 pad 上启用流
Parameters
struct v4l2_subdev *sd
子设备
u32 pad
pad
u64 streams_mask
要启用的流的位掩码
描述
此函数在子设备的源 pad 上启用流。 pad 由其索引标识,而流由 streams_mask 位掩码标识。 这允许一次在 pad 上启用多个流。
不允许启用已启用的流。 如果 streams_mask 包含已启用的流,则此函数将返回 -EALREADY,而不执行任何操作。
每个流启用仅适用于实现 .enable_streams() 和 .disable_streams() 操作的子设备。 对于其他子设备,此函数通过调用 .s_stream() 操作来实现最大程度的兼容性,该操作仅限于具有单个源 pad 的子设备。
不知道流的驱动程序应将 streams_mask 设置为 BIT_ULL(0)。
返回
0:成功
-EALREADY:streams_mask 中的一个流已启用
-EINVAL: pad 索引无效,或者不对应于源 pad
-EOPNOTSUPP: 无法回退到旧的 .s_stream() 操作,因为 subdev 有多个源 pad
-
int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad, u64 streams_mask)¶
禁用 pad 上的流
Parameters
struct v4l2_subdev *sd
子设备
u32 pad
pad
u64 streams_mask
要禁用的流的位掩码
描述
此函数禁用子设备的源 pad 上的流。 pad 由其索引标识,而流由 streams_mask 位掩码标识。这允许一次禁用 pad 上的多个流。
不允许禁用未启用的流。如果 streams_mask 包含禁用的流,则此函数返回 -EALREADY 而不执行任何操作。
每个流的禁用仅适用于实现 .enable_streams() 和 .disable_streams() 操作的 subdev。对于其他 subdev,此函数通过调用 .s_stream() 操作来实现尽力而为的兼容性,仅限于具有单个源 pad 的 subdev。
不知道流的驱动程序应将 streams_mask 设置为 BIT_ULL(0)。
返回
0:成功
-EALREADY: streams_mask 中的一个流未启用
-EINVAL: pad 索引无效,或者不对应于源 pad
-EOPNOTSUPP: 无法回退到旧的 .s_stream() 操作,因为 subdev 有多个源 pad
-
int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable)¶
使用 enable_streams 和 disable_streams 实现 subdev s_stream 操作的辅助函数
Parameters
struct v4l2_subdev *sd
子设备
int enable
启用或禁用流式传输
描述
实现流感知的 v4l2_subdev_pad_ops.enable_streams
和 v4l2_subdev_pad_ops.disable_streams
操作的子设备驱动程序可以使用此辅助函数来实现旧的 v4l2_subdev_video_ops.s_stream
操作。
此辅助函数只能由具有单个源 pad 的 subdev 使用。
返回
成功时为 0,否则为负错误代码。
-
void v4l2_subdev_lock_state(struct v4l2_subdev_state *state)¶
锁定 subdev 状态
Parameters
struct v4l2_subdev_state *state
子设备状态
描述
锁定给定的 subdev 状态。
使用后必须使用 v4l2_subdev_unlock_state()
解锁该状态。
-
void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state)¶
解锁 subdev 状态
Parameters
struct v4l2_subdev_state *state
子设备状态
描述
解锁给定的 subdev 状态。
-
void v4l2_subdev_lock_states(struct v4l2_subdev_state *state1, struct v4l2_subdev_state *state2)¶
锁定两个子设备状态
Parameters
struct v4l2_subdev_state *state1
一个子设备状态
struct v4l2_subdev_state *state2
另一个子设备状态
描述
锁定两个子设备的状态。
使用后必须使用 v4l2_subdev_unlock_states()
解锁这些状态。
这不同于对两个状态都调用 v4l2_subdev_lock_state()
,这样如果状态共享同一个锁,则锁只会被获取一次(因此不会发生死锁)。调用者负责确保锁将始终以相同的顺序获取。
-
void v4l2_subdev_unlock_states(struct v4l2_subdev_state *state1, struct v4l2_subdev_state *state2)¶
解锁两个子设备状态
Parameters
struct v4l2_subdev_state *state1
一个子设备状态
struct v4l2_subdev_state *state2
另一个子设备状态
描述
解锁两个子设备的状态。
这不同于对两个状态都调用 v4l2_subdev_unlock_state()
,这样如果状态共享同一个锁,则锁只会被释放一次。
-
struct v4l2_subdev_state *v4l2_subdev_get_unlocked_active_state(struct v4l2_subdev *sd)¶
检查活动 subdev 状态是否已解锁并返回它
Parameters
struct v4l2_subdev *sd
子设备
描述
返回子设备的活动状态,如果 subdev 不支持活动状态,则返回 NULL。如果状态不为 NULL,则调用 lockdep_assert_not_held() 以在状态被锁定时发出警告。
此函数用于例如当获取活动状态仅用于向前传递而无需访问状态字段时。
-
struct v4l2_subdev_state *v4l2_subdev_get_locked_active_state(struct v4l2_subdev *sd)¶
检查活动 subdev 状态是否已锁定并返回它
Parameters
struct v4l2_subdev *sd
子设备
描述
返回子设备的活动状态,如果 subdev 不支持活动状态,则返回 NULL。如果状态不为 NULL,则调用 lockdep_assert_held() 以在状态未锁定时发出警告。
当调用者知道活动状态已被锁定时,应使用此函数。
-
struct v4l2_subdev_state *v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)¶
锁定并返回子设备的活动 subdev 状态
Parameters
struct v4l2_subdev *sd
子设备
描述
返回子设备的锁定的活动状态,如果 subdev 不支持活动状态,则返回 NULL。
使用后必须使用 v4l2_subdev_unlock_state()
解锁该状态。
-
void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)¶
初始化子设备结构
Parameters
struct v4l2_subdev *sd
指向要初始化的
struct v4l2_subdev
的指针const struct v4l2_subdev_ops *ops
指向
struct v4l2_subdev_ops
的指针。
-
v4l2_subdev_call¶
v4l2_subdev_call (sd, o, f, args...)
调用 v4l2_subdev 的操作。
Parameters
sd
指向
struct v4l2_subdev
的指针o
包含 f 的
struct v4l2_subdev_ops
中元素的名称。那里的每个元素都对一组回调函数进行分组。f
要调用的回调函数。回调函数根据
struct v4l2_subdev_ops
中每个元素进行分组。args...
f 的参数。
例子
err = v4l2_subdev_call(sd, video, s_std, norm);
-
v4l2_subdev_call_state_active¶
v4l2_subdev_call_state_active (sd, o, f, args...)
调用 v4l2_subdev 的一个操作,该操作将状态作为参数,并将 subdev 的活动状态传递给它。
Parameters
sd
指向
struct v4l2_subdev
的指针o
包含 f 的
struct v4l2_subdev_ops
中元素的名称。那里的每个元素都对一组回调函数进行分组。f
要调用的回调函数。回调函数根据
struct v4l2_subdev_ops
中每个元素进行分组。args...
f 的参数。
描述
这类似于 v4l2_subdev_call()
,只是此版本只能用于将 subdev 状态作为参数的操作。该宏将在调用 op 之前获取活动状态并将其锁定,并在调用之后将其解锁。
-
v4l2_subdev_call_state_try¶
v4l2_subdev_call_state_try (sd, o, f, args...)
调用 v4l2_subdev 的一个操作,该操作将状态作为参数,并将 subdev 的新分配的 try 状态传递给它。
Parameters
sd
指向
struct v4l2_subdev
的指针o
包含 f 的
struct v4l2_subdev_ops
中元素的名称。那里的每个元素都对一组回调函数进行分组。f
要调用的回调函数。回调函数根据
struct v4l2_subdev_ops
中每个元素进行分组。args...
f 的参数。
描述
这类似于 v4l2_subdev_call_state_active()
,只是由于此版本分配了一个新状态,因此它仅适用于 V4L2_SUBDEV_FORMAT_TRY 用例。
注意
只有旧的非 MC 驱动程序可能需要此宏。
-
v4l2_subdev_has_op¶
v4l2_subdev_has_op (sd, o, f)
检查 subdev 是否定义了某个操作。
Parameters
sd
指向
struct v4l2_subdev
的指针o
回调函数 f 所属的
struct v4l2_subdev_ops
中的回调函数组。f
要检查其存在的回调函数。
-
void v4l2_subdev_notify_event(struct v4l2_subdev *sd, const struct v4l2_event *ev)¶
传递子设备的事件通知
Parameters
struct v4l2_subdev *sd
要为其传递事件的 subdev
const struct v4l2_event *ev
要传递的事件
描述
将指定的事件传递给所有订阅了 v42l subdev 事件队列的用户空间事件侦听器,以及使用通知回调的桥接驱动程序。通知回调的通知类型将是 V4L2_DEVICE_NOTIFY_EVENT
。
-
bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd)¶
返回 subdev 是否正在流式传输
Parameters
struct v4l2_subdev *sd
子设备
描述
v4l2_subdev_is_streaming()
告诉 subdev 当前是否正在流式传输。“流式传输”在此处表示是否已成功调用 .s_stream() 或 .enable_streams(),并且尚未禁用流式传输。
如果 subdev 实现了 .enable_streams(),则必须在保持活动状态锁定的情况下调用此函数。