Commit 7f7652ee authored by Martin Leung's avatar Martin Leung Committed by Alex Deucher

drm/amd/display: enable single dp seamless boot

[why]
seamless boot didn't work for non edp's before

[how]
removed edp-specific code, made dp read uefi-set link settings. Also fixed
a hubbub code line to be consistent with usage of function.
Signed-off-by: default avatarMartin Leung <martin.leung@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c84ad0d6
...@@ -974,29 +974,33 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, ...@@ -974,29 +974,33 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
{ {
struct timing_generator *tg; struct timing_generator *tg;
struct dc_link *link = sink->link; struct dc_link *link = sink->link;
unsigned int enc_inst, tg_inst; unsigned int enc_inst, tg_inst, i;
// Seamless port only support single DP and EDP so far
if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
sink->sink_signal != SIGNAL_TYPE_EDP)
return false;
/* Check for enabled DIG to identify enabled display */ /* Check for enabled DIG to identify enabled display */
if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
return false; return false;
/* Check for which front end is used by this encoder.
* Note the inst is 1 indexed, where 0 is undefined.
* Note that DIG_FE can source from different OTG but our
* current implementation always map 1-to-1, so this code makes
* the same assumption and doesn't check OTG source.
*/
enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
/* Instance should be within the range of the pool */ if (enc_inst == ENGINE_ID_UNKNOWN)
if (enc_inst >= dc->res_pool->pipe_count)
return false; return false;
if (enc_inst >= dc->res_pool->stream_enc_count) for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
return false; if (dc->res_pool->stream_enc[i]->id == enc_inst) {
tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
dc->res_pool->stream_enc[i]);
break;
}
}
tg_inst = dc->res_pool->stream_enc[enc_inst]->funcs->dig_source_otg( // tg_inst not found
dc->res_pool->stream_enc[enc_inst]); if (i == dc->res_pool->stream_enc_count)
return false;
if (tg_inst >= dc->res_pool->timing_generator_count) if (tg_inst >= dc->res_pool->timing_generator_count)
return false; return false;
......
...@@ -519,7 +519,7 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin ...@@ -519,7 +519,7 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
} }
static void read_edp_current_link_settings_on_detect(struct dc_link *link) static void read_current_link_settings_on_detect(struct dc_link *link)
{ {
union lane_count_set lane_count_set = { {0} }; union lane_count_set lane_count_set = { {0} };
uint8_t link_bw_set; uint8_t link_bw_set;
...@@ -554,17 +554,23 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link) ...@@ -554,17 +554,23 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
&link_bw_set, sizeof(link_bw_set)); &link_bw_set, sizeof(link_bw_set));
if (link_bw_set == 0) { if (link_bw_set == 0) {
/* If standard link rates are not being used, if (link->connector_signal == SIGNAL_TYPE_EDP) {
* Read DPCD 00115h to find the link rate set used /* If standard link rates are not being used,
*/ * Read DPCD 00115h to find the edp link rate set used
core_link_read_dpcd(link, DP_LINK_RATE_SET, */
&link_rate_set, sizeof(link_rate_set)); core_link_read_dpcd(link, DP_LINK_RATE_SET,
&link_rate_set, sizeof(link_rate_set));
if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
link->cur_link_settings.link_rate = // edp_supported_link_rates_count = 0 for DP
link->dpcd_caps.edp_supported_link_rates[link_rate_set]; if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
link->cur_link_settings.link_rate_set = link_rate_set; link->cur_link_settings.link_rate =
link->cur_link_settings.use_link_rate_set = true; link->dpcd_caps.edp_supported_link_rates[link_rate_set];
link->cur_link_settings.link_rate_set = link_rate_set;
link->cur_link_settings.use_link_rate_set = true;
}
} else {
// Link Rate not found. Seamless boot may not work.
ASSERT(false);
} }
} else { } else {
link->cur_link_settings.link_rate = link_bw_set; link->cur_link_settings.link_rate = link_bw_set;
...@@ -752,6 +758,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -752,6 +758,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
struct dpcd_caps prev_dpcd_caps; struct dpcd_caps prev_dpcd_caps;
bool same_dpcd = true; bool same_dpcd = true;
enum dc_connection_type new_connection_type = dc_connection_none; enum dc_connection_type new_connection_type = dc_connection_none;
bool perform_dp_seamless_boot = false;
DC_LOGGER_INIT(link->ctx->logger); DC_LOGGER_INIT(link->ctx->logger);
if (dc_is_virtual_signal(link->connector_signal)) if (dc_is_virtual_signal(link->connector_signal))
...@@ -808,15 +815,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -808,15 +815,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
} }
case SIGNAL_TYPE_EDP: { case SIGNAL_TYPE_EDP: {
read_edp_current_link_settings_on_detect(link); read_current_link_settings_on_detect(link);
detect_edp_sink_caps(link); detect_edp_sink_caps(link);
sink_caps.transaction_type = sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
sink_caps.signal = SIGNAL_TYPE_EDP; sink_caps.signal = SIGNAL_TYPE_EDP;
break; break;
} }
case SIGNAL_TYPE_DISPLAY_PORT: { case SIGNAL_TYPE_DISPLAY_PORT: {
/* wa HPD high coming too early*/ /* wa HPD high coming too early*/
if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) { if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
...@@ -870,6 +877,17 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -870,6 +877,17 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
return false; return false;
} }
// For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified.
if (reason == DETECT_REASON_BOOT &&
dc_ctx->dc->config.power_down_display_on_boot == false &&
link->link_status.link_active == true)
perform_dp_seamless_boot = true;
if (perform_dp_seamless_boot) {
read_current_link_settings_on_detect(link);
link->verified_link_cap = link->reported_link_cap;
}
break; break;
} }
...@@ -954,10 +972,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -954,10 +972,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
* two link trainings * two link trainings
*/ */
/* deal with non-mst cases */ // verify link cap for SST non-seamless boot
dp_verify_link_cap_with_retries(link, if (!perform_dp_seamless_boot)
&link->reported_link_cap, dp_verify_link_cap_with_retries(link,
LINK_TRAINING_MAX_VERIFY_RETRY); &link->reported_link_cap,
LINK_TRAINING_MAX_VERIFY_RETRY);
} else { } else {
// If edid is the same, then discard new sink and revert back to original sink // If edid is the same, then discard new sink and revert back to original sink
if (same_edid) { if (same_edid) {
......
...@@ -1848,28 +1848,28 @@ static int acquire_resource_from_hw_enabled_state( ...@@ -1848,28 +1848,28 @@ static int acquire_resource_from_hw_enabled_state(
struct dc_stream_state *stream) struct dc_stream_state *stream)
{ {
struct dc_link *link = stream->link; struct dc_link *link = stream->link;
unsigned int inst, tg_inst; unsigned int inst, tg_inst, i;
/* Check for enabled DIG to identify enabled display */ /* Check for enabled DIG to identify enabled display */
if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
return -1; return -1;
/* Check for which front end is used by this encoder.
* Note the inst is 1 indexed, where 0 is undefined.
* Note that DIG_FE can source from different OTG but our
* current implementation always map 1-to-1, so this code makes
* the same assumption and doesn't check OTG source.
*/
inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
/* Instance should be within the range of the pool */ if (inst == ENGINE_ID_UNKNOWN)
if (inst >= pool->pipe_count) return false;
return -1;
if (inst >= pool->stream_enc_count) for (i = 0; i < pool->stream_enc_count; i++) {
return -1; if (pool->stream_enc[i]->id == inst) {
tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
pool->stream_enc[i]);
break;
}
}
tg_inst = pool->stream_enc[inst]->funcs->dig_source_otg(pool->stream_enc[inst]); // tg_inst not found
if (i == pool->stream_enc_count)
return false;
if (tg_inst >= pool->timing_generator_count) if (tg_inst >= pool->timing_generator_count)
return false; return false;
......
...@@ -588,7 +588,7 @@ static void hubbub2_program_watermarks( ...@@ -588,7 +588,7 @@ static void hubbub2_program_watermarks(
DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180); REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180);
hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); hubbub->funcs->allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
} }
static const struct hubbub_funcs hubbub2_funcs = { static const struct hubbub_funcs hubbub2_funcs = {
...@@ -600,7 +600,8 @@ static const struct hubbub_funcs hubbub2_funcs = { ...@@ -600,7 +600,8 @@ static const struct hubbub_funcs hubbub2_funcs = {
.get_dcc_compression_cap = hubbub2_get_dcc_compression_cap, .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
.wm_read_state = hubbub2_wm_read_state, .wm_read_state = hubbub2_wm_read_state,
.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
.program_watermarks = hubbub2_program_watermarks .program_watermarks = hubbub2_program_watermarks,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control
}; };
void hubbub2_construct(struct dcn20_hubbub *hubbub, void hubbub2_construct(struct dcn20_hubbub *hubbub,
......
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