Advamation framebuffer

Version: 2014-05-21
Author: Advamation, Roland Koebler (support@advamation.de)


1   Overview

The Advamation framebuffer driver consists of two parts:

  • a display-/device-independent Linux-kernel-module
  • a user-space daemon, which reads the framebuffer-contents and writes it to the display

This is an extremely flexible solution, since:

  • The kernel-framebuffer-driver only provides virtual framebuffers and is completely device-independent.
  • New display-types can be added without any change to the kernel-module.
  • Virtual framebuffers can be added and removed dynamically.
  • There's no fixed assignment between framebuffers and displays. This means that:
    • The display-framebuffer-assignment can be modified dynamically (e.g. select which framebuffer to display).
    • A display can be "detached" from a framebuffer, reconfigured (e.g. rotated by 180 degrees) and attached to the framebuffer again.
    • The contents of a framebuffer could be spread to several displays.
    • A single display could even display several framebuffers at once, or display the framebuffer-contents in a part of its screen and display additional information in the remaining parts.
    • ...
  • The framebuffer-data could be tunneled over a network, over RS-232, RS-485 or any other transport by using a modified user-space daemon.

The framebuffer-driver was written for the Raspberry Pi, but it could also be used in other systems.

2   Installation/configuration

To install and configure the framebuffer-driver, we recommend to use the install-/setup-script advaboard_rpi1_setup.sh.

The following sections describe the details of the framebuffer-driver, incl. manual installation and configuration of every component, if advaboard_rpi1_setup.sh does not work in your case (e.g. for non-Raspbian-/non-Debian-based distributions).

3   Kernel-module

The Advamation framebuffer kernel-module (advamationfb.ko) provides configurable virtual framebuffers. All it needs to know about a framebuffer is its resolution and bit-depth/pixel-format (currently fixed at 16 bit, RGB565).

The virtual framebuffers can be added and removed dynamically via sysfs.

3.1   HDMI-framebuffer

Note that if you only use a TFT-display and no HDMI-display on the Raspberry Pi (or if the HDMI-display and the TFT-display should show exactly the same image), it's not necessary to use this kernel-module. Instead, the default HDMI-framebuffer could be modified and used for the TFT-display.

To use this, skip the rest of this "Kernel-module" section, and use:

  • /dev/fb0 as framebuffer-device for the user-space daemon

  • fbset -fb /dev/fb0 -i to get information about this framebuffer

  • fbset -fb /dev/fb0 -xres ... -yres ... -vxres ... -vyres ... -depth 16 to modify the resolution of the HDMI-framebuffer to match the TFT-display, e.g. for the TFT50 display:

    fbset -fb /dev/fb0 -xres 800 -yres 480 -vxres 800 -vyres 480 -depth 16``
    

More information can be found in the TFT-display manual (currently only available in German).

3.2   Installation

