drm/amd/display: Support Compliance Test Pattern Generation with DP2 Retimer
authorMichael Strauss <michael.strauss@amd.com>
Thu, 22 Jun 2023 19:30:24 +0000 (15:30 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 15 Aug 2023 22:08:27 +0000 (18:08 -0400)
[WHY]
Certain retimer requires workarounds in order to correctly output test patterns.

[HOW]
Add vendor-specific aux sequences to program retimer's TX and pattern generator
when specific compliance test patterns are requested by sink.
Note: SQ128 w/a in DPMF mode only works in one flip orientation currently

Reviewed-by: Hansen Dsouza <hansen.dsouza@amd.com>
Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Acked-by: Stylon Wang <stylon.wang@amd.com>
Signed-off-by: Michael Strauss <michael.strauss@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
17 files changed:
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/inc/link.h
drivers/gpu/drm/amd/display/dc/link/Makefile
drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.h
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/link/link_factory.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c

index 7561fe7..853e5b9 100644 (file)
@@ -45,6 +45,8 @@
 #include "link/hwss/link_hwss_dio.h"
 #include "link/hwss/link_hwss_dpia.h"
 #include "link/hwss/link_hwss_hpo_dp.h"
+#include "link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h"
+#include "link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h"
 
 #if defined(CONFIG_DRM_AMD_DC_SI)
 #include "dce60/dce60_resource.h"
@@ -4198,11 +4200,13 @@ const struct link_hwss *get_link_hwss(const struct dc_link *link,
                 * with an hpo encoder. Or we can return a very dummy one that doesn't
                 * do work for all functions
                 */
-               return get_hpo_dp_link_hwss();
+               return (requires_fixed_vs_pe_retimer_hpo_link_hwss(link) ?
+                               get_hpo_fixed_vs_pe_retimer_dp_link_hwss() : get_hpo_dp_link_hwss());
        else if (can_use_dpia_link_hwss(link, link_res))
                return get_dpia_link_hwss();
        else if (can_use_dio_link_hwss(link, link_res))
-               return get_dio_link_hwss();
+               return (requires_fixed_vs_pe_retimer_dio_link_hwss(link)) ?
+                               get_dio_fixed_vs_pe_retimer_link_hwss() : get_dio_link_hwss();
        else
                return get_virtual_link_hwss();
 }
index 44b6172..fc9756e 100644 (file)
@@ -1498,6 +1498,7 @@ struct dc_link {
        enum engine_id eng_id;
 
        bool test_pattern_enabled;
+       enum dp_test_pattern current_test_pattern;
        union compliance_test_state compliance_test_state;
 
        void *priv;
index c07096e..e3e8c76 100644 (file)
@@ -179,6 +179,10 @@ struct link_service {
        int (*aux_transfer_raw)(struct ddc_service *ddc,
                        struct aux_payload *payload,
                        enum aux_return_code_type *operation_result);
+       bool (*configure_fixed_vs_pe_retimer)(
+                       struct ddc_service *ddc,
+                       const uint8_t *data,
+                       uint32_t len);
        bool (*aux_transfer_with_retries_no_mutex)(struct ddc_service *ddc,
                        struct aux_payload *payload);
        bool (*is_in_aux_transaction_mode)(struct ddc_service *ddc);
index a52b56e..6af8a97 100644 (file)
@@ -42,7 +42,8 @@ AMD_DISPLAY_FILES += $(AMD_DAL_LINK_ACCESSORIES)
 ###############################################################################
 # hwss
 ###############################################################################
-LINK_HWSS = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o
+LINK_HWSS = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o \
+link_hwss_dio_fixed_vs_pe_retimer.o link_hwss_hpo_fixed_vs_pe_retimer_dp.o
 
 AMD_DAL_LINK_HWSS = $(addprefix $(AMDDALPATH)/dc/link/hwss/, \
 $(LINK_HWSS))
index 9fd68a1..c7e1f22 100644 (file)
@@ -703,6 +703,7 @@ bool dp_set_test_pattern(
 
                /* Reset Test Pattern state */
                link->test_pattern_enabled = false;
+               link->current_test_pattern = test_pattern;
 
                return true;
        }
@@ -740,6 +741,7 @@ bool dp_set_test_pattern(
                if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
                        /* Set Test Pattern state */
                        link->test_pattern_enabled = true;
+                       link->current_test_pattern = test_pattern;
                        if (p_link_settings != NULL)
                                dpcd_set_link_settings(link,
                                                p_link_settings);
@@ -938,6 +940,7 @@ bool dp_set_test_pattern(
 
                /* Set Test Pattern state */
                link->test_pattern_enabled = true;
+               link->current_test_pattern = test_pattern;
        }
 
        return true;
index d19a0a9..1328a0a 100644 (file)
@@ -166,7 +166,7 @@ void set_dio_dp_lane_settings(struct dc_link *link,
        link_enc->funcs->dp_set_lane_settings(link_enc, link_settings, lane_settings);
 }
 
-static void update_dio_stream_allocation_table(struct dc_link *link,
+void update_dio_stream_allocation_table(struct dc_link *link,
                const struct link_resource *link_res,
                const struct link_mst_stream_allocation_table *table)
 {
index 8b8a099..f4633d3 100644 (file)
@@ -55,5 +55,8 @@ void setup_dio_audio_output(struct pipe_ctx *pipe_ctx,
                struct audio_output *audio_output, uint32_t audio_inst);
 void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx);
 void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx);
+void update_dio_stream_allocation_table(struct dc_link *link,
+               const struct link_resource *link_res,
+               const struct link_mst_stream_allocation_table *table);
 
 #endif /* __LINK_HWSS_DIO_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.c
new file mode 100644 (file)
index 0000000..b659baa
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "link_hwss_dio.h"
+#include "link_hwss_dio_fixed_vs_pe_retimer.h"
+#include "link_enc_cfg.h"
+
+uint8_t dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(struct dc_link *link)
+{
+       // TODO: Get USB-C cable orientation
+       if (link->cur_link_settings.lane_count == LANE_COUNT_FOUR)
+               return 0xF2;
+       else
+               return 0x12;
+}
+
+void dp_dio_fixed_vs_pe_retimer_exit_manual_automation(struct dc_link *link)
+{
+       const uint8_t dp_type = dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(link);
+       const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06};
+       const uint8_t vendor_lttpr_exit_manual_automation_1[4] = {0x1, 0x50, dp_type, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_2[4] = {0x1, 0x50, 0x50, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_3[4] = {0x1, 0x51, 0x50, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_4[4] = {0x1, 0x10, 0x58, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_5[4] = {0x1, 0x10, 0x59, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_6[4] = {0x1, 0x30, 0x51, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_7[4] = {0x1, 0x30, 0x52, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_8[4] = {0x1, 0x30, 0x54, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_9[4] = {0x1, 0x30, 0x55, 0x0};
+
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_0[0], sizeof(vendor_lttpr_exit_manual_automation_0));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_1[0], sizeof(vendor_lttpr_exit_manual_automation_1));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_2[0], sizeof(vendor_lttpr_exit_manual_automation_2));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_3[0], sizeof(vendor_lttpr_exit_manual_automation_3));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_4[0], sizeof(vendor_lttpr_exit_manual_automation_4));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_5[0], sizeof(vendor_lttpr_exit_manual_automation_5));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_6[0], sizeof(vendor_lttpr_exit_manual_automation_6));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_7[0], sizeof(vendor_lttpr_exit_manual_automation_7));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_8[0], sizeof(vendor_lttpr_exit_manual_automation_8));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_exit_manual_automation_9[0], sizeof(vendor_lttpr_exit_manual_automation_9));
+}
+
+static bool set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override(struct dc_link *link,
+               const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params,
+               const struct link_hwss *link_hwss)
+{
+       struct encoder_set_dp_phy_pattern_param hw_tp_params = { 0 };
+       const uint8_t pltpat_custom[10] = {0x1F, 0x7C, 0xF0, 0xC1, 0x07, 0x1F, 0x7C, 0xF0, 0xC1, 0x07};
+       const uint8_t vendor_lttpr_write_data_pg0[4] = {0x1, 0x11, 0x0, 0x0};
+       const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06};
+
+
+       if (tp_params == NULL)
+               return false;
+
+       if (link->current_test_pattern >= DP_TEST_PATTERN_SQUARE_BEGIN &&
+                       link->current_test_pattern <= DP_TEST_PATTERN_SQUARE_END) {
+               // Deprogram overrides from previous test pattern
+               dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link);
+       }
+
+       switch (tp_params->dp_phy_pattern) {
+       case DP_TEST_PATTERN_80BIT_CUSTOM:
+               if (tp_params->custom_pattern_size == 0 || memcmp(tp_params->custom_pattern,
+                               pltpat_custom, tp_params->custom_pattern_size) != 0)
+                       return false;
+               break;
+       case DP_TEST_PATTERN_D102:
+               break;
+       default:
+               if (link->current_test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM ||
+                               link->current_test_pattern == DP_TEST_PATTERN_D102)
+                       // Deprogram overrides from previous test pattern
+                       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                                       &vendor_lttpr_exit_manual_automation_0[0],
+                                       sizeof(vendor_lttpr_exit_manual_automation_0));
+
+               return false;
+       }
+
+       hw_tp_params.dp_phy_pattern = tp_params->dp_phy_pattern;
+       hw_tp_params.dp_panel_mode = tp_params->dp_panel_mode;
+
+       if (link_hwss->ext.set_dp_link_test_pattern)
+               link_hwss->ext.set_dp_link_test_pattern(link, link_res, &hw_tp_params);
+
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg0[0], sizeof(vendor_lttpr_write_data_pg0));
+
+       return true;
+}
+
+static void set_dio_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *link,
+               const struct link_resource *link_res,
+               struct encoder_set_dp_phy_pattern_param *tp_params)
+{
+       struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link);
+
+       if (!set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override(
+                       link, link_res, tp_params, get_dio_link_hwss())) {
+               link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params);
+       }
+       link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
+}
+
+void enable_dio_fixed_vs_pe_retimer_program_4lane_output(struct dc_link *link)
+{
+       const uint8_t vendor_lttpr_write_data_4lane_1[4] = {0x1, 0x6E, 0xF2, 0x19};
+       const uint8_t vendor_lttpr_write_data_4lane_2[4] = {0x1, 0x6B, 0xF2, 0x01};
+       const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18};
+       const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03};
+       const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06};
+
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_4lane_2[0], sizeof(vendor_lttpr_write_data_4lane_2));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_4lane_3[0], sizeof(vendor_lttpr_write_data_4lane_3));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_4lane_4[0], sizeof(vendor_lttpr_write_data_4lane_4));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_4lane_5[0], sizeof(vendor_lttpr_write_data_4lane_5));
+}
+
+static void enable_dio_fixed_vs_pe_retimer_dp_link_output(struct dc_link *link,
+               const struct link_resource *link_res,
+               enum signal_type signal,
+               enum clock_source_id clock_source,
+               const struct dc_link_settings *link_settings)
+{
+       if (link_settings->lane_count == LANE_COUNT_FOUR)
+               enable_dio_fixed_vs_pe_retimer_program_4lane_output(link);
+
+       enable_dio_dp_link_output(link, link_res, signal, clock_source, link_settings);
+}
+
+static const struct link_hwss dio_fixed_vs_pe_retimer_link_hwss = {
+       .setup_stream_encoder = setup_dio_stream_encoder,
+       .reset_stream_encoder = reset_dio_stream_encoder,
+       .setup_stream_attribute = setup_dio_stream_attribute,
+       .disable_link_output = disable_dio_link_output,
+       .setup_audio_output = setup_dio_audio_output,
+       .enable_audio_packet = enable_dio_audio_packet,
+       .disable_audio_packet = disable_dio_audio_packet,
+       .ext = {
+               .set_throttled_vcp_size = set_dio_throttled_vcp_size,
+               .enable_dp_link_output = enable_dio_fixed_vs_pe_retimer_dp_link_output,
+               .set_dp_link_test_pattern = set_dio_fixed_vs_pe_retimer_dp_link_test_pattern,
+               .set_dp_lane_settings = set_dio_dp_lane_settings,
+               .update_stream_allocation_table = update_dio_stream_allocation_table,
+       },
+};
+
+bool requires_fixed_vs_pe_retimer_dio_link_hwss(const struct dc_link *link)
+{
+       if (!(link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN))
+               return false;
+
+       if (!link->dpcd_caps.lttpr_caps.main_link_channel_coding.bits.DP_128b_132b_SUPPORTED)
+               return false;
+
+       return true;
+}
+
+const struct link_hwss *get_dio_fixed_vs_pe_retimer_link_hwss(void)
+{
+       return &dio_fixed_vs_pe_retimer_link_hwss;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h
new file mode 100644 (file)
index 0000000..9ac08a3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __LINK_HWSS_DIO_FIXED_VS_PE_RETIMER_H__
+#define __LINK_HWSS_DIO_FIXED_VS_PE_RETIMER_H__
+
+#include "link.h"
+
+uint32_t dp_dio_fixed_vs_pe_retimer_get_lttpr_write_address(struct dc_link *link);
+uint8_t dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(struct dc_link *link);
+void dp_dio_fixed_vs_pe_retimer_exit_manual_automation(struct dc_link *link);
+void enable_dio_fixed_vs_pe_retimer_program_4lane_output(struct dc_link *link);
+bool requires_fixed_vs_pe_retimer_dio_link_hwss(const struct dc_link *link);
+const struct link_hwss *get_dio_fixed_vs_pe_retimer_link_hwss(void);
+
+#endif /* __LINK_HWSS_DIO_FIXED_VS_PE_RETIMER_H__ */
index dc1cb54..e125740 100644 (file)
@@ -28,7 +28,7 @@
 #include "dccg.h"
 #include "clk_mgr.h"
 
-static void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
+void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
                struct fixed31_32 throttled_vcp_size)
 {
        struct hpo_dp_stream_encoder *hpo_dp_stream_encoder =
@@ -41,7 +41,7 @@ static void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
                        throttled_vcp_size);
 }
 
