]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Don't set 4to1MPC config dynamically
authorHarry Wentland <harry.wentland@amd.com>
Fri, 16 Jan 2026 16:47:50 +0000 (11:47 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 30 Mar 2026 18:52:56 +0000 (14:52 -0400)
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>
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c

index 80e217c5a23d63a73e5bb62d9fa215e21cc7bd6d..41b5dedb6effb7954715cbd912c033b15c77eb27 100644 (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;
index df9d50b9b57cd39170f059d69e152c75cf6d5819..ab016c294ba7e5057c79998f90d0aae99c89a2f0 100644 (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;
index 8a177d5ae213e7c4d2d715c3453d20b3d4c0202f..6713cd8ba86ac7849bc37119dbbb7a9b8acadf69 100644 (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
index 77023b619f1e0ba58b6c3127e6c5e9782a0882bc..73c2aee57f288898ffba7005d30a907115dfb821 100644 (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
index 8426d5f9f3771e887cd0e5d25ac502d4279c255b..b50a2509463e7e777eb9945e0f058d36751e24ba 100644 (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;
index 6ce6b2b1f288a1b0b696d27898cde83869077aca..428524f2ede6d6a764f8f728d94f4d726366898b 100644 (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;
index 66bf7725aeaf093bb08c770f8f6f50cb9bfb795e..795de8f651179a5bf6f2563175552d43cf5af054 100644 (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;
index 0e0c52128c55d699daf466188eac82de0f3d36fe..4db684fbc2171f3238e76883497d9140630622ae 100644 (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;
index 63675b53674af505fe5ebe4985322b6e817bb1d8..db94141d113ff2d266cab75c38c45a5ccaf5a76d 100644 (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*/
index ff557c4d594e4929c378ca9cda9dcd310782b168..5118bec38d32afd6ba300311b397293ab118df19 100644 (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),
index 0c39d0b17947011a80ccacbe0b6e934d2bf04dbe..b64ad2d9fc2f4dee3c6d3d4071ca83f24a1b8eef 100644 (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),