Repository navigation
Conversation
This was referenced Oct 11, 2026
sithglan
force-pushed
the
dcp-typec-relink
branch
from
October 12, 2026 13:34
64ed68c to
51577e5
Compare
This was referenced Oct 12, 2026
theoparis
pushed a commit
to tinted-software/linux
that referenced
this pull request
Oct 13, 2026
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>
sithglan
force-pushed
the
dcp-typec-relink
branch
2 times, most recently
from
October 15, 2026 05:18
7aeb413 to
3a6e391
Compare
A USB-C monitor with a built-in USB hub (EIZO EV2780) intermittently stays dark after a cold boot or a hot-plug on the M1 MacBook Air and the M1 Mac mini. DCP trains the link for the first modeset at about the time the monitor's hub brings its SuperSpeed link up. When the two overlap, the sink loses the link, but DCP still reports the modeset as linked: UnifiedPipeline::mode_set_gated(): 2560x1440@59 Hz link: 1 Then one of two things happens. DCP gives up on its own 2.008 s after asserting HPD: IOMFB: IOAVVideoInterface terminated VideoInterfaceIOAV::unplug_gated(): display HPD removed or it keeps driving the dead link without noticing, while the monitor pulses HPD about 2-4 s later to be detected again. In both cases the CD321x still reports DP alt mode with HPD high, and nothing re-detects the sink. With dwc3 kept off the port, 5 out of 5 boots brought the display up; with it, 3 out of 6 failed. Replay an unplug and replug of the sink when DCP drops a sink that still asserts HPD, or when the sink asks for attention (IRQ_HPD): the link is then retrained after the hub has settled, as a cable replug does. A request from the sink within 4 s after a relink is the sink's late reaction to the loss the relink already handled and is ignored; another relink would only interrupt the new link. A sink request must not be dropped as an unchanged route state either. A connection gets at most three relinks; the replay does not reset that count. Pulsing only DCP's HPD instead, with the connector kept connected, raced with DCP re-detecting the sink on its own and left the display dark on the Mac mini. With this, 8 out of 8 cold boots of the MacBook Air and 8 out of 8 of the Mac mini (EIZO on the port that failed) brought the display up. Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
A DisplayPort sink that lost the link drops HPD and raises it again to be detected anew. The EIZO EV2780 does so for about 250 ms, which falls within the 500 ms debounce of cd321x_update_work(). The worker then sees DP alt mode with HPD high, the state it already applied, and cd321x_typec_update_mode() returns without telling the mux, so the display driver never learns that the sink wants attention and the display stays dark. The out-of-band DRM hotplug event does not cover this either on the M1 MacBook Air and Mac mini: their connector nodes have no "displayport" reference, so connector_fwnode is NULL. When HPD changed within the debounce window and is high before and after, pass the state on with DP_STATUS_IRQ_HPD set, even though it otherwise matches the applied one. Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
Waking a DP alt mode display from DPMS off with sway ("output * power
on") on the M1 Mac mini (Fujitsu E24T-7 Pro on USB-C, which keeps HPD
asserted while blanked) power cycles the display about every 750 ms
until reboot:
dcp_hotplug() connected:1 valid_mode:0 nr_modes:1
dcp_poweron() starting
set_digital_out_mode finished
dcp_poweroff() done
...
With the cable attached, dcp_poweron() reconnects DPTX and waits for
IOMFB to report the sink before the commit does its modeset. At that
point no mode is valid yet, so dcpep_cb_hotplug() takes the HPD for a
sink that asserted HPD only after a failed modeset and sends
DCP_HOTPLUG_NOTIFY. dcp_hotplug() then sets the connector's link-status
to BAD. wlroots treats a bad link as a disconnect and recreates the
output, which disables the CRTC and enables it again. That wake does
the same, so the loop never ends. Each round also leaks AFK service
slots ("AFK[ep:29]: no reusable service slots") and the system becomes
sluggish.
Do not take the HPD that dcp_poweron() waits for as a late one: the
modeset of the same commit follows. A sink that asserts HPD only after
dcp_poweron() stopped waiting is still handled as before.
Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
On the M1 Mac mini with two Fujitsu E24T-7 Pro monitors, which have no audio (single-block EDID 1.3), PipeWire logs spa.alsa: hw:0p: snd_pcm_start: No such device or address about 130000 times a second, for hours, as soon as something plays to a DCP audio output: 4.1 million log lines in one boot, with journald dropping most of them, and a core kept busy. Without a sink, opening, configuring and preparing the PCM succeed, as userspace drops an output that fails its probe for good, but START fails with -ENXIO. That does not stop userspace from trying: PipeWire starts playback after its first write and ignores the error, and a stream that never starts never makes it wait, so the next wakeup is immediate and tries again. Any other error ends up in its recovery, which prepares and starts again. Play into the void instead, as HDMI PCMs on other platforms do: without a sink, or once the sink the stream was opened for is gone, START succeeds and the stream runs on the clock, without DMA and without a DCP audio link. The position follows the time since START and a work item reports the periods. The samples are dropped. A stream playing into the void is not stopped as disconnected when a sink goes away; a sink attached later is used by the next stream opened. Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
A USB-C monitor with a built-in hub drops the DP link right after the first modeset of every DPMS wake, which dcp_typec_relink() recovers by replaying an unplug and replug. Its retry counter is only reset when the Type-C generation changes, i.e. on a real cable replug, so all wakes of one connection share DPTX_RELINK_RETRIES tries: after three wakes the fourth drop is handled as an unplug and the display stays dark until the cable is replugged. The limit exists to stop relink loops within one link bring-up. Reset it in dcp_poweron() when the CRTC comes back from DPMS off. No relink can run while the CRTC is off, dcp_typec_relink_start() refuses then. Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
Since commit 57f9f36 ("drm/apple: fence EDID publication by service lifetime and unblock RX"), the teardown of DCP's AV service schedules the connector hotplug worker to invalidate the EDID. DCP tears that service down whenever a Type-C CRTC is powered off with the display attached (DPMS off). dcp_hotplug() then finds the connector connected without a valid mode and reports the link as bad. wlroots treats a bad link as a disconnect and replaces the output on the next wake, which powers the CRTC off and on again, and that power off does the same: the display never comes back from the first DPMS off (Mac mini, EIZO EV2780 on USB-C). There is no link while the CRTC is off, and dcp_poweron() retrains one on wake. Leave the link status and the CRTC alone then; the EDID is still invalidated. Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
Commit 57f9f36 ("drm/apple: fence EDID publication by service lifetime and unblock RX") moved the connector dimension update for DisplayAttributes from the RTKit RX worker to the connector hotplug worker. Besides the dimensions, dcp_hotplug() reports the link as bad and retrains an active CRTC without a valid mode. DCP sends DisplayAttributes on every DPTX connect, and a Type-C DPMS wake connects DPTX in dcp_poweron(), before the modeset of its commit. dcp_hotplug() then finds the CRTC being enabled without a valid mode, replays its state (a second modeset) and reports a bad link. wlroots treats that as a disconnect and replaces the output, which powers the CRTC off and on again, and that wake does the same: the display never comes back from the first DPMS off, and every round leaks AFK service slots until the system crawls (Mac mini, EIZO EV2780 on USB-C). Defer the dimension update to a work item of its own, which does what the RX worker did before, outside it. External H17P keeps using the hotplug worker, as its display publication was written for that. Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
sithglan
force-pushed
the
dcp-typec-relink
branch
from
October 15, 2026 16:59
3a6e391 to
d4e92c2
Compare
DjDeveloperr
pushed a commit
that referenced
this pull request
Oct 16, 2026
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 #275-#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>
Contributor
|
Closing as superseded: this work was ported by #328 (merged 2026-10-16) and carried into the maintained 7.3 integration/aurora line. Thanks for the original change; nothing here is lost. |
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.
Problem
A USB-C monitor with a built-in USB hub (EIZO EV2780, plain DP alt mode, pin assignment D) intermittently stays dark after a cold boot, a hot-plug or a macOS → Linux reboot. Seen on the M1 MacBook Air (j313) and the M1 Mac mini (j274).
DCP trains the DP link for the first modeset at about the time the monitor's hub brings its USB3 SuperSpeed link up. When the two overlap, the sink loses the link, but DCP still reports
2560x1440@59 Hz link: 1. Then either:IOAVVideoInterface terminated,display HPD removed), orThe CD321x still reports DP alt mode with HPD high the whole time, and nothing re-detects the sink.
With
dwc3_appleblacklisted (no USB3 on the port), 5/5 boots came up. With it, 3/6 failed on the Air.Changes
drm: apple: relink a Type-C sink that lost its link to a hub's USB3. When DCP drops a sink that still asserts HPD, or the sink asks for attention (IRQ_HPD), replay an unplug and a replug 1 s later. The link is then retrained after the hub has settled, as a cable replug does.
dcp_external_hotplug()).usb: typec: tipd: report a coalesced sink HPD pulse as IRQ_HPD. The EIZO's ~250 ms HPD pulse falls within the 500 ms debounce of
cd321x_update_work(). The worker then saw the state it had already applied and never told the mux. On j313/j274 the out-of-band DRM hotplug path doesn't cover it either: the connector nodes have nodisplayportreference, soconnector_fwnodeis NULL.drm: apple: do not report a bad link for the HPD a Type-C wake awaits. Waking a DP alt mode display from DPMS off (
swaymsg "output * power off"/"power on") power cycled it about every 750 ms until reboot, on the Mac mini with a Fujitsu E24T-7 Pro on USB-C (it keeps HPD asserted while blanked).dcp_poweron()reconnects DPTX and waits for IOMFB to report the sink before the commit's modeset.dcpep_cb_hotplug()took that HPD for a sink that asserted HPD only after a failed modeset, sodcp_hotplug()set link-status BAD. wlroots treats a bad link as a disconnect and recreates the output, which disables and re-enables the CRTC, and that wake does the same again. Each round also leaked AFK service slots (AFK[ep:29]: no reusable service slots) and the system became sluggish. The HPDdcp_poweron()waits for is no longer handled as a late one; an HPD after the wait is still handled as before.drm: apple: audio: play into the void without a sink. Found on the same Mac mini: the Fujitsu monitors have no audio (single-block EDID 1.3), so DCP never brings up an audio interface. Without a sink, opening, configuring and preparing the PCM succeed (userspace drops an output that fails its probe), but START failed with
-ENXIO. PipeWire ignores that error and retries on every wakeup; any other error ends up in its recovery, which prepares and starts again. With mpv moved to the display output in pavucontrol it loggedsnd_pcm_start: No such device or address~45 times a second per stream, and after ~80 min (spa.alsa: hw:0p: impossible timeout) ~130000 times a second: 4.1 million lines in one boot and a busy core. Now, without a sink (or once the stream's sink is gone), START succeeds and the stream runs on the clock without DMA or a DCP audio link, its samples dropped, as HDMI PCMs elsewhere do. A stream playing into the void is not stopped as disconnected; a sink attached later is used by the next stream opened. This adds a minimalsync_stop; on top of drm: apple: audio: ask for audio elements like macOS, and balance runtime PM around the DMA stop #276, which adds one too, it reduces to onecancel_delayed_work_sync()there.drm: apple: reset the Type-C relink budget on every DPMS wake. The EIZO EV2780 on the Mac mini loses the link after the first modeset of every DPMS wake, not only after a hot-plug, and item 1 recovers it each time. But the three relinks were counted per connection, i.e. until the cable is replugged, so all wakes shared them: the 4th wake after a replug was handled as an unplug and the display stayed dark (seen in daily use: relinks 1/3, 2/3, 3/3 on three wakes, then dark). The limit is there to stop relink loops within one link bring-up, so
dcp_poweron()now resets it when the CRTC comes back from DPMS off. No relink can run while the CRTC is off.drm: apple: do not report a bad link for a powered-off Type-C CRTC. Since 57f9f36 ("drm/apple: fence EDID publication by service lifetime and unblock RX") the teardown of DCP's AV service schedules the connector hotplug worker. DCP tears that service down on every DPMS off, and
dcp_hotplug()then reported the link of the powered-off CRTC as bad, which wlroots answers on wake by replacing the output. There is no link while the CRTC is off anddcp_poweron()retrains one on wake, so the link status is left alone then; the EDID is still invalidated.drm: apple: update connector dimensions without a hotplug. The same commit also moved the dimension update for
DisplayAttributesto the hotplug worker. DCP sendsDisplayAttributeson every DPTX connect, which a Type-C DPMS wake does before its modeset, sodcp_hotplug()found the CRTC being enabled without a valid mode, replayed its state (a second modeset) and reported a bad link: on the current aurora-wip the display did not come back from the first DPMS off, and every round of wlroots replacing the output added DPTX reconnects until the system crawled. The dimensions now get a work item of their own, which does what the RX worker did before, outside it. External H17P keeps the hotplug worker.Rebased onto aurora-wip 27da3a5 (no conflicts). The DCP host selftests (
tools/testing/selftests/drivers/gpu/apple-dcp) get stubs for the new calls in their harnesses. On 5f6c917 52/52 passed at every commit of this PR. On 27da3a5 45/52 pass at the head of this PR, and the same 7 (oslog-events, service-rebind, provider-admission, parser-policy, publication-hpd, typec-probe, probe-mux-pm-dispatch) already fail on the base alone: the harnesses lack stubs fordev_dbg()andcd321x_display_taken(), added upstream.Testing
TimingElements without valid modes) first and recovered on the second relinksnd_pcm_starterrors/s per stream (~130000/s after ~80 min in daily use); with it: 0 errors on both outputs,aplayof 3 s takes 3.006 s, two streams for 30 s keep PipeWire at 1% CPU (tested on top of #276 + #277)snd_pcm_drop: File descriptor in bad stateand closes the device, no retry loop, PipeWire at ~0.1% CPU; HDMI playback runs again ~3 s after replug; USB-C sink comes back after replug, tone audible before unplugoutput DP-1 power off; sleep 20; power on; sleep 20in a loop (on top of #276 + #277 + #281)1/3), no kernel warnings. Needs wlroots not to fall back to the legacy gamma ioctl on CRTCs without gamma support, else sway'spower oncommit fails before reaching the kernel (separate wlroots fix)swaymsg output DP-1 power off/on1/3), no kernel warnings; a cable replug afterwards came up tooThe earlier test kernels exported
dwc3_event_buffers_cleanup()locally to build withCONFIG_USB_DWC3=yandCONFIG_USB_DWC3_APPLE=m; aurora-wip now does that itself (e87b71d).Also checked on the Air: a USB-C → HDMI adapter and a dock still work.