|
@@ -350,19 +350,44 @@ int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type,
|
|
|
{
|
|
|
uint8_t tmds_oen = enable ? 0 : DP_DUAL_MODE_TMDS_DISABLE;
|
|
|
ssize_t ret;
|
|
|
+ int retry;
|
|
|
|
|
|
if (type < DRM_DP_DUAL_MODE_TYPE2_DVI)
|
|
|
return 0;
|
|
|
|
|
|
- ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
|
|
|
- &tmds_oen, sizeof(tmds_oen));
|
|
|
- if (ret) {
|
|
|
- DRM_DEBUG_KMS("Failed to %s TMDS output buffers\n",
|
|
|
- enable ? "enable" : "disable");
|
|
|
- return ret;
|
|
|
+ /*
|
|
|
+ * LSPCON adapters in low-power state may ignore the first write, so
|
|
|
+ * read back and verify the written value a few times.
|
|
|
+ */
|
|
|
+ for (retry = 0; retry < 3; retry++) {
|
|
|
+ uint8_t tmp;
|
|
|
+
|
|
|
+ ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
|
|
|
+ &tmds_oen, sizeof(tmds_oen));
|
|
|
+ if (ret) {
|
|
|
+ DRM_DEBUG_KMS("Failed to %s TMDS output buffers (%d attempts)\n",
|
|
|
+ enable ? "enable" : "disable",
|
|
|
+ retry + 1);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_TMDS_OEN,
|
|
|
+ &tmp, sizeof(tmp));
|
|
|
+ if (ret) {
|
|
|
+ DRM_DEBUG_KMS("I2C read failed during TMDS output buffer %s (%d attempts)\n",
|
|
|
+ enable ? "enabling" : "disabling",
|
|
|
+ retry + 1);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tmp == tmds_oen)
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ DRM_DEBUG_KMS("I2C write value mismatch during TMDS output buffer %s\n",
|
|
|
+ enable ? "enabling" : "disabling");
|
|
|
+
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_dp_dual_mode_set_tmds_output);
|
|
|
|