Skip to content

Instantly share code, notes, and snippets.

@mcjmigdal
Last active December 15, 2025 02:59
Show Gist options
  • Select an option

  • Save mcjmigdal/3079ca80ad6b18bf077dcadc51563fac to your computer and use it in GitHub Desktop.

Select an option

Save mcjmigdal/3079ca80ad6b18bf077dcadc51563fac to your computer and use it in GitHub Desktop.
Custom Resolutions on KDE Wayland via EDID Injection

This is a AI enhanced note on my half day struggle to make my monitor work after KDE transitioned to Wayland

Custom Resolutions on KDE Wayland via EDID Injection

Under Wayland (KWin) the kernel’s DRM/KMS (Direct Rendering Manager/Kernel Mode-Setting) controls display modes. Unlike X11, Wayland does not support on-the-fly modelines via xrandr – it only uses modes that the monitor reports via EDID. In practice, this means you must override the monitor’s EDID to add unsupported modes. This guide shows how to generate a custom EDID for 3440×1440@40Hz on HDMI-A-1 and load it so KDE/Wayland will offer the new mode.

Why xrandr and gtf/cvt don’t work on Wayland

On X11 you could use xrandr --newmode or feed a modeline from cvt/gtf. But on Wayland/KWin, the compositor ignores non-native modes. For example, KWin states “the display is not supported in any geometry other than what is supported by a native mode”. In other words, adding a virtual 40 Hz mode is impossible without changing the EDID. We therefore create a firmware EDID containing the new timing.

Generating the custom EDID

If your monitor works on a different machine it might be easier to copy EDID from there.

  1. Get the mode timings: Use cvt or gtf to compute a modeline for 3440×1440@40Hz. For example:

    cvt 3440 1440 40 -r
    # 3440x1440 39.54 Hz (CVT) hsync: 52.49 kHz; pclk: 358.25 MHz
    Modeline "3440x1440R" 358.25 3440 3472 3512 3584 1440 1443 1454 1498 +hsync -vsync

    Take note of the numbers: here the HTimings (hdisp, hsync start, hsync end, htotal) are 3440 3472 3512 3584, and the VTimings (vdisp, vsync start, vsync end, vtotal) are 1440 1443 1454 1498.

  2. Edit an EDID template: The Linux kernel comes with example EDID source files (e.g. 1024x768.S) in the documentation (usually under /usr/src/linux/Documentation/EDID/ available in linux-docs package). Copy one (say 1024x768.S) to a new file (e.g. 3440x1440.S), and replace the #define values with your mode:

    • Set XPIX = 3440, XBLANK = 3584–3440, XOFFSET = 3472–3440, XPULSE = 3512–3472,
    • YPIX = 1440, YBLANK = 1498–1440, YOFFSET = 1443–1440 + 63 (the EDID standard adds 63), YPULSE = 1454–1443 + 63, as per the EDID HOWTO. (The kernel docs explain how X11 modeline values map to EDID macros; e.g. [15†L226-L229]).
  3. Compile the EDID: In the directory with the .S file there is a Makefile. Run make (you may need kernel headers installed). This generates a binary EDID (*.bin). Run edid-decode on it to verify the timings; it will also report the checksum. For example:

    edid-decode 3440x1440.bin

    If the CRC is wrong, edit the #define CRC in the .S file as instructed (or use edid-generator scripts), then re-make. This ensures the EDID block is valid.

Installing the EDID firmware

  1. Copy to firmware directory: Create /lib/firmware/edid/ (or /usr/lib/firmware/edid/) and place your binary EDID there. For example:

    sudo mkdir -p /lib/firmware/edid
    sudo cp 3440x1440.bin /lib/firmware/edid/custom-edid.bin

    This path is where the kernel looks for EDID blobs.

  2. (optional) Bind EDID to the HDMI output: You must tell the DRM driver to load your EDID for HDMI-A-1. There are two main ways:

    • Kernel command line (preferred on modern kernels): Edit your bootloader’s kernel parameters. - For example, in /etc/default/grub add:
GRUB_CMDLINE_LINUX_DEFAULT="... drm.edid_firmware=HDMI-A-1:edid/custom-edid.bin video=HDMI-A-1:3440x1440@40e"

