From 3f43c48d333777e815ae68d66396cb6dfbc2dd79 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 12 May 2011 22:17:24 +0100 Subject: drm/i915: Share the common force-audio property between connectors Make the audio property creation routine common and share the single property between the connectors. Signed-off-by: Chris Wilson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a4d80314e7f8..391b55f1cc74 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -59,8 +59,6 @@ struct intel_dp { bool is_pch_edp; uint8_t train_set[4]; uint8_t link_status[DP_LINK_STATUS_SIZE]; - - struct drm_property *force_audio_property; }; /** @@ -1702,7 +1700,7 @@ intel_dp_set_property(struct drm_connector *connector, if (ret) return ret; - if (property == intel_dp->force_audio_property) { + if (property == dev_priv->force_audio_property) { int i = val; bool has_audio; @@ -1841,16 +1839,7 @@ bool intel_dpd_is_edp(struct drm_device *dev) static void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - - intel_dp->force_audio_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2); - if (intel_dp->force_audio_property) { - intel_dp->force_audio_property->values[0] = -1; - intel_dp->force_audio_property->values[1] = 1; - drm_connector_attach_property(connector, intel_dp->force_audio_property, 0); - } - + intel_attach_force_audio_property(connector); intel_attach_broadcast_rgb_property(connector); } -- cgit v1.2.3 From 858fa03527ded333dc5701f546bd5d1b5d7515ad Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 24 Jun 2011 12:19:24 -0700 Subject: drm/i915: use pipe bpp in DP link bandwidth calculations The pipe may be driving various bpp values depending on the display configuration, so take that into account when calculating link bandwidth requirements. Signed-off-by: Jesse Barnes Reviewed-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 391b55f1cc74..26ce8c0af9b8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -682,7 +682,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_encoder *encoder; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int lane_count = 4, bpp = 24; + int lane_count = 4; struct intel_dp_m_n m_n; int pipe = intel_crtc->pipe; @@ -701,7 +701,6 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, break; } else if (is_edp(intel_dp)) { lane_count = dev_priv->edp.lanes; - bpp = dev_priv->edp.bpp; break; } } @@ -711,7 +710,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, * the number of bytes_per_pixel post-LUT, which we always * set up for 8-bits of R/G/B, or 3 bytes total. */ - intel_dp_compute_m_n(bpp, lane_count, + intel_dp_compute_m_n(intel_crtc->bpp, lane_count, mode->clock, adjusted_mode->clock, &m_n); if (HAS_PCH_SPLIT(dev)) { -- cgit v1.2.3 From 89c6143263ef8e14e42e17324a234418d8030b10 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 24 Jun 2011 12:19:28 -0700 Subject: drm/i915: use pipe bpp in DP link bandwidth calculation Now that we track bpp on a per-pipe basis, we can use the actual value rather than assuming 24bpp. Signed-off-by: Jesse Barnes Reviewed-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 26ce8c0af9b8..e17de2b3d415 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -179,12 +179,14 @@ intel_dp_link_clock(uint8_t link_bw) static int intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = intel_dp->base.base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int bpp = 24; - if (is_edp(intel_dp)) - return (pixel_clock * dev_priv->edp.bpp + 7) / 8; - else - return pixel_clock * 3; + if (intel_crtc) + bpp = intel_crtc->bpp; + + return (pixel_clock * bpp + 7) / 8; } static int -- cgit v1.2.3 From 61da5fab5a9b129cf05b1fe4666c3e45b3103fd4 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Jul 2011 11:10:57 -0700 Subject: drm/i915/dp: retry link status read 3 times on failure Especially after a hotplug or power status change, the sink may not reply immediately to a link status query. So retry 3 times per the spec to really make sure nothing is there. See section 9.1 of the 1.1a DisplayPort spec. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 391b55f1cc74..86912bd737ad 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1019,14 +1019,20 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) static bool intel_dp_get_link_status(struct intel_dp *intel_dp) { - int ret; + int ret, i; + + /* Must try AUX reads for this at least 3 times */ + 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) + return true; + msleep(1); + } - 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) - return false; - return true; + return false; } static uint8_t -- cgit v1.2.3 From 7183dc2912510cf005fcc59239f8d153ef51d3f0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Jul 2011 11:10:58 -0700 Subject: drm/i915/dp: use DP DPCD defines when looking at DPCD values Makes it easier to search for DP related constants. Reviewed-by: Keith Packard Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 86912bd737ad..fc51730b89d6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -138,8 +138,8 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp) { int max_lane_count = 4; - if (intel_dp->dpcd[0] >= 0x11) { - max_lane_count = intel_dp->dpcd[2] & 0x1f; + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) { + max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f; switch (max_lane_count) { case 1: case 2: case 4: break; @@ -153,7 +153,7 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp) static int intel_dp_max_link_bw(struct intel_dp *intel_dp) { - int max_link_bw = intel_dp->dpcd[1]; + int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE]; switch (max_link_bw) { case DP_LINK_BW_1_62: @@ -774,7 +774,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, /* * Check for DPCD version > 1.1 and enhanced framing support */ - if (intel_dp->dpcd[0] >= 0x11 && (intel_dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)) { + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && + (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) { intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; intel_dp->DP |= DP_ENHANCED_FRAMING; } @@ -1553,7 +1554,7 @@ ironlake_dp_detect(struct intel_dp *intel_dp) 0x000, intel_dp->dpcd, sizeof (intel_dp->dpcd)) == sizeof(intel_dp->dpcd)) { - if (intel_dp->dpcd[0] != 0) + if (intel_dp->dpcd[DP_DPCD_REV] != 0) status = connector_status_connected; } DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0], @@ -1592,7 +1593,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd, sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd)) { - if (intel_dp->dpcd[0] != 0) + if (intel_dp->dpcd[DP_DPCD_REV] != 0) status = connector_status_connected; } @@ -1960,8 +1961,9 @@ intel_dp_init(struct drm_device *dev, int output_reg) sizeof(intel_dp->dpcd)); ironlake_edp_panel_vdd_off(intel_dp); if (ret == sizeof(intel_dp->dpcd)) { - if (intel_dp->dpcd[0] >= 0x11) - dev_priv->no_aux_handshake = intel_dp->dpcd[3] & + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) + dev_priv->no_aux_handshake = + intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_NO_AUX_HANDSHAKE_LINK_TRAINING; } else { /* if this fails, presume the device is a ghost */ -- cgit v1.2.3 From 59cd09e1aea3ac6eb15b45e5d2261a63ecb1799c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Jul 2011 11:10:59 -0700 Subject: drm/i915/dp: read more receiver capability bits on hotplug When a hotplug event is received, we need to check the receiver cap bits in case they've changed (as they might with a hub or chain config). Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fc51730b89d6..a9a5051419df 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1522,6 +1522,8 @@ intel_dp_link_down(struct intel_dp *intel_dp) static void intel_dp_check_link_status(struct intel_dp *intel_dp) { + int ret; + if (!intel_dp->base.base.crtc) return; @@ -1530,6 +1532,15 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) return; } + /* Try to read receiver status if the link appears to be up */ + ret = intel_dp_aux_native_read(intel_dp, + 0x000, intel_dp->dpcd, + sizeof (intel_dp->dpcd)); + if (ret != sizeof(intel_dp->dpcd)) { + intel_dp_link_down(intel_dp); + return; + } + if (!intel_channel_eq_ok(intel_dp)) { intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); -- cgit v1.2.3 From 899526d9a73fda47516cf11ccb3467ad6702f568 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Jul 2011 11:11:00 -0700 Subject: drm/i915/dp: try to read receiver capabilities 3 times when detecting If ->detect is called too soon after a hot plug event, the sink may not be ready yet. So try up to 3 times with 1ms sleeps in between tries to get the data (spec dictates that receivers must be ready to respond within 1ms and that sources should try 3 times). See section 9.1 of the 1.1a DisplayPort spec. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a9a5051419df..70075d9900da 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1551,6 +1551,7 @@ static enum drm_connector_status ironlake_dp_detect(struct intel_dp *intel_dp) { enum drm_connector_status status; + int ret, i; /* Can't disconnect eDP, but you can close the lid... */ if (is_edp(intel_dp)) { @@ -1561,12 +1562,16 @@ ironlake_dp_detect(struct intel_dp *intel_dp) } status = connector_status_disconnected; - if (intel_dp_aux_native_read(intel_dp, - 0x000, intel_dp->dpcd, - sizeof (intel_dp->dpcd)) - == sizeof(intel_dp->dpcd)) { - if (intel_dp->dpcd[DP_DPCD_REV] != 0) + 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); } 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]); -- cgit v1.2.3 From 885a50147f00a8a80108904bf58a18af357717f3 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Jul 2011 11:11:01 -0700 Subject: drm/i915/dp: remove DPMS mode tracking from DP We currently use this when a hot plug event is received, only checking the link status and re-training if we had previously configured a link. However if we want to preserve the DP configuration across both hot plug and DPMS events (which we do for userspace apps that don't respond to hot plug uevents), we need to unconditionally check the link and try to bring it up on hot plug. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 70075d9900da..5f97c1751ff0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -50,7 +50,6 @@ struct intel_dp { bool has_audio; int force_audio; uint32_t color_range; - int dpms_mode; uint8_t link_bw; uint8_t lane_count; uint8_t dpcd[4]; @@ -1010,7 +1009,6 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) if (is_edp(intel_dp)) ironlake_edp_backlight_on(dev); } - intel_dp->dpms_mode = mode; } /* @@ -1813,8 +1811,7 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder) { struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); - if (intel_dp->dpms_mode == DRM_MODE_DPMS_ON) - intel_dp_check_link_status(intel_dp); + intel_dp_check_link_status(intel_dp); } /* Return which DP Port should be selected for Transcoder DP control */ @@ -1882,7 +1879,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) return; intel_dp->output_reg = output_reg; - intel_dp->dpms_mode = -1; intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); if (!intel_connector) { -- cgit v1.2.3 From df0c237d124fb8d10b98f7b43d63d962eeed9355 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Jul 2011 11:11:02 -0700 Subject: drm/i915/dp: consolidate AUX retry code When checking link status during a hot plug event or detecting sink presence, we need to retry 3 times per the spec (section 9.1 of the 1.1a DisplayPort spec). Consolidate the retry code into a native_aux_read_retry function for use by get_link_status and _detect. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 51 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5f97c1751ff0..bca48b05520b 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; -- cgit v1.2.3 From c7ad381078ee1b5ce2ab5274bd5f12fee6e1e59a Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 7 Jul 2011 11:11:03 -0700 Subject: drm/i915/dp: manage sink power state if possible On sinks with a DPCD rev of 1.1 or greater, we can send sink power management commands to address 0x600 per section 5.1.5 of the DisplayPort 1.1a spec. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bca48b05520b..e2aced6eec4c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -942,11 +942,44 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder) udelay(200); } +/* If the sink supports it, try to set the power state appropriately */ +static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) +{ + int ret, i; + + /* Should have a valid DPCD by this point */ + if (intel_dp->dpcd[DP_DPCD_REV] < 0x11) + return; + + if (mode != DRM_MODE_DPMS_ON) { + ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER, + DP_SET_POWER_D3); + if (ret != 1) + DRM_DEBUG_DRIVER("failed to write sink power state\n"); + } else { + /* + * When turning on, we need to retry for 1ms to give the sink + * time to wake up. + */ + for (i = 0; i < 3; i++) { + ret = intel_dp_aux_native_write_1(intel_dp, + DP_SET_POWER, + DP_SET_POWER_D0); + if (ret == 1) + break; + msleep(1); + } + } +} + static void intel_dp_prepare(struct drm_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct drm_device *dev = encoder->dev; + /* Wake up the sink first */ + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + if (is_edp(intel_dp)) { ironlake_edp_backlight_off(dev); ironlake_edp_panel_off(dev); @@ -990,6 +1023,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) if (mode != DRM_MODE_DPMS_ON) { if (is_edp(intel_dp)) ironlake_edp_backlight_off(dev); + intel_dp_sink_dpms(intel_dp, mode); intel_dp_link_down(intel_dp); if (is_edp(intel_dp)) ironlake_edp_panel_off(dev); @@ -998,6 +1032,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) } else { if (is_edp(intel_dp)) ironlake_edp_panel_vdd_on(intel_dp); + intel_dp_sink_dpms(intel_dp, mode); if (!(dp_reg & DP_PORT_EN)) { intel_dp_start_link_train(intel_dp); if (is_edp(intel_dp)) { -- cgit v1.2.3 From 97cdd7101079adc3c626d159c62d43de949516c8 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 12 Jul 2011 17:38:00 -0400 Subject: drm/i915/dp: Zero the DPCD data before connection probe Signed-off-by: Adam Jackson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e2aced6eec4c..de24f314eda9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1673,6 +1673,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) struct edid *edid = NULL; intel_dp->has_audio = false; + memset(intel_dp->dpcd, 0, sizeof(intel_dp->dpcd)); if (HAS_PCH_SPLIT(dev)) status = ironlake_dp_detect(intel_dp); -- cgit v1.2.3 From 1b9be9d09d85b3697418dc444db30d069203ff7d Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 12 Jul 2011 17:38:01 -0400 Subject: drm/i915/dp: Move DPCD dump to common code instead of PCH-only No reason not to see this on g4x, after all. Signed-off-by: Adam Jackson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index de24f314eda9..0be85a00bb52 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1615,8 +1615,6 @@ ironlake_dp_detect(struct intel_dp *intel_dp) 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; } @@ -1679,6 +1677,10 @@ intel_dp_detect(struct drm_connector *connector, bool force) status = ironlake_dp_detect(intel_dp); else status = g4x_dp_detect(intel_dp); + + 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]); + if (status != connector_status_connected) return status; -- cgit v1.2.3 From 9de88e6e89a2222061af8e1448f6f346e3413fc8 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 12 Jul 2011 17:38:02 -0400 Subject: drm/i915/dp: Read more DPCD registers on connection probe For parity with radeon and nouveau, and also because I suspect we're going to need it to get format-conversion dongles right. Signed-off-by: Adam Jackson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0be85a00bb52..2f0566b12f71 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -52,7 +52,7 @@ struct intel_dp { uint32_t color_range; uint8_t link_bw; uint8_t lane_count; - uint8_t dpcd[4]; + uint8_t dpcd[8]; struct i2c_adapter adapter; struct i2c_algo_dp_aux_data algo; bool is_pch_edp; @@ -1678,8 +1678,10 @@ intel_dp_detect(struct drm_connector *connector, bool force) else status = g4x_dp_detect(intel_dp); - 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]); + DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx%hx%hx%hx%hx\n", intel_dp->dpcd[0], + intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3], + intel_dp->dpcd[4], intel_dp->dpcd[5], intel_dp->dpcd[6], + intel_dp->dpcd[7]); if (status != connector_status_connected) return status; -- cgit v1.2.3 From ac66ae8346fff704301e24ac55da1d76020660b2 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 12 Jul 2011 17:38:03 -0400 Subject: drm/i915/dp: Better hexdump of DPCD %hx alone prints 0 as "0", not "00". Signed-off-by: Adam Jackson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2f0566b12f71..13bddd34c057 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1678,10 +1678,10 @@ intel_dp_detect(struct drm_connector *connector, bool force) else status = g4x_dp_detect(intel_dp); - DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx%hx%hx%hx%hx\n", intel_dp->dpcd[0], - intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3], - intel_dp->dpcd[4], intel_dp->dpcd[5], intel_dp->dpcd[6], - intel_dp->dpcd[7]); + DRM_DEBUG_KMS("DPCD: %02hx%02hx%02hx%02hx%02hx%02hx%02hx%02hx\n", + intel_dp->dpcd[0], intel_dp->dpcd[1], intel_dp->dpcd[2], + intel_dp->dpcd[3], intel_dp->dpcd[4], intel_dp->dpcd[5], + intel_dp->dpcd[6], intel_dp->dpcd[7]); if (status != connector_status_connected) return status; -- cgit v1.2.3 From 71ba9000e673d6171a52f2a8b14e0419087f7199 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 12 Jul 2011 17:38:04 -0400 Subject: drm/i915/dp: Retry DPCD fetch on G4X too Signed-off-by: Adam Jackson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 13bddd34c057..9a0c3ca1ffa9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1595,11 +1595,23 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) } } +static enum drm_connector_status +i915_dp_detect_common(struct intel_dp *intel_dp) +{ + enum drm_connector_status status = connector_status_disconnected; + + if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, + sizeof (intel_dp->dpcd)) && + (intel_dp->dpcd[DP_DPCD_REV] != 0)) + status = connector_status_connected; + + return status; +} + static enum drm_connector_status ironlake_dp_detect(struct intel_dp *intel_dp) { enum drm_connector_status status; - bool ret; /* Can't disconnect eDP, but you can close the lid... */ if (is_edp(intel_dp)) { @@ -1609,13 +1621,7 @@ ironlake_dp_detect(struct intel_dp *intel_dp) return status; } - status = connector_status_disconnected; - 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; - return status; + return i915_dp_detect_common(intel_dp); } static enum drm_connector_status @@ -1623,7 +1629,6 @@ g4x_dp_detect(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum drm_connector_status status; uint32_t temp, bit; switch (intel_dp->output_reg) { @@ -1645,15 +1650,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) if ((temp & bit) == 0) return connector_status_disconnected; - status = connector_status_disconnected; - if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd, - sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd)) - { - if (intel_dp->dpcd[DP_DPCD_REV] != 0) - status = connector_status_connected; - } - - return status; + return i915_dp_detect_common(intel_dp); } /** -- cgit v1.2.3 From a2cab1b24a4ea75a68fa21bfb7d5b1a45121583c Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 12 Jul 2011 17:38:05 -0400 Subject: drm/i915/dp: Explicitly request 8/10 channel coding It's not clear what a sink would do if you wrote zero to this register - which I guess would mean "I don't support any channel encodings, good luck" - but let's not find out. Signed-off-by: Adam Jackson Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9a0c3ca1ffa9..1c3a36feaf69 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -769,6 +769,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); intel_dp->link_configuration[0] = intel_dp->link_bw; intel_dp->link_configuration[1] = intel_dp->lane_count; + intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B; /* * Check for DPCD version > 1.1 and enhanced framing support -- cgit v1.2.3 From 81055854d096959898fdc17ed11729eb019eff07 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 21 Jul 2011 17:48:37 -0400 Subject: drm/i915/dp: Explicitly disable symbol scrambling while training The DP spec says training patterns 1 and 2 are to be sent non-scrambled, and the GPU docs claim that happens (or at least, there's no explicit scrambling control). But the sink may be confused if we don't explicitly tell it what we're doing, so play it safe. Signed-off-by: Adam Jackson Reviewed-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1c3a36feaf69..8aecb072466b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1370,7 +1370,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) reg = DP | DP_LINK_TRAIN_PAT_1; if (!intel_dp_set_link_train(intel_dp, reg, - DP_TRAINING_PATTERN_1)) + DP_TRAINING_PATTERN_1 | + DP_LINK_SCRAMBLING_DISABLE)) break; /* Set training pattern 1 */ @@ -1445,7 +1446,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) /* channel eq pattern */ if (!intel_dp_set_link_train(intel_dp, reg, - DP_TRAINING_PATTERN_2)) + DP_TRAINING_PATTERN_2 | + DP_LINK_SCRAMBLING_DISABLE)) break; udelay(400); -- cgit v1.2.3 From e85194641bec56179dcf5e1704ce5c6bf30340c6 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 21 Jul 2011 17:48:38 -0400 Subject: drm/i915/dp: Don't turn CPT DP ports on too early The docs say the port has to come on in training pattern 1; at this point, though, ->DP is in normal mode. The intent here is to wait until the port is in fact sending data, but that doesn't happen since we've broken the sequence the hardware expects, and the vblank wait will time out and kvetch in the log. Signed-off-by: Adam Jackson Reviewed-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8aecb072466b..dcc7ae6d4141 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1334,10 +1334,16 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) u32 reg; uint32_t DP = intel_dp->DP; - /* Enable output, wait for it to become active */ - I915_WRITE(intel_dp->output_reg, intel_dp->DP); - POSTING_READ(intel_dp->output_reg); - intel_wait_for_vblank(dev, intel_crtc->pipe); + /* + * On CPT we have to enable the port in training pattern 1, which + * will happen below in intel_dp_set_link_train. Otherwise, enable + * the port and wait for it to become active. + */ + if (!HAS_PCH_CPT(dev)) { + I915_WRITE(intel_dp->output_reg, intel_dp->DP); + POSTING_READ(intel_dp->output_reg); + intel_wait_for_vblank(dev, intel_crtc->pipe); + } /* Write the link configuration data */ intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, -- cgit v1.2.3 From 92fd8fd13b7570f6a8ba519c4e8ec98f10a86ce9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jul 2011 19:50:10 -0700 Subject: drm/i915: Use dp_detect_common in hotplug helper function This uses the common dpcd reading routine, i915_dp_detect_common, instead of open-coding a call to intel_dp_aux_native_read. Besides reducing duplicated code, this also gains the read retries which may be necessary when a cable is first plugged back in and the link needs to be retrained. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes Reviewed-by: Adam Jackson --- drivers/gpu/drm/i915/intel_dp.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index dcc7ae6d4141..45db8106ab12 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1567,6 +1567,20 @@ intel_dp_link_down(struct intel_dp *intel_dp) POSTING_READ(intel_dp->output_reg); } +static enum drm_connector_status +i915_dp_detect_common(struct intel_dp *intel_dp) +{ + enum drm_connector_status status = connector_status_disconnected; + + if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, + sizeof (intel_dp->dpcd)) && + (intel_dp->dpcd[DP_DPCD_REV] != 0)) { + status = connector_status_connected; + } + + return status; +} + /* * According to DP spec * 5.1.2: @@ -1579,44 +1593,29 @@ intel_dp_link_down(struct intel_dp *intel_dp) static void intel_dp_check_link_status(struct intel_dp *intel_dp) { - int ret; - if (!intel_dp->base.base.crtc) return; + /* Try to read receiver status if the link appears to be up */ if (!intel_dp_get_link_status(intel_dp)) { intel_dp_link_down(intel_dp); return; } - /* Try to read receiver status if the link appears to be up */ - ret = intel_dp_aux_native_read(intel_dp, - 0x000, intel_dp->dpcd, - sizeof (intel_dp->dpcd)); - if (ret != sizeof(intel_dp->dpcd)) { + /* Now read the DPCD to see if it's actually running */ + if (i915_dp_detect_common(intel_dp) != connector_status_connected) { intel_dp_link_down(intel_dp); return; } if (!intel_channel_eq_ok(intel_dp)) { + DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", + drm_get_encoder_name(&intel_dp->base.base)); intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); } } -static enum drm_connector_status -i915_dp_detect_common(struct intel_dp *intel_dp) -{ - enum drm_connector_status status = connector_status_disconnected; - - if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, - sizeof (intel_dp->dpcd)) && - (intel_dp->dpcd[DP_DPCD_REV] != 0)) - status = connector_status_connected; - - return status; -} - static enum drm_connector_status ironlake_dp_detect(struct intel_dp *intel_dp) { -- cgit v1.2.3 From 26d61aad7a46115628341e9eb95433f30efef21a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jul 2011 20:01:09 -0700 Subject: drm/i915: Rename i915_dp_detect_common to intel_dp_get_dpcd This describes the function better, allowing it to be used where the DPCD value is relevant. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes Reviewed-by: Adam Jackson --- drivers/gpu/drm/i915/intel_dp.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 45db8106ab12..41674e1a26c7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1567,18 +1567,16 @@ intel_dp_link_down(struct intel_dp *intel_dp) POSTING_READ(intel_dp->output_reg); } -static enum drm_connector_status -i915_dp_detect_common(struct intel_dp *intel_dp) +static bool +intel_dp_get_dpcd(struct intel_dp *intel_dp) { - enum drm_connector_status status = connector_status_disconnected; - if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, sizeof (intel_dp->dpcd)) && (intel_dp->dpcd[DP_DPCD_REV] != 0)) { - status = connector_status_connected; + return true; } - return status; + return false; } /* @@ -1603,7 +1601,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) } /* Now read the DPCD to see if it's actually running */ - if (i915_dp_detect_common(intel_dp) != connector_status_connected) { + if (!intel_dp_get_dpcd(intel_dp)) { intel_dp_link_down(intel_dp); return; } @@ -1616,6 +1614,14 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) } } +static enum drm_connector_status +intel_dp_detect_dpcd(struct intel_dp *intel_dp) +{ + if (intel_dp_get_dpcd(intel_dp)) + return connector_status_connected; + return connector_status_disconnected; +} + static enum drm_connector_status ironlake_dp_detect(struct intel_dp *intel_dp) { @@ -1629,7 +1635,7 @@ ironlake_dp_detect(struct intel_dp *intel_dp) return status; } - return i915_dp_detect_common(intel_dp); + return intel_dp_detect_dpcd(intel_dp); } static enum drm_connector_status @@ -1658,7 +1664,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) if ((temp & bit) == 0) return connector_status_disconnected; - return i915_dp_detect_common(intel_dp); + return intel_dp_detect_dpcd(intel_dp); } /** -- cgit v1.2.3 From 59f3e272d788305e16098f0b18309919c9216d67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jul 2011 20:01:56 -0700 Subject: drm/i915: In intel_dp_init, replace read of DPCD with intel_dp_get_dpcd Eliminates an open-coded read and also gains the retry behaviour of intel_dp_get_dpcd, which seems like a good idea. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes Reviewed-by: Adam Jackson --- drivers/gpu/drm/i915/intel_dp.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 41674e1a26c7..9f134d2b7bec 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2015,7 +2015,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) /* Cache some DPCD data in the eDP case */ if (is_edp(intel_dp)) { - int ret; + bool ret; u32 pp_on, pp_div; pp_on = I915_READ(PCH_PP_ON_DELAYS); @@ -2028,11 +2028,9 @@ intel_dp_init(struct drm_device *dev, int output_reg) dev_priv->panel_t12 *= 100; /* t12 in 100ms units */ ironlake_edp_panel_vdd_on(intel_dp); - ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV, - intel_dp->dpcd, - sizeof(intel_dp->dpcd)); + ret = intel_dp_get_dpcd(intel_dp); ironlake_edp_panel_vdd_off(intel_dp); - if (ret == sizeof(intel_dp->dpcd)) { + if (ret) { if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] & -- cgit v1.2.3 From d2b996ac698aebb28557355857927b8b934bb4f9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jul 2011 22:37:51 -0700 Subject: Revert and fix "drm/i915/dp: remove DPMS mode tracking from DP" This reverts commit 885a50147f00a8a80108904bf58a18af357717f3. We actually *do* need to track DPMS state so that on hotplug, we don't retrain the link until DPMS is disabled. However, that code had avery small bug -- it wouldn't set the dpms_mode at mode set time, and so link retraining would not actually occur on monitor hotplug until the monitor had gone through a DPMS off/DPMS on cycle. Signed-off-by: Keith Packard Tested-by: Andrew Lutomirski --- drivers/gpu/drm/i915/intel_dp.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9f134d2b7bec..449364187bc0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -50,6 +50,7 @@ struct intel_dp { bool has_audio; int force_audio; uint32_t color_range; + int dpms_mode; uint8_t link_bw; uint8_t lane_count; uint8_t dpcd[8]; @@ -1011,6 +1012,8 @@ static void intel_dp_commit(struct drm_encoder *encoder) if (is_edp(intel_dp)) ironlake_edp_backlight_on(dev); + + intel_dp->dpms_mode = DRM_MODE_DPMS_ON; } static void @@ -1045,6 +1048,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) if (is_edp(intel_dp)) ironlake_edp_backlight_on(dev); } + intel_dp->dpms_mode = mode; } /* @@ -1591,6 +1595,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) static void intel_dp_check_link_status(struct intel_dp *intel_dp) { + if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON) + return; + if (!intel_dp->base.base.crtc) return; @@ -1939,6 +1946,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) return; intel_dp->output_reg = output_reg; + intel_dp->dpms_mode = -1; intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); if (!intel_connector) { -- cgit v1.2.3 From 11bee43ebba0bfc92165c059f6e9869197ea8889 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 1 Aug 2011 15:02:20 -0700 Subject: drm/i915/dp: wait for previous AUX channel activity to clear Before initiating a new read or write on the DP AUX channel, wait for any outstanding activity to complete. This may happen during normal retry behavior. If the wait fails (i.e. after 1ms the AUX channel is still busy) dump a backtrace to make the caller easier to spot. v2: use msleep instead, and timeout after 3ms (only ever saw 1 retry with msleep in testing) v3: fix backtrace check to trigger if the 3ms wait times out Fixes https://bugs.freedesktop.org/show_bug.cgi?id=38136. Signed-off-by: Jesse Barnes Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 449364187bc0..ba72fbcbbbc9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -315,9 +315,17 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, else precharge = 5; - if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { - DRM_ERROR("dp_aux_ch not started status 0x%08x\n", - I915_READ(ch_ctl)); + /* Try to wait for any previous AUX channel activity */ + for (try = 0; try < 3; try++) { + status = I915_READ(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + msleep(1); + } + + if (try == 3) { + WARN(1, "dp_aux_ch not started status 0x%08x\n", + I915_READ(ch_ctl)); return -EBUSY; } -- cgit v1.2.3 From 4edd17a25c99f34bd7a75c1daf31afe840237da8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 3 Aug 2011 10:34:58 -0700 Subject: Revert "drm/i915/dp: Zero the DPCD data before connection probe" This reverts commit 97cdd7101079adc3c626d159c62d43de949516c8. Clearing the dpcd data means that if the fetch fails, any previous data will be lost. On eDP, this is no fun as we only fetch dpcd at init time, so the memset will destroy that the next time through. --- drivers/gpu/drm/i915/intel_dp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ba72fbcbbbc9..2f901c05ea2c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1697,7 +1697,6 @@ intel_dp_detect(struct drm_connector *connector, bool force) struct edid *edid = NULL; intel_dp->has_audio = false; - memset(intel_dp->dpcd, 0, sizeof(intel_dp->dpcd)); if (HAS_PCH_SPLIT(dev)) status = ironlake_dp_detect(intel_dp); -- cgit v1.2.3