-static void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
+void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
                const struct dc_link_settings *link_settings,
                struct fixed31_32 throttled_vcp_size)
 {
@@ -69,7 +69,7 @@ static void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
                        hblank_min_symbol_width);
 }
 
-static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
+void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
 {
        struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
        struct hpo_dp_link_encoder *link_enc = pipe_ctx->link_res.hpo_dp_link_enc;
@@ -78,14 +78,14 @@ static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
        stream_enc->funcs->map_stream_to_link(stream_enc, stream_enc->inst, link_enc->inst);
 }
 
-static void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
+void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
 {
        struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
 
        stream_enc->funcs->disable(stream_enc);
 }
 
-static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
+void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
 {
        struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
        struct dc_stream_state *stream = pipe_ctx->stream;
@@ -102,7 +102,7 @@ static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
                        DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
 }
 
-static void enable_hpo_dp_link_output(struct dc_link *link,
+void enable_hpo_dp_link_output(struct dc_link *link,
                const struct link_resource *link_res,
                enum signal_type signal,
                enum clock_source_id clock_source,
@@ -120,7 +120,7 @@ static void enable_hpo_dp_link_output(struct dc_link *link,
                        link->link_enc->hpd_source);
 }
 
-static void disable_hpo_dp_link_output(struct dc_link *link,
+void disable_hpo_dp_link_output(struct dc_link *link,
                const struct link_resource *link_res,
                enum signal_type signal)
 {
@@ -154,7 +154,7 @@ static void set_hpo_dp_lane_settings(struct dc_link *link,
                        lane_settings[0].FFE_PRESET.raw);
 }
 
-static void update_hpo_dp_stream_allocation_table(struct dc_link *link,
+void update_hpo_dp_stream_allocation_table(struct dc_link *link,
                const struct link_resource *link_res,
                const struct link_mst_stream_allocation_table *table)
 {
@@ -163,7 +163,7 @@ static void update_hpo_dp_stream_allocation_table(struct dc_link *link,
                        table);
 }
 
-static void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx,
+void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx,
                struct audio_output *audio_output, uint32_t audio_inst)
 {
        pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
@@ -172,13 +172,13 @@ static void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx,
                        &pipe_ctx->stream->audio_info);
 }
 
-static void enable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx)
+void enable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx)
 {
        pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(
                        pipe_ctx->stream_res.hpo_dp_stream_enc);
 }
 
