How can I get the Nvidia driver to drive my projector at 1280x720?

Solution 1:

Success!

After many hours of blindly fooling around with xorg.conf and xrandr, I found a solution that works.

The problem appears to be:

  1. The Nvidia driver insists on using EDID data from the display rather than anything set by xrandr or in xorg.conf.
  2. For some reason the Nvidia driver couldn't read the EDID data from my projector.

Thus, the solution is to provide an EDID override. I couldn't find one for my particular display, but I was able to find one for some other 720p projector. It works!

After getting the EDID file and putting it some place, it's installed in the xorg.conf file by adding a line like this to the "Screen" section of xorg.conf:

Option         "CustomEDID" "CRT-0:/path/to/edid.bin"

Here "CRT-0" is where the projector is connected: to the VGA port.

One more additional complication is that I couldn't actually find a binary EDID file. Instead, by searching for "720p EDID file", I found some .INF files that contain EDID information extracted by some Windows program. These are Windows .ini format files. They contain the actual EDID information in a block that looks like this:

[OVERRIDDEN-EDID_AddReg]
;Base EDID
HKR,EDID_OVERRIDE,"0",0x01,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x3D,0xCB,0x81,0x07,0x00,0x00,0x00,0x0
0,0x00,0x11,0x01,0x03,0x80,0x6E,0x3E,0x78,0x0A,0xEE,0x91,0xA3,0x54,0x4C,0x99,0x26,0x0F,0x50,0x54,0x20,0x0
0,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1D,0x00,0x7
2,0x51,0xD0,0x1E,0x20,0x6E,0x28,0x55,0x00,0x53,0x6F,0x42,0x00,0x00,0x1E,0x01,0x1D,0x80,0x18,0x71,0x1C,0x1
6,0x20,0x58,0x2C,0x25,0x00,0x53,0x6F,0x42,0x00,0x00,0x9E,0x00,0x00,0x00,0xFC,0x00,0x54,0x58,0x2D,0x53,0x5
2,0x38,0x30,0x35,0x0A,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xFD,0x00,0x3B,0x3D,0x1E,0x2E,0x08,0x00,0x0A,0x2
0,0x20,0x20,0x20,0x20,0x20,0x01,0x5A

To turn that into a binary file, I wrote the following tiny Python script:

#!/usr/bin/python

# first item was 0x01

s = "0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x3D,0xCB,0x81,0x07,0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x03,0x80,0x6E,0x3E,0x78,0x0A,0xEE,0x91,0xA3,0x54,0x4C,0x99,0x26,0x0F,0x50,0x54,0x20,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1D,0x00,0x72,0x51,0xD0,0x1E,0x20,0x6E,0x28,0x55,0x00,0x53,0x6F,0x42,0x00,0x00,0x1E,0x01,0x1D,0x80,0x18,0x71,0x1C,0x16,0x20,0x58,0x2C,0x25,0x00,0x53,0x6F,0x42,0x00,0x00,0x9E,0x00,0x00,0x00,0xFC,0x00,0x54,0x58,0x2D,0x53,0x52,0x38,0x30,0x35,0x0A,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xFD,0x00,0x3B,0x3D,0x1E,0x2E,0x08,0x00,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x01,0x5A"

s = "".join(map(lambda x : chr(int(x, 16)), s.split(",")))

f = open("edid.bin", "w")
f.write(s)
f.close()

Note that you have to remove the first three fields from the line in the .inf file: "HKR,EDID_OVERRIDE,"0",0x01".

To verify that the resulting EDID file was valid, I used parse-edid (part of the read-edid package):

tobin@thinktop:~/pathname/$ 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:fc
    Identifier "TX-SR805"
    VendorName "ONK"
    ModelName "TX-SR805"
    # Block type: 2:0 3:fc
    # Block type: 2:0 3:fd
    HorizSync 30-46
    VertRefresh 59-61
    # Max dot clock (video bandwidth) 80 MHz
    # DPMS capabilities: Active off:no  Suspend:no  Standby:no

    Mode    "1280x720"  # vfreq 60.000Hz, hfreq 45.000kHz
        DotClock    74.250000
        HTimings    1280 1390 1430 1650
        VTimings    720 725 730 750
        Flags   "+HSync" "+VSync"
    EndMode
    Mode    "1920x540"  # vfreq 60.053Hz, hfreq 33.750kHz
        DotClock    74.250000
        HTimings    1920 2008 2052 2200
        VTimings    540 542 547 562
        Flags   "Interlace" "+HSync" "+VSync"
    EndMode
    # Block type: 2:0 3:fc
    # Block type: 2:0 3:fd
EndSection

So it appeared valid. Indeed, after restarting the X server, I was able to go into the Ubuntu Display settings and click "Detect Displays". It sees my fake 'ONKYO Corporation 50"' display and happily drives it at 1280x720. Required one more X reset to get everything working.

...And this is why we love Linux. (-: