From e84ecdc5bd753632a90ec1eba26f9bb198030d08 Mon Sep 17 00:00:00 2001 From: Jimmy Kizito Date: Tue, 27 Apr 2021 18:46:11 -0400 Subject: [PATCH] drm/amd/display: Expand DP module clock recovery API. [Why & How] Add functionality useful for DP clock recovery phase of link training to public interface. Signed-off-by: Jimmy Kizito Reviewed-by: Jun Lei Acked-by: Qingqing Zhuo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 79 +++++++++---------- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 49 ++++++++++++ 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index f77cc38cbdb4..425409ea5a7e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -25,8 +25,6 @@ static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA"; link->ctx->logger #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ -#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50 - /* maximum pre emphasis level allowed for each voltage swing level*/ static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3, @@ -39,14 +37,6 @@ enum { POST_LT_ADJ_REQ_TIMEOUT = 200 }; -enum { - LINK_TRAINING_MAX_RETRY_COUNT = 5, - /* to avoid infinite loop where-in the receiver - * switches between different VS - */ - LINK_TRAINING_MAX_CR_RETRY = 100 -}; - static bool decide_fallback_link_setting( struct dc_link_settings initial_link_settings, struct dc_link_settings *current_link_setting, @@ -97,7 +87,7 @@ static uint32_t get_eq_training_aux_rd_interval( return wait_in_micro_secs; } -static void wait_for_training_aux_rd_interval( +void dp_wait_for_training_aux_rd_interval( struct dc_link *link, uint32_t wait_in_micro_secs) { @@ -108,7 +98,7 @@ static void wait_for_training_aux_rd_interval( wait_in_micro_secs); } -static enum dpcd_training_patterns +enum dpcd_training_patterns dc_dp_training_pattern_to_dpcd_training_pattern( struct dc_link *link, enum dc_dp_training_pattern pattern) @@ -284,7 +274,7 @@ enum dc_status dpcd_set_link_settings( return status; } -static uint8_t dc_dp_initialize_scrambling_data_symbols( +uint8_t dc_dp_initialize_scrambling_data_symbols( struct dc_link *link, enum dc_dp_training_pattern pattern) { @@ -433,7 +423,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( link->cur_lane_setting = lt_settings->lane_settings[0]; } -static bool is_cr_done(enum dc_lane_count ln_count, +bool dp_is_cr_done(enum dc_lane_count ln_count, union lane_status *dpcd_lane_status) { uint32_t lane; @@ -472,7 +462,7 @@ static inline bool is_interlane_aligned(union lane_align_status_updated align_st return align_status.bits.INTERLANE_ALIGN_DONE == 1; } -static void update_drive_settings( +void dp_update_drive_settings( struct link_training_settings *dest, struct link_training_settings src) { @@ -616,7 +606,7 @@ static void find_max_drive_settings( } -static void get_lane_status_and_drive_settings( +enum dc_status dp_get_lane_status_and_drive_settings( struct dc_link *link, const struct link_training_settings *link_training_setting, union lane_status *ln_status, @@ -631,6 +621,7 @@ static void get_lane_status_and_drive_settings( union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } }; struct link_training_settings request_settings = { {0} }; uint32_t lane; + enum dc_status status; memset(req_settings, '\0', sizeof(struct link_training_settings)); @@ -641,7 +632,7 @@ static void get_lane_status_and_drive_settings( lane_adjust_offset = 3; } - core_link_read_dpcd( + status = core_link_read_dpcd( link, lane01_status_address, (uint8_t *)(dpcd_buf), @@ -729,9 +720,10 @@ static void get_lane_status_and_drive_settings( * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C */ + return status; } -static void dpcd_set_lane_settings( +enum dc_status dpcd_set_lane_settings( struct dc_link *link, const struct link_training_settings *link_training_setting, uint32_t offset) @@ -739,6 +731,7 @@ static void dpcd_set_lane_settings( union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; uint32_t lane; unsigned int lane0_set_address; + enum dc_status status; lane0_set_address = DP_TRAINING_LANE0_SET; @@ -766,7 +759,7 @@ static void dpcd_set_lane_settings( PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); } - core_link_write_dpcd(link, + status = core_link_write_dpcd(link, lane0_set_address, (uint8_t *)(dpcd_lane), link_training_setting->link_settings.lane_count); @@ -812,9 +805,10 @@ static void dpcd_set_lane_settings( } link->cur_lane_setting = link_training_setting->lane_settings[0]; + return status; } -static bool is_max_vs_reached( +bool dp_is_max_vs_reached( const struct link_training_settings *lt_settings) { uint32_t lane; @@ -856,19 +850,19 @@ static bool perform_post_lt_adj_req_sequence( union lane_align_status_updated dpcd_lane_status_updated; - get_lane_status_and_drive_settings( - link, - lt_settings, - dpcd_lane_status, - &dpcd_lane_status_updated, - &req_settings, - DPRX); + dp_get_lane_status_and_drive_settings( + link, + lt_settings, + dpcd_lane_status, + &dpcd_lane_status_updated, + &req_settings, + DPRX); if (dpcd_lane_status_updated.bits. POST_LT_ADJ_REQ_IN_PROGRESS == 0) return true; - if (!is_cr_done(lane_count, dpcd_lane_status)) + if (!dp_is_cr_done(lane_count, dpcd_lane_status)) return false; if (!is_ch_eq_done(lane_count, dpcd_lane_status) || @@ -891,7 +885,7 @@ static bool perform_post_lt_adj_req_sequence( } if (req_drv_setting_changed) { - update_drive_settings( + dp_update_drive_settings( lt_settings, req_settings); dc_link_dp_set_drive_settings(link, @@ -943,7 +937,7 @@ static uint32_t translate_training_aux_read_interval(uint32_t dpcd_aux_read_inte return aux_rd_interval_us; } -static enum link_training_result get_cr_failure(enum dc_lane_count ln_count, +enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count, union lane_status *dpcd_lane_status) { enum link_training_result result = LINK_TRAINING_SUCCESS; @@ -1007,14 +1001,14 @@ static enum link_training_result perform_channel_equalization_sequence( translate_training_aux_read_interval( link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]); - wait_for_training_aux_rd_interval( + dp_wait_for_training_aux_rd_interval( link, wait_time_microsec); /* 4. Read lane status and requested * drive settings as set by the sink*/ - get_lane_status_and_drive_settings( + dp_get_lane_status_and_drive_settings( link, lt_settings, dpcd_lane_status, @@ -1023,7 +1017,7 @@ static enum link_training_result perform_channel_equalization_sequence( offset); /* 5. check CR done*/ - if (!is_cr_done(lane_count, dpcd_lane_status)) + if (!dp_is_cr_done(lane_count, dpcd_lane_status)) return LINK_TRAINING_EQ_FAIL_CR; /* 6. check CHEQ done*/ @@ -1033,13 +1027,12 @@ static enum link_training_result perform_channel_equalization_sequence( return LINK_TRAINING_SUCCESS; /* 7. update VS/PE/PC2 in lt_settings*/ - update_drive_settings(lt_settings, req_settings); + dp_update_drive_settings(lt_settings, req_settings); } return LINK_TRAINING_EQ_FAIL_EQ; } -#define TRAINING_AUX_RD_INTERVAL 100 //us static void start_clock_recovery_pattern_early(struct dc_link *link, struct link_training_settings *lt_settings, @@ -1110,14 +1103,14 @@ static enum link_training_result perform_clock_recovery_sequence( if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) wait_time_microsec = TRAINING_AUX_RD_INTERVAL; - wait_for_training_aux_rd_interval( + dp_wait_for_training_aux_rd_interval( link, wait_time_microsec); /* 4. Read lane status and requested drive * settings as set by the sink */ - get_lane_status_and_drive_settings( + dp_get_lane_status_and_drive_settings( link, lt_settings, dpcd_lane_status, @@ -1126,11 +1119,11 @@ static enum link_training_result perform_clock_recovery_sequence( offset); /* 5. check CR done*/ - if (is_cr_done(lane_count, dpcd_lane_status)) + if (dp_is_cr_done(lane_count, dpcd_lane_status)) return LINK_TRAINING_SUCCESS; /* 6. max VS reached*/ - if (is_max_vs_reached(lt_settings)) + if (dp_is_max_vs_reached(lt_settings)) break; /* 7. same lane settings*/ @@ -1145,7 +1138,7 @@ static enum link_training_result perform_clock_recovery_sequence( retries_cr = 0; /* 8. update VS/PE/PC2 in lt_settings*/ - update_drive_settings(lt_settings, req_settings); + dp_update_drive_settings(lt_settings, req_settings); retry_count++; } @@ -1158,7 +1151,7 @@ static enum link_training_result perform_clock_recovery_sequence( } - return get_cr_failure(lane_count, dpcd_lane_status); + return dp_get_cr_failure(lane_count, dpcd_lane_status); } static inline enum link_training_result dp_transition_to_video_idle( @@ -1585,7 +1578,7 @@ bool dc_link_dp_perform_link_training_skip_aux( dp_set_hw_lane_settings(link, <_settings, DPRX); /* wait receiver to lock-on*/ - wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time); + dp_wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time); /* 2. Perform_channel_equalization_sequence. */ @@ -1596,7 +1589,7 @@ bool dc_link_dp_perform_link_training_skip_aux( dp_set_hw_lane_settings(link, <_settings, DPRX); /* wait receiver to lock-on. */ - wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time); + dp_wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time); /* 3. Perform_link_training_int. */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index be1c5d822704..bbb054f58fe2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -30,11 +30,21 @@ #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ #define LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD 3200 /*us*/ #define LINK_AUX_DEFAULT_TIMEOUT_PERIOD 552 /*us*/ +#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50 +#define TRAINING_AUX_RD_INTERVAL 100 //us struct dc_link; struct dc_stream_state; struct dc_link_settings; +enum { + LINK_TRAINING_MAX_RETRY_COUNT = 5, + /* to avoid infinite loop where-in the receiver + * switches between different VS + */ + LINK_TRAINING_MAX_CR_RETRY = 100 +}; + bool dp_verify_link_cap( struct dc_link *link, struct dc_link_settings *known_limit_link_setting, @@ -96,6 +106,45 @@ void dpcd_set_source_specific_data(struct dc_link *link); enum dc_status dpcd_set_link_settings( struct dc_link *link, const struct link_training_settings *lt_settings); +/* Write DPCD drive settings. */ +enum dc_status dpcd_set_lane_settings( + struct dc_link *link, + 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( + 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, + uint32_t offset); + +void dp_wait_for_training_aux_rd_interval( + struct dc_link *link, + uint32_t wait_in_micro_secs); + +bool dp_is_cr_done(enum dc_lane_count ln_count, + union lane_status *dpcd_lane_status); + +enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count, + union lane_status *dpcd_lane_status); + +bool dp_is_max_vs_reached( + const struct link_training_settings *lt_settings); + +void dp_update_drive_settings( + struct link_training_settings *dest, + struct link_training_settings src); + +enum dpcd_training_patterns + dc_dp_training_pattern_to_dpcd_training_pattern( + struct dc_link *link, + enum dc_dp_training_pattern pattern); + +uint8_t dc_dp_initialize_scrambling_data_symbols( + struct dc_link *link, + enum dc_dp_training_pattern pattern); enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready); void dp_set_fec_enable(struct dc_link *link, bool enable); -- 2.39.5