diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5f97c1751ff..bca48b05520 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1012,21 +1012,23 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) } /* - * Fetch AUX CH registers 0x202 - 0x207 which contain - * link status information + * Native read with retry for link status and receiver capability reads for + * cases where the sink may still be asleep. */ static bool -intel_dp_get_link_status(struct intel_dp *intel_dp) +intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address, + uint8_t *recv, int recv_bytes) { int ret, i; - /* Must try AUX reads for this at least 3 times */ + /* + * Sinks are *supposed* to come up within 1ms from an off state, + * but we're also supposed to retry 3 times per the spec. + */ for (i = 0; i < 3; i++) { - ret = intel_dp_aux_native_read(intel_dp, - DP_LANE0_1_STATUS, - intel_dp->link_status, - DP_LINK_STATUS_SIZE); - if (ret == DP_LINK_STATUS_SIZE) + ret = intel_dp_aux_native_read(intel_dp, address, recv, + recv_bytes); + if (ret == recv_bytes) return true; msleep(1); } @@ -1034,6 +1036,19 @@ intel_dp_get_link_status(struct intel_dp *intel_dp) return false; } +/* + * Fetch AUX CH registers 0x202 - 0x207 which contain + * link status information + */ +static bool +intel_dp_get_link_status(struct intel_dp *intel_dp) +{ + return intel_dp_aux_native_read_retry(intel_dp, + DP_LANE0_1_STATUS, + intel_dp->link_status, + DP_LINK_STATUS_SIZE); +} + static uint8_t intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int r) @@ -1549,7 +1564,7 @@ static enum drm_connector_status ironlake_dp_detect(struct intel_dp *intel_dp) { enum drm_connector_status status; - int ret, i; + bool ret; /* Can't disconnect eDP, but you can close the lid... */ if (is_edp(intel_dp)) { @@ -1560,17 +1575,11 @@ ironlake_dp_detect(struct intel_dp *intel_dp) } status = connector_status_disconnected; - for (i = 0; i < 3; i++) { - ret = intel_dp_aux_native_read(intel_dp, - 0x000, intel_dp->dpcd, - sizeof (intel_dp->dpcd)); - if (ret == sizeof(intel_dp->dpcd) && - intel_dp->dpcd[DP_DPCD_REV] != 0) { - status = connector_status_connected; - break; - } - msleep(1); - } + ret = intel_dp_aux_native_read_retry(intel_dp, + 0x000, intel_dp->dpcd, + sizeof (intel_dp->dpcd)); + if (ret && intel_dp->dpcd[DP_DPCD_REV] != 0) + status = connector_status_connected; DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0], intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]); return status; |