This blog provides a concise overview of the DRM and KMS components of Linux OS.
DRM (Direct Rendering Manager) and KMS (Kernel Mode Setting) are components of the Linux graphics subsystem that manage access to graphics hardware and display settings.
The Direct Rendering Manager (DRM) is a subsystem of the Linux kernel that interfaces with modern video card GPUs (Graphics Processing Units). It provides an API for user-space programs to communicate with the GPU, enabling hardware-accelerated 3D rendering, video decoding, and GPGPU computing. DRM allows multiple programs to access the GPU simultaneously without conflicts, and it manages resources such as command queues and memory. DRM includes methods like Graphics Execution Manager (GEM) and Translation Table Maps (TTM) for efficient video memory management and synchronization between the CPU and GPU.
DRM consists of a generic “DRM core” and a specific one (“DRM driver”) for each hardware:
- DRM core provides the basic framework where different DRM drivers can register and provides user space interface with a set of ioctls.
- A DRM driver implements the hardware-dependent part of the API, specific to the type of GPU it supports; This driver can provide extra APIs for the additional functionality of hardware. This additional functionality is provided to userspace as libdrm-driver.
libdrm is a library that provides the interface between user-space programs and the DRM subsystem. In addition, drivers export device-specific interfaces for use by user-space drivers and device-aware applications through ioctls and sysfs files. External interfaces include: memory mapping, context management, DMA operations, AGP management, vblank control, fence management, memory management, and output management.
DRM Master and DRM Auth
- DRM Master: This is the process that has exclusive control over a DRM device, typically the first process to open the device and call the SET_MASTER ioctl1. It manages privileged operations and ensures no conflicts occur when multiple programs access the GPU.
- DRM Auth: This is a method for other processes to gain certain privileges on a DRM device after DRM Master’s approval. It involves an authentication process to securely share access to restricted operations.
DRM Internals
The “DRM Internals” page from the Linux Kernel documentation provides detailed information for driver authors and developers working on DRM (Direct Rendering Manager) drivers:
Initialization:
Typical initialization involves setting up command buffers, creating an initial output configuration, and initializing core services.
Drivers initialize using a struct drm_driver structure, which is passed to drm_dev_alloc() to allocate a device instance. Once initialized, the device can be registered with drm_dev_register().
Driver Features:
The driver_features field in struct drm_driver indicates the driver’s capabilities, such as support for AGP, PCI DMA, scatter/gather DMA, IRQ handling, GEM memory management, mode setting (KMS), PRIME buffer sharing, and render nodes. Currently valid features are:
- DRIVER_USE_AGP, DRIVER_HAVE_IRQ, DRIVER_IRQ_SHARED, DRIVER_GEM, DRIVER_MODESET, DRIVER_PRIME, DRIVER_RENDER, DRIVER_ATOMIC
struct drm_driver
This structure has the following function pointer fields:
- get_vblank_counter : Driver callback for fetching a raw hardware vblank counter for the CRTC specified with the pipe argument.
- enable_vblank, disable_vblank: Enable, Disable vblank interrupts for the CRTC specified with the pipe argument.
- get_scanout_position: Returns the current display scanout position from a crtc
- get_vblank_timestamp: Should return a precise timestamp when the most recent VBLANK interval ended or will end.
- master_create, master_destroy, master_set, master_drop: Functions used by master setting, etc. Only used by vmwgfx.
- gem_create_object: constructor for gem objects
- dumb_create, dumb_map_offset, dumb_destroy: Function pointers related to dumb buffers.
drm_irq_install
This function is used to register an interrupt handler for a DRM device.
Here’s a brief overview of how drm_irq_install works:
- Pre-installation: It calls the optional irq_preinstall operation to prepare the hardware and ensure no pending interrupts.
- Requesting IRQ: It uses request_irq() to register the IRQ handler. If the DRIVER_IRQ_SHARED flag is set, it requests a shared IRQ handler.
- Post-installation: It calls the optional irq_postinstall operation to enable interrupts, excluding vblank interrupts, which are enabled separately.
note: This function supports only a single interrupt per device.
Memory manager Initialization
Every DRM driver requires a memory manager which must be initialized at load time. DRM currently contains two memory managers, the Translation Table Manager (TTM) and the Graphics Execution Manager (GEM).
PCI support
drm_pci_alloc: Allocate a PCI consistent memory block, for DMA.
drm_pci_free: Free a PCI consistent memory block
TODO : Interfacing with user space app, GEM, and the corresponding driver specific functions flow.
KMS
Mode setting is the process of setting a video card’s screen resolution, color depth, and refresh rate to values supported by both the card and the display. It requires direct access to the graphics hardware.
Kernel Mode Setting (KMS) is a part of the DRM subsystem that handles setting the display mode (resolution, refresh rate, etc.) in kernel space. This allows for more efficient and reliable management of display settings, especially during boot and when switching between different graphical applications.
KMS models and manages the output devices as a series of abstract hardware blocks. These blocks are:
CRTCs (CRT Controllers): These are scanout engines that read pixel data from a framebuffer and generate video mode timing signals.
Connectors: Represent physical connections (like VGA, HDMI) where the video signal is sent to the display.
Encoders: These hardware blocks encode the video signal from the CRTC into a format suitable for the connector.
Planes: a plane is not a hardware block but a memory object containing a buffer for the scanout engine (a CRTC). The primary plane holds the framebuffer, which is essential for determining the video mode. Additional planes can be used for hardware cursor overlays or secondary overlays for more complex image compositions.
Linux Kernel documentation provides an overview of how KMS works:
- Initialization: Drivers must initialize the mode setting core by calling drmm_mode_config_init() on the DRM device. This sets up the mode_config field in the drm_device structure.
Display Pipeline:
The basic structure includes:
- Framebuffers: Represented by struct drm_framebuffer, they feed into planes.
- Planes: Represented by struct drm_plane, they blend pixel data and feed it into a CRTC.
- CRTCs: Represented by struct drm_crtc, they handle the blending of planes.
- Encoders: Represented by struct drm_encoder, they route the output from CRTCs to connectors.
- Connectors: Represented by struct drm_connector, they are the final endpoint in the display chain.
Ouptput Pipeline
Output pipeline includes additional helper objects like struct drm_bridge for sharing code between encoders and struct drm_panel for handling panel-related information.
KMS Core Structures and Functions
Various functions are used to set up and manage the display modes, including setting minimum and maximum width and height for framebuffers, and configuring mode setting functions through struct drm_mode_config_funcs.
Frame buffer is buffer between the CPU and the display, containing the color values for every pixel in a complete video frame.
References:
Direct Rendering Manager — Wikipedia