⚠️ This video=... parameter was the key to solving my issue.
It forces the HDMI output to use the custom mode at boot, even if the EDID doesn’t mark it as preferred or active.

 Then run `sudo update-grub` (or `grub-mkconfig`) and reboot. This tells the kernel to use your EDID for HDMI-A-1. (Older kernels before 4.13 used `drm_kms_helper.edid_firmware=`, but new kernels support `drm.edid_firmware=`). The format must include the output name (e.g. `HDMI-A-1`) and the firmware path. For example, foosel’s guide does exactly this with `drm.edid_firmware=DP-6:edid/…`. Remember to replace `HDMI-A-1` with whatever `/sys/class/drm/card*/-*` shows for your HDMI port.
  • Modprobe config (alternative, mostly for built-in drivers): Create a file /etc/modprobe.d/force-edid.conf with a line like:

    options drm_kms_helper edid_firmware=HDMI-A-1:edid/custom-edid.bin
    

    However, note that on many systems “drm” is built into the kernel, so an initramfs approach (see below) or kernel param is more reliable.

  1. (optional) Rebuild initramfs: If you bound the EDID in early boot (for example with drm_kms_helper.edid_firmware), you must include the EDID file in the initramfs.

    • On Arch Linux: Edit /etc/mkinitcpio.conf. Add your GPU module (e.g. amdgpu or i915) to the MODULES=(...) array if not already there, and add the EDID file to the FILES=(...) array. For example:

      MODULES=(amdgpu)
      FILES=(/usr/lib/firmware/edid/custom-edid.bin)

      Then run sudo mkinitcpio -P to rebuild. This embeds the EDID so it’s available when the GPU driver loads.

    • On Ubuntu/Debian: You can include the EDID by updating initramfs:

      sudo update-initramfs -u -k all

      and ensure the kernel param (e.g. drm.edid_firmware=...) is set in GRUB. The Monado EDID docs explain this, including adding the firmware directory and updating GRUB.

Applying the custom mode in KDE

After reboot, the kernel should load your EDID. Verify with dmesg | grep -i edid or check /sys/class/drm/card0-HDMI-A-1/edid to see if the override took effect. In KDE Wayland you can now use kscreen-doctor (part of libkscreen) to confirm and enable the new mode. First list outputs:

kscreen-doctor --outputs
# Output: 1 Acer ... HDMI
#   Modes: 0:3440x1440@60*! 1:3440x1440@40  2:2560x1440@60 ...

The * marks the current mode and ! the preferred. If your 40 Hz mode appears (as above), apply it:

kscreen-doctor output.HDMI-A-1.enable \
              output.HDMI-A-1.mode.3440x1440@40

This turns on the HDMI output and sets 3440×1440@40Hz. You can also disable the laptop panel if desired:

kscreen-doctor output.eDP-1.disable

If you prefer a boot-time solution, note that adding video=eDP-1:d to the kernel command line will keep the internal display off (eDP-1).

Finally, ensure KDE remembers the layout. In System Settings ▶ Startup and Shutdown ▶ Login Screen (SDDM), click “Configure Display” (or similar) to copy your current display setup to the login screen. This ensures the custom mode is used on the greeter. Alternatively, run your kscreen-doctor commands in an autostart script so they apply every session.

Troubleshooting

  • EDID not applied: Check dmesg for errors (e.g. “no such output”) and verify the output name is correct (ls /sys/class/drm). The override parameter must match exactly (e.g. HDMI-A-1:); otherwise the wrong connector (often the laptop’s eDP-1) may be overridden.
  • Output stays black: If you see EDID override but the screen stays off, try adding video=<OUTPUT>:e to the kernel parameters to force-enable it (for example video=HDMI-A-1:e) as some users have found necessary.
  • Mode missing: Ensure the EDID binary was regenerated after any changes (correct CRC), and that the initramfs/grub was fully updated. You can re-run edid-decode on the final /lib/firmware/edid file to double-check.
  • Output name changes: High-end setups may rename connectors on wake (e.g. DP-6 ↔ DP-8). If that happens, you can bind multiple EDIDs in drm.edid_firmware (comma-separated) or script around the change.

With these steps, KDE/Wayland will offer your custom 3440×1440@40 Hz mode on HDMI-A-1. You can adapt the procedure for other resolutions or outputs as needed. Always double-check kscreen-doctor --outputs after applying to confirm the mode is active.

Sources: Authoritative guides on EDID injection and Wayland mode-setting provide the technical details behind these steps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment