2022–03–21:
Some finer points about Alt-DP support in mainline kernel
Docks that support Alt-DP come in two flavors. With Alt-DP present either on
a Type-C receptacle
or on a plug (with a captive cable like the Pine
dock). Pinephone just has a receptacle.
Each port supporting Alt-DP communicates its type via a VDO that is
communicated using USB-PD protocol. VDO is a 32bit value where each bit has some meaning.
Pinephone Pro's VDO should be 0×c46:
- DFP_D-capable
- Supports DP v1.3 signaling rates and electrical specification
- DisplayPort interface is presented on a USB Type-C Receptacle
- DFP_D pin assignments supported:
- pin assignment C and D is supported
- UFP_D pin assignments supported:
Pinephone dock (and all my other docks with captive cable) reports
0×c05:
- UFP_D-capable
- Supports DP v1.3 signaling rates and electrical specification
- DisplayPort interface is presented on a USB Type-C plug
- UFP_D pin assignments supported:
- pin assignment C and D is supported
- DFP_D pin assignments supported:
A dock with a Type-C receptacle with Alt-D support would report
0×c0045:
- UFP_D-capable
- Supports DP v1.3 signaling rates and electrical specification
- DisplayPort interface is presented on a USB Type-C Receptacle
- UFP_D pin assignments supported:
- pin assignment C and D is supported
- DFP_D pin assignments supported:
Now all this information is retrieved by the TCPM driver and passed to the usb/typec/altmodes/displayport.c
driver for processing.
All these VDOs from Pinephone and from the connected dock should be compared
against each other to figure out whether the current connection satisfies one of
these valid combinations:
- When both ends of the connection are receptacles, valid connection must have
one DFP_D (DisplayPort source, such as a computer) and one UFP_D (DisplayPort
sink, such as a monitor).
- When one end of the connection is a plug and the other is a receptacle, a
valid connection is either a DFP_D plug connected to a DFP_D receptacle or a
UFP_D plug connected to a UFP_D receptacle.
The code has to figure out whether both ports share one of the supported pin
assignments and properly pass the selected assignments down the stack.
This is the current check in the code:
531 /* Make sure we have compatiple pin configurations */
532 if (!(DP_CAP_DFP_D_PIN_ASSIGN(port->vdo) &
533 DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo)) &&
534 !(DP_CAP_UFP_D_PIN_ASSIGN(port->vdo) &
535 DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo)))
536 return -ENODEV;
#define DP_CAP_DFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(15, 8)) >> 8)
#define DP_CAP_UFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(23, 16)) >> 16)
It succeeds if there is at least one shared pin assignment option between
bits 15:8 and 23:16 on either VDO. This is a valid check for
receptacle<->receptacle combination.
For receptacle<->plug combination this check is not valid, because when
bit DP_CAP_RECEPTACLE
is 0, DP_CAP_UFP_D_PIN_ASSIGN
and DP_CAP_DFP_D_PIN_ASSIGN
swap their meanings.
So it looks like mainline code doesn't support Pinephone convergence dock at
all. The only reason this check passes in my kernel is because I've set this VDO
value in device tree (workaround to make the check pass, without fixing the
mainline code):
altmodes {
dp {
svid = <0xff01>;
vdo = <0x0c0046>;
};
};
Instead of using proper one according to the spec. :)
Of course what happened is that someone bought a dock with a receptacle and
reported to me that it doesn't work. It is detected properly, but Alt-DP mode is
not entered because no valid combination of pin assignments is found.
Time for a proper fix.