[PATCH 12/14] drm/amd/display: refactor dio link encoder assigning

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Peichen Huang <PeiChen.Huang@xxxxxxx>

[WHY]
We would like to have new dio encoder assigning flow.
Which should be aligned with hpo assigning and have
simple logic and data representation.

[HOW}
1. A new config option to enable/disable the new code.
2. Encoder-link mapping is in res_ctx and assigned encoder.
is accessed through pipe_ctx.
3. assign dio encoder when add stream to ctx

Reviewed-by: Jun Lei <jun.lei@xxxxxxx>
Reviewed-by: Meenakshikumar Somasundaram <meenakshikumar.somasundaram@xxxxxxx>
Signed-off-by: Peichen Huang <PeiChen.Huang@xxxxxxx>
Signed-off-by: Zaeem Mohamed <zaeem.mohamed@xxxxxxx>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |   2 +-
 .../gpu/drm/amd/display/dc/core/dc_resource.c | 202 +++++++++++++++++-
 drivers/gpu/drm/amd/display/dc/dc.h           |   2 +
 .../gpu/drm/amd/display/dc/inc/core_types.h   |   3 +
 4 files changed, 206 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 3ebbb59a22e3..e22a056af4a0 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2267,7 +2267,7 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params
 	/*
 	 * Only update link encoder to stream assignment after bandwidth validation passed.
 	 */
-	if (res == DC_OK && dc->res_pool->funcs->link_encs_assign)
+	if (res == DC_OK && dc->res_pool->funcs->link_encs_assign && !dc->config.unify_link_enc_assignment)
 		dc->res_pool->funcs->link_encs_assign(
 			dc, context, context->streams, context->stream_count);
 
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 72c88fdeb28c..9d2f24cefeeb 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -2683,6 +2683,162 @@ static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
 	}
 }
 
