mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user