Can't get NixOS + X to work on a Raspberry Pi with DSI display

I have a Raspberry Pi 4 Model B connected to a 5-inch FREENOVE touchscreen display via the DSI cable.

When I boot it up using Raspberry Pi OS, it automatically detects the display and shows a desktop environment on it. I’m able to send clicks to the desktop by touching the screen. It looks like this:

I’d like to get the same thing working with NixOS 23.11, but I cannot figure it out. Here’s the best configuration I could come up with (with the networking and user login details elided):

{ config, pkgs, modulesPath, ... }:
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      #(modulesPath + "/profiles/all-hardware.nix") # doesn't help
    ];

  boot.loader.grub.enable = false;
  boot.loader.generic-extlinux-compatible.enable = true;

  # Using the RPi kernel like this makes a text console show up on DSI monitor,
  # but not X, and it also prevents X from showing up on an HDMI monitor.
  #boot.kernelPackages = pkgs.linuxPackages_rpi4;

  # [networking, SSH, and user setup omitted]
  
  services.xserver = {
    enable = true;
    displayManager.gdm.enable = true;
    desktopManager.gnome.enable = true;
  };

  system.stateVersion = "23.11";
}

In case it matters, I initialied my NixOS SD card using nixos-sd-image-23.11.6708.12430e43bd9b-aarch64-linux.img.

When I use the configuration above, I can see some text while NixOS is booting, but then it just goes into a loop where the touchscreen is filled with one color, cycling between black, white, red, green, and blue. Here’s a 58-second video showing what happens:

This problem is specific to this particular type of monitor. If I boot up NixOS with an HDMI monitor attached instead of DSI, then it displays GNOME on the HDMI monitor just fine.

Additional troubleshooting info:

  • Raspberry Pi OS, successfully displaying an X desktop on the DSI monitor:
  • NixOS 23.11, mainline kernel, displaying a cycle of colors on the DSI monitor:
  • NixOS 23.11, mainline kernel, successfully displaying an X desktop on an HDMI monitor:

(This forum doesn’t let me upload a 2.2 MB mp4 video, or TXT files, but luckily I know how to host these files myself!)

So, has anyone gotten Rasbperry Pi + DSI + NixOS + X to work before? Or does anyone know how to start troubleshooting this sort of thing? What component is generating the black/white/red/green/blue cycle and what does it mean? I’m not really sure what components are responsible for making a DSI display work and how to see the error messages produced by them. Thanks!

2 Likes

Raspbian OS’s are meant for Pi’s and therefore comes with some utils / tools so you get some “plug n’ play” feeling

So with your shared config, it would set the bare minimum.
The LCD display then needs to be configured to render and handle touch inputs.

  1. check if any drivers is missing / required for the screen
  2. ensure that the graphical output is sent to the correct output, by default HDMI so needs to redirect to the LCD (e.g /dev/fb1)
    e.g raspberry-pi-examples/waveshare-lcd.md at 4d35c48f0a1b8b2628f858f4deab7ec6ab785706 · JimJ92120/raspberry-pi-examples · GitHub
  3. configure / calibrate the touchscreen

Note that different LCD models and brands will behave differently and might need some extra config

1 Like

Thanks for the suggestions.

  • With the mainline kernel and just a DSI monitor connected when booting, there are no /dev/fb* devices.
  • With the mainline kernel and just an HDMI monitor connected when booting, there is just /dev/fb0. (The HDMI monitor works in this scenario and displays a desktop.)
  • With the Raspberry Pi 4 kernel provided by NixOS I am always seeing /dev/fb0 and /dev/fb1 as long as one type of display is plugged in when booting. I can successfully display images on the touchscreen using nix-shell -p fbida and then a command like fbi -d /dev/fb1 image.jpg. When the touchscreen display is connected, fb0 and fb1 both correspond to it, but using fb0 makes the red and blue channels get swapped.

So this is some good progress!

Given the results above, I think the most promising path is to use the Raspberry Pi 4 kernel provided in NixOS (i.e. boot.kernelPackages = pkgs.linuxPackages_rpi4;). However, I’ve never gotten that kernel to display any kind of graphical desktop. In my latest attempt, I looked at the link you sent, and I converted it to this config fragment:

  services.xserver = {
    enable = true;
    displayManager.gdm.enable = true;
    desktopManager.gnome.enable = true;
    drivers = [
      {
        name = "myfb";
        driverName = "fbdev";
        deviceSection = ''
          Option "fbdev" "/dev/fb1"
        '';
        display = true;
      }
    ];
  };

By looking in /etc/systemd/system/display-manager.service, I can tell that these new lines of Nix code were converted to the following lines in the generated xorg.conf file:

