usb: typec: altmodes: displayport: Fix pin assignment

Fix pin-assignment as per specification.

Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
Signed-off-by: Wang Jie <dave.wang@rock-chips.com>
Change-Id: Iad7e211e43ebc01607ae534b56666ec56da2f54b
(cherry picked from commit b3e060dc22)
This commit is contained in:
Wyon Bi
2021-07-26 16:19:07 +08:00
committed by Tao Huang
parent c0878f6c38
commit 8a4e79051b

View File

@@ -48,6 +48,17 @@ enum {
BIT(DP_PIN_ASSIGN_D) | \
BIT(DP_PIN_ASSIGN_F))
/*
* A UFP_U that uses a USB Type-C plug describes the pin assignments supported
* for the corresponding receptacle. (i.e., a UFP_D will describe the DFP_D pin
* assignments to which it connects), whereas a UFP_U that uses a USB Type-C
* receptacle describes its pin assignments directly (i.e., a UFP_D will
* describe its own UFP_D pin assignments).
*/
#define DP_CAP_PIN_ASSIGN(_cap_) (((_cap_) & DP_CAP_RECEPTACLE) ? \
DP_CAP_UFP_D_PIN_ASSIGN(_cap_) : \
DP_CAP_DFP_D_PIN_ASSIGN(_cap_))
enum dp_state {
DP_STATE_IDLE,
DP_STATE_ENTER,
@@ -85,14 +96,10 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
return 0;
case DP_STATUS_CON_DFP_D:
conf |= DP_CONF_UFP_U_AS_DFP_D;
pin_assign = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo) &
DP_CAP_DFP_D_PIN_ASSIGN(dp->port->vdo);
break;
case DP_STATUS_CON_UFP_D:
case DP_STATUS_CON_BOTH: /* NOTE: First acting as DP source */
conf |= DP_CONF_UFP_U_AS_UFP_D;
pin_assign = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo) &
DP_CAP_UFP_D_PIN_ASSIGN(dp->port->vdo);
break;
default:
break;
@@ -100,6 +107,8 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
/* Determining the initial pin assignment. */
if (!DP_CONF_GET_PIN_ASSIGN(dp->data.conf)) {
pin_assign = DP_CAP_PIN_ASSIGN(dp->alt->vdo);
/* Is USB together with DP preferred */
if (dp->data.status & DP_STATUS_PREFER_MULTI_FUNC &&
pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK)
@@ -107,6 +116,13 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
else
pin_assign &= DP_PIN_ASSIGN_DP_ONLY_MASK;
/*
* DFP_U never selects Pin Assignment E when Pin Assignment C
* and possibly Pin Assignment D are offered by the UFP_U.
*/
if (pin_assign & (BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D)))
pin_assign &= ~BIT(DP_PIN_ASSIGN_E);
if (!pin_assign)
return -EINVAL;
@@ -437,10 +453,7 @@ pin_assignment_store(struct device *dev, struct device_attribute *attr,
goto out_unlock;
}
if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D)
assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo);
else
assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo);
assignments = DP_CAP_PIN_ASSIGN(dp->alt->vdo);
if (!(DP_CONF_GET_PIN_ASSIGN(conf) & assignments)) {
ret = -EINVAL;
@@ -477,10 +490,7 @@ static ssize_t pin_assignment_show(struct device *dev,
cur = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D)
assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo);
else
assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo);
assignments = DP_CAP_PIN_ASSIGN(dp->alt->vdo);
for (i = 0; assignments; assignments >>= 1, i++) {
if (assignments & 1) {