Commit c224aac8 authored by Wenjing Liu's avatar Wenjing Liu Committed by Alex Deucher

drm/amd/display: implement decide lane settings

[why]
Decouple lane settings decision logic all to its own function. The
function takes in lane adjust array and link training settings and
decide what hw lane setting and dpcd lane setting should be used.
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 5354b2bd
......@@ -263,10 +263,12 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
uint32_t retry_count = 0;
/* From DP spec, CR read interval is always 100us. */
uint32_t wait_time_microsec = TRAINING_AUX_RD_INTERVAL;
struct link_training_settings req_settings;
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX] = { { {0} } };
uint8_t set_cfg_data;
enum dpia_set_config_ts ts;
......@@ -345,11 +347,12 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
/* Read status and adjustment requests from DPCD. */
status = dp_get_lane_status_and_drive_settings(link,
status = dp_get_lane_status_and_lane_adjust(
link,
lt_settings,
dpcd_lane_status,
&dpcd_lane_status_updated,
&req_settings,
dpcd_lane_adjust,
hop);
if (status != DC_OK) {
result = LINK_TRAINING_ABORT;
......@@ -371,16 +374,18 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
* Note: settings are the same for all lanes,
* so comparing first lane is sufficient.
*/
if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
req_settings.lane_settings[0].VOLTAGE_SWING &&
lt_settings->lane_settings[0].PRE_EMPHASIS ==
req_settings.lane_settings[0].PRE_EMPHASIS)
if ((lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
&& (lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET ==
dpcd_lane_adjust[0].bits.PRE_EMPHASIS_LANE))
retries_cr++;
else
retries_cr = 0;
/* Update VS/PE. */
dp_update_drive_settings(lt_settings, req_settings);
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
lt_settings->lane_settings,
dpcd_lane_settings);
retry_count++;
}
......@@ -416,10 +421,11 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
uint32_t retries_cr = 0; /* Number of consecutive attempts with same VS or PE. */
uint32_t retry_count = 0;
uint32_t wait_time_microsec = lt_settings->cr_pattern_time;
struct link_training_settings req_settings;
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX] = { { {0} } };
/* Cap of LINK_TRAINING_MAX_CR_RETRY attempts at clock recovery.
* Fix inherited from perform_clock_recovery_sequence() -
......@@ -445,11 +451,12 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
/* Read status and adjustment requests from DPCD. */
status = dp_get_lane_status_and_drive_settings(link,
status = dp_get_lane_status_and_lane_adjust(
link,
lt_settings,
dpcd_lane_status,
&dpcd_lane_status_updated,
&req_settings,
dpcd_lane_adjust,
DPRX);
if (status != DC_OK) {
result = LINK_TRAINING_ABORT;
......@@ -471,16 +478,17 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
* Note: settings are the same for all lanes,
* so comparing first lane is sufficient.
*/
if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
req_settings.lane_settings[0].VOLTAGE_SWING &&
lt_settings->lane_settings[0].PRE_EMPHASIS ==
req_settings.lane_settings[0].PRE_EMPHASIS)
if ((lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
&& (lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET ==
dpcd_lane_adjust[0].bits.PRE_EMPHASIS_LANE))
retries_cr++;
else
retries_cr = 0;
/* Update VS/PE. */
dp_update_drive_settings(lt_settings, req_settings);
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
retry_count++;
}
......@@ -566,10 +574,11 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
enum dc_status status;
enum dc_dp_training_pattern tr_pattern;
uint32_t wait_time_microsec;
struct link_training_settings req_settings;
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX] = { { {0} } };
uint8_t set_cfg_data;
enum dpia_set_config_ts ts;
......@@ -639,11 +648,12 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
/* Read status and adjustment requests from DPCD. */
status = dp_get_lane_status_and_drive_settings(link,
status = dp_get_lane_status_and_lane_adjust(
link,
lt_settings,
dpcd_lane_status,
&dpcd_lane_status_updated,
&req_settings,
dpcd_lane_adjust,
hop);
if (status != DC_OK) {
result = LINK_TRAINING_ABORT;
......@@ -664,7 +674,8 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
}
/* Update VS/PE. */
dp_update_drive_settings(lt_settings, req_settings);
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
lt_settings->lane_settings, dpcd_lane_settings);
}
/* Abort link training if equalization failed due to HPD unplug. */
......@@ -701,10 +712,11 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
enum dc_status status;
enum dc_dp_training_pattern tr_pattern = lt_settings->pattern_for_eq;
uint32_t wait_time_microsec;
struct link_training_settings req_settings;
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX] = { { {0} } };
wait_time_microsec = dpia_get_eq_aux_rd_interval(link, lt_settings, DPRX);
......@@ -720,11 +732,12 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
/* Read status and adjustment requests from DPCD. */
status = dp_get_lane_status_and_drive_settings(link,
status = dp_get_lane_status_and_lane_adjust(
link,
lt_settings,
dpcd_lane_status,
&dpcd_lane_status_updated,
&req_settings,
dpcd_lane_adjust,
DPRX);
if (status != DC_OK) {
result = LINK_TRAINING_ABORT;
......@@ -745,7 +758,8 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
}
/* Update VS/PE. */
dp_update_drive_settings(lt_settings, req_settings);
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
lt_settings->lane_settings, dpcd_lane_settings);
}
/* Abort link training if equalization failed due to HPD unplug. */
......
......@@ -121,12 +121,12 @@ enum dc_status dpcd_set_lane_settings(
const struct link_training_settings *link_training_setting,
uint32_t offset);
/* Read training status and adjustment requests from DPCD. */
enum dc_status dp_get_lane_status_and_drive_settings(
enum dc_status dp_get_lane_status_and_lane_adjust(
struct dc_link *link,
const struct link_training_settings *link_training_setting,
union lane_status *ln_status,
union lane_align_status_updated *ln_status_updated,
struct link_training_settings *req_settings,
union lane_status ln_status[LANE_COUNT_DP_MAX],
union lane_align_status_updated *ln_align,
union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
uint32_t offset);
void dp_wait_for_training_aux_rd_interval(
......@@ -151,9 +151,11 @@ void dp_hw_to_dpcd_lane_settings(
const struct link_training_settings *lt_settings,
const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX]);
void dp_update_drive_settings(
struct link_training_settings *dest,
struct link_training_settings src);
void dp_decide_lane_settings(
const struct link_training_settings *lt_settings,
const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX]);
uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval);
......
......@@ -123,6 +123,23 @@ struct link_training_settings {
/* dpcd lane settings will always use the same hw lane settings
* even if it doesn't match requested lane adjust */
bool always_match_dpcd_with_hw_lane_settings;
/*****************************************************************
* training states - parameters that can change in link training
*****************************************************************/
/* TODO: Move hw_lane_settings and dpcd_lane_settings
* along with lane adjust, lane align, offset and all
* other training states into a new structure called
* training states, so link_training_settings becomes
* a constant input pre-decided prior to link training.
*
* The goal is to strictly decouple link training settings
* decision making process from link training states to
* prevent it from messy code practice of changing training
* decision on the fly.
*/
struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX];
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX];
};
/*TODO: Move this enum test harness*/
......
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