+static inline int find_acquired_dio_link_enc_for_link(
+		const struct resource_context *res_ctx,
+		const struct dc_link *link)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(res_ctx->dio_link_enc_ref_cnts); i++)
+		if (res_ctx->dio_link_enc_ref_cnts[i] > 0 &&
+				res_ctx->dio_link_enc_to_link_idx[i] == link->link_index)
+			return i;
+
+	return -1;
+}
+
+static inline int find_fixed_dio_link_enc(const struct dc_link *link)
+{
+	/* the 8b10b dp phy can only use fixed link encoder */
+	return link->eng_id;
+}
+
+static inline int find_free_dio_link_enc(const struct resource_context *res_ctx,
+		const struct dc_link *link, const struct resource_pool *pool)
+{
+	int i;
+	int enc_count = pool->dig_link_enc_count;
+
+	/* for dpia, check preferred encoder first and then the next one */
+	for (i = 0; i < enc_count; i++)
+		if (res_ctx->dio_link_enc_ref_cnts[(link->dpia_preferred_eng_id + i) % enc_count] == 0)
+			break;
+
+	return (i >= 0 && i < enc_count) ? (link->dpia_preferred_eng_id + i) % enc_count : -1;
+}
+
+static inline void acquire_dio_link_enc(
+		struct resource_context *res_ctx,
+		unsigned int link_index,
+		int enc_index)
+{
+	res_ctx->dio_link_enc_to_link_idx[enc_index] = link_index;
+	res_ctx->dio_link_enc_ref_cnts[enc_index] = 1;
+}
+
+static inline void retain_dio_link_enc(
+		struct resource_context *res_ctx,
+		int enc_index)
+{
+	res_ctx->dio_link_enc_ref_cnts[enc_index]++;
+}
+
+static inline void release_dio_link_enc(
+		struct resource_context *res_ctx,
+		int enc_index)
+{
+	ASSERT(res_ctx->dio_link_enc_ref_cnts[enc_index] > 0);
+	res_ctx->dio_link_enc_ref_cnts[enc_index]--;
+}
+
+static bool is_dio_enc_acquired_by_other_link(const struct dc_link *link,
+		int enc_index,
+		int *link_index)
+{
+	const struct dc *dc  = link->dc;
+	const struct resource_context *res_ctx = &dc->current_state->res_ctx;
+
+	/* pass the link_index that acquired the enc_index */
+	if (res_ctx->dio_link_enc_ref_cnts[enc_index] > 0 &&
+			res_ctx->dio_link_enc_to_link_idx[enc_index] != link->link_index) {
+		*link_index = res_ctx->dio_link_enc_to_link_idx[enc_index];
+		return true;
+	}
+
+	return false;
+}
+
+static void swap_dio_link_enc_to_muxable_ctx(struct dc_state *context,
+		const struct resource_pool *pool,
+		int new_encoder,
+		int old_encoder)
+{
+	struct resource_context *res_ctx = &context->res_ctx;
+	int stream_count = context->stream_count;
+	int i = 0;
+
+	res_ctx->dio_link_enc_ref_cnts[new_encoder] = res_ctx->dio_link_enc_ref_cnts[old_encoder];
+	res_ctx->dio_link_enc_to_link_idx[new_encoder] = res_ctx->dio_link_enc_to_link_idx[old_encoder];
+	res_ctx->dio_link_enc_ref_cnts[old_encoder] = 0;
+
+	for (i = 0; i < stream_count; i++) {
+		struct dc_stream_state *stream = context->streams[i];
+		struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
+
+		if (pipe_ctx && pipe_ctx->link_res.dio_link_enc == pool->link_encoders[old_encoder])
+			pipe_ctx->link_res.dio_link_enc = pool->link_encoders[new_encoder];
+	}
+}
+
+static bool add_dio_link_enc_to_ctx(const struct dc *dc,
+		struct dc_state *context,
+		const struct resource_pool *pool,
+		struct pipe_ctx *pipe_ctx,
+		struct dc_stream_state *stream)
+{
+	struct resource_context *res_ctx = &context->res_ctx;
+	int enc_index;
+
+	enc_index = find_acquired_dio_link_enc_for_link(res_ctx, stream->link);
+
+	if (enc_index >= 0) {
+		retain_dio_link_enc(res_ctx, enc_index);
+	} else {
+		if (stream->link->is_dig_mapping_flexible)
+			enc_index = find_free_dio_link_enc(res_ctx, stream->link, pool);
+		else {
+			int link_index = 0;
+
+			enc_index = find_fixed_dio_link_enc(stream->link);
+			/* Fixed mapping link can only use its fixed link encoder.
+			 * If the encoder is acquired by other link then get a new free encoder and swap the new
+			 * one into the acquiring link.
+			 */
+			if (enc_index >= 0 && is_dio_enc_acquired_by_other_link(stream->link, enc_index, &link_index)) {
+				int new_enc_index = find_free_dio_link_enc(res_ctx, dc->links[link_index], pool);
+
+				if (new_enc_index >= 0)
+					swap_dio_link_enc_to_muxable_ctx(context, pool, new_enc_index, enc_index);
+				else
+					return false;
+			}
+		}
+
+		if (enc_index >= 0)
+			acquire_dio_link_enc(res_ctx, stream->link->link_index, enc_index);
+	}
+
+	if (enc_index >= 0)
+		pipe_ctx->link_res.dio_link_enc = pool->link_encoders[enc_index];
+
+	return pipe_ctx->link_res.dio_link_enc != NULL;
+}
+
+static void remove_dio_link_enc_from_ctx(struct resource_context *res_ctx,
+		struct pipe_ctx *pipe_ctx,
+		struct dc_stream_state *stream)
+{
+	int enc_index = -1;
+
+	if (stream->link)
+		enc_index = find_acquired_dio_link_enc_for_link(res_ctx, stream->link);
+
+	if (enc_index >= 0) {
+		release_dio_link_enc(res_ctx, enc_index);
+		pipe_ctx->link_res.dio_link_enc = NULL;
+	}
+}
+
 static int get_num_of_free_pipes(const struct resource_pool *pool, const struct dc_state *context)
 {
 	int i;
@@ -2730,6 +2886,10 @@ void resource_remove_otg_master_for_stream_output(struct dc_state *context,
 		remove_hpo_dp_link_enc_from_ctx(
 				&context->res_ctx, otg_master, stream);
 	}
+
+	if (stream->ctx->dc->config.unify_link_enc_assignment)
+		remove_dio_link_enc_from_ctx(&context->res_ctx, otg_master, stream);
+
 	if (otg_master->stream_res.audio)
 		update_audio_usage(
 			&context->res_ctx,
@@ -2744,6 +2904,7 @@ void resource_remove_otg_master_for_stream_output(struct dc_state *context,
 	if (pool->funcs->remove_stream_from_ctx)
 		pool->funcs->remove_stream_from_ctx(
 				stream->ctx->dc, context, stream);
+
 	memset(otg_master, 0, sizeof(*otg_master));
 }
 
@@ -3712,6 +3873,7 @@ enum dc_status resource_map_pool_resources(
 	struct pipe_ctx *pipe_ctx = NULL;
 	int pipe_idx = -1;
 	bool acquired = false;
+	bool is_dio_encoder = true;
 
 	calculate_phy_pix_clks(stream);
 
@@ -3777,6 +3939,10 @@ enum dc_status resource_map_pool_resources(
 		}
 	}
 
+	if (dc->config.unify_link_enc_assignment && is_dio_encoder)
+		if (!add_dio_link_enc_to_ctx(dc, context, pool, pipe_ctx, stream))
+			return DC_NO_LINK_ENC_RESOURCE;
+
 	/* TODO: Add check if ASIC support and EDID audio */
 	if (!stream->converter_disable_audio &&
 	    dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
@@ -5013,6 +5179,28 @@ void get_audio_check(struct audio_info *aud_modes,
 	}
 }
 
+static struct link_encoder *get_temp_dio_link_enc(
+		const struct resource_context *res_ctx,
+		const struct resource_pool *const pool,
+		const struct dc_link *link)
+{
+	struct link_encoder *link_enc = NULL;
+	int enc_index;
+
+	if (link->is_dig_mapping_flexible)
+		enc_index = find_acquired_dio_link_enc_for_link(res_ctx, link);
+	else
+		enc_index = link->eng_id;
+
+	if (enc_index < 0)
+		enc_index = find_free_dio_link_enc(res_ctx, link, pool);
+
+	if (enc_index >= 0)
+		link_enc = pool->link_encoders[enc_index];
+
+	return link_enc;
+}
+
 static struct hpo_dp_link_encoder *get_temp_hpo_dp_link_enc(
 		const struct resource_context *res_ctx,
 		const struct resource_pool *const pool,
@@ -5042,11 +5230,17 @@ bool get_temp_dp_link_res(struct dc_link *link,
 	memset(link_res, 0, sizeof(*link_res));
 
 	if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
-		link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx,
-				dc->res_pool, link);
+		link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx, dc->res_pool, link);
 		if (!link_res->hpo_dp_link_enc)
 			return false;
+	} else if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
+				dc->config.unify_link_enc_assignment) {
+		link_res->dio_link_enc = get_temp_dio_link_enc(res_ctx,
+				dc->res_pool, link);
+		if (!link_res->dio_link_enc)
+			return false;
 	}
