drm/amd/display: Improve DisplayPort monitor interop
authorAric Cyr <aric.cyr@amd.com>
Tue, 26 May 2020 17:56:53 +0000 (13:56 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 Aug 2020 06:26:18 +0000 (08:26 +0200)
[ Upstream commit eec3303de3378cdfaa0bb86f43546dbbd88f94e2 ]

[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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
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/dce110/dce110_hw_sequencer.c

index 48ab51533d5d6affd96ed25b8dec379af671be78..841cc051b7d01859d948fad0b5821754698d2cb6 100644 (file)
@@ -3298,9 +3298,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 91cd884d6f25712cde81d7384a62700f85f0f740..6124af571bff659f46faecf2ff160906f9949b9e 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(
@@ -1567,12 +1577,6 @@ bool perform_link_training_with_retries(
 
                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 b77e9dc1608634ca9ad7329e5ecd5081234b990e..2af1d74d16ad8ddae682b795db0aefae1d690802 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);
+       }
+
 }