Kernel mode setting (简体中文)
内核级显示模式设置 (KMS) ,作用是可以在内核级别而不是最终用户级别切换显示分辨率和颜色深度。
Linux 内核的 KMS 实现支持在 framebuffer 中使用原生分辨率和即时终端(tty)切换。KMS 使用了更新的技术(例如 DRI2),可以减少失真、增强3D性能,甚至使用内核空间节能功能。
背景
以前,设定显卡是 X 服务器的工作。所以虚拟终端不可能提供漂亮的图像效果。同时,每次使用Ctrl+Alt+F1~7
从X切换到虚拟终端时,x服务器必须将显卡的控制权交给内核,这个流程显得低效并且会导致闪烁。将控制权切回到X服务器同样是一个“痛苦”的过程。
使用内核模式设置后,内核可以设定显卡的模式。这样开机启动即可看到漂亮的显示画面,在 X 图形界面 和 终端 之间也可以快速切换,还有其他的一些优点。
安装
不管使用什么方法,都需要先“禁用”下列项:
- 所有启动加载器中的 "vga=" 选项,这个选项与 KMS 的原生分辨率设置冲突。
- 所有 "video=" 选项,这个选项会启动帧缓冲,导致驱动冲突。
- 所有帧缓冲驱动(例如 uvesafb)。
KMS 晚启动
Intel, Nouveau, ATI 和 AMDGPU 驱动已经为所有芯片组提供了 KMS 支持。这些驱动也会自动启用 KMS。
闭源的 NVIDIA 驱动从 364.12 开始支持 KMS,但是需要 手动启用。
KMS 早启动
KMS通常是在initramfs stage之后开始初始化,但是你也可以在initramfs的阶段启用KMS:
将视频驱动模块加入/etc/mkinitcpio.conf
的 MODULES 行。
-
AMDGPU 驱动加入
amdgpu
; 老的 ATI 驱动加入radeon
-
Intel 卡加入
i915
- 开源的 Nouveau 驱动加入
nouveau
- Matrox 卡加入
mgag200
. -
QEMU 显卡: VirtIO 加入
virtio-gpu
, QXL 加入qxl
for QXL,Cirrus 加入cirrus
例如对 Intel 显卡,将 i915
模块加入到 /etc/mkinitcpio.conf
的 MODULES
行:
MODULES=(i915)
i915
之前添加intel_agp
用来阻止 ACPI 错误。顺序很重要,因为模块是按顺序加载的.如果您使用的是自定义的 EDID 文件,你应该也把它添加到initramfs中:
/etc/mkinitcpio.conf
FILES=(/lib/firmware/edid/your_edid.bin)
最后,重新生成内核镜像(详情参阅 mkinitcpio (简体中文))。
问题解决
字体太小
Linux console#Fonts介绍了如何在终端中使用大字体。软件仓库中的 (terminus-font) 字体提供了很多字号,比如更大一些的 ter-132n
。
或者,可以#禁用 KMS 以切换为更低的分辨率,使得字体外观显得更大一些。
启动错误信息
在比较老的系统上轮询已连接的显示设备的开销很大。在不同的硬件上甚至可能每几百毫秒就轮询一次。这会导致在视频播放等场景中可见的显示延迟,即使视频具有HDP输出,若硬件设置为其他非HDP输出仍会出现延迟。如果每10秒延迟一次,则应禁用轮询。
如果启动时看到 0x00000010 (2) 错误码,(应该有 10 行文字,最后一行是错误码),请使用
/etc/modprobe.d/modprobe.conf
options drm_kms_helper poll=0
Forcing modes and EDID
如果無法自動配置您本機的分辨率,或者根本無法偵測到顯示器;您的顯示器很有可能沒有或發送了破損的 EDID 文件。內核將嘗試捕獲這種情況並設置爲某一通用分辨率。
如果您擁有貴顯示器的 EDID 文件,您只需明確地強制設置即可(詳見下文)。但是,您在大多數情況下可能無法直接取得一個健全的 EDID 文件。您可能需要提取現有 EDID 文件中的信息並試圖修復它,從而獲得了一個新的 EDID 文件。
在內核編譯期間,可以通過遵循 上游文檔 來生成用於各種分辨率和配置的新EDID二進製文件(另請參見 此處 的簡短指南)。 這篇文章 也詳細概述了其他解決方案。在大多數情況下,提取現有文件比較容易。例如從Windows下的驅動程序中提取EDID,如果您的監視器在那裡運行良好。或者您可以使用來自 read-edid 包的 get-edid
命令,從具有相同設置的類似顯示器中提取。可以从 /sys/class/drm/*/edid
中查找一下。
在您的EDID準備就緒後,請將它放置於特定的文件夾。例如一個在 /usr/lib/firmware
下名爲 edid
的文件夾,您可以將您的二進制文件放入其中。
爲了使起在啓動時加載,請在內核命令行加入下列參數:
drm_kms_helper.edid_firmware=edid/your_edid.bin
或者(從內核版本 4.15 開始),您也可以通過下列方式在底層強制EDID信息:
drm.edid_firmware=edid/your_edid.bin
如果您希望僅將其應用於特定的連接器:
drm_kms_helper.edid_firmware=VGA-1:edid/your_edid.bin
您可以從下表找到內置的分辨率。名稱列指定了為了強制使用該分辨率而應該使用的名稱。
分辨率 | 名稱 |
800x600 | edid/800x600.bin |
1024x768 | edid/1024x768.bin |
1280x1024 | edid/1280x1024.bin |
1600x1200 (kernel 3.10 or higher) | edid/1600x1200.bin |
1680x1050 | edid/1680x1050.bin |
1920x1080 | edid/1920x1080.bin |
如果您要進行KMS早啓動,則必須在initramfs中包含自定義EDID文件,否則可能會遇到問題。
Forcing modes
video=
command line may be useful in some scenarios.From the nouveau wiki:
- A mode can be forced on the kernel command line. Unfortunately, the command line option video is poorly documented in the DRM case. Bits and pieces on how to use it can be found in
The format is:
video=<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
-
<conn>
: Connector, e.g. DVI-I-1, see/sys/class/drm/
for available connectors -
<xres> x <yres>
: resolution -
M
: compute a CVT mode? -
R
: reduced blanking? -
-<bpp>
: color depth -
@<refresh>
: refresh rate -
i
: interlaced (non-CVT mode) -
m
: margins? -
e
: output forced to on -
d
: output forced to off -
D
: digital output forced to on (e.g. DVI-I connector)
You can override the modes of several outputs using video=
several times, for instance, to force DVI
to 1024x768 at 85 Hz and TV-out
off:
video=DVI-I-1:1024x768@85 video=TV-1:d
To get the name and current status of connectors, you can use the following shell oneliner:
$ 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
Forcing modes
video=
command line may be useful in some scenarios来自 nouveau wiki:
用内核命令行可以强制设置使用的模式。但是 DRM 内核选项的文档很少,使用的方法位于:
- https://cgit.freedesktop.org/nouveau/linux-2.6/tree/Documentation/fb/modedb.txt
- https://cgit.freedesktop.org/nouveau/linux-2.6/tree/drivers/gpu/drm/drm_fb_helper.c
格式:
video=<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
- <conn>: Connector, e.g. DVI-I-1, 查看
/sys/class/drm/
. - <xres> x <yres>: resolution
- M: compute a CVT mode?
- R: reduced blanking?
- -<bpp>: color depth
- @<refresh>: refresh rate
- i: interlaced (non-CVT mode)
- m: margins?
- e: output forced to on
- d: output forced to off
- D: digital output forced to on (e.g. DVI-I connector)
可以使用多个 "video" 设置不同输出的分辨率,例如要强制 DVI 使用 1024x768 85 Hz ,同时禁用 TV-out :
video=DVI-I-1:1024x768@85 video=TV-1:d
要获取当前连接器的状态,使用下面命令:
$ 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,例如使用 catalyst 驱动时. 只需在内核参数中加入 nomodeset 即可,设置方法请阅读内核参数页面。
使用 nomodeset
内核参数的同时,Intel 卡需要添加 i915.modeset=0
, Nvidia 卡需要添加 nouveau.modeset=0
. Nvidia Optimus 双显卡系统,需要添加三个内核参数:
"nomodeset i915.modeset=0 nouveau.modeset=0"