+
 	return true;
 }
 
@@ -5318,6 +5512,10 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
 			remove_hpo_dp_link_enc_from_ctx(&context->res_ctx, pipe_ctx, pipe_ctx->stream);
 	}
 
+	if (pipe_ctx->link_res.dio_link_enc == NULL && dc->config.unify_link_enc_assignment)
+		if (!add_dio_link_enc_to_ctx(dc, context, dc->res_pool, pipe_ctx, pipe_ctx->stream))
+			return DC_NO_LINK_ENC_RESOURCE;
+
 	return DC_OK;
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 019459dfd6fe..06d9cf0a7edc 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -473,6 +473,7 @@ struct dc_config {
 	bool consolidated_dpia_dp_lt;
 	bool set_pipe_unlock_order;
 	bool enable_dpia_pre_training;
+	bool unify_link_enc_assignment;
 };
 
 enum visual_confirm {
@@ -778,6 +779,7 @@ union dpia_debug_options {
 		uint32_t disable_usb4_pm_support:1; /* bit 5 */
 		uint32_t enable_consolidated_dpia_dp_lt:1; /* bit 6 */
 		uint32_t enable_dpia_pre_training:1; /* bit 7 */
+		uint32_t unify_link_enc_assignment:1; /* bit 8 */
 		uint32_t reserved:24;
 	} bits;
 	uint32_t raw;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index 652d52040f4e..37632be09e09 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -376,6 +376,7 @@ struct plane_resource {
 
 /* all mappable hardware resources used to enable a link */
 struct link_resource {
+	struct link_encoder *dio_link_enc;
 	struct hpo_dp_link_encoder *hpo_dp_link_enc;
 };
 
@@ -500,6 +501,8 @@ struct resource_context {
 	uint8_t dp_clock_source_ref_count;
 	bool is_dsc_acquired[MAX_PIPES];
 	struct link_enc_cfg_context link_enc_cfg_ctx;
+	unsigned int dio_link_enc_to_link_idx[MAX_DIG_LINK_ENCODERS];
+	int dio_link_enc_ref_cnts[MAX_DIG_LINK_ENCODERS];
 	bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS];
 	unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS];
 	int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS];
-- 
2.34.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux