Kernel mode setting
Kernel Mode Setting (KMS) is a method for setting display resolution and depth in the kernel space rather than user space.
The Linux kernel's implementation of KMS enables native resolution in the framebuffer and allows for instant console (tty) switching. KMS also enables newer technologies (such as DRI2) which will help reduce artifacts and increase 3D performance, even kernel space power-saving.
Background
Previously, setting up the video card was the job of the X server. Because of this, it was not easily possible to have fancy graphics in virtual consoles. Also, each time a switch from X to a virtual console was made (Ctrl+Alt+F2
), the server had to give control over the video card to the kernel, which was slow and caused flickering. The same "painful" process happened when the control was given back to the X server (Alt+F7
when X runs in VT7).
With Kernel Mode Setting (KMS), the kernel is now able to set the mode of the video card. This makes fancy graphics during bootup, virtual console and X fast switching possible, among other things.
Installation
At first, note that for any method you use, you should always disable:
- Any
vga=
options in your bootloader as these will conflict with the native resolution enabled by KMS. - Any
video=
lines that enable a framebuffer that conflicts with the driver. - Any other framebuffer drivers (such as uvesafb).
Late KMS start
Intel, Nouveau, ATI and AMDGPU drivers already enable KMS automatically for all chipsets, so you need not install it manually.
The proprietary NVIDIA driver supports KMS (since 364.12), which has to be manually enabled.
Early KMS start
KMS is typically initialized after the initramfs stage. However, it is possible to enable KMS already during the initramfs stage. Add the required module for the video driver to the initramfs configuration file:
-
amdgpu
for AMDGPU, orradeon
when using the legacy ATI driver. -
i915
for Intel graphics. -
nouveau
for the open-source Nouveau driver. -
mgag200
for Matrox graphics. - Depending on QEMU graphics in use:
virtio-gpu
for VirtIO,qxl
for QXL, orcirrus
for Cirrus. -
nvidia nvidia_modeset nvidia_uvm nvidia_drm
for nvidia driver. See NVIDIA#DRM kernel mode setting for details.
Initramfs configuration instructions are slightly different depending on the initramfs generator you use.
mkinitcpio
For example, to enable early KMS for the Intel graphics driver:
/etc/mkinitcpio.conf
MODULES=(... i915 ...)
intel_agp
before i915
to suppress the ACPI errors (check the output of lsmod
on your running system to see if intel_agp
is loaded). This may be required for resuming from hibernation to work with a changed display configuration. If you use PRIME GPU with Intel IGP being your primary GPU and AMD as the discrete one, adding intel_agp
may lead to troubles when resuming from hibernation (monitor gets no signal). See [1] for details.If you are using a custom EDID file (not applicable for the built-in resolutions), you should embed it into initramfs as well:
/etc/mkinitcpio.conf
FILES=(/usr/lib/firmware/edid/your_edid.bin)
Then regenerate the initramfs.
Booster
If you use Booster you can load required modules with this config change:
/etc/booster.yaml
modules_force_load: i915
To add extra files to the image:
/etc/booster.yaml
extra_files: /usr/lib/firmware/edid/your_edid.bin
Then regenerate booster images.
Troubleshooting
My fonts are too tiny
See Linux console#Fonts for how to change your console font to a large font. The Terminus font (terminus-font) is available in many sizes, such as ter-132n
which is larger.
Alternatively, disabling modesetting might switch to lower resolution and make fonts appear larger.
Problem upon bootloading and dmesg
Polling for connected display devices on older systems can be quite expensive. Poll will happen periodically and can in worst cases take several hundred milliseconds, depending on the hardware. This will cause visible stalls, for example in video playback. These stalls might happen even when your video is on HDP output but you have other non HDP outputs in your hw configuration. If you experience stalls in display output occurring every 10 seconds, disabling polling might help.
If you see an error code of 0x00000010 (2)
while booting up, (you will get about 10 lines of text, the last part denoting that error code), use:
/etc/modprobe.d/modprobe.conf
options drm_kms_helper poll=0
Forcing modes and EDID
If your native resolution is not automatically configured or no display at all is detected, then your monitor might send none or just a skewed EDID file. The kernel will try to catch this case and will set one of the most typical resolutions.
In case you have the EDID file for your monitor you merely need to explicitly enforce it (see below). However most often one does not have direct access to a sane file and it is necessary to either extract an existing one and fix it or to generate a new one.
Generating new EDID binaries for various resolutions and configurations is possible during kernel compilation by following the upstream documentation (also see here for a short guide). Other solutions are outlined in details in this article.
Extracting an existing one is in most cases easier, e.g. if your monitor works fine under Windows you might have luck extracting the EDID from the corresponding driver, or if a similar monitor works which has the same settings you may use get-edid
from the read-edid package. You can also try looking in /sys/class/drm/*/edid
.
After having prepared your EDID place it in a folder, e.g. called edid
under /usr/lib/firmware
and copy your binary into it.
To load it at boot, specify the following in the kernel command line:
drm.edid_firmware=edid/your_edid.bin
For kernels older than 4.13, use this line instead:
drm_kms_helper.edid_firmware=edid/your_edid.bin
In order to apply it only to a specific connector use:
drm.edid_firmware=VGA-1:edid/your_edid.bin
For the built-in resolutions, refer to the table below. The Name column specifies the name which one is supposed to use in order to enforce its usage.
Resolution | Name |
---|---|
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 |
If you are doing early KMS, you must include the custom EDID file in the initramfs, otherwise you will run into problems.
The value of the drm.edid_firmware
parameter may also be altered after boot by writing to /sys/module/drm/parameters/edid_firmware
:
# echo edid/your_edid.bin > /sys/module/drm/parameters/edid_firmware
This will only take affect for newly plugged in displays, already plugged-in screens will continue to use their existing EDID settings. For external displays replugging them is sufficient to see the effect however.
Since kernel 3.15, to load an EDID after boot, you can use debugfs instead of a kernel command line parameter if the kernel is not in lockdown mode. This is very useful if you swap the monitors on a connector or just for testing. Once you have an EDID file as above, run:
# cat correct-edid.bin > /sys/kernel/debug/dri/0/HDMI-A-2/edid_override
And to disable:
# echo -n reset > /sys/kernel/debug/dri/0/HDMI-A-2/edid_override
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
Disabling modesetting
You may want to disable KMS for various reasons. To disable KMS add nomodeset
as a kernel parameter. See Kernel parameters for more info.
Along with nomodeset
kernel parameter, for Intel graphics card you need to add i915.modeset=0
and for Nvidia graphics card you need to add nouveau.modeset=0
. For Nvidia Optimus dual-graphics system, you need to add all the three kernel parameters (i.e. "nomodeset i915.modeset=0 nouveau.modeset=0"
).