Force RGB pixel format over YCbCr
There are some monitors, in my case Dell U2413, that report having YCbCr support when plugged in over HDMI. My AMD Radeon RX 570 Series video card sees this YCbCr pixel format and then prefers that over the RGB pixel format. The result is that fonts, graphics and other visuals are pixelated and not smooth in Ubuntu.
This actually is not just a Linux problem. With the same monitor hooked up over HDMI in macOS you get the same behavior. In fact an article by John Ruble on the Atomic Object blog called Fixing the External Monitor Color Problem with My 2018 MacBook Pro discusses and attempts to explain how to force RGB using EDID patching.
What follows here is essentially EDID patching on Linux. I’m not going to explain EDID, John did a better job, so I’m just going to cut to the chase and explain what I did to fix it on Ubuntu (19.10 and 20.04).
Solution⌗
All of the articles I could find exploring this topic advocate patching the EDID for the monitor. Unfortunately the macOS solution would not work here. Luckily I found a Reddit post that covered how to get it working.
Install Patched EDID⌗
Install the patched EDID (this example uses the pre-patched EDID attached here) and modify GRUB to use the new EDID.
$ sudo mkdir -p /lib/firmware/edid
$ cd /lib/firmware/edid
$ wget https://gist.github.com/RLovelett/171c374be1ad4f14eb22fe4e271b7eeb/raw/edid.bin
Create initramfs hook to copy the new EDID⌗
$ sudo tee "/etc/initramfs-tools/hooks/edid" > /dev/null <<'EOF'
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
# Begin real processing below this line
mkdir -p "${DESTDIR}/lib/firmware/edid"
cp -a /lib/firmware/edid/edid.bin "${DESTDIR}/lib/firmware/edid/edid.bin"
exit 0
EOF
$ chmod +x /etc/initramfs-tools/hooks/edid
$ sudo update-initramfs -u
Modify the GRUB configuration to use the new EDID⌗
Edit /etc/default/grub and add drm_kms_helper.edid_firmware=edid/edid.bin to the end of GRUB_CMDLINE_LINUX_DEFAULT.
For example:
--- /etc/default/grub 2020-03-19 15:27:24.350222700 -0400
+++ /etc/default/grub 2020-03-19 14:22:58.052179120 -0400
@@ -7,7 +7,7 @@
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
-GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
+GRUB_CMDLINE_LINUX_DEFAULT="quiet splash drm_kms_helper.edid_firmware=edid/edid.bin"
GRUB_CMDLINE_LINUX=""
# Uncomment to enable BadRAM filtering, modify to suit your needs
After saving the changes to /etc/default/grub run sudo grub-mkconfig -o /boot/grub/grub.cfg and reboot.
Creating a Patched EDID⌗
Get Unpatched EDID⌗
Find your current EDID and copy it to the current working directory.
$ sudo find /sys/devices/pci*/*/*/*/*/*HDMI* -name "*edid*" | head -1 | xargs -I{} cp {} edid.bin
Compile wxEDID Utility⌗
$ sudo apt install -y libwxgtk3.0-dev
$ wget https://sourceforge.net/projects/wxedid/files/wxedid-0.0.19.tar.gz/download
$ tar xvf wxedid-0.0.19.tar.gz
$ cd wxedid-0.0.19
$ ./configure --prefix=$HOME
$ make
$ make install
Run the wxEDID Utility⌗
$HOME/bin/wxEDID
Edit/Patch EDID with wxEDID Utility⌗
- Open the
edid.binfile with wxEDID - Find
SPF: Supported features->vsig_format-> replace0b01wih0b00 - Find
CHD: CEA-861 header-> change the value ofYCbCr420andYCbCr444to0 - Find
VSD: Vendor Specific Data Block-> Change the value ofDC_Y444to0 - Click
Optionon the panel->Recalc Checksum - Save patched EDID and exit
