Controlling External Monitors On M1 Macs With Undocumented APIs

Screenshot of MacOS Lunar app

Display Data Channel (DDC) is a very useful feature of modern digital displays, as it allows the graphics card (and thus the OS) to communicate with a display and control features such as brightness and contrast. The biggest negative aspect here is the relatively poor access to this feature within an operating system like MacOS, which can change on a whim, as [Alin Panaitiu] found out recently.

Current displays implement DDC2, which is based around an I2C bus. Despite this, few OSes offer DDC-based control of features such as brightness which is where [Alin] developed a popular utility for MacOS that used undocumented APIs to talk DDC2 with external monitors via I2C. Until the new Arm-based Mac systems got released and these undocumented APIs got changed, that is.

Even though there are some ways around this, with some utilities using a simple software-based overlay to ‘dim’ the display, or using an external gamma adjustment via an external Raspberry Pi system hooked up to HDMI and using ddcutil, the best way is still via DDC2. Ultimately the new (undocumented) APIs that provide access were discovered, with another user going by the name [zhuowei] notifying [Alin] of the new IOAVServiceReadI2C and IOAVServiceWriteI2C methods with Arm-based MacOS.

After this it took some more sleuthing to figure out which of the devices on the I2C bus were which monitor in the case of multiple external monitors, but in the end it all worked again, adding hardware-based brightness controls back in the hands of MacOS users. Minus a few apparent hardware issues with HDMI on the M1 Mac Mini and some displays, but who is counting?

[Heading image: Screenshot of the Lunar app on MacOS. Credit: Alin Panaitiu]

8 thoughts on “Controlling External Monitors On M1 Macs With Undocumented APIs

  1. Developer of Lunar here.

    Thanks for the very nice write-up Maya!

    The HDMI port of the Mac mini is still blocking I2C writes. I know there are a lot of way-smarter-than-me people in this community so I’d like to take this chance to ask: does anyone have any idea what could be going on?

    The HDMI port seems to upgrade to using DisplayPort for upstream and keeps HDMI for downstream communication.

    I have no idea if this means anything in relation to DDC or I2C, I’m just hoping that someone with deeper knowledge will comment on this with the perfect answer because I see this happening quite often on other articles here on Hackaday.

    1. I don’t understand what you mean by “upgrade to DisplayPort for upstream.” While port compatible with HDMI, I thought the communication method was different between the two, LVDS for DP and TMDS for HDMI? According to Apple’s spec sheet, the HDMI port only produces the TMDS signal and a Thunderbolt adapter is needed for DP but you’re implying that it only outputs DP++ and the HDMI is a simple built in passive/active adapter. If the latter is true, it would seem you’re configuring the wrong signal since DP would implement the i2c with the aux pins and that would be in the video card drivers. I’m not sure this is something you’ll be able to fix but then again, I’m not sure how your app is communicating with the driver in the first place but I’d start looking there. If you can control the pins directly, you could always implement the protocol by bit banging.

    2. You probably should talk to the Asahi Linux people at some point, especially Hector Martin and Alyssa Rosenzweig. They’re currently working to reverse-engineer a lot of the low-level OSX display driving stuff (in order to implement a linux display driver) and would probably LOVE to compare notes.

  2. Very cool, but is there an undocumented API to stop an external display flickering me into a seizure every time I ask my M1 to do anything more strenuous than reading a mouse click….?

  3. Undocumented API changes without warning? It’s almost as if they didn’t document it because it wasn’t stable.

    Anyway, you probably shouldn’t change the hardware brightness, you should calibrate and set brightness and contrast once and then leave them. OSX manages colour and if you change the hardware settings the colour will be off. If you really want to change the brightness, isn’t changing the gamma curve the better option?

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.