-static void disable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx)
+void disable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx)
 {
        if (pipe_ctx->stream_res.audio)
                pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable(
index 3cbb94b..1d3ed8c 100644 (file)
 #include "link_hwss.h"
 #include "link.h"
 
+void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
+               struct fixed31_32 throttled_vcp_size);
+void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
+               const struct dc_link_settings *link_settings,
+               struct fixed31_32 throttled_vcp_size);
+void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
+               const struct dc_link_settings *link_settings,
+               struct fixed31_32 throttled_vcp_size);
+void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx);
+void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx);
+void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx);
+void enable_hpo_dp_link_output(struct dc_link *link,
+               const struct link_resource *link_res,
+               enum signal_type signal,
+               enum clock_source_id clock_source,
+               const struct dc_link_settings *link_settings);
+void disable_hpo_dp_link_output(struct dc_link *link,
+               const struct link_resource *link_res,
+               enum signal_type signal);
+void update_hpo_dp_stream_allocation_table(struct dc_link *link,
+               const struct link_resource *link_res,
+               const struct link_mst_stream_allocation_table *table);
+void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx,
+               struct audio_output *audio_output, uint32_t audio_inst);
+void enable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx);
+void disable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx);
+const struct link_hwss *get_hpo_dp_link_hwss(void);
 bool can_use_hpo_dp_link_hwss(const struct dc_link *link,
                const struct link_resource *link_res);
-const struct link_hwss *get_hpo_dp_link_hwss(void);
 
 
 #endif /* __LINK_HWSS_HPO_DP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
