ddcctl icon indicating copy to clipboard operation
ddcctl copied to clipboard

Wanted: access DDC on M1 (ARM) platform Macs

Open thekeith opened this issue 3 years ago • 42 comments

Please update to allow an ARM64 target compatible with Apple Silicon Macs. Current implementation fails to compile, even when running terminal in Rosetta 2 mode.

Steps to reproduce:

  1. Clone repo onto M1 Mac
  2. Open terminal in Rosetta 2 mode
  3. Attempt to compile with "make intel"
  4. Fails silently

Output:

ddcctl % make intel
rm -f *.o ddcctl
cc -Wall -Wno-unused-variable -DkDDCMinReplyDelay=1 -c -o DDC.o DDC.c
cc -Wall -Wno-unused-variable -DkDDCMinReplyDelay=1 -o ddcctl -lobjc -framework IOKit -framework AppKit -framework Foundation DDC.o ddcctl.m

Notes: I do understand that this is likely just due to the Apple GPU simply not being a valid target here, and get it if this ticket isn't super high priority.

thekeith avatar Nov 18 '20 21:11 thekeith

Interesting, I don't have issues compiling ddcctl with "make intel" even on my M1 Mac, but the resulting binary does not work like expected (which I in turn expected, because I compiled with "make intel" even though it's an Apple Silicon Mac, because there currently is no Apple Silicon implementation). The program starts, shows the help, for example, and it even recognizes my external display, but it can't change the display's brightness or contrast. It can't poll the display's EDID apparently.

I would love to get Apple Silicon support in the future! :)

kieselit avatar Nov 21 '20 22:11 kieselit

I wish I understood more about how this works. FWIW I was able to build this without Rosetta for all variants. Just can't figure out how to resolve the EDID error.

jclusso avatar Nov 23 '20 12:11 jclusso

what does make framebuffers displaylist say on your M1 machines?

kfix avatar Nov 26 '20 06:11 kfix

rosetta emulation isn't helping here, make intel refers to tuning a constant for Intel GPUs, not the runtime arch.

we could do something like this so we don't have to build to a specific vendor anymore, but that's a side issue.

the bigger deal is that IOFramebuffer and I2C userspace support is (guessing) a stub on ARM

kfix avatar Nov 26 '20 06:11 kfix

My test with MacBook Air M1 connected to an external Dell monitor:

➜  make intel
rm -f *.o ddcctl
cc -Wall -Wno-unused-variable -DkDDCMinReplyDelay=1 -c -o DDC.o DDC.c
cc -Wall -Wno-unused-variable -DkDDCMinReplyDelay=1 -o ddcctl -lobjc -framework IOKit -framework AppKit -framework Foundation DDC.o ddcctl.m

➜  ./ddcctl
D: NSScreen #2 (1200x1600 90°) 95.00 DPI
I: found 1 external display
2020-11-26 15:26:35.810 ddcctl[32667:680154] Usage:
ddcctl 	-d <1-..>  [display#]
	-w 100000  [delay usecs between settings]

----- Basic settings -----
	-b <1-..>  [brightness]
	-c <1-..>  [contrast]
	-rbc       [reset brightness and contrast]

----- Settings that don't always work -----
	-m <1|2>   [mute speaker OFF/ON]
	-v <1-254> [speaker volume]
	-i <1-18>  [select input source]
	-p <1|2-5> [power on | standby/off]
	-o         [read-only orientation]

----- Settings (testing) -----
	-rg <1-..>  [red gain]
	-gg <1-..>  [green gain]
	-bg <1-..>  [blue gain]
	-rrgb       [reset color]

----- Setting grammar -----
	-X ?       (query value of setting X)
	-X NN      (put setting X to NN)
	-X <NN>-   (decrease setting X by NN)
	-X <NN>+   (increase setting X by NN)

➜  make framebuffers displaylist
ioreg -c IOFramebuffer -k IOFBI2CInterfaceIDs -b -f -l -r -d 1
ioreg -c IODisplayConnect -b -f -r -l -i -d 2

emanueldima avatar Nov 26 '20 14:11 emanueldima

@kfix here you go. This is to a Dell 2718Q.

$ ./ddcctl
D: NSScreen #1 (2560x1440 0°) HiDPI
D: NSScreen #2 (2560x1440 0°) HiDPI
I: found 2 external displays
2020-11-26 09:34:03.394 ddcctl[31747:5363539] Usage:
ddcctl  -d <1-..>  [display#]
        -w 100000  [delay usecs between settings]

----- Basic settings -----
        -b <1-..>  [brightness]
        -c <1-..>  [contrast]
        -rbc       [reset brightness and contrast]

----- Settings that don't always work -----
        -m <1|2>   [mute speaker OFF/ON]
        -v <1-254> [speaker volume]
        -i <1-18>  [select input source]
        -p <1|2-5> [power on | standby/off]
        -o         [read-only orientation]

----- Settings (testing) -----
        -rg <1-..>  [red gain]
        -gg <1-..>  [green gain]
        -bg <1-..>  [blue gain]
        -rrgb       [reset color]

----- Setting grammar -----
        -X ?       (query value of setting X)
        -X NN      (put setting X to NN)
        -X <NN>-   (decrease setting X by NN)
        -X <NN>+   (increase setting X by NN)

$ make framebuffers displaylist
ioreg -c IOFramebuffer -k IOFBI2CInterfaceIDs -b -f -l -r -d 1
ioreg -c IODisplayConnect -b -f -r -l -i -d 2```

jclusso avatar Nov 26 '20 14:11 jclusso

I should update the "found external display" message because its only a count of high-level NSScreen objects, not the lower-level IOFramebuffers to send DDC (I2C) to.

Based on that empty ioreg output, it doesn't look like they (IOFramebuffer) are being exposed - at least not in the same way as we expect on X86.

can an M1-owner run system_profiler SPDisplaysDataType?

kfix avatar Nov 26 '20 16:11 kfix

@kfix here you go.

$ system_profiler SPDisplaysDataType
Graphics/Displays:

    Apple M1:

      Chipset Model: Apple M1
      Type: GPU
      Bus: Built-In
      Total Number of Cores: 8
      Vendor: Apple (0x106b)
      Metal Family: Supported, Metal GPUFamily Apple 7
      Displays:
        DELL U2718Q:
          Resolution: 5120 x 2880 (5K/UHD+ - Ultra High Definition Plus)
          UI Looks like: 2560 x 1440 @ 60Hz
          Main Display: Yes
          Mirror: Off
          Online: Yes
          Automatically Adjust Brightness: Yes
        DELL U2718Q:
          Resolution: 5120 x 2880 (5K/UHD+ - Ultra High Definition Plus)
          UI Looks like: 2560 x 1440 @ 60Hz
          Mirror: Off
          Online: Yes
          Automatically Adjust Brightness: Yes```

jclusso avatar Nov 26 '20 16:11 jclusso

ooh, I just found that system_profiler SPDisplaysDataType -xml displays WAY more info, including displayID and IOFramebuffer paths on x86.

please attach that as a text file!

kfix avatar Nov 26 '20 16:11 kfix

@kfix here you go. display_data.txt

Mention me and I'll respond as fast as I can. Just turned notifications on for my phone. Will be around for a bit today.

jclusso avatar Nov 26 '20 16:11 jclusso

Thanks, I'm down for the holidays as well. Its why I had some time to work on this..

It looks like there isn't any info in the M1 dump about IORegistryEntry paths,EDID, etc etc.

For comparison, here's the dump on my MBP 15" 2018: MBP_15_2018_SPDisplays.txt

Hopefully Apple gives us something to work with in a future MacOS-on-ARM version?

kfix avatar Nov 26 '20 16:11 kfix

@kfix so we're SOL right now I guess? Any thoughts about some sort of config for the EDID and obtaining it manually some how?

jclusso avatar Nov 26 '20 16:11 jclusso

@jclusso It might stash the blob somewhere so we could parse it and display some info, but we still don't have a path to the I2C device to send control & query commands.

I'm not surprised things are a bit more obscured & abstracted on the M1. Various forums relay similar problems with other apps that do the same kind of things (SwitchResX)

kfix avatar Nov 26 '20 17:11 kfix

@kfix what does that other information look like. I can obtain the EDIDs by doing this ioreg -lw0 | grep "EDID UUID" -B 20

I'm not 100% familiar with what information we need, but here is the output of this. I'd give the whole ioreg -lw0 but it's huge and I don't know if any information I shouldn't share is in that.

$ ioreg -lw0 | grep "EDID UUID" -B 20
    | |   |   |   "BlendOutputCSCMethod" = 0
    | |   |   |   "IOMFBBrightnessCompensationEnable" = No
    | |   |   |   "ChargeValuesReset" = No
    | |   |   |   "VideoClock" = 297000000
    | |   |   |   "IdleCachingMethod" = 2
    | |   |   |   "DisplayPipePlaneBaseAlignment" = {"DefaultStride"=0,"LinearX_Alignment"=64,"LinearY_Alignment"=1,"PlaneBaseAlignmentLinear"=64}
    | |   |   |   "RuntimeProperty::registerTraceEnable" = No
    | |   |   |   "DisplayHeight" = 2160
    | |   |   |   "color-accuracy-index" = 0
    | |   |   |   "PDCGlobalTemp" = 0
    | |   |   |   "APTEnableEvents" = No
    | |   |   |   "ALSSSupported" = No
    | |   |   |   "IdleState" = 5
    | |   |   |   "APTLimitRefreshRate" = No
    | |   |   |   "IOMFBSupportsYFlip" = Yes
    | |   |   |   "IOMFBMaxSrcPixels" = {"PixelClock"=533333328,"MaxSrcRectTotal"=20971520,"MaxSrcBufferHeight"=16384,"IOMFBMaxCompressedSizeInBytes"=0,"VideoClock"=74250000,"MaxSrcRectWidth"=5120,"MaxSrcBufferWidth"=16384,"MaxVideoSrcDownscalingWidth"=27582}
    | |   |   |   "DisplayAttributes" = {"ProductAttributes"={"ManufacturerID"="DEL","YearOfManufacture"=2017,"SerialNumber"=811151436,"ProductName"="DELL U2718Q","AlphanumericSerialNumber"="4K8X77720Y0L","LegacyManufacturerID"=4268,"ProductID"=41193,"WeekOfManufacture"=27},"Chromaticity"={"Red"={"X"=41920,"Y"=21632},"Green"={"X"=19648,"Y"=39296},"Blue"={"X"=9856,"Y"=3904}},"DefaultWhitePoint"={"X"=20544,"Y"=21568,"Gamma"=144179},"SupportsStandby"=Yes,"PreciseAspectRatio"=114220,"MaxHorizontalImageSize"=61,"DefaultColorSpaceIsSRGB"=Yes,"SupportsSuspend"=Yes,"SupportsActiveOff"=Yes,"MaxVerticalImageSize"=35,"WhitePoints"=({"X"=20544,"Y"=21568,"Gamma"=144179}),"HasHDMILegacyEDID"=No,"NativeFormatVerticalPixels"=2160,"ContinuousFrequencySupport"="None","AspectRatio"=15,"NativeFormatHorizontalPixels"=3840}
    | |   |   |   "APTPDCEnablePM" = Yes
    | |   |   |   "SPLCSupported" = No
    | |   |   |   "APTPanicOnStuckPolarity" = No
    | |   |   |   "EDID UUID" = "10ACE9A0-0000-0000-1B1B-0103803D2378"
--
    | |   |   |   "BlendOutputCSCMethod" = 0
    | |   |   |   "IOMFBBrightnessCompensationEnable" = No
    | |   |   |   "ChargeValuesReset" = No
    | |   |   |   "VideoClock" = 0
    | |   |   |   "IdleCachingMethod" = 2
    | |   |   |   "DisplayPipePlaneBaseAlignment" = {"DefaultStride"=0,"LinearX_Alignment"=64,"LinearY_Alignment"=1,"PlaneBaseAlignmentLinear"=64}
    | |   |   |   "RuntimeProperty::registerTraceEnable" = No
    | |   |   |   "DisplayHeight" = 2160
    | |   |   |   "color-accuracy-index" = 0
    | |   |   |   "PDCGlobalTemp" = 0
    | |   |   |   "APTEnableEvents" = No
    | |   |   |   "ALSSSupported" = No
    | |   |   |   "IdleState" = 5
    | |   |   |   "APTLimitRefreshRate" = No
    | |   |   |   "IOMFBSupportsYFlip" = Yes
    | |   |   |   "IOMFBMaxSrcPixels" = {"PixelClock"=0,"MaxSrcRectTotal"=25165824,"MaxSrcBufferHeight"=16384,"IOMFBMaxCompressedSizeInBytes"=0,"VideoClock"=0,"MaxSrcRectWidth"=6144,"MaxSrcBufferWidth"=16384,"MaxVideoSrcDownscalingWidth"=0}
    | |   |   |   "DisplayAttributes" = {"ProductAttributes"={"ManufacturerID"="DEL","YearOfManufacture"=2017,"SerialNumber"=809055564,"ProductName"="DELL U2718Q","AlphanumericSerialNumber"="4K8X776T095L","LegacyManufacturerID"=4268,"ProductID"=41196,"WeekOfManufacture"=26},"Chromaticity"={"Red"={"X"=41920,"Y"=21632},"Green"={"X"=19648,"Y"=39296},"Blue"={"X"=9856,"Y"=3904}},"DefaultWhitePoint"={"X"=20544,"Y"=21568,"Gamma"=144179},"SupportsStandby"=Yes,"PreciseAspectRatio"=114220,"MaxHorizontalImageSize"=61,"DefaultColorSpaceIsSRGB"=Yes,"SupportsSuspend"=No,"SupportsActiveOff"=No,"MaxVerticalImageSize"=35,"WhitePoints"=({"X"=20544,"Y"=21568,"Gamma"=144179}),"HasHDMILegacyEDID"=No,"NativeFormatVerticalPixels"=2160,"ContinuousFrequencySupport"="None","AspectRatio"=15,"NativeFormatHorizontalPixels"=3840}
    | |   |   |   "APTPDCEnablePM" = Yes
    | |   |   |   "SPLCSupported" = No
    | |   |   |   "APTPanicOnStuckPolarity" = No
    | |   |   |   "EDID UUID" = "10ACECA0-0000-0000-1A1B-0104B53D2378"

jclusso avatar Nov 26 '20 17:11 jclusso

@kfix also not sure if what's going on over here would be of any interest. Seems they are talking about some sort of Apple bug that needs to be fixed. I don't know how they're doing stuff in comparison.

jclusso avatar Nov 26 '20 17:11 jclusso

Gonna keep guessing that "IOMFB" is short for IOMobileFramebuffer.

"IOMFB" also Seems to show up in iOS logdumps.

The GPU code that Apple might have ported from iThingsOS -> macOS probably didn't expose I2C apis to pesky app developers 😜

kfix avatar Nov 27 '20 01:11 kfix

Wouldn't they have to expose it somehow on the MacBook Pro. Somehow the OS has to be able to control the screen brightness... right?

jclusso avatar Nov 27 '20 01:11 jclusso

Is there an update of the possibility to bring this to M1 architecture?

ATG1209 avatar Dec 04 '20 12:12 ATG1209

I'll lock the thread if people want to keep asking when there's obviously no update...

kfix avatar Dec 04 '20 17:12 kfix

I just read a comment on the app QuickShade (on app store) where controls worked on a M1. I have not found anything as to how it was accomplished.

gwww avatar Feb 06 '21 20:02 gwww

Quoting from Lunar issue:

QuickShade adds a software black overlay over the whole screen which renders colors incorrectly, decreases contrast linearly instead of exponentially, and keeps the monitor LED backlight at the same strength which consumes more power and can heat up the monitor panel depending on how much time the monitor is kept on.

carbncl avatar Feb 06 '21 21:02 carbncl

QuickShade adds a software black overlay over the whole screen which renders colors incorrectly, decreases contrast linearly instead of exponentially, and keeps the monitor LED backlight at the same strength which consumes more power and can heat up the monitor panel depending on how much time the monitor is kept on.

Beats going into my monitor’s menu and adjusting the brightness

jkpe avatar Feb 06 '21 21:02 jkpe

Beats going into my monitor’s menu and adjusting the brightness

Indeed, It's incredible how they can make these menus so unusable, so I'm using QuickShade as well, but missing Lunar/ddcctl ¯\_(ツ)_/¯

carbncl avatar Feb 06 '21 21:02 carbncl

hey, adding a comment to watch but also i'm more than happy to run commands on a m1 and to help debug/test.

imajes avatar Mar 01 '21 19:03 imajes

+1

My life depends on ddcctl multiple times a day :)

adams-family avatar Mar 02 '21 15:03 adams-family

Any news with I2C interface on IOMobileFramebuffer with MacOS 11.3 ?

HyperCed avatar Apr 27 '21 07:04 HyperCed

Same here, just got a m1 mac mini yesterday, now I can jump from my intel 16 inch macbook pro to the m1 mac mini using ddcctl but not the other way around.

Let me know you need more info/test on the m1

sfdye avatar May 10 '21 05:05 sfdye

Quoting my comment from Lunar issue, as we're all in this together:

Please do note that Apple has sent a survey for M1 Mac users on May 5 via Feedback Assistant (it's preinstalled in macOS betas). I have mentioned inaccessible DDC there.

I think we can make the difference, should enough people chime in with the problem.

photovirus avatar May 10 '21 08:05 photovirus

Might worth relooking into the issue now with beta 2 MacOS Monterey. Per the issue from lunar, it's at least partially functional with DDC.

joshvasquez avatar Jul 02 '21 22:07 joshvasquez

A working solution of DDC on M1

https://gist.github.com/tao-j/c7a3c1ec7c2f59ebe45d161d620d9169

tao-j avatar Jul 03 '21 22:07 tao-j

Is that working on Big Sur or only on Monterey ? I tried the code on the link on my Mac Mini M1 with 11.4 and it did not seem to work.

HyperCed avatar Jul 04 '21 10:07 HyperCed

Is that working on Big Sur or only on Monterey ?

The API works on Big Sur too, but on Mac Mini M1 you need additional logic to select an external display (or the external display).

See the thread on Lunar for more info.

dguerri avatar Jul 04 '21 10:07 dguerri

Hey, just to let you know,

here is a small console tool for basic command line DDC control on the M1 Mini:

https://github.com/waydabber/m1ddc

here is a complete implementation of the matching logic and all the required basics in Swift (made it for MonitorControl but as it is self contained it can be used in a generic fashion):

https://github.com/MonitorControl/MonitorControl/blob/master/MonitorControl/Support/Arm64DDC.swift

These might be helpful for the ddcctl implementation as well. :)

waydabber avatar Aug 15 '21 14:08 waydabber

@waydabber if you could add a LICENCE file, that'd be helpful when it comes time for me to ~copypaste~ use that.

I don't have an M1 yet - holding out for the next M1Air - so no timetable on that.

kfix avatar Aug 15 '21 19:08 kfix

Hi @kfix - MonitorControl uses MIT license. Added it to m1ddc as well. :)

waydabber avatar Aug 16 '21 02:08 waydabber