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

drm/amd/display: Update FIXED_VS Retimer HWSS Test Pattern Sequences

[WHY]
Need to fix some broken logic and sequencing in initial commit

[HOW]
Fix logic handling override deprogramming when exiting SQ128.

Don't exit early from dp_set_hw_lane_settings for DP2/FIXED_VS case.

Move LTTPR 128b/132b check out of  requires_hwss and check during
runtime, as LTTPR caps are not populated on initial call.

Add pending_test_pattern to link state to allow HWSS to set FFE overrides
on retimer TX and/or skip setting APU TX FFE depending on requested pattern.

Use updated clock source for SQ128 override sequence.

Skip HW FFE preset programming when performing test pattern overrides.
Reviewed-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Acked-by: default avatarAurabindo Pillai <aurabindo.pillai@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 41364afe
...@@ -1572,7 +1572,19 @@ struct dc_link { ...@@ -1572,7 +1572,19 @@ struct dc_link {
enum engine_id dpia_preferred_eng_id; enum engine_id dpia_preferred_eng_id;
bool test_pattern_enabled; bool test_pattern_enabled;
/* Pending/Current test pattern are only used to perform and track
* FIXED_VS retimer test pattern/lane adjustment override state.
* Pending allows link HWSS to differentiate PHY vs non-PHY pattern,
* to perform specific lane adjust overrides before setting certain
* PHY test patterns. In cases when lane adjust and set test pattern
* calls are not performed atomically (i.e. performing link training),
* pending_test_pattern will be invalid or contain a non-PHY test pattern
* and current_test_pattern will contain required context for any future
* set pattern/set lane adjust to transition between override state(s).
* */
enum dp_test_pattern current_test_pattern; enum dp_test_pattern current_test_pattern;
enum dp_test_pattern pending_test_pattern;
union compliance_test_state compliance_test_state; union compliance_test_state compliance_test_state;
void *priv; void *priv;
......
...@@ -61,22 +61,6 @@ static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate) ...@@ -61,22 +61,6 @@ static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
} }
} }
static bool is_dp_phy_sqaure_pattern(enum dp_test_pattern test_pattern)
{
return (DP_TEST_PATTERN_SQUARE_BEGIN <= test_pattern &&
test_pattern <= DP_TEST_PATTERN_SQUARE_END);
}
static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
{
if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
return true;
else
return false;
}
static void dp_retrain_link_dp_test(struct dc_link *link, static void dp_retrain_link_dp_test(struct dc_link *link,
struct dc_link_settings *link_setting, struct dc_link_settings *link_setting,
bool skip_video_pattern) bool skip_video_pattern)
...@@ -361,7 +345,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) ...@@ -361,7 +345,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
test_pattern_size); test_pattern_size);
} }
if (is_dp_phy_sqaure_pattern(test_pattern)) { if (IS_DP_PHY_SQUARE_PATTERN(test_pattern)) {
test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
core_link_read_dpcd( core_link_read_dpcd(
link, link,
...@@ -623,6 +607,8 @@ bool dp_set_test_pattern( ...@@ -623,6 +607,8 @@ bool dp_set_test_pattern(
if (pipe_ctx == NULL) if (pipe_ctx == NULL)
return false; return false;
link->pending_test_pattern = test_pattern;
/* Reset CRTC Test Pattern if it is currently running and request is VideoMode */ /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
if (link->test_pattern_enabled && test_pattern == if (link->test_pattern_enabled && test_pattern ==
DP_TEST_PATTERN_VIDEO_MODE) { DP_TEST_PATTERN_VIDEO_MODE) {
...@@ -643,12 +629,13 @@ bool dp_set_test_pattern( ...@@ -643,12 +629,13 @@ bool dp_set_test_pattern(
/* Reset Test Pattern state */ /* Reset Test Pattern state */
link->test_pattern_enabled = false; link->test_pattern_enabled = false;
link->current_test_pattern = test_pattern; link->current_test_pattern = test_pattern;
link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
return true; return true;
} }
/* Check for PHY Test Patterns */ /* Check for PHY Test Patterns */
if (is_dp_phy_pattern(test_pattern)) { if (IS_DP_PHY_PATTERN(test_pattern)) {
/* Set DPCD Lane Settings before running test pattern */ /* Set DPCD Lane Settings before running test pattern */
if (p_link_settings != NULL) { if (p_link_settings != NULL) {
if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
...@@ -681,6 +668,7 @@ bool dp_set_test_pattern( ...@@ -681,6 +668,7 @@ bool dp_set_test_pattern(
/* Set Test Pattern state */ /* Set Test Pattern state */
link->test_pattern_enabled = true; link->test_pattern_enabled = true;
link->current_test_pattern = test_pattern; link->current_test_pattern = test_pattern;
link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
if (p_link_settings != NULL) if (p_link_settings != NULL)
dpcd_set_link_settings(link, dpcd_set_link_settings(link,
p_link_settings); p_link_settings);
...@@ -756,7 +744,7 @@ bool dp_set_test_pattern( ...@@ -756,7 +744,7 @@ bool dp_set_test_pattern(
return false; return false;
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
if (is_dp_phy_sqaure_pattern(test_pattern)) if (IS_DP_PHY_SQUARE_PATTERN(test_pattern))
core_link_write_dpcd(link, core_link_write_dpcd(link,
DP_LINK_SQUARE_PATTERN, DP_LINK_SQUARE_PATTERN,
p_custom_pattern, p_custom_pattern,
...@@ -884,6 +872,7 @@ bool dp_set_test_pattern( ...@@ -884,6 +872,7 @@ bool dp_set_test_pattern(
/* Set Test Pattern state */ /* Set Test Pattern state */
link->test_pattern_enabled = true; link->test_pattern_enabled = true;
link->current_test_pattern = test_pattern; link->current_test_pattern = test_pattern;
link->pending_test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
} }
return true; return true;
......
...@@ -80,21 +80,23 @@ static bool set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override(struct dc_ ...@@ -80,21 +80,23 @@ static bool set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override(struct dc_
const uint8_t vendor_lttpr_write_data_pg0[4] = {0x1, 0x11, 0x0, 0x0}; 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}; const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06};
if (!link->dpcd_caps.lttpr_caps.main_link_channel_coding.bits.DP_128b_132b_SUPPORTED)
return false;
if (tp_params == NULL) if (tp_params == NULL)
return false; return false;
if (link->current_test_pattern >= DP_TEST_PATTERN_SQUARE_BEGIN && if (IS_DP_PHY_SQUARE_PATTERN(link->current_test_pattern))
link->current_test_pattern <= DP_TEST_PATTERN_SQUARE_END) {
// Deprogram overrides from previous test pattern // Deprogram overrides from previous test pattern
dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link); dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link);
}
switch (tp_params->dp_phy_pattern) { switch (tp_params->dp_phy_pattern) {
case DP_TEST_PATTERN_80BIT_CUSTOM: case DP_TEST_PATTERN_80BIT_CUSTOM:
if (tp_params->custom_pattern_size == 0 || memcmp(tp_params->custom_pattern, if (tp_params->custom_pattern_size == 0 || memcmp(tp_params->custom_pattern,
pltpat_custom, tp_params->custom_pattern_size) != 0) pltpat_custom, tp_params->custom_pattern_size) != 0)
return false; return false;
hw_tp_params.custom_pattern = tp_params->custom_pattern;
hw_tp_params.custom_pattern_size = tp_params->custom_pattern_size;
break; break;
case DP_TEST_PATTERN_D102: case DP_TEST_PATTERN_D102:
break; break;
...@@ -185,13 +187,7 @@ static const struct link_hwss dio_fixed_vs_pe_retimer_link_hwss = { ...@@ -185,13 +187,7 @@ static const struct link_hwss dio_fixed_vs_pe_retimer_link_hwss = {
bool requires_fixed_vs_pe_retimer_dio_link_hwss(const struct dc_link *link) 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 (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) const struct link_hwss *get_dio_fixed_vs_pe_retimer_link_hwss(void)
......
...@@ -74,13 +74,16 @@ static void dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(struct dc_link *link, ...@@ -74,13 +74,16 @@ static void dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(struct dc_link *link,
static void dp_hpo_fixed_vs_pe_retimer_program_override_test_pattern(struct dc_link *link, 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) struct encoder_set_dp_phy_pattern_param *tp_params)
{ {
uint8_t clk_src = 0x4C;
uint8_t pattern = 0x4F; /* SQ128 */
const uint8_t vendor_lttpr_write_data_pg0[4] = {0x1, 0x11, 0x0, 0x0}; 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_pg1[4] = {0x1, 0x50, 0x50, clk_src};
const uint8_t vendor_lttpr_write_data_pg2[4] = {0x1, 0x51, 0x50, 0x0}; const uint8_t vendor_lttpr_write_data_pg2[4] = {0x1, 0x51, 0x50, clk_src};
const uint8_t vendor_lttpr_write_data_pg3[4] = {0x1, 0x10, 0x58, 0x21}; 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_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_pg5[4] = {0x1, 0x1C, 0x58, pattern};
const uint8_t vendor_lttpr_write_data_pg6[4] = {0x1, 0x1C, 0x59, 0x4F}; const uint8_t vendor_lttpr_write_data_pg6[4] = {0x1, 0x1C, 0x59, pattern};
const uint8_t vendor_lttpr_write_data_pg7[4] = {0x1, 0x30, 0x51, 0x20}; 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_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_pg9[4] = {0x1, 0x30, 0x54, 0x20};
...@@ -123,18 +126,20 @@ static bool dp_hpo_fixed_vs_pe_retimer_set_override_test_pattern(struct dc_link ...@@ -123,18 +126,20 @@ static bool dp_hpo_fixed_vs_pe_retimer_set_override_test_pattern(struct dc_link
struct encoder_set_dp_phy_pattern_param hw_tp_params = { 0 }; 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}; const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06};
if (!link->dpcd_caps.lttpr_caps.main_link_channel_coding.bits.DP_128b_132b_SUPPORTED)
return false;
if (tp_params == NULL) if (tp_params == NULL)
return false; return false;
if (tp_params->dp_phy_pattern < DP_TEST_PATTERN_SQUARE_BEGIN || if (!IS_DP_PHY_SQUARE_PATTERN(tp_params->dp_phy_pattern)) {
tp_params->dp_phy_pattern > DP_TEST_PATTERN_SQUARE_END) {
// Deprogram overrides from previously set square wave override // Deprogram overrides from previously set square wave override
if (link->current_test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM || if (link->current_test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM ||
link->current_test_pattern == DP_TEST_PATTERN_D102) link->current_test_pattern == DP_TEST_PATTERN_D102)
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc, link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
&vendor_lttpr_exit_manual_automation_0[0], &vendor_lttpr_exit_manual_automation_0[0],
sizeof(vendor_lttpr_exit_manual_automation_0)); sizeof(vendor_lttpr_exit_manual_automation_0));
else else if (IS_DP_PHY_SQUARE_PATTERN(link->current_test_pattern))
dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link); dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link);
return false; return false;
...@@ -148,8 +153,6 @@ static bool dp_hpo_fixed_vs_pe_retimer_set_override_test_pattern(struct dc_link ...@@ -148,8 +153,6 @@ static bool dp_hpo_fixed_vs_pe_retimer_set_override_test_pattern(struct dc_link
dp_hpo_fixed_vs_pe_retimer_program_override_test_pattern(link, 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; return true;
} }
...@@ -170,16 +173,18 @@ static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link, ...@@ -170,16 +173,18 @@ static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link,
const struct dc_link_settings *link_settings, const struct dc_link_settings *link_settings,
const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
{ {
// Don't update our HW FFE when outputting phy test patterns
if (IS_DP_PHY_PATTERN(link->pending_test_pattern)) {
// Directly program FIXED_VS retimer FFE for SQ128 override
if (IS_DP_PHY_SQUARE_PATTERN(link->pending_test_pattern)) {
dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(link, &lane_settings[0]);
}
} else {
link_res->hpo_dp_link_enc->funcs->set_ffe( link_res->hpo_dp_link_enc->funcs->set_ffe(
link_res->hpo_dp_link_enc, link_res->hpo_dp_link_enc,
link_settings, link_settings,
lane_settings[0].FFE_PRESET.raw); 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, static void enable_hpo_fixed_vs_pe_retimer_dp_link_output(struct dc_link *link,
...@@ -214,13 +219,7 @@ static const struct link_hwss hpo_fixed_vs_pe_retimer_dp_link_hwss = { ...@@ -214,13 +219,7 @@ static const struct link_hwss hpo_fixed_vs_pe_retimer_dp_link_hwss = {
bool requires_fixed_vs_pe_retimer_hpo_link_hwss(const struct dc_link *link) 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 requires_fixed_vs_pe_retimer_dio_link_hwss(link);
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) const struct link_hwss *get_hpo_fixed_vs_pe_retimer_dp_link_hwss(void)
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "clk_mgr.h" #include "clk_mgr.h"
#include "resource.h" #include "resource.h"
#include "link_enc_cfg.h" #include "link_enc_cfg.h"
#include "atomfirmware.h"
#define DC_LOGGER \ #define DC_LOGGER \
link->ctx->logger link->ctx->logger
...@@ -100,8 +101,11 @@ void dp_set_hw_lane_settings( ...@@ -100,8 +101,11 @@ void dp_set_hw_lane_settings(
{ {
const struct link_hwss *link_hwss = get_link_hwss(link, link_res); const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
// Don't return here if using FIXED_VS link HWSS and encoding is 128b/132b
if ((link_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && if ((link_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) &&
!is_immediate_downstream(link, offset)) !is_immediate_downstream(link, offset) &&
(!(link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) ||
link_dp_get_encoding_format(&link_settings->link_settings) == DP_8b_10b_ENCODING))
return; return;
if (link_hwss->ext.set_dp_lane_settings) if (link_hwss->ext.set_dp_lane_settings)
......
...@@ -169,6 +169,15 @@ enum dp_test_pattern { ...@@ -169,6 +169,15 @@ enum dp_test_pattern {
DP_TEST_PATTERN_UNSUPPORTED DP_TEST_PATTERN_UNSUPPORTED
}; };
#define IS_DP_PHY_SQUARE_PATTERN(test_pattern)\
(DP_TEST_PATTERN_SQUARE_BEGIN <= test_pattern &&\
test_pattern <= DP_TEST_PATTERN_SQUARE_END)
#define IS_DP_PHY_PATTERN(test_pattern)\
((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&\
test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||\
test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
enum dp_test_pattern_color_space { enum dp_test_pattern_color_space {
DP_TEST_PATTERN_COLOR_SPACE_RGB, DP_TEST_PATTERN_COLOR_SPACE_RGB,
DP_TEST_PATTERN_COLOR_SPACE_YCBCR601, DP_TEST_PATTERN_COLOR_SPACE_YCBCR601,
......
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