aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2014-10-16 13:46:09 -0400
committerJani Nikula <jani.nikula@intel.com>2014-10-27 07:37:12 -0400
commitf6a1906674005377b64ee5431c1418077c1b2425 (patch)
tree8a99c7c17169c7c96695f1391c641ed31372a569
parentcac7f2429872d3733dc3f9915857b1691da2eb2f (diff)
drm/i915: Do a dummy DPCD read before the actual read
Sometimes we seem to get utter garbage from DPCD reads. The resulting buffer is filled with the same byte, and the operation completed without errors. My HP ZR24w monitor seems particularly susceptible to this problem once it's gone into a sleep mode. The issue seems to happen only for the first AUX message that wakes the sink up. But as the first AUX read we often do is the DPCD receiver cap it does wreak a bit of havoc with subsequent link training etc. when the receiver cap bw/lane/etc. information is garbage. A sufficient workaround seems to be to perform a single byte dummy read before reading the actual data. I suppose that just wakes up the sink sufficiently and we can just throw away the returned data in case it's crap. DP_DPCD_REV seems like a sufficiently safe location to read here. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Todd Previte <tprevite@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula <jani.nikula@intel.com>
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f6a3fdd5589e..f9c5f17af9d8 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2806,6 +2806,13 @@ intel_dp_dpcd_read_wake(struct drm_dp_aux *aux, unsigned int offset,
2806 ssize_t ret; 2806 ssize_t ret;
2807 int i; 2807 int i;
2808 2808
2809 /*
2810 * Sometime we just get the same incorrect byte repeated
2811 * over the entire buffer. Doing just one throw away read
2812 * initially seems to "solve" it.
2813 */
2814 drm_dp_dpcd_read(aux, DP_DPCD_REV, buffer, 1);
2815
2809 for (i = 0; i < 3; i++) { 2816 for (i = 0; i < 3; i++) {
2810 ret = drm_dp_dpcd_read(aux, offset, buffer, size); 2817 ret = drm_dp_dpcd_read(aux, offset, buffer, size);
2811 if (ret == size) 2818 if (ret == size)