new file mode 100644 (file)
index 0000000..b621b97
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "link_hwss_hpo_dp.h"
+#include "link_hwss_hpo_fixed_vs_pe_retimer_dp.h"
+#include "link_hwss_dio_fixed_vs_pe_retimer.h"
+
+static void dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(struct dc_link *link,
+               const struct dc_lane_settings *hw_lane_settings)
+{
+       const uint8_t vendor_ffe_preset_table[16] = {
+                                                                                       0x01, 0x41, 0x61, 0x81,
+                                                                                       0xB1, 0x05, 0x35, 0x65,
+                                                                                       0x85, 0xA5, 0x09, 0x39,
+                                                                                       0x59, 0x89, 0x0F, 0x24};
+
+       const uint8_t ffe_mask[4] = {
+                       (hw_lane_settings[0].FFE_PRESET.settings.no_deemphasis != 0 ? 0x0F : 0xFF)
+                               & (hw_lane_settings[0].FFE_PRESET.settings.no_preshoot != 0 ? 0xF1 : 0xFF),
+                       (hw_lane_settings[1].FFE_PRESET.settings.no_deemphasis != 0 ? 0x0F : 0xFF)
+                               & (hw_lane_settings[1].FFE_PRESET.settings.no_preshoot != 0 ? 0xF1 : 0xFF),
+                       (hw_lane_settings[2].FFE_PRESET.settings.no_deemphasis != 0 ? 0x0F : 0xFF)
+                               & (hw_lane_settings[2].FFE_PRESET.settings.no_preshoot != 0 ? 0xF1 : 0xFF),
+                       (hw_lane_settings[3].FFE_PRESET.settings.no_deemphasis != 0 ? 0x0F : 0xFF)
+                               & (hw_lane_settings[3].FFE_PRESET.settings.no_preshoot != 0 ? 0xF1 : 0xFF)};
+
+       const uint8_t ffe_cfg[4] = {
+                       vendor_ffe_preset_table[hw_lane_settings[0].FFE_PRESET.settings.level] & ffe_mask[0],
+                       vendor_ffe_preset_table[hw_lane_settings[1].FFE_PRESET.settings.level] & ffe_mask[1],
+                       vendor_ffe_preset_table[hw_lane_settings[2].FFE_PRESET.settings.level] & ffe_mask[2],
+                       vendor_ffe_preset_table[hw_lane_settings[3].FFE_PRESET.settings.level] & ffe_mask[3]};
+
+       const uint8_t dp_type = dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(link);
+
+       const uint8_t vendor_lttpr_write_data_ffe1[4] = {0x01, 0x50, dp_type, 0x0F};
+       const uint8_t vendor_lttpr_write_data_ffe2[4] = {0x01, 0x55, dp_type, ffe_cfg[0]};
+       const uint8_t vendor_lttpr_write_data_ffe3[4] = {0x01, 0x56, dp_type, ffe_cfg[1]};
+       const uint8_t vendor_lttpr_write_data_ffe4[4] = {0x01, 0x57, dp_type, ffe_cfg[2]};
+       const uint8_t vendor_lttpr_write_data_ffe5[4] = {0x01, 0x58, dp_type, ffe_cfg[3]};
+
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_ffe1[0], sizeof(vendor_lttpr_write_data_ffe1));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_ffe2[0], sizeof(vendor_lttpr_write_data_ffe2));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_ffe3[0], sizeof(vendor_lttpr_write_data_ffe3));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_ffe4[0], sizeof(vendor_lttpr_write_data_ffe4));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_ffe5[0], sizeof(vendor_lttpr_write_data_ffe5));
+}
+
+static void dp_hpo_fixed_vs_pe_retimer_program_override_test_pattern(struct dc_link *link,
+               struct encoder_set_dp_phy_pattern_param *tp_params)
+{
+       const uint8_t vendor_lttpr_write_data_pg0[4] = {0x1, 0x11, 0x0, 0x0};
+       const uint8_t vendor_lttpr_write_data_pg1[4] = {0x1, 0x50, 0x50, 0x0};
+       const uint8_t vendor_lttpr_write_data_pg2[4] = {0x1, 0x51, 0x50, 0x0};
+       const uint8_t vendor_lttpr_write_data_pg3[4]  = {0x1, 0x10, 0x58, 0x21};
+       const uint8_t vendor_lttpr_write_data_pg4[4]  = {0x1, 0x10, 0x59, 0x21};
+       const uint8_t vendor_lttpr_write_data_pg5[4] = {0x1, 0x1C, 0x58, 0x4F};
+       const uint8_t vendor_lttpr_write_data_pg6[4] = {0x1, 0x1C, 0x59, 0x4F};
+       const uint8_t vendor_lttpr_write_data_pg7[4]  = {0x1, 0x30, 0x51, 0x20};
+       const uint8_t vendor_lttpr_write_data_pg8[4]  = {0x1, 0x30, 0x52, 0x20};
+       const uint8_t vendor_lttpr_write_data_pg9[4]  = {0x1, 0x30, 0x54, 0x20};
+       const uint8_t vendor_lttpr_write_data_pg10[4] = {0x1, 0x30, 0x55, 0x20};
+
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg0[0], sizeof(vendor_lttpr_write_data_pg0));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg1[0], sizeof(vendor_lttpr_write_data_pg1));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg2[0], sizeof(vendor_lttpr_write_data_pg2));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg3[0], sizeof(vendor_lttpr_write_data_pg3));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg4[0], sizeof(vendor_lttpr_write_data_pg4));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg5[0], sizeof(vendor_lttpr_write_data_pg5));
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg6[0], sizeof(vendor_lttpr_write_data_pg6));
+
+       if (link->cur_link_settings.lane_count == LANE_COUNT_FOUR)
+               link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_pg7[0], sizeof(vendor_lttpr_write_data_pg7));
+
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg8[0], sizeof(vendor_lttpr_write_data_pg8));
+
+       if (link->cur_link_settings.lane_count == LANE_COUNT_FOUR)
+               link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_pg9[0], sizeof(vendor_lttpr_write_data_pg9));
+
+       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pg10[0], sizeof(vendor_lttpr_write_data_pg10));
+}
+
+static bool dp_hpo_fixed_vs_pe_retimer_set_override_test_pattern(struct dc_link *link,
+               const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params,
+               const struct link_hwss *link_hwss)
+{
+       struct encoder_set_dp_phy_pattern_param hw_tp_params = { 0 };
+       const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06};
+
+       if (tp_params == NULL)
+               return false;
+
+       if (tp_params->dp_phy_pattern < DP_TEST_PATTERN_SQUARE_BEGIN ||
+                       tp_params->dp_phy_pattern > DP_TEST_PATTERN_SQUARE_END) {
+               // Deprogram overrides from previously set square wave override
+               if (link->current_test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM ||
+                               link->current_test_pattern == DP_TEST_PATTERN_D102)
+                       link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
+                                       &vendor_lttpr_exit_manual_automation_0[0],
+                                       sizeof(vendor_lttpr_exit_manual_automation_0));
+               else
+                       dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link);
+
+               return false;
+       }
+
+       hw_tp_params.dp_phy_pattern = DP_TEST_PATTERN_PRBS31;
+       hw_tp_params.dp_panel_mode = tp_params->dp_panel_mode;
+
+       if (link_hwss->ext.set_dp_link_test_pattern)
+               link_hwss->ext.set_dp_link_test_pattern(link, link_res, &hw_tp_params);
+
+       dp_hpo_fixed_vs_pe_retimer_program_override_test_pattern(link, tp_params);
+
+       dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(link, &link->cur_lane_setting[0]);
+
+       return true;
+}
+
+static void set_hpo_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *link,
+               const struct link_resource *link_res,
+               struct encoder_set_dp_phy_pattern_param *tp_params)
+{
+       if (!dp_hpo_fixed_vs_pe_retimer_set_override_test_pattern(
+                       link, link_res, tp_params, get_hpo_dp_link_hwss())) {
+               link_res->hpo_dp_link_enc->funcs->set_link_test_pattern(
+                               link_res->hpo_dp_link_enc, tp_params);
+       }
+       link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
+}
+
+static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link,
+               const struct link_resource *link_res,
+               const struct dc_link_settings *link_settings,
+               const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
+{
+       link_res->hpo_dp_link_enc->funcs->set_ffe(
+                       link_res->hpo_dp_link_enc,
+                       link_settings,
+                       lane_settings[0].FFE_PRESET.raw);
+
+       // FFE is programmed when retimer is programmed for SQ128, but explicit
+       // programming needed here as well in case FFE-only update is requested
+       if (link->current_test_pattern >= DP_TEST_PATTERN_SQUARE_BEGIN &&
+                       link->current_test_pattern <= DP_TEST_PATTERN_SQUARE_END)
+               dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(link, &lane_settings[0]);
+}
+
+static void enable_hpo_fixed_vs_pe_retimer_dp_link_output(struct dc_link *link,
+               const struct link_resource *link_res,
+               enum signal_type signal,
+               enum clock_source_id clock_source,
+               const struct dc_link_settings *link_settings)
+{
+       if (link_settings->lane_count == LANE_COUNT_FOUR)
+               enable_dio_fixed_vs_pe_retimer_program_4lane_output(link);
+
+       enable_hpo_dp_link_output(link, link_res, signal, clock_source, link_settings);
+}
+
+static const struct link_hwss hpo_fixed_vs_pe_retimer_dp_link_hwss = {
+       .setup_stream_encoder = setup_hpo_dp_stream_encoder,
+       .reset_stream_encoder = reset_hpo_dp_stream_encoder,
+       .setup_stream_attribute = setup_hpo_dp_stream_attribute,
+       .disable_link_output = disable_hpo_dp_link_output,
+       .setup_audio_output = setup_hpo_dp_audio_output,
+       .enable_audio_packet = enable_hpo_dp_audio_packet,
+       .disable_audio_packet = disable_hpo_dp_audio_packet,
+       .ext = {
+               .set_throttled_vcp_size = set_hpo_dp_throttled_vcp_size,
+               .set_hblank_min_symbol_width = set_hpo_dp_hblank_min_symbol_width,
+               .enable_dp_link_output = enable_hpo_fixed_vs_pe_retimer_dp_link_output,
+               .set_dp_link_test_pattern  = set_hpo_fixed_vs_pe_retimer_dp_link_test_pattern,
+               .set_dp_lane_settings = set_hpo_fixed_vs_pe_retimer_dp_lane_settings,
+               .update_stream_allocation_table = update_hpo_dp_stream_allocation_table,
+       },
+};
+
+bool requires_fixed_vs_pe_retimer_hpo_link_hwss(const struct dc_link *link)
+{
+       if (!(link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN))
+               return false;
+
+       if (!link->dpcd_caps.lttpr_caps.main_link_channel_coding.bits.DP_128b_132b_SUPPORTED)
+               return false;
+
+       return true;
+}
+
+const struct link_hwss *get_hpo_fixed_vs_pe_retimer_dp_link_hwss(void)
+{
+       return &hpo_fixed_vs_pe_retimer_dp_link_hwss;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h
new file mode 100644 (file)
index 0000000..8230118
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __LINK_HWSS_HPO_FIXED_VS_PE_RETIMER_DP_H__
+#define __LINK_HWSS_HPO_FIXED_VS_PE_RETIMER_DP_H__
+
+#include "link.h"
+
+bool requires_fixed_vs_pe_retimer_hpo_link_hwss(const struct dc_link *link);
+const struct link_hwss *get_hpo_fixed_vs_pe_retimer_dp_link_hwss(void);
+
+#endif /* __LINK_HWSS_HPO_FIXED_VS_PE_RETIMER_DP_H__ */
index bb063e1..195ca9e 100644 (file)
@@ -132,6 +132,7 @@ static void construct_link_service_ddc(struct link_service *link_srv)
        link_srv->destroy_ddc_service = link_destroy_ddc_service;
        link_srv->query_ddc_data = link_query_ddc_data;
        link_srv->aux_transfer_raw = link_aux_transfer_raw;
+       link_srv->configure_fixed_vs_pe_retimer = link_configure_fixed_vs_pe_retimer;
        link_srv->aux_transfer_with_retries_no_mutex =
                        link_aux_transfer_with_retries_no_mutex;
        link_srv->is_in_aux_transaction_mode = link_is_in_aux_transaction_mode;
index 0f19c07..ecfd832 100644 (file)
@@ -412,6 +412,88 @@ int link_aux_transfer_raw(struct ddc_service *ddc,
        }
 }
 
