DDC/CI on a Mac mini M4: HDMI, adapters, and a silent monitor

My test Mac has one external monitor, and it ignored every DDC/CI command. m1ddc failed, and Dimmerly fell back to software dimming. On 29 October I went through the connection one piece at a time, mostly with read-only probes. These are the notes, in case your monitor is doing the same thing. If you just want your brightness slider back, start with the DDC/CI troubleshooting guide.

The cause The monitor’s DDC/CI controller had stopped answering
The fix Unplugging the monitor from mains power for 1–2 minutes
Not the cause The Mac or the cables

The setup

DDC/CI is a small I²C bus inside the video cable. The monitor’s DDC/CI controller listens at address 0x37. On Apple Silicon, apps don’t drive that bus themselves. They hand each request to the display coprocessor (DCP), which passes it on through whatever chip sits between the Mac and the monitor.

Every command-line tool gave the same answer at first:

$ m1ddc display 1 get luminance
DDC communication failure: (iokit/?) unknown subsystem error

1. The built-in HDMI port forwards I²C

On M1 Macs and the entry-level M2 Mac mini, HDMI has a reputation for blocking DDC/CI. On this M4 the HDMI port goes through a Parade PS190 DisplayPort-to-HDMI converter, and macOS reports it as AppleDCPPS190. So I tested what gets through it.

Over the built-in port, the DCP read the monitor’s EDID (the block that identifies the monitor) at 0x50, its HDMI status registers (SCDC) at 0x54, and its HDCP receiver at 0x3a. Only the DDC/CI address stayed silent:

Address What lives there Result
0x50EDIDRead correctly
0x54SCDC (HDMI status)Read correctly
0x3aHDCP 1.4 receiverRead correctly
0x37DDC/CI0xe0114000
0x49, 0x59Two devices I didn’t identifyAnswered
106 unused addressesNothing0xe0114000

The DDC/CI address returned exactly what an empty address returns: nothing acknowledged it. On its own, that code can’t say whether the monitor ignored 0x37 or the converter didn’t pass it on. The cable in the next section returns the same code without forwarding DDC/CI at all. What settled it was the power cycle in section 5. The HDMI port carries the monitor’s other I²C devices, but I haven’t yet changed brightness through it (see the end of this page).

2. A USB-C to HDMI cable that forwards only EDID

The USB-C to HDMI cable contains its own converter, a MegaChips MCDP2900, which macOS reports as AppleDCPMCDP2900. DDC/CI apps use 0xB7 instead of 0x37 for the MegaChips HDMI bridge built into some M1 and M2 Macs (AppleDCPMCDP29XX), so I tried both addresses.

Through this cable only EDID answered, at 0x50 and its alias 0xD0. A full scan of all 256 addresses found nothing else. The HDCP and SCDC devices that answered over the built-in port were gone, and both DDC/CI addresses returned the no-acknowledge code.

Later the same day, once the monitor was answering again, I tried the cable a second time. It still forwarded nothing at 0x37 or 0xB7. The picture is fine through it, but it doesn’t carry DDC/CI at all.

3. On DisplayPort, a missing reply can look like success

A USB-C to DisplayPort cable has no converter in the path. Over it, every address from 0x00 to 0xFF returned success. Apart from the real EDID at 0x50, the data was filler: the byte 0x5b repeated.

On a native DisplayPort connection, an unanswered I²C request comes back as a success with bytes that aren’t a reply, not as an error. m1ddc printed a brightness of 91, which is 0x5b read as a number. The brightness looked valid, but the monitor hadn’t answered.

If a DDC/CI tool reports the same odd value for every setting on DisplayPort, check whether it is 91 or 255 (0x5b or 0xff). A real DDC/CI reply carries a checksum. Dimmerly rejects any reply whose checksum doesn’t match, so filler bytes don’t turn into a brightness value.

4. What didn’t revive it

5. What fixed it: mains power

I unplugged the monitor’s power cable for one to two minutes and plugged it back in. Over the DisplayPort cable it answered: brightness 100 of 100, contrast 50, volume 80. m1ddc worked, and Dimmerly listed the monitor’s hardware controls as Brightness, Contrast, Volume, and Input.

I’m not the first to see this. Someone with the same model reported in ddcutil issue #410 that it ignored DDC/CI until it was replugged and power-cycled, and then worked.

Dimmerly now suggests the power cycle itself. When the Mac reaches a monitor but the monitor never answers, Settings › Displays shows No DDC/CI reply. Unplug the monitor from power for a minute. I haven’t seen it appear on a silent monitor yet, because this one recovered before the hint existed. The DDC/CI troubleshooting guide has the same step.

6. Once awake, it ignores the first request

The revived monitor had one more quirk. A single request followed by a read never returned a fresh answer. The read returned the previous reply with a damaged header (6e 80 be), and its checksum failed. Sending the identical request twice, 10 to 50 ms apart, and then reading worked every time:

Sequence Fresh replies
One write, then read (waits of 50 or 150 ms, with or without a 10 ms pre-wait)0 of 6, in each variant
Two identical writes 10 ms apart, then read6 of 6
Two identical writes 50 ms apart, then read6 of 6

The read offset and read length made no difference. m1ddc already sends each request twice, and so does Dimmerly, which is why both worked once the monitor was awake.

7. Two DDC/CI tools at once make a working monitor look broken

One of my test runs failed 18 times out of 18 on a monitor that was working. Dimmerly was running in the background and talking to the same monitor, and the two programs’ requests and replies got interleaved on the bus. With Dimmerly quit, the double-write requests worked every time.

If you test with m1ddc or a similar tool, quit MonitorControl, Lunar, BetterDisplay, and Dimmerly first, or you’ll be measuring the collision.

What I’d check next time

  1. If DDC/CI stopped working on a connection where it used to work, unplug the monitor from mains power for a minute before you buy a new cable.
  2. Quit every other DDC/CI app before you test.
  3. On DisplayPort, don’t trust a success code. Check that the reply has a valid checksum.
  4. If a USB-C to HDMI cable passes only EDID, a USB-C to DisplayPort cable is the simplest way around it.

One thing I haven’t checked yet: DDC/CI end to end over the built-in HDMI port with the revived monitor. The probes above show the port forwards I²C to the monitor, but I haven’t changed brightness through it yet. I’ll update this page when I do.

If you have a monitor, dock, or adapter that behaves differently, please open a monitor compatibility report.