drm/dp: add 128b/132b link status helpers from DP 2.0 E11
authorJani Nikula <jani.nikula@intel.com>
Thu, 3 Feb 2022 09:03:51 +0000 (11:03 +0200)
committerJani Nikula <jani.nikula@intel.com>
Fri, 11 Feb 2022 09:35:37 +0000 (11:35 +0200)
The DP 2.0 errata redefines link training. There are some new status
bits, and some of the old ones need to be checked independently. Add
helpers to do this.

Cc: Uma Shankar <uma.shankar@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/5a46260d1f171fed46d0ab8fe4b6499abd65ce24.1643878928.git.jani.nikula@intel.com
drivers/gpu/drm/drm_dp_helper.c
include/drm/drm_dp_helper.h

index 81c4aaee422b19e11b233f2ccbdc45cc677f67ed..4a5527cbd448e9d84de3cec53fe85cbd8135ed33 100644 (file)
@@ -144,6 +144,69 @@ u8 drm_dp_get_adjust_tx_ffe_preset(const u8 link_status[DP_LINK_STATUS_SIZE],
 }
 EXPORT_SYMBOL(drm_dp_get_adjust_tx_ffe_preset);
 
+/* DP 2.0 errata for 128b/132b */
+bool drm_dp_128b132b_lane_channel_eq_done(const u8 link_status[DP_LINK_STATUS_SIZE],
+                                         int lane_count)
+{
+       u8 lane_align, lane_status;
+       int lane;
+
+       lane_align = dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
+       if (!(lane_align & DP_INTERLANE_ALIGN_DONE))
+               return false;
+
+       for (lane = 0; lane < lane_count; lane++) {
+               lane_status = dp_get_lane_status(link_status, lane);
+               if (!(lane_status & DP_LANE_CHANNEL_EQ_DONE))
+                       return false;
+       }
+       return true;
+}
+EXPORT_SYMBOL(drm_dp_128b132b_lane_channel_eq_done);
+
+/* DP 2.0 errata for 128b/132b */
+bool drm_dp_128b132b_lane_symbol_locked(const u8 link_status[DP_LINK_STATUS_SIZE],
+                                       int lane_count)
+{
+       u8 lane_status;
+       int lane;
+
+       for (lane = 0; lane < lane_count; lane++) {
+               lane_status = dp_get_lane_status(link_status, lane);
+               if (!(lane_status & DP_LANE_SYMBOL_LOCKED))
+                       return false;
+       }
+       return true;
+}
+EXPORT_SYMBOL(drm_dp_128b132b_lane_symbol_locked);
+
+/* DP 2.0 errata for 128b/132b */
+bool drm_dp_128b132b_eq_interlane_align_done(const u8 link_status[DP_LINK_STATUS_SIZE])
+{
+       u8 status = dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
+
+       return status & DP_128B132B_DPRX_EQ_INTERLANE_ALIGN_DONE;
+}
+EXPORT_SYMBOL(drm_dp_128b132b_eq_interlane_align_done);
+
+/* DP 2.0 errata for 128b/132b */
+bool drm_dp_128b132b_cds_interlane_align_done(const u8 link_status[DP_LINK_STATUS_SIZE])
+{
+       u8 status = dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
+
+       return status & DP_128B132B_DPRX_CDS_INTERLANE_ALIGN_DONE;
+}
+EXPORT_SYMBOL(drm_dp_128b132b_cds_interlane_align_done);
+
+/* DP 2.0 errata for 128b/132b */
+bool drm_dp_128b132b_link_training_failed(const u8 link_status[DP_LINK_STATUS_SIZE])
+{
+       u8 status = dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED);
+
+       return status & DP_128B132B_LT_FAILED;
+}
+EXPORT_SYMBOL(drm_dp_128b132b_link_training_failed);
+
 u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZE],
                                         unsigned int lane)
 {
index 629ac2272e554c3ea82d591de552606ee9d0241d..c9ca38941514b5be282e9866d9639675a125d3b8 100644 (file)
@@ -738,11 +738,13 @@ struct drm_panel;
                            DP_LANE_CHANNEL_EQ_DONE |   \
                            DP_LANE_SYMBOL_LOCKED)
 
-#define DP_LANE_ALIGN_STATUS_UPDATED       0x204
-
-#define DP_INTERLANE_ALIGN_DONE                    (1 << 0)
-#define DP_DOWNSTREAM_PORT_STATUS_CHANGED   (1 << 6)
-#define DP_LINK_STATUS_UPDATED             (1 << 7)
+#define DP_LANE_ALIGN_STATUS_UPDATED                    0x204
+#define  DP_INTERLANE_ALIGN_DONE                        (1 << 0)
+#define  DP_128B132B_DPRX_EQ_INTERLANE_ALIGN_DONE       (1 << 2) /* 2.0 E11 */
+#define  DP_128B132B_DPRX_CDS_INTERLANE_ALIGN_DONE      (1 << 3) /* 2.0 E11 */
+#define  DP_128B132B_LT_FAILED                          (1 << 4) /* 2.0 E11 */
+#define  DP_DOWNSTREAM_PORT_STATUS_CHANGED              (1 << 6)
+#define  DP_LINK_STATUS_UPDATED                         (1 << 7)
 
 #define DP_SINK_STATUS                     0x205
 # define DP_RECEIVE_PORT_0_STATUS          (1 << 0)
@@ -1554,6 +1556,13 @@ void drm_dp_lttpr_link_train_channel_eq_delay(const struct drm_dp_aux *aux,
                                              const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
 
 int drm_dp_128b132b_read_aux_rd_interval(struct drm_dp_aux *aux);
+bool drm_dp_128b132b_lane_channel_eq_done(const u8 link_status[DP_LINK_STATUS_SIZE],
+                                         int lane_count);
+bool drm_dp_128b132b_lane_symbol_locked(const u8 link_status[DP_LINK_STATUS_SIZE],
+                                       int lane_count);
+bool drm_dp_128b132b_eq_interlane_align_done(const u8 link_status[DP_LINK_STATUS_SIZE]);
+bool drm_dp_128b132b_cds_interlane_align_done(const u8 link_status[DP_LINK_STATUS_SIZE]);
+bool drm_dp_128b132b_link_training_failed(const u8 link_status[DP_LINK_STATUS_SIZE]);
 
 u8 drm_dp_link_rate_to_bw_code(int link_rate);
 int drm_dp_bw_code_to_link_rate(u8 link_bw);