OSDN Git Service

drm/amd/display: Move dlg params calculation
authorRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Fri, 8 Jul 2022 15:50:22 +0000 (11:50 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 25 Jul 2022 13:31:04 +0000 (09:31 -0400)
Move dlg params calculation to the FPU folder and make it static.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h

index 3385b5c..0ca1d4c 100644 (file)
@@ -1752,368 +1752,6 @@ void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context,
        }
 }
 
-static bool dcn32_split_stream_for_mpc_or_odm(
-               const struct dc *dc,
-               struct resource_context *res_ctx,
-               struct pipe_ctx *pri_pipe,
-               struct pipe_ctx *sec_pipe,
-               bool odm)
-{
-       int pipe_idx = sec_pipe->pipe_idx;
-       const struct resource_pool *pool = dc->res_pool;
-
-       if (pri_pipe->plane_state) {
-               /* ODM + window MPO, where MPO window is on left half only */
-               if (pri_pipe->plane_state->clip_rect.x + pri_pipe->plane_state->clip_rect.width <=
-                               pri_pipe->stream->src.x + pri_pipe->stream->src.width/2)
-                       return true;
-
-               /* ODM + window MPO, where MPO window is on right half only */
-               if (pri_pipe->plane_state->clip_rect.x >= pri_pipe->stream->src.width/2)
-                       return true;
-       }
-
-       *sec_pipe = *pri_pipe;
-
-       sec_pipe->pipe_idx = pipe_idx;
-       sec_pipe->plane_res.mi = pool->mis[pipe_idx];
-       sec_pipe->plane_res.hubp = pool->hubps[pipe_idx];
-       sec_pipe->plane_res.ipp = pool->ipps[pipe_idx];
-       sec_pipe->plane_res.xfm = pool->transforms[pipe_idx];
-       sec_pipe->plane_res.dpp = pool->dpps[pipe_idx];
-       sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst;
-       sec_pipe->stream_res.dsc = NULL;
-       if (odm) {
-               if (pri_pipe->next_odm_pipe) {
-                       ASSERT(pri_pipe->next_odm_pipe != sec_pipe);
-                       sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe;
-                       sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe;
-               }
-               if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) {
-                       pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe;
-                       sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe;
-               }
-               if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) {
-                       pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe;
-                       sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe;
-               }
-               pri_pipe->next_odm_pipe = sec_pipe;
-               sec_pipe->prev_odm_pipe = pri_pipe;
-               ASSERT(sec_pipe->top_pipe == NULL);
-
-               if (!sec_pipe->top_pipe)
-                       sec_pipe->stream_res.opp = pool->opps[pipe_idx];
-               else
-                       sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp;
-               if (sec_pipe->stream->timing.flags.DSC == 1) {
-                       dcn20_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx);
-                       ASSERT(sec_pipe->stream_res.dsc);
-                       if (sec_pipe->stream_res.dsc == NULL)
-                               return false;
-               }
-       } else {
-               if (pri_pipe->bottom_pipe) {
-                       ASSERT(pri_pipe->bottom_pipe != sec_pipe);
-                       sec_pipe->bottom_pipe = pri_pipe->bottom_pipe;
-                       sec_pipe->bottom_pipe->top_pipe = sec_pipe;
-               }
-               pri_pipe->bottom_pipe = sec_pipe;
-               sec_pipe->top_pipe = pri_pipe;
-
-               ASSERT(pri_pipe->plane_state);
-       }
-
-       return true;
-}
-
-static struct pipe_ctx *dcn32_find_split_pipe(
-               struct dc *dc,
-               struct dc_state *context,
-               int old_index)
-{
-       struct pipe_ctx *pipe = NULL;
-       int i;
-
-       if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) {
-               pipe = &context->res_ctx.pipe_ctx[old_index];
-               pipe->pipe_idx = old_index;
-       }
-
-       if (!pipe)
-               for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
-                       if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL
-                                       && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) {
-                               if (context->res_ctx.pipe_ctx[i].stream == NULL) {
-                                       pipe = &context->res_ctx.pipe_ctx[i];
-                                       pipe->pipe_idx = i;
-                                       break;
-                               }
-                       }
-               }
-
-       /*
-        * May need to fix pipes getting tossed from 1 opp to another on flip
-        * Add for debugging transient underflow during topology updates:
-        * ASSERT(pipe);
-        */
-       if (!pipe)
-               for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
-                       if (context->res_ctx.pipe_ctx[i].stream == NULL) {
-                               pipe = &context->res_ctx.pipe_ctx[i];
-                               pipe->pipe_idx = i;
-                               break;
-                       }
-               }
-
-       return pipe;
-}
-
-static bool dcn32_internal_validate_bw(
-               struct dc *dc,
-               struct dc_state *context,
-               display_e2e_pipe_params_st *pipes,
-               int *pipe_cnt_out,
-               int *vlevel_out,
-               bool fast_validate)
-{
-       bool out = false;
-       bool repopulate_pipes = false;
-       int split[MAX_PIPES] = { 0 };
-       bool merge[MAX_PIPES] = { false };
-       bool newly_split[MAX_PIPES] = { false };
-       int pipe_cnt, i, pipe_idx, vlevel;
-       struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
-
-       ASSERT(pipes);
-       if (!pipes)
-               return false;
-
-       // For each full update, remove all existing phantom pipes first
-       dc->res_pool->funcs->remove_phantom_pipes(dc, context);
-
-       dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
-
-       pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
-
-       if (!pipe_cnt) {
-               out = true;
-               goto validate_out;
-       }
-
-       dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt);
-
-       if (!fast_validate) {
-               DC_FP_START();
-               dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt);
-               DC_FP_END();
-       }
-
-       if (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states ||
-                       vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported) {
-               /*
-                * If mode is unsupported or there's still no p-state support then
-                * fall back to favoring voltage.
-                *
-                * We don't actually support prefetch mode 2, so require that we
-                * at least support prefetch mode 1.
-                */
-               context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
-                               dm_prefetch_support_stutter;
-
-               vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
-               if (vlevel < context->bw_ctx.dml.soc.num_states) {
-                       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);
-               }
-       }
-
-       dml_log_mode_support_params(&context->bw_ctx.dml);
-
-       if (vlevel == context->bw_ctx.dml.soc.num_states)
-               goto validate_fail;
-
-       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
-               struct pipe_ctx *mpo_pipe = pipe->bottom_pipe;
-
-               if (!pipe->stream)
-                       continue;
-
-               /* We only support full screen mpo with ODM */
-               if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled
-                               && pipe->plane_state && mpo_pipe
-                               && memcmp(&mpo_pipe->plane_res.scl_data.recout,
-                                               &pipe->plane_res.scl_data.recout,
-                                               sizeof(struct rect)) != 0) {
-                       ASSERT(mpo_pipe->plane_state != pipe->plane_state);
-                       goto validate_fail;
-               }
-               pipe_idx++;
-       }
-
-       /* merge pipes if necessary */
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
-
-               /*skip pipes that don't need merging*/
-               if (!merge[i])
-                       continue;
-
-               /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */
-               if (pipe->prev_odm_pipe) {
-                       /*split off odm pipe*/
-                       pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;
-                       if (pipe->next_odm_pipe)
-                               pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
-
-                       pipe->bottom_pipe = NULL;
-                       pipe->next_odm_pipe = NULL;
-                       pipe->plane_state = NULL;
-                       pipe->stream = NULL;
-                       pipe->top_pipe = NULL;
-                       pipe->prev_odm_pipe = NULL;
-                       if (pipe->stream_res.dsc)
-                               dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);
-                       memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
-                       memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
-                       repopulate_pipes = true;
-               } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
-                       struct pipe_ctx *top_pipe = pipe->top_pipe;
-                       struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;
-
-                       top_pipe->bottom_pipe = bottom_pipe;
-                       if (bottom_pipe)
-                               bottom_pipe->top_pipe = top_pipe;
-
-                       pipe->top_pipe = NULL;
-                       pipe->bottom_pipe = NULL;
-                       pipe->plane_state = NULL;
-                       pipe->stream = NULL;
-                       memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
-                       memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
-                       repopulate_pipes = true;
-               } else
-                       ASSERT(0); /* Should never try to merge master pipe */
-
-       }
-
-       for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
-               struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
-               struct pipe_ctx *hsplit_pipe = NULL;
-               bool odm;
-               int old_index = -1;
-
-               if (!pipe->stream || newly_split[i])
-                       continue;
-
-               pipe_idx++;
-               odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled;
-
-               if (!pipe->plane_state && !odm)
-                       continue;
-
-               if (split[i]) {
-                       if (odm) {
-                               if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)
-                                       old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
-                               else if (old_pipe->next_odm_pipe)
-                                       old_index = old_pipe->next_odm_pipe->pipe_idx;
-                       } else {
-                               if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
-                                               old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
-                                       old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;
-                               else if (old_pipe->bottom_pipe &&
-                                               old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
-                                       old_index = old_pipe->bottom_pipe->pipe_idx;
-                       }
-                       hsplit_pipe = dcn32_find_split_pipe(dc, context, old_index);
-                       ASSERT(hsplit_pipe);
-                       if (!hsplit_pipe)
-                               goto validate_fail;
-
-                       if (!dcn32_split_stream_for_mpc_or_odm(
-                                       dc, &context->res_ctx,
-                                       pipe, hsplit_pipe, odm))
-                               goto validate_fail;
-
-                       newly_split[hsplit_pipe->pipe_idx] = true;
-                       repopulate_pipes = true;
-               }
-               if (split[i] == 4) {
-                       struct pipe_ctx *pipe_4to1;
-
-                       if (odm && old_pipe->next_odm_pipe)
-                               old_index = old_pipe->next_odm_pipe->pipe_idx;
-                       else if (!odm && old_pipe->bottom_pipe &&
-                                               old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
-                               old_index = old_pipe->bottom_pipe->pipe_idx;
-                       else
-                               old_index = -1;
-                       pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
-                       ASSERT(pipe_4to1);
-                       if (!pipe_4to1)
-                               goto validate_fail;
-                       if (!dcn32_split_stream_for_mpc_or_odm(
-                                       dc, &context->res_ctx,
-                                       pipe, pipe_4to1, odm))
-                               goto validate_fail;
-                       newly_split[pipe_4to1->pipe_idx] = true;
-
-                       if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe
-                                       && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
-                               old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
-                       else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
-                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
-                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
-                               old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;
-                       else
-                               old_index = -1;
-                       pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
-                       ASSERT(pipe_4to1);
-                       if (!pipe_4to1)
-                               goto validate_fail;
-                       if (!dcn32_split_stream_for_mpc_or_odm(
-                                       dc, &context->res_ctx,
-                                       hsplit_pipe, pipe_4to1, odm))
-                               goto validate_fail;
-                       newly_split[pipe_4to1->pipe_idx] = true;
-               }
-               if (odm)
-                       dcn20_build_mapped_resource(dc, context, pipe->stream);
-       }
-
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
-
-               if (pipe->plane_state) {
-                       if (!resource_build_scaling_params(pipe))
-                               goto validate_fail;
-               }
-       }
-
-       /* Actual dsc count per stream dsc validation*/
-       if (!dcn20_validate_dsc(dc, context)) {
-               vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE;
-               goto validate_fail;
-       }
-
-       if (repopulate_pipes)
-               pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
-       *vlevel_out = vlevel;
-       *pipe_cnt_out = pipe_cnt;
-
-       out = true;
-       goto validate_out;
-
-validate_fail:
-       out = false;
-
-validate_out:
-       return out;
-}
-
 bool dcn32_validate_bandwidth(struct dc *dc,
                struct dc_state *context,
                bool fast_validate)
@@ -2129,9 +1767,9 @@ bool dcn32_validate_bandwidth(struct dc *dc,
 
        BW_VAL_TRACE_COUNT();
 
-    DC_FP_START();
+       DC_FP_START();
        out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
-    DC_FP_END();
+       DC_FP_END();
 
        if (pipe_cnt == 0)
                goto validate_out;
@@ -2317,125 +1955,6 @@ void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context,
     DC_FP_END();
 }
 
-static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
-{
-       int i;
-
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               if (!context->res_ctx.pipe_ctx[i].stream)
-                       continue;
-               if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i]))
-                       return true;
-       }
-       return false;
-}
-
-void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes,
-               int pipe_cnt, int vlevel)
-{
-       int i, pipe_idx;
-       bool usr_retraining_support = false;
-       bool unbounded_req_enabled = false;
-
-       /* Writeback MCIF_WB arbitration parameters */
-       dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt);
-
-       context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000;
-       context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000;
-       context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000;
-       context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16;
-       context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000;
-       context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000;
-       context->bw_ctx.bw.dcn.clk.p_state_change_support =
-                       context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb]
-                                       != dm_dram_clock_change_unsupported;
-       context->bw_ctx.bw.dcn.clk.num_ways = dcn32_helper_calculate_num_ways_for_subvp(dc, context);
-       /*
- *
-        * TODO: needs FAMS
-        * Pstate change might not be supported by hardware, but it might be
-        * possible with firmware driven vertical blank stretching.
-        */
-       // context->bw_ctx.bw.dcn.clk.p_state_change_support |= context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching;
-       context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
-       context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context);
-       context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = context->bw_ctx.dml.vba.DTBCLKPerState[vlevel] * 1000;
-       if (context->bw_ctx.dml.vba.FCLKChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_fclock_change_unsupported)
-               context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false;
-       else
-               context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true;
-
-       usr_retraining_support = context->bw_ctx.dml.vba.USRRetrainingSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
-       ASSERT(usr_retraining_support);
-
-       if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz)
-               context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz;
-
-       unbounded_req_enabled = get_unbounded_request_enabled(&context->bw_ctx.dml, pipes, pipe_cnt);
-
-       if (unbounded_req_enabled && pipe_cnt > 1) {
-               // Unbounded requesting should not ever be used when more than 1 pipe is enabled.
-               ASSERT(false);
-               unbounded_req_enabled = false;
-       }
-
-       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
-               if (!context->res_ctx.pipe_ctx[i].stream)
-                       continue;
-               pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt,
-                               pipe_idx);
-               pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt,
-                               pipe_idx);
-               pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt,
-                               pipe_idx);
-               pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt,
-                               pipe_idx);
-               if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) {
-                       // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
-                       context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0;
-                       context->res_ctx.pipe_ctx[i].unbounded_req = false;
-               } else {
-                       context->res_ctx.pipe_ctx[i].det_buffer_size_kb = get_det_buffer_size_kbytes(&context->bw_ctx.dml, pipes, pipe_cnt,
-                                                       pipe_idx);
-                       context->res_ctx.pipe_ctx[i].unbounded_req = unbounded_req_enabled;
-               }
-               if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
-                       context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
-               context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
-               context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
-               pipe_idx++;
-       }
-       /*save a original dppclock copy*/
-       context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
-       context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
-       context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz
-                       * 1000;
-       context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz
-                       * 1000;
-
-       context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes;
-
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               if (context->res_ctx.pipe_ctx[i].stream)
-                       context->bw_ctx.bw.dcn.compbuf_size_kb -= context->res_ctx.pipe_ctx[i].det_buffer_size_kb;
-       }
-
-       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
-
-               if (!context->res_ctx.pipe_ctx[i].stream)
-                       continue;
-
-               context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg_v2(&context->bw_ctx.dml,
-                               &context->res_ctx.pipe_ctx[i].dlg_regs, &context->res_ctx.pipe_ctx[i].ttu_regs, pipes,
-                               pipe_cnt, pipe_idx);
-
-               context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg_v2(&context->res_ctx.pipe_ctx[i].rq_regs,
-                               &context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
-
-               pipe_idx++;
-       }
-}
-
 static void get_optimal_ntuple(struct _vcs_dpi_voltage_scaling_st *entry)
 {
        if (entry->dcfclk_mhz > 0) {
index 37d3706..fc0fe48 100644 (file)
@@ -44,12 +44,6 @@ struct resource_pool *dcn32_create_resource_pool(
                const struct dc_init_data *init_data,
                struct dc *dc);
 
-void dcn32_calculate_dlg_params(
-               struct dc *dc, struct dc_state *context,
-               display_e2e_pipe_params_st *pipes,
-               int pipe_cnt,
-               int vlevel);
-
 struct panel_cntl *dcn32_panel_cntl_create(
                const struct panel_cntl_init_data *init_data);
 
index 353d3a7..66102db 100644 (file)
  *
  */
 #include "dcn32_fpu.h"
+#include "dc_link_dp.h"
 #include "dcn32/dcn32_resource.h"
 #include "dcn20/dcn20_resource.h"
 #include "display_mode_vba_util_32.h"
 // We need this includes for WATERMARKS_* defines
 #include "clk_mgr/dcn32/dcn32_smu13_driver_if.h"
 
+#define DC_LOGGER_INIT(logger)
+
 struct _vcs_dpi_ip_params_st dcn3_2_ip = {
        .gpuvm_enable = 0,
        .gpuvm_max_page_table_levels = 4,
@@ -931,7 +934,7 @@ static bool subvp_validate_static_schedulability(struct dc *dc,
        return schedulable;
 }
 
-void dcn32_full_validate_bw_helper(struct dc *dc,
+static void dcn32_full_validate_bw_helper(struct dc *dc,
                                   struct dc_state *context,
                                   display_e2e_pipe_params_st *pipes,
                                   int *vlevel,
@@ -1058,6 +1061,507 @@ void dcn32_full_validate_bw_helper(struct dc *dc,
        }
 }
 
+static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
+{
+       int i;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (!context->res_ctx.pipe_ctx[i].stream)
+                       continue;
+               if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i]))
+                       return true;
+       }
+       return false;
+}
+
+static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
+                                      display_e2e_pipe_params_st *pipes,
+                                      int pipe_cnt, int vlevel)
+{
+       int i, pipe_idx;
+       bool usr_retraining_support = false;
+       bool unbounded_req_enabled = false;
+
+       dc_assert_fp_enabled();
+
+       /* Writeback MCIF_WB arbitration parameters */
+       dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt);
+
+       context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000;
+       context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000;
+       context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000;
+       context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16;
+       context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000;
+       context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000;
+       context->bw_ctx.bw.dcn.clk.p_state_change_support =
+                       context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb]
+                                       != dm_dram_clock_change_unsupported;
+       context->bw_ctx.bw.dcn.clk.num_ways = dcn32_helper_calculate_num_ways_for_subvp(dc, context);
+
+       context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
+       context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context);
+       context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = context->bw_ctx.dml.vba.DTBCLKPerState[vlevel] * 1000;
+       if (context->bw_ctx.dml.vba.FCLKChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_fclock_change_unsupported)
+               context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false;
+       else
+               context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true;
+
+       usr_retraining_support = context->bw_ctx.dml.vba.USRRetrainingSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
+       ASSERT(usr_retraining_support);
+
+       if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz)
+               context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz;
+
+       unbounded_req_enabled = get_unbounded_request_enabled(&context->bw_ctx.dml, pipes, pipe_cnt);
+
+       if (unbounded_req_enabled && pipe_cnt > 1) {
+               // Unbounded requesting should not ever be used when more than 1 pipe is enabled.
+               ASSERT(false);
+               unbounded_req_enabled = false;
+       }
+
+       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
+               if (!context->res_ctx.pipe_ctx[i].stream)
+                       continue;
+               pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt,
+                               pipe_idx);
+               pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt,
+                               pipe_idx);
+               pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt,
+                               pipe_idx);
+               pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt,
+                               pipe_idx);
+
+               if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) {
+                       // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
+                       context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0;
+                       context->res_ctx.pipe_ctx[i].unbounded_req = false;
+               } else {
+                       context->res_ctx.pipe_ctx[i].det_buffer_size_kb = get_det_buffer_size_kbytes(&context->bw_ctx.dml, pipes, pipe_cnt,
+                                                       pipe_idx);
+                       context->res_ctx.pipe_ctx[i].unbounded_req = unbounded_req_enabled;
+               }
+
+               if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
+                       context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
+               context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
+               context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
+               pipe_idx++;
+       }
+       /*save a original dppclock copy*/
+       context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
+       context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
+       context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz
+                       * 1000;
+       context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz
+                       * 1000;
+
+       context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (context->res_ctx.pipe_ctx[i].stream)
+                       context->bw_ctx.bw.dcn.compbuf_size_kb -= context->res_ctx.pipe_ctx[i].det_buffer_size_kb;
+       }
+
+       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
+
+               if (!context->res_ctx.pipe_ctx[i].stream)
+                       continue;
+
+               context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg_v2(&context->bw_ctx.dml,
+                               &context->res_ctx.pipe_ctx[i].dlg_regs, &context->res_ctx.pipe_ctx[i].ttu_regs, pipes,
+                               pipe_cnt, pipe_idx);
+
+               context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg_v2(&context->res_ctx.pipe_ctx[i].rq_regs,
+                               &context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
+               pipe_idx++;
+       }
+}
+
+static struct pipe_ctx *dcn32_find_split_pipe(
+               struct dc *dc,
+               struct dc_state *context,
+               int old_index)
+{
+       struct pipe_ctx *pipe = NULL;
+       int i;
+
+       if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) {
+               pipe = &context->res_ctx.pipe_ctx[old_index];
+               pipe->pipe_idx = old_index;
+       }
+
+       if (!pipe)
+               for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
+                       if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL
+                                       && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) {
+                               if (context->res_ctx.pipe_ctx[i].stream == NULL) {
+                                       pipe = &context->res_ctx.pipe_ctx[i];
+                                       pipe->pipe_idx = i;
+                                       break;
+                               }
+                       }
+               }
+
+       /*
+        * May need to fix pipes getting tossed from 1 opp to another on flip
+        * Add for debugging transient underflow during topology updates:
+        * ASSERT(pipe);
+        */
+       if (!pipe)
+               for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
+                       if (context->res_ctx.pipe_ctx[i].stream == NULL) {
+                               pipe = &context->res_ctx.pipe_ctx[i];
+                               pipe->pipe_idx = i;
+                               break;
+                       }
+               }
+
+       return pipe;
+}
+
+static bool dcn32_split_stream_for_mpc_or_odm(
+               const struct dc *dc,
+               struct resource_context *res_ctx,
+               struct pipe_ctx *pri_pipe,
+               struct pipe_ctx *sec_pipe,
+               bool odm)
+{
+       int pipe_idx = sec_pipe->pipe_idx;
+       const struct resource_pool *pool = dc->res_pool;
+
+       DC_LOGGER_INIT(dc->ctx->logger);
+
+       if (odm && pri_pipe->plane_state) {
+               /* ODM + window MPO, where MPO window is on left half only */
+               if (pri_pipe->plane_state->clip_rect.x + pri_pipe->plane_state->clip_rect.width <=
+                               pri_pipe->stream->src.x + pri_pipe->stream->src.width/2) {
+
+                       DC_LOG_SCALER("%s - ODM + window MPO(left). pri_pipe:%d\n",
+                                       __func__,
+                                       pri_pipe->pipe_idx);
+                       return true;
+               }
+
+               /* ODM + window MPO, where MPO window is on right half only */
+               if (pri_pipe->plane_state->clip_rect.x >= pri_pipe->stream->src.x +  pri_pipe->stream->src.width/2) {
+
+                       DC_LOG_SCALER("%s - ODM + window MPO(right). pri_pipe:%d\n",
+                                       __func__,
+                                       pri_pipe->pipe_idx);
+                       return true;
+               }
+       }
+
+       *sec_pipe = *pri_pipe;
+
+       sec_pipe->pipe_idx = pipe_idx;
+       sec_pipe->plane_res.mi = pool->mis[pipe_idx];
+       sec_pipe->plane_res.hubp = pool->hubps[pipe_idx];
+       sec_pipe->plane_res.ipp = pool->ipps[pipe_idx];
+       sec_pipe->plane_res.xfm = pool->transforms[pipe_idx];
+       sec_pipe->plane_res.dpp = pool->dpps[pipe_idx];
+       sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst;
+       sec_pipe->stream_res.dsc = NULL;
+       if (odm) {
+               if (pri_pipe->next_odm_pipe) {
+                       ASSERT(pri_pipe->next_odm_pipe != sec_pipe);
+                       sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe;
+                       sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe;
+               }
+               if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) {
+                       pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe;
+                       sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe;
+               }
+               if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) {
+                       pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe;
+                       sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe;
+               }
+               pri_pipe->next_odm_pipe = sec_pipe;
+               sec_pipe->prev_odm_pipe = pri_pipe;
+               ASSERT(sec_pipe->top_pipe == NULL);
+
+               if (!sec_pipe->top_pipe)
+                       sec_pipe->stream_res.opp = pool->opps[pipe_idx];
+               else
+                       sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp;
+               if (sec_pipe->stream->timing.flags.DSC == 1) {
+                       dcn20_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx);
+                       ASSERT(sec_pipe->stream_res.dsc);
+                       if (sec_pipe->stream_res.dsc == NULL)
+                               return false;
+               }
+       } else {
+               if (pri_pipe->bottom_pipe) {
+                       ASSERT(pri_pipe->bottom_pipe != sec_pipe);
+                       sec_pipe->bottom_pipe = pri_pipe->bottom_pipe;
+                       sec_pipe->bottom_pipe->top_pipe = sec_pipe;
+               }
+               pri_pipe->bottom_pipe = sec_pipe;
+               sec_pipe->top_pipe = pri_pipe;
+
+               ASSERT(pri_pipe->plane_state);
+       }
+
+       return true;
+}
+
+bool dcn32_internal_validate_bw(struct dc *dc,
+                               struct dc_state *context,
+                               display_e2e_pipe_params_st *pipes,
+                               int *pipe_cnt_out,
+                               int *vlevel_out,
+                               bool fast_validate)
+{
+       bool out = false;
+       bool repopulate_pipes = false;
+       int split[MAX_PIPES] = { 0 };
+       bool merge[MAX_PIPES] = { false };
+       bool newly_split[MAX_PIPES] = { false };
+       int pipe_cnt, i, pipe_idx, vlevel;
+       struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
+
+       dc_assert_fp_enabled();
+
+       ASSERT(pipes);
+       if (!pipes)
+               return false;
+
+       // For each full update, remove all existing phantom pipes first
+       dc->res_pool->funcs->remove_phantom_pipes(dc, context);
+
+       dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
+
+       pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
+
+       if (!pipe_cnt) {
+               out = true;
+               goto validate_out;
+       }
+
+       dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt);
+
+       if (!fast_validate) {
+               DC_FP_START();
+               dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt);
+               DC_FP_END();
+       }
+
+       if (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states ||
+                       vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported) {
+               /*
+                * If mode is unsupported or there's still no p-state support then
+                * fall back to favoring voltage.
+                *
+                * If Prefetch mode 0 failed for this config, or passed with Max UCLK, try if
+                * supported with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2)
+                */
+               context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
+                               dm_prefetch_support_fclk_and_stutter;
+
+               vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+
+               /* Last attempt with Prefetch mode 2 (dm_prefetch_support_stutter == 3) */
+               if (vlevel == context->bw_ctx.dml.soc.num_states) {
+                       context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
+                               dm_prefetch_support_stutter;
+                       vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+               }
+
+               if (vlevel < context->bw_ctx.dml.soc.num_states) {
+                       memset(split, 0, sizeof(split));
+                       memset(merge, 0, sizeof(merge));
+                       vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);
+               }
+       }
+
+       dml_log_mode_support_params(&context->bw_ctx.dml);
+
+       if (vlevel == context->bw_ctx.dml.soc.num_states)
+               goto validate_fail;
+
+       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *mpo_pipe = pipe->bottom_pipe;
+
+               if (!pipe->stream)
+                       continue;
+
+               if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled
+                               && !dc->config.enable_windowed_mpo_odm
+                               && pipe->plane_state && mpo_pipe
+                               && memcmp(&mpo_pipe->plane_res.scl_data.recout,
+                                               &pipe->plane_res.scl_data.recout,
+                                               sizeof(struct rect)) != 0) {
+                       ASSERT(mpo_pipe->plane_state != pipe->plane_state);
+                       goto validate_fail;
+               }
+               pipe_idx++;
+       }
+
+       /* merge pipes if necessary */
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+               /*skip pipes that don't need merging*/
+               if (!merge[i])
+                       continue;
+
+               /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */
+               if (pipe->prev_odm_pipe) {
+                       /*split off odm pipe*/
+                       pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;
+                       if (pipe->next_odm_pipe)
+                               pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
+
+                       pipe->bottom_pipe = NULL;
+                       pipe->next_odm_pipe = NULL;
+                       pipe->plane_state = NULL;
+                       pipe->stream = NULL;
+                       pipe->top_pipe = NULL;
+                       pipe->prev_odm_pipe = NULL;
+                       if (pipe->stream_res.dsc)
+                               dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);
+                       memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
+                       memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
+                       repopulate_pipes = true;
+               } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
+                       struct pipe_ctx *top_pipe = pipe->top_pipe;
+                       struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;
+
+                       top_pipe->bottom_pipe = bottom_pipe;
+                       if (bottom_pipe)
+                               bottom_pipe->top_pipe = top_pipe;
+
+                       pipe->top_pipe = NULL;
+                       pipe->bottom_pipe = NULL;
+                       pipe->plane_state = NULL;
+                       pipe->stream = NULL;
+                       memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
+                       memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
+                       repopulate_pipes = true;
+               } else
+                       ASSERT(0); /* Should never try to merge master pipe */
+
+       }
+
+       for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *hsplit_pipe = NULL;
+               bool odm;
+               int old_index = -1;
+
+               if (!pipe->stream || newly_split[i])
+                       continue;
+
+               pipe_idx++;
+               odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled;
+
+               if (!pipe->plane_state && !odm)
+                       continue;
+
+               if (split[i]) {
+                       if (odm) {
+                               if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)
+                                       old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
+                               else if (old_pipe->next_odm_pipe)
+                                       old_index = old_pipe->next_odm_pipe->pipe_idx;
+                       } else {
+                               if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
+                                               old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+                                       old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;
+                               else if (old_pipe->bottom_pipe &&
+                                               old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+                                       old_index = old_pipe->bottom_pipe->pipe_idx;
+                       }
+                       hsplit_pipe = dcn32_find_split_pipe(dc, context, old_index);
+                       ASSERT(hsplit_pipe);
+                       if (!hsplit_pipe)
+                               goto validate_fail;
+
+                       if (!dcn32_split_stream_for_mpc_or_odm(
+                                       dc, &context->res_ctx,
+                                       pipe, hsplit_pipe, odm))
+                               goto validate_fail;
+
+                       newly_split[hsplit_pipe->pipe_idx] = true;
+                       repopulate_pipes = true;
+               }
+               if (split[i] == 4) {
+                       struct pipe_ctx *pipe_4to1;
+
+                       if (odm && old_pipe->next_odm_pipe)
+                               old_index = old_pipe->next_odm_pipe->pipe_idx;
+                       else if (!odm && old_pipe->bottom_pipe &&
+                                               old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+                               old_index = old_pipe->bottom_pipe->pipe_idx;
+                       else
+                               old_index = -1;
+                       pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
+                       ASSERT(pipe_4to1);
+                       if (!pipe_4to1)
+                               goto validate_fail;
+                       if (!dcn32_split_stream_for_mpc_or_odm(
+                                       dc, &context->res_ctx,
+                                       pipe, pipe_4to1, odm))
+                               goto validate_fail;
+                       newly_split[pipe_4to1->pipe_idx] = true;
+
+                       if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe
+                                       && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
+                               old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
+                       else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
+                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
+                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+                               old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;
+                       else
+                               old_index = -1;
+                       pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
+                       ASSERT(pipe_4to1);
+                       if (!pipe_4to1)
+                               goto validate_fail;
+                       if (!dcn32_split_stream_for_mpc_or_odm(
+                                       dc, &context->res_ctx,
+                                       hsplit_pipe, pipe_4to1, odm))
+                               goto validate_fail;
+                       newly_split[pipe_4to1->pipe_idx] = true;
+               }
+               if (odm)
+                       dcn20_build_mapped_resource(dc, context, pipe->stream);
+       }
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+               if (pipe->plane_state) {
+                       if (!resource_build_scaling_params(pipe))
+                               goto validate_fail;
+               }
+       }
+
+       /* Actual dsc count per stream dsc validation*/
+       if (!dcn20_validate_dsc(dc, context)) {
+               vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE;
+               goto validate_fail;
+       }
+
+       if (repopulate_pipes)
+               pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
+       *vlevel_out = vlevel;
+       *pipe_cnt_out = pipe_cnt;
+
+       out = true;
+       goto validate_out;
+
+validate_fail:
+       out = false;
+
+validate_out:
+       return out;
+}
+
+
 void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
                                display_e2e_pipe_params_st *pipes,
                                int pipe_cnt,
index c7602f0..56973de 100644 (file)
@@ -57,13 +57,12 @@ void dcn32_set_phantom_stream_timing(struct dc *dc,
                                     unsigned int pipe_cnt,
                                     unsigned int dc_pipe_idx);
 
-void dcn32_full_validate_bw_helper(struct dc *dc,
-                                  struct dc_state *context,
-                                  display_e2e_pipe_params_st *pipes,
-                                  int *vlevel,
-                                  int *split,
-                                  bool *merge,
-                                  int *pipe_cnt);
+bool dcn32_internal_validate_bw(struct dc *dc,
+                               struct dc_state *context,
+                               display_e2e_pipe_params_st *pipes,
+                               int *pipe_cnt_out,
+                               int *vlevel_out,
+                               bool fast_validate);
 
 void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
                                display_e2e_pipe_params_st *pipes,