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,
{
struct timing_generator *tg;
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 */
if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
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);
/* Instance should be within the range of the pool */
if (enc_inst >= dc->res_pool->pipe_count)
if (enc_inst == ENGINE_ID_UNKNOWN)
return false;
if (enc_inst >= dc->res_pool->stream_enc_count)
return false;
for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
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(
dc->res_pool->stream_enc[enc_inst]);
// tg_inst not found
if (i == dc->res_pool->stream_enc_count)
return false;
if (tg_inst >= dc->res_pool->timing_generator_count)
return false;
......
......@@ -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} };
uint8_t link_bw_set;
......@@ -554,17 +554,23 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
&link_bw_set, sizeof(link_bw_set));
if (link_bw_set == 0) {
/* If standard link rates are not being used,
* Read DPCD 00115h to find the link rate set used
*/
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 =
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;
if (link->connector_signal == SIGNAL_TYPE_EDP) {
/* 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));
// edp_supported_link_rates_count = 0 for DP
if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
link->cur_link_settings.link_rate =
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 {
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)
struct dpcd_caps prev_dpcd_caps;
bool same_dpcd = true;
enum dc_connection_type new_connection_type = dc_connection_none;
bool perform_dp_seamless_boot = false;
DC_LOGGER_INIT(link->ctx->logger);
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)
}
case SIGNAL_TYPE_EDP: {
read_edp_current_link_settings_on_detect(link);
read_current_link_settings_on_detect(link);
detect_edp_sink_caps(link);
sink_caps.transaction_type =
DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
sink_caps.signal = SIGNAL_TYPE_EDP;
break;
}
case SIGNAL_TYPE_DISPLAY_PORT: {
/* wa HPD high coming too early*/
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)
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;
}
......@@ -954,10 +972,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
* two link trainings
*/
/* deal with non-mst cases */
dp_verify_link_cap_with_retries(link,
&link->reported_link_cap,
LINK_TRAINING_MAX_VERIFY_RETRY);
// verify link cap for SST non-seamless boot
if (!perform_dp_seamless_boot)
dp_verify_link_cap_with_retries(link,
&link->reported_link_cap,
LINK_TRAINING_MAX_VERIFY_RETRY);
} else {
// If edid is the same, then discard new sink and revert back to original sink
if (same_edid) {
......
......@@ -1848,28 +1848,28 @@ static int acquire_resource_from_hw_enabled_state(
struct dc_stream_state *stream)
{
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 */
if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
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);
/* Instance should be within the range of the pool */
if (inst >= pool->pipe_count)
return -1;
if (inst == ENGINE_ID_UNKNOWN)
return false;
if (inst >= pool->stream_enc_count)
return -1;
for (i = 0; i < pool->stream_enc_count; i++) {
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)
return false;
......
......@@ -588,7 +588,7 @@ static void hubbub2_program_watermarks(
DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
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 = {
......@@ -600,7 +600,8 @@ static const struct hubbub_funcs hubbub2_funcs = {
.get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
.wm_read_state = hubbub2_wm_read_state,
.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,
......
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