内核模式设置
内核模式设置 (KMS) 是一种在内核空间而不是用户空间中设置显示分辨率和深度的方法。
Linux 内核实现的 KMS 可以在帧缓冲区中启用原生分辨率,并允许即时控制台 (tty) 切换。KMS 还支持更新的技术(例如 DRI2),这将有助于减少伪影并提高 3D 性能,甚至内核空间节能。
背景
以前,设置显卡是 X 服务器的工作。因此,在虚拟控制台中不容易拥有精美的图形。此外,每次从 X 切换到虚拟控制台(Ctrl+Alt+F2
)时,服务器都必须将显卡的控制权交给内核,这很慢并且会导致闪烁。当控制权交还给 X 服务器时(当 X 在 VT7 中运行时,使用 Alt+F7
),也会发生相同的“痛苦”过程。
有了内核模式设置 (KMS),内核现在能够设置显卡的模式。这使得启动、虚拟控制台和 X 快速切换期间的精美图形成为可能,以及其他功能。
配置
首先,请注意,对于您使用的任何方法,您都应始终禁用
- 启动引导程序中的任何
vga=
选项,因为这些选项会与 KMS 启用的原生分辨率冲突。 - 任何启用与驱动程序冲突的帧缓冲区的
video=
行。 - 任何其他帧缓冲区驱动程序(例如 uvesafb)。
后期 KMS 启动
Intel、Nouveau、ATI 和 AMDGPU 驱动程序已经为所有芯片组自动启用 KMS,因此您无需执行任何操作。
专有 NVIDIA 驱动程序支持 KMS(自 364.12 起),必须手动启用。
早期 KMS 启动
KMS 通常在 initramfs 阶段之后初始化。但是,可以在 initramfs 阶段启用 KMS。将 视频驱动程序所需的模块添加到 initramfs 配置文件中
amdgpu
用于 AMDGPU,或在使用旧版 ATI 驱动程序时使用radeon
。i915
用于 Intel 显卡。nouveau
用于开源 Nouveau 驱动程序。nvidia nvidia_modeset nvidia_uvm nvidia_drm
用于树外 nvidia 和 nvidia-open 驱动程序。有关详细信息,请参阅 NVIDIA#DRM 内核模式设置。
mgag200
用于 Matrox 显卡。- 取决于 QEMU 使用的图形(qemu 选项
-vga type
或 libvirt<video><model type='type'>
[2])bochs
用于std
(qemu) 和vga
/bochs
(libvirt),virtio-gpu
用于virtio
,qxl
用于qxl
,vmwgfx
用于vmware
(qemu) 和vmvga
(libvirt),cirrus
用于cirrus
。
- 取决于 VirtualBox 图形控制器
vmwgfx
用于 VMSVGA,vboxvideo
用于 VBoxVGA 或 VBoxSVGA。
Initramfs 配置说明根据您使用的 initramfs 生成器略有不同。
mkinitcpio
对于树内模块,请确保 kms
包含在 /etc/mkinitcpio.conf
中的 HOOKS 数组中(这是自 mkinitcpio v33 以来的默认设置)。
对于树外模块,请将模块名称放在 MODULES 数组中。例如,要为 NVIDIA 显卡驱动程序启用早期 KMS
/etc/mkinitcpio.conf
MODULES=(... nvidia nvidia_modeset nvidia_uvm nvidia_drm ...)
intel_agp
可能会导致问题(显示器没有信号)。有关详细信息,请参阅 [3]。如果您正在使用 #强制模式和 EDID 方法,您还应该将自定义文件嵌入到 initramfs 中
/etc/mkinitcpio.conf
FILES=(/usr/lib/firmware/edid/your_edid.bin)
Booster
如果您使用 Booster,您可以使用此配置更改加载所需的模块
/etc/booster.yaml
modules_force_load: i915
如果您正在使用 #强制模式和 EDID 方法,您还应该将自定义文件嵌入到 booster 镜像中
/etc/booster.yaml
extra_files: /usr/lib/firmware/edid/your_edid.bin
然后重新生成 booster 镜像。
故障排除
我的字体太小
请参阅 Linux 控制台#字体,了解如何将控制台字体更改为大字体。Terminus 字体 (terminus-font) 有多种尺寸可供选择,例如较大的 ter-132b
。
或者,禁用模式设置可能会切换到较低的分辨率并使字体显得更大。
强制模式和 EDID
如果您的原生分辨率未自动配置或未检测到任何显示器,则您的显示器可能未发送或仅发送了倾斜的 EDID 文件。内核将尝试捕获这种情况,并将设置最典型的分辨率之一。
如果您有显示器的 EDID 文件,则只需显式强制执行它(见下文)。但是,在大多数情况下,人们无法直接访问健全的文件,因此有必要提取现有文件并对其进行修复,或生成新文件。
通过遵循 上游文档(另请参阅 此处 的简短指南),可以在内核编译期间为各种分辨率和配置生成新的 EDID 二进制文件。此文章详细概述了其他解决方案。提取现有文件在大多数情况下更容易,例如,如果您的显示器在 Windows 下工作正常,您可能很幸运地从相应的驱动程序中提取 EDID,或者如果具有相同设置的类似显示器工作正常,您可以使用 get-edid(1) 从 read-edid 软件包中获取。您也可以尝试在 /sys/class/drm/*/edid
中查找。
准备好 EDID 后,将其放在一个目录中,例如在 /usr/lib/firmware/
下名为 edid
的目录中,并将您的二进制文件复制到其中。
要在启动时加载它,请在 内核命令行中指定以下内容
drm.edid_firmware=edid/your_edid.bin
为了仅将其应用于特定连接器,请使用
drm.edid_firmware=VGA-1:edid/your_edid.bin
如果要设置多个 edid 文件,请使用
drm.edid_firmware=VGA-1:edid/your_edid.bin,VGA-2:edid/your_other_edid.bin
如果您正在进行早期 KMS,则必须将自定义 EDID 文件包含在 initramfs 中,否则您将遇到问题。
也可以在启动后通过写入 /sys/module/drm/parameters/edid_firmware
来更改 drm.edid_firmware
参数的值
# echo edid/your_edid.bin > /sys/module/drm/parameters/edid_firmware
这仅对新插入的显示器生效,已插入的屏幕将继续使用其现有的 EDID 设置。但是,对于外部显示器,重新插入它们足以看到效果。
要在启动后加载 EDID,如果内核未处于锁定模式,您可以使用 debugfs 而不是内核命令行参数。如果您在连接器上更换显示器或仅用于测试,这非常有用。一旦您拥有如上的 EDID 文件,请运行
# cat correct-edid.bin > /sys/kernel/debug/dri/0/HDMI-A-2/edid_override
并禁用
# echo -n reset > /sys/kernel/debug/dri/0/HDMI-A-2/edid_override
如果您的显示器支持热插拔,您还可以触发热插拔以使显示器使用您刚刚加载的新 EDID(例如,加载到 edid_override
中),这样您就不必物理地重新插入显示器或重新启动
# echo 1 > /sys/kernel/debug/dri/0/HDMI-A-2/trigger_hotplug
强制模式
video=
命令行指定分辨率可能很有用。来自 nouveau wiki
- 可以在内核命令行上强制模式。不幸的是,命令行选项 video 在 DRM 情况下文档记录不充分。有关如何使用它的片段可以在以下位置找到
格式为
video=<driver>:<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
<driver>
:在启动时指定视频模式。<conn>
:指定视频连接类型,例如 VGA、DVI、HDMI 等,请参阅/sys/class/drm/
以获取可用连接器<xres>
:水平分辨率,以像素为单位。<yres>
:垂直分辨率,以像素为单位。[M]
:启用使用 VESA 协调视频定时 (CVT) 来计算视频模式定时,而不是从数据库中查找模式[R]
:在使用 CVT 时,为数字显示启用减少消隐计算。这减少了水平和垂直消隐间隔以节省带宽。[-<bpp>]
:指定颜色深度或每像素位数(例如,-24 表示 24 位颜色)。[@<refresh>]
:指定刷新率,以 Hz 为单位。[i]
:启用隔行扫描模式。[m]
:将边距添加到 CVT 计算(xres 的 1.8% 向下舍入到 8 像素,以及 yres 的 1.8%)[e]
:强制输出为开启[D]
:强制数字输出为开启(例如 DVI-I 连接器)[d]
:强制输出为关闭
您可以多次使用 video=
覆盖多个输出的模式,例如,强制 DVI
为 1024x768,85 Hz 并关闭 TV-out
video=DVI-I-1:1024x768@85 video=TV-1:d
要获取连接器的名称和当前状态,您可以使用以下 shell 单行命令
$ for p in /sys/class/drm/*/status; do con=${p%/status}; echo -n "${con#*/card?-}: "; cat $p; done
DVI-I-1: connected HDMI-A-1: disconnected VGA-1: disconnected
禁用模式设置
您可能出于各种原因想要禁用 KMS。要禁用 KMS,请添加 nomodeset
作为内核参数。有关更多信息,请参阅 内核参数。
除了 nomodeset
内核参数外,对于 Intel 显卡,您需要添加 i915.modeset=0
,对于 Nvidia 显卡,您需要添加 nouveau.modeset=0
。对于 Nvidia Optimus 双显卡系统,您需要添加所有三个内核参数(即 "nomodeset i915.modeset=0 nouveau.modeset=0"
)。