+uint32_t link_get_fixed_vs_pe_retimer_write_address(struct dc_link *link)
+{
+       uint32_t vendor_lttpr_write_address = 0xF004F;
+       uint8_t offset;
+
+       switch (link->dpcd_caps.lttpr_caps.phy_repeater_cnt) {
+       case 0x80: // 1 lttpr repeater
+               offset =  1;
+               break;
+       case 0x40: // 2 lttpr repeaters
+               offset = 2;
+               break;
+       case 0x20: // 3 lttpr repeaters
+               offset = 3;
+               break;
+       case 0x10: // 4 lttpr repeaters
+               offset = 4;
+               break;
+       case 0x08: // 5 lttpr repeaters
+               offset = 5;
+               break;
+       case 0x04: // 6 lttpr repeaters
+               offset = 6;
+               break;
+       case 0x02: // 7 lttpr repeaters
+               offset = 7;
+               break;
+       case 0x01: // 8 lttpr repeaters
+               offset = 8;
+               break;
+       default:
+               offset = 0xFF;
+       }
+
+       if (offset != 0xFF) {
+               vendor_lttpr_write_address +=
+                               ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
+       }
+       return vendor_lttpr_write_address;
+}
+
+uint32_t link_get_fixed_vs_pe_retimer_read_address(struct dc_link *link)
+{
+       return link_get_fixed_vs_pe_retimer_write_address(link) + 4;
+}
+
+bool link_configure_fixed_vs_pe_retimer(struct ddc_service *ddc, const uint8_t *data, uint32_t length)
+{
+       struct aux_payload write_payload = {
+               .i2c_over_aux = false,
+               .write = true,
+               .address = link_get_fixed_vs_pe_retimer_write_address(ddc->link),
+               .length = length,
+               .data = (uint8_t *) data,
+               .reply = NULL,
+               .mot = I2C_MOT_UNDEF,
+               .write_status_update = false,
+               .defer_delay = 0,
+       };
+
+       return link_aux_transfer_with_retries_no_mutex(ddc,
+                       &write_payload);
+}
+
+bool link_query_fixed_vs_pe_retimer(struct ddc_service *ddc, uint8_t *data, uint32_t length)
+{
+       struct aux_payload read_payload = {
+               .i2c_over_aux = false,
+               .write = false,
+               .address = link_get_fixed_vs_pe_retimer_read_address(ddc->link),
+               .length = length,
+               .data = data,
+               .reply = NULL,
+               .mot = I2C_MOT_UNDEF,
+               .write_status_update = false,
+               .defer_delay = 0,
+       };
+
+       return link_aux_transfer_with_retries_no_mutex(ddc,
+                       &read_payload);
+}
+
 bool link_aux_transfer_with_retries_no_mutex(struct ddc_service *ddc,
                struct aux_payload *payload)
 {
index 860ef15..a3e25e5 100644 (file)
@@ -72,6 +72,20 @@ bool link_query_ddc_data(
 bool link_aux_transfer_with_retries_no_mutex(struct ddc_service *ddc,
                struct aux_payload *payload);
 
+bool link_configure_fixed_vs_pe_retimer(
+               struct ddc_service *ddc,
+               const uint8_t *data,
+               uint32_t length);
+
+bool link_query_fixed_vs_pe_retimer(
+               struct ddc_service *ddc,
+               uint8_t *data,
+               uint32_t length);
+
+uint32_t link_get_fixed_vs_pe_retimer_read_address(struct dc_link *link);
+uint32_t link_get_fixed_vs_pe_retimer_write_address(struct dc_link *link);
+
+
 void write_scdc_data(
                struct ddc_service *ddc_service,
                uint32_t pix_clk,
index ca0543e..fd8f6f1 100644 (file)
@@ -36,6 +36,7 @@
 #include "link_dpcd.h"
 #include "link_dp_phy.h"
 #include "link_dp_capability.h"
+#include "link_ddc.h"
 
 #define DC_LOGGER \
        link->ctx->logger
@@ -46,42 +47,20 @@ void dp_fixed_vs_pe_read_lane_adjust(
 {
        const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63};
        const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63};
-       const uint8_t offset = dp_parse_lttpr_repeater_count(
-                       link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
-       uint32_t vendor_lttpr_write_address = 0xF004F;
-       uint32_t vendor_lttpr_read_address = 0xF0053;
        uint8_t dprx_vs = 0;
        uint8_t dprx_pe = 0;
        uint8_t lane;
 
-       if (offset != 0xFF) {
-               vendor_lttpr_write_address +=
-                               ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
-               vendor_lttpr_read_address +=
-                               ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
-       }
-
        /* W/A to read lane settings requested by DPRX */
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_vs[0],
-                       sizeof(vendor_lttpr_write_data_vs));
-       core_link_read_dpcd(
-                       link,
-                       vendor_lttpr_read_address,
-                       &dprx_vs,
-                       1);
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_pe[0],
-                       sizeof(vendor_lttpr_write_data_pe));
-       core_link_read_dpcd(
-                       link,
-                       vendor_lttpr_read_address,
-                       &dprx_pe,
-                       1);
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+
+       link_query_fixed_vs_pe_retimer(link->ddc, &dprx_vs, 1);
+
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
+
+       link_query_fixed_vs_pe_retimer(link->ddc, &dprx_pe, 1);
 
        for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
                dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET  = (dprx_vs >> (2 * lane)) & 0x3;
@@ -95,19 +74,11 @@ void dp_fixed_vs_pe_set_retimer_lane_settings(
        const union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX],
        uint8_t lane_count)
 {
-       const uint8_t offset = dp_parse_lttpr_repeater_count(
-                       link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
        const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
-       uint32_t vendor_lttpr_write_address = 0xF004F;
        uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
        uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
        uint8_t lane = 0;
 
-       if (offset != 0xFF) {
-               vendor_lttpr_write_address +=
-                               ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
-       }
-
        for (lane = 0; lane < lane_count; lane++) {
                vendor_lttpr_write_data_vs[3] |=
                                dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
@@ -116,21 +87,14 @@ void dp_fixed_vs_pe_set_retimer_lane_settings(
        }
 
        /* Force LTTPR to output desired VS and PE */
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_reset[0],
-                       sizeof(vendor_lttpr_write_data_reset));
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_vs[0],
-                       sizeof(vendor_lttpr_write_data_vs));
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_pe[0],
-                       sizeof(vendor_lttpr_write_data_pe));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_reset[0], sizeof(vendor_lttpr_write_data_reset));
+
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
 }
 
 static enum link_training_result perform_fixed_vs_pe_nontransparent_training_sequence(
@@ -241,7 +205,6 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
        const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18};
        const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03};
        const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06};
