Fix corrupt EDID in Linux running ATI/Catalyst/flgrx drivers

 

I couldn’t set the native resolution on one of my monitors after I installed ATI/AMD’s proprietary Catalyst drivers. With the open-source radeon drivers, you could at least throw some badly documented settings into a custom xorg.conf file and have X ignore a corrupt EDID and accept custom ModeLines. Sadly, the fglrx (Catalyst) drivers don’t play that.

Forcing EDID with closed-source undocumented fglrx/Catalyst drivers was a mystery. Took me 2 days to go through all the methods that don’t work until I found this gem of instructions by ubuntuforum’s @lukax at the bottom of page 4. All praise be to lukax and chris from this obscure impossible to find forum.

I extended their instructions a tad for my specific problem: dual screens (a pair of 1920×1200@60hz puppies), one of which has a fried EDID. X/fglrx detects one screen’s native resolution just fine, but force the other screen to be 640×480. So instead of wrestling with ModeLines/xrandr, I grabbed one screen’s EDID data and forced it on the other screen.

Fixing a screen with a bad EDID using a good screen

Note: the screens should have the same resolution and refresh-rate. No idea what will happen if they don’t :)

DFP4 (my Samsung SyncMaster) has a working EDID that I will use to override the other monitor (an otherwise lovely Benq, sporting the same native resolution and refresh-rate).

Using no third-party EDID extracting tools, lets dig the Xorg log for treasure. The good screen, having been detected by fglrx will have a nice juicy EDID in hex for us :)

aleckz@kronos:/var/log$ cat Xorg.0.log
...
[    29.695] (II) fglrx(0): Ranges: V min: 50 V max: 63 Hz, H min: 30 H max: 81 kHz, PixClock max 175 MHz
[    29.695] (II) fglrx(0): Monitor name: SyncMaster
[    29.695] (II) fglrx(0): Serial No: HCLZC01539
[    29.695] (II) fglrx(0): Number of EDID sections to follow: 1
[    29.695] (II) fglrx(0): EDID (in hex):
[    29.695] (II) fglrx(0): 	00ffffffffffff004c2d87053949315a
[    29.695] (II) fglrx(0): 	30140103803420782aee91a3544c9926
[    29.696] (II) fglrx(0): 	0f5054230800a9408180814081009500
[    29.696] (II) fglrx(0): 	b30001010101283c80a070b023403020
[    29.696] (II) fglrx(0): 	360006442100001a000000fd00323f1e
[    29.696] (II) fglrx(0): 	5111000a202020202020000000fc0053
[    29.696] (II) fglrx(0): 	796e634d61737465720a2020000000ff
[    29.696] (II) fglrx(0): 	0048434c5a4330313533390a20200186
[    29.696] (II) fglrx(0): Printing probed modes for output DFP4
[    29.696] (II) fglrx(0): Modeline "1920x1200"x60.0  154.00  1920 1968 2000 2080  1200 1203 1209 1235 +hsync -vsync (74.0 kHz eP)
[    29.696] (II) fglrx(0): Modeline "1920x1080"x60.0  154.00  1920 1968 2000 2080  1080 1203 1209 1235 +hsync -vsync (74.0 kHz e)
[    29.696] (II) fglrx(0): Modeline "1600x1200"x60.0  162.00  1600 1664 1856 2160  1200 1201 1204 1250 +hsync +vsync (75.0 kHz e)
...

Take the EDID hex, strip all the spaces and debug cruft, and create one nice string: “00ffffffffffff004c2d87053949315a30140103803420782aee91a3544c99260f5054230800a9408180814081009500b30001010101283c80a070b023403020360006442100001a000000fd00323f1e5111000a202020202020000000fc0053796e634d61737465720a2020000000ff0048434c5a4330313533390a20200186”

Apply any of the many possible GNU one-liners to convert the hex stream into a binary blob:

aleckz@kronos:~$ echo -n "00ffffffffffff004c2d87053949315a30140103803420782aee91a3544c99260f5054230800a9408180814081009500b30001010101283c80a070b023403020360006442100001a000000fd00323f1e5111000a202020202020000000fc0053796e634d61737465720a2020000000ff0048434c5a4330313533390a20200186" | perl -nE 'print pack "H*", $_' > edid.bin

We can verify the EDID binary using parse-edid tool  (apt-get install read-edid  in ubuntu):

aleckz@kronos:~$ parse-edid edid.bin
parse-edid: parse-edid version 2.0.0
parse-edid: EDID checksum passed.

	# EDID version 1 revision 3
Section "Monitor"
	# Block type: 2:0 3:fd
	# Block type: 2:0 3:fc
	Identifier "SyncMaster"
	VendorName "SAM"
	ModelName "SyncMaster"
	# Block type: 2:0 3:fd
	HorizSync 30-81
	VertRefresh 50-63
	# Max dot clock (video bandwidth) 170 MHz
	# Block type: 2:0 3:fc
	# Block type: 2:0 3:ff
	# DPMS capabilities: Active off:yes  Suspend:no  Standby:no

	Mode 	"1920x1200"	# vfreq 59.950Hz, hfreq 74.038kHz
		DotClock	154.000000
		HTimings	1920 1968 2000 2080
		VTimings	1200 1203 1209 1235
		Flags	"-HSync" "+VSync"
	EndMode
	# Block type: 2:0 3:fd
	# Block type: 2:0 3:fc
	# Block type: 2:0 3:ff
