Skip to content

T6041 M4 Max: internal display on DCP through aura's handoff, and the 25G83 GPU build on 40 cores (#1332) - #1345

Merged
DjDeveloperr merged 3 commits into
integration/aurorafrom
fix/t6041-max-internal-dcp-gpu-25g83
Nov 9, 2026
Merged

DjDeveloperr merged 3 commits into
integration/aurorafrom
fix/t6041-max-internal-dcp-gpu-25g83

Conversation

@DjDeveloperr

Copy link
Copy Markdown
Contributor

Fixes the two remaining gaps of #1332 (J614c, MacBook Pro 14-inch M4 Max, 40-core GPU, 26.6.2 stub). The other fixes from that report are already merged (u-boot#42, alarm-aurora#204, aurora-sep-userspace#19).

1. Internal display on DCP for the J614c and J616c

aura hands the M4 Max display over the same way it hands over the M4 Pro's (apple,t6041-handoff on the DCP, display subsystem and piodma). The two sides didn't agree, though:

Both now work the way they do on the J616s:

  • soc: apple: display-gate: adopt the M4 Max internal display handoff: the M4 Max gate runs gate_t6041_internal() first, with the same marker, compatibles, 26.6.2 firmware, DART/SID and running-DCP checks as the M4 Pro. Then it enables the external chains, which need the display subsystem that this handoff enables. Without a handoff, nothing changes.
  • arm64: dts: apple: t6041-j614c-j616c: leave the internal display to the handoff: the display subsystem stays disabled (the t604x.dtsi default), and the panel is disabled too. The gate enables both with the DCP.

aura side: aurora-silicon/aura#132 adds apple,j614c to the M4 Max handoff. The J616c is already covered there (aura#67).

Behaviour change: without a handoff, the external displays stay off together with the internal one, as on the J616s. aura publishes the external processors' firmware memory only together with the panel handoff, so nothing that worked with aura is lost. A loader that fills the external memory without handing the panel over (the local one #749 was tested with) would lose the external displays.

2. GPU: the 25G83 build on the 40-core M4 Max

drm/asahi: run the 25G83 build on the 40-core M4 Max: T6041 admitted only 25F84 (40 cores). The 25G83 profile in #1050 was captured on a 32-core J616C and is still open.

One value can't be derived: the loaded-image identity. The build admits the only T6041 25G83 image measured so far (sha256 aa113ed6…effc5, from #1050's 32-core J616C). iBoot fills part of the loaded TEXT for each Mac (three J616s loaded three different T6040 images), so joske's 40-core J614c most likely loads a different one. In that case the driver logs unsupported GPU firmware build: TEXT 0x60000 DATA 0x138000 entropy 0x59839/0x5991c sha256 <hash>, and that hash is a one-line addition. #1332 asks joske for that line.

The hardware-data words come from the 25F84 profile. The only other T6041 25G83 contents available are #1050's 32-core ones, which another driver built and which differ per core and per unit, so they can neither confirm nor refute those words.

Testing

  • ./linux-build/build kernel --profile asahi linux-t6041-max-dcp -- Image modules dtbs (LLVM, Rust): builds, with no new warnings in the changed files.
  • KUnit under QEMU (arm64, DRM_ASAHI=y, APPLE_DISPLAY_GATE_KUNIT_TEST=y): 286 tests, 284 passed, 2 skipped (UCLAMP_TASK and the G16 suite aren't configured). This covers all five apple-display-gate-* suites, including the 7 apple-display-gate-t6041-max cases, the new asahi_fwid.t6041_builds_admit_only_their_own_images, and asahi_g17_ta_mode.policy_is_local_to_the_admitted_t6041_builds.
  • tools/asahi/g17-firmware-selection-tests.py: PASS (the selector returns the identified build's configuration).
  • tools/asahi/g17-t6041-initdata-tests.py: builds the 25F84 and 25G83 objects. The hardware data builder accepts the 25G83 register map, and power configuration and region C are identical between the two.
  • DTB diff against integration/aurora, decompiled: t6041-j614c.dtb and t6041-j616c.dtb each change in exactly two properties (/display-subsystem and its panel become status = "disabled"). Their DCP, display and DART nodes now have the same status as the J616s's.
  • Not run on hardware. No J614c or J616c is available here. joske's next build is the first hardware test.

🤖 Generated with Claude Code

aura hands the M4 Max's internal display over the way it hands over the
M4 Pro's: the DCP, the display subsystem and the DCP's piodma carry
apple,t6041-handoff, the DCP names the 26.6.2 firmware, and the streams
sit on the same DARTs. The M4 Max gate only enabled the external
chains, so a handoff there was ignored and the panel stayed on
simpledrm.

Run the M4 Pro's internal display check on the M4 Max first. With the
handoff and a running DCP it enables the DARTs, the mailbox, the
display subsystem, the DCP and the panel; without it nothing changes.
The external chains still need an enabled display subsystem, now the
one this handoff enables, and still only add their DARTs to it.

Link: #1332
Signed-off-by: Diljit Singh <hey@djdev.me>
…he handoff

The J614c/J616c tree enabled /display-subsystem itself. aura refuses
to hand over a display whose nodes are already enabled ("display is
not status "disabled"", linux#1332), so the panel stayed on simpledrm.
Keep the display subsystem disabled, and the panel with it, as the
J616s tree does. The display gate enables them with the DCP once the
boot loader has handed the display over.

Without a handoff the display subsystem now stays disabled, and the
external chains, which need it, stay off too. aura publishes the
external processors' firmware memory only together with the panel
handoff, so nothing that worked with aura before is lost. A loader
that fills that memory without handing the panel over loses the
external displays until it hands the panel over as well.

Link: #1332
Signed-off-by: Diljit Singh <hey@djdev.me>
The macOS 26.6.2 boot firmware (iBoot mBoot-18000.161.10) loads the
25G83 GPU firmware on the M4 Max as well. integration/aurora admits
only 25F84 there, so a 40-core J614c booting through a 26.6.2 stub has
no GPU (linux#1332).

A firmware build can now carry the SoC configuration it runs with. Once
the build is identified, that configuration replaces the probed one.
This is the mechanism linux#1050 proposes, so its 32-core profile can
build on it.

T6041 gains a 25G83 build. Its configuration is the 40-core 25F84
profile with two changes:
- the 25G83 variant, with the four-cluster tiler values (TA mode 1)
  that 25F84 uses on this machine and #1050 uses for 25G83;
- the 25G83 register map. It has the same 25 windows (slot 3 holds the
  40-core part's eight memory controllers), laid out the way 25G83
  lays them out on the M4 Pro: from +0x200000, each window followed by
  a 16K guard page, with no reserved slots. This rule reproduces both
  known 25G83 maps, the M4 Pro's (four controllers) and #1050's 32-core
  M4 Max map (six). A compile-time check holds the M4 Pro's map and
  the new one to the rule, and the new one to 25F84's windows.

The rest comes from the 25F84 profile: 40 cores in four clusters, the
operand-state and deflake layouts, the 160-block compute pool, the
hardware data and power words, and region C. The core count check
stays, so a 32-core part is refused with this configuration.

The build admits one loaded image: the only T6041 25G83 image measured
so far (sha256 aa113ed6...effc5, measured on #1050's 32-core J616C).
iBoot fills part of the loaded TEXT for each Mac (three J616s loaded
three different T6040 images), so a 40-core Mac most likely loads a
different one. If so, its "unsupported GPU firmware build" line gives
the sha256 to add.

KUnit tests cover the identities of both T6041 builds, the 25G83
configuration, and the render policy of both builds. The host model of
the build selector now returns the build's configuration, and the T6041
initdata host test also builds the 25G83 objects.

Not run on hardware.

Link: #1332
Link: #1050
Signed-off-by: Diljit Singh <hey@djdev.me>
@joske

joske commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Tested on the J614c (MacBook Pro 14-inch M4 Max, 16-core CPU, 40-core GPU, 26.6.2 stub, system firmware 27.0). I used linux-aurora -28 (b1c9943) with this PR applied, plus the J614c's 25G83 image added to BUILD_25G83 (sha256 7c04360e05a6b8628f61262d0a244166187ad87a734716d8910908e94ffec08a), and aura main at 0a1f501 (with aura#132) as Stage 2. Mesa is aurora-wip 4fc7a6856c.

Internal display: works.

aura:   DCP: T6041: handoff published (firmware 6CC9349E-D30B-33FB-B12B-8D6D38F9F1B3, 26.6.2); display nodes left disabled, marker apple,t6041-handoff set
kernel: apple-t6041-display: display handoff accepted
        apple-dcp 402e00000.dcp: coprocessor handoff: CPU_CONTROL 0x10 CPU_STATUS 0xec
        apple-dcp 402e00000.dcp: Detected display with notch of 74 pixel
        apple-drm display-subsystem: bound 402e00000.dcp (ops dcp_comp_ops [appledrm])
        [drm] Initialized apple 1.0.0 for display-subsystem on minor 1

simpledrm is gone, and card1-eDP-1 is connected at 3024×1890. GDM comes up on it, both through the aura proxy and from disk: update-m1n1 built the trial and Stage 2 1.0.0b10-g0a1f501a booted from the internal SSD. The external chains stay off (dcpext0/1 firmware memory refused; placeholder remains disabled), as the PR describes.

GPU: the 25G83 build on 40 cores doesn't run work yet. With the J614c digest the image is admitted and RTKit comes up, but the first job never completes. This is the same with vkcube as with gnome-shell:

aurora 28a600000.gpu: GPU firmware build: Apple GFX 25G83 for T6041 (normalized loaded image, 40-core J614C)
aurora 28a600000.gpu: GPU firmware: macOS 26.6.2 (25G83, iBoot mBoot-18000.161.10)
aurora: GPU work of a client failed (ETIMEDOUT, reported at g17/runtime.rs:1316, client vkcube[4532]); the client sees a lost device

There was no firmware crash or fault, only the timeout. Every later client then waits behind the first job (Render watchdog … blocker_failed=1) until a reboot. Before this PR I tried a local build with the 25F84 register map unchanged, and with RENDER_BLOCKS at 120. It failed the same way. So the register map doesn't seem to be the cause. My guess is the 25F84-derived hardware data and power words, which the PR itself says can't be confirmed. For now the GPU is blacklisted on this machine.

If you want the digest in this PR, here is the FirmwareBuild entry I used, as a second image of BUILD_25G83:

crate::fwid::FirmwareBuild {
    name: "Apple GFX 25G83 for T6041 (normalized loaded image, 40-core J614C)",
    text_size: 0x60000,
    data_size: 0x138000,
    entropy: [0x59839, 0x5991c],
    text_sha256: [
        0x7c, 0x04, 0x36, 0x0e, 0x05, 0xa6, 0xb8, 0x62, 0x8f, 0x61, 0x26, 0x2d, 0x0a,
        0x24, 0x41, 0x66, 0x18, 0x7a, 0xd8, 0x7a, 0x73, 0x47, 0x16, 0xd8, 0x91, 0x09,
        0x08, 0xe9, 0x4f, 0xfe, 0xc0, 0x8a,
    ],
},

I'm happy to test the next GPU change on this machine.

🤖 Generated with Claude Code

DjDeveloperr pushed a commit that referenced this pull request Nov 10, 2026
The 40-core T6041 runs 25G83 with the 25F84 profile and the 25G83
register map (#1345). On the J614C (MacBook Pro 14" M4 Max, 40 cores,
macOS 26.6.2 stub) the firmware then starts, takes every job and marks
its items done, but the GPU never runs one: no completion stamp, no
fault, no firmware crash. Every job times out after two seconds.

The 25F84 profile's hardware data words include +0x2610 = 1. The J616C's
25G83 contents, and #1373's 32-core builders that reproduce them, have 0
there. Bisected on the J614C, with the J616C capture as the baseline:

  capture as dumped (32-core words, 6-MCC map)     runs
  + the 40-core words +0xf6c/+0xf88/+0xf8c/+0xfac/
    +0xfb8/+0xfc0/+0x2570 and this unit's OPP/CS   runs
  + +0x2610 = 1 alone                              hangs

and on this tree:

  40-core 25G83 configuration as merged            hangs
  the same with +0x2610 left at 0                  runs

"Runs" means a Vulkan compute dispatch (1, 64 and 4096 workgroups), a
buffer fill, a clear and a triangle render pass all complete with the
expected contents. With the fix, vkcube and a full X11 desktop (Cinnamon
on yserver, with fractional scaling and full-screen video) run on the GPU.

Give the 40-core 25G83 configuration its own chip without the word. The
25F84 configuration keeps it. The initdata host test now builds the
25G83 objects with that chip and checks that they differ from 25F84's
only in the register map and +0x2610.

Link: #1372
Fixes: 579bcc3 ("drm/asahi: run the 25G83 build on the 40-core M4 Max")
Signed-off-by: Jos Dehaes <jos.dehaes@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants