m1n1: Mac mini 12+ DCP initialization fails with some monitors

I have two monitors: An iiyama ProLite E2473HDS (1080p) and a Philips 279P1 (4K). They do not work with m1n1 from a 12.1 Mac mini (connected over HDMI). When m1n1 starts, the 1080p monitor wakes up from sleep (power LED turns blue), and a few seconds later displays “No signal” and goes back to sleep. m1n1 logs (including the DCP syslog messages) indicate nothing out of the ordinary; the display is correctly recognized at the correct resolution/refresh rate. In fact, the log is identical to the one produced when the mini is connected to a 1080p capture card. The 4K monitor does not seem to even wake up.

I’ve messed with m1n1’s display init code (mostly with the 1080p monitor since it’s not my primary display) and found out the following:

  • The monitor wakes up from sleep when dcp_ib_swap_begin is called.
  • Calling dcp_ib_set_mode after dcp_ib_swap_begin does not change anything at that point.
  • Calling dcp_ib_get_hpd in a loop after dcp_ib_swap_begin shows that connected goes back to 0 after 1-2 seconds, then goes back to 1 after ~400ms.
  • Calling dcp_ib_set_mode after connected is back to 1, then completing the swap (dcp_ib_swap_set_layer/dcp_ib_swap_end) makes the monitor work correctly; it will actually show m1n1 logo/console. It still takes a couple of seconds after completing the swap for the image to actually appear.
  • When rebooting, the situation is messier; after the call to dcp_ib_swap_begin, the monitor will still disconnect/reconnect, but after 5-6 seconds, not 1-2 seconds. It is, however, not necessary to wait for the disconnection: calling dcp_ib_set_mode a couple of seconds after dcp_ib_swap_begin seems to prevent the disconnection, and the monitor works afterwards.

I managed to make both my monitors work by making these changes: wait up to 5 seconds for the display to disconnect; if it does, wait for it to reconnect and call dcp_ib_set_mode; if it doesn’t, call dcp_ib_set_mode anyway.

This has the obvious issue of slowing down startup by at least 5 seconds on all monitors; it also seems very fragile and timing-dependent. I’m guessing there must be a better solution, since the monitors work (most of the time) in m1n1 with 11.6 iBoot, and it doesn’t seem to wait 5 seconds for the monitor to disconnect/reconnect… (I’ve tried to measure the time iBoot takes before starting m1n1, and it seems 11.6 is only slower than 12.1 by 900ms)

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 3
  • Comments: 45 (21 by maintainers)

Commits related to this issue

Most upvoted comments

Once Linux has a real display driver it will work like macOS.

coughs it works for me

None of these displays “work” under macOS because Apple disabled iBoot display output entirely since 12.0 😉

There is no display output until the OS driver loads, which means no verbose boot, no iBoot messages, no Apple logo and no progress bar until the kernel is half booted, etc. In fact, you get those features back if you chainload macOS under m1n1 and the display was initialized properly.

Once Linux has a real display driver it will work like macOS. The problem we’re trying to solve in this bug is bootloader display output, which is handicapped by the iBoot-mode interface that Apple provides for it. That’s why we’re having so much trouble with modes and timeouts and such.

@patlux Don’t reinstall! This is normal behavior. The boot.bin file I provided doesn’t include the U-Boot payload, so once m1n1 is started it waits for a payload to be sent over serial (from another computer). I’ll try to build a full version later; in the meantime, you can restore your original boot.bin from macOS.

Okay, for the folks with issues: please make a backup of /boot/efi/m1n1/boot.bin (in the same folder) and replace it with this one: https://mrcn.st/t/boot_display-test.bin (make sure to rename it to boot.bin).

Let me know if that improves things by default, for folks with no display output at all. Then, if you want to set the mode:

echo display=1920x1080 >> /boot/efi/m1n1/boot.bin

You can also use 1920x1080@60 to set the rate, or even 1920x1080@59.94 for fractional rates (but the parser is really dumb, always use two decimals).

You can also do:

echo display=auto >> /boot/efi/m1n1/boot.bin

And that will re-invoke the mode autoconfig logic (@pat42smith this should help with your 4K issue).

Obviously only do the echo once. For each time m1n1 finds the display= line it’ll set the mode, so if you append it multiple times you’ll wind up with the mode changing repeatedly.

By the way, the framebuffer size is limited and currently unchecked, so 4K modes may not work / may make everything crash. You’ve been warned. You can restore the boot.bin from macOS if this breaks things, as long as you backed up boot.bin inside /boot/efi, since macOS can access that FAT32 partition.

@patlux can you try boot_display_wait.bin? It should wait for the monitor to come up and then boot Linux. @tpwrules I followed your suggestion of adding a way to control the wait delay; you can test it by downloading either m1n1.bin or boot.bin from https://vincent.duvert.net/dropbox/ and append a display=... line to them. The format is:

Parameter
<none> Display is initialized by stage2 m1n1 and if only if it wasn’t initialized in stage1
display=auto Display is (re-)initialized by stage2 m1n1 regardless of its current state
display=1280x1024 Display is (re-)initialized by stage2 m1n1, preferring 1280x1024 resolution
display=wait
display=wait,auto
Display is (re-)initialized by stage2 m1n1 after waiting 10 seconds for monitor reset
display=wait:6
display=wait:6,auto
Display is (re-)initialized by stage2 m1n1 after waiting 6 seconds for monitor reset
display=wait,1280x1024 Display is (re-)initialized by stage2 m1n1 after waiting 10 seconds for monitor reset, preferring 1280x1024 resolution
display=wait:6,1280x1024 Display is (re-)initialized by stage2 m1n1 after waiting 6 seconds for monitor reset, preferring 1280x1024 resolution

@Skirmisher if you’re interested, you can download m1n1_1280_modes.bin that will dump all the timing modes that the DCP thinks are supported by the monitor (after setting it to 1280x1024). On my monitor it detects some resolutions that are probably not supported (3840x2160 on a 1080p monitor…), and I guess it’s the same in your case…