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 #include "resource.h"
0026 #include "clk_mgr.h"
0027 #include "reg_helper.h"
0028 #include "dcn_calc_math.h"
0029 #include "dcn20/dcn20_resource.h"
0030 #include "dcn30/dcn30_resource.h"
0031
0032 #include "clk_mgr/dcn30/dcn30_smu11_driver_if.h"
0033 #include "display_mode_vba_30.h"
0034 #include "dcn30_fpu.h"
0035
0036 #define REG(reg)\
0037 optc1->tg_regs->reg
0038
0039 #define CTX \
0040 optc1->base.ctx
0041
0042 #undef FN
0043 #define FN(reg_name, field_name) \
0044 optc1->tg_shift->field_name, optc1->tg_mask->field_name
0045
0046
0047 struct _vcs_dpi_ip_params_st dcn3_0_ip = {
0048 .use_min_dcfclk = 0,
0049 .clamp_min_dcfclk = 0,
0050 .odm_capable = 1,
0051 .gpuvm_enable = 0,
0052 .hostvm_enable = 0,
0053 .gpuvm_max_page_table_levels = 4,
0054 .hostvm_max_page_table_levels = 4,
0055 .hostvm_cached_page_table_levels = 0,
0056 .pte_group_size_bytes = 2048,
0057 .num_dsc = 6,
0058 .rob_buffer_size_kbytes = 184,
0059 .det_buffer_size_kbytes = 184,
0060 .dpte_buffer_size_in_pte_reqs_luma = 84,
0061 .pde_proc_buffer_size_64k_reqs = 48,
0062 .dpp_output_buffer_pixels = 2560,
0063 .opp_output_buffer_lines = 1,
0064 .pixel_chunk_size_kbytes = 8,
0065 .pte_enable = 1,
0066 .max_page_table_levels = 2,
0067 .pte_chunk_size_kbytes = 2,
0068 .meta_chunk_size_kbytes = 2,
0069 .writeback_chunk_size_kbytes = 8,
0070 .line_buffer_size_bits = 789504,
0071 .is_line_buffer_bpp_fixed = 0,
0072 .line_buffer_fixed_bpp = 0,
0073 .dcc_supported = true,
0074 .writeback_interface_buffer_size_kbytes = 90,
0075 .writeback_line_buffer_buffer_size = 0,
0076 .max_line_buffer_lines = 12,
0077 .writeback_luma_buffer_size_kbytes = 12,
0078 .writeback_chroma_buffer_size_kbytes = 8,
0079 .writeback_chroma_line_buffer_width_pixels = 4,
0080 .writeback_max_hscl_ratio = 1,
0081 .writeback_max_vscl_ratio = 1,
0082 .writeback_min_hscl_ratio = 1,
0083 .writeback_min_vscl_ratio = 1,
0084 .writeback_max_hscl_taps = 1,
0085 .writeback_max_vscl_taps = 1,
0086 .writeback_line_buffer_luma_buffer_size = 0,
0087 .writeback_line_buffer_chroma_buffer_size = 14643,
0088 .cursor_buffer_size = 8,
0089 .cursor_chunk_size = 2,
0090 .max_num_otg = 6,
0091 .max_num_dpp = 6,
0092 .max_num_wb = 1,
0093 .max_dchub_pscl_bw_pix_per_clk = 4,
0094 .max_pscl_lb_bw_pix_per_clk = 2,
0095 .max_lb_vscl_bw_pix_per_clk = 4,
0096 .max_vscl_hscl_bw_pix_per_clk = 4,
0097 .max_hscl_ratio = 6,
0098 .max_vscl_ratio = 6,
0099 .hscl_mults = 4,
0100 .vscl_mults = 4,
0101 .max_hscl_taps = 8,
0102 .max_vscl_taps = 8,
0103 .dispclk_ramp_margin_percent = 1,
0104 .underscan_factor = 1.11,
0105 .min_vblank_lines = 32,
0106 .dppclk_delay_subtotal = 46,
0107 .dynamic_metadata_vm_enabled = true,
0108 .dppclk_delay_scl_lb_only = 16,
0109 .dppclk_delay_scl = 50,
0110 .dppclk_delay_cnvc_formatter = 27,
0111 .dppclk_delay_cnvc_cursor = 6,
0112 .dispclk_delay_subtotal = 119,
0113 .dcfclk_cstate_latency = 5.2,
0114 .max_inter_dcn_tile_repeaters = 8,
0115 .max_num_hdmi_frl_outputs = 1,
0116 .odm_combine_4to1_supported = true,
0117
0118 .xfc_supported = false,
0119 .xfc_fill_bw_overhead_percent = 10.0,
0120 .xfc_fill_constant_bytes = 0,
0121 .gfx7_compat_tiling_supported = 0,
0122 .number_of_cursors = 1,
0123 };
0124
0125 struct _vcs_dpi_soc_bounding_box_st dcn3_0_soc = {
0126 .clock_limits = {
0127 {
0128 .state = 0,
0129 .dispclk_mhz = 562.0,
0130 .dppclk_mhz = 300.0,
0131 .phyclk_mhz = 300.0,
0132 .phyclk_d18_mhz = 667.0,
0133 .dscclk_mhz = 405.6,
0134 },
0135 },
0136
0137 .min_dcfclk = 500.0,
0138 .num_states = 1,
0139 .sr_exit_time_us = 15.5,
0140 .sr_enter_plus_exit_time_us = 20,
0141 .urgent_latency_us = 4.0,
0142 .urgent_latency_pixel_data_only_us = 4.0,
0143 .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
0144 .urgent_latency_vm_data_only_us = 4.0,
0145 .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
0146 .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
0147 .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
0148 .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0,
0149 .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0,
0150 .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
0151 .max_avg_sdp_bw_use_normal_percent = 60.0,
0152 .max_avg_dram_bw_use_normal_percent = 40.0,
0153 .writeback_latency_us = 12.0,
0154 .max_request_size_bytes = 256,
0155 .fabric_datapath_to_dcn_data_return_bytes = 64,
0156 .dcn_downspread_percent = 0.5,
0157 .downspread_percent = 0.38,
0158 .dram_page_open_time_ns = 50.0,
0159 .dram_rw_turnaround_time_ns = 17.5,
0160 .dram_return_buffer_per_channel_bytes = 8192,
0161 .round_trip_ping_latency_dcfclk_cycles = 191,
0162 .urgent_out_of_order_return_per_channel_bytes = 4096,
0163 .channel_interleave_bytes = 256,
0164 .num_banks = 8,
0165 .gpuvm_min_page_size_bytes = 4096,
0166 .hostvm_min_page_size_bytes = 4096,
0167 .dram_clock_change_latency_us = 404,
0168 .dummy_pstate_latency_us = 5,
0169 .writeback_dram_clock_change_latency_us = 23.0,
0170 .return_bus_width_bytes = 64,
0171 .dispclk_dppclk_vco_speed_mhz = 3650,
0172 .xfc_bus_transport_time_us = 20,
0173 .xfc_xbuf_latency_tolerance_us = 4,
0174 .use_urgent_burst_bw = 1,
0175 .do_urgent_latency_adjustment = true,
0176 .urgent_latency_adjustment_fabric_clock_component_us = 1.0,
0177 .urgent_latency_adjustment_fabric_clock_reference_mhz = 1000,
0178 };
0179
0180
0181 void optc3_fpu_set_vrr_m_const(struct timing_generator *optc,
0182 double vtotal_avg)
0183 {
0184 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0185 double vtotal_min, vtotal_max;
0186 double ratio, modulo, phase;
0187 uint32_t vblank_start;
0188 uint32_t v_total_mask_value = 0;
0189
0190 dc_assert_fp_enabled();
0191
0192
0193
0194
0195 v_total_mask_value = 16;
0196 vtotal_min = dcn_bw_floor(vtotal_avg);
0197 vtotal_max = dcn_bw_ceil(vtotal_avg);
0198
0199
0200
0201
0202
0203 REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START,
0204 &vblank_start);
0205 ASSERT(vtotal_min >= vblank_start + 1);
0206
0207
0208
0209
0210 if (vtotal_min == vtotal_max) {
0211 REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL, (uint32_t)vtotal_min);
0212
0213 optc->funcs->set_vtotal_min_max(optc, 0, 0);
0214 REG_SET(OTG_M_CONST_DTO0, 0, OTG_M_CONST_DTO_PHASE, 0);
0215 REG_SET(OTG_M_CONST_DTO1, 0, OTG_M_CONST_DTO_MODULO, 0);
0216 REG_UPDATE_3(OTG_V_TOTAL_CONTROL,
0217 OTG_V_TOTAL_MIN_SEL, 0,
0218 OTG_V_TOTAL_MAX_SEL, 0,
0219 OTG_SET_V_TOTAL_MIN_MASK_EN, 0);
0220 return;
0221 }
0222
0223 ratio = vtotal_max - vtotal_avg;
0224 modulo = 65536.0 * 65536.0 - 1.0;
0225 phase = ratio * modulo;
0226
0227
0228
0229
0230 if (phase <= 0 || phase >= modulo) {
0231 REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL,
0232 phase <= 0 ?
0233 (uint32_t)vtotal_max : (uint32_t)vtotal_min);
0234 REG_SET(OTG_V_TOTAL_MIN, 0, OTG_V_TOTAL_MIN, 0);
0235 REG_SET(OTG_V_TOTAL_MAX, 0, OTG_V_TOTAL_MAX, 0);
0236 REG_SET(OTG_M_CONST_DTO0, 0, OTG_M_CONST_DTO_PHASE, 0);
0237 REG_SET(OTG_M_CONST_DTO1, 0, OTG_M_CONST_DTO_MODULO, 0);
0238 REG_UPDATE_3(OTG_V_TOTAL_CONTROL,
0239 OTG_V_TOTAL_MIN_SEL, 0,
0240 OTG_V_TOTAL_MAX_SEL, 0,
0241 OTG_SET_V_TOTAL_MIN_MASK_EN, 0);
0242 return;
0243 }
0244 REG_UPDATE_6(OTG_V_TOTAL_CONTROL,
0245 OTG_V_TOTAL_MIN_SEL, 1,
0246 OTG_V_TOTAL_MAX_SEL, 1,
0247 OTG_SET_V_TOTAL_MIN_MASK_EN, 1,
0248 OTG_SET_V_TOTAL_MIN_MASK, v_total_mask_value,
0249 OTG_VTOTAL_MID_REPLACING_MIN_EN, 0,
0250 OTG_VTOTAL_MID_REPLACING_MAX_EN, 0);
0251 REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL, (uint32_t)vtotal_min);
0252 optc->funcs->set_vtotal_min_max(optc, vtotal_min, vtotal_max);
0253 REG_SET(OTG_M_CONST_DTO0, 0, OTG_M_CONST_DTO_PHASE, (uint32_t)phase);
0254 REG_SET(OTG_M_CONST_DTO1, 0, OTG_M_CONST_DTO_MODULO, (uint32_t)modulo);
0255 }
0256
0257 void dcn30_fpu_populate_dml_writeback_from_context(
0258 struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes)
0259 {
0260 int pipe_cnt, i, j;
0261 double max_calc_writeback_dispclk;
0262 double writeback_dispclk;
0263 struct writeback_st dout_wb;
0264
0265 dc_assert_fp_enabled();
0266
0267 for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
0268 struct dc_stream_state *stream = res_ctx->pipe_ctx[i].stream;
0269
0270 if (!stream)
0271 continue;
0272 max_calc_writeback_dispclk = 0;
0273
0274
0275 pipes[pipe_cnt].dout.wb_enable = 0;
0276 pipes[pipe_cnt].dout.num_active_wb = 0;
0277 for (j = 0; j < stream->num_wb_info; j++) {
0278 struct dc_writeback_info *wb_info = &stream->writeback_info[j];
0279
0280 if (wb_info->wb_enabled && wb_info->writeback_source_plane &&
0281 (wb_info->writeback_source_plane == res_ctx->pipe_ctx[i].plane_state)) {
0282 pipes[pipe_cnt].dout.wb_enable = 1;
0283 pipes[pipe_cnt].dout.num_active_wb++;
0284 dout_wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_en ?
0285 wb_info->dwb_params.cnv_params.crop_height :
0286 wb_info->dwb_params.cnv_params.src_height;
0287 dout_wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_en ?
0288 wb_info->dwb_params.cnv_params.crop_width :
0289 wb_info->dwb_params.cnv_params.src_width;
0290 dout_wb.wb_dst_width = wb_info->dwb_params.dest_width;
0291 dout_wb.wb_dst_height = wb_info->dwb_params.dest_height;
0292
0293
0294 if (dc->dml.ip.writeback_max_hscl_taps > 1) {
0295 dout_wb.wb_htaps_luma = wb_info->dwb_params.scaler_taps.h_taps;
0296 dout_wb.wb_vtaps_luma = wb_info->dwb_params.scaler_taps.v_taps;
0297 } else {
0298 dout_wb.wb_htaps_luma = 1;
0299 dout_wb.wb_vtaps_luma = 1;
0300 }
0301 dout_wb.wb_htaps_chroma = 0;
0302 dout_wb.wb_vtaps_chroma = 0;
0303 dout_wb.wb_hratio = wb_info->dwb_params.cnv_params.crop_en ?
0304 (double)wb_info->dwb_params.cnv_params.crop_width /
0305 (double)wb_info->dwb_params.dest_width :
0306 (double)wb_info->dwb_params.cnv_params.src_width /
0307 (double)wb_info->dwb_params.dest_width;
0308 dout_wb.wb_vratio = wb_info->dwb_params.cnv_params.crop_en ?
0309 (double)wb_info->dwb_params.cnv_params.crop_height /
0310 (double)wb_info->dwb_params.dest_height :
0311 (double)wb_info->dwb_params.cnv_params.src_height /
0312 (double)wb_info->dwb_params.dest_height;
0313 if (wb_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_ARGB ||
0314 wb_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_RGBA)
0315 dout_wb.wb_pixel_format = dm_444_64;
0316 else
0317 dout_wb.wb_pixel_format = dm_444_32;
0318
0319
0320
0321
0322
0323
0324 writeback_dispclk = dml30_CalculateWriteBackDISPCLK(
0325 dout_wb.wb_pixel_format,
0326 pipes[pipe_cnt].pipe.dest.pixel_rate_mhz,
0327 dout_wb.wb_hratio,
0328 dout_wb.wb_vratio,
0329 dout_wb.wb_htaps_luma,
0330 dout_wb.wb_vtaps_luma,
0331 dout_wb.wb_src_width,
0332 dout_wb.wb_dst_width,
0333 pipes[pipe_cnt].pipe.dest.htotal,
0334 dc->current_state->bw_ctx.dml.ip.writeback_line_buffer_buffer_size);
0335
0336 if (writeback_dispclk > max_calc_writeback_dispclk) {
0337 max_calc_writeback_dispclk = writeback_dispclk;
0338 pipes[pipe_cnt].dout.wb = dout_wb;
0339 }
0340 }
0341 }
0342
0343 pipe_cnt++;
0344 }
0345 }
0346
0347 void dcn30_fpu_set_mcif_arb_params(struct mcif_arb_params *wb_arb_params,
0348 struct display_mode_lib *dml,
0349 display_e2e_pipe_params_st *pipes,
0350 int pipe_cnt,
0351 int cur_pipe)
0352 {
0353 int i;
0354
0355 dc_assert_fp_enabled();
0356
0357 for (i = 0; i < ARRAY_SIZE(wb_arb_params->cli_watermark); i++) {
0358 wb_arb_params->cli_watermark[i] = get_wm_writeback_urgent(dml, pipes, pipe_cnt) * 1000;
0359 wb_arb_params->pstate_watermark[i] = get_wm_writeback_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
0360 }
0361
0362 wb_arb_params->dram_speed_change_duration = dml->vba.WritebackAllowDRAMClockChangeEndPosition[cur_pipe] * pipes[0].clks_cfg.refclk_mhz;
0363 }
0364
0365 void dcn30_fpu_update_soc_for_wm_a(struct dc *dc, struct dc_state *context)
0366 {
0367
0368 dc_assert_fp_enabled();
0369
0370 if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].valid) {
0371 context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us;
0372 context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us;
0373 context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us;
0374 }
0375 }
0376
0377 void dcn30_fpu_calculate_wm_and_dlg(
0378 struct dc *dc, struct dc_state *context,
0379 display_e2e_pipe_params_st *pipes,
0380 int pipe_cnt,
0381 int vlevel)
0382 {
0383 int maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb;
0384 int i, pipe_idx;
0385 double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][maxMpcComb];
0386 bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] != dm_dram_clock_change_unsupported;
0387
0388 dc_assert_fp_enabled();
0389
0390 if (context->bw_ctx.dml.soc.min_dcfclk > dcfclk)
0391 dcfclk = context->bw_ctx.dml.soc.min_dcfclk;
0392
0393 pipes[0].clks_cfg.voltage = vlevel;
0394 pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
0395 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
0396
0397
0398
0399
0400
0401 if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid) {
0402 if (vlevel == 0) {
0403 pipes[0].clks_cfg.voltage = 1;
0404 pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dcfclk_mhz;
0405 }
0406 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;
0407 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;
0408 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;
0409 }
0410 context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0411 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;
0412 context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0413 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;
0414 context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0415 context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0416 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;
0417 context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0418
0419 pipes[0].clks_cfg.voltage = vlevel;
0420 pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) {
0449 unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
0450 unsigned int min_dram_speed_mts_margin = 160;
0451
0452 if (context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_unsupported)
0453 min_dram_speed_mts = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz * 16;
0454
0455
0456 for (i = 3; i > 0; i--)
0457 if (min_dram_speed_mts + min_dram_speed_mts_margin > dc->clk_mgr->bw_params->dummy_pstate_table[i].dram_speed_mts)
0458 break;
0459
0460 context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[i].dummy_pstate_latency_us;
0461
0462 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;
0463 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;
0464 }
0465
0466 context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0467 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;
0468 context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0469 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;
0470 context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0471 context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0472 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;
0473 context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0474
0475 if (!pstate_en) {
0476
0477
0478
0479 context->bw_ctx.bw.dcn.watermarks.a = context->bw_ctx.bw.dcn.watermarks.c;
0480 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 0;
0481 } else {
0482
0483
0484
0485
0486
0487
0488 dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
0489 context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0490 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;
0491 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0492 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;
0493 context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0494 context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0495 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;
0496 context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
0497 }
0498
0499 context->perf_params.stutter_period_us = context->bw_ctx.dml.vba.StutterPeriod;
0500
0501
0502 context->bw_ctx.bw.dcn.watermarks.d = context->bw_ctx.bw.dcn.watermarks.a;
0503
0504 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
0505 if (!context->res_ctx.pipe_ctx[i].stream)
0506 continue;
0507
0508 pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
0509 pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
0510
0511 if (dc->config.forced_clocks) {
0512 pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
0513 pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
0514 }
0515 if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
0516 pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
0517 if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
0518 pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
0519
0520 pipe_idx++;
0521 }
0522
0523 DC_FP_START();
0524 dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
0525 DC_FP_END();
0526
0527 if (!pstate_en)
0528
0529 context->bw_ctx.dml.soc.dram_clock_change_latency_us =
0530 dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us;
0531
0532 if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching)
0533 dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(dc, context);
0534 }
0535
0536 void dcn30_fpu_update_dram_channel_width_bytes(struct dc *dc)
0537 {
0538 dc_assert_fp_enabled();
0539
0540 if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
0541 dcn3_0_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
0542 }
0543
0544 void dcn30_fpu_update_max_clk(struct dc_bounding_box_max_clk *dcn30_bb_max_clk)
0545 {
0546 dc_assert_fp_enabled();
0547
0548 if (!dcn30_bb_max_clk->max_dcfclk_mhz)
0549 dcn30_bb_max_clk->max_dcfclk_mhz = dcn3_0_soc.clock_limits[0].dcfclk_mhz;
0550 if (!dcn30_bb_max_clk->max_dispclk_mhz)
0551 dcn30_bb_max_clk->max_dispclk_mhz = dcn3_0_soc.clock_limits[0].dispclk_mhz;
0552 if (!dcn30_bb_max_clk->max_dppclk_mhz)
0553 dcn30_bb_max_clk->max_dppclk_mhz = dcn3_0_soc.clock_limits[0].dppclk_mhz;
0554 if (!dcn30_bb_max_clk->max_phyclk_mhz)
0555 dcn30_bb_max_clk->max_phyclk_mhz = dcn3_0_soc.clock_limits[0].phyclk_mhz;
0556 }
0557
0558 void dcn30_fpu_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts,
0559 unsigned int *optimal_dcfclk,
0560 unsigned int *optimal_fclk)
0561 {
0562 double bw_from_dram, bw_from_dram1, bw_from_dram2;
0563
0564 dc_assert_fp_enabled();
0565
0566 bw_from_dram1 = uclk_mts * dcn3_0_soc.num_chans *
0567 dcn3_0_soc.dram_channel_width_bytes * (dcn3_0_soc.max_avg_dram_bw_use_normal_percent / 100);
0568 bw_from_dram2 = uclk_mts * dcn3_0_soc.num_chans *
0569 dcn3_0_soc.dram_channel_width_bytes * (dcn3_0_soc.max_avg_sdp_bw_use_normal_percent / 100);
0570
0571 bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2;
0572
0573 if (optimal_fclk)
0574 *optimal_fclk = bw_from_dram /
0575 (dcn3_0_soc.fabric_datapath_to_dcn_data_return_bytes * (dcn3_0_soc.max_avg_sdp_bw_use_normal_percent / 100));
0576
0577 if (optimal_dcfclk)
0578 *optimal_dcfclk = bw_from_dram /
0579 (dcn3_0_soc.return_bus_width_bytes * (dcn3_0_soc.max_avg_sdp_bw_use_normal_percent / 100));
0580 }
0581
0582 void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
0583 struct clk_bw_params *bw_params,
0584 struct dc_bounding_box_max_clk *dcn30_bb_max_clk,
0585 unsigned int *dcfclk_mhz,
0586 unsigned int *dram_speed_mts)
0587 {
0588 unsigned int i;
0589
0590 dc_assert_fp_enabled();
0591
0592 dcn3_0_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
0593 dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
0594
0595 for (i = 0; i < dcn3_0_soc.num_states; i++) {
0596 dcn3_0_soc.clock_limits[i].state = i;
0597 dcn3_0_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
0598 dcn3_0_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i];
0599 dcn3_0_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i];
0600
0601
0602 dcn3_0_soc.clock_limits[i].dispclk_mhz = dcn30_bb_max_clk->max_dispclk_mhz;
0603 dcn3_0_soc.clock_limits[i].dppclk_mhz = dcn30_bb_max_clk->max_dppclk_mhz;
0604 dcn3_0_soc.clock_limits[i].phyclk_mhz = dcn30_bb_max_clk->max_phyclk_mhz;
0605 dcn3_0_soc.clock_limits[i].dtbclk_mhz = dcn3_0_soc.clock_limits[0].dtbclk_mhz;
0606
0607
0608 dcn3_0_soc.clock_limits[i].phyclk_d18_mhz = dcn3_0_soc.clock_limits[0].phyclk_d18_mhz;
0609 dcn3_0_soc.clock_limits[i].socclk_mhz = dcn3_0_soc.clock_limits[0].socclk_mhz;
0610 dcn3_0_soc.clock_limits[i].dscclk_mhz = dcn3_0_soc.clock_limits[0].dscclk_mhz;
0611 }
0612
0613 dml_init_instance(&dc->dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30);
0614 if (dc->current_state)
0615 dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30);
0616
0617 }
0618
0619
0620
0621
0622
0623
0624
0625 int dcn30_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
0626 struct dc_state *context,
0627 display_e2e_pipe_params_st *pipes,
0628 int pipe_cnt,
0629 int vlevel)
0630 {
0631 const int max_latency_table_entries = 4;
0632 int dummy_latency_index = 0;
0633
0634 dc_assert_fp_enabled();
0635
0636 while (dummy_latency_index < max_latency_table_entries) {
0637 context->bw_ctx.dml.soc.dram_clock_change_latency_us =
0638 dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
0639 dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
0640
0641 if (context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank ==
0642 dm_allow_self_refresh_and_mclk_switch)
0643 break;
0644
0645 dummy_latency_index++;
0646 }
0647
0648 if (dummy_latency_index == max_latency_table_entries) {
0649 ASSERT(dummy_latency_index != max_latency_table_entries);
0650
0651
0652
0653
0654
0655
0656 dummy_latency_index = 3;
0657 }
0658
0659 return dummy_latency_index;
0660 }
0661
0662 void dcn3_fpu_build_wm_range_table(struct clk_mgr *base)
0663 {
0664
0665 double pstate_latency_us = base->ctx->dc->dml.soc.dram_clock_change_latency_us;
0666 double sr_exit_time_us = base->ctx->dc->dml.soc.sr_exit_time_us;
0667 double sr_enter_plus_exit_time_us = base->ctx->dc->dml.soc.sr_enter_plus_exit_time_us;
0668 uint16_t min_uclk_mhz = base->bw_params->clk_table.entries[0].memclk_mhz;
0669
0670 dc_assert_fp_enabled();
0671
0672
0673 base->bw_params->wm_table.nv_entries[WM_A].valid = true;
0674 base->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;
0675 base->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;
0676 base->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
0677 base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
0678 base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = 0;
0679 base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;
0680 base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;
0681 base->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695 base->bw_params->wm_table.nv_entries[WM_C].valid = true;
0696 base->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = 0;
0697 base->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;
0698 base->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
0699 base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;
0700 base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = 0;
0701 base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;
0702 base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
0703 base->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
0704 base->bw_params->dummy_pstate_table[0].dram_speed_mts = 1600;
0705 base->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us = 38;
0706 base->bw_params->dummy_pstate_table[1].dram_speed_mts = 8000;
0707 base->bw_params->dummy_pstate_table[1].dummy_pstate_latency_us = 9;
0708 base->bw_params->dummy_pstate_table[2].dram_speed_mts = 10000;
0709 base->bw_params->dummy_pstate_table[2].dummy_pstate_latency_us = 8;
0710 base->bw_params->dummy_pstate_table[3].dram_speed_mts = 16000;
0711 base->bw_params->dummy_pstate_table[3].dummy_pstate_latency_us = 5;
0712
0713
0714 base->bw_params->wm_table.nv_entries[WM_D].valid = true;
0715 base->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
0716 base->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
0717 base->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
0718 base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
0719 base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
0720 base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
0721 base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
0722 base->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
0723 }
0724
0725 void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip)
0726 {
0727 dc_assert_fp_enabled();
0728
0729 if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
0730 struct bp_soc_bb_info bb_info = {0};
0731
0732 if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
0733 if (bb_info.dram_clock_change_latency_100ns > 0)
0734 dcn3_0_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
0735
0736 if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
0737 dcn3_0_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
0738
0739 if (bb_info.dram_sr_exit_latency_100ns > 0)
0740 dcn3_0_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
0741 }
0742 }
0743 }