From: Jimmy Kizito <jimmy.kiz...@amd.com>

[Why]
Some display endpoints may be dynamically mapped to the link encoders
which drive them.

[How]
Update the code paths for display enabling/disabling to accommodate
the dynamic association between links and link encoders.

Signed-off-by: Jimmy Kizito <jimmy.kiz...@amd.com>
Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Anson Jacob <anson.ja...@amd.com>
---
 .../gpu/drm/amd/display/dc/core/dc_link_dp.c  | 15 ++-
 .../drm/amd/display/dc/core/dc_link_enc_cfg.c | 99 +++++++++++++++++++
 .../drm/amd/display/dc/core/dc_link_hwss.c    | 22 ++++-
 .../gpu/drm/amd/display/dc/inc/link_enc_cfg.h | 18 ++++
 4 files changed, 146 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index cebf68200f43..0b8082a15e24 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -1728,11 +1728,16 @@ bool perform_link_training_with_retries(
                if (link->aux_access_disabled) {
                        dc_link_dp_perform_link_training_skip_aux(link, 
link_setting);
                        return true;
-               } else if (dc_link_dp_perform_link_training(
-                               link,
-                               link_setting,
-                               skip_video_pattern) == LINK_TRAINING_SUCCESS)
-                       return true;
+               } else {
+                       enum link_training_result status = 
LINK_TRAINING_CR_FAIL_LANE0;
+
+                               status = dc_link_dp_perform_link_training(
+                                                                               
link,
+                                                                               
link_setting,
+                                                                               
skip_video_pattern);
+                       if (status == LINK_TRAINING_SUCCESS)
+                               return true;
+               }
 
                /* latest link training still fail, skip delay and keep PHY on
                 */
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
index c2bf9e5d9675..1361b87d86d7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
@@ -127,6 +127,32 @@ static enum engine_id find_first_avail_link_enc(
        return eng_id;
 }
 
+/* Return stream using DIG link encoder resource. NULL if unused. */
+static struct dc_stream_state *get_stream_using_link_enc(
+               struct dc_state *state,
+               enum engine_id eng_id)
+{
+       struct dc_stream_state *stream = NULL;
+       int stream_idx = -1;
+       int i;
+
+       for (i = 0; i < state->stream_count; i++) {
+               struct link_enc_assignment assignment = 
state->res_ctx.link_enc_assignments[i];
+
+               if (assignment.valid && (assignment.eng_id == eng_id)) {
+                       stream_idx = i;
+                       break;
+               }
+       }
+
+       if (stream_idx != -1)
+               stream = state->streams[stream_idx];
+       else
+               dm_output_to_console("%s: No stream using DIG(%d).\n", 
__func__, eng_id);
+
+       return stream;
+}
+
 void link_enc_cfg_init(
                struct dc *dc,
                struct dc_state *state)
@@ -202,3 +228,76 @@ void link_enc_cfg_link_enc_unassign(
 
        update_link_enc_assignment(state, stream, eng_id, false);
 }
