Commit ad5594ad authored by Michael Strauss's avatar Michael Strauss Committed by Alex Deucher

drm/amd/display: Support Compliance Test Pattern Generation with DP2 Retimer

[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: default avatarHansen Dsouza <hansen.dsouza@amd.com>
Reviewed-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Acked-by: default avatarStylon Wang <stylon.wang@amd.com>
Signed-off-by: default avatarMichael Strauss <michael.strauss@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent dba24294
......@@ -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();
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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))
......
......@@ -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;
......
......@@ -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)
{
......
......@@ -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__ */
/*
* 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;
}
/*
* 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__ */
......@@ -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(
......
......@@ -28,9 +28,35 @@
#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__ */
/*
* 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;
}
/*
* 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__ */
......@@ -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;
......
......@@ -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)
{
......
......@@ -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,
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment