megi's PinePhone Development Log RSS

Genocide is bad

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:

Pinephone dock (and all my other docks with captive cable) reports 0×c05:

A dock with a Type-C receptacle with Alt-D support would report 0×c0045:

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:

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.