The Advamation framebuffer kernel-module requires a kernel with support for framebuffer-modules [1] and with available kernel-headers.

  1. Check / install kernel:

    • for Raspbian: Unfortunately, the default kernel in Raspbian is rather limited, does not include support for external framebuffer-modules, and does not provide kernel-headers. So, a different kernel from Raspbian must be installed:

      sudo apt-get update
      
      # kernel 3.6:
      sudo apt-get install linux-image-3.6-trunk-rpi
      
      # kernel 3.10:
      sudo apt-get install linux-image-3.10-3-rpi
      

      Afterwards, configure /boot/config.txt to boot the new kernel by adding/modifying the line:

      # for Raspbian 2014-01-07:
      kernel=vmlinuz-3.10-3-rpi
      
      # for Raspbian 2013-09-25:
      kernel=vmlinuz-3.6-trunk-rpi
      

      If kernel=... already exists in /boot/config.txt, the existing line should be modified; otherwise, e.g. sudo sh -c 'echo "kernel=vmlinuz-3.10-3-rpi" >> /boot/config.txt' can be used.)

    • for other Linux-distributions: Make sure that your kernel includes the following modules (e.g. by ls /lib/modules/`uname -r`/kernel/drivers/video/):

      fb_sys_fops.ko
      syscopyarea.ko
      sysfillrect.ko
      sysimgblt.ko
      

      If these modules do not exist, you probably need an other kernel (either from your distribution or self-compiled). In this case, search the repository of your distribution for a kernel-package, e.g. for Debian-based systems:

      apt-cache search linux-image
      # or: aptitude search linux-image
      

      Select and install such a kernel, and configure /boot/config.txt to boot the new kernel, by adding the line (or modifying the line, if a kernel=...-line already exists):

      kernel=YOUR_KERNEL_IMAGE_FILENAME
      

      You can probably find the name of your kernelimage by looking at the contents of your /boot-directory; it's probably a file beginning with "vmlinuz-".

    • If you have changed your kernel: Reboot and check if the new kernel booted (and not the old one):

      sudo reboot
      

      After reboot, get the booted kernel version:

      uname -r
      
  2. Compile framebuffer-module:

    • for Raspbian: A precompiled kernel-module for Raspbian with the 3.10-3-rpi and 3.6-trunk-kernel is included, so it's not necessary to compile the kernel-module yourself:

      cd advaboard_rpi1-VERSION/prebuilt/raspbian-7/
      
    • for other Linux-distributions:

      • Use uname -r to determine the name/version of your running kernel.

      • Install the kernel-headers for your running kernel from the repository of your distribution, e.g. for Raspbian 3.6-trunk:

        sudo apt-get install linux-headers-3.6-trunk-all
        
      • Compile module:

        cd advaboard_rpi1-VERSION/kernel/advamationfb/
        make clean
        make
        
  3. Test the framebuffer-module: Try to insert the module into the kernel. Make sure to close all applications before, since the kernel may crash here if something went wrong:

    sudo modprobe -a fb_sys_fops sysfillrect syscopyarea sysimgblt
    sudo insmod ./advamationfb.ko
    

    If insmod fails with Invalid module format. or Exec format error, the module was compiled for a different kernel than yours; check this by comparing the output of uname -a and modinfo ./advamationfb.ko.

    Afterwards, try to create a virtual framebuffer (as root):

    $ sudo bash
    $ echo "320,240,16" > /sys/bus/platform/drivers/advamationfb/new_device
    $ cat /sys/bus/platform/drivers/advamationfb/list_devices
    0: fb1, 320x240x16
    $ echo 0 >> /sys/bus/platform/drivers/advamationfb/delete_device
    $ exit
    

    (Instead of fb1, list_devices may show a different device.)

    To complete the test, you can remap the console to the created framebuffer and take a screenshot. Make sure the console is not blank (e.g. by pressing a key on a keyboard, attached to the Raspberry Pi), otherwise your screenshot will be black:

    sudo apt-get install fbcat
    sudo sh -c 'echo "800,480,16" > /sys/bus/platform/drivers/advamationfb/new_device'
    con2fbmap 1 1
    fbcat /dev/fb1 > ~/advamationfb_test.ppm
    con2fbmap 1 0
    sudo sh -c 'echo 0 >> /sys/bus/platform/drivers/advamationfb/delete_device'
    

    Now, advamationfb_test.ppm should contain a console-screenshot.

  4. Install the module (optional):

    sudo make install_fb
    sudo depmod
    
[1]

Kernel configuration:

CONFIG_FB=y
CONFIG_FB_SYS_FILLRECT=m
CONFIG_FB_SYS_COPYAREA=m
CONFIG_FB_SYS_IMAGEBLIT=m
CONFIG_FB_SYS_FOPS=m
CONFIG_FB_DEFERRED_IO=y

Unfortunately, some of these options cannot be selected manually; if you want to compile the kernel yourself, use <M> Displaylink USB Framebuffer support, which will automatically set the above options.

3.3   Usage

Init:
  • If you have installed the kernel-module, use:

    sudo modprobe advamationfb
    
  • If you have not installed the kernel-module, use:

    sudo modprobe -a fb_sys_fops sysfillrect syscopyarea sysimgblt
    sudo insmod ./advamationfb.ko
    
Add a framebuffer:

Write XRES,YRES,BITDEPTH to /sys/bus/platform/drivers/advamationfb/new_device, e.g. (as root):

