From: Lucy Li Date: Fri, 25 Oct 2019 21:59:32 +0000 (-0400) Subject: drm/amd/display: Disable link before reenable X-Git-Tag: v5.6-rc1~114^2~21^2~71 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=61f14c5b528f0c828e0d1f27f8580a7f43ad1a5b;p=linux.git drm/amd/display: Disable link before reenable [Why] Black screen seen after display is disabled then re-enabled. Caused by difference in link settings when switching between different resolutions. [How] In PnP case, or whenever the display is still enabled but the driver is unloaded, disable link before re-enabling with new link settings. Signed-off-by: Lucy Li Reviewed-by: Anthony Koo Acked-by: Leo Li Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 5a35395e6060..4681ca20f683 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1511,15 +1511,6 @@ static enum dc_status enable_link_dp( decide_link_settings(stream, &link_settings); if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) { - /* 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 || - 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); @@ -2039,6 +2030,45 @@ static void write_i2c_redriver_setting( ASSERT(i2c_success); } +static void disable_link(struct dc_link *link, enum signal_type signal) +{ + /* + * TODO: implement call for dp_set_hw_test_pattern + * it is needed for compliance testing + */ + + /* Here we need to specify that encoder output settings + * need to be calculated as for the set mode, + * it will lead to querying dynamic link capabilities + * which should be done before enable output + */ + + if (dc_is_dp_signal(signal)) { + /* SST DP, eDP */ + if (dc_is_dp_sst_signal(signal)) + dp_disable_link_phy(link, signal); + else + dp_disable_link_phy_mst(link, signal); + + if (dc_is_dp_sst_signal(signal) || + link->mst_stream_alloc_table.stream_count == 0) { + dp_set_fec_enable(link, false); + dp_set_fec_ready(link, false); + } + } else { + if (signal != SIGNAL_TYPE_VIRTUAL) + link->link_enc->funcs->disable_output(link->link_enc, signal); + } + + if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + /* MST disable link only when no stream use the link */ + if (link->mst_stream_alloc_table.stream_count <= 0) + link->link_status.link_active = false; + } else { + link->link_status.link_active = false; + } +} + static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; @@ -2123,6 +2153,19 @@ static enum dc_status enable_link( struct pipe_ctx *pipe_ctx) { enum dc_status status = DC_ERROR_UNEXPECTED; + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->link; + + /* There's some scenarios where driver is unloaded with display + * still enabled. When driver is reloaded, it may cause a display + * to not light up if there is a mismatch between old and new + * link settings. Need to call disable first before enabling at + * new link settings. + */ + if (link->link_status.link_active) { + disable_link(link, pipe_ctx->stream->signal); + } + switch (pipe_ctx->stream->signal) { case SIGNAL_TYPE_DISPLAY_PORT: status = enable_link_dp(state, pipe_ctx); @@ -2157,44 +2200,6 @@ static enum dc_status enable_link( return status; } -static void disable_link(struct dc_link *link, enum signal_type signal) -{ - /* - * TODO: implement call for dp_set_hw_test_pattern - * it is needed for compliance testing - */ - - /* here we need to specify that encoder output settings - * need to be calculated as for the set mode, - * it will lead to querying dynamic link capabilities - * which should be done before enable output */ - - if (dc_is_dp_signal(signal)) { - /* SST DP, eDP */ - if (dc_is_dp_sst_signal(signal)) - dp_disable_link_phy(link, signal); - else - dp_disable_link_phy_mst(link, signal); - - if (dc_is_dp_sst_signal(signal) || - link->mst_stream_alloc_table.stream_count == 0) { - dp_set_fec_enable(link, false); - dp_set_fec_ready(link, false); - } - } else { - if (signal != SIGNAL_TYPE_VIRTUAL) - link->link_enc->funcs->disable_output(link->link_enc, signal); - } - - if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - /* MST disable link only when no stream use the link */ - if (link->mst_stream_alloc_table.stream_count <= 0) - link->link_status.link_active = false; - } else { - link->link_status.link_active = false; - } -} - static uint32_t get_timing_pixel_clock_100hz(const struct dc_crtc_timing *timing) {