Commit 7211b605 authored by Jimmy Kizito's avatar Jimmy Kizito Committed by Alex Deucher

drm/amd/display: Update DP link configuration.

[Why & How]
- Update application of training settings for links whose encoders are
assigned dynamically.
- Add functionality useful for DP link configuration to public
interface.
Signed-off-by: default avatarJimmy Kizito <Jimmy.Kizito@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 68d9821f
...@@ -206,11 +206,12 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li ...@@ -206,11 +206,12 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li
return DP_TRAINING_PATTERN_SEQUENCE_2; return DP_TRAINING_PATTERN_SEQUENCE_2;
} }
static void dpcd_set_link_settings( enum dc_status dpcd_set_link_settings(
struct dc_link *link, struct dc_link *link,
const struct link_training_settings *lt_settings) const struct link_training_settings *lt_settings)
{ {
uint8_t rate; uint8_t rate;
enum dc_status status;
union down_spread_ctrl downspread = { {0} }; union down_spread_ctrl downspread = { {0} };
union lane_count_set lane_count_set = { {0} }; union lane_count_set lane_count_set = { {0} };
...@@ -225,15 +226,16 @@ static void dpcd_set_link_settings( ...@@ -225,15 +226,16 @@ static void dpcd_set_link_settings(
lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) { if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED; link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
} }
core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
&downspread.raw, sizeof(downspread)); &downspread.raw, sizeof(downspread));
core_link_write_dpcd(link, DP_LANE_COUNT_SET, status = core_link_write_dpcd(link, DP_LANE_COUNT_SET,
&lane_count_set.raw, 1); &lane_count_set.raw, 1);
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 && if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
...@@ -249,12 +251,12 @@ static void dpcd_set_link_settings( ...@@ -249,12 +251,12 @@ static void dpcd_set_link_settings(
core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
supported_link_rates, sizeof(supported_link_rates)); supported_link_rates, sizeof(supported_link_rates));
} }
core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
core_link_write_dpcd(link, DP_LINK_RATE_SET, status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
&lt_settings->link_settings.link_rate_set, 1); &lt_settings->link_settings.link_rate_set, 1);
} else { } else {
rate = (uint8_t) (lt_settings->link_settings.link_rate); rate = (uint8_t) (lt_settings->link_settings.link_rate);
core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
} }
if (rate) { if (rate) {
...@@ -278,6 +280,8 @@ static void dpcd_set_link_settings( ...@@ -278,6 +280,8 @@ static void dpcd_set_link_settings(
DP_DOWNSPREAD_CTRL, DP_DOWNSPREAD_CTRL,
lt_settings->link_settings.link_spread); lt_settings->link_settings.link_spread);
} }
return status;
} }
static uint8_t dc_dp_initialize_scrambling_data_symbols( static uint8_t dc_dp_initialize_scrambling_data_symbols(
...@@ -1329,7 +1333,7 @@ static inline void decide_8b_10b_training_settings( ...@@ -1329,7 +1333,7 @@ static inline void decide_8b_10b_training_settings(
lt_settings->enhanced_framing = 1; lt_settings->enhanced_framing = 1;
} }
static void decide_training_settings( void dp_decide_training_settings(
struct dc_link *link, struct dc_link *link,
const struct dc_link_settings *link_settings, const struct dc_link_settings *link_settings,
const struct dc_link_training_overrides *overrides, const struct dc_link_training_overrides *overrides,
...@@ -1365,18 +1369,18 @@ uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count) ...@@ -1365,18 +1369,18 @@ uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
return 0; // invalid value return 0; // invalid value
} }
static void configure_lttpr_mode_transparent(struct dc_link *link) enum dc_status configure_lttpr_mode_transparent(struct dc_link *link)
{ {
uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT; uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__); DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
core_link_write_dpcd(link, return core_link_write_dpcd(link,
DP_PHY_REPEATER_MODE, DP_PHY_REPEATER_MODE,
(uint8_t *)&repeater_mode, (uint8_t *)&repeater_mode,
sizeof(repeater_mode)); sizeof(repeater_mode));
} }
static void configure_lttpr_mode_non_transparent( enum dc_status configure_lttpr_mode_non_transparent(
struct dc_link *link, struct dc_link *link,
const struct link_training_settings *lt_settings) const struct link_training_settings *lt_settings)
{ {
...@@ -1431,6 +1435,8 @@ static void configure_lttpr_mode_non_transparent( ...@@ -1431,6 +1435,8 @@ static void configure_lttpr_mode_non_transparent(
} }
} }
} }
return result;
} }
static void repeater_training_done(struct dc_link *link, uint32_t offset) static void repeater_training_done(struct dc_link *link, uint32_t offset)
...@@ -1564,7 +1570,7 @@ bool dc_link_dp_perform_link_training_skip_aux( ...@@ -1564,7 +1570,7 @@ bool dc_link_dp_perform_link_training_skip_aux(
{ {
struct link_training_settings lt_settings; struct link_training_settings lt_settings;
decide_training_settings( dp_decide_training_settings(
link, link,
link_setting, link_setting,
&link->preferred_training_settings, &link->preferred_training_settings,
...@@ -1602,6 +1608,19 @@ bool dc_link_dp_perform_link_training_skip_aux( ...@@ -1602,6 +1608,19 @@ bool dc_link_dp_perform_link_training_skip_aux(
return true; return true;
} }
enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings)
{
enum dc_status status = DC_OK;
if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT)
status = configure_lttpr_mode_transparent(link);
else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
status = configure_lttpr_mode_non_transparent(link, lt_settings);
return status;
}
enum link_training_result dc_link_dp_perform_link_training( enum link_training_result dc_link_dp_perform_link_training(
struct dc_link *link, struct dc_link *link,
const struct dc_link_settings *link_setting, const struct dc_link_settings *link_setting,
...@@ -1614,7 +1633,7 @@ enum link_training_result dc_link_dp_perform_link_training( ...@@ -1614,7 +1633,7 @@ enum link_training_result dc_link_dp_perform_link_training(
uint8_t repeater_cnt; uint8_t repeater_cnt;
uint8_t repeater_id; uint8_t repeater_id;
decide_training_settings( dp_decide_training_settings(
link, link,
link_setting, link_setting,
&link->preferred_training_settings, &link->preferred_training_settings,
...@@ -1899,7 +1918,7 @@ enum link_training_result dc_link_dp_sync_lt_attempt( ...@@ -1899,7 +1918,7 @@ enum link_training_result dc_link_dp_sync_lt_attempt(
enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL; enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
bool fec_enable = false; bool fec_enable = false;
decide_training_settings( dp_decide_training_settings(
link, link,
link_settings, link_settings,
lt_overrides, lt_overrides,
...@@ -4606,50 +4625,74 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link) ...@@ -4606,50 +4625,74 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
return DP_PANEL_MODE_DEFAULT; return DP_PANEL_MODE_DEFAULT;
} }
void dp_set_fec_ready(struct dc_link *link, bool ready) enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready)
{ {
/* FEC has to be "set ready" before the link training. /* FEC has to be "set ready" before the link training.
* The policy is to always train with FEC * The policy is to always train with FEC
* if the sink supports it and leave it enabled on link. * if the sink supports it and leave it enabled on link.
* If FEC is not supported, disable it. * If FEC is not supported, disable it.
*/ */
struct link_encoder *link_enc = link->link_enc; struct link_encoder *link_enc = NULL;
enum dc_status status = DC_OK;
uint8_t fec_config = 0; uint8_t fec_config = 0;
/* Access link encoder based on whether it is statically
* or dynamically assigned to a link.
*/
if (link->is_dig_mapping_flexible &&
link->dc->res_pool->funcs->link_encs_assign)
link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
else
link_enc = link->link_enc;
ASSERT(link_enc);
if (!dc_link_should_enable_fec(link)) if (!dc_link_should_enable_fec(link))
return; return status;
if (link_enc->funcs->fec_set_ready && if (link_enc->funcs->fec_set_ready &&
link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) { link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
if (ready) { if (ready) {
fec_config = 1; fec_config = 1;
if (core_link_write_dpcd(link, status = core_link_write_dpcd(link,
DP_FEC_CONFIGURATION, DP_FEC_CONFIGURATION,
&fec_config, &fec_config,
sizeof(fec_config)) == DC_OK) { sizeof(fec_config));
if (status == DC_OK) {
link_enc->funcs->fec_set_ready(link_enc, true); link_enc->funcs->fec_set_ready(link_enc, true);
link->fec_state = dc_link_fec_ready; link->fec_state = dc_link_fec_ready;
} else { } else {
link->link_enc->funcs->fec_set_ready(link->link_enc, false); link_enc->funcs->fec_set_ready(link->link_enc, false);
link->fec_state = dc_link_fec_not_ready; link->fec_state = dc_link_fec_not_ready;
dm_error("dpcd write failed to set fec_ready"); dm_error("dpcd write failed to set fec_ready");
} }
} else if (link->fec_state == dc_link_fec_ready) { } else if (link->fec_state == dc_link_fec_ready) {
fec_config = 0; fec_config = 0;
core_link_write_dpcd(link, status = core_link_write_dpcd(link,
DP_FEC_CONFIGURATION, DP_FEC_CONFIGURATION,
&fec_config, &fec_config,
sizeof(fec_config)); sizeof(fec_config));
link->link_enc->funcs->fec_set_ready( link_enc->funcs->fec_set_ready(link_enc, false);
link->link_enc, false);
link->fec_state = dc_link_fec_not_ready; link->fec_state = dc_link_fec_not_ready;
} }
} }
return status;
} }
void dp_set_fec_enable(struct dc_link *link, bool enable) void dp_set_fec_enable(struct dc_link *link, bool enable)
{ {
struct link_encoder *link_enc = link->link_enc; struct link_encoder *link_enc = NULL;
/* Access link encoder based on whether it is statically
* or dynamically assigned to a link.
*/
if (link->is_dig_mapping_flexible &&
link->dc->res_pool->funcs->link_encs_assign)
link_enc = link_enc_cfg_get_link_enc_used_by_link(
link->dc->current_state, link);
else
link_enc = link->link_enc;
ASSERT(link_enc);
if (!dc_link_should_enable_fec(link)) if (!dc_link_should_enable_fec(link))
return; return;
......
...@@ -92,8 +92,12 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode); ...@@ -92,8 +92,12 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode);
bool dp_overwrite_extended_receiver_cap(struct dc_link *link); bool dp_overwrite_extended_receiver_cap(struct dc_link *link);
void dpcd_set_source_specific_data(struct dc_link *link); void dpcd_set_source_specific_data(struct dc_link *link);
/* Write DPCD link configuration data. */
enum dc_status dpcd_set_link_settings(
struct dc_link *link,
const struct link_training_settings *lt_settings);
void dp_set_fec_ready(struct dc_link *link, bool ready); enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready);
void dp_set_fec_enable(struct dc_link *link, bool enable); void dp_set_fec_enable(struct dc_link *link, bool enable);
bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable);
bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable); bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable);
...@@ -101,6 +105,13 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); ...@@ -101,6 +105,13 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable);
bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx); bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx);
bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable); bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable);
/* Initialize output parameter lt_settings. */
void dp_decide_training_settings(
struct dc_link *link,
const struct dc_link_settings *link_setting,
const struct dc_link_training_overrides *overrides,
struct link_training_settings *lt_settings);
/* Convert PHY repeater count read from DPCD uint8_t. */ /* Convert PHY repeater count read from DPCD uint8_t. */
uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count); uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count);
...@@ -109,5 +120,9 @@ enum link_training_result dp_check_link_loss_status( ...@@ -109,5 +120,9 @@ enum link_training_result dp_check_link_loss_status(
struct dc_link *link, struct dc_link *link,
const struct link_training_settings *link_training_setting); const struct link_training_settings *link_training_setting);
enum dc_status dpcd_configure_lttpr_mode(
struct dc_link *link,
struct link_training_settings *lt_settings);
enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings);
#endif /* __DC_LINK_DP_H__ */ #endif /* __DC_LINK_DP_H__ */
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