内核模式设置 (KMS)¶
驱动程序必须通过调用 drmm_mode_config_init()
在 DRM 设备上初始化模式设置核心。该函数初始化 struct drm_device
mode_config 字段且永远不会失败。完成后,必须通过初始化以下字段来设置模式配置。
int min_width, min_height; int max_width, max_height; 帧缓冲区在像素单位中的最小和最大宽度和高度。
struct drm_mode_config_funcs
*funcs; 模式设置函数。
概述¶
KMS 显示流水线概述¶
KMS 呈现给用户空间的基本对象结构相当简单。帧缓冲区(由 struct drm_framebuffer
表示,请参阅 帧缓冲区抽象)馈送到平面中。平面由 struct drm_plane
表示,有关更多详细信息,请参阅 平面抽象。一个或多个(甚至没有)平面将其像素数据馈送到 CRTC(由 struct drm_crtc
表示,请参阅 CRTC 抽象)以进行混合。精确的混合步骤在 平面合成属性和相关章节中进行了更详细的解释。
对于输出路由,第一步是编码器(由 struct drm_encoder
表示,请参阅 编码器抽象)。这些实际上只是用于实现 KMS 驱动程序的辅助库的内部产物。除此之外,它们不必要地使用户空间更难以弄清楚 CRTC 和连接器之间的哪些连接是可能的,以及支持什么样的克隆,它们在用户空间 API 中没有任何作用。不幸的是,编码器已暴露给用户空间,因此此时无法删除它们。此外,公开的限制通常被驱动程序错误地设置,并且在许多情况下不足以表达实际限制。CRTC 可以连接到多个编码器,并且对于活动的 CRTC,必须至少有一个编码器。
显示链中的最终和真正的端点是连接器(由 struct drm_connector
表示,请参阅 连接器抽象)。连接器可以具有不同的可能编码器,但内核驱动程序会为每个连接器选择要使用的编码器。用例是 DVI,它可以在模拟和数字编码器之间切换。编码器也可以驱动多个不同的连接器。每个活动的编码器都有一个活动的连接器。
在内部,输出流水线稍微复杂一些,并且与今天的硬件更匹配
KMS 输出流水线¶
在内部,还有两个额外的辅助对象发挥作用。首先,为了能够共享编码器的代码(有时在同一 SoC 上,有时在芯片外),一个或多个 桥接器(由 struct drm_bridge
表示)可以链接到编码器。此链接是静态的且无法更改,这意味着需要在 CRTC 和任何编码器之间映射交叉开关(如果有)。通常对于带有桥接器的驱动程序,编码器级别上没有剩余代码。原子驱动程序可以省略所有编码器回调,从而基本上只留下一个虚拟路由对象,这对于向后兼容性是必需的,因为编码器已暴露给用户空间。
第二个对象用于面板,由 struct drm_panel
表示,请参阅 面板辅助程序参考。面板没有固定的绑定点,但通常链接到嵌入 struct drm_connector
的驱动程序私有结构。
请注意,目前桥接器链接以及与连接器和面板的交互仍在变化中,尚未完全解决。
KMS 核心结构和函数¶
-
struct drm_mode_config_funcs¶
基本驱动程序提供的模式设置函数
定义:
struct drm_mode_config_funcs {
struct drm_framebuffer *(*fb_create)(struct drm_device *dev,struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd);
const struct drm_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd);
enum drm_mode_status (*mode_valid)(struct drm_device *dev, const struct drm_display_mode *mode);
int (*atomic_check)(struct drm_device *dev, struct drm_atomic_state *state);
int (*atomic_commit)(struct drm_device *dev,struct drm_atomic_state *state, bool nonblock);
struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev);
void (*atomic_state_clear)(struct drm_atomic_state *state);
void (*atomic_state_free)(struct drm_atomic_state *state);
};
成员
fb_create
创建一个新的帧缓冲区对象。核心对请求的元数据进行基本检查,但大部分留给驱动程序。有关详细信息,请参阅
struct drm_mode_fb_cmd2
。为了验证像素格式和修饰符,驱动程序可以使用
drm_any_plane_has_format()
来确保至少一个平面支持请求的值。请注意,如果请求未指定实际使用的修饰符,即当 (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) == 0 时,驱动程序必须首先确定实际使用的修饰符。重要提示:这些用于旧用户空间的隐含修饰符必须存储在 struct
drm_framebuffer
中,包括所有相关元数据,如drm_framebuffer.pitches
和drm_framebuffer.offsets
,如果修饰符启用了四cc像素格式代码之外的附加平面。GETFB2 ioctl 需要这样做。如果参数被认为是有效的,并且底层内存管理器中的后备存储对象都存在,则驱动程序会分配一个新的
drm_framebuffer
结构,该结构被子类化以包含驱动程序特定的信息(如内部原生缓冲区对象引用)。它还需要填写所有相关的元数据,这应该通过调用drm_helper_mode_fill_fb_struct()
来完成。通过调用
drm_framebuffer_init()
完成初始化,该函数注册帧缓冲区并使其可供其他线程访问。返回值
一个新的帧缓冲区,其初始引用计数为 1,或者使用
ERR_PTR()
编码的负错误代码。get_format_info
允许驱动程序为特殊的 fb 布局(例如,带有辅助压缩控制平面的布局)返回自定义格式信息。
返回值
特定于给定 fb 元数据的格式信息,如果未找到,则返回 NULL。
mode_valid
设备特定的显示模式验证。可用于拒绝永远无法支持的模式。此处只能检查设备范围内的约束。应在每个特定对象的 .mode_valid() 钩子中检查 crtc/encoder/bridge/connector 特定的约束。
atomic_check
这是验证原子模式设置更新的唯一钩子。此函数必须拒绝硬件或驱动程序不支持的任何模式设置和状态更改。这包括但不限于
检查模式、帧缓冲区、缩放和放置要求等是否在硬件的限制范围内。
检查任何隐藏的共享资源是否未被过度订阅。这可以是共享 PLL、共享通道、整体内存带宽、显示 FIFO 空间(在平面之间或甚至 CRTC 之间共享)。
检查导出到用户空间的虚拟化资源是否未被过度订阅。由于各种原因,暴露比物理存在的更多平面、crtc 或编码器是有意义的。一个例子是双通道操作(如果在硬件中锁定,通常应该对用户空间隐藏,否则公开),其中一个平面可能需要 1 个硬件平面(如果它只在一个通道上),2 个硬件平面(当它跨越两个通道时),或者甚至与第二个平面共享一个硬件平面(如果在另一个通道处理的区域上请求了兼容的平面)。
检查任何过渡状态是否可能,并且如果请求,更新确实可以在 vblank 期间完成,而不会暂时禁用某些功能。
检查驱动程序或硬件可能具有的任何其他约束。
此回调还需要正确填写此更新中的
drm_crtc_state
,以确保drm_atomic_crtc_needs_modeset()
反映可能更新的性质,并且当且仅当无法在 CRTC 上的一个 vblank 内应用更新而不撕裂时才返回 true。核心使用该信息来拒绝需要完整模式设置的更新(即,使屏幕空白,或者至少暂停更新相当长的时间),如果用户空间在其请求中不允许这样做。驱动程序也不需要重复基本输入验证,例如对相应的旧入口点所做的验证。核心在调用此钩子之前执行此操作。
有关不必在此回调中检查的错误条件的详尽列表,请参阅 atomic_commit 的文档。
有关如何准确描述原子模式设置更新的信息,请参阅
struct drm_atomic_state
的文档。使用原子辅助程序的驱动程序可以使用
drm_atomic_helper_check()
或其导出的子函数之一来实现此钩子。返回值
成功时为 0,或者为以下负错误代码之一
-EINVAL,如果违反了上述任何约束。
-EDEADLK,当从尝试通过
drm_modeset_lock()
获取附加的drm_modeset_lock
时返回。-ENOMEM,如果由于缺少内存而导致分配附加状态子结构失败。
-EINTR、-EAGAIN 或 -ERESTARTSYS,如果应重新启动 IOCTL。这可能是由于挂起的信号,或者因为驱动程序需要完全退出以从 GPU 挂起等异常情况中恢复。从用户空间的角度来看,所有错误都受到同等对待。
atomic_commit
这是提交原子模式设置更新的唯一钩子。核心保证在调用此函数之前已成功调用 atomic_check,并且在此期间未进行任何更改。
有关如何准确描述原子模式设置更新的信息,请参阅
struct drm_atomic_state
的文档。使用原子辅助程序的驱动程序可以使用
drm_atomic_helper_commit()
或其导出的子函数之一来实现此钩子。非阻塞提交(如非阻塞参数所示)必须在此回调的上下文中执行任何可能导致提交失败的准备工作。唯一的例外是导致 -EIO 的硬件错误。但即使在这种情况下,驱动程序也必须确保显示通道至少正在运行,以避免在页面翻转不起作用时合成器崩溃。任何其他操作,特别是将更新提交到硬件,都应该在不阻塞调用者的情况下完成。对于不需要模式设置的更新,必须保证这一点。
驱动程序必须等待完成对新帧缓冲区的任何挂起渲染,然后才能执行翻转。如果底层缓冲区是共享的 dma-buf,它也应该等待来自其他驱动程序的任何挂起渲染。非阻塞提交不得在此回调的上下文中等待渲染。
应用程序可以请求在原子提交完成后收到通知。这些事件是按 CRTC 发生的,可以通过
drm_event
中提供给用户空间的 CRTC 索引来区分。drm 核心将在每个 CRTC 的
drm_crtc_state.event
中提供一个struct drm_event
。有关此事件的精确语义的更多详细信息,请参阅drm_crtc_state.event
的文档。注意
驱动程序不允许自行关闭通过原子提交成功启用的任何显示通道。这样做会导致合成器崩溃,如果突然拒绝页面翻转,因为通道已关闭。
返回值
成功时为 0,或者为以下负错误代码之一
-EBUSY,如果请求了非阻塞更新,并且有更早的更新挂起。驱动程序允许支持未完成更新的队列,但目前没有驱动程序支持这一点。请注意,如果请求了同步更新,驱动程序必须等待前面的更新完成,在这种情况下不允许提交失败。
-ENOMEM,如果驱动程序未能分配内存。具体来说,这可能发生在尝试固定帧缓冲区时,这只能在提交状态时完成。
-ENOSPC,作为更通用的 -ENOMEM 的细化,用于指示驱动程序已耗尽用于帧缓冲区的 vram、iommu 空间或类似的 GPU 地址空间。
-EIO,如果硬件完全死机。
-EINTR、-EAGAIN 或 -ERESTARTSYS,如果应重新启动 IOCTL。这可能是由于挂起的信号,或者因为驱动程序需要完全退出以从 GPU 挂起等异常情况中恢复。从用户空间的角度来看,所有错误都受到同等对待。
此列表是详尽的。具体来说,不允许此钩子返回 -EINVAL(任何无效请求都应在 atomic_check 中捕获)或 -EDEADLK(此函数不得获取附加的模式设置锁)。
atomic_state_alloc
想要子类化 struct
drm_atomic_state
以便能够轻松跟踪自己的驱动程序私有全局状态的驱动程序可以使用此可选钩子。如果实现了此钩子,驱动程序还必须实现 atomic_state_clear 和 atomic_state_free。不建议使用
drm_atomic_state
的子类化,而建议使用drm_private_state
和drm_private_obj
。返回值
成功时为新的
drm_atomic_state
,失败时为 NULL。atomic_state_clear
此钩子必须清除复制到传入的
drm_atomic_state
中的任何驱动程序私有状态。当调用者遇到drm_modeset_lock
死锁并且需要删除作为drm_modeset_backoff()
中实现的死锁避免舞蹈的一部分的所有已获取锁时,将调用此钩子。任何复制的状态都必须失效,因为并发的原子更新可能会更改它,并且 drm 原子接口始终将更新作为相对于当前状态的更改应用。
实现此功能的驱动程序必须调用
drm_atomic_state_default_clear()
以清除常见状态。不建议使用
drm_atomic_state
的子类化,而建议使用drm_private_state
和drm_private_obj
。atomic_state_free
此钩子需要驱动程序私有资源和
drm_atomic_state
本身。请注意,核心首先调用drm_atomic_state_clear()
以避免清除和释放钩子之间的代码重复。实现此功能的驱动程序必须调用
drm_atomic_state_default_release()
以释放常见资源。不建议使用
drm_atomic_state
的子类化,而建议使用drm_private_state
和drm_private_obj
。
描述
一些涉及驱动程序的全局(即,不是每个 CRTC、连接器等)模式设置函数。
-
struct drm_mode_config¶
模式配置控制结构
定义:
struct drm_mode_config {
struct mutex mutex;
struct drm_modeset_lock connection_mutex;
struct drm_modeset_acquire_ctx *acquire_ctx;
struct mutex idr_mutex;
struct idr object_idr;
struct idr tile_idr;
struct mutex fb_lock;
int num_fb;
struct list_head fb_list;
spinlock_t connector_list_lock;
int num_connector;
struct ida connector_ida;
struct list_head connector_list;
struct llist_head connector_free_list;
struct work_struct connector_free_work;
int num_encoder;
struct list_head encoder_list;
int num_total_plane;
struct list_head plane_list;
struct raw_spinlock panic_lock;
int num_crtc;
struct list_head crtc_list;
struct list_head property_list;
struct list_head privobj_list;
unsigned int min_width, min_height;
unsigned int max_width, max_height;
const struct drm_mode_config_funcs *funcs;
bool poll_enabled;
bool poll_running;
bool delayed_event;
struct delayed_work output_poll_work;
struct mutex blob_lock;
struct list_head property_blob_list;
struct drm_property *edid_property;
struct drm_property *dpms_property;
struct drm_property *path_property;
struct drm_property *tile_property;
struct drm_property *link_status_property;
struct drm_property *plane_type_property;
struct drm_property *prop_src_x;
struct drm_property *prop_src_y;
struct drm_property *prop_src_w;
struct drm_property *prop_src_h;
struct drm_property *prop_crtc_x;
struct drm_property *prop_crtc_y;
struct drm_property *prop_crtc_w;
struct drm_property *prop_crtc_h;
struct drm_property *prop_fb_id;
struct drm_property *prop_in_fence_fd;
struct drm_property *prop_out_fence_ptr;
struct drm_property *prop_crtc_id;
struct drm_property *prop_fb_damage_clips;
struct drm_property *prop_active;
struct drm_property *prop_mode_id;
struct drm_property *prop_vrr_enabled;
struct drm_property *dvi_i_subconnector_property;
struct drm_property *dvi_i_select_subconnector_property;
struct drm_property *dp_subconnector_property;
struct drm_property *tv_subconnector_property;
struct drm_property *tv_select_subconnector_property;
struct drm_property *legacy_tv_mode_property;
struct drm_property *tv_mode_property;
struct drm_property *tv_left_margin_property;
struct drm_property *tv_right_margin_property;
struct drm_property *tv_top_margin_property;
struct drm_property *tv_bottom_margin_property;
struct drm_property *tv_brightness_property;
struct drm_property *tv_contrast_property;
struct drm_property *tv_flicker_reduction_property;
struct drm_property *tv_overscan_property;
struct drm_property *tv_saturation_property;
struct drm_property *tv_hue_property;
struct drm_property *scaling_mode_property;
struct drm_property *aspect_ratio_property;
struct drm_property *content_type_property;
struct drm_property *degamma_lut_property;
struct drm_property *degamma_lut_size_property;
struct drm_property *ctm_property;
struct drm_property *gamma_lut_property;
struct drm_property *gamma_lut_size_property;
struct drm_property *suggested_x_property;
struct drm_property *suggested_y_property;
struct drm_property *non_desktop_property;
struct drm_property *panel_orientation_property;
struct drm_property *writeback_fb_id_property;
struct drm_property *writeback_pixel_formats_property;
struct drm_property *writeback_out_fence_ptr_property;
struct drm_property *hdr_output_metadata_property;
struct drm_property *content_protection_property;
struct drm_property *hdcp_content_type_property;
uint32_t preferred_depth, prefer_shadow;
bool quirk_addfb_prefer_xbgr_30bpp;
bool quirk_addfb_prefer_host_byte_order;
bool async_page_flip;
bool fb_modifiers_not_supported;
bool normalize_zpos;
struct drm_property *modifiers_property;
struct drm_property *async_modifiers_property;
struct drm_property *size_hints_property;
uint32_t cursor_width, cursor_height;
struct drm_atomic_state *suspend_state;
const struct drm_mode_config_helper_funcs *helper_private;
};
成员
mutex
这是大型的、可怕的模式设置 BKL,它保护未以其他方式保护的所有内容。范围不明确且模糊,尝试从其保护下删除任何内容并将其移动到范围更好的锁定中。
它保护的一个重要的事情是 acquire_ctx 的使用。
connection_mutex
这保护连接器状态和连接器到编码器到 CRTC 路由链。
对于原子驱动程序,具体来说,这保护
drm_connector.state
。acquire_ctx
原子驱动程序用于旧 IOCTL 的全局隐式获取上下文。已弃用,因为隐式锁定上下文使得无法使用驱动程序私有的
struct drm_modeset_lock
。它的用户必须持有 mutex。idr_mutex
用于 KMS ID 分配和管理的互斥锁。同时保护 object_idr 和 tile_idr。
object_idr
主 KMS ID 跟踪对象。对此 ID 使用所有 ID、fb、crtc、connector、模式 - 只有一个可以更轻松地生活。
tile_idr
使用此 idr 为平铺接收器分配新 ID,例如在某些高分辨率 DP MST 屏幕中使用。
fb_lock
互斥锁,用于保护 fb 全局 fb_list 和 num_fb。
num_fb
fb_list 上的条目数。
fb_list
所有
struct drm_framebuffer
的列表。connector_list_lock
保护 num_connector 和 connector_list 以及 connector_free_list。
num_connector
此设备上的连接器数。受 connector_list_lock 保护。
connector_ida
连接器索引的 ID 分配器。
connector_list
使用
drm_connector.head
链接的连接器对象列表。受 connector_list_lock 保护。仅使用drm_for_each_connector_iter()
和struct drm_connector_list_iter
遍历此列表。connector_free_list
使用
drm_connector.free_head
链接的连接器对象列表。受 connector_list_lock 保护。由drm_for_each_connector_iter()
和struct drm_connector_list_iter
使用,以使用 connector_free_work 安全地释放连接器。connector_free_work
用于清理 connector_free_list 的工作。
num_encoder
此设备上的编码器数。这在设备的整个生命周期内是不变的,因此不需要任何锁定。
encoder_list
与
drm_encoder.head
链接的编码器对象列表。此列表在设备的整个生命周期内是不变的,因此不需要任何锁。num_total_plane
此设备上的通用(即带有主/光标)平面数量。此数量在设备的整个生命周期内是不变的,因此不需要任何锁。
plane_list
与
drm_plane.head
链接的平面对象列表。此列表在设备的整个生命周期内是不变的,因此不需要任何锁。panic_lock
原始自旋锁,用于保护访问显示硬件或模式设置软件状态的关键代码段,紧急打印代码必须防止访问这些代码段。参见
drm_panic_trylock()
、drm_panic_lock()
和drm_panic_unlock()
。num_crtc
此设备上与
drm_crtc.head
链接的 CRTC 数量。此数量在设备的整个生命周期内是不变的,因此不需要任何锁。crtc_list
与
drm_crtc.head
链接的 CRTC 对象列表。此列表在设备的整个生命周期内是不变的,因此不需要任何锁。property_list
与
drm_property.head
链接的属性类型对象列表。此列表在设备的整个生命周期内是不变的,因此不需要任何锁。privobj_list
与
drm_private_obj.head
链接的私有对象列表。此列表在设备的整个生命周期内是不变的,因此不需要任何锁。min_width
此设备上的最小帧缓冲区像素宽度
min_height
此设备上的最小帧缓冲区像素高度
max_width
此设备上的最大帧缓冲区像素宽度
max_height
此设备上的最大帧缓冲区像素高度
funcs
核心驱动程序提供的模式设置函数
poll_enabled
跟踪此设备的轮询支持
poll_running
跟踪此设备的轮询状态
delayed_event
跟踪此设备的延迟轮询 uevent 传递
output_poll_work
进程上下文中轮询的延迟工作
blob_lock
用于 blob 属性分配和管理的互斥锁,保护 property_blob_list 和
drm_file.blobs
。property_blob_list
与
drm_property_blob.head
链接的所有 blob 属性对象的列表。受 blob_lock 保护。edid_property
默认连接器属性,用于保存当前连接的接收器的 EDID(如果有)。
dpms_property
默认连接器属性,用于控制连接器的 DPMS 状态。
path_property
默认连接器属性,用于保存端口的 DP MST 路径。
tile_property
默认连接器属性,用于存储平铺屏幕的平铺位置,适用于需要使用多个 CRTC 驱动的接收器。
link_status_property
连接器链接状态的默认连接器属性
plane_type_property
默认平面属性,用于区分平面 CURSOR、PRIMARY 和 OVERLAY 的旧用法。
prop_src_x
用于连接的
drm_framebuffer
中平面源位置的默认原子平面属性。prop_src_y
用于连接的
drm_framebuffer
中平面源位置的默认原子平面属性。prop_src_w
用于连接的
drm_framebuffer
中平面源位置的默认原子平面属性。prop_src_h
用于连接的
drm_framebuffer
中平面源位置的默认原子平面属性。prop_crtc_x
用于
drm_crtc
上显示的平面目标位置的默认原子平面属性。prop_crtc_y
用于
drm_crtc
上显示的平面目标位置的默认原子平面属性。prop_crtc_w
用于
drm_crtc
上显示的平面目标位置的默认原子平面属性。prop_crtc_h
用于
drm_crtc
上显示的平面目标位置的默认原子平面属性。prop_fb_id
用于指定
drm_framebuffer
的默认原子平面属性。prop_in_fence_fd
表示平面传入围栏的同步文件 fd。
prop_out_fence_ptr
表示 CRTC 传出围栏的同步文件 fd 指针。用户空间应提供指向 s32 类型值的指针,然后将该指针转换为 u64。
prop_crtc_id
用于指定
drm_crtc
的默认原子平面属性。prop_fb_damage_clips
可选平面属性,用于标记平面上附加到平面的帧缓冲区的帧缓冲区坐标中的损坏区域。
blob 数据的布局只是一个
drm_mode_rect
数组。与平面源坐标不同,损坏剪辑不是 16.16 定点。prop_active
控制活动状态的默认原子 CRTC 属性,这是原子驱动程序中 DPMS 的简化实现。
prop_mode_id
用于设置 CRTC 模式的默认原子 CRTC 属性。0 模式表示 CRTC 已完全禁用 - 所有连接器必须关闭,并且活动状态必须设置为禁用。
prop_vrr_enabled
默认原子 CRTC 属性,用于指示是否应在 CRTC 上启用可变刷新率。
dvi_i_subconnector_property
可选 DVI-I 属性,用于区分模拟或数字模式。
dvi_i_select_subconnector_property
可选 DVI-I 属性,用于在模拟或数字模式之间进行选择。
dp_subconnector_property
可选 DP 属性,用于区分不同的 DP 下游端口类型。
tv_subconnector_property
可选 TV 属性,用于区分不同的 TV 连接器类型。
tv_select_subconnector_property
可选 TV 属性,用于在不同的 TV 连接器类型之间进行选择。
legacy_tv_mode_property
可选 TV 属性,用于选择输出 TV 模式。
已由 tv_mode_property 取代
tv_mode_property
可选 TV 属性,用于选择连接器上的 TV 标准输出。
tv_left_margin_property
可选 TV 属性,用于设置左边距(以像素为单位表示)。
tv_right_margin_property
可选 TV 属性,用于设置右边距(以像素为单位表示)。
tv_top_margin_property
可选 TV 属性,用于设置右边距(以像素为单位表示)。
tv_bottom_margin_property
可选 TV 属性,用于设置右边距(以像素为单位表示)。
tv_brightness_property
可选 TV 属性,用于设置亮度。
tv_contrast_property
可选 TV 属性,用于设置对比度。
tv_flicker_reduction_property
可选 TV 属性,用于控制闪烁减少模式。
tv_overscan_property
可选 TV 属性,用于控制过扫描设置。
tv_saturation_property
可选 TV 属性,用于设置饱和度。
tv_hue_property
可选 TV 属性,用于设置色调。
scaling_mode_property
可选连接器属性,用于控制放大,主要用于内置面板。
aspect_ratio_property
可选连接器属性,用于控制 HDMI 信息帧宽高比设置。
content_type_property
可选连接器属性,用于控制 HDMI 信息帧内容类型设置。
degamma_lut_property
可选 CRTC 属性,用于设置用于将帧缓冲区的颜色转换为线性伽玛的 LUT。
degamma_lut_size_property
可选 CRTC 属性,用于驱动程序支持的去伽玛 LUT 的大小(只读)。
ctm_property
可选 CRTC 属性,用于设置在去伽玛 LUT 中查找后用于转换颜色的矩阵。
gamma_lut_property
可选 CRTC 属性,用于设置在 CTM 矩阵之后用于将颜色转换为连接屏幕的伽玛空间的 LUT。
gamma_lut_size_property
可选 CRTC 属性,用于驱动程序支持的伽玛 LUT 的大小(只读)。
suggested_x_property
可选连接器属性,提示输出在主机屏幕上的位置。
suggested_y_property
可选连接器属性,提示输出在主机屏幕上的位置。
non_desktop_property
可选连接器属性,提示设备不是标准显示器,并且不应在其上显示控制台/桌面。
panel_orientation_property
可选连接器属性,指示液晶面板在外壳内的安装方式(例如,正常或倒置)。
writeback_fb_id_property
用于回写连接器的属性,存储输出帧缓冲区的 ID。另请参见:
drm_writeback_connector_init()
writeback_pixel_formats_property
用于回写连接器的属性,存储回写引擎支持的像素格式数组(只读)。另请参见:
drm_writeback_connector_init()
writeback_out_fence_ptr_property
用于回写连接器的属性,fd 指针表示回写连接器的传出围栏。用户空间应提供指向 s32 类型值的指针,然后将该指针转换为 u64。另请参见:
drm_writeback_connector_init()
hdr_output_metadata_property
包含 HDR 元数据的连接器属性。这将由用户空间合成器基于 HDR 内容提供
content_protection_property
用于内容保护的 DRM ENUM 属性。参见
drm_connector_attach_content_protection_property()
。hdcp_content_type_property
用于受保护内容的 DRM ENUM 属性。
preferred_depth
首选 RBG 像素深度,由 fb 辅助函数使用
prefer_shadow
提示用户空间首选阴影 fb 渲染
quirk_addfb_prefer_xbgr_30bpp
用于旧 ADDFB 的特殊 hack,以保持 nouveau 用户空间正常工作。应仅由 nouveau 内核驱动程序设置。
quirk_addfb_prefer_host_byte_order
如果设置为 true,则 drm_mode_addfb() 在调用 drm_mode_addfb2() 时将选择主机字节顺序 pixel_format。这应该是 drm_mode_addfb() 从一开始就应该工作的方式。但事实并非如此,因此我们最终在内核和用户空间驱动程序中都存在怪癖,以处理错误的行为。简单地无条件修复 drm_mode_addfb() 会破坏这些驱动程序,因此在此处添加一个怪癖位以允许驱动程序选择加入。
async_page_flip
此设备是否支持在主平面上进行异步翻转?
fb_modifiers_not_supported
设置此标志后,DRM 设备将不会向用户空间公开修饰符支持。这仅由通过启发式方法推断缓冲区布局而不使用修饰符的旧驱动程序使用。新驱动程序不应设置此标志。
normalize_zpos
如果为 true,则 DRM 核心将调用
drm_atomic_normalize_zpos()
作为来自drm_atomic_helper_check()
的原子模式检查的一部分modifiers_property
用于列出支持的修饰符/格式组合的平面属性。
async_modifiers_property
用于列出异步翻转支持的修饰符/格式组合的平面属性。
size_hints_property
平面 SIZE_HINTS 属性。
cursor_width
提示用户空间最大光标宽度
cursor_height
提示用户空间最大光标高度
suspend_state
挂起时的原子状态。由
drm_mode_config_helper_suspend()
设置,并由drm_mode_config_helper_resume()
清除。helper_private
中间层私有数据
描述
核心模式资源跟踪结构。驱动程序枚举的所有 CRTC、编码器和连接器都将添加到此处,全局属性也是如此。一些全局限制也在这里,例如维度限制。
帧缓冲区大小是指 CRTC 可以显示的虚拟屏幕。这可能与编程的物理分辨率不同。存储在 min_width 和 min_height 中的最小宽度和高度描述了帧缓冲区的最小尺寸。它与最小可编程分辨率相关。存储在 max_width 中的最大宽度通常受两个相邻扫描线之间的最大间距限制。存储在 max_height 中的最大高度通常仅受可寻址视频内存量的限制。对于没有实际最大值的硬件,驱动程序应选择一个合理的默认值。
另请参见 DRM_SHADOW_PLANE_MAX_WIDTH 和 DRM_SHADOW_PLANE_MAX_HEIGHT。
-
int drm_mode_config_init(struct drm_device *dev)¶
DRM mode_configuration 结构初始化
参数
struct drm_device *dev
DRM 设备
描述
这是 drmm_mode_config_init()
的非托管版本,适用于仍显式调用 drm_mode_config_cleanup()
的驱动程序。
FIXME:此函数已弃用,应将驱动程序转换为 drmm_mode_config_init()
。
-
void drm_mode_config_reset(struct drm_device *dev)¶
调用 ->reset 回调
参数
struct drm_device *dev
drm 设备
描述
此函数调用所有 crtc、编码器和连接器的 ->reset 回调。驱动程序可以在其驱动程序加载或恢复代码中使用此功能来重置硬件和软件状态。
-
int drmm_mode_config_init(struct drm_device *dev)¶
托管的 DRM mode_configuration 结构初始化
参数
struct drm_device *dev
DRM 设备
描述
初始化 dev 的 mode_config 结构,用于跟踪 dev 的图形配置。
由于这会初始化模式设置锁,因此不可能进行锁定。这没有问题,因为这应该在初始化时以单线程方式进行。驱动程序有责任确保此保证。
清理通过使用 drmm_add_action()
注册 drm_mode_config_cleanup 来自动处理。
返回
成功时返回 0,失败时返回负错误值。
-
void drm_mode_config_cleanup(struct drm_device *dev)¶
释放 DRM mode_config 信息
参数
struct drm_device *dev
DRM 设备
描述
释放与此 DRM 设备关联的所有连接器和 CRTC,然后释放帧缓冲区和关联的缓冲区对象。
请注意,由于这/应该/在驱动程序/设备拆卸时以单线程方式进行,因此不需要锁定。驱动程序的工作是确保此保证实际上成立。
FIXME:使用托管的 drmm_mode_config_init()
后,驱动程序不再需要显式调用此函数。
模式设置基本对象抽象¶
模式对象和属性¶
所有 KMS 对象的基本结构是 struct drm_mode_object
。它提供的基本服务之一是跟踪属性,这对于原子 IOCTL(请参见 原子模式设置)尤其重要。这里有点令人惊讶的是,属性不是直接在每个对象上实例化的,而是独立的模式对象本身,由 struct drm_property
表示,它仅指定属性的类型和值范围。可以使用 drm_object_attach_property()
将任何给定属性多次附加到不同的对象。
-
struct drm_mode_object¶
模式设置对象的基本结构
定义:
struct drm_mode_object {
uint32_t id;
uint32_t type;
struct drm_object_properties *properties;
struct kref refcount;
void (*free_cb)(struct kref *kref);
};
成员
id
用户空间可见的标识符
type
对象的类型,为 DRM_MODE_OBJECT_* 之一
properties
附加到此对象的属性,包括值
refcount
具有动态生命周期的对象的引用计数
free_cb
释放函数回调,仅为具有动态生命周期的对象设置
描述
用户空间可见的模式设置对象的基本结构。可以使用 drm_mode_object_find()
查找对象。除了 id 和 type 等基本 uapi 接口属性之外,它还提供两项服务
它跟踪附加的属性及其值。这由
drm_crtc
、drm_plane
和drm_connector
使用。通过在对象对用户空间可见之前调用drm_object_attach_property()
来附加属性。对于具有动态生命周期的对象(由非 NULL 的 free_cb 指示),它通过
drm_mode_object_get()
和drm_mode_object_put()
提供引用计数。这被drm_framebuffer
、drm_connector
和drm_property_blob
使用。这些对象提供了专门的引用计数包装器。
-
struct drm_object_properties¶
用于
drm_mode_object
的属性跟踪
定义:
struct drm_object_properties {
int count;
struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
uint64_t values[DRM_OBJECT_MAX_PROPERTY];
};
成员
count
有效属性的数量,必须小于或等于 DRM_OBJECT_MAX_PROPERTY。
properties
指向
drm_property
的指针数组。注意:如果我们开始动态销毁属性(即不在
drm_mode_config_cleanup()
时),那么我们必须更好地将属性从模式对象分离,以避免悬挂属性指针values
用于存储属性值的数组,与 properties 匹配。不要直接读取/写入值,而是使用
drm_object_property_get_value()
和drm_object_property_set_value()
。请注意,原子驱动程序不会在此数组中存储可变属性,而只会将解码后的值存储在相应的状态结构中。解码使用
drm_crtc.atomic_get_property
和drm_crtc.atomic_set_property
钩子对于struct drm_crtc
完成。 对于struct drm_plane
, 钩子是drm_plane_funcs.atomic_get_property
和drm_plane_funcs.atomic_set_property
。对于struct drm_connector
, 钩子是drm_connector_funcs.atomic_get_property
和drm_connector_funcs.atomic_set_property
。因此,原子驱动程序不应在可变对象上使用
drm_object_property_set_value()
和drm_object_property_get_value()
,即那些没有设置 DRM_MODE_PROP_IMMUTABLE 标志的对象。对于原子驱动程序,属性的默认值存储在此数组中,因此可以使用 drm_object_property_get_default_value 检索它。
-
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, struct drm_file *file_priv, uint32_t id, uint32_t type)¶
查找具有静态生命周期的 drm 对象
参数
struct drm_device *dev
drm 设备
struct drm_file *file_priv
drm 文件
uint32_t id
模式对象的 ID
uint32_t type
模式对象的类型
描述
此函数用于查找模式设置对象。它将获取引用计数的对象的引用。必须通过调用 drm_mode_object_put()
再次删除此引用。
-
void drm_mode_object_put(struct drm_mode_object *obj)¶
释放模式对象引用
参数
struct drm_mode_object *obj
DRM 模式对象
描述
如果对象是一个引用计数的模式设置对象,此函数会递减对象的引用计数。 它对任何其他对象都是空操作。 这用于删除通过 drm_mode_object_get()
获取的引用。
-
void drm_mode_object_get(struct drm_mode_object *obj)¶
获取模式对象引用
参数
struct drm_mode_object *obj
DRM 模式对象
描述
如果对象是一个引用计数的模式设置对象,此函数会递增对象的引用计数。 它对任何其他对象都是空操作。 应通过调用 drm_mode_object_put()
再次删除引用。
-
void drm_object_attach_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t init_val)¶
将属性附加到模式设置对象
参数
struct drm_mode_object *obj
drm 模式设置对象
struct drm_property *property
要附加的属性
uint64_t init_val
属性的初始值
描述
这会将给定的属性与给定的初始值附加到模式设置对象。目前,此函数不会失败,因为属性存储在静态大小的数组中。
请注意,所有属性必须在对象本身被注册并可从用户空间访问之前附加。
-
int drm_object_property_set_value(struct drm_mode_object *obj, struct drm_property *property, uint64_t val)¶
设置属性的值
参数
struct drm_mode_object *obj
要设置属性值的 drm 模式对象
struct drm_property *property
要设置的属性
uint64_t val
属性应设置为的值
描述
此函数设置给定对象上的给定属性。此函数仅更改属性的软件状态,它不会调用驱动程序的 ->set_property 回调。
请注意,原子驱动程序应该不需要调用此函数,核心将确保通过适当的 ->atomic_get_property 回调将值报告回用户空间的一致性。只有传统驱动程序才应调用此函数来更新跟踪的值(在应用钳制和其他限制后)。
返回
成功时为零,失败时为错误代码。
-
int drm_object_property_get_value(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val)¶
检索属性的值
参数
struct drm_mode_object *obj
从中获取属性值的 drm 模式对象
struct drm_property *property
要检索的属性
uint64_t *val
属性值的存储
描述
此函数检索给定属性的软件状态。由于没有驱动程序回调来检索当前属性值,因此根据驱动程序和属性,这可能与硬件不同步。
原子驱动程序永远不应直接调用此函数,核心将通过各种 ->atomic_get_property 回调读取属性值。
返回
成功时为零,失败时为错误代码。
-
int drm_object_property_get_default_value(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val)¶
在原子模式下检索属性的默认值。
参数
struct drm_mode_object *obj
从中获取属性值的 drm 模式对象
struct drm_property *property
要检索的属性
uint64_t *val
属性值的存储
描述
此函数检索传递给 drm_object_attach_property 的给定属性的默认状态
只有原子驱动程序才应直接调用此函数,因为对于非原子驱动程序,它将返回当前值。
返回
成功时为零,失败时为错误代码。
原子模式设置¶
模式对象和属性¶
原子提供了事务性的模式设置(包括 plane)更新,但与通常的 try-commit 和回滚事务性方法略有不同
首先,当提交将失败时,不允许硬件更改。这使我们能够实现 DRM_MODE_ATOMIC_TEST_ONLY 模式,该模式允许用户空间探索某些配置是否有效。
这仍然允许仅设置和回滚软件状态,从而简化了现有驱动程序的转换。但是,审计驱动程序的 atomic_check 代码的正确性变得非常困难:在各处的数据结构中回滚更改很难做好。
最后,为了向后兼容并支持所有用例,原子更新需要是增量的并且能够并行执行。硬件并不总是允许它,但在可能的情况下,不同 CRTC 上的平面更新不应相互干扰,并且不应由于不同 CRTC 上的输出路由更改而停滞。
综上所述,原子设计有两个后果
总体状态分为每个对象的状态结构:
struct drm_plane_state
用于 plane,struct drm_crtc_state
用于 CRTC 和struct drm_connector_state
用于 connector。 这些是唯一具有用户空间可见和可设置状态的对象。 对于内部状态,驱动程序可以通过嵌入来子类化这些结构,或者为其全局共享的硬件功能添加全新的状态结构,请参见struct drm_private_state
.原子更新在
drm_atomic_state
容器中被组装和验证为完全独立的结构堆。驱动程序私有状态结构也在同一结构中被跟踪;请参见下一章。只有在提交状态时,它才会被应用于驱动程序和模式设置对象。这样,回滚更新就归结为释放内存和取消引用诸如帧缓冲区的对象。
原子状态结构的锁定在内部使用 struct drm_modeset_lock
。作为一般规则,不应将锁定暴露给驱动程序,而是应由任何复制或窥视状态的函数自动获取正确的锁定,例如 drm_atomic_get_crtc_state()
。锁定仅保护软件数据结构,将状态更改提交到硬件的顺序使用 struct drm_crtc_commit
进行排序。
请继续阅读本章以及 原子模式设置助手函数参考 以获得有关特定主题的更详细的报道。
处理驱动程序私有状态¶
通常,在原子模式设置 api 中暴露给用户空间的 DRM 对象(drm_connector
, drm_crtc
和 drm_plane
) 不能完全映射到底层硬件。特别是对于任何类型的共享资源(例如,在 planes 或 CRTC 组之间共享的共享时钟、缩放器单元、带宽和 fifo 限制等等),将这些建模为独立对象是有意义的。然后,驱动程序需要为这些私有对象(因为未暴露给用户空间)执行类似的状态跟踪和提交排序,原子核心和 helpers 已经为 connectors、planes 和 CRTC 提供了这些功能。
为了使驱动程序更容易,原子核心提供了一些支持,以使用 struct drm_private_obj
和相关的状态 struct drm_private_state
来跟踪驱动程序私有状态对象。
类似于用户空间暴露的对象,可以通过调用 drm_atomic_get_private_obj_state()
获取私有状态结构。 这也负责锁定,因此驱动程序不需要直接调用 drm_modeset_lock()
。 不处理实际硬件状态提交的顺序,驱动程序可能需要根据需要在 drm_private_state
的子类化结构中跟踪 struct drm_crtc_commit
,例如类似于 drm_plane_state.commit
。另请参见 drm_atomic_state.fake_commit
。
可以使用 for_each_oldnew_private_obj_in_state()
, for_each_new_private_obj_in_state()
和 for_each_old_private_obj_in_state()
迭代 drm_atomic_state
更新中包含的所有私有状态结构。建议驱动程序为它们拥有的每种驱动程序私有状态对象包装这些函数,并使用 for_each_if() 过滤 drm_private_obj.funcs
,至少如果他们想要迭代给定类型的所有对象。
先前处理驱动程序私有状态的方法是通过子类化 struct drm_atomic_state
。但是,由于这鼓励了非标准方式来实现原子所需的 check/commit 分裂(例如,使用“检查和回滚或提交而不是”而不是“复制状态,检查,然后提交或释放复制状态),因此它已被弃用,而赞成使用 drm_private_state
。
原子模式设置功能参考¶
-
struct drm_crtc_commit¶
跟踪 CRTC 上的模式设置提交
定义:
struct drm_crtc_commit {
struct drm_crtc *crtc;
struct kref ref;
struct completion flip_done;
struct completion hw_done;
struct completion cleanup_done;
struct list_head commit_entry;
struct drm_pending_vblank_event *event;
bool abort_completion;
};
成员
crtc
此提交的 DRM CRTC。
ref
此结构的引用计数。 需要允许阻塞完成而没有完成消失的风险。
flip_done
当硬件翻转到新的缓冲区集时,将发出信号。 与将此提交的 drm 事件发送到用户空间或发出 out-fence 信号时同时发出信号。 请注意,对于大多数硬件,在大多数情况下,这发生在 hw_done 发出信号之后。
此阶段的完成通过在
drm_crtc_state.event
上调用drm_crtc_send_vblank_event()
来隐式发出信号。hw_done
当此次提交的所有硬件寄存器更改都已写入后,将发出信号。尤其是在禁用管道时,这可能比 flip_done 晚得多,因为 flip_done 可以在屏幕变黑时发出信号,而完全关闭管道需要更多的寄存器 I/O。
请注意,这不需要包括单独的引用计数资源,如后备存储缓冲区锁定或运行时电源管理。
驱动程序应调用
drm_atomic_helper_commit_hw_done()
以发出此阶段完成的信号。cleanup_done
在通过调用
drm_atomic_helper_cleanup_planes()
清理旧缓冲区后,将发出信号。由于这只能在 vblank 等待完成后发生,因此可能会稍晚一些。此完成对于限制更新并避免硬件更新过多地超前于缓冲区清理非常有用。驱动程序应调用
drm_atomic_helper_commit_cleanup_done()
以发出此阶段完成的信号。commit_entry
每个 CRTC 的
drm_crtc.commit_list
上的条目。受 $drm_crtc.commit_lock 保护。event
指向清除私有事件的
drm_pending_vblank_event
指针。abort_completion
在
drm_atomic_helper_setup_commit()
为 $drm_crtc_state.event 的完成获取第二个引用后设置的标志。它被 free 代码用于在提交失败时删除第二个引用。
描述
此结构用于跟踪每个 CRTC 上挂起的模式设置更改和原子提交。由于更新列表永远不应阻塞,因此此结构是引用计数的,以允许等待者安全地等待事件完成,而无需持有任何锁。
它总共有 3 个不同的事件,以允许在未完成的更新之间进行细粒度的同步
atomic commit thread hardware
write new state into hardware ----> ...
signal hw_done
switch to new state on next
... v/hblank
wait for buffers to show up ...
... send completion irq
irq handler signals flip_done
cleanup old buffers
signal cleanup_done
wait for flip_done <----
clean up atomic state
需要了解的重要一点是 cleanup_done
是终端事件,但 flip_done
和 hw_done
之间的顺序完全取决于特定的驱动程序和模式设置状态更改。
有关如何使用此功能的实现,请参阅原子助手库中的 drm_atomic_helper_setup_commit()
。
另请参阅 drm_crtc_commit_wait()
。
-
struct drm_private_state_funcs¶
私有对象的原子状态函数
定义:
struct drm_private_state_funcs {
struct drm_private_state *(*atomic_duplicate_state)(struct drm_private_obj *obj);
void (*atomic_destroy_state)(struct drm_private_obj *obj, struct drm_private_state *state);
void (*atomic_print_state)(struct drm_printer *p, const struct drm_private_state *state);
};
成员
atomic_duplicate_state
复制私有对象的当前状态并返回它。在 obj->state 初始化之前调用此方法是一个错误。
返回值
复制的原子状态,或者当 obj->state 未初始化或分配失败时为 NULL。
atomic_destroy_state
释放使用 atomic_duplicate_state 创建的私有对象状态。
atomic_print_state
如果驱动程序子类化
struct drm_private_state
,它应该实现这个可选的 hook 来打印额外的驱动程序特定状态。不要直接调用此函数,请改用 drm_atomic_private_obj_print_state()。
描述
这些 hook 被原子助手用来创建、交换和销毁私有对象的状态。该结构本身用作 vtable 来识别关联的私有对象类型。需要添加到原子状态的每种私有对象类型都应实现这些 hook,并将指向其 drm_private_state_funcs 结构的指针传递给 drm_atomic_get_private_obj_state()
。
-
struct drm_private_obj¶
驱动程序私有原子对象的基本结构
定义:
struct drm_private_obj {
struct list_head head;
struct drm_modeset_lock lock;
struct drm_private_state *state;
const struct drm_private_state_funcs *funcs;
};
成员
head
用于将私有对象附加到
drm_device
的列表条目(排队到drm_mode_config.privobj_list
)。lock
模式设置锁,用于保护状态对象。
state
此驱动程序私有对象的当前原子状态。
funcs
用于操作此驱动程序私有对象状态的函数,请参阅
drm_private_state_funcs
。
描述
驱动程序私有对象通过调用 drm_atomic_private_obj_init()
初始化,并通过调用 drm_atomic_private_obj_fini()
清理。
当前仅跟踪状态更新函数和不透明的驱动程序私有状态本身,但在将来也可能跟踪需要哪个 drm_modeset_lock
来复制和更新此对象的状态。
所有私有对象都必须在它们所附加到的 DRM 设备注册到 DRM 子系统之前初始化(调用 drm_dev_register()
),并且应该一直存在,直到此 DRM 设备注销(调用 drm_dev_unregister()
)。换句话说,私有对象的生命周期与 DRM 设备的生命周期相关联。这意味着
- 1/ 所有对 drm_atomic_private_obj_init() 的调用都必须在调用之前完成
- 2/ 所有对 drm_atomic_private_obj_fini() 的调用都必须在调用之后完成
如果该私有对象用于存储多个 CRTC 共享的状态,则必须采取适当的措施来确保非阻塞提交正确排序,以避免发生 use-after-free 问题。
事实上,假设在两个不同的 drm_crtc
上进行两次非阻塞 drm_atomic_commit
,使用不同的 drm_plane
和 drm_connector
,因此没有共享资源,无法保证哪个提交会首先发生。但是,第二个 drm_atomic_commit
会将第一个 drm_private_obj
视为其旧状态,并且在第二个 drm_atomic_commit
完成时,负责释放它。
如果第一个 drm_atomic_commit
在它之后发生,它会将其 drm_private_obj
视为新状态,并且可能会访问它,从而导致访问已释放的内存区域。驱动程序应在 drm_mode_config_helper_funcs.atomic_commit_setup
中的私有状态中存储(并获取对)drm_crtc_commit
结构,然后在 drm_mode_config_helper_funcs.atomic_commit_tail
的第一步中等待该提交完成,类似于 drm_atomic_helper_wait_for_dependencies()
。
-
drm_for_each_privobj¶
drm_for_each_privobj (privobj, dev)
私有对象迭代器
参数
privobj
指向当前私有对象的指针。每次迭代后更新
dev
我们想要从中获取私有对象的 DRM 设备
描述
允许人们迭代附加到 dev 的所有私有对象
-
struct drm_private_state¶
驱动程序私有对象状态的基本结构
定义:
struct drm_private_state {
struct drm_atomic_state *state;
struct drm_private_obj *obj;
};
成员
state
指向全局 drm_atomic_state 的后向指针
obj
指向私有对象的后向指针
描述
当前仅包含指向整体原子更新的后向指针和相关的私有对象,但将来也可能包含类似于例如 drm_crtc.commit
的同步信息。
-
struct drm_atomic_state¶
原子提交结构
定义:
struct drm_atomic_state {
struct kref ref;
struct drm_device *dev;
bool allow_modeset : 1;
bool legacy_cursor_update : 1;
bool async_update : 1;
bool duplicated : 1;
struct __drm_planes_state *planes;
struct __drm_crtcs_state *crtcs;
int num_connector;
struct __drm_connnectors_state *connectors;
int num_private_objs;
struct __drm_private_objs_state *private_objs;
struct drm_modeset_acquire_ctx *acquire_ctx;
struct drm_crtc_commit *fake_commit;
struct work_struct commit_work;
};
成员
ref
对此更新的所有引用的计数(在归零之前不会释放)。
dev
父 DRM 设备。
allow_modeset
允许完全模式设置。这被 ATOMIC IOCTL 处理程序用于实现 DRM_MODE_ATOMIC_ALLOW_MODESET 标志。驱动程序通常不应查询此标志,而应查看
drm_atomic_crtc_needs_modeset()
的输出。详细规则如下驱动程序不得在原子提交路径中查询 allow_modeset。请改用
drm_atomic_crtc_needs_modeset()
。驱动程序必须在通过调用
drm_atomic_get_crtc_state()
将不相关的struct drm_crtc_state
添加到此提交之前查询 allow_modeset。另请参阅该函数文档中的警告。驱动程序不得更改此标志,它受用户空间的独家控制。
驱动程序可以在原子检查路径中查询 allow_modeset,如果它们可以选择需要模式设置的最佳硬件配置,以及可以在没有模式设置的情况下提交的次优配置。一个例子是次优的扫描输出 FIFO 分配导致空闲功耗增加。这允许用户空间以合理的成本避免正常组合循环的闪烁和延迟。
legacy_cursor_update
强制执行旧光标 IOCTL 语义的提示。
警告:这完全损坏并且几乎不可能正确实现。驱动程序必须忽略此项,而应实现
drm_plane_helper_funcs.atomic_async_check
和drm_plane_helper_funcs.atomic_async_commit
hook。不允许使用此标志的新用户。async_update
用于异步平面更新的提示
duplicated
指示此原子状态是否使用
drm_atomic_helper_duplicate_state()
复制。驱动程序和原子助手应使用它来修复复制状态中的正常不一致。planes
指向属于此更新的 drm_plane 和 drm_plane_state 数组的指针。
crtcs
指向属于此更新的 drm_crtc 和 drm_crtc_state 数组的指针。
num_connector
connectors 数组的大小
connectors
指向属于此更新的 drm_connector 和 drm_connector_state 数组的指针。
num_private_objs
private_objs 数组的大小
private_objs
指向属于此更新的 drm_private_obj 和 drm_private_obj_state 数组的指针。
acquire_ctx
此原子模式设置状态更新的获取上下文
fake_commit
用于发出未绑定平面/连接器的信号。当连接器或平面未绑定到任何 CRTC 时,保持线性以防止过早释放原子状态仍然很重要。
此提交(如果设置)未绑定到任何 CRTC,但将在调用
drm_atomic_helper_commit_hw_done()
时完成。commit_work
工作项,驱动程序或助手可以使用它来执行提交而不阻塞。
描述
此结构是 drm_mode_atomic 的内核对应物,表示从旧显示状态转换到新显示状态的原子提交。它包含受原子提交影响的所有对象,以及这些对象的新状态结构和指向旧状态结构的指针。
通过调用 drm_atomic_get_crtc_state()
、drm_atomic_get_plane_state()
、drm_atomic_get_connector_state()
或对于私有状态结构,drm_atomic_get_private_obj_state()
将状态添加到原子更新中。
在 atomic_check 时,您可以从 drm_atomic_state 获取即将提交的状态,并从实体状态指针(例如 drm_crtc.state)获取当前运行的状态。在调用 drm_atomic_helper_swap_state()
之后,实体状态指针将包含先前检查的状态,而 drm_atomic_state 结构将包含旧状态。
随着时间的推移,为了避免混淆,drm_atomic_state 已经发展为同时具有旧状态(即,我们替换的状态)和新状态(即,我们想要应用的状态)。这些名称在提交过程中是稳定的,这使得推理更容易。
您仍然可以通过一些采用名为“old_state”的 drm_atomic_state 参数的 hook 或回调来找到该演变的痕迹。这不一定意味着传递了先前的 drm_atomic_state,而是说这曾经是我们 drm_atomic_helper_swap_state()
之后替换的状态集合,但变量名称从未更新。
一些原子操作实现遵循类似的过程。我们首先开始仅传递实体状态。然而,对于驱动程序,尤其是 CRTC,检索其他组件的状态非常麻烦。因此,我们切换为将整个 drm_atomic_state 作为参数传递给这些操作。同样,过渡尚未完成,并且可能仍然找到采用 drm_atomic_state 指针或组件状态指针的原子操作。前者是首选形式。
注意
struct drm_atomic_state
首先开始作为实体状态指针(drm_plane_state、drm_crtc_state 等)的单个集合。
-
struct drm_crtc_commit *drm_crtc_commit_get(struct drm_crtc_commit *commit)¶
获取对 CRTC 提交的引用
参数
struct drm_crtc_commit *commit
CRTC 提交
描述
增加 commit 的引用。
返回
指向 commit 的指针,引用增加。
-
void drm_crtc_commit_put(struct drm_crtc_commit *commit)¶
释放对 CRTC 提交的引用
参数
struct drm_crtc_commit *commit
CRTC 提交
描述
这会释放对 commit 的引用,该引用在删除最终引用后释放。不需要锁定,并且可以从任何上下文调用。
-
struct drm_atomic_state *drm_atomic_state_get(struct drm_atomic_state *state)¶
获取对原子状态的引用
参数
struct drm_atomic_state *state
原子状态
描述
返回对 state 的新引用
-
void drm_atomic_state_put(struct drm_atomic_state *state)¶
释放对原子状态的引用
参数
struct drm_atomic_state *state
原子状态
描述
这会释放对 state 的引用,该引用在删除最终引用后释放。不需要锁定,并且可以从任何上下文调用。
-
struct drm_crtc_state *drm_atomic_get_existing_crtc_state(const struct drm_atomic_state *state, struct drm_crtc *crtc)¶
获取 CRTC 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_crtc *crtc
要获取的 CRTC
描述
此函数返回给定 CRTC 的 CRTC 状态,如果 CRTC 不属于全局原子状态,则返回 NULL。
此函数已弃用,应改用 drm_atomic_get_old_crtc_state 或 drm_atomic_get_new_crtc_state。
-
struct drm_crtc_state *drm_atomic_get_old_crtc_state(const struct drm_atomic_state *state, struct drm_crtc *crtc)¶
获取旧的 CRTC 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_crtc *crtc
要获取的 CRTC
描述
此函数返回给定 CRTC 的旧 CRTC 状态,如果 CRTC 不属于全局原子状态,则返回 NULL。
-
struct drm_crtc_state *drm_atomic_get_new_crtc_state(const struct drm_atomic_state *state, struct drm_crtc *crtc)¶
获取新的 CRTC 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_crtc *crtc
要获取的 CRTC
描述
此函数返回给定 CRTC 的新 CRTC 状态,如果 CRTC 不属于全局原子状态,则返回 NULL。
-
struct drm_plane_state *drm_atomic_get_existing_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane)¶
获取 plane 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取的 plane
描述
此函数返回给定 plane 的 plane 状态,如果 plane 不属于全局原子状态,则返回 NULL。
此函数已弃用,应改用 drm_atomic_get_old_plane_state 或 drm_atomic_get_new_plane_state。
-
struct drm_plane_state *drm_atomic_get_old_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane)¶
获取 plane 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取的 plane
描述
此函数返回给定 plane 的旧 plane 状态,如果 plane 不属于全局原子状态,则返回 NULL。
-
struct drm_plane_state *drm_atomic_get_new_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane)¶
获取 plane 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取的 plane
描述
此函数返回给定 plane 的新 plane 状态,如果 plane 不属于全局原子状态,则返回 NULL。
-
struct drm_connector_state *drm_atomic_get_existing_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector)¶
获取 connector 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_connector *connector
要获取的 connector
描述
此函数返回给定 connector 的 connector 状态,如果 connector 不属于全局原子状态,则返回 NULL。
此函数已弃用,应改用 drm_atomic_get_old_connector_state 或 drm_atomic_get_new_connector_state。
-
struct drm_connector_state *drm_atomic_get_old_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector)¶
获取 connector 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_connector *connector
要获取的 connector
描述
此函数返回给定 connector 的旧 connector 状态,如果 connector 不属于全局原子状态,则返回 NULL。
-
struct drm_connector_state *drm_atomic_get_new_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector)¶
获取 connector 状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_connector *connector
要获取的 connector
描述
此函数返回给定 connector 的新 connector 状态,如果 connector 不属于全局原子状态,则返回 NULL。
-
const struct drm_plane_state *__drm_atomic_get_current_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane)¶
获取当前的 plane 状态
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取的 plane
描述
此函数返回给定 plane 的 plane 状态,如果该 plane 不属于原子状态更新,则从 state 返回,否则从 plane 返回。 这在原子检查回调中很有用,因为驱动程序需要查看但不更改其他 plane 的状态,因为它避免了将错误代码向上传递调用链。
警告
请注意,此函数通常是不安全的,因为它不检查访问状态结构所需的锁定。 驱动程序必须确保通过其他方式访问返回的状态结构是安全的。 一个常见的例子是,当 plane 固定到单个 CRTC 时,驱动程序知道已经保持了 CRTC 锁。 在这种情况下,保持 CRTC 锁可以对连接到该 CRTC 的所有 plane 进行读取锁定。 但是,如果可以重新分配 plane,情况会变得更加棘手。 在这种情况下,最好使用 drm_atomic_get_plane_state 并连接完整的错误处理。
指向当前 plane 状态的只读指针。
-
for_each_oldnew_connector_in_state¶
for_each_oldnew_connector_in_state (__state, connector, old_connector_state, new_connector_state, __i)
迭代原子更新中的所有 connector
参数
__state
connector
struct drm_connector
迭代光标old_connector_state
struct drm_connector_state
旧状态的迭代光标new_connector_state
struct drm_connector_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 connector,跟踪旧状态和新状态。 这在需要考虑状态增量的地方很有用,例如在原子检查函数中。
-
for_each_old_connector_in_state¶
for_each_old_connector_in_state (__state, connector, old_connector_state, __i)
迭代原子更新中的所有 connector
参数
__state
connector
struct drm_connector
迭代光标old_connector_state
struct drm_connector_state
旧状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 connector,仅跟踪旧状态。 这在禁用函数中很有用,我们需要硬件仍在使用的旧状态。
-
for_each_new_connector_in_state¶
for_each_new_connector_in_state (__state, connector, new_connector_state, __i)
迭代原子更新中的所有 connector
参数
__state
connector
struct drm_connector
迭代光标new_connector_state
struct drm_connector_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 connector,仅跟踪新状态。 这在启用函数中很有用,我们需要硬件在原子提交操作完成后应处于的新状态。
-
for_each_oldnew_crtc_in_state¶
for_each_oldnew_crtc_in_state (__state, crtc, old_crtc_state, new_crtc_state, __i)
迭代原子更新中的所有 CRTC
参数
__state
crtc
struct drm_crtc
迭代光标old_crtc_state
struct drm_crtc_state
旧状态的迭代光标new_crtc_state
struct drm_crtc_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 CRTC,跟踪旧状态和新状态。 这在需要考虑状态增量的地方很有用,例如在原子检查函数中。
-
for_each_old_crtc_in_state¶
for_each_old_crtc_in_state (__state, crtc, old_crtc_state, __i)
迭代原子更新中的所有 CRTC
参数
__state
crtc
struct drm_crtc
迭代光标old_crtc_state
struct drm_crtc_state
旧状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 CRTC,仅跟踪旧状态。 这在禁用函数中很有用,我们需要硬件仍在使用的旧状态。
-
for_each_new_crtc_in_state¶
for_each_new_crtc_in_state (__state, crtc, new_crtc_state, __i)
迭代原子更新中的所有 CRTC
参数
__state
crtc
struct drm_crtc
迭代光标new_crtc_state
struct drm_crtc_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 CRTC,仅跟踪新状态。 这在启用函数中很有用,我们需要硬件在原子提交操作完成后应处于的新状态。
-
for_each_oldnew_plane_in_state¶
for_each_oldnew_plane_in_state (__state, plane, old_plane_state, new_plane_state, __i)
迭代原子更新中的所有 plane
参数
__state
plane
struct drm_plane
迭代光标old_plane_state
struct drm_plane_state
旧状态的迭代光标new_plane_state
struct drm_plane_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 plane,跟踪旧状态和新状态。 这在需要考虑状态增量的地方很有用,例如在原子检查函数中。
-
for_each_oldnew_plane_in_state_reverse¶
for_each_oldnew_plane_in_state_reverse (__state, plane, old_plane_state, new_plane_state, __i)
以相反的顺序迭代原子更新中的所有 plane
参数
__state
plane
struct drm_plane
迭代光标old_plane_state
struct drm_plane_state
旧状态的迭代光标new_plane_state
struct drm_plane_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会以相反的顺序迭代原子更新中的所有 plane,跟踪旧状态和新状态。 这在需要考虑状态增量的地方很有用,例如在原子检查函数中。
-
for_each_new_plane_in_state_reverse¶
for_each_new_plane_in_state_reverse (__state, plane, new_plane_state, __i)
除了仅跟踪新状态之外,它与 for_each_oldnew_plane_in_state_reverse 相同
参数
__state
plane
struct drm_plane
迭代光标new_plane_state
struct drm_plane_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
-
for_each_old_plane_in_state¶
for_each_old_plane_in_state (__state, plane, old_plane_state, __i)
迭代原子更新中的所有 plane
参数
__state
plane
struct drm_plane
迭代光标old_plane_state
struct drm_plane_state
旧状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
这会迭代原子更新中的所有 plane,仅跟踪旧状态。 这在禁用函数中很有用,我们需要硬件仍在使用的旧状态。
-
for_each_new_plane_in_state¶
for_each_new_plane_in_state (__state, plane, new_plane_state, __i)
迭代原子更新中的所有 plane
参数
__state
plane
struct drm_plane
迭代光标new_plane_state
struct drm_plane_state
新状态的迭代光标__i
int 迭代光标,用于宏内部使用
描述
此函数迭代原子更新中的所有平面,仅跟踪新状态。这在启用函数中非常有用,在这些函数中,我们需要在原子提交操作完成后硬件应处于的新状态。
-
for_each_oldnew_private_obj_in_state¶
for_each_oldnew_private_obj_in_state (__state, obj, old_obj_state, new_obj_state, __i)
迭代原子更新中的所有私有对象
参数
__state
obj
old_obj_state
struct drm_private_state
旧状态的迭代游标new_obj_state
struct drm_private_state
新状态的迭代游标__i
int 迭代光标,用于宏内部使用
描述
此函数迭代原子更新中的所有私有对象,同时跟踪旧状态和新状态。这在需要考虑状态增量的地方非常有用,例如在原子检查函数中。
-
for_each_old_private_obj_in_state¶
for_each_old_private_obj_in_state (__state, obj, old_obj_state, __i)
迭代原子更新中的所有私有对象
参数
__state
obj
old_obj_state
struct drm_private_state
旧状态的迭代游标__i
int 迭代光标,用于宏内部使用
描述
此函数迭代原子更新中的所有私有对象,仅跟踪旧状态。这在禁用函数中非常有用,在这些函数中,我们需要硬件仍然处于的旧状态。
-
for_each_new_private_obj_in_state¶
for_each_new_private_obj_in_state (__state, obj, new_obj_state, __i)
迭代原子更新中的所有私有对象
参数
__state
obj
new_obj_state
struct drm_private_state
新状态的迭代游标__i
int 迭代光标,用于宏内部使用
描述
此函数迭代原子更新中的所有私有对象,仅跟踪新状态。这在启用函数中非常有用,在这些函数中,我们需要在原子提交操作完成后硬件应处于的新状态。
-
bool drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)¶
计算组合的模式设置需求
参数
const struct drm_crtc_state *state
CRTC 的
drm_crtc_state
描述
为了给驱动程序灵活性,struct drm_crtc_state
具有 3 个布尔值来跟踪状态 CRTC 是否发生了足够的改变,需要完整的模式设置周期:mode_changed、active_changed 和 connectors_changed。此辅助函数简单地将这三个值组合起来,以计算 **state** 的模式设置的总体需求。
原子辅助代码设置这些布尔值,但驱动程序可以并且应该适当地更改它们,以准确地表示是否真的需要模式设置。通常,驱动程序应尽可能避免完整的模式设置。
例如,如果 CRTC 模式已更改,并且硬件能够在不经过完整的模式设置的情况下实现所请求的模式更改,则驱动程序应在其 drm_mode_config_funcs.atomic_check
实现中清除 mode_changed。
-
bool drm_atomic_crtc_effectively_active(const struct drm_crtc_state *state)¶
计算 CRTC 是否实际处于活动状态
参数
const struct drm_crtc_state *state
CRTC 的
drm_crtc_state
描述
在自刷新模式下,crtc_state->active 值将为 false,因为 CRTC 已关闭。但是,在某些情况下,我们对 CRTC 是否处于活动状态或有效活动状态(即:它是否连接到活动显示器)感兴趣。在这些情况下,请使用此函数而不是仅检查活动状态。
-
struct drm_bus_cfg¶
总线配置
定义:
struct drm_bus_cfg {
u32 format;
u32 flags;
};
成员
格式
在此总线上使用的格式(MEDIA_BUS_FMT_* 格式之一)
驱动程序不应直接修改此字段 (drm_atomic_bridge_chain_select_bus_fmts() 负责总线格式协商)。
标志
在此总线上使用的 DRM_BUS_* 标志
描述
此结构存储输出管道中两个组件之间(通常是两个桥接器、编码器和桥接器,或桥接器和连接器之间)的物理总线的配置。
总线配置存储在 drm_bridge_state
中,对于输入总线和输出总线分别存储,从每个桥接器的角度来看。桥接器输出的总线配置通常与下一个桥接器的输入的配置相同,但如果在两个桥接器之间修改信号,例如通过板上的反相器,则可能会有所不同。如果桥接器在内部修改信号(例如通过执行格式转换或修改信号极性),则桥接器的输入和输出配置可能会有所不同。
-
struct drm_bridge_state¶
原子桥接器状态对象
定义:
struct drm_bridge_state {
struct drm_private_state base;
struct drm_bridge *bridge;
struct drm_bus_cfg input_bus_cfg;
struct drm_bus_cfg output_bus_cfg;
};
成员
基本
桥接器
此状态引用的桥接器
input_bus_cfg
输入总线配置
output_bus_cfg
输出总线配置
-
int drm_crtc_commit_wait(struct drm_crtc_commit *commit)¶
等待提交完成
参数
struct drm_crtc_commit *commit
要等待的
drm_crtc_commit
描述
等待给定的 drm_crtc_commit
被编程到硬件中并翻转到。
返回
成功时返回 0,否则返回负错误代码。
-
void drm_atomic_state_default_release(struct drm_atomic_state *state)¶
释放 drm_atomic_state_init 初始化的内存
参数
struct drm_atomic_state *state
原子状态
描述
释放 drm_atomic_state_init 分配的所有内存。这应该只由仍然对 drm_atomic_state
进行子类化且尚未切换到 drm_private_state
的驱动程序使用。
-
int drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)¶
初始化新的原子状态
参数
struct drm_device *dev
DRM 设备
struct drm_atomic_state *state
原子状态
描述
用于填充新原子状态的默认实现。这应该只由仍然对 drm_atomic_state
进行子类化且尚未切换到 drm_private_state
的驱动程序使用。
-
struct drm_atomic_state *drm_atomic_state_alloc(struct drm_device *dev)¶
分配原子状态
参数
struct drm_device *dev
DRM 设备
描述
这将分配一个空的原子状态以跟踪更新。
-
void drm_atomic_state_default_clear(struct drm_atomic_state *state)¶
清除基本原子状态
参数
struct drm_atomic_state *state
原子状态
描述
用于清除原子状态的默认实现。这应该只由仍然对 drm_atomic_state
进行子类化且尚未切换到 drm_private_state
的驱动程序使用。
-
void drm_atomic_state_clear(struct drm_atomic_state *state)¶
清除状态对象
参数
struct drm_atomic_state *state
原子状态
描述
当 w/w 互斥算法检测到死锁时,我们需要退出并删除所有锁。因此,其他人可能会偷偷进入并更改当前的模式设置配置。这意味着 **state** 中组装的所有状态不再是对当前状态的原子更新,而是对一些任意的早期状态的更新。这可能会破坏驱动程序的 drm_mode_config_funcs.atomic_check
可能依赖的假设。
因此,我们必须清除所有缓存的状态并使用此函数完全重新开始。
-
void __drm_atomic_state_free(struct kref *ref)¶
释放原子状态的所有内存
参数
struct kref *ref
要取消分配的原子状态
描述
这会释放与原子状态关联的所有内存,包括平面、CRTC 和连接器的所有按对象状态。
-
struct drm_crtc_state *drm_atomic_get_crtc_state(struct drm_atomic_state *state, struct drm_crtc *crtc)¶
获取 CRTC 状态
参数
struct drm_atomic_state *state
全局原子状态对象
struct drm_crtc *crtc
要获取状态对象的 CRTC
描述
此函数返回给定 CRTC 的 CRTC 状态,如果需要,则分配它。它还将获取相关的 CRTC 锁,以确保状态一致。
警告:只有在设置了 drm_atomic_state.allow_modeset 时,或者如果是用户空间通过 IOCTL 调用创建的驱动程序内部提交,驱动程序才能向 **state** 添加新的 CRTC 状态。
返回
分配的状态或编码到指针中的错误代码。当错误为 EDEADLK 时,w/w 互斥代码检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
-
struct drm_plane_state *drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane)¶
获取平面状态
参数
struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取状态对象的平面
描述
此函数返回给定平面的平面状态,如果需要,则分配它。它还将获取相关的平面锁,以确保状态一致。
返回
分配的状态或编码到指针中的错误代码。当错误为 EDEADLK 时,w/w 互斥代码检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
-
void drm_atomic_private_obj_init(struct drm_device *dev, struct drm_private_obj *obj, struct drm_private_state *state, const struct drm_private_state_funcs *funcs)¶
初始化私有对象
参数
struct drm_device *dev
此对象将附加到的 DRM 设备
struct drm_private_obj *obj
私有对象
struct drm_private_state *state
初始私有对象状态
const struct drm_private_state_funcs *funcs
指向标识对象类型的函数指针结构的指针
描述
初始化私有对象,该对象可以嵌入到任何需要自己的原子状态的驱动程序私有对象中。
-
void drm_atomic_private_obj_fini(struct drm_private_obj *obj)¶
完成私有对象
参数
struct drm_private_obj *obj
私有对象
描述
完成私有对象。
-
struct drm_private_state *drm_atomic_get_private_obj_state(struct drm_atomic_state *state, struct drm_private_obj *obj)¶
获取私有对象状态
参数
struct drm_atomic_state *state
全局原子状态
struct drm_private_obj *obj
要获取状态的私有对象
描述
此函数返回给定私有对象的私有对象状态,如果需要,则分配该状态。它还将获取相关的私有对象锁,以确保状态一致。
返回
分配的状态或编码为指针的错误代码。
-
struct drm_private_state *drm_atomic_get_old_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj)¶
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_private_obj *obj
要获取的private_obj
描述
此函数返回给定 private_obj 的旧的私有对象状态,如果 private_obj 不是全局原子状态的一部分,则返回 NULL。
-
struct drm_private_state *drm_atomic_get_new_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj)¶
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_private_obj *obj
要获取的private_obj
描述
此函数返回给定 private_obj 的新的私有对象状态,如果 private_obj 不是全局原子状态的一部分,则返回 NULL。
-
struct drm_connector *drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder)¶
获取编码器的旧连接器
参数
const struct drm_atomic_state *state
原子状态
struct drm_encoder *encoder
要获取连接器状态的编码器
描述
此函数查找并返回由 state 指定的连接到 encoder 的连接器。
如果在 state 中没有之前连接到 encoder 的连接器,则此函数将返回 NULL。虽然这看起来像是一个无效的用例,但有时区分没有连接到 encoder 的先前连接器的提交与确实连接的提交(并检查它们的状态)很有用。这在启用钩子中尤其如此,因为管道已更改。
如果您无法访问原子状态,请参阅 drm_atomic_get_connector_for_encoder()
。
返回
连接到 encoder 的旧连接器,如果编码器未连接,则为 NULL。
-
struct drm_connector *drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder)¶
获取编码器的新连接器
参数
const struct drm_atomic_state *state
原子状态
struct drm_encoder *encoder
要获取连接器状态的编码器
描述
此函数查找并返回由 state 指定的将连接到 encoder 的连接器。
如果在 state 中没有将连接到 encoder 的连接器,则此函数将返回 NULL。虽然这看起来像是一个无效的用例,但有时区分没有连接到 encoder 的连接器的提交与确实连接的提交(并检查它们的状态)很有用。这在禁用钩子中尤其如此,因为管道将更改。
如果您无法访问原子状态,请参阅 drm_atomic_get_connector_for_encoder()
。
返回
连接到 encoder 的新连接器,如果编码器未连接,则为 NULL。
-
struct drm_connector *drm_atomic_get_connector_for_encoder(const struct drm_encoder *encoder, struct drm_modeset_acquire_ctx *ctx)¶
获取当前分配给编码器的连接器
参数
const struct drm_encoder *encoder
要查找连接器的编码器
struct drm_modeset_acquire_ctx *ctx
Modeset 锁定上下文
描述
此函数查找并返回当前分配给 encoder 的连接器。
它类似于 drm_atomic_get_old_connector_for_encoder()
和 drm_atomic_get_new_connector_for_encoder()
助手,但不需要访问原子状态。如果您可以访问它,请首选使用这些。此助手通常在您无法访问原子状态的情况下很有用,例如检测、链接修复、线程化中断处理程序或其他框架(ALSA、CEC 等)中的钩子。
返回
连接到 encoder 的连接器,否则为错误指针。当错误为 EDEADLK 时,已检测到死锁,必须重新启动该序列。
-
struct drm_crtc *drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state, struct drm_encoder *encoder)¶
获取编码器的旧 crtc
参数
struct drm_atomic_state *state
原子状态
struct drm_encoder *encoder
要获取 crtc 状态的编码器
描述
此函数查找并返回由 state 指定的连接到 encoder 的 crtc。
返回
连接到 encoder 的旧 crtc,如果编码器未连接,则为 NULL。
-
struct drm_crtc *drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state, struct drm_encoder *encoder)¶
获取编码器的新 crtc
参数
struct drm_atomic_state *state
原子状态
struct drm_encoder *encoder
要获取 crtc 状态的编码器
描述
此函数查找并返回由 state 指定的将连接到 encoder 的 crtc。
返回
连接到 encoder 的新 crtc,如果编码器未连接,则为 NULL。
-
struct drm_connector_state *drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector)¶
获取连接器状态
参数
struct drm_atomic_state *state
全局原子状态对象
struct drm_connector *connector
要获取状态对象的连接器
描述
此函数返回给定连接器的连接器状态,并在需要时分配它。它还将获取相关的连接器锁,以确保状态是一致的。
返回
分配的状态或编码到指针中的错误代码。当错误为 EDEADLK 时,w/w 互斥代码检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
-
struct drm_bridge_state *drm_atomic_get_bridge_state(struct drm_atomic_state *state, struct drm_bridge *bridge)¶
获取桥接状态
参数
struct drm_atomic_state *state
全局原子状态对象
struct drm_bridge *bridge
要获取状态对象的桥接
描述
此函数返回给定桥接的桥接状态,并在需要时分配它。它还将获取相关的桥接锁,以确保状态是一致的。
返回
分配的状态或编码到指针中的错误代码。当错误为 EDEADLK 时,w/w 互斥代码已检测到死锁,必须重新启动整个原子序列。
-
struct drm_bridge_state *drm_atomic_get_old_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge)¶
获取旧的桥接状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_bridge *bridge
要抓取的桥接
描述
此函数返回给定桥接的旧的桥接状态,如果该桥接不是全局原子状态的一部分,则返回 NULL。
-
struct drm_bridge_state *drm_atomic_get_new_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge)¶
获取新的桥接状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_bridge *bridge
要抓取的桥接
描述
此函数返回给定桥接的新的桥接状态,如果该桥接不是全局原子状态的一部分,则返回 NULL。
-
int drm_atomic_add_encoder_bridges(struct drm_atomic_state *state, struct drm_encoder *encoder)¶
添加连接到编码器的桥接
参数
struct drm_atomic_state *state
原子状态
struct drm_encoder *encoder
DRM 编码器
描述
此函数添加连接到 encoder 的所有桥接。需要将桥接状态添加到 state,并在调用 drm_bridge_funcs.atomic_check()
、drm_bridge_funcs.atomic_pre_enable()
、drm_bridge_funcs.atomic_enable()
、drm_bridge_funcs.atomic_disable_post_disable()
时使它们可用。
返回
成功时返回 0,或在出现 -EDEADLK 或 -ENOMEM 错误时失败。当错误为 EDEADLK 时,w/w 互斥代码已检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
-
int drm_atomic_add_affected_connectors(struct drm_atomic_state *state, struct drm_crtc *crtc)¶
为 CRTC 添加连接器
参数
struct drm_atomic_state *state
原子状态
struct drm_crtc *crtc
DRM CRTC
描述
此函数遍历当前配置,并将当前使用 crtc 的所有连接器添加到原子配置 state。请注意,此函数必须获取连接互斥锁。如果更新仅适用于一个 CRTC 上的平面,这可能会导致不必要的序列化。因此,驱动程序和助手应仅在真正需要时才调用此函数(例如,由于某些更改而需要进行完整的模式设置时)。
返回
成功时返回 0,或在出现 -EDEADLK 或 -ENOMEM 错误时失败。当错误为 EDEADLK 时,w/w 互斥代码已检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
-
int drm_atomic_add_affected_planes(struct drm_atomic_state *state, struct drm_crtc *crtc)¶
为 CRTC 添加平面
参数
struct drm_atomic_state *state
原子状态
struct drm_crtc *crtc
DRM CRTC
描述
此函数遍历当前配置,并将 crtc 当前使用的所有平面添加到原子配置 state。当原子提交还需要检查 crtc 上的所有当前已启用平面时(例如,在更改模式时),这非常有用。在重新启用 CRTC 时,避免强制启用所有平面的特殊代码也很有用。
由于获取平面状态始终还会获取该平面当前 CRTC 的 w/w 互斥锁(如果存在),因此添加 CRTC 的所有平面状态不会降低原子更新的并行性。
返回
成功时返回 0,或在出现 -EDEADLK 或 -ENOMEM 错误时失败。当错误为 EDEADLK 时,w/w 互斥代码已检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
-
int drm_atomic_check_only(struct drm_atomic_state *state)¶
检查给定的配置是否有效
参数
struct drm_atomic_state *state
要检查的原子配置
描述
请注意,如果驱动程序需要获取更多锁但遇到死锁,则此函数可能会返回 -EDEADLK。然后,调用方必须执行通常的 w/w 回退舞并重新启动。所有其他错误都是致命的。
返回
成功时返回 0,失败时返回负错误代码。
-
int drm_atomic_commit(struct drm_atomic_state *state)¶
以原子方式提交配置
参数
struct drm_atomic_state *state
要检查的原子配置
描述
请注意,如果驱动程序需要获取更多锁但遇到死锁,则此函数可能会返回 -EDEADLK。然后,调用方必须执行通常的 w/w 回退舞并重新启动。所有其他错误都是致命的。
此函数将采用 state 上的自身引用。调用方应始终使用 drm_atomic_state_put()
释放其引用。
返回
成功时返回 0,失败时返回负错误代码。
-
int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)¶
原子非阻塞提交
参数
struct drm_atomic_state *state
要检查的原子配置
描述
请注意,如果驱动程序需要获取更多锁但遇到死锁,则此函数可能会返回 -EDEADLK。然后,调用方必须执行通常的 w/w 回退舞并重新启动。所有其他错误都是致命的。
此函数将采用 state 上的自身引用。调用方应始终使用 drm_atomic_state_put()
释放其引用。
返回
成功时返回 0,失败时返回负错误代码。
-
void drm_atomic_print_new_state(const struct drm_atomic_state *state, struct drm_printer *p)¶
打印drm原子状态
参数
const struct drm_atomic_state *state
要检查的原子配置
struct drm_printer *p
drm打印机
描述
此函数使用传递给它的drm打印机打印drm原子状态快照。此快照可用于调试目的。
请注意,此函数会查看新的状态对象,因此在调用drm_atomic_helper_commit_hw_done()
之后使用它是不安全的。
-
void drm_state_dump(struct drm_device *dev, struct drm_printer *p)¶
转储整个设备原子状态
参数
struct drm_device *dev
drm设备
struct drm_printer *p
状态打印到哪里
描述
仅用于调试。驱动程序可能希望在错误 irq 的情况下选择将状态转储到 dmesg。(提示,您可能想要速率限制它!)
调用者必须包装drm_modeset_lock_all_ctx()
和drm_modeset_drop_locks()
。 如果从错误 irq 处理程序调用此函数,则默认情况下不应启用 - 如果您正在调试错误,您可能不关心这是竞争的,但在未持有所有模式设置锁的情况下调用此函数本质上是不安全的。
原子模式设置 IOCTL 和 UAPI 函数¶
此文件包含所有形式的原子 UAPI 的编组和解组粘合代码:怪物 ATOMIC IOCTL 本身,GET_PROPERTY 和 SET_PROPERTY IOCTL 的代码。 加上兼容性辅助程序和驱动程序的接口函数,这些辅助程序和驱动程序有特殊的需求来构造自己的原子更新,例如,用于负载检测或类似目的。
-
int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, const struct drm_display_mode *mode)¶
为CRTC设置模式
参数
struct drm_crtc_state *state
要更新的CRTC的传入状态
const struct drm_display_mode *mode
用于CRTC的内核内部模式,或禁用时为NULL
描述
在所需的CRTC状态上设置模式(源自内核),并更新enable属性。
返回
成功时为零,失败时为错误代码。不能返回-EDEADLK。
-
int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, struct drm_property_blob *blob)¶
为CRTC设置模式
参数
struct drm_crtc_state *state
要更新的CRTC的传入状态
struct drm_property_blob *blob
指向用于模式的blob属性的指针
描述
在所需的CRTC状态上设置模式(源自blob属性)。此函数将获取CRTC状态的blob属性的引用,并释放状态的现有模式属性(如果已设置)上保留的引用。
返回
成功时为零,失败时为错误代码。不能返回-EDEADLK。
-
int drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, struct drm_crtc *crtc)¶
为平面设置CRTC
参数
struct drm_plane_state *plane_state
要更新的平面的传入状态
struct drm_crtc *crtc
用于平面的CRTC
描述
更改平面的指定CRTC需要我们根据需要获取新CRTC的锁和状态。 除了更新状态对象本身的指针之外,此函数还处理所有这些细节。
返回
成功时返回 0,或在出现 -EDEADLK 或 -ENOMEM 错误时失败。当错误为 EDEADLK 时,w/w 互斥代码已检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
-
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, struct drm_framebuffer *fb)¶
为平面设置帧缓冲区
参数
struct drm_plane_state *plane_state
平面的原子状态对象
struct drm_framebuffer *fb
用于平面的fb
描述
更改平面的指定帧缓冲区需要我们获取对新fb的引用并删除对旧fb的引用(如果有)。 除了更新状态对象本身的指针之外,此函数还处理所有这些细节。
-
int drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_crtc *crtc)¶
为连接器设置CRTC
参数
struct drm_connector_state *conn_state
连接器的原子状态对象
struct drm_crtc *crtc
用于连接器的CRTC
描述
更改连接器的指定CRTC需要我们根据需要获取新CRTC的锁和状态。 除了更新状态对象本身的指针之外,此函数还处理所有这些细节。
返回
成功时返回 0,或在出现 -EDEADLK 或 -ENOMEM 错误时失败。当错误为 EDEADLK 时,w/w 互斥代码已检测到死锁,必须重新启动整个原子序列。所有其他错误都是致命的。
CRTC抽象¶
CRTC表示整体显示流水线。 它从drm_plane
接收像素数据并将它们混合在一起。 drm_display_mode
也附加到CRTC,指定显示时序。 在输出端,数据被馈送到一个或多个drm_encoder
,然后每个drm_encoder
连接到一个drm_connector
。
要创建CRTC,KMS驱动程序分配并将struct drm_crtc
的一个实例(可能作为更大的结构的一部分)归零,并通过调用drm_crtc_init_with_planes()
注册它。
CRTC也是传统模式设置操作的入口点(请参阅drm_crtc_funcs.set_config
),传统平面操作(请参阅drm_crtc_funcs.page_flip
和drm_crtc_funcs.cursor_set2
)以及其他传统操作(如drm_crtc_funcs.gamma_set
)。 对于原子驱动程序,所有这些功能都通过drm_property
和drm_mode_config_funcs.atomic_check
控制。
CRTC函数参考¶
-
struct drm_crtc_state¶
可变的CRTC状态
定义:
struct drm_crtc_state {
struct drm_crtc *crtc;
bool enable;
bool active;
bool planes_changed : 1;
bool mode_changed : 1;
bool active_changed : 1;
bool connectors_changed : 1;
bool zpos_changed : 1;
bool color_mgmt_changed : 1;
bool no_vblank : 1;
u32 plane_mask;
u32 connector_mask;
u32 encoder_mask;
struct drm_display_mode adjusted_mode;
struct drm_display_mode mode;
struct drm_property_blob *mode_blob;
struct drm_property_blob *degamma_lut;
struct drm_property_blob *ctm;
struct drm_property_blob *gamma_lut;
u32 target_vblank;
bool async_flip;
bool vrr_enabled;
bool self_refresh_active;
enum drm_scaling_filter scaling_filter;
struct drm_pending_vblank_event *event;
struct drm_crtc_commit *commit;
struct drm_atomic_state *state;
};
成员
crtc
返回到CRTC的指针
启用
是否应启用CRTC,门控所有其他状态。 这控制共享资源的预留。 实际硬件状态由active控制。
active
CRTC是否正在主动显示(用于DPMS)。 意味着设置了enable。 如果将active设置为false但enable仍为true,则驱动程序不得释放任何共享资源,因为用户空间期望DPMS ON始终成功。
因此,驱动程序不得在其各种
drm_mode_config_funcs.atomic_check
回调中查询active以拒绝原子提交。 它们可以查询它以帮助计算派生的硬件状态,因为即使在DPMS OFF状态下,显示硬件也应尽可能地关闭电源,就像通过将enable设置为false来完全禁用CRTC一样。planes_changed
此crtc上的平面已更新。 原子辅助程序和驱动程序使用它来控制原子提交控制流程。
mode_changed
mode或enable已更改。 原子辅助程序和驱动程序使用它来控制原子提交控制流程。 另请参阅
drm_atomic_crtc_needs_modeset()
。驱动程序应该为此设置任何需要完整模式设置的CRTC状态更改。 他们还可以将其重置为false,例如,如果可以通过仅更改缩放器设置来完成没有完整模式设置的mode更改。
active_changed
active已切换。 原子辅助程序和驱动程序使用它来控制原子提交控制流程。 另请参阅
drm_atomic_crtc_needs_modeset()
。connectors_changed
此crtc的连接器已更新,无论是在其状态还是路由中。 原子辅助程序和驱动程序使用它来控制原子提交控制流程。 另请参阅
drm_atomic_crtc_needs_modeset()
。驱动程序应该根据需要从他们自己的原子检查代码中设置此项,例如从
drm_encoder_helper_funcs.atomic_check
zpos_changed
此crtc上平面的zpos值已更新。 原子辅助程序和驱动程序使用它来控制原子提交控制流程。
color_mgmt_changed
颜色管理属性已更改(gamma_lut、degamma_lut或ctm)。 原子辅助程序和驱动程序使用它来控制原子提交控制流程。
no_vblank
反映CRTC发送VBLANK事件的能力。 此状态通常取决于流水线配置。 如果设置为true,则DRM原子辅助程序将在提交所有硬件更改后,在显示更新期间发送伪VBLANK事件。 这在
drm_atomic_helper_fake_vblank()
中实现。一种用法是用于不支持VBLANK中断的驱动程序和/或硬件。 此类驱动程序通常不初始化垂直消隐(即,使用CRTC的数量调用
drm_vblank_init()
)。 对于没有初始化垂直消隐的CRTC,此字段在drm_atomic_helper_check_modeset()
中设置为true,并且drm_atomic_helper_fake_vblank()
将在每次更新显示流水线时发送伪VBLANK事件。另一种用法是CRTC馈送以单次模式运行的回写连接器。 在这种情况下,仅当作业排队到回写连接器时才会生成伪VBLANK事件,并且我们希望核心在流水线的这一部分未更改但其他部分已更改时或CRTC和连接器被禁用时伪造VBLANK事件。
__drm_atomic_helper_crtc_duplicate_state()
不会重置当前状态的值,然后CRTC驱动程序负责在需要时更新此字段。请注意,
drm_crtc_state.event
== NULL和drm_crtc_state.no_blank
== true的组合有效,通常在附加到CRTC的回写连接器已将新作业排队时使用。 在这种情况下,驱动程序将在回写作业完成时自行发送VBLANK事件。plane_mask
附加到此CRTC的平面的drm_plane_mask(plane)的位掩码。
connector_mask
附加到此CRTC的连接器的drm_connector_mask(connector)的位掩码。
encoder_mask
附加到此CRTC的编码器的drm_encoder_mask(encoder)的位掩码。
adjusted_mode
内部显示时序,驱动程序可以使用这些时序来处理用户空间在mode中请求的模式与实际编程到硬件中的模式之间的差异。
对于使用
drm_bridge
的驱动程序,这存储CRTC和第一个桥之间的硬件显示时序。 对于其他驱动程序,adjusted_mode字段的含义纯粹是驱动程序实现定义的信息,通常用于存储CRTC和编码器块之间的硬件显示时序。mode
用户空间请求的显示时序。 驱动程序应尝试尽可能地匹配刷新率(但请注意,尚不清楚到底足够接近,例如,某些HDMI模式的刷新率差异小于1%)。 用户空间观察到的用于定位平面的活动宽度和高度必须完全匹配。
对于接收器未固定的外部连接器(例如内置面板),此处的模式应与线上的物理模式匹配到最后一个细节(即,包括同步极性等)。
mode_blob
drm_property_blob
用于mode,用于将模式公开给原子用户空间。degamma_lut
用于在应用颜色转换矩阵ctm之前转换帧缓冲区像素数据的查找表。 请参阅
drm_crtc_enable_color_mgmt()
。 blob(如果不是NULL)是struct drm_color_lut
的数组。ctm
颜色转换矩阵。 请参阅
drm_crtc_enable_color_mgmt()
。 blob(如果不是NULL)是struct drm_color_ctm
。gamma_lut
用于在颜色转换矩阵ctm之后转换像素数据的查找表。 请参阅
drm_crtc_enable_color_mgmt()
。 blob(如果不是NULL)是struct drm_color_lut
的数组。请注意,由于主要来自Xorg传承的历史原因,它也用于存储索引格式(如DRM_FORMAT_C8)的颜色映射(有时也称为颜色lut、CLUT或调色板)。
target_vblank
页面翻转生效时的目标垂直消隐周期。
async_flip
当在传统PAGE_FLIP IOCTL中设置DRM_MODE_PAGE_FLIP_ASYNC时,将设置此项。 它尚未连接到原子IOCTL本身。
vrr_enabled
指示是否应为CRTC启用可变刷新率。 对请求的vrr状态的支持将取决于驱动程序和硬件功能 - 缺少支持不被视为失败。
self_refresh_active
由自刷新辅助程序使用,以表示正在发生自刷新转换。 启用/禁用自刷新时,将在启用/禁用回调上设置此项。 在某些情况下,可能不希望在自刷新期间完全关闭crtc。 CRTC可以检查此标志并确定最佳操作方案。
scaling_filter
要应用的缩放过滤器
event
指向DRM事件的可选指针,以在状态更新完成后发出信号。 驱动程序必须在原子提交操作完成后发送事件。 有两种情况
此事件用于通过原子提交禁用的 CRTC。在这种情况下,硬件停止扫描当前帧缓冲区后,可以随时发送该事件。它应该包含显示管道关闭前的最后一个垂直空白的 timestamp 和计数器。实现这一点的最简单方法是在调用
drm_crtc_vblank_off()
之后,在某个时刻调用drm_crtc_send_vblank_event()
。对于在提交结束时启用的 CRTC(即使它经历了完整的模式设置),垂直空白 timestamp 和计数器必须是扫描输出新缓冲区集之前的垂直空白。同样,只有在硬件停止扫描输出旧缓冲区后,才能发送该事件。
不允许禁用 CRTC 的事件,驱动程序可以忽略这种情况。
对于没有 VBLANK 中断的非常简单的硬件,启用
struct drm_crtc_state
.no_vblank 会使 DRM 的原子提交辅助函数在所有硬件更改应用后,在显示更新结束时发送一个伪 VBLANK 事件。请参阅drm_atomic_helper_fake_vblank()
。对于更复杂的硬件,这可以通过
drm_crtc_send_vblank_event()
函数来处理,驱动程序应在原子提交完成后,在提供的事件上调用该函数。请注意,如果驱动程序支持垂直空白信号和 timestamp,则垂直空白计数器和 timestamp 必须与页面翻转事件返回的计数器和 timestamp 一致。使用当前的垂直空白辅助基础结构,这可以通过在页面翻转挂起时保持垂直空白引用来实现,该引用通过drm_crtc_vblank_get()
获取,并通过drm_crtc_vblank_put()
释放。驱动程序可以自由地实现自己的垂直空白计数器和 timestamp 跟踪,例如,如果它们在硬件中具有精确的 timestamp 寄存器。对于支持某种方式将垂直空白中断传递与提交显示状态同步的硬件,还存在
drm_crtc_arm_vblank_event()
。有关安全使用它所需约束的详细讨论,请参阅该函数的文档。如果设备根本无法以无竞争的方式通知翻转完成,则应在页面翻转提交后立即准备好该事件。在最坏的情况下,驱动程序会将事件发送到用户空间,延迟一帧。这不允许真正的原子更新,但应避免撕裂。
提交
这跟踪此更新的提交如何通过各个阶段。除非我们销毁状态,否则它永远不会被清除,以便后续提交可以与之前的提交同步。
state
指向全局 drm_atomic_state 的后向指针
描述
请注意,**enable** 和 **active** 之间的区别非常微妙:在 enable 设置时翻转 active 而不更改任何其他内容,可能永远不会从 drm_mode_config_funcs.atomic_check
回调中返回失败。用户空间假定 DPMS On 总是会成功。换句话说:**enable** 控制资源分配,**active** 控制实际的硬件状态。
三个布尔值 active_changed、connectors_changed 和 mode_changed 旨在指示是否需要完整的模式设置,而不是严格描述提交中发生了什么更改。另请参阅:drm_atomic_crtc_needs_modeset()
-
struct drm_crtc_funcs¶
控制给定设备的 CRTC
定义:
struct drm_crtc_funcs {
void (*reset)(struct drm_crtc *crtc);
int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height);
int (*cursor_set2)(struct drm_crtc *crtc, struct drm_file *file_priv,uint32_t handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y);
int (*cursor_move)(struct drm_crtc *crtc, int x, int y);
int (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,uint32_t size, struct drm_modeset_acquire_ctx *ctx);
void (*destroy)(struct drm_crtc *crtc);
int (*set_config)(struct drm_mode_set *set, struct drm_modeset_acquire_ctx *ctx);
int (*page_flip)(struct drm_crtc *crtc,struct drm_framebuffer *fb,struct drm_pending_vblank_event *event,uint32_t flags, struct drm_modeset_acquire_ctx *ctx);
int (*page_flip_target)(struct drm_crtc *crtc,struct drm_framebuffer *fb,struct drm_pending_vblank_event *event,uint32_t flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx);
int (*set_property)(struct drm_crtc *crtc, struct drm_property *property, uint64_t val);
struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
void (*atomic_destroy_state)(struct drm_crtc *crtc, struct drm_crtc_state *state);
int (*atomic_set_property)(struct drm_crtc *crtc,struct drm_crtc_state *state,struct drm_property *property, uint64_t val);
int (*atomic_get_property)(struct drm_crtc *crtc,const struct drm_crtc_state *state,struct drm_property *property, uint64_t *val);
int (*late_register)(struct drm_crtc *crtc);
void (*early_unregister)(struct drm_crtc *crtc);
int (*set_crc_source)(struct drm_crtc *crtc, const char *source);
int (*verify_crc_source)(struct drm_crtc *crtc, const char *source, size_t *values_cnt);
const char *const *(*get_crc_sources)(struct drm_crtc *crtc, size_t *count);
void (*atomic_print_state)(struct drm_printer *p, const struct drm_crtc_state *state);
u32 (*get_vblank_counter)(struct drm_crtc *crtc);
int (*enable_vblank)(struct drm_crtc *crtc);
void (*disable_vblank)(struct drm_crtc *crtc);
bool (*get_vblank_timestamp)(struct drm_crtc *crtc,int *max_error,ktime_t *vblank_time, bool in_vblank_irq);
};
成员
重置
将 CRTC 硬件和软件状态重置为关闭。此函数不是由核心直接调用的,而是仅通过
drm_mode_config_reset()
调用的。它不是仅用于历史原因的辅助钩子。原子驱动程序可以使用
drm_atomic_helper_crtc_reset()
通过此钩子重置原子状态。cursor_set
更新光标图像。光标位置相对于 CRTC,可以部分或完全位于可见区域之外。
请注意,与所有其他 KMS 函数相反,旧版光标入口点不采用帧缓冲区对象,而是直接从驱动程序的缓冲区管理器(对于当前驱动程序,为 GEM 或 TTM)获取原始缓冲区对象 ID。
此入口点已弃用,驱动程序应改为实现通用平面支持,并使用
drm_crtc_init_with_planes()
注册适当的光标平面。此回调是可选的
返回值
成功时为 0,失败时为负错误代码。
cursor_set2
更新光标图像,包括热点信息。热点不得影响 CRTC 坐标中的光标位置,而仅用作虚拟化显示硬件协调访客和主机光标位置的提示。光标热点相对于光标图像。否则,此函数的工作方式与 **cursor_set** 完全相同。
此入口点已弃用,驱动程序应改为实现通用平面支持,并使用
drm_crtc_init_with_planes()
注册适当的光标平面。此回调是可选的。
返回值
成功时为 0,失败时为负错误代码。
cursor_move
更新光标位置。调用此钩子时,光标不需要可见。
此入口点已弃用,驱动程序应改为实现通用平面支持,并使用
drm_crtc_init_with_planes()
注册适当的光标平面。此回调是可选的。
返回值
成功时为 0,失败时为负错误代码。
gamma_set
在 CRTC 上设置 gamma。
此回调是可选的。
想要支持 gamma 表的原子驱动程序应实现原子颜色管理支持,通过调用
drm_crtc_enable_color_mgmt()
启用,然后通过 drm_atomic_helper_legacy_gamma_set() 兼容性实现支持旧版 gamma 接口。destroy
清理 CRTC 资源。仅在驱动程序卸载时通过
drm_mode_config_cleanup()
调用,因为 CRTC 无法在 DRM 中热插拔。set_config
这是在 CRTC 上更改模式设置状态的主要旧版入口点。所需配置的所有详细信息都通过
struct drm_mode_set
传递 - 有关详细信息,请参见那里。实现原子模式设置的驱动程序应使用
drm_atomic_helper_set_config()
来实现此钩子。返回值
成功时为 0,失败时为负错误代码。
page_flip
旧版入口点,用于计划翻转到给定的帧缓冲区。
页面翻转是一种同步机制,它在垂直消隐期间用新的帧缓冲区替换 CRTC 正在扫描输出的帧缓冲区,从而避免了撕裂(除非通过 DRM_MODE_PAGE_FLIP_ASYNC 标志另行请求)。当应用程序请求页面翻转时,DRM 核心会验证新的帧缓冲区是否足够大,可以在当前配置的模式下由 CRTC 扫描输出,然后使用指向新帧缓冲区的指针调用此钩子。
驱动程序必须等待任何挂起的对新帧缓冲区的渲染完成,然后才能执行翻转。如果底层缓冲区是共享的 dma-buf,它还应等待来自其他驱动程序的任何挂起的渲染。
应用程序可以请求在页面翻转完成后收到通知。在这种情况下,drm 核心将在 event 参数中提供
struct drm_event
。这可以通过drm_crtc_send_vblank_event()
函数来处理,驱动程序应在翻转完成后,在提供的事件上调用该函数。请注意,如果驱动程序支持垂直空白信号和 timestamp,则垂直空白计数器和 timestamp 必须与页面翻转事件返回的计数器和 timestamp 一致。使用当前的垂直空白辅助基础结构,这可以通过在页面翻转挂起时保持垂直空白引用来实现,该引用通过drm_crtc_vblank_get()
获取,并通过drm_crtc_vblank_put()
释放。驱动程序可以自由地实现自己的垂直空白计数器和 timestamp 跟踪,例如,如果它们在硬件中具有精确的 timestamp 寄存器。此回调是可选的。
注意
KMS ABI 的非常早期的版本规定,驱动程序必须阻止(但不拒绝)任何对旧帧缓冲区的渲染,直到翻转操作完成并且旧帧缓冲区不再可见。此要求已取消,而是希望用户空间请求传递事件并等待回收旧缓冲区,直到收到此类事件。
返回值
成功时为 0,失败时为负错误代码。请注意,如果页面翻转操作已挂起,则回调应返回 -EBUSY。在禁用的 CRTC 上(通过设置 NULL 模式或仅通过 DPMS 分别运行时禁用新的原子“ACTIVE”状态)进行页面翻转应导致 -EINVAL 错误代码。请注意,
drm_atomic_helper_page_flip()
已经为原子驱动程序检查了这一点。page_flip_target
与 **page_flip** 相同,但具有一个额外的参数,用于指定翻转生效时的绝对目标垂直消隐周期(如
drm_crtc_vblank_count()
报告的)。请注意,核心代码会在调用此入口点之前调用 drm_crtc_vblank_get,如果此入口点返回任何非 0 错误代码,则会调用 drm_crtc_vblank_put。驱动程序有责任在此入口点返回 0 后调用 drm_crtc_vblank_put,通常在翻转完成时调用。
set_property
这是更新附加到 CRTC 的属性的旧版入口点。
如果驱动程序不支持任何旧版驱动程序私有属性,则此回调是可选的。对于原子驱动程序,它不使用,因为属性处理完全在 DRM 核心中完成。
返回值
成功时为 0,失败时为负错误代码。
atomic_duplicate_state
复制此 CRTC 的当前原子状态并返回它。核心和辅助函数保证任何使用此钩子复制的原子状态,并且仍然由调用者拥有(即,没有通过调用
drm_mode_config_funcs.atomic_commit
转移到驱动程序)将通过调用此结构中的 **atomic_destroy_state** 钩子进行清理。此回调对于原子驱动程序是必需的。
不继承
struct drm_crtc_state
的原子驱动程序应使用drm_atomic_helper_crtc_duplicate_state()
。继承状态结构以使用驱动程序私有状态扩展它的驱动程序应使用__drm_atomic_helper_crtc_duplicate_state()
以确保共享状态以跨驱动程序一致的方式复制。在正确初始化
drm_crtc.state
之前调用此钩子是一个错误。注意
如果重复的状态引用了引用计数的资源,则此钩子必须获取对每个资源的引用。驱动程序必须在 **atomic_destroy_state** 中再次释放这些引用。
返回值
重复的原子状态,或者当分配失败时为 NULL。
atomic_destroy_state
销毁使用 **atomic_duplicate_state** 复制的状态,并释放或取消引用它引用的所有资源
此回调对于原子驱动程序是必需的。
atomic_set_property
解码驱动程序私有属性值,并将解码后的值存储到传入的状态结构中。由于原子核心解码所有标准化属性(即使是超出核心属性集范围的扩展,这些扩展可能并非所有驱动程序都实现),因此这要求驱动程序继承状态结构。
此类驱动程序私有属性实际上只应为真正的硬件/供应商特定状态实现。相反,最好标准化原子扩展并在核心中解码用于公开此类扩展的属性。
不要直接调用此函数,而是使用 drm_atomic_crtc_set_property()。
如果驱动程序不支持任何驱动程序私有原子属性,则此回调是可选的。
注意
此函数在原子模式设置的状态程序集阶段中调用,该阶段可能因任何原因中止(包括应用户空间请求仅检查配置是否可能)。驱动程序不得触摸任何持久状态(硬件或软件)或数据结构,除了传入的 **state** 参数。
此外,由于用户空间控制属性的设置顺序,因此此函数不得进行任何输入验证(因为状态更新不完整,因此可能不一致)。相反,任何此类输入验证都必须在各种 atomic_check 回调中完成。
返回值
如果找到了该属性,则为 0;如果该属性未由驱动程序实现,则为 -EINVAL(这不应该发生,核心只请求附加到此 CRTC 的属性)。驱动程序不允许进行其他验证。核心已经检查了属性值是否在驱动程序注册属性时设置的范围内(整数、有效枚举值等)。
atomic_get_property
读出解码后的驱动程序私有属性。这用于实现 GETCRTC IOCTL。
不要直接调用此函数,而是使用 drm_atomic_crtc_get_property()。
如果驱动程序不支持任何驱动程序私有原子属性,则此回调是可选的。
返回值
成功时为 0,如果该属性未由驱动程序实现,则为 -EINVAL(这不应该发生,核心只请求附加到此 CRTC 的属性)。
late_register
此可选钩子可用于注册附加到 crtc 的其他用户空间接口,如 debugfs 接口。它在驱动程序加载序列的后期从
drm_dev_register()
调用。从此回调添加的所有内容都应在 early_unregister 回调中取消注册。返回
成功时为 0,失败时为负错误代码。
early_unregister
应使用此可选钩子来取消注册附加到 crtc 的其他用户空间接口,这些接口来自 **late_register**。它从
drm_dev_unregister()
调用,在驱动程序卸载序列的早期,以在数据结构被拆除之前禁用用户空间访问。set_crc_source
应用户空间的要求,更改帧的 CRC 校验和的来源,通常用于测试目的。可用来源是每个驱动程序特定的,
NULL
值表示要关闭 CRC 生成。启用 CRC 生成后,驱动程序应在每个帧调用
drm_crtc_add_crc_entry()
,在 crcN 参数中提供任何表征帧内容的信息,这些信息来自配置的来源。驱动程序必须接受一个“auto”来源名称,该名称将为此 CRTC 选择一个默认来源。如果需要,这可能会触发原子模式设置提交,以启用 CRC 生成。
请注意,“auto”可能取决于当前的模式设置配置,例如,它可以选择编码器或输出特定的 CRC 采样点。
如果驱动程序不支持任何 CRC 生成功能,则此回调是可选的。
返回值
成功时为 0,失败时为负错误代码。
verify_crc_source
在设置 CRC 的来源之前和在 crc 打开期间验证帧的 CRC 校验和的来源。在禁用 crc 来源时,Source 参数可以为 NULL。
如果驱动程序不支持任何 CRC 生成功能,则此回调是可选的。
返回值
成功时为 0,失败时为负错误代码。
get_crc_sources
用于获取 CRC 生成的所有可用来源列表的驱动程序回调。此回调依赖于 verify_crc_source,因此应在实现此回调之前实现 verify_crc_source 回调。驱动程序可以传递可用 crc 来源的完整列表,此回调在将每个 crc-source 传递给用户空间之前对其进行验证。
如果驱动程序不支持导出可能的 CRC 来源列表,则此回调是可选的。
返回值
指向所有可用 CRC 来源列表的常量字符指针。如果失败,驱动程序应返回 NULL。应使用列表中的来源数量更新 count。如果为零,我们不处理列表中的任何来源。
atomic_print_state
如果驱动程序继承
struct drm_crtc_state
,它应实现此可选钩子以打印其他驱动程序特定状态。不要直接调用此函数,而是使用 drm_atomic_crtc_print_state()。
get_vblank_counter
用于获取 CRTC 的原始硬件垂直空白计数器的驱动程序回调。它旨在供新驱动程序使用,作为
drm_driver.get_vblank_counter
钩子的替代品。此回调是可选的。如果设备没有硬件计数器,驱动程序可以简单地将钩子保留为 NULL。DRM 核心会在中断被禁用时,根据系统 timestamp 考虑错过的垂直空白事件。
由于模式设置导致的环绕处理和事件丢失在 DRM 核心代码中处理,只要驱动程序在禁用或启用 CRTC 时调用
drm_crtc_vblank_off()
和drm_crtc_vblank_on()
即可。另请参阅
drm_device.vblank_disable_immediate
和drm_device.max_vblank_count
。返回
原始垂直空白计数器值。
enable_vblank
为 CRTC 启用垂直空白中断。它旨在供新驱动程序使用,作为
drm_driver.enable_vblank
钩子的替代品。返回
成功时为零,如果无法启用垂直空白中断,则为适当的 errno。
disable_vblank
为 CRTC 禁用垂直空白中断。它旨在供新驱动程序使用,作为
drm_driver.disable_vblank
钩子的替代品。get_vblank_timestamp
由 drm_get_last_vbltimestamp() 调用。应返回最精确的 timestamp,指示最近的垂直空白间隔何时结束或将要结束。
具体来说,**vblank_time** 中的 timestamp 应尽可能接近垂直空白结束后视频帧的第一条视频扫描线将开始扫描输出的时间,即垂直空白间隔结束后立即的时间。如果 **crtc** 当前位于垂直空白中,这将是未来的时间。如果 **crtc** 当前正在扫描输出帧,这将是当前扫描输出的过去开始时间。这意味着要符合 OpenML OML_sync_control 扩展规范。
参数
- crtc
要为其返回 timestamp 的 CRTC。
- max_error
允许的最大 timestamp 误差(以纳秒为单位)。实现应努力提供误差最多为 max_error 纳秒的 timestamp。返回 timestamp 误差的真上界。
- vblank_time
返回的垂直空白 timestamp 的目标位置。
- in_vblank_irq
从
drm_crtc_handle_vblank()
调用时为 True。如果设置了标志,某些驱动程序需要应用一些针对 gpu 特定垂直空白 irq 怪癖的解决方法。
返回
成功时为 True,失败时为 False,这意味着核心应回退到在
drm_crtc_handle_vblank()
中获取的简单 timestamp。
描述
drm_crtc_funcs 结构是 DRM 中的中心 CRTC 管理结构。每个 CRTC 控制一个或多个连接器(请注意,名称 CRTC 只是历史名称,CRTC 可以控制 LVDS、VGA、DVI、TV 输出等连接器,而不仅仅是 CRT)。
除了提供其他模式设置功能(如 i2c 和 DDC 总线访问器)外,每个驱动程序都负责在启动时填写此结构。
-
struct drm_crtc¶
中心 CRTC 控制结构
定义:
struct drm_crtc {
struct drm_device *dev;
struct device_node *port;
struct list_head head;
char *name;
struct drm_modeset_lock mutex;
struct drm_mode_object base;
struct drm_plane *primary;
struct drm_plane *cursor;
unsigned index;
int cursor_x;
int cursor_y;
bool enabled;
struct drm_display_mode mode;
struct drm_display_mode hwmode;
int x;
int y;
const struct drm_crtc_funcs *funcs;
uint32_t gamma_size;
uint16_t *gamma_store;
const struct drm_crtc_helper_funcs *helper_private;
struct drm_object_properties properties;
struct drm_property *scaling_filter_property;
struct drm_crtc_state *state;
struct list_head commit_list;
spinlock_t commit_lock;
struct dentry *debugfs_entry;
struct drm_crtc_crc crc;
unsigned int fence_context;
spinlock_t fence_lock;
unsigned long fence_seqno;
char timeline_name[32];
struct drm_self_refresh_data *self_refresh_data;
};
成员
dev
父 DRM 设备
端口
由
drm_of_find_possible_crtcs()
使用的 OF 节点。head
dev 上的所有 CRTC 的列表,从
drm_mode_config.crtc_list
链接。在 dev 的整个生命周期内不变,因此不需要锁定。名称
人类可读的名称,可以由驱动程序覆盖
mutex
这为整体 CRTC 状态(模式、dpms 状态等)提供了一个读锁,为可以在没有完整模式设置的情况下更新的所有内容(fb、光标数据、CRTC 属性等)提供了一个写锁。完整的模式设置还需要获取
drm_mode_config.connection_mutex
。对于原子驱动程序,这专门保护 state。
基本
用于 ID 跟踪等的基本 KMS 对象。
主要
此 CRTC 的主平面。请注意,这仅与旧版 IOCTL 相关,它指定了 SETCRTC 和 PAGE_FLIP IOCTL 隐式使用的平面。除此之外,它没有任何意义。
光标
此 CRTC 的光标平面。请注意,这仅与旧版 IOCTL 相关,它指定了 SETCURSOR 和 SETCURSOR2 IOCTL 隐式使用的平面。除此之外,它没有任何意义。
索引
模式配置列表中的位置,可以用作数组索引。它在 CRTC 的整个生命周期内不变。
cursor_x
光标的当前 x 位置,用于通用光标平面,因为 SETCURSOR IOCTL 只能更新帧缓冲区,而无需提供坐标。驱动程序不应直接使用此值,原子驱动程序应查看光标平面的
drm_plane_state.crtc_x
。cursor_y
光标的当前 y 位置,用于通用光标平面,因为 SETCURSOR IOCTL 只能更新帧缓冲区,而无需提供坐标。驱动程序不应直接使用此值,原子驱动程序应查看光标平面的
drm_plane_state.crtc_y
。已启用
是否启用了 CRTC?仅应由旧驱动程序使用,原子驱动程序应改为查阅
drm_crtc_state.enable
和drm_crtc_state.active
。原子驱动程序可以通过调用drm_atomic_helper_update_legacy_modeset_state()
来更新此设置。mode
当前模式时序。仅应由旧驱动程序使用,原子驱动程序应改为查阅
drm_crtc_state.mode
。原子驱动程序可以通过调用drm_atomic_helper_update_legacy_modeset_state()
来更新此设置。hwmode
硬件中已编程的模式,经过对编码器、CRTC、面板缩放等的调整。仅应由旧驱动程序使用,用于
drm_crtc_vblank_helper_get_vblank_timestamp()
中的高精度垂直消隐时间戳。请注意,原子驱动程序不应使用此项,而应使用
drm_crtc_state.adjusted_mode
。对于高精度时间戳,drm_crtc_vblank_helper_get_vblank_timestamp()
使用drm_vblank_crtc.hwmode
,后者通过调用drm_calc_timestamping_constants()
填充。x
屏幕上的 x 位置。仅应由旧驱动程序使用,原子驱动程序应查看主平面的
drm_plane_state.crtc_x
。通过调用drm_atomic_helper_update_legacy_modeset_state()
更新。y
屏幕上的 y 位置。仅应由旧驱动程序使用,原子驱动程序应查看主平面的
drm_plane_state.crtc_y
。通过调用drm_atomic_helper_update_legacy_modeset_state()
更新。funcs
CRTC 控制函数
gamma_size
报告给用户空间的旧版伽马斜坡的大小。通过调用
drm_mode_crtc_set_gamma_size()
设置。请注意,原子驱动程序需要改为使用
drm_crtc_state.gamma_lut
。请参阅drm_crtc_enable_color_mgmt()
。gamma_store
旧版 SETGAMMA 和 GETGAMMA IOCTL 使用的伽马斜坡值。通过调用
drm_mode_crtc_set_gamma_size()
设置。请注意,原子驱动程序需要改为使用
drm_crtc_state.gamma_lut
。请参阅drm_crtc_enable_color_mgmt()
。helper_private
中间层私有数据
properties
此 CRTC 的属性跟踪
scaling_filter_property
在缩放时应用特定过滤器的属性。
state
此 CRTC 的当前原子状态。
受 **mutex** 保护。请注意,非阻塞原子提交在不获取锁的情况下访问当前的 CRTC 状态。可以通过
struct drm_atomic_state
指针,请参阅for_each_oldnew_crtc_in_state()
、for_each_old_crtc_in_state()
和for_each_new_crtc_in_state()
。或者通过原子辅助程序中实现的原子提交操作的仔细排序,请参阅struct drm_crtc_commit
。commit_list
跟踪挂起提交的
drm_crtc_commit
结构的列表。受 **commit_lock** 保护。此列表持有其自己的完整引用,正在进行的提交也是如此。“请注意,状态更改的提交也在
drm_crtc_state.commit
中跟踪。为了访问原子更新中紧邻之前的提交,建议仅使用旧 CRTC 状态中的指针,因为访问它不需要任何锁定或列表遍历。**commit_list** 仅应用于暂停帧缓冲区清理,该清理通过drm_crtc_commit.cleanup_done
发出信号。”commit_lock
用于保护 **commit_list** 的自旋锁。
debugfs_entry
此 CRTC 的 Debugfs 目录。
crc
CRC 捕获的配置设置。
fence_context
用于栅栏操作的时间线上下文。
fence_lock
用于保护 fence_context 中栅栏的自旋锁。
fence_seqno
用作 CRTC 时间线上创建的栅栏的单调计数器的 Seqno 变量。
timeline_name
CRTC 栅栏时间线的名称。
self_refresh_data
保存自刷新辅助程序的状态
通过
drm_self_refresh_helper_init()
初始化。
描述
每个 CRTC 可以有一个或多个与其关联的连接器。此结构允许控制 CRTC。
-
struct drm_mode_set¶
CRTC 配置更改的新值
定义:
struct drm_mode_set {
struct drm_framebuffer *fb;
struct drm_crtc *crtc;
struct drm_display_mode *mode;
uint32_t x;
uint32_t y;
struct drm_connector **connectors;
size_t num_connectors;
};
成员
fb
用于新配置的帧缓冲区
crtc
我们要更改其配置的 CRTC
mode
要使用的模式时序
x
此 CRTC 相对于 **fb** 的位置
y
此 CRTC 相对于 **fb** 的位置
connectors
如果可能,用于驱动此 CRTC 的连接器数组
num_connectors
**connectors** 数组的大小
描述
这表示旧版 SETCRTC ioctl 的模式集配置,也用于内部。原子驱动程序改为使用 drm_atomic_state
。
-
drmm_crtc_alloc_with_planes¶
drmm_crtc_alloc_with_planes (dev, type, member, primary, cursor, funcs, name, ...)
分配并初始化具有指定的主平面和光标平面的新 CRTC 对象。
参数
dev
DRM 设备
type
包含 struct
drm_crtc
的结构体的类型member
**type** 中的
drm_crtc
的名称。主要
CRTC 的主平面
光标
CRTC 的光标平面
funcs
新 CRTC 的回调
名称
CRTC 名称的 printf 样式格式字符串,如果为 NULL,则为默认名称
...
可变参数
描述
分配并初始化新的 crtc 对象。通过使用 drmm_add_action()
注册 drmm_crtc_cleanup() 来自动处理清理。
**drm_crtc_funcs.destroy** 挂钩必须为 NULL。
返回
指向新 crtc 的指针,如果失败,则为 ERR_PTR。
参数
const struct drm_crtc *crtc
要查找索引的 CRTC
描述
给定一个已注册的 CRTC,返回该 CRTC 在 DRM 设备的 CRTC 列表中的索引。
参数
const struct drm_crtc *crtc
要查找掩码的 CRTC
描述
给定一个已注册的 CRTC,返回该 CRTC 的掩码位,用于 drm_encoder.possible_crtcs
和 drm_plane.possible_crtcs
字段。
-
struct drm_crtc *drm_crtc_find(struct drm_device *dev, struct drm_file *file_priv, uint32_t id)¶
从其 ID 查找 CRTC 对象
参数
struct drm_device *dev
DRM 设备
struct drm_file *file_priv
用于检查租赁的 DRM 文件。
uint32_t id
描述
这可用于从其用户空间 ID 查找 CRTC。仅由驱动程序用于旧版 IOCTL 和接口,如今,KMS 用户空间接口的扩展应使用 drm_property
完成。
-
drm_for_each_crtc¶
drm_for_each_crtc (crtc, dev)
迭代所有 CRTC
-
drm_for_each_crtc_reverse¶
drm_for_each_crtc_reverse (crtc, dev)
以相反的顺序迭代所有 CRTC
-
struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)¶
查找索引处的已注册 CRTC
参数
struct drm_device *dev
DRM 设备
int idx
要查找的已注册 CRTC 的索引
描述
给定一个 CRTC 索引,从 DRM 设备的 CRTC 列表中返回具有匹配索引的已注册 CRTC。这是 drm_crtc_index()
的逆运算。它在垂直消隐回调(如 drm_driver.enable_vblank
或 drm_driver.disable_vblank
)中很有用,因为这仍然处理索引而不是指向 struct drm_crtc
的指针。”
-
int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor, const struct drm_crtc_funcs *funcs, const char *name, ...)¶
使用指定的主平面和光标平面初始化新的 CRTC 对象。
参数
struct drm_device *dev
DRM 设备
struct drm_crtc *crtc
要初始化的 CRTC 对象
struct drm_plane *primary
CRTC 的主平面
struct drm_plane *cursor
CRTC 的光标平面
const struct drm_crtc_funcs *funcs
新 CRTC 的回调
const char *name
CRTC 名称的 printf 样式格式字符串,如果为 NULL,则为默认名称
...
可变参数
描述
初始化作为驱动程序 crtc 对象基本部分创建的新对象。驱动程序应使用此函数而不是 drm_crtc_init()
,该函数仅为与尚不支持通用平面的驱动程序向后兼容而提供)。对于只有 1 个平面的非常简单的硬件,请查看 drm_simple_display_pipe_init()
。应该调用 drm_crtc_funcs.destroy
钩子 drm_crtc_cleanup()
和 kfree()
crtc 结构。crtc 结构不应使用 devm_kzalloc() 分配。
**primary** 和 **cursor** 平面仅与旧版 uAPI 相关,请参阅 drm_crtc.primary
和 drm_crtc.cursor
。
注意
考虑使用 drmm_crtc_alloc_with_planes()
或 drmm_crtc_init_with_planes()
而不是 drm_crtc_init_with_planes()
,以让 DRM 管理的资源基础设施负责清理和释放。
返回
成功时为零,失败时为错误代码。
-
int drmm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, struct drm_plane *cursor, const struct drm_crtc_funcs *funcs, const char *name, ...)¶
使用指定的主平面和光标平面初始化新的 CRTC 对象。
参数
struct drm_device *dev
DRM 设备
struct drm_crtc *crtc
要初始化的 CRTC 对象
struct drm_plane *primary
CRTC 的主平面
struct drm_plane *cursor
CRTC 的光标平面
const struct drm_crtc_funcs *funcs
新 CRTC 的回调
const char *name
CRTC 名称的 printf 样式格式字符串,如果为 NULL,则为默认名称
...
可变参数
描述
初始化作为驱动程序 crtc 对象基本部分创建的新对象。驱动程序应使用此函数代替 drm_crtc_init()
,它仅用于向后兼容尚不支持通用平面的驱动程序)。对于只有 1 个平面的非常简单的硬件,请查看 drm_simple_display_pipe_init()
。
清理工作通过使用 drmm_add_action()
注册 drmm_crtc_cleanup() 自动处理。应使用 drmm_kzalloc()
分配 crtc 结构。
**drm_crtc_funcs.destroy** 挂钩必须为 NULL。
**primary** 和 **cursor** 平面仅与旧版 uAPI 相关,请参阅 drm_crtc.primary
和 drm_crtc.cursor
。
返回
成功时为零,失败时为错误代码。
参数
struct drm_crtc *crtc
要清理的 CRTC
描述
此函数清理 **crtc** 并将其从 DRM 模式设置核心中移除。请注意,该函数_不会_释放 crtc 结构本身,这是调用者的责任。
-
int drm_mode_set_config_internal(struct drm_mode_set *set)¶
调用
drm_mode_config_funcs.set_config
的帮助程序
参数
struct drm_mode_set *set
要设置的模式集配置
描述
这是一个用于包装对 drm_mode_config_funcs.set_config
驱动程序接口的内部调用的一个小帮助程序。它唯一添加的是正确的引用计数。
这应该仅由非原子旧版驱动程序使用。
返回
成功时返回零,失败时返回负 errno。
-
int drm_crtc_check_viewport(const struct drm_crtc *crtc, int x, int y, const struct drm_display_mode *mode, const struct drm_framebuffer *fb)¶
检查帧缓冲区是否足够大以用于 CRTC 视口
参数
const struct drm_crtc *crtc
将在其上显示帧缓冲区的 CRTC
int x
x 平移
int y
y 平移
const struct drm_display_mode *mode
将在其下显示帧缓冲区的模式
const struct drm_framebuffer *fb
要检查大小的帧缓冲区
-
int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc, unsigned int supported_filters)¶
创建新的缩放滤镜属性
参数
struct drm_crtc *crtc
drm CRTC
unsigned int supported_filters
支持的缩放滤镜的位掩码,必须包括 BIT(DRM_SCALING_FILTER_DEFAULT)。
描述
此函数允许驱动程序在给定的 CRTC 上启用缩放滤镜属性。
返回
成功时返回零,或返回 -errno
-
bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state)¶
检查给定的 CRTC 状态是否处于克隆模式
参数
struct drm_crtc_state *crtc_state
要检查的 CRTC 状态
描述
此函数确定给定的 CRTC 状态是否正被多个编码器克隆。
返回
如果 CRTC 状态处于克隆模式,则为 True。否则为 False
颜色管理函数参考¶
-
u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n)¶
参数
u64 user_input
输入值
u32 m
整数位的数量,仅支持 m <= 32,包括符号位
u32 n
小数位的数量,仅支持 n <= 32
描述
将 S31.32 符号大小转换为 Qm.n(带符号的 2 的补码)并进行截断。符号位 BIT(m+n-1) 及以上为 0 表示正值,为 1 表示负值,值的范围为 [-2^(m-1), 2^(m-1) - 2^-n]
例如,Q3.12 格式的数字: - 必需的位:3 + 12 = 15 位 - 范围:[-2^2, 2^2 - 2^−15]
注意
- 如果所有 bit_precision 都用于表示小数,则 m 可以为零
位,如 Q0.32
-
void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, uint degamma_lut_size, bool has_ctm, uint gamma_lut_size)¶
启用颜色管理属性
参数
struct drm_crtc *crtc
DRM CRTC
uint degamma_lut_size
去伽玛 lut 的大小(CSC 之前)
bool has_ctm
是否为 CSC 矩阵附加 ctm_property
uint gamma_lut_size
伽玛 lut 的大小(CSC 之后)
描述
此函数允许驱动程序在 CRTC 上启用颜色校正属性。这包括 3 个去伽玛、csc 和伽玛属性,用户空间可以设置,以及 2 个大小属性,用于通知用户空间 lut 的大小。每个属性都是可选的。仅当大小不为 0 时才附加伽玛和去伽玛属性,并且仅当 has_ctm 为 true 时才附加 ctm_property。
参数
struct drm_crtc *crtc
要设置伽玛表大小的 CRTC
int gamma_size
伽玛表的大小
描述
支持伽玛表的驱动程序应在初始化 CRTC 时将其设置为支持的伽玛表大小。目前,drm 核心仅支持固定的伽玛表大小。
返回
成功时返回零,失败时返回负 errno。
-
int drm_plane_create_color_properties(struct drm_plane *plane, u32 supported_encodings, u32 supported_ranges, enum drm_color_encoding default_encoding, enum drm_color_range default_range)¶
颜色编码相关的平面属性
参数
struct drm_plane *plane
平面对象
u32 supported_encodings
指示支持的颜色编码的位字段
u32 supported_ranges
指示支持的颜色范围的位字段
enum drm_color_encoding default_encoding
默认颜色编码
enum drm_color_range default_range
默认颜色范围
描述
创建并附加平面特定的 COLOR_ENCODING 和 COLOR_RANGE 属性到 **plane**。支持的编码和范围应在 supported_encodings 和 supported_ranges 位掩码中提供。在位掩码中设置的每个位指示支持将其编号作为枚举值。
-
int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests)¶
检查查找表的有效性
参数
const struct drm_property_blob *lut
包含要检查的 LUT 的属性 Blob
u32 tests
要运行的测试的位掩码
描述
帮助程序,用于检查用户空间提供的查找表是否有效并满足硬件要求。驱动程序传递一个位掩码,指示应执行 drm_color_lut_tests
中的哪些测试。
成功时返回 0,失败时返回 -EINVAL。
-
u32 drm_color_lut_extract(u32 user_input, int bit_precision)¶
截断并舍入 LUT 条目
参数
u32 user_input
输入值
int bit_precision
硬件 LUT 支持的位数
描述
提取用户提供的去伽玛/伽玛 LUT 值(以 drm_color_lut
条目的形式),并按照 OpenGL int<->float 转换规则将其舍入到硬件支持的精度(例如,请参见 OpenGL 4.6 规范 - 2.3.5 定点数据转换)。
-
int drm_color_lut_size(const struct drm_property_blob *blob)¶
计算 LUT 中的条目数
参数
const struct drm_property_blob *blob
包含 LUT 的 Blob
返回
存储在 **blob** 中的颜色 LUT 中的条目数。
-
enum drm_color_lut_tests¶
要执行的特定于硬件的 LUT 测试
常量
DRM_COLOR_LUT_EQUAL_CHANNELS
检查 LUT 的条目是否所有通道(红色、绿色和蓝色)都具有相等的值。适用于仅接受每个 LUT 条目的单个值并假定该值应用于所有三个颜色分量的硬件。
DRM_COLOR_LUT_NON_DECREASING
检查 LUT 的条目是否始终平坦或增加(从不减少)。
描述
drm_color_lut_check()
函数采用此处值的位掩码,以确定要应用于用户空间提供的 LUT 的哪些测试。
帧缓冲区抽象¶
帧缓冲区是抽象的内存对象,它提供像素源以扫描到 CRTC。应用程序通过 DRM_IOCTL_MODE_ADDFB(2) ioctl 显式请求创建帧缓冲区,并接收一个不透明的句柄,该句柄可以传递到 KMS CRTC 控制、平面配置和页面翻转函数。
帧缓冲区依赖于底层内存管理器来分配后备存储。创建帧缓冲区时,应用程序通过 struct drm_mode_fb_cmd2
参数传递内存句柄(或用于多平面格式的内存句柄列表)。对于使用 GEM 作为其用户空间缓冲区管理接口的驱动程序,这将是 GEM 句柄。但是,驱动程序可以自由使用其自己的后备存储对象句柄,例如,vmwgfx 直接向用户空间公开特殊的 TTM 句柄,因此在创建 ioctl 中需要 TTM 句柄,而不是 GEM 句柄。
帧缓冲区使用 struct drm_framebuffer
进行跟踪。它们使用 drm_framebuffer_init()
发布 - 调用该函数后,用户空间可以使用和访问帧缓冲区对象。帮助程序函数 drm_helper_mode_fill_fb_struct()
可用于预填充所需的元数据字段。
DRM帧缓冲区的生命周期由引用计数控制,驱动程序可以使用drm_framebuffer_get()
获取额外的引用,并使用drm_framebuffer_put()
再次释放它们。对于驱动程序私有的帧缓冲区,其中最后一个引用永远不会被释放(例如,当struct drm_framebuffer
结构嵌入到fbdev辅助结构中时,用于fbdev帧缓冲区),驱动程序可以在模块卸载时使用drm_framebuffer_unregister_private()
手动清理帧缓冲区。但不建议这样做,最好有一个独立的struct drm_framebuffer
。
帧缓冲区函数参考¶
-
struct drm_framebuffer_funcs¶
帧缓冲区钩子
定义:
struct drm_framebuffer_funcs {
void (*destroy)(struct drm_framebuffer *framebuffer);
int (*create_handle)(struct drm_framebuffer *fb,struct drm_file *file_priv, unsigned int *handle);
int (*dirty)(struct drm_framebuffer *framebuffer,struct drm_file *file_priv, unsigned flags,unsigned color, struct drm_clip_rect *clips, unsigned num_clips);
};
成员
destroy
清理帧缓冲区资源,特别是取消对后备存储的引用。核心保证为每个通过调用
drm_mode_config_funcs.fb_create
成功创建的帧缓冲区调用此函数。驱动程序还必须调用drm_framebuffer_cleanup()
来释放此帧缓冲区的DRM核心资源。create_handle
在特定于驱动程序的缓冲区管理器(GEM或TTM)中为传入的
struct drm_file
创建一个缓冲区句柄。核心使用它来实现GETFB IOCTL,它(对于具有足够权限的用户)也返回一个本机缓冲区句柄。这可以用于模式设置客户端之间的无缝转换,方法是将当前屏幕内容复制到私有缓冲区,并在该缓冲区和新内容之间进行混合。基于GEM的驱动程序应该调用
drm_gem_handle_create()
来创建句柄。返回值
成功时为 0,失败时为负错误代码。
dirty
用于脏fb IOCTL的可选回调。
用户空间可以通过此回调通知驱动程序帧缓冲区的某个区域已更改,应刷新到显示硬件。这也可以在内部使用,例如,通过fbdev仿真,但目前情况并非如此。
有关更多信息,请参阅drm_mode.h中的drm_mode_fb_dirty_cmd结构文档,因为所有语义和参数都与此函数一一对应。
原子驱动程序应使用
drm_atomic_helper_dirtyfb()
来实现此钩子。返回值
成功时为 0,失败时为负错误代码。
-
struct drm_framebuffer¶
帧缓冲区对象
定义:
struct drm_framebuffer {
struct drm_device *dev;
struct list_head head;
struct drm_mode_object base;
char comm[TASK_COMM_LEN];
const struct drm_format_info *format;
const struct drm_framebuffer_funcs *funcs;
unsigned int pitches[DRM_FORMAT_MAX_PLANES];
unsigned int offsets[DRM_FORMAT_MAX_PLANES];
uint64_t modifier;
unsigned int width;
unsigned int height;
int flags;
struct list_head filp_head;
struct drm_gem_object *obj[DRM_FORMAT_MAX_PLANES];
};
成员
dev
此帧缓冲区所属的DRM设备
head
基本
基本模式设置对象结构,包含引用计数。
comm
分配fb的进程名称,用于fb转储。
格式
帧缓冲区格式信息
funcs
帧缓冲区vfunc表
pitches
每个缓冲区的行跨度。对于用户空间创建的对象,这是从drm_mode_fb_cmd2复制的。
offsets
从缓冲区开始到实际像素数据的偏移量(以字节为单位),每个缓冲区。对于用户空间创建的对象,这是从drm_mode_fb_cmd2复制的。
请注意,这是一个线性偏移量,不考虑每个modifier的平铺或缓冲区布局。它旨在用于此帧缓冲区平面的实际像素数据以偏移量开始时,例如,当多个平面在同一个后备存储缓冲区对象中分配时。对于平铺布局,这通常意味着它的offsets必须至少与平铺大小对齐,但硬件通常有更严格的要求。
这不应用于指定到缓冲区数据中的x/y像素偏移量(即使对于线性缓冲区)。指定x/y像素偏移量而是通过
struct drm_plane_state
中的源矩形完成的。modifier
数据布局修饰符。这用于描述辅助缓冲区的平铺或特殊布局(如压缩)。对于用户空间创建的对象,这是从drm_mode_fb_cmd2复制的。
width
帧缓冲区可见区域的逻辑宽度(以像素为单位)。
height
帧缓冲区可见区域的逻辑高度(以像素为单位)。
标志
帧缓冲区标志,如DRM_MODE_FB_INTERLACED或DRM_MODE_FB_MODIFIERS。
filp_head
放置在
drm_file.fbs
上,受drm_file.fbs_lock
保护。obj
支持帧缓冲区的GEM对象,每个平面一个(可选)。
这由GEM帧缓冲区辅助程序使用,例如,请参阅
drm_gem_fb_create()
。
描述
请注意,fb被引用计数,以方便驱动程序内部使用,例如,某些硬件,禁用CRTC/平面是异步的,并且扫描输出实际上直到下一个垂直消隐才完成。因此,一些清理(如释放对后备GEM bo的引用)应该被推迟。在这种情况下,驱动程序希望保持对fb的引用,即使它已经从用户空间的角度删除了。请参阅drm_framebuffer_get()
和drm_framebuffer_put()
。
引用计数存储在模式对象base中。
-
void drm_framebuffer_get(struct drm_framebuffer *fb)¶
获取帧缓冲区引用
参数
struct drm_framebuffer *fb
DRM帧缓冲区
描述
此函数递增帧缓冲区的引用计数。
-
void drm_framebuffer_put(struct drm_framebuffer *fb)¶
释放帧缓冲区引用
参数
struct drm_framebuffer *fb
DRM帧缓冲区
描述
此函数递减帧缓冲区的引用计数,如果引用计数降至零,则释放帧缓冲区。
-
uint32_t drm_framebuffer_read_refcount(const struct drm_framebuffer *fb)¶
读取帧缓冲区引用计数。
参数
const struct drm_framebuffer *fb
帧缓冲区
描述
此函数返回帧缓冲区的引用计数。
-
void drm_framebuffer_assign(struct drm_framebuffer **p, struct drm_framebuffer *fb)¶
存储对fb的引用
参数
struct drm_framebuffer **p
存储帧缓冲区的位置
struct drm_framebuffer *fb
新的帧缓冲区(可能为NULL)
描述
此函数设置存储对帧缓冲区的引用的位置,取消引用先前存储在该位置的帧缓冲区。
-
struct drm_afbc_framebuffer¶
一个特殊的afbc帧缓冲区对象
定义:
struct drm_afbc_framebuffer {
struct drm_framebuffer base;
u32 block_width;
u32 block_height;
u32 aligned_width;
u32 aligned_height;
u32 offset;
u32 afbc_size;
};
成员
基本
基本帧缓冲区结构。
block_width
单个afbc块的宽度
block_height
单个afbc块的高度
aligned_width
对齐的帧缓冲区宽度
aligned_height
对齐的帧缓冲区高度
offset
第一个afbc标头的偏移量
afbc_size
afbc缓冲区的最小大小
描述
一个struct drm_framebuffer
的派生类,专用于afbc用例。
-
int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, const struct drm_framebuffer_funcs *funcs)¶
初始化帧缓冲区
参数
struct drm_device *dev
DRM 设备
struct drm_framebuffer *fb
要初始化的帧缓冲区
const struct drm_framebuffer_funcs *funcs
...使用这些函数
描述
为帧缓冲区的父模式对象分配一个ID,设置其模式函数和设备文件,并将其添加到主fd列表。
重要提示:此函数发布fb并使其可供其他用户并发访问。这意味着到目前为止,fb _必须_完全设置 - 由于所有fb属性在其生命周期内是不变的,因此不需要进一步锁定,只需要正确的引用计数。
返回
成功时为零,失败时为错误代码。
-
struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, struct drm_file *file_priv, uint32_t id)¶
查找DRM帧缓冲区并获取引用
参数
struct drm_device *dev
drm 设备
struct drm_file *file_priv
用于检查租赁的 DRM 文件。
uint32_t id
fb对象的id
描述
如果成功,这将获取对帧缓冲区的额外引用 - 调用者需要确保最终再次取消引用返回的帧缓冲区,使用drm_framebuffer_put()
。
-
void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)¶
从查找idr中注销私有fb
参数
struct drm_framebuffer *fb
要注销的fb
描述
驱动程序需要在清理驱动程序私有帧缓冲区时调用此函数,例如,用于fbdev的帧缓冲区。请注意,调用者必须持有自己的引用,即对象可能不会通过此调用销毁(因为它会导致锁定反转)。
注意
此函数已弃用。对于驱动程序私有帧缓冲区,不建议将帧缓冲区结构嵌入到fbdev结构中,而是首选帧缓冲区指针,并且在清理帧缓冲区时应调用drm_framebuffer_put()
。
-
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)¶
删除帧缓冲区对象
参数
struct drm_framebuffer *fb
要删除的帧缓冲区
描述
清理帧缓冲区。此函数旨在从驱动程序的drm_framebuffer_funcs.destroy
回调中使用。它也可以用于清理嵌入到较大结构中的驱动程序私有帧缓冲区。
请注意,此函数不会从活动使用中删除fb - 如果它仍然在任何地方使用,可能会出现混乱,因为用户空间可以调用getfb上的id并返回-EINVAL。显然,在驱动程序卸载时不用担心。
此外,帧缓冲区不会从查找idr中删除 - 对于用户创建的帧缓冲区,这将发生在rmfb ioctl中。对于驱动程序私有对象(例如,对于fbdev),驱动程序需要显式调用drm_framebuffer_unregister_private。
-
void drm_framebuffer_remove(struct drm_framebuffer *fb)¶
删除并取消引用帧缓冲区对象
参数
struct drm_framebuffer *fb
要删除的帧缓冲区
描述
扫描dev的mode_config中的所有CRTC和平面。如果它们正在使用fb,则将其删除,将其设置为NULL。然后删除对传入帧缓冲区的引用。可能需要模式设置锁。
请注意,如果调用者持有对帧缓冲区的最后一个引用,则此函数会优化清理过程。在这种情况下,它也保证不会获取模式设置锁。
DRM格式处理¶
在DRM子系统中,帧缓冲区像素格式使用include/uapi/drm/drm_fourcc.h中定义的fourcc代码描述。除了fourcc代码外,还可以选择提供格式修饰符,以便进一步描述缓冲区的格式 - 例如平铺或压缩。
格式修饰符¶
格式修饰符与fourcc代码结合使用,形成唯一的fourcc:modifier对。此格式:modifier对必须完全定义缓冲区的格式和数据布局,并且应该是描述该特定缓冲区的唯一方法。
应避免具有描述相同布局的多个fourcc:modifier对,因为此类别名存在不同的驱动程序为相同数据格式公开不同名称的风险,从而迫使用户空间了解它们是别名。
格式修饰符可以更改缓冲区的任何属性,包括平面数和/或所需的分配大小。格式修饰符是供应商命名的,因此fourcc代码和修饰符之间的关系特定于正在使用的修饰符。例如,某些修饰符可能会保留来自fourcc代码的含义 - 例如平面数 - 而另一些修饰符可能不会。
修饰符必须唯一地编码缓冲区布局。换句话说,一个缓冲区必须只匹配一个修饰符。一个修饰符不能是另一个修饰符的布局的子集。例如,在修饰符中编码pitch对齐是不正确的:一个缓冲区可能匹配一个64像素对齐的修饰符和一个32像素对齐的修饰符。也就是说,修饰符可以具有隐式最小要求。
对于fourcc代码和修饰符的组合可以别名的修饰符,需要定义一个规范对并由所有驱动程序使用。还鼓励使用首选组合,在所有组合都可能导致混淆并过度降低互操作性的情况下。AFBC是后者的一个例子,其中ABGR布局优先于ARGB布局。
有两种类型的修饰符用户
内核和用户空间驱动程序:对于驱动程序来说,修饰符不别名非常重要,否则两个驱动程序可能支持相同的格式但使用不同的别名,从而阻止它们以高效的格式共享缓冲区。
与KMS/GBM/EGL/Vulkan等接口的高级程序:这些用户将修饰符视为他们可以检查相等性和相交的不透明令牌。这些用户不需要知道修饰符值的推理(即,不期望他们从修饰符中提取信息)。
供应商应尽可能详细地记录其修饰符的使用情况,以确保跨设备、驱动程序和应用程序的最大兼容性。
格式修饰符代码的权威列表可以在include/uapi/drm/drm_fourcc.h中找到
开源用户豁免¶
因为这是GL、Vulkan扩展和其他标准引用的像素格式和修饰符的权威来源,因此被开源和闭源驱动程序堆栈使用,因此通常的上游内核或开源用户空间用户的要求不适用。
为了尽可能确保跨堆栈的兼容性,并避免与不兼容的枚举混淆,所有相关驱动程序堆栈的利益相关者都应批准添加。
格式函数参考¶
-
DRM_FORMAT_MAX_PLANES¶
DRM_FORMAT_MAX_PLANES
DRM格式可以具有的最大平面数
-
struct drm_format_info¶
有关DRM格式的信息
定义:
struct drm_format_info {
u32 format;
u8 depth;
u8 num_planes;
union {
u8 cpp[DRM_FORMAT_MAX_PLANES];
u8 char_per_block[DRM_FORMAT_MAX_PLANES];
};
u8 block_w[DRM_FORMAT_MAX_PLANES];
u8 block_h[DRM_FORMAT_MAX_PLANES];
u8 hsub;
u8 vsub;
bool has_alpha;
bool is_yuv;
bool is_color_indexed;
};
成员
格式
4CC格式标识符 (DRM_FORMAT_*)
depth
颜色深度(每个像素的位数,不包括填充位),仅对RGB格式的子集有效。这是一个遗留字段,请勿在新代码中使用,并为新格式设置为0。
num_planes
颜色平面数(1到3)
{unnamed_union}
anonymous
cpp
每个像素(每个平面)的字节数,这与char_per_block别名。不推荐使用它,而推荐使用三元组char_per_block、block_w、block_h,以便更好地描述像素格式。
char_per_block
每个块(每个平面)的字节数,其中块定义为像素的矩形,这些像素存储在字节对齐的内存区域中。与block_w和block_h一起,这用于正确描述平铺格式中的图块或描述打包格式中的像素组,对于这些格式,单个像素所需的内存不是字节对齐的。
由于驱动程序中有很多地方使用cpp,因此出于历史原因保留了它。在drm核心中,对于通用代码路径,首选使用char_per_block、
drm_format_info_block_width()
和drm_format_info_block_height()
,这允许以相同的方式处理块和非块格式。对于仅用于非线性修改器的格式,通用格式表中的 cpp 和 char_per_block 必须都为 0。如果驱动程序希望核心验证 pitch,它们可以从其 drm_mode_config.get_format_info 钩子提供准确的信息。
block_w
块的像素宽度,旨在通过
drm_format_info_block_width()
访问block_h
块的像素高度,旨在通过
drm_format_info_block_height()
访问hsub
水平色度子采样因子
vsub
垂直色度子采样因子
has_alpha
该格式是否嵌入了 alpha 分量?
is_yuv
它是否是 YUV 格式?
is_color_indexed
它是否是颜色索引格式?
-
bool drm_format_info_is_yuv_packed(const struct drm_format_info *info)¶
检查格式信息是否与以单平面形式排列的 YUV 格式匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 packed YUV 格式匹配。
-
bool drm_format_info_is_yuv_semiplanar(const struct drm_format_info *info)¶
检查格式信息是否与以两个平面形式排列的 YUV 格式匹配(亮度分量和色度分量)
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 semiplanar YUV 格式匹配。
-
bool drm_format_info_is_yuv_planar(const struct drm_format_info *info)¶
检查格式信息是否与以三个平面形式排列的 YUV 格式匹配(每个 YUV 分量一个平面)
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 planar YUV 格式匹配。
-
bool drm_format_info_is_yuv_sampling_410(const struct drm_format_info *info)¶
检查格式信息是否与 4:1:0 子采样的 YUV 格式匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 4:1:0 子采样的 YUV 格式匹配。
-
bool drm_format_info_is_yuv_sampling_411(const struct drm_format_info *info)¶
检查格式信息是否与 4:1:1 子采样的 YUV 格式匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 4:1:1 子采样的 YUV 格式匹配。
-
bool drm_format_info_is_yuv_sampling_420(const struct drm_format_info *info)¶
检查格式信息是否与 4:2:0 子采样的 YUV 格式匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 4:2:0 子采样的 YUV 格式匹配。
-
bool drm_format_info_is_yuv_sampling_422(const struct drm_format_info *info)¶
检查格式信息是否与 4:2:2 子采样的 YUV 格式匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 4:2:2 子采样的 YUV 格式匹配。
-
bool drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info)¶
检查格式信息是否与 4:4:4 子采样的 YUV 格式匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与 4:4:4 子采样的 YUV 格式匹配。
-
int drm_format_info_plane_width(const struct drm_format_info *info, int width, int plane)¶
给定第一个平面,计算该平面的宽度
参数
const struct drm_format_info *info
像素格式信息
int width
第一个平面的宽度
int plane
平面索引
返回
如果第一个平面的宽度为 width,则 plane 的宽度。
-
int drm_format_info_plane_height(const struct drm_format_info *info, int height, int plane)¶
给定第一个平面,计算该平面的高度
参数
const struct drm_format_info *info
像素格式信息
int height
第一个平面的高度
int plane
平面索引
返回
如果第一个平面的高度为 height,则 plane 的高度。
-
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)¶
从传统描述计算 drm fourcc 代码
参数
uint32_t bpp
每像素位数
uint32_t depth
每像素位深度
描述
为给定的 bpp/depth 值计算 drm fourcc 像素格式代码。
-
uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth)¶
从传统描述计算 drm fourcc 代码
参数
struct drm_device *dev
DRM 设备
uint32_t bpp
每像素位数
uint32_t depth
每像素位深度
描述
为给定的 bpp/depth 值计算 drm fourcc 像素格式代码。与 drm_mode_legacy_fb_format()
不同,它会查看驱动程序的 mode_config,并根据 drm_mode_config.quirk_addfb_prefer_host_byte_order
标志返回小端字节序或主机字节序帧缓冲格式。
-
uint32_t drm_driver_color_mode_format(struct drm_device *dev, unsigned int color_mode)¶
从颜色模式计算 DRM 4CC 代码
参数
struct drm_device *dev
DRM 设备
unsigned int color_mode
命令行颜色模式
描述
使用 drm_driver_color_mode() 为给定的颜色模式计算 DRM 4CC 像素格式代码。颜色模式采用命令行使用的格式。它在一个值中指定每像素的位数和颜色深度。
在 fbdev 仿真代码中非常有用,因为它处理这些值。该助手不考虑 YUV 或其他复杂格式。这意味着仅支持传统格式(fmt->depth 是一个传统字段),但帧缓冲仿真只能处理此类格式,特别是 RGB/BGA 格式。
-
const struct drm_format_info *drm_format_info(u32 format)
查询给定格式的信息
参数
u32 format
像素格式 (DRM_FORMAT_*)
描述
调用者应仅将支持的像素格式传递给此函数。不支持的像素格式将在内核日志中生成警告。
返回
描述像素格式的 struct drm_format_info
实例,如果不支持该格式,则为 NULL。
-
const struct drm_format_info *drm_get_format_info(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd)¶
查询给定帧缓冲配置的信息
参数
struct drm_device *dev
DRM 设备
const struct drm_mode_fb_cmd2 *mode_cmd
来自用户空间 fb 创建请求的元数据
返回
描述像素格式的 struct drm_format_info
实例,如果不支持该格式,则为 NULL。
-
unsigned int drm_format_info_block_width(const struct drm_format_info *info, int plane)¶
块的像素宽度。
参数
const struct drm_format_info *info
像素格式信息
int plane
平面索引
返回
块的像素宽度,具体取决于平面索引。
-
unsigned int drm_format_info_block_height(const struct drm_format_info *info, int plane)¶
块的像素高度
参数
const struct drm_format_info *info
像素格式信息
int plane
平面索引
返回
块的像素高度,具体取决于平面索引。
-
unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane)¶
每像素位数
参数
const struct drm_format_info *info
像素格式信息
int plane
平面索引
返回
每像素的实际位数,具体取决于平面索引。
-
uint64_t drm_format_info_min_pitch(const struct drm_format_info *info, int plane, unsigned int buffer_width)¶
计算所需的最小 pitch(以字节为单位)
参数
const struct drm_format_info *info
像素格式信息
int plane
平面索引
unsigned int buffer_width
缓冲区宽度(以像素为单位)
返回
通过考虑像素格式信息和缓冲区宽度,计算缓冲区所需的最小 pitch(以字节为单位)。
Dumb 缓冲区对象¶
KMS API 不标准化后备存储对象的创建,而是将其留给特定于驱动程序的 ioctl。此外,即使对于基于 GEM 的驱动程序,实际创建缓冲区对象也是通过特定于驱动程序的 ioctl 完成的 - GEM 仅具有用于共享和销毁对象的通用用户空间接口。虽然对于包括设备特定用户空间组件的完整图形堆栈(例如在 libdrm 中)来说这不是问题,但此限制使基于 DRM 的早期启动图形不必要地复杂。
Dumb 对象通过提供适用于扫描输出的 dumb 缓冲区的标准 API,部分缓解了该问题,然后可用于创建 KMS 帧缓冲区。
为了支持 dumb 对象,驱动程序必须实现 drm_driver.dumb_create
和 drm_driver.dumb_map_offset
操作(如果未设置后者,则默认为 drm_gem_dumb_map_offset()
)。不使用 GEM 句柄的驱动程序还需要实现 drm_driver.dumb_destroy
操作。有关更多详细信息,请参见回调。
请注意,dumb 对象可能不用于 gpu 加速,正如某些 ARM 嵌入式平台上尝试的那样。此类驱动程序确实必须具有特定于硬件的 ioctl 才能分配合适的缓冲区对象。
平面抽象¶
平面表示一个图像源,可以在扫描输出过程中与 CRTC 混合或叠加在 CRTC 之上。平面从 drm_framebuffer
对象获取其输入数据。平面本身指定该图像的裁剪和缩放,以及它在显示流水线的可见区域上的位置,该可见区域由 drm_crtc
表示。平面还可以具有指定像素如何定位和混合的其他属性,例如旋转或 Z 轴位置。所有这些属性都存储在 drm_plane_state
中。
除非明确指定(通过 CRTC 属性或其他方式),否则 CRTC 的活动区域默认将为黑色。这意味着未被平面覆盖的活动区域部分将为黑色,并且任何平面与 CRTC 背景的 alpha 混合将在最低 zpos 处与黑色混合。
要创建平面,KMS 驱动程序会分配并将 struct drm_plane
的实例清零(可能作为更大的结构的一部分),并通过调用 drm_universal_plane_init()
注册它。
每个平面都有一个类型,请参见 enum drm_plane_type
。一个平面可以与多个 CRTC 兼容,请参见 drm_plane.possible_crtcs
。
每个 CRTC 必须具有一个唯一的 primary plane,用户空间可以附加该 primary plane 以启用 CRTC。换句话说,用户空间必须能够同时将不同的 primary plane 附加到每个 CRTC。Primary plane 仍然可以与多个 CRTC 兼容。Primary plane 的数量必须与 CRTC 的数量完全相同。
旧版 uAPI 不会直接公开 primary plane 和 cursor plane。DRM 核心依赖于驱动程序来设置用于旧版 IOCTL 的 primary plane 和可选的 cursor plane。这是通过调用 drm_crtc_init_with_planes()
来完成的。所有驱动程序都必须为每个 CRTC 提供一个 primary plane,以避免让旧版用户空间感到意外。
平面函数参考¶
-
struct drm_plane_state¶
可变平面状态
定义:
struct drm_plane_state {
struct drm_plane *plane;
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct dma_fence *fence;
int32_t crtc_x;
int32_t crtc_y;
uint32_t crtc_w, crtc_h;
uint32_t src_x;
uint32_t src_y;
uint32_t src_h, src_w;
int32_t hotspot_x, hotspot_y;
u16 alpha;
uint16_t pixel_blend_mode;
unsigned int rotation;
unsigned int zpos;
unsigned int normalized_zpos;
enum drm_color_encoding color_encoding;
enum drm_color_range color_range;
struct drm_property_blob *fb_damage_clips;
bool ignore_damage_clips;
struct drm_rect src, dst;
bool visible;
enum drm_scaling_filter scaling_filter;
struct drm_crtc_commit *commit;
struct drm_atomic_state *state;
bool color_mgmt_changed : 1;
};
成员
plane
指向平面的后向指针
crtc
当前绑定的 CRTC,如果禁用则为 NULL。不要直接写入此项,请使用
drm_atomic_set_crtc_for_plane()
fb
当前绑定的帧缓冲区。不要直接写入此项,请使用
drm_atomic_set_fb_for_plane()
fence
在扫描输出 fb 之前要等待的可选 fence。当用户空间使用显式 fencing 时,核心原子代码将设置此项。不要为驱动程序的隐式 fence 直接写入此字段。
驱动程序应从此结构中存储来自其
drm_plane_helper_funcs.prepare_fb
回调中的任何隐式 fence。请参见drm_gem_plane_helper_prepare_fb()
以获取合适的帮助程序。crtc_x
平面在 crtc 上的可见部分的左侧位置,带符号的目标位置允许其部分位于屏幕外。
crtc_y
平面在 crtc 上的可见部分的上方位置,带符号的目标位置允许其部分位于屏幕外。
crtc_w
平面在 crtc 上的可见部分的宽度
crtc_h
平面在 crtc 上的可见部分的高度
src_x
平面内平面可见部分的左侧位置(以 16.16 定点表示)。
src_y
平面内平面可见部分的上方位置(以 16.16 定点表示)。
src_h
平面可见部分的高度(以 16.16 表示)
src_w
平面可见部分的宽度(以 16.16 表示)
hotspot_x
鼠标光标热点的 x 偏移量
hotspot_y
鼠标光标热点的 y 偏移量
alpha
平面的不透明度,0 表示完全透明,0xffff 表示完全不透明。有关更多详细信息,请参见
drm_plane_create_alpha_property()
。pixel_blend_mode
alpha 混合公式选择,描述当前平面的像素如何与背景合成。值可以是 DRM_MODE_BLEND_* 之一
rotation
平面的旋转。有关更多详细信息,请参见
drm_plane_create_rotation_property()
。zpos
给定平面在 crtc 上的优先级(可选)。
用户空间可以设置可变 zpos 属性,以便同一 CRTC 上的多个活动平面具有相同的 zpos 值。这是一个用户空间的错误,但驱动程序可以通过比较平面对象 ID 来解决冲突;ID 较高的平面堆叠在 ID 较低的平面之上。
有关更多详细信息,请参见
drm_plane_create_zpos_property()
和drm_plane_create_zpos_immutable_property()
。normalized_zpos
zpos 的标准化值:唯一,范围从 0 到 N-1,其中 N 是给定 crtc 的活动平面数。请注意,驱动程序必须设置
drm_mode_config.normalize_zpos
或调用drm_atomic_normalize_zpos()
以在此值可信之前更新它。color_encoding
非 RGB 格式的颜色编码
color_range
非 RGB 格式的颜色范围
fb_damage_clips
Blob 表示损坏(自上次平面更新以来平面帧缓冲区中更改的区域),作为附加帧缓冲区的帧缓冲区坐标中的
drm_mode_rect
数组。请注意,与平面 src 不同,损坏剪辑不是 16.16 定点。有关访问这些剪辑的信息,请参见
drm_plane_get_damage_clips()
和drm_plane_get_damage_clips_count()
。ignore_damage_clips
由驱动程序设置,以指示
drm_atomic_helper_damage_iter_init()
帮助程序应忽略 fb_damage_clips blob 属性。有关更多信息,请参见 损坏跟踪属性。
src
平面的源坐标(以 16.16 表示)。
使用
drm_atomic_helper_check_plane_state()
时,坐标会被裁剪,但当硬件自动执行裁剪时,驱动程序可以选择改用未裁剪的坐标。dst
平面的裁剪目标坐标。
使用
drm_atomic_helper_check_plane_state()
时,坐标会被裁剪,但当硬件自动执行裁剪时,驱动程序可以选择改用未裁剪的坐标。visible
平面的可见性。即使 fb!=NULL 且 crtc!=NULL,由于裁剪,这也可能为 false。
scaling_filter
要应用的缩放过滤器
提交
跟踪挂起的提交以防止使用后释放情况,并用于异步平面更新。
可能为 NULL。
state
指向全局 drm_atomic_state 的后向指针
color_mgmt_changed
颜色管理属性已更改。由原子帮助程序和驱动程序用于引导原子提交控制流。
描述
请注意,目标坐标 crtc_x、crtc_y、crtc_h 和 crtc_w 以及源坐标 src_x、src_y、src_h 和 src_w 是用户空间提供的原始坐标。驱动程序应使用 drm_atomic_helper_check_plane_state()
,并且仅使用 src 和 dst 中的派生矩形来编程硬件。
-
struct drm_plane_funcs¶
驱动程序平面控制函数
定义:
struct drm_plane_funcs {
int (*update_plane)(struct drm_plane *plane,struct drm_crtc *crtc, struct drm_framebuffer *fb,int crtc_x, int crtc_y,unsigned int crtc_w, unsigned int crtc_h,uint32_t src_x, uint32_t src_y,uint32_t src_w, uint32_t src_h, struct drm_modeset_acquire_ctx *ctx);
int (*disable_plane)(struct drm_plane *plane, struct drm_modeset_acquire_ctx *ctx);
void (*destroy)(struct drm_plane *plane);
void (*reset)(struct drm_plane *plane);
int (*set_property)(struct drm_plane *plane, struct drm_property *property, uint64_t val);
struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);
void (*atomic_destroy_state)(struct drm_plane *plane, struct drm_plane_state *state);
int (*atomic_set_property)(struct drm_plane *plane,struct drm_plane_state *state,struct drm_property *property, uint64_t val);
int (*atomic_get_property)(struct drm_plane *plane,const struct drm_plane_state *state,struct drm_property *property, uint64_t *val);
int (*late_register)(struct drm_plane *plane);
void (*early_unregister)(struct drm_plane *plane);
void (*atomic_print_state)(struct drm_printer *p, const struct drm_plane_state *state);
bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format, uint64_t modifier);
bool (*format_mod_supported_async)(struct drm_plane *plane, u32 format, u64 modifier);
};
成员
update_plane
这是启用和配置给定 CRTC 和帧缓冲区的平面的旧版入口点。它永远不会被调用来禁用平面,即传入的 crtc 和 fb 参数永远不会为 NULL。
帧缓冲区内存坐标中的源矩形由 src_x、src_y、src_w 和 src_h 参数给出(作为 16.16 定点值)。不支持子像素平面坐标的设备可以忽略小数部分。
CRTC 坐标中的目标矩形由 crtc_x、crtc_y、crtc_w 和 crtc_h 参数给出(作为整数值)。设备将源矩形缩放到目标矩形。如果不支持缩放,并且源矩形大小与目标矩形大小不匹配,则驱动程序必须返回 -<errorname>EINVAL</errorname> 错误。
实现原子模式设置的驱动程序应使用
drm_atomic_helper_update_plane()
来实现此挂钩。返回值
成功时为 0,失败时为负错误代码。
disable_plane
这是禁用平面的旧版入口点。DRM 核心响应于帧缓冲区 ID 设置为 0 的 DRM_IOCTL_MODE_SETPLANE IOCTL 调用来调用此方法。CRTC 不得处理禁用的平面。
实现原子模式设置的驱动程序应使用
drm_atomic_helper_disable_plane()
来实现此挂钩。返回值
成功时为 0,失败时为负错误代码。
destroy
清理平面资源。这仅在驱动程序卸载时通过
drm_mode_config_cleanup()
调用,因为平面无法在 DRM 中热插拔。重置
将平面硬件和软件状态重置为关闭。此函数不是由核心直接调用,而是仅通过
drm_mode_config_reset()
调用。它不是帮助程序挂钩,仅是出于历史原因。原子驱动程序可以使用
drm_atomic_helper_plane_reset()
以使用此挂钩重置原子状态。set_property
这是更新附加到平面的属性的旧版入口点。
如果驱动程序不支持任何旧版驱动程序私有属性,则此回调是可选的。对于原子驱动程序,它不使用,因为属性处理完全在 DRM 核心中完成。
返回值
成功时为 0,失败时为负错误代码。
atomic_duplicate_state
为此平面复制当前原子状态并返回它。核心和帮助程序保证使用此挂钩复制的任何原子状态,并且仍然由调用方拥有(即,未通过调用
drm_mode_config_funcs.atomic_commit
转移到驱动程序)将通过调用此结构中的 atomic_destroy_state 挂钩来清理。此回调对于原子驱动程序是必需的。
不继承
struct drm_plane_state
的原子驱动程序应使用drm_atomic_helper_plane_duplicate_state()
。继承状态结构以使用驱动程序私有状态扩展它的驱动程序应使用__drm_atomic_helper_plane_duplicate_state()
以确保在驱动程序之间以一致的方式复制共享状态。在正确初始化
drm_plane.state
之前调用此挂钩是一个错误。注意
如果重复的状态引用了引用计数的资源,则此钩子必须获取对每个资源的引用。驱动程序必须在 **atomic_destroy_state** 中再次释放这些引用。
返回值
重复的原子状态,或者当分配失败时为 NULL。
atomic_destroy_state
销毁使用 **atomic_duplicate_state** 复制的状态,并释放或取消引用它引用的所有资源
此回调对于原子驱动程序是必需的。
atomic_set_property
解码驱动程序私有属性值,并将解码后的值存储到传入的状态结构中。由于原子核心解码所有标准化属性(即使是超出核心属性集范围的扩展,这些扩展可能并非所有驱动程序都实现),因此这要求驱动程序继承状态结构。
此类驱动程序私有属性实际上只应为真正的硬件/供应商特定状态实现。相反,最好标准化原子扩展并在核心中解码用于公开此类扩展的属性。
不要直接调用此函数,请改为使用 drm_atomic_plane_set_property()。
如果驱动程序不支持任何驱动程序私有原子属性,则此回调是可选的。
注意
此函数在原子模式设置的状态程序集阶段中调用,该阶段可能因任何原因中止(包括应用户空间请求仅检查配置是否可能)。驱动程序不得触摸任何持久状态(硬件或软件)或数据结构,除了传入的 **state** 参数。
此外,由于用户空间控制属性的设置顺序,因此此函数不得进行任何输入验证(因为状态更新不完整,因此可能不一致)。相反,任何此类输入验证都必须在各种 atomic_check 回调中完成。
返回值
如果已找到该属性,则为 0;如果驱动程序未实现该属性,则为 -EINVAL(这永远不应发生,核心仅请求附加到此平面的属性)。驱动程序不允许进行其他验证。核心已检查属性值是否在驱动程序在注册属性时设置的范围内(整数、有效枚举值等)。
atomic_get_property
读出解码的驱动程序私有属性。这用于实现 GETPLANE IOCTL。
不要直接调用此函数,请改为使用 drm_atomic_plane_get_property()。
如果驱动程序不支持任何驱动程序私有原子属性,则此回调是可选的。
返回值
成功时为 0,如果驱动程序未实现该属性,则为 -EINVAL(这永远不应发生,核心仅请求附加到此平面的属性)。
late_register
此可选挂钩可用于注册附加到平面的其他用户空间接口,如 debugfs 接口。它在驱动程序加载序列的后期从
drm_dev_register()
调用。应在 early_unregister 回调中取消注册从此回调添加的所有内容。返回
成功时为 0,失败时为负错误代码。
early_unregister
此可选挂钩应用于取消注册来自 late_register 的附加到平面的其他用户空间接口。它从
drm_dev_unregister()
调用,在驱动程序卸载序列的早期禁用用户空间访问,然后再分解数据结构。atomic_print_state
如果驱动程序继承
struct drm_plane_state
,则它应实现此可选挂钩以打印其他驱动程序特定状态。不要直接调用此函数,请改为使用 drm_atomic_plane_print_state()。
format_mod_supported
此可选挂钩由 DRM 用于确定给定的格式/修饰符组合对于平面是否有效。这允许 DRM 生成正确的格式位掩码(哪些格式适用于哪些修饰符),并在 atomic_check 时验证修饰符。
如果不存在,则允许平面的修饰符列表中的任何修饰符与平面的任何格式一起使用。
返回
如果给定的修饰符对于平面上的该格式有效,则为 True。否则为 False。
format_mod_supported_async
此可选挂钩由 DRM 用于确定对于异步翻转,给定的格式/修饰符组合对于平面是否有效。这允许 DRM 生成正确的格式位掩码(哪些格式适用于哪些修饰符),并在 atomic_check 时验证修饰符。
返回
如果给定的修饰符对于平面上的该格式有效,则为 True。否则为 False。
-
enum drm_plane_type¶
uapi 平面类型枚举
常量
DRM_PLANE_TYPE_OVERLAY
Overlay plane 表示所有非 primary、非 cursor plane。某些驱动程序在内部将这些类型的平面称为“精灵”。
DRM_PLANE_TYPE_PRIMARY
当不使用缩放/裁剪并且平面覆盖整个 CRTC 时,附加到 CRTC 的 primary plane 最有可能能够点亮 CRTC。
DRM_PLANE_TYPE_CURSOR
当不使用缩放/裁剪并且帧缓冲区的大小由
drm_mode_config.cursor_width
和drm_mode_config.cursor_height
指示时,附加到 CRTC 的 cursor plane 更有可能能够启用。此外,如果驱动程序不支持修饰符,则帧缓冲区应具有线性布局。
描述
由于历史原因,并非所有平面的制造方式都相同。此枚举用于区分不同类型的平面,以实现它们的不同 uapi 语义。对于了解通用平面并且正在使用原子 IOCTL 的用户空间,这些平面之间没有区别(当然,除了驱动程序和硬件可以支持的内容之外)。
为了与旧版用户空间兼容,默认情况下仅向用户空间提供 overlay plane。用户空间客户端可以设置 DRM_CLIENT_CAP_UNIVERSAL_PLANES
客户端功能位,以指示他们希望接收包含所有平面类型的通用平面列表。另请参见 drm_for_each_legacy_plane()
。
除了设置每个平面的类型外,驱动程序还需要为旧版 IOCTL 设置 drm_crtc.primary
和可选的 drm_crtc.cursor
指针。请参见 drm_crtc_init_with_planes()
。
警告:此枚举的值是 UABI,因为它们在“type”属性中公开。
-
struct drm_plane¶
中央 DRM 平面控制结构
定义:
struct drm_plane {
struct drm_device *dev;
struct list_head head;
char *name;
struct drm_modeset_lock mutex;
struct drm_mode_object base;
uint32_t possible_crtcs;
uint32_t *format_types;
unsigned int format_count;
bool format_default;
uint64_t *modifiers;
unsigned int modifier_count;
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_framebuffer *old_fb;
const struct drm_plane_funcs *funcs;
struct drm_object_properties properties;
enum drm_plane_type type;
unsigned index;
const struct drm_plane_helper_funcs *helper_private;
struct drm_plane_state *state;
struct drm_property *alpha_property;
struct drm_property *zpos_property;
struct drm_property *rotation_property;
struct drm_property *blend_mode_property;
struct drm_property *color_encoding_property;
struct drm_property *color_range_property;
struct drm_property *scaling_filter_property;
struct drm_property *hotspot_x_property;
struct drm_property *hotspot_y_property;
struct kmsg_dumper kmsg_panic;
};
成员
dev
此平面所属的 DRM 设备
head
dev 上的所有平面列表,从
drm_mode_config.plane_list
链接。在 dev 的生命周期内是不变的,因此不需要锁定。名称
人类可读的名称,可以由驱动程序覆盖
mutex
与此平面链接的 CRTC 的
drm_crtc.mutex
一起保护模式设置平面状态(当活动、正在激活或正在禁用时)。对于原子驱动程序,这专门保护 state。
基本
基本模式对象
possible_crtcs
此平面可以绑定到的管道,由
drm_crtc_mask()
构造format_types
此平面支持的格式数组
format_count
format_types 指向的数组的大小。
format_default
驱动程序未提供平面支持的格式。仅由非原子驱动程序兼容性包装器使用。
modifiers
此平面支持的修饰符数组
modifier_count
modifier_count 指向的数组的大小。
crtc
当前绑定的 CRTC,仅对非原子驱动程序有意义。对于原子驱动程序,这将被强制为 NULL,原子驱动程序应改为检查
drm_plane_state.crtc
。fb
当前绑定的帧缓冲区,仅对非原子驱动程序有意义。对于原子驱动程序,这将被强制为 NULL,原子驱动程序应改为检查
drm_plane_state.fb
。old_fb
在模式设置正在进行时,临时跟踪旧的 fb。仅由非原子驱动程序使用,对于原子驱动程序,这将被强制为 NULL。
funcs
平面控制函数
properties
此平面的属性跟踪
type
平面类型,有关详细信息,请参见
enum drm_plane_type
。索引
模式配置列表中位置,可以用作数组索引。在平面的生命周期内是不变的。
helper_private
中间层私有数据
state
此平面的当前原子状态。
这受 mutex 保护。请注意,非阻塞原子提交无需获取锁即可访问当前平面状态。可以通过
struct drm_atomic_state
指针进行访问,请参见for_each_oldnew_plane_in_state()
、for_each_old_plane_in_state()
和for_each_new_plane_in_state()
。或者通过原子帮助程序中实现的原子提交操作的仔细排序进行访问,请参见struct drm_crtc_commit
。alpha_property
此平面可选的 alpha 属性。请参阅
drm_plane_create_alpha_property()
。zpos_property
此平面可选的 zpos 属性。请参阅
drm_plane_create_zpos_property()
。rotation_property
此平面可选的 rotation 属性。请参阅
drm_plane_create_rotation_property()
。blend_mode_property
此平面可选的“像素混合模式”枚举属性。混合模式属性表示 alpha 混合方程的选择,描述如何将当前平面的像素与背景合成。
color_encoding_property
可选的“COLOR_ENCODING”枚举属性,用于为非 RGB 格式指定颜色编码。请参阅
drm_plane_create_color_properties()
。color_range_property
可选的“COLOR_RANGE”枚举属性,用于为非 RGB 格式指定颜色范围。请参阅
drm_plane_create_color_properties()
。scaling_filter_property
在缩放时应用特定过滤器的属性。
hotspot_x_property
用于设置鼠标热点 x 偏移量的属性。
hotspot_y_property
用于设置鼠标热点 y 偏移量的属性。
kmsg_panic
用于为此平面注册 panic 通知器
描述
平面代表显示块的扫描输出硬件。它们从 drm_framebuffer
接收其输入数据,并将其馈送到 drm_crtc
。平面控制颜色转换,更多细节请参阅 平面合成属性,并且还参与输入像素的颜色转换,有关详细信息,请参阅 颜色管理属性。
-
drmm_universal_plane_alloc¶
drmm_universal_plane_alloc (dev, type, member, possible_crtcs, funcs, formats, format_count, format_modifiers, plane_type, name, ...)
分配并初始化一个通用平面对象
参数
dev
DRM 设备
type
包含结构体
drm_plane
的结构体的类型member
type 中
drm_plane
的名称possible_crtcs
可能的 CRTC 的位掩码
funcs
新平面的回调
格式
支持格式的数组 (DRM_FORMAT_*)
format_count
formats 中的元素数量
format_modifiers
struct drm_format modifiers 数组,以 DRM_FORMAT_MOD_INVALID 结尾
plane_type
平面类型(overlay,primary,cursor)
名称
平面名称的 printf 样式格式字符串,如果为 NULL 则使用默认名称
...
可变参数
描述
分配并初始化类型为 type 的平面对象。通过使用 drmm_add_action()
注册 drm_plane_cleanup()
来自动处理清理工作。
drm_plane_funcs.destroy 钩子必须为 NULL。
仅支持 DRM_FORMAT_MOD_LINEAR modifier 的驱动程序可以将 format_modifiers 设置为 NULL。该平面将声明 linear modifier。
返回
指向新平面的指针,如果失败,则为 ERR_PTR。
-
drm_universal_plane_alloc¶
drm_universal_plane_alloc (dev, type, member, possible_crtcs, funcs, formats, format_count, format_modifiers, plane_type, name, ...)
分配并初始化一个通用平面对象
参数
dev
DRM 设备
type
包含结构体
drm_plane
的结构体的类型member
type 中
drm_plane
的名称possible_crtcs
可能的 CRTC 的位掩码
funcs
新平面的回调
格式
支持格式的数组 (DRM_FORMAT_*)
format_count
formats 中的元素数量
format_modifiers
struct drm_format modifiers 数组,以 DRM_FORMAT_MOD_INVALID 结尾
plane_type
平面类型(overlay,primary,cursor)
名称
平面名称的 printf 样式格式字符串,如果为 NULL 则使用默认名称
...
可变参数
描述
分配并初始化类型为 type 的平面对象。调用者负责使用 kfree()
释放已分配的内存。
建议驱动程序使用 drmm_universal_plane_alloc()
代替。
仅支持 DRM_FORMAT_MOD_LINEAR modifier 的驱动程序可以将 format_modifiers 设置为 NULL。该平面将声明 linear modifier。
返回
指向新平面的指针,如果失败,则为 ERR_PTR。
参数
要查找索引的平面
用于查找索引的平面
描述
给定一个已注册的平面,返回该平面在 DRM 设备平面列表中的索引。
参数
要查找索引的平面
要查找掩码的平面
-
struct drm_plane *drm_plane_find(struct drm_device *dev, struct drm_file *file_priv, uint32_t id)¶
查找一个
drm_plane
参数
struct drm_device *dev
DRM 设备
struct drm_file *file_priv
用于检查租赁的 DRM 文件。
uint32_t id
平面 ID
描述
返回具有 id 的平面,如果不存在则返回 NULL。只是 drm_mode_object_find()
的一个简单包装器。
-
drm_for_each_plane_mask¶
drm_for_each_plane_mask (plane, dev, plane_mask)
迭代由位掩码指定的平面
参数
plane
循环游标
dev
DRM 设备
plane_mask
平面索引的位掩码
描述
迭代由位掩码指定的所有平面。
-
drm_for_each_legacy_plane¶
drm_for_each_legacy_plane (plane, dev)
为旧版用户空间迭代所有平面
参数
plane
循环游标
dev
DRM 设备
描述
迭代 dev 的所有旧版平面,不包括主平面和光标平面。当用户空间不知道通用平面时,这对于实现用户空间 API 非常有用。另请参阅 enum drm_plane_type
。
-
drm_for_each_plane¶
drm_for_each_plane (plane, dev)
迭代所有平面
参数
plane
循环游标
dev
DRM 设备
描述
迭代 dev 的所有平面,包括主平面和光标平面。
-
int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, uint32_t possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, unsigned int format_count, const uint64_t *format_modifiers, enum drm_plane_type type, const char *name, ...)¶
初始化一个新的通用平面对象
参数
struct drm_device *dev
DRM 设备
struct drm_plane *plane
要初始化的平面对象
uint32_t possible_crtcs
可能的 CRTC 的位掩码
const struct drm_plane_funcs *funcs
新平面的回调
const uint32_t *formats
支持格式的数组 (DRM_FORMAT_*)
unsigned int format_count
formats 中的元素数量
const uint64_t *format_modifiers
struct drm_format modifiers 数组,以 DRM_FORMAT_MOD_INVALID 结尾
enum drm_plane_type type
平面类型(overlay,primary,cursor)
const char *name
平面名称的 printf 样式格式字符串,如果为 NULL 则使用默认名称
...
可变参数
描述
初始化类型为 type 的平面对象。drm_plane_funcs.destroy
钩子应该调用 drm_plane_cleanup()
并且使用 kfree()
释放平面结构。不应该使用 devm_kzalloc() 分配平面结构。
仅支持 DRM_FORMAT_MOD_LINEAR modifier 的驱动程序可以将 format_modifiers 设置为 NULL。该平面将声明 linear modifier。
注意
考虑使用 drmm_universal_plane_alloc()
代替 drm_universal_plane_init()
,以便让 DRM 管理的资源基础架构处理清理和释放。
返回
成功时为零,失败时为错误代码。
参数
struct drm_plane *plane
要清理的平面
描述
此函数清理 plane 并将其从 DRM 模式设置核心中移除。请注意,该函数 *不* 释放平面结构本身,这由调用者负责。
-
struct drm_plane *drm_plane_from_index(struct drm_device *dev, int idx)¶
查找指定索引处的已注册平面
参数
struct drm_device *dev
DRM 设备
int idx
要查找的已注册平面的索引
描述
给定一个平面索引,从 DRM 设备的平面列表中返回具有匹配索引的已注册平面。这是 drm_plane_index()
的逆操作。
参数
struct drm_plane *plane
要禁用的平面
描述
强制禁用该平面。
在该平面当前 framebuffer 被销毁时以及恢复 fbdev 模式时使用。
请注意,此函数不适用于原子驱动程序,因为它没有正确地连接锁定获取上下文,因此无法处理重试或驱动程序私有锁定。你可能想使用 drm_atomic_helper_disable_plane()
或 drm_atomic_helper_disable_planes_on_crtc()
来代替。
-
int drm_mode_plane_set_obj_prop(struct drm_plane *plane, struct drm_property *property, uint64_t value)¶
设置属性的值
参数
struct drm_plane *plane
要在其上设置属性值的 drm 平面对象
struct drm_property *property
要设置的属性
uint64_t value
属性应设置为的值
描述
此函数在给定的平面对象上设置给定的属性。如果回调成功,此函数将调用驱动程序的 ->set_property 回调并更改属性的软件状态。
返回
成功时为零,失败时为错误代码。
参数
struct drm_plane *plane
drm 平面
u32 format
像素格式 (DRM_FORMAT_*)
u64 modifier
数据布局修饰符
返回
平面是否支持指定的格式和修饰符组合。
-
bool drm_any_plane_has_format(struct drm_device *dev, u32 format, u64 modifier)¶
检查是否有任何平面支持此格式和修饰符组合
参数
struct drm_device *dev
DRM 设备
u32 format
像素格式 (DRM_FORMAT_*)
u64 modifier
数据布局修饰符
返回
是否至少有一个平面支持指定的格式和修饰符组合。
参数
struct drm_plane *plane
要在其上启用损坏剪辑属性的平面。
描述
此函数允许驱动程序在平面上启用损坏剪辑属性。
-
unsigned int drm_plane_get_damage_clips_count(const struct drm_plane_state *state)¶
返回损坏剪辑计数。
参数
const struct drm_plane_state *state
平面状态。
描述
一个简单的辅助函数,用于获取用户空间在平面更新期间设置的 drm_mode_rect
裁剪区域的数量。
返回
平面 fb_damage_clips blob 属性中的裁剪区域数量。
-
struct drm_mode_rect *drm_plane_get_damage_clips(const struct drm_plane_state *state)¶
返回损坏的裁剪区域。
参数
const struct drm_plane_state *state
平面状态。
描述
请注意,此函数返回 uapi 类型 drm_mode_rect
。驱动程序可能希望使用辅助函数 drm_atomic_helper_damage_iter_init()
和 drm_atomic_helper_damage_iter_next()
或 drm_atomic_helper_damage_merged()
,如果驱动程序最多只能处理单个损坏区域。
返回
平面 fb_damage_clips blob 属性中的损坏裁剪区域。
-
int drm_plane_create_scaling_filter_property(struct drm_plane *plane, unsigned int supported_filters)¶
创建新的缩放滤镜属性
参数
struct drm_plane *plane
drm 平面
unsigned int supported_filters
支持的缩放滤镜的位掩码,必须包括 BIT(DRM_SCALING_FILTER_DEFAULT)。
描述
此函数允许驱动程序在给定平面上启用缩放滤镜属性。
返回
成功时返回零,或返回 -errno
-
int drm_plane_add_size_hints_property(struct drm_plane *plane, const struct drm_plane_size_hint *hints, int num_hints)¶
创建一个大小提示属性
参数
struct drm_plane *plane
drm 平面
const struct drm_plane_size_hint *hints
大小提示
int num_hints
大小提示的数量
描述
为平面创建一个大小提示属性。
返回
成功时返回零,或返回 -errno
平面合成函数参考¶
参数
struct drm_plane *plane
drm 平面
描述
此函数创建一个通用的、可变的 alpha 属性,并在 DRM 核心中启用对其的支持。 它附加到 plane。
alpha 属性将被允许在 0(透明)到 0xffff(不透明)的范围内。
返回
成功时返回 0,失败时返回负错误代码。
-
int drm_plane_create_rotation_property(struct drm_plane *plane, unsigned int rotation, unsigned int supported_rotations)¶
创建一个新的旋转属性
参数
struct drm_plane *plane
drm 平面
unsigned int rotation
旋转属性的初始值
unsigned int supported_rotations
支持的旋转和反射的位掩码
描述
这将创建一个新属性,其中包含对转换的选定支持。
由于旋转 180° 与同时沿 x 轴和 y 轴反射相同,因此旋转属性有点冗余。驱动程序可以使用 drm_rotation_simplify()
来标准化此属性的值。
暴露给用户空间的属性是一个位掩码属性(请参阅 drm_property_create_bitmask()
),名为“rotation”,并具有以下位掩码枚举值
- DRM_MODE_ROTATE_0
“rotate-0”
- DRM_MODE_ROTATE_90
“rotate-90”
- DRM_MODE_ROTATE_180
“rotate-180”
- DRM_MODE_ROTATE_270
“rotate-270”
- DRM_MODE_REFLECT_X
“reflect-x”
- DRM_MODE_REFLECT_Y
“reflect-y”
旋转是在逆时针方向上指定的角度量,X 轴和 Y 轴位于源矩形内,即旋转之前的 X/Y 轴。 反射后,旋转将应用于从源矩形采样的图像,然后在缩放该图像以适合目标矩形之前。
-
unsigned int drm_rotation_simplify(unsigned int rotation, unsigned int supported_rotations)¶
尝试简化旋转
参数
unsigned int rotation
要简化的旋转
unsigned int supported_rotations
支持的旋转
描述
尝试将旋转简化为支持的形式。例如,如果硬件支持除 DRM_MODE_REFLECT_X 之外的所有内容,则可以像这样调用此函数
- drm_rotation_simplify(rotation, DRM_MODE_ROTATE_0 |
DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_Y);
消除 DRM_MODE_REFLECT_X 标志。根据硬件支持的转换类型,此函数可能无法生成支持的转换,因此调用者应在之后检查结果。
-
int drm_plane_create_zpos_property(struct drm_plane *plane, unsigned int zpos, unsigned int min, unsigned int max)¶
创建可变 zpos 属性
参数
struct drm_plane *plane
drm 平面
unsigned int zpos
zpos 属性的初始值
unsigned int min
zpos 属性的最小可能值
unsigned int max
zpos 属性的最大可能值
描述
此函数初始化通用可变 zpos 属性,并在 drm 核心中启用对其的支持。然后,驱动程序可以将此属性附加到平面,以启用对混合操作期间可配置平面排列的支持。将可变 zpos 属性附加到任何平面的驱动程序应在其 drm_mode_config_funcs.atomic_check()
的实现期间调用 drm_atomic_normalize_zpos()
辅助函数,这将更新规范化的 zpos 值并将其存储在 drm_plane_state.normalized_zpos
中。通常,min 应设置为 0,max 设置为给定 crtc 的最大平面数 - 1。
如果某些平面的 zpos 无法更改(如固定背景或光标/最顶层平面),则驱动程序应调整 min/max 值,并将这些平面分配给具有较低或较高值的不可变 zpos 属性(有关更多信息,请参阅 drm_plane_create_zpos_immutable_property()
函数)。在这种情况下,驱动程序还应在其 plane_reset() 回调中为所有平面分配正确的初始 zpos 值,以便平面始终正确排序。
另请参阅 drm_atomic_normalize_zpos()
。
暴露给用户空间的属性称为“zpos”。
返回
成功时返回零,失败时返回负 errno。
-
int drm_plane_create_zpos_immutable_property(struct drm_plane *plane, unsigned int zpos)¶
创建不可变的 zpos 属性
参数
struct drm_plane *plane
drm 平面
unsigned int zpos
zpos 属性的值
描述
此函数初始化通用不可变 zpos 属性,并在 drm 核心中启用对其的支持。使用此属性驱动程序允许用户空间获取用于混合操作的平面的排列,并通知用户空间硬件(或驱动程序)不支持更改平面的顺序。对于可变 zpos,请参阅 drm_plane_create_zpos_property()
。
暴露给用户空间的属性称为“zpos”。
返回
成功时返回零,失败时返回负 errno。
-
int drm_atomic_normalize_zpos(struct drm_device *dev, struct drm_atomic_state *state)¶
计算所有 crtc 的规范化 zpos 值
参数
struct drm_device *dev
DRM 设备
struct drm_atomic_state *state
DRM 设备的原子状态
描述
此函数计算提供的 DRM 设备的原子状态中所有修改后的平面的规范化 zpos 值。
对于每个 CRTC,此函数检查分配给它的所有平面的新状态,并计算这些平面的规范化 zpos 值。 平面首先按其 zpos 值进行比较,然后按平面 id 进行比较(如果 zpos 相等)。 具有最低 zpos 值的平面位于底部。 然后,drm_plane_state.normalized_zpos
填充从 0 到 crtc 中活动平面数减 1 的唯一值。
成功时返回零,否则返回 -errno
-
int drm_plane_create_blend_mode_property(struct drm_plane *plane, unsigned int supported_modes)¶
创建一个新的混合模式属性
参数
struct drm_plane *plane
drm 平面
unsigned int supported_modes
支持的模式的位掩码,必须包括 BIT(DRM_MODE_BLEND_PREMULTI)。 当前的 DRM 假设 alpha 已预乘,如果该属性默认为其他值,则旧的用户空间可能会中断。
描述
这将创建一个描述混合模式的新属性。
暴露给用户空间的属性是一个枚举属性(请参阅 drm_property_create_enum()
),名为“pixel blend mode”,并具有以下枚举值
- “None”
忽略像素 alpha 的混合公式。
- “Pre-multiplied”
混合公式假定像素颜色值已预先乘以 alpha 通道值。
- “Coverage”
混合公式假定像素颜色值尚未预乘,并在将它们混合到背景颜色值时将这样做。
返回
成功时返回零,或返回 -errno
平面损坏跟踪函数参考¶
-
void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, struct drm_plane_state *plane_state)¶
在 atomic_check 上验证平面损坏。
参数
struct drm_atomic_state *state
驱动程序状态对象。
struct drm_plane_state *plane_state
要验证损坏的平面状态。
描述
此辅助函数确保为完整模式设置丢弃平面状态的损坏。如果驱动程序有更多理由希望进行完整的平面更新,而不是处理单个损坏区域,则应在此处处理这些情况。
请注意,平面状态中的 drm_plane_state.fb_damage_clips
== NULL 意味着应该进行完整的平面更新。 它还确保辅助迭代器将返回 drm_plane_state.src
作为损坏。
-
int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned int flags, unsigned int color, struct drm_clip_rect *clips, unsigned int num_clips)¶
dirtyfb 的辅助函数。
参数
struct drm_framebuffer *fb
DRM 帧缓冲区。
struct drm_file *file_priv
ioctl 调用的 Drm 文件。
unsigned int flags
脏 fb 注释标志。
unsigned int color
用于注释填充的颜色。
struct drm_clip_rect *clips
脏区域。
unsigned int num_clips
剪辑区域中的剪辑计数。
描述
一个辅助函数,用于在使用平面更新期间的损坏界面实现 drm_framebuffer_funcs.dirty
。 如果 num_clips 为 0,则此辅助函数将执行完整的平面更新。 这与 DIRTFB IOCTL 期望的行为相同。
请注意,此辅助函数是阻塞实现。 这是当前驱动程序和用户空间在其 DIRTYFB IOCTL 实现中所期望的,作为限制用户空间速率并确保其渲染不会过多地超前于上传新数据的一种方式。
返回
成功时返回零,失败时返回负 errno。
-
void drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter, const struct drm_plane_state *old_state, const struct drm_plane_state *state)¶
初始化损坏迭代器。
参数
struct drm_atomic_helper_damage_iter *iter
要初始化的迭代器。
const struct drm_plane_state *old_state
用于验证的旧平面状态。
const struct drm_plane_state *state
从中迭代损坏剪辑的平面状态。
描述
初始化一个迭代器,该迭代器将平面损坏 drm_plane_state.fb_damage_clips
剪辑到平面 drm_plane_state.src
。 如果损坏不存在,因为用户空间未发送或驱动程序已丢弃(它想要执行完整的平面更新),则此迭代器将返回完整的平面 src。 目前,如果平面 src 更改,此迭代器将返回完整的平面 src,但将来可以更改为返回损坏。
如果平面不可见或不应发生平面更新,则第一次调用 iter_next 将返回 false。 请注意,此帮助程序使用剪裁的 drm_plane_state.src
,因此调用此帮助程序的驱动程序应已更早地调用 drm_atomic_helper_check_plane_state()
。
-
bool drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter, struct drm_rect *rect)¶
推进损坏迭代器。
参数
struct drm_atomic_helper_damage_iter *iter
要推进的迭代器。
struct drm_rect *rect
返回剪裁到平面 src 的 fb 坐标中的矩形。
描述
由于平面 src 采用 16.16 定点数,而损坏剪辑是整数,因此此迭代器会舍入与平面 src 相交的剪辑。 对于相交的坐标,x1/y1 向下舍入,x2/y2 向上舍入。 如果返回为损坏,则对完整平面 src 进行类似的舍入。 此迭代器将跳过平面 src 之外的损坏剪辑。
如果对迭代器 next 的第一次调用返回 false,则意味着无需更新平面。
返回
如果输出有效,则为 True,如果到达末尾,则为 false。
-
bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state, const struct drm_plane_state *state, struct drm_rect *rect)¶
合并平面损坏
参数
const struct drm_plane_state *old_state
用于验证的旧平面状态。
const struct drm_plane_state *state
从中迭代损坏剪辑的平面状态。
struct drm_rect *rect
返回合并的损坏矩形
描述
此函数将任何有效的平面损坏剪辑合并到一个矩形中,并将其返回到 rect 中。
有关详细信息,请参见:drm_atomic_helper_damage_iter_init()
和 drm_atomic_helper_damage_iter_next()
。
返回
如果存在有效的平面损坏,则为 True,否则为 false。
-
drm_atomic_for_each_plane_damage¶
drm_atomic_for_each_plane_damage (iter, rect)
平面损坏的迭代器宏。
参数
iter
要推进的迭代器。
rect
返回剪裁到平面 src 的 fb 坐标中的矩形。
描述
请注意,如果对迭代器宏的第一次调用返回 false,则无需执行平面更新。 当用户空间未传递损坏时,迭代器将返回完整的平面 src。
-
struct drm_atomic_helper_damage_iter¶
损坏迭代器的闭包结构。
定义:
struct drm_atomic_helper_damage_iter {
};
成员
描述
此结构跟踪遍历平面损坏剪辑列表所需的状态。
平面 Panic 功能¶
要为驱动程序启用 DRM panic,主平面必须实现 drm_plane_helper_funcs.get_scanout_buffer
辅助函数。 然后会自动注册到 drm panic 处理程序。 发生 panic 时,将调用 drm_plane_helper_funcs.get_scanout_buffer
,并且驱动程序可以提供帧缓冲区,以便 panic 处理程序可以在其上绘制 panic 屏幕。 目前仅支持线性缓冲区和一些颜色格式。 (可选)驱动程序还可以提供一个 drm_plane_helper_funcs.panic_flush
回调,该回调将在之后调用,以向硬件发送其他命令以使扫描输出缓冲区可见。
平面 Panic 函数参考¶
-
struct drm_scanout_buffer¶
DRM 扫描输出缓冲区
定义:
struct drm_scanout_buffer {
const struct drm_format_info *format;
struct iosys_map map[DRM_FORMAT_MAX_PLANES];
struct page **pages;
unsigned int width;
unsigned int height;
unsigned int pitch[DRM_FORMAT_MAX_PLANES];
void (*set_pixel)(struct drm_scanout_buffer *sb, unsigned int x, unsigned int y, u32 color);
};
成员
格式
扫描输出缓冲区的 drm 格式。
map
扫描输出缓冲区的虚拟地址,位于内存或 iomem 中。 扫描输出缓冲区应为线性格式,并且可以直接发送到显示硬件。 对于 panic 屏幕,撕裂不是问题。
pages
可选,如果未映射扫描输出缓冲区,则将此字段设置为扫描输出缓冲区的页面数组。 panic 代码将使用 kmap_local_page_try_from_panic() 一次映射一个页面以写入所有像素。 不应从 get_scanoutbuffer() 回调中分配此数组。 扫描输出缓冲区应为线性格式。
width
扫描输出缓冲区的宽度(以像素为单位)。
height
扫描输出缓冲区的高度(以像素为单位)。
pitch
两个连续行的开头之间的长度(以字节为单位)。
set_pixel
可选函数,用于在帧缓冲区上设置像素颜色。 它允许处理驱动程序内部的特殊平铺格式。 它优先于 map 和 pages 字段。
描述
此结构保存 drm_panic 绘制 panic 屏幕并显示它所需的信息。
-
drm_panic_trylock¶
drm_panic_trylock (dev, flags)
尝试进入 panic 打印关键部分
参数
dev
标志
你需要传递给 unlock() 对应部分的无符号长 irq 标志
描述
任何 panic 打印代码都必须调用此函数。 如果 trylock 失败,则必须中止 panic 打印尝试。
panic 打印代码在持有 panic 锁时可以做出以下假设
受
drm_panic_lock()
和drm_panic_unlock()
对保护的任何内容都可以安全访问。此外,panic 打印代码仅在
drm_dev_unregister()
中注册,并在drm_dev_unregister()
中删除。 这允许 panic 代码安全地访问这些两个函数调用之间不变的任何状态,例如平面列表drm_mode_config.plane_list
或struct drm_plane
结构的大部分。
特别感谢 drm_atomic_helper_swap_state()
中平面更新的保护,以下额外保证成立
可以安全地取消引用 drm_plane.state 指针。
struct drm_plane_state
或驱动程序子类中的任何在原子检查代码完成后保持不变的内容都可以安全访问。 特别是,这包括对帧缓冲区和缓冲区对象的引用计数指针。由
drm_plane_helper_funcs.fb_prepare
设置和由drm_plane_helper_funcs.fb_cleanup
清理的任何内容都可以安全访问,只要它在这两个调用之间保持不变。 这也意味着对于使用动态缓冲区管理的驱动程序,帧缓冲区被固定,因此,可以在不采取任何进一步锁定的情况下访问所有相关的数据结构(这在 panic 上下文中是不可能的)。重要的是,由
drm_plane_helper_funcs.begin_fb_access
和drm_plane_helper_funcs.end_fb_access
设置的软件和硬件状态无法安全访问。
驱动程序不得对硬件的实际状态做出任何假设,除非它们使用 drm_panic_lock()
和 drm_panic_unlock()
显式保护了这些硬件访问。
返回
0
表示未能获取原始自旋锁,非零表示成功。
-
drm_panic_lock¶
drm_panic_lock (dev, flags)
保护 panic 打印相关状态
参数
dev
标志
你需要传递给 unlock() 对应部分的无符号长 irq 标志
描述
必须调用此函数来保护 panic 打印代码必须能够依赖的软件和硬件状态。 受保护的部分必须尽可能小。 它使用 irqsave/irqrestore 变体,并且可以从 irq 处理程序中调用。 示例包括
访问 peek/poke 或其他类似寄存器,如果这是驱动程序在 panic 时将像素打印到扫描输出缓冲区的方式。
更新指针,例如
drm_plane.state
,允许 panic 处理程序安全地取消引用这些指针。 这在drm_atomic_helper_swap_state()
中完成。驱动程序在 panic 打印期间必须能够访问的非不变状态。
-
drm_panic_unlock¶
drm_panic_unlock (dev, flags)
panic 打印关键部分的结尾
-
bool drm_panic_is_enabled(struct drm_device *dev)¶
参数
struct drm_device *dev
可能支持 drm_panic 的 drm 设备
描述
如果 drm 设备支持 drm_panic,则返回 true
显示模式函数参考¶
-
enum drm_mode_status¶
模式的硬件支持状态
常量
MODE_OK
模式正常
MODE_HSYNC
hsync 超出范围
MODE_VSYNC
vsync 超出范围
MODE_H_ILLEGAL
模式具有非法的水平时序
MODE_V_ILLEGAL
模式具有非法的垂直时序
MODE_BAD_WIDTH
需要不支持的行距
MODE_NOMODE
没有具有匹配名称的模式
MODE_NO_INTERLACE
不支持隔行扫描模式
MODE_NO_DBLESCAN
不支持倍频扫描模式
MODE_NO_VSCAN
不支持多重扫描模式
MODE_MEM
视频内存不足
MODE_VIRTUAL_X
模式宽度对于指定的虚拟大小而言太大
MODE_VIRTUAL_Y
模式高度对于指定的虚拟大小而言太大
MODE_MEM_VIRT
给定虚拟大小,视频内存不足
MODE_NOCLOCK
没有可用的固定时钟
MODE_CLOCK_HIGH
所需的时钟太高
MODE_CLOCK_LOW
所需的时钟太低
MODE_CLOCK_RANGE
时钟/模式不在 ClockRange 中
MODE_BAD_HVALUE
水平时序超出范围
MODE_BAD_VVALUE
垂直时序超出范围
MODE_BAD_VSCAN
VScan 值超出范围
MODE_HSYNC_NARROW
水平同步太窄
MODE_HSYNC_WIDE
水平同步太宽
MODE_HBLANK_NARROW
水平消隐太窄
MODE_HBLANK_WIDE
水平消隐太宽
MODE_VSYNC_NARROW
垂直同步太窄
MODE_VSYNC_WIDE
垂直同步太宽
MODE_VBLANK_NARROW
垂直消隐太窄
MODE_VBLANK_WIDE
垂直消隐太宽
MODE_PANEL
超出面板尺寸
MODE_INTERLACE_WIDTH
宽度对于隔行扫描模式而言太大
MODE_ONE_WIDTH
仅支持一种宽度
MODE_ONE_HEIGHT
仅支持一种高度
MODE_ONE_SIZE
仅支持一种分辨率
MODE_NO_REDUCED
监视器不接受减少的消隐
MODE_NO_STEREO
不支持立体模式
MODE_NO_420
不支持 ycbcr 420 模式
MODE_STALE
模式已过时
MODE_BAD
未指定原因
MODE_ERROR
错误情况
描述
此枚举用于滤除驱动程序/硬件组合不支持的模式。
-
DRM_MODE_RES_MM¶
DRM_MODE_RES_MM (res, dpi)
根据分辨率和 DPI 计算显示尺寸
参数
res
分辨率(以像素为单位)
dpi
每英寸的点数
-
DRM_MODE_INIT¶
DRM_MODE_INIT (hz, hd, vd, hd_mm, vd_mm)
初始化显示模式
参数
hz
垂直刷新率(以赫兹为单位)
hd
水平分辨率,宽度
vd
垂直分辨率,高度
hd_mm
显示宽度(以毫米为单位)
vd_mm
显示高度(以毫米为单位)
描述
此宏初始化一个 drm_display_mode
,该模式包含有关刷新率、分辨率和物理尺寸的信息。
-
DRM_SIMPLE_MODE¶
DRM_SIMPLE_MODE (hd, vd, hd_mm, vd_mm)
简单显示模式
参数
hd
水平分辨率,宽度
vd
垂直分辨率,高度
hd_mm
显示宽度(以毫米为单位)
vd_mm
显示高度(以毫米为单位)
描述
此宏初始化一个 drm_display_mode
,它只包含分辨率和物理尺寸的信息。
-
struct drm_display_mode¶
DRM内核内部显示模式结构体
定义:
struct drm_display_mode {
int clock;
u16 hdisplay;
u16 hsync_start;
u16 hsync_end;
u16 htotal;
u16 hskew;
u16 vdisplay;
u16 vsync_start;
u16 vsync_end;
u16 vtotal;
u16 vscan;
u32 flags;
int crtc_clock;
u16 crtc_hdisplay;
u16 crtc_hblank_start;
u16 crtc_hblank_end;
u16 crtc_hsync_start;
u16 crtc_hsync_end;
u16 crtc_htotal;
u16 crtc_hskew;
u16 crtc_vdisplay;
u16 crtc_vblank_start;
u16 crtc_vblank_end;
u16 crtc_vsync_start;
u16 crtc_vsync_end;
u16 crtc_vtotal;
u16 width_mm;
u16 height_mm;
u8 type;
bool expose_to_userspace;
struct list_head head;
char name[DRM_DISPLAY_MODE_LEN];
enum drm_mode_status status;
enum hdmi_picture_aspect picture_aspect_ratio;
};
成员
clock
像素时钟,单位为 kHz。
hdisplay
水平显示尺寸
hsync_start
水平同步起始位置
hsync_end
水平同步结束位置
htotal
水平总尺寸
hskew
水平倾斜?!
vdisplay
垂直显示尺寸
vsync_start
垂直同步起始位置
vsync_end
垂直同步结束位置
vtotal
垂直总尺寸
vscan
垂直扫描?!
标志
同步和时序标志
DRM_MODE_FLAG_PHSYNC:水平同步为高电平有效。
DRM_MODE_FLAG_NHSYNC:水平同步为低电平有效。
DRM_MODE_FLAG_PVSYNC:垂直同步为高电平有效。
DRM_MODE_FLAG_NVSYNC:垂直同步为低电平有效。
DRM_MODE_FLAG_INTERLACE:模式为隔行扫描。
DRM_MODE_FLAG_DBLSCAN:模式使用双扫描。
DRM_MODE_FLAG_CSYNC:模式使用复合同步。
DRM_MODE_FLAG_PCSYNC:复合同步为高电平有效。
DRM_MODE_FLAG_NCSYNC:复合同步为低电平有效。
DRM_MODE_FLAG_HSKEW:提供了 hskew(未使用?)。
DRM_MODE_FLAG_BCAST:<已弃用>
DRM_MODE_FLAG_PIXMUX:<已弃用>
DRM_MODE_FLAG_DBLCLK:双时钟模式。
DRM_MODE_FLAG_CLKDIV2:半时钟模式。
此外,还有一些标志用于指定 3D 模式的打包方式
DRM_MODE_FLAG_3D_NONE:正常,非 3D 模式。
DRM_MODE_FLAG_3D_FRAME_PACKING:左右眼各 2 个完整帧。
DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:像字段一样交错。
DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:交错的行。
DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:并排的完整帧。
DRM_MODE_FLAG_3D_L_DEPTH:?
DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:?
DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:帧分为顶部和底部两部分。
DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:帧分为左右两部分。
crtc_clock
硬件中的实际像素或点时钟。当使用隔行扫描、双时钟、立体模式或其他改变实际通过电线发送的时序和信号的复杂操作时,这与逻辑 **clock** 不同。
这再次以 kHz 为单位。
请注意,对于像 HDMI 或 DP 这样的数字输出,通常在位编码级别的点时钟和信号时钟之间存在很大的混淆。特别是当使用 8b/10b 编码时,差异正好是 10 的因子。
crtc_hdisplay
硬件模式水平显示尺寸
crtc_hblank_start
硬件模式水平消隐起始位置
crtc_hblank_end
硬件模式水平消隐结束位置
crtc_hsync_start
硬件模式水平同步起始位置
crtc_hsync_end
硬件模式水平同步结束位置
crtc_htotal
硬件模式水平总尺寸
crtc_hskew
硬件模式水平倾斜?!
crtc_vdisplay
硬件模式垂直显示尺寸
crtc_vblank_start
硬件模式垂直消隐起始位置
crtc_vblank_end
硬件模式垂直消隐结束位置
crtc_vsync_start
硬件模式垂直同步起始位置
crtc_vsync_end
硬件模式垂直同步结束位置
crtc_vtotal
硬件模式垂直总尺寸
width_mm
输出的可寻址尺寸,单位为毫米,投影仪应将其设置为 0。
height_mm
输出的可寻址尺寸,单位为毫米,投影仪应将其设置为 0。
type
标志的位掩码,主要关于模式的来源。可能的标志有
DRM_MODE_TYPE_PREFERRED:首选模式,通常是 LCD 面板的原始分辨率。每个连接器在任何给定时间都应该只有一个首选模式。
DRM_MODE_TYPE_DRIVER:由驱动程序创建的模式,实际上就是所有模式。驱动程序必须为他们创建并暴露给用户空间的所有模式设置此位。
DRM_MODE_TYPE_USERDEF:通过内核命令行定义或选择的模式。
以及一大堆不应该使用的标志,但由于这些标志也在用户空间 ABI 中使用,所以仍然存在。我们不再接受这些类型的模式
DRM_MODE_TYPE_BUILTIN:用于硬编码模式,未使用。请改用 DRM_MODE_TYPE_DRIVER。
DRM_MODE_TYPE_DEFAULT:同样是遗留物,请改用 DRM_MODE_TYPE_PREFERRED。
DRM_MODE_TYPE_CLOCK_C 和 DRM_MODE_TYPE_CRTC_C:定义遗留物,它们仅因历史原因而存在。没有人知道它们的用途。不要使用。
expose_to_userspace
指示是否将模式暴露给用户空间。这是为了在 drm_mode_getconnector ioctl 中准备用户模式列表时,维护一组暴露的模式。此目的仅在于 ioctl 函数,不应在函数外部使用。
head
用于模式列表的 struct list_head。
名称
模式的人类可读名称,使用
drm_mode_set_name()
填充。status
模式的状态,用于过滤掉硬件不支持的模式。参见 enum
drm_mode_status
。picture_aspect_ratio
用于设置模式的 HDMI 画面宽高比的字段。
描述
这是内核 API 显示模式信息结构。对于用户空间版本,请参见 struct drm_mode_modeinfo
。
水平和垂直时序根据以下图表定义。
Active Front Sync Back
Region Porch Porch
<-----------------------><----------------><-------------><-------------->
//////////////////////|
////////////////////// |
////////////////////// |.................. ................
_______________
<----- [hv]display ----->
<------------- [hv]sync_start ------------>
<--------------------- [hv]sync_end --------------------->
<-------------------------------- [hv]total ----------------------------->*
此结构包含时序的两个副本。首先是普通的时序,它指定逻辑模式,就像在用户空间可以通过 vblank 时间戳观察到的刷新率下进行逐行 1:1 扫描一样。然后是硬件时序,它们已经针对隔行扫描、双时钟和类似的事情进行了校正。它们作为便利提供,可以使用 drm_mode_set_crtcinfo()
适当地计算它们。
对于打印,你可以使用 DRM_MODE_FMT
和 DRM_MODE_ARG()
。
-
DRM_MODE_FMT¶
DRM_MODE_FMT
用于
struct drm_display_mode
的 printf 字符串
-
DRM_MODE_ARG¶
DRM_MODE_ARG (m)
用于
struct drm_display_mode
的 printf 参数
参数
m
显示模式
-
bool drm_mode_is_stereo(const struct drm_display_mode *mode)¶
检查立体模式标志
参数
const struct drm_display_mode *mode
要检查的 drm_display_mode
返回
如果模式是立体模式之一(如并排),则为 True,否则为 False。
-
void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)¶
将模式打印到 dmesg
参数
const struct drm_display_mode *mode
要打印的模式
描述
使用 DRM_DEBUG 描述 **mode**。
-
struct drm_display_mode *drm_mode_create(struct drm_device *dev)¶
创建一个新的显示模式
参数
struct drm_device *dev
DRM 设备
描述
使用 kzalloc 创建一个新的、已清除的 drm_display_mode,为其分配一个 ID 并返回它。
返回
成功时指向新模式的指针,出错时为 NULL。
-
void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)¶
删除一个模式
参数
struct drm_device *dev
DRM 设备
struct drm_display_mode *mode
要删除的模式
描述
释放 **mode** 的唯一 ID,然后使用 kfree 释放 **mode** 结构本身。
-
void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode)¶
将模式添加到连接器的 probed_mode 列表
参数
struct drm_connector *connector
新模式的连接器
struct drm_display_mode *mode
模式数据
描述
将 **mode** 添加到 **connector** 的 probed_mode 列表中以供以后使用。然后,此列表应在第二步中进行过滤,并将硬件实际支持的所有模式移动到 **connector** 的模式列表中。
-
struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev, enum drm_connector_tv_mode tv_mode, unsigned long pixel_clock_hz, unsigned int hdisplay, unsigned int vdisplay, bool interlace)¶
为模拟电视创建显示模式
参数
struct drm_device *dev
drm 设备
enum drm_connector_tv_mode tv_mode
用于创建模式的电视模式标准。参见 DRM_MODE_TV_MODE_*。
unsigned long pixel_clock_hz
像素时钟频率,单位为赫兹
unsigned int hdisplay
hdisplay 大小
unsigned int vdisplay
vdisplay 大小
bool interlace
是否计算隔行扫描模式
描述
此函数创建一个适合模拟电视输出的 struct drm_display_mode
实例,用于通常的模拟电视模式之一。如果此值为 DRM_MODE_TV_MODE_MONOCHROME,将创建一个 625 行模式。
请注意,**hdisplay** 大于 PAL 和 NTSC 时序的通常约束,并且我们将选择忽略大多数时序约束以达到这些分辨率。
返回
指向该模式的指针,使用 drm_mode_create()
分配。出错时返回 NULL。
-
struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool reduced, bool interlaced, bool margins)¶
创建一个基于 CVT 算法的模式线
参数
struct drm_device *dev
drm 设备
int hdisplay
hdisplay 大小
int vdisplay
vdisplay 大小
int vrefresh
vrefresh 速率
bool reduced
是否使用减少的消隐
bool interlaced
是否计算隔行扫描模式
bool margins
是否添加边距(边框)
描述
调用此函数以根据 hdisplay、vdisplay、vrefresh 基于 CVT 算法生成模式线。它基于 Graham Loveridge 于 2003 年 4 月 9 日发布的 VESA(TM) Coordinated Video Timing Generator,可在 http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls 获取
并且它是从 xserver/hw/xfree86/modes/xf86cvt.c 中的 xf86CVTmode 复制的。我所做的是使用整数计算来翻译它。
返回
基于 CVT 算法的模式线存储在 drm_display_mode 对象中。显示模式对象使用 drm_mode_create()
分配。当无法分配任何模式时,返回 NULL。
-
struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool interlaced, int margins, int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)¶
基于完整 GTF 算法创建模式线
参数
struct drm_device *dev
drm 设备
int hdisplay
hdisplay 大小
int vdisplay
vdisplay 大小
int vrefresh
vrefresh 速率。
bool interlaced
是否计算隔行扫描模式
int margins
所需的边距(边框)大小
int GTF_M
扩展的 GTF 公式参数
int GTF_2C
扩展的 GTF 公式参数
int GTF_K
扩展的 GTF 公式参数
int GTF_2J
扩展的 GTF 公式参数
描述
GTF 特征块以 0.5 的倍数指定 C 和 J,因此我们将它们乘以 2 后传递到此处。对于 C 为 40,传入 80。
返回
基于完整 GTF 算法的模式线存储在 drm_display_mode 对象中。显示模式对象使用 drm_mode_create()
分配。当无法分配任何模式时,返回 NULL。
-
struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool interlaced, int margins)¶
基于 GTF 算法创建 modeline
参数
struct drm_device *dev
drm 设备
int hdisplay
hdisplay 大小
int vdisplay
vdisplay 大小
int vrefresh
vrefresh 速率。
bool interlaced
是否计算隔行扫描模式
int margins
所需的边距(边框)大小
描述
返回基于 GTF 算法的 modeline
此函数用于基于 GTF 算法创建 modeline。通用时序公式源自
Andy Morrish (1/5/97) 的 GTF 电子表格,可在 https://www.vesa.org 获取
它复制自 xserver/hw/xfree86/modes/xf86gtf.c 文件。我所做的是使用整数计算对其进行翻译。我还参考了 drivers/video/fbmon.c 文件中的 fb_get_mode 函数
标准 GTF 参数
M = 600
C = 40
K = 128
J = 20
返回
基于 GTF 算法的 modeline 存储在 drm_display_mode 对象中。显示模式对象使用 drm_mode_create()
分配。如果无法分配模式,则返回 NULL。
-
void drm_display_mode_from_videomode(const struct videomode *vm, struct drm_display_mode *dmode)¶
使用 vm 填充 dmode,
参数
const struct videomode *vm
用作源的 videomode 结构
struct drm_display_mode *dmode
用作目标的 drm_display_mode 结构
描述
使用 vm 中指定的显示模式填充 dmode。
-
void drm_display_mode_to_videomode(const struct drm_display_mode *dmode, struct videomode *vm)¶
使用 dmode 填充 vm,
参数
const struct drm_display_mode *dmode
用作源的 drm_display_mode 结构
struct videomode *vm
用作目标的 videomode 结构
描述
使用 dmode 中指定的显示模式填充 vm。
-
void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)¶
从 videomode 提取有关 pixelclk 和 DE 极性的信息,并将其存储在单独的变量中
参数
const struct videomode *vm
要使用的 videomode 结构
u32 *bus_flags
有关 pixelclk、同步和 DE 极性的信息将存储在此处
描述
根据 vm 中找到的 DISPLAY_FLAGS,在 bus_flags 中设置 DRM_BUS_FLAG_DE_(LOW|HIGH)、DRM_BUS_FLAG_PIXDATA_DRIVE_(POS|NEG)EDGE 和 DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE
-
int of_get_drm_display_mode(struct device_node *np, struct drm_display_mode *dmode, u32 *bus_flags, int index)¶
从设备树获取 drm_display_mode
参数
struct device_node *np
具有时序规范的 device_node
struct drm_display_mode *dmode
将设置为返回值
u32 *bus_flags
有关 pixelclk、同步和 DE 极性的信息
int index
设备树中显示时序列表的索引
描述
此函数开销很大,仅当从 DT 读取一种模式时才应使用。要获取多种模式,请从 of_get_display_timings 开始,然后使用它。
返回
成功时为 0,未找到 of videomode 节点时为负 errno 代码。
-
int of_get_drm_panel_display_mode(struct device_node *np, struct drm_display_mode *dmode, u32 *bus_flags)¶
从设备树获取 panel-timing drm_display_mode
参数
struct device_node *np
具有 panel-timing 规范的 device_node
struct drm_display_mode *dmode
将设置为返回值
u32 *bus_flags
有关 pixelclk、同步和 DE 极性的信息
描述
读取强制设备树属性 width-mm 和 height-mm 并在显示模式下设置。
返回
成功时为零,失败时为负错误代码。
-
void drm_mode_set_name(struct drm_display_mode *mode)¶
在模式下设置名称
参数
struct drm_display_mode *mode
名称将在此模式下设置
描述
将 mode 的名称设置为标准格式,即 <hdisplay>x<vdisplay>,对于隔行扫描模式,可以选择添加 ‘i’ 后缀。
-
int drm_mode_vrefresh(const struct drm_display_mode *mode)¶
获取模式的 vrefresh
参数
const struct drm_display_mode *mode
mode
返回
modes 的 vrefresh 率,单位为 Hz,四舍五入到最接近的整数。
-
void drm_mode_get_hv_timing(const struct drm_display_mode *mode, int *hdisplay, int *vdisplay)¶
获取给定模式的 hdisplay/vdisplay
参数
const struct drm_display_mode *mode
要查询的模式
int *hdisplay
要填充的 hdisplay 值
int *vdisplay
要填充的 vdisplay 值
描述
如果指定的模式是适当布局的立体模式,则 vdisplay 值将加倍。
-
void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)¶
设置 CRTC 模式设置时序参数
参数
struct drm_display_mode *p
mode
int adjust_flags
调整标志的组合
描述
为 p 设置 CRTC 模式设置时序参数,必要时进行调整。
CRTC_INTERLACE_HALVE_V 标志可用于将隔行扫描模式的垂直时序减半。
CRTC_STEREO_DOUBLE 标志可用于计算包含两个眼睛的缓冲区的时序(仅在需要时调整时序,例如,对于“帧封装”或“并排完整”)。
CRTC_NO_DBLSCAN 和 CRTC_NO_VSCAN 标志分别请求不对双扫描和 vscan > 1 模式执行调整。
-
void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)¶
复制模式
参数
struct drm_display_mode *dst
要覆盖的模式
const struct drm_display_mode *src
要复制的模式
描述
将现有模式复制到另一个模式,保留目标模式的列表头。
-
void drm_mode_init(struct drm_display_mode *dst, const struct drm_display_mode *src)¶
从另一个模式初始化模式
参数
struct drm_display_mode *dst
要覆盖的模式
const struct drm_display_mode *src
要复制的模式
描述
将现有模式复制到另一个模式,将目标模式的列表头清零。通常用于保证列表头不会在堆栈模式下留下堆栈垃圾。
-
struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, const struct drm_display_mode *mode)¶
分配并复制现有模式
参数
struct drm_device *dev
用于分配重复模式的 drm_device
const struct drm_display_mode *mode
要复制的模式
描述
只需分配一个新模式,将现有模式复制到其中,然后返回指向它的指针。用于创建已建立模式的新实例。
返回
成功时指向重复模式的指针,出错时为 NULL。
-
bool drm_mode_match(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2, unsigned int match_flags)¶
测试模式是否(部分)相等
参数
const struct drm_display_mode *mode1
第一种模式
const struct drm_display_mode *mode2
第二种模式
unsigned int match_flags
哪些部分需要匹配 (DRM_MODE_MATCH_*)
描述
检查 mode1 和 mode2 是否等效。
返回
如果模式(部分)相等,则为 True,否则为 False。
-
bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)¶
测试模式是否相等
参数
const struct drm_display_mode *mode1
第一种模式
const struct drm_display_mode *mode2
第二种模式
描述
检查 mode1 和 mode2 是否等效。
返回
如果模式相等,则为 True,否则为 False。
-
bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)¶
测试模式是否相等
参数
const struct drm_display_mode *mode1
第一种模式
const struct drm_display_mode *mode2
第二种模式
描述
检查 mode1 和 mode2 是否等效,但不检查像素时钟。
返回
如果模式相等,则为 True,否则为 False。
-
bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)¶
测试模式是否相等
参数
const struct drm_display_mode *mode1
第一种模式
const struct drm_display_mode *mode2
第二种模式
描述
检查 mode1 和 mode2 是否等效,但不检查像素时钟和立体布局。
返回
如果模式相等,则为 True,否则为 False。
-
enum drm_mode_status drm_mode_validate_driver(struct drm_device *dev, const struct drm_display_mode *mode)¶
确保模式在某种程度上是合理的
参数
struct drm_device *dev
drm 设备
const struct drm_display_mode *mode
要检查的模式
描述
首先对模式进行基本验证,然后允许驱动程序通过可选的 drm_mode_config_helper_funcs.mode_valid
钩子检查设备/驱动程序特定的限制。
返回
模式状态
-
enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, int maxX, int maxY)¶
确保模式符合尺寸约束
参数
const struct drm_display_mode *mode
要检查的模式
int maxX
最大宽度
int maxY
最大高度
描述
此函数是一个辅助函数,可用于根据 DRM 设备/连接器的尺寸限制验证模式。如果模式太大,则其状态成员将使用相应的验证失败代码进行更新。列表本身不会更改。
返回
模式状态
-
enum drm_mode_status drm_mode_validate_ycbcr420(const struct drm_display_mode *mode, struct drm_connector *connector)¶
仅在允许时添加“ycbcr420-only”模式
参数
const struct drm_display_mode *mode
要检查的模式
struct drm_connector *connector
正在操作的 DRM 连接器
描述
此函数是一个辅助函数,可用于过滤掉任何仅 YCBCR420 模式,当源不支持它时。
返回
模式状态
-
void drm_mode_prune_invalid(struct drm_device *dev, struct list_head *mode_list, bool verbose)¶
从模式列表中删除无效模式
参数
struct drm_device *dev
DRM 设备
struct list_head *mode_list
要检查的模式列表
bool verbose
详细说明
描述
此辅助函数可用于在验证完成后修剪显示模式列表。状态不是 MODE_OK 的所有模式都将从列表中删除,如果 verbose,状态代码和模式名称也会打印到 dmesg。
-
void drm_mode_sort(struct list_head *mode_list)¶
对模式列表进行排序
参数
struct list_head *mode_list
要排序的 drm_display_mode 结构的列表
描述
按有利性对 mode_list 进行排序,将良好的模式移动到列表的头部。
-
void drm_connector_list_update(struct drm_connector *connector)¶
更新连接器的模式列表
参数
struct drm_connector *connector
要更新的连接器
描述
这将模式从 connector probed_modes 列表移动到实际模式列表。它将探测到的模式与当前列表进行比较,并且仅添加不同的/新的模式。
这只是一个辅助函数,本身不验证任何模式,也不修剪任何无效模式。调用者需要自己完成。
-
bool drm_mode_parse_command_line_for_connector(const char *mode_option, const struct drm_connector *connector, struct drm_cmdline_mode *mode)¶
解析连接器的命令行 modeline
参数
const char *mode_option
可选的每个连接器的模式选项
const struct drm_connector *connector
要解析 modeline 的连接器
struct drm_cmdline_mode *mode
要填充的预分配的 drm_cmdline_mode 结构
描述
这将解析 mode_option 命令行 modeline,用于配置连接器的模式和选项。
这使用与 fb modedb.c 相同的参数,除了末尾的一个额外的强制启用、强制启用数字和强制禁用位
<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
可以使用逗号分隔每个选项,在模式之后提供其他选项。有效的选项可以在 modedb 默认视频模式支持 中找到。
需要中间 drm_cmdline_mode 结构来存储来自命令行 modline 的其他选项,例如 force-enable/disable 标志。
返回
如果已解析有效的 modeline,则为 True,否则为 False。
-
struct drm_display_mode *drm_mode_create_from_cmdline_mode(struct drm_device *dev, struct drm_cmdline_mode *cmd)¶
将命令行 modeline 转换为 DRM 显示模式
参数
struct drm_device *dev
用于创建新模式的 DRM 设备
struct drm_cmdline_mode *cmd
输入命令行 modeline
返回
成功时指向转换后的模式的指针,出错时为 NULL。
-
bool drm_mode_is_420_only(const struct drm_display_info *display, const struct drm_display_mode *mode)¶
如果给定的视频模式只能在 YCBCR420 输出格式中支持
参数
const struct drm_display_info *display
正在操作的显示器
const struct drm_display_mode *mode
要测试的视频模式。
返回
如果该模式可以在 YCBCR420 格式中支持,则为 true,否则为 false。
-
bool drm_mode_is_420_also(const struct drm_display_info *display, const struct drm_display_mode *mode)¶
如果给定的视频模式也可以在 YCBCR420 输出格式中支持(以及 RGB/YCBCR444/422)
参数
const struct drm_display_info *display
正在操作的显示器。
const struct drm_display_mode *mode
要测试的视频模式。
返回
如果该模式可以支持 YCBCR420 格式,则为 true,否则为 false。
-
bool drm_mode_is_420(const struct drm_display_info *display, const struct drm_display_mode *mode)¶
如果给定的视频模式可以在 YCBCR420 输出格式中支持
参数
const struct drm_display_info *display
正在操作的显示器。
const struct drm_display_mode *mode
要测试的视频模式。
返回
如果该模式可以在 YCBCR420 格式中支持,则为 true,否则为 false。
-
void drm_set_preferred_mode(struct drm_connector *connector, int hpref, int vpref)¶
设置连接器的首选模式
参数
struct drm_connector *connector
应处理其模式列表的连接器
int hpref
首选模式的水平分辨率
int vpref
首选模式的垂直分辨率
描述
如果模式与 hpref 和 vpref 指定的分辨率匹配,则将其标记为首选。
连接器抽象¶
在 DRM 中,连接器是显示接收器的通用抽象,并且还包括固定面板或任何其他可以以某种形式显示像素的东西。与代表硬件的所有其他 KMS 对象(如 CRTC、编码器或平面抽象)不同,连接器可以在运行时热插拔和拔出。因此,它们使用 drm_connector_get()
和 drm_connector_put()
进行引用计数。
KMS 驱动程序必须为每个此类接收器创建一个 struct drm_connector
、初始化、注册和附加。该实例与其他 KMS 对象一样创建,并通过设置以下字段进行初始化。通过调用 drm_connector_init()
,使用指向 struct drm_connector_funcs
和连接器类型的指针来初始化连接器,然后通过调用 drm_connector_register()
将其公开给用户空间。
必须将连接器附加到编码器才能使用。对于将连接器映射到编码器的设备,连接器应在初始化时通过调用 drm_connector_attach_encoder()
来附加。驱动程序还必须将 drm_connector.encoder
字段设置为指向附加的编码器。
对于非固定连接器(如内置面板),驱动程序需要支持热插拔通知。最简单的方法是使用探测帮助程序,有关没有硬件支持热插拔中断的连接器,请参阅 drm_kms_helper_poll_init()
。具有硬件热插拔支持的连接器可以改为使用例如 drm_helper_hpd_irq_event()
。
连接器函数参考¶
-
enum drm_connector_status¶
drm_connector
的状态
常量
connector_status_connected
连接器肯定已连接到接收器设备,并且可以启用。
connector_status_disconnected
连接器未连接到可以自动检测的接收器设备。对于数字输出(如 DP 或 HDMI)(可以可靠地进行探测),这意味着实际上没有任何东西。是否可以点亮具有此状态的连接器取决于驱动程序。
connector_status_unknown
无法可靠地检测到连接器的状态。当探测会导致闪烁(如使用连接器时的负载检测)或硬件资源不可用(如负载检测需要空闲 CRTC 时)时,会发生这种情况。应该可以使用列出的回退模式之一来点亮连接器。对于默认配置,用户空间应仅在没有具有 connector_status_connected 的连接器时才尝试点亮具有未知状态的连接器。
描述
此枚举用于跟踪连接器状态。没有单独的 #defines 用于 uapi!
-
enum drm_connector_registration_state¶
drm_connector
的用户空间注册状态
常量
DRM_CONNECTOR_INITIALIZING
连接器刚刚创建,但尚未公开给用户空间。如何修改此连接器的状态应该没有其他限制。
DRM_CONNECTOR_REGISTERED
连接器已完全初始化并在 sysfs 中注册,因此它已公开给用户空间。如何修改此连接器的状态应该没有其他限制。
DRM_CONNECTOR_UNREGISTERED
连接器已公开给用户空间,此后已从用户空间取消注册和删除,或者连接器在有机会公开给用户空间之前已取消注册(例如,仍在 DRM_CONNECTOR_INITIALIZING 状态)。取消注册连接器后,如何修改其状态存在其他限制
取消注册的连接器只能将其 DPMS 从 On->Off 更改。一旦 DPMS 更改为 Off,就不能将其切换回 On。
除非它们会导致禁用其分配的 CRTC,否则不允许在未注册的连接器上进行 Modeset。这意味着禁用未注册的连接器上的 CRTC 是可以的,但启用一个 CRTC 是不可以的。
从未注册的连接器中删除 CRTC 是可以的,但新的 CRTC 永远不能分配给未注册的连接器。
描述
此枚举用于跟踪初始化连接器并将其注册到用户空间的状态,以便 DRM 可以防止在不再存在的连接器上进行虚假模式设置。
-
enum drm_connector_tv_mode¶
模拟电视输出模式
常量
DRM_MODE_TV_MODE_NTSC
CCIR 系统 M(也称为 525 行)以及 NTSC 颜色编码。
DRM_MODE_TV_MODE_NTSC_443
DRM_MODE_TV_MODE_NTSC 的变体。使用 4.43 MHz 的颜色副载波频率。
DRM_MODE_TV_MODE_NTSC_J
DRM_MODE_TV_MODE_NTSC 的变体,用于日本。使用等于消隐级别的黑电平。
DRM_MODE_TV_MODE_PAL
CCIR 系统 B 以及 PAL 颜色系统。
DRM_MODE_TV_MODE_PAL_M
CCIR 系统 M(也称为 525 行)以及 PAL 颜色编码
DRM_MODE_TV_MODE_PAL_N
CCIR 系统 N 以及 PAL 颜色编码。它使用 625 行,但具有 3.58MHz 的颜色副载波频率、SECAM 颜色空间以及比大多数其他 PAL 变体更窄的通道。
DRM_MODE_TV_MODE_SECAM
CCIR 系统 B 以及 SECAM 颜色系统。
DRM_MODE_TV_MODE_MONOCHROME
使用适合 DRM 模式的计时,包括用于 525 行或 625 行模式的均衡脉冲,没有基座或颜色编码。
DRM_MODE_TV_MODE_MAX
模拟电视输出模式的数量。
内部实施细节;这不是 uABI。
描述
此枚举用于指示模拟电视连接器上使用的电视输出模式。
警告:此枚举的值是 uABI,因为它们在“TV 模式”连接器属性中公开。
-
struct drm_scrambling¶
接收器的加扰支持。
定义:
struct drm_scrambling {
bool supported;
bool low_rates;
};
成员
已支持
支持速率 > 340 Mhz 的加扰。
low_rates
支持速率 <= 340 Mhz 的加扰。
-
struct drm_hdmi_dsc_cap¶
HDMI 接收器的 DSC 功能
定义:
struct drm_hdmi_dsc_cap {
bool v_1p2;
bool native_420;
bool all_bpp;
u8 bpc_supported;
u8 max_slices;
int clk_per_slice;
u8 max_lanes;
u8 max_frl_rate_per_lane;
u8 total_chunk_kbytes;
};
成员
v_1p2
接收器支持 dsc1.2 版本的标志
native_420
接收器是否支持使用 4:2:0 压缩的 DSC
all_bpp
接收器是否支持所有 bpp 以及 4:4:4: 或 4:2:2 压缩格式
bpc_supported
接收器支持的压缩 bpc:10、12 或 16 bpc
max_slices
支持的最大水平切片数
clk_per_slice
每个切片支持的最大像素时钟(MHz)
max_lanes
固定速率链路训练的 DSC 最大支持通道数
max_frl_rate_per_lane
每个通道使用 DSC 的最大 frl 速率
total_chunk_kbytes
每行支持的最大数据块大小(KB)
描述
描述 HDMI 2.1 接收器提供的 DSC 支持。 此信息从为 HDMI 2.1 定义的附加 HFVSDB 块中获取。
-
struct drm_hdmi_info¶
有关已连接 HDMI 接收器的运行时信息
定义:
struct drm_hdmi_info {
struct drm_scdc scdc;
unsigned long y420_vdb_modes[BITS_TO_LONGS(256)];
unsigned long y420_cmdb_modes[BITS_TO_LONGS(256)];
u8 y420_dc_modes;
u8 max_frl_rate_per_lane;
u8 max_lanes;
struct drm_hdmi_dsc_cap dsc_cap;
};
成员
scdc
接收器的 scdc 支持和功能
y420_vdb_modes
仅支持 ycbcr420 输出的模式的位图(不是普通的 RGB/YCBCR444/422 输出)。CEA-861-G 规范定义的最大 VIC 为 219,因此大小为 256 位,最多可映射 256 个 VIC。
y420_cmdb_modes
可以同时支持 ycbcr420 输出和普通 HDMI 输出的模式的位图。CEA-861-G 规范定义的最大 VIC 为 219,因此大小为 256 位,最多可映射 256 个 VIC。
y420_dc_modes
深度颜色支持索引的位图
max_frl_rate_per_lane
支持固定速率链路
max_lanes
接收器支持
dsc_cap
接收器的 DSC 功能
描述
描述给定的显示器是否支持高级 HDMI 2.0 功能。 此信息可在 CEA-861-F 扩展块(如 HF-VSDB)中找到。
-
enum drm_link_status¶
连接器的 link_status 属性值
常量
DRM_LINK_STATUS_GOOD
由于成功的链路训练,DP 链路良好
DRM_LINK_STATUS_BAD
由于链路训练失败,DP 链路不良
描述
此枚举用作连接器的链路状态属性值。 它设置为 uapi 中定义的值。
-
enum drm_panel_orientation¶
drm_display_info
的 panel_orientation 信息
常量
DRM_MODE_PANEL_ORIENTATION_UNKNOWN
drm 驱动程序未提供任何面板方向信息(非面板的正常情况),在这种情况下,不会附加“面板方向”连接器属性。
DRM_MODE_PANEL_ORIENTATION_NORMAL
面板的顶部与设备外壳的顶部匹配。
DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP
面板的顶部与设备外壳的底部匹配,即面板倒置安装。
DRM_MODE_PANEL_ORIENTATION_LEFT_UP
面板的左侧与设备外壳的顶部匹配。
DRM_MODE_PANEL_ORIENTATION_RIGHT_UP
面板的右侧与设备外壳的顶部匹配。
描述
此枚举用于跟踪 (LCD) 面板的方向。 uapi 没有单独的 #defines!
-
enum drm_hdmi_broadcast_rgb¶
HDMI **drm_connector** 的广播 RGB 选择
常量
DRM_HDMI_BROADCAST_RGB_AUTO
RGB 范围根据模式自动选择。
DRM_HDMI_BROADCAST_RGB_FULL
强制使用全范围 RGB。
DRM_HDMI_BROADCAST_RGB_LIMITED
强制使用有限范围 RGB。
-
struct drm_monitor_range_info¶
drm_display_info
的 EDID 中面板的监视器范围
定义:
struct drm_monitor_range_info {
u16 min_vfreq;
u16 max_vfreq;
};
成员
min_vfreq
这是来自 EDID 详细监视器范围的最小支持刷新率(以 Hz 为单位)。
max_vfreq
这是来自 EDID 详细监视器范围的最大支持刷新率(以 Hz 为单位)
描述
此结构用于存储面板支持的频率范围,该范围从 EDID 的详细监视器范围描述符块中解析。
-
struct drm_luminance_range_info¶
drm_display_info
的面板亮度范围。 使用 EDID 中的数据计算得出
定义:
struct drm_luminance_range_info {
u32 min_luminance;
u32 max_luminance;
};
成员
min_luminance
这是最小支持的亮度值
max_luminance
这是最大支持的亮度值
描述
此结构用于存储面板支持的亮度范围,该范围使用来自 EDID 静态 hdr 元数据的数据计算得出。
-
enum drm_privacy_screen_status¶
隐私屏幕状态
常量
PRIVACY_SCREEN_DISABLED
面板上的隐私屏幕已禁用
PRIVACY_SCREEN_ENABLED
面板上的隐私屏幕已启用
PRIVACY_SCREEN_DISABLED_LOCKED
面板上的隐私屏幕已禁用并锁定(无法更改)
PRIVACY_SCREEN_ENABLED_LOCKED
面板上的隐私屏幕已启用并锁定(无法更改)
描述
此枚举用于通过“隐私屏幕 sw-state”和“隐私屏幕 hw-state”属性跟踪和控制某些显示面板上存在的集成隐私屏幕的状态。 请注意,_LOCKED 枚举值仅对“隐私屏幕 hw-state”属性有效。
-
enum drm_colorspace¶
色彩空间
常量
DRM_MODE_COLORIMETRY_DEFAULT
驱动程序特定行为。
DRM_MODE_COLORIMETRY_NO_DATA
驱动程序特定行为。
DRM_MODE_COLORIMETRY_SMPTE_170M_YCC
(HDMI) SMPTE ST 170M 色彩格式
DRM_MODE_COLORIMETRY_BT709_YCC
(HDMI, DP) ITU-R BT.709 色彩格式
DRM_MODE_COLORIMETRY_XVYCC_601
(HDMI, DP) xvYCC601 色彩格式
DRM_MODE_COLORIMETRY_XVYCC_709
(HDMI, DP) xvYCC709 色彩格式
DRM_MODE_COLORIMETRY_SYCC_601
(HDMI, DP) sYCC601 色彩格式
DRM_MODE_COLORIMETRY_OPYCC_601
(HDMI, DP) opYCC601 色彩格式
DRM_MODE_COLORIMETRY_OPRGB
(HDMI, DP) opRGB 色彩格式
DRM_MODE_COLORIMETRY_BT2020_CYCC
(HDMI, DP) ITU-R BT.2020 Y’c C’bc C’rc(恒定亮度)色彩格式
DRM_MODE_COLORIMETRY_BT2020_RGB
(HDMI, DP) ITU-R BT.2020 R’ G’ B’ 色彩格式
DRM_MODE_COLORIMETRY_BT2020_YCC
(HDMI, DP) ITU-R BT.2020 Y’ C’b C’r 色彩格式
DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65
(HDMI) SMPTE ST 2113 P3D65 色彩格式
DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER
(HDMI) SMPTE ST 2113 P3DCI 色彩格式
DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED
(DP) RGB 宽色域定点色彩格式
DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT
(DP) RGB 宽色域浮点 (scRGB (IEC 61966-2-2)) 色彩格式
DRM_MODE_COLORIMETRY_BT601_YCC
(DP) ITU-R BT.601 色彩格式。DP 规范未说明这是 525 行版本还是 625 行版本。
DRM_MODE_COLORIMETRY_COUNT
不是有效值;仅用于计数
描述
此枚举是 HDMI 和 DP 协议标准支持的合并色彩列表。 相应的连接器将注册一个属性,其中包含此列表的子集(由该相应协议支持)。 用户空间将通过色彩空间属性设置色彩空间,该属性将被创建并公开给用户空间。
DP 定义来自 DP v2.0 规范 HDMI 定义来自 CTA-861-H 规范
-
enum drm_bus_flags¶
drm_display_info
的 bus_flags 信息
常量
DRM_BUS_FLAG_DE_LOW
数据启用信号为低电平有效
DRM_BUS_FLAG_DE_HIGH
数据启用信号为高电平有效
DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE
数据在像素时钟的上升沿驱动
DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE
数据在像素时钟的下降沿驱动
DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE
数据在像素时钟的上升沿采样
DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE
数据在像素时钟的下降沿采样
DRM_BUS_FLAG_DATA_MSB_TO_LSB
数据在总线上从 MSB 传输到 LSB
DRM_BUS_FLAG_DATA_LSB_TO_MSB
数据在总线上从 LSB 传输到 MSB
DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE
同步信号在像素时钟的上升沿驱动
DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE
同步信号在像素时钟的下降沿驱动
DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE
同步信号在像素时钟的上升沿采样
DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE
同步信号在像素时钟的下降沿采样
DRM_BUS_FLAG_SHARP_SIGNALS
如果必须使用 Sharp 特有的信号(SPL、CLS、PS、REV),则设置
描述
此枚举定义了总线上信号的信号极性和时钟沿信息,作为位掩码标志。
时钟沿信息由两组符号传达,DRM_BUS_FLAGS_*_DRIVE_* 和 DRM_BUS_FLAGS_*_SAMPLE_*。 当此枚举用于从发射器的角度描述总线时,应使用 *_DRIVE_* 标志。 当从接收器的角度使用时,应使用 *_SAMPLE_* 标志。 *_DRIVE_* 和 *_SAMPLE_* 标志相互别名,其中 *_SAMPLE_POSEDGE 和 *_SAMPLE_NEGEDGE 标志分别等于 *_DRIVE_NEGEDGE 和 *_DRIVE_POSEDGE。 这简化了代码,因为信号通常在驱动沿的相反边沿采样。 但是,发射器和接收器可能需要考虑其他信号时序才能在驱动和采样沿之间进行转换。
-
struct drm_display_info¶
有关已连接接收器的运行时数据
定义:
struct drm_display_info {
unsigned int width_mm;
unsigned int height_mm;
unsigned int bpc;
enum subpixel_order subpixel_order;
#define DRM_COLOR_FORMAT_RGB444 (1<<0);
#define DRM_COLOR_FORMAT_YCBCR444 (1<<1);
#define DRM_COLOR_FORMAT_YCBCR422 (1<<2);
#define DRM_COLOR_FORMAT_YCBCR420 (1<<3);
int panel_orientation;
u32 color_formats;
const u32 *bus_formats;
unsigned int num_bus_formats;
u32 bus_flags;
int max_tmds_clock;
bool dvi_dual;
bool is_hdmi;
bool has_audio;
bool has_hdmi_infoframe;
bool rgb_quant_range_selectable;
u8 edid_hdmi_rgb444_dc_modes;
u8 edid_hdmi_ycbcr444_dc_modes;
u8 cea_rev;
struct drm_hdmi_info hdmi;
bool non_desktop;
struct drm_monitor_range_info monitor_range;
struct drm_luminance_range_info luminance_range;
u8 mso_stream_count;
u8 mso_pixel_overlap;
u32 max_dsc_bpp;
u8 *vics;
int vics_len;
u32 quirks;
u16 source_physical_address;
};
成员
width_mm
以毫米为单位的物理宽度。
height_mm
以毫米为单位的物理高度。
bpc
每个颜色通道的最大位数。 由 HDMI 和 DP 输出使用。
subpixel_order
LCD 面板的子像素顺序。
panel_orientation
内置面板的只读连接器属性,指示面板相对于设备外壳的方向。
drm_connector_init()
将其设置为 DRM_MODE_PANEL_ORIENTATION_UNKNOWN。 当不是 UNKNOWN 时,drm_fb_helpers 会使用它来旋转 fb 以进行补偿,并作为 prop 导出到用户空间。color_formats
HDMI 颜色格式,在 RGB 和 YCrCb 模式之间进行选择。 使用 DRM_COLOR_FORMAT_ 定义,这些定义与用于描述帧缓冲区中像素格式的定义不同,并且与 **bus_formats** 中的格式也不匹配,后者与 v4l 共享。
bus_formats
线上的像素数据格式,在某种程度上与 **color_formats** 冗余。 使用与 v4l 和媒体驱动程序共享的 MEDIA_BUS_FMT_ 定义编码的 **num_bus_formats** 大小的数组。
num_bus_formats
**bus_formats** 数组的大小。
bus_flags
总线上像素数据的附加信息(如像素信号极性),使用
enum drm_bus_flags
值 DRM_BUS_FLAGS_。max_tmds_clock
接收器支持的最大 TMDS 时钟速率(以 kHz 为单位)。 0 表示未定义。
dvi_dual
双链路 DVI 接收器?
is_hdmi
如果接收器是 HDMI 设备,则为 True。
此字段应在可能的情况下代替调用
drm_detect_hdmi_monitor()
。has_audio
如果接收器支持音频,则为 True。
此字段应在可能的情况下代替调用
drm_detect_monitor_audio()
。has_hdmi_infoframe
接收器是否支持 HDMI 信息帧?
rgb_quant_range_selectable
接收器是否支持选择 RGB 量化范围?
edid_hdmi_rgb444_dc_modes
RGB 4:4:4 中支持的 hdmi 深度颜色模式的掩码。 更多与 **bus_formats** 冗余的内容。
edid_hdmi_ycbcr444_dc_modes
YCbCr 4:4:4 中支持的 hdmi 深度颜色模式的掩码。 更多与 **bus_formats** 冗余的内容。
cea_rev
HDMI 接收器的 CEA 修订版本。
hdmi
HDMI 接收器的高级功能。
non_desktop
非桌面显示器 (HMD)。
monitor_range
监视器范围描述符支持的频率范围
luminance_range
面板支持的亮度范围
mso_stream_count
来自 DisplayID VESA 供应商块的 eDP 多 SST 操作 (MSO) 流计数。 常规单流传输 (SST) 为 0,或为 2 或 4 个 MSO 流。
mso_pixel_overlap
eDP MSO 段像素重叠,0-8 像素。
max_dsc_bpp
最大 DSC 目标比特率,如果设置为 0,则改为使用监视器的默认值。
vics
vics_len VIC 的数组。 EDID 解析的内部变量。
vics_len
vics 中的元素数。 EDID 解析的内部变量。
quirks
基于 EDID 的怪癖。 EDID 解析的内部变量。
source_physical_address
来自 HDMI 供应商特定数据块的源物理地址,用于 CEC 用途。
默认为 CEC_PHYS_ADDR_INVALID (0xffff)。
描述
描述给定的显示器(例如 CRT 或平板面板)及其限制。 对于像内置面板这样的固定显示器接收器,这与 struct drm_connector
之间没有太大区别。 但对于带有真电缆的接收器,此结构旨在描述电缆另一端的所有内容。
对于提供 EDID 的接收器,可以通过调用 drm_add_edid_modes()
来填充此结构。
-
struct drm_connector_tv_margins¶
TV 连接器相关边距
定义:
struct drm_connector_tv_margins {
unsigned int bottom;
unsigned int left;
unsigned int right;
unsigned int top;
};
成员
bottom
以像素为单位的底部边距。
left
以像素为单位的左侧边距。
right
以像素为单位的右侧边距。
top
以像素为单位的顶部边距。
描述
描述在 TV 连接器上的图像周围放置的边距(以像素为单位),以处理过扫描。
-
struct drm_tv_connector_state¶
TV 连接器相关状态
定义:
struct drm_tv_connector_state {
enum drm_mode_subconnector select_subconnector;
enum drm_mode_subconnector subconnector;
struct drm_connector_tv_margins margins;
unsigned int legacy_mode;
unsigned int mode;
unsigned int brightness;
unsigned int contrast;
unsigned int flicker_reduction;
unsigned int overscan;
unsigned int saturation;
unsigned int hue;
};
成员
select_subconnector
选择的子连接器
subconnector
检测到的子连接器
margins
TV 边距
legacy_mode
旧版 TV 模式,驱动程序特定的值
mode
TV 模式
brightness
以百分比表示的亮度
contrast
以百分比表示的对比度
flicker_reduction
以百分比表示的闪烁减少
overscan
以百分比表示的过扫描
saturation
以百分比表示的饱和度
hue
以百分比表示的色调
-
struct drm_connector_hdmi_infoframe¶
HDMI 信息帧容器
定义:
struct drm_connector_hdmi_infoframe {
union hdmi_infoframe data;
bool set;
};
成员
data
HDMI 信息帧结构
set
**data** 的内容是否有效?
-
struct drm_connector_state¶
可变连接器状态
定义:
struct drm_connector_state {
struct drm_connector *connector;
struct drm_crtc *crtc;
struct drm_encoder *best_encoder;
enum drm_link_status link_status;
struct drm_atomic_state *state;
struct drm_crtc_commit *commit;
struct drm_tv_connector_state tv;
bool self_refresh_aware;
enum hdmi_picture_aspect picture_aspect_ratio;
unsigned int content_type;
unsigned int hdcp_content_type;
unsigned int scaling_mode;
unsigned int content_protection;
enum drm_colorspace colorspace;
struct drm_writeback_job *writeback_job;
u8 max_requested_bpc;
u8 max_bpc;
enum drm_privacy_screen_status privacy_screen_sw_state;
struct drm_property_blob *hdr_output_metadata;
struct drm_connector_hdmi_state hdmi;
};
成员
connector
指向连接器的后向指针
crtc
将连接器连接到的 CRTC,如果禁用,则为 NULL。
请勿直接修改此项,请使用
drm_atomic_set_crtc_for_connector()
代替。best_encoder
由原子 helpers 使用,通过
drm_connector_helper_funcs.atomic_best_encoder
或drm_connector_helper_funcs.best_encoder
回调来选择编码器。这也被原子 helpers 使用,用于将编码器映射到它们当前和先前的连接器,参见
drm_atomic_get_old_connector_for_encoder()
和drm_atomic_get_new_connector_for_encoder()
。注意:原子驱动程序必须填充此项(无论是自己填充还是通过 helpers),否则 GETCONNECTOR 和 GETENCODER IOCTL 将不会向用户空间返回正确的数据。
link_status
连接器 link_status 用于跟踪链接是 GOOD 还是 BAD,以便在需要重新训练时通知用户空间。
state
指向全局 drm_atomic_state 的后向指针
提交
跟踪挂起的提交,以防止使用后释放的情况。
仅当 crtc 为 NULL 时设置。
tv
TV 连接器状态
self_refresh_aware
这跟踪连接器是否知道自刷新状态。对于那些了解自刷新状态的连接器实现,应将其设置为 true。这是必需的,因为 crtc 注册了自刷新 helpers,并且它不知道下游的连接器是否已实现自刷新进入/退出。
如果驱动程序知道如何处理 self_refresh 请求,则应在 atomic_check 中将其设置为 true。
picture_aspect_ratio
连接器属性,用于控制 HDMI 信息帧宽高比设置。
DRM_MODE_PICTURE_ASPECT_
* 值必须与enum hdmi_picture_aspect
的值匹配content_type
连接器属性,用于控制 HDMI 信息帧内容类型设置。
DRM_MODE_CONTENT_TYPE_
* 值必须与相应的值匹配。hdcp_content_type
连接器属性,用于传递受保护内容类型。这通常用于 HDCP。
scaling_mode
连接器属性,用于控制放大,主要用于内置面板。
content_protection
连接器属性,用于请求内容保护。这通常用于 HDCP。
colorspace
连接器属性的状态变量,用于请求在 Sink 上更改颜色空间。这通常用于切换到更宽的色域,如 BT2020。
writeback_job
回写连接器的回写作业
保存回写连接器的帧缓冲区和输出栅栏。由于回写完成可能与正常提交周期异步,因此回写作业的生命周期由此对象与正常原子状态分开管理。
另请参见:
drm_writeback_queue_job()
和drm_writeback_signal_completion()
max_requested_bpc
连接器属性,用于限制像素的最大位深度。
max_bpc
基于请求的 max_bpc 属性和从 edid 获取的连接器 bpc 限制的连接器 max_bpc。
privacy_screen_sw_state
参见 标准连接器属性
hdr_output_metadata
HDR 输出元数据的 DRM blob 属性
hdmi
与 HDMI 相关的变量和属性。由
drm_atomic_helper_connector_hdmi_check()
填充。
-
struct drm_connector_hdmi_funcs¶
drm_hdmi_connector 控制函数
定义:
struct drm_connector_hdmi_funcs {
enum drm_mode_status(*tmds_char_rate_valid)(const struct drm_connector *connector,const struct drm_display_mode *mode, unsigned long long tmds_rate);
int (*clear_infoframe)(struct drm_connector *connector, enum hdmi_infoframe_type type);
int (*write_infoframe)(struct drm_connector *connector,enum hdmi_infoframe_type type, const u8 *buffer, size_t len);
const struct drm_edid *(*read_edid)(struct drm_connector *connector);
};
成员
tmds_char_rate_valid
此回调在 atomic_check 时被调用,以确定驱动程序是否支持特定的 TMDS 字符速率。
tmds_char_rate_valid 回调是可选的。
返回
drm_mode_status.MODE_OK
或enum drm_mode_status
中的失败原因之一。clear_infoframe
此回调通过 drm_atomic_helper_connector_hdmi_update_infoframes 在提交期间调用,以将信息帧清除到硬件中。它将被多次调用,对于每个禁用的信息帧类型调用一次。
clear_infoframe 回调是可选的。
返回值:成功时为 0,否则为负错误代码
write_infoframe
此回调通过 drm_atomic_helper_connector_hdmi_update_infoframes 在提交期间调用,以将信息帧编程到硬件中。它将被多次调用,对于每个更新的信息帧类型调用一次。
write_infoframe 回调是强制性的。
返回值:成功时为 0,否则为负错误代码
read_edid
此回调被框架用作从 connector->ddc 读取 EDID 的替代方法。仍然建议提供 connector->ddc 而不是实现此回调。返回的 EDID 应通过
drm_edid_free()
释放。read_edid 回调是可选的。
返回值:成功时为有效 EDID,失败时为 NULL。
-
struct drm_connector_funcs¶
控制给定设备上的连接器
定义:
struct drm_connector_funcs {
int (*dpms)(struct drm_connector *connector, int mode);
void (*reset)(struct drm_connector *connector);
enum drm_connector_status (*detect)(struct drm_connector *connector, bool force);
void (*force)(struct drm_connector *connector);
int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
int (*set_property)(struct drm_connector *connector, struct drm_property *property, uint64_t val);
int (*late_register)(struct drm_connector *connector);
void (*early_unregister)(struct drm_connector *connector);
void (*destroy)(struct drm_connector *connector);
struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
void (*atomic_destroy_state)(struct drm_connector *connector, struct drm_connector_state *state);
int (*atomic_set_property)(struct drm_connector *connector,struct drm_connector_state *state,struct drm_property *property, uint64_t val);
int (*atomic_get_property)(struct drm_connector *connector,const struct drm_connector_state *state,struct drm_property *property, uint64_t *val);
void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state);
void (*oob_hotplug_event)(struct drm_connector *connector, enum drm_connector_status status);
void (*debugfs_init)(struct drm_connector *connector, struct dentry *root);
};
成员
dpms
设置每个连接器 DPMS 状态的传统入口点。传统 DPMS 作为连接器上的标准属性公开,但在 drm 核心中被转移到此回调。请注意,原子驱动程序不再在连接器上实现 4 级 DPMS 支持,而是仅在 CRTC 对象上具有一个开/关“ACTIVE”属性。
原子驱动程序不使用此钩子,传统 DPMS 属性的重新映射完全在 DRM 核心中处理。
返回值
成功时为 0,失败时为负错误代码。
重置
将连接器硬件和软件状态重置为关闭。此函数不由核心直接调用,仅通过
drm_mode_config_reset()
调用。由于历史原因,它不是一个 helper 钩子。原子驱动程序可以使用
drm_atomic_helper_connector_reset()
使用此钩子重置原子状态。detect
检查是否有任何东西连接到连接器。参数 force 在轮询时设置为 false,在由于用户请求而检查连接器时设置为 true。驱动程序可以使用 force 来避免在自动探测期间进行昂贵的、破坏性的操作。
此回调是可选的,如果未实现,则连接器将被视为始终连接。
待办
请注意,此钩子仅由 probe helper 调用。它不在 helper 库 vtable 中仅仅是出于历史原因。探测连接器状态的唯一 DRM 核心入口点是 fill_modes。
请注意,helper 库已经持有
drm_mode_config.connection_mutex
。需要获取其他锁以避免与并发模式集更改竞争的驱动程序需要使用drm_connector_helper_funcs.detect_ctx
代替。另请注意,无论连接器处于何种状态,都可以调用此回调。需要底层设备上电才能执行检测的驱动程序首先需要确保已正确启用它。
返回值
drm_connector_status 指示连接器的状态。
force
当用户空间通过 sysfs 接口或在内核命令行上强制将连接器设置为特定状态时,将调用此函数以更新内部编码器状态。在这种情况下,不会调用 detect 回调。
待办
请注意,此钩子仅由 probe helper 调用。它不在 helper 库 vtable 中仅仅是出于历史原因。探测连接器状态的唯一 DRM 核心入口点是 fill_modes。
fill_modes
输出检测和基本模式验证的入口点。如果需要,驱动程序应重新探测输出(例如,当热插拔处理不可靠时),将所有检测到的模式添加到
drm_connector.modes
,并过滤掉设备在任何配置中都无法支持的任何模式。它还需要过滤掉任何比参数 max_width 和 max_height 指示的更宽或更高的模式。驱动程序还必须从
drm_connector.modes
中删除任何不再有效的模式。此外,它必须更新drm_connector.status
和drm_connector.edid
。如果此输出没有收到 EDID,则 connector->edid 必须为 NULL。使用 probe helpers 的驱动程序应使用
drm_helper_probe_single_connector_modes()
来实现此函数。返回值
检测到的模式数量并填充到
drm_connector.modes
中。set_property
这是更新附加到连接器的属性的传统入口点。
如果驱动程序不支持任何旧版驱动程序私有属性,则此回调是可选的。对于原子驱动程序,它不使用,因为属性处理完全在 DRM 核心中完成。
返回值
成功时为 0,失败时为负错误代码。
late_register
可以使用此可选钩子来注册附加到连接器的其他用户空间接口,例如背光控制、i2c、DP aux 或类似接口。它在驱动程序加载序列的后期从
drm_connector_register()
调用,以注册所有核心 drm 连接器接口。从此回调添加的所有内容都应在 early_unregister 回调中注销。在持有
drm_connector.mutex
时调用。返回
成功时为 0,失败时为负错误代码。
early_unregister
此可选钩子应用于注销附加到连接器的其他用户空间接口,这些接口来自 late_register()。它从
drm_connector_unregister()
调用,在驱动程序卸载序列的早期调用,以在数据结构被拆除之前禁用用户空间访问。在持有
drm_connector.mutex
时调用。destroy
清理连接器资源。这在驱动程序卸载时通过
drm_mode_config_cleanup()
调用。当连接器被热插拔时,也可能在运行时调用它,对于支持连接器热插拔的驱动程序(例如 DisplayPort MST)。atomic_duplicate_state
复制此连接器的当前原子状态并返回它。核心和 helpers 保证任何使用此钩子复制的原子状态,并且仍然由调用者拥有(即,未通过调用
drm_mode_config_funcs.atomic_commit
转移到驱动程序)将通过调用此结构中的 atomic_destroy_state 钩子来清理。此回调对于原子驱动程序是必需的。
不子类化
struct drm_connector_state
的原子驱动程序应使用drm_atomic_helper_connector_duplicate_state()
。子类化状态结构以使用驱动程序私有状态扩展它的驱动程序应使用__drm_atomic_helper_connector_duplicate_state()
来确保跨驱动程序以一致的方式复制共享状态。在正确初始化
drm_connector.state
之前调用此钩子是一个错误。注意
如果重复的状态引用了引用计数的资源,则此钩子必须获取对每个资源的引用。驱动程序必须在 **atomic_destroy_state** 中再次释放这些引用。
返回值
重复的原子状态,或者当分配失败时为 NULL。
atomic_destroy_state
销毁使用 **atomic_duplicate_state** 复制的状态,并释放或取消引用它引用的所有资源
此回调对于原子驱动程序是必需的。
atomic_set_property
解码驱动程序私有属性值,并将解码后的值存储到传入的状态结构中。由于原子核心解码所有标准化属性(即使是超出核心属性集范围的扩展,这些扩展可能并非所有驱动程序都实现),因此这要求驱动程序继承状态结构。
此类驱动程序私有属性实际上只应为真正的硬件/供应商特定状态实现。相反,最好标准化原子扩展并在核心中解码用于公开此类扩展的属性。
不要直接调用此函数,请使用 drm_atomic_connector_set_property() 代替。
如果驱动程序不支持任何驱动程序私有原子属性,则此回调是可选的。
注意
此函数在原子模式设置的状态程序集阶段中调用,该阶段可能因任何原因中止(包括应用户空间请求仅检查配置是否可能)。驱动程序不得触摸任何持久状态(硬件或软件)或数据结构,除了传入的 **state** 参数。
此外,由于用户空间控制属性的设置顺序,因此此函数不得进行任何输入验证(因为状态更新不完整,因此可能不一致)。相反,任何此类输入验证都必须在各种 atomic_check 回调中完成。
返回值
如果找到了该属性,则为 0;如果驱动程序未实现该属性,则为 -EINVAL(这不应该发生,核心只请求附加到此连接器的属性)。驱动程序不允许进行其他验证。核心已经检查了属性值是否在驱动程序注册该属性时设置的范围内(整数、有效枚举值...)。
atomic_get_property
读取解码后的驱动程序私有属性。这用于实现 GETCONNECTOR IOCTL。
不要直接调用此函数,请使用 drm_atomic_connector_get_property() 代替。
如果驱动程序不支持任何驱动程序私有原子属性,则此回调是可选的。
返回值
成功时为 0,如果驱动程序未实现该属性,则为 -EINVAL(这不应该发生,核心只请求附加到此连接器的属性)。
atomic_print_state
如果驱动程序子类化
struct drm_connector_state
,则应实现此可选钩子以打印其他驱动程序特定状态。不要直接调用此函数,请使用 drm_atomic_connector_print_state() 代替。
oob_hotplug_event
当从显示驱动程序/设备外部的源接收到 drm-connector 的热插拔事件时,将调用此函数。
debugfs_init
允许连接器创建特定于连接器的 debugfs 文件。
描述
每个 CRTC 可以连接到一个或多个连接器。以下函数允许核心 DRM 代码控制连接器、枚举可用模式等。
-
struct drm_cmdline_mode¶
通过内核命令行传递的 DRM 模式
定义:
struct drm_cmdline_mode {
char name[DRM_DISPLAY_MODE_LEN];
bool specified;
bool refresh_specified;
bool bpp_specified;
unsigned int pixel_clock;
int xres;
int yres;
int bpp;
int refresh;
bool rb;
bool interlace;
bool cvt;
bool margins;
enum drm_connector_force force;
unsigned int rotation_reflection;
enum drm_panel_orientation panel_orientation;
struct drm_connector_tv_margins tv_margins;
enum drm_connector_tv_mode tv_mode;
bool tv_mode_specified;
};
成员
名称
模式的名称。
specified
是否已从命令行读取模式?
refresh_specified
该模式是否具有首选刷新率?
bpp_specified
该模式是否具有首选 BPP?
pixel_clock
像素时钟,单位为 kHz。可选。
xres
X 轴上的活动分辨率,以像素为单位。
yres
Y 轴上的活动分辨率,以像素为单位。
bpp
该模式的每像素位数。
refresh
刷新率,单位为赫兹。
rb
我们需要使用减少的消隐吗?
interlace
该模式是隔行扫描的。
cvt
时序将使用 VESA 协调视频时序计算,而不是从表中查找模式。
margins
将边距添加到模式计算(xres 的 1.8% 向下舍入到 8 像素,yres 的 1.8%)。
force
忽略连接器的热插拔状态,并强制将其状态设置为 DRM_FORCE_* 值之一。
rotation_reflection
从命令行设置的模式的初始旋转和反射。参见 DRM_MODE_ROTATE_* 和 DRM_MODE_REFLECT_*. 仅支持的旋转是 DRM_MODE_ROTATE_0 和 DRM_MODE_ROTATE_180。
panel_orientation
drm-connector “面板方向”属性覆盖值,如果未设置,则为 DRM_MODE_PANEL_ORIENTATION_UNKNOWN。
tv_margins
应用于模式的 TV 边距。
tv_mode
电视模式标准。参见 DRM_MODE_TV_MODE_*。
tv_mode_specified
该模式是否具有首选电视模式?
描述
每个连接器都可以有一个初始模式,其中包含通过内核命令行传递的其他选项。此结构允许表达这些参数,并将由命令行解析器填充。
-
struct drm_connector_hdmi_audio¶
DRM gemeric HDMI 编解码器相关结构
定义:
struct drm_connector_hdmi_audio {
const struct drm_connector_hdmi_audio_funcs *funcs;
struct platform_device *codec_pdev;
struct mutex lock;
void (*plugged_cb)(struct device *dev, bool plugged);
struct device *plugged_cb_dev;
bool last_state;
int dai_port;
};
成员
funcs
要由 DRM HDMI 编解码器框架使用的 HDMI 编解码器功能的实现。
codec_pdev
为保存 HDMI 编解码器而创建的平台设备。它将在
drm_connector_cleanup()
期间自动注销。lock
Mutex 用于保护 last_state、plugged_cb 和 plugged_cb_dev。
plugged_cb
当 HDMI sink 插入或从该连接器拔出时要调用的回调。当 ASoC 代码请求时,框架会分配此回调。
plugged_cb_dev
plugged_cb() 的数据。它由 ASoC 提供。
last_state
框架记录的上次插入状态。它用于正确地向 plugged_cb() 报告状态。
dai_port
DT 中用于编解码器 DAI 的端口。
描述
HDMI 驱动程序通常包含 HDMI 编解码器。此结构表示 DRM HDMI 编解码器框架使用的通用 HDMI 编解码器。
-
struct drm_connector¶
中央 DRM 连接器控制结构
定义:
struct drm_connector {
struct drm_device *dev;
struct device *kdev;
struct device_attribute *attr;
struct fwnode_handle *fwnode;
struct list_head head;
struct list_head global_connector_list_entry;
struct drm_mode_object base;
char *name;
struct mutex mutex;
unsigned index;
int connector_type;
int connector_type_id;
bool interlace_allowed;
bool doublescan_allowed;
bool stereo_allowed;
bool ycbcr_420_allowed;
enum drm_connector_registration_state registration_state;
struct list_head modes;
enum drm_connector_status status;
struct list_head probed_modes;
struct drm_display_info display_info;
const struct drm_connector_funcs *funcs;
struct drm_property_blob *edid_blob_ptr;
struct drm_object_properties properties;
struct drm_property *scaling_mode_property;
struct drm_property *vrr_capable_property;
struct drm_property *colorspace_property;
struct drm_property_blob *path_blob_ptr;
unsigned int max_bpc;
struct drm_property *max_bpc_property;
struct drm_privacy_screen *privacy_screen;
struct notifier_block privacy_screen_notifier;
struct drm_property *privacy_screen_sw_state_property;
struct drm_property *privacy_screen_hw_state_property;
struct drm_property *broadcast_rgb_property;
#define DRM_CONNECTOR_POLL_HPD (1 << 0);
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1);
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2);
uint8_t polled;
int dpms;
const struct drm_connector_helper_funcs *helper_private;
struct drm_cmdline_mode cmdline_mode;
enum drm_connector_force force;
const struct drm_edid *edid_override;
struct mutex edid_override_mutex;
u64 epoch_counter;
u32 possible_encoders;
struct drm_encoder *encoder;
#define MAX_ELD_BYTES 128;
uint8_t eld[MAX_ELD_BYTES];
struct mutex eld_mutex;
bool latency_present[2];
int video_latency[2];
int audio_latency[2];
struct i2c_adapter *ddc;
int null_edid_counter;
unsigned bad_edid_counter;
bool edid_corrupt;
u8 real_edid_checksum;
struct dentry *debugfs_entry;
struct drm_connector_state *state;
struct drm_property_blob *tile_blob_ptr;
bool has_tile;
struct drm_tile_group *tile_group;
bool tile_is_single_monitor;
uint8_t num_h_tile, num_v_tile;
uint8_t tile_h_loc, tile_v_loc;
uint16_t tile_h_size, tile_v_size;
struct llist_node free_node;
struct hdr_sink_metadata hdr_sink_metadata;
struct drm_connector_hdmi hdmi;
struct drm_connector_hdmi_audio hdmi_audio;
};
成员
dev
父 DRM 设备
kdev
sysfs 属性的内核设备
attr
sysfs 属性
fwnode
平台固件提供的关联 fwnode
驱动程序可以设置此项以将 fwnode 与连接器关联,驱动程序应在设置此项时获取对 fwnode 的引用。
drm_connector_cleanup()
将在此项上调用 fwnode_handle_put()。head
dev 上所有连接器的列表,从
drm_mode_config.connector_list
链接。受drm_mode_config.connector_list_lock
保护,但请仅使用drm_connector_list_iter
遍历此列表。global_connector_list_entry
全局连接器列表中的连接器条目,由 drm_connector_find_by_fwnode() 使用。
基本
基本 KMS 对象
名称
人类可读的名称,可以由驱动程序覆盖
mutex
用于一般连接器状态的锁,但目前仅保护 registered。大多数连接器状态仍然受
drm_mode_config.mutex
保护。索引
压缩的连接器索引,与不支持热添加/删除的驱动程序的 mode_config.list 中的位置匹配。可以用作数组索引。它在连接器的生命周期内是不变的。
connector_type
drm_mode.h 中的 DRM_MODE_CONNECTOR_<foo> 类型之一
connector_type_id
连接器类型枚举中的索引
interlace_allowed
此连接器可以处理隔行扫描模式吗?仅由
drm_helper_probe_single_connector_modes()
用于模式过滤。doublescan_allowed
此连接器可以处理 doublescan 吗?仅由
drm_helper_probe_single_connector_modes()
用于模式过滤。stereo_allowed
此连接器可以处理立体模式吗?仅由
drm_helper_probe_single_connector_modes()
用于模式过滤。ycbcr_420_allowed
此布尔值指示此连接器是否能够处理 YCBCR 420 输出。在解析 EDID 块时,了解源是否能够处理 YCBCR 420 输出非常有帮助。
registration_state
此连接器是在初始化、已向用户空间公开(已注册)还是未注册?
受 mutex 保护。
modes
此连接器上可用的模式(来自 fill_modes() + 用户)。受
drm_mode_config.mutex
保护。status
drm_connector_status 枚举之一(已连接、未连接或未知)。受
drm_mode_config.mutex
保护。probed_modes
这些是使用 DDC 或 BIOS 探测添加的模式,在应用过滤之前。由 probe helpers 使用。受
drm_mode_config.mutex
保护。display_info
检测到显示器时,显示信息会从 EDID 信息中填充。对于非热插拔的显示器,例如嵌入式系统中的平板显示器,驱动程序应使用显示器的物理尺寸初始化
drm_display_info.width_mm
和drm_display_info.height_mm
字段。受
drm_mode_config.mutex
保护。funcs
连接器控制函数
edid_blob_ptr
DRM 属性,如果存在则包含 EDID。受
drm_mode_config.mutex
保护。只能通过调用
drm_edid_connector_update()
或drm_connector_update_edid_property()
来更新此属性。驱动程序不得直接使用此属性。
properties
此连接器的属性跟踪
scaling_mode_property
用于控制放大比例的可选原子属性。请参阅
drm_connector_attach_content_protection_property()
。vrr_capable_property
可选属性,用于帮助用户空间查询连接器上可变刷新率的硬件支持。驱动程序可以通过调用
drm_connector_attach_vrr_capable_property()
将该属性添加到连接器。只能通过调用
drm_connector_set_vrr_capable_property()
来更新此属性。colorspace_property
连接器属性,用于设置接收器支持的合适颜色空间。
path_blob_ptr
DP MST 路径属性的 DRM blob 属性数据。只能通过调用
drm_connector_set_path_property()
来更新此属性。max_bpc
连接器支持的每个颜色通道的最大位数。
max_bpc_property
用于驱动连接器的最大 bpc 的默认连接器属性。
privacy_screen
此连接器的 drm_privacy_screen,或 NULL。
privacy_screen_notifier
privacy-screen notifier_block
privacy_screen_sw_state_property
用于控制集成隐私屏幕的连接器的可选原子属性。
privacy_screen_hw_state_property
用于报告实际集成隐私屏幕状态的连接器的可选原子属性。
broadcast_rgb_property
用于设置 Broadcast RGB 选择以进行输出的连接器属性。
polled
连接器轮询模式,是以下项的组合:
- DRM_CONNECTOR_POLL_HPD
连接器生成热插拔事件,不需要定期轮询。CONNECT 和 DISCONNECT 标志不得与 HPD 标志一起设置。
- DRM_CONNECTOR_POLL_CONNECT
定期轮询连接器的连接状态。
- DRM_CONNECTOR_POLL_DISCONNECT
定期轮询连接器的断开连接状态,即使连接器正在使用中也不会导致闪烁。DAC 在没有大量测试的情况下应很少这样做。
对于不支持连接状态发现的连接器,设置为 0。
dpms
当前的 dpms 状态。对于旧版驱动程序,
drm_connector_funcs.dpms
回调必须更新此值。对于原子驱动程序,这由核心原子代码处理,驱动程序只需考虑drm_crtc_state.active
即可。helper_private
中间层私有数据
cmdline_mode
从此连接器的内核 cmdline 中解析的模式行
force
强制模式设置的 DRM_FORCE_<foo> 状态
edid_override
通过 debugfs 设置的覆盖 EDID。
请勿在 drm_edid_override_* 系列函数之外修改或访问。
edid_override_mutex
保护对 edid_override 的访问。
epoch_counter
用于检测连接器中的任何其他更改,状态除外
possible_encoders
可以驱动此连接器的编码器的位掩码,
drm_encoder_index()
确定位域中的索引,位使用drm_connector_attach_encoder()
设置。encoder
当前绑定到驱动此连接器的编码器(如果存在)。仅对于非原子驱动程序真正有意义。原子驱动程序应改为查看
drm_connector_state.best_encoder
,如果需要驱动此输出的 CRTC,则查看drm_connector_state.crtc
。eld
类似 EDID 的数据(如果存在),受 eld_mutex 保护
eld_mutex
保护对 eld 的并发访问
latency_present
来自 ELD 的 AV 延迟信息(如果找到)
video_latency
来自 ELD 的视频延迟信息(如果找到)。[0]:逐行扫描,[1]:隔行扫描
audio_latency
来自 ELD 的音频延迟信息(如果找到)。[0]:逐行扫描,[1]:隔行扫描
ddc
关联的 ddc 适配器。连接器通常具有其关联的 ddc 适配器。如果驱动程序使用此字段,则在连接器 sysfs 目录中创建一个相应的符号链接,以便用户可以轻松地判断哪个 i2c 适配器用于特定显示器。
应通过调用
drm_connector_init_with_ddc()
来设置该字段。null_edid_counter
跟踪为我们提供 EDID 全零的接收器。需要解决我们获得全 0 的一些硬件错误
bad_edid_counter
跟踪为我们提供具有无效校验和的 EDID 的接收器
edid_corrupt
指示上次读取的 EDID 是否已损坏。用于 Displayport 一致性测试 - Displayport Link CTS Core 1.2 rev1.1 4.2.2.6
real_edid_checksum
损坏的 edid 块的真实 edid 校验和。Displayport 1.4 一致性测试 rev1.1 4.2.2.6 中需要
debugfs_entry
此连接器的 debugfs 目录
state
此连接器的当前原子状态。
受
drm_mode_config.connection_mutex
保护。请注意,非阻塞原子提交在不加锁的情况下访问当前连接器状态。要么通过struct drm_atomic_state
指针,请参阅for_each_oldnew_connector_in_state()
、for_each_old_connector_in_state()
和for_each_new_connector_in_state()
。要么通过原子辅助函数中实现的原子提交操作的仔细排序,请参阅struct drm_crtc_commit
。tile_blob_ptr
平铺属性的 DRM blob 属性数据(主要由 DP MST 使用)。这适用于通过由
drm_crtc
表示的单独显示流水线驱动的屏幕,这些流水线可能未运行 genlocked 时钟。对于像双链路 LVDS 或双链路 DSI 这样 genlocked 的平铺面板,驱动程序应尽量不公开平铺,并在需要时虚拟化drm_crtc
和drm_plane
。只能通过调用
drm_connector_set_tile_property()
来更新此属性。has_tile
此连接器是否连接到平铺显示器
tile_group
连接显示器的平铺组
tile_is_single_monitor
平铺是否为单个显示器外壳
num_h_tile
平铺组中的水平平铺数
num_v_tile
平铺组中的垂直平铺数
tile_h_loc
此平铺的水平位置
tile_v_loc
此平铺的垂直位置
tile_h_size
此平铺的水平大小。
tile_v_size
此平铺的垂直大小。
free_node
仅由
drm_connector_list_iter
使用的列表,以便能够从任何上下文中清理连接器,与drm_mode_config.connector_free_work
结合使用。hdr_sink_metadata
从接收器读取的 HDR 元数据信息
hdmi
HDMI 相关变量和属性。
hdmi_audio
HDMI 编解码器属性和非 DRM 状态。
描述
每个连接器可以连接到一个或多个 CRTC,或者如果它们可以共享一个 CRTC,则可以被另一个连接器克隆。每个连接器在更广泛的显示器中也具有特定位置(称为“屏幕”,尽管它可以跨越多个显示器)。
-
struct drm_connector *drm_connector_lookup(struct drm_device *dev, struct drm_file *file_priv, uint32_t id)¶
查找连接器对象
参数
struct drm_device *dev
DRM 设备
struct drm_file *file_priv
用于检查租赁的 DRM 文件。
uint32_t id
连接器对象 ID
描述
此函数查找由 id 指定的连接器对象,并获取对其的引用。
-
void drm_connector_get(struct drm_connector *connector)¶
获取连接器引用
参数
struct drm_connector *connector
DRM 连接器
描述
此函数递增连接器的 refcount。
-
void drm_connector_put(struct drm_connector *connector)¶
释放连接器引用
参数
struct drm_connector *connector
DRM 连接器
描述
此函数递减连接器的引用计数,并在引用计数降至零时释放该对象。
-
bool drm_connector_is_unregistered(struct drm_connector *connector)¶
连接器是否已从用户空间注销?
参数
struct drm_connector *connector
DRM 连接器
描述
检查是否已从用户空间注销了 connector。
返回
如果已注销连接器,则为 True;如果已注册连接器或尚未向用户空间注册,则为 False。
-
struct drm_tile_group¶
平铺组元数据
定义:
struct drm_tile_group {
struct kref refcount;
struct drm_device *dev;
int id;
u8 group_data[8];
};
成员
refcount
引用计数
dev
DRM 设备
id
暴露给用户空间的平铺组 ID
group_data
标识此组的接收器私有数据
描述
对于具有 EDID 的外部屏幕,group_data 对应于 displayid vend/prod/serial。
-
struct drm_connector_list_iter¶
connector_list 迭代器
定义:
struct drm_connector_list_iter {
};
成员
描述
此迭代器跟踪在 struct drm_mode_config
中遍历 connector_list 所需的状态。仅与 drm_connector_list_iter_begin()
、drm_connector_list_iter_end()
和 drm_connector_list_iter_next()
以及便捷宏 drm_for_each_connector_iter()
一起使用。
请注意,drm_connector_list_iter_next()
的返回值仅在下一次 drm_connector_list_iter_next()
或 drm_connector_list_iter_end()
调用之前有效。如果稍后要使用该连接器,则需要首先使用 drm_connector_get()
获取自己的引用。
-
drm_for_each_connector_iter¶
drm_for_each_connector_iter (connector, iter)
connector_list 迭代器宏
参数
connector
用作游标的
struct drm_connector
指针iter
描述
请注意,connector 仅在列表主体中有效。如果在调用 drm_connector_list_iter_end()
后要使用 connector,则需要首先使用 drm_connector_get()
获取自己的引用。
-
drm_connector_for_each_possible_encoder¶
drm_connector_for_each_possible_encoder (connector, encoder)
迭代连接器的可能编码器
参数
connector
encoder
用作游标的
struct drm_encoder
指针
-
const char *drm_get_connector_type_name(unsigned int type)¶
返回连接器类型的字符串
参数
unsigned int type
连接器类型 (DRM_MODE_CONNECTOR_*)
返回
连接器类型的名称,如果类型无效,则为 NULL。
-
int drm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type)¶
初始化预分配的连接器
参数
struct drm_device *dev
DRM 设备
struct drm_connector *connector
要初始化的连接器
const struct drm_connector_funcs *funcs
此连接器的回调
int connector_type
用户可见的连接器类型
描述
初始化预分配的连接器。连接器应作为驱动程序连接器对象的一部分进行子类化。
在驱动程序卸载时,驱动程序的 drm_connector_funcs.destroy
钩子函数应调用 drm_connector_cleanup()
并释放连接器结构体。连接器结构体不应使用 devm_kzalloc() 分配。
注意
考虑使用 drmm_connector_init()
而不是 drm_connector_init()
,以便让 DRM 管理的资源基础设施负责清理和释放。
返回
成功时为零,失败时为错误代码。
-
int drm_connector_dynamic_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type, struct i2c_adapter *ddc)¶
初始化一个预先分配的动态连接器
参数
struct drm_device *dev
DRM 设备
struct drm_connector *connector
要初始化的连接器
const struct drm_connector_funcs *funcs
此连接器的回调
int connector_type
用户可见的连接器类型
struct i2c_adapter *ddc
指向关联的 ddc 适配器的指针
描述
初始化一个预先分配的动态连接器。连接器应作为驱动程序连接器对象的一部分进行子类化。连接器结构体不应使用 devm_kzalloc() 分配。
对于在 drm_dev_register()
被调用后可以热插拔的动态连接器,例如 DP MST 连接器,驱动程序应调用此函数。对于所有其他 - 静态 - 连接器,驱动程序应调用 drm_connector_init*()/drmm_connector_init*() 函数之一。
调用此函数后,驱动程序必须调用 drm_connector_dynamic_register()
。
要移除连接器,驱动程序必须调用 drm_connector_unregister()
,然后调用 drm_connector_put()
。释放最后一个引用将调用驱动程序的 drm_connector_funcs.destroy
钩子函数,该函数又必须调用 drm_connector_cleanup()
并释放连接器结构体。
返回
成功时为零,失败时为错误代码。
-
int drm_connector_init_with_ddc(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type, struct i2c_adapter *ddc)¶
初始化预分配的连接器
参数
struct drm_device *dev
DRM 设备
struct drm_connector *connector
要初始化的连接器
const struct drm_connector_funcs *funcs
此连接器的回调
int connector_type
用户可见的连接器类型
struct i2c_adapter *ddc
指向关联的 ddc 适配器的指针
描述
初始化预分配的连接器。连接器应作为驱动程序连接器对象的一部分进行子类化。
在驱动程序卸载时,驱动程序的 drm_connector_funcs.destroy
钩子函数应调用 drm_connector_cleanup()
并释放连接器结构体。连接器结构体不应使用 devm_kzalloc() 分配。
确保正确设置连接器的 ddc 字段。
注意
考虑使用 drmm_connector_init()
而不是 drm_connector_init_with_ddc()
,以便让 DRM 管理的资源基础设施负责清理和释放。
返回
成功时为零,失败时为错误代码。
-
int drmm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type, struct i2c_adapter *ddc)¶
初始化预分配的连接器
参数
struct drm_device *dev
DRM 设备
struct drm_connector *connector
要初始化的连接器
const struct drm_connector_funcs *funcs
此连接器的回调
int connector_type
用户可见的连接器类型
struct i2c_adapter *ddc
指向关联的 ddc 适配器的可选指针
描述
初始化预分配的连接器。连接器应作为驱动程序连接器对象的一部分进行子类化。
通过在 DRM 管理的操作中调用 drm_connector_cleanup()
自动处理清理。
连接器结构体应使用 drmm_kzalloc()
分配。
drm_connector_funcs.destroy 钩子函数必须为 NULL。
返回
成功时为零,失败时为错误代码。
-
int drmm_connector_hdmi_init(struct drm_device *dev, struct drm_connector *connector, const char *vendor, const char *product, const struct drm_connector_funcs *funcs, const struct drm_connector_hdmi_funcs *hdmi_funcs, int connector_type, struct i2c_adapter *ddc, unsigned long supported_formats, unsigned int max_bpc)¶
初始化一个预先分配的 HDMI 连接器
参数
struct drm_device *dev
DRM 设备
struct drm_connector *connector
指向要初始化的 HDMI 连接器的指针
const char *vendor
HDMI 控制器供应商名称
const char *product
HDMI 控制器产品名称
const struct drm_connector_funcs *funcs
此连接器的回调
const struct drm_connector_hdmi_funcs *hdmi_funcs
此连接器的 HDMI 相关回调
int connector_type
用户可见的连接器类型
struct i2c_adapter *ddc
指向关联的 ddc 适配器的可选指针
unsigned long supported_formats
hdmi_colorspace 的位掩码,列出支持的输出格式
unsigned int max_bpc
HDMI 连接器支持的最大每字符位数
描述
初始化一个预先分配的 HDMI 连接器。连接器可以作为驱动程序连接器对象的一部分进行子类化。
通过在 DRM 管理的操作中调用 drm_connector_cleanup()
自动处理清理。
连接器结构体应使用 drmm_kzalloc()
分配。
drm_connector_funcs.destroy 钩子函数必须为 NULL。
返回
成功时为零,失败时为错误代码。
-
void drm_connector_attach_edid_property(struct drm_connector *connector)¶
附加 edid 属性。
参数
struct drm_connector *connector
连接器
描述
某些连接器类型(如 DRM_MODE_CONNECTOR_VIRTUAL)默认情况下不会附加 edid 属性。此函数可用于在这些情况下显式启用 edid 属性。
-
int drm_connector_attach_encoder(struct drm_connector *connector, struct drm_encoder *encoder)¶
将连接器附加到编码器
参数
struct drm_connector *connector
要附加的连接器
struct drm_encoder *encoder
要将 connector 附加到的编码器
描述
此函数将连接器链接到编码器。请注意,编码器和 crtc 之间的路由限制通过 possible_clones 和 possible_crtcs 位掩码暴露给用户空间。
返回
成功时返回零,失败时返回负 errno。
-
bool drm_connector_has_possible_encoder(struct drm_connector *connector, struct drm_encoder *encoder)¶
检查连接器和编码器是否彼此关联
参数
struct drm_connector *connector
连接器
struct drm_encoder *encoder
编码器
返回
如果 encoder 是 connector 的可能编码器之一,则为 True。
-
void drm_connector_cleanup(struct drm_connector *connector)¶
清理已初始化的连接器
参数
struct drm_connector *connector
要清理的连接器
描述
清理连接器但不释放对象。
-
int drm_connector_register(struct drm_connector *connector)¶
注册连接器
参数
struct drm_connector *connector
要注册的连接器
描述
为连接器注册用户空间接口。驱动程序不应调用此函数。静态连接器将由 DRM 核心从 drm_dev_register()
自动注册,动态连接器 (MST) 应由驱动程序调用 drm_connector_dynamic_register()
注册。
当连接器不再可用时,调用者必须调用 drm_connector_unregister()
。
注意
驱动程序中此函数的现有用法应已是空操作,并且计划移除。
返回
成功时为零,失败时为错误代码。
-
int drm_connector_dynamic_register(struct drm_connector *connector)¶
注册动态连接器
参数
struct drm_connector *connector
要注册的连接器
描述
为连接器注册用户空间接口。仅对通过调用 drm_connector_dynamic_init()
初始化的连接器调用此函数。所有其他连接器将在调用 drm_dev_register()
时自动注册。
当连接器不再可用时,驱动程序必须调用 drm_connector_unregister()
。
返回
成功时为零,失败时为错误代码。
-
void drm_connector_unregister(struct drm_connector *connector)¶
注销连接器
参数
struct drm_connector *connector
要注销的连接器
描述
为连接器注销用户空间接口。驱动程序应仅对通过调用 drm_connector_dynamic_register()
显式注册的动态连接器 (MST) 调用此函数。所有其他 - 静态 - 连接器将由 DRM 核心自动注销,驱动程序不应为这些连接器调用此函数。
注意
驱动程序中此函数的现有用法应已是空操作,并且计划移除。
-
const char *drm_get_connector_status_name(enum drm_connector_status status)¶
返回连接器状态的字符串
参数
enum drm_connector_status status
要计算名称的连接器状态
描述
与其他 drm_get_*_name 函数相比,此函数返回一个 const 指针,因此是线程安全的。
返回
连接器状态字符串
-
void drm_connector_list_iter_begin(struct drm_device *dev, struct drm_connector_list_iter *iter)¶
初始化 connector_list 迭代器
参数
struct drm_device *dev
DRM 设备
struct drm_connector_list_iter *iter
connector_list 迭代器
描述
设置 iter 以遍历 dev 的 drm_mode_config.connector_list
。 iter 必须始终通过调用 drm_connector_list_iter_end()
再次清理。迭代本身使用 drm_connector_list_iter_next()
或 drm_for_each_connector_iter()
进行。
-
struct drm_connector *drm_connector_list_iter_next(struct drm_connector_list_iter *iter)¶
返回下一个连接器
参数
struct drm_connector_list_iter *iter
connector_list 迭代器
返回
iter 的下一个连接器,或者在列表遍历完成时返回 NULL。
-
void drm_connector_list_iter_end(struct drm_connector_list_iter *iter)¶
拆卸连接器列表迭代器
参数
struct drm_connector_list_iter *iter
connector_list 迭代器
描述
拆卸 iter 并释放任何资源(如遍历列表时获取的 drm_connector
引用)。无论迭代完全完成还是在未遍历整个列表的情况下中止,都必须始终调用此函数。
-
const char *drm_get_subpixel_order_name(enum subpixel_order order)¶
返回给定子像素枚举的字符串
参数
enum subpixel_order order
subpixel_order 的枚举
描述
请注意,你可以滥用此功能并返回超出范围的内容,但这将是调用者的错误。任何未清理的用户数据都不应到达此处。
返回
描述枚举的子像素属性的字符串
-
int drm_display_info_set_bus_formats(struct drm_display_info *info, const u32 *formats, unsigned int num_formats)¶
设置支持的总线格式
参数
struct drm_display_info *info
用于存储总线格式的显示信息
const u32 *formats
包含支持的总线格式的数组
unsigned int num_formats
fmts 数组中的条目数
描述
将支持的总线格式存储在显示信息结构中。有关可用格式的完整列表,请参见 include/uapi/linux/media-bus-format.h 中的 MEDIA_BUS_FMT_* 定义。
返回
成功时为 0,失败时为负错误代码。
-
int drm_get_tv_mode_from_name(const char *name, size_t len)¶
将电视模式名称转换为其枚举值
参数
const char *name
我们要转换的电视模式名称
size_t len
name 的长度
描述
将 name 转换为 enum drm_connector_tv_mode
。
返回
成功时的枚举值,否则为负的 errno。
-
int drm_mode_create_dvi_i_properties(struct drm_device *dev)¶
创建 DVI-I 特定的连接器属性
参数
struct drm_device *dev
DRM 设备
描述
由驱动程序在首次创建 DVI-I 连接器时调用。
返回
0
-
void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector)¶
为 DP 创建子连接器属性
参数
struct drm_connector *connector
要附加属性的 drm_connector
描述
由驱动程序在创建 DP 连接器时调用。
-
int drm_connector_attach_content_type_property(struct drm_connector *connector)¶
附加 content-type 属性
参数
struct drm_connector *connector
要在其上附加 content type 属性的连接器。
描述
由驱动程序在首次创建 HDMI 连接器时调用。
返回
0
-
void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)¶
附加 TV 连接器边距属性
参数
struct drm_connector *connector
DRM 连接器
描述
当驱动程序需要将 TV 边距属性附加到连接器时调用。通常用于 SDTV 和 HDMI 连接器。
-
int drm_mode_create_tv_margin_properties(struct drm_device *dev)¶
创建 TV 连接器边距属性
参数
struct drm_device *dev
DRM 设备
描述
此函数由驱动程序的 HDMI 连接器初始化例程调用,用于为给定设备创建 TV 边距属性。对于 SDTV 连接器,无需调用此函数,它已经从 drm_mode_create_tv_properties_legacy()
中调用。
返回
成功时为 0,失败时为负错误代码。
-
int drm_mode_create_tv_properties_legacy(struct drm_device *dev, unsigned int num_modes, const char *const modes[])¶
创建 TV 特定的连接器属性
参数
struct drm_device *dev
DRM 设备
unsigned int num_modes
支持的不同 TV 格式(模式)的数量
const char * const modes[]
指向包含每个格式名称的字符串的指针数组
描述
此函数由驱动程序的 TV 初始化例程调用,用于为给定设备创建 TV 特定的连接器属性。调用者负责分配格式名称列表并将它们传递给此例程。
注意
此函数注册已弃用的“mode”连接器属性,以选择模拟电视模式(即,NTSC、PAL 等)。新的驱动程序必须使用 drm_mode_create_tv_properties()
代替。
返回
成功时为 0,失败时为负错误代码。
-
int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int supported_tv_modes)¶
创建 TV 特定的连接器属性
参数
struct drm_device *dev
DRM 设备
unsigned int supported_tv_modes
支持的 TV 模式的位掩码(参见 DRM_MODE_TV_MODE_*)
描述
此函数由驱动程序的 TV 初始化例程调用,用于为给定设备创建 TV 特定的连接器属性。
返回
成功时为 0,失败时为负错误代码。
-
int drm_mode_create_scaling_mode_property(struct drm_device *dev)¶
创建缩放模式属性
参数
struct drm_device *dev
DRM 设备
描述
由驱动程序在首次需要时调用,必须附加到所需的连接器。
原子驱动程序应使用 drm_connector_attach_scaling_mode_property()
代替,以在原子状态中正确分配 drm_connector_state.scaling_mode
。
返回
0
-
int drm_connector_attach_vrr_capable_property(struct drm_connector *connector)¶
创建 vrr_capable 属性
参数
struct drm_connector *connector
在其上创建 vrr_capable 属性的连接器。
描述
原子驱动程序使用它来添加对查询连接器的可变刷新率功能的支持。
返回
成功时返回零,失败时返回负 errno。
-
int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, u32 scaling_mode_mask)¶
附加原子缩放模式属性
参数
struct drm_connector *connector
要在其上附加缩放模式属性的连接器。
u32 scaling_mode_mask
BIT(
DRM_MODE_SCALE_
*) 的或运算掩码。
描述
这用于向原子驱动程序添加对缩放模式的支持。缩放模式将设置为 drm_connector_state.scaling_mode
,并且可以从 drm_connector_helper_funcs->atomic_check
中用于验证。
这是 drm_mode_create_scaling_mode_property()
的原子版本。
返回
成功时返回零,失败时返回负 errno。
-
int drm_mode_create_aspect_ratio_property(struct drm_device *dev)¶
创建宽高比属性
参数
struct drm_device *dev
DRM 设备
描述
由驱动程序在首次需要时调用,必须附加到所需的连接器。
返回
成功时返回零,失败时返回负 errno。
-
int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector, u32 supported_colorspaces)¶
创建 HDMI 色彩空间属性
参数
struct drm_connector *connector
在其上创建 Colorspace 属性的连接器。
u32 supported_colorspaces
支持的颜色空间的位图
描述
由驱动程序在首次需要时调用,必须附加到所需的 HDMI 连接器。
返回
成功时返回零,失败时返回负 errno。
-
int drm_mode_create_dp_colorspace_property(struct drm_connector *connector, u32 supported_colorspaces)¶
创建 dp 色彩空间属性
参数
struct drm_connector *connector
在其上创建 Colorspace 属性的连接器。
u32 supported_colorspaces
支持的颜色空间的位图
描述
由驱动程序在首次需要时调用,必须附加到所需的 DP 连接器。
返回
成功时返回零,失败时返回负 errno。
-
int drm_mode_create_content_type_property(struct drm_device *dev)¶
创建 content type 属性
参数
struct drm_device *dev
DRM 设备
描述
由驱动程序在首次需要时调用,必须附加到所需的连接器。
返回
成功时返回零,失败时返回负 errno。
-
int drm_mode_create_suggested_offset_properties(struct drm_device *dev)¶
创建 suggests offset 属性
参数
struct drm_device *dev
DRM 设备
描述
为连接器创建建议的 x/y 偏移属性。
返回
成功时为 0,失败时为负错误代码。
-
int drm_connector_set_path_property(struct drm_connector *connector, const char *path)¶
在连接器上设置 tile 属性
参数
struct drm_connector *connector
要在其上设置属性的连接器。
const char *path
用于属性的路径;不得为 NULL。
描述
这会创建一个属性,以向用户空间公开,以指定连接器路径。这主要用于 DisplayPort MST,其中连接器具有拓扑结构,并且我们希望允许用户空间为它们提供更有意义的名称。
返回
成功时返回零,失败时返回负 errno。
-
int drm_connector_set_tile_property(struct drm_connector *connector)¶
在连接器上设置 tile 属性
参数
struct drm_connector *connector
要在其上设置属性的连接器。
描述
这将查找连接器的 tile 信息,并创建一个属性供用户空间在存在时进行解析。该属性的形式为 8 个整数,使用“:”作为分隔符。这用于具有 DisplayPort SST 或 DisplayPort MST 连接器的双端口 tiled 显示器。
返回
成功时返回零,失败时返回 errno。
-
void drm_connector_set_link_status_property(struct drm_connector *connector, uint64_t link_status)¶
设置连接器的链接状态属性
参数
struct drm_connector *connector
drm 连接器
uint64_t link_status
链接状态属性的新值(0:良好,1:不良)
描述
在通常的工作场景中,此链接状态属性将始终设置为“GOOD”。如果在模式设置期间或之后发生某些错误,则内核驱动程序可能会将此链接状态属性设置为“BAD”。然后,调用者需要发送一个热插拔 uevent,以便用户空间通过 GET_CONNECTOR_IOCTL 重新检查有效模式并重试模式设置。
添加此属性的原因是为了处理链接训练失败,但这并不限于 DP 或链接训练。例如,如果我们实现异步 setcrtc,则可以使用此属性报告其中的任何失败。
注意
驱动程序不能依赖于用户空间来支持此属性并发出模式设置。因此,他们可以选择在没有用户空间干预的情况下处理问题(如重新训练链接)。
-
int drm_connector_attach_max_bpc_property(struct drm_connector *connector, int min, int max)¶
附加 "max bpc" 属性
参数
struct drm_connector *connector
连接器,用于附加 max bpc 属性。
int min
连接器支持的最小位深度。
int max
连接器支持的最大位深度。
描述
用于添加限制连接器位深度的支持。
返回
成功时返回零,失败时返回负 errno。
-
int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector)¶
附加 “HDR_OUTPUT_METADA” 属性
参数
struct drm_connector *connector
连接器,用于附加属性。
描述
用于允许用户空间将 HDR 元数据发送到驱动程序。
返回
成功时返回零,失败时返回负 errno。
-
int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector)¶
附加 “Broadcast RGB” 属性
参数
struct drm_connector *connector
连接器,用于附加属性。
描述
用于添加强制连接器上 RGB 范围的支持
返回
成功时返回零,失败时返回负 errno。
-
int drm_connector_attach_colorspace_property(struct drm_connector *connector)¶
附加 "Colorspace" 属性
参数
struct drm_connector *connector
连接器,用于附加属性。
描述
用于允许用户空间将输出色彩空间信号发送到驱动程序。
返回
成功时返回零,失败时返回负 errno。
-
bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state, struct drm_connector_state *new_state)¶
检查 hdr 元数据是否已更改
参数
struct drm_connector_state *old_state
要比较的旧连接器状态
struct drm_connector_state *new_state
要比较的新连接器状态
描述
启用了 HDR 的驱动程序使用此功能来测试两个不同连接器状态之间的 HDR 元数据是否已更改(因此可能需要进行全面的模式更改)。
返回
如果元数据相等,则为 True,否则为 False
-
void drm_connector_set_vrr_capable_property(struct drm_connector *connector, bool capable)¶
设置连接器的可变刷新率能力属性
参数
struct drm_connector *connector
drm 连接器
bool capable
如果连接器具有可变刷新率能力,则为 True
描述
应由 atomic 驱动程序使用来更新连接器上指示的可变刷新率支持。
-
int drm_connector_set_panel_orientation(struct drm_connector *connector, enum drm_panel_orientation panel_orientation)¶
设置连接器的 panel_orientation
参数
struct drm_connector *connector
要为其设置面板方向属性的连接器。
enum drm_panel_orientation panel_orientation
要设置的 drm_panel_orientation 值
描述
此函数设置连接器的 panel_orientation,并将“面板方向”属性附加到连接器。
在已设置 panel_orientation 的连接器上调用此函数是一个空操作(例如,已使用内核命令行选项覆盖了方向)。
允许使用 DRM_MODE_PANEL_ORIENTATION_UNKNOWN 的 panel_orientation 调用此函数,在这种情况下,它是一个空操作。
该函数不应在注册 drm 后在面板中调用(即在 drm 中调用 drm_dev_register()
)。
返回
成功时返回零,失败时返回负 errno。
-
int drm_connector_set_panel_orientation_with_quirk(struct drm_connector *connector, enum drm_panel_orientation panel_orientation, int width, int height)¶
在检查怪癖后设置连接器的 panel_orientation
参数
struct drm_connector *connector
要为其初始化面板方向属性的连接器。
enum drm_panel_orientation panel_orientation
要设置的 drm_panel_orientation 值
int width
面板的像素宽度,用于面板怪癖检测
int height
面板的像素高度,用于面板怪癖检测
描述
类似于 drm_connector_set_panel_orientation()
,但具有平台特定的(例如,基于 DMI)怪癖检查,该怪癖会覆盖传入的 panel_orientation。
返回
成功时返回零,失败时返回负 errno。
-
int drm_connector_set_orientation_from_panel(struct drm_connector *connector, struct drm_panel *panel)¶
从面板的回调设置连接器的 panel_orientation。
参数
struct drm_connector *connector
要为其初始化面板方向属性的连接器。
struct drm_panel *panel
可以提供方向信息的面板。
描述
Drm 驱动程序应在 drm_dev_register()
之前调用此函数。方向是从面板的 .get_orientation() 回调获得的。
返回
成功时返回零,失败时返回负 errno。
-
void drm_connector_create_privacy_screen_properties(struct drm_connector *connector)¶
创建 drm 连接器的隐私屏幕属性。
参数
struct drm_connector *connector
要为其创建隐私屏幕属性的连接器
描述
此函数为连接器创建“privacy-screen sw-state”和“privacy-screen hw-state”属性。 它们未附加。
-
void drm_connector_attach_privacy_screen_properties(struct drm_connector *connector)¶
附加 drm 连接器的隐私屏幕属性。
参数
struct drm_connector *connector
要在其上附加隐私屏幕属性的连接器
描述
此函数将“privacy-screen sw-state”和“privacy-screen hw-state”属性附加到连接器。 两者的初始状态都设置为“Disabled”。
-
void drm_connector_attach_privacy_screen_provider(struct drm_connector *connector, struct drm_privacy_screen *priv)¶
将隐私屏幕附加到连接器
参数
struct drm_connector *connector
要将隐私屏幕附加到的连接器
struct drm_privacy_screen *priv
要附加的 drm_privacy_screen
描述
创建并附加标准隐私屏幕属性,并注册一个通用通知程序,用于在隐私屏幕状态发生外部更改时生成 sysfs-connector-status-events。 此函数获取传入的 drm_privacy_screen 的所有权,并在销毁连接器时对其调用 drm_privacy_screen_put()
。
-
void drm_connector_update_privacy_screen(const struct drm_connector_state *connector_state)¶
更新连接器的隐私屏幕 sw-state
参数
const struct drm_connector_state *connector_state
要更新隐私屏幕的连接器状态
描述
此函数在连接器的隐私屏幕上调用 drm_privacy_screen_set_sw_state()
。
如果连接器没有隐私屏幕,则这是一个空操作。
-
void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, enum drm_connector_status status)¶
将带外热插拔事件报告给连接器
参数
struct fwnode_handle *connector_fwnode
要在其上报告事件的 fwnode_handle
enum drm_connector_status status
热插拔检测逻辑状态
描述
在某些硬件上,热插拔事件通知可能来自显示驱动程序/设备外部。 例如,某些 USB Type-C 设置,其中硬件复用 DisplayPort 数据和辅助线,但不将 altmode HPD 状态位传递到 GPU 的 DP HPD 引脚。
此函数可用于在通过调用 drm_connector_find_by_fwnode() 获取 drm_connector 引用后报告这些带外事件。
-
void drm_mode_put_tile_group(struct drm_device *dev, struct drm_tile_group *tg)¶
删除对图块组的引用。
参数
struct drm_device *dev
DRM 设备
struct drm_tile_group *tg
要删除引用的图块组。
描述
删除对图块组的引用,如果为 0,则释放。
-
struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, const char topology[8])¶
获取对现有图块组的引用
参数
struct drm_device *dev
DRM 设备
const char topology[8]
每个监视器唯一的 8 字节。
描述
使用唯一字节获取对现有图块组的引用。
返回
如果未找到,则返回图块组或 NULL。
-
struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, const char topology[8])¶
从 displayid 描述创建图块组
参数
struct drm_device *dev
DRM 设备
const char topology[8]
每个监视器唯一的 8 字节。
描述
为唯一的监视器创建图块组,并获取图块组的唯一标识符。
返回
新的图块组或 NULL。
回写连接器¶
回写连接器用于公开可以将 CRTC 的输出写入内存缓冲区的硬件。 它们的使用方式和其他类型的连接器类似,但有一些重要的区别
回写连接器不提供以视觉方式输出给用户的方式。
仅当客户端设置 DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 时,回写连接器才对用户空间可见。
回写连接器没有 EDID。
仅当帧缓冲区连接到 CRTC 时,才能将帧缓冲区连接到回写连接器。 设置帧缓冲区的 WRITEBACK_FB_ID 属性仅适用于单个提交(请参见下文)。 当 CRTC 关闭时,不得附加帧缓冲区。
与平面不同,当用户空间删除回写帧缓冲区时,DRM 不会尝试将其从连接器的活动使用中删除。 这是因为没有提供中止回写操作的方法,并且在任何情况下,在回写正在进行时进行新的提交都是未定义的(请参见下面的 WRITEBACK_OUT_FENCE_PTR)。 一旦当前的回写完成,帧缓冲区将自动不再处于活动使用状态。 由于它也已经从帧缓冲区列表中删除,因此任何用户空间应用程序都无法在中间期间检索对其的引用。
回写连接器具有一些额外的属性,用户空间可以使用这些属性来查询和控制它们
- “WRITEBACK_FB_ID”
只写对象属性,用于存储 DRM_MODE_OBJECT_FB:它存储要由回写连接器写入的帧缓冲区。 此属性类似于平面上的 FB_ID 属性,但始终读取为零,并且不会跨提交保留。 用户空间每次希望填充缓冲区时都必须将此属性设置为输出缓冲区。
- “WRITEBACK_PIXEL_FORMATS”
不可变 blob 属性,用于存储支持的像素格式表。 数据是 u32 DRM_FORMAT_* fourcc 值的数组。 用户空间可以使用此 blob 查找连接器的回写引擎支持哪些像素格式。
- “WRITEBACK_OUT_FENCE_PTR”
用户空间可以使用此属性为内核提供一个指针,以填充 sync_file 文件描述符,该描述符将在回写完成后发出信号。 该值应为 32 位有符号整数的地址,转换为 u64。 用户空间应在等待此栅栏发出信号后,再进行另一个影响任何相同 CRTC、Plane 或连接器的提交。 否则将导致未定义的行为。 因此,强烈建议所有使用回写连接器的用户空间应用程序始终检索提交的出栅栏并适当使用它。 在用户空间中,此属性将始终读取为零。
-
struct drm_writeback_connector¶
DRM 回写连接器
定义:
struct drm_writeback_connector {
struct drm_connector base;
struct drm_encoder encoder;
struct drm_property_blob *pixel_formats_blob_ptr;
spinlock_t job_lock;
struct list_head job_queue;
unsigned int fence_context;
spinlock_t fence_lock;
unsigned long fence_seqno;
char timeline_name[32];
};
成员
基本
基本 drm_connector 对象
encoder
连接器使用的内部编码器,用于满足 DRM 框架的需求。drm_writeback_connector 的用户通过将 enc_funcs 参数传递给
drm_writeback_connector_init()
函数来控制 encoder 的行为。对于drm_writeback_connector_init_with_encoder()
的用户,此字段无效,因为编码器由其驱动程序管理。pixel_formats_blob_ptr
用于回写连接器的像素格式列表的 DRM Blob 属性数据。另请参见
drm_writeback_connector_init()
job_lock
保护 job_queue
job_queue
保存连接器的回写作业列表;最后一项是最近的。第一项可能正在等待硬件开始写入,或者当前正在写入。
另请参见:
drm_writeback_queue_job()
和drm_writeback_signal_completion()
fence_context
用于栅栏操作的时间线上下文。
fence_lock
用于保护 fence_context 中栅栏的自旋锁。
fence_seqno
Seqno 变量用作连接器时间线上创建的 fence 的单调计数器。
timeline_name
连接器的 fence 时间线的名称。
-
struct drm_writeback_job¶
DRM 回写作业
定义:
struct drm_writeback_job {
struct drm_writeback_connector *connector;
bool prepared;
struct work_struct cleanup_work;
struct list_head list_entry;
struct drm_framebuffer *fb;
struct dma_fence *out_fence;
void *priv;
};
成员
connector
指向与作业关联的回写连接器的后向指针
prepared
使用 drm_writeback_prepare_job() 准备作业时设置
cleanup_work
用于允许 drm_writeback_signal_completion 将帧缓冲区引用延迟到工作队列
list_entry
回写连接器的 job_queue 的列表项
fb
要由回写连接器写入的帧缓冲区。不要直接设置,请使用 drm_writeback_set_fb()
out_fence
一旦回写完成,Fence 将发出信号
priv
驱动程序私有数据
-
int drm_writeback_connector_init(struct drm_device *dev, struct drm_writeback_connector *wb_connector, const struct drm_connector_funcs *con_funcs, const struct drm_encoder_helper_funcs *enc_helper_funcs, const u32 *formats, int n_formats, u32 possible_crtcs)¶
初始化回写连接器及其属性
参数
struct drm_device *dev
DRM 设备
struct drm_writeback_connector *wb_connector
要初始化的回写连接器
const struct drm_connector_funcs *con_funcs
连接器 funcs vtable
const struct drm_encoder_helper_funcs *enc_helper_funcs
内部编码器使用的编码器辅助函数 vtable
const u32 *formats
回写引擎支持的像素格式数组
int n_formats
格式数组的长度
u32 possible_crtcs
内部回写编码器的可能的 crtc
描述
如果尚未创建,则此函数将创建特定于回写连接器的属性,将连接器初始化为 DRM_MODE_CONNECTOR_WRITEBACK 类型,并正确初始化属性值。它还将创建一个与 drm_writeback_connector 关联的内部编码器,并将其设置为使用 enc_helper_funcs vtable 作为编码器辅助函数。
驱动程序应始终使用此函数而不是 drm_connector_init()
来设置回写连接器。
返回
成功时为 0,否则为负错误代码
-
int drm_writeback_connector_init_with_encoder(struct drm_device *dev, struct drm_writeback_connector *wb_connector, struct drm_encoder *enc, const struct drm_connector_funcs *con_funcs, const u32 *formats, int n_formats)¶
使用自定义编码器初始化回写连接器
参数
struct drm_device *dev
DRM 设备
struct drm_writeback_connector *wb_connector
要初始化的回写连接器
struct drm_encoder *enc
已初始化的 drm 编码器的句柄
const struct drm_connector_funcs *con_funcs
连接器 funcs vtable
const u32 *formats
回写引擎支持的像素格式数组
int n_formats
格式数组的长度
描述
如果尚未创建,则此函数将创建特定于回写连接器的属性,将连接器初始化为 DRM_MODE_CONNECTOR_WRITEBACK 类型,并正确初始化属性值。
此函数假定在调用此函数之前,已经创建并初始化了 drm_writeback_connector 的编码器。
此外,此函数还假定此 API 的调用者将管理分配编码器辅助函数、possible_crtcs 和任何其他特定于编码器的操作。
如果驱动程序想要自行管理关联编码器的生命周期,则应始终使用此函数而不是 drm_connector_init()
来设置回写连接器。
返回
成功时为 0,否则为负错误代码
-
int drmm_writeback_connector_init(struct drm_device *dev, struct drm_writeback_connector *wb_connector, const struct drm_connector_funcs *con_funcs, struct drm_encoder *enc, const u32 *formats, int n_formats)¶
使用自定义编码器初始化回写连接器
参数
struct drm_device *dev
DRM 设备
struct drm_writeback_connector *wb_connector
要初始化的回写连接器
const struct drm_connector_funcs *con_funcs
连接器 funcs vtable
struct drm_encoder *enc
用于连接此回写连接器的编码器
const u32 *formats
回写引擎支持的像素格式数组
int n_formats
格式数组的长度
描述
此函数初始化回写连接器并注册其清理。
如果尚未创建,则此函数将创建特定于回写连接器的属性,将连接器初始化为 DRM_MODE_CONNECTOR_WRITEBACK 类型,并正确初始化属性值。
返回
成功时为 0,否则为负错误代码
-
void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector, struct drm_connector_state *conn_state)¶
排队一个回写作业以供稍后发出信号
参数
struct drm_writeback_connector *wb_connector
要排队作业的回写连接器
struct drm_connector_state *conn_state
包含要排队的作业的连接器状态
描述
此函数将 conn_state 中包含的作业添加到回写连接器的 job_queue。它获取回写作业的所有权并将 conn_state->writeback_job 设置为 NULL,因此在此函数返回后,调用者不得访问该作业。
驱动程序必须确保对于给定的回写连接器,作业的排队顺序与硬件完成的顺序完全相同(并通过 drm_writeback_signal_completion 发出信号)。
对于每次调用 drm_writeback_queue_job()
,必须正好调用一次 drm_writeback_signal_completion()
-
void drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector, int status)¶
发出回写作业完成的信号
参数
struct drm_writeback_connector *wb_connector
其作业已完成的回写连接器
int status
要在回写 out_fence 中设置的状态代码(成功时为 0)
描述
驱动程序应调用此函数以发出先前排队的回写作业完成的信号。应在硬件完成写入后尽快调用它,并且可以从中断上下文调用。驱动程序有责任确保对于给定的连接器,硬件以与排队顺序相同的顺序完成回写作业。
除非驱动程序持有对帧缓冲区的引用,否则在调用此函数后不得访问该帧缓冲区。
编码器抽象¶
编码器表示 CRTC(作为由 struct drm_crtc
表示的整体像素管线)和连接器(作为由 struct drm_connector
表示的通用接收器实体)之间的连接元素。编码器从 CRTC 获取像素数据,并将其转换为适合于任何连接的连接器的格式。编码器是暴露给用户空间的对象,最初允许用户空间推断克隆和连接器/CRTC 限制。不幸的是,几乎所有驱动程序都弄错了这一点,使得 uabi 几乎毫无用处。最重要的是,暴露的限制对于今天的硬件来说太简单了,推断限制的推荐方法是使用 atomic IOCTL 的 DRM_MODE_ATOMIC_TEST_ONLY 标志。
否则,编码器根本不用于 uapi 中(来自用户空间的任何 modeset 请求都直接将连接器与 CRTC 连接),因此驱动程序可以随意使用它们。Modeset 辅助库强烈使用编码器来促进代码共享。但是对于更复杂的设置,通常最好将共享代码移动到单独的 drm_bridge
中。与编码器相比,网桥的优势还在于它们纯粹是内部抽象,因为它们根本不暴露给用户空间。
使用 drm_encoder_init()
初始化编码器,并使用 drm_encoder_cleanup()
清理编码器。
编码器函数参考¶
-
struct drm_encoder_funcs¶
编码器控件
定义:
struct drm_encoder_funcs {
void (*reset)(struct drm_encoder *encoder);
void (*destroy)(struct drm_encoder *encoder);
int (*late_register)(struct drm_encoder *encoder);
void (*early_unregister)(struct drm_encoder *encoder);
void (*debugfs_init)(struct drm_encoder *encoder, struct dentry *root);
};
成员
重置
将编码器硬件和软件状态重置为关闭。此函数不是由核心直接调用的,而是仅通过
drm_mode_config_reset()
调用的。它不是仅出于历史原因的辅助钩子。destroy
清理编码器资源。这仅在驱动程序卸载时通过
drm_mode_config_cleanup()
调用,因为编码器无法在 DRM 中热插拔。late_register
此可选钩子可用于注册附加到编码器的其他用户空间接口。它在驱动程序加载序列的后期从
drm_dev_register()
调用。从此回调添加的所有内容都应在 early_unregister 回调中注销。返回
成功时为 0,失败时为负错误代码。
early_unregister
此可选钩子应用于注销从 late_register 附加到编码器的其他用户空间接口。它从
drm_dev_unregister()
调用,在驱动程序卸载序列的早期禁用用户空间访问,然后在数据结构被拆除之前。debugfs_init
允许编码器创建特定于编码器的 debugfs 文件。
描述
编码器位于 CRTC 和连接器之间。
-
struct drm_encoder¶
中央 DRM 编码器结构
定义:
struct drm_encoder {
struct drm_device *dev;
struct list_head head;
struct drm_mode_object base;
char *name;
int encoder_type;
unsigned index;
uint32_t possible_crtcs;
uint32_t possible_clones;
struct drm_crtc *crtc;
struct list_head bridge_chain;
const struct drm_encoder_funcs *funcs;
const struct drm_encoder_helper_funcs *helper_private;
struct dentry *debugfs_entry;
};
成员
dev
父 DRM 设备
head
列表管理
基本
基本 KMS 对象
名称
人类可读的名称,可以由驱动程序覆盖
encoder_type
drm_mode.h 中的 DRM_MODE_ENCODER_<foo> 类型之一。到目前为止,已定义以下编码器类型
用于 VGA 和 DVI-I/DVI-A 上的模拟的 DRM_MODE_ENCODER_DAC。
用于 DVI、HDMI 和(嵌入式)DisplayPort 的 DRM_MODE_ENCODER_TMDS。
用于显示面板的 DRM_MODE_ENCODER_LVDS,或者通常是具有专有并行连接器的任何面板。
用于电视输出(复合、S-视频、分量、SCART)的 DRM_MODE_ENCODER_TVDAC。
用于虚拟机的 DRM_MODE_ENCODER_VIRTUAL 显示器
用于使用 DSI 串行总线连接的面板的 DRM_MODE_ENCODER_DSI。
用于使用 DPI 并行总线连接的面板的 DRM_MODE_ENCODER_DPI。
用于允许多个 DP MST 流共享一个物理编码器的特殊伪编码器的 DRM_MODE_ENCODER_DPMST。
索引
模式配置列表中的位置,可以用作数组索引。它在编码器的生命周期内是不变的。
possible_crtcs
潜在 CRTC 绑定的位掩码,使用
drm_crtc_index()
作为位字段的索引。驱动程序必须在调用drm_dev_register()
之前,为该编码器可以连接到的所有drm_crtc
对象设置位。如果驱动程序中出现错误,您将收到 WARN。
请注意,由于 CRTC 对象无法热插拔,因此分配的索引是稳定的,因此在注册所有对象之前是已知的。
possible_clones
用于克隆的潜在同级编码器的位掩码,使用
drm_encoder_index()
作为位字段的索引。驱动程序必须在调用drm_dev_register()
之前,为可以与此编码器一起克隆drm_crtc
的所有drm_encoder
对象设置位。驱动程序也应设置表示编码器本身的位。克隆位的设置方式应为:当两个编码器可以在克隆配置中使用时,它们都应设置彼此的位。作为上述规则的例外,如果驱动程序未实现任何克隆,则可以将其 possible_clones 设置为 0。核心将通过设置编码器本身的位来自动修复此问题。
如果驱动程序中出现错误,您将收到 WARN。
请注意,由于编码器对象无法热插拔,因此分配的索引是稳定的,因此在注册所有对象之前是已知的。
crtc
当前绑定的 CRTC,仅对非原子驱动程序真正有意义。原子驱动程序应改为检查
drm_connector_state.crtc
。bridge_chain
附加到此编码器的网桥。驱动程序不得直接访问此字段。
funcs
控制函数,对于简单的托管编码器可以为 NULL
helper_private
中间层私有数据
debugfs_entry
此 CRTC 的 Debugfs 目录。
描述
CRTC 将像素驱动到编码器,编码器将其转换为适合于给定连接器或一组连接器的信号。
-
drmm_encoder_alloc¶
drmm_encoder_alloc (dev, type, member, funcs, encoder_type, name, ...)
分配并初始化编码器
参数
dev
drm 设备
type
包含 struct
drm_encoder
的结构体的类型member
type 中
drm_encoder
的名称funcs
此编码器的回调(可选)
encoder_type
用户可见的编码器类型
名称
编码器名称的 printf 样式格式字符串,如果为 NULL,则使用默认名称
...
可变参数
描述
分配并初始化编码器。编码器应作为驱动程序编码器对象的一部分进行子类化。清理通过使用 drmm_add_action()
注册 drm_encoder_cleanup()
自动处理。
drm_encoder_funcs.destroy 钩子必须为 NULL。
返回
指向新编码器的指针,如果失败,则为 ERR_PTR。
-
drmm_plain_encoder_alloc¶
drmm_plain_encoder_alloc (dev, funcs, encoder_type, name, ...)
分配并初始化编码器
参数
dev
drm 设备
funcs
此编码器的回调(可选)
encoder_type
用户可见的编码器类型
名称
编码器名称的 printf 样式格式字符串,如果为 NULL,则使用默认名称
...
可变参数
描述
这是 drmm_encoder_alloc()
的简化版本,它只分配并返回一个 struct drm_encoder
实例,没有子类化。
返回
指向新的 drm_encoder 结构的指针,如果失败则返回 ERR_PTR。
-
unsigned int drm_encoder_index(const struct drm_encoder *encoder)¶
查找已注册编码器的索引
参数
const struct drm_encoder *encoder
要查找索引的编码器
描述
给定一个已注册的编码器,返回该编码器在 DRM 设备编码器列表中的索引。
-
u32 drm_encoder_mask(const struct drm_encoder *encoder)¶
查找已注册编码器的掩码
参数
const struct drm_encoder *encoder
要查找掩码的编码器
描述
给定一个已注册的编码器,返回该编码器在 encoder 的 possible_clones 字段中的掩码位。
-
bool drm_encoder_crtc_ok(struct drm_encoder *encoder, struct drm_crtc *crtc)¶
给定的 crtc 能否驱动给定的编码器?
参数
struct drm_encoder *encoder
要测试的编码器
struct drm_crtc *crtc
要测试的 crtc
描述
如果 **encoder** 不能被 **crtc** 驱动,则返回 false,否则返回 true。
-
struct drm_encoder *drm_encoder_find(struct drm_device *dev, struct drm_file *file_priv, uint32_t id)¶
查找一个
drm_encoder
参数
struct drm_device *dev
DRM 设备
struct drm_file *file_priv
用于检查租赁的 DRM 文件。
uint32_t id
编码器 id
描述
返回具有 **id** 的编码器,如果不存在则返回 NULL。 围绕 drm_mode_object_find()
的简单包装器。
-
drm_for_each_encoder_mask¶
drm_for_each_encoder_mask (encoder, dev, encoder_mask)
迭代由位掩码指定的编码器
参数
encoder
循环游标
dev
DRM 设备
encoder_mask
编码器索引的位掩码
描述
迭代由位掩码指定的所有编码器。
-
drm_for_each_encoder¶
drm_for_each_encoder (encoder, dev)
迭代所有编码器
参数
encoder
循环游标
dev
DRM 设备
描述
迭代 **dev** 的所有编码器。
-
int drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, int encoder_type, const char *name, ...)¶
初始化一个预先分配的编码器
参数
struct drm_device *dev
drm 设备
struct drm_encoder *encoder
要初始化的编码器
const struct drm_encoder_funcs *funcs
此编码器的回调
int encoder_type
用户可见的编码器类型
const char *name
编码器名称的 printf 样式格式字符串,如果为 NULL,则使用默认名称
...
可变参数
描述
初始化一个预先分配的编码器。 编码器应作为驱动程序编码器对象的一部分进行子类化。 在驱动程序卸载时,驱动程序的 drm_encoder_funcs.destroy
钩子应调用 drm_encoder_cleanup()
和 kfree()
编码器结构。 编码器结构不应使用 devm_kzalloc() 分配。
注意
考虑使用 drmm_encoder_alloc()
或 drmm_encoder_init()
而不是 drm_encoder_init()
,以便让 DRM 管理的资源基础结构处理清理和释放。
返回
成功时为零,失败时为错误代码。
-
void drm_encoder_cleanup(struct drm_encoder *encoder)¶
清理已初始化的编码器
参数
struct drm_encoder *encoder
要清理的编码器
描述
清理编码器,但不释放对象。
-
int drmm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, int encoder_type, const char *name, ...)¶
初始化一个预先分配的编码器
参数
struct drm_device *dev
drm 设备
struct drm_encoder *encoder
要初始化的编码器
const struct drm_encoder_funcs *funcs
此编码器的回调(可选)
int encoder_type
用户可见的编码器类型
const char *name
编码器名称的 printf 样式格式字符串,如果为 NULL,则使用默认名称
...
可变参数
描述
初始化一个预先分配的编码器。 编码器应作为驱动程序编码器对象的一部分进行子类化。 通过使用 drmm_add_action()
注册 drm_encoder_cleanup()
,可自动处理清理工作。 编码器结构应使用 drmm_kzalloc()
进行分配。
drm_encoder_funcs.destroy 钩子必须为 NULL。
返回
成功时为零,失败时为错误代码。
KMS 锁定¶
随着 KMS 转向更细粒度的锁定和原子 ioctl,用户空间可以间接控制锁定顺序,因此有必要使用 ww_mutex
和 acquire-contexts 来避免死锁。 但是由于锁定在驱动程序代码中分布得更广泛,因此我们希望从 acquire-ctx 中获得一些额外的实用程序/跟踪。 这由 struct drm_modeset_lock
和 struct drm_modeset_acquire_ctx
提供。
有关 ww_mutex
的基本原理,请参见:Wound/Wait 防死锁互斥锁设计
基本使用模式是
drm_modeset_acquire_init(ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE)
retry:
foreach (lock in random_ordered_set_of_locks) {
ret = drm_modeset_lock(lock, ctx)
if (ret == -EDEADLK) {
ret = drm_modeset_backoff(ctx);
if (!ret)
goto retry;
}
if (ret)
goto out;
}
... do stuff ...
out:
drm_modeset_drop_locks(ctx);
drm_modeset_acquire_fini(ctx);
为方便起见,当需要通过 drm_modeset_lock_all_ctx()
获取所有 modeset 锁时,此控制流在 DRM_MODESET_LOCK_ALL_BEGIN()
和 DRM_MODESET_LOCK_ALL_END()
中实现。
如果只需要单个 modeset 锁,则不需要 struct drm_modeset_acquire_ctx
,并且可以通过在 drm_modeset_lock()
调用中传递 NULL 而不是 ctx 或调用 drm_modeset_lock_single_interruptible()
来简化锁定。 要在之后解锁,请调用 drm_modeset_unlock()
。
除了使用 ww_mutex
的这些每个对象锁之外,还有一个总体的 drm_mode_config.mutex
,用于保护其他所有内容。 主要这意味着连接器的探测状态,并防止热插拔添加/删除连接器。
最后,还有一堆专用锁来保护 drm 核心内部列表和查找数据结构。
-
struct drm_modeset_acquire_ctx¶
锁定上下文(请参阅 ww_acquire_ctx)
定义:
struct drm_modeset_acquire_ctx {
struct ww_acquire_ctx ww_ctx;
struct drm_modeset_lock *contended;
depot_stack_handle_t stack_depot;
struct list_head locked;
bool trylock_only;
bool interruptible;
};
成员
ww_ctx
基本获取 ctx
contended
内部用于 -EDEADLK 处理
stack_depot
内部用于争用调试
locked
持有的锁的列表
trylock_only
原子上下文/panic 通知程序中使用的 tryLock 模式
interruptible
是否应使用可中断锁定。
描述
争用一组锁的每个线程都必须使用一个 acquire ctx。 并且如果任何锁 fxn 返回 -EDEADLK,它必须退避并重试。
-
struct drm_modeset_lock¶
用于锁定 modeset 资源。
定义:
struct drm_modeset_lock {
struct ww_mutex mutex;
struct list_head head;
};
成员
mutex
资源锁定
head
用于在作为原子更新的一部分时,保持其在
drm_atomi_state.locked
列表中的位置
描述
用于锁定 CRTC 和其他 modeset 资源。
-
void drm_modeset_lock_fini(struct drm_modeset_lock *lock)¶
清理锁
参数
struct drm_modeset_lock *lock
要清理的锁
-
bool drm_modeset_is_locked(struct drm_modeset_lock *lock)¶
参数
struct drm_modeset_lock *lock
要检查的锁
-
void drm_modeset_lock_assert_held(struct drm_modeset_lock *lock)¶
等同于 lockdep_assert_held()
参数
struct drm_modeset_lock *lock
要检查的锁
-
DRM_MODESET_LOCK_ALL_BEGIN¶
DRM_MODESET_LOCK_ALL_BEGIN (dev, ctx, flags, ret)
用于获取 modeset 锁的帮助程序
参数
dev
drm 设备
ctx
本地 modeset 获取上下文,将被取消引用
标志
要传递给
drm_modeset_acquire_init()
的 DRM_MODESET_ACQUIRE_* 标志ret
用于跟踪错误状态的本地 ret/err/etc 变量
描述
使用这些宏可简化使用本地上下文获取所有 modeset 锁。 这样做的好处是减少了样板代码,而且还正确地检查了返回值(如果适用)。
在 BEGIN 和 END 之间运行的任何代码都将持有 modeset 锁。
这必须与 DRM_MODESET_LOCK_ALL_END()
配对。 我们将在死锁和错误条件下的标签之间来回跳转。
驱动程序可以获取额外的 modeset 锁。 如果任何锁获取失败,则控制流需要跳转到 DRM_MODESET_LOCK_ALL_END()
,其中 **ret** 参数包含 drm_modeset_lock()
的返回值。
返回
紧接在 DRM_MODESET_LOCK_ALL_BEGIN()
之后的 ret 的唯一可能值为 0,因此无需进行错误检查
-
DRM_MODESET_LOCK_ALL_END¶
DRM_MODESET_LOCK_ALL_END (dev, ctx, ret)
用于释放和清理 modeset 锁的帮助程序
参数
dev
drm 设备
ctx
本地 modeset 获取上下文,将被取消引用
ret
用于跟踪错误状态的本地 ret/err/etc 变量
描述
与 DRM_MODESET_LOCK_ALL_BEGIN()
的另一面。 如果 ret 为 -EDEADLK,它将弹回 BEGIN。
重要的是,BEGIN 和 END 使用相同的 ret 变量,以便正确处理死锁条件。
返回
除非在输入时为 -EDEADLK,否则 ret 将保持不变。 这意味着如果成功获取锁,ret 将是代码设置的任何值。 如果获取或退避时出现死锁或其他失败,则 ret 将设置为该失败。 在这两种情况下,都不会运行 BEGIN/END 之间的代码,因此失败将反映无法获取锁。
-
void drm_modeset_lock_all(struct drm_device *dev)¶
获取所有 modeset 锁
参数
struct drm_device *dev
DRM 设备
描述
此函数获取所有模式设置锁,适用于尚未实现更细粒度方案的情况。必须通过调用 drm_modeset_unlock_all()
函数来释放锁。
此函数已弃用。它分配一个锁获取上下文并将其存储在 drm_device.mode_config
中。这有助于转换现有代码,因为它消除了手动处理获取上下文的需要,但它也很脆弱,因为上下文是全局的,必须注意不要嵌套调用。新代码应使用 drm_modeset_lock_all_ctx()
函数并显式传递上下文。
-
void drm_modeset_unlock_all(struct drm_device *dev)¶
释放所有模式设置锁
参数
struct drm_device *dev
DRM 设备
描述
此函数释放之前调用 drm_modeset_lock_all()
函数所获取的所有模式设置锁。
此函数已弃用。它使用存储在 drm_device.mode_config
中的锁获取上下文。这有助于转换现有代码,因为它消除了手动处理获取上下文的需要,但它也很脆弱,因为上下文是全局的,必须注意不要嵌套调用。新代码应将获取上下文直接传递给 drm_modeset_drop_locks()
函数。
-
void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)¶
检查是否所有模式设置锁都已锁定
参数
struct drm_device *dev
设备
描述
可用作调试断言。
-
void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx, uint32_t flags)¶
初始化获取上下文
参数
struct drm_modeset_acquire_ctx *ctx
获取上下文
uint32_t flags
0 或
DRM_MODESET_ACQUIRE_INTERRUPTIBLE
描述
当将 DRM_MODESET_ACQUIRE_INTERRUPTIBLE
传递给 flags 时,所有对 drm_modeset_lock()
的调用都将执行可中断等待。
-
void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx)¶
清理获取上下文
参数
struct drm_modeset_acquire_ctx *ctx
获取上下文
-
void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx)¶
释放所有锁
参数
struct drm_modeset_acquire_ctx *ctx
获取上下文
描述
释放当前针对此获取上下文持有的所有锁。
-
int drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx)¶
死锁避免退避
参数
struct drm_modeset_acquire_ctx *ctx
获取上下文
描述
如果检测到死锁(即 drm_modeset_lock()
返回 -EDEADLK),则必须调用此函数以释放当前持有的所有锁并阻塞,直到争用的锁变为可用。
此函数在成功时返回 0,如果此上下文使用 DRM_MODESET_ACQUIRE_INTERRUPTIBLE
初始化且等待已中断,则返回 -ERESTARTSYS。
-
void drm_modeset_lock_init(struct drm_modeset_lock *lock)¶
初始化锁
参数
struct drm_modeset_lock *lock
要初始化的锁
-
int drm_modeset_lock(struct drm_modeset_lock *lock, struct drm_modeset_acquire_ctx *ctx)
获取模式设置锁
参数
struct drm_modeset_lock *lock
要获取的锁
struct drm_modeset_acquire_ctx *ctx
获取上下文
描述
如果 ctx 不为 NULL,则使用其 ww 获取上下文,并且该锁将由上下文跟踪,并且可以通过调用 drm_modeset_drop_locks()
来释放。如果返回 -EDEADLK,则表示检测到死锁情况,并且在没有首先调用 drm_modeset_backoff()
的情况下尝试获取更多锁是错误的。
如果 ctx 不为 NULL 且使用 DRM_MODESET_ACQUIRE_INTERRUPTIBLE
初始化,则此函数将在中断时失败并返回 -ERESTARTSYS。
如果 ctx 为 NULL,则函数调用行为类似于正常的、不可中断的非嵌套 mutex_lock()
调用。
-
int drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock)¶
获取单个模式设置锁
参数
struct drm_modeset_lock *lock
要获取的锁
描述
此函数的作用类似于具有 NULL 上下文的 drm_modeset_lock()
,但执行可中断等待。
此函数在成功时返回 0,在中断时返回 -ERESTARTSYS。
-
void drm_modeset_unlock(struct drm_modeset_lock *lock)¶
释放模式设置锁
参数
struct drm_modeset_lock *lock
要释放的锁
-
int drm_modeset_lock_all_ctx(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx)¶
获取所有 modeset 锁
参数
struct drm_device *dev
DRM 设备
struct drm_modeset_acquire_ctx *ctx
锁获取上下文
描述
此函数获取所有模式设置锁,适用于尚未实现更细粒度方案的情况。
与 drm_modeset_lock_all()
不同,它不获取 drm_mode_config.mutex
,因为模式设置状态更改不需要该锁。也需要获取该锁的调用者需要在获取上下文 ctx 之外执行此操作。
使用此函数获取的锁应通过在 ctx 上调用 drm_modeset_drop_locks()
函数来释放。
另请参见:DRM_MODESET_LOCK_ALL_BEGIN()
和 DRM_MODESET_LOCK_ALL_END()
返回
成功时返回 0,失败时返回负错误代码。
KMS 属性¶
文档的此部分主要针对用户空间开发人员。有关驱动程序 API,请参见其他部分。
要求¶
KMS 驱动程序可能需要添加额外的属性以支持新功能。驱动程序中引入的每个新属性除了上面提到的属性外,还需要满足一些要求
它必须是标准化的,并记录
完整的、准确的名称字符串;
如果属性是枚举,则所有有效的名称字符串;
接受哪些值,以及这些值的含义;
属性的作用以及如何使用它;
属性如何与其他现有属性交互。
它必须在核心代码中提供一个通用助手,以便在它附加到的对象上注册该属性。
其内容必须由核心解码,并在对象的关联状态结构中提供。这包括驱动程序可能想要预计算的任何内容,例如平面的 struct drm_clip_rect。
其初始状态必须与引入属性之前的行为匹配。这可能是与硬件执行的操作相匹配的固定值,或者可能是从固件在启动期间将系统留在的状态继承而来的。
在合理的情况下,必须提交 IGT 测试。
由于历史原因,存在非标准的、特定于驱动程序的属性。如果 KMS 驱动程序想要添加对其中一个属性的支持,则尽可能适用新属性的要求。此外,记录的行为必须与现有属性的实际语义相匹配,以确保兼容性。首次添加该属性的驱动程序的开发人员应协助完成这些任务,并且必须确认(ACK)记录的行为(如果可能)。
属性类型和 Blob 属性支持¶
由 drm_property
表示的属性用于扩展暴露给用户空间的模式设置接口。对于原子模式设置 IOCTL,属性甚至是将有关所需的新模式设置配置的元数据从用户空间传输到内核的唯一方法。属性具有明确定义的值范围,该范围由 drm 核心强制执行。有关不同属性类型和范围的概述,请参见 struct drm_property
的 flags 成员的文档。
属性不直接存储当前值,而是需要通过使用 drm_object_attach_property()
将它们附加到 drm_mode_object
来实例化。
属性值只有 64 位。为了支持更大的数据堆(例如 gamma 表、颜色校正矩阵或大型结构),属性可以指向具有该附加数据的 drm_property_blob
。
属性由其符号名称定义,用户空间必须维护从这些名称到原子 IOCTL 和 get/set 属性 IOCTL 中使用的属性 ID 的每个对象的映射。
-
struct drm_property_enum¶
枚举的符号值
定义:
struct drm_property_enum {
uint64_t value;
struct list_head head;
char name[DRM_PROP_NAME_LEN];
};
成员
值
此枚举条目的数字属性值
如果属性的类型为
DRM_MODE_PROP_BITMASK
,则 value 存储一个位移,而不是一个位掩码。换句话说,如果属性的值中设置了位编号 value,则启用枚举条目。此枚举条目的位掩码为1 << value
。head
枚举值列表,链接到
drm_property.enum_list
名称
枚举的符号名称
描述
对于枚举和位掩码属性,此结构存储每个值的符号解码。例如,这用于旋转属性。
-
struct drm_property¶
模式设置对象属性
定义:
struct drm_property {
struct list_head head;
struct drm_mode_object base;
uint32_t flags;
char name[DRM_PROP_NAME_LEN];
uint32_t num_values;
uint64_t *values;
struct drm_device *dev;
struct list_head enum_list;
};
成员
head
每个设备的属性列表,用于清理。
基本
基本 KMS 对象
标志
属性标志和类型。属性需要是以下类型之一
- DRM_MODE_PROP_RANGE
范围属性报告其最小和最大允许的无符号值。KMS 核心验证应用程序设置的值是否在该范围内。范围是无符号的。范围属性使用
drm_property_create_range()
创建。- DRM_MODE_PROP_SIGNED_RANGE
范围属性报告其最小和最大允许的无符号值。KMS 核心验证应用程序设置的值是否在该范围内。范围是有符号的。范围属性使用
drm_property_create_signed_range()
创建。- DRM_MODE_PROP_ENUM
枚举属性采用一个数字值,该值范围从 0 到由属性定义的枚举值的数量减 1,并将一个自由格式的字符串名称与每个值关联。应用程序可以检索定义的键值对列表,并使用数值来获取和设置属性实例值。枚举属性使用
drm_property_create_enum()
创建。- DRM_MODE_PROP_BITMASK
位掩码属性是枚举属性,它还会将所有枚举值限制在 0..63 范围内。位掩码属性实例值组合由属性定义的一个或多个枚举位。位掩码属性使用
drm_property_create_bitmask()
创建。- DRM_MODE_PROP_OBJECT
对象属性用于链接模式设置对象。这广泛用于原子支持中,通过将
drm_framebuffer
链接到drm_plane
、将drm_plane
链接到drm_crtc
以及将drm_connector
链接到drm_crtc
来创建显示管道。对象属性只能链接到特定类型的drm_mode_object
,此限制由核心强制执行。对象属性使用drm_property_create_object()
创建。对象属性的工作方式类似于 blob 属性,但方式更通用。它们仅限于原子驱动程序,并且必须设置 DRM_MODE_PROP_ATOMIC 标志。
- DRM_MODE_PROP_BLOB
Blob 属性存储没有任何格式限制的二进制 blob。二进制 blob 创建为 KMS 独立对象,blob 属性实例值存储其关联的 blob 对象的 ID。Blob 属性通过使用 DRM_MODE_PROP_BLOB 作为类型调用
drm_property_create()
创建。用于包含 blob 数据的实际 blob 对象使用
drm_property_create_blob()
创建,或通过相应的 IOCTL 创建。除了只接受 blob 对象的内置限制外,blob 属性的工作方式与对象属性完全相同。blob 属性存在的唯一原因是与现有用户空间的向后兼容性。
此外,属性可以具有以下标志的任意组合
- DRM_MODE_PROP_ATOMIC
为编码原子模式设置状态的属性设置。此类属性不向旧版用户空间公开。
- DRM_MODE_PROP_IMMUTABLE
为用户空间无法更改其值的属性设置。允许内核更新这些属性的值。这通常用于向用户空间公开探测状态,例如 EDID 或 DP MST sink 上的连接器路径属性。内核可以通过调用
drm_object_property_set_value()
来更新不可变属性的值。
名称
属性的符号名称
num_values
values 数组的大小。
values
具有属性限制和值的数组。这些限制的解释取决于 flags 的类型。
dev
DRM 设备
enum_list
drm_prop_enum_list
结构的列表,其中包含枚举和位掩码值的符号名称。
描述
此结构表示一个模式集对象属性。它将属性的名称与允许的值集合结合在一起。这意味着当驱动程序想要在不同的对象上使用具有相同名称的属性,但具有不同的值范围时,它必须为每个对象创建一个属性。一个例子是drm_plane
的旋转,例如,当主平面不能旋转时。但是,如果名称和值范围都匹配,则可以为同一对象多次实例化相同的属性结构。用户空间必须能够处理这种情况,并且不能假设相同的符号属性在所有模式集对象上都具有相同的模式集对象 ID。
属性由特殊的函数创建,详细说明在 flags 结构成员中。
要实际公开一个属性,必须使用drm_object_attach_property()
将其附加到每个对象。目前,属性只能附加到drm_connector
、drm_crtc
和drm_plane
。
属性也被用作原子 IOCTL 的通用元数据传输。在传统的模式集 IOCTL 中直接在结构中设置的所有内容(例如平面源或目标窗口,或例如与 CRTC 的链接)都作为设置了 DRM_MODE_PROP_ATOMIC 标志的属性公开。
-
struct drm_property_blob¶
drm_property
的 Blob 数据
定义:
struct drm_property_blob {
struct drm_mode_object base;
struct drm_device *dev;
struct list_head head_global;
struct list_head head_file;
size_t length;
void *data;
};
成员
基本
基本 KMS 对象
dev
DRM 设备
head_global
在
drm_mode_config.property_blob_list
中的全局 blob 列表上的条目。head_file
在
drm_file.blobs
列表中的每个文件的 blob 列表上的条目。length
blob 的大小(以字节为单位),在对象的整个生命周期内是不变的
data
实际数据,嵌入在此结构的末尾
描述
Blob 用于存储比drm_property
可用的 64 位更大的值。
Blob 使用drm_property_blob_get()
和drm_property_blob_put()
进行引用计数。它们使用drm_property_create_blob()
创建。
-
bool drm_property_type_is(struct drm_property *property, uint32_t type)¶
检查属性的类型
参数
struct drm_property *property
要检查的属性
uint32_t type
要比较的属性类型
描述
这是一个辅助函数,因为属性类型的 uapi 编码由于历史原因有点特殊。
-
struct drm_property *drm_property_find(struct drm_device *dev, struct drm_file *file_priv, uint32_t id)¶
查找属性对象
参数
struct drm_device *dev
DRM 设备
struct drm_file *file_priv
用于检查租赁的 DRM 文件。
uint32_t id
属性对象 ID
描述
此函数查找由 ID 指定的属性对象并返回它。
-
struct drm_property *drm_property_create(struct drm_device *dev, u32 flags, const char *name, int num_values)¶
创建一个新的属性类型
参数
struct drm_device *dev
drm 设备
u32 flags
指定属性类型的标志
const char *name
属性的名称
int num_values
预定义值的数量
描述
这将创建一个新的通用 drm 属性,然后可以使用drm_object_attach_property()
将其附加到 drm 对象。返回的属性对象必须使用drm_property_destroy()
释放,这在调用drm_mode_config_cleanup()
时自动完成。
返回
成功时指向新创建的属性的指针,失败时为 NULL。
-
struct drm_property *drm_property_create_enum(struct drm_device *dev, u32 flags, const char *name, const struct drm_prop_enum_list *props, int num_values)¶
创建一个新的枚举属性类型
参数
struct drm_device *dev
drm 设备
u32 flags
指定属性类型的标志
const char *name
属性的名称
const struct drm_prop_enum_list *props
带有属性值的枚举列表
int num_values
预定义值的数量
描述
这将创建一个新的通用 drm 属性,然后可以使用drm_object_attach_property()
将其附加到 drm 对象。返回的属性对象必须使用drm_property_destroy()
释放,这在调用drm_mode_config_cleanup()
时自动完成。
用户空间只允许为枚举属性设置一个预定义的值。
返回
成功时指向新创建的属性的指针,失败时为 NULL。
-
struct drm_property *drm_property_create_bitmask(struct drm_device *dev, u32 flags, const char *name, const struct drm_prop_enum_list *props, int num_props, uint64_t supported_bits)¶
创建一个新的位掩码属性类型
参数
struct drm_device *dev
drm 设备
u32 flags
指定属性类型的标志
const char *name
属性的名称
const struct drm_prop_enum_list *props
带有属性位标志的枚举列表
int num_props
props 数组的大小
uint64_t supported_bits
所有支持的枚举值的位掩码
描述
这将创建一个新的位掩码 drm 属性,然后可以使用drm_object_attach_property()
将其附加到 drm 对象。返回的属性对象必须使用drm_property_destroy()
释放,这在调用drm_mode_config_cleanup()
时自动完成。
与普通枚举属性相比,用户空间允许设置预定义的属性位标志值的任何或在一起的组合
返回
成功时指向新创建的属性的指针,失败时为 NULL。
-
struct drm_property *drm_property_create_range(struct drm_device *dev, u32 flags, const char *name, uint64_t min, uint64_t max)¶
创建一个新的无符号范围属性类型
参数
struct drm_device *dev
drm 设备
u32 flags
指定属性类型的标志
const char *name
属性的名称
uint64_t min
属性的最小值
uint64_t max
属性的最大值
描述
这将创建一个新的通用 drm 属性,然后可以使用drm_object_attach_property()
将其附加到 drm 对象。返回的属性对象必须使用drm_property_destroy()
释放,这在调用drm_mode_config_cleanup()
时自动完成。
用户空间允许设置 (min, max) 范围内的任何无符号整数值,包括端点值。
返回
成功时指向新创建的属性的指针,失败时为 NULL。
-
struct drm_property *drm_property_create_signed_range(struct drm_device *dev, u32 flags, const char *name, int64_t min, int64_t max)¶
创建一个新的有符号范围属性类型
参数
struct drm_device *dev
drm 设备
u32 flags
指定属性类型的标志
const char *name
属性的名称
int64_t min
属性的最小值
int64_t max
属性的最大值
描述
这将创建一个新的通用 drm 属性,然后可以使用drm_object_attach_property()
将其附加到 drm 对象。返回的属性对象必须使用drm_property_destroy()
释放,这在调用drm_mode_config_cleanup()
时自动完成。
用户空间允许设置 (min, max) 范围内的任何有符号整数值,包括端点值。
返回
成功时指向新创建的属性的指针,失败时为 NULL。
-
struct drm_property *drm_property_create_object(struct drm_device *dev, u32 flags, const char *name, uint32_t type)¶
创建一个新的对象属性类型
参数
struct drm_device *dev
drm 设备
u32 flags
指定属性类型的标志
const char *name
属性的名称
uint32_t type
来自 DRM_MODE_OBJECT_* 定义的对象类型
描述
这将创建一个新的通用 drm 属性,然后可以使用drm_object_attach_property()
将其附加到 drm 对象。返回的属性对象必须使用drm_property_destroy()
释放,这在调用drm_mode_config_cleanup()
时自动完成。
用户空间只允许将其设置为给定 type 的任何属性值。仅对强制执行的原子属性有用。
返回
成功时指向新创建的属性的指针,失败时为 NULL。
-
struct drm_property *drm_property_create_bool(struct drm_device *dev, u32 flags, const char *name)¶
创建一个新的布尔属性类型
参数
struct drm_device *dev
drm 设备
u32 flags
指定属性类型的标志
const char *name
属性的名称
描述
这将创建一个新的通用 drm 属性,然后可以使用drm_object_attach_property()
将其附加到 drm 对象。返回的属性对象必须使用drm_property_destroy()
释放,这在调用drm_mode_config_cleanup()
时自动完成。
这是作为只有 {0, 1} 作为有效值的范围属性实现的。
返回
成功时指向新创建的属性的指针,失败时为 NULL。
-
int drm_property_add_enum(struct drm_property *property, uint64_t value, const char *name)¶
向枚举属性添加一个可能的值
参数
struct drm_property *property
要更改的枚举属性
uint64_t value
新枚举的值
const char *name
新枚举的符号名称
描述
此函数向属性添加枚举。
它的使用已被弃用,驱动程序应该使用更具体的辅助函数来直接创建带有所有已附加枚举的属性。
返回
成功时为零,失败时为错误代码。
-
void drm_property_destroy(struct drm_device *dev, struct drm_property *property)¶
销毁一个 drm 属性
参数
struct drm_device *dev
drm 设备
struct drm_property *property
要销毁的属性
描述
此函数释放一个属性,包括任何附加的资源,如枚举值。
-
struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, size_t length, const void *data)¶
创建新的 blob 属性
参数
struct drm_device *dev
要为其创建属性的 DRM 设备
size_t length
要为 blob 数据分配的长度
const void *data
如果指定,将数据复制到 blob 中
描述
为指定的 DRM 设备创建一个新的 blob 属性,可以选择复制数据。请注意,blob 属性应该是不可变的,因此数据必须在 blob 用作任何属性的值之前填充。
返回
成功时,具有单个引用计数的新 blob 属性,失败时为 ERR_PTR 值。
-
void drm_property_blob_put(struct drm_property_blob *blob)¶
释放 blob 属性引用
参数
struct drm_property_blob *blob
DRM blob 属性
描述
释放对 blob 属性的引用。可能会释放对象。
-
struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)¶
获取 blob 属性引用
参数
struct drm_property_blob *blob
DRM blob 属性
描述
获取现有 blob 属性的引用。返回 blob,允许将其用作赋值的简写。
-
struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev, uint32_t id)¶
查找 blob 属性并获取引用
参数
struct drm_device *dev
drm 设备
uint32_t id
blob 属性的 ID
描述
如果成功,则会获取对 blob 属性的额外引用。调用者需要确保最终再次取消引用返回的属性,使用 drm_property_blob_put()
。
返回
失败时为 NULL,成功时为指向 blob 的指针。
-
int drm_property_replace_global_blob(struct drm_device *dev, struct drm_property_blob **replace, size_t length, const void *data, struct drm_mode_object *obj_holds_id, struct drm_property *prop_holds_id)¶
替换现有 blob 属性
参数
struct drm_device *dev
drm 设备
struct drm_property_blob **replace
要替换的 blob 属性指针的位置
size_t length
新 blob 的数据长度,如果无数据则为 0
const void *data
新 blob 的内容,如果无数据则为 NULL
struct drm_mode_object *obj_holds_id
可选对象,用于属性保存 blob ID
struct drm_property *prop_holds_id
可选属性,用于保存 blob ID 返回 成功时为 0,失败时返回错误
描述
此函数将替换 blob 列表中的全局属性,可以选择更新保存该属性 ID 的属性。
如果 length 为 0 或 data 为 NULL,则不会创建新的 blob,并且保存属性(如果指定)将设置为 0。
假定对 replace 指针的访问受到调用者的保护,例如,通过持有其父对象的相应模式设置对象锁。
例如,drm_connector 具有一个“PATH”属性,该属性包含具有 MST 路径信息的 blob 属性的 ID。使用 replace 指向连接器的 path_blob_ptr、为新路径信息设置的 length 和 data、obj_holds_id 设置为连接器的基本对象以及 prop_holds_id 设置为路径属性名称调用此函数将执行完全原子的更新。对 path_blob_ptr 的访问受到调用者持有连接器上的锁的保护。
-
bool drm_property_replace_blob(struct drm_property_blob **blob, struct drm_property_blob *new_blob)¶
替换 blob 属性
参数
struct drm_property_blob **blob
指向要替换的成员 blob 的指针
struct drm_property_blob *new_blob
用于替换的新 blob
返回
如果 blob 实际上已被替换,则为 true。
-
int drm_property_replace_blob_from_id(struct drm_device *dev, struct drm_property_blob **blob, uint64_t blob_id, ssize_t expected_size, ssize_t expected_elem_size, bool *replaced)¶
替换 blob 属性并获取引用
参数
struct drm_device *dev
DRM 设备
struct drm_property_blob **blob
指向要替换的成员 blob 的指针
uint64_t blob_id
用于替换的新 blob 的 ID
ssize_t expected_size
blob 属性的预期大小
ssize_t expected_elem_size
blob 属性中元素的预期大小
bool *replaced
如果 blob 实际上已被替换
描述
从 ID 查找新 blob,获取其引用,检查 blob 及其元素的预期大小,然后用新 blob 替换旧 blob。告知替换操作是否成功。
返回
如果 blob 实际上已被替换,则为 true。如果未找到新 blob 或大小不匹配,则为 -EINVAL。
标准连接器属性¶
DRM 连接器具有一些标准化的属性
- EDID
Blob 属性,其中包含从接收器读取的当前 EDID。这对于解析接收器识别信息(如供应商、型号和序列号)很有用。驱动程序应通过调用
drm_connector_update_edid_property()
来更新此属性,通常在使用drm_add_edid_modes()
解析 EDID 后。用户空间无法更改此属性。用户空间不应解析 EDID 以获取通过其他 KMS 属性公开的信息(因为内核可能会对 EDID 应用限制、怪癖或修复)。例如,用户空间不应尝试从 EDID 解析模式列表。
- DPMS
用于设置连接器的电源状态的旧属性。对于原子驱动程序,仅提供此属性以向后兼容现有驱动程序,它会重新映射到控制连接器链接到的 CRTC 上的“ACTIVE”属性。驱动程序绝不应直接设置此属性,它由 DRM 核心通过调用
drm_connector_funcs.dpms
回调来处理。对于原子驱动程序,到“ACTIVE”属性的重新映射在 DRM 核心中实现。在原子驱动程序上,任何值没有更改的 DPMS setproperty ioctl 都会完全跳过,否则将发生完全原子提交。在旧驱动程序上,确切的行为是驱动程序特定的。
请注意,此属性无法通过 MODE_ATOMIC ioctl 设置,用户空间必须改为使用 CRTC 上的“ACTIVE”。
警告
对于也在旧驱动程序上运行的用户空间,“DPMS”语义要复杂得多。首先,用户空间不能依赖于 GETCONNECTOR 返回的“DPMS”值来实际反映现实,因为许多驱动程序无法更新它。对于原子驱动程序,这在
drm_atomic_helper_update_legacy_modeset_state()
中处理。第二个问题是,DPMS 状态仅在连接器连接到 CRTC 时才明确定义。在原子中,DRM 核心强制在这种情况下“ACTIVE”为关闭,对于“DPMS”不存在此类检查。
最后,当使用旧的 SETCONFIG ioctl 启用输出时,“DPMS”将被强制为 ON。但请参见上文,这可能不会反映在旧驱动程序上的软件值中。
总结:仅在已知连接器已启用时才设置“DPMS”,假定成功的 SETCONFIG 调用也会将“DPMS”设置为 on,并且永远不要读回“DPMS”的值,因为它可能不正确。
- PATH
连接器路径属性,用于标识此接收器的物理连接方式。由 DP MST 使用。这应通过调用
drm_connector_set_path_property()
来设置,在 DP MST 的情况下,使用 MST 管理器创建的路径属性。用户空间无法更改此属性。在 DP MST 的情况下,该属性的格式为
mst:<parent>-<ports>
,其中<parent>
是父连接器的 KMS 对象 ID,<ports>
是以连字符分隔的 DP MST 端口号列表。请注意,KMS 对象 ID 不能保证在重新启动后保持稳定。- TILE
连接器平铺组属性,用于指示一组 DRM 连接器如何组合成一个逻辑屏幕。这由高分辨率外部屏幕(通常仅使用一根电缆,但公开多个 DP MST 接收器)或高分辨率集成面板(如双链路 DSI)使用,这些面板未进行基因锁定。请注意,对于基因锁定的平铺面板,如双链路 LVDS 或双链路 DSI,驱动程序应尝试不公开平铺并虚拟化
drm_crtc
和drm_plane
(如果需要)。驱动程序应使用drm_connector_set_tile_property()
更新此值。用户空间无法更改此属性。- link-status
连接器链接状态属性,用于指示链接的状态。链接状态的默认值为“GOOD”。如果在模式设置期间或之后发生某些错误,则内核驱动程序可能会将其设置为“BAD”并发出热插拔 uevent。驱动程序应使用
drm_connector_set_link_status_property()
更新此值。当用户空间接收到热插拔 uevent 并检测到“BAD”链接状态时,接收器不再接收像素(例如,屏幕完全变黑)。可用模式的列表可能已更改。用户空间应选择一种新模式(如果当前模式已消失)并执行新的模式设置,并将链接状态设置为“GOOD”以重新启用连接器。
如果多个连接器共享同一个 CRTC,并且其中一个连接器获得“BAD”链接状态,则其他连接器不受影响(即,接收器仍继续接收像素)。
当用户空间对具有“BAD”链接状态的连接器执行原子提交而不将该属性重置为“GOOD”时,接收器可能仍然不接收像素。当用户空间执行将链接状态属性重置为“GOOD”的原子提交而不设置 ALLOW_MODESET 标志时,它可能会失败,因为需要模式设置。
用户空间只能将链接状态更改为“GOOD”,将其更改为“BAD”是空操作。
为了与非原子用户空间向后兼容,内核尝试在 SETCRTC IOCTL 中自动将链接状态设置回“GOOD”。如果该模式不再有效,则这可能会失败,类似于在过渡期间连接了不同的屏幕时可能会失败的情况。
- non_desktop
指示应忽略输出以用于显示标准桌面环境或控制台。这很可能是因为输出设备不是直线的。
- 内容保护
用户空间使用此属性来请求内核保护将来通过链接传输的内容。当请求时,内核将应用适当的保护方式(通常是 HDCP),并使用该属性告诉用户空间保护已激活。
驱动程序可以通过在初始化时调用
drm_connector_attach_content_protection_property()
来进行设置。此属性的值可以是以下之一
- DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0
链接未受保护,内容以明文形式传输。
- DRM_MODE_CONTENT_PROTECTION_DESIRED = 1
用户空间已请求内容保护,但链接当前未受保护。在此状态下,内核应尽快启用内容保护。
- DRM_MODE_CONTENT_PROTECTION_ENABLED = 2
用户空间已请求内容保护,并且链接已受保护。只有驱动程序可以将该属性设置为此值。如果用户空间尝试设置为 ENABLED,内核将返回 -EINVAL。
一些准则
在用户空间通过将该属性设置为 UNDESIRED 来取消断言之前,应保留 DESIRED 状态。这意味着只有在用户明确请求时,ENABLED 才应转换为 UNDESIRED。
如果状态为 DESIRED,内核应尽可能尝试重新验证链接。这包括跨禁用/启用、dpms、热插拔、下游设备更改、链接状态失败等。
内核通过 drm_hdcp_update_content_protection 发送带有连接器 ID 和属性 ID 的 uevent,在以下内核触发的场景中:
DESIRED -> ENABLED(身份验证成功)
ENABLED -> DESIRED(终止身份验证)
请注意,对于用户空间触发的属性状态更改,没有 uevent,这些更改不会失败,例如
DESIRED/ENABLED -> UNDESIRED
UNDESIRED -> DESIRED
用户空间负责轮询属性或侦听 uevent 以确定值何时从 ENABLED 转换为 DESIRED。这表示链接不再受保护,用户空间应采取适当的操作(无论可能是什么)。
- HDCP 内容类型
此枚举属性由用户空间用于向内核声明显示流的内容类型。此处,显示流代表用户空间打算通过 HDCP 加密显示的任何显示内容。
流的内容类型由流的所有者决定,作为“HDCP Type0”或“HDCP Type1”。
- 该属性的值可以是以下之一
“HDCP Type0”:DRM_MODE_HDCP_CONTENT_TYPE0 = 0
“HDCP Type1”:DRM_MODE_HDCP_CONTENT_TYPE1 = 1
当内核启动 HDCP 身份验证(有关详细信息,请参见“内容保护”)时,它使用“HDCP 内容类型”中的内容类型来执行与显示接收器的 HDCP 身份验证。
请注意,在 HDCP 规范版本中,可以使用 HDCP 2.2 对链接进行内容类型 0/内容类型 1 的身份验证。而只能使用 HDCP1.4 对链接进行内容类型 0 的身份验证(尽管本质上是隐式的。因为在 HDCP1.4 中没有对内容类型的引用)。
HDCP2.2 身份验证协议本身将“内容类型”作为参数,该参数是 DP HDCP2.2 加密算法的输入。
对于类型 0 内容保护请求,内核驱动程序可以选择 HDCP 规范版本 1.4 和 2.2 中的任一个。当 HDCP2.2 用于“HDCP Type 0”时,下游中支持 HDCP 2.2 的中继器可以将该内容发送到通过 HDCP 1.4 验证的 HDCP 接收器(Type0 链接)。但是,如果内容被归类为“HDCP Type 1”,则上述 HDCP 2.2 中继器不会将内容发送到 HDCP 接收器,因为它无法对“HDCP Type 1”的 HDCP1.4 接收器进行身份验证。
请注意,用户空间可以忽略内核驱动程序用于实现“HDCP 内容类型”的 HDCP 版本。
在当前情况下,将内容分类为 Type 1 可确保内容仅通过 HDCP2.2 加密链接显示。
请注意,HDCP 内容类型属性是在 HDCP 2.2 中引入的,默认类型为 0。它仅由支持 HDCP 2.2(因此支持 Type 0 和 Type 1)的驱动程序公开。根据 HDCP 规范的后续版本如何定义,内容类型也可以用于更高的版本。
如果在“内容保护”不是 UNDESIRED 时更改了内容类型,则内核将禁用 HDCP,并在同一原子提交中使用新类型重新启用 HDCP。当“内容保护”为 ENABLED 时,表示链接已通过 HDCP 验证和加密,用于传输“HDCP 内容类型”中提到的流类型。
- HDR_OUTPUT_METADATA
连接器属性,用于使用户空间能够将 HDR 元数据发送到驱动程序。此元数据基于用户决定的合成和混合策略,同时考虑了硬件和接收器的功能。驱动程序获取此元数据,并在 HDMI 的情况下创建动态范围和母带信息帧 (DRM),在 DP 的情况下创建 SDP 数据包(非音频 INFOFRAME SDP v1.3)。然后将其发送到接收器。这会将即将到来的帧的颜色编码和亮度参数通知接收器。
用户空间首先需要通过读取和解析 EDID 来检测接收器的 HDR 功能。有关 HDMI 的 HDR 元数据的详细信息已添加到 CTA 861.G 规范中。对于 DP,它在 VESA DP Standard v1.4 中定义。然后,它需要获取视频/游戏/应用程序内容(基本上是使用 HDR 传输函数进行编码)的元数据信息。有了这些信息,它需要决定混合策略并将相关图层/叠加层合成为一种通用格式。完成此混合后,用户空间将知道要发送到接收器的合成帧的元数据。然后,它使用此属性将此元数据传达给驱动程序,该驱动程序随后根据连接的编码器的类型制作信息帧数据包并发送到接收器。
- 在以下情况下,用户空间将负责进行色调映射操作
某些图层是 HDR,而其他图层是 SDR
HDR 图层的亮度与接收器的亮度不同
它甚至需要进行颜色空间转换并将所有图层转换为一种通用颜色空间以进行混合。它可以基于相关硬件的功能使用 GL、媒体或显示引擎来完成此操作。
驱动程序期望将元数据放入来自用户空间的
struct hdr_output_metadata
结构中。这作为 blob 接收并存储在drm_connector_state.hdr_output_metadata
中。它解析 EDID 并将接收器元数据保存在struct hdr_sink_metadata
中,作为drm_connector.hdr_sink_metadata
。在 HDMI 编码器的情况下,驱动程序使用 drm_hdmi_infoframe_set_hdr_metadata() 辅助函数设置 HDR 元数据,使用hdmi_drm_infoframe_pack()
按照规范打包信息帧。- max bpc
此范围属性由用户空间用于限制位深度。使用时,驱动程序将根据硬件和接收器支持的有效范围限制 bpc。驱动程序可以使用函数
drm_connector_attach_max_bpc_property()
在初始化期间创建属性并将其附加到连接器。
连接器还具有一个标准化的原子属性
- CRTC_ID
此连接器应连接到的
drm_crtc
的模式对象 ID。
LCD 面板的连接器也可能具有一个标准化的属性
- panel orientation
在某些设备上,LCD 面板以这样一种方式安装在外壳中,即面板的向上/顶部与设备的顶部不匹配。用户空间可以使用此属性来检查此情况。请注意,来自触摸屏(带有 INPUT_PROP_DIRECT 的输入设备)的输入坐标仍将 1:1 映射到实际的 LCD 面板坐标,因此,如果用户空间旋转图片以调整方向,则还必须对触摸屏输入坐标应用相同的转换。此属性通过调用
drm_connector_set_panel_orientation()
或drm_connector_set_panel_orientation_with_quirk()
初始化- scaling mode
此属性定义如何将非原生模式放大到 LCD 面板的本机模式
- None
不发生放大,缩放留给面板。并非所有驱动程序都公开此模式。
- Full
输出被放大到面板的完整分辨率,忽略纵横比。
- Center
不发生放大,输出在面板的本机分辨率内居中。
- Full aspect
输出被放大以最大化宽度或高度,同时保持宽高比。
此属性应通过调用
drm_connector_attach_scaling_mode_property()
来设置。请注意,驱动程序也可以将此属性暴露给外部输出,在这种情况下,它们必须支持“None”,这应该是默认值(因为外部屏幕具有内置的缩放器)。- subconnector
此属性由 DVI-I、TVout 和 DisplayPort 用于指示不同的连接器子类型。枚举值或多或少与主要连接器类型的枚举值匹配。对于 DVI-I 和 TVout,还有一个匹配的属性“选择子连接器”,允许在信号类型之间切换。DP 子连接器对应于下游端口。
- privacy-screen sw-state, privacy-screen hw-state
这两个可选属性可用于查询某些显示器上提供的电子隐私屏幕的状态;在某些情况下,还可以控制状态。如果驱动程序实现了这些属性,则必须同时存在这两个属性。
“privacy-screen hw-state”是只读的,反映了隐私屏幕的实际状态,可能的值:“Enabled”、“Disabled”、“Enabled-locked”、“Disabled-locked”。锁定状态表示无法通过 DRM API 更改状态。例如,可能存在固件设置选项或硬件滑块开关提供始终开启/关闭模式的设备。
当未锁定时,可以设置“privacy-screen sw-state”来更改隐私屏幕状态。在这种情况下,驱动程序必须在 sw-state 属性提交完成后更新 hw-state 属性以反映新状态。当 hw-state 被锁定时,将 sw-state 属性设置为某个值必须被驱动程序解释为请求在 hw-state 变为解锁状态时将状态更改为设置的状态。例如,如果“privacy-screen hw-state”为“Enabled-locked”,并且 sw-state 被设置为“Disabled”,随后用户通过更改滑块开关位置来解锁状态,则驱动程序必须在收到解锁事件后将状态设置为“Disabled”。
在某些情况下,隐私屏幕的实际状态可能会在 DRM 代码控制之外发生更改。例如,可能存在固件处理的热键可以切换实际状态,或者可以通过另一个用户空间 API(例如写入 /proc/acpi/ibm/lcdshadow)来更改实际状态。在这种情况下,驱动程序必须更新 hw-state 和 sw-state 以反映新值,从而覆盖 sw-state 中的任何挂起状态请求。因此,任何挂起的 sw-state 请求都将被丢弃。
请注意,状态可以在 DRM 主进程控制之外更改这一事实意味着用户空间不得缓存 sw-state 的值。缓存 sw-state 值并将其包含在以后的原子提交中可能会导致覆盖通过例如固件处理的热键完成的状态更改。因此,除非用户空间想要更改隐私屏幕的 sw-state 值,否则不得将其包含在原子提交中。
- left margin, right margin, top margin, bottom margin
将边距添加到连接器的视口。这通常用于缓解电视上的过扫描。
该值是将添加的黑色边框的大小(以像素为单位)。附加的 CRTC 的内容将被缩放以填充边距内的整个区域。
边距配置可能会被发送到接收器,例如通过 HDMI AVI InfoFrames。
驱动程序可以通过调用
drm_mode_create_tv_margin_properties()
来设置这些属性。- Colorspace
此属性用于通知驱动程序用户空间配置像素操作属性以产生的颜色编码。这些变体设置了色度、传递特性以及必要时应使用的 YCbCr 转换。来自 HDR_OUTPUT_METADATA 的传递特性优先于此属性。用户空间始终配置像素操作属性以产生全量化范围数据(请参阅 Broadcast RGB 属性)。
驱动程序告知接收器期望的色度、传递特性、YCbCr 转换和量化范围(这可能取决于输出模式、输出格式和其他属性)。驱动程序还将用户空间提供的数据转换为接收器期望的数据。
用户空间必须通过解析 EDID 来检查接收器是否支持驱动程序允许选择的所有可能的色度。
由于历史原因,此属性暴露了许多会导致未定义行为的变体。
- Default
该行为是特定于驱动程序的。
BT2020_RGB
- BT2020_YCC
用户空间配置像素操作属性以产生具有 Rec. ITU-R BT.2020 色度、Rec. ITU-R BT.2020(表 4,RGB)传递特性和全量化范围的 RGB 内容。用户空间可以使用 HDR_OUTPUT_METADATA 属性将传递特性设置为 PQ(Rec. ITU-R BT.2100 表 4)或 HLG(Rec. ITU-R BT.2100 表 5),在这种情况下,用户空间配置像素操作属性以产生具有相应传递特性的内容。用户空间必须确保接收器支持 Rec. ITU-R BT.2020 R'G'B' 和 Rec. ITU-R BT.2020 Y'C'BC'R 色度。驱动程序可以将接收器配置为使用 RGB 格式,告诉接收器期望 Rec. ITU-R BT.2020 R'G'B' 色度,并转换为适当的量化范围。驱动程序可以将接收器配置为使用 YCbCr 格式,告诉接收器期望 Rec. ITU-R BT.2020 Y'C'BC'R 色度,使用 Rec. ITU-R BT.2020 非恒定亮度转换矩阵转换为 YCbCr,并转换为适当的量化范围。变体 BT2020_RGB 和 BT2020_YCC 是等效的,驱动程序自行选择 RGB 和 YCbCr。
SMPTE_170M_YCC: BT709_YCC: XVYCC_601: XVYCC_709: SYCC_601: opYCC_601: opRGB: BT2020_CYCC: DCI-P3_RGB_D65: DCI-P3_RGB_Theater: RGB_WIDE_FIXED: RGB_WIDE_FLOAT
- BT601_YCC
该行为未定义。
由于 HDMI 和 DP 具有不同的色彩空间,drm_mode_create_hdmi_colorspace_property()
用于 HDMI 连接器,drm_mode_create_dp_colorspace_property()
用于 DP 连接器。
HDMI 特定连接器属性¶
- Broadcast RGB (HDMI specific)
指示使用的量化范围(完整与有限)。颜色处理管道将被调整以匹配属性的值,并且将相应地生成和发送信息帧。
仅当 HDMI 输出格式为 RGB 时,此属性才相关。如果是 YCbCr 变体之一,它将被忽略。
连接到连接器的 CRTC 必须由用户空间配置为始终产生全范围像素。
此属性的值可以是以下之一
- Automatic
根据 HDMI 规范(HDMI 1.4b - 第 6.6 节 - 视频量化范围),根据模式自动选择量化范围。
- Full
强制使用全量化范围。
- Limited 16:235
强制使用有限量化范围。与名称建议的不同,这适用于任何每分量位数。
除 Automatic 之外的属性值可能会导致颜色偏差(如果选择了 limited 但显示器期望 full),或者黑屏(如果选择了 full 但显示器期望 limited)。
驱动程序可以通过调用
drm_connector_attach_broadcast_rgb_property()
来设置此属性。- content type (HDMI specific)
指示要在 HDMI 信息帧中使用的内容类型设置,以指示外部设备的内容类型,以便它相应地调整其显示设置。
此属性的值可以是以下之一
- No Data
内容类型未知
- Graphics
内容类型是图形
- Photo
内容类型是照片
- Cinema
内容类型是电影
- Game
内容类型是游戏
每种内容类型的含义在 CTA-861-G 表 15 中定义。
驱动程序可以通过调用
drm_connector_attach_content_type_property()
来设置此属性。到信息帧值的解码通过 drm_hdmi_avi_infoframe_content_type() 完成。
模拟电视特定连接器属性¶
- TV Mode
指示在模拟电视连接器上使用的电视模式。此属性的值可以是以下之一
- NTSC
电视模式是 CCIR 系统 M(又名 525 行),与 NTSC 颜色编码一起使用。
NTSC-443
电视模式是 CCIR 系统 M(又名 525 行),与 NTSC 颜色编码一起使用,但颜色副载波频率为 4.43MHz
NTSC-J
电视模式是 CCIR 系统 M(又名 525 行),与 NTSC 颜色编码一起使用,但黑电平等于消隐电平。
PAL
电视模式是 CCIR 系统 B(又名 625 行),与 PAL 颜色编码一起使用。
PAL-M
电视模式是 CCIR 系统 M(又名 525 行),与 PAL 颜色编码一起使用。
PAL-N
电视模式是 CCIR 系统 N,与 PAL 颜色编码一起使用,颜色副载波频率为 3.58MHz,SECAM 色彩空间,并且通道比其他 PAL 变体窄。
SECAM
电视模式是 CCIR 系统 B(又名 625 行),与 SECAM 颜色编码一起使用。
Mono
使用适合 DRM 模式的计时,包括用于 525 行或 625 行模式的均衡脉冲,没有基座或颜色编码。
驱动程序可以通过调用
drm_mode_create_tv_properties()
来设置此属性。
标准 CRTC 属性¶
DRM CRTC 具有一些标准化的属性
- ACTIVE
用于设置 CRTC 电源状态的原子属性。当设置为 1 时,CRTC 将主动显示内容。当设置为 0 时,CRTC 将关闭电源。不期望用户空间在将 ACTIVE 设置为 0 时重置 CRTC 资源,如模式和平面。
用户空间可以依赖于 ACTIVE 更改为 1 永远不会导致原子测试失败,只要没有其他属性发生更改。如果对 ACTIVE 的更改导致原子测试失败,这是一个驱动程序错误。因此,将 ACTIVE 设置为 0 不得释放内部资源(如保留的内存带宽或时钟发生器)。
请注意,连接器上的旧版 DPMS 属性在内部被路由以控制原子驱动程序的此属性。
- MODE_ID
用于设置 CRTC 显示时序的原子属性。该值是包含 DRM 模式信息的 blob 的 ID。要禁用 CRTC,用户空间必须将此属性设置为 0。
将 MODE_ID 设置为 0 将释放为 CRTC 保留的资源。
- SCALING_FILTER
用于设置 CRTC 缩放器的缩放过滤器的原子属性
此属性的值可以是以下之一
- Default
驱动程序的默认缩放滤波器
- Nearest Neighbor
最近邻缩放滤波器
标准平面属性¶
DRM 平面具有一些标准化的属性
- type
描述平面类型的不可变属性。
对于已启用
DRM_CLIENT_CAP_ATOMIC
功能的用户空间,平面类型只是一个提示,并且主要被原子测试提交所取代。类型提示仍然可以用来更容易地提出驱动程序接受的平面配置。此属性的值可以是以下之一
- “Primary”
要点亮 CRTC,如果附加一个覆盖整个 CRTC 且未设置缩放或裁剪的主平面,则最有可能有效。
驱动程序可以支持主平面的更多功能,用户空间可以通过仅测试的原子提交来找出答案。
一些主平面由内核在旧版 IOCTL
DRM_IOCTL_MODE_SETCRTC
和DRM_IOCTL_MODE_PAGE_FLIP
中隐式使用。因此,用户空间不得将任何主平面的显式用法(例如,通过原子提交)与这些旧版 IOCTL 混合使用。- “Cursor”
要启用此平面,使用配置为不进行缩放或裁剪并具有以下属性的帧缓冲区最有可能有效
如果驱动程序提供功能
DRM_CAP_CURSOR_WIDTH
和DRM_CAP_CURSOR_HEIGHT
,请使用此大小创建帧缓冲区。否则,创建一个大小为 64x64 的帧缓冲区。如果驱动程序不支持修饰符,请使用线性布局创建帧缓冲区。否则,请使用 IN_FORMATS 平面属性。
驱动程序可以支持光标平面的更多功能,用户空间可以通过仅测试的原子提交来找出答案。
一些光标平面由内核在旧版 IOCTL
DRM_IOCTL_MODE_CURSOR
和DRM_IOCTL_MODE_CURSOR2
中隐式使用。因此,用户空间不得将任何光标平面的显式用法(例如,通过原子提交)与这些旧版 IOCTL 混合使用。即使没有暴露光标平面,一些驱动程序也可能支持光标。在这种情况下,可以使用旧版光标 IOCTL 来配置光标。
- “Overlay”
既不是主平面也不是光标平面。
当禁用
DRM_CLIENT_CAP_UNIVERSAL_PLANES
功能时,覆盖平面是唯一暴露的平面。
- IN_FORMATS
blob 属性,包含此平面支持的缓冲区格式和修饰符对的集合。该 blob 是一个 struct drm_format_modifier_blob。没有此属性,平面不支持带有修饰符的缓冲区。用户空间无法更改此属性。
请注意,用户空间可以检查
DRM_CAP_ADDFB2_MODIFIERS
驱动程序功能以获得通用修饰符支持。如果设置了此标志,则每个平面都将具有 IN_FORMATS 属性,即使它仅支持 DRM_FORMAT_MOD_LINEAR。在 linux 内核版本 v5.1 之前,此区域存在各种错误,功能标志和每个平面属性之间存在不一致。- IN_FORMATS_ASYNC
blob 属性,包含此平面支持的异步翻转的缓冲区格式和修饰符对的集合。该 blob 是一个 struct drm_format_modifier_blob。用户空间无法更改此属性。这是一个可选属性,如果不存在,则用户应该预期在使用原子 ioctl 时会失败,因为异步翻转下该平面不支持修饰符/格式。
- SIZE_HINTS
blob 属性,包含建议的平面大小的集合,可用于简单的“类似光标”的用例(例如,没有缩放)。使用这些提示可以避免用户空间通过原子/setcursor ioctl 大量探测支持的平面大小。
blob 包含一个
struct drm_plane_size_hint
数组,按优先级排序。为了获得最佳使用效果,用户空间应选择满足其自身要求的第一个大小。驱动程序应仅将此属性附加到支持非常有限的大小集合的平面。
请注意,属性值 0(即没有 blob)保留供将来潜在使用。当前的用户空间应忽略该属性(如果值为 0),并回退到其他方式(例如,
DRM_CAP_CURSOR_WIDTH
和DRM_CAP_CURSOR_HEIGHT
)来确定要使用的适当平面大小。
平面合成属性¶
标准平面属性支持的基本平面合成模型只有一个源矩形(在 drm_framebuffer
中的逻辑像素中),具有亚像素精度,该源矩形被放大到 drm_crtc
可见区域中的像素对齐目标矩形。CRTC 的可见区域由请求的模式的水平和垂直可见像素(存储在 **hdisplay** 和 **vdisplay** 中)定义(存储在 drm_crtc_state.mode
中)。这两个矩形都存储在 drm_plane_state
中。
对于原子 ioctl,平面对象上的以下标准(原子)属性对基本平面合成模型进行编码
- SRC_X
源矩形在
drm_framebuffer
中的 X 坐标偏移量,以 16.16 定点表示。必须为正数。- SRC_Y
源矩形在
drm_framebuffer
中的 Y 坐标偏移量,以 16.16 定点表示。必须为正数。- SRC_W
源矩形在
drm_framebuffer
中的宽度,以 16.16 定点表示。SRC_X 加 SRC_W 必须在源帧缓冲区的宽度内。必须为正数。- SRC_H
源矩形在
drm_framebuffer
中的高度,以 16.16 定点表示。SRC_Y 加 SRC_H 必须在源帧缓冲区的高度内。必须为正数。- CRTC_X
目标矩形的 X 坐标偏移量。可以为负数。
- CRTC_Y
目标矩形的 Y 坐标偏移量。可以为负数。
- CRTC_W
目标矩形的宽度。CRTC_X 加 CRTC_W 可以超出
drm_crtc
的当前可见水平区域。- CRTC_H
目标矩形的高度。CRTC_Y 加 CRTC_H 可以超出
drm_crtc
的当前可见垂直区域。- FB_ID
此平面应扫描出的
drm_framebuffer
的模式对象 ID。当 KMS 客户端执行前缓冲区渲染时,它应该在每个原子提交上将 FB_ID 设置为相同的前缓冲区 FB。这意味着驱动程序需要再次重新读取相同的 FB。否则,不采用连续重复扫描循环的驱动程序可能不会更新屏幕。
- CRTC_ID
此平面应连接到的
drm_crtc
的模式对象 ID。
请注意,源矩形必须完全位于 drm_framebuffer
的边界内。目标矩形可以位于 CRTC 当前模式的可见区域之外。它必须由驱动程序适当裁剪,可以通过调用 drm_plane_helper_check_update() 来完成。还允许驱动程序适当地舍入子像素采样位置,但只能舍入到下一个完整像素。不得对源矩形之外的任何像素进行采样,这在应用比双线性滤波更复杂的滤波进行缩放时非常重要。缩放时的滤波模式未指定。
除了此基本转换之外,驱动程序还可以公开其他属性
- alpha
Alpha 通过
drm_plane_create_alpha_property()
设置。它控制整个平面的不透明度,从透明 (0) 到不透明 (0xffff)。它可以与像素 alpha 结合使用。帧缓冲区中的像素值预计不会与与平面关联的全局 alpha 预乘。- rotation
Rotation 通过
drm_plane_create_rotation_property()
设置。它在源矩形和目标矩形之间添加旋转和反射步骤。没有此属性,矩形仅缩放,但不旋转或反射。可能的值
- “rotate-<degrees>”
指示 DRM 平面以逆时针方向旋转 <degrees> 度。
- “reflect-<axis>”
指示 DRM 平面的内容沿 <axis> 轴反射,方式与镜像相同。
reflect-x
|o | | o| | | -> | | | v| |v |
reflect-y
|o | | ^| | | -> | | | v| |o |
- zpos
Z position 通过
drm_plane_create_zpos_immutable_property()
和drm_plane_create_zpos_property()
设置。它控制重叠平面的可见性。没有此属性,主平面始终位于光标平面下方,并且所有其他平面之间的排序未定义。正 Z 轴指向用户,即,Z 位置值较低的平面位于 Z 位置值较高的平面下方。具有相同 Z 位置值的两个平面具有未定义的排序。请注意,Z 位置值也可以是不可变的,以告知用户空间平面的硬编码堆叠,请参阅drm_plane_create_zpos_immutable_property()
。如果任何平面具有 zpos 属性(可变或不可变),则所有平面都应具有 zpos 属性。- pixel blend mode
Pixel blend mode 通过
drm_plane_create_blend_mode_property()
设置。它为 alpha 混合方程选择添加了一个混合模式,描述了当前平面的像素如何与背景合成。定义了三个 alpha 混合方程
- “None”
忽略像素 alpha 的混合公式
out.rgb = plane_alpha * fg.rgb + (1 - plane_alpha) * bg.rgb
- “Pre-multiplied”
假设像素颜色值已经与 alpha 通道值预乘的混合公式
out.rgb = plane_alpha * fg.rgb + (1 - (plane_alpha * fg.alpha)) * bg.rgb
- “Coverage”
假设像素颜色值未预乘,并且在将它们混合到背景颜色值时将进行预乘的混合公式
out.rgb = plane_alpha * fg.alpha * fg.rgb + (1 - (plane_alpha * fg.alpha)) * bg.rgb
使用以下符号
- “fg.rgb”
来自平面像素的每个 RGB 分量值
- “fg.alpha”
来自平面像素的 Alpha 分量值。如果平面的像素格式没有 alpha 分量,则假定此值为 1.0。在这些情况下,此属性无效,因为所有三个方程都变得等效。
- “bg.rgb”
来自背景的每个 RGB 分量值
- “plane_alpha”
由平面“alpha”属性设置的平面 alpha 值。如果平面不暴露“alpha”属性,则假定此值为 1.0
请注意,此处描述的所有属性扩展都适用于平面或 CRTC(例如,对于背景颜色,当前未公开且假定为黑色)。
- SCALING_FILTER
指示要用于平面缩放器的缩放滤波器
此属性的值可以是以下之一
- Default
驱动程序的默认缩放滤波器
- Nearest Neighbor
最近邻缩放滤波器
驱动程序可以通过调用 drm_plane_create_scaling_filter_property 为平面设置此属性
损坏跟踪属性¶
FB_DAMAGE_CLIPS 是一个可选的平面属性,它提供了一种在附加到平面的帧缓冲区的帧缓冲区坐标中指定平面上损坏矩形列表的方法。在当前上下文中,损坏是指自上次平面更新(也称为页面翻转)以来,平面帧缓冲区中已更改的区域,无论当前附加的帧缓冲区是否与上次平面更新期间附加的帧缓冲区相同。
FB_DAMAGE_CLIPS 是内核的一个提示,它可能有助于某些驱动程序在内部进行优化,特别是对于每个帧缓冲区更改都需要通过网络、USB 等传输的虚拟设备。
由于 FB_DAMAGE_CLIPS 是一个提示,因此它是一个可选属性。用户空间可以忽略损坏剪辑属性,在这种情况下,驱动程序将执行完整的平面更新。如果提供了损坏剪辑,则保证损坏剪辑内的区域将更新到平面。为了提高效率,驱动程序可以进行完整更新,或者可以更新比损坏剪辑中指定的更多的内容。由于驱动程序可以自由读取更多内容,因此用户空间必须始终渲染整个可见帧缓冲区。否则可能会出现损坏。此外,如果用户空间提供的损坏剪辑未涵盖帧缓冲区的实际损坏(自上次平面更新以来),可能会导致不正确的渲染。
FB_DAMAGE_CLIPS 是一个 Blob 属性,Blob 数据的布局只是一个 drm_mode_rect
数组。与平面 drm_plane_state.src
坐标不同,损坏剪辑不是 16.16 定点数。与帧缓冲区中的平面 src 类似,损坏剪辑不能为负数。在损坏剪辑中,x1/y1 是包含性的,而 x2/y2 是排他性的。虽然内核不会因重叠的损坏剪辑而报错,但不鼓励这样做。
对平面损坏接口感兴趣的驱动程序应通过调用 drm_plane_enable_fb_damage_clips()
启用 FB_DAMAGE_CLIPS 属性。实现损坏的驱动程序可以使用 drm_atomic_helper_damage_iter_init()
和 drm_atomic_helper_damage_iter_next()
辅助迭代器函数来获取剪辑到 drm_plane_state.src
的损坏矩形。
请注意,有两种类型的损坏处理:帧损坏和缓冲区损坏,实现的损坏处理类型取决于驱动程序的上传目标。实现每个平面或每个 CRTC 上传目标的驱动程序需要处理帧损坏,而实现每个缓冲区上传目标的驱动程序需要处理缓冲区损坏。
现有的损坏辅助程序仅支持帧损坏类型,目前还没有实现缓冲区年龄支持或类似的损坏累积算法。
只有处理帧损坏的驱动程序才能使用上述损坏辅助程序来迭代损坏区域。处理缓冲区损坏的驱动程序必须为 drm_atomic_helper_damage_iter_init()
设置 drm_plane_state.ignore_damage_clips
,以了解应忽略损坏剪辑并将 drm_plane_state.src
作为损坏矩形返回,以强制进行完整的平面更新。
具有每个缓冲区上传目标的驱动程序可以比较新旧平面状态的 drm_plane_state.fb
,以确定附加到平面的帧缓冲区自上次平面更新以来是否已更改。如果 drm_plane_state.fb
已更改,则必须将 drm_plane_state.ignore_damage_clips
设置为 true。
这是因为具有每个平面上传目标的驱动程序期望后备存储缓冲区对于给定的平面不会更改。如果在页面翻转之间上传缓冲区发生更改,则必须整体更新新的上传缓冲区。如果 DRM 损坏辅助程序添加了对帧损坏的支持,则可以改进这一点,类似于用户空间已经如何处理这种情况,如下面的文档中所述
颜色管理属性¶
颜色管理或颜色空间调整通过 drm_crtc
对象上的一组 5 个属性来支持。它们通过调用 drm_crtc_enable_color_mgmt()
来设置。
- “DEGAMMA_LUT”
Blob 属性,用于设置反伽玛查找表 (LUT),该表在像素数据提供给变换矩阵之前将像素数据从帧缓冲区映射出来。该数据被解释为
struct drm_color_lut
元素的数组。硬件可能会选择不使用 LUT 元素的完整精度,也不使用 LUT 的所有元素(例如,硬件可能会选择在 LUT[0] 和 LUT[4] 之间进行插值)。将此值设置为 NULL(Blob 属性值设置为 0)意味着应使用线性/直通伽玛表。这通常也是驱动程序的启动状态。驱动程序可以通过
drm_crtc_state.degamma_lut
访问此 Blob。- “DEGAMMA_LUT_SIZE”
无符号范围属性,用于提供 DEGAMMA_LUT 属性上设置的查找表的大小(大小取决于底层硬件)。如果驱动程序支持多个 LUT 大小,则应发布最大大小,并适当地对较小大小的 LUT 进行子采样(例如,对于拆分伽玛模式)。
- “CTM”
Blob 属性,用于设置当前变换矩阵 (CTM),该矩阵应用于通过反伽玛 LUT 查找后和通过伽玛 LUT 查找前的像素数据。该数据被解释为 struct
drm_color_ctm
。将此值设置为 NULL(Blob 属性值设置为 0)意味着应使用单位/直通矩阵。这通常也是驱动程序的启动状态。驱动程序可以通过
drm_crtc_state.ctm
访问颜色转换矩阵的 Blob。- “GAMMA_LUT”
Blob 属性,用于设置伽玛查找表 (LUT),该表将转换矩阵后的像素数据映射到发送到连接器的数据。该数据被解释为
struct drm_color_lut
元素的数组。硬件可能会选择不使用 LUT 元素的完整精度,也不使用 LUT 的所有元素(例如,硬件可能会选择在 LUT[0] 和 LUT[4] 之间进行插值)。将此值设置为 NULL(Blob 属性值设置为 0)意味着应使用线性/直通伽玛表。这通常也是驱动程序的启动状态。驱动程序可以通过
drm_crtc_state.gamma_lut
访问此 Blob。请注意,由于主要来自Xorg传承的历史原因,它也用于存储索引格式(如DRM_FORMAT_C8)的颜色映射(有时也称为颜色lut、CLUT或调色板)。
- “GAMMA_LUT_SIZE”
无符号范围属性,用于提供 GAMMA_LUT 属性上设置的查找表的大小(大小取决于底层硬件)。如果驱动程序支持多个 LUT 大小,则应发布最大大小,并适当地对较小大小的 LUT 进行子采样(例如,对于拆分伽玛模式)。
还支持旧版伽玛表,该伽玛表通过调用 drm_mode_crtc_set_gamma_size()
来设置。然后,DRM 核心将旧版伽玛斜坡与“GAMMA_LUT”或(如果该值不可用)“DEGAMMA_LUT”别名。
对不同非 RGB 颜色编码的支持通过 drm_plane
特定的 COLOR_ENCODING 和 COLOR_RANGE 属性来控制。它们通过调用 drm_plane_create_color_properties()
来设置。
- “COLOR_ENCODING”
可选的平面枚举属性,用于支持不同的非 RGB 颜色编码。驱动程序可以提供 DRM 平面支持的标准枚举值的子集。
- “COLOR_RANGE”
可选的平面枚举属性,用于支持不同的非 RGB 颜色参数范围。驱动程序可以提供 DRM 平面支持的标准枚举值的子集。
平铺组属性¶
平铺组用于表示具有唯一整数标识符的平铺监视器。使用 DisplayID v1.3 的平铺监视器具有唯一的 8 字节句柄,我们将其存储在平铺组中,因此我们为监视器组中的所有平铺都有一个公共标识符。该属性称为“TILE”。驱动程序可以使用 drm_mode_create_tile_group()
、drm_mode_put_tile_group()
和 drm_mode_get_tile_group()
来管理平铺组。但这仅对于通过非标准方式公开平铺组信息的内部面板是必需的。
显式围栏属性¶
显式围栏允许用户空间控制设备之间的缓冲区同步。围栏或一组围栏使用同步文件 fd 传输到/从用户空间传输,并且有两个 DRM 属性用于此。每个 DRM 平面上的 IN_FENCE_FD 用于将围栏发送到内核,每个 DRM CRTC 上的 OUT_FENCE_PTR 用于从内核接收围栏。
相比之下,使用隐式围栏,内核会跟踪任何正在进行的渲染,并自动确保原子更新等待任何挂起的渲染完成。这通常在 struct dma_resv
中跟踪,该结构也可以包含强制性的内核围栏。隐式同步是 Linux 传统的工作方式(例如,X.org 上的 DRI2/3),而显式围栏是 Android 所需的。
- “IN_FENCE_FD”
使用此属性传递 DRM 应等待的围栏,然后再继续执行原子提交请求并在屏幕上显示平面的帧缓冲区。围栏可以是普通围栏或合并围栏,sync_file 框架将处理这两种情况,如果收到合并围栏,则使用 fence_array。在此处传递 -1 意味着没有要等待的围栏。
如果原子提交请求具有 DRM_MODE_ATOMIC_TEST_ONLY 标志,它将仅检查同步文件是否有效。
在驱动程序端,围栏存储在
struct drm_plane_state
的 fence 参数上。还支持隐式围栏的驱动程序应使用drm_gem_plane_helper_prepare_fb()
提取隐式围栏,以确保在隐式围栏与显式围栏的优先级方面,驱动程序之间具有一致的行为。- “OUT_FENCE_PTR”
使用此属性将文件描述符指针传递给 DRM。原子提交请求调用返回后,OUT_FENCE_PTR 将填充同步文件的文件描述符编号。此同步文件包含 CRTC 围栏,当原子提交 * 请求中针对给定 CRTC 的所有帧缓冲区都在屏幕上扫描出来时,将发出信号。
如果传递了无效的指针,则原子提交请求将失败。如果原子提交请求因任何其他原因失败,则返回的输出围栏 fd 将为 -1。在使用 DRM_MODE_ATOMIC_TEST_ONLY 标志的原子提交上,输出围栏也将设置为 -1。
请注意,输出围栏没有特殊的驱动程序接口,并且在内部由 struct
drm_crtc_state
中的struct drm_pending_vblank_event
表示,非阻塞原子提交辅助程序和现有用户空间的 DRM 事件处理也使用该结构。
可变刷新属性¶
能够动态调整刷新率的可变刷新率显示器可以通过延长其垂直前沿的持续时间直到页面翻转或超时来动态调整其刷新率。这可以减少或消除页面翻转与垂直消隐间隔不对齐的情况下的卡顿和延迟。
一个示例场景是应用程序在 60Hz 显示器上以恒定的 48Hz 速率翻转。页面翻转将经常错过垂直消隐间隔,并且相同的内容将显示两次。对于具有运动的内容,可以观察到卡顿。
如果在支持 35Hz 到 60Hz 的可变刷新范围的显示器上激活了可变刷新率,则对于示例场景,将无法观察到卡顿。35Hz 的最小支持的可变刷新率低于页面翻转频率,并且可以延长垂直前沿,直到发生页面翻转。垂直消隐间隔将直接与页面翻转率对齐。
并非所有用户空间内容都适合与可变刷新率一起使用。垂直前沿持续时间的较大且频繁的更改可能会使输入敏感型应用程序的感知卡顿恶化。
面板亮度也会随着垂直前沿持续时间而变化。某些面板在最小垂直前沿持续时间和最大垂直前沿持续时间之间可能具有明显的亮度差异。垂直前沿持续时间的较大且频繁的更改可能会产生此类面板的可观察到的闪烁。
通过 drm_connector
和 drm_crtc
对象上的属性支持可变刷新率的用户空间控制。
- “vrr_capable”
可选的
drm_connector
布尔属性,驱动程序应使用drm_connector_attach_vrr_capable_property()
将其附加到可能支持可变刷新率的连接器。驱动程序应通过调用drm_connector_set_vrr_capable_property()
更新属性值。不存在该属性应指示不存在支持。
- “VRR_ENABLED”
默认的
drm_crtc
布尔属性,用于通知驱动程序 CRTC 上的内容适合可变刷新率呈现。如果接收器支持,驱动程序将以此属性作为启用可变刷新率支持的提示,即如果drm_connector
对象上的“vrr_capable”属性为 true。启用后,垂直前沿持续时间将延长,直到页面翻转或超时。最小垂直前沿持续时间定义为当前模式的垂直前沿持续时间。
最大垂直前沿持续时间大于或等于最小垂直前沿持续时间。该持续时间来自连接器的最小支持的可变刷新率。
驱动程序可能会在这些最小和最大边界内设置进一步的限制。
光标热点属性¶
HOTSPOT_X:用于设置鼠标热点 x 偏移量的属性。HOTSPOT_Y:用于设置鼠标热点 y 偏移量的属性。
当平面用作光标图像以显示鼠标指针时,“热点”是光标图像中预期鼠标事件发生的位置的偏移量。
正值将热点从光标平面的左上角向右和底部移动。
大多数显示驱动程序不需要此信息,因为热点实际上未连接到屏幕上可见的任何内容。但是,这对于显示驱动程序(如准虚拟化驱动程序(例如,qxl、vbox、virtio、vmwgfx))是必需的,这些驱动程序附加到具有鼠标指针的用户控制台。由于这些控制台通常通过网络进行远程控制,因此否则他们必须等待向用户显示指针移动,直到发生完整的网络往返。必须通过网络从用户的控制台发送新的鼠标事件到虚拟输入设备,转发到桌面进行处理,然后才能更新光标平面的位置并通过网络发送回用户的控制台。相反,使用热点信息,控制台可以预测新位置,并在确认传入之前在那里绘制鼠标光标。为了正确地执行此操作,用户的控制台必须能够预测桌面将如何处理鼠标事件,这通常需要桌面的鼠标拓扑信息,即每个 CRTC 在鼠标坐标空间中的位置。这通常使用一些特定于驱动程序的方法发送到准虚拟化驱动程序,然后驱动程序通过虚拟显示设备或虚拟机管理程序将其转发到控制台。
通常假设一次只有使用一个光标平面,并且桌面正在将所有鼠标设备馈送到同一个全局指针中。需要此功能的准虚拟化驱动程序应仅公开单个光标平面,或者找到其他一些方法与支持多个指针的用户空间桌面进行协调。如果设置了热点属性,则假定光标平面仅用于显示鼠标光标图像,因此组合光标平面 + 偏移量的位置可用于与来自鼠标设备的输入进行协调。
然后,光标将绘制在 CRTC 控制台中平面所在的位置,或者作为用户控制台上与其桌面鼠标位置相对应的自由浮动光标平面。
希望在公开热点属性的驱动程序上正确工作的 DRM 客户端应通告 DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT。在未专门处理光标平面的驱动程序上设置此属性将返回 EOPNOTSUPP,用户空间可以使用该属性来衡量其运行的硬件/驱动程序的要求。通告 DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT 意味着用户空间客户端将正确设置热点属性。
现有 KMS 属性¶
下表给出了各种模块/驱动程序公开的 DRM 属性的说明。由于此表非常笨拙,因此请勿在此处添加任何新属性。而是在上面的部分中记录它们。
所有者模块/驱动程序 |
组 |
属性名称 |
类型 |
属性值 |
附加的对象 |
描述/限制 |
---|---|---|---|---|---|---|
DVI-I |
“子连接器” |
枚举 |
{ “未知”, “DVI-D”, “DVI-A” } |
连接器 |
待定 |
|
“选择子连接器” |
枚举 |
{ “自动”, “DVI-D”, “DVI-A” } |
连接器 |
待定 |
||
电视 |
“子连接器” |
枚举 |
{ “未知”, “复合”, “SVIDEO”, “分量”, “SCART” } |
连接器 |
待定 |
|
“选择子连接器” |
枚举 |
{ “自动”, “复合”, “SVIDEO”, “分量”, “SCART” } |
连接器 |
待定 |
||
“模式” |
枚举 |
{ “NTSC_M”, “NTSC_J”, “NTSC_443”, “PAL_B” } 等。 |
连接器 |
待定 |
||
“左边距” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“右边距” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“上边距” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“下边距” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“亮度” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“对比度” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“闪烁减少” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“过扫描” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“饱和度” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
“色调” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
||
虚拟 GPU |
“建议的 X” |
范围 |
最小=0, 最大=0xffffffff |
连接器 |
用于建议连接器的 X 偏移量的属性 |
|
“建议的 Y” |
范围 |
最小=0, 最大=0xffffffff |
连接器 |
用于建议连接器的 Y 偏移量的属性 |
||
可选 |
“纵横比” |
枚举 |
{ “无”, “4:3”, “16:9” } |
连接器 |
待定 |
|
“音频” |
枚举 |
{ “强制 dvi”, “关闭”, “自动”, “开启” } |
连接器 |
待定 |
||
SDVO-TV |
“模式” |
枚举 |
{ “NTSC_M”, “NTSC_J”, “NTSC_443”, “PAL_B” } 等。 |
连接器 |
待定 |
|
“左边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“右边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“上边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“下边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“hpos” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“vpos” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“对比度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“饱和度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“色调” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“清晰度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“闪烁_过滤器” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“闪烁_过滤器_自适应” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“闪烁_过滤器_2d” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“电视_色度_过滤器” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“电视_亮度_过滤器” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“点_爬行” |
范围 |
最小=0, 最大=1 |
连接器 |
待定 |
||
SDVO-TV/LVDS |
“亮度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
|
CDV gma-500 |
通用 |
“广播 RGB” |
枚举 |
{ “完整”, “有限 16:235” } |
连接器 |
待定 |
Poulsbo |
通用 |
“背光” |
范围 |
最小=0, 最大=100 |
连接器 |
待定 |
SDVO-TV |
“模式” |
枚举 |
{ “NTSC_M”, “NTSC_J”, “NTSC_443”, “PAL_B” } 等。 |
连接器 |
待定 |
|
“左边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“右边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“上边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“下边距” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“hpos” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“vpos” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“对比度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“饱和度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“色调” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“清晰度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“闪烁_过滤器” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“闪烁_过滤器_自适应” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“闪烁_过滤器_2d” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“电视_色度_过滤器” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“电视_亮度_过滤器” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
||
“点_爬行” |
范围 |
最小=0, 最大=1 |
连接器 |
待定 |
||
SDVO-TV/LVDS |
“亮度” |
范围 |
最小=0, 最大= SDVO 相关 |
连接器 |
待定 |
|
armada |
CRTC |
“CSC_YUV” |
枚举 |
{ “自动” , “CCIR601”, “CCIR709” } |
CRTC |
待定 |
“CSC_RGB” |
枚举 |
{ “自动”, “计算机系统”, “工作室” } |
CRTC |
待定 |
||
覆盖 |
“颜色键” |
范围 |
最小=0, 最大=0xffffff |
平面 |
待定 |
|
“颜色键_最小” |
范围 |
最小=0, 最大=0xffffff |
平面 |
待定 |
||
“颜色键_最大” |
范围 |
最小=0, 最大=0xffffff |
平面 |
待定 |
||
“颜色键_值” |
范围 |
最小=0, 最大=0xffffff |
平面 |
待定 |
||
“颜色键_alpha” |
范围 |
最小=0, 最大=0xffffff |
平面 |
待定 |
||
“颜色键_模式” |
枚举 |
{ “已禁用”, “Y 分量”, “U 分量” , “V 分量”, “RGB”, “R 分量”, “G 分量”, “B 分量” } |
平面 |
待定 |
||
“亮度” |
范围 |
最小=0, 最大=256 + 255 |
平面 |
待定 |
||
“对比度” |
范围 |
最小=0, 最大=0x7fff |
平面 |
待定 |
||
“饱和度” |
范围 |
最小=0, 最大=0x7fff |
平面 |
待定 |
||
exynos |
CRTC |
“模式” |
枚举 |
{ “正常”, “空白” } |
CRTC |
待定 |
i2c/ch7006_drv |
通用 |
“比例” |
范围 |
最小=0, 最大=2 |
连接器 |
待定 |
电视 |
“模式” |
枚举 |
{ “PAL”, “PAL-M”,”PAL-N”}, ”PAL-Nc” , “PAL-60”, “NTSC-M”, “NTSC-J” } |
连接器 |
待定 |
|
nouveau |
NV10 覆盖 |
“颜色键” |
范围 |
最小=0, 最大=0x01ffffff |
平面 |
待定 |
“对比度” |
范围 |
最小=0, 最大=8192-1 |
平面 |
待定 |
||
“亮度” |
范围 |
最小=0, 最大=1024 |
平面 |
待定 |
||
“色调” |
范围 |
最小=0, 最大=359 |
平面 |
待定 |
||
“饱和度” |
范围 |
最小=0, 最大=8192-1 |
平面 |
待定 |
||
“iturbt_709” |
范围 |
最小=0, 最大=1 |
平面 |
待定 |
||
Nv04 覆盖 |
“颜色键” |
范围 |
最小=0, 最大=0x01ffffff |
平面 |
待定 |
|
“亮度” |
范围 |
最小=0, 最大=1024 |
平面 |
待定 |
||
显示 |
“抖动模式” |
枚举 |
{ “自动”, “关闭”, “开启” } |
连接器 |
待定 |
|
“抖动深度” |
枚举 |
{ “自动”, “关闭”, “开启”, “静态 2x2”, “动态 2x2”, “时序” } |
连接器 |
待定 |
||
“底边扫描” |
枚举 |
{ “自动”, “6 bpc”, “8 bpc” } |
连接器 |
待定 |
||
“底边扫描水平边框” |
范围 |
最小值=0, 最大值=128 |
连接器 |
待定 |
||
“底边扫描垂直边框” |
范围 |
最小值=0, 最大值=128 |
连接器 |
待定 |
||
“鲜艳色调” |
范围 |
最小值=0, 最大值=180 |
连接器 |
待定 |
||
“颜色鲜艳度” |
范围 |
最小值=0, 最大值=200 |
连接器 |
待定 |
||
omap |
通用 |
“z序” |
范围 |
最小值=0, 最大值=3 |
CRTC, 平面 |
待定 |
qxl |
通用 |
“热插拔模式更新” |
范围 |
最小=0, 最大=1 |
连接器 |
待定 |
radeon |
DVI-I |
“一致性” |
范围 |
最小=0, 最大=1 |
连接器 |
待定 |
DAC 使能加载检测 |
“加载检测” |
范围 |
最小=0, 最大=1 |
连接器 |
待定 |
|
电视标准 |
“电视标准” |
枚举 |
{ “ntsc”, “pal”, “pal-m”, “pal-60”, “ntsc-j” , “scart-pal”, “pal-cn”, “secam” } |
连接器 |
待定 |
|
传统 TMDS PLL 检测 |
“tmds_pll” |
枚举 |
{ “驱动”, “bios” } |
待定 |
||
底边扫描 |
“底边扫描” |
枚举 |
{ “关闭”, “开启”, “自动” } |
连接器 |
待定 |
|
“底边扫描水平边框” |
范围 |
最小值=0, 最大值=128 |
连接器 |
待定 |
||
“底边扫描垂直边框” |
范围 |
最小值=0, 最大值=128 |
连接器 |
待定 |
||
音频 |
“音频” |
枚举 |
{ “关闭”, “开启”, “自动” } |
连接器 |
待定 |
|
FMT 抖动 |
“抖动” |
枚举 |
{ “关闭”, “开启” } |
连接器 |
待定 |
|
“颜色键” |
范围 |
最小=0, 最大=0x01ffffff |
平面 |
待定 |
垂直消隐¶
从计算机的角度来看,每次监视器显示新帧时,扫描引擎都会“扫描输出”从上到下显示的图像,一次一行像素。当前行的像素称为当前扫描线。
除了显示器的可视区域外,通常还有一些额外的扫描线实际上并未显示在屏幕上。 这些额外的扫描线不包含图像数据,偶尔用于音频和信息帧等功能。 由这些扫描线组成的区域称为垂直消隐区域,或简称为 vblank。
作为历史参考,垂直消隐期的设计是为了让电子枪(在 CRT 上)有足够的时间移回屏幕顶部,以便开始扫描下一帧。 水平消隐期也是如此。 它们的设计目的是为了让电子枪有足够的时间移回屏幕的另一侧,以便开始扫描下一条扫描线。
physical → ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
top of | |
display | |
| New frame |
| |
|↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓|
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| ← Scanline,
|↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓| updates the
| | frame as it
| | travels down
| | ("scan out")
| Old frame |
| |
| |
| |
| | physical
| | bottom of
vertical |⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽| ← display
blanking ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
region → ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
start of → ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
new frame
“显示器的物理顶部”是高精度/校正时间戳的参考点。
在许多显示硬件上,编程需要在垂直消隐期间生效,以便可以安全地更改伽玛、要扫描输出的图像缓冲区等设置,而不会在屏幕上显示任何视觉伪影。 在一些严苛的硬件中,某些编程必须在同一个 vblank 中开始和结束。 为了帮助进行硬件编程的计时,通常会提供一个中断来通知驱动程序何时可以开始更新寄存器。 在这种情况下,中断被称为 vblank 中断。
vblank 中断可能会在不同的时间点触发,具体取决于硬件。 某些硬件实现将在新帧开始时触发中断,而其他实现将在不同的时间点触发中断。
垂直消隐在图形渲染中起着重要作用。 要实现无撕裂显示,用户必须将页面翻转和/或渲染与垂直消隐同步。 DRM API 提供 ioctl 来执行与垂直消隐同步的页面翻转,并等待垂直消隐。
DRM 核心处理大部分垂直消隐管理逻辑,其中包括过滤掉虚假中断、保持无竞争消隐计数器、处理计数器回绕和重置以及保持使用计数。 它依靠驱动程序生成垂直消隐中断,并可以选择提供硬件垂直消隐计数器。
驱动程序必须通过调用 drm_vblank_init()
初始化垂直消隐处理核心。 至少,驱动程序需要实现 drm_crtc_funcs.enable_vblank
和 drm_crtc_funcs.disable_vblank
,并调用 drm_crtc_handle_vblank()
以获得有效的 vblank 支持。
垂直消隐中断可以由 DRM 核心或驱动程序本身启用(例如,处理页面翻转操作)。 DRM 核心维护一个垂直消隐使用计数,以确保在用户仍然需要时不会禁用中断。 要增加使用计数,驱动程序调用 drm_crtc_vblank_get()
并使用 drm_crtc_vblank_put()
再次释放 vblank 引用。 在这两个调用之间,保证启用 vblank 中断。
在许多硬件上,无法以无竞争的方式禁用 vblank 中断,请参阅 drm_vblank_crtc_config.disable_immediate
和 drm_driver.max_vblank_count
。 在这种情况下,vblank 核心仅在计时器到期后才禁用 vblank,可以通过 vblankoffdelay
模块参数配置计时器。
对于不支持垂直消隐中断的硬件的驱动程序不得调用 drm_vblank_init()
。 对于此类驱动程序,原子辅助程序将自动生成伪 vblank 事件作为显示更新的一部分。 驱动程序还可以通过启用和禁用 struct drm_crtc_state
.no_vblank 来控制此功能。
垂直消隐和中断处理函数参考¶
-
struct drm_pending_vblank_event¶
挂起的 vblank 事件跟踪
定义:
struct drm_pending_vblank_event {
struct drm_pending_event base;
unsigned int pipe;
u64 sequence;
union {
struct drm_event base;
struct drm_event_vblank vbl;
struct drm_event_crtc_sequence seq;
} event;
};
成员
基本
用于跟踪挂起的 DRM 事件的基本结构。
管道
此事件所对应的
drm_crtc
的drm_crtc_index()
。序列
应该触发帧事件的时间
event
将发送到用户空间的实际事件。
event.base
DRM 事件基类。
event.vbl
通过 MODE_PAGE_FLIP 或 MODE_ATOMIC IOCTL 请求的 vblank 事件的事件有效负载。 也由传统的 WAIT_VBLANK IOCTL 生成,但新的用户空间应改用 MODE_QUEUE_SEQUENCE 和
event.seq
。event.seq
MODE_QUEUEU_SEQUENCE IOCTL 的事件有效负载。
-
struct drm_vblank_crtc_config¶
CRTC 的 vblank 配置
定义:
struct drm_vblank_crtc_config {
int offdelay_ms;
bool disable_immediate;
};
成员
offdelay_ms
Vblank 关闭延迟(以毫秒为单位),用于确定
drm_vblank_crtc.disable_timer
在禁用之前等待的时间。默认为
drm_crtc_vblank_on()
中的 drm_vblank_offdelay 值。disable_immediate
有关立即 vblank 禁用的确切语义,请参阅
drm_device.vblank_disable_immediate
。此外,这会跟踪每个 crtc 的禁用立即值,以防它需要不同于给定设备的默认值。
默认为
drm_crtc_vblank_on()
中的drm_device.vblank_disable_immediate
的值。
-
struct drm_vblank_crtc¶
CRTC 的 vblank 跟踪
定义:
struct drm_vblank_crtc {
struct drm_device *dev;
wait_queue_head_t queue;
struct timer_list disable_timer;
seqlock_t seqlock;
atomic64_t count;
ktime_t time;
atomic_t refcount;
u32 last;
u32 max_vblank_count;
unsigned int inmodeset;
unsigned int pipe;
int framedur_ns;
int linedur_ns;
struct drm_display_mode hwmode;
struct drm_vblank_crtc_config config;
bool enabled;
struct kthread_worker *worker;
struct list_head pending_work;
wait_queue_head_t work_wait_queue;
};
成员
dev
指向
drm_device
的指针。队列
vblank 等待者的等待队列。
disable_timer
用于延迟 vblank 禁用滞后逻辑的禁用计时器。 Vblank 禁用通过
drm_vblank_crtc_config.offdelay_ms
和drm_device.max_vblank_count
值的设置来控制。seqlock
保护 vblank 计数和时间。
count
当前软件 vblank 计数器。
请注意,对于给定的 vblank 计数器值,
drm_crtc_handle_vblank()
和drm_crtc_vblank_count()
或drm_crtc_vblank_count_and_time()
提供了一个屏障:在调用drm_crtc_handle_vblank()
之前完成的任何写入对于后面的函数的调用者都是可见的,前提是 vblank 计数相同或更高。重要提示:此保证需要屏障,因此切勿直接访问此字段。 请改用
drm_crtc_vblank_count()
。时间
与 count 对应的 Vblank 时间戳。
refcount
vblank 中断的用户/等待者数量。 只有当此引用计数达到 0 时,才能使用 disable_timer 禁用硬件中断。
最后
受
drm_device.vbl_lock
保护,用于回绕处理。max_vblank_count
此 crtc 的 vblank 寄存器的最大值。 此值 +1 将导致 vblank 寄存器回绕。 它由 vblank 核心用于处理回绕。
如果设置为零,则 vblank 核心将尝试通过高精度时间戳猜测通过禁用 vblank 中断时经过的 vblank。 这种方法会因较长时间内的小竞争和不精确而受到影响,因此始终建议公开硬件 vblank 计数器。
这是通过
drm_crtc_set_max_vblank_count()
设置的运行时可配置的每个 crtc 最大值。 如果使用此方法,则驱动程序必须将设备范围的drm_device.max_vblank_count
保留为零。如果非零,则必须设置
drm_crtc_funcs.get_vblank_counter
。inmodeset
跟踪由于模式设置而禁用 vblank 的情况。 对于传统驱动程序,位 2 还会额外跟踪是否已获取额外的临时 vblank 引用以掩盖硬件计数器重置/跳变。 KMS 驱动程序应改为调用
drm_crtc_vblank_off()
和drm_crtc_vblank_on()
,它们显式保存和恢复 vblank 计数。管道
与此结构对应的
drm_crtc
的drm_crtc_index()
。framedur_ns
帧/场持续时间(以纳秒为单位),由
drm_crtc_vblank_helper_get_vblank_timestamp()
使用,并由drm_calc_timestamping_constants()
计算。linedur_ns
行持续时间(以纳秒为单位),由
drm_crtc_vblank_helper_get_vblank_timestamp()
使用,并由drm_calc_timestamping_constants()
计算。hwmode
当前硬件显示模式的缓存。 仅当设置了 enabled 时才有效。 这由
drm_crtc_vblank_helper_get_vblank_timestamp()
等辅助程序使用。 我们不能仅仅通过查看drm_crtc_state.adjusted_mode
等来访问硬件模式,因为从中断上下文很难获得该模式。配置
存储给定 CRTC 的 vblank 配置值。 另请参阅
drm_crtc_vblank_on_config()
。已启用
跟踪相应
drm_crtc
的启用状态,以避免双重禁用,从而破坏保存的状态。 使用原子 KMS 的驱动程序需要这样做,因为这些驱动程序可能会多次执行其 CRTC 禁用功能。worker
用于执行 vblank 工作的
kthread_worker
。pending_work
等待未来 vblank 的计划的
drm_vblank_work
项的列表。work_wait_queue
用于发出信号,表明
drm_vblank_work
项已完成执行或已被取消的等待队列。
描述
此结构跟踪一个 CRTC 的 vblank 状态。
请注意,由于历史原因 - vblank 处理代码仍然与传统/非 kms 驱动程序共享 - 这是一个独立的结构,不直接连接到 struct drm_crtc
。 但是,所有公共接口函数都采用 struct drm_crtc
以隐藏此实现细节。
参数
struct drm_crtc *crtc
要检索哪个计数器
描述
此函数类似于 drm_crtc_vblank_count()
,但此函数使用高精度时间戳支持进行插值以处理与 vblank 中断的竞争。
这对于可以获取扫描输出位置但没有硬件帧计数器的硬件最有用。
-
int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)¶
初始化 vblank 支持
参数
struct drm_device *dev
DRM 设备
unsigned int num_crtcs
dev 支持的 CRTC 数量
描述
此函数初始化 num_crtcs 显示管道的 vblank 支持。 清理由通过 drmm_add_action_or_reset()
添加的清理函数自动处理。
返回
成功时为零,失败时为负错误代码。
-
bool drm_dev_has_vblank(const struct drm_device *dev)¶
测试是否已初始化设备的 vblank
参数
const struct drm_device *dev
设备
描述
驱动程序可以调用此函数来测试是否已初始化设备的 vblank 支持。 对于大多数硬件,这意味着也可以启用 vblank。
原子辅助程序使用此函数来初始化 drm_crtc_state.no_vblank
。 另请参阅 drm_atomic_helper_check_modeset()
。
返回
如果已初始化给定设备的 vblank,则为 True;否则为 False。
参数
struct drm_crtc *crtc
要检索哪个 CRTC 的 vblank 等待队列
描述
此函数返回指向 CRTC 的 vblank 等待队列的指针。 驱动程序可以使用它来使用 wait_event()
和相关函数实现 vblank 等待。
-
void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode)¶
计算垂直消隐时间戳常量
参数
struct drm_crtc *crtc
drm_crtc,其时间戳常量应被更新。
const struct drm_display_mode *mode
包含扫描输出时序的显示模式
描述
计算并存储各种常量,这些常量稍后会被垂直消隐和交换完成时间戳使用,例如,通过 drm_crtc_vblank_helper_get_vblank_timestamp()
。它们源自 CRTC 的真实扫描输出时序,因此它们会考虑诸如面板缩放或其他调整之类的事情。
-
bool drm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, bool in_vblank_irq, drm_vblank_get_scanout_position_func get_scanout_position)¶
精确的垂直消隐时间戳辅助函数
参数
struct drm_crtc *crtc
要检索其垂直消隐时间戳的 CRTC
int *max_error
时间戳中允许的最大误差(纳秒)。返回时包含时间戳的真实最大误差
ktime_t *vblank_time
指向应接收时间戳的时间的指针
bool in_vblank_irq
从
drm_crtc_handle_vblank()
调用时为 True。如果设置了标志,某些驱动程序需要应用一些针对 gpu 特定垂直空白 irq 怪癖的解决方法。drm_vblank_get_scanout_position_func get_scanout_position
用于检索扫描输出位置的回调函数。参见 struct drm_crtc_helper_funcs.get_scanout_position。
描述
从给定的 drm_display_mode 时序和 CRTC 的当前视频扫描输出位置实现精确的垂直消隐时间戳计算。
当前实现仅处理标准视频模式。对于双扫描和隔行模式,驱动程序应该调整硬件模式(从 drm_crtc_state.adjusted
模式获取,适用于原子模式设置驱动程序)以匹配报告的扫描输出位置。
请注意,原子驱动程序必须在启用 CRTC 之前调用 drm_calc_timestamping_constants()
。原子辅助函数已经在 drm_atomic_helper_calc_timestamping_constants()
中处理了这个问题。
返回
成功时返回 true,失败时返回 false,即无法获取精确的时间戳。
-
bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, bool in_vblank_irq)¶
精确的垂直消隐时间戳辅助函数
参数
struct drm_crtc *crtc
要检索其垂直消隐时间戳的 CRTC
int *max_error
时间戳中允许的最大误差(纳秒)。返回时包含时间戳的真实最大误差
ktime_t *vblank_time
指向应接收时间戳的时间的指针
bool in_vblank_irq
从
drm_crtc_handle_vblank()
调用时为 True。如果设置了标志,某些驱动程序需要应用一些针对 gpu 特定垂直空白 irq 怪癖的解决方法。
描述
从给定的 drm_display_mode 时序和 CRTC 的当前视频扫描输出位置实现精确的垂直消隐时间戳计算。如果实现了 drm_crtc_helper_funcs.get_scanout_position
,则可以直接用作 KMS 驱动程序的 drm_crtc_funcs.get_vblank_timestamp
实现。
当前实现仅处理标准视频模式。对于双扫描和隔行模式,驱动程序应该调整硬件模式(从 drm_crtc_state.adjusted
模式获取,适用于原子模式设置驱动程序)以匹配报告的扫描输出位置。
请注意,原子驱动程序必须在启用 CRTC 之前调用 drm_calc_timestamping_constants()
。原子辅助函数已经在 drm_atomic_helper_calc_timestamping_constants()
中处理了这个问题。
返回
成功时返回 true,失败时返回 false,即无法获取精确的时间戳。
参数
struct drm_crtc *crtc
要检索哪个计数器
描述
获取 “cooked” 垂直消隐计数器值,该值表示自系统启动以来发生的垂直消隐事件的数量,包括由于模式设置活动而丢失的事件。请注意,此计时器对于竞争的垂直消隐中断是不正确的(因为它只报告软件垂直消隐计数器),有关此类用例,请参见 drm_crtc_accurate_vblank_count()
。
请注意,对于给定的垂直消隐计数器值,drm_crtc_handle_vblank()
和 drm_crtc_vblank_count()
或 drm_crtc_vblank_count_and_time()
提供了一个屏障:在调用 drm_crtc_handle_vblank()
之前完成的任何写入对于后一个函数的调用者都是可见的,如果垂直消隐计数是相同或更高。
另请参见 drm_vblank_crtc.count
。
返回
软件垂直消隐计数器。
-
u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, ktime_t *vblanktime)¶
检索 “cooked” 垂直消隐计数器值以及对应于该垂直消隐计数器值的系统时间戳
参数
struct drm_crtc *crtc
要检索哪个计数器
ktime_t *vblanktime
指向接收垂直消隐时间戳的时间的指针。
描述
获取 “cooked” 垂直消隐计数器值,该值表示自系统启动以来发生的垂直消隐事件的数量,包括由于模式设置活动而丢失的事件。返回与当前垂直消隐计数器值相对应的垂直消隐间隔时间的相应系统时间戳。
请注意,对于给定的垂直消隐计数器值,drm_crtc_handle_vblank()
和 drm_crtc_vblank_count()
或 drm_crtc_vblank_count_and_time()
提供了一个屏障:在调用 drm_crtc_handle_vblank()
之前完成的任何写入对于后一个函数的调用者都是可见的,如果垂直消隐计数是相同或更高。
另请参见 drm_vblank_crtc.count
。
参数
struct drm_crtc *crtc
要计算下一个垂直消隐时间的 crtc
ktime_t *vblanktime
指向接收下一个垂直消隐时间戳的时间的指针。
描述
根据上一个垂直消隐时间和帧持续时间计算下一个垂直消隐周期开始的预期时间
-
void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e)¶
在页面翻转后准备垂直消隐事件
参数
struct drm_crtc *crtc
垂直消隐事件的源 CRTC
struct drm_pending_vblank_event *e
要发送的事件
描述
许多驱动程序需要为下一个垂直消隐中断生成垂直消隐事件。例如,当页面翻转中断在页面翻转准备好时发生,而不是在实际在下一个垂直消隐周期内执行时发生。此辅助函数实现了完全所需的垂直消隐准备行为。
驱动程序将新的硬件状态提交到垂直消隐同步的寄存器中。
发生垂直消隐,提交硬件状态。此外,相应的垂直消隐中断被触发并由中断处理程序完全处理。
原子提交操作继续调用
drm_crtc_arm_vblank_event()
。该事件仅为下一个垂直消隐发送,这是错误的。
当驱动程序在写出新的硬件状态之前调用 drm_crtc_arm_vblank_event()
时,可能会发生等效的竞争。
使此方法安全工作的唯一方法是阻止垂直消隐触发(以及硬件提交任何其他内容),直到整个原子提交序列运行完成。如果硬件没有这样的功能(例如,使用 “go” 位),则使用此函数是不安全的。相反,驱动程序需要通过调用 drm_crtc_send_vblank_event()
从其中断处理程序手动发送事件,并确保硬件提交原子更新时没有可能的竞争。
调用者必须为事件 e 持有一个由 drm_crtc_vblank_get()
获取的垂直消隐引用,该引用将在下一个垂直消隐到达时被丢弃。
注意
使用此方法发送作为原子提交的一部分的 drm_crtc_state.event
的驱动程序必须确保下一个垂直消隐与原子提交提交到硬件的时间完全相同。此函数本身不防止下一个垂直消隐中断与此函数调用或原子提交操作发生竞争。一个可能的序列可能是
-
void drm_crtc_send_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e)¶
用于在页面翻转后发送垂直消隐事件的辅助函数
参数
struct drm_crtc *crtc
垂直消隐事件的源 CRTC
struct drm_pending_vblank_event *e
要发送的事件
描述
更新事件的序列号和时间戳以用于最近处理的垂直消隐,并将其发送到用户空间。调用者必须持有事件锁。
有关可以在某些情况下使用的辅助函数,尤其是用于发送原子提交操作的事件,请参见 drm_crtc_arm_vblank_event()
。
参数
struct drm_crtc *crtc
要拥有的 CRTC
描述
获取垂直消隐事件的引用计数,以避免在使用时禁用它们。
返回
成功时为零,失败时为负错误代码。
参数
struct drm_crtc *crtc
要放弃的计数器
描述
释放给定垂直消隐计数器的所有权,如果可能,则关闭中断。在 drm_vblank_crtc_config.offdelay_ms
毫秒后禁用中断。
-
void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)¶
等待一个垂直消隐
参数
struct drm_device *dev
DRM 设备
unsigned int pipe
CRTC 索引
描述
这会等待 pipe 上的一个垂直消隐过去,使用 irq 驱动程序接口。当禁用 pipe 的垂直消隐 irq 时,例如由于缺少驱动程序支持或由于 crtc 关闭,调用此函数会失败。
这是 drm_crtc_wait_one_vblank()
的旧版本。
参数
struct drm_crtc *crtc
DRM crtc
描述
这会等待 crtc 上的一个垂直消隐过去,使用 irq 驱动程序接口。当禁用 crtc 的垂直消隐 irq 时,例如由于缺少驱动程序支持或由于 crtc 关闭,调用此函数会失败。
参数
struct drm_crtc *crtc
有问题的 CRTC
描述
驱动程序可以使用此函数在禁用 crtc 时关闭垂直消隐中断处理。此函数确保存储最新的垂直消隐帧计数,以便 drm_vblank_on 可以再次恢复它。
当硬件垂直消隐计数器可以被重置时,例如在挂起或通常禁用 crtc 时,驱动程序必须使用此函数。
参数
struct drm_crtc *crtc
有问题的 CRTC
描述
驱动程序可以使用此函数在加载时将垂直消隐状态重置为关闭。驱动程序应将此函数与 drm_crtc_vblank_off()
和 drm_crtc_vblank_on()
函数一起使用。与 drm_crtc_vblank_off()
相比,不同之处在于此函数不保存垂直消隐计数器,因此不需要调用任何驱动程序挂钩。
这对于恢复驱动程序状态(例如,在驱动程序加载时或恢复时)非常有用。
参数
struct drm_crtc *crtc
有问题的 CRTC
u32 max_vblank_count
最大硬件垂直消隐计数器值
描述
在运行时更新 crtc 的最大硬件垂直消隐计数器值。对于硬件垂直消隐计数器的操作取决于当前活动的显示配置的硬件很有用。
例如,如果硬件垂直消隐计数器在特定连接器处于活动状态时不工作,则最大值可以设置为零。并且当该特定连接器不处于活动状态时,最大值可以再次设置为适当的非零值。
如果使用,必须在 drm_vblank_on() 之前调用。
-
void drm_crtc_vblank_on_config(struct drm_crtc *crtc, const struct drm_vblank_crtc_config *config)¶
使用自定义配置选项启用 CRTC 上的垂直消隐事件
参数
struct drm_crtc *crtc
有问题的 CRTC
const struct drm_vblank_crtc_config *config
垂直消隐配置值
描述
请参阅 drm_crtc_vblank_on()
。 此外,此函数允许你为给定的 CRTC 提供自定义的垂直消隐配置。
请注意,config 会被复制,指针不需要在此函数调用后仍然有效。有关参数的详细信息,请参阅 struct drm_vblank_crtc_config
。
参数
struct drm_crtc *crtc
有问题的 CRTC
描述
此函数恢复使用 drm_crtc_vblank_off()
捕获的垂直消隐中断状态,通常在启用 crtc 时调用。请注意,对 drm_crtc_vblank_on()
和 drm_crtc_vblank_off()
的调用可能是不平衡的,因此也可以在驱动程序加载代码中无条件调用,以反映 crtc 的当前硬件状态。
请注意,与 drm_crtc_vblank_on_config()
不同,此处使用默认值。
参数
struct drm_crtc *crtc
有问题的 CRTC
描述
电源管理功能可能会导致在垂直消隐禁用和启用之间重置帧计数器。 驱动程序可以在他们的 drm_crtc_funcs.enable_vblank
实现中使用此函数来估计自上次 drm_crtc_funcs.disable_vblank
以来丢失的垂直消隐,使用时间戳并更新垂直消隐计数器。
请注意,驱动程序必须具有无竞争的高精度时间戳支持,即 drm_crtc_funcs.get_vblank_timestamp
必须被连接,并且 drm_vblank_crtc_config.disable_immediate
必须设置为指示时间戳函数相对于垂直消隐硬件计数器增量是无竞争的。
-
bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)¶
处理垂直消隐事件
参数
struct drm_device *dev
DRM 设备
unsigned int pipe
发生此事件的 CRTC 的索引
描述
驱动程序应在其垂直消隐中断处理程序中调用此例程,以更新垂直消隐计数器并发送任何可能挂起的信号。
这是 drm_crtc_handle_vblank()
的旧版本。
参数
struct drm_crtc *crtc
发生此事件的位置
描述
驱动程序应在其垂直消隐中断处理程序中调用此例程,以更新垂直消隐计数器并发送任何可能挂起的信号。
这是 drm_handle_vblank()
的原生 KMS 版本。
请注意,对于给定的垂直消隐计数器值,drm_crtc_handle_vblank()
和 drm_crtc_vblank_count()
或 drm_crtc_vblank_count_and_time()
提供了一个屏障:在调用 drm_crtc_handle_vblank()
之前完成的任何写入对于后一个函数的调用者都是可见的,如果垂直消隐计数是相同或更高。
另请参见 drm_vblank_crtc.count
。
返回
如果事件成功处理则为 True,失败则为 False。
垂直消隐工作¶
许多 DRM 驱动程序需要以时间敏感的方式编程硬件,很多时候需要在扫描输出的某个区域内开始和完成,且具有截止日期。 完成此操作最安全的方法通常是在驱动程序的 IRQ 处理程序中简单地执行所述时间敏感的编程,这允许驱动程序避免在这些关键区域中被抢占。 或者更好的是,硬件甚至可以独立于 CPU 处理此类时间关键的编程。
虽然有相当数量的硬件被设计为 CPU 不需要关注极其时间敏感的编程,但在少数情况下这是不可避免的。 一些不容情的硬件可能要求某些时间敏感的编程完全由 CPU 处理,并且所述编程甚至可能花费太长时间而无法在 IRQ 处理程序中处理。 另一种这样的情况是,驱动程序需要执行一项需要在特定扫描输出周期内完成的任务,但可能会阻塞,因此无法在 IRQ 上下文中处理。 所有这些情况都无法在 Linux 中完美解决,因为我们不是实时内核,因此如果调度程序决定抢占我们,它可能会导致我们错过截止日期。 但对于某些驱动程序来说,如果我们能将我们被抢占的可能性降低到绝对最低限度,那就足够好了。
这就是 drm_vblank_work
的用武之地。 drm_vblank_work
提供了一个简单的通用延迟工作实现,它将工作执行延迟到特定的垂直消隐过去之后,然后在实时优先级执行工作。 即使系统处于高负载状态,这也能以最佳方式按时执行时间敏感的硬件编程。 drm_vblank_work
还支持重新调度,以便可以轻松实现自我重新武装的工作项。
垂直消隐工作函数参考¶
-
struct drm_vblank_work¶
延迟的工作项,它会延迟到目标垂直消隐过去之后,然后在 IRQ 上下文之外以实时优先级执行。
定义:
struct drm_vblank_work {
struct kthread_work base;
struct drm_vblank_crtc *vblank;
u64 count;
int cancelling;
struct list_head node;
};
成员
基本
将由
drm_vblank_crtc.worker
执行的基础kthread_work
项。 驱动程序不应直接与此交互,而应依赖drm_vblank_work_init()
来初始化它。vblank
指向此工作项所属的
drm_vblank_crtc
的指针。count
此工作将执行的目标垂直消隐。 驱动程序不应直接修改此值,而应使用
drm_vblank_work_schedule()
cancelling
当前正在运行的
drm_vblank_work_cancel_sync()
调用的数量。 工作项在所有调用完成后才能重新调度。node
此工作项在
drm_vblank_crtc.pending_work
中的位置。
描述
另请参阅: drm_vblank_work_schedule()
drm_vblank_work_init()
drm_vblank_work_cancel_sync()
drm_vblank_work_flush()
drm_vblank_work_flush_all()
-
to_drm_vblank_work¶
to_drm_vblank_work (_work)
从
kthread_work
中检索相应的drm_vblank_work
项
参数
_work
嵌入在
drm_vblank_work
中的kthread_work
-
int drm_vblank_work_schedule(struct drm_vblank_work *work, u64 count, bool nextonmiss)¶
调度垂直消隐工作
参数
struct drm_vblank_work *work
要调度的垂直消隐工作
u64 count
目标垂直消隐计数
bool nextonmiss
如果错过了目标垂直消隐,则延迟到下一个垂直消隐
描述
调度 work 以在 crtc 垂直消隐计数达到 count 后执行。
如果 crtc 垂直消隐计数已达到 count 并且 nextonmiss 为 false
,则工作立即开始执行。
如果 crtc 垂直消隐计数已达到 count 并且 nextonmiss 为 true
,则该工作将延迟到下一个垂直消隐(就像 count 已被指定为 crtc 垂直消隐计数 + 1 一样)。
如果已调度 work,则此函数将使用新的 count 重新调度所述工作。 这可以用于自我重新武装的工作项。
返回
如果 work 成功地(重新)调度则为 1
,如果它已经调度或取消则为 0
,或者失败时为负错误代码。
-
bool drm_vblank_work_cancel_sync(struct drm_vblank_work *work)¶
取消垂直消隐工作并等待其完成执行
参数
struct drm_vblank_work *work
要取消的垂直消隐工作
描述
取消已调度的垂直消隐工作并等待其执行完成。
在返回时,保证 work 不再被调度或运行,即使它是自我武装的。
返回
如果在工作开始执行之前取消了该工作,则为 True
,否则为 false
。
-
void drm_vblank_work_flush(struct drm_vblank_work *work)¶
等待已调度的垂直消隐工作完成执行
参数
struct drm_vblank_work *work
要刷新的垂直消隐工作
描述
等待 work 完成一次执行。
参数
struct drm_crtc *crtc
要刷新垂直消隐工作的 crtc
描述
等待 crtc 上所有当前排队的垂直消隐工作完成一次执行。
-
void drm_vblank_work_init(struct drm_vblank_work *work, struct drm_crtc *crtc, void (*func)(struct kthread_work *work))¶
初始化垂直消隐工作项
参数
struct drm_vblank_work *work
垂直消隐工作项
struct drm_crtc *crtc
其垂直消隐将触发工作执行的 CRTC
void (*func)(struct kthread_work *work)
要执行的工作函数
描述
初始化特定 crtc 的垂直消隐工作项。