usb: typec: Add driver for DisplayPort alternate mode

DisplayPort USB Type-C Alt Mode allows DisplayPort displays
and adapters to be attached to the USB Type-C ports on the
system.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Heikki Krogerus 2018-06-27 18:19:51 +03:00 committed by Greg Kroah-Hartman
parent 8a37d87d72
commit 0e3bb7d689
7 changed files with 741 additions and 0 deletions

View File

@ -0,0 +1,49 @@
What: /sys/bus/typec/devices/.../displayport/configuration
Date: July 2018
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Shows the current DisplayPort configuration for the connector.
Valid values are USB, source and sink. Source means DisplayPort
source, and sink means DisplayPort sink.
All supported configurations are listed as space separated list
with the active one wrapped in square brackets.
Source example:
USB [source] sink
The configuration can be changed by writing to the file
Note. USB configuration does not equal to Exit Mode. It is
separate configuration defined in VESA DisplayPort Alt Mode on
USB Type-C Standard. Functionally it equals to the situation
where the mode has been exited (to exit the mode, see
Documentation/ABI/testing/sysfs-bus-typec, and use file
/sys/bus/typec/devices/.../active).
What: /sys/bus/typec/devices/.../displayport/pin_assignment
Date: July 2018
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
VESA DisplayPort Alt Mode on USB Type-C Standard defines six
different pin assignments for USB Type-C connector that are
labeled A, B, C, D, E, and F. The supported pin assignments are
listed as space separated list with the active one wrapped in
square brackets.
Example:
C [D]
Pin assignment can be changed by writing to the file. It is
possible to set pin assignment before configuration has been
set, but the assignment will not be active before the
connector is actually configured.
Note. As of VESA DisplayPort Alt Mode on USB Type-C Standard
version 1.0b, pin assignments A, B, and F are deprecated. Only
pin assignment D can now carry simultaneously one channel of
USB SuperSpeed protocol. From user perspective pin assignments C
and E are equal, where all channels on the connector are used
for carrying DisplayPort protocol (allowing higher resolutions).

View File

@ -104,4 +104,6 @@ config TYPEC_TPS6598X
source "drivers/usb/typec/mux/Kconfig"
source "drivers/usb/typec/altmodes/Kconfig"
endif # TYPEC

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_TYPEC) += typec.o
typec-y := class.o mux.o bus.o
obj-$(CONFIG_TYPEC) += altmodes/
obj-$(CONFIG_TYPEC_TCPM) += tcpm.o
obj-y += fusb302/
obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o

View File

@ -0,0 +1,14 @@
menu "USB Type-C Alternate Mode drivers"
config TYPEC_DP_ALTMODE
tristate "DisplayPort Alternate Mode driver"
help
DisplayPort USB Type-C Alternate Mode allows DisplayPort
displays and adapters to be attached to the USB Type-C
connectors on the system.
To compile this driver as a module, choose M here: the
module will be called typec_displayport.
endmenu

View File

@ -0,0 +1,2 @@
obj-$(CONFIG_TYPEC_DP_ALTMODE) += typec_displayport.o
typec_displayport-y := displayport.o

View File

@ -0,0 +1,578 @@
// SPDX-License-Identifier: GPL-2.0
/**
* USB Typec-C DisplayPort Alternate Mode driver
*
* Copyright (C) 2018 Intel Corporation
* Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
*
* DisplayPort is trademark of VESA (www.vesa.org)
*/
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/usb/pd_vdo.h>
#include <linux/usb/typec_dp.h>
#define DP_HEADER(cmd) (VDO(USB_TYPEC_DP_SID, 1, cmd) | \
VDO_OPOS(USB_TYPEC_DP_MODE))
enum {
DP_CONF_USB,
DP_CONF_DFP_D,
DP_CONF_UFP_D,
DP_CONF_DUAL_D,
};
/* Helper for setting/getting the pin assignement value to the configuration */
#define DP_CONF_SET_PIN_ASSIGN(_a_) ((_a_) << 8)
#define DP_CONF_GET_PIN_ASSIGN(_conf_) (((_conf_) & GENMASK(15, 8)) >> 8)
/* Pin assignments that use USB3.1 Gen2 signaling to carry DP protocol */
#define DP_PIN_ASSIGN_GEN2_BR_MASK (BIT(DP_PIN_ASSIGN_A) | \
BIT(DP_PIN_ASSIGN_B))
/* Pin assignments that use DP v1.3 signaling to carry DP protocol */
#define DP_PIN_ASSIGN_DP_BR_MASK (BIT(DP_PIN_ASSIGN_C) | \
BIT(DP_PIN_ASSIGN_D) | \
BIT(DP_PIN_ASSIGN_E) | \
BIT(DP_PIN_ASSIGN_F))
/* DP only pin assignments */
#define DP_PIN_ASSIGN_DP_ONLY_MASK (BIT(DP_PIN_ASSIGN_A) | \
BIT(DP_PIN_ASSIGN_C) | \
BIT(DP_PIN_ASSIGN_E))
/* Pin assignments where one channel is for USB */
#define DP_PIN_ASSIGN_MULTI_FUNC_MASK (BIT(DP_PIN_ASSIGN_B) | \
BIT(DP_PIN_ASSIGN_D) | \
BIT(DP_PIN_ASSIGN_F))
enum dp_state {
DP_STATE_IDLE,
DP_STATE_ENTER,
DP_STATE_UPDATE,
DP_STATE_CONFIGURE,
DP_STATE_EXIT,
};
struct dp_altmode {
struct typec_displayport_data data;
enum dp_state state;
struct mutex lock; /* device lock */
struct work_struct work;
struct typec_altmode *alt;
const struct typec_altmode *port;
};
static int dp_altmode_notify(struct dp_altmode *dp)
{
u8 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
return typec_altmode_notify(dp->alt, TYPEC_MODAL_STATE(state),
&dp->data);
}
static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
{
u32 conf = DP_CONF_SIGNALING_DP; /* Only DP signaling supported */
u8 pin_assign = 0;
switch (con) {
case DP_STATUS_CON_DISABLED:
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;
}
/* Determining the initial pin assignment. */
if (!DP_CONF_GET_PIN_ASSIGN(dp->data.conf)) {
/* Is USB together with DP preferred */
if (dp->data.status & DP_STATUS_PREFER_MULTI_FUNC &&
pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK)
pin_assign &= DP_PIN_ASSIGN_MULTI_FUNC_MASK;
else
pin_assign &= DP_PIN_ASSIGN_DP_ONLY_MASK;
if (!pin_assign)
return -EINVAL;
conf |= DP_CONF_SET_PIN_ASSIGN(pin_assign);
}
dp->data.conf = conf;
return 0;
}
static int dp_altmode_status_update(struct dp_altmode *dp)
{
bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
u8 con = DP_STATUS_CONNECTION(dp->data.status);
int ret = 0;
if (configured && (dp->data.status & DP_STATUS_SWITCH_TO_USB)) {
dp->data.conf = 0;
dp->state = DP_STATE_CONFIGURE;
} else if (dp->data.status & DP_STATUS_EXIT_DP_MODE) {
dp->state = DP_STATE_EXIT;
} else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) {
ret = dp_altmode_configure(dp, con);
if (!ret)
dp->state = DP_STATE_CONFIGURE;
}
return ret;
}
static int dp_altmode_configured(struct dp_altmode *dp)
{
int ret;
sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
if (!dp->data.conf)
return typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
&dp->data);
ret = dp_altmode_notify(dp);
if (ret)
return ret;
sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
return 0;
}
static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)
{
u32 header = DP_HEADER(DP_CMD_CONFIGURE);
int ret;
ret = typec_altmode_notify(dp->alt, TYPEC_STATE_SAFE, &dp->data);
if (ret) {
dev_err(&dp->alt->dev,
"unable to put to connector to safe mode\n");
return ret;
}
ret = typec_altmode_vdm(dp->alt, header, &conf, 2);
if (ret) {
if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf))
dp_altmode_notify(dp);
else
typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
&dp->data);
}
return ret;
}
static void dp_altmode_work(struct work_struct *work)
{
struct dp_altmode *dp = container_of(work, struct dp_altmode, work);
u32 header;
u32 vdo;
int ret;
mutex_lock(&dp->lock);
switch (dp->state) {
case DP_STATE_ENTER:
ret = typec_altmode_enter(dp->alt);
if (ret)
dev_err(&dp->alt->dev, "failed to enter mode\n");
break;
case DP_STATE_UPDATE:
header = DP_HEADER(DP_CMD_STATUS_UPDATE);
vdo = 1;
ret = typec_altmode_vdm(dp->alt, header, &vdo, 2);
if (ret)
dev_err(&dp->alt->dev,
"unable to send Status Update command (%d)\n",
ret);
break;
case DP_STATE_CONFIGURE:
ret = dp_altmode_configure_vdm(dp, dp->data.conf);
if (ret)
dev_err(&dp->alt->dev,
"unable to send Configure command (%d)\n", ret);
break;
case DP_STATE_EXIT:
if (typec_altmode_exit(dp->alt))
dev_err(&dp->alt->dev, "Exit Mode Failed!\n");
break;
default:
break;
}
dp->state = DP_STATE_IDLE;
mutex_unlock(&dp->lock);
}
static void dp_altmode_attention(struct typec_altmode *alt, const u32 vdo)
{
struct dp_altmode *dp = typec_altmode_get_drvdata(alt);
u8 old_state;
mutex_lock(&dp->lock);
old_state = dp->state;
dp->data.status = vdo;
if (old_state != DP_STATE_IDLE)
dev_warn(&alt->dev, "ATTENTION while processing state %d\n",
old_state);
if (dp_altmode_status_update(dp))
dev_warn(&alt->dev, "%s: status update failed\n", __func__);
if (dp_altmode_notify(dp))
dev_err(&alt->dev, "%s: notification failed\n", __func__);
if (old_state == DP_STATE_IDLE && dp->state != DP_STATE_IDLE)
schedule_work(&dp->work);
mutex_unlock(&dp->lock);
}
static int dp_altmode_vdm(struct typec_altmode *alt,
const u32 hdr, const u32 *vdo, int count)
{
struct dp_altmode *dp = typec_altmode_get_drvdata(alt);
int cmd_type = PD_VDO_CMDT(hdr);
int cmd = PD_VDO_CMD(hdr);
int ret = 0;
mutex_lock(&dp->lock);
if (dp->state != DP_STATE_IDLE) {
ret = -EBUSY;
goto err_unlock;
}
switch (cmd_type) {
case CMDT_RSP_ACK:
switch (cmd) {
case CMD_ENTER_MODE:
dp->state = DP_STATE_UPDATE;
break;
case CMD_EXIT_MODE:
dp->data.status = 0;
dp->data.conf = 0;
break;
case DP_CMD_STATUS_UPDATE:
dp->data.status = *vdo;
ret = dp_altmode_status_update(dp);
break;
case DP_CMD_CONFIGURE:
ret = dp_altmode_configured(dp);
break;
default:
break;
}
break;
case CMDT_RSP_NAK:
switch (cmd) {
case DP_CMD_CONFIGURE:
dp->data.conf = 0;
ret = dp_altmode_configured(dp);
break;
default:
break;
}
break;
default:
break;
}
if (dp->state != DP_STATE_IDLE)
schedule_work(&dp->work);
err_unlock:
mutex_unlock(&dp->lock);
return ret;
}
static int dp_altmode_activate(struct typec_altmode *alt, int activate)
{
return activate ? typec_altmode_enter(alt) : typec_altmode_exit(alt);
}
static const struct typec_altmode_ops dp_altmode_ops = {
.attention = dp_altmode_attention,
.vdm = dp_altmode_vdm,
.activate = dp_altmode_activate,
};
static const char * const configurations[] = {
[DP_CONF_USB] = "USB",
[DP_CONF_DFP_D] = "source",
[DP_CONF_UFP_D] = "sink",
};
static ssize_t
configuration_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
{
struct dp_altmode *dp = dev_get_drvdata(dev);
u32 conf;
u32 cap;
int con;
int ret;
con = sysfs_match_string(configurations, buf);
if (con < 0)
return con;
mutex_lock(&dp->lock);
if (dp->state != DP_STATE_IDLE) {
ret = -EBUSY;
goto err_unlock;
}
cap = DP_CAP_CAPABILITY(dp->alt->vdo);
if ((con == DP_CONF_DFP_D && !(cap & DP_CAP_DFP_D)) ||
(con == DP_CONF_UFP_D && !(cap & DP_CAP_UFP_D)))
return -EINVAL;
conf = dp->data.conf & ~DP_CONF_DUAL_D;
conf |= con;
if (dp->alt->active) {
ret = dp_altmode_configure_vdm(dp, conf);
if (ret)
goto err_unlock;
}
dp->data.conf = conf;
err_unlock:
mutex_unlock(&dp->lock);
return ret ? ret : size;
}
static ssize_t configuration_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dp_altmode *dp = dev_get_drvdata(dev);
int len;
u8 cap;
u8 cur;
int i;
mutex_lock(&dp->lock);
cap = DP_CAP_CAPABILITY(dp->alt->vdo);
cur = DP_CONF_CURRENTLY(dp->data.conf);
len = sprintf(buf, "%s ", cur ? "USB" : "[USB]");
for (i = 1; i < ARRAY_SIZE(configurations); i++) {
if (i == cur)
len += sprintf(buf + len, "[%s] ", configurations[i]);
else if ((i == DP_CONF_DFP_D && cap & DP_CAP_DFP_D) ||
(i == DP_CONF_UFP_D && cap & DP_CAP_UFP_D))
len += sprintf(buf + len, "%s ", configurations[i]);
}
mutex_unlock(&dp->lock);
buf[len - 1] = '\n';
return len;
}
static DEVICE_ATTR_RW(configuration);
static const char * const pin_assignments[] = {
[DP_PIN_ASSIGN_A] = "A",
[DP_PIN_ASSIGN_B] = "B",
[DP_PIN_ASSIGN_C] = "C",
[DP_PIN_ASSIGN_D] = "D",
[DP_PIN_ASSIGN_E] = "E",
[DP_PIN_ASSIGN_F] = "F",
};
static ssize_t
pin_assignment_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
{
struct dp_altmode *dp = dev_get_drvdata(dev);
u8 assignments;
u32 conf;
int ret;
ret = sysfs_match_string(pin_assignments, buf);
if (ret < 0)
return ret;
conf = DP_CONF_SET_PIN_ASSIGN(BIT(ret));
ret = 0;
mutex_lock(&dp->lock);
if (conf & dp->data.conf)
goto out_unlock;
if (dp->state != DP_STATE_IDLE) {
ret = -EBUSY;
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);
if (!(DP_CONF_GET_PIN_ASSIGN(conf) & assignments)) {
ret = -EINVAL;
goto out_unlock;
}
conf |= dp->data.conf & ~DP_CONF_PIN_ASSIGNEMENT_MASK;
/* Only send Configure command if a configuration has been set */
if (dp->alt->active && DP_CONF_CURRENTLY(dp->data.conf)) {
ret = dp_altmode_configure_vdm(dp, conf);
if (ret)
goto out_unlock;
}
dp->data.conf = conf;
out_unlock:
mutex_unlock(&dp->lock);
return ret ? ret : size;
}
static ssize_t pin_assignment_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dp_altmode *dp = dev_get_drvdata(dev);
u8 assignments;
int len = 0;
u8 cur;
int i;
mutex_lock(&dp->lock);
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);
for (i = 0; assignments; assignments >>= 1, i++) {
if (assignments & 1) {
if (i == cur)
len += sprintf(buf + len, "[%s] ",
pin_assignments[i]);
else
len += sprintf(buf + len, "%s ",
pin_assignments[i]);
}
}
mutex_unlock(&dp->lock);
buf[len - 1] = '\n';
return len;
}
static DEVICE_ATTR_RW(pin_assignment);
static struct attribute *dp_altmode_attrs[] = {
&dev_attr_configuration.attr,
&dev_attr_pin_assignment.attr,
NULL
};
static const struct attribute_group dp_altmode_group = {
.name = "displayport",
.attrs = dp_altmode_attrs,
};
static int dp_altmode_probe(struct typec_altmode *alt)
{
const struct typec_altmode *port = typec_altmode_get_partner(alt);
struct dp_altmode *dp;
int ret;
/* FIXME: Port can only be DFP_U. */
/* Make sure we have compatiple pin configurations */
if (!(DP_CAP_DFP_D_PIN_ASSIGN(port->vdo) &
DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo)) &&
!(DP_CAP_UFP_D_PIN_ASSIGN(port->vdo) &
DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo)))
return -ENODEV;
ret = sysfs_create_group(&alt->dev.kobj, &dp_altmode_group);
if (ret)
return ret;
dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL);
if (!dp)
return -ENOMEM;
INIT_WORK(&dp->work, dp_altmode_work);
mutex_init(&dp->lock);
dp->port = port;
dp->alt = alt;
alt->desc = "DisplayPort";
alt->ops = &dp_altmode_ops;
typec_altmode_set_drvdata(alt, dp);
dp->state = DP_STATE_ENTER;
schedule_work(&dp->work);
return 0;
}
static void dp_altmode_remove(struct typec_altmode *alt)
{
struct dp_altmode *dp = typec_altmode_get_drvdata(alt);
sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
cancel_work_sync(&dp->work);
}
static const struct typec_device_id dp_typec_id[] = {
{ USB_TYPEC_DP_SID, USB_TYPEC_DP_MODE },
{ },
};
MODULE_DEVICE_TABLE(typec, dp_typec_id);
static struct typec_altmode_driver dp_altmode_driver = {
.id_table = dp_typec_id,
.probe = dp_altmode_probe,
.remove = dp_altmode_remove,
.driver = {
.name = "typec_displayport",
.owner = THIS_MODULE,
},
};
module_typec_altmode_driver(dp_altmode_driver);
MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DisplayPort Alternate Mode");

View File

@ -0,0 +1,95 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __USB_TYPEC_DP_H
#define __USB_TYPEC_DP_H
#include <linux/usb/typec_altmode.h>
#define USB_TYPEC_DP_SID 0xff01
#define USB_TYPEC_DP_MODE 1
/*
* Connector states matching the pin assignments in DisplayPort Alt Mode
* Specification.
*
* These values are meant primarily to be used by the mux drivers, but they are
* also used as the "value" part in the alternate mode notification chain, so
* receivers of those notifications will always see them.
*
* Note. DisplayPort USB Type-C Alt Mode Specification version 1.0b deprecated
* pin assignments A, B and F, but they are still defined here for legacy
* purposes.
*/
enum {
TYPEC_DP_STATE_A = TYPEC_STATE_MODAL, /* Not supported after v1.0b */
TYPEC_DP_STATE_B, /* Not supported after v1.0b */
TYPEC_DP_STATE_C,
TYPEC_DP_STATE_D,
TYPEC_DP_STATE_E,
TYPEC_DP_STATE_F, /* Not supported after v1.0b */
};
/*
* struct typec_displayport_data - DisplayPort Alt Mode specific data
* @status: Status Update command VDO content
* @conf: Configure command VDO content
*
* This structure is delivered as the data part with the notifications. It
* contains the VDOs from the two DisplayPort Type-C alternate mode specific
* commands: Status Update and Configure.
*
* @status will show for example the status of the HPD signal.
*/
struct typec_displayport_data {
u32 status;
u32 conf;
};
enum {
DP_PIN_ASSIGN_A, /* Not supported after v1.0b */
DP_PIN_ASSIGN_B, /* Not supported after v1.0b */
DP_PIN_ASSIGN_C,
DP_PIN_ASSIGN_D,
DP_PIN_ASSIGN_E,
DP_PIN_ASSIGN_F, /* Not supported after v1.0b */
};
/* DisplayPort alt mode specific commands */
#define DP_CMD_STATUS_UPDATE VDO_CMD_VENDOR(0)
#define DP_CMD_CONFIGURE VDO_CMD_VENDOR(1)
/* DisplayPort Capabilities VDO bits (returned with Discover Modes) */
#define DP_CAP_CAPABILITY(_cap_) ((_cap_) & 3)
#define DP_CAP_UFP_D 1
#define DP_CAP_DFP_D 2
#define DP_CAP_DFP_D_AND_UFP_D 3
#define DP_CAP_DP_SIGNALING BIT(2) /* Always set */
#define DP_CAP_GEN2 BIT(3) /* Reserved after v1.0b */
#define DP_CAP_RECEPTACLE BIT(6)
#define DP_CAP_USB BIT(7)
#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)
/* DisplayPort Status Update VDO bits */
#define DP_STATUS_CONNECTION(_status_) ((_status_) & 3)
#define DP_STATUS_CON_DISABLED 0
#define DP_STATUS_CON_DFP_D 1
#define DP_STATUS_CON_UFP_D 2
#define DP_STATUS_CON_BOTH 3
#define DP_STATUS_POWER_LOW BIT(2)
#define DP_STATUS_ENABLED BIT(3)
#define DP_STATUS_PREFER_MULTI_FUNC BIT(4)
#define DP_STATUS_SWITCH_TO_USB BIT(5)
#define DP_STATUS_EXIT_DP_MODE BIT(6)
#define DP_STATUS_HPD_STATE BIT(7) /* 0 = HPD_Low, 1 = HPD_High */
#define DP_STATUS_IRQ_HPD BIT(8)
/* DisplayPort Configurations VDO bits */
#define DP_CONF_CURRENTLY(_conf_) ((_conf_) & 3)
#define DP_CONF_UFP_U_AS_DFP_D BIT(0)
#define DP_CONF_UFP_U_AS_UFP_D BIT(1)
#define DP_CONF_SIGNALING_DP BIT(2)
#define DP_CONF_SIGNALING_GEN_2 BIT(3) /* Reserved after v1.0b */
#define DP_CONF_PIN_ASSIGNEMENT_SHIFT 8
#define DP_CONF_PIN_ASSIGNEMENT_MASK GENMASK(15, 8)
#endif /* __USB_TYPEC_DP_H */