+
+bool link_enc_cfg_is_transmitter_mappable(
+               struct dc_state *state,
+               struct link_encoder *link_enc)
+{
+       bool is_mappable = false;
+       enum engine_id eng_id = link_enc->preferred_engine;
+       struct dc_stream_state *stream = get_stream_using_link_enc(state, 
eng_id);
+
+       if (stream)
+               is_mappable = stream->link->is_dig_mapping_flexible;
+
+       return is_mappable;
+}
+
+struct dc_link *link_enc_cfg_get_link_using_link_enc(
+               struct dc_state *state,
+               enum engine_id eng_id)
+{
+       struct dc_link *link = NULL;
+       int stream_idx = -1;
+       int i;
+
+       for (i = 0; i < state->stream_count; i++) {
+               struct link_enc_assignment assignment = 
state->res_ctx.link_enc_assignments[i];
+
+               if (assignment.valid && (assignment.eng_id == eng_id)) {
+                       stream_idx = i;
+                       break;
+               }
+       }
+
+       if (stream_idx != -1)
+               link = state->streams[stream_idx]->link;
+       else
+               dm_output_to_console("%s: No link using DIG(%d).\n", __func__, 
eng_id);
+
+       return link;
+}
+
+struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
+               struct dc_state *state,
+               struct dc_link *link)
+{
+       struct link_encoder *link_enc = NULL;
+       struct display_endpoint_id ep_id;
+       int stream_idx = -1;
+       int i;
+
+       ep_id = (struct display_endpoint_id) {
+               .link_id = link->link_id,
+               .ep_type = link->ep_type};
+
+       for (i = 0; i < state->stream_count; i++) {
+               struct link_enc_assignment assignment = 
state->res_ctx.link_enc_assignments[i];
+
+               if (assignment.valid &&
+                               assignment.ep_id.link_id.id == ep_id.link_id.id 
&&
+                               assignment.ep_id.link_id.enum_id == 
ep_id.link_id.enum_id &&
+                               assignment.ep_id.link_id.type == 
ep_id.link_id.type &&
+                               assignment.ep_id.ep_type == ep_id.ep_type) {
+                       stream_idx = i;
+                       break;
+               }
+       }
+
+       if (stream_idx != -1)
+               link_enc = state->streams[stream_idx]->link_enc;
+       else
+               dm_output_to_console("%s: No link encoder used by link(%d).\n", 
__func__, link->link_index);
+
+       return link_enc;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index 22fe19ee842d..48ad1a8d4a74 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -14,6 +14,7 @@
 #include "dpcd_defs.h"
 #include "dsc.h"
 #include "resource.h"
+#include "link_enc_cfg.h"
 #include "clk_mgr.h"
 
 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
@@ -95,7 +96,7 @@ void dp_enable_link_phy(
        enum clock_source_id clock_source,
        const struct dc_link_settings *link_settings)
 {
-       struct link_encoder *link_enc = link->link_enc;
+       struct link_encoder *link_enc;
        struct dc  *dc = link->ctx->dc;
        struct dmcu *dmcu = dc->res_pool->dmcu;
 
@@ -105,6 +106,13 @@ void dp_enable_link_phy(
                        link->dc->res_pool->dp_clock_source;
        unsigned int i;
 
+       /* Link should always be assigned encoder when en-/disabling. */
+       if (link->is_dig_mapping_flexible && 
dc->res_pool->funcs->link_encs_assign)
+               link_enc = 
link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
+       else
+               link_enc = link->link_enc;
+       ASSERT(link_enc);
+
        if (link->connector_signal == SIGNAL_TYPE_EDP) {
                link->dc->hwss.edp_power_control(link, true);
                link->dc->hwss.edp_wait_for_hpd_ready(link, true);
@@ -227,6 +235,14 @@ void dp_disable_link_phy(struct dc_link *link, enum 
signal_type signal)
 {
        struct dc  *dc = link->ctx->dc;
        struct dmcu *dmcu = dc->res_pool->dmcu;
+       struct link_encoder *link_enc;
+
+       /* Link should always be assigned encoder when en-/disabling. */
+       if (link->is_dig_mapping_flexible && 
dc->res_pool->funcs->link_encs_assign)
+               link_enc = 
link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
+       else
+               link_enc = link->link_enc;
+       ASSERT(link_enc);
 
        if (!link->wa_flags.dp_keep_receiver_powered)
                dp_receiver_power_ctrl(link, false);
@@ -234,13 +250,13 @@ void dp_disable_link_phy(struct dc_link *link, enum 
signal_type signal)
        if (signal == SIGNAL_TYPE_EDP) {
                if (link->dc->hwss.edp_backlight_control)
                        link->dc->hwss.edp_backlight_control(link, false);
-               link->link_enc->funcs->disable_output(link->link_enc, signal);
+               link_enc->funcs->disable_output(link_enc, signal);
                link->dc->hwss.edp_power_control(link, false);
        } else {
                if (dmcu != NULL && dmcu->funcs->lock_phy)
                        dmcu->funcs->lock_phy(dmcu);
 
-               link->link_enc->funcs->disable_output(link->link_enc, signal);
+               link_enc->funcs->disable_output(link_enc, signal);
 
                if (dmcu != NULL && dmcu->funcs->unlock_phy)
                        dmcu->funcs->unlock_phy(dmcu);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h 
b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h
index ad641632eadd..7d36e55f3097 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h
@@ -65,4 +65,22 @@ void link_enc_cfg_link_enc_unassign(
                struct dc_state *state,
                struct dc_stream_state *stream);
 
+/*
+ * Check whether the transmitter driven by a link encoder is a mappable
+ * endpoint.
+ */
+bool link_enc_cfg_is_transmitter_mappable(
+               struct dc_state *state,
+               struct link_encoder *link_enc);
+
+/* Return link using DIG link encoder resource. NULL if unused. */
+struct dc_link *link_enc_cfg_get_link_using_link_enc(
+               struct dc_state *state,
+               enum engine_id eng_id);
+
+/* Return DIG link encoder used by link. NULL if unused. */
+struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
+               struct dc_state *state,
+               struct dc_link *link);
+
 #endif /* DC_INC_LINK_ENC_CFG_H_ */
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to