]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
drm/amd/display: Improve DisplayPort monitor interop
authorAric Cyr <aric.cyr@amd.com>
Tue, 26 May 2020 17:56:53 +0000 (13:56 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2020 05:59:21 +0000 (01:59 -0400)
[Why]
DC is very fast at link training and stream enablement
which causes issues such as blackscreens for non-compliant
monitors.

[How]
After debugging with scaler vendors we implement the
minimum delays at the necessary locations to ensure
the monitor does not hang.  Delays are generic due to
lack of IEEE OUI information on the failing displays.

Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Acked-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c

index cbb4c24d748da2c24943b1ae7a5d988ee3594c50..114ee29132fa10720d76459510bb4f527cfdf5a2 100644 (file)
@@ -3309,9 +3309,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
                        write_i2c_redriver_setting(pipe_ctx, false);
                }
        }
-       dc->hwss.disable_stream(pipe_ctx);
 
        disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
+
+       dc->hwss.disable_stream(pipe_ctx);
+
        if (pipe_ctx->stream->timing.flags.DSC) {
                if (dc_is_dp_signal(pipe_ctx->stream->signal))
                        dp_set_dsc_enable(pipe_ctx, false);
index fe15bdb57295f6e5d11650eda027445280473c92..f7a0e495f215dda3d8b10189c43c5c5ec5602c12 100644 (file)
@@ -1102,6 +1102,10 @@ static inline enum link_training_result perform_link_training_int(
        dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
        dpcd_set_training_pattern(link, dpcd_pattern);
 
+       /* delay 5ms after notifying sink of idle pattern before switching output */
+       if (link->connector_signal != SIGNAL_TYPE_EDP)
+               msleep(5);
+
        /* 4. mainlink output idle pattern*/
        dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
 
@@ -1551,6 +1555,12 @@ bool perform_link_training_with_retries(
        struct dc_link *link = stream->link;
        enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
 
+       /* We need to do this before the link training to ensure the idle pattern in SST
+        * mode will be sent right after the link training
+        */
+       link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+                                                       pipe_ctx->stream_res.stream_enc->id, true);
+
        for (j = 0; j < attempts; ++j) {
 
                dp_enable_link_phy(
@@ -1559,21 +1569,14 @@ bool perform_link_training_with_retries(
                        pipe_ctx->clock_source->id,
                        link_setting);
 
-               if ((link && link->dc->debug.dppowerup_delay > 0) || stream->sink_patches.dppowerup_delay > 0) {
-                       int delay_dp_power_up_in_ms =
-                               (link->dc->debug.dppowerup_delay >= stream->sink_patches.dppowerup_delay) ?
-                               link->dc->debug.dppowerup_delay : stream->sink_patches.dppowerup_delay;
+               if (stream->sink_patches.dppowerup_delay > 0) {
+                       int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
+
                        msleep(delay_dp_power_up_in_ms);
                }
 
                dp_set_panel_mode(link, panel_mode);
 
-               /* We need to do this before the link training to ensure the idle pattern in SST
-                * mode will be sent right after the link training
-                */
-               link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
-                                                               pipe_ctx->stream_res.stream_enc->id, true);
-
                if (link->aux_access_disabled) {
                        dc_link_dp_perform_link_training_skip_aux(link, link_setting);
                        return true;
index f9bdd9115edc384c3f7b545ad0f8a6fbb4eae603..7da41d465a34b63735121339795da4c3b01bcf0f 100644 (file)
@@ -498,7 +498,6 @@ struct dc_debug_options {
        bool usbc_combo_phy_reset_wa;
        bool disable_dsc;
        bool enable_dram_clock_change_one_display_vactive;
-       unsigned int dppowerup_delay;
 };
 
 struct dc_debug_data {
index 0ce430cf4dd05531f827a1f40afe0249394d2cad..49380ed3aeae14ba96839ca99ea1a4f0971d3477 100644 (file)
@@ -1069,8 +1069,17 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
                link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
        }
 
-       if (dc_is_dp_signal(pipe_ctx->stream->signal))
+       if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
                pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
+
+               /*
+                * After output is idle pattern some sinks need time to recognize the stream
+                * has changed or they enter protection state and hang.
+                */
+               if (!dc_is_embedded_signal(pipe_ctx->stream->signal))
+                       msleep(60);
+       }
+
 }