rubensolvang.com

Custom monitor resolution on Wayland

The DELL 2711b monitor has a native resolution of 2560x1440 which is available when using the DisplayPort. The HDMI port however, is limited to 1920x1080. The X display server has some well documented methods to override a monitors resolution, but none of them work on Wayland. I have made many attemps to find a solution to this problem in the past, but never really figured it out – until now!

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 my Mastodon account.

Extract 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 compat-wxGTK3-gtk2 instead.

Download the latest release from the projects page on SourceForge, which was 0.0.26 when I compiled it.

Compiling wxEDID

After installing the gcc-c++ and 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 /usr/lib/firmware/edid/. The 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 drm_kms_helper.edid_firmware=HDMI-A-1:edid/your-edid-file.bin.

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 dracut. Open /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!

Kategori(er): howto, linux