drm/amd/display: Fix DPIA link encoder assignment issue
authorCruise Hung <Cruise.Hung@amd.com>
Tue, 13 Dec 2022 01:39:49 +0000 (09:39 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 13 Jan 2023 19:57:17 +0000 (14:57 -0500)
[Why]
The DPIA link encoder (DIG) was not released when a Display XDR 6K
monitor was disconnected. That's because the DPIA link encoder logic
checked the BW when it removed the link encoder for it. And the timing
BW was less than DP link BW.  So, it failed to release the link encoder.
And that caused the DIG was occupied and can't be used.  The reason it
checked the BW is it wants to identify whether this link was using DIG
or HPO. It skips if it's not DIG.

[How]
Not to check the BW when it removes the link encoder because it's
already in the assignment table, it must be the DIG.

Tested-by: Daniel Wheeler <Daniel.Wheeler@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Cruise Hung <Cruise.Hung@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c

index 614f022..049e755 100644 (file)
@@ -305,15 +305,17 @@ void link_enc_cfg_link_encs_assign(
        for (i = 0; i < stream_count; i++) {
                struct dc_stream_state *stream = streams[i];
 
+               /* skip it if the link is mappable endpoint. */
+               if (stream->link->is_dig_mapping_flexible)
+                       continue;
+
                /* Skip stream if not supported by DIG link encoder. */
                if (!is_dig_link_enc_stream(stream))
                        continue;
 
                /* Physical endpoints have a fixed mapping to DIG link encoders. */
-               if (!stream->link->is_dig_mapping_flexible) {
-                       eng_id = stream->link->eng_id;
-                       add_link_enc_assignment(state, stream, eng_id);
-               }
+               eng_id = stream->link->eng_id;
+               add_link_enc_assignment(state, stream, eng_id);
        }
 
        /* (b) Retain previous assignments for mappable endpoints if encoders still available. */
@@ -325,11 +327,12 @@ void link_enc_cfg_link_encs_assign(
                for (i = 0; i < stream_count; i++) {
                        struct dc_stream_state *stream = state->streams[i];
 
-                       /* Skip stream if not supported by DIG link encoder. */
-                       if (!is_dig_link_enc_stream(stream))
+                       /* Skip it if the link is NOT mappable endpoint. */
+                       if (!stream->link->is_dig_mapping_flexible)
                                continue;
 
-                       if (!stream->link->is_dig_mapping_flexible)
+                       /* Skip stream if not supported by DIG link encoder. */
+                       if (!is_dig_link_enc_stream(stream))
                                continue;
 
                        for (j = 0; j < prev_state->stream_count; j++) {
@@ -338,6 +341,7 @@ void link_enc_cfg_link_encs_assign(
                                if (stream == prev_stream && stream->link == prev_stream->link &&
                                                prev_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j].valid) {
                                        eng_id = prev_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j].eng_id;
+
                                        if (is_avail_link_enc(state, eng_id, stream))
                                                add_link_enc_assignment(state, stream, eng_id);
                                }
@@ -350,6 +354,15 @@ void link_enc_cfg_link_encs_assign(
 
        for (i = 0; i < stream_count; i++) {
                struct dc_stream_state *stream = streams[i];
+               struct link_encoder *link_enc = NULL;
+
+               /* Skip it if the link is NOT mappable endpoint. */
+               if (!stream->link->is_dig_mapping_flexible)
+                       continue;
+
+               /* Skip if encoder assignment retained in step (b) above. */
+               if (stream->link_enc)
+                       continue;
 
                /* Skip stream if not supported by DIG link encoder. */
                if (!is_dig_link_enc_stream(stream)) {
@@ -358,24 +371,18 @@ void link_enc_cfg_link_encs_assign(
                }
 
                /* Mappable endpoints have a flexible mapping to DIG link encoders. */
-               if (stream->link->is_dig_mapping_flexible) {
-                       struct link_encoder *link_enc = NULL;
 
-                       /* Skip if encoder assignment retained in step (b) above. */
-                       if (stream->link_enc)
-                               continue;
+               /* For MST, multiple streams will share the same link / display
+                * endpoint. These streams should use the same link encoder
+                * assigned to that endpoint.
+                */
+               link_enc = get_link_enc_used_by_link(state, stream->link);
+               if (link_enc == NULL)
+                       eng_id = find_first_avail_link_enc(stream->ctx, state);
+               else
+                       eng_id =  link_enc->preferred_engine;
 
-                       /* For MST, multiple streams will share the same link / display
-                        * endpoint. These streams should use the same link encoder
-                        * assigned to that endpoint.
-                        */
-                       link_enc = get_link_enc_used_by_link(state, stream->link);
-                       if (link_enc == NULL)
-                               eng_id = find_first_avail_link_enc(stream->ctx, state);
-                       else
-                               eng_id =  link_enc->preferred_engine;
-                       add_link_enc_assignment(state, stream, eng_id);
-               }
+               add_link_enc_assignment(state, stream, eng_id);
        }
 
        link_enc_cfg_validate(dc, state);
@@ -420,10 +427,6 @@ void link_enc_cfg_link_enc_unassign(
 {
        enum engine_id eng_id = ENGINE_ID_UNKNOWN;
 
-       /* Only DIG link encoders. */
-       if (!is_dig_link_enc_stream(stream))
-               return;
-
        if (stream->link_enc)
                eng_id = stream->link_enc->preferred_engine;