aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2018-04-16 11:53:09 -0400
committerJani Nikula <jani.nikula@intel.com>2018-04-18 09:33:14 -0400
commit7eb2c4dd54ff841f2fe509a84973eb25fa20bda2 (patch)
tree88df30ed3cdb70891385db05728ca510a25fa8a4
parentb8e47d87be65aec931846ced9a34a22d2021c311 (diff)
drm/i915: Fix LSPCON TMDS output buffer enabling from low-power state
LSPCON adapters in low-power state may ignore the first I2C write during TMDS output buffer enabling, resulting in a blank screen even with an otherwise enabled pipe. Fix this by reading back and validating the written value a few times. The problem was noticed on GLK machines with an onboard LSPCON adapter after entering/exiting DC5 power state. Doing an I2C read of the adapter ID as the first transaction - instead of the I2C write to enable the TMDS buffers - returns the correct value. Based on this we assume that the transaction itself is sent properly, it's only the adapter that is not ready for some reason to accept this first write after waking from low-power state. In my case the second I2C write attempt always succeeded. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105854 Cc: Clinton Taylor <clinton.a.taylor@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: stable@vger.kernel.org Signed-off-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180416155309.11100-1-imre.deak@intel.com
-rw-r--r--drivers/gpu/drm/drm_dp_dual_mode_helper.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
index 02a50929af67..e7f4fe2848a5 100644
--- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
+++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
@@ -350,19 +350,44 @@ int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type,
350{ 350{
351 uint8_t tmds_oen = enable ? 0 : DP_DUAL_MODE_TMDS_DISABLE; 351 uint8_t tmds_oen = enable ? 0 : DP_DUAL_MODE_TMDS_DISABLE;
352 ssize_t ret; 352 ssize_t ret;
353 int retry;
353 354
354 if (type < DRM_DP_DUAL_MODE_TYPE2_DVI) 355 if (type < DRM_DP_DUAL_MODE_TYPE2_DVI)
355 return 0; 356 return 0;
356 357
357 ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN, 358 /*
358 &tmds_oen, sizeof(tmds_oen)); 359 * LSPCON adapters in low-power state may ignore the first write, so
359 if (ret) { 360 * read back and verify the written value a few times.
360 DRM_DEBUG_KMS("Failed to %s TMDS output buffers\n", 361 */
361 enable ? "enable" : "disable"); 362 for (retry = 0; retry < 3; retry++) {
362 return ret; 363 uint8_t tmp;
364
365 ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
366 &tmds_oen, sizeof(tmds_oen));
367 if (ret) {
368 DRM_DEBUG_KMS("Failed to %s TMDS output buffers (%d attempts)\n",
369 enable ? "enable" : "disable",
370 retry + 1);
371 return ret;
372 }
373
374 ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_TMDS_OEN,
375 &tmp, sizeof(tmp));
376 if (ret) {
377 DRM_DEBUG_KMS("I2C read failed during TMDS output buffer %s (%d attempts)\n",
378 enable ? "enabling" : "disabling",
379 retry + 1);
380 return ret;
381 }
382
383 if (tmp == tmds_oen)
384 return 0;
363 } 385 }
364 386
365 return 0; 387 DRM_DEBUG_KMS("I2C write value mismatch during TMDS output buffer %s\n",
388 enable ? "enabling" : "disabling");
389
390 return -EIO;
366} 391}
367EXPORT_SYMBOL(drm_dp_dual_mode_set_tmds_output); 392EXPORT_SYMBOL(drm_dp_dual_mode_set_tmds_output);
368 393