Kernel mode setting

From ArchWiki

This article or section needs expansion.

Reason: KMS and rootless X (1.16), see Talk:Kernel mode setting and Xorg#Rootless Xorg. (Discuss in Talk: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.

Note: The proprietary NVIDIA driver (since 364.12) also implements kernel mode-setting, but it does not use the built-in kernel implementation and a fbdev driver for the high-resolution console is only present as an opt-in experimental feature (since 545.29)

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.

Configuration

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).

This article or section is out of date.

Reason: Arch officially supported kernels have simpledrm KMS driver inbuilt [1] for years now. Which means Arch users always have early KMS start. So this section is more about "when simpledrm transfers control to another driver". (Discuss in Talk:Kernel mode setting)

This article or section needs expansion.

Reason: Mention simpledrm and its ability to work as a generic graphics driver. (Discuss in Talk:Kernel mode setting)

Late KMS start

Intel, Nouveau, ATI and AMDGPU drivers already enable KMS automatically for all chipsets, so you do not need to do anything.

The proprietary NVIDIA driver supports KMS (since 364.12), which has to be manually enabled.

Early KMS start

Tip: If you encounter problems with the resolution, you can check whether enforcing the mode helps.

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:

  • mgag200 for Matrox graphics.
  • Depending on QEMU graphics in use (qemu option -vga type or libvirt <video><model type='type'>[2]):
    • bochs for std (qemu) and vga/bochs (libvirt),
    • virtio-gpu for virtio,
    • qxl for qxl,
    • vmwgfx for vmware (qemu) and vmvga (libvirt),
    • cirrus for cirrus.
  • Depending on VirtualBox graphics controller:
    • vmwgfx for VMSVGA,
    • vboxvideo for VBoxVGA or VBoxSVGA.

Initramfs configuration instructions are slightly different depending on the initramfs generator you use.

mkinitcpio

For in-tree modules, make sure kms is included in the HOOKS array in /etc/mkinitcpio.conf (this is the default since mkinitcpio v33).

For out-of-tree modules, place the module names in the MODULES array. For example, to enable early KMS for the NVIDIA graphics driver:

/etc/mkinitcpio.conf
MODULES=(... nvidia nvidia_modeset nvidia_uvm nvidia_drm ...)
Note: If you use PRIME Graphics Processing Unit (GPU) with Intel Integrated Graphics Processors (IGP) being your primary GPU and AMD as the discrete one, intel_agp may lead to troubles when resuming from hibernation (monitor gets no signal). See [3] for details.

If you are using the #Forcing modes and EDID method, you should embed the custom file 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

If you are using the #Forcing modes and EDID method, you should embed the custom file into your booster images as well:

/etc/booster.yaml
extra_files: /usr/lib/firmware/edid/your_edid.bin

Then regenerate the 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-132b which is larger.

Alternatively, disabling modesetting might switch to lower resolution and make fonts appear larger.

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(1) from the read-edid package. You can also try looking in /sys/class/drm/*/edid.

After having prepared your EDID, place it in a directory, 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

In order to apply it only to a specific connector, use:

drm.edid_firmware=VGA-1:edid/your_edid.bin

If you want to set multiple edid files, use:

drm.edid_firmware=VGA-1:edid/your_edid.bin,VGA-2:edid/your_other_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.

Note: Users of kernel version >=6.9 have to provide their own custom EDID binary as the built-in modes were removed in version 6.9.
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 effect 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

If your monitor supports hotplugging, you can also trigger a hotplug to make the monitor use the new EDID you just loaded (e.g. into edid_override), so you don't have to physically replug the monitor nor reboot:

# echo 1 > /sys/kernel/debug/dri/0/HDMI-A-2/trigger_hotplug

Forcing modes

Warning: The method described below is somehow incomplete because e.g. Xorg does not take into account the resolution specified, so users are encouraged to use the method described above. However, specifying resolution with 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=<driver>:<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
  • <driver>: Specify a video mode at bootup.
  • <conn>: Specifies the video connection type, such as VGA, DVI, HDMI, etc., see /sys/class/drm/ for available connectors
  • <xres>: The horizontal resolution in pixels.
  • <yres>: The vertical resolution in pixels.
  • [M]: Enables the use of VESA Coordinated Video Timings (CVT) to calculate the video mode timings instead of looking up the mode from a database
  • [R]: Enables reduced blanking calculations for digital displays when using CVT. This reduces the horizontal and vertical blanking intervals to save bandwidth.
  • [-<bpp>]: Specifies the color depth or bits per pixel (e.g., -24 for 24-bit color).
  • [@<refresh>]: Specifies the refresh rate in Hz.
  • [i]: Enables interlaced mode.
  • [m]: Adds margins to the CVT calculation (1.8% of xres rounded down to 8 pixels and 1.8% of yres)
  • [e]: output forced to on
  • [D]: digital output forced to on (e.g. DVI-I connector)
  • [d]: output forced to off

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 the nomodeset kernel parameter, for an Intel graphics card, you need to add i915.modeset=0, and for an 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").

Note: Some Xorg drivers will not work with KMS disabled. See the wiki page on your specific driver for details.