---
title: "Monado - EDID Override"
layout: main
---

* TOC
{:toc}

# Wrong colors on AMD GPUs

## Known affected HMDs

* Playstation VR
* Direct-Tek WVR2 / VR-Tek Windows VR Glasses 2560x1440
* OSVR HDK2 with firmware < 2.01

## The problem

Like monitors, HMDs provide their capabilities to the operating system with a small standardized block of data named EDID.

Some HMDs claim to support several color space modes over HDMI, in particular a YUV and an RGB mode, while in reality only supporting the RGB mode.

The kernel drivers for intel and nvidia generally choose the RGB mode and these HMDs will work fine.

amdgpu however tends to choose the YUV mode when the HMD is connected with HDMI, which leads to the HMD showing wrong colors, or even not showing anything.

## Workarounds

This behavior is part of the amdgpu kernel driver and at time of writing there is no simple API to control this behavior from user space.

### non-HDMI Connector

Choosing the YUV color mode is a HDMI specific behavior. Using an adapter from a different connector type like for example a DVI-to-HDMI adapter can work around this problem.

However this is not guaranteed to work with all adapters. HMDs connected with Displayport-to-HDMI adapters may still behave like HDMI connected HMDs.

### EDID Override

The most reliable workaround involves getting the buggy EDID from the device, removing the YUV color mode, and overriding the EDID the kernel uses for the output at boot time.

#### Getting and Fixing the EDID

Linux provides direct access to the EDID data as a file, per display output of the GPU in a path like `/sys/class/drm/card0-HDMI-A-1/edid`.

To remove the YUV mode, the EDID may be transformed to a human readable format, edited and transformed back by an appropriate tool, or the data may be edited directly with a hex editor.

The `wxEDID` GUI application can be used to change all values of `YCbCr420`, `YCbCr444` and similar to `0`.

Alternatively the `cros-chameleon` command line tool can transform edid data to human readable json and back.

```
git clone https://github.com/rpavlik/cros-chameleon.git
~/cros-chameleon/edid2json.py /sys/class/drm/card0-HDMI-A-1/edid > edid.json
```
Now in edid.json the YUV modes have to be disabled. The Direkt-Tek WVR2 for example contains these modes:
```
"YCbCr 4:2:2": true,
"YCbCr 4:4:4": true
```
Switch those to false
```
"YCbCr 4:2:2": false,
"YCbCr 4:4:4": false
```
and convert the fixed json back to edid data:
```
~/cros-chameleon/json2edid.py edid.json override.edid
```

#### Overriding the EDID

Create a directory in /lib/firmware for the edid `sudo mkdir -p /lib/firmware/edid/`.

Place the edid file in `/lib/firmware/edid/`, for example `/lib/firmware/edid/override.edid`.

You may need to regenerate your initramfs to include the firmware files. On Ubuntu this is done with `update-initramfs -u -k all`.

Append `drm.edid_firmware=HDMI-A-1:edid/override.edid` to your kernel command line. Most default installations will use grub as boot loader. Edit `/etc/default/grub` and add the override string to `GRUB_CMDLINE_LINUX_DEFAULT` so it looks like `GRUB_CMDLINE_LINUX_DEFAULT="quiet drm.edid_firmware=HDMI-A-1:edid/override.edid"`. Replace HDMI-A-1 with the appropriate output name found in `/sys/class/drm/card*-*`.

On kernels older than 4.13, replace `drm.edid_firmware=` with `drm_kms_helper.edid_firmware=`.

Generate an updated grub configuration from the /etc/default/grub template: `sudo grub-mkconfig -o /boot/grub/grub.cfg` and reboot.