TODO 列表¶
本节包含内核 DRM 图形子系统中一些较小的日常任务列表,这些任务适合作为新手项目。或者在缓慢的雨天进行。
难度¶
为了方便起见,任务被分为不同的级别
入门:适合开始使用 DRM 子系统的良好任务。
中级:需要在 DRM 子系统中工作的一些经验,或者一些特定的 GPU/显示图形知识的任务。 对于调试问题,最好有相关的硬件(或虚拟驱动程序设置)可用于测试。
高级:需要相当了解 DRM 子系统和图形主题的棘手任务。 通常需要相关硬件进行开发和测试。
专家:仅在您已经成功完成一些棘手的重构并且是特定领域的专家时才尝试这些任务
子系统范围的重构¶
删除自定义 dumb_map_offset 实现¶
所有基于 GEM 的驱动程序都应使用 drm_gem_create_mmap_offset()
代替。 检查每个单独的驱动程序,确保它可以与通用实现一起工作(各种实现中存在大量过时的锁定遗留),然后将其删除。
联系人:Simona Vetter,各自的驱动程序维护者
级别:中级
将现有 KMS 驱动程序转换为原子模式设置¶
3.19 具有原子模式设置接口和助手,因此现在可以转换驱动程序。 像 Wayland 或 Android 上的 Surfaceflinger 这样的现代合成器真正需要原子模式设置接口,所以这一切都关乎美好的未来。
有一个原子转换指南 [1],您只需要一个用于非转换驱动程序的 GPU。 LWN.net 上的“原子模式设置设计概述”系列 [2] [3] 也可能会有所帮助。
作为此的一部分,驱动程序还需要转换为通用平面(这意味着将主平面和光标作为适当的平面对象公开)。 但是,通过直接使用新的原子助手驱动程序回调,这更容易完成。
联系人:Simona Vetter,各自的驱动程序维护者
级别:高级
清理平面周围的剪切坐标混乱¶
我们有一个助手可以通过 drm_plane_helper_check_update() 来纠正这一点,但它没有被一致地使用。 应该修复此问题,最好是在原子助手中(然后将驱动程序转移到剪切坐标)。 也可能应该将助手从 drm_plane_helper.c 移动到原子助手,以避免混淆 - 该文件中的其他助手都是已弃用的旧助手。
联系人:Ville Syrjälä,Simona Vetter,驱动程序维护者
级别:高级
改进平面 atomic_check 助手¶
除了上面提到的剪切坐标外,当前助手还存在一些次优的问题
drm_plane_helper_funcs->atomic_check 被调用用于启用或禁用平面。 最多,这似乎会让驱动程序感到困惑,最糟糕的是,这意味着当平面在没有 CRTC 的情况下被禁用时,它们会崩溃。 唯一的特殊处理是重置平面状态结构中的值,而这应该移动到 drm_plane_funcs->atomic_duplicate_state 函数中。
完成后,助手可以停止为禁用的平面调用 ->atomic_check。
然后我们可以遍历所有驱动程序并删除对 plane_state->fb 和 plane_state->crtc 的或多或少令人困惑的检查。
联系人:Simona Vetter
级别:高级
将早期原子驱动程序转换为异步提交助手¶
第一年,原子模式设置助手不支持异步/非阻塞提交,每个驱动程序都必须手动滚动它们。 现在已经修复了此问题,但仍然有一堆现有的驱动程序可以很容易地转换为新的基础设施。
助手的一个问题是它们要求驱动程序正确处理原子提交的完成事件。 但是无论如何,修复这些错误是好事。
有点相关的是 legacy_cursor_update 黑客,它应该在仍然查看该标志的驱动程序中用助手中的新 atomic_async_check/commit 功能替换。
联系人:Simona Vetter,各自的驱动程序维护者
级别:高级
重命名 drm_atomic_state¶
KMS 框架对 state
概念使用两个略有不同的定义。 对于给定的对象(平面、CRTC、编码器等,即 drm_$OBJECT_state
),状态是该对象的整个状态。 但是,在设备级别,drm_atomic_state
指的是对有限数量的对象的状态更新。
状态不是整个设备状态,而只是该设备中某些对象的完整状态。 这会让新手感到困惑,应该将 drm_atomic_state
重命名为更清晰的名称,例如 drm_atomic_commit
。
除了重命名结构本身外,它还意味着重命名一些相关函数(drm_atomic_state_alloc
、drm_atomic_state_get
、drm_atomic_state_put
、drm_atomic_state_init
、__drm_atomic_state_free
等)。
联系人:Maxime Ripard <mripard@kernel.org>
级别:高级
原子 KMS 的影响¶
drm_atomic_helper.c
提供了一批在新的原子驱动程序接口之上实现旧 IOCTL 的函数。 这对于驱动程序的逐步转换非常有用,但不幸的是,语义不匹配有点太严重了。 因此,需要进行一些后续工作来调整函数接口以解决这些问题
原子需要锁获取上下文。 目前,它通过一些可怕的技巧隐式传递,并且还在后台使用
GFP_NOFAIL
进行分配。 所有旧路径都需要开始在堆栈上显式分配获取上下文,然后将其显式传递到驱动程序中,以便原子旧函数可以使用它们。除了某些驱动程序代码外,这已经完成。 此任务应通过在
drm_modeset_lock_all()
中添加 WARN_ON(!drm_drv_uses_atomic_modeset) 来完成。现在,一些 vtable 挂钩的位置错误:DRM 在核心 vfunc 表(名为
drm_foo_funcs
)之间进行了拆分,这些表用于实现用户空间 ABI。 然后是辅助库的可选挂钩(名称drm_foo_helper_funcs
),这些挂钩纯粹用于内部使用。 其中一些挂钩应从_funcs
移动到_helper_funcs
,因为它们不是核心 ABI 的一部分。 对于drm_crtc.h
中的每种情况,内核文档中都有一个FIXME
注释。
联系人:Simona Vetter
级别:中级
从 GEM 驱动程序中删除 dev->struct_mutex¶
dev->struct_mutex
是来自旧时代的 Big DRM Lock,并且感染了一切。 现在,在现代驱动程序中,唯一必须的是串行化 GEM 缓冲区对象销毁。 不幸的是,这意味着驱动程序必须跟踪该锁,并根据上下文调用 unreference
或 unreference_locked
。
核心 GEM 不再需要 struct_mutex
,因为内核 4.8,并且对于完全没有 struct_mutex
的任何驱动程序,都有 GEM 对象 free
回调。
对于需要 struct_mutex
的驱动程序,应将其替换为驱动程序私有锁。 棘手的部分是 BO free 函数,因为这些函数不能再可靠地获取该锁。 相反,需要使用适当的从属锁来保护状态,或者将一些清理工作推送到工作线程。 对于性能关键的驱动程序,使用更细粒度的每个缓冲区对象和每个上下文锁定方案可能也会更好。 目前只有 msm
和 i915 驱动程序使用 struct_mutex
。
联系人:Simona Vetter,各自的驱动程序维护者
级别:高级
将缓冲区对象锁定移动到 dma_resv_lock()¶
许多驱动程序都有自己的按对象加锁方案,通常使用 mutex_lock()
。这给缓冲区共享带来了各种问题,因为根据哪个驱动程序是导出者和导入者,锁定层次结构会反转。
为了解决这个问题,我们需要一个标准的按对象加锁机制,即 dma_resv_lock()
。此锁需要作为最外层的锁来调用,并删除所有其他驱动程序特定的按对象锁。问题在于,由于 struct dma_buf
缓冲区共享,将实际更改推广到锁定契约是一个重要的日子。
级别:专家
将日志记录转换为带 drm_device 参数的 drm_* 函数¶
对于可能存在多个实例的驱动程序,有必要在日志中区分它们。由于 DRM_INFO/WARN/ERROR 不执行此操作,驱动程序过去使用 dev_info/warn/err 来进行区分。我们现在有了 drm 打印函数的 drm_* 变体,因此我们可以开始将这些驱动程序转换回使用 drm 格式的特定日志消息。
在开始此转换之前,请联系相关的维护人员,以确保您的工作将被合并 - 并非所有人都认为 DRM dmesg 宏更好。
联系人:Sean Paul,您计划转换的驱动程序的维护者
级别:入门
转换驱动程序以使用简单的模式设置挂起/恢复¶
大多数使用 drm_atomic_helper_suspend/resume() 的驱动程序(i915 和 nouveau 除外)可能可以转换为使用 drm_mode_config_helper_suspend/resume()。此外,在较旧的原子模式设置驱动程序中仍然存在原子挂起/恢复代码的开放式编码版本。
联系人:您计划转换的驱动程序的维护者
级别:中级
在不使用 fbdev 的情况下重新实现 drm_fbdev_fb_ops 中的函数¶
drm_fbdev_fb_ops 中的许多回调函数可以从在不依赖 fbdev 模块的情况下重写中获益。一些辅助函数可以进一步受益于使用 struct iosys_map
而不是原始指针。
联系人:Thomas Zimmermann <tzimmermann@suse.de>,Simona Vetter
级别:高级
基准测试并优化位块传输和格式转换函数¶
快速绘制到显示内存对于许多应用程序的性能至关重要。
至少在 x86-64 上,sys_imageblit() 比 cfb_imageblit() 慢得多,尽管两者都使用相同的位块传输算法,并且后者是为 I/O 内存编写的。事实证明,cfb_imageblit() 使用 movl 指令,而 sys_imageblit 显然没有。这似乎是 gcc 优化器的问题。DRM 的格式转换辅助函数可能也会遇到类似的问题。
基准测试并优化 fbdev 的 sys_() 辅助函数和 DRM 的格式转换辅助函数。在可以进一步优化的情况下,也许可以实现不同的算法。对于微优化,请显式使用 movl/movq 指令。这可能需要特定于架构的辅助函数(例如,storel() storeq())。
联系人:Thomas Zimmermann <tzimmermann@suse.de>
级别:中级
drm_framebuffer_funcs 和 drm_mode_config_funcs.fb_create 清理¶
更多驱动程序可以切换到 drm_gem_framebuffer 辅助函数。各种障碍
首先需要使用 drm_atomic_helper_dirtyfb 切换到通用的脏跟踪代码(例如 qxl)。
需要切换到 drm_fbdev_generic_setup(),否则很多自定义的 fb 设置代码无法删除。
需要切换到
drm_gem_fb_create()
,因为现在drm_gem_fb_create()
会检查原子驱动程序的有效格式。许多驱动程序都继承了 drm_framebuffer,我们需要各种 drm_gem_fb_create 函数的嵌入兼容版本。可以根据需要称为 drm_gem_fb_create/_with_dirty/_with_funcs。
联系人:Simona Vetter
级别:中级
通用 fbdev defio 支持¶
fbdev 核心中的 defio 支持代码有一些非常具体的要求,这意味着驱动程序需要为 fbdev 提供特殊的帧缓冲。主要问题是它在 struct page 本身中使用了一些字段,这会破坏 shmem gem 对象(和其他东西)。为了支持 defio,受影响的驱动程序需要使用影子缓冲区,这可能会增加 CPU 和内存开销。
可能的解决方案是在 drm fbdev 模拟中编写我们自己的 defio mmap 代码。它需要完全包装现有的 mmap 操作,并在完成写保护/mkwrite 技巧后转发所有内容
在 drm_fbdev_fb_mmap 辅助函数中,如果我们需要 defio,请将默认页面保护更改为写保护,类似于这样
vma->vm_page_prot = pgprot_wrprotect(vma->vm_page_prot);
设置 mkwrite 和 fsync 回调,其实现方式类似于核心 fbdev defio 内容。这些都应该在普通的 ptes 上工作,它们实际上不需要 struct page。uff。这些都应该在普通的 ptes 上工作,它们实际上不需要 struct page。
在单独的结构中跟踪脏页(每个页面一个位的位字段应该可以工作),以避免破坏 struct page。
最好也为此提供一些 igt 测试用例。
联系人:Simona Vetter,Noralf Tronnes
级别:高级
连接器注册/注销修复¶
对于大多数连接器,直接从驱动程序代码调用 drm_connector_register/unregister 是一个空操作,drm_dev_register/unregister 已经处理了这个问题。我们可以删除所有这些。
对于 dp 驱动程序来说,情况有点混乱,因为我们在调用 drm_dp_aux_register 时需要注册连接器。通过调用 drm_dp_aux_init 并按照 kerneldoc 中的建议将实际注册移动到 late_register 回调中来解决此问题。
级别:中级
删除加载/卸载回调¶
struct &drm_driver 中的加载/卸载回调非常像中间层,而且由于历史原因,它们在设置 &drm_driver 结构和调用 drm_dev_register()
之间顺序错误(我们无法修复)。
重做驱动程序以不再使用加载/卸载回调,直接将加载/卸载序列编码到驱动程序的 probe 函数中。
转换完所有驱动程序后,删除加载/卸载回调。
联系人:Simona Vetter
级别:中级
用 drm_display_info.is_hdmi 替换 drm_detect_hdmi_monitor()¶
解析 EDID 后,可以通过 drm_display_info.is_hdmi 获取显示器的 HDMI 支持信息。许多驱动程序仍然调用 drm_detect_hdmi_monitor()
来检索相同的信息,这效率较低。
审核每个调用 drm_detect_hdmi_monitor()
的驱动程序,并在适用时切换到 drm_display_info.is_hdmi。
联系人:Laurent Pinchart,各自的驱动程序维护者
级别:中级
整合自定义驱动程序模式设置属性¶
在原子模式设置发生之前,许多驱动程序都在创建自己的属性。除其他外,原子性要求不应使用自定义的、驱动程序特定的属性。
对于此任务,我们的目标是引入核心辅助函数或重用现有的辅助函数(如果可用)
一个快速的、未经证实的示例列表。
引入核心辅助函数:- 音频(amdgpu、intel、gma500、radeon)- 亮度、对比度等(armada、nouveau)- 仅限叠加(?)- 广播 rgb(gma500、intel)- 色键(armada、nouveau、rcar)- 仅限叠加(?)- 抖动(amdgpu、nouveau、radeon)- 各驱动程序差异很大 - 下扫描系列(amdgpu、radeon、nouveau)
已在核心中:- 色彩空间 (sti) - 电视格式名称、增强功能(gma500、intel)- 电视过扫描、边距等(gma500、intel)- zorder (omapdrm) - 与 zpos 相同(?)
联系人:Emil Velikov,各自的驱动程序维护者
级别:中级
在整个代码库中使用 struct iosys_map¶
指向共享设备内存的指针存储在 struct iosys_map
中。每个实例都知道它指的是系统内存还是 I/O 内存。大多数 DRM 范围的接口都已转换为使用 struct iosys_map
,但实现通常仍然使用原始指针。
任务是在有意义的地方使用 struct iosys_map
。
内存管理器应将
struct iosys_map
用于 dma-buf 导入的缓冲区。TTM 可能会从内部使用
struct iosys_map
中获益。帧缓冲复制和位块传输辅助函数应在
struct iosys_map
上运行。
联系人:Thomas Zimmermann <tzimmermann@suse.de>,Christian König,Simona Vetter
级别:中级
检查所有驱动程序是否正确设置了 struct drm_mode_config.{max_width,max_height}¶
struct drm_mode_config
.{max_width,max_height} 中的值描述了支持的最大帧缓冲大小。它是虚拟屏幕大小,但许多驱动程序将其视为物理分辨率的限制。
最大宽度取决于硬件的最大扫描线间距。最大高度取决于可寻址的显存量。检查所有驱动程序以将字段初始化为正确的值。
联系人:Thomas Zimmermann <tzimmermann@suse.de>
级别:中级
在所有驱动程序中请求内存区域¶
遍历所有驱动程序,并添加代码来请求驱动程序使用的内存区域。这需要添加对 request_mem_region()、pci_request_region()
或类似函数的调用。尽可能使用辅助函数进行托管清理。
驱动程序在这方面做得相当糟糕,并且以前 DRM 和 fbdev 驱动程序之间存在冲突。尽管如此,这样做是正确的。
联系人:Thomas Zimmermann <tzimmermann@suse.de>
级别:入门
移除驱动程序对 FB_DEVICE 的依赖¶
许多 fbdev 驱动程序通过 sysfs 提供属性,因此依赖于选择 CONFIG_FB_DEVICE。审查每个驱动程序,并尝试使对 CONFIG_FB_DEVICE 的任何依赖成为可选的。至少,驱动程序中的相应代码可以通过 ifdef CONFIG_FB_DEVICE 进行条件化。并非所有驱动程序都可能能够删除 CONFIG_FB_DEVICE。
联系人:Thomas Zimmermann <tzimmermann@suse.de>
级别:入门
移除 panel-simple 和 panel-edp 中 remove/shutdown 中的 disable/unprepare¶
从commit d2aacaf07395(“drm/panel: Check for already prepared/enabled in drm_panel”)开始,我们在 drm_panel 核心中有一个检查,以确保没有人双重调用 prepare/enable/disable/unprepare。最终,这应该可能被转换为 WARN_ON() 或以某种方式发出更大的声音。
目前,我们预计在使用 panel-simple 和 panel-edp 时,仍然可能会在 drm_panel 核心中遇到警告。由于这些面板驱动程序与许多不同的 DRM modeset 驱动程序一起使用,它们仍然会额外努力在关闭时禁用/取消准备面板。具体来说,如果面板驱动程序在 DRM modeset 驱动程序_之前_调用 shutdown(),并且 DRM modeset 驱动程序在其自己的 shutdown() 回调中正确调用 drm_atomic_helper_shutdown()
,我们仍然可能会遇到这些警告。在这种情况下,可以通过使用设备链接等方式来避免警告,以确保面板在 DRM modeset 驱动程序之后调用 shutdown()。
一旦已知所有 DRM modeset 驱动程序都正确关闭,则应删除 panel-simple 和 panel-edp 中 remove/shutdown 中的额外 disable/unprepare 调用,并将此 TODO 项标记为完成。
联系人:Douglas Anderson <dianders@chromium.org>
级别:中级
过渡到不使用 mipi_dsi_*_write_seq()¶
宏 mipi_dsi_generic_write_seq()
和 mipi_dsi_dcs_write_seq()
是不直观的,因为如果存在错误,它们会从_调用者_的函数中返回。我们应该将所有调用者转移到使用 mipi_dsi_generic_write_seq_multi()
和 mipi_dsi_dcs_write_seq_multi()
宏。
一旦所有调用者都进行了转换,就可以删除宏及其调用的函数 mipi_dsi_generic_write_chatty()
和 mipi_dsi_dcs_write_buffer_chatty()
。或者,如果人们觉得 _multi() 变体对于某些用例来说有点过头,我们可以保留 mipi_dsi_*_write_seq() 变体,但更改它们使其不从调用者中返回。
联系人:Douglas Anderson <dianders@chromium.org>
级别:入门
核心重构¶
使 panic 处理工作¶
这是一个非常多样化的任务,包含许多小片段。
当前无法测试 panic 路径,导致不断崩溃。这里的主要问题是,panic 可以从硬中断上下文触发,因此所有与 panic 相关的回调都可以在硬中断上下文中运行。如果我们能够至少通过例如通过 drm debugfs 文件触发调用来测试 fbdev 辅助代码和驱动程序代码,那就太好了。可以使用到本地处理器的 IPI 来实现硬中断上下文。
不同的 panic 处理程序之间存在巨大的混淆。DRM fbdev 模拟辅助程序有自己的(已长期删除),但除此之外,fbcon 代码本身也有一个。我们需要确保它们不再相互争斗。通过在进入 DRM fbdev 模拟辅助程序的各个入口点检查
oops_in_progress
来解决此问题。这里更简洁的方法是将 fbcon 切换到 线程化 printk 支持。drm_can_sleep()
一团糟。它隐藏了正常操作中的实际错误,并且不是 panic 路径的完整解决方案。我们需要确保只有在真正发生 panic 时它才返回 true,并解决所有不良后果。panic 处理程序绝不能休眠,这也意味着它永远不能
mutex_lock()
。而且它不能无条件地获取任何其他锁,即使是自旋锁(因为 NMI 和硬中断也可能 panic)。我们需要确保不调用此类路径,或尝试锁定所有内容。这真的很难。一个简洁的解决方案是在 KMS 中提供一个完全独立的 panic 输出支持,绕过当前的 fbcon 支持。请参阅 [PATCH v2 0/3] drm: Add panic handling。
将实际的 oops 和前面的 dmesg 编码为 QR 码可能有助于解决可怕的“重要内容已滚动消失”问题。请参阅 [RFC][PATCH] Oops messages transfer using QR codes,其中包含一些可以重用的示例代码。
联系人:Simona Vetter
级别:高级
清理 debugfs 支持¶
它存在许多问题。
转换驱动程序以支持
drm_debugfs_add_files()
函数,而不是drm_debugfs_create_files()
函数。通过为连接器和 crtc 也推出相同的 debugfs 预注册基础结构,改进后期注册 debugfs。这样,驱动程序就不再需要将其设置代码拆分为 init 和注册。
我们可能希望在核心中直接支持 crtc/连接器以及其他 kms 对象上的 debugfs 文件。这些对象的功能中甚至有 drm_print 支持来转储 kms 状态,所以一切都已就绪。然后,->show() 函数显然应该为您提供指向正确对象的指针。
我们拥有的 drm_driver->debugfs_init 钩子只是旧的中间层加载序列的产物。DRM debugfs 的工作方式应该更像 sysfs,您可以随时为对象创建属性/文件,并且核心负责在注册/取消注册时发布/取消发布所有文件。驱动程序不应担心这些技术细节,并且修复此问题(以及 drm_minor->drm_device 移动)将允许我们删除 debugfs_init。
联系人:Simona Vetter
级别:中级
对象生命周期修复¶
这里有两个相关的问题。
清理各种 ->destroy 回调,它们通常都是相同的简单代码。
许多驱动程序错误地使用 devm_kzalloc 分配 DRM modeset 对象,这会导致在驱动程序卸载时出现释放后使用问题。由于 EPROBE_DEFERRED 退避,即使对于集成在 SoC 上的硬件的驱动程序,这也会带来严重的问题。
这两个问题都可以通过切换到 drmm_kzalloc()
以及提供的各种便利包装器来解决,例如 drmm_crtc_alloc_with_planes()
、drmm_universal_plane_alloc()
等等。
联系人:Simona Vetter
级别:中级
从 dma-buf 导入中移除自动页面映射¶
导入 dma-buf 时,dma-buf 和 PRIME 框架会自动将导入的页面映射到导入器的 DMA 区域。drm_gem_prime_fd_to_handle()
和 drm_gem_prime_handle_to_fd()
要求导入器调用 dma_buf_attach()
,即使它们从不进行实际的设备 DMA,而只通过 dma_buf_vmap()
进行 CPU 访问。对于不支持 DMA 操作的 USB 设备,这是一个问题。
要解决此问题,应从缓冲区共享代码中删除自动页面映射。修复此问题会更复杂一些,因为导入/导出缓存也与 &drm_gem_object.import_attach 相关联。同时,只要 USB 主机控制器设备支持 DMA,我们就为 USB 设备掩盖此问题。否则,导入仍然会不必要地失败。
联系人:Thomas Zimmermann <tzimmermann@suse.de>,Simona Vetter
级别:高级
更好的测试¶
使用内核单元测试 (KUnit) 框架添加单元测试¶
KUnit 为 Linux 内核中的单元测试提供了通用框架。拥有一个测试套件可以更早地识别回归。
第一个单元测试的良好候选是 drm_format_helper.c
中的格式转换辅助函数。
联系人:Javier Martinez Canillas <javierm@redhat.com>
级别:中级
清理并记录之前的自测套件¶
一些 KUnit 测试套件(drm_buddy、drm_cmdline_parser、drm_damage_helper、drm_format、drm_framebuffer、drm_dp_mst_helper、drm_mm、drm_plane_helper 和 drm_rect)是最初引入 KUnit 时转换过来的之前的自测套件。
这些套件文档记录相当少,并且目标与单元测试可以达到的目标不同。尝试确定这些套件中的每个测试实际测试的内容,这对于单元测试是否有意义,如果没意义则删除,如果有意义则记录下来,这将非常有帮助。
联系人:Maxime Ripard <mripard@kernel.org>
级别:中级
为 DRM 启用 trinity¶
并修复由此带来的问题。应该会非常有趣……
级别:高级
使 i-g-t 中的 KMS 测试通用化¶
i915 驱动程序团队维护着一个广泛的 i915 DRM 驱动程序测试套件,其中包括大量针对模式设置 API 中极端情况的测试用例。如果这些测试(至少是不依赖于英特尔特定 GEM 功能的测试)能够在任何 KMS 驱动程序上运行,那就太棒了。
在非 i915 上运行 i-g-t 测试的基础工作已经完成,现在缺少的是大规模的转换。对于模式设置测试,我们还需要一些基础设施,使用哑缓冲区处理非平铺缓冲区,以便能够运行所有非 i915 特定的模式设置测试。
级别:高级
扩展虚拟测试驱动程序 (VKMS)¶
有关更多详细信息,请参阅 VKMS 的文档。这是一个理想的实习任务,因为它只需要一个虚拟机,并且可以调整大小以适应可用时间。
级别:请参阅详细信息
背光重构¶
背光驱动程序具有三重启用/禁用状态,这有点多余。计划修复此问题
在所有地方推出
backlight_enable()
和backlight_disable()
辅助函数。这已经开始了。总而言之,只查看上述辅助函数设置的三个状态位中的一个。
删除其他两个状态位。
联系人:Simona Vetter
级别:中级
驱动程序特定¶
AMD DC 显示驱动程序¶
AMD DC 是 Vega 及以后 AMD 设备的显示驱动程序。在清理方面已经取得了很多进展,但仍有大量工作要做。
有关任务,请参阅 drivers/gpu/drm/amd/display/TODO。
联系人:Harry Wentland,Alex Deucher
启动画面¶
现在已经支持编写内部 DRM 客户端,从而可以接手之前由于是为 fbdev 编写而被拒绝的启动画面工作。
[v6,8/8] drm/client:Hack:添加启动画面示例 https://patchwork.freedesktop.org/patch/306579/
[RFC PATCH v2 00/13] 基于内核的启动画面 https://lore.kernel.org/r/[email protected]
联系人:Sam Ravnborg
级别:高级
具有多个内部面板的设备的亮度处理¶
在 x86/ACPI 设备上,可能存在多个背光固件接口:(ACPI) 视频、供应商特定接口和其他接口。以及 KMS 驱动程序的直接/原生 (PWM) 寄存器编程。
为了处理这种情况,x86/ACPI 上使用的背光驱动程序会调用 acpi_video_get_backlight_type(),它具有启发式方法(+怪癖)来选择要使用的背光接口;并且不匹配返回类型的背光驱动程序将不会注册自身,因此只注册一个背光设备(在单个 GPU 设置中,请参阅下文)。
目前,这或多或少假设系统上只有一个(内部)面板。
在具有两个面板的系统上,这可能会成为问题,具体取决于 acpi_video_get_backlight_type() 选择的接口。
原生:在这种情况下,KMS 驱动程序应该知道哪个背光设备属于哪个输出,因此一切都应该正常工作。
视频:这确实支持控制多个背光,但需要进行一些工作以获取输出 <-> 背光设备的映射
以上假设两个面板都需要相同的背光接口类型。在具有多个面板的系统上,如果两个面板需要不同类型的控制,则会出现问题。例如,一个面板需要 ACPI 视频背光控制,而另一个面板正在使用原生背光控制。目前,在这种情况下,只会根据 acpi_video_get_backlight_type() 返回值注册 2 个所需背光设备中的一个。
如果出现这种情况(理论上),那么支持这种情况将需要一些工作。此处的可能解决方案是将设备和连接器名称传递给 acpi_video_get_backlight_type(),以便它可以处理这种情况。
请注意,在某种程度上,我们已经有一个用户空间看到两个面板的情况,在具有多路复用器的双 GPU 笔记本电脑设置中。在这些系统上,我们可能会看到 2 个原生背光设备;或 2 个原生背光设备。
用户空间已经具有通过检测相关面板是否处于活动状态(即 GPU 和面板之间的多路复用器指向哪个方向)来处理这种情况的代码,然后使用该背光设备。但是,此处的用户空间很大程度上假设只有一个面板。它只选择 2 个背光设备中的 1 个,然后只使用该设备。
请注意,(据我所知)所有用户空间代码目前都被硬编码为假设只有一个面板。
在最近的更改之前,对于单个面板(在单个 GPU 笔记本电脑上),不注册多个(例如视频 + 原生)/sys/class/backlight 设备,用户空间会看到多个背光设备,所有设备都控制着同一个背光。
为了处理这种情况,用户空间必须始终选择 /sys/class/backlight 下的一个首选设备,并且会忽略其他设备。因此,为了支持具有多个面板的设备的亮度控制,也需要更新用户空间。
计划通过向面板的 drm_connector 对象添加“显示亮度”属性来允许通过 KMS API 进行亮度控制。这解决了 /sys/class/backlight API 的许多问题,包括无法将 sysfs 背光设备映射到特定连接器。任何为具有多个面板的设备添加亮度控制支持的用户空间更改都应该基于此新的 KMS 属性之上构建。
联系人:Hans de Goede
级别:高级
缓冲区损坏的缓冲区老化或其他损坏累积算法¶
执行每个缓冲区上传的驱动程序需要缓冲区损坏处理(而不是像执行每个平面或每个 CRTC 上传的驱动程序那样的帧损坏),但不支持获取缓冲区老化或任何其他损坏累积算法。
因此,如果自上次页面翻转以来附加到平面的帧缓冲区已更改,则损坏辅助函数只会回退到完整的平面更新。驱动程序将 &drm_plane_state.ignore_damage_clips 设置为 true,以指示 drm_atomic_helper_damage_iter_init()
和 drm_atomic_helper_damage_iter_next()
辅助函数应忽略损坏剪辑。
应该对此进行改进,以便在执行每个缓冲区上传的驱动程序上正确地进行损坏跟踪。
有关损坏跟踪以及学习资料的更多信息,请参见 损坏跟踪属性。
联系人:Javier Martinez Canillas <javierm@redhat.com>
级别:高级
从 drm_syncobj 查询错误¶
驱动程序独立代码可以使用 drm_syncobj 容器来表示提交完成。
仍然缺少的一个小功能是通用的 DRM IOCTL,用于查询二进制和时间线 drm_syncobj 的错误状态。
应该通过实现必要的内核接口并在用户空间堆栈中添加对该接口的支持来对此进行改进。
联系人:Christian König
级别:入门
DRM 之外¶
将 fbdev 驱动程序转换为 DRM¶
有很多用于旧硬件的 fbdev 驱动程序。一些硬件已经过时,但一些硬件仍然提供足够好的帧缓冲区。仍然有用的驱动程序应转换为 DRM,然后从 fbdev 中删除。
最好通过从新的 DRM 驱动程序开始来转换非常简单的 fbdev 驱动程序。简单的 KMS 辅助函数和 SHMEM 应该能够处理任何现有硬件。新驱动程序的回调函数从现有的 fbdev 代码中填充。
更复杂的 fbdev 驱动程序可以使用 DRM fbconv 辅助函数逐步重构为 DRM 驱动程序 [4]。这些辅助函数提供 DRM 核心基础设施和 fbdev 驱动程序接口之间的过渡层。在 fbconv 辅助函数之上创建一个新的 DRM 驱动程序,复制 fbdev 驱动程序,并将其连接到 DRM 代码。Thomas Zimmermann 的 fbconv 树 [4] 中提供了几个 fbdev 驱动程序的示例,以及此过程的教程 [5]。结果是一个原始的 DRM 驱动程序,可以运行 X11 和 Weston。
联系人:Thomas Zimmermann <tzimmermann@suse.de>
级别:高级