Custom monitor resolution on Wayland
TL;DR: My monitor doesn’t advertise its native resolution when connecting to the HMDI port. Every monitor sends information using a metadata format called Extended Display Identification Data (EDID). The solution involves extracting and modifying the the EDID metadata from my monitor and then force my computer to load this customized EDID file on boot.
NB! This method force-loads a custom EDID file on a port level, not only for a specific monitor! Plugging in a different monitor will probably cause trouble. A quick fix for this is to reboot and remove the kernel boot argument in your boot loader. If anyone know how to limit the custom EDID to a specific monitor, please contact me on Mastodon.
Grab the monitors EDID
We are not actually fetching the data straight from the monitor, but from the record that is stored in
/sys/devices/<deviceID/drm/card#/card#-PORT-#. That is where I found it on my Fedora system, other linux distributions might use slightly different paths. A quick way to find all available EDID files:
sudo find /sys -iname edid
Which outputs something like this, one file for every port:
/sys/devices/<deviceID>/drm/card0/card0-HDMI-A-1/edid /sys/devices/<deviceID/drm/card0/card0-eDP-1/edid /sys/devices/<deviceID>/drm/card0/card0-DP-2/edid /sys/devices/<deviceID>/drm/card0/card0-DP-1/edid
Identify which port you are targeting and copy the EDID file to your home directory:
sudo cp /sys/devices/[…]/edid ~/edid.bin
Using wxEDID to modify the file
The wxEDID tool needs to be compiled from source and depends on a legacy development package, which on Fedora is called
compat-wxGTK3-gtk2-devel. Since the software is written in C++,
gcc-c++ is also required. After compilation you can remove the development package and install the regular library
Download the latest release from the projects page on SourceForge, which was 0.0.26 when I compiled it.
After installing the
compat-wxGTK3-gtk2-devel packages (or the equivalent on your distro), do the following:
# Uncompress the tar.gz file, enter the directory ./configure make # To install it on your system, run sudo make install
Check out the INSTALL and README file for more details.
Modifying the EDID file
If you installed wxEDID to your system, you can simply write
wxedid in a terminal. Look for the DTD entries.
Select the highest resolution you can find in the list (at least that is what I did), then go to the “DTD Constructor” tab. You need to modify three values: first the V-res and X-res, then the Pixel Clock (in that order). Adjust the Pixel Clock so that the V-Refresh value equals 60Hz or wathever your monitor supports.
Save the changes to a new EDID file in your home directory.
Load your EDID file at boot
The following steps are very dependent on the distro you use. The big picture is that you need include your EDID file in the initrd image and add an argument to your kernel that loads your modified EDID file early in the boot process. Most distros document how to do this.
This is how you do it on Fedora
First you have to copy your modified EDID file to
edid folder probably does not exists, so you have to create it.
sudo mkdir /usr/lib/firmware/edid sudo cp your-edid-file.bin /usr/lib/firmware/edid
The argument you have to add to the kernel boot is
In Fedora your should use Grubby to add the kernel argument to Grub2:
sudo grubby --update-kernel=ALL --args=drm_kms_helper.edid_firmware=HDMI-A-1:edid/your-edid-file.bin
To include your EDID in the initrd image, you’ll have to use
/etc/dracut.conf.d/99-local.conf in your favorite text editor and add the following line:
install_items+=" /usr/lib/firmware/edid/<your-edid-file>.bin "
This will make sure that your EDID file is added to the initrd. Force dracut to regenerate the initrd file:
sudo dracut -f
To make sure your EDID file got included, run:
sudo lsinitrd | grep edid
Thats it. Reboot and pray that everything works!