drm/amd/display: SubVP pipe split case
authorAlvin Lee <Alvin.Lee2@amd.com>
Thu, 1 Sep 2022 22:54:22 +0000 (18:54 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 19 Sep 2022 19:12:39 +0000 (15:12 -0400)
[Why and How]
For SubVP pipe split case, pass in split index for
main and phantom pipes to ensure that the P-State
sequence will force P-State for all required pipes.

Reviewed-by: Nevenko Stupar <Nevenko.Stupar@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c

index df5ad02..f09a3dd 100644 (file)
@@ -674,12 +674,32 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
        pipe_data->pipe_config.subvp_data.processing_delay_lines =
                        div64_u64(((uint64_t)(dc->caps.subvp_fw_processing_delay_us) * ((uint64_t)phantom_timing->pix_clk_100hz * 100) +
                                        ((uint64_t)phantom_timing->h_total * 1000000 - 1)), ((uint64_t)phantom_timing->h_total * 1000000));
+
+       /* TODO: Uncomment once FW headers are promoted
+       if (subvp_pipe->bottom_pipe) {
+               pipe_data->pipe_config.subvp_data.main_split_pipe_index = subvp_pipe->bottom_pipe->pipe_idx;
+       } else if (subvp_pipe->next_odm_pipe) {
+               pipe_data->pipe_config.subvp_data.main_split_pipe_index = subvp_pipe->next_odm_pipe->pipe_idx;
+       } else {
+               pipe_data->pipe_config.subvp_data.main_split_pipe_index = 0;
+       }
+       */
+
        // Find phantom pipe index based on phantom stream
        for (j = 0; j < dc->res_pool->pipe_count; j++) {
                struct pipe_ctx *phantom_pipe = &context->res_ctx.pipe_ctx[j];
 
                if (phantom_pipe->stream == subvp_pipe->stream->mall_stream_config.paired_stream) {
                        pipe_data->pipe_config.subvp_data.phantom_pipe_index = phantom_pipe->pipe_idx;
+                       /* TODO: Uncomment once FW headers are promoted
+                       if (phantom_pipe->bottom_pipe) {
+                               pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->bottom_pipe->pipe_idx;
+                       } else if (phantom_pipe->next_odm_pipe) {
+                               pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->next_odm_pipe->pipe_idx;
+                       } else {
+                               pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = 0;
+                       }
+                       */
                        break;
                }
        }
@@ -724,7 +744,9 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
                if (!pipe->stream)
                        continue;
 
-               if (pipe->plane_state && !pipe->top_pipe &&
+               /* For SubVP pipe count, only count the top most (ODM / MPC) pipe
+                */
+               if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe &&
                                pipe->stream->mall_stream_config.type == SUBVP_MAIN)
                        subvp_pipes[subvp_count++] = pipe;
        }
@@ -737,7 +759,12 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
                        if (!pipe->stream)
                                continue;
 
+                       /* When populating subvp cmd info, only pass in the top most (ODM / MPC) pipe.
+                        * Any ODM or MPC splits being used in SubVP will be handled internally in
+                        * populate_subvp_cmd_pipe_info
+                        */
                        if (pipe->plane_state && pipe->stream->mall_stream_config.paired_stream &&
+                                       !pipe->top_pipe && !pipe->prev_odm_pipe &&
                                        pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
                                populate_subvp_cmd_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
                        } else if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_NONE) {
index 86ab3a7..ab56f14 100644 (file)
@@ -1906,10 +1906,13 @@ void dcn20_post_unlock_program_front_end(
                         * can underflow due to HUBP_VTG_SEL programming if done in the regular front end
                         * programming sequence).
                         */
-                       if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
-                               if (dc->hwss.update_phantom_vp_position)
-                                       dc->hwss.update_phantom_vp_position(dc, context, pipe);
-                               dcn20_program_pipe(dc, pipe, context);
+                       while (pipe) {
+                               if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
+                                       if (dc->hwss.update_phantom_vp_position)
+                                               dc->hwss.update_phantom_vp_position(dc, context, pipe);
+                                       dcn20_program_pipe(dc, pipe, context);
+                               }
+                               pipe = pipe->bottom_pipe;
                        }
                }
        }
index 2b3ffa3..7ff7cd8 100644 (file)
@@ -1160,17 +1160,23 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
                                vba->VoltageLevel = *vlevel;
                        }
                } else {
-                       // only call dcn20_validate_apply_pipe_split_flags if we found a supported config
-                       memset(split, 0, MAX_PIPES * sizeof(int));
-                       memset(merge, 0, MAX_PIPES * sizeof(bool));
-                       *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge);
-                       vba->VoltageLevel = *vlevel;
-
                        // Most populate phantom DLG params before programming hardware / timing for phantom pipe
                        DC_FP_START();
                        dcn32_helper_populate_phantom_dlg_params(dc, context, pipes, *pipe_cnt);
                        DC_FP_END();
 
+                       /* Call validate_apply_pipe_split flags after calling DML getters for
+                        * phantom dlg params, or some of the VBA params indicating pipe split
+                        * can be overwritten by the getters.
+                        *
+                        * When setting up SubVP config, all pipes are merged before attempting to
+                        * add phantom pipes. If pipe split (ODM / MPC) is required, both the main
+                        * and phantom pipes will be split in the regular pipe splitting sequence.
+                        */
+                       memset(split, 0, MAX_PIPES * sizeof(int));
+                       memset(merge, 0, MAX_PIPES * sizeof(bool));
+                       *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge);
+                       vba->VoltageLevel = *vlevel;
                        // Note: We can't apply the phantom pipes to hardware at this time. We have to wait
                        // until driver has acquired the DMCUB lock to do it safely.
                }