-       uint32_t vendor_lttpr_write_address = 0xF004F;
        enum link_training_result status = LINK_TRAINING_SUCCESS;
        uint8_t lane = 0;
        union down_spread_ctrl downspread = {0};
@@ -259,8 +222,6 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
        }
 
        if (offset != 0xFF) {
-               vendor_lttpr_write_address +=
-                               ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
                if (offset == 2) {
                        pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
 
@@ -271,28 +232,17 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
        }
 
        /* Vendor specific: Reset lane settings */
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_reset[0],
-                       sizeof(vendor_lttpr_write_data_reset));
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_vs[0],
-                       sizeof(vendor_lttpr_write_data_vs));
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_pe[0],
-                       sizeof(vendor_lttpr_write_data_pe));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_reset[0], sizeof(vendor_lttpr_write_data_reset));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
 
        /* Vendor specific: Enable intercept */
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_intercept_en[0],
-                       sizeof(vendor_lttpr_write_data_intercept_en));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_intercept_en[0], sizeof(vendor_lttpr_write_data_intercept_en));
+
 
        /* 1. set link rate, lane count and spread. */
 
@@ -344,31 +294,16 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
                lt_settings->link_settings.link_spread);
 
        if (lt_settings->link_settings.lane_count == LANE_COUNT_FOUR) {
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_1[0],
-                               sizeof(vendor_lttpr_write_data_4lane_1));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_2[0],
-                               sizeof(vendor_lttpr_write_data_4lane_2));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_3[0],
-                               sizeof(vendor_lttpr_write_data_4lane_3));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_4[0],
-                               sizeof(vendor_lttpr_write_data_4lane_4));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_5[0],
-                               sizeof(vendor_lttpr_write_data_4lane_5));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_2[0], sizeof(vendor_lttpr_write_data_4lane_2));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_3[0], sizeof(vendor_lttpr_write_data_4lane_3));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_4[0], sizeof(vendor_lttpr_write_data_4lane_4));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_5[0], sizeof(vendor_lttpr_write_data_4lane_5));
        }
 
        /* 2. Perform link training */
