Skip to content

T6034 (J516M): external displays over Thunderbolt, tested with a Studio Display at 5K (stacked on #405, overlaps #292) - #406

Draft
BTNG-studio wants to merge 7 commits into
omacom:chris/j514m-t6034-pmp-20261105from
BTNG-studio:t6034-dcpext
Draft

BTNG-studio wants to merge 7 commits into
omacom:chris/j514m-t6034-pmp-20261105from
BTNG-studio:t6034-dcpext

Conversation

@BTNG-studio

@BTNG-studio BTNG-studio commented Nov 7, 2026 •

Copy link
Copy Markdown

Summary

Draft. External displays on the T6034, from a J516M (16" M3 Max) driving an Apple Studio Display at 5120x2880@60 (DSC) over Thunderbolt on the right-side port, through dcpext0.

Overlaps #292. digital-brew's #292 (and omacom/m1n1#21) bring the same T6030 dcpext path to the T6031 (J516C) and are further along. Several patches here make the same moves for the T6034: apple,t6030 checks widened to an M3 helper, the display subsystem lookup, dispext<N>_fe as the processor's power domain, the panel's own 14.7 image, and Thunderbolt DP on the qualified list. I'm opening this as a draft so the T6034 results are on record. I'm happy to rebase it onto #292 once that lands, so the T6034 becomes a few table entries on top of it. If you'd rather have that now, say so.

Stacked on #405 (J516M display and GPU), which is stacked on #372. It targets #372's branch, so only the last four commits are this PR:

  1. apple: run Thunderbolt DP tunnels on T6034: apple_dp_tunnel_m3_soc() (T6030 or T6034) replaces the apple,t6030 checks in the display fabric, crossbar and ATC PHY. apple,t6034 joins the Thunderbolt DP qualified list, and the T6031-compatible ACIO gets the M3 DP IN policy. T6031 is not on the qualified list, so its policy stays apple_dpin_disabled and the J514C/J516C are unchanged.
  2. soc: apple: display-gate: hand over the T6034 dcpext0: the gate takes T6034 dcpext processors on the T6030 handoff markers, resolving dcpext → dispextN_fe → _cpu → _sys (ext_fe_first).
  3. drm: apple: run the T6034 dcpext0 on its own 14.7 image: T6034 display subsystem for the native path, the T6034 image admitted on apple,t6034 roots, and dcp_ext_cpu_domain() for the power and scanout DART checks.
  4. arm64: dts: apple: t6034-j516m: describe dcpext0 and the display crossbars: from the J516M ADT, J516M only, every node disabled until the gate enables it.

Paired m1n1 change: omacom/m1n1#29 hands off dcpext0 on T6034, opt-in with chosen.asahi,t6034-dispext=1 (the same idea as omacom/m1n1#21 for T6031). Without that line nothing changes.

Evidence

Hardware: my J516M (Mac15,11), OS firmware 14.7, system firmware 27.0, Apple Studio Display on the right-side Thunderbolt port (ATC2/ACIO2), coldplug and hotplug after boot. Hyprland 0.56.2.

What ran: these changes on the previous #372 head 19b6f899f, as local linux-aurora 7.2.11.aurora14-107 with m1n1-aurora 1.6.1.aurora22-103 and chosen.asahi,t6034-dispext=1. The rebase onto #372's current head applied cleanly and is compile-tested, not booted. Code-wise it differs from what booted only in comments. Left out of this PR: line-numbered refusal logs I used while debugging (m1n1), and an untested PCIe-tunnel follow-up for the display's USB side.

How it got there (each attempt was one boot):

Kernel Refusal Fix (now in this PR)
-104 dcp_t6030_ext_native() saw no T6030 display subsystem: "waiting for explicit dcpext_start" T6034 display subsystem (patch 3)
-105 external display processor firmware F493F03E-… is not supported T6034 image admitted (patch 3)
-106 dcpext startup refused: power prerequisites failed: -22 (power-domains[0] is dispext0_fe on T6034) dcp_ext_cpu_domain() (patch 3)
-107 none

On -107:

apple-dcp 306c00000.dcp: external display processor ready; its firmware starts when a display is attached
thunderbolt 0-1: Apple Inc. Studio Display
apple-dcp 306c00000.dcp: display attached: starting the external display processor
apple-dcp 306c00000.dcp: external display processor running
apple-dcp 306c00000.dcp: display routed to Thunderbolt DP tunnel dpin0
apple-dcp 306c00000.dcp: DPTXPort: port 0 carries tile (0,0) of a 2x1 tiled 5120x2880 display
apple-dcp 306c00000.dcp: display has 5 usable modes
apple-dcp 306c00000.dcp: display mode "5120x2880": 60 936000 5120 5128 5160 5200 2880 2986 2994 3000 0x48 0x0 (timing 43, color 48) already active and showing
  • Studio Display, 5120x2880@60 DSC on DP-3, next to eDP-1 at 3456x2234@120: pass. 5 modes read (5K, 4K, 2560x2880, 1440p, 1080p). No GPU faults.
  • First modeset: the firmware's first DSC modeset fails (ERROR: Modeset done, but pipe not enabled, Resetting DSC and it's PS on modeset failure), then succeeds on its own retry. This looks like the first-mode race M3 Max (J516C): external displays over USB-C and HDMI #292's patch 15 (wait for a dcpext display's timings before its first swap) describes on T6031, so I'd expect that patch to help here too.
  • Host tests (full manifest, this branch's head): 159 of 166 pass, plus the manifest's 6 known failures. tunnel-route-tests.py and t6030-clock-tests.py extract the functions that now call apple_dp_tunnel_m3_soc(), so patch 1 makes them extract it too, and the tunnel-route fixture answers apple,t6034. The one failure, tools/testing/selftests/drivers/gpu/apple-dcp/run.sh, fails the same 6 cases on Add guarded J514M/T6034 native graphics bring-up #372's unmodified head on this machine.
  • Compile: compile-check.py --per-commit with the shipped config: every commit builds, no new W=1 warnings. drivers/gpu/drm/apple, drivers/soc/apple, drivers/mux, drivers/phy/apple, drivers/thunderbolt and t6034-j516m.dtb also build with the package's toolchain (LLVM 18, W=1).
  • Commits: all signed off. checkpatch: advisory UNDOCUMENTED_DT_STRING for apple,t6031-dart, apple,t6031-asc-mailbox, apple,t6031-display-crossbar (also added by M3 Max (J516C): external displays over USB-C and HDMI #292), apple,t6030-dcpext, apple,t6034-dcpext and apple,t6030-display-subsystem. Most are already used undocumented in the tree. One FILE_PATH_CHANGES (new dtsi).
  • Not tested: the two left-side ports (routes described, untested), HDMI, a second external display (only dcpext0 is described), DP audio (No audio support), suspend/resume with the display attached, the display's USB side (camera, mic, speakers, its USB-C ports: no PCIe tunnel yet), use beyond a few hours, other monitors.

Unverified assumptions: the T6034 crossbar registers equal T6030's, and the T6030 tunnel clock sequence holds on T6034. Both held on the right-side port.

Merge Danger

Door: two-way

Blast Radius: J516M with chosen.asahi,t6034-dispext=1, plus the M3 DP helper on T6030

The new device tree nodes are J516M only and stay disabled without the m1n1 opt-in. On T6030, apple_dp_tunnel_m3_soc() returns what the apple,t6030 checks did. On T6031, the ACIO match changes the hardware entry but not the effective DP IN policy (still disabled). The J514M gets no dcpext nodes, so the gate's T6034 dcpext loop finds nothing.

🤖 Generated with Claude Code

The 16" binned M3 Max MacBook Pro (J516M) carries the J514M's T6034
die: its ADT names the same DCP image (F493F03E-...), and m1n1 gives
it the same T6034 handoff. Its chassis and panel are the J516C's.

Give it a v14 board record with the J514M's DCP, image and handoff,
and the J516 panel: 3456x2234 with 74 notch rows above the 3456x2160
boot framebuffer, ProMotion allowed and bring-up logging on. As on the
J514M, the panel controls stay off. The display gate starts native
display by default on the J514M and J516M, and
apple_t6034_display.enable=0 still keeps the boot framebuffer. The
T6034 GPU link follows the display on both boards.

Tests: a KUnit case for the J516M record, the T6034 display host test
admits the J516M and catches dropping it from the gate or the record,
and the display-order test links the J516M GPU while an unknown T6034
board (apple,j999) stays refused.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Philip Wallage <philip@btng.studio>
Include the T6034 DCP and give the J516M's DCP its panel node. The
panel is the J516C's (same 16" chassis): 346 x 223 mm, 216 mm below
the notch, 500 nits.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Philip Wallage <philip@btng.studio>
The J516M loads the J514M's 14.7 G15C image: on a J516M the loaded
firmware measured TEXT 0x64000, DATA 0x140000, GKTS 0x5cf28 and the
J514M's TEXT sha256 (4ca24b65...04b7), and the GPU reports the same
B1 identity (version 0x7041100, counts 0x21040a) with 30 enabled
cores in four ten-slot clusters ([8, 8, 7, 7]).

Admit apple,j516m with apple,t6034 alongside the J514M, and pin the
image to the J516M on a row of its own, so neither board's row admits
the other. The PMP, display, record and hardware identity checks are
unchanged. The profile test checks both rows, that each board pins
only its own, and that a changed digest is refused on the J516M too.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Philip Wallage <philip@btng.studio>
On the T6034 (J516M) the Thunderbolt link to a display comes up and its
DP tunnels are created, then torn down again: nothing drives the DP IN
adapters. The T6034 has the T6030's T8122-generation ATC PHYs, so it
takes the T6030 (M3) DP IN flow.

Add apple_dp_tunnel_m3_soc(), true on T6030 and T6034, and use it where
the display fabric, the display crossbar and the ATC PHY checked
apple,t6030 alone. Put apple,t6034 on the Thunderbolt DP qualified list
and give the T6031-compatible ACIO (shared by T6031 and T6034) the M3
DP IN policy. T6031 is not on the qualified list, so its policy stays
disabled and the J514C/J516C are unchanged; the T6030 path is the same
as before.

The T6030 crossbar registers and tunnel clock sequence are assumed to
hold on T6034; they do for dcpext0 on the right-side port of a J516M.

The tunnel-route and T6030 clock host tests extract the production
functions that now call apple_dp_tunnel_m3_soc(), so they extract it
too, and the tunnel-route fixture answers apple,t6034 (no scenario
there models it).

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Philip Wallage <philip@btng.studio>
Let the display gate enable the T6034's external display processors
on the T6030 dcpext handoff protocol: m1n1 publishes the T6030 markers
for dcpext0 when chosen.asahi,t6034-dcpext=1 or -dispext=1 is set, and
without them every node stays off.

On T6031/T6034 dispextN_fe is the child of dispextN_cpu, as disp_fe is
of disp_cpu, so the processor holds the front end and with it all
three states. Resolve the power chain from the front end there
(ext_fe_first), and keep the T6030 order (cpu, fe, sys) on T6030.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Philip Wallage <philip@btng.studio>
With the gate's handoff, the T6034 dcpext0 was still refused three
times on the way to a picture:

- dcp_t6030_ext_native() looked only for an
  apple,t6030-display-subsystem, so it waited for an explicit start.
- The external path admitted only the T6030 image (DDF38191-...). The
  T6034 external processors run the panel's own image (F493F03E-...),
  which the panel's DCP already drives on the same 14.7 layouts.
- dcpext_check_power() and the scanout's DART check took
  power-domains[0] to be dispextN_cpu; on T6034 it is dispextN_fe.

Accept the T6034 display subsystem, admit the T6034 image on
apple,t6034 roots (dcp_ext_firmware_admitted(), used by the external
prepare and the scanout's pageflip check), and find the CPU domain
through dcp_ext_cpu_domain(), which follows _fe to its _cpu parent.
T6030 behaves as before.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Philip Wallage <philip@btng.studio>
…sbars

Describe the T6034 external display processor dcpext0 (coprocessor,
mailbox, firmware and display DARTs, display pipe), the ATC display
crossbars and the Type-C routes, from the J516M ADT. dcpext0 sits
0x8000_0000 below the panel's DCP; both its DARTs are on interrupt
1047, as on T6030. Every node stays disabled; the display gate enables
them only after m1n1's handoff.

Include it from the J516M only: the J514M has the same SoC but is not
tested.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Philip Wallage <philip@btng.studio>
@briantoll

Copy link
Copy Markdown

One thing to look at once the Studio Display is lit on the T6034: colour. On the M1 path, apple-drm tags every RGB surface DCP_COLORSPACE_NATIVE and the firmware picks the SDR RGB link by score alone, which on a Studio Display XDR is a BT.2020 RGB link (colorimetry 9). Both together make sRGB come out heavily oversaturated next to the internal panel. The H17P path already refuses wide-gamut modes by score (external_sdr_rank); #157 gives the other externals the same preference and is worth checking against what the T6034 negotiates. You can see what the firmware chose with:

sudo dmesg | grep 'set_digital_out_mode() color mode'

and decode what the display offers from /sys/kernel/debug/dri/*/DP-*/ColorElements with the script in https://github.com/briantoll/omarchy-thunderbolt-display/blob/main/scripts/dcp-plist-decode.py. If the 5K Studio Display on your M3 Max logs colorimetry:16, that is a useful data point for #157 too, and I'd appreciate hearing it either way.

Also, if that machine sleeps with the display attached: #401 fixes the PMP dropping the dispext power domain during s2idle on the j314c, which blanked the XDR after resume. The T603x trees link each dcpext to its PMP DISPEXT request (per #292's patch 4), so the same path may be in play.

@techgyani

Copy link
Copy Markdown

Tested on a J514M (14-inch M3 Max, T6034): this PR's driver commits on 8eddf5aeb6ac (after #408), with a J514M dcpext0 device-tree node and omacom/m1n1#29, chosen.asahi,t6034-dispext=1. An LG 27UP850N on a USB-C to USB-C cable (no Thunderbolt device enumerated) came up at 3840x2160@60 (DSC=NO) on all three USB-C ports on hotplug, and on the right-side port on coldplug, with the internal panel still running and with the lid closed. A second monitor at the same time stays dark: display on USB-C Left Back waits for a free external display pipeline, as only dcpext0 is described. Results and logs: #333 (comment)

@techgyani

Copy link
Copy Markdown

Follow-up for the J514M: with a dcpext1 node added (apple,typec-mux-indices = <2 2 2>, power on dispext1_cpu as this PR does for dcpext0) and a J514M dcpext1 entry in m1n1#29's table, two USB-C monitors run at the same time, lid open and closed: #333 (comment)

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.

3 participants