[PATCH v2 09/24] drm/amd/display: implement map dc pipe with callback in DML2
Roman.Li at amd.com
Roman.Li at amd.com
Thu Oct 19 13:32:07 UTC 2023
From: Wenjing Liu <wenjing.liu at amd.com>
[why]
Unify pipe resource management logic in dc resource layer.
V2:
Add default case for switch.
CC: Hamza Mahfooz <hamza.mahfooz at amd.com>
Reviewed-by: Chaitanya Dhere <chaitanya.dhere at amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu at amd.com>
Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira at amd.com>
Reviewed-by: Jun Lei <jun.lei at amd.com>
Acked-by: Roman Li <roman.li at amd.com>
Signed-off-by: Qingqing Zhuo <qingqing.zhuo at amd.com>
---
.../drm/amd/display/dc/dcn32/dcn32_resource.c | 1 +
.../display/dc/dml2/dml2_dc_resource_mgmt.c | 146 ++++++++++++++++++
.../drm/amd/display/dc/dml2/dml2_wrapper.h | 1 +
3 files changed, 148 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
index 02d3168f1673..0e1d395a9340 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
@@ -2481,6 +2481,7 @@ static bool dcn32_resource_construct(
dc->dml2_options.max_segments_per_hubp = 18;
dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;
+ dc->dml2_options.map_dc_pipes_with_callbacks = true;
if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0))
dc->config.sdpif_request_limit_words_per_umc = 16;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
index 36baf35bb170..fc266c6e1398 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
@@ -756,6 +756,148 @@ static void map_pipes_for_plane(struct dml2_context *ctx, struct dc_state *state
free_unused_pipes_for_plane(ctx, state, plane, &scratch->pipe_pool, stream->stream_id);
}
+static unsigned int get_mpc_factor(struct dml2_context *ctx,
+ const struct dc_state *state,
+ const struct dml_display_cfg_st *disp_cfg,
+ struct dml2_dml_to_dc_pipe_mapping *mapping,
+ const struct dc_stream_status *status, unsigned int stream_id,
+ int plane_idx)
+{
+ unsigned int plane_id;
+ unsigned int cfg_idx;
+
+ get_plane_id(state, status->plane_states[plane_idx], stream_id, &plane_id);
+ cfg_idx = find_disp_cfg_idx_by_plane_id(mapping, plane_id);
+ if (ctx->architecture == dml2_architecture_20)
+ return (unsigned int)disp_cfg->hw.DPPPerSurface[cfg_idx];
+ ASSERT(false);
+ return 1;
+}
+
+static unsigned int get_odm_factor(
+ const struct dml2_context *ctx,
+ const struct dml_display_cfg_st *disp_cfg,
+ struct dml2_dml_to_dc_pipe_mapping *mapping,
+ const struct dc_stream_state *stream)
+{
+ unsigned int cfg_idx = find_disp_cfg_idx_by_stream_id(
+ mapping, stream->stream_id);
+
+ if (ctx->architecture == dml2_architecture_20)
+ switch (disp_cfg->hw.ODMMode[cfg_idx]) {
+ case dml_odm_mode_bypass:
+ return 1;
+ case dml_odm_mode_combine_2to1:
+ return 2;
+ case dml_odm_mode_combine_4to1:
+ return 4;
+ default:
+ break;
+ }
+ ASSERT(false);
+ return 1;
+}
+
+static void populate_mpc_factors_for_stream(
+ struct dml2_context *ctx,
+ const struct dml_display_cfg_st *disp_cfg,
+ struct dml2_dml_to_dc_pipe_mapping *mapping,
+ const struct dc_state *state,
+ unsigned int stream_idx,
+ unsigned int odm_factor,
+ unsigned int mpc_factors[MAX_PIPES])
+{
+ const struct dc_stream_status *status = &state->stream_status[stream_idx];
+ unsigned int stream_id = state->streams[stream_idx]->stream_id;
+ int i;
+
+ for (i = 0; i < status->plane_count; i++)
+ if (odm_factor == 1)
+ mpc_factors[i] = get_mpc_factor(
+ ctx, state, disp_cfg, mapping, status,
+ stream_id, i);
+ else
+ mpc_factors[i] = 1;
+}
+
+static void populate_odm_factors(const struct dml2_context *ctx,
+ const struct dml_display_cfg_st *disp_cfg,
+ struct dml2_dml_to_dc_pipe_mapping *mapping,
+ const struct dc_state *state,
+ unsigned int odm_factors[MAX_PIPES])
+{
+ int i;
+
+ for (i = 0; i < state->stream_count; i++)
+ odm_factors[i] = get_odm_factor(
+ ctx, disp_cfg, mapping, state->streams[i]);
+}
+
+static bool map_dc_pipes_for_stream(struct dml2_context *ctx,
+ struct dc_state *state,
+ const struct dc_state *existing_state,
+ const struct dc_stream_state *stream,
+ const struct dc_stream_status *status,
+ unsigned int odm_factor,
+ unsigned int mpc_factors[MAX_PIPES])
+{
+ int plane_idx;
+ bool result = true;
+
+ if (odm_factor == 1)
+ /*
+ * ODM and MPC combines are by DML design mutually exclusive.
+ * ODM factor of 1 means MPC factors may be greater than 1.
+ * In this case, we want to set ODM factor to 1 first to free up
+ * pipe resources from previous ODM configuration before setting
+ * up MPC combine to acquire more pipe resources.
+ */
+ result &= ctx->config.callbacks.update_pipes_for_stream_with_slice_count(
+ state,
+ existing_state,
+ ctx->config.callbacks.dc->res_pool,
+ stream,
+ odm_factor);
+ for (plane_idx = 0; plane_idx < status->plane_count; plane_idx++)
+ result &= ctx->config.callbacks.update_pipes_for_plane_with_slice_count(
+ state,
+ existing_state,
+ ctx->config.callbacks.dc->res_pool,
+ status->plane_states[plane_idx],
+ mpc_factors[plane_idx]);
+ if (odm_factor > 1)
+ result &= ctx->config.callbacks.update_pipes_for_stream_with_slice_count(
+ state,
+ existing_state,
+ ctx->config.callbacks.dc->res_pool,
+ stream,
+ odm_factor);
+ return result;
+}
+
+static bool map_dc_pipes_with_callbacks(struct dml2_context *ctx,
+ struct dc_state *state,
+ const struct dml_display_cfg_st *disp_cfg,
+ struct dml2_dml_to_dc_pipe_mapping *mapping,
+ const struct dc_state *existing_state)
+{
+ unsigned int odm_factors[MAX_PIPES];
+ unsigned int mpc_factors_for_stream[MAX_PIPES];
+ int i;
+ bool result = true;
+
+ populate_odm_factors(ctx, disp_cfg, mapping, state, odm_factors);
+ for (i = 0; i < state->stream_count; i++) {
+ populate_mpc_factors_for_stream(ctx, disp_cfg, mapping, state,
+ i, odm_factors[i], mpc_factors_for_stream);
+ result &= map_dc_pipes_for_stream(ctx, state, existing_state,
+ state->streams[i],
+ &state->stream_status[i],
+ odm_factors[i], mpc_factors_for_stream);
+ }
+ return result;
+}
+
bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const struct dml_display_cfg_st *disp_cfg, struct dml2_dml_to_dc_pipe_mapping *mapping, const struct dc_state *existing_state)
{
int stream_index, plane_index, i;
@@ -770,6 +912,10 @@ bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const s
unsigned int odm_mode_array[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}, dpp_per_surface_array[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
struct dc_pipe_mapping_scratch scratch;
+ if (ctx->config.map_dc_pipes_with_callbacks)
+ return map_dc_pipes_with_callbacks(
+ ctx, state, disp_cfg, mapping, existing_state);
+
if (ctx->architecture == dml2_architecture_21) {
/*
* Extract ODM and DPP outputs from DML2.1 and map them in an array as required for pipe mapping in dml2_map_dc_pipes.
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
index c3d5b84ee914..5494380062dd 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
@@ -167,6 +167,7 @@ struct dml2_configuration_options {
struct dml2_soc_bbox_overrides bbox_overrides;
unsigned int max_segments_per_hubp;
unsigned int det_segment_size;
+ bool map_dc_pipes_with_callbacks;
};
/*
--
2.34.1
More information about the amd-gfx
mailing list