内核模式设置 (KMS)¶
驱动程序必须通过在 DRM 设备上调用 drmm_mode_config_init()
来初始化模式设置核心。该函数初始化 struct drm_device
的 mode_config 字段,并且永远不会失败。完成后,必须通过初始化以下字段来设置模式配置。
int min_width, min_height; int max_width, max_height; 帧缓冲区以像素为单位的最小和最大宽度和高度。
struct drm_mode_config_funcs
*funcs; 模式设置函数。
概述¶
KMS 向用户空间呈现的基本对象结构相当简单。帧缓冲区(由 struct drm_framebuffer
表示,请参阅 帧缓冲区抽象)馈送到平面。平面由 struct drm_plane
表示,有关更多详细信息,请参阅 平面抽象。一个或多个(甚至没有)平面将其像素数据馈送到 CRTC(由 struct drm_crtc
表示,请参阅 CRTC 抽象)进行混合。在 平面合成属性 和相关章节中更详细地解释了精确的混合步骤。
对于输出路由,第一步是编码器(由 struct drm_encoder
表示,请参阅 编码器抽象)。这些实际上只是用于实现 KMS 驱动程序的辅助库的内部产物。除此之外,它们使用户空间不必要地更难以弄清楚 CRTC 和连接器之间的哪些连接是可能的,以及支持哪种克隆,它们在用户空间 API 中没有任何用途。不幸的是,编码器已暴露给用户空间,因此此时无法删除它们。此外,暴露的限制通常由驱动程序错误地设置,并且在许多情况下不足以表达实际的限制。一个 CRTC 可以连接到多个编码器,并且对于一个活动的 CRTC,必须至少有一个编码器。
显示链中的最终也是真正的端点是连接器(由 struct drm_connector
表示,请参阅 连接器抽象)。连接器可以有不同的可能编码器,但内核驱动程序会为每个连接器选择要使用的编码器。用例是 DVI,它可以在模拟和数字编码器之间切换。编码器还可以驱动多个不同的连接器。每个活动编码器都有一个活动的连接器。
在内部,输出管道稍微复杂一些,并且更接近当今的硬件
在内部,另外两个辅助对象会发挥作用。首先,为了能够共享编码器的代码(有时在同一 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
,如果修饰符启用超出 fourcc 像素格式代码的其他平面。这是 GETFB2 ioctl 所必需的。如果参数被认为是有效的,并且底层内存管理器中的后备存储对象都存在,那么驱动程序会分配一个新的
drm_framebuffer
结构,该结构被子类化以包含特定于驱动程序的信息(如内部本机缓冲区对象引用)。它还需要填写所有相关元数据,这应该通过调用drm_helper_mode_fill_fb_struct()
来完成。初始化通过调用
drm_framebuffer_init()
完成,该函数注册帧缓冲区并使其可供其他线程访问。返回
具有初始引用计数 1 的新帧缓冲区或使用
ERR_PTR()
编码的负错误代码。get_format_info
允许驱动程序为特殊的 fb 布局(例如,具有辅助压缩控制平面的布局)返回自定义格式信息。
返回
特定于给定 fb 元数据的格式信息,如果未找到,则返回 NULL。
mode_valid
设备特定显示模式验证。可用于拒绝永远无法支持的模式。此处只能检查设备范围的约束。crtc/encoder/bridge/connector 的特定约束应在每个特定对象的 .mode_valid() 钩子中检查。
atomic_check
这是验证原子模式设置更新的唯一钩子。此函数必须拒绝硬件或驱动程序不支持的任何模式设置和状态更改。这包括但不限于:
检查模式、帧缓冲区、缩放和放置要求等是否在硬件的限制范围内。
检查任何隐藏的共享资源是否未被过度订阅。这可以是共享 PLL、共享通道、总体内存带宽、显示 FIFO 空间(在平面或甚至 CRTC 之间共享)。
检查导出到用户空间的虚拟资源是否未被过度订阅。出于各种原因,暴露比物理上存在的更多平面、crtc 或编码器可能是有意义的。一个示例是双管道操作(如果硬件以锁定方式步进,则通常应隐藏在用户空间中,否则会暴露),其中一个平面可能需要 1 个硬件平面(如果它仅在一个管道上),2 个硬件平面(当它跨越两个管道时)或者甚至与第二个平面共享一个硬件平面(如果另一个管道处理的区域上请求了兼容的平面)。
检查任何过渡状态是否可能,以及如果请求,更新是否确实可以在垂直消隐期内完成,而不会临时禁用某些功能。
检查驱动程序或硬件可能存在的任何其他约束。
此回调还需要正确填充此更新中的
drm_crtc_state
,以确保drm_atomic_crtc_needs_modeset()
反映可能更新的性质,并且当且仅当更新无法在单个垂直消隐期间在 CRTC 上无撕裂地应用时才返回 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()
或其导出的子函数之一来实现此钩子。非阻塞提交(如 nonblock 参数所示)必须在此回调的上下文中完成任何可能导致提交失败的准备工作。唯一的例外是导致 -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
希望对结构
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;
int min_width, min_height;
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 *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 跟踪对象。将此 idr 用于所有 ID、fb、crtc、连接器、模式 - 仅使用一个就可以更轻松地生活。
tile_idr
使用此 idr 为诸如某些高分辨率 DP MST 屏幕中使用的平铺接收器分配新 ID。
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
原始自旋锁,用于保护访问显示硬件或模式设置软件状态的关键代码段,必须防止 panic 打印代码访问这些代码段。请参阅
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 完全禁用 - 所有连接器都必须关闭,并且 active 也必须设置为禁用。
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
可选的连接器属性,指示 LCD 面板在机壳内的安装方式(例如,正常或倒置)。
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 枚举属性。
preferred_depth
首选的 RGB 像素深度,供 fb 辅助函数使用
prefer_shadow
提示用户空间首选使用 shadow-fb 渲染
quirk_addfb_prefer_xbgr_30bpp
为保持旧版 ADDFB 与 nouveau 用户空间兼容而进行的特殊 hack。 仅应由 nouveau 内核驱动程序设置。
quirk_addfb_prefer_host_byte_order
如果设置为 true,则 drm_mode_addfb() 在调用 drm_mode_addfb2() 时会选择主机字节序像素格式。这本应是 drm_mode_addfb() 的工作方式。但实际上并非如此,所以我们最终在内核和用户空间驱动程序中都使用了 quirk 来处理这种错误行为。简单地无条件修复 drm_mode_addfb() 会破坏这些驱动程序,因此在此处添加一个 quirk 位以允许驱动程序选择加入。
async_page_flip
此设备是否支持主平面上的异步翻转?
fb_modifiers_not_supported
设置此标志后,DRM 设备不会向用户空间公开修改器支持。这仅由通过启发式方法推断缓冲区布局而不使用修改器的旧版驱动程序使用。新驱动程序不应设置此标志。
normalize_zpos
如果为 true,drm 核心将从
drm_atomic_helper_check()
中调用drm_atomic_normalize_zpos()
作为原子模式检查的一部分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
hook 来完成的,用于struct drm_crtc
。对于struct drm_plane
,hook 是drm_plane_funcs.atomic_get_property
和drm_plane_funcs.atomic_set_property
。对于struct drm_connector
,hook 是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 的给定属性的默认状态
只有原子驱动程序才应直接调用此函数,因为对于非原子驱动程序,它将返回当前值。
返回
成功时为零,失败时为错误代码。
原子模式设置¶
原子提供了事务性的模式设置(包括平面)更新,但与通常的尝试提交和回滚的事务方法略有不同
首先,当提交失败时,不允许进行任何硬件更改。这使我们可以实现 DRM_MODE_ATOMIC_TEST_ONLY 模式,该模式允许用户空间探索某些配置是否有效。
这仍然允许只设置和回滚软件状态,从而简化现有驱动程序的转换。但是,要审计驱动程序中 atomic_check 代码的正确性就变得非常困难:回滚遍布各处的数据结构中的更改很难做到正确。
最后,为了向后兼容并支持所有用例,原子更新需要是增量的并且能够并行执行。硬件并不总是允许这样做,但在可能的情况下,不同 CRTC 上的平面更新不应相互干扰,并且不会因为不同 CRTC 上输出路由的更改而停滞。
总而言之,原子设计有两个结果
整体状态被拆分为每个对象的状态结构:平面的
struct drm_plane_state
、CRTC 的struct drm_crtc_state
和连接器的struct drm_connector_state
。这些是唯一具有用户可见和可设置状态的对象。对于内部状态,驱动程序可以通过嵌入来子类化这些结构,或者为其全局共享的硬件功能添加全新的状态结构,请参阅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
)并不能完全映射到底层硬件。特别是对于任何类型的共享资源(例如,在多个平面或 CRTC 组之间共享的共享时钟、缩放器单元、带宽和 FIFO 限制等),将这些建模为独立对象是有意义的。然后,驱动程序需要为这些私有对象(因为不暴露给用户空间)执行类似的状态跟踪和提交排序,就像原子核心和辅助函数已经为连接器、平面和 CRTC 提供的那样。
为了使驱动程序更容易,原子核心提供了一些支持,以使用结构 drm_private_obj
跟踪驱动程序私有状态对象,以及关联的状态结构 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
上进行筛选,至少在它们想要迭代给定类型的所有对象时是这样。
处理驱动程序私有状态的早期方法是通过子类化结构 drm_atomic_state
。但是,由于这鼓励了实现检查/提交拆分原子操作的非标准方法(例如,使用“检查和回滚或提交”而不是“复制状态,检查,然后提交或释放复制的状态”),因此不建议使用它,而建议使用 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 晚得多,因为当屏幕变黑时它可能已经发出信号,而要完全关闭管道则需要更多的寄存器 I/O。
请注意,这不需要包括单独引用计数的资源,如后备存储缓冲区固定或运行时电源管理。
驱动程序应调用
drm_atomic_helper_commit_hw_done()
来发出此阶段完成的信号。cleanup_done
在调用
drm_atomic_helper_cleanup_planes()
清理旧缓冲区后将发出信号。由于这只能在垂直消隐等待完成后发生,因此可能会晚一些。此完成对于限制更新并避免硬件更新过多地领先于缓冲区清理非常有用。驱动程序应调用
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 的完成获取第二个引用后设置的标志。它被释放代码用来在提交失败时删除第二个引用。
描述
此结构用于跟踪每个 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
,则应实现此可选钩子以打印其他特定于驱动程序的状态。不要直接调用此函数,请改用 drm_atomic_private_obj_print_state()。
描述
这些钩子由原子助手用来创建、交换和销毁私有对象的状态。该结构本身用作 vtable 来标识关联的私有对象类型。每个需要添加到原子状态的私有对象类型都应实现这些钩子,并将指向其 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 共享的状态,则必须适当注意确保非阻塞提交正确排序,以避免发生释放后使用问题。
实际上,假设在两个不同的 drm_crtc
上使用不同的 drm_plane
和 drm_connector
进行两次非阻塞 drm_atomic_commit
的序列,因此在没有共享资源的情况下,无法保证哪个提交将首先发生。但是,第二个 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()
的输出。legacy_cursor_update
强制执行旧式光标 IOCTL 语义的提示。
警告:这完全损坏,并且几乎不可能正确实现。驱动程序必须忽略此项,而应实现
drm_plane_helper_funcs.atomic_async_check
和drm_plane_helper_funcs.atomic_async_commit
钩子。不允许此标志的新用户。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()
将状态添加到原子更新中。
-
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)¶
获取平面状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_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)¶
获取平面状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取的平面
描述
此函数返回给定平面的旧平面状态,如果平面不是全局原子状态的一部分,则返回 NULL。
-
struct drm_plane_state *drm_atomic_get_new_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane)¶
获取平面状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取的平面
描述
此函数返回给定平面的新平面状态,如果平面不是全局原子状态的一部分,则返回 NULL。
-
struct drm_connector_state *drm_atomic_get_existing_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector)¶
获取连接器状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_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)¶
获取连接器状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_connector *connector
要获取的连接器
描述
此函数返回给定连接器的旧连接器状态,如果该连接器不属于全局原子状态,则返回 NULL。
-
struct drm_connector_state *drm_atomic_get_new_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector)¶
获取连接器状态(如果存在)
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_connector *connector
要获取的连接器
描述
此函数返回给定连接器的新连接器状态,如果该连接器不属于全局原子状态,则返回 NULL。
-
const struct drm_plane_state *__drm_atomic_get_current_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane)¶
获取当前平面状态
参数
const struct drm_atomic_state *state
全局原子状态对象
struct drm_plane *plane
要获取的平面
描述
此函数返回给定平面的平面状态,要么来自 state,要么如果平面不属于原子状态更新,则来自 plane。这在原子检查回调中很有用,当驱动程序需要查看但不更改其他平面的状态时,因为它避免了将错误代码向上传递到调用链中。
警告
请注意,此函数通常是不安全的,因为它不检查访问状态结构所需的锁定。驱动程序必须确保通过其他方式访问返回的状态结构是安全的。一个常见的例子是,当平面固定到单个 CRTC 时,并且驱动程序知道 CRTC 锁已经持有。在这种情况下,持有 CRTC 锁可以对连接到该 CRTC 的所有平面进行读锁定。但是,如果可以重新分配平面,事情会变得更加棘手。在这种情况下,最好使用 drm_atomic_get_plane_state 并连接完整的错误处理。
指向当前平面状态的只读指针。
返回
-
for_each_oldnew_connector_in_state¶
for_each_oldnew_connector_in_state (__state, connector, old_connector_state, new_connector_state, __i)
在原子更新中迭代所有连接器
参数
__state
connector
struct drm_connector
迭代游标old_connector_state
struct drm_connector_state
用于旧状态的迭代游标new_connector_state
struct drm_connector_state
用于新状态的迭代游标__i
int 迭代游标,供宏内部使用
描述
这将迭代原子更新中的所有连接器,跟踪旧状态和新状态。这在需要考虑状态增量的地方很有用,例如在原子检查函数中。
-
for_each_old_connector_in_state¶
for_each_old_connector_in_state (__state, connector, old_connector_state, __i)
在原子更新中迭代所有连接器
参数
__state
connector
struct drm_connector
迭代游标old_connector_state
struct drm_connector_state
用于旧状态的迭代游标__i
int 迭代游标,供宏内部使用
描述
这将迭代原子更新中的所有连接器,仅跟踪旧状态。这在禁用函数中很有用,在禁用函数中,我们需要硬件仍处于的旧状态。
-
for_each_new_connector_in_state¶
for_each_new_connector_in_state (__state, connector, new_connector_state, __i)
在原子更新中迭代所有连接器
参数
__state
connector
struct drm_connector
迭代游标new_connector_state
struct drm_connector_state
用于新状态的迭代游标__i
int 迭代游标,供宏内部使用
描述
这将迭代原子更新中的所有连接器,仅跟踪新状态。这在启用函数中很有用,在启用函数中,我们需要原子提交操作完成后硬件应处于的新状态。
-
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)
在原子更新中迭代所有平面
参数
__state
plane
struct drm_plane
迭代游标old_plane_state
struct drm_plane_state
用于旧状态的迭代游标new_plane_state
struct drm_plane_state
用于新状态的迭代游标__i
int 迭代游标,供宏内部使用
描述
这将迭代原子更新中的所有平面,跟踪旧状态和新状态。这在需要考虑状态增量的地方很有用,例如在原子检查函数中。
-
for_each_oldnew_plane_in_state_reverse¶
for_each_oldnew_plane_in_state_reverse (__state, plane, old_plane_state, new_plane_state, __i)
以相反的顺序迭代原子更新中的所有平面
参数
__state
plane
struct drm_plane
迭代游标old_plane_state
struct drm_plane_state
用于旧状态的迭代游标new_plane_state
struct drm_plane_state
用于新状态的迭代游标__i
int 迭代游标,供宏内部使用
描述
此函数以相反的顺序迭代原子更新中的所有平面,同时跟踪旧状态和新状态。这在需要考虑状态变化的地方很有用,例如在原子检查函数中。
-
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)
在原子更新中迭代所有平面
参数
__state
plane
struct drm_plane
迭代游标old_plane_state
struct drm_plane_state
用于旧状态的迭代游标__i
int 迭代游标,供宏内部使用
描述
此函数迭代原子更新中的所有平面,仅跟踪旧状态。这在禁用函数中很有用,我们需要硬件仍然处于的旧状态。
-
for_each_new_plane_in_state¶
for_each_new_plane_in_state (__state, plane, new_plane_state, __i)
在原子更新中迭代所有平面
参数
__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
drm_crtc_state
用于 CRTC
描述
为了给驱动程序灵活性,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
drm_crtc_state
用于 CRTC
描述
在自刷新模式下,crtc_state->active 值将为 false,因为 CRTC 已关闭。但是,在某些情况下,我们对 CRTC 是否处于活动状态或有效活动状态(即:它是否连接到活动显示器)感兴趣。在这些情况下,请使用此函数,而不仅仅是检查 active。
-
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** 的连接器与有先前连接器的提交(并检查其状态)有时很有用,因为管道已更改。
返回
连接到 **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** 的连接器与有连接器的提交(并检查其状态)有时很有用,因为管道将发生更改。
返回
连接到 **encoder** 的新连接器,如果编码器未连接,则为 NULL。
-
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
将状态打印到何处
描述
仅用于调试。驱动程序可能需要在发生错误中断时选择将状态转储到 dmesg。(提示,您可能需要限制此操作!)
调用者必须包装此 drm_modeset_lock_all_ctx()
和 drm_modeset_drop_locks()
。如果这是从错误中断处理程序调用的,则默认情况下不应启用它 - 如果您正在调试错误,您可能不关心这是否是竞争性的,但是在没有保持所有模式设置锁的情况下调用此函数本质上是不安全的。
原子模式设置 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 状态上设置一个模式(源自内核)并更新启用属性。
返回
成功时返回零,失败时返回错误代码。不能返回 -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
用于平面的帧缓冲区
描述
更改平面的分配帧缓冲区需要我们获取新帧缓冲区的引用并删除旧帧缓冲区的引用(如果有)。此函数处理所有这些细节,除了更新状态对象本身的指针。
-
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 控制。
活动
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 状态更改,驱动程序都应设置此项。如果例如仅通过更改缩放器设置就可以在不进行完全模式设置的情况下完成 mode 更改,他们也可以将其重置为 false。
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 的平面 (plane) 的 drm_plane_mask(plane) 的位掩码。
connector_mask
附加到此 CRTC 的连接器 (connector) 的 drm_connector_mask(connector) 的位掩码。
encoder_mask
附加到此 CRTC 的编码器 (encoder) 的 drm_encoder_mask(encoder) 的位掩码。
adjusted_mode
内部显示时序,驱动程序可以使用它来处理用户空间在 mode 中请求的模式与实际编程到硬件中的模式之间的差异。
对于使用
drm_bridge
的驱动程序,此字段存储 CRTC 和第一个桥接器之间使用的硬件显示时序。对于其他驱动程序,adjusted_mode 字段的含义纯粹是驱动程序实现定义的信息,通常用于存储 CRTC 和编码器块之间使用的硬件显示时序。mode
用户空间请求的显示时序。驱动程序应尝试尽可能地匹配刷新率(但请注意,究竟多接近才算足够是未定义的,例如,某些 HDMI 模式仅在刷新率上相差不到 1%)。用户空间用于定位平面的活动宽度和高度必须完全匹配。
对于接收器未固定的外部连接器(例如内置面板),此处的模式应与线上的物理模式在最后一个细节上匹配(即,包括同步极性和所有内容)。
mode_blob
用于 mode 的
drm_property_blob
,用于向原子用户空间公开模式。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)的颜色映射(有时也称为颜色查找表、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。在这种情况下,可以在硬件停止扫描输出当前帧缓冲区之后的任何时间发送事件。它应包含显示管道关闭之前最后一次垂直消隐的时间戳和计数器。实现此目的的最简单方法是在调用
drm_crtc_vblank_off()
之后的某个时间调用drm_crtc_send_vblank_event()
。对于在提交结束时启用的 CRTC(即使它经历了完整的模式设置),垂直消隐时间戳和计数器必须是扫描输出新缓冲区集的第一帧之前的垂直消隐的时间戳和计数器。同样,只有在硬件停止扫描输出旧缓冲区之后才能发送事件。
不允许禁用 CRTC 的事件,驱动程序可以忽略这种情况。
对于没有垂直消隐中断的非常简单的硬件,启用
struct drm_crtc_state
.no_vblank 会使 DRM 的原子提交辅助程序在应用所有硬件更改后,在显示更新结束时发送一个伪 VBLANK 事件。请参阅drm_atomic_helper_fake_vblank()
。对于更复杂的硬件,可以通过
drm_crtc_send_vblank_event()
函数来处理,驱动程序应在原子提交完成后对提供的事件调用该函数。请注意,如果驱动程序支持垂直消隐信号和时间戳,则垂直消隐计数器和时间戳必须与页面翻转事件返回的计数器和时间戳一致。使用当前的垂直消隐辅助程序基础架构,可以通过在页面翻转挂起时保持垂直消隐引用来实现此目的,该引用通过drm_crtc_vblank_get()
获取,并通过drm_crtc_vblank_put()
释放。驱动程序可以自由地实现他们自己的垂直消隐计数器和时间戳跟踪,例如,如果它们在硬件中具有精确的时间戳寄存器。对于支持某种方法将垂直消隐中断的传递与提交显示状态同步的硬件,还有
drm_crtc_arm_vblank_event()
。有关安全使用它的约束的详细讨论,请参阅该函数的文档。如果设备根本无法以无竞争方式通知翻转完成,则应在页面翻转提交后立即配置事件。在最坏的情况下,驱动程序会将事件发送到用户空间晚一帧。这不允许真正的原子更新,但应避免撕裂。
commit
此项跟踪此更新的提交如何通过各个阶段。除非我们销毁状态,否则它永远不会被清除,以便后续提交可以与之前的提交同步。
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);
};
成员
reset
将 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 内核将在事件参数中提供一个
struct drm_event
。这可以通过drm_crtc_send_vblank_event()
函数处理,驱动程序应在翻转完成后在提供的事件上调用此函数。请注意,如果驱动程序支持垂直消隐信号和时间戳,则垂直消隐计数器和时间戳必须与页面翻转事件返回的计数器和时间戳一致。使用当前的垂直消隐辅助基础设施,可以通过在页面翻转挂起时保持垂直消隐引用来实现这一点,该引用通过drm_crtc_vblank_get()
获取,并通过drm_crtc_vblank_put()
释放。驱动程序可以自由实现自己的垂直消隐计数器和时间戳跟踪,例如,如果它们在硬件中有准确的时间戳寄存器。此回调是可选的。
注意
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
这个可选钩子应该用于取消注册从 late_register 附加到 CRTC 的额外用户空间接口。它从
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 源传递给用户空间之前对其进行验证。
如果驱动程序不支持导出可能的 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 核心将在基于系统时间戳的禁用中断期间考虑错过的垂直消隐事件。
由于模式设置导致的事件回绕处理和丢失在 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() 调用。应该返回最近的垂直消隐间隔结束或将要结束时的精确时间戳。
具体来说,vblank_time 中的时间戳应尽可能接近视频帧的第一个视频扫描线在垂直消隐结束后开始扫描输出的时间,即垂直消隐间隔结束后立即的时间。如果 crtc 当前在垂直消隐内,这将是未来的时间。如果 crtc 当前正在扫描输出一个帧,这将是当前扫描输出的过去开始时间。这旨在遵守 OpenML OML_sync_control 扩展规范。
参数
- crtc
应返回时间戳的 CRTC。
- max_error
允许的最大时间戳误差,以纳秒为单位。实现应努力提供时间戳,其误差最大为 max_error 纳秒。返回时间戳误差的真实上限。
- vblank_time
返回的垂直消隐时间戳的目标位置。
- in_vblank_irq
从
drm_crtc_handle_vblank()
调用时为 True。如果设置了标志,一些驱动程序需要为 GPU 特定的垂直消隐 irq 怪癖应用一些解决方法。
返回值
成功时为 True,失败时为 false,这意味着核心应该回退到
drm_crtc_handle_vblank()
中获取的简单时间戳。
描述
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 对象。
primary
此 CRTC 的主平面。请注意,这仅与旧版 IOCTL 相关,它指定了 SETCRTC 和 PAGE_FLIP IOCTL 隐式使用的平面。除此之外,它没有任何意义。
cursor
此 CRTC 的光标平面。请注意,这仅与旧版 IOCTL 相关,它指定了 SETCURSOR 和 SETCURSOR2 IOCTL 隐式使用的平面。除此之外,它没有任何意义。
index
在 mode_config.list 中的位置,可以用作数组索引。它在 CRTC 的生命周期中保持不变。
cursor_x
光标的当前 x 位置,用于通用光标平面,因为 SETCURSOR IOCTL 只能在不提供坐标的情况下更新帧缓冲区。驱动程序不应直接使用此值,原子驱动程序应查看光标平面的
drm_plane_state.crtc_x
。cursor_y
光标的当前 y 位置,用于通用光标平面,因为 SETCURSOR IOCTL 只能在不提供坐标的情况下更新帧缓冲区。驱动程序不应直接使用此值,原子驱动程序应查看光标平面的
drm_plane_state.crtc_y
。enabled
此 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
报告给用户空间的旧式 gamma 斜坡的大小。通过调用
drm_mode_crtc_set_gamma_size()
设置。请注意,原子驱动程序需要改为使用
drm_crtc_state.gamma_lut
。请参阅drm_crtc_enable_color_mgmt()
。gamma_store
旧式 SETGAMMA 和 GETGAMMA IOCTls 使用的 gamma 斜坡值。通过调用
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
包含结构
drm_crtc
的结构的类型member
type 中的
drm_crtc
的名称。primary
CRTC 的主平面
cursor
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, ...)¶
使用指定的 primary 和 cursor 平面初始化新的 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()
,它仅为向后兼容尚不支持通用平面的驱动程序提供。对于只有一个平面的非常简单的硬件,请查看 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, ...)¶
使用指定的 primary 和 cursor 平面初始化新的 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()
,它仅为向后兼容尚不支持通用平面的驱动程序提供。对于只有一个平面的非常简单的硬件,请查看 drm_simple_display_pipe_init()
。
清理工作通过使用 drmm_add_action()
注册 drmm_crtc_cleanup() 自动处理。crtc 结构应使用 drmm_kzalloc()
分配。
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
要设置的 modeset 配置
描述
这是一个小的辅助函数,用于包装对 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
颜色管理函数参考¶
-
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]
注意
- 如果所有位精度都用于表示小数,则 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
反伽玛查找表的大小(在 CSC 之前)
bool has_ctm
是否为 CSC 矩阵附加 ctm_property
uint gamma_lut_size
伽玛查找表的大小(在 CSC 之后)
描述
此函数允许驱动程序在 CRTC 上启用颜色校正属性。这包括用户空间可以设置的 3 个反伽玛、csc 和伽玛属性,以及 2 个大小属性以通知用户空间查找表的大小。每个属性都是可选的。只有当伽玛和反伽玛属性的大小不为 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
用于 dirty fb IOCTL 的可选回调。
用户空间可以通过此回调通知驱动程序帧缓冲区的某个区域已更改,应刷新到显示硬件。这也可以在内部使用,例如通过 fbdev 仿真,尽管目前情况并非如此。
有关更多信息,请参见 drm_mode.h 中的 struct 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
放置在
drm_mode_config.fb_list
上,访问受drm_mode_config.fb_lock
保护。基础
基本模式设置对象结构,包含引用计数。
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/平面是异步的,并且扫描输出直到下一个 vblank 才真正完成。因此,某些清理(如释放后备 GEM bo(s) 上的引用)应延迟。在这种情况下,即使已从用户空间角度删除 fb,驱动程序也希望保留对 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 - 如果它仍然在任何地方使用,则可能会导致混乱,因为用户空间可能会在 id 上调用 getfb 并返回 -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 对。此 format:modifier 对必须完全定义缓冲区的格式和数据布局,并且应该是描述该特定缓冲区的唯一方法。
应避免使用描述相同布局的多个 fourcc:modifier 对,因为此类别名可能会导致不同的驱动程序为相同的数据格式公开不同的名称,从而迫使用户空间了解它们是别名。
格式修饰符可能会更改缓冲区的任何属性,包括平面数量和/或所需的分配大小。格式修饰符是供应商命名空间的,因此 fourcc 代码和修饰符之间的关系特定于所使用的修饰符。例如,某些修饰符可能会保留 fourcc 代码的含义 - 例如平面数量 - 而其他修饰符可能不会。
修饰符必须唯一地编码缓冲区布局。换句话说,缓冲区必须仅匹配单个修饰符。修饰符不得是另一个修饰符布局的子集。例如,在修饰符中编码 pitch 对齐是不正确的:缓冲区可能匹配 64 像素对齐的修饰符和 32 像素对齐的修饰符。也就是说,修饰符可以具有隐式的最小要求。
对于 fourcc 代码和修饰符的组合可以别名的修饰符,需要定义一个规范对,并由所有驱动程序使用。如果所有组合都可能导致混淆并降低不必要的互操作性,则还鼓励使用首选组合。后者的一个例子是 AFBC,其中 ABGR 布局优先于 ARGB 布局。
修饰符用户有两种:
内核和用户空间驱动程序:对于驱动程序来说,修饰符不应该别名很重要,否则两个驱动程序可能支持相同的格式,但使用不同的别名,从而阻止它们以高效的格式共享缓冲区。
与 KMS/GBM/EGL/Vulkan/etc 接口的更高级程序:这些用户将修饰符视为它们可以检查相等性和交叉的不透明令牌。这些用户不需要知道推理修饰符值(即,不希望他们从修饰符中提取信息)。
供应商应尽可能详细地记录其修饰符的使用情况,以确保跨设备、驱动程序和应用程序的最大兼容性。
格式修饰符代码的权威列表位于 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_*)
深度
颜色深度(每个像素的位数,不包括填充位),仅对 RGB 格式的子集有效。这是一个遗留字段,请勿在新代码中使用,对于新格式请设置为 0。
num_planes
颜色平面数(1 到 3)
{unnamed_union}
匿名
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
格式信息
返回
一个布尔值,指示格式信息是否与打包的 YUV 格式匹配。
-
bool drm_format_info_is_yuv_semiplanar(const struct drm_format_info *info)¶
检查格式信息是否与以两个平面布局的 YUV 格式(亮度和色度)匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与半平面 YUV 格式匹配。
-
bool drm_format_info_is_yuv_planar(const struct drm_format_info *info)¶
检查格式信息是否与以三个平面布局的 YUV 格式(每个 YUV 分量一个平面)匹配
参数
const struct drm_format_info *info
格式信息
返回
一个布尔值,指示格式信息是否与平面 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
平面索引
返回
plane 的宽度,前提是第一个平面的宽度为 width。
-
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
来自用户空间帧缓冲区创建请求的元数据
返回
描述像素格式的 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)¶
计算最小的所需跨距(以字节为单位)
参数
const struct drm_format_info *info
像素格式信息
int plane
平面索引
unsigned int buffer_width
缓冲区的像素宽度
返回
通过考虑像素格式信息和缓冲区宽度,计算缓冲区所需的最小跨距(以字节为单位)。
Dumb 缓冲区对象¶
KMS API 没有标准化后备存储对象的创建,而是将其留给驱动程序特定的 ioctl。此外,即使对于基于 GEM 的驱动程序,实际创建缓冲区对象也是通过驱动程序特定的 ioctl 完成的 - GEM 仅具有用于共享和销毁对象的通用用户空间接口。虽然对于包含设备特定用户空间组件(例如在 libdrm 中)的成熟图形堆栈来说这不是问题,但此限制使基于 DRM 的早期启动图形变得不必要的复杂。
Dumb 对象通过提供一个用于创建适用于扫描输出的哑缓冲区的标准 API 来部分缓解此问题,然后可以使用该 API 来创建 KMS 帧缓冲区。
为了支持哑对象,驱动程序必须实现 drm_driver.dumb_create
和 drm_driver.dumb_map_offset
操作(如果未设置,则后者默认为 drm_gem_dumb_map_offset()
)。不使用 GEM 句柄的驱动程序还需要实现 drm_driver.dumb_destroy
操作。有关详细信息,请参阅回调。
请注意,哑对象可能不用于 GPU 加速,正如某些 ARM 嵌入式平台上尝试的那样。此类驱动程序确实必须具有硬件特定的 ioctl 来分配合适的缓冲区对象。
平面抽象¶
平面表示一个图像源,可以在扫描输出过程中与 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 必须有一个独特的主平面,用户空间可以附加该平面来启用 CRTC。换句话说,用户空间必须能够同时将不同的主平面附加到每个 CRTC。主平面仍然可以与多个 CRTC 兼容。主平面的数量必须与 CRTC 的数量完全相同。
传统的 uAPI 不会直接暴露主平面和光标平面。DRM 核心依赖驱动程序来设置用于传统 IOCTL 的主平面和可选的光标平面。这是通过调用 drm_crtc_init_with_planes()
完成的。所有驱动程序都必须为每个 CRTC 提供一个主平面,以避免让传统的用户空间感到意外。
平面函数参考¶
-
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()
栅栏
在扫描输出 fb 之前要等待的可选栅栏。当用户空间使用显式栅栏时,核心原子代码将设置此项。不要直接为驱动程序的隐式栅栏写入此字段。
驱动程序应将任何隐式栅栏存储在它们的
drm_plane_helper_funcs.prepare_fb
回调中。有关合适的助手,请参阅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
将损坏(自上次平面更新以来平面帧缓冲区中发生更改的区域)表示为
drm_mode_rect
数组的 Blob,以附加帧缓冲区的帧缓冲区坐标表示。请注意,与平面 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
要应用的缩放滤镜
commit
跟踪挂起的提交以防止释放后使用条件,并用于异步平面更新。
可以为 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);
};
成员
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 中热插拔。reset
将平面硬件和软件状态重置为关闭。此函数不由核心直接调用,仅通过
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。
-
enum drm_plane_type¶
uapi 平面类型枚举
常量
DRM_PLANE_TYPE_OVERLAY
覆盖平面表示所有非主平面、非光标平面。一些驱动程序在内部将这些类型的平面称为“精灵”。
DRM_PLANE_TYPE_PRIMARY
当不使用缩放/裁剪并且平面覆盖整个 CRTC 时,附加到 CRTC 的主平面最有可能能够点亮 CRTC。
DRM_PLANE_TYPE_CURSOR
当不使用缩放/裁剪并且帧缓冲具有
drm_mode_config.cursor_width
和drm_mode_config.cursor_height
指示的大小,并且如果驱动程序不支持修饰符,则帧缓冲应该具有线性布局时,附加到 CRTC 的光标平面更有可能被启用。
描述
由于历史原因,并非所有平面都相同。此枚举用于区分不同类型的平面,以实现它们的不同 uapi 语义。对于通用平面感知的用户空间以及正在使用原子 IOCTL 的用户空间,这些平面之间没有区别(当然,除了驱动程序和硬件可以支持的内容之外)。
为了与旧版用户空间兼容,默认情况下只向用户空间提供覆盖平面。用户空间客户端可以设置 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
。index
mode_config.list 中的位置,可以用作数组索引。在平面的生命周期内是不变的。
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
此平面可选的旋转属性。请参阅
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
由 DRM_FORMAT_MOD_INVALID 终止的结构体 drm_format 修饰符数组
plane_type
平面类型(覆盖、主、光标)
名称
平面名称的 printf 样式格式字符串,如果使用默认名称则为 NULL
...
可变参数
描述
分配并初始化 type 类型的平面对象。清理工作通过使用 drmm_add_action()
注册 drm_plane_cleanup()
来自动处理。
drm_plane_funcs.destroy 钩子必须为 NULL。
仅支持 DRM_FORMAT_MOD_LINEAR 修饰符的驱动程序可以将 format_modifiers 设置为 NULL。该平面将通告线性修饰符。
返回
指向新平面的指针,如果失败则为 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
由 DRM_FORMAT_MOD_INVALID 终止的结构体 drm_format 修饰符数组
plane_type
平面类型(覆盖、主、光标)
名称
平面名称的 printf 样式格式字符串,如果使用默认名称则为 NULL
...
可变参数
描述
分配并初始化 type 类型的平面对象。调用者负责使用 kfree()
释放已分配的内存。
鼓励驱动程序使用 drmm_universal_plane_alloc()
。
仅支持 DRM_FORMAT_MOD_LINEAR 修饰符的驱动程序可以将 format_modifiers 设置为 NULL。该平面将通告线性修饰符。
返回
指向新平面的指针,如果失败则为 ERR_PTR。
参数
const struct drm_plane *plane
要查找索引的平面
描述
给定一个已注册的平面,返回该平面在 DRM 设备平面列表中的索引。
参数
const struct drm_plane *plane
要查找掩码的平面
-
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
由 DRM_FORMAT_MOD_INVALID 终止的结构体 drm_format 修饰符数组
enum drm_plane_type type
平面类型(覆盖、主、光标)
const char *name
平面名称的 printf 样式格式字符串,如果使用默认名称则为 NULL
...
可变参数
描述
初始化类型为 **type** 的平面对象。 drm_plane_funcs.destroy
钩子应该调用 drm_plane_cleanup()
和 kfree()
来释放平面结构。平面结构不应该使用 devm_kzalloc() 分配。
仅支持 DRM_FORMAT_MOD_LINEAR 修饰符的驱动程序可以将 format_modifiers 设置为 NULL。该平面将通告线性修饰符。
注意
考虑使用 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
要禁用的平面
描述
强制禁用该平面。
当平面的当前帧缓冲区被销毁,以及恢复 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 中活动平面数减一的唯一值。
返回值:成功时返回零,失败时返回 -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()
),名为 “像素混合模式”,并具有以下枚举值:
- “无”
忽略像素 alpha 的混合公式。
- “预乘”
假设像素颜色值已预先乘以 alpha 通道值的混合公式。
- “覆盖”
假设像素颜色值未预先乘,并且在将其混合到背景颜色值时将执行此操作的混合公式。
返回
成功则返回零,失败则返回 -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
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)¶
推进 damage 迭代器。
参数
struct drm_atomic_helper_damage_iter *iter
要推进的迭代器。
struct drm_rect *rect
返回一个裁剪到平面 src 的 fb 坐标中的矩形。
描述
由于平面 src 是 16.16 定点数,而 damage 剪切是整数,此迭代器会舍入与平面 src 相交的剪切。对于相交的坐标,x1/y1 向下舍入,x2/y2 向上舍入。对于完整平面 src,如果它作为 damage 返回,则进行类似的舍入。此迭代器将跳过平面 src 之外的 damage 剪切。
如果第一次调用迭代器 next 返回 false,则表示无需更新平面。
返回
如果输出有效,则返回 True;如果到达末尾,则返回 false。
-
bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state, struct drm_plane_state *state, struct drm_rect *rect)¶
合并的平面 damage
参数
const struct drm_plane_state *old_state
用于验证的旧平面状态。
struct drm_plane_state *state
从中迭代损坏剪辑的平面状态。
struct drm_rect *rect
返回合并的 damage 矩形
描述
此函数将任何有效的平面 damage 剪切合并为一个矩形,并将其返回到 rect 中。
有关详细信息,请参见:drm_atomic_helper_damage_iter_init()
和 drm_atomic_helper_damage_iter_next()
。
返回
如果存在有效的平面 damage,则返回 True;否则返回 false。
-
drm_atomic_for_each_plane_damage¶
drm_atomic_for_each_plane_damage (iter, rect)
平面 damage 的迭代器宏。
参数
iter
要推进的迭代器。
rect
返回一个裁剪到平面 src 的 fb 坐标中的矩形。
描述
请注意,如果第一次调用迭代器宏返回 false,则无需进行平面更新。当用户空间未传递 damage 时,迭代器将返回完整的平面 src。
-
struct drm_atomic_helper_damage_iter¶
damage 迭代器的闭包结构。
定义:
struct drm_atomic_helper_damage_iter {
};
成员
描述
此结构跟踪遍历平面 damage 剪切列表所需的状态。
平面 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];
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 屏幕,撕裂不是问题。
width
扫描输出缓冲区的宽度,以像素为单位。
height
扫描输出缓冲区的高度,以像素为单位。
pitch
两条连续线起点之间的长度(以字节为单位)。
set_pixel
可选函数,用于在帧缓冲区上设置像素颜色。它允许在驱动程序内部处理特殊的平铺格式。
描述
此结构保存 drm_panic 绘制 panic 屏幕并显示它所需的信息。
-
drm_panic_trylock¶
drm_panic_trylock (dev, flags)
尝试进入 panic 打印临界区
参数
dev
标志
你需要传递给 unlock() 对等的 unsigned long 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() 对等的 unsigned long 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)
恐慌打印临界区的结束
-
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
行同步超出范围
MODE_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
硬件中的实际像素或点时钟。例如,当使用隔行扫描、双时钟、立体模式或其他改变实际通过导线发送的时序和信号的特殊功能时,它与逻辑**时钟**不同。用户空间可以通过垂直空白时间戳观察到该逻辑时钟。
同样以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
用于模式列表的结构体 list_head。
名称
模式的人类可读名称,使用
drm_mode_set_name()
填充。status
模式的状态,用于筛选出硬件不支持的模式。请参阅枚举
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 ----------------------------->*
此结构包含时序的两个副本。第一个是简单的时序,它指定了逻辑模式,就像在刷新率下进行逐行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 的 modes 列表中。
-
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
水平显示尺寸
unsigned int 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
水平显示尺寸
int vdisplay
垂直显示尺寸
int vrefresh
垂直刷新率
bool reduced
是否使用缩减消隐
bool interlaced
是否计算隔行模式
bool margins
是否添加边距(边框)
描述
调用此函数以根据 hdisplay、vdisplay、vrefresh 基于 CVT 算法生成模式行。它基于 Graham Loveridge 于 2003 年 4 月 9 日提供的 VESA(TM) 协调视频定时生成器,该生成器位于 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
水平显示尺寸
int vdisplay
垂直显示尺寸
int 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 算法创建模式行
参数
struct drm_device *dev
drm 设备
int hdisplay
水平显示尺寸
int vdisplay
垂直显示尺寸
int vrefresh
垂直刷新率。
bool interlaced
是否计算隔行模式
int margins
所需的边距(边框)大小
描述
返回基于 GTF 算法的模式行
此函数用于基于 GTF 算法创建模式行。通用定时公式来源于
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 算法的模式行存储在 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,当未找到 videomode 节点时为负 errno 代码。
-
int of_get_drm_panel_display_mode(struct device_node *np, struct drm_display_mode *dmode, u32 *bus_flags)¶
从设备树获取面板定时 drm_display_mode
参数
struct device_node *np
带有面板定时规范的 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 的垂直刷新率,以 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 时过滤掉任何仅限 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 为 true,则状态代码和模式名称也会打印到 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)¶
解析连接器的命令行模式行
参数
const char *mode_option
可选的每个连接器模式选项
const struct drm_connector *connector
要为其解析模式行的连接器
struct drm_cmdline_mode *mode
要填充的预分配 drm_cmdline_mode 结构
描述
这将解析 mode_option 命令行模式行,以获取配置连接器的模式和选项。
这使用与 fb modedb.c 相同的参数,除了末尾的额外的强制启用、强制启用数字和强制禁用位
<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
可以在模式之后提供其他选项,使用逗号分隔每个选项。有效的选项可以在 modedb 默认视频模式支持 中找到。
需要中间的 drm_cmdline_mode 结构来存储来自命令行模式行的其他选项,例如强制启用/禁用标志。
返回
如果已解析有效的模式行,则为 True,否则为 false。
-
struct drm_display_mode *drm_mode_create_from_cmdline_mode(struct drm_device *dev, struct drm_cmdline_mode *cmd)¶
将命令行模式行转换为 DRM 显示模式
参数
struct drm_device *dev
用于创建新模式的 DRM 设备
struct drm_cmdline_mode *cmd
输入命令行模式行
返回
成功时指向转换后的模式的指针,错误时为 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 对象一样创建,并通过设置以下字段进行初始化。使用指向 struct drm_connector_funcs
和连接器类型的指针调用 drm_connector_init()
初始化连接器,然后通过调用 drm_connector_register()
将其暴露给用户空间。
连接器必须附加到编码器才能使用。对于将连接器映射到编码器 1:1 的设备,应在初始化时通过调用 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** 的连接器时,用户空间应仅尝试点亮具有未知状态的连接器。
描述
此枚举用于跟踪连接器状态。uapi 没有单独的 #defines!
-
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,否则不允许在未注册的连接器上进行模式设置。这意味着禁用未注册连接器上的 CRTC 是可以的,但启用它则不行。
从未注册的连接器中移除 CRTC 是可以的,但新的 CRTC 永远不能分配给未注册的连接器。
描述
此枚举用于跟踪初始化连接器并将其注册到用户空间的状态,以便 DRM 可以防止在不再存在的连接器上进行虚假的模式设置。
-
enum drm_connector_tv_mode¶
模拟电视输出模式
常量
DRM_MODE_TV_MODE_NTSC
CCIR System 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 System B 与 PAL 彩色系统一起使用。
DRM_MODE_TV_MODE_PAL_M
CCIR System M(又名 525 线)与 PAL 彩色编码一起使用
DRM_MODE_TV_MODE_PAL_N
CCIR System N 与 PAL 彩色编码一起使用。它使用 625 行,但具有 3.58MHz 的彩色副载波频率、SECAM 色彩空间以及比大多数其他 PAL 变体更窄的通道。
DRM_MODE_TV_MODE_SECAM
CCIR System B 与 SECAM 彩色系统一起使用。
DRM_MODE_TV_MODE_MONOCHROME
使用适合 DRM 模式的时序,包括用于 525 线或 625 线模式的均衡脉冲,没有基座或颜色编码。
DRM_MODE_TV_MODE_MAX
模拟电视输出模式的数量。
内部实现细节;这不是 uABI。
描述
此枚举用于指示模拟电视连接器上使用的电视输出模式。
警告:此枚举的值是 uABI,因为它们在“电视模式”连接器属性中公开。
-
struct drm_scrambling¶
接收器的加扰支持。
定义:
struct drm_scrambling {
bool supported;
bool low_rates;
};
成员
supported
支持高于 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¶
面板在 EDID 中的监视器范围,用于
drm_display_info
定义:
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
面板上的隐私屏幕已启用并锁定(无法更改)。
描述
此枚举用于通过 “privacy-screen sw-state” 和 “privacy-screen hw-state” 属性跟踪和控制某些显示面板上集成的隐私屏幕的状态。请注意,_LOCKED 枚举值仅对 “privacy-screen 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
物理宽度,单位为毫米 (mm)。
height_mm
物理高度,单位为毫米 (mm)。
bpc
每个颜色通道的最大位数。由 HDMI 和 DP 输出使用。
subpixel_order
液晶面板的子像素顺序。
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) 流计数。0 表示传统的单流传输 (SST),或 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¶
电视接口相关的边距
定义:
struct drm_connector_tv_margins {
unsigned int bottom;
unsigned int left;
unsigned int right;
unsigned int top;
};
成员
bottom
底部边距,以像素为单位。
left
左侧边距,以像素为单位。
right
右侧边距,以像素为单位。
top
顶部边距,以像素为单位。
描述
描述在电视接口上围绕图像放置的边距(以像素为单位),以处理过扫描。
-
struct drm_tv_connector_state¶
电视接口相关的状态
定义:
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
电视边距
legacy_mode
旧式电视模式,驱动程序特定的值
mode
电视模式
brightness
亮度,以百分比表示
contrast
对比度,以百分比表示
flicker_reduction
闪烁减少,以百分比表示
overscan
过扫描,以百分比表示
saturation
饱和度,以百分比表示
hue
色调,以百分比表示
-
struct drm_connector_hdmi_infoframe¶
HDMI Infoframe 容器
定义:
struct drm_connector_hdmi_infoframe {
union hdmi_infoframe data;
bool set;
};
成员
data
HDMI Infoframe 结构
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
由原子助手使用,通过
drm_connector_helper_funcs.atomic_best_encoder
或drm_connector_helper_funcs.best_encoder
回调来选择编码器。这也在原子助手中使用,以将编码器映射到其当前和之前的连接器,请参阅
drm_atomic_get_old_connector_for_encoder()
和drm_atomic_get_new_connector_for_encoder()
。注意:原子驱动程序必须填写此项(无论是自己填写还是通过助手填写),否则 GETCONNECTOR 和 GETENCODER IOCTL 将不会向用户空间返回正确的数据。
link_status
连接器 link_status 用于跟踪链路是 GOOD 还是 BAD,以便在需要重新训练时通知用户空间。
state
指向全局 drm_atomic_state 的后向指针
commit
跟踪待处理的提交,以防止出现使用后释放的情况。
仅当 crtc 为 NULL 时才设置。
tv
电视接口状态
self_refresh_aware
这跟踪连接器是否知道自刷新状态。对于那些了解自刷新状态的连接器实现,应将其设置为 true。这是必需的,因为 crtc 注册了自刷新助手,并且它不知道下游的连接器是否已实现自刷新进入/退出。
如果驱动程序知道如何处理自刷新请求,则应在 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
用于请求在接收器上更改色彩空间的连接器属性的状态变量。这通常用于切换到更宽的色域,例如 BT2020。
writeback_job
回写连接器的回写作业
为回写连接器保存帧缓冲区和输出栅栏。由于回写完成可能与正常的提交周期异步,因此回写作业的生命周期由该对象与正常的原子状态分开管理。
另请参阅:
drm_writeback_queue_job()
和drm_writeback_signal_completion()
max_requested_bpc
用于限制像素最大位深度的连接器属性。
max_bpc
连接器 max_bpc 基于请求的 max_bpc 属性和从 edid 获取的连接器 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);
};
成员
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,否则为负错误代码
-
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,失败返回负错误代码。
reset
将连接器硬件和软件状态重置为关闭。此函数不由核心直接调用,仅通过
drm_mode_config_reset()
调用。它不是一个助手挂钩,仅出于历史原因。原子驱动程序可以使用
drm_atomic_helper_connector_reset()
使用此挂钩重置原子状态。detect
检查是否有任何东西连接到连接器。参数 force 在轮询时设置为 false,在由于用户请求检查连接器时设置为 true。驱动程序可以使用 force 来避免在自动探测期间进行代价高昂的破坏性操作。
此回调是可选的,如果未实现,则连接器将被视为始终处于连接状态。
FIXME
请注意,此挂钩仅由探测助手调用。它没有在助手库 vtable 中,纯粹是出于历史原因。用于探测连接器状态的唯一 DRM 核心入口点是 fill_modes。
请注意,助手库将已经持有
drm_mode_config.connection_mutex
。需要获取其他锁以避免与并发模式设置更改发生竞争的驱动程序需要改用drm_connector_helper_funcs.detect_ctx
。另请注意,无论连接器处于什么状态,都可以调用此回调。需要底层设备通电才能执行检测的驱动程序首先需要确保已正确启用该设备。
返回
drm_connector_status 表示连接器的状态。
force
当用户空间通过 sysfs 接口或内核 cmdline 强制连接器进入特定状态时,将调用此函数以更新内部编码器状态。在这种情况下,不会调用 detect 回调。
FIXME
请注意,此挂钩仅由探测助手调用。它没有在助手库 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。使用探测助手的驱动程序应使用
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
复制此连接器的当前原子状态并返回它。核心和助手保证任何通过此钩子复制的原子状态,并且仍然由调用者拥有(即,没有通过调用
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 连接器的热插拔事件时,将调用此函数。
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_mode
电视模式标准。请参阅 DRM_MODE_TV_MODE_*。
tv_mode_specified
模式是否有首选的电视模式?
描述
每个连接器都可以有一个初始模式,以及通过内核命令行传递的附加选项。此结构允许表达这些参数,并将由命令行解析器填充。
-
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];
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;
};
成员
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
保护。index
压缩的连接器索引,它与不支持热添加/删除的驱动程序的 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
此连接器可以处理双扫描吗?仅由
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 探测添加的模式,在应用过滤之前。由探测助手使用。受
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
包含 EDID 的 DRM 属性(如果存在)。受
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
隐私屏幕 notifier_block
privacy_screen_sw_state_property
可选的原子属性,用于连接器控制集成的隐私屏幕。
privacy_screen_hw_state_property
可选的原子属性,用于连接器报告实际的集成隐私屏幕状态。
broadcast_rgb_property
连接器属性,用于设置要输出的广播 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 的数据,如果存在
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
用于 tile 属性的 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 相关变量和属性。
描述
每个连接器可以连接到一个或多个 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 连接器
描述
此函数会递增连接器的引用计数。
-
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¶
Tile 组元数据
定义:
struct drm_tile_group {
struct kref refcount;
struct drm_device *dev;
int id;
u8 group_data[8];
};
成员
refcount
引用计数
dev
DRM 设备
id
暴露给用户空间的 tile 组 ID
group_data
标识此组的 Sink 私有数据
描述
**group_data** 对应于具有 EDID 的外部屏幕的 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_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_dev_register()
后可以热插拔的连接器(例如 DP MST 连接器)调用此函数。 所有其他连接器将在调用 drm_dev_register()
时自动注册。
当连接器不再可用时,调用者必须调用 drm_connector_unregister()
。
返回
成功时为零,失败时为错误代码。
-
void drm_connector_unregister(struct drm_connector *connector)¶
注销连接器。
参数
struct drm_connector *connector
要注销的连接器。
描述
为连接器注销用户空间接口。仅对通过调用 drm_connector_register()
显式注册的连接器调用此函数。
-
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
。必须通过调用 drm_connector_list_iter_end()
来清理 iter。迭代本身使用 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)¶
拆卸 connector_list 迭代器
参数
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
子像素顺序的枚举
描述
请注意,您可以滥用此函数并返回超出范围的值,但这将是调用者的错误。不应有未经清理的用户数据到达此处。
返回
描述枚举的子像素属性的字符串
-
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)¶
附加内容类型属性
参数
struct drm_connector *connector
要在其上附加内容类型属性的连接器。
描述
驱动程序首次创建 HDMI 连接器时调用。
返回
0
-
void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)¶
附加电视连接器边距属性
参数
struct drm_connector *connector
DRM 连接器
描述
驱动程序需要在连接器上附加电视边距属性时调用。通常用于 SDTV 和 HDMI 连接器。
-
int drm_mode_create_tv_margin_properties(struct drm_device *dev)¶
创建电视连接器边距属性
参数
struct drm_device *dev
DRM 设备
描述
此函数由驱动程序的 HDMI 连接器初始化例程调用,为给定设备创建电视边距属性。对于 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[])¶
创建特定于电视的连接器属性
参数
struct drm_device *dev
DRM 设备
unsigned int num_modes
支持的不同电视格式(模式)的数量
const char * const modes[]
指向包含每种格式名称的字符串的指针数组
描述
此函数由驱动程序的电视初始化例程调用,为给定设备创建特定于电视的连接器属性。调用者负责分配格式名称列表并将其传递给此例程。
注意
此函数注册已弃用的“mode”连接器属性,以选择模拟电视模式(即 NTSC、PAL 等)。新驱动程序必须使用 drm_mode_create_tv_properties()
代替。
返回
成功返回 0,失败返回负错误代码。
-
int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int supported_tv_modes)¶
创建特定于电视的连接器属性
参数
struct drm_device *dev
DRM 设备
unsigned int supported_tv_modes
支持的电视模式的位掩码(参见 DRM_MODE_TV_MODE_*)
描述
此函数由驱动程序的电视初始化例程调用,为给定设备创建电视特定的连接器属性。
返回
成功返回 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
在其上创建色彩空间属性的连接器。
u32 supported_colorspaces
支持的色彩空间的位图
描述
由驱动程序首次需要时调用,必须附加到所需的 HDMI 连接器。
返回
成功返回零,失败返回负 errno。
-
int drm_mode_create_dp_colorspace_property(struct drm_connector *connector, u32 supported_colorspaces)¶
创建 DP 色彩空间属性
参数
struct drm_connector *connector
在其上创建色彩空间属性的连接器。
u32 supported_colorspaces
支持的色彩空间的位图
描述
由驱动程序首次需要时调用,必须附加到所需的 DP 连接器。
返回
成功返回零,失败返回负 errno。
-
int drm_mode_create_content_type_property(struct drm_device *dev)¶
创建内容类型属性
参数
struct drm_device *dev
DRM 设备
描述
由驱动程序首次需要时调用,必须附加到所需的连接器。
返回
成功返回零,失败返回负 errno。
-
int drm_mode_create_suggested_offset_properties(struct drm_device *dev)¶
创建建议的偏移属性
参数
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 显示器。
返回
成功时返回 0,失败时返回 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:不良)
描述
在通常的工作场景中,此链接状态属性将始终设置为“良好”。如果在模式设置期间或之后发生某些故障,内核驱动程序可能会将此链接状态属性设置为“不良”。然后,调用者需要发送一个热插拔 uevent,以便用户空间通过 GET_CONNECTOR_IOCTL 重新检查有效模式并重试 modeset。
添加此属性的原因是为了处理链路训练失败,但它不限于 DP 或链路训练。例如,如果我们实现异步 setcrtc,则可以使用此属性来报告其中的任何故障。
注意
驱动程序不能依赖用户空间来支持此属性并发出 modeset。 因此,他们可以选择在没有用户空间干预的情况下处理问题(如重新训练链路)。
-
int drm_connector_attach_max_bpc_property(struct drm_connector *connector, int min, int max)¶
附加“最大 bpc”属性
参数
struct drm_connector *connector
在其上附加最大 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)¶
附加“广播 RGB”属性
参数
struct drm_connector *connector
要在其上附加属性的连接器。
描述
此功能用于添加对强制连接器上的 RGB 范围的支持
返回
成功返回零,失败返回负 errno。
-
int drm_connector_attach_colorspace_property(struct drm_connector *connector)¶
附加“色彩空间”属性
参数
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
描述
原子驱动程序应使用此函数来更新连接器上指示的可变刷新率支持。
-
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
要为其创建隐私屏幕属性的连接器
描述
此函数为连接器创建“隐私屏幕软件状态”和“隐私屏幕硬件状态”属性。它们未附加。
-
void drm_connector_attach_privacy_screen_properties(struct drm_connector *connector)¶
附加 drm 连接器的隐私屏幕属性。
参数
struct drm_connector *connector
要在其上附加隐私屏幕属性的连接器
描述
此函数将“隐私屏幕软件状态”和“隐私屏幕硬件状态”属性附加到连接器。两者的初始状态都设置为“已禁用”。
-
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 连接器状态事件。此函数获取传入的 drm_privacy_screen 的所有权,并在连接器销毁时调用 drm_privacy_screen_put()
。
-
void drm_connector_update_privacy_screen(const struct drm_connector_state *connector_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、平面或连接器的另一次提交。**未能这样做将导致未定义的行为。** 因此,强烈建议所有使用回写连接器的用户空间应用程序*始终*检索提交的输出栅栏并适当使用它。从用户空间来看,此属性将始终读取为零。
-
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 变量用作连接器时间轴上创建的栅栏的单调计数器。
timeline_name
连接器的栅栏时间轴的名称。
-
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
一旦回写完成,栅栏将发出信号
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
连接器函数虚表
const struct drm_encoder_helper_funcs *enc_helper_funcs
内部编码器要使用的编码器辅助函数虚表
const u32 *formats
回写引擎支持的像素格式数组
int n_formats
格式数组的长度
u32 possible_crtcs
内部回写编码器可能的 crtc
描述
如果尚未创建,此函数将创建回写连接器特定的属性,将连接器初始化为 DRM_MODE_CONNECTOR_WRITEBACK 类型,并正确初始化属性值。 它还会创建一个与 drm_writeback_connector 关联的内部编码器,并将其设置为使用编码器辅助函数的 enc_helper_funcs 虚表。
驱动程序应始终使用此函数而不是 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
连接器函数虚表
const u32 *formats
回写引擎支持的像素格式数组
int n_formats
格式数组的长度
描述
如果尚未创建,此函数将创建回写连接器特定的属性,将连接器初始化为 DRM_MODE_CONNECTOR_WRITEBACK 类型,并正确初始化属性值。
此函数假定在调用此函数之前已创建并初始化 drm_writeback_connector 的编码器。
此外,此函数还假定此 API 的调用者将管理分配编码器辅助函数、possible_crtcs 和任何其他特定于编码器的操作。
如果驱动程序想要自行管理关联编码器的生命周期,则应始终使用此函数而不是 drm_connector_init()
来设置回写连接器。
返回
成功时返回 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 几乎没用。 最重要的是,暴露的限制对于当今的硬件来说太简单了,而推断限制的推荐方法是使用原子 IOCTL 的 DRM_MODE_ATOMIC_TEST_ONLY 标志。
否则,编码器根本不会在 uapi 中使用(来自用户空间的任何模式设置请求都会直接将连接器与 CRTC 连接),因此驱动程序可以随意使用它们。 模式设置辅助库强烈使用编码器来促进代码共享。 但是对于更复杂的设置,通常最好将共享代码移动到单独的 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);
};
成员
reset
将编码器硬件和软件状态重置为关闭。 此函数不是由核心直接调用的,仅通过
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-Video、分量、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。
index
在 mode_config.list 中的位置,可以用作数组索引。它在编码器的生命周期内是不变的。
possible_crtcs
使用
drm_crtc_index()
作为位域索引的潜在 CRTC 绑定的位掩码。驱动程序必须为所有drm_crtc
对象设置位,该编码器可以在调用drm_dev_register()
之前连接到这些对象。如果驱动程序中出现此错误,您将收到警告。
请注意,由于 CRTC 对象无法热插拔,因此分配的索引是稳定的,因此在注册所有对象之前就已知。
possible_clones
使用
drm_encoder_index()
作为位域索引的潜在克隆兄弟编码器的位掩码。驱动程序必须为所有drm_encoder
对象设置位,这些对象可以在调用drm_dev_register()
之前与此编码器一起克隆一个drm_crtc
。驱动程序也应设置表示编码器本身的位。克隆位应设置成当两个编码器可以在克隆配置中使用时,它们都应设置彼此的位。作为上述规则的例外,如果驱动程序没有实现任何克隆,它可以将 possible_clones 设置为 0。核心将通过为编码器本身设置位来自动修复此问题。
如果驱动程序中出现此错误,您将收到警告。
请注意,由于编码器对象无法热插拔,因此分配的索引是稳定的,因此在注册所有对象之前就已知。
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
要查找掩码的编码器
描述
给定一个已注册的编码器,返回该编码器用于编码器的 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-context 来避免死锁。但是由于锁定在驱动程序代码中分布更广,我们希望从 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_BEGIN()
和 DRM_MODESET_LOCK_ALL_END()
中实现,以用于需要通过 drm_modeset_lock_all_ctx()
获取所有模式设置锁定的情况。
如果只需要单个模式设置锁定,则不需要 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
争用
内部用于 -EDEADLK 处理
stack_depot
内部用于争用调试
已锁定
持有的锁列表
trylock_only
原子上下文/panic 通知器中使用的 trylock 模式
可中断
是否应使用可中断锁定。
描述
每个竞争一组锁的线程都必须使用一个获取 ctx。如果任何锁 fxn 返回 -EDEADLK,则它必须回退并重试。
-
struct drm_modeset_lock¶
用于锁定模式设置资源。
定义:
struct drm_modeset_lock {
struct ww_mutex mutex;
struct list_head head;
};
成员
mutex
资源锁定
head
用于在作为原子更新的一部分时,将其保留在
drm_atomi_state.locked
列表中的位置
描述
用于锁定 CRTC 和其他模式设置资源。
-
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)
用于获取模式设置锁的助手
参数
dev
drm 设备
ctx
本地模式设置获取上下文,将被解引用
标志
要传递给
drm_modeset_acquire_init()
的 DRM_MODESET_ACQUIRE_* 标志ret
用于跟踪错误状态的本地 ret/err/etc 变量
描述
使用这些宏可以简化使用本地上下文获取所有模式设置锁的操作。 这样做的好处是减少了样板代码,而且在适当的情况下可以正确检查返回值。
在 BEGIN 和 END 之间运行的任何代码都将持有模式设置锁。
必须与 DRM_MODESET_LOCK_ALL_END()
配对使用。 我们将在死锁和错误条件下的标签之间来回跳转。
驱动程序可以获取额外的模式设置锁。 如果任何锁获取失败,控制流需要跳转到 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)
用于释放和清理模式设置锁的助手
参数
dev
drm 设备
ctx
本地模式设置获取上下文,将被解引用
ret
用于跟踪错误状态的本地 ret/err/etc 变量
描述
DRM_MODESET_LOCK_ALL_BEGIN()
的另一半。 如果 ret 为 -EDEADLK,它将跳回 BEGIN。
重要的是,你为 begin 和 end 使用相同的 ret 变量,以便正确处理死锁条件。
返回
除非输入时 ret 为 -EDEADLK,否则 ret 不会被修改。 这意味着,如果你成功获取了锁,ret 将为你代码设置的值。 如果在获取或退避时出现死锁或其他故障,ret 将设置为该故障。 在这两种情况下,都不会运行 BEGIN/END 之间的代码,因此故障将反映无法获取锁。
-
void drm_modeset_lock_all(struct drm_device *dev)¶
获取所有模式设置锁
参数
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),则必须调用此函数来释放当前持有的所有锁,并阻止直到争用的锁变为可用。
如果此上下文使用 DRM_MODESET_ACQUIRE_INTERRUPTIBLE
初始化,并且等待已中断,则此函数在成功时返回 0,否则返回 -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)¶
获取所有模式设置锁
参数
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 驱动程序想要添加对其中一个属性的支持,则在可能的情况下,新属性的要求也适用。此外,记录的行为必须与现有属性的实际语义相匹配,以确保兼容性。最初添加该属性的驱动程序的开发人员应帮助完成这些任务,并且必须在可能的情况下确认记录的行为。
属性类型和 Blob 属性支持¶
由 drm_property
表示的属性用于扩展暴露给用户空间的模式设置接口。对于原子模式设置 IOCTL,属性甚至是将所需新模式设置配置的元数据从用户空间传输到内核的唯一方式。属性具有明确定义的值范围,由 drm 核心强制执行。有关不同属性类型和范围的概述,请参阅 struct drm_property
的 flags 成员的文档。
属性不直接存储当前值,而是需要通过使用 drm_object_attach_property()
将它们附加到 drm_mode_object
来实例化。
属性值只有 64 位。为了支持更大的数据堆(如伽玛表、色彩校正矩阵或大型结构),属性可以改为指向具有该附加数据的 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 到属性定义的枚举值数量减一,并将一个自由格式的字符串名称与每个值关联。应用程序可以检索已定义的数值-名称对列表,并使用数值来获取和设置属性实例值。枚举属性使用
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_property_create()
并将 DRM_MODE_PROP_BLOB 作为类型来创建。用于包含 blob 数据的实际 blob 对象使用
drm_property_create_blob()
或通过相应的 IOCTL 创建。除了仅接受 blob 对象的内置限制之外,blob 属性的工作方式与对象属性完全相同。blob 属性存在的唯一原因是与现有用户空间的向后兼容性。
此外,属性可以具有以下标志的任意组合
- DRM_MODE_PROP_ATOMIC
为编码原子模式设置状态的属性设置。此类属性不会暴露给传统的用户空间。
- DRM_MODE_PROP_IMMUTABLE
为用户空间无法更改其值的属性设置。内核允许更新这些属性的值。这通常用于向用户空间暴露探测状态,例如 EDID 或 DP MST 接收器上的连接器路径属性。内核可以通过调用
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
实际数据,嵌入在此结构的末尾
描述
Blobs 用于存储比适合 drm_property
可用的 64 位更大的值。
Blobs 使用 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()
时会自动完成。
用户空间允许设置(包括最小值和最大值)范围内的任何无符号整数值。
返回
成功时指向新创建的属性的指针,失败时为 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()
时会自动完成。
用户空间允许设置(包括最小值和最大值)范围内的任何有符号整数值。
返回
成功时指向新创建的属性的指针,失败时为 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 的属性 return 成功时返回 0,失败时返回错误
描述
此函数将替换 blob 列表中的全局属性,可以选择更新持有该属性 ID 的属性。
如果长度为 0 或数据为 NULL,则不会创建新的 blob,并且如果指定了持有属性,则该属性将设置为 0。
假设调用者保护对 replace 指针的访问,例如通过为其父项持有相关的模式设置对象锁。
例如,drm_connector 有一个“PATH”属性,其中包含 blob 属性的 ID,该属性具有 MST 路径信息的值。使用 replace 指向连接器的 path_blob_ptr、为新路径信息设置的长度和数据、obj_holds_id 设置为连接器的基本对象以及 prop_holds_id 设置为 path 属性名称来调用此函数将执行完全原子的更新。对 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 核心中实现。请注意,无法通过 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
连接器 link-status 属性,用于指示链路的状态。link-status 的默认值为“GOOD”。如果在模式设置期间或之后出现错误,则内核驱动程序可能会将其设置为“BAD”并发出热插拔 uevent。驱动程序应使用
drm_connector_set_link_status_property()
更新此值。当用户空间接收到热插拔 uevent 并检测到“BAD” link-status 时,接收器将不再接收像素(例如,屏幕完全变黑)。可用模式列表可能已更改。如果当前模式已消失,则用户空间应选择新的模式,并执行新的模式设置,并将 link-status 设置为“GOOD”以重新启用连接器。
如果多个连接器共享同一个 CRTC,并且其中一个连接器获得“BAD” link-status,则其他连接器不受影响(即,接收器仍然继续接收像素)。
当用户空间对具有“BAD” link-status 的连接器执行原子提交而不将该属性重置为“GOOD”时,接收器可能仍然不接收像素。当用户空间执行原子提交,将 link-status 属性重置为“GOOD”而没有设置 ALLOW_MODESET 标志时,它可能会失败,因为需要进行模式设置。
用户空间只能将 link-status 更改为“GOOD”,将其更改为“BAD”是空操作。
为了与非原子用户空间向后兼容,内核会尝试在 SETCRTC IOCTL 中自动将 link-status 设置回“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。
一些准则
应保留 DESIRED 状态,直到用户空间通过将该属性设置为 UNDESIRED 来取消断言它。这意味着只有当用户明确请求时,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 的身份验证。而链路只能使用 HDCP 1.4 进行内容类型 0 的身份验证(尽管本质上是隐含的。因为 HDCP 1.4 中没有内容类型的参考)。
HDCP 2.2 身份验证协议本身将“内容类型”作为参数,这是 DP HDCP 2.2 加密算法的输入。
在内容类型 0 的内容保护请求的情况下,内核驱动程序可以选择 HDCP 规范版本 1.4 或 2.2。当 HDCP 2.2 用于“HDCP 类型 0”时,下游中具有 HDCP 2.2 功能的中继器可以将内容发送到经过 HDCP 1.4 身份验证的 HDCP 接收器(类型 0 链路)。但是,如果内容被分类为“HDCP 类型 1”,则上述提到的 HDCP 2.2 中继器不会将内容发送到 HDCP 接收器,因为它无法为“HDCP 类型 1”验证具有 HDCP 1.4 功能的接收器。
请注意,用户空间可以忽略内核驱动程序用于实现“HDCP 内容类型”的 HDCP 版本。
在当前情况下,将内容分类为类型 1 可确保内容只能通过 HDCP 2.2 加密链路显示。
请注意,“HDCP 内容类型”属性是在 HDCP 2.2 中引入的,默认设置为类型 0。它仅由支持 HDCP 2.2(因此支持类型 0 和类型 1)的驱动程序公开。根据 HDCP 规范的后续版本的定义方式,内容类型也可以用于更高的版本。
如果当“内容保护”不是 UNDESIRED 时更改了内容类型,则内核将在同一原子提交中禁用 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 标准 v1.4 中定义。然后,它需要获取以 HDR 编码(基本上是使用 HDR 传输函数)的视频/游戏/应用程序内容的元数据信息。有了这些信息,它需要决定混合策略,并将相关图层/叠加层合成为通用格式。完成混合后,用户空间将知道要发送到接收端的合成帧的元数据。然后,它使用此属性将此元数据通信给驱动程序,驱动程序然后根据连接的编码器类型生成信息帧数据包并发送到接收端。
- 在以下情况下,用户空间将负责执行色调映射操作
某些图层是 HDR,而另一些图层是 SDR
HDR 图层的亮度与接收端不同
它甚至需要进行色彩空间转换,并将所有图层转换为一个通用的色彩空间进行混合。它可以基于相关硬件的功能,使用 GL、Media 或显示引擎来完成此操作。
驱动程序期望将元数据从用户空间放入
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()
按照规范打包信息帧。- 最大 bpc
用户空间使用此范围属性来限制位深度。使用时,驱动程序会根据硬件和接收端支持的有效范围限制 bpc。驱动程序应使用函数
drm_connector_attach_max_bpc_property()
在初始化期间创建属性并将其附加到连接器。
连接器还具有一个标准化的原子属性
- CRTC_ID
此连接器应连接到的
drm_crtc
的模式对象 ID。
LCD 面板的连接器也可能具有一个标准化属性
- 面板方向
在某些设备上,LCD 面板以这样一种方式安装在外壳中,即面板的向上/顶部与设备的顶部不匹配。用户空间可以使用此属性进行检查。请注意,来自触摸屏(具有 INPUT_PROP_DIRECT 的输入设备)的输入坐标仍将 1:1 映射到实际 LCD 面板坐标,因此如果用户空间旋转图片以调整方向,则还必须对触摸屏输入坐标应用相同的转换。此属性通过调用
drm_connector_set_panel_orientation()
或drm_connector_set_panel_orientation_with_quirk()
进行初始化- 缩放模式
此属性定义了如何将非原生模式放大到 LCD 面板的原生模式
- 无
不进行放大,缩放留给面板处理。并非所有驱动程序都公开此模式。
- 全
输出将放大到面板的完整分辨率,忽略纵横比。
- 居中
不进行放大,输出在面板的原生分辨率内居中。
- 全纵横比
输出将放大以最大化宽度或高度,同时保持纵横比。
应通过调用
drm_connector_attach_scaling_mode_property()
来设置此属性。请注意,驱动程序也可以将此属性公开给外部输出,在这种情况下,它们必须支持“无”,这应该是默认值(因为外部屏幕具有内置缩放器)。- subconnector
此属性由 DVI-I、TVout 和 DisplayPort 使用,以指示不同的连接器子类型。枚举值或多或少与主连接器类型的枚举值匹配。对于 DVI-I 和 TVout,还有一个匹配的属性“选择子连接器”,允许在信号类型之间切换。DP 子连接器对应于下游端口。
- 隐私屏幕软件状态、隐私屏幕硬件状态
这两个可选属性可用于查询某些显示器上可用的电子隐私屏幕的状态;在某些情况下,还可以控制状态。如果驱动程序实现了这些属性,则必须同时存在这两个属性。
“隐私屏幕硬件状态”是只读的,它反映了隐私屏幕的实际状态,可能的值为:“已启用”、“已禁用”、“已启用锁定”、“已禁用锁定”。锁定状态表示无法通过 DRM API 更改状态。例如,某些设备可能存在固件设置选项或硬件滑块开关,提供始终开启/关闭模式。
当未锁定时,可以设置“隐私屏幕软件状态”来更改隐私屏幕状态。在这种情况下,驱动程序必须更新硬件状态属性,以反映软件状态属性提交完成后新的状态。当硬件状态被锁定时设置软件状态属性必须被驱动程序解释为当硬件状态变为解锁时将状态更改为设置状态的请求。例如,如果“隐私屏幕硬件状态”为“已启用锁定”,并且软件状态设置为“已禁用”,然后用户通过更改滑块开关位置解锁该状态,则驱动程序必须在收到解锁事件后将状态设置为“已禁用”。
在某些情况下,隐私屏幕的实际状态可能会在 DRM 代码的控制之外更改。例如,可能存在固件处理的热键,用于切换实际状态,或者可以通过其他用户空间 API(例如写入 /proc/acpi/ibm/lcdshadow)更改实际状态。在这种情况下,驱动程序必须更新硬件状态和软件状态以反映新值,从而覆盖软件状态中的任何挂起状态请求。因此,任何挂起的软件状态请求都会被丢弃。
请注意,状态可以在 DRM 主进程控制之外更改的事实意味着用户空间不得缓存软件状态的值。缓存软件状态值并将其包含在以后的原子提交中可能会导致覆盖通过例如固件处理的热键完成的状态更改。因此,除非用户空间想要更改其值,否则不得将隐私屏幕软件状态包含在原子提交中。
- 左边距、右边距、上边距、下边距
将边距添加到连接器的视口。这通常用于减轻电视上的过扫描。
该值是以像素为单位的黑边大小,该黑边将被添加。附加的 CRTC 的内容将被缩放以填充边距内的整个区域。
边距配置可能会发送到接收端,例如通过 HDMI AVI 信息帧。
驱动程序可以通过调用
drm_mode_create_tv_margin_properties()
来设置这些属性。- 色彩空间
此属性用于通知驱动程序用户空间配置像素操作属性以生成什么颜色编码。这些变体设置了色度、传输特性,以及必要时应使用哪个 YCbCr 转换。HDR_OUTPUT_METADATA 的传输特性优先于此属性。用户空间始终配置像素操作属性以生成完整量化范围数据(请参阅广播 RGB 属性)。
驱动程序会通知接收端期望什么色度、传输特性、YCbCr 转换和量化范围(这可能取决于输出模式、输出格式和其他属性)。驱动程序还会将用户空间提供的数据转换为接收端期望的数据。
用户空间必须通过解析 EDID 来检查接收端是否支持驱动程序允许选择的所有可能色度。
由于历史原因,此属性公开了许多会导致未定义行为的变体。
- 默认
该行为是特定于驱动程序的。
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 特定连接器属性¶
- 广播 RGB(HDMI 特定)
指示所使用的量化范围(全范围或有限范围)。颜色处理管道将进行调整以匹配此属性的值,并且将相应地生成和发送 Infoframes。
此属性仅在 HDMI 输出格式为 RGB 时相关。如果它是 YCbCr 变体之一,则会被忽略。
连接器所连接的 CRTC 必须由用户空间配置为始终产生全范围像素。
此属性的值可以是以下之一
- 自动
量化范围会根据 HDMI 规范(HDMI 1.4b - 第 6.6 节 - 视频量化范围)自动根据模式选择。
- 全
强制使用全量化范围。
- 有限 16:235
强制使用有限量化范围。与名称所暗示的不同,这适用于任何位/组件数。
除“自动”之外的属性值可能会导致颜色偏差(如果选择了“有限”但显示器预期为“全范围”),或者出现黑屏(如果选择了“全范围”但显示器预期为“有限”)。
驱动程序可以通过调用
drm_connector_attach_broadcast_rgb_property()
来设置此属性。- 内容类型(HDMI 特定)
指示要在 HDMI infoframes 中使用的内容类型设置,以向外部设备指示内容类型,以便其相应地调整其显示设置。
此属性的值可以是以下之一
- 无数据
内容类型未知
- 图形
内容类型为图形
- 照片
内容类型为照片
- 电影
内容类型为电影
- 游戏
内容类型为游戏
每个内容类型的含义在 CTA-861-G 表 15 中定义。
驱动程序可以通过调用
drm_connector_attach_content_type_property()
来设置此属性。到 infoframe 值的解码通过 drm_hdmi_avi_infoframe_content_type() 完成。
模拟电视特定连接器属性¶
- 电视模式
指示在模拟电视连接器上使用的电视模式。此属性的值可以是以下之一
- 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 颜色编码。
单色
使用适合 DRM 模式的时序,包括用于 525 线或 625 线模式的均衡脉冲,没有基座或颜色编码。
驱动程序可以通过调用
drm_mode_create_tv_properties()
来设置此属性。
标准 CRTC 属性¶
DRM CRTC 有一些标准化属性
- 活动
用于设置 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 缩放器的缩放滤镜的原子属性
此属性的值可以是以下之一
- 默认
驱动程序的默认缩放滤镜
- 最近邻
最近邻缩放滤镜
标准平面属性¶
DRM 平面有一些标准化属性
- type
描述平面类型的不可变属性。
对于启用了
DRM_CLIENT_CAP_ATOMIC
功能的用户空间,平面类型只是一个提示,并且主要被仅限原子测试的提交所取代。类型提示仍然可以用来更容易地找到驱动程序接受的平面配置。此属性的值可以是以下之一
- “主”
要点亮 CRTC,如果附加一个覆盖整个 CRTC 且未设置缩放或裁剪的主平面,则最有可能起作用。
驱动程序可能支持主平面的更多功能,用户空间可以通过仅限测试的原子提交来找到。
内核在旧版 IOCTL
DRM_IOCTL_MODE_SETCRTC
和DRM_IOCTL_MODE_PAGE_FLIP
中隐式使用一些主平面。因此,用户空间不得将任何主平面的显式用法(例如通过原子提交)与这些旧版 IOCTL 混合使用。- “光标”
要启用此平面,使用未配置缩放或裁剪且具有以下属性的帧缓冲,则最有可能起作用
如果驱动程序提供
DRM_CAP_CURSOR_WIDTH
和DRM_CAP_CURSOR_HEIGHT
功能,请使用此大小创建帧缓冲。否则,创建一个大小为 64x64 的帧缓冲。如果驱动程序不支持修饰符,则创建一个具有线性布局的帧缓冲。否则,使用 IN_FORMATS 平面属性。
驱动程序可能支持光标平面的更多功能,用户空间可以通过仅限测试的原子提交来找到。
内核在旧版 IOCTL
DRM_IOCTL_MODE_CURSOR
和DRM_IOCTL_MODE_CURSOR2
中隐式使用一些光标平面。因此,用户空间不得将任何光标平面的显式用法(例如通过原子提交)与这些旧版 IOCTL 混合使用。即使未公开光标平面,某些驱动程序也可能支持光标。在这种情况下,可以使用旧版光标 IOCTL 来配置光标。
- “覆盖”
既不是主平面也不是光标平面。
当禁用
DRM_CLIENT_CAP_UNIVERSAL_PLANES
功能时,覆盖平面是唯一公开的平面。
- IN_FORMATS
Blob 属性,其中包含此平面支持的缓冲区格式和修饰符对的集合。blob 是一个结构体 drm_format_modifier_blob。如果没有此属性,则平面不支持带有修饰符的缓冲区。用户空间无法更改此属性。
请注意,用户空间可以检查
DRM_CAP_ADDFB2_MODIFIERS
驱动程序功能以获得通用修饰符支持。如果设置了此标志,则每个平面都将具有 IN_FORMATS 属性,即使它仅支持 DRM_FORMAT_MOD_LINEAR。在 linux 内核版本 v5.1 之前,这方面存在各种错误,导致功能标志和每个平面属性之间不一致。- 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。- 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
旋转使用
drm_plane_create_rotation_property()
设置。它在源矩形和目标矩形之间添加一个旋转和反射步骤。如果没有此属性,则矩形仅缩放,而不旋转或反射。可能的值
- “rotate-<度数>”
表示 drm 平面沿逆时针方向旋转了 <度数> 度。
- “reflect-<轴>”
表示 drm 平面的内容沿 <轴> 轴反射,方式与镜像相同。
reflect-x
|o | | o| | | -> | | | v| |v |
reflect-y
|o | | ^| | | -> | | | v| |o |
- zpos
Z 位置使用
drm_plane_create_zpos_immutable_property()
和drm_plane_create_zpos_property()
设置。它控制重叠平面的可见性。如果没有此属性,则主平面始终位于光标平面之下,并且所有其他平面之间的顺序未定义。正 Z 轴指向用户,即 Z 位置值较低的平面位于 Z 位置值较高的平面之下。Z 位置值相同的两个平面的顺序未定义。请注意,Z 位置值也可以是不可变的,以告知用户空间有关平面的硬编码堆叠的信息,请参阅drm_plane_create_zpos_immutable_property()
。如果任何平面具有 zpos 属性(可变或不可变),则所有平面都应具有 zpos 属性。- 像素混合模式
像素混合模式使用
drm_plane_create_blend_mode_property()
设置。它为 alpha 混合方程选择添加一个混合模式,描述当前平面的像素如何与背景合成。定义了三种 alpha 混合方程
- “无”
忽略像素 alpha 的混合公式
out.rgb = plane_alpha * fg.rgb + (1 - plane_alpha) * bg.rgb
- “预乘”
假设像素颜色值已与 alpha 通道值进行预乘的混合公式
out.rgb = plane_alpha * fg.rgb + (1 - (plane_alpha * fg.alpha)) * bg.rgb
- “覆盖”
假设像素颜色值尚未预乘,并且在将其混合到背景颜色值时将执行此操作的混合公式
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
指示要用于平面缩放器的缩放过滤器
此属性的值可以是以下之一
- 默认
驱动程序的默认缩放滤镜
- 最近邻
最近邻缩放滤镜
驱动程序可以通过调用 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 查找之前的像素数据。数据被解释为结构体
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)的颜色映射(有时也称为颜色查找表、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_pending_vblank_event
在结构体drm_crtc_state
中表示,该结构体也由非阻塞原子提交帮助程序和现有用户空间的 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”属性为真,则驱动程序会将此属性作为启用可变刷新率支持的提示。当启用时,垂直前沿时间将延长直到页面翻转或超时。最小垂直前沿时间定义为当前模式的垂直前沿时间。
最大垂直前沿时间大于或等于最小垂直前沿时间。该持续时间来自连接器的最小支持可变刷新率。
驱动程序可能会在这些最小和最大边界内设置进一步的限制。
光标热点属性¶
HOTSPOT_X:用于设置鼠标热点 X 偏移量的属性。HOTSPOT_Y:用于设置鼠标热点 Y 偏移量的属性。
当平面被用作光标图像以显示鼠标指针时,“热点”是光标图像内鼠标事件预期发生位置的偏移量。
正值将热点从光标平面的左上角向右和向下移动。
大多数显示驱动程序不需要此信息,因为热点实际上没有连接到屏幕上的任何可见内容。但是,对于诸如 para-virtualized 驱动程序(例如 qxl、vbox、virtio、vmwgfx)之类的显示驱动程序,这是必要的,这些驱动程序连接到带有鼠标指针的用户控制台。由于这些控制台通常通过网络进行远程访问,因此它们必须等待完整的网络往返后才能向用户显示指针移动。新的鼠标事件必须从用户的控制台通过网络发送到虚拟输入设备,转发到桌面进行处理,然后才能更新光标平面的位置并通过网络发送回用户的控制台。相反,通过热点信息,控制台可以预测新位置,并在收到确认之前在那里绘制鼠标光标。为了正确执行此操作,用户控制台必须能够预测桌面将如何处理鼠标事件,这通常需要桌面的鼠标拓扑信息,即每个 CRTC 在鼠标坐标空间中的位置。这通常使用一些特定于驱动程序的方法发送到 para-virtualized 驱动程序,然后驱动程序通过虚拟显示设备或虚拟机监控程序将其转发到控制台。
通常假设一次只有一个光标平面以这种方式使用,并且桌面将所有鼠标设备馈送到同一个全局指针。需要此功能的 para-virtualized 驱动程序应仅公开单个光标平面,或找到其他方法与支持多个指针的用户空间桌面进行协调。如果设置了热点属性,则假定光标平面仅用于显示鼠标光标图像,因此,组合光标平面 + 偏移量的位置可以用于与来自鼠标设备的输入进行协调。
然后,光标将绘制在 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-电视 |
“模式” |
枚举 |
{ “NTSC_M”,“NTSC_J”,“NTSC_443”,“PAL_B” } 等 |
连接器 |
待定 |
|
“左_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“右_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“上_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“下_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“水平位置” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“垂直位置” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“对比度” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“饱和度” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“色调” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“清晰度” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“闪烁_滤镜” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“闪烁_滤镜_自适应” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“闪烁_滤镜_2d” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“电视_色度_滤镜” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“电视_亮度_滤镜” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“点爬行” |
范围 |
最小值=0,最大值=1 |
连接器 |
待定 |
||
SDVO-电视/LVDS |
“亮度” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
|
CDV gma-500 |
通用 |
“广播 RGB” |
枚举 |
{ “完整”,“受限 16:235” } |
连接器 |
待定 |
Poulsbo |
通用 |
“背光” |
范围 |
最小值=0,最大值=100 |
连接器 |
待定 |
SDVO-电视 |
“模式” |
枚举 |
{ “NTSC_M”,“NTSC_J”,“NTSC_443”,“PAL_B” } 等 |
连接器 |
待定 |
|
“左_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“右_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“上_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“下_边距” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“水平位置” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“垂直位置” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“对比度” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“饱和度” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“色调” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“清晰度” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“闪烁_滤镜” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“闪烁_滤镜_自适应” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“闪烁_滤镜_2d” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“电视_色度_滤镜” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“电视_亮度_滤镜” |
范围 |
最小值=0,最大值=SDVO 相关 |
连接器 |
待定 |
||
“点爬行” |
范围 |
最小值=0,最大值=1 |
连接器 |
待定 |
||
SDVO-电视/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
,并在其 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 事件的基础结构。
pipe
此事件所属的
drm_crtc
的drm_crtc_index()
。sequence
帧事件应触发的时间
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
的指针。queue
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()
。time
与 count 对应的 Vblank 时间戳。
refcount
vblank 中断的用户/等待程序的数量。仅当此引用计数达到 0 时,才能使用 disable_timer 禁用硬件中断。
last
受
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 计数。pipe
与此结构对应的
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
来访问硬件模式,因为很难从中断上下文中获取它。config
存储给定 CRTC 的 vblank 配置值。另请参阅
drm_crtc_vblank_on_config()
。enabled
跟踪相应
drm_crtc
的启用状态,以避免重复禁用,从而破坏保存的状态。非原子 KMS 的驱动程序需要它,因为这些驱动程序可能会多次执行其 CRTC 禁用功能。worker
用于执行 vblank 工作的
kthread_worker
。pending_work
等待未来 vblank 的已计划
drm_vblank_work
项的列表。work_wait_queue
用于发出
drm_vblank_work
项已完成执行或已取消信号的等待队列。
描述
此结构跟踪一个 CRTC 的 vblank 状态。
请注意,出于历史原因,垂直同步消隐处理代码仍然与旧式/非 KMS 驱动程序共享 - 这是一个独立的结构,不直接连接到 struct drm_crtc
。但所有公共接口函数都接受一个 struct drm_crtc
来隐藏此实现细节。
参数
struct drm_crtc *crtc
要检索哪个计数器
描述
此函数类似于 drm_crtc_vblank_count()
,但此函数使用高精度时间戳支持进行插值,以处理与垂直同步消隐中断的竞争。
这对于可以获取扫描输出位置但没有硬件帧计数器的硬件最有用。
-
int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)¶
初始化垂直同步消隐支持
参数
struct drm_device *dev
DRM 设备
unsigned int num_crtcs
dev 支持的 CRTC 数量
描述
此函数初始化 num_crtcs 显示管道的垂直同步消隐支持。清理工作通过使用 drmm_add_action_or_reset()
添加的清理函数自动处理。
返回
成功时返回零,失败时返回负错误代码。
-
bool drm_dev_has_vblank(const struct drm_device *dev)¶
测试是否已为设备初始化垂直同步消隐
参数
const struct drm_device *dev
设备
描述
驱动程序可以调用此函数来测试是否已为设备初始化垂直同步消隐支持。对于大多数硬件,这意味着也可以启用垂直同步消隐。
原子助手使用此函数初始化 drm_crtc_state.no_vblank
。另请参阅 drm_atomic_helper_check_modeset()
。
返回
如果已为给定设备初始化垂直同步消隐,则为 True,否则为 False。
参数
struct drm_crtc *crtc
要检索哪个 CRTC 的垂直同步消隐等待队列
描述
此函数返回指向 CRTC 的垂直同步消隐等待队列的指针。驱动程序可以使用它来实现使用 wait_event()
和相关函数的垂直同步消隐等待。
-
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
要检索哪个计数器
描述
获取表示自系统启动以来垂直同步消隐事件数量的“处理过的”垂直同步消隐计数值,包括由于模式设置活动而丢失的事件。请注意,此计时器对于竞争的垂直同步消隐中断是不正确的(因为它只报告软件垂直同步消隐计数器),对于此类用例,请参阅 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)¶
检索“处理过”的垂直同步消隐计数器值以及与该垂直同步消隐计数器值对应的系统时间戳
参数
struct drm_crtc *crtc
要检索哪个计数器
ktime_t *vblanktime
指向接收垂直同步消隐时间戳的时间的指针。
描述
获取“处理过”的垂直同步消隐计数器值,该值表示自系统启动以来垂直同步消隐事件的数量,包括由于模式设置活动而丢失的事件。返回与当前垂直同步消隐计数器值相对应的垂直同步消隐间隔时间的系统时间戳。
请注意,对于给定的垂直同步消隐计数器值,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()
从其中断处理程序手动发送事件,并确保硬件在提交原子更新时不会发生任何可能的竞争。
调用者必须为通过 drm_crtc_vblank_get()
获取的事件 e 持有垂直同步消隐引用,该引用将在下一个垂直同步消隐到达时被丢弃。
注意
使用此函数发送 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 索引
描述
这会使用 irq 驱动程序接口等待 pipe 上通过一个垂直同步消隐。当 pipe 的垂直同步消隐 irq 被禁用时(例如,由于缺少驱动程序支持或因为 crtc 关闭),调用此操作会失败。
这是 drm_crtc_wait_one_vblank()
的旧版本。
参数
struct drm_crtc *crtc
DRM crtc
描述
这会使用 irq 驱动程序接口等待 crtc 上通过一个垂直同步消隐。当 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¶
一个延迟的工作项,它会延迟到目标垂直同步(vblank)信号通过后,然后在中断请求(IRQ)上下文之外以实时优先级执行。
定义:
struct drm_vblank_work {
struct kthread_work base;
struct drm_vblank_crtc *vblank;
u64 count;
int cancelling;
struct list_head node;
};
成员
基础
基本的
kthread_work
项,将由drm_vblank_crtc.worker
执行。驱动程序不应直接与此交互,而应依赖drm_vblank_work_init()
来初始化它。垂直同步(vblank)
指向此工作项所属的
drm_vblank_crtc
的指针。count
此工作将执行的目标垂直同步信号。驱动程序不应直接修改此值,而应使用
drm_vblank_work_schedule()
。正在取消
当前正在运行的
drm_vblank_work_cancel_sync()
调用的次数。在所有调用完成之前,无法重新调度工作项。节点
此工作项在
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 初始化一个垂直同步工作项。