$ echo "320,240,16" > /sys/bus/platform/drivers/advamationfb/new_device
$ echo "240,320,16" > /sys/bus/platform/drivers/advamationfb/new_device
$ echo "800,480,16" > /sys/bus/platform/drivers/advamationfb/new_device
List all framebuffers (as root):

/sys/bus/platform/drivers/advamationfb/list_device returns a list of all its framebuffers, as NUMBER: DEVICE, XRESxYRESxBITDEPTH, e.g. (as root):

$ cat /sys/bus/platform/drivers/advamationfb/list_devices
0: fb1, 320x240x16
1: fb2, 240x320x16
2: fb3, 800x480x16

$ ls -l /dev/fb*
crw-rw---T 1 root video 29, 0 Jan  1  1970 /dev/fb0
crw-rw---T 1 root video 29, 1 Nov  3 23:05 /dev/fb1
crw-rw---T 1 root video 29, 3 Nov  4 17:47 /dev/fb2
crw-rw---T 1 root video 29, 4 Nov  4 17:47 /dev/fb3

(The framebuffer /dev/fb0 here is the HDMI-display of the Raspberry Pi.)

Remove a framebuffer:

Write the number of the framebuffer to delete to /sys/bus/platform/drivers/advamationfb/delete_device, e.g. (as root):

$ cat /sys/bus/platform/drivers/advamationfb/list_devices
0: fb1, 320x240x16
1: fb2, 240x320x16
2: fb3, 800x480x16

$ echo 1 > /sys/bus/platform/drivers/advamationfb/delete_device

$ cat /sys/bus/platform/drivers/advamationfb/list_devices
0: fb1, 320x240x16
2: fb3, 800x480x16

4   User-space daemon

Now that we have virtual framebuffers, a user-space program could (e.g. periodically) read the framebuffer-contents and write the changes to the display.

Such a user-space program for the Raspberry Pi, which writes the framebuffer-contents to a TFT-display on the AdvaBoard RPi1, is included. For compilation/installation instructions, read the README of the AdvaBoard RPi1 software.

Usage (see also am_rpi_framebuffer --help):

am_rpi_framebuffer -t TFT_TYPE -d FRAMEBUFFER ...

  -?, --help                     Show help options

  -d, --dev=N                    framebuffer-number (e.g. 0 for /dev/fb0)
  -i, --iface=ADVABOARD_RPi1     display-interface (default: ADVABOARD_RPi1)
  -t, --type=TFT_..              display-type (TFT_32,TFT_43,TFT_50,TFT_70)
  -f, --fps=FPS                  max. frames-per-second
        Lower framerates reduce the CPU load.
  -r, --rot=angle                display-rotation (0, 90, 180, 270)
  -x, --x0=X                     display-window X-coordinate (default: 0)
  -y, --y0=Y                     display-window Y-coordinate (default: 0)
  -w, --width=W                  display-window width  (default: max.)
  -h, --height=H                 display-window height (default: max.)
  -b, --brightness=0..255        backlight-brightness (0..255, default 255)
  --skipon                       skip 'display-on'
  -v, --verbose=LEVEL            verbosity level (default: 64)
    (DEBUG: 128, INFO: 64, MESSAGE: 32, WARNING: 16, CRITICAL: 8, ERROR: 4|0)
--fps:
FPS controls how long the daemon should sleep between updates. High FPS-values result in a high CPU load (up to 100%).
-x/-y/-w/-h:
only necessary, if only a part of the display should be used
--skipon
Should be used, if the display was turned on and configured before (e.g. by am_rpi_tft_tool) and this configuration should not be lost.

If the framebuffer-resolution does not match the display-resolution, the display only shows the part of the framebuffer which fits onto the screen.

The daemon may be aborted any time, and started again later. E.g. if your screen is upside-down, abort the daemon and start it again with -r 180.

5   Usage

Before testing/using the framebuffer, make sure the TFT-display on the AdvaBoard RPi1 works correctly, e.g. with the am_rpi_tft_tool, e.g.:

sudo am_rpi_tft_tool -t TFT_32 -m ON
sudo am_rpi_tft_tool -t TFT_32 -m BACKLIGHT ON 255
sudo am_rpi_tft_tool -t TFT_32 -m TEST_ROTATE

(You may have to replace TFT_32 by TFT_43, TFT_50 or TFT_70, depending on your display.)

So, after having installed (and maybe compiled) the software, the following commands are necessary to use the framebuffer on the TFT-display of the AdvaBoard RPi1:

  • init the AdvaBoard RPi1:

    sudo am_rpi_advaboard_tool -m init
    
  • create/modify the framebuffer:

    You could either create a new virtual framebuffer, or modify and use the default HDMI framebuffer:

    • virtual framebuffer:

      • insert kernel-module:

        sudo modprobe advamationfb
        
      • create virtual framebuffer:

        • for TFT_32:

          sudo sh -c 'echo "240,320,16" > /sys/bus/platform/drivers/advamationfb/new_device'
          
        • for TFT_43:

          sudo sh -c 'echo "480,272,16" > /sys/bus/platform/drivers/advamationfb/new_device'
          
        • for TFT_50 and TFT_70:

          sudo sh -c 'echo "800,480,16" > /sys/bus/platform/drivers/advamationfb/new_device'
          
    • HDMI-framebuffer:

      • for TFT_32:

        fbset -fb /dev/fb0 -xres 240 -yres 320 -vxres 240 -vyres 320 -depth 16``
        
      • for TFT_43:

        fbset -fb /dev/fb0 -xres 480 -yres 272 -vxres 480 -vyres 272 -depth 16``
        
      • for TFT_50 and TFT_70:

        fbset -fb /dev/fb0 -xres 800 -yres 480 -vxres 800 -vyres 480 -depth 16``
        
  • Display the Linux-text-console on the virtual framebuffer:

    con2fbmap 1 1
    

    (Depending on your framebuffer-device, you may need to use a different 2nd number, e.g.: 0 for the HDMI-framebuffer (/dev/fb0), 1 for /dev/fb1 etc.)

  • Start X11 on the virtual framebuffer:

    FRAMEBUFFER=/dev/fb1 startx
    

    (Depending on your framebuffer-device, you may need to use a different FRAMEBUFFER-parameter.)

    If X11 should always use the framebuffer-device by default, create (or modify) /etc/X11/xorg.conf:

    Section "Device"
        Identifier "Advamation Framebuffer"
        Driver "fbdev"
        Option "fbdev" "/dev/fb1"
    EndSection
    

    An universal xorg.conf, incl. multi-monitor setups, is included in this download.

  • Start the user-space daemon, to show the contents of the virtual framebuffer on the display:

    • for TFT_32:

      sudo am_rpi_framebuffer -t TFT_32 -d 1
      
    • for TFT_43:

      sudo am_rpi_framebuffer -t TFT_43 -d 1
      
    • for TFT_50:

      sudo am_rpi_framebuffer -t TFT_50 -d 1
      
    • for TFT_70:

      sudo am_rpi_framebuffer -t TFT_70 -d 1
      

    If several framebuffers are used, you may need a different number for -d. To determine the correct number, use:

    sudo cat /sys/bus/platform/drivers/advamationfb/list_devices
    
  • To use a rotated framebuffer, switch the XRES and YRES size and use -r, e.g.:

    # remove old framebuffer
    # (if you added one before and don't need the old framebuffer anymore)
    con2fbmap 1 0
    sudo sh -c 'echo 0 > /sys/bus/platform/drivers/advamationfb/delete_device'
    
    # new framebuffer
    # (You may have to use different con2fbmap and -d parameters if you're
    #  using multiple framebuffers.)
    sudo sh -c 'echo "320,240,16" > /sys/bus/platform/drivers/advamationfb/new_device'
    con2fbmap 1 1
    sudo am_rpi_framebuffer -t TFT_32 -d 1 -r 90
    
    # or, upside-down:
    sudo am_rpi_framebuffer -t TFT_32 -d 1 -r 270
    
  • The brightness of the backlight etc. can also be configured by commandline-parameters.

  • See scripts/sysvinit/ for scripts to start the framebuffer automatically during boot.