]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/amd/display: Disable link before reenable
authorLucy Li <lucy.li@amd.com>
Fri, 25 Oct 2019 21:59:32 +0000 (17:59 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 5 Dec 2019 21:27:31 +0000 (16:27 -0500)
[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 <lucy.li@amd.com>
Reviewed-by: Anthony Koo <Anthony.Koo@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link.c

index 5a35395e6060184a5baf3a4c8c0d82f71633b745..4681ca20f683a81b9fd3bdd549432c809182a07f 100644 (file)
@@ -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)
 {