1 // SPDX-License-Identifier: MIT
2 //
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_* defines
8 #include "clk_mgr/dcn401/dcn401_smu14_driver_if.h"
9 #include "link.h"
10 
11 #define DC_LOGGER_INIT(logger)
12 
dcn401_build_wm_range_table_fpu(struct clk_mgr * clk_mgr)13 void 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 	else
32 		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; // TBD
88 	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; // TBD
89 	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_box
98  *
99  * This would override some dcn4_01 ip_or_soc initial parameters hardcoded from
100  * spreadsheet with actual values as per dGPU SKU:
101  * - with passed few options from dc->config
102  * - with dentist_vco_frequency from Clk Mgr (currently hardcoded, but might
103  *   need to get it from PM FW)
104  * - with passed latency values (passed in ns units) in dc-> bb override for
105  *   debugging purposes
106  * - with passed latencies from VBIOS (in 100_ns units) if available for
107  *   certain dGPU SKU
108  * - with number of DRAM channels from VBIOS (which differ for certain dGPU SKU
109  *   of the same ASIC)
110  * - clocks levels with passed clk_table entries from Clk Mgr as reported by PM
111  *   FW for different clocks (which might differ for certain dGPU SKU of the
112  *   same ASIC)
113  */
dcn401_update_bw_bounding_box_fpu(struct dc * dc,struct clk_bw_params * bw_params)114 void 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