240 lines · c
1// SPDX-License-Identifier: MIT2//3// Copyright 2024 Advanced Micro Devices, Inc.4 5#include "dcn401_fpu.h"6#include "dcn401/dcn401_resource.h"7// We need this includes for WATERMARKS_* defines8#include "clk_mgr/dcn401/dcn401_smu14_driver_if.h"9#include "link.h"10 11#define DC_LOGGER_INIT(logger)12 13void dcn401_build_wm_range_table_fpu(struct clk_mgr *clk_mgr)14{15 /* defaults */16 double pstate_latency_us = clk_mgr->ctx->dc->dml.soc.dram_clock_change_latency_us;17 double fclk_change_latency_us = clk_mgr->ctx->dc->dml.soc.fclk_change_latency_us;18 double sr_exit_time_us = clk_mgr->ctx->dc->dml.soc.sr_exit_time_us;19 double sr_enter_plus_exit_time_us = clk_mgr->ctx->dc->dml.soc.sr_enter_plus_exit_time_us;20 /* For min clocks use as reported by PM FW and report those as min */21 uint16_t min_uclk_mhz = clk_mgr->bw_params->clk_table.entries[0].memclk_mhz;22 uint16_t min_dcfclk_mhz = clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz;23 uint16_t setb_min_uclk_mhz = min_uclk_mhz;24 uint16_t dcfclk_mhz_for_the_second_state = clk_mgr->ctx->dc->dml.soc.clock_limits[2].dcfclk_mhz;25 26 dc_assert_fp_enabled();27 28 /* For Set B ranges use min clocks state 2 when available, and report those to PM FW */29 if (dcfclk_mhz_for_the_second_state)30 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = dcfclk_mhz_for_the_second_state;31 else32 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz;33 34 if (clk_mgr->bw_params->clk_table.entries[2].memclk_mhz)35 setb_min_uclk_mhz = clk_mgr->bw_params->clk_table.entries[2].memclk_mhz;36 37 /* Set A - Normal - default values */38 clk_mgr->bw_params->wm_table.nv_entries[WM_A].valid = true;39 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;40 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us = fclk_change_latency_us;41 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;42 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;43 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;44 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;45 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;46 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;47 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;48 49 /* Set B - Performance - higher clocks, using DPM[2] DCFCLK and UCLK */50 clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid = true;51 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us;52 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.fclk_change_latency_us = fclk_change_latency_us;53 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us;54 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;55 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;56 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF;57 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = setb_min_uclk_mhz;58 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF;59 60 /* Set C - Dummy P-State - P-State latency set to "dummy p-state" value */61 /* 'DalDummyClockChangeLatencyNs' registry key option set to 0x7FFFFFFF can be used to disable Set C for dummy p-state */62 if (clk_mgr->ctx->dc->bb_overrides.dummy_clock_change_latency_ns != 0x7FFFFFFF) {63 clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid = true;64 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = 50;65 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.fclk_change_latency_us = fclk_change_latency_us;66 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;67 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;68 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;69 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;70 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;71 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;72 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;73 clk_mgr->bw_params->dummy_pstate_table[0].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 16;74 clk_mgr->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us = 50;75 clk_mgr->bw_params->dummy_pstate_table[1].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[1].memclk_mhz * 16;76 clk_mgr->bw_params->dummy_pstate_table[1].dummy_pstate_latency_us = 9;77 clk_mgr->bw_params->dummy_pstate_table[2].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[2].memclk_mhz * 16;78 clk_mgr->bw_params->dummy_pstate_table[2].dummy_pstate_latency_us = 8;79 clk_mgr->bw_params->dummy_pstate_table[3].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[3].memclk_mhz * 16;80 clk_mgr->bw_params->dummy_pstate_table[3].dummy_pstate_latency_us = 5;81 }82 /* Set D - MALL - SR enter and exit time specific to MALL, TBD after bringup or later phase for now use DRAM values / 2 */83 /* For MALL DRAM clock change latency is N/A, for watermak calculations use lowest value dummy P state latency */84 clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid = true;85 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = clk_mgr->bw_params->dummy_pstate_table[3].dummy_pstate_latency_us;86 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.fclk_change_latency_us = fclk_change_latency_us;87 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = sr_exit_time_us / 2; // TBD88 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us / 2; // TBD89 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;90 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;91 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;92 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;93 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;94}95 96/*97 * dcn401_update_bw_bounding_box98 *99 * This would override some dcn4_01 ip_or_soc initial parameters hardcoded from100 * spreadsheet with actual values as per dGPU SKU:101 * - with passed few options from dc->config102 * - with dentist_vco_frequency from Clk Mgr (currently hardcoded, but might103 * need to get it from PM FW)104 * - with passed latency values (passed in ns units) in dc-> bb override for105 * debugging purposes106 * - with passed latencies from VBIOS (in 100_ns units) if available for107 * certain dGPU SKU108 * - with number of DRAM channels from VBIOS (which differ for certain dGPU SKU109 * of the same ASIC)110 * - clocks levels with passed clk_table entries from Clk Mgr as reported by PM111 * FW for different clocks (which might differ for certain dGPU SKU of the112 * same ASIC)113 */114void dcn401_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)115{116 dc_assert_fp_enabled();117 118 /* Override from passed dc->bb_overrides if available*/119 if (dc->bb_overrides.sr_exit_time_ns)120 dc->dml2_options.bbox_overrides.sr_exit_latency_us =121 dc->bb_overrides.sr_exit_time_ns / 1000.0;122 123 if (dc->bb_overrides.sr_enter_plus_exit_time_ns)124 dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us =125 dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;126 127 if (dc->bb_overrides.urgent_latency_ns)128 dc->dml2_options.bbox_overrides.urgent_latency_us =129 dc->bb_overrides.urgent_latency_ns / 1000.0;130 131 if (dc->bb_overrides.dram_clock_change_latency_ns)132 dc->dml2_options.bbox_overrides.dram_clock_change_latency_us =133 dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;134 135 if (dc->bb_overrides.fclk_clock_change_latency_ns)136 dc->dml2_options.bbox_overrides.fclk_change_latency_us =137 dc->bb_overrides.fclk_clock_change_latency_ns / 1000;138 139 /* Override from VBIOS if VBIOS bb_info available */140 if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {141 struct bp_soc_bb_info bb_info = {0};142 if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {143 if (bb_info.dram_clock_change_latency_100ns > 0)144 dc->dml2_options.bbox_overrides.dram_clock_change_latency_us =145 bb_info.dram_clock_change_latency_100ns * 10;146 147 if (bb_info.dram_sr_enter_exit_latency_100ns > 0)148 dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us =149 bb_info.dram_sr_enter_exit_latency_100ns * 10;150 151 if (bb_info.dram_sr_exit_latency_100ns > 0)152 dc->dml2_options.bbox_overrides.sr_exit_latency_us =153 bb_info.dram_sr_exit_latency_100ns * 10;154 }155 }156 157 /* Override from VBIOS for num_chan */158 if (dc->ctx->dc_bios->vram_info.num_chans) {159 dc->dml2_options.bbox_overrides.dram_num_chan =160 dc->ctx->dc_bios->vram_info.num_chans;161 162 }163 164 if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)165 dc->dml2_options.bbox_overrides.dram_chanel_width_bytes =166 dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;167 168 dc->dml2_options.bbox_overrides.disp_pll_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;169 dc->dml2_options.bbox_overrides.xtalclk_mhz = dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency / 1000.0;170 dc->dml2_options.bbox_overrides.dchub_refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0;171 dc->dml2_options.bbox_overrides.dprefclk_mhz = dc->clk_mgr->dprefclk_khz / 1000.0;172 173 if (dc->clk_mgr->bw_params->clk_table.num_entries > 1) {174 unsigned int i = 0;175 176 dc->dml2_options.bbox_overrides.clks_table.num_states = dc->clk_mgr->bw_params->clk_table.num_entries;177 178 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels =179 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels;180 181 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels =182 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels;183 184 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels =185 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels;186 187 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_socclk_levels =188 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels;189 190 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels =191 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels;192 193 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels =194 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;195 196 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dppclk_levels =197 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels;198 199 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels; i++) {200 if (dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz)201 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz =202 dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz;203 }204 205 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels; i++) {206 if (dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz)207 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].fclk_mhz =208 dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz;209 }210 211 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels; i++) {212 if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz)213 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz =214 dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz;215 }216 217 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels; i++) {218 if (dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz)219 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].socclk_mhz =220 dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz;221 }222 223 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels; i++) {224 if (dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz)225 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz =226 dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz;227 }228 229 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; i++) {230 if (dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz) {231 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dispclk_mhz =232 dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz;233 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dppclk_mhz =234 dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz;235 }236 }237 }238}239 240