Modifying macOS Display Resolutions

Some backstory:

I have a Dell U2713HM 27" monitor that has DisplayPort, DVI-D, VGA and HDMI input. I have a dock that only outputs HDMI, so to use my MacBook Pro with the Display I must connect with HDMI. However, the Dell U2713HM can't support its full resolution and frame rate over HDMI. I also previously used SwitchResX but the trial period ended and I am not willing to fork up $23 SGD for something that I can do myself and learn something new in the process.

How a monitor advertises its supported resolutions is by sending EDID metadata to the source. (Read more on Wikipedia) macOS has a feature called EDID overrides that can force a specific display to use a specific resolution. The EDID overrides shipped with macOS is found in /System/Library/Displays/Contents/Resources/Overrides. When a new display is connected, macOS will look in this folder by display vendor and product ID, and if that file exists, it will use the EDID data contained within the file instead of the one sent by the display. The U2713HM for example has a Vendor ID of 10ac and Product ID of 407f, therefore macOS will read the file in DisplayVendorID-10ac/DisplayProductID-407f. This file is a standard PLIST file and looks something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>DisplayProductID</key>
	<integer>16511</integer>
	<key>DisplayProductName</key>
	<string>DELL U2713HM (Modified)</string>
	<key>DisplayVendorID</key>
	<integer>4268</integer>
	<key>IODisplayEDID</key>
	<data>
	AP///////wAQrH9AAAAAAAEAAQSgAAB44Eu1p1ZLoyUKUFQAAAABAAEAAQABAAEAAQABAAEAHi0AUKCgFVAIIHgAALAxAAAekz8AUKCgHVAIIPgAALAxAAAeDTSAUHA4H0AIIBgAQEQhAAAeAAAA/ABEZWxsIFUyNzEzSE0KAIEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
	</data>
</dict>
</plist>

Inside the <data> element contains the EDID data that macOS will read instead of the one the display sends. This is usually used by macOS to fix misbehaving monitors.

We can add a new override by creating a new file in the same format, but first you might have to disable System Integrity Protection. Look up on how to do that if you haven't.

First, let's create an EDID file. I did this using the freely available AW EDID Editor tool.

I won't explain how to use this tool but above is how I configured it for my monitor. You might have to look up online for various parameters for you monitor, but most of it can be left at defaults. A very useful button to use is the CVT 1.2 Wizard that will generate the frequency values for a given width, height and framerate.

Save this EDID data will give you a binary file that can you can convert to Base 64. How you could do this is run in a terminal:

base64 path/to/file.bin

This will produce a block of Base 64 encoded text you can put into the PLIST file and save:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>DisplayProductID</key>
	<integer>PRODUCT ID INTEGER</integer>
	<key>DisplayProductName</key>
	<string>GIVE IT A CUSTOM DISPLAY NAME</string>
	<key>DisplayVendorID</key>
	<integer>VENDOR ID INTEGER</integer>
	<key>IODisplayEDID</key>
	<data>
	BASE64 ENCODED EDID DATA GOES HERE
	</data>
</dict>
</plist>

Take note that the ProductID and VendorID fields in the PLIST file are read as integers. Convert the hexadecimal value used in the file/folder name into integers before using them here.

Save the file into the right folder in the Overrides folder. As an example, my configuration is saved into /System/Library/Displays/Contents/Resources/Overrides/DisplayVendorID-10ac/DisplayProductID-407f.

Now, when you reconnect your display, it should make use of the new EDID configuration and resolution.

If you need a bit assistance, I'm sometimes available on Twitter as @serverwentdown.