diff mbox

Wake up DP sinks for DPCD read-based detection.

Message ID 1376613069-15790-8-git-send-email-james.ausmus@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

James Ausmus Aug. 16, 2013, 12:30 a.m. UTC
From: Stuart Abercrombie <sabercrombie@chromium.org>

When in DPMS sleep state the Apple mini DP->VGA adapter doesn't respond.
This led to no external display on boot.

v2: Avoid DPCD check and keep AUX awake for EDID read.

BUG=chrome-os-partner:17063
TEST=Straight DP and various adapters on mini-DP and DP platforms.

Change-Id: I90bea73006ae9c99464b0b5bc57f3803918313a8
Reviewed-on: https://gerrit.chromium.org/gerrit/42583
Reviewed-by: St├ęphane Marchesin <marcheu@chromium.org>
Commit-Queue: Stuart Abercrombie <sabercrombie@chromium.org>
Tested-by: Stuart Abercrombie <sabercrombie@chromium.org>
[marcheu: fixups for 3.8]
Signed-off-by: St├ęphane Marchesin <marcheu@chromium.org>
---
 drivers/gpu/drm/i915/intel_dp.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

Comments

Chris Wilson Aug. 16, 2013, 8:01 a.m. UTC | #1
On Thu, Aug 15, 2013 at 05:30:32PM -0700, james.ausmus@intel.com wrote:
>  static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
>  				  enum pipe *pipe)
>  {
> @@ -2330,6 +2336,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  
>  	intel_dp->has_audio = false;
>  
> +	/* Ensure the sink is awake for DPCD/EDID reads. */

I would try using the force parameter to return the last known status to
avoid the extra busy work.

> +	if (connector->dpms != DRM_MODE_DPMS_ON) {
> +		/* Bypass DPCD check, since we obtain it during detection. */
> +		intel_dp_do_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> +	}
> +
>  	if (HAS_PCH_SPLIT(dev))
>  		status = ironlake_dp_detect(intel_dp);
>  	else
> @@ -2339,8 +2351,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  			   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
>  	DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
>  
> -	if (status != connector_status_connected)
> +	if (status != connector_status_connected) {
> +		if (connector->dpms != DRM_MODE_DPMS_ON)
> +			intel_dp_do_sink_dpms(intel_dp, connector->dpms);
>  		return status;
> +	}
>  
>  	intel_dp_probe_oui(intel_dp);
>  
> @@ -2356,6 +2371,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  
>  	if (intel_encoder->type != INTEL_OUTPUT_EDP)
>  		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
> +
> +	/* Restore the sink state */
> +	if (connector->dpms != DRM_MODE_DPMS_ON)
> +		intel_dp_do_sink_dpms(intel_dp, connector->dpms);
> +
>  	return connector_status_connected;
>  }
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c271c05..f886ae9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1290,14 +1290,10 @@  static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 }
 
 /* If the sink supports it, try to set the power state appropriately */
-void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
+static void intel_dp_do_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);
@@ -1319,6 +1315,16 @@  void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 	}
 }
 
+/* If we have a valid DPCD, set the power state. */
+void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
+{
+	/* Should have a valid DPCD by this point */
+	if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
+		return;
+
+	intel_dp_do_sink_dpms(intel_dp, mode);
+}
+
 static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
 				  enum pipe *pipe)
 {
@@ -2330,6 +2336,12 @@  intel_dp_detect(struct drm_connector *connector, bool force)
 
 	intel_dp->has_audio = false;
 
+	/* Ensure the sink is awake for DPCD/EDID reads. */
+	if (connector->dpms != DRM_MODE_DPMS_ON) {
+		/* Bypass DPCD check, since we obtain it during detection. */
+		intel_dp_do_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+	}
+
 	if (HAS_PCH_SPLIT(dev))
 		status = ironlake_dp_detect(intel_dp);
 	else
@@ -2339,8 +2351,11 @@  intel_dp_detect(struct drm_connector *connector, bool force)
 			   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
 	DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
 
-	if (status != connector_status_connected)
+	if (status != connector_status_connected) {
+		if (connector->dpms != DRM_MODE_DPMS_ON)
+			intel_dp_do_sink_dpms(intel_dp, connector->dpms);
 		return status;
+	}
 
 	intel_dp_probe_oui(intel_dp);
 
@@ -2356,6 +2371,11 @@  intel_dp_detect(struct drm_connector *connector, bool force)
 
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+
+	/* Restore the sink state */
+	if (connector->dpms != DRM_MODE_DPMS_ON)
+		intel_dp_do_sink_dpms(intel_dp, connector->dpms);
+
 	return connector_status_connected;
 }