wiki:linux/display

Goals

The purpose of this page is to help educate about display output on upstream Linux (not to be confused with the 'downstream' vendor kernel provided in Yocto).

Linux Display Drivers

Video Graphics Processing Units (GPU) are extremely complicated and have evolved over time. There are a set of frameworks within the Linux kernel to support various GPU's and video cards as well as GPU-less hardware.

There is a variety of terminology used here.

Frame Buffer Device (fbdev)

An early kernel API called 'fbdev' is used to manage the framebuffer of a graphics adapter. Essentially the framebuffer provides direct access to an array of pixels mapped to the display. Because of this simplistic design, it supports software rendering only (no support 2D or 3D hardware acceleration), does not support double-buffering or page flipping.

While you can still use fbdev today it's extremely inefficient.

References:

Direct Rendering Manager (DRM)

DRM is the driver subsystem in the kernel that is able to communicate with video drivers, such as the Freescale I.MX6 processors. Through ioctl() calls, multiple userspace programs can draw to a display at any given time as DRM will manage these requests. DRM is also able to interface with the graphics processor (GPU) in order to hardware accelerate these requests. This is separate from framebuffer in that it only allowed raw writes to a display. DRM exposes some information via sysfs in the /sys/class/drm directory.

DRM drivers deal with DMA, AGP memory management, resource locking, and secure hardware access. In order to support multiple, simultaneous 3D applications the 3D graphics hardware must be treated as a shared resource. Locking is required to provide mutual exclusion. DMA transfers and the AGP interface are used to send buffers of graphics commands to the hardware. Finally, there must be security to prevent clients from escalating privilege using the graphics hardware.

For example, to retrieve info about the DRM devices found on your system (Gateworks GW540x Linux 4.18):

root@bionic-armhf:~# ls /sys/class/drm
card0  card1  card1-HDMI-A-1  card1-LVDS-1  renderD128  version
# show 
  • card0 is from etnaviv the GPU driver (if enabled)
  • card1 is from the IPU display driver

References:

Kernel Mode Settings (KMS)

Kernel Mode Setting (KMS) is a method for setting display resolution, pixel depth, and screen refresh in the kernel space rather than user space. In the past this was done in user-space by the X-Server. Modern video drivers like the etnaviv driver for the IMX6 GPU support KMS.

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 help reduce artifacts and increase 3D performance.

When booting your kernel, mode settings are read by what appears in the kernel command line, else defaults are chosen. DRM exports the available modes for a given display in the DRM 'modes' file:

root@bionic-armhf:~# for i in $(ls -1 /sys/class/drm/*/modes); do echo "$i:"; cat $i; done 
/sys/class/drm/card1-HDMI-A-1/modes:
1920x1080
1280x1024
1440x900
1280x800
1152x864
1024x768
1024x768
800x600
800x600
640x480
640x480
720x400
/sys/class/drm/card1-LVDS-1/modes:
  • the above shows that the HDMI is connected to a 1080p capable monitor with several resolutions available and that the board also has an LVDS connector but it is disabled

Default mode settings can be passed to the kernel via the video= parameter from within U-Boot. The format of this is as follows: video=<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]

Note the following variables (see also modedb.txt):

  • <conn>: Connector
  • <xres> x <yres>: Resolution
  • M: Display timings will be calculated using VESA(TM) Coordinated Video Timings instead of a lookup table (Please see modedb.txt for more details)
  • R: Do "Reduce Blanking" calculation for digital displays
  • -<bpp>: color depth
  • i: Calculate timings for an interlaced Mode
  • m: Add margins to the calculation (1.8% of xres rounded down to 8 pixels and 1.8% of yres)
  • e: Output Forced On
  • D: Output Forced On and use Digital Outputs
  • d: Output Forced Off

Examples:

  • Enable LVDS for a 1280x800 display and disable HDMI:
    setenv video 'video=LVDS-1:1280x800@60M video=HDMI-A-1:d'
    
  • Enable HDMI for a 1080p display with 60Hz refresh rate and disable LVDS:
    setenv video 'video=LVDS-1:d video=HDMI-A-1:1920x1080@60'
    
  • Enable HDMI for a 800x600 display with 60Hz refresh rate and disable LVDS:
    setenv video 'video=LVDS-1:d video=HDMI-A-1:800x600@60'
    
  • Disable both the LVDS and HDMI outputs on a Gateworks GW540x:
    setenv video 'video=LVDS-1:d video=HDMI-A-1:d'
    

References:

IMX6 Vivante GC2000 Linux Driver - Etnaviv

The Vivante GPU within the IMX6 SoC is supported by the open-source etnaviv driver (which was reverse engineered from the original Vivante driver provided as pre-built shared library objects with a think kernel shim layer).

To use Entaviv enable CONFIG_DRM_ETNAVIV=y

During boot you will see something like:

  • IMX6Q
    root@bionic-armhf:~# dmesg | grep etnaviv
    [    3.117448] etnaviv etnaviv: bound 130000.gpu (ops gpu_ops)
    [    3.123828] etnaviv etnaviv: bound 134000.gpu (ops gpu_ops)
    [    3.129970] etnaviv etnaviv: bound 2204000.gpu (ops gpu_ops)
    [    3.135761] etnaviv-gpu 130000.gpu: model: GC2000, revision: 5108
    [    3.156234] etnaviv-gpu 134000.gpu: model: GC320, revision: 5007
    [    3.176170] etnaviv-gpu 2204000.gpu: model: GC355, revision: 1215
    [    3.182362] etnaviv-gpu 2204000.gpu: Ignoring GPU with VG and FE2.0
    [    3.191412] [drm] Initialized etnaviv 1.2.0 20151214 for etnaviv on minor 0
    

Example Applications:

  • kmscube - a demonstration program showing how to drive bare metal graphics without a compositor like X11, Wayland or similar using DRM/KMS/GBM and EGL.
  • Ubuntu pre-built packages:
    # install pre-packaged
    apt install kmscube
    kmscube -D /dev/dri/card1
    
  • glmark2 - an OpenGL 2.0 and ES2.0 benchmark
    # build from source as the pre-packaged one is too old to be of use
    apt install build-essentials git
    apt install python libpng-dev libgbm-dev libegl1-mesa-dev libgl1-mesa-dev libgles2-mesa-dev
    git clone https://github.com/glmark2/glmark2
    cd glmark2
    ./waf configure --with-flavors=drm-glesv2
    ./waf
    ./waf install
    glmark2-es2-drm
    
  • GStreamer - A Multimedia framework/library which provides kmssink for rendering to a DRM/KMS driver and glimagesink for rendering to EGL:
    # install GStreamer packages
    apt-get install gstreamer1.0-x gstreamer1.0-tools libgstreamer1.0-0 \
      gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
      gstreamer1.0-libav gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio \
      v4l-utils
    gst-launch-1.0 videotestsrc ! kmssink
    

The above examples were performed on an Ubuntu 19.10 root filesystem with the Linux 5.3.8 kernel built with imx_v6_v7_defconfig

Last modified 8 days ago Last modified on 11/05/2019 06:27:37 PM