drm/amd/display: Don't set 4to1MPC config dynamically

We were previously modifying the global dc->config.enable_4to1MPC
dynamically. These variables are meant as global configs, not to
by dynamically modified. Modifying them dynamically prevents us
from enabling/disabling functionality for debug purposes and can
easily lead to bad things since we're not operating on the current
state but on DC-wide variables.

Instead we should look at the existing split4mpc decision in
dcn20_validate_apply_split_flags and make the decision there,
if the global config.enable_4to1MPC is set to true for the
DCN version we're running.

This fixes corruption that is observed when running a new IGT
kms_colorop test for color-space-conversion that uses a
YUV plane and outputs to a writeback connector.

Co-developed by Claude Sonnet 4.5.

Assisted-by: Claude:claude-sonnet-4.5
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Chuanyu Tseng <chuanyu.tseng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Harry Wentland 2026-01-16 11:47:50 -05:00 committed by Alex Deucher
parent 86117c5ab4
commit 4c3aeb11d5
11 changed files with 39 additions and 29 deletions

View File

@ -521,7 +521,7 @@ struct dc_config {
union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode;
bool multi_mon_pp_mclk_switch;
bool disable_dmcu;
bool enable_4to1MPC;
bool allow_4to1MPC;
bool enable_windowed_mpo_odm;
bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520
uint32_t allow_edp_hotplug_detection;

View File

@ -391,13 +391,9 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE;
dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state
&& pipe->plane_state->rotation == ROTATION_ANGLE_0 && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
dc->config.enable_4to1MPC = true;
} else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
/* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
pipes[0].pipe.src.unbounded_req_mode = true;

View File

@ -528,14 +528,9 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc,
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/
dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 &&
pipe->plane_state->src_rect.height <= 1080) {
dc->config.enable_4to1MPC = true;
} else if (!is_dual_plane(pipe->plane_state->format) &&
if (!is_dual_plane(pipe->plane_state->format) &&
pipe->plane_state->src_rect.width <= 5120) {
/*
* Limit to 5k max to avoid forced pipe split when there

View File

@ -561,14 +561,9 @@ int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc,
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/
dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 &&
pipe->plane_state->src_rect.height <= 1080) {
dc->config.enable_4to1MPC = true;
} else if (!is_dual_plane(pipe->plane_state->format) &&
if (!is_dual_plane(pipe->plane_state->format) &&
pipe->plane_state->src_rect.width <= 5120) {
/*
* Limit to 5k max to avoid forced pipe split when there

View File

@ -1814,6 +1814,11 @@ void dcn20_merge_pipes_for_validate(
}
}
static bool is_dual_plane(enum surface_pixel_format format)
{
return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
}
int dcn20_validate_apply_pipe_split_flags(
struct dc *dc,
struct dc_state *context,
@ -1898,8 +1903,15 @@ int dcn20_validate_apply_pipe_split_flags(
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
int pipe_plane = v->pipe_plane[pipe_idx];
bool split4mpc = context->stream_count == 1 && plane_count == 1
&& dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4;
bool split4mpc = false;
if (context->stream_count == 1 && plane_count == 1
&& dc->config.allow_4to1MPC && dc->res_pool->pipe_count >= 4
&& !dc->debug.disable_z9_mpc
&& pipe->plane_state && is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920
&& pipe->plane_state->src_rect.height <= 1080)
split4mpc = true;
if (!context->res_ctx.pipe_ctx[i].stream)
continue;

View File

@ -1699,12 +1699,9 @@ int dcn31_populate_dml_pipes_from_context(
pipe_cnt++;
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE;
dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
dc->config.enable_4to1MPC = true;
} else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
/* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
pipes[0].pipe.src.unbounded_req_mode = true;
@ -1922,6 +1919,9 @@ static bool dcn31_resource_construct(
dc->caps.is_apu = true;
dc->caps.zstate_support = true;
/* Enable 4to1MPC by default */
dc->config.allow_4to1MPC = true;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
dc->caps.color.dpp.input_lut_shared = 0;

View File

@ -1830,6 +1830,9 @@ static bool dcn314_resource_construct(
pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
/* Enable 4to1MPC by default */
dc->config.allow_4to1MPC = true;
dc->caps.max_downscale_ratio = 400;
dc->caps.i2c_speed_in_khz = 100;
dc->caps.i2c_speed_in_khz_hdcp = 100;

View File

@ -1785,11 +1785,9 @@ static int dcn315_populate_dml_pipes_from_context(
if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE)
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE;
dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
dc->config.enable_4to1MPC = true;
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB;
} else if (!is_dual_plane(pipe->plane_state->format)
@ -1870,6 +1868,9 @@ static bool dcn315_resource_construct(
*************************************************/
pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
/* Enable 4to1MPC by default */
dc->config.allow_4to1MPC = true;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
dc->caps.i2c_speed_in_khz = 100;

View File

@ -1669,11 +1669,9 @@ static int dcn316_populate_dml_pipes_from_context(
if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_16_MAX_DET_SIZE)
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_16_MAX_DET_SIZE;
ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_16_DEFAULT_DET_SIZE);
dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
dc->config.enable_4to1MPC = true;
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / 4) * DCN3_16_CRB_SEGMENT_SIZE_KB;
} else if (!is_dual_plane(pipe->plane_state->format)) {
@ -1746,6 +1744,10 @@ static bool dcn316_resource_construct(
pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
/* Enable 4to1MPC by default */
dc->config.allow_4to1MPC = true;
dc->caps.max_downscale_ratio = 600;
dc->caps.i2c_speed_in_khz = 100;
dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/

View File

@ -1827,6 +1827,9 @@ static bool dcn35_resource_construct(
clk_src_regs_init(3, D),
clk_src_regs_init(4, E);
/* Enable 4to1MPC by default */
dc->config.allow_4to1MPC = true;
#undef REG_STRUCT
#define REG_STRUCT abm_regs
abm_regs_init(0),

View File

@ -1800,6 +1800,9 @@ static bool dcn351_resource_construct(
clk_src_regs_init(3, D),
clk_src_regs_init(4, E);
/* Enable 4to1MPC by default */
dc->config.allow_4to1MPC = true;
#undef REG_STRUCT
#define REG_STRUCT abm_regs
abm_regs_init(0),