Repository navigation
drm: apple: answer the DPTX port's group 1 calls as macOS does - #282
Merged
RyanTheTide merged 1 commit intoOct 12, 2026
Merged
Conversation
On t6020 with the 13.5 firmware, DCP's DPTX port sends AP calls of group
1, commands 3 and 4, around link (re)configuration, audio prepare
included. The AFK v1 notify path dropped the group, so they reached the
group 0 handlers of the same numbers, SET/GET_DRIVE_SETTINGS: DCP
addresses from the payload were stored as drive settings. Behind a USB-C
to HDMI adapter DCP then refused the audio start ("Capabilities
changed") or never confirmed the stream.
Pass the group through a call_v2 op, with the signature of call_v2 on
aurora's J700 test branch (85d81b7, not in aurora-wip), and keep .call
for group 0 only. A group call to a service without call_v2 gets a
warning and no reply: AFK has no handler and does not guess one.
The DPTX port answers group 1 commands 3 and 4 the way macOS 13 does in
42 of 42 traced pairs (TV through the adapter, Dell over Thunderbolt):
an echo of the request with +0x00..0x03 cleared for (1, 3), and
+0x10..0x13 and +0x20 to the end cleared for (1, 4). The lane count sits
at +0x10 in (1, 3) and at +0x00 in (1, 4); macOS keeps it in all 42 and
clears the other slot. The J700 code reads (1, 3) the same way, with
per-lane levels from +0x20, which macOS does not clear there; it refuses
(1, 4), and its group 0 GET (0, 4) has the count at +0x00. Other groups
are echoed with a rate-limited warning.
Testing: MacBook Pro 16" M2 Pro (j416s), DCP firmware 13.5, a TV on a
USB-C to HDMI adapter and a Dell over Thunderbolt, 8 audio starts on
the TV per boot. Cold boots under the m1n1 hypervisor, aurora-wip with
PRs aurora-silicon#275-aurora-silicon#277, the AFK slots series and a bench DT change,
interleaved: with this commit the first start was accepted in 5 of 5
boots, with 0 refusals and 8 of 8 starts played; without it, 3 of 3
boots refused the first start, 2 refusals each, 4 of 8 played. The
Dell had no refusals in any boot, and no group warning was logged.
Natively, on a downstream tree with the same reply rule, the boot
connect and 3 of 8 TV replugs reached DCP (the rest failed earlier, in
the PHY): 0 refusals in 4 connects; before, 10 refusals in 5 connects.
Not tested: other SoCs, other firmware, AFK v2.
Assisted-by: Claude:claude-opus-5-5 checkpatch
Signed-off-by: nekolyanich <me@nekolyanich.com>
This was referenced Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On an M2 Pro (j416s) with the DCP 13.5 firmware, DCP's DPTX port (
AppleDCPDPTXRemotePort) sends the APcalls of group 1, commands 3 and 4, around link (re)configuration, audio prepare included. The group sits in
the call header (the
groupofstruct epic_service_call, one word into the notify payload), and the AFKv1 notify path didn't read it, so these calls reached the group 0 handlers with the same numbers,
SET_DRIVE_SETTINGS and GET_DRIVE_SETTINGS. Our log had
set_drive_settings: 2:0:1089336960:-1:0:0:0:0xffffffff40edf680 with the high word, a DCP address from the call's payload. With a TV on a USB-C to HDMI
adapter, DCP then refused the first audio start ("Restarting interfaces with reason - Capabilities changed"),
replugged the display, and sometimes never confirmed the stream (report 0xe0115001 stays 1). macOS 13 with the
same TV on the same adapter, traced in 3 cold boots, had 0 refusals in 5 audio prepares.
The reply. I traced macOS 13 on the m1n1 hypervisor in three sessions: the TV on that adapter, the TV in
an earlier session whose adapter wasn't recorded (macOS got 1 refusal there), and a Dell over Thunderbolt.
All 42 group 1 calls get a NotifyAck with the 68-byte header unchanged and the data
echoed, with some fields cleared:
The lane count is 2 on the TV path and 4 on the Dell, and macOS keeps it in all 42. In (1, 4) it clears
what DCP left past +0x20 (non-zero in all 31, DCP addresses included). A plain echo matches 9 of the 42; this
rule matches 42 of 42. Clearing 4 bytes at +0x10 rather than 8 rests on 1 call (the only one with a
non-zero high word there). The first word of the ack isn't in the traces (the tracer dumps from +4); it's
copied from the notify, as before.
The commit.
afk.c: the notify header is now{ __le32 unk0; struct epic_service_call call; }(68 bytes, asserted)instead of a private copy. If a service has
call_v2, every call goes there with its group; else.callgets group 0 only. A group call to a service without
call_v2gets a rate-limited warning and no reply,as a call to a service without a handler does now.
dptxep.c:.call_v2 = dptxport_group_call. Group 0 goes todptxport_call()unchanged, (1, 3) and(1, 4) get the macOS reply above, and any other (group, command) is echoed with a rate-limited warning: no
reply might stall DCP's caller.
trace.h:dptxport_apcallrecords the group (AP Call 1:4 (-); group 0 keeps the command name).Relation to the J700 work.
call_v2and its signature come from 85d81b7 ("phy: apple: implementbounded J700 DisplayPort main-link training") on
test/t8140-external-output-qualification, which isn't inaurora-wip. I didn't base this on that branch. Merging the two:afk.h: both add the samecall_v2line.afk.c: this changes the v1 notify path, 85d81b7 the v2 callback; they don't overlap.dptxep.c: both set.call_v2 = dptxport_group_call, with different bodies. Theirs sends (1, 3) todptx_j700_training()and refuses (1, 4) with-EOPNOTSUPPon AFK v2; this one acks both as macOS 13 doeson AFK v1, where USB4 DP-in has no ATC PHY for the training. One body that branches on
service->ep->wire_v2keeps both.Testing: MacBook Pro 16" M2 Pro (j416s), DCP firmware 13.5. A TV on a USB-C to HDMI adapter
(
dcpext0), Dell U2725QE over Thunderbolt (dcpext1). An initramfs starts 2 s of silence on the TV's cardabout every 7 s from 40 s, 8 audio starts on the TV per boot; nobody replugs anything. Under the m1n1 hypervisor, cold boots,
with and without the commit interleaved, on
aurora-wip30812f49+ #275 + #276 + #277 + the AFK slots seriesatc0out of the DCP routes):set_drive_settingslines per boot (the group 1 calls reaching group 0)The control is 3 boots. Earlier, on our downstream tree (Asahi fairydust with the USB4 series backported),
the same setup without the fix refused the first prepare in 5 of 5 cold boots, with 3 to 9 refusals each.
With this change on that tree: 3 of 3 boots clean under the hypervisor, 8 of 8 played, no
set_drive_settingsline.
Natively on our tree, with TV adapter hot replugs: the boot connect and 3 of 8 replugs reached DCP (the other 5
failed earlier, in the Type-C PHY: "Failed to lock pipehandler", a separate problem). All 4 connects had no
refusal, link up and stream confirmed. Before the fix, the same setup had 10 refusals in 5 connects (boot and 4
replugs; 2 of the 5 connects were refused 5 times each).
Not tested: other Macs and SoCs, the 12.3 and 14.x firmware, AFK v2, and the paths for other groups and
for a service without
call_v2(no such call was seen in the traces or on Linux).🤖 Generated with Claude Code