Section "Device"
  Identifier "Device-myfb[0]"
  Driver "fbdev"

            Option "fbdev" "/dev/fb1"


EndSection

I also tried display = false;.

But still, all I can see on the touchscreen is a text console, even if I try pressing Ctrl+Shift+Fx for every x from 1 to 12.

According to systemctl status display-manager, the display manager service is running, but its log has warnings in it according to journalctl -xu display-manager:

-- Boot 5a1ebe0249244df0ba86f844d8c93e18 --
May 07 19:48:11 pololupi3 systemd[1]: Starting Display Manager...
░░ Subject: A start job for unit display-manager.service has begun execution
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ A start job for unit display-manager.service has begun execution.
░░
░░ The job identifier is 97.
May 07 19:48:11 pololupi3 systemd[1]: Started Display Manager.
░░ Subject: A start job for unit display-manager.service has finished successfully
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ A start job for unit display-manager.service has finished successfully.
░░
░░ The job identifier is 97.
May 07 19:48:51 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:51 pololupi3 gdm[903]: Gdm: Child process -1000 was already dead.
May 07 19:48:51 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:51 pololupi3 gdm[903]: Gdm: Child process -1000 was already dead.
May 07 19:48:51 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:51 pololupi3 gdm[903]: Gdm: Child process -1011 was already dead.
May 07 19:48:51 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:51 pololupi3 gdm[903]: Gdm: Child process -1011 was already dead.
May 07 19:48:51 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:51 pololupi3 gdm[903]: Gdm: Child process -1022 was already dead.
May 07 19:48:51 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:51 pololupi3 gdm[903]: Gdm: Child process -1022 was already dead.
May 07 19:48:52 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:52 pololupi3 gdm[903]: Gdm: Child process -1033 was already dead.
May 07 19:48:52 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:52 pololupi3 gdm[903]: Gdm: Child process -1033 was already dead.
May 07 19:48:52 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:52 pololupi3 gdm[903]: Gdm: Child process -1044 was already dead.
May 07 19:48:52 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:52 pololupi3 gdm[903]: Gdm: Child process -1044 was already dead.
May 07 19:48:52 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 19:48:52 pololupi3 gdm[903]: Gdm: GdmLocalDisplayFactory: maximum number of X display failures reached: ch>
May 07 19:48:52 pololupi3 gdm[903]: Gdm: Child process -1055 was already dead.
May 07 20:04:35 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 20:04:35 pololupi3 gdm[903]: Gdm: GdmLocalDisplayFactory: maximum number of X display failures reached: ch>
May 07 20:04:35 pololupi3 gdm[903]: Gdm: Child process -1186 was already dead.
May 07 20:04:44 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 20:04:44 pololupi3 gdm[903]: Gdm: GdmLocalDisplayFactory: maximum number of X display failures reached: ch>
May 07 20:04:44 pololupi3 gdm[903]: Gdm: Child process -1198 was already dead.
May 07 20:05:02 pololupi3 gdm[903]: Gdm: GdmDisplay: Session never registered, failing
May 07 20:05:02 pololupi3 gdm[903]: Gdm: GdmLocalDisplayFactory: maximum number of X display failures reached: ch>
May 07 20:05:02 pololupi3 gdm[903]: Gdm: Child process -1227 was already dead.

–David

1 Like

The nixos-hardware project is the key to solving this!

Here is my working configuration:

{ config, pkgs, ... }:

{
  imports =
    [
      <nixos-hardware/raspberry-pi/4>
      ./hardware-configuration.nix
    ];

  boot.loader.grub.enable = false;
  boot.loader.generic-extlinux-compatible.enable = true;

  boot.kernelPackages = pkgs.linuxPackages_rpi4;

  hardware.enableRedistributableFirmware = true;

  hardware.raspberry-pi."4" = {
    fkms-3d.enable = true;
    touch-ft5406.enable = true;
  };

  services.xserver = {
    enable = true;
    displayManager.gdm.enable = true;
    desktopManager.gnome.enable = true;
  };

  # [networking, SSH, and user setup omitted]

  system.stateVersion = "23.11";
}

The fkms-3d.enable options makes the desktop environment show up on the DSI screen, and the touch-ft5406.enable option makes its touch input work.

However, I don’t particularly like gdm and gnome on this screen. The on-screen keyboard that Gnome brings up is too big (there’s wasted space at the top of it), and I don’t know how to close it. (Still, it’s probably better than Raspberry Pi OS, which did not have any on-screen keyboard by default.) I’ll probably be looking into other display managers / desktop managers to see if their default behavior is better.

1 Like