Commit 5b7c0d8d authored by Anthony Koo's avatar Anthony Koo Committed by Alex Deucher

drm/amd/display: Fix eDP Black screen after S4 resume

[Why]
Power down of PHY on eDP requires us to call eDP power
control to power on again

[How]
1. In the case link rates don't match, disable PHY
requires calling of eDP power control ON after

2. Link disable case limit to eDP path since
this is not really applicable to DP since we do
power down PHY as part of verify link cap

3. Move detection of eDP link settings to be
done even for S4 resume cases where other
dpcd cap read and edid read can be skipped
Signed-off-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent abdef755
...@@ -514,6 +514,40 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin ...@@ -514,6 +514,40 @@ 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)
{
union lane_count_set lane_count_set = { {0} };
uint8_t link_bw_set;
uint8_t link_rate_set;
// Read DPCD 00101h to find out the number of lanes currently set
core_link_read_dpcd(link, DP_LANE_COUNT_SET,
&lane_count_set.raw, sizeof(lane_count_set));
link->cur_link_settings.lane_count = lane_count_set.bits.LANE_COUNT_SET;
// Read DPCD 00100h to find if standard link rates are set
core_link_read_dpcd(link, DP_LINK_BW_SET,
&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;
}
} else {
link->cur_link_settings.link_rate = link_bw_set;
link->cur_link_settings.use_link_rate_set = false;
}
}
static bool detect_dp( static bool detect_dp(
struct dc_link *link, struct dc_link *link,
struct display_sink_capability *sink_caps, struct display_sink_capability *sink_caps,
...@@ -648,9 +682,14 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -648,9 +682,14 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
return false; return false;
} }
if (link->connector_signal == SIGNAL_TYPE_EDP && if (link->connector_signal == SIGNAL_TYPE_EDP) {
link->local_sink) /* On detect, we want to make sure current link settings are
return true; * up to date, especially if link was powered on by GOP.
*/
read_edp_current_link_settings_on_detect(link);
if (link->local_sink)
return true;
}
if (link->connector_signal == SIGNAL_TYPE_LVDS && if (link->connector_signal == SIGNAL_TYPE_LVDS &&
link->local_sink) link->local_sink)
...@@ -1396,13 +1435,19 @@ static enum dc_status enable_link_dp( ...@@ -1396,13 +1435,19 @@ static enum dc_status enable_link_dp(
/* get link settings for video mode timing */ /* get link settings for video mode timing */
decide_link_settings(stream, &link_settings); decide_link_settings(stream, &link_settings);
/* If link settings are different than current and link already enabled if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {
* then need to disable before programming to new rate. /* If link settings are different than current and link already enabled
*/ * then need to disable before programming to new rate.
if (link->link_status.link_active && */
(link->cur_link_settings.lane_count != link_settings.lane_count || if (link->link_status.link_active &&
link->cur_link_settings.link_rate != link_settings.link_rate)) { (link->cur_link_settings.lane_count != link_settings.lane_count ||
dp_disable_link_phy(link, pipe_ctx->stream->signal); link->cur_link_settings.link_rate != link_settings.link_rate)) {
dp_disable_link_phy(link, pipe_ctx->stream->signal);
}
/*in case it is not on*/
link->dc->hwss.edp_power_control(link, true);
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
} }
pipe_ctx->stream_res.pix_clk_params.requested_sym_clk = pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
...@@ -1448,15 +1493,9 @@ static enum dc_status enable_link_edp( ...@@ -1448,15 +1493,9 @@ static enum dc_status enable_link_edp(
struct pipe_ctx *pipe_ctx) struct pipe_ctx *pipe_ctx)
{ {
enum dc_status status; enum dc_status status;
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
/*in case it is not on*/
link->dc->hwss.edp_power_control(link, true);
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
status = enable_link_dp(state, pipe_ctx); status = enable_link_dp(state, pipe_ctx);
return status; return status;
} }
......
...@@ -2586,9 +2586,6 @@ void detect_edp_sink_caps(struct dc_link *link) ...@@ -2586,9 +2586,6 @@ void detect_edp_sink_caps(struct dc_link *link)
uint32_t entry; uint32_t entry;
uint32_t link_rate_in_khz; uint32_t link_rate_in_khz;
enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
union lane_count_set lane_count_set = { {0} };
uint8_t link_bw_set;
uint8_t link_rate_set;
retrieve_link_cap(link); retrieve_link_cap(link);
link->dpcd_caps.edp_supported_link_rates_count = 0; link->dpcd_caps.edp_supported_link_rates_count = 0;
...@@ -2614,33 +2611,6 @@ void detect_edp_sink_caps(struct dc_link *link) ...@@ -2614,33 +2611,6 @@ void detect_edp_sink_caps(struct dc_link *link)
} }
} }
link->verified_link_cap = link->reported_link_cap; link->verified_link_cap = link->reported_link_cap;
// Read DPCD 00101h to find out the number of lanes currently set
core_link_read_dpcd(link, DP_LANE_COUNT_SET,
&lane_count_set.raw, sizeof(lane_count_set));
link->cur_link_settings.lane_count = lane_count_set.bits.LANE_COUNT_SET;
// Read DPCD 00100h to find if standard link rates are set
core_link_read_dpcd(link, DP_LINK_BW_SET,
&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;
}
} else {
link->cur_link_settings.link_rate = link_bw_set;
link->cur_link_settings.use_link_rate_set = false;
}
} }
void dc_link_dp_enable_hpd(const struct dc_link *link) void dc_link_dp_enable_hpd(const struct dc_link *link)
......
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