mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 08:58:07 +00:00
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: Jimmy Kizito <Jimmy.Kizito@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
68d9821ff4
commit
7211b60514
2 changed files with 83 additions and 25 deletions
|
@ -206,11 +206,12 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li
|
|||
return DP_TRAINING_PATTERN_SEQUENCE_2;
|
||||
}
|
||||
|
||||
static void dpcd_set_link_settings(
|
||||
enum dc_status dpcd_set_link_settings(
|
||||
struct dc_link *link,
|
||||
const struct link_training_settings *lt_settings)
|
||||
{
|
||||
uint8_t rate;
|
||||
enum dc_status status;
|
||||
|
||||
union down_spread_ctrl downspread = { {0} };
|
||||
union lane_count_set lane_count_set = { {0} };
|
||||
|
@ -225,15 +226,16 @@ static void dpcd_set_link_settings(
|
|||
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 =
|
||||
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));
|
||||
|
||||
core_link_write_dpcd(link, DP_LANE_COUNT_SET,
|
||||
status = core_link_write_dpcd(link, DP_LANE_COUNT_SET,
|
||||
&lane_count_set.raw, 1);
|
||||
|
||||
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
|
||||
|
@ -249,12 +251,12 @@ static void dpcd_set_link_settings(
|
|||
core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
|
||||
supported_link_rates, sizeof(supported_link_rates));
|
||||
}
|
||||
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_BW_SET, &rate, 1);
|
||||
status = core_link_write_dpcd(link, DP_LINK_RATE_SET,
|
||||
<_settings->link_settings.link_rate_set, 1);
|
||||
} else {
|
||||
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) {
|
||||
|
@ -278,6 +280,8 @@ static void dpcd_set_link_settings(
|
|||
DP_DOWNSPREAD_CTRL,
|
||||
lt_settings->link_settings.link_spread);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint8_t dc_dp_initialize_scrambling_data_symbols(
|
||||
|
@ -1329,7 +1333,7 @@ static inline void decide_8b_10b_training_settings(
|
|||
lt_settings->enhanced_framing = 1;
|
||||
}
|
||||
|
||||
static void decide_training_settings(
|
||||
void dp_decide_training_settings(
|
||||
struct dc_link *link,
|
||||
const struct dc_link_settings *link_settings,
|
||||
const struct dc_link_training_overrides *overrides,
|
||||
|
@ -1365,18 +1369,18 @@ uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
|
|||
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;
|
||||
|
||||
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,
|
||||
(uint8_t *)&repeater_mode,
|
||||
sizeof(repeater_mode));
|
||||
}
|
||||
|
||||
static void configure_lttpr_mode_non_transparent(
|
||||
enum dc_status configure_lttpr_mode_non_transparent(
|
||||
struct dc_link *link,
|
||||
const struct link_training_settings *lt_settings)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -1564,7 +1570,7 @@ bool dc_link_dp_perform_link_training_skip_aux(
|
|||
{
|
||||
struct link_training_settings lt_settings;
|
||||
|
||||
decide_training_settings(
|
||||
dp_decide_training_settings(
|
||||
link,
|
||||
link_setting,
|
||||
&link->preferred_training_settings,
|
||||
|
@ -1602,6 +1608,19 @@ bool dc_link_dp_perform_link_training_skip_aux(
|
|||
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(
|
||||
struct dc_link *link,
|
||||
const struct dc_link_settings *link_setting,
|
||||
|
@ -1614,7 +1633,7 @@ enum link_training_result dc_link_dp_perform_link_training(
|
|||
uint8_t repeater_cnt;
|
||||
uint8_t repeater_id;
|
||||
|
||||
decide_training_settings(
|
||||
dp_decide_training_settings(
|
||||
link,
|
||||
link_setting,
|
||||
&link->preferred_training_settings,
|
||||
|
@ -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;
|
||||
bool fec_enable = false;
|
||||
|
||||
decide_training_settings(
|
||||
dp_decide_training_settings(
|
||||
link,
|
||||
link_settings,
|
||||
lt_overrides,
|
||||
|
@ -4606,50 +4625,74 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
|
|||
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.
|
||||
* The policy is to always train with FEC
|
||||
* if the sink supports it and leave it enabled on link.
|
||||
* 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;
|
||||
|
||||
/* 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))
|
||||
return;
|
||||
return status;
|
||||
|
||||
if (link_enc->funcs->fec_set_ready &&
|
||||
link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
|
||||
if (ready) {
|
||||
fec_config = 1;
|
||||
if (core_link_write_dpcd(link,
|
||||
status = core_link_write_dpcd(link,
|
||||
DP_FEC_CONFIGURATION,
|
||||
&fec_config,
|
||||
sizeof(fec_config)) == DC_OK) {
|
||||
sizeof(fec_config));
|
||||
if (status == DC_OK) {
|
||||
link_enc->funcs->fec_set_ready(link_enc, true);
|
||||
link->fec_state = dc_link_fec_ready;
|
||||
} 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;
|
||||
dm_error("dpcd write failed to set fec_ready");
|
||||
}
|
||||
} else if (link->fec_state == dc_link_fec_ready) {
|
||||
fec_config = 0;
|
||||
core_link_write_dpcd(link,
|
||||
status = core_link_write_dpcd(link,
|
||||
DP_FEC_CONFIGURATION,
|
||||
&fec_config,
|
||||
sizeof(fec_config));
|
||||
link->link_enc->funcs->fec_set_ready(
|
||||
link->link_enc, false);
|
||||
link_enc->funcs->fec_set_ready(link_enc, false);
|
||||
link->fec_state = dc_link_fec_not_ready;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
|
|
|
@ -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);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
@ -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_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. */
|
||||
uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count);
|
||||
|
||||
|
@ -109,5 +120,9 @@ enum link_training_result dp_check_link_loss_status(
|
|||
struct dc_link *link,
|
||||
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);
|
||||
#endif /* __DC_LINK_DP_H__ */
|
||||
|
|
Loading…
Reference in a new issue