0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dcn32_fpu.h"
0027 #include "dc_link_dp.h"
0028 #include "dcn32/dcn32_resource.h"
0029 #include "dcn20/dcn20_resource.h"
0030 #include "display_mode_vba_util_32.h"
0031
0032 #include "clk_mgr/dcn32/dcn32_smu13_driver_if.h"
0033 #include "dcn30/dcn30_resource.h"
0034
0035 #define DC_LOGGER_INIT(logger)
0036
0037 struct _vcs_dpi_ip_params_st dcn3_2_ip = {
0038 .gpuvm_enable = 0,
0039 .gpuvm_max_page_table_levels = 4,
0040 .hostvm_enable = 0,
0041 .rob_buffer_size_kbytes = 128,
0042 .det_buffer_size_kbytes = DCN3_2_DEFAULT_DET_SIZE,
0043 .config_return_buffer_size_in_kbytes = 1280,
0044 .compressed_buffer_segment_size_in_kbytes = 64,
0045 .meta_fifo_size_in_kentries = 22,
0046 .zero_size_buffer_entries = 512,
0047 .compbuf_reserved_space_64b = 256,
0048 .compbuf_reserved_space_zs = 64,
0049 .dpp_output_buffer_pixels = 2560,
0050 .opp_output_buffer_lines = 1,
0051 .pixel_chunk_size_kbytes = 8,
0052 .alpha_pixel_chunk_size_kbytes = 4,
0053 .min_pixel_chunk_size_bytes = 1024,
0054 .dcc_meta_buffer_size_bytes = 6272,
0055 .meta_chunk_size_kbytes = 2,
0056 .min_meta_chunk_size_bytes = 256,
0057 .writeback_chunk_size_kbytes = 8,
0058 .ptoi_supported = false,
0059 .num_dsc = 4,
0060 .maximum_dsc_bits_per_component = 12,
0061 .maximum_pixels_per_line_per_dsc_unit = 6016,
0062 .dsc422_native_support = true,
0063 .is_line_buffer_bpp_fixed = true,
0064 .line_buffer_fixed_bpp = 57,
0065 .line_buffer_size_bits = 1171920,
0066 .max_line_buffer_lines = 32,
0067 .writeback_interface_buffer_size_kbytes = 90,
0068 .max_num_dpp = 4,
0069 .max_num_otg = 4,
0070 .max_num_hdmi_frl_outputs = 1,
0071 .max_num_wb = 1,
0072 .max_dchub_pscl_bw_pix_per_clk = 4,
0073 .max_pscl_lb_bw_pix_per_clk = 2,
0074 .max_lb_vscl_bw_pix_per_clk = 4,
0075 .max_vscl_hscl_bw_pix_per_clk = 4,
0076 .max_hscl_ratio = 6,
0077 .max_vscl_ratio = 6,
0078 .max_hscl_taps = 8,
0079 .max_vscl_taps = 8,
0080 .dpte_buffer_size_in_pte_reqs_luma = 64,
0081 .dpte_buffer_size_in_pte_reqs_chroma = 34,
0082 .dispclk_ramp_margin_percent = 1,
0083 .max_inter_dcn_tile_repeaters = 8,
0084 .cursor_buffer_size = 16,
0085 .cursor_chunk_size = 2,
0086 .writeback_line_buffer_buffer_size = 0,
0087 .writeback_min_hscl_ratio = 1,
0088 .writeback_min_vscl_ratio = 1,
0089 .writeback_max_hscl_ratio = 1,
0090 .writeback_max_vscl_ratio = 1,
0091 .writeback_max_hscl_taps = 1,
0092 .writeback_max_vscl_taps = 1,
0093 .dppclk_delay_subtotal = 47,
0094 .dppclk_delay_scl = 50,
0095 .dppclk_delay_scl_lb_only = 16,
0096 .dppclk_delay_cnvc_formatter = 28,
0097 .dppclk_delay_cnvc_cursor = 6,
0098 .dispclk_delay_subtotal = 125,
0099 .dynamic_metadata_vm_enabled = false,
0100 .odm_combine_4to1_supported = false,
0101 .dcc_supported = true,
0102 .max_num_dp2p0_outputs = 2,
0103 .max_num_dp2p0_streams = 4,
0104 };
0105
0106 struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc = {
0107 .clock_limits = {
0108 {
0109 .state = 0,
0110 .dcfclk_mhz = 1564.0,
0111 .fabricclk_mhz = 400.0,
0112 .dispclk_mhz = 2150.0,
0113 .dppclk_mhz = 2150.0,
0114 .phyclk_mhz = 810.0,
0115 .phyclk_d18_mhz = 667.0,
0116 .phyclk_d32_mhz = 625.0,
0117 .socclk_mhz = 1200.0,
0118 .dscclk_mhz = 716.667,
0119 .dram_speed_mts = 16000.0,
0120 .dtbclk_mhz = 1564.0,
0121 },
0122 },
0123 .num_states = 1,
0124 .sr_exit_time_us = 42.97,
0125 .sr_enter_plus_exit_time_us = 49.94,
0126 .sr_exit_z8_time_us = 285.0,
0127 .sr_enter_plus_exit_z8_time_us = 320,
0128 .writeback_latency_us = 12.0,
0129 .round_trip_ping_latency_dcfclk_cycles = 263,
0130 .urgent_latency_pixel_data_only_us = 4.0,
0131 .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
0132 .urgent_latency_vm_data_only_us = 4.0,
0133 .fclk_change_latency_us = 20,
0134 .usr_retraining_latency_us = 2,
0135 .smn_latency_us = 2,
0136 .mall_allocated_for_dcn_mbytes = 64,
0137 .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
0138 .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
0139 .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
0140 .pct_ideal_sdp_bw_after_urgent = 100.0,
0141 .pct_ideal_fabric_bw_after_urgent = 67.0,
0142 .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 20.0,
0143 .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0,
0144 .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0,
0145 .pct_ideal_dram_bw_after_urgent_strobe = 67.0,
0146 .max_avg_sdp_bw_use_normal_percent = 80.0,
0147 .max_avg_fabric_bw_use_normal_percent = 60.0,
0148 .max_avg_dram_bw_use_normal_strobe_percent = 50.0,
0149 .max_avg_dram_bw_use_normal_percent = 15.0,
0150 .num_chans = 8,
0151 .dram_channel_width_bytes = 2,
0152 .fabric_datapath_to_dcn_data_return_bytes = 64,
0153 .return_bus_width_bytes = 64,
0154 .downspread_percent = 0.38,
0155 .dcn_downspread_percent = 0.5,
0156 .dram_clock_change_latency_us = 400,
0157 .dispclk_dppclk_vco_speed_mhz = 4300.0,
0158 .do_urgent_latency_adjustment = true,
0159 .urgent_latency_adjustment_fabric_clock_component_us = 1.0,
0160 .urgent_latency_adjustment_fabric_clock_reference_mhz = 1000,
0161 };
0162
0163 void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr)
0164 {
0165
0166 double pstate_latency_us = clk_mgr->base.ctx->dc->dml.soc.dram_clock_change_latency_us;
0167 double fclk_change_latency_us = clk_mgr->base.ctx->dc->dml.soc.fclk_change_latency_us;
0168 double sr_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_exit_time_us;
0169 double sr_enter_plus_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_enter_plus_exit_time_us;
0170
0171 uint16_t min_uclk_mhz = clk_mgr->base.bw_params->clk_table.entries[0].memclk_mhz;
0172 uint16_t min_dcfclk_mhz = clk_mgr->base.bw_params->clk_table.entries[0].dcfclk_mhz;
0173 uint16_t setb_min_uclk_mhz = min_uclk_mhz;
0174 uint16_t dcfclk_mhz_for_the_second_state = clk_mgr->base.ctx->dc->dml.soc.clock_limits[2].dcfclk_mhz;
0175
0176 dc_assert_fp_enabled();
0177
0178
0179 if (dcfclk_mhz_for_the_second_state)
0180 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = dcfclk_mhz_for_the_second_state;
0181 else
0182 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = clk_mgr->base.bw_params->clk_table.entries[0].dcfclk_mhz;
0183
0184 if (clk_mgr->base.bw_params->clk_table.entries[2].memclk_mhz)
0185 setb_min_uclk_mhz = clk_mgr->base.bw_params->clk_table.entries[2].memclk_mhz;
0186
0187
0188 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].valid = true;
0189 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;
0190 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us = fclk_change_latency_us;
0191 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;
0192 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
0193 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
0194 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;
0195 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;
0196 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;
0197 clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;
0198
0199
0200 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].valid = true;
0201 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us;
0202 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.fclk_change_latency_us = fclk_change_latency_us;
0203 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us;
0204 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
0205 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
0206 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF;
0207 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = setb_min_uclk_mhz;
0208 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF;
0209
0210
0211
0212 if (clk_mgr->base.ctx->dc->bb_overrides.dummy_clock_change_latency_ns != 0x7FFFFFFF) {
0213 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].valid = true;
0214 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = 38;
0215 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.fclk_change_latency_us = fclk_change_latency_us;
0216 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;
0217 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
0218 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;
0219 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;
0220 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;
0221 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
0222 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
0223 clk_mgr->base.bw_params->dummy_pstate_table[0].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[0].memclk_mhz * 16;
0224 clk_mgr->base.bw_params->dummy_pstate_table[0].dummy_pstate_latency_us = 38;
0225 clk_mgr->base.bw_params->dummy_pstate_table[1].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[1].memclk_mhz * 16;
0226 clk_mgr->base.bw_params->dummy_pstate_table[1].dummy_pstate_latency_us = 9;
0227 clk_mgr->base.bw_params->dummy_pstate_table[2].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[2].memclk_mhz * 16;
0228 clk_mgr->base.bw_params->dummy_pstate_table[2].dummy_pstate_latency_us = 8;
0229 clk_mgr->base.bw_params->dummy_pstate_table[3].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[3].memclk_mhz * 16;
0230 clk_mgr->base.bw_params->dummy_pstate_table[3].dummy_pstate_latency_us = 5;
0231 }
0232
0233
0234 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].valid = true;
0235 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = clk_mgr->base.bw_params->dummy_pstate_table[3].dummy_pstate_latency_us;
0236 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.fclk_change_latency_us = fclk_change_latency_us;
0237 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = sr_exit_time_us / 2;
0238 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us / 2;
0239 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
0240 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;
0241 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
0242 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
0243 clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
0244 }
0245
0246
0247
0248
0249
0250
0251
0252 int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
0253 struct dc_state *context,
0254 display_e2e_pipe_params_st *pipes,
0255 int pipe_cnt,
0256 int vlevel)
0257 {
0258 const int max_latency_table_entries = 4;
0259 const struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
0260 int dummy_latency_index = 0;
0261
0262 dc_assert_fp_enabled();
0263
0264 while (dummy_latency_index < max_latency_table_entries) {
0265 context->bw_ctx.dml.soc.dram_clock_change_latency_us =
0266 dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
0267 dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
0268
0269 if (vlevel < context->bw_ctx.dml.vba.soc.num_states &&
0270 vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported)
0271 break;
0272
0273 dummy_latency_index++;
0274 }
0275
0276 if (dummy_latency_index == max_latency_table_entries) {
0277 ASSERT(dummy_latency_index != max_latency_table_entries);
0278
0279
0280
0281
0282
0283
0284 dummy_latency_index = max_latency_table_entries - 1;
0285 }
0286
0287 return dummy_latency_index;
0288 }
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
0304 struct dc_state *context,
0305 display_e2e_pipe_params_st *pipes,
0306 int pipe_cnt)
0307 {
0308 uint32_t i, pipe_idx;
0309
0310 dc_assert_fp_enabled();
0311
0312 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
0313 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0314
0315 if (!pipe->stream)
0316 continue;
0317
0318 if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
0319 pipes[pipe_idx].pipe.dest.vstartup_start =
0320 get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
0321 pipes[pipe_idx].pipe.dest.vupdate_offset =
0322 get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
0323 pipes[pipe_idx].pipe.dest.vupdate_width =
0324 get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
0325 pipes[pipe_idx].pipe.dest.vready_offset =
0326 get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
0327 pipe->pipe_dlg_param = pipes[pipe_idx].pipe.dest;
0328 }
0329 pipe_idx++;
0330 }
0331 }
0332
0333 bool dcn32_predict_pipe_split(struct dc_state *context, display_pipe_params_st pipe, int index)
0334 {
0335 double pscl_throughput;
0336 double pscl_throughput_chroma;
0337 double dpp_clk_single_dpp, clock;
0338 double clk_frequency = 0.0;
0339 double vco_speed = context->bw_ctx.dml.soc.dispclk_dppclk_vco_speed_mhz;
0340
0341 dc_assert_fp_enabled();
0342
0343 dml32_CalculateSinglePipeDPPCLKAndSCLThroughput(pipe.scale_ratio_depth.hscl_ratio,
0344 pipe.scale_ratio_depth.hscl_ratio_c,
0345 pipe.scale_ratio_depth.vscl_ratio,
0346 pipe.scale_ratio_depth.vscl_ratio_c,
0347 context->bw_ctx.dml.ip.max_dchub_pscl_bw_pix_per_clk,
0348 context->bw_ctx.dml.ip.max_pscl_lb_bw_pix_per_clk,
0349 pipe.dest.pixel_rate_mhz,
0350 pipe.src.source_format,
0351 pipe.scale_taps.htaps,
0352 pipe.scale_taps.htaps_c,
0353 pipe.scale_taps.vtaps,
0354 pipe.scale_taps.vtaps_c,
0355
0356 &pscl_throughput, &pscl_throughput_chroma,
0357 &dpp_clk_single_dpp);
0358
0359 clock = dpp_clk_single_dpp * (1 + context->bw_ctx.dml.soc.dcn_downspread_percent / 100);
0360
0361 if (clock > 0)
0362 clk_frequency = vco_speed * 4.0 / ((int)(vco_speed * 4.0));
0363
0364 if (clk_frequency > context->bw_ctx.dml.soc.clock_limits[index].dppclk_mhz)
0365 return true;
0366 else
0367 return false;
0368 }
0369
0370 static float calculate_net_bw_in_kbytes_sec(struct _vcs_dpi_voltage_scaling_st *entry)
0371 {
0372 float memory_bw_kbytes_sec;
0373 float fabric_bw_kbytes_sec;
0374 float sdp_bw_kbytes_sec;
0375 float limiting_bw_kbytes_sec;
0376
0377 memory_bw_kbytes_sec = entry->dram_speed_mts *
0378 dcn3_2_soc.num_chans *
0379 dcn3_2_soc.dram_channel_width_bytes *
0380 ((float)dcn3_2_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only / 100);
0381
0382 fabric_bw_kbytes_sec = entry->fabricclk_mhz *
0383 dcn3_2_soc.return_bus_width_bytes *
0384 ((float)dcn3_2_soc.pct_ideal_fabric_bw_after_urgent / 100);
0385
0386 sdp_bw_kbytes_sec = entry->dcfclk_mhz *
0387 dcn3_2_soc.return_bus_width_bytes *
0388 ((float)dcn3_2_soc.pct_ideal_sdp_bw_after_urgent / 100);
0389
0390 limiting_bw_kbytes_sec = memory_bw_kbytes_sec;
0391
0392 if (fabric_bw_kbytes_sec < limiting_bw_kbytes_sec)
0393 limiting_bw_kbytes_sec = fabric_bw_kbytes_sec;
0394
0395 if (sdp_bw_kbytes_sec < limiting_bw_kbytes_sec)
0396 limiting_bw_kbytes_sec = sdp_bw_kbytes_sec;
0397
0398 return limiting_bw_kbytes_sec;
0399 }
0400
0401 static void get_optimal_ntuple(struct _vcs_dpi_voltage_scaling_st *entry)
0402 {
0403 if (entry->dcfclk_mhz > 0) {
0404 float bw_on_sdp = entry->dcfclk_mhz * dcn3_2_soc.return_bus_width_bytes * ((float)dcn3_2_soc.pct_ideal_sdp_bw_after_urgent / 100);
0405
0406 entry->fabricclk_mhz = bw_on_sdp / (dcn3_2_soc.return_bus_width_bytes * ((float)dcn3_2_soc.pct_ideal_fabric_bw_after_urgent / 100));
0407 entry->dram_speed_mts = bw_on_sdp / (dcn3_2_soc.num_chans *
0408 dcn3_2_soc.dram_channel_width_bytes * ((float)dcn3_2_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only / 100));
0409 } else if (entry->fabricclk_mhz > 0) {
0410 float bw_on_fabric = entry->fabricclk_mhz * dcn3_2_soc.return_bus_width_bytes * ((float)dcn3_2_soc.pct_ideal_fabric_bw_after_urgent / 100);
0411
0412 entry->dcfclk_mhz = bw_on_fabric / (dcn3_2_soc.return_bus_width_bytes * ((float)dcn3_2_soc.pct_ideal_sdp_bw_after_urgent / 100));
0413 entry->dram_speed_mts = bw_on_fabric / (dcn3_2_soc.num_chans *
0414 dcn3_2_soc.dram_channel_width_bytes * ((float)dcn3_2_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only / 100));
0415 } else if (entry->dram_speed_mts > 0) {
0416 float bw_on_dram = entry->dram_speed_mts * dcn3_2_soc.num_chans *
0417 dcn3_2_soc.dram_channel_width_bytes * ((float)dcn3_2_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only / 100);
0418
0419 entry->fabricclk_mhz = bw_on_dram / (dcn3_2_soc.return_bus_width_bytes * ((float)dcn3_2_soc.pct_ideal_fabric_bw_after_urgent / 100));
0420 entry->dcfclk_mhz = bw_on_dram / (dcn3_2_soc.return_bus_width_bytes * ((float)dcn3_2_soc.pct_ideal_sdp_bw_after_urgent / 100));
0421 }
0422 }
0423
0424 void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
0425 unsigned int *num_entries,
0426 struct _vcs_dpi_voltage_scaling_st *entry)
0427 {
0428 int i = 0;
0429 int index = 0;
0430 float net_bw_of_new_state = 0;
0431
0432 dc_assert_fp_enabled();
0433
0434 get_optimal_ntuple(entry);
0435
0436 if (*num_entries == 0) {
0437 table[0] = *entry;
0438 (*num_entries)++;
0439 } else {
0440 net_bw_of_new_state = calculate_net_bw_in_kbytes_sec(entry);
0441 while (net_bw_of_new_state > calculate_net_bw_in_kbytes_sec(&table[index])) {
0442 index++;
0443 if (index >= *num_entries)
0444 break;
0445 }
0446
0447 for (i = *num_entries; i > index; i--)
0448 table[i] = table[i - 1];
0449
0450 table[index] = *entry;
0451 (*num_entries)++;
0452 }
0453 }
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477 void dcn32_set_phantom_stream_timing(struct dc *dc,
0478 struct dc_state *context,
0479 struct pipe_ctx *ref_pipe,
0480 struct dc_stream_state *phantom_stream,
0481 display_e2e_pipe_params_st *pipes,
0482 unsigned int pipe_cnt,
0483 unsigned int dc_pipe_idx)
0484 {
0485 unsigned int i, pipe_idx;
0486 struct pipe_ctx *pipe;
0487 uint32_t phantom_vactive, phantom_bp, pstate_width_fw_delay_lines;
0488 unsigned int vlevel = context->bw_ctx.dml.vba.VoltageLevel;
0489 unsigned int dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
0490 unsigned int socclk = context->bw_ctx.dml.vba.SOCCLKPerState[vlevel];
0491
0492 dc_assert_fp_enabled();
0493
0494
0495 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
0496 pipe = &context->res_ctx.pipe_ctx[i];
0497
0498 if (!pipe->stream)
0499 continue;
0500
0501 if (i == dc_pipe_idx)
0502 break;
0503
0504 pipe_idx++;
0505 }
0506
0507
0508 pstate_width_fw_delay_lines = ((double)(dc->caps.subvp_fw_processing_delay_us +
0509 dc->caps.subvp_pstate_allow_width_us) / 1000000) *
0510 (ref_pipe->stream->timing.pix_clk_100hz * 100) /
0511 (double)ref_pipe->stream->timing.h_total;
0512
0513
0514 pipes[0].clks_cfg.voltage = vlevel;
0515 pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
0516 pipes[0].clks_cfg.socclk_mhz = socclk;
0517
0518
0519
0520
0521
0522
0523 phantom_vactive = get_subviewport_lines_needed_in_mall(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx) +
0524 pstate_width_fw_delay_lines + dc->caps.subvp_swath_height_margin_lines;
0525
0526
0527 phantom_bp = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
0528
0529 phantom_stream->dst.y = 0;
0530 phantom_stream->dst.height = phantom_vactive;
0531 phantom_stream->src.y = 0;
0532 phantom_stream->src.height = phantom_vactive;
0533
0534 phantom_stream->timing.v_addressable = phantom_vactive;
0535 phantom_stream->timing.v_front_porch = 1;
0536 phantom_stream->timing.v_total = phantom_stream->timing.v_addressable +
0537 phantom_stream->timing.v_front_porch +
0538 phantom_stream->timing.v_sync_width +
0539 phantom_bp;
0540 phantom_stream->timing.flags.DSC = 0;
0541 }
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555 static unsigned int dcn32_get_num_free_pipes(struct dc *dc, struct dc_state *context)
0556 {
0557 unsigned int i;
0558 unsigned int free_pipes = 0;
0559 unsigned int num_pipes = 0;
0560
0561 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0562 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0563
0564 if (pipe->stream && !pipe->top_pipe) {
0565 while (pipe) {
0566 num_pipes++;
0567 pipe = pipe->bottom_pipe;
0568 }
0569 }
0570 }
0571
0572 free_pipes = dc->res_pool->pipe_count - num_pipes;
0573 return free_pipes;
0574 }
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598 static bool dcn32_assign_subvp_pipe(struct dc *dc,
0599 struct dc_state *context,
0600 unsigned int *index)
0601 {
0602 unsigned int i, pipe_idx;
0603 unsigned int max_frame_time = 0;
0604 bool valid_assignment_found = false;
0605 unsigned int free_pipes = dcn32_get_num_free_pipes(dc, context);
0606 bool current_assignment_freesync = false;
0607
0608 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
0609 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0610 unsigned int num_pipes = 0;
0611 unsigned int refresh_rate = 0;
0612
0613 if (!pipe->stream)
0614 continue;
0615
0616
0617 refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 +
0618 pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1)
0619 / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total);
0620 if (pipe->plane_state && !pipe->top_pipe &&
0621 pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120) {
0622 while (pipe) {
0623 num_pipes++;
0624 pipe = pipe->bottom_pipe;
0625 }
0626
0627 pipe = &context->res_ctx.pipe_ctx[i];
0628 if (num_pipes <= free_pipes) {
0629 struct dc_stream_state *stream = pipe->stream;
0630 unsigned int frame_us = (stream->timing.v_total * stream->timing.h_total /
0631 (double)(stream->timing.pix_clk_100hz * 100)) * 1000000;
0632 if (frame_us > max_frame_time && !stream->ignore_msa_timing_param) {
0633 *index = i;
0634 max_frame_time = frame_us;
0635 valid_assignment_found = true;
0636 current_assignment_freesync = false;
0637
0638
0639
0640 } else if (stream->ignore_msa_timing_param && (!valid_assignment_found ||
0641 (current_assignment_freesync && frame_us > max_frame_time))) {
0642 *index = i;
0643 valid_assignment_found = true;
0644 current_assignment_freesync = true;
0645 }
0646 }
0647 }
0648 pipe_idx++;
0649 }
0650 return valid_assignment_found;
0651 }
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673 static bool dcn32_enough_pipes_for_subvp(struct dc *dc, struct dc_state *context)
0674 {
0675 unsigned int i, split_cnt, free_pipes;
0676 unsigned int min_pipe_split = dc->res_pool->pipe_count + 1;
0677 bool subvp_possible = false;
0678
0679 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0680 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0681
0682
0683 if (pipe->stream && !pipe->top_pipe &&
0684 pipe->stream->mall_stream_config.type == SUBVP_NONE) {
0685 split_cnt = 0;
0686 while (pipe) {
0687 split_cnt++;
0688 pipe = pipe->bottom_pipe;
0689 }
0690
0691 if (split_cnt < min_pipe_split)
0692 min_pipe_split = split_cnt;
0693 }
0694 }
0695
0696 free_pipes = dcn32_get_num_free_pipes(dc, context);
0697
0698
0699
0700 if (free_pipes >= min_pipe_split && free_pipes < dc->res_pool->pipe_count)
0701 subvp_possible = true;
0702
0703 return subvp_possible;
0704 }
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721 static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
0722 {
0723 struct pipe_ctx *subvp_pipes[2];
0724 struct dc_stream_state *phantom = NULL;
0725 uint32_t microschedule_lines = 0;
0726 uint32_t index = 0;
0727 uint32_t i;
0728 uint32_t max_microschedule_us = 0;
0729 int32_t vactive1_us, vactive2_us, vblank1_us, vblank2_us;
0730
0731 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0732 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0733 uint32_t time_us = 0;
0734
0735
0736
0737
0738 if (pipe->stream && pipe->plane_state && !pipe->top_pipe &&
0739 pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
0740 phantom = pipe->stream->mall_stream_config.paired_stream;
0741 microschedule_lines = (phantom->timing.v_total - phantom->timing.v_front_porch) +
0742 phantom->timing.v_addressable;
0743
0744
0745 time_us = (microschedule_lines * phantom->timing.h_total) /
0746 (double)(phantom->timing.pix_clk_100hz * 100) * 1000000 +
0747 dc->caps.subvp_prefetch_end_to_mall_start_us +
0748 dc->caps.subvp_fw_processing_delay_us + 1;
0749 if (time_us > max_microschedule_us)
0750 max_microschedule_us = time_us;
0751
0752 subvp_pipes[index] = pipe;
0753 index++;
0754
0755
0756 if (index == 2)
0757 break;
0758 }
0759 }
0760 vactive1_us = ((subvp_pipes[0]->stream->timing.v_addressable * subvp_pipes[0]->stream->timing.h_total) /
0761 (double)(subvp_pipes[0]->stream->timing.pix_clk_100hz * 100)) * 1000000;
0762 vactive2_us = ((subvp_pipes[1]->stream->timing.v_addressable * subvp_pipes[1]->stream->timing.h_total) /
0763 (double)(subvp_pipes[1]->stream->timing.pix_clk_100hz * 100)) * 1000000;
0764 vblank1_us = (((subvp_pipes[0]->stream->timing.v_total - subvp_pipes[0]->stream->timing.v_addressable) *
0765 subvp_pipes[0]->stream->timing.h_total) /
0766 (double)(subvp_pipes[0]->stream->timing.pix_clk_100hz * 100)) * 1000000;
0767 vblank2_us = (((subvp_pipes[1]->stream->timing.v_total - subvp_pipes[1]->stream->timing.v_addressable) *
0768 subvp_pipes[1]->stream->timing.h_total) /
0769 (double)(subvp_pipes[1]->stream->timing.pix_clk_100hz * 100)) * 1000000;
0770
0771 if ((vactive1_us - vblank2_us) / 2 > max_microschedule_us &&
0772 (vactive2_us - vblank1_us) / 2 > max_microschedule_us)
0773 return true;
0774
0775 return false;
0776 }
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795 static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struct pipe_ctx *drr_pipe)
0796 {
0797 bool schedulable = false;
0798 uint32_t i;
0799 struct pipe_ctx *pipe = NULL;
0800 struct dc_crtc_timing *main_timing = NULL;
0801 struct dc_crtc_timing *phantom_timing = NULL;
0802 struct dc_crtc_timing *drr_timing = NULL;
0803 int16_t prefetch_us = 0;
0804 int16_t mall_region_us = 0;
0805 int16_t drr_frame_us = 0;
0806 int16_t subvp_active_us = 0;
0807 int16_t stretched_drr_us = 0;
0808 int16_t drr_stretched_vblank_us = 0;
0809 int16_t max_vblank_mallregion = 0;
0810
0811
0812 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0813 pipe = &context->res_ctx.pipe_ctx[i];
0814
0815
0816
0817 if (!pipe->stream || !pipe->plane_state || pipe->top_pipe || pipe->prev_odm_pipe)
0818 continue;
0819
0820
0821 if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
0822 break;
0823 }
0824
0825 main_timing = &pipe->stream->timing;
0826 phantom_timing = &pipe->stream->mall_stream_config.paired_stream->timing;
0827 drr_timing = &drr_pipe->stream->timing;
0828 prefetch_us = (phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total /
0829 (double)(phantom_timing->pix_clk_100hz * 100) * 1000000 +
0830 dc->caps.subvp_prefetch_end_to_mall_start_us;
0831 subvp_active_us = main_timing->v_addressable * main_timing->h_total /
0832 (double)(main_timing->pix_clk_100hz * 100) * 1000000;
0833 drr_frame_us = drr_timing->v_total * drr_timing->h_total /
0834 (double)(drr_timing->pix_clk_100hz * 100) * 1000000;
0835
0836 mall_region_us = phantom_timing->v_addressable * phantom_timing->h_total /
0837 (double)(phantom_timing->pix_clk_100hz * 100) * 1000000;
0838 stretched_drr_us = drr_frame_us + mall_region_us + SUBVP_DRR_MARGIN_US;
0839 drr_stretched_vblank_us = (drr_timing->v_total - drr_timing->v_addressable) * drr_timing->h_total /
0840 (double)(drr_timing->pix_clk_100hz * 100) * 1000000 + (stretched_drr_us - drr_frame_us);
0841 max_vblank_mallregion = drr_stretched_vblank_us > mall_region_us ? drr_stretched_vblank_us : mall_region_us;
0842
0843
0844
0845
0846
0847
0848 if (stretched_drr_us < (1 / (double)drr_timing->min_refresh_in_uhz) * 1000000 * 1000000 &&
0849 subvp_active_us - prefetch_us - stretched_drr_us - max_vblank_mallregion > 0)
0850 schedulable = true;
0851
0852 return schedulable;
0853 }
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871 static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
0872 {
0873 struct pipe_ctx *pipe = NULL;
0874 struct pipe_ctx *subvp_pipe = NULL;
0875 bool found = false;
0876 bool schedulable = false;
0877 uint32_t i = 0;
0878 uint8_t vblank_index = 0;
0879 uint16_t prefetch_us = 0;
0880 uint16_t mall_region_us = 0;
0881 uint16_t vblank_frame_us = 0;
0882 uint16_t subvp_active_us = 0;
0883 uint16_t vblank_blank_us = 0;
0884 uint16_t max_vblank_mallregion = 0;
0885 struct dc_crtc_timing *main_timing = NULL;
0886 struct dc_crtc_timing *phantom_timing = NULL;
0887 struct dc_crtc_timing *vblank_timing = NULL;
0888
0889
0890
0891
0892
0893
0894
0895 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0896 pipe = &context->res_ctx.pipe_ctx[i];
0897
0898
0899
0900 if (!pipe->stream || !pipe->plane_state || pipe->top_pipe || pipe->prev_odm_pipe)
0901 continue;
0902
0903 if (!found && pipe->stream->mall_stream_config.type == SUBVP_NONE) {
0904
0905 vblank_index = i;
0906 found = true;
0907 }
0908
0909 if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN)
0910 subvp_pipe = pipe;
0911 }
0912
0913 if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param) {
0914
0915 schedulable = subvp_drr_schedulable(dc, context, &context->res_ctx.pipe_ctx[vblank_index]);
0916 } else if (found) {
0917 main_timing = &subvp_pipe->stream->timing;
0918 phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
0919 vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing;
0920
0921
0922 prefetch_us = (phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total /
0923 (double)(phantom_timing->pix_clk_100hz * 100) * 1000000 +
0924 dc->caps.subvp_prefetch_end_to_mall_start_us;
0925
0926 mall_region_us = phantom_timing->v_addressable * phantom_timing->h_total /
0927 (double)(phantom_timing->pix_clk_100hz * 100) * 1000000;
0928 vblank_frame_us = vblank_timing->v_total * vblank_timing->h_total /
0929 (double)(vblank_timing->pix_clk_100hz * 100) * 1000000;
0930 vblank_blank_us = (vblank_timing->v_total - vblank_timing->v_addressable) * vblank_timing->h_total /
0931 (double)(vblank_timing->pix_clk_100hz * 100) * 1000000;
0932 subvp_active_us = main_timing->v_addressable * main_timing->h_total /
0933 (double)(main_timing->pix_clk_100hz * 100) * 1000000;
0934 max_vblank_mallregion = vblank_blank_us > mall_region_us ? vblank_blank_us : mall_region_us;
0935
0936
0937
0938
0939 if (subvp_active_us - prefetch_us - vblank_frame_us - max_vblank_mallregion > 0)
0940 schedulable = true;
0941 }
0942 return schedulable;
0943 }
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961 static bool subvp_validate_static_schedulability(struct dc *dc,
0962 struct dc_state *context,
0963 int vlevel)
0964 {
0965 bool schedulable = true;
0966 struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
0967 uint32_t i, pipe_idx;
0968 uint8_t subvp_count = 0;
0969 uint8_t vactive_count = 0;
0970
0971 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
0972 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0973
0974 if (!pipe->stream)
0975 continue;
0976
0977 if (pipe->plane_state && !pipe->top_pipe &&
0978 pipe->stream->mall_stream_config.type == SUBVP_MAIN)
0979 subvp_count++;
0980
0981
0982
0983
0984 if (vba->ActiveDRAMClockChangeLatencyMargin[vba->pipe_plane[pipe_idx]] > 0 &&
0985 pipe->stream->mall_stream_config.type == SUBVP_NONE) {
0986 vactive_count++;
0987 }
0988 pipe_idx++;
0989 }
0990
0991 if (subvp_count == 2) {
0992
0993 schedulable = subvp_subvp_schedulable(dc, context);
0994 } else if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vblank_w_mall_sub_vp) {
0995
0996
0997 if (vactive_count > 0)
0998 schedulable = false;
0999 else
1000 schedulable = subvp_vblank_schedulable(dc, context);
1001 } else if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vactive_w_mall_sub_vp &&
1002 vactive_count > 0) {
1003
1004
1005
1006 schedulable = false;
1007 }
1008 return schedulable;
1009 }
1010
1011 static void dcn32_full_validate_bw_helper(struct dc *dc,
1012 struct dc_state *context,
1013 display_e2e_pipe_params_st *pipes,
1014 int *vlevel,
1015 int *split,
1016 bool *merge,
1017 int *pipe_cnt)
1018 {
1019 struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
1020 unsigned int dc_pipe_idx = 0;
1021 bool found_supported_config = false;
1022 struct pipe_ctx *pipe = NULL;
1023 uint32_t non_subvp_pipes = 0;
1024 bool drr_pipe_found = false;
1025 uint32_t drr_pipe_index = 0;
1026 uint32_t i = 0;
1027
1028 dc_assert_fp_enabled();
1029
1030
1031
1032
1033
1034
1035
1036 if (dc->debug.dml_disallow_alternate_prefetch_modes)
1037 context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
1038 dm_prefetch_support_uclk_fclk_and_stutter;
1039 else
1040 context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
1041 dm_prefetch_support_uclk_fclk_and_stutter_if_possible;
1042
1043 *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt);
1044
1045 if (*vlevel < context->bw_ctx.dml.soc.num_states)
1046 *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge);
1047
1048
1049
1050
1051
1052
1053
1054
1055 if (!dc->debug.force_disable_subvp && dcn32_all_pipes_have_stream_and_plane(dc, context) &&
1056 !dcn32_mpo_in_use(context) && (*vlevel == context->bw_ctx.dml.soc.num_states ||
1057 vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported ||
1058 dc->debug.force_subvp_mclk_switch)) {
1059
1060 dcn32_merge_pipes_for_subvp(dc, context);
1061
1062 for (int i = 0; i < dc->res_pool->pipe_count; i++) {
1063 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1064
1065 if (!pipe_ctx->plane_state || !pipe_ctx->stream)
1066 continue;
1067
1068 resource_build_scaling_params(pipe_ctx);
1069 }
1070
1071 while (!found_supported_config && dcn32_enough_pipes_for_subvp(dc, context) &&
1072 dcn32_assign_subvp_pipe(dc, context, &dc_pipe_idx)) {
1073
1074
1075
1076
1077
1078
1079
1080 if (*vlevel == context->bw_ctx.dml.soc.num_states &&
1081 context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final ==
1082 dm_prefetch_support_uclk_fclk_and_stutter) {
1083 context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
1084 dm_prefetch_support_stutter;
1085
1086
1087
1088
1089
1090 *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt);
1091 }
1092
1093 dc->res_pool->funcs->add_phantom_pipes(dc, context, pipes, *pipe_cnt, dc_pipe_idx);
1094
1095 *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false);
1096
1097
1098 pipes[0].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, *pipe_cnt, 0);
1099 *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt);
1100
1101 if (*vlevel < context->bw_ctx.dml.soc.num_states &&
1102 vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported
1103 && subvp_validate_static_schedulability(dc, context, *vlevel)) {
1104 found_supported_config = true;
1105 } else if (*vlevel < context->bw_ctx.dml.soc.num_states &&
1106 vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported) {
1107
1108
1109
1110
1111 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1112 pipe = &context->res_ctx.pipe_ctx[i];
1113 if (pipe->stream && pipe->plane_state && !pipe->top_pipe &&
1114 pipe->stream->mall_stream_config.type == SUBVP_NONE) {
1115 non_subvp_pipes++;
1116
1117 if (pipe->stream->ignore_msa_timing_param) {
1118 drr_pipe_found = true;
1119 drr_pipe_index = i;
1120 }
1121 }
1122 }
1123
1124
1125 if (non_subvp_pipes == 1 && drr_pipe_found) {
1126 found_supported_config = subvp_drr_schedulable(dc, context,
1127 &context->res_ctx.pipe_ctx[drr_pipe_index]);
1128 }
1129 }
1130 }
1131
1132
1133
1134 if (!found_supported_config) {
1135 dc->res_pool->funcs->remove_phantom_pipes(dc, context);
1136 vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] = dm_dram_clock_change_unsupported;
1137 *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false);
1138 } else {
1139
1140 memset(split, 0, MAX_PIPES * sizeof(int));
1141 memset(merge, 0, MAX_PIPES * sizeof(bool));
1142 *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge);
1143
1144
1145 DC_FP_START();
1146 dcn32_helper_populate_phantom_dlg_params(dc, context, pipes, *pipe_cnt);
1147 DC_FP_END();
1148
1149
1150
1151 }
1152 }
1153 }
1154
1155 static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
1156 {
1157 int i;
1158
1159 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1160 if (!context->res_ctx.pipe_ctx[i].stream)
1161 continue;
1162 if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i]))
1163 return true;
1164 }
1165 return false;
1166 }
1167
1168 static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
1169 display_e2e_pipe_params_st *pipes,
1170 int pipe_cnt, int vlevel)
1171 {
1172 int i, pipe_idx;
1173 bool usr_retraining_support = false;
1174 bool unbounded_req_enabled = false;
1175
1176 dc_assert_fp_enabled();
1177
1178
1179 dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt);
1180
1181 context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000;
1182 context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000;
1183 context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000;
1184 context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16;
1185 context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000;
1186 context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000;
1187 context->bw_ctx.bw.dcn.clk.p_state_change_support =
1188 context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb]
1189 != dm_dram_clock_change_unsupported;
1190 context->bw_ctx.bw.dcn.clk.num_ways = dcn32_helper_calculate_num_ways_for_subvp(dc, context);
1191
1192 context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
1193 context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context);
1194 context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = context->bw_ctx.dml.vba.DTBCLKPerState[vlevel] * 1000;
1195 if (context->bw_ctx.dml.vba.FCLKChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_fclock_change_unsupported)
1196 context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false;
1197 else
1198 context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true;
1199
1200 usr_retraining_support = context->bw_ctx.dml.vba.USRRetrainingSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
1201 ASSERT(usr_retraining_support);
1202
1203 if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz)
1204 context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz;
1205
1206 unbounded_req_enabled = get_unbounded_request_enabled(&context->bw_ctx.dml, pipes, pipe_cnt);
1207
1208 if (unbounded_req_enabled && pipe_cnt > 1) {
1209
1210 ASSERT(false);
1211 unbounded_req_enabled = false;
1212 }
1213
1214 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1215 if (!context->res_ctx.pipe_ctx[i].stream)
1216 continue;
1217 pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt,
1218 pipe_idx);
1219 pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt,
1220 pipe_idx);
1221 pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt,
1222 pipe_idx);
1223 pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt,
1224 pipe_idx);
1225
1226 if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) {
1227
1228 context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0;
1229 context->res_ctx.pipe_ctx[i].unbounded_req = false;
1230 } else {
1231 context->res_ctx.pipe_ctx[i].det_buffer_size_kb = get_det_buffer_size_kbytes(&context->bw_ctx.dml, pipes, pipe_cnt,
1232 pipe_idx);
1233 context->res_ctx.pipe_ctx[i].unbounded_req = unbounded_req_enabled;
1234 }
1235
1236 if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
1237 context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
1238 context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
1239 context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
1240 pipe_idx++;
1241 }
1242
1243 context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
1244 context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
1245 context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz
1246 * 1000;
1247 context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz
1248 * 1000;
1249
1250 context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes;
1251
1252 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1253 if (context->res_ctx.pipe_ctx[i].stream)
1254 context->bw_ctx.bw.dcn.compbuf_size_kb -= context->res_ctx.pipe_ctx[i].det_buffer_size_kb;
1255 }
1256
1257 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1258
1259 if (!context->res_ctx.pipe_ctx[i].stream)
1260 continue;
1261
1262 context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg_v2(&context->bw_ctx.dml,
1263 &context->res_ctx.pipe_ctx[i].dlg_regs, &context->res_ctx.pipe_ctx[i].ttu_regs, pipes,
1264 pipe_cnt, pipe_idx);
1265
1266 context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg_v2(&context->res_ctx.pipe_ctx[i].rq_regs,
1267 &context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
1268 pipe_idx++;
1269 }
1270 }
1271
1272 static struct pipe_ctx *dcn32_find_split_pipe(
1273 struct dc *dc,
1274 struct dc_state *context,
1275 int old_index)
1276 {
1277 struct pipe_ctx *pipe = NULL;
1278 int i;
1279
1280 if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) {
1281 pipe = &context->res_ctx.pipe_ctx[old_index];
1282 pipe->pipe_idx = old_index;
1283 }
1284
1285 if (!pipe)
1286 for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
1287 if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL
1288 && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) {
1289 if (context->res_ctx.pipe_ctx[i].stream == NULL) {
1290 pipe = &context->res_ctx.pipe_ctx[i];
1291 pipe->pipe_idx = i;
1292 break;
1293 }
1294 }
1295 }
1296
1297
1298
1299
1300
1301
1302 if (!pipe)
1303 for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
1304 if (context->res_ctx.pipe_ctx[i].stream == NULL) {
1305 pipe = &context->res_ctx.pipe_ctx[i];
1306 pipe->pipe_idx = i;
1307 break;
1308 }
1309 }
1310
1311 return pipe;
1312 }
1313
1314 static bool dcn32_split_stream_for_mpc_or_odm(
1315 const struct dc *dc,
1316 struct resource_context *res_ctx,
1317 struct pipe_ctx *pri_pipe,
1318 struct pipe_ctx *sec_pipe,
1319 bool odm)
1320 {
1321 int pipe_idx = sec_pipe->pipe_idx;
1322 const struct resource_pool *pool = dc->res_pool;
1323
1324 DC_LOGGER_INIT(dc->ctx->logger);
1325
1326 if (odm && pri_pipe->plane_state) {
1327
1328 if (pri_pipe->plane_state->clip_rect.x + pri_pipe->plane_state->clip_rect.width <=
1329 pri_pipe->stream->src.x + pri_pipe->stream->src.width/2) {
1330
1331 DC_LOG_SCALER("%s - ODM + window MPO(left). pri_pipe:%d\n",
1332 __func__,
1333 pri_pipe->pipe_idx);
1334 return true;
1335 }
1336
1337
1338 if (pri_pipe->plane_state->clip_rect.x >= pri_pipe->stream->src.x + pri_pipe->stream->src.width/2) {
1339
1340 DC_LOG_SCALER("%s - ODM + window MPO(right). pri_pipe:%d\n",
1341 __func__,
1342 pri_pipe->pipe_idx);
1343 return true;
1344 }
1345 }
1346
1347 *sec_pipe = *pri_pipe;
1348
1349 sec_pipe->pipe_idx = pipe_idx;
1350 sec_pipe->plane_res.mi = pool->mis[pipe_idx];
1351 sec_pipe->plane_res.hubp = pool->hubps[pipe_idx];
1352 sec_pipe->plane_res.ipp = pool->ipps[pipe_idx];
1353 sec_pipe->plane_res.xfm = pool->transforms[pipe_idx];
1354 sec_pipe->plane_res.dpp = pool->dpps[pipe_idx];
1355 sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst;
1356 sec_pipe->stream_res.dsc = NULL;
1357 if (odm) {
1358 if (pri_pipe->next_odm_pipe) {
1359 ASSERT(pri_pipe->next_odm_pipe != sec_pipe);
1360 sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe;
1361 sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe;
1362 }
1363 if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) {
1364 pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe;
1365 sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe;
1366 }
1367 if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) {
1368 pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe;
1369 sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe;
1370 }
1371 pri_pipe->next_odm_pipe = sec_pipe;
1372 sec_pipe->prev_odm_pipe = pri_pipe;
1373 ASSERT(sec_pipe->top_pipe == NULL);
1374
1375 if (!sec_pipe->top_pipe)
1376 sec_pipe->stream_res.opp = pool->opps[pipe_idx];
1377 else
1378 sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp;
1379 if (sec_pipe->stream->timing.flags.DSC == 1) {
1380 dcn20_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx);
1381 ASSERT(sec_pipe->stream_res.dsc);
1382 if (sec_pipe->stream_res.dsc == NULL)
1383 return false;
1384 }
1385 } else {
1386 if (pri_pipe->bottom_pipe) {
1387 ASSERT(pri_pipe->bottom_pipe != sec_pipe);
1388 sec_pipe->bottom_pipe = pri_pipe->bottom_pipe;
1389 sec_pipe->bottom_pipe->top_pipe = sec_pipe;
1390 }
1391 pri_pipe->bottom_pipe = sec_pipe;
1392 sec_pipe->top_pipe = pri_pipe;
1393
1394 ASSERT(pri_pipe->plane_state);
1395 }
1396
1397 return true;
1398 }
1399
1400 bool dcn32_internal_validate_bw(struct dc *dc,
1401 struct dc_state *context,
1402 display_e2e_pipe_params_st *pipes,
1403 int *pipe_cnt_out,
1404 int *vlevel_out,
1405 bool fast_validate)
1406 {
1407 bool out = false;
1408 bool repopulate_pipes = false;
1409 int split[MAX_PIPES] = { 0 };
1410 bool merge[MAX_PIPES] = { false };
1411 bool newly_split[MAX_PIPES] = { false };
1412 int pipe_cnt, i, pipe_idx;
1413 int vlevel = context->bw_ctx.dml.soc.num_states;
1414 struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
1415
1416 dc_assert_fp_enabled();
1417
1418 ASSERT(pipes);
1419 if (!pipes)
1420 return false;
1421
1422
1423 dc->res_pool->funcs->remove_phantom_pipes(dc, context);
1424
1425 dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
1426
1427 pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
1428
1429 if (!pipe_cnt) {
1430 out = true;
1431 goto validate_out;
1432 }
1433
1434 dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt);
1435
1436 if (!fast_validate) {
1437 DC_FP_START();
1438 dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt);
1439 DC_FP_END();
1440 }
1441
1442 if (fast_validate ||
1443 (dc->debug.dml_disallow_alternate_prefetch_modes &&
1444 (vlevel == context->bw_ctx.dml.soc.num_states ||
1445 vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported))) {
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456 context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
1457 dm_prefetch_support_fclk_and_stutter;
1458
1459 vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
1460
1461
1462 if (vlevel == context->bw_ctx.dml.soc.num_states) {
1463 context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
1464 dm_prefetch_support_stutter;
1465 vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
1466 }
1467
1468 if (vlevel < context->bw_ctx.dml.soc.num_states) {
1469 memset(split, 0, sizeof(split));
1470 memset(merge, 0, sizeof(merge));
1471 vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);
1472 }
1473 }
1474
1475 dml_log_mode_support_params(&context->bw_ctx.dml);
1476
1477 if (vlevel == context->bw_ctx.dml.soc.num_states)
1478 goto validate_fail;
1479
1480 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1481 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1482 struct pipe_ctx *mpo_pipe = pipe->bottom_pipe;
1483
1484 if (!pipe->stream)
1485 continue;
1486
1487 if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled
1488 && !dc->config.enable_windowed_mpo_odm
1489 && pipe->plane_state && mpo_pipe
1490 && memcmp(&mpo_pipe->plane_res.scl_data.recout,
1491 &pipe->plane_res.scl_data.recout,
1492 sizeof(struct rect)) != 0) {
1493 ASSERT(mpo_pipe->plane_state != pipe->plane_state);
1494 goto validate_fail;
1495 }
1496 pipe_idx++;
1497 }
1498
1499
1500 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1501 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1502
1503
1504 if (!merge[i])
1505 continue;
1506
1507
1508 if (pipe->prev_odm_pipe) {
1509
1510 pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;
1511 if (pipe->next_odm_pipe)
1512 pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
1513
1514 pipe->bottom_pipe = NULL;
1515 pipe->next_odm_pipe = NULL;
1516 pipe->plane_state = NULL;
1517 pipe->stream = NULL;
1518 pipe->top_pipe = NULL;
1519 pipe->prev_odm_pipe = NULL;
1520 if (pipe->stream_res.dsc)
1521 dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);
1522 memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
1523 memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
1524 repopulate_pipes = true;
1525 } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
1526 struct pipe_ctx *top_pipe = pipe->top_pipe;
1527 struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;
1528
1529 top_pipe->bottom_pipe = bottom_pipe;
1530 if (bottom_pipe)
1531 bottom_pipe->top_pipe = top_pipe;
1532
1533 pipe->top_pipe = NULL;
1534 pipe->bottom_pipe = NULL;
1535 pipe->plane_state = NULL;
1536 pipe->stream = NULL;
1537 memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
1538 memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
1539 repopulate_pipes = true;
1540 } else
1541 ASSERT(0);
1542
1543 }
1544
1545 for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
1546 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1547 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1548 struct pipe_ctx *hsplit_pipe = NULL;
1549 bool odm;
1550 int old_index = -1;
1551
1552 if (!pipe->stream || newly_split[i])
1553 continue;
1554
1555 pipe_idx++;
1556 odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled;
1557
1558 if (!pipe->plane_state && !odm)
1559 continue;
1560
1561 if (split[i]) {
1562 if (odm) {
1563 if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)
1564 old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
1565 else if (old_pipe->next_odm_pipe)
1566 old_index = old_pipe->next_odm_pipe->pipe_idx;
1567 } else {
1568 if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
1569 old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
1570 old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;
1571 else if (old_pipe->bottom_pipe &&
1572 old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
1573 old_index = old_pipe->bottom_pipe->pipe_idx;
1574 }
1575 hsplit_pipe = dcn32_find_split_pipe(dc, context, old_index);
1576 ASSERT(hsplit_pipe);
1577 if (!hsplit_pipe)
1578 goto validate_fail;
1579
1580 if (!dcn32_split_stream_for_mpc_or_odm(
1581 dc, &context->res_ctx,
1582 pipe, hsplit_pipe, odm))
1583 goto validate_fail;
1584
1585 newly_split[hsplit_pipe->pipe_idx] = true;
1586 repopulate_pipes = true;
1587 }
1588 if (split[i] == 4) {
1589 struct pipe_ctx *pipe_4to1;
1590
1591 if (odm && old_pipe->next_odm_pipe)
1592 old_index = old_pipe->next_odm_pipe->pipe_idx;
1593 else if (!odm && old_pipe->bottom_pipe &&
1594 old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
1595 old_index = old_pipe->bottom_pipe->pipe_idx;
1596 else
1597 old_index = -1;
1598 pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
1599 ASSERT(pipe_4to1);
1600 if (!pipe_4to1)
1601 goto validate_fail;
1602 if (!dcn32_split_stream_for_mpc_or_odm(
1603 dc, &context->res_ctx,
1604 pipe, pipe_4to1, odm))
1605 goto validate_fail;
1606 newly_split[pipe_4to1->pipe_idx] = true;
1607
1608 if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe
1609 && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
1610 old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
1611 else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
1612 old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
1613 old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
1614 old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;
1615 else
1616 old_index = -1;
1617 pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index);
1618 ASSERT(pipe_4to1);
1619 if (!pipe_4to1)
1620 goto validate_fail;
1621 if (!dcn32_split_stream_for_mpc_or_odm(
1622 dc, &context->res_ctx,
1623 hsplit_pipe, pipe_4to1, odm))
1624 goto validate_fail;
1625 newly_split[pipe_4to1->pipe_idx] = true;
1626 }
1627 if (odm)
1628 dcn20_build_mapped_resource(dc, context, pipe->stream);
1629 }
1630
1631 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1632 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1633
1634 if (pipe->plane_state) {
1635 if (!resource_build_scaling_params(pipe))
1636 goto validate_fail;
1637 }
1638 }
1639
1640
1641 if (!dcn20_validate_dsc(dc, context)) {
1642 vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE;
1643 goto validate_fail;
1644 }
1645
1646 if (repopulate_pipes)
1647 pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
1648 *vlevel_out = vlevel;
1649 *pipe_cnt_out = pipe_cnt;
1650
1651 out = true;
1652 goto validate_out;
1653
1654 validate_fail:
1655 out = false;
1656
1657 validate_out:
1658 return out;
1659 }
1660
1661
1662 void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
1663 display_e2e_pipe_params_st *pipes,
1664 int pipe_cnt,
1665 int vlevel)
1666 {
1667 int i, pipe_idx, vlevel_temp = 0;
1668 double dcfclk = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
1669 double dcfclk_from_validation = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
1670 bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] !=
1671 dm_dram_clock_change_unsupported;
1672 unsigned int dummy_latency_index = 0;
1673 int maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb;
1674 unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
1675 unsigned int min_dram_speed_mts_margin;
1676
1677 dc_assert_fp_enabled();
1678
1679
1680 if (!pstate_en && dcn32_subvp_in_use(dc, context)) {
1681 context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp;
1682 pstate_en = true;
1683 }
1684
1685 context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
1686
1687 if (!pstate_en) {
1688
1689 context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching =
1690 dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(dc, context);
1691
1692 if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
1693 dummy_latency_index = dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(dc,
1694 context, pipes, pipe_cnt, vlevel);
1695
1696
1697
1698
1699
1700
1701 context->bw_ctx.dml.soc.dram_clock_change_latency_us =
1702 dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us;
1703 dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
1704 maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb;
1705 dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
1706 pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] !=
1707 dm_dram_clock_change_unsupported;
1708 }
1709 }
1710
1711
1712
1713
1714
1715
1716
1717
1718 if (dcn3_2_soc.num_states > 2) {
1719 vlevel_temp = 2;
1720 dcfclk = dcn3_2_soc.clock_limits[2].dcfclk_mhz;
1721 } else
1722 dcfclk = 615;
1723
1724 pipes[0].clks_cfg.voltage = vlevel_temp;
1725 pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
1726 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel_temp].socclk_mhz;
1727
1728 if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid) {
1729 context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us;
1730 context->bw_ctx.dml.soc.fclk_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.fclk_change_latency_us;
1731 context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us;
1732 context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us;
1733 }
1734 context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1735 context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1736 context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1737 context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1738 context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1739 context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1740 context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1741 context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1742 context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1743 context->bw_ctx.bw.dcn.watermarks.b.usr_retraining_ns = get_usr_retraining_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1744
1745
1746
1747
1748
1749
1750
1751
1752 if (dcn3_2_soc.num_states > 2) {
1753 vlevel_temp = 0;
1754 dcfclk = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz;
1755 } else
1756 dcfclk = 615;
1757
1758 pipes[0].clks_cfg.voltage = vlevel_temp;
1759 pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
1760 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel_temp].socclk_mhz;
1761
1762 if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid) {
1763 context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us;
1764 context->bw_ctx.dml.soc.fclk_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.fclk_change_latency_us;
1765 context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us;
1766 context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us;
1767 }
1768 context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1769 context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1770 context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1771 context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1772 context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1773 context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1774 context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1775 context->bw_ctx.bw.dcn.watermarks.d.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1776 context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1777 context->bw_ctx.bw.dcn.watermarks.d.usr_retraining_ns = get_usr_retraining_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787 pipes[0].clks_cfg.voltage = vlevel;
1788 pipes[0].clks_cfg.dcfclk_mhz = dcfclk_from_validation;
1789 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
1790
1791 if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) {
1792 min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
1793 min_dram_speed_mts_margin = 160;
1794
1795 context->bw_ctx.dml.soc.dram_clock_change_latency_us =
1796 dc->clk_mgr->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us;
1797
1798 if (context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] ==
1799 dm_dram_clock_change_unsupported) {
1800 int min_dram_speed_mts_offset = dc->clk_mgr->bw_params->clk_table.num_entries - 1;
1801
1802 min_dram_speed_mts =
1803 dc->clk_mgr->bw_params->clk_table.entries[min_dram_speed_mts_offset].memclk_mhz * 16;
1804 }
1805
1806 if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
1807
1808
1809
1810 for (dummy_latency_index = 3; dummy_latency_index > 0; dummy_latency_index--)
1811 if (min_dram_speed_mts + min_dram_speed_mts_margin >
1812 dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dram_speed_mts)
1813 break;
1814 }
1815
1816 context->bw_ctx.dml.soc.dram_clock_change_latency_us =
1817 dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
1818
1819 context->bw_ctx.dml.soc.fclk_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.fclk_change_latency_us;
1820 context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us;
1821 context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us;
1822 }
1823
1824 context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1825 context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1826 context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1827 context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1828 context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1829 context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1830 context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1831 context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1832 context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1833 context->bw_ctx.bw.dcn.watermarks.c.usr_retraining_ns = get_usr_retraining_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1834
1835 if ((!pstate_en) && (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid)) {
1836
1837
1838
1839
1840 context->bw_ctx.bw.dcn.watermarks.a = context->bw_ctx.bw.dcn.watermarks.c;
1841 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 0;
1842 } else {
1843
1844
1845
1846
1847
1848 dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
1849 context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1850 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1851 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1852 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1853 context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1854 context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1855 context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1856 context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1857 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1858 context->bw_ctx.bw.dcn.watermarks.a.usr_retraining_ns = get_usr_retraining_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1859 }
1860
1861 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1862 if (!context->res_ctx.pipe_ctx[i].stream)
1863 continue;
1864
1865 pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
1866 pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
1867
1868 if (dc->config.forced_clocks) {
1869 pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
1870 pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
1871 }
1872 if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
1873 pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
1874 if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
1875 pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
1876
1877 pipe_idx++;
1878 }
1879
1880 context->perf_params.stutter_period_us = context->bw_ctx.dml.vba.StutterPeriod;
1881
1882 dcn32_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
1883
1884 if (!pstate_en)
1885
1886 context->bw_ctx.dml.soc.dram_clock_change_latency_us =
1887 dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us;
1888
1889 if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching)
1890 dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(dc, context);
1891 }
1892
1893 static void dcn32_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts,
1894 unsigned int *optimal_dcfclk,
1895 unsigned int *optimal_fclk)
1896 {
1897 double bw_from_dram, bw_from_dram1, bw_from_dram2;
1898
1899 bw_from_dram1 = uclk_mts * dcn3_2_soc.num_chans *
1900 dcn3_2_soc.dram_channel_width_bytes * (dcn3_2_soc.max_avg_dram_bw_use_normal_percent / 100);
1901 bw_from_dram2 = uclk_mts * dcn3_2_soc.num_chans *
1902 dcn3_2_soc.dram_channel_width_bytes * (dcn3_2_soc.max_avg_sdp_bw_use_normal_percent / 100);
1903
1904 bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2;
1905
1906 if (optimal_fclk)
1907 *optimal_fclk = bw_from_dram /
1908 (dcn3_2_soc.fabric_datapath_to_dcn_data_return_bytes * (dcn3_2_soc.max_avg_sdp_bw_use_normal_percent / 100));
1909
1910 if (optimal_dcfclk)
1911 *optimal_dcfclk = bw_from_dram /
1912 (dcn3_2_soc.return_bus_width_bytes * (dcn3_2_soc.max_avg_sdp_bw_use_normal_percent / 100));
1913 }
1914
1915 static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries,
1916 unsigned int index)
1917 {
1918 int i;
1919
1920 if (*num_entries == 0)
1921 return;
1922
1923 for (i = index; i < *num_entries - 1; i++) {
1924 table[i] = table[i + 1];
1925 }
1926 memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st));
1927 }
1928
1929 void dcn32_patch_dpm_table(struct clk_bw_params *bw_params)
1930 {
1931 int i;
1932 unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,
1933 max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0;
1934
1935 for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
1936 if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
1937 max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
1938 if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
1939 max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
1940 if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
1941 max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
1942 if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
1943 max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
1944 if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
1945 max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
1946 if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
1947 max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
1948 if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
1949 max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
1950 }
1951
1952
1953
1954
1955
1956
1957
1958 if (max_dcfclk_mhz == 0)
1959 bw_params->clk_table.entries[0].dcfclk_mhz = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
1960 if (max_dispclk_mhz == 0)
1961 bw_params->clk_table.entries[0].dispclk_mhz = dcn3_2_soc.clock_limits[0].dispclk_mhz;
1962 if (max_dtbclk_mhz == 0)
1963 bw_params->clk_table.entries[0].dtbclk_mhz = dcn3_2_soc.clock_limits[0].dtbclk_mhz;
1964 if (max_uclk_mhz == 0)
1965 bw_params->clk_table.entries[0].memclk_mhz = dcn3_2_soc.clock_limits[0].dram_speed_mts / 16;
1966 }
1967
1968 static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
1969 struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
1970 {
1971 int i, j;
1972 struct _vcs_dpi_voltage_scaling_st entry = {0};
1973
1974 unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,
1975 max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0;
1976
1977 unsigned int min_dcfclk_mhz = 199, min_fclk_mhz = 299;
1978
1979 static const unsigned int num_dcfclk_stas = 5;
1980 unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {199, 615, 906, 1324, 1564};
1981
1982 unsigned int num_uclk_dpms = 0;
1983 unsigned int num_fclk_dpms = 0;
1984 unsigned int num_dcfclk_dpms = 0;
1985
1986 for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
1987 if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
1988 max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
1989 if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
1990 max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
1991 if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
1992 max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
1993 if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
1994 max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
1995 if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
1996 max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
1997 if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
1998 max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
1999 if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
2000 max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
2001
2002 if (bw_params->clk_table.entries[i].memclk_mhz > 0)
2003 num_uclk_dpms++;
2004 if (bw_params->clk_table.entries[i].fclk_mhz > 0)
2005 num_fclk_dpms++;
2006 if (bw_params->clk_table.entries[i].dcfclk_mhz > 0)
2007 num_dcfclk_dpms++;
2008 }
2009
2010 if (!max_dcfclk_mhz || !max_dispclk_mhz || !max_dtbclk_mhz)
2011 return -1;
2012
2013 if (max_dppclk_mhz == 0)
2014 max_dppclk_mhz = max_dispclk_mhz;
2015
2016 if (max_fclk_mhz == 0)
2017 max_fclk_mhz = max_dcfclk_mhz * dcn3_2_soc.pct_ideal_sdp_bw_after_urgent / dcn3_2_soc.pct_ideal_fabric_bw_after_urgent;
2018
2019 if (max_phyclk_mhz == 0)
2020 max_phyclk_mhz = dcn3_2_soc.clock_limits[0].phyclk_mhz;
2021
2022 *num_entries = 0;
2023 entry.dispclk_mhz = max_dispclk_mhz;
2024 entry.dscclk_mhz = max_dispclk_mhz / 3;
2025 entry.dppclk_mhz = max_dppclk_mhz;
2026 entry.dtbclk_mhz = max_dtbclk_mhz;
2027 entry.phyclk_mhz = max_phyclk_mhz;
2028 entry.phyclk_d18_mhz = dcn3_2_soc.clock_limits[0].phyclk_d18_mhz;
2029 entry.phyclk_d32_mhz = dcn3_2_soc.clock_limits[0].phyclk_d32_mhz;
2030
2031
2032 for (i = 0; i < num_dcfclk_stas; i++) {
2033 entry.dcfclk_mhz = dcfclk_sta_targets[i];
2034 entry.fabricclk_mhz = 0;
2035 entry.dram_speed_mts = 0;
2036
2037 DC_FP_START();
2038 insert_entry_into_table_sorted(table, num_entries, &entry);
2039 DC_FP_END();
2040 }
2041
2042
2043 entry.dcfclk_mhz = max_dcfclk_mhz;
2044 entry.fabricclk_mhz = 0;
2045 entry.dram_speed_mts = 0;
2046
2047 DC_FP_START();
2048 insert_entry_into_table_sorted(table, num_entries, &entry);
2049 DC_FP_END();
2050
2051
2052 for (i = 0; i < num_uclk_dpms; i++) {
2053 entry.dcfclk_mhz = 0;
2054 entry.fabricclk_mhz = 0;
2055 entry.dram_speed_mts = bw_params->clk_table.entries[i].memclk_mhz * 16;
2056
2057 DC_FP_START();
2058 insert_entry_into_table_sorted(table, num_entries, &entry);
2059 DC_FP_END();
2060 }
2061
2062
2063 if (num_fclk_dpms > 2) {
2064 for (i = 0; i < num_fclk_dpms; i++) {
2065 entry.dcfclk_mhz = 0;
2066 entry.fabricclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
2067 entry.dram_speed_mts = 0;
2068
2069 DC_FP_START();
2070 insert_entry_into_table_sorted(table, num_entries, &entry);
2071 DC_FP_END();
2072 }
2073 }
2074
2075 else {
2076 entry.dcfclk_mhz = 0;
2077 entry.fabricclk_mhz = max_fclk_mhz;
2078 entry.dram_speed_mts = 0;
2079
2080 DC_FP_START();
2081 insert_entry_into_table_sorted(table, num_entries, &entry);
2082 DC_FP_END();
2083 }
2084
2085
2086
2087
2088
2089
2090 for (i = *num_entries - 1; i >= 0 ; i--) {
2091 if (table[i].dcfclk_mhz > max_dcfclk_mhz ||
2092 table[i].fabricclk_mhz > max_fclk_mhz ||
2093 table[i].dram_speed_mts > max_uclk_mhz * 16)
2094 remove_entry_from_table_at_index(table, num_entries, i);
2095 }
2096
2097
2098
2099
2100
2101
2102
2103 for (i = *num_entries - 1; i >= 0 ; i--) {
2104 for (j = 0; j < num_uclk_dpms; j++) {
2105 if (bw_params->clk_table.entries[j].memclk_mhz * 16 >= table[i].dram_speed_mts) {
2106 table[i].dram_speed_mts = bw_params->clk_table.entries[j].memclk_mhz * 16;
2107 break;
2108 }
2109 }
2110 }
2111
2112
2113 if (num_fclk_dpms > 2) {
2114 for (i = *num_entries - 1; i >= 0 ; i--) {
2115 for (j = 0; j < num_fclk_dpms; j++) {
2116 if (bw_params->clk_table.entries[j].fclk_mhz >= table[i].fabricclk_mhz) {
2117 table[i].fabricclk_mhz = bw_params->clk_table.entries[j].fclk_mhz;
2118 break;
2119 }
2120 }
2121 }
2122 }
2123
2124 else {
2125 for (i = *num_entries - 1; i >= 0 ; i--) {
2126 if (table[i].fabricclk_mhz < min_fclk_mhz) {
2127 table[i].fabricclk_mhz = min_fclk_mhz;
2128 break;
2129 }
2130 }
2131 }
2132
2133
2134 for (i = *num_entries - 1; i >= 0 ; i--) {
2135 if (table[i].dcfclk_mhz < min_dcfclk_mhz) {
2136 table[i].dcfclk_mhz = min_dcfclk_mhz;
2137 break;
2138 }
2139 }
2140
2141
2142 i = 0;
2143 while (i < *num_entries - 1) {
2144 if (table[i].dcfclk_mhz == table[i + 1].dcfclk_mhz &&
2145 table[i].fabricclk_mhz == table[i + 1].fabricclk_mhz &&
2146 table[i].dram_speed_mts == table[i + 1].dram_speed_mts)
2147 remove_entry_from_table_at_index(table, num_entries, i + 1);
2148 else
2149 i++;
2150 }
2151
2152
2153 for (i = *num_entries - 1; i >= 0 ; i--) {
2154 table[i].state = i;
2155 }
2156
2157 return 0;
2158 }
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178 void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)
2179 {
2180 dc_assert_fp_enabled();
2181
2182 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2183
2184 dcn3_2_ip.clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
2185
2186
2187 if ((int)(dcn3_2_soc.sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
2188 && dc->bb_overrides.sr_exit_time_ns) {
2189 dcn3_2_soc.sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
2190 }
2191
2192 if ((int)(dcn3_2_soc.sr_enter_plus_exit_time_us * 1000)
2193 != dc->bb_overrides.sr_enter_plus_exit_time_ns
2194 && dc->bb_overrides.sr_enter_plus_exit_time_ns) {
2195 dcn3_2_soc.sr_enter_plus_exit_time_us =
2196 dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
2197 }
2198
2199 if ((int)(dcn3_2_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
2200 && dc->bb_overrides.urgent_latency_ns) {
2201 dcn3_2_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
2202 }
2203
2204 if ((int)(dcn3_2_soc.dram_clock_change_latency_us * 1000)
2205 != dc->bb_overrides.dram_clock_change_latency_ns
2206 && dc->bb_overrides.dram_clock_change_latency_ns) {
2207 dcn3_2_soc.dram_clock_change_latency_us =
2208 dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
2209 }
2210
2211 if ((int)(dcn3_2_soc.fclk_change_latency_us * 1000)
2212 != dc->bb_overrides.fclk_clock_change_latency_ns
2213 && dc->bb_overrides.fclk_clock_change_latency_ns) {
2214 dcn3_2_soc.fclk_change_latency_us =
2215 dc->bb_overrides.fclk_clock_change_latency_ns / 1000;
2216 }
2217
2218 if ((int)(dcn3_2_soc.dummy_pstate_latency_us * 1000)
2219 != dc->bb_overrides.dummy_clock_change_latency_ns
2220 && dc->bb_overrides.dummy_clock_change_latency_ns) {
2221 dcn3_2_soc.dummy_pstate_latency_us =
2222 dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0;
2223 }
2224
2225
2226 if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
2227 struct bp_soc_bb_info bb_info = {0};
2228
2229 if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
2230 if (bb_info.dram_clock_change_latency_100ns > 0)
2231 dcn3_2_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
2232
2233 if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
2234 dcn3_2_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
2235
2236 if (bb_info.dram_sr_exit_latency_100ns > 0)
2237 dcn3_2_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
2238 }
2239 }
2240
2241
2242 if (dc->ctx->dc_bios->vram_info.num_chans)
2243 dcn3_2_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
2244
2245 if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
2246 dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
2247
2248 }
2249
2250
2251 dcn3_2_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
2252 dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
2253
2254
2255 if ((!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) && (bw_params->clk_table.entries[0].memclk_mhz)) {
2256 if (dc->debug.use_legacy_soc_bb_mechanism) {
2257 unsigned int i = 0, j = 0, num_states = 0;
2258
2259 unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0};
2260 unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0};
2261 unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0};
2262 unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0};
2263 unsigned int min_dcfclk = UINT_MAX;
2264
2265
2266 unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {199, 615, 906, 1324, 1564};
2267 unsigned int num_dcfclk_sta_targets = 4, num_uclk_states = 0;
2268 unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0;
2269
2270 for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
2271 if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
2272 max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
2273 if (bw_params->clk_table.entries[i].dcfclk_mhz != 0 &&
2274 bw_params->clk_table.entries[i].dcfclk_mhz < min_dcfclk)
2275 min_dcfclk = bw_params->clk_table.entries[i].dcfclk_mhz;
2276 if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
2277 max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
2278 if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
2279 max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
2280 if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
2281 max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
2282 }
2283 if (min_dcfclk > dcfclk_sta_targets[0])
2284 dcfclk_sta_targets[0] = min_dcfclk;
2285 if (!max_dcfclk_mhz)
2286 max_dcfclk_mhz = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
2287 if (!max_dispclk_mhz)
2288 max_dispclk_mhz = dcn3_2_soc.clock_limits[0].dispclk_mhz;
2289 if (!max_dppclk_mhz)
2290 max_dppclk_mhz = dcn3_2_soc.clock_limits[0].dppclk_mhz;
2291 if (!max_phyclk_mhz)
2292 max_phyclk_mhz = dcn3_2_soc.clock_limits[0].phyclk_mhz;
2293
2294 if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
2295
2296 dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz;
2297 num_dcfclk_sta_targets++;
2298 } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
2299
2300 for (i = 0; i < num_dcfclk_sta_targets; i++) {
2301 if (dcfclk_sta_targets[i] > max_dcfclk_mhz) {
2302 dcfclk_sta_targets[i] = max_dcfclk_mhz;
2303 break;
2304 }
2305 }
2306
2307 num_dcfclk_sta_targets = i + 1;
2308 }
2309
2310 num_uclk_states = bw_params->clk_table.num_entries;
2311
2312
2313 for (i = 0; i < num_uclk_states; i++) {
2314 dcn32_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,
2315 &optimal_dcfclk_for_uclk[i], NULL);
2316 if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) {
2317 optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz;
2318 }
2319 }
2320
2321
2322 for (i = 0; i < num_dcfclk_sta_targets; i++) {
2323 for (j = 0; j < num_uclk_states; j++) {
2324 if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) {
2325 optimal_uclk_for_dcfclk_sta_targets[i] =
2326 bw_params->clk_table.entries[j].memclk_mhz * 16;
2327 break;
2328 }
2329 }
2330 }
2331
2332 i = 0;
2333 j = 0;
2334
2335 while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) {
2336 if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) {
2337 dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
2338 dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
2339 } else {
2340 if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
2341 dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
2342 dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
2343 } else {
2344 j = num_uclk_states;
2345 }
2346 }
2347 }
2348
2349 while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) {
2350 dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
2351 dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
2352 }
2353
2354 while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES &&
2355 optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
2356 dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
2357 dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
2358 }
2359
2360 dcn3_2_soc.num_states = num_states;
2361 for (i = 0; i < dcn3_2_soc.num_states; i++) {
2362 dcn3_2_soc.clock_limits[i].state = i;
2363 dcn3_2_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
2364 dcn3_2_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i];
2365
2366
2367 dcn3_2_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz;
2368 dcn3_2_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz;
2369 dcn3_2_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz;
2370 dcn3_2_soc.clock_limits[i].dscclk_mhz = max_dispclk_mhz / 3;
2371
2372
2373 if (i > 0) {
2374 if (!bw_params->clk_table.entries[i].dtbclk_mhz) {
2375 dcn3_2_soc.clock_limits[i].dtbclk_mhz = dcn3_2_soc.clock_limits[i-1].dtbclk_mhz;
2376 } else {
2377 dcn3_2_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
2378 }
2379 } else if (bw_params->clk_table.entries[i].dtbclk_mhz) {
2380 dcn3_2_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
2381 }
2382
2383 if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0)
2384 dcn3_2_soc.clock_limits[i].socclk_mhz = dcn3_2_soc.clock_limits[i-1].socclk_mhz;
2385 else
2386 dcn3_2_soc.clock_limits[i].socclk_mhz = bw_params->clk_table.entries[i].socclk_mhz;
2387
2388 if (!dram_speed_mts[i] && i > 0)
2389 dcn3_2_soc.clock_limits[i].dram_speed_mts = dcn3_2_soc.clock_limits[i-1].dram_speed_mts;
2390 else
2391 dcn3_2_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i];
2392
2393
2394
2395 dcn3_2_soc.clock_limits[i].phyclk_d18_mhz = dcn3_2_soc.clock_limits[0].phyclk_d18_mhz;
2396 dcn3_2_soc.clock_limits[i].phyclk_d32_mhz = dcn3_2_soc.clock_limits[0].phyclk_d32_mhz;
2397 }
2398 } else {
2399 build_synthetic_soc_states(bw_params, dcn3_2_soc.clock_limits, &dcn3_2_soc.num_states);
2400 }
2401
2402
2403 dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);
2404 if (dc->current_state)
2405 dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);
2406 }
2407 }
2408