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 setup
- Mac mini M4 on macOS 27.2.
- Philips 276E8V, a 4K 27-inch monitor from 2019, with HDMI and DisplayPort inputs.
- Three ways to connect it: the Mac’s built-in HDMI port, a USB-C to HDMI cable, and a USB-C to DisplayPort cable.
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 |
|---|---|---|
0x50 | EDID | Read correctly |
0x54 | SCDC (HDMI status) | Read correctly |
0x3a | HDCP 1.4 receiver | Read correctly |
0x37 | DDC/CI | 0xe0114000 |
0x49, 0x59 | Two devices I didn’t identify | Answered |
| 106 unused addresses | Nothing | 0xe0114000 |
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
- A DDC/CI setting in the on-screen menu. This monitor doesn’t have one. The manual mentions DDC/CI only as a compatibility feature.
- Resetting the on-screen menu to factory defaults. The filler bytes changed from
0x5bto0xff, so something in the monitor reset, but DDC/CI stayed silent. - Switching the DisplayPort input from 1.1 to 1.2. The link went up from HBR to HBR2, and DDC/CI didn’t change.
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 read | 6 of 6 |
| Two identical writes 50 ms apart, then read | 6 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
- 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.
- Quit every other DDC/CI app before you test.
- On DisplayPort, don’t trust a success code. Check that the reply has a valid checksum.
- 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.