2025-07-24 13:52:31 +02:00

4.6 KiB

Customizing display configuration

This section describes how to customize display configuration using:

  • kernel modes
  • EDID files

Example situations it can help you with:

  • display controllers (external hardware) not advertising EDID at all,
  • misbehaving graphics drivers,
  • loading custom display configuration before the Display Manager is running,

Forcing display modes

In case of very wrong monitor controller and/or video driver combination you can force the display to be enabled and skip some driver-side checks by adding video=<OUTPUT>:e to boot.kernelParams. This is exactly the case with amdgpu drivers

{
  # force enabled output to skip `amdgpu` checks
  hardware.display.outputs."DP-1".mode = "e";
  # completely disable output no matter what is connected to it
  hardware.display.outputs."VGA-2".mode = "d";

  /*
    equals
    boot.kernelParams = [ "video=DP-1:e" "video=VGA-2:d" ];
  */
}

Crafting custom EDID files

To make custom EDID binaries discoverable you should first create a derivation storing them at $out/lib/firmware/edid/ and secondly add that derivation to hardware.display.edid.packages NixOS option:

{
  hardware.display.edid.packages = [
    (pkgs.runCommand "edid-custom" { } ''
      mkdir -p $out/lib/firmware/edid
      base64 -d > "$out/lib/firmware/edid/custom1.bin" <<'EOF'
      <insert your base64 encoded EDID file here `base64 < /sys/class/drm/card0-.../edid`>
      EOF
      base64 -d > "$out/lib/firmware/edid/custom2.bin" <<'EOF'
      <insert your base64 encoded EDID file here `base64 < /sys/class/drm/card1-.../edid`>
      EOF
    '')
  ];
}

There are 2 options significantly easing preparation of EDID files:

  • hardware.display.edid.linuxhw
  • hardware.display.edid.modelines

Assigning EDID files to displays

To assign available custom EDID binaries to your monitor (video output) use hardware.display.outputs."<NAME>".edid option. Under the hood it adds drm.edid_firmware entry to boot.kernelParams NixOS option for each configured output:

{
  hardware.display.outputs."VGA-1".edid = "custom1.bin";
  hardware.display.outputs."VGA-2".edid = "custom2.bin";
  /*
    equals:
    boot.kernelParams = [ "drm.edid_firmware=VGA-1:edid/custom1.bin,VGA-2:edid/custom2.bin" ];
  */
}

Pulling files from linuxhw/EDID database

hardware.display.edid.linuxhw utilizes pkgs.linuxhw-edid-fetcher to extract EDID files from https://github.com/linuxhw/EDID based on simple string/regexp search identifying exact entries:

{
  hardware.display.edid.linuxhw."PG278Q_2014" = [
    "PG278Q"
    "2014"
  ];

  /*
    equals:
    hardware.display.edid.packages = [
      (pkgs.linuxhw-edid-fetcher.override {
        displays = {
          "PG278Q_2014" = [ "PG278Q" "2014" ];
        };
      })
    ];
  */
}

Using XFree86 Modeline definitions

hardware.display.edid.modelines utilizes pkgs.edid-generator package allowing you to conveniently use XFree86 Modeline entries as EDID binaries:

{
  hardware.display.edid.modelines."PG278Q_60" =
    "    241.50   2560 2608 2640 2720   1440 1443 1448 1481   -hsync +vsync";
  hardware.display.edid.modelines."PG278Q_120" =
    "   497.75   2560 2608 2640 2720   1440 1443 1448 1525   +hsync -vsync";

  /*
    equals:
    hardware.display.edid.packages = [
      (pkgs.edid-generator.overrideAttrs {
        clean = true;
        modelines = ''
          Modeline "PG278Q_60"      241.50   2560 2608 2640 2720   1440 1443 1448 1481   -hsync +vsync
          Modeline "PG278Q_120"     497.75   2560 2608 2640 2720   1440 1443 1448 1525   +hsync -vsync
        '';
      })
    ];
  */
}

Complete example for Asus PG278Q

And finally this is a complete working example for a 2014 (first) batch of Asus PG278Q monitor with amdgpu drivers:

{
  hardware.display.edid.modelines."PG278Q_60" =
    "   241.50   2560 2608 2640 2720   1440 1443 1448 1481   -hsync +vsync";
  hardware.display.edid.modelines."PG278Q_120" =
    "  497.75   2560 2608 2640 2720   1440 1443 1448 1525   +hsync -vsync";

  hardware.display.outputs."DP-1".edid = "PG278Q_60.bin";
  hardware.display.outputs."DP-1".mode = "e";
}