EndSection

Excellent! Captured my good screen’s EDID!

How do you make fglrx use the custom EDID binary for a bad screen?

Well we can either read the instructions from @lukax, or figure it out ourselves!

Let’s snoop on ATI/AMD’s proprietary closed-source drivers using strace, and see what files X server is trying to open while its booting up.

Switch to a different virtual console (CTRL+ALT+F1)
Stop X nicely (service stop gdm , or service stop lightdm , whichever is applicable. don’t forget to sudo up)
Use strace to log X’s open() system calls:

aleckz@kronos:~$ strace -e "trace=open" X -retro 2> xtrace.log

This should open up an old fashioned X server. Give it a few seconds, then switch back to the virtual console and kill it (CTRL+C).

A few pages into xtrace.log you should see something wonderful:

open("/proc/ati/major", O_RDONLY)       = 15
open("/dev/ati/card0", O_RDWR)          = 15
open("/sys/bus/pci/devices/0000:01:00.0/config", O_RDONLY|O_CLOEXEC) = 16
open("/sys/bus/pci/devices/0000:01:00.0/config", O_WRONLY|O_CLOEXEC) = 16
open("/sys/bus/pci/devices/0000:01:00.0/resource2", O_RDWR|O_CLOEXEC) = 16
open("/usr/lib/xorg/modules/libfb.so", O_RDONLY|O_CLOEXEC) = 16
open("/etc/ati/amdpcsdb", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 16
open("/etc/ati/DFP3.edid", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ati/dfp3.edid", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ati/DFP3.edid", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ati/dfp3.edid", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/proc/mtrr", O_RDWR)              = 16
Loading extension ATIFGLRXDRI
open("/proc/ati/major", O_RDONLY)       = 16

fglrx is making X look for EDID files in the /etc/ati folder! And the names of the files correspond to the port-names ATI assigns to your screens (DFP is their name for DVI?)

So now just copy the custom edid.bin to /etc/ati/DFP3.edid and /etc/ati/DFP4.edid (using whatever names appear in your trace log). No secret xorg.conf  settings necessary :)

Now when we restart X we will see something glorious in the new /var/log/Xorg.0.log

[ 43592.103] (II) fglrx(0): Successfully loaded EDID override file - /etc/ati/DFP3.edid - bytes:128 
[ 43592.103] (II) fglrx(0): EDID vendor "SAM", prod id 1415
[ 43592.103] (II) fglrx(0): Using EDID range info for horizontal sync
[ 43592.103] (II) fglrx(0): Using EDID range info for vertical refresh
[ 43592.103] (II) fglrx(0): Printing DDC gathered Modelines:
[ 43592.103] (II) fglrx(0): Modeline "1920x1200"x0.0  154.00  1920 1968 2000 2080  1200 1203 1209 1235 +hsync -vsync (74.0 kHz eP)
[ 43592.103] (II) fglrx(0): Modeline "800x600"x0.0   40.00  800 840 968 1056  600 601 605 628 +hsync +vsync (37.9 kHz e)

Now we have native-resolution support throughout X and every window manager and tweaking tool you want :)

Happy Desktoping!

5 thoughts on “Fix corrupt EDID in Linux running ATI/Catalyst/flgrx drivers

  1. Pingback: ATI Binärtreiber (fglrx) benutzt nur Modes die via EDID ausgelesen werden / Faken von EDID Informationen | Blog de imo

  2. I’ve a problem related to this.
    If that works the way you described it, it might save me a lot! of troublem thanks!

  3. wow !! it works. It took me two days of frustating searching and many, many unsuccessful tweaks of xorg.conf till I finally found your link – and discovered that flgrx drivers are ignoring all those settings anyway!

    So I followed your guide…
    I simply copied my screen’s EDID binary file to /etc/ati then renamed it to “CRT2.edid” (as i am using a VGA port), rebooted and voila !!
    I now have 1680×1050 working via VGA. Grin.

    Many thanks for your persistance in discovering how to workaround this “flgrx driver anomaly”, and more importantly publishing it so succinctly for us.

    PS – I am using a Chimei CMV 221D monitor on VGA port of ATI Radeon HD 5570, Linux Mint 16 on Core 2 Duo 6600. Smooth as silk for a 7 yr old machine !

  4. Nice tips for spelunking, not just the given problem. Syntax goof alert: on Arch Linux I had to do

    $ parse-edid < edid.bin

    with the redirect operator. Otherwise parse-edid hangs waiting for input. The install package in Arch is "read-edid".

    Samsungs are very good but I once found errors in onboard EDID data and so put modelines in xorg.conf derived straight from the Samsung user manual.

Leave a Reply

Your email address will not be published. Required fields are marked *