]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/gpu/drm/drm_dp_dual_mode_helper.c
drm/hisilicon: hibmc: Don't overwrite fb helper surface depth
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / drm_dp_dual_mode_helper.c
index 02a50929af6759ab7769bba100134b2e6f4b0713..e7f4fe2848a542c3e45b55a8c92b258273cd71c8 100644 (file)
@@ -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);