summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Broch <tbroch@chromium.org>2015-01-07 21:18:01 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-09 05:40:13 +0000
commita2720a0f68bbadfabdacfad3411175733c0c4098 (patch)
tree989f167a05b2db5d41a21db0df1cc6f0b47e0b90
parentccb46f6d8e9c141f22c9d9cfe25dfcd1d433e8a4 (diff)
downloadchrome-ec-a2720a0f68bbadfabdacfad3411175733c0c4098.tar.gz
pd: Queue initial DFP HPD till after DP Config VDM.
VESA DisplayPort Alt Mode on USB Type-C Standard specifies: When DisplayPort Configuration is not selected (and the converter is driving its HPD output low), the converter shall track the current state of HPD, ready for appropriate indication when DisplayPort Configuration is subsequently selected. Not only are we violating specification here but it also causes a race between enabling DPout muxes to AUX line which in turn causes GPU to timeout trying to read EDID/DPCD on occasion. Change adds post_config function for DFPs alternate mode and in the case of DP it sets the dp_on flag there. This allows attention function to correctly defer HPD_HI that may accompany 'DP status' VDM to be queued (deferred) until such time that AUX muxes are enabled properly. Signed-off-by: Todd Broch <tbroch@chromium.org> BRANCH=samus BUG=chrome-os-partner:35219 TEST=manual, using hoho & dingdong With kernel bootarg drm.debug=0x6 following cases all show these drm debug lines: [drm:i915_hotplug_work_func], Connector DP-2 (pin 5) received hotplug event. [drm:intel_dp_get_dpcd], DPCD: 12 14 c4 01 01 00 01 00 02 02 06 00 00 00 00 [drm:intel_hpd_irq_event], [CONNECTOR:38:DP-2] status updated from disconnected to connected case1: boot connected to external display case2: attach dongle to external display then samus case3: attach dongle to samus then to external display case4: connect/disconnect rapidly on type-C side case5: connect/disconnect rapidly on external display side. Change-Id: I40eab797fdd5090c8ad13fae2cd053b740d9a307 Reviewed-on: https://chromium-review.googlesource.com/239420 Trybot-Ready: Todd Broch <tbroch@chromium.org> Tested-by: Todd Broch <tbroch@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Commit-Queue: Todd Broch <tbroch@chromium.org>
-rw-r--r--board/samus_pd/usb_pd_policy.c32
-rw-r--r--common/usb_pd_policy.c3
-rw-r--r--include/usb_pd.h5
3 files changed, 35 insertions, 5 deletions
diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c
index 8ba4d7a327..ca16c5759d 100644
--- a/board/samus_pd/usb_pd_policy.c
+++ b/board/samus_pd/usb_pd_policy.c
@@ -17,6 +17,7 @@
#include "timer.h"
#include "util.h"
#include "usb_pd.h"
+#include "usb_pd_config.h"
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
@@ -215,10 +216,13 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload,
return 0;
}
+static int dp_flags[PD_PORT_COUNT];
+
static void svdm_safe_dp_mode(int port)
{
/* make DP interface safe until configure */
board_set_usb_mux(port, TYPEC_MUX_NONE, pd_get_polarity(port));
+ dp_flags[port] = 0;
}
static int svdm_enter_dp_mode(int port, uint32_t mode_caps)
@@ -232,8 +236,6 @@ static int svdm_enter_dp_mode(int port, uint32_t mode_caps)
return -1;
}
-static int dp_on;
-
static int svdm_dp_status(int port, uint32_t *payload)
{
payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
@@ -243,16 +245,15 @@ static int svdm_dp_status(int port, uint32_t *payload)
0, /* exit DP? ... no */
0, /* usb mode? ... no */
0, /* multi-function ... no */
- dp_on,
+ (!!(dp_flags[port] & DP_FLAGS_DP_ON)),
0, /* power low? ... no */
- dp_on);
+ (!!(dp_flags[port] & DP_FLAGS_DP_ON)));
return 2;
};
static int svdm_dp_config(int port, uint32_t *payload)
{
board_set_usb_mux(port, TYPEC_MUX_DP, pd_get_polarity(port));
- dp_on = 1;
payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
CMD_DP_CONFIG | VDO_OPOS(pd_alt_mode(port)));
payload[1] = VDO_DP_CFG(MODE_DP_PIN_E, /* sink pins */
@@ -262,6 +263,18 @@ static int svdm_dp_config(int port, uint32_t *payload)
return 2;
};
+static void svdm_dp_post_config(int port)
+{
+ dp_flags[port] |= DP_FLAGS_DP_ON;
+ if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING))
+ return;
+
+ if (port)
+ gpio_set_level(GPIO_USB_C1_DP_HPD, 1);
+ else
+ gpio_set_level(GPIO_USB_C0_DP_HPD, 1);
+}
+
static void hpd0_irq_deferred(void)
{
gpio_set_level(GPIO_USB_C0_DP_HPD, 1);
@@ -284,6 +297,14 @@ static int svdm_dp_attention(int port, uint32_t *payload)
int irq = PD_VDO_HPD_IRQ(payload[1]);
enum gpio_signal hpd = PORT_TO_HPD(port);
cur_lvl = gpio_get_level(hpd);
+
+ /* Its initial DP status message prior to config */
+ if (!(dp_flags[port] & DP_FLAGS_DP_ON)) {
+ if (lvl)
+ dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING;
+ return 1;
+ }
+
if (irq & cur_lvl) {
gpio_set_level(hpd, 0);
/* 250 usecs is minimum, 2msec is max */
@@ -343,6 +364,7 @@ const struct svdm_amode_fx supported_modes[] = {
.enter = &svdm_enter_dp_mode,
.status = &svdm_dp_status,
.config = &svdm_dp_config,
+ .post_config = &svdm_dp_post_config,
.attention = &svdm_dp_attention,
.exit = &svdm_exit_dp_mode,
},
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index b9ac431d58..05c9363de8 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -509,6 +509,9 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
rsize = 0;
break;
case CMD_DP_CONFIG:
+ if (AMODE_VALID(port) &&
+ pe[port].amode.fx->post_config)
+ pe[port].amode.fx->post_config(port);
/* no response after DFPs ack */
rsize = 0;
break;
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 8e7fac1c66..7220f74d7d 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -176,6 +176,7 @@ struct svdm_amode_fx {
int (*enter)(int port, uint32_t mode_caps);
int (*status)(int port, uint32_t *payload);
int (*config)(int port, uint32_t *payload);
+ void (*post_config)(int port);
int (*attention)(int port, uint32_t *payload);
void (*exit)(int port);
};
@@ -200,6 +201,10 @@ enum hpd_event {
hpd_irq,
};
+/* DisplayPort flags */
+#define DP_FLAGS_DP_ON (1 << 0) /* Display port mode is on */
+#define DP_FLAGS_HPD_HI_PENDING (1 << 1) /* Pending HPD_HI */
+
/* Policy structure for driving alternate mode */
struct pd_policy {
/* index of svid currently being operated on */