@@ -383,7 +318,6 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
                union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
                union lane_align_status_updated dpcd_lane_status_updated;
                union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
-               enum dc_status dpcd_status = DC_OK;
                uint8_t i = 0;
 
                retries_cr = 0;
@@ -418,18 +352,12 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
                                for (i = 0; i < max_vendor_dpcd_retries; i++) {
                                        if (pre_disable_intercept_delay_ms != 0)
                                                msleep(pre_disable_intercept_delay_ms);
-                                       dpcd_status = core_link_write_dpcd(
-                                                       link,
-                                                       vendor_lttpr_write_address,
+                                       if (link_configure_fixed_vs_pe_retimer(link->ddc,
                                                        &vendor_lttpr_write_data_intercept_dis[0],
-                                                       sizeof(vendor_lttpr_write_data_intercept_dis));
-
-                                       if (dpcd_status == DC_OK)
+                                                       sizeof(vendor_lttpr_write_data_intercept_dis)))
                                                break;
 
-                                       core_link_write_dpcd(
-                                                       link,
-                                                       vendor_lttpr_write_address,
+                                       link_configure_fixed_vs_pe_retimer(link->ddc,
                                                        &vendor_lttpr_write_data_intercept_en[0],
                                                        sizeof(vendor_lttpr_write_data_intercept_en));
                                }
@@ -445,16 +373,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
                                }
 
                                /* Vendor specific: Update VS and PE to DPRX requested value */
-                               core_link_write_dpcd(
-                                               link,
-                                               vendor_lttpr_write_address,
-                                               &vendor_lttpr_write_data_vs[0],
-                                               sizeof(vendor_lttpr_write_data_vs));
-                               core_link_write_dpcd(
-                                               link,
-                                               vendor_lttpr_write_address,
-                                               &vendor_lttpr_write_data_pe[0],
-                                               sizeof(vendor_lttpr_write_data_pe));
+                               link_configure_fixed_vs_pe_retimer(link->ddc,
+                                               &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+                               link_configure_fixed_vs_pe_retimer(link->ddc,
+                                               &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
 
                                dpcd_set_lane_settings(
                                                link,
@@ -550,16 +472,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
                        }
 
                        /* Vendor specific: Update VS and PE to DPRX requested value */
-                       core_link_write_dpcd(
-                                       link,
-                                       vendor_lttpr_write_address,
-                                       &vendor_lttpr_write_data_vs[0],
-                                       sizeof(vendor_lttpr_write_data_vs));
-                       core_link_write_dpcd(
-                                       link,
-                                       vendor_lttpr_write_address,
-                                       &vendor_lttpr_write_data_pe[0],
-                                       sizeof(vendor_lttpr_write_data_pe));
+                       link_configure_fixed_vs_pe_retimer(link->ddc,
+                                       &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+                       link_configure_fixed_vs_pe_retimer(link->ddc,
+                                       &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
 
                        /* 2. update DPCD*/
                        if (!retries_ch_eq)
@@ -636,7 +552,6 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
        const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18};
        const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03};
        const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06};
-       uint32_t vendor_lttpr_write_address = 0xF004F;
        enum link_training_result status = LINK_TRAINING_SUCCESS;
        uint8_t lane = 0;
        union down_spread_ctrl downspread = {0};
@@ -654,8 +569,6 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
        }
 
        if (offset != 0xFF) {
-               vendor_lttpr_write_address +=
-                               ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
                if (offset == 2) {
                        pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
 
@@ -666,28 +579,16 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
        }
 
        /* Vendor specific: Reset lane settings */
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_reset[0],
-                       sizeof(vendor_lttpr_write_data_reset));
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_vs[0],
-                       sizeof(vendor_lttpr_write_data_vs));
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_pe[0],
-                       sizeof(vendor_lttpr_write_data_pe));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_reset[0], sizeof(vendor_lttpr_write_data_reset));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
 
        /* Vendor specific: Enable intercept */
-       core_link_write_dpcd(
-                       link,
-                       vendor_lttpr_write_address,
-                       &vendor_lttpr_write_data_intercept_en[0],
-                       sizeof(vendor_lttpr_write_data_intercept_en));
+       link_configure_fixed_vs_pe_retimer(link->ddc,
+                       &vendor_lttpr_write_data_intercept_en[0], sizeof(vendor_lttpr_write_data_intercept_en));
 
        /* 1. set link rate, lane count and spread. */
 
@@ -739,31 +640,16 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
                lt_settings->link_settings.link_spread);
 
        if (lt_settings->link_settings.lane_count == LANE_COUNT_FOUR) {
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_1[0],
-                               sizeof(vendor_lttpr_write_data_4lane_1));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_2[0],
-                               sizeof(vendor_lttpr_write_data_4lane_2));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_3[0],
-                               sizeof(vendor_lttpr_write_data_4lane_3));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_4[0],
-                               sizeof(vendor_lttpr_write_data_4lane_4));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
-                               &vendor_lttpr_write_data_4lane_5[0],
-                               sizeof(vendor_lttpr_write_data_4lane_5));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_2[0], sizeof(vendor_lttpr_write_data_4lane_2));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_3[0], sizeof(vendor_lttpr_write_data_4lane_3));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_4[0], sizeof(vendor_lttpr_write_data_4lane_4));
+               link_configure_fixed_vs_pe_retimer(link->ddc,
+                               &vendor_lttpr_write_data_4lane_5[0], sizeof(vendor_lttpr_write_data_4lane_5));
        }
 
        /* 2. Perform link training */
@@ -778,7 +664,6 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
                union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
                union lane_align_status_updated dpcd_lane_status_updated;
                union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
-               enum dc_status dpcd_status = DC_OK;
                uint8_t i = 0;
 
                retries_cr = 0;
@@ -813,18 +698,12 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
                                for (i = 0; i < max_vendor_dpcd_retries; i++) {
                                        if (pre_disable_intercept_delay_ms != 0)
                                                msleep(pre_disable_intercept_delay_ms);
-                                       dpcd_status = core_link_write_dpcd(
-                                                       link,
-                                                       vendor_lttpr_write_address,
+                                       if (link_configure_fixed_vs_pe_retimer(link->ddc,
                                                        &vendor_lttpr_write_data_intercept_dis[0],
-                                                       sizeof(vendor_lttpr_write_data_intercept_dis));
-
-                                       if (dpcd_status == DC_OK)
+                                                       sizeof(vendor_lttpr_write_data_intercept_dis)))
                                                break;
 
-                                       core_link_write_dpcd(
-                                                       link,
-                                                       vendor_lttpr_write_address,
+                                       link_configure_fixed_vs_pe_retimer(link->ddc,
                                                        &vendor_lttpr_write_data_intercept_en[0],
                                                        sizeof(vendor_lttpr_write_data_intercept_en));
                                }
@@ -840,16 +719,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
                                }
 
                                /* Vendor specific: Update VS and PE to DPRX requested value */
-                               core_link_write_dpcd(
-                                               link,
-                                               vendor_lttpr_write_address,
-                                               &vendor_lttpr_write_data_vs[0],
-                                               sizeof(vendor_lttpr_write_data_vs));
-                               core_link_write_dpcd(
-                                               link,
-                                               vendor_lttpr_write_address,
-                                               &vendor_lttpr_write_data_pe[0],
-                                               sizeof(vendor_lttpr_write_data_pe));
+                               link_configure_fixed_vs_pe_retimer(link->ddc,
+                                               &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+                               link_configure_fixed_vs_pe_retimer(link->ddc,
+                                               &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
 
                                dpcd_set_lane_settings(
                                                link,
@@ -922,17 +795,14 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
                union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
                union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
 
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
+               link_configure_fixed_vs_pe_retimer(link->ddc,
                                &vendor_lttpr_write_data_adicora_eq1[0],
                                sizeof(vendor_lttpr_write_data_adicora_eq1));
-               core_link_write_dpcd(
-                               link,
-                               vendor_lttpr_write_address,
+               link_configure_fixed_vs_pe_retimer(link->ddc,
                                &vendor_lttpr_write_data_adicora_eq2[0],
                                sizeof(vendor_lttpr_write_data_adicora_eq2));
 
+
                /* Note: also check that TPS4 is a supported feature*/
                tr_pattern = lt_settings->pattern_for_eq;
 
@@ -956,16 +826,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
                        }
 
                        /* Vendor specific: Update VS and PE to DPRX requested value */
-                       core_link_write_dpcd(
-                                       link,
-                                       vendor_lttpr_write_address,
-                                       &vendor_lttpr_write_data_vs[0],
-                                       sizeof(vendor_lttpr_write_data_vs));
-                       core_link_write_dpcd(
-                                       link,
-                                       vendor_lttpr_write_address,
-                                       &vendor_lttpr_write_data_pe[0],
-                                       sizeof(vendor_lttpr_write_data_pe));
+                       link_configure_fixed_vs_pe_retimer(link->ddc,
+                                       &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
+                       link_configure_fixed_vs_pe_retimer(link->ddc,
+                                       &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
 
                        /* 2. update DPCD*/
                        if (!retries_ch_eq) {
@@ -978,11 +842,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
                                        lt_settings,
                                        tr_pattern, 0);
 
-                               core_link_write_dpcd(
-                                       link,
-                                       vendor_lttpr_write_address,
-                                       &vendor_lttpr_write_data_adicora_eq3[0],
-                                       sizeof(vendor_lttpr_write_data_adicora_eq3));
+                               link_configure_fixed_vs_pe_retimer(link->ddc,
+                                               &vendor_lttpr_write_data_adicora_eq3[0],
+                                               sizeof(vendor_lttpr_write_data_adicora_eq3));
+
                        } else
                                dpcd_set_lane_settings(link, lt_settings, 0);