xref: /linux/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c (revision 1fc5a74b108fc90951890ec513ac81869f5eaff1)
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2025 Advanced Micro Devices, Inc.
4 
5 #include "dccg.h"
6 #include "clk_mgr_internal.h"
7 #include "dcn60/dcn60_clk_mgr_smu_msg.h"
8 #include "hw_sequencer.h"
9 #include "dce100/dce_clk_mgr.h"
10 #include "dcn20/dcn20_clk_mgr.h"
11 #include "dcn401/dcn401_clk_mgr.h"
12 #include "dcn60/dcn60_clk_mgr.h"
13 #include "soc_and_ip_translator.h"
14 #include "bounding_boxes/utm_qos_model_types.h"
15 #include "bounding_boxes/utm_qos_model_dchub_v3.h"
16 #include "reg_helper.h"
17 #include "core_types.h"
18 #include "dm_helpers.h"
19 #include "link_service.h"
20 #include "dc_state_priv.h"
21 #include "atomfirmware.h"
22 
23 #include "dcn401/dcn401_smu14_driver_if.h"
24 
25 #include "dcn/dcn_6_0_0_offset.h"
26 #include "dcn/dcn_6_0_0_sh_mask.h"
27 
28 #undef DC_LOGGER
29 #define DC_LOGGER \
30 	clk_mgr_base->ctx->logger
31 
32 #define mmCLK08_CLK8_CLK0_CURRENT_CNT                      0x1B83F
33 #define mmCLK08_CLK8_CLK1_CURRENT_CNT                      0x1B840
34 #define mmCLK08_CLK8_CLK2_CURRENT_CNT                      0x1B841
35 #define mmCLK08_CLK8_CLK3_CURRENT_CNT                      0x1B842
36 #define mmCLK08_CLK8_CLK4_CURRENT_CNT                      0x1B843
37 
38 #define mmCLK08_CLK8_CLK0_BYPASS_CNTL                      0x1B816
39 #define mmCLK08_CLK8_CLK1_BYPASS_CNTL                      0x1B81E
40 #define mmCLK08_CLK8_CLK2_BYPASS_CNTL                      0x1B826
41 #define mmCLK08_CLK8_CLK3_BYPASS_CNTL                      0x1B82E
42 #define mmCLK08_CLK8_CLK4_BYPASS_CNTL                      0x1B836
43 
44 #define mmCLK08_CLK8_CLK0_DS_CNTL                          0x1B810
45 #define mmCLK08_CLK8_CLK1_DS_CNTL                          0x1B818
46 #define mmCLK08_CLK8_CLK2_DS_CNTL                          0x1B820
47 #define mmCLK08_CLK8_CLK3_DS_CNTL                          0x1B828
48 #define mmCLK08_CLK8_CLK4_DS_CNTL                          0x1B830
49 
50 #define mmCLK08_CLK8_CLK_TICK_CNT_CONFIG_REG               0x1B83D
51 
52 #define DCN_BASE__INST0_SEG1                       0x000000C0
53 
54 #define CLK8_CLK_TICK_CNT_CONFIG_REG__TIMER_THRESHOLD__SHIFT        0x0
55 #define CLK8_CLK_TICK_CNT_CONFIG_REG__TIMER_THRESHOLD_MASK          0x00FFFFFFL
56 #define CLK8_CLK0_BYPASS_CNTL__CLK0_BYPASS_SEL__SHIFT               0x0
57 #define CLK8_CLK0_BYPASS_CNTL__CLK0_BYPASS_SEL_MASK                 0x00000007L
58 #define CLK8_CLK1_BYPASS_CNTL__CLK1_BYPASS_SEL__SHIFT               0x0
59 #define CLK8_CLK1_BYPASS_CNTL__CLK1_BYPASS_SEL_MASK                 0x00000007L
60 #define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT               0x0
61 #define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK                 0x00000007L
62 #define CLK8_CLK3_BYPASS_CNTL__CLK3_BYPASS_SEL__SHIFT               0x0
63 #define CLK8_CLK3_BYPASS_CNTL__CLK3_BYPASS_SEL_MASK                 0x00000007L
64 #define CLK8_CLK4_BYPASS_CNTL__CLK4_BYPASS_SEL__SHIFT               0x0
65 #define CLK8_CLK4_BYPASS_CNTL__CLK4_BYPASS_SEL_MASK                 0x00000007L
66 #define CLK8_CLK0_DS_CNTL__CLK0_DS_DIV_ID__SHIFT                    0x0
67 #define CLK8_CLK0_DS_CNTL__CLK0_ALLOW_DS__SHIFT                     0x4
68 #define CLK8_CLK0_DS_CNTL__CLK0_DS_DIV_ID_MASK                      0x0000000FL
69 #define CLK8_CLK0_DS_CNTL__CLK0_ALLOW_DS_MASK                       0x00000010L
70 #define CLK8_CLK1_DS_CNTL__CLK1_DS_DIV_ID__SHIFT                    0x0
71 #define CLK8_CLK1_DS_CNTL__CLK1_ALLOW_DS__SHIFT                     0x4
72 #define CLK8_CLK1_DS_CNTL__CLK1_DS_DIV_ID_MASK                      0x0000000FL
73 #define CLK8_CLK1_DS_CNTL__CLK1_ALLOW_DS_MASK                       0x00000010L
74 #define CLK8_CLK2_DS_CNTL__CLK2_DS_DIV_ID__SHIFT                    0x0
75 #define CLK8_CLK2_DS_CNTL__CLK2_ALLOW_DS__SHIFT                     0x4
76 #define CLK8_CLK2_DS_CNTL__CLK2_DS_DIV_ID_MASK                      0x0000000FL
77 #define CLK8_CLK2_DS_CNTL__CLK2_ALLOW_DS_MASK                       0x00000010L
78 #define CLK8_CLK3_DS_CNTL__CLK3_DS_DIV_ID__SHIFT                    0x0
79 #define CLK8_CLK3_DS_CNTL__CLK3_ALLOW_DS__SHIFT                     0x4
80 #define CLK8_CLK3_DS_CNTL__CLK3_DS_DIV_ID_MASK                      0x0000000FL
81 #define CLK8_CLK3_DS_CNTL__CLK3_ALLOW_DS_MASK                       0x00000010L
82 #define CLK8_CLK4_DS_CNTL__CLK4_DS_DIV_ID__SHIFT                    0x0
83 #define CLK8_CLK4_DS_CNTL__CLK4_ALLOW_DS__SHIFT                     0x4
84 #define CLK8_CLK4_DS_CNTL__CLK4_DS_DIV_ID_MASK                      0x0000000FL
85 #define CLK8_CLK4_DS_CNTL__CLK4_ALLOW_DS_MASK                       0x00000010L
86 
87 #define DCN60_CLKIP_REFCLK_KHZ 48000 /* 48 MHz */
88 
89 #undef FN
90 #define FN(reg_name, field_name) \
91 	clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name
92 
93 #define REG(reg) \
94 	(clk_mgr->regs->reg)
95 
96 #define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
97 
98 #define BASE(seg) BASE_INNER(seg)
99 
100 #define SR(reg_name)\
101 		.reg_name = BASE(reg ## reg_name ## _BASE_IDX) +  \
102 					reg ## reg_name
103 
104 #define CLK_SR_DCN60(reg_name, block, inst)\
105 	.reg_name = mm ## block ## _ ## reg_name
106 
107 static const struct clk_mgr_registers clk_mgr_regs_dcn60 = {
108 	CLK_REG_LIST_DCN60()
109 };
110 
111 static const struct clk_mgr_shift clk_mgr_shift_dcn60 = {
112 	CLK_COMMON_MASK_SH_LIST_DCN60(__SHIFT)
113 };
114 
115 static const struct clk_mgr_mask clk_mgr_mask_dcn60 = {
116 	CLK_COMMON_MASK_SH_LIST_DCN60(_MASK)
117 };
118 
119 #define TO_DCN60_CLK_MGR(clk_mgr)\
120 	container_of(clk_mgr, struct dcn60_clk_mgr, base)
121 
dcn60_is_ppclk_dpm_enabled(struct clk_mgr_internal * clk_mgr,PPCLK_e clk)122 static bool dcn60_is_ppclk_dpm_enabled(struct clk_mgr_internal *clk_mgr, PPCLK_e clk)
123 {
124 	bool ppclk_dpm_enabled = false;
125 
126 	switch (clk) {
127 	case PPCLK_SOCCLK:
128 		ppclk_dpm_enabled =
129 			clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_socclk_levels > 1;
130 		break;
131 	case PPCLK_UCLK:
132 		ppclk_dpm_enabled =
133 			clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_memclk_levels > 1;
134 		break;
135 	case PPCLK_FCLK:
136 		ppclk_dpm_enabled =
137 			clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_fclk_levels > 1;
138 		break;
139 	case PPCLK_DISPCLK:
140 		ppclk_dpm_enabled =
141 			clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels > 1;
142 		break;
143 	case PPCLK_DPPCLK:
144 		ppclk_dpm_enabled =
145 			clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dppclk_levels > 1;
146 		break;
147 	case PPCLK_DPREFCLK:
148 		ppclk_dpm_enabled = false;
149 		break;
150 	case PPCLK_DCFCLK:
151 		ppclk_dpm_enabled =
152 			clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels > 1;
153 		break;
154 	case PPCLK_DTBCLK:
155 		ppclk_dpm_enabled =
156 			clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels > 1;
157 		break;
158 	default:
159 		ppclk_dpm_enabled = false;
160 	}
161 
162 	ppclk_dpm_enabled &= clk_mgr->smu_present;
163 
164 	return ppclk_dpm_enabled;
165 }
166 
dcn60_check_native_scaling(struct pipe_ctx * pipe)167 static bool dcn60_check_native_scaling(struct pipe_ctx *pipe)
168 {
169 	bool is_native_scaling = false;
170 	int width = pipe->plane_state->src_rect.width;
171 	int height = pipe->plane_state->src_rect.height;
172 
173 	if (pipe->stream->timing.h_addressable == width &&
174 		pipe->stream->timing.v_addressable == height &&
175 		pipe->plane_state->dst_rect.width == width &&
176 		pipe->plane_state->dst_rect.height == height)
177 		is_native_scaling = true;
178 
179 	return is_native_scaling;
180 }
181 
dcn60_update_clocks_update_dpp_dto(struct clk_mgr_internal * clk_mgr,struct dc_state * context,bool safe_to_lower,int ref_dppclk_khz)182 static void dcn60_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
183 	struct dc_state *context, bool safe_to_lower, int ref_dppclk_khz)
184 {
185 	uint32_t i;
186 
187 	clk_mgr->dccg->ref_dppclk = ref_dppclk_khz;
188 	for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
189 		int dpp_inst = 0, dppclk_khz, prev_dppclk_khz;
190 
191 		dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
192 
193 		if (context->res_ctx.pipe_ctx[i].plane_res.dpp)
194 			dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
195 		else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) {
196 			/* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting.
197 			 * In this case just continue in loop
198 			 */
199 			continue;
200 		} else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) {
201 			/* The software state is not valid if dpp resource is NULL and
202 			 * dppclk_khz > 0.
203 			 */
204 			ASSERT(false);
205 			continue;
206 		}
207 
208 		prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];
209 
210 		if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
211 			clk_mgr->dccg->funcs->update_dpp_dto(
212 				clk_mgr->dccg, dpp_inst, dppclk_khz);
213 	}
214 }
215 
dcn60_set_hard_min_by_freq_optimized(struct clk_mgr_internal * clk_mgr,PPCLK_e clk,int requested_clk_khz)216 static int dcn60_set_hard_min_by_freq_optimized(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, int requested_clk_khz)
217 {
218 	if (!clk_mgr->smu_present || !dcn60_is_ppclk_dpm_enabled(clk_mgr, clk))
219 		return 0;
220 
221 	/*
222 	 * SMU set hard min interface takes requested clock in mhz and return
223 	 * actual clock configured in khz. If we floor requested clk to mhz,
224 	 * there is a chance that the actual clock configured in khz is less
225 	 * than requested. If we ceil it to mhz, there is a chance that it
226 	 * unnecessarily dumps up to a higher dpm level, which burns more power.
227 	 * The solution is to set by flooring it to mhz first. If the actual
228 	 * clock returned is less than requested, then we will ceil the
229 	 * requested value to mhz and call it again.
230 	 */
231 	int actual_clk_khz = dcn60_smu_set_hard_min_by_freq(clk_mgr, clk,
232 		(uint16_t)khz_to_mhz_floor(requested_clk_khz));
233 
234 	if (actual_clk_khz < requested_clk_khz)
235 		actual_clk_khz = dcn60_smu_set_hard_min_by_freq(clk_mgr, clk,
236 			(uint16_t)khz_to_mhz_ceil(requested_clk_khz));
237 
238 	return actual_clk_khz;
239 }
240 
dcn60_update_clocks_update_dtb_dto(struct clk_mgr_internal * clk_mgr,struct dc_state * context,int ref_dtbclk_khz)241 static void dcn60_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
242 	struct dc_state *context,
243 	int ref_dtbclk_khz)
244 {
245 	(void)ref_dtbclk_khz;
246 	int i;
247 	struct dccg *dccg = clk_mgr->dccg;
248 	struct pipe_ctx *otg_master;
249 	bool use_hpo_encoder;
250 
251 	for (i = 0; i < context->stream_count; i++) {
252 		otg_master = resource_get_otg_master_for_stream(
253 			&context->res_ctx, context->streams[i]);
254 
255 		ASSERT(otg_master);
256 		if (!otg_master)
257 			continue;
258 
259 		ASSERT(otg_master->clock_source);
260 		ASSERT(otg_master->clock_source->funcs->program_pix_clk);
261 		ASSERT(otg_master->stream_res.pix_clk_params.controller_id >= CONTROLLER_ID_D0);
262 
263 		use_hpo_encoder = dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(otg_master);
264 		use_hpo_encoder |= dc_is_hdmi_frl_signal(otg_master->stream->signal);
265 		if (!use_hpo_encoder)
266 			continue;
267 
268 		if (otg_master->stream_res.pix_clk_params.controller_id > CONTROLLER_ID_UNDEFINED)
269 			otg_master->clock_source->funcs->program_pix_clk(
270 				otg_master->clock_source,
271 				&otg_master->stream_res.pix_clk_params,
272 				dccg->ctx->dc->link_srv->dp_get_encoding_format(
273 					&otg_master->link_config.dp_link_settings),
274 				&otg_master->pll_settings);
275 	}
276 }
277 
dcn60_build_update_display_clocks_sequence(struct clk_mgr * clk_mgr_base,struct dc_state * context,struct dc_clocks * new_clocks,bool safe_to_lower,unsigned int num_steps_start)278 static unsigned int dcn60_build_update_display_clocks_sequence(
279 	struct clk_mgr *clk_mgr_base,
280 	struct dc_state *context,
281 	struct dc_clocks *new_clocks,
282 	bool safe_to_lower,
283 	unsigned int num_steps_start)
284 {
285 	struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
286 	struct dcn60_clk_mgr *clk_mgr60 = TO_DCN60_CLK_MGR(clk_mgr_internal);
287 	struct dc *dc = clk_mgr_base->ctx->dc;
288 	struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
289 	struct dcn60_clk_mgr_block_sequence *block_sequence = clk_mgr60->block_sequence;
290 	bool force_reset = false;
291 	bool update_dispclk = false;
292 	bool update_dppclk = false;
293 	bool dppclk_lowered = false;
294 	struct pipe_ctx *otg_master;
295 	bool frl_present = false;
296 	unsigned int i;
297 
298 	unsigned int num_steps = num_steps_start;
299 
300 	/* CLK_MGR60_READ_CLOCKS_FROM_DENTIST */
301 	if (clk_mgr_base->clks.dispclk_khz == 0 ||
302 		(dc->debug.force_clock_mode & 0x1)) {
303 		/* This is from resume or boot up, if forced_clock cfg option used,
304 		 * we bypass program dispclk and DPPCLK, but need set them for S3.
305 		 * Force_clock_mode 0x1:  force reset the clock even it is the same clock
306 		 * as long as it is in Passive level.
307 		 */
308 		force_reset = true;
309 
310 		clk_mgr_base->clks.dispclk_khz = clk_mgr_base->boot_snapshot.dispclk;
311 		clk_mgr_base->clks.actual_dispclk_khz = clk_mgr_base->clks.dispclk_khz;
312 
313 		clk_mgr_base->clks.dppclk_khz = clk_mgr_base->boot_snapshot.dppclk;
314 		clk_mgr_base->clks.actual_dppclk_khz = clk_mgr_base->clks.dppclk_khz;
315 	}
316 
317 	/* DTBCLK */
318 	if (!new_clocks->dtbclk_en && dcn60_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DTBCLK)) {
319 		new_clocks->ref_dtbclk_khz = clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
320 	}
321 
322 	/* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
323 	if (!dc->debug.disable_dtb_ref_clk_switch &&
324 		should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, clk_mgr_base->clks.ref_dtbclk_khz / 1000) && //TODO these should be ceiled
325 		dcn60_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DTBCLK)) {
326 		/* DCCG requires KHz precision for DTBCLK */
327 		block_sequence[num_steps].params.update_hardmin_params.ppclk = PPCLK_DTBCLK;
328 		block_sequence[num_steps].params.update_hardmin_params.freq_mhz =
329 			(uint16_t)khz_to_mhz_ceil(new_clocks->ref_dtbclk_khz);
330 		for (i = 0; i < context->stream_count; i++) {
331 			otg_master = resource_get_otg_master_for_stream(
332 				&context->res_ctx, context->streams[i]);
333 			if (otg_master != NULL &&
334 				otg_master->stream != NULL &&
335 				dc_is_hdmi_frl_signal(otg_master->stream->signal)) {
336 				frl_present = true;
337 				break;
338 			}
339 		}
340 		if (frl_present)
341 			block_sequence[num_steps].params.update_hardmin_params.freq_mhz =
342 				(uint16_t)clk_mgr_base->bw_params->clk_table.entries[
343 					clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels - 1].dtbclk_mhz;
344 		block_sequence[num_steps].params.update_hardmin_params.response = &clk_mgr_base->clks.ref_dtbclk_khz;
345 		block_sequence[num_steps].func = CLK_MGR60_UPDATE_HARDMIN_PPCLK;
346 		num_steps++;
347 
348 		/* Update DTO in DCCG */
349 		block_sequence[num_steps].params.update_dtbclk_dto_params.context = context;
350 		block_sequence[num_steps].params.update_dtbclk_dto_params.ref_dtbclk_khz = &clk_mgr_base->clks.ref_dtbclk_khz;
351 		block_sequence[num_steps].func = CLK_MGR60_UPDATE_DTBCLK_DTO;
352 		num_steps++;
353 	}
354 
355 	if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
356 		if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
357 			dppclk_lowered = true;
358 
359 		clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
360 		clk_mgr_base->clks.actual_dppclk_khz = new_clocks->dppclk_khz;
361 
362 		update_dppclk = true;
363 	}
364 
365 	if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
366 		clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
367 
368 		if (dcn60_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DISPCLK)) {
369 			block_sequence[num_steps].params.update_hardmin_optimized_params.ppclk = PPCLK_DISPCLK;
370 			block_sequence[num_steps].params.update_hardmin_optimized_params.freq_khz = clk_mgr_base->clks.dispclk_khz;
371 			block_sequence[num_steps].params.update_hardmin_optimized_params.response = &clk_mgr_base->clks.actual_dispclk_khz;
372 			block_sequence[num_steps].func = CLK_MGR60_UPDATE_HARDMIN_PPCLK_OPTIMIZED;
373 			num_steps++;
374 		}
375 
376 		update_dispclk = true;
377 	}
378 
379 	if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
380 		if (dppclk_lowered) {
381 			/* if clock is being lowered, increase DTO before lowering refclk */
382 			block_sequence[num_steps].params.update_dppclk_dto_params.context = context;
383 			block_sequence[num_steps].params.update_dppclk_dto_params.ref_dppclk_khz = &clk_mgr_base->clks.dppclk_khz;
384 			block_sequence[num_steps].params.update_dppclk_dto_params.safe_to_lower = safe_to_lower;
385 			block_sequence[num_steps].func = CLK_MGR60_UPDATE_DPPCLK_DTO;
386 			num_steps++;
387 
388 			if (dcn60_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DPPCLK)) {
389 				block_sequence[num_steps].params.update_hardmin_optimized_params.ppclk = PPCLK_DPPCLK;
390 				block_sequence[num_steps].params.update_hardmin_optimized_params.freq_khz = clk_mgr_base->clks.dppclk_khz;
391 				block_sequence[num_steps].params.update_hardmin_optimized_params.response = &clk_mgr_base->clks.actual_dppclk_khz;
392 				block_sequence[num_steps].func = CLK_MGR60_UPDATE_HARDMIN_PPCLK_OPTIMIZED;
393 				num_steps++;
394 
395 				block_sequence[num_steps].params.update_dppclk_dto_params.context = context;
396 				block_sequence[num_steps].params.update_dppclk_dto_params.ref_dppclk_khz = &clk_mgr_base->clks.actual_dppclk_khz;
397 				block_sequence[num_steps].params.update_dppclk_dto_params.safe_to_lower = safe_to_lower;
398 				block_sequence[num_steps].func = CLK_MGR60_UPDATE_DPPCLK_DTO;
399 				num_steps++;
400 			}
401 		} else {
402 			/* if clock is being raised, increase refclk before lowering DTO */
403 			if (update_dppclk && dcn60_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DPPCLK)) {
404 				block_sequence[num_steps].params.update_hardmin_optimized_params.ppclk = PPCLK_DPPCLK;
405 				block_sequence[num_steps].params.update_hardmin_optimized_params.freq_khz = clk_mgr_base->clks.dppclk_khz;
406 				block_sequence[num_steps].params.update_hardmin_optimized_params.response = &clk_mgr_base->clks.actual_dppclk_khz;
407 				block_sequence[num_steps].func = CLK_MGR60_UPDATE_HARDMIN_PPCLK_OPTIMIZED;
408 				num_steps++;
409 			}
410 
411 			block_sequence[num_steps].params.update_dppclk_dto_params.context = context;
412 			block_sequence[num_steps].params.update_dppclk_dto_params.ref_dppclk_khz = &clk_mgr_base->clks.actual_dppclk_khz;
413 			block_sequence[num_steps].params.update_dppclk_dto_params.safe_to_lower = safe_to_lower;
414 			block_sequence[num_steps].func = CLK_MGR60_UPDATE_DPPCLK_DTO;
415 			num_steps++;
416 		}
417 	}
418 
419 	if (update_dispclk && dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
420 		/*update dmcu for wait_loop count*/
421 		block_sequence[num_steps].params.update_psr_wait_loop_params.dmcu = dmcu;
422 		block_sequence[num_steps].params.update_psr_wait_loop_params.wait = clk_mgr_base->clks.dispclk_khz / 1000 / 7;
423 		block_sequence[num_steps].func = CLK_MGR60_UPDATE_PSR_WAIT_LOOP;
424 		num_steps++;
425 	}
426 
427 	return num_steps;
428 }
429 
dcn60_get_vco_frequency_from_reg(struct clk_mgr_internal * clk_mgr)430 static uint32_t dcn60_get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
431 {
432 	(void)clk_mgr;
433 	//TODO: Get VCO frequency
434 	return 0;
435 }
436 
dcn60_are_clock_states_equal(struct dc_clocks * a,struct dc_clocks * b)437 static bool dcn60_are_clock_states_equal(struct dc_clocks *a,
438 	struct dc_clocks *b)
439 {
440 	if (a->dispclk_khz != b->dispclk_khz)
441 		return false;
442 	else if (a->dppclk_khz != b->dppclk_khz)
443 		return false;
444 	else if (a->dcfclk_khz != b->dcfclk_khz)
445 		return false;
446 	else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
447 		return false;
448 	else if (a->dramclk_khz != b->dramclk_khz)
449 		return false;
450 	else if (a->p_state_change_support != b->p_state_change_support)
451 		return false;
452 	else if (a->fclk_p_state_change_support != b->fclk_p_state_change_support)
453 		return false;
454 
455 	return true;
456 }
457 
dcn60_is_smu_present(struct clk_mgr * clk_mgr_base)458 static bool dcn60_is_smu_present(struct clk_mgr *clk_mgr_base)
459 {
460 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
461 	return clk_mgr->smu_present;
462 }
463 
dcn60_get_dtb_ref_freq_khz(struct clk_mgr * clk_mgr_base)464 static int dcn60_get_dtb_ref_freq_khz(struct clk_mgr *clk_mgr_base)
465 {
466 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
467 
468 	int dtb_ref_clk_khz = 0;
469 
470 	if (clk_mgr->smu_present && dcn60_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DTBCLK)) {
471 		/* DPM enabled, use currently set value */
472 		dtb_ref_clk_khz = clk_mgr_base->clks.ref_dtbclk_khz;
473 	} else {
474 		/* DPM disabled, so use boot snapshot */
475 		dtb_ref_clk_khz = clk_mgr_base->boot_snapshot.dtbclk;
476 	}
477 
478 	return dtb_ref_clk_khz;
479 }
480 
dcn60_get_dc_mode_limit_mhz(const DpmClock_t * dpm_clk)481 static unsigned int dcn60_get_dc_mode_limit_mhz(const DpmClock_t *dpm_clk)
482 {
483 	if (dpm_clk->NumClocks
484 			&& dpm_clk->DcMaxClock == dpm_clk->Clocks[dpm_clk->NumClocks - 1])
485 		return 0;
486 
487 	return dpm_clk->DcMaxClock;
488 }
489 
490 /**
491  * dcn60_populate_dc_mode_limit - Populate DC mode limits from DAL init table.
492  * @dc_limit: output DC mode limit to populate
493  * @init_table: DAL init table transferred from PMFW
494  *
495  * Sets the DC mode max frequency for each clock. If DcMaxClock equals the
496  * highest DPM level, the limit is set to 0 (no DC-specific cap).
497  */
dcn60_populate_dc_mode_limit(struct clk_limit_table_entry * dc_limit,const DalInitTable_t * init_table)498 static void dcn60_populate_dc_mode_limit(
499 		struct clk_limit_table_entry *dc_limit,
500 		const DalInitTable_t *init_table)
501 {
502 	dc_limit->dcfclk_mhz  = dcn60_get_dc_mode_limit_mhz(&init_table->PPClocks[PPCLK_DCFCLK]);
503 	dc_limit->socclk_mhz  = dcn60_get_dc_mode_limit_mhz(&init_table->PPClocks[PPCLK_SOCCLK]);
504 	dc_limit->dtbclk_mhz  = dcn60_get_dc_mode_limit_mhz(&init_table->PPClocks[PPCLK_DTBCLK]);
505 	dc_limit->dispclk_mhz = dcn60_get_dc_mode_limit_mhz(&init_table->PPClocks[PPCLK_DISPCLK]);
506 	dc_limit->memclk_mhz  = dcn60_get_dc_mode_limit_mhz(&init_table->PPClocks[PPCLK_UCLK]);
507 	dc_limit->fclk_mhz    = dcn60_get_dc_mode_limit_mhz(&init_table->PPClocks[PPCLK_FCLK]);
508 }
509 
510 /**
511  * dcn60_populate_clk_table - Populate clock table from DAL init table.
512  * @clk_mgr: clock manager instance
513  * @clk_table: output clock table to populate
514  * @init_table: DAL init table transferred from PMFW
515  *
516  * Reads the DPM clock levels from the PPClocks array within the DalInitTable_t
517  * populated by PMFW via TABLE_DAL_INIT transfer.
518  */
dcn60_populate_clk_table(struct clk_mgr_internal * clk_mgr,struct clk_limit_table * clk_table,const DalInitTable_t * init_table)519 static void dcn60_populate_clk_table(struct clk_mgr_internal *clk_mgr,
520 		struct clk_limit_table *clk_table,
521 		const DalInitTable_t *init_table)
522 {
523 	struct clk_limit_num_entries *num_entries = &clk_table->num_entries_per_clk;
524 	const DpmClock_t *dpm_clk;
525 	unsigned int i;
526 
527 	/* DCFCLK */
528 	dpm_clk = &init_table->PPClocks[PPCLK_DCFCLK];
529 	num_entries->num_dcfclk_levels = dpm_clk->NumClocks;
530 	for (i = 0; i < dpm_clk->NumClocks && i < NUM_CLOCK_LEVELS; i++)
531 		clk_table->entries[i].dcfclk_mhz = dpm_clk->Clocks[i];
532 
533 	/* SOCCLK */
534 	dpm_clk = &init_table->PPClocks[PPCLK_SOCCLK];
535 	num_entries->num_socclk_levels = dpm_clk->NumClocks;
536 	for (i = 0; i < dpm_clk->NumClocks && i < NUM_CLOCK_LEVELS; i++)
537 		clk_table->entries[i].socclk_mhz = dpm_clk->Clocks[i];
538 
539 	/* DTBCLK */
540 	dpm_clk = &init_table->PPClocks[PPCLK_DTBCLK];
541 	num_entries->num_dtbclk_levels = dpm_clk->NumClocks;
542 	for (i = 0; i < dpm_clk->NumClocks && i < NUM_CLOCK_LEVELS; i++)
543 		clk_table->entries[i].dtbclk_mhz = dpm_clk->Clocks[i];
544 
545 	/* DISPCLK */
546 	dpm_clk = &init_table->PPClocks[PPCLK_DISPCLK];
547 	num_entries->num_dispclk_levels = dpm_clk->NumClocks;
548 	for (i = 0; i < dpm_clk->NumClocks && i < NUM_CLOCK_LEVELS; i++)
549 		clk_table->entries[i].dispclk_mhz = dpm_clk->Clocks[i];
550 
551 	/* DPPCLK */
552 	dpm_clk = &init_table->PPClocks[PPCLK_DPPCLK];
553 	num_entries->num_dppclk_levels = dpm_clk->NumClocks;
554 	for (i = 0; i < dpm_clk->NumClocks && i < NUM_CLOCK_LEVELS; i++)
555 		clk_table->entries[i].dppclk_mhz = dpm_clk->Clocks[i];
556 
557 	/* UCLK */
558 	dpm_clk = &init_table->PPClocks[PPCLK_UCLK];
559 	num_entries->num_memclk_levels = dpm_clk->NumClocks;
560 	for (i = 0; i < dpm_clk->NumClocks && i < NUM_CLOCK_LEVELS; i++)
561 		clk_table->entries[i].memclk_mhz = dpm_clk->Clocks[i];
562 	if (num_entries->num_memclk_levels)
563 		clk_mgr->base.bw_params->max_memclk_mhz =
564 				clk_table->entries[num_entries->num_memclk_levels - 1].memclk_mhz;
565 
566 	/* FCLK */
567 	dpm_clk = &init_table->PPClocks[PPCLK_FCLK];
568 	num_entries->num_fclk_levels = dpm_clk->NumClocks;
569 	for (i = 0; i < dpm_clk->NumClocks && i < NUM_CLOCK_LEVELS; i++)
570 		clk_table->entries[i].fclk_mhz = dpm_clk->Clocks[i];
571 
572 	if (num_entries->num_memclk_levels >= num_entries->num_fclk_levels)
573 		clk_table->num_entries = num_entries->num_memclk_levels;
574 	else
575 		clk_table->num_entries = num_entries->num_fclk_levels;
576 	if (!clk_table->num_entries)
577 		clk_table->num_entries = 1;
578 }
579 
dcn60_override_bw_params(struct clk_mgr_internal * clk_mgr,struct clk_bw_params * bw_params)580 static void dcn60_override_bw_params(struct clk_mgr_internal *clk_mgr,
581 		struct clk_bw_params *bw_params)
582 {
583 	struct clk_limit_table *clk_table = &bw_params->clk_table;
584 	unsigned int i;
585 
586 	if (clk_mgr->base.ctx->dc->debug.min_disp_clk_khz) {
587 		for (i = 0; i < clk_table->num_entries_per_clk.num_dispclk_levels; i++)
588 			if (clk_table->entries[i].dispclk_mhz
589 					< (unsigned int)khz_to_mhz_ceil(clk_mgr->base.ctx->dc->debug.min_disp_clk_khz))
590 				clk_table->entries[i].dispclk_mhz
591 					= (unsigned int)khz_to_mhz_ceil(clk_mgr->base.ctx->dc->debug.min_disp_clk_khz);
592 	}
593 
594 	if (clk_mgr->base.ctx->dc->debug.min_dpp_clk_khz) {
595 		for (i = 0; i < clk_table->num_entries_per_clk.num_dppclk_levels; i++)
596 			if (clk_table->entries[i].dppclk_mhz
597 					< (unsigned int)khz_to_mhz_ceil(clk_mgr->base.ctx->dc->debug.min_dpp_clk_khz))
598 				clk_table->entries[i].dppclk_mhz
599 					= (unsigned int)khz_to_mhz_ceil(clk_mgr->base.ctx->dc->debug.min_dpp_clk_khz);
600 	}
601 
602 	if (clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch)
603 		bw_params->dc_mode_limit.dtbclk_mhz = 0;
604 
605 	bw_params->dc_mode_softmax_memclk = bw_params->dc_mode_limit.memclk_mhz;
606 }
607 
608 /**
609  * dcn60_fetch_dal_init_table - Transfer and apply the DAL init table from PMFW.
610  * @clk_mgr: clock manager instance
611  *
612  * Issues TABLE_DAL_INIT transfer, populates clock table and bounding box.
613  *
614  * Return: true on success, false if transfer failed
615  */
dcn60_populate_utm_qos_model(struct clk_mgr_internal * clk_mgr,const struct utm_qos_model ** qos_model,const DalInitTable_t * init_table)616 static void dcn60_populate_utm_qos_model(
617 		struct clk_mgr_internal *clk_mgr,
618 		const struct utm_qos_model **qos_model,
619 		const DalInitTable_t *init_table)
620 {
621 	struct dcn60_clk_mgr *dcn60_clk_mgr =
622 			container_of(clk_mgr, struct dcn60_clk_mgr, base);
623 	struct utm_qos_model *model = &dcn60_clk_mgr->utm_qos_model;
624 	struct utm_qos_model_dchub_v3 *dchub = &dcn60_clk_mgr->dchub_v3;
625 	const SocUtmTable_t *utm_table = &init_table->UtmTable;
626 	unsigned int ll, sop;
627 
628 	memset(dchub, 0, sizeof(*dchub));
629 	dchub->load_level_count = (uint8_t)utm_table->Header.LoadLevelCount;
630 	dchub->sop_count = (uint8_t)utm_table->Header.SopCount;
631 
632 	for (ll = 0; ll < dchub->load_level_count
633 			&& ll < UTM_QOS_MODEL_V3_MAX_LOAD_LEVEL_COUNT; ll++) {
634 		for (sop = 0; sop < dchub->sop_count
635 				&& sop < UTM_QOS_MODEL_V3_MAX_SOP_COUNT; sop++) {
636 			const SocUtmSopEntry_t *src = &utm_table->Sops[ll][sop];
637 			struct utm_qos_model_dchub_v3_sop_entry *dst =
638 					&dchub->sops[ll][sop];
639 
640 			dst->urgent_ramp_ps = src->UrgentRampPs;
641 			dst->t_trip_ps = src->TripPs;
642 			dst->meta_trip_to_mem_ps = src->MetaTripToMemPs;
643 			dst->max_req_latency_urg_ps = src->MaxReqLatencyUrgPs;
644 			dst->avg_req_latency_urg_ps = src->AvgReqLatencyUrgPs;
645 			dst->max_req_latency_non_urg_ps = src->MaxReqLatencyNonUrgPs;
646 			dst->avg_req_latency_non_urg_ps = src->AvgReqLatencyNonUrgPs;
647 			dst->df_response_time_ps = src->DfResponseTimePs;
648 			dst->urgent_bandwidth_KBps = src->UrgentBandwidthKBps;
649 			dst->nominal_bandwidth_KBps = src->NominalBandwidthKBps;
650 			dst->lsdma_bandwidth_KBps = src->LsdmaBandwidthKBps;
651 		}
652 	}
653 
654 	model->version = utm_qos_model_version_v3;
655 	model->dchub_v3 = dchub;
656 	*qos_model = model;
657 }
658 
dcn60_fetch_dal_init_table(struct clk_mgr_internal * clk_mgr)659 static bool dcn60_fetch_dal_init_table(struct clk_mgr_internal *clk_mgr)
660 {
661 	struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
662 	const DalInitTable_t *init_table;
663 
664 	if (!dcn60_smu_get_dal_init_table(clk_mgr, &init_table))
665 		return false;
666 
667 	clk_mgr->smu_ver = init_table->Header.SmuVersion;
668 
669 	dcn60_populate_clk_table(clk_mgr, &bw_params->clk_table, init_table);
670 	dcn60_populate_dc_mode_limit(&bw_params->dc_mode_limit, init_table);
671 
672 	bw_params->num_channels = init_table->MemoryConfig.NumUmcChannels;
673 	bw_params->dram_channel_width_bytes =
674 			clk_mgr->base.ctx->dc_bios->vram_info.dram_channel_width_bytes;
675 
676 	dcn60_populate_utm_qos_model(clk_mgr, &bw_params->utm_qos_model, init_table);
677 
678 	dcn60_override_bw_params(clk_mgr, bw_params);
679 
680 	return true;
681 }
682 
dcn60_init_clocks(struct clk_mgr * clk_mgr_base)683 void dcn60_init_clocks(struct clk_mgr *clk_mgr_base)
684 {
685 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
686 	uint32_t smu_header_ver = 0;
687 
688 	memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
689 	clk_mgr_base->clks.p_state_change_support = true;
690 	clk_mgr_base->clks.fclk_p_state_change_support = false;
691 	clk_mgr_base->force_smu_not_present = true; // temporary until SMU ready
692 	clk_mgr->smu_present = !clk_mgr_base->force_smu_not_present /* not force-disabled */
693 			&& dcn60_smu_get_msg_header_version(clk_mgr, &smu_header_ver)
694 			&& smu_header_ver != 0;
695 
696 	clk_mgr->dpm_present = clk_mgr->smu_present
697 			&& dcn60_fetch_dal_init_table(clk_mgr)
698 			&& clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels
699 			&& clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels
700 			&& clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
701 
702 	if (clk_mgr->dpm_present)
703 		clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
704 				clk_mgr_base->ctx->dc, clk_mgr_base->bw_params);
705 }
706 
count_to_khz(uint32_t count,uint32_t timer_ths,uint32_t refclk_khz)707 static inline uint32_t count_to_khz(uint32_t count, uint32_t timer_ths, uint32_t refclk_khz)
708 {
709 	if (timer_ths == 0)
710 		return 0;
711 
712 	return (uint32_t)div_u64((uint64_t)count * (uint64_t)refclk_khz, timer_ths);
713 }
714 
dcn60_dump_clk_registers_internal(struct dcn42_clk_internal * internal,struct clk_mgr * clk_mgr_base)715 static void dcn60_dump_clk_registers_internal(struct dcn42_clk_internal *internal, struct clk_mgr *clk_mgr_base)
716 {
717 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
718 
719 	// read ths
720 	REG_GET(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, &internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD);
721 
722 	// read dtbclk
723 	internal->CLK8_CLK4_CURRENT_CNT = REG_READ(CLK8_CLK4_CURRENT_CNT);
724 	internal->CLK8_CLK4_BYPASS_CNTL = REG_READ(CLK8_CLK4_BYPASS_CNTL);
725 
726 	// read dcfclk
727 	internal->CLK8_CLK0_CURRENT_CNT = REG_READ(CLK8_CLK0_CURRENT_CNT);
728 	internal->CLK8_CLK0_BYPASS_CNTL = REG_READ(CLK8_CLK0_BYPASS_CNTL);
729 
730 	// read dcf deep sleep divider
731 	internal->CLK8_CLK0_DS_CNTL = REG_READ(CLK8_CLK0_DS_CNTL);
732 	internal->CLK8_CLK3_DS_CNTL = REG_READ(CLK8_CLK3_DS_CNTL);
733 
734 	// read dppclk
735 	internal->CLK8_CLK2_CURRENT_CNT = REG_READ(CLK8_CLK2_CURRENT_CNT);
736 	internal->CLK8_CLK2_BYPASS_CNTL = REG_READ(CLK8_CLK2_BYPASS_CNTL);
737 
738 	// read dprefclk
739 	internal->CLK8_CLK3_CURRENT_CNT = REG_READ(CLK8_CLK3_CURRENT_CNT);
740 	internal->CLK8_CLK3_BYPASS_CNTL = REG_READ(CLK8_CLK3_BYPASS_CNTL);
741 
742 	// read dispclk
743 	internal->CLK8_CLK1_CURRENT_CNT = REG_READ(CLK8_CLK1_CURRENT_CNT);
744 	internal->CLK8_CLK1_BYPASS_CNTL = REG_READ(CLK8_CLK1_BYPASS_CNTL);
745 }
746 
dcn60_dump_clk_registers(struct clk_state_registers_and_bypass * regs_and_bypass,struct clk_mgr * clk_mgr_base,struct clk_log_info * log_info)747 static void dcn60_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
748 		struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
749 {
750 	(void)log_info;
751 	struct dcn42_clk_internal internal = {0};
752 	char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"};
753 	const uint32_t refclk_khz = DCN60_CLKIP_REFCLK_KHZ;
754 	uint32_t timer_ths;
755 
756 	dcn60_dump_clk_registers_internal(&internal, clk_mgr_base);
757 	regs_and_bypass->timer_threshold = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD;
758 	timer_ths = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD;
759 
760 	regs_and_bypass->dcfclk = count_to_khz(internal.CLK8_CLK0_CURRENT_CNT, timer_ths, refclk_khz);
761 	regs_and_bypass->dcf_deep_sleep_divider = internal.CLK8_CLK0_DS_CNTL / 10;
762 	regs_and_bypass->dcf_deep_sleep_allow = true;
763 	regs_and_bypass->dprefclk = count_to_khz(internal.CLK8_CLK3_CURRENT_CNT, timer_ths, refclk_khz);
764 	regs_and_bypass->dispclk = count_to_khz(internal.CLK8_CLK1_CURRENT_CNT, timer_ths, refclk_khz);
765 	regs_and_bypass->dppclk = count_to_khz(internal.CLK8_CLK2_CURRENT_CNT, timer_ths, refclk_khz);
766 	regs_and_bypass->dtbclk = count_to_khz(internal.CLK8_CLK4_CURRENT_CNT, timer_ths, refclk_khz);
767 
768 	regs_and_bypass->dispclk_bypass = get_reg_field_value(internal.CLK8_CLK0_BYPASS_CNTL, CLK8_CLK0_BYPASS_CNTL, CLK0_BYPASS_SEL);
769 	regs_and_bypass->dppclk_bypass = get_reg_field_value(internal.CLK8_CLK1_BYPASS_CNTL, CLK8_CLK1_BYPASS_CNTL, CLK1_BYPASS_SEL);
770 	regs_and_bypass->dprefclk_bypass = get_reg_field_value(internal.CLK8_CLK2_BYPASS_CNTL, CLK8_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL);
771 	regs_and_bypass->dcfclk_bypass = get_reg_field_value(internal.CLK8_CLK3_BYPASS_CNTL, CLK8_CLK3_BYPASS_CNTL, CLK3_BYPASS_SEL);
772 
773 	if (clk_mgr_base->ctx->dc->debug.pstate_enabled) {
774 		DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n");
775 
776 		DC_LOG_SMU("dcfclk,%d,%d,%d,%s\n",
777 				   regs_and_bypass->dcfclk,
778 				   regs_and_bypass->dcf_deep_sleep_divider,
779 				   regs_and_bypass->dcf_deep_sleep_allow,
780 				   bypass_clks[(int) regs_and_bypass->dcfclk_bypass]);
781 
782 		DC_LOG_SMU("dprefclk,%d,N/A,N/A,%s\n",
783 			regs_and_bypass->dprefclk,
784 			bypass_clks[(int) regs_and_bypass->dprefclk_bypass]);
785 
786 		DC_LOG_SMU("dispclk,%d,N/A,N/A,%s\n",
787 			regs_and_bypass->dispclk,
788 			bypass_clks[(int) regs_and_bypass->dispclk_bypass]);
789 
790 		//split
791 		DC_LOG_SMU("SPLIT\n");
792 
793 		// REGISTER VALUES
794 		DC_LOG_SMU("reg_name,value,clk_type\n");
795 		DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk\n",
796 				internal.CLK8_CLK3_CURRENT_CNT);
797 
798 		DC_LOG_SMU("CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider\n",
799 					internal.CLK8_CLK3_DS_CNTL);
800 
801 		DC_LOG_SMU("CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow\n",
802 					(internal.CLK8_CLK3_DS_CNTL & 0x10));
803 
804 		DC_LOG_SMU("CLK1_CLK2_CURRENT_CNT,%d,dprefclk\n",
805 					internal.CLK8_CLK2_CURRENT_CNT);
806 
807 		DC_LOG_SMU("CLK1_CLK0_CURRENT_CNT,%d,dispclk\n",
808 					internal.CLK8_CLK0_CURRENT_CNT);
809 
810 		DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk\n",
811 					internal.CLK8_CLK1_CURRENT_CNT);
812 
813 		DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass\n",
814 					internal.CLK8_CLK3_BYPASS_CNTL);
815 
816 		DC_LOG_SMU("CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass\n",
817 					internal.CLK8_CLK2_BYPASS_CNTL);
818 
819 		DC_LOG_SMU("CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass\n",
820 					internal.CLK8_CLK0_BYPASS_CNTL);
821 
822 		DC_LOG_SMU("CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass\n",
823 					internal.CLK8_CLK1_BYPASS_CNTL);
824 	}
825 }
826 
dcn60_auto_dpm_test_log(struct dc_clocks * new_clocks,struct clk_mgr_internal * clk_mgr,struct dc_state * context)827 static void dcn60_auto_dpm_test_log(
828 		struct dc_clocks *new_clocks,
829 		struct clk_mgr_internal *clk_mgr,
830 		struct dc_state *context)
831 {
832 	unsigned int mall_ss_size_bytes;
833 	int dramclk_khz_override, fclk_khz_override, num_fclk_levels;
834 	struct clk_mgr *clk_mgr_base = &clk_mgr->base;
835 
836 	struct pipe_ctx *pipe_ctx_list[MAX_PIPES];
837 	int active_pipe_count = 0;
838 
839 	for (int i = 0; i < MAX_PIPES; i++) {
840 		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
841 
842 		if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) {
843 			pipe_ctx_list[active_pipe_count] = pipe_ctx;
844 			active_pipe_count++;
845 		}
846 	}
847 
848 	msleep(5);
849 
850 	mall_ss_size_bytes = context->bw_ctx.bw.dcn.mall_ss_size_bytes;
851 
852 	struct clk_log_info log_info = {0};
853 	struct clk_state_registers_and_bypass clk_register_dump;
854 
855 	dcn60_dump_clk_registers(&clk_register_dump, clk_mgr_base, &log_info);
856 
857 	// Overrides for these clocks in case there is no p_state change support
858 	dramclk_khz_override = new_clocks->dramclk_khz;
859 	fclk_khz_override = new_clocks->fclk_khz;
860 
861 	num_fclk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_fclk_levels - 1;
862 
863 	if (!new_clocks->p_state_change_support)
864 		dramclk_khz_override = clk_mgr->base.bw_params->max_memclk_mhz * 1000;
865 
866 	if (!new_clocks->fclk_p_state_change_support)
867 		fclk_khz_override = clk_mgr->base.bw_params->clk_table.entries[num_fclk_levels].fclk_mhz * 1000;
868 
869 	////////////////////////////////////////////////////////////////////////////
870 	//	IMPORTANT:	When adding more clocks to these logs, do NOT put a newline
871 	//				anywhere other than at the very end of the string.
872 	//
873 	//	Formatting example (make sure to have " - " between each entry):
874 	//
875 	//				AutoDPMTest: clk1:%d - clk2:%d - clk3:%d - clk4:%d\n"
876 	////////////////////////////////////////////////////////////////////////////
877 	if (active_pipe_count > 0 &&
878 		new_clocks->dramclk_khz > 0 &&
879 		new_clocks->fclk_khz > 0 &&
880 		new_clocks->dcfclk_khz > 0 &&
881 		new_clocks->dppclk_khz > 0) {
882 
883 		uint32_t pix_clk_list[MAX_PIPES] = {0};
884 		int p_state_list[MAX_PIPES] = {0};
885 		int disp_src_width_list[MAX_PIPES] = {0};
886 		int disp_src_height_list[MAX_PIPES] = {0};
887 		uint64_t disp_src_refresh_list[MAX_PIPES] = {0};
888 		bool is_scaled_list[MAX_PIPES] = {0};
889 
890 		for (int i = 0; i < active_pipe_count; i++) {
891 			struct pipe_ctx *curr_pipe_ctx = pipe_ctx_list[i];
892 			uint64_t refresh_rate;
893 
894 			pix_clk_list[i] = curr_pipe_ctx->stream->timing.pix_clk_100hz;
895 			p_state_list[i] = curr_pipe_ctx->p_state_type;
896 
897 			refresh_rate = (curr_pipe_ctx->stream->timing.pix_clk_100hz * (uint64_t)100 +
898 				curr_pipe_ctx->stream->timing.v_total
899 				* (uint64_t) curr_pipe_ctx->stream->timing.h_total - (uint64_t)1);
900 			refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.v_total);
901 			refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.h_total);
902 			disp_src_refresh_list[i] = refresh_rate;
903 
904 			if (curr_pipe_ctx->plane_state) {
905 				is_scaled_list[i] = !(dcn60_check_native_scaling(curr_pipe_ctx));
906 				disp_src_width_list[i] = curr_pipe_ctx->plane_state->src_rect.width;
907 				disp_src_height_list[i] = curr_pipe_ctx->plane_state->src_rect.height;
908 			}
909 		}
910 
911 		DC_LOG_AUTO_DPM_TEST("AutoDPMTest: dramclk:%d - fclk:%d - "
912 			"dcfclk:%d - dppclk:%d - dispclk_hw:%d - "
913 			"dppclk_hw:%d - dprefclk_hw:%d - dcfclk_hw:%d - "
914 			"dtbclk_hw:%d - fclk_hw:%d - pix_clk_0:%d - pix_clk_1:%d - "
915 			"pix_clk_2:%d - pix_clk_3:%d - mall_ss_size:%d - p_state_type_0:%d - "
916 			"p_state_type_1:%d - p_state_type_2:%d - p_state_type_3:%d - "
917 			"pix_width_0:%d - pix_height_0:%d - refresh_rate_0:%lld - is_scaled_0:%d - "
918 			"pix_width_1:%d - pix_height_1:%d - refresh_rate_1:%lld - is_scaled_1:%d - "
919 			"pix_width_2:%d - pix_height_2:%d - refresh_rate_2:%lld - is_scaled_2:%d - "
920 			"pix_width_3:%d - pix_height_3:%d - refresh_rate_3:%lld - is_scaled_3:%d - LOG_END\n",
921 			dramclk_khz_override,
922 			fclk_khz_override,
923 			new_clocks->dcfclk_khz,
924 			new_clocks->dppclk_khz,
925 			clk_register_dump.dispclk,
926 			clk_register_dump.dppclk,
927 			clk_register_dump.dprefclk,
928 			clk_register_dump.dcfclk,
929 			clk_register_dump.dtbclk,
930 			clk_register_dump.fclk,
931 			pix_clk_list[0], pix_clk_list[1], pix_clk_list[3], pix_clk_list[2],
932 			mall_ss_size_bytes,
933 			p_state_list[0], p_state_list[1], p_state_list[2], p_state_list[3],
934 			disp_src_width_list[0], disp_src_height_list[0], disp_src_refresh_list[0], is_scaled_list[0],
935 			disp_src_width_list[1], disp_src_height_list[1], disp_src_refresh_list[1], is_scaled_list[1],
936 			disp_src_width_list[2], disp_src_height_list[2], disp_src_refresh_list[2], is_scaled_list[2],
937 			disp_src_width_list[3], disp_src_height_list[3], disp_src_refresh_list[3], is_scaled_list[3]);
938 	}
939 }
940 
dcn60_execute_block_sequence(struct clk_mgr * clk_mgr_base,unsigned int num_steps)941 static void dcn60_execute_block_sequence(struct clk_mgr *clk_mgr_base, unsigned int num_steps)
942 {
943 	struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
944 	struct dcn60_clk_mgr *clk_mgr60 = TO_DCN60_CLK_MGR(clk_mgr_internal);
945 
946 	unsigned int i;
947 	union dcn60_clk_mgr_block_sequence_params *params;
948 
949 	/* execute sequence */
950 	for (i = 0; i < num_steps; i++) {
951 		params = &clk_mgr60->block_sequence[i].params;
952 
953 		switch (clk_mgr60->block_sequence[i].func) {
954 		case CLK_MGR60_UPDATE_HARDMIN_PPCLK:
955 			if (params->update_hardmin_params.response)
956 				*params->update_hardmin_params.response = dcn60_smu_set_hard_min_by_freq(
957 						clk_mgr_internal,
958 						params->update_hardmin_params.ppclk,
959 						params->update_hardmin_params.freq_mhz);
960 			else
961 				dcn60_smu_set_hard_min_by_freq(clk_mgr_internal,
962 						params->update_hardmin_params.ppclk,
963 						params->update_hardmin_params.freq_mhz);
964 			break;
965 		case CLK_MGR60_UPDATE_HARDMIN_PPCLK_OPTIMIZED:
966 			if (params->update_hardmin_optimized_params.response)
967 				*params->update_hardmin_optimized_params.response =
968 					dcn60_set_hard_min_by_freq_optimized(
969 						clk_mgr_internal,
970 						params->update_hardmin_optimized_params.ppclk,
971 						params->update_hardmin_optimized_params.freq_khz);
972 			else
973 				dcn60_set_hard_min_by_freq_optimized(clk_mgr_internal,
974 						params->update_hardmin_optimized_params.ppclk,
975 						params->update_hardmin_optimized_params.freq_khz);
976 			break;
977 		case CLK_MGR60_UPDATE_DEEP_SLEEP_DCFCLK:
978 			dcn60_smu_set_min_deep_sleep_dcfclk(
979 					clk_mgr_internal,
980 					params->update_deep_sleep_dcfclk_params.freq_mhz);
981 			break;
982 		case CLK_MGR60_INDICATE_PSTATE_STATUS:
983 			dcn60_smu_indicate_pstate_status(
984 					clk_mgr_internal,
985 					params->indicate_pstate_status_params.allow_fclk,
986 					params->indicate_pstate_status_params.allow_uclk,
987 					params->indicate_pstate_status_params.wait_resp,
988 					params->indicate_pstate_status_params.drr_enable,
989 					params->indicate_pstate_status_params.alt_ch_enable);
990 			break;
991 		case CLK_MGR60_UPDATE_DPPCLK_DTO:
992 			dcn60_update_clocks_update_dpp_dto(
993 					clk_mgr_internal,
994 					params->update_dppclk_dto_params.context,
995 					params->update_dppclk_dto_params.safe_to_lower,
996 					*params->update_dppclk_dto_params.ref_dppclk_khz);
997 			break;
998 		case CLK_MGR60_UPDATE_DTBCLK_DTO:
999 			dcn60_update_clocks_update_dtb_dto(
1000 					clk_mgr_internal,
1001 					params->update_dtbclk_dto_params.context,
1002 					*params->update_dtbclk_dto_params.ref_dtbclk_khz);
1003 			break;
1004 		case CLK_MGR60_UPDATE_PSR_WAIT_LOOP:
1005 			params->update_psr_wait_loop_params.dmcu->funcs->set_psr_wait_loop(
1006 					params->update_psr_wait_loop_params.dmcu,
1007 					params->update_psr_wait_loop_params.wait);
1008 			break;
1009 		case CLK_MGR60_UPDATE_STUTTER_EFFICIENCY:
1010 			dcn60_smu_set_stutter_efficiency(
1011 					clk_mgr_internal,
1012 					params->update_stutter_efficiency_params.base_efficiency,
1013 					params->update_stutter_efficiency_params.low_power_efficiency);
1014 			break;
1015 		case CLK_MGR60_UPDATE_UTM_QOS_REQUEST:
1016 			dcn60_smu_update_utm_qos_request(clk_mgr_internal,
1017 					params->update_utm_qos_request_params.utm_latency_ub_index,
1018 					params->update_utm_qos_request_params.utm_nominal_bandwidth_lb_KBps,
1019 					params->update_utm_qos_request_params.utm_urgent_bandwidth_lb_KBps,
1020 					params->update_utm_qos_request_params.utm_lsdma_bandwidth_lb_KBps);
1021 			break;
1022 		default:
1023 			/* this should never happen */
1024 			BREAK_TO_DEBUGGER();
1025 			break;
1026 		}
1027 	}
1028 }
1029 
1030 /**
1031  * dcn60_make_bandwidth_clocks_update_action - Determine what clock and p-state
1032  * updates are needed by comparing new_clocks against current clk_mgr state.
1033  * @action: output action struct, zeroed and populated by this function
1034  * @clk_mgr_base: current clock manager state (read-only)
1035  * @context: dc state with active plane information
1036  * @new_clocks: requested clock values to compare against current state
1037  * @safe_to_lower: whether clocks are allowed to decrease
1038  */
dcn60_make_bandwidth_clocks_update_action(struct dcn60_bandwidth_clocks_update_action * action,struct clk_mgr * clk_mgr_base,struct dc_state * context,struct dc_clocks * new_clocks,bool safe_to_lower)1039 static void dcn60_make_bandwidth_clocks_update_action(
1040 		struct dcn60_bandwidth_clocks_update_action *action,
1041 		struct clk_mgr *clk_mgr_base,
1042 		struct dc_state *context,
1043 		struct dc_clocks *new_clocks,
1044 		bool safe_to_lower)
1045 {
1046 	struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1047 	int total_plane_count = clk_mgr_helper_get_active_plane_cnt(
1048 			clk_mgr_base->ctx->dc, context);
1049 	bool dcfclk_dpm_enabled = dcn60_is_ppclk_dpm_enabled(clk_mgr_internal,
1050 			PPCLK_DCFCLK);
1051 	bool uclk_pstate_supported = new_clocks->p_state_change_support
1052 			|| (total_plane_count == 0);
1053 
1054 	bool fclk_pstate_supported = new_clocks->fclk_p_state_change_support
1055 			|| (total_plane_count == 0);
1056 
1057 	memset(action, 0, sizeof(*action));
1058 	/* clock actions */
1059 	if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz,
1060 			clk_mgr_base->clks.dcfclk_khz)) {
1061 		action->dcfclk.update = true;
1062 		action->dcfclk.send_message = dcfclk_dpm_enabled;
1063 	}
1064 
1065 	if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz,
1066 			clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
1067 		action->deep_sleep_dcfclk.update = true;
1068 		action->deep_sleep_dcfclk.send_message = dcfclk_dpm_enabled;
1069 	}
1070 
1071 	if (should_set_clock(safe_to_lower, new_clocks->socclk_khz,
1072 			clk_mgr_base->clks.socclk_khz)) {
1073 		action->socclk.update = true;
1074 		/* state tracking only — no SMU hardmin message for socclk */
1075 		action->socclk.send_message = false;
1076 	}
1077 
1078 	if (clk_mgr_base->clks.stutter_efficiency.base_efficiency
1079 				!= new_clocks->stutter_efficiency.base_efficiency
1080 			|| clk_mgr_base->clks.stutter_efficiency.low_power_efficiency
1081 				!= new_clocks->stutter_efficiency.low_power_efficiency) {
1082 		action->stutter.update = true;
1083 		action->stutter.send_message = true;
1084 	}
1085 
1086 	if (new_clocks->utm_nominal_bandwidth_lb_KBps != clk_mgr_base->clks.utm_nominal_bandwidth_lb_KBps
1087 			|| new_clocks->utm_urgent_bandwidth_lb_KBps != clk_mgr_base->clks.utm_urgent_bandwidth_lb_KBps
1088 			|| new_clocks->utm_lsdma_bandwidth_lb_KBps != clk_mgr_base->clks.utm_lsdma_bandwidth_lb_KBps
1089 			|| new_clocks->utm_latency_ub_index != clk_mgr_base->clks.utm_latency_ub_index) {
1090 		action->utm_qos.update = true;
1091 		action->utm_qos.send_message = true;
1092 	}
1093 
1094 	/* p-state actions */
1095 	if (should_update_pstate_support(safe_to_lower,
1096 			uclk_pstate_supported,
1097 			clk_mgr_base->clks.p_state_change_support)) {
1098 		action->uclk_pstate.enable = uclk_pstate_supported;
1099 		action->uclk_pstate.disable = !uclk_pstate_supported;
1100 		action->uclk_pstate.send_message =
1101 				dcn60_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK);
1102 	}
1103 
1104 	if (should_update_pstate_support(safe_to_lower,
1105 			fclk_pstate_supported,
1106 			clk_mgr_base->clks.fclk_p_state_change_support)) {
1107 		action->fclk_pstate.enable = fclk_pstate_supported;
1108 		action->fclk_pstate.disable = !fclk_pstate_supported;
1109 		action->fclk_pstate.send_message =
1110 				dcn60_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK);
1111 	}
1112 
1113 	if (new_clocks->fw_based_mclk_switching
1114 			!= clk_mgr_base->clks.fw_based_mclk_switching) {
1115 		action->fams.enable = new_clocks->fw_based_mclk_switching;
1116 		action->fams.disable = !new_clocks->fw_based_mclk_switching
1117 				&& safe_to_lower;
1118 		action->fams.send_message = action->fams.enable
1119 				|| action->fams.disable;
1120 	}
1121 
1122 	if (new_clocks->alt_ch_pstate_switch != clk_mgr_base->clks.alt_ch_pstate_switch) {
1123 		action->alt_ch.enable = new_clocks->alt_ch_pstate_switch;
1124 		action->alt_ch.disable = !new_clocks->alt_ch_pstate_switch
1125 				&& safe_to_lower;
1126 		action->alt_ch.send_message = action->alt_ch.enable
1127 				|| action->alt_ch.disable;
1128 	}
1129 }
1130 
1131 /**
1132  * dcn60_build_bandwidth_clocks_block_sequence_with_action - Build the SMU
1133  * message sequence from the action struct without mutating clk_mgr state.
1134  * @block_sequence: output array of block sequence steps
1135  * @action: action struct populated by dcn60_make_bandwidth_clocks_update_action
1136  * @clk_mgr_base: current clock manager state (read-only, used for original values)
1137  * @new_clocks: requested clock values for message parameters
1138  *
1139  * Return: number of steps written to block_sequence
1140  */
dcn60_build_bandwidth_clocks_block_sequence_with_action(struct dcn60_clk_mgr_block_sequence * block_sequence,struct dcn60_bandwidth_clocks_update_action * action,struct clk_mgr * clk_mgr_base,struct dc_clocks * new_clocks)1141 static unsigned int dcn60_build_bandwidth_clocks_block_sequence_with_action(
1142 		struct dcn60_clk_mgr_block_sequence *block_sequence,
1143 		struct dcn60_bandwidth_clocks_update_action *action,
1144 		struct clk_mgr *clk_mgr_base,
1145 		struct dc_clocks *new_clocks)
1146 {
1147 	unsigned int num_steps = 0;
1148 
1149 	/* CLK_MGR60_INDICATE_PSTATE_STATUS — enable */
1150 	if ((action->uclk_pstate.enable && action->uclk_pstate.send_message)
1151 			|| (action->fclk_pstate.enable && action->fclk_pstate.send_message)
1152 			|| (action->fams.enable && action->fams.send_message)
1153 			|| (action->alt_ch.enable && action->alt_ch.send_message)) {
1154 		block_sequence[num_steps].params.indicate_pstate_status_params.allow_uclk =
1155 				action->uclk_pstate.enable
1156 				|| clk_mgr_base->clks.p_state_change_support;
1157 		block_sequence[num_steps].params.indicate_pstate_status_params.allow_fclk =
1158 				action->fclk_pstate.enable
1159 				|| clk_mgr_base->clks.fclk_p_state_change_support;
1160 		block_sequence[num_steps].params.indicate_pstate_status_params.drr_enable =
1161 				action->fams.enable
1162 				|| clk_mgr_base->clks.fw_based_mclk_switching;
1163 		block_sequence[num_steps].params.indicate_pstate_status_params.wait_resp =
1164 				action->fams.enable;
1165 		block_sequence[num_steps].params.indicate_pstate_status_params.alt_ch_enable =
1166 				action->alt_ch.enable
1167 				|| clk_mgr_base->clks.alt_ch_pstate_switch;
1168 		block_sequence[num_steps].func = CLK_MGR60_INDICATE_PSTATE_STATUS;
1169 		num_steps++;
1170 	}
1171 
1172 	/* CLK_MGR60_UPDATE_HARDMIN_PPCLK — DCFCLK */
1173 	if (action->dcfclk.send_message) {
1174 		block_sequence[num_steps].params.update_hardmin_params.ppclk = PPCLK_DCFCLK;
1175 		block_sequence[num_steps].params.update_hardmin_params.freq_mhz =
1176 			(uint16_t)khz_to_mhz_ceil(new_clocks->dcfclk_khz);
1177 		block_sequence[num_steps].params.update_hardmin_params.response = NULL;
1178 		block_sequence[num_steps].func = CLK_MGR60_UPDATE_HARDMIN_PPCLK;
1179 		num_steps++;
1180 	}
1181 
1182 	/* CLK_MGR60_UPDATE_DEEP_SLEEP_DCFCLK */
1183 	if (action->deep_sleep_dcfclk.send_message) {
1184 		block_sequence[num_steps].params.update_deep_sleep_dcfclk_params.freq_mhz =
1185 			(uint16_t)khz_to_mhz_ceil(new_clocks->dcfclk_deep_sleep_khz);
1186 		block_sequence[num_steps].func = CLK_MGR60_UPDATE_DEEP_SLEEP_DCFCLK;
1187 		num_steps++;
1188 	}
1189 
1190 	/* CLK_MGR60_UPDATE_UTM_QOS_REQUEST */
1191 	if (action->utm_qos.send_message) {
1192 		block_sequence[num_steps].params.update_utm_qos_request_params.utm_nominal_bandwidth_lb_KBps =
1193 				new_clocks->utm_nominal_bandwidth_lb_KBps;
1194 		block_sequence[num_steps].params.update_utm_qos_request_params.utm_urgent_bandwidth_lb_KBps =
1195 				new_clocks->utm_urgent_bandwidth_lb_KBps;
1196 		block_sequence[num_steps].params.update_utm_qos_request_params.utm_lsdma_bandwidth_lb_KBps =
1197 				new_clocks->utm_lsdma_bandwidth_lb_KBps;
1198 		block_sequence[num_steps].params.update_utm_qos_request_params.utm_latency_ub_index =
1199 				new_clocks->utm_latency_ub_index;
1200 		block_sequence[num_steps].func = CLK_MGR60_UPDATE_UTM_QOS_REQUEST;
1201 		num_steps++;
1202 	}
1203 
1204 	/* CLK_MGR60_INDICATE_PSTATE_STATUS — disable */
1205 	if ((action->uclk_pstate.disable && action->uclk_pstate.send_message)
1206 			|| (action->fclk_pstate.disable && action->fclk_pstate.send_message)
1207 			|| (action->fams.disable && action->fams.send_message)
1208 			|| (action->alt_ch.disable && action->alt_ch.send_message)) {
1209 		block_sequence[num_steps].params.indicate_pstate_status_params.allow_uclk =
1210 				!action->uclk_pstate.disable
1211 				&& (action->uclk_pstate.enable
1212 						|| clk_mgr_base->clks.p_state_change_support);
1213 		block_sequence[num_steps].params.indicate_pstate_status_params.allow_fclk =
1214 				!action->fclk_pstate.disable
1215 				&& (action->fclk_pstate.enable
1216 						|| clk_mgr_base->clks.fclk_p_state_change_support);
1217 		block_sequence[num_steps].params.indicate_pstate_status_params.drr_enable =
1218 				!action->fams.disable
1219 				&& (action->fams.enable
1220 						|| clk_mgr_base->clks.fw_based_mclk_switching);
1221 		block_sequence[num_steps].params.indicate_pstate_status_params.alt_ch_enable =
1222 				!action->alt_ch.disable
1223 				&& (action->alt_ch.enable
1224 						|| clk_mgr_base->clks.alt_ch_pstate_switch);
1225 		block_sequence[num_steps].params.indicate_pstate_status_params.wait_resp = false;
1226 		block_sequence[num_steps].func = CLK_MGR60_INDICATE_PSTATE_STATUS;
1227 		num_steps++;
1228 	}
1229 
1230 	/* CLK_MGR60_UPDATE_STUTTER_EFFICIENCY */
1231 	if (action->stutter.send_message) {
1232 		block_sequence[num_steps].params.update_stutter_efficiency_params.base_efficiency =
1233 			new_clocks->stutter_efficiency.base_efficiency;
1234 		block_sequence[num_steps].params.update_stutter_efficiency_params.low_power_efficiency =
1235 			new_clocks->stutter_efficiency.low_power_efficiency;
1236 		block_sequence[num_steps].func = CLK_MGR60_UPDATE_STUTTER_EFFICIENCY;
1237 		num_steps++;
1238 	}
1239 
1240 	return num_steps;
1241 }
1242 
1243 /**
1244  * dcn60_update_bandwidth_clocks_state_with_action - Apply all pending clock
1245  * and p-state changes to clk_mgr state based on the action struct.
1246  * @clk_mgr_base: clock manager state to update
1247  * @action: action struct populated by dcn60_make_bandwidth_clocks_update_action
1248  * @new_clocks: new clock values to copy into clk_mgr state
1249  */
dcn60_update_bandwidth_clocks_state_with_action(struct clk_mgr * clk_mgr_base,struct dcn60_bandwidth_clocks_update_action * action,struct dc_clocks * new_clocks)1250 static void dcn60_update_bandwidth_clocks_state_with_action(
1251 		struct clk_mgr *clk_mgr_base,
1252 		struct dcn60_bandwidth_clocks_update_action *action,
1253 		struct dc_clocks *new_clocks)
1254 {
1255 	if (action->uclk_pstate.enable)
1256 		clk_mgr_base->clks.p_state_change_support = true;
1257 	if (action->uclk_pstate.disable)
1258 		clk_mgr_base->clks.p_state_change_support = false;
1259 	if (action->fclk_pstate.enable)
1260 		clk_mgr_base->clks.fclk_p_state_change_support = true;
1261 	if (action->fclk_pstate.disable)
1262 		clk_mgr_base->clks.fclk_p_state_change_support = false;
1263 	if (action->fams.enable)
1264 		clk_mgr_base->clks.fw_based_mclk_switching = true;
1265 	if (action->fams.disable)
1266 		clk_mgr_base->clks.fw_based_mclk_switching = false;
1267 	if (action->alt_ch.enable)
1268 		clk_mgr_base->clks.alt_ch_pstate_switch = true;
1269 	if (action->alt_ch.disable)
1270 		clk_mgr_base->clks.alt_ch_pstate_switch = false;
1271 	if (action->dcfclk.update)
1272 		clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
1273 	if (action->deep_sleep_dcfclk.update)
1274 		clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
1275 	if (action->socclk.update)
1276 		clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
1277 	if (action->utm_qos.update) {
1278 		clk_mgr_base->clks.utm_nominal_bandwidth_lb_KBps = new_clocks->utm_nominal_bandwidth_lb_KBps;
1279 		clk_mgr_base->clks.utm_urgent_bandwidth_lb_KBps  = new_clocks->utm_urgent_bandwidth_lb_KBps;
1280 		clk_mgr_base->clks.utm_lsdma_bandwidth_lb_KBps   = new_clocks->utm_lsdma_bandwidth_lb_KBps;
1281 		clk_mgr_base->clks.utm_latency_ub_index          = new_clocks->utm_latency_ub_index;
1282 	}
1283 	if (action->stutter.update) {
1284 		clk_mgr_base->clks.stutter_efficiency.base_efficiency =
1285 				new_clocks->stutter_efficiency.base_efficiency;
1286 		clk_mgr_base->clks.stutter_efficiency.low_power_efficiency =
1287 				new_clocks->stutter_efficiency.low_power_efficiency;
1288 	}
1289 }
1290 
1291 /**
1292  * dcn60_build_update_bandwidth_clocks_sequence - Build block sequence for
1293  * bandwidth clock updates and apply new clock values to clk_mgr state.
1294  * @clk_mgr_base: clock manager to update
1295  * @context: dc state with active plane information
1296  * @new_clocks: requested clock values from bandwidth calculation
1297  * @safe_to_lower: whether clocks are allowed to decrease
1298  *
1299  * Return: number of block sequence steps to execute
1300  */
dcn60_build_update_bandwidth_clocks_sequence(struct clk_mgr * clk_mgr_base,struct dc_state * context,struct dc_clocks * new_clocks,bool safe_to_lower)1301 static unsigned int dcn60_build_update_bandwidth_clocks_sequence(
1302 		struct clk_mgr *clk_mgr_base,
1303 		struct dc_state *context,
1304 		struct dc_clocks *new_clocks,
1305 		bool safe_to_lower)
1306 {
1307 	struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1308 	struct dcn60_clk_mgr *clk_mgr60 = TO_DCN60_CLK_MGR(clk_mgr_internal);
1309 	struct dcn60_bandwidth_clocks_update_action action = {0};
1310 	unsigned int num_steps;
1311 
1312 	dcn60_make_bandwidth_clocks_update_action(&action,
1313 			clk_mgr_base, context, new_clocks, safe_to_lower);
1314 
1315 	num_steps = dcn60_build_bandwidth_clocks_block_sequence_with_action(
1316 			clk_mgr60->block_sequence, &action,
1317 			clk_mgr_base, new_clocks);
1318 
1319 	dcn60_update_bandwidth_clocks_state_with_action(clk_mgr_base, &action, new_clocks);
1320 
1321 	return num_steps;
1322 }
1323 
dcn60_update_clocks(struct clk_mgr * clk_mgr_base,struct dc_state * context,bool safe_to_lower)1324 static void dcn60_update_clocks(struct clk_mgr *clk_mgr_base,
1325 		struct dc_state *context,
1326 		bool safe_to_lower)
1327 {
1328 	struct dc *dc = clk_mgr_base->ctx->dc;
1329 	unsigned int num_steps = 0;
1330 
1331 	/* TODO: mutates context bw clocks. This is a side effect */
1332 	if (dc->debug.force_min_dcfclk_mhz > 0) {
1333 		int force_min_dcfclk_khz =
1334 				dc->debug.force_min_dcfclk_mhz * 1000;
1335 
1336 		if (context->bw_ctx.bw.dcn.clk.dcfclk_khz < force_min_dcfclk_khz)
1337 			context->bw_ctx.bw.dcn.clk.dcfclk_khz = force_min_dcfclk_khz;
1338 	}
1339 
1340 	/* build bandwidth related clocks update sequence */
1341 	num_steps = dcn60_build_update_bandwidth_clocks_sequence(clk_mgr_base,
1342 			context,
1343 			&context->bw_ctx.bw.dcn.clk,
1344 			safe_to_lower);
1345 
1346 	/* execute sequence */
1347 	dcn60_execute_block_sequence(clk_mgr_base,	num_steps);
1348 
1349 	/* build display related clocks update sequence */
1350 	num_steps = dcn60_build_update_display_clocks_sequence(clk_mgr_base,
1351 			context,
1352 			&context->bw_ctx.bw.dcn.clk,
1353 			safe_to_lower,
1354 			0);
1355 
1356 	/* execute sequence */
1357 	dcn60_execute_block_sequence(clk_mgr_base,	num_steps);
1358 
1359 	if (dc->config.enable_auto_dpm_test_logs)
1360 		dcn60_auto_dpm_test_log(&context->bw_ctx.bw.dcn.clk, TO_CLK_MGR_INTERNAL(clk_mgr_base), context);
1361 
1362 }
1363 
dcn60_clock_read_ss_info(struct clk_mgr_internal * clk_mgr)1364 static void dcn60_clock_read_ss_info(struct clk_mgr_internal *clk_mgr)
1365 {
1366 	struct dc_bios *bp = clk_mgr->base.ctx->dc_bios;
1367 	int ss_info_num = bp->funcs->get_ss_entry_number(
1368 			bp, AS_SIGNAL_TYPE_GPU_PLL);
1369 
1370 	if (ss_info_num) {
1371 		struct spread_spectrum_info info = { { 0 } };
1372 		enum bp_result result = bp->funcs->get_spread_spectrum_info(
1373 				bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info);
1374 
1375 		/* SSInfo.spreadSpectrumPercentage !=0 would be sign
1376 		 * that SS is enabled
1377 		 */
1378 		if (result == BP_RESULT_OK &&
1379 				info.spread_spectrum_percentage != 0) {
1380 			clk_mgr->ss_on_dprefclk = true;
1381 			clk_mgr->dprefclk_ss_divider = info.spread_percentage_divider;
1382 
1383 			if (info.type.CENTER_MODE == 0) {
1384 				/* Currently for DP Reference clock we
1385 				 * need only SS percentage for
1386 				 * downspread
1387 				 */
1388 				clk_mgr->dprefclk_ss_percentage =
1389 						info.spread_spectrum_percentage;
1390 			}
1391 		}
1392 	}
1393 }
1394 
1395 /* Set min memclk to minimum, either constrained by the current mode or DPM0 */
dcn60_set_hard_min_memclk(struct clk_mgr * clk_mgr_base,bool current_mode)1396 static void dcn60_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current_mode)
1397 {
1398 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1399 	const struct dc *dc = clk_mgr->base.ctx->dc;
1400 	struct dc_state *context = dc->current_state;
1401 	struct dc_clocks new_clocks;
1402 	int num_steps;
1403 
1404 	if (!clk_mgr->smu_present || !dcn60_is_ppclk_dpm_enabled(clk_mgr, PPCLK_UCLK))
1405 		return;
1406 
1407 	/* build clock update */
1408 	memcpy(&new_clocks, &clk_mgr_base->clks, sizeof(struct dc_clocks));
1409 
1410 	if (current_mode) {
1411 		new_clocks.dramclk_khz = context->bw_ctx.bw.dcn.clk.dramclk_khz;
1412 		new_clocks.idle_dramclk_khz = context->bw_ctx.bw.dcn.clk.idle_dramclk_khz;
1413 		new_clocks.p_state_change_support = context->bw_ctx.bw.dcn.clk.p_state_change_support;
1414 	} else {
1415 		new_clocks.dramclk_khz = clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz * 1000;
1416 		new_clocks.idle_dramclk_khz = new_clocks.dramclk_khz;
1417 		new_clocks.p_state_change_support = true;
1418 	}
1419 
1420 	num_steps = dcn60_build_update_bandwidth_clocks_sequence(clk_mgr_base,
1421 			context,
1422 			&new_clocks,
1423 			true);
1424 
1425 	/* execute sequence */
1426 	dcn60_execute_block_sequence(clk_mgr_base,	num_steps);
1427 }
1428 
dcn60_get_memclk_states_from_smu(struct clk_mgr * clk_mgr_base)1429 static void dcn60_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
1430 {
1431 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1432 
1433 	if (!clk_mgr->smu_present)
1434 		return;
1435 
1436 	if (!dcn60_fetch_dal_init_table(clk_mgr))
1437 		return;
1438 
1439 	clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
1440 			clk_mgr_base->ctx->dc, clk_mgr_base->bw_params);
1441 }
1442 
dcn60_enable_pme_wa(struct clk_mgr * clk_mgr_base)1443 static void dcn60_enable_pme_wa(struct clk_mgr *clk_mgr_base)
1444 {
1445 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1446 
1447 	if (!clk_mgr->smu_present)
1448 		return;
1449 
1450 	dcn60_smu_set_pme_workaround(clk_mgr);
1451 }
1452 
dcn60_get_max_active_utm_bandwidth_kbps(struct clk_mgr * clk_mgr_base)1453 static unsigned int dcn60_get_max_active_utm_bandwidth_kbps(
1454 		struct clk_mgr *clk_mgr_base)
1455 {
1456 	const struct utm_qos_model *qos_model = clk_mgr_base->bw_params->utm_qos_model;
1457 	const struct utm_qos_model_dchub_v3 *dchub;
1458 	unsigned int highest;
1459 
1460 	if (!qos_model
1461 			|| qos_model->version != utm_qos_model_version_v3
1462 			|| !qos_model->dchub_v3)
1463 		return 0;
1464 
1465 	dchub = qos_model->dchub_v3;
1466 	highest = dchub->sop_count - 1;
1467 
1468 	return dchub->sops[UTM_QOS_MODEL_V3_LOAD_LEVEL_ACTIVE_ALTERNATE_PSTATE]
1469 			[highest].nominal_bandwidth_KBps;
1470 }
1471 
dcn60_get_requested_memory_qos(struct clk_mgr * clk_mgr_base,struct dc_requested_memory_qos * qos)1472 static void dcn60_get_requested_memory_qos(
1473 		struct clk_mgr *clk_mgr_base,
1474 		struct dc_requested_memory_qos *qos)
1475 {
1476 	const struct dc_clocks *clks = &clk_mgr_base->clks;
1477 
1478 	qos->bandwidth_lb_in_mbps = clks->utm_nominal_bandwidth_lb_KBps / 1000;
1479 	qos->calculated_avg_bw_in_mbps = clks->required_avg_active_bandwidth_KBps / 1000;
1480 	qos->max_latency_ub_in_ns = clks->utm_nominal_max_latency_ub_ns;
1481 	qos->avg_latency_ub_in_ns = clks->utm_nominal_avg_latency_ub_ns;
1482 	qos->max_bw_budget_in_mbps = dcn60_get_max_active_utm_bandwidth_kbps(clk_mgr_base) / 1000;
1483 }
1484 
dcn60_override_memory_bandwidth_request(struct clk_mgr * clk_mgr_base,unsigned int bw_kbps)1485 static unsigned int dcn60_override_memory_bandwidth_request(
1486 		struct clk_mgr *clk_mgr_base,
1487 		unsigned int bw_kbps)
1488 {
1489 	const struct dc *dc = clk_mgr_base->ctx->dc;
1490 	struct dc_clocks new_clocks;
1491 	unsigned int max_bw_kbps;
1492 	unsigned int capped_bw_kbps;
1493 	int num_steps;
1494 
1495 	memcpy(&new_clocks, &clk_mgr_base->clks, sizeof(struct dc_clocks));
1496 
1497 	if (bw_kbps == 0) {
1498 		new_clocks.utm_nominal_bandwidth_lb_KBps = 0;
1499 		new_clocks.utm_urgent_bandwidth_lb_KBps  = 0;
1500 	} else {
1501 		max_bw_kbps    = dcn60_get_max_active_utm_bandwidth_kbps(clk_mgr_base);
1502 		capped_bw_kbps = (bw_kbps > max_bw_kbps) ? max_bw_kbps : bw_kbps;
1503 
1504 		new_clocks.utm_nominal_bandwidth_lb_KBps = capped_bw_kbps;
1505 		if (new_clocks.utm_urgent_bandwidth_lb_KBps < capped_bw_kbps)
1506 			new_clocks.utm_urgent_bandwidth_lb_KBps = capped_bw_kbps;
1507 	}
1508 
1509 	num_steps = dcn60_build_update_bandwidth_clocks_sequence(clk_mgr_base,
1510 			dc->current_state, &new_clocks, true);
1511 
1512 	dcn60_execute_block_sequence(clk_mgr_base, num_steps);
1513 
1514 	return new_clocks.utm_nominal_bandwidth_lb_KBps;
1515 }
1516 
dcn60_set_idle_power_optimizations(struct clk_mgr * clk_mgr_base,bool enable)1517 static void dcn60_set_idle_power_optimizations(struct clk_mgr *clk_mgr_base, bool enable)
1518 {
1519 	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1520 
1521 	if (!clk_mgr->smu_present)
1522 		return;
1523 
1524 	dcn60_smu_set_display_idle_optimization(clk_mgr, enable);
1525 }
1526 
1527 /*
1528  * Build-for-BLS functions.
1529  * These build both bandwidth and display clock sequences into the clk_mgr's
1530  * internal block sequence array, then add a single CLK_MGR_UPDATE_CLOCKS step
1531  * to the HWSS block sequence whose executor will call
1532  * execute_clk_mgr_block_sequence to dispatch all accumulated steps.
1533  */
dcn60_build_clock_update_for_bls(struct clk_mgr * clk_mgr_base,struct dc_state * context,bool safe_to_lower,struct block_sequence_state * seq_state)1534 void dcn60_build_clock_update_for_bls(
1535 		struct clk_mgr *clk_mgr_base,
1536 		struct dc_state *context,
1537 		bool safe_to_lower,
1538 		struct block_sequence_state *seq_state)
1539 {
1540 	struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1541 	struct dcn60_clk_mgr *clk_mgr60 = TO_DCN60_CLK_MGR(clk_mgr_internal);
1542 	unsigned int num_bw_steps;
1543 	unsigned int total_steps;
1544 
1545 	/* Build bandwidth clocks sequence starting at index 0 */
1546 	num_bw_steps = dcn60_build_update_bandwidth_clocks_sequence(clk_mgr_base,
1547 			context,
1548 			&context->bw_ctx.bw.dcn.clk,
1549 			safe_to_lower);
1550 
1551 	/* Build display clocks sequence appended after bandwidth steps */
1552 	total_steps = dcn60_build_update_display_clocks_sequence(clk_mgr_base,
1553 			context,
1554 			&context->bw_ctx.bw.dcn.clk,
1555 			safe_to_lower,
1556 			num_bw_steps);
1557 
1558 	/* Store total step count for the executor */
1559 	clk_mgr60->num_block_sequence_steps = total_steps;
1560 
1561 	/* Add single HWSS step that will execute all clk_mgr block sequence steps */
1562 	hwss_add_clk_mgr_update_clocks(seq_state, clk_mgr_base);
1563 }
1564 
dcn60_execute_clk_mgr_block_sequence_bls(struct clk_mgr * clk_mgr_base)1565 static void dcn60_execute_clk_mgr_block_sequence_bls(struct clk_mgr *clk_mgr_base)
1566 {
1567 	struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
1568 	struct dcn60_clk_mgr *clk_mgr60 = TO_DCN60_CLK_MGR(clk_mgr_internal);
1569 
1570 	dcn60_execute_block_sequence(clk_mgr_base, clk_mgr60->num_block_sequence_steps);
1571 }
1572 
1573 static struct clk_mgr_funcs dcn60_funcs = {
1574 		.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
1575 		.get_dtb_ref_clk_frequency = dcn60_get_dtb_ref_freq_khz,
1576 		.update_clocks = dcn60_update_clocks,
1577 		.dump_clk_registers = dcn60_dump_clk_registers,
1578 		.init_clocks = dcn60_init_clocks,
1579 		.set_hard_min_memclk = dcn60_set_hard_min_memclk,
1580 		.get_memclk_states_from_smu = dcn60_get_memclk_states_from_smu,
1581 		.are_clock_states_equal = dcn60_are_clock_states_equal,
1582 		.enable_pme_wa = dcn60_enable_pme_wa,
1583 		.is_smu_present = dcn60_is_smu_present,
1584 		.get_dispclk_from_dentist = NULL,
1585 		.get_max_clock_khz = dcn401_get_max_clock_khz,
1586 		.override_memory_bandwidth_request = dcn60_override_memory_bandwidth_request,
1587 		.get_requested_memory_qos = dcn60_get_requested_memory_qos,
1588 		.set_idle_power_optimizations = dcn60_set_idle_power_optimizations,
1589 		.build_clock_update_for_bls = dcn60_build_clock_update_for_bls,
1590 		.execute_clk_mgr_block_sequence = dcn60_execute_clk_mgr_block_sequence_bls,
1591 };
1592 
dcn60_clk_mgr_construct(struct dc_context * ctx,struct dccg * dccg)1593 struct clk_mgr_internal *dcn60_clk_mgr_construct(
1594 		struct dc_context *ctx,
1595 		struct dccg *dccg)
1596 {
1597 	struct clk_log_info log_info = {0};
1598 	struct dcn60_clk_mgr *clk_mgr60 = kzalloc_obj(struct dcn60_clk_mgr);
1599 	struct clk_mgr_internal *clk_mgr;
1600 
1601 	if (!clk_mgr60)
1602 		return NULL;
1603 
1604 	clk_mgr = &clk_mgr60->base;
1605 	clk_mgr->base.ctx = ctx;
1606 	clk_mgr->base.funcs = &dcn60_funcs;
1607 	clk_mgr->regs = &clk_mgr_regs_dcn60;
1608 	clk_mgr->clk_mgr_shift = &clk_mgr_shift_dcn60;
1609 	clk_mgr->clk_mgr_mask = &clk_mgr_mask_dcn60;
1610 
1611 	clk_mgr->dccg = dccg;
1612 	clk_mgr->dfs_bypass_disp_clk = 0;
1613 
1614 	clk_mgr->dprefclk_ss_percentage = 0;
1615 	clk_mgr->dprefclk_ss_divider = 1000;
1616 	clk_mgr->ss_on_dprefclk = false;
1617 	clk_mgr->dfs_ref_freq_khz = 100000;
1618 
1619 	/* Changed from DCN3.2_clock_frequency doc to match
1620 	 * dcn60_dump_clk_registers from 4 * dentist_vco_freq_khz /
1621 	 * dprefclk DID divider
1622 	 */
1623 	clk_mgr->base.dprefclk_khz = 720000;
1624 
1625 		/* integer part is now VCO frequency in kHz */
1626 		clk_mgr->base.dentist_vco_freq_khz = dcn60_get_vco_frequency_from_reg(clk_mgr);
1627 
1628 		/* in case we don't get a value from the register, use default */
1629 		if (clk_mgr->base.dentist_vco_freq_khz == 0)
1630 			clk_mgr->base.dentist_vco_freq_khz = 4500000;
1631 
1632 		dcn60_dump_clk_registers(&clk_mgr->base.boot_snapshot, &clk_mgr->base, &log_info);
1633 
1634 		if (ctx->dc->debug.disable_dtb_ref_clk_switch &&
1635 				clk_mgr->base.clks.ref_dtbclk_khz != clk_mgr->base.boot_snapshot.dtbclk) {
1636 			clk_mgr->base.clks.ref_dtbclk_khz = clk_mgr->base.boot_snapshot.dtbclk;
1637 		}
1638 
1639 		if (clk_mgr->base.boot_snapshot.dprefclk != 0)
1640 			clk_mgr->base.dprefclk_khz = clk_mgr->base.boot_snapshot.dprefclk;
1641 		dcn60_clock_read_ss_info(clk_mgr);
1642 
1643 	clk_mgr->dfs_bypass_enabled = false;
1644 
1645 	clk_mgr->smu_present = false;
1646 
1647 	clk_mgr->base.bw_params = kzalloc_obj(*clk_mgr->base.bw_params);
1648 	if (!clk_mgr->base.bw_params)
1649 		goto fail;
1650 
1651 	clk_mgr->dal_init_table = dm_helpers_allocate_gpu_mem(clk_mgr->base.ctx,
1652 			DC_MEM_ALLOC_TYPE_GART, sizeof(DalInitTable_t),
1653 			&clk_mgr->dal_init_table_addr);
1654 	if (!clk_mgr->dal_init_table)
1655 		goto fail;
1656 
1657 	return &clk_mgr60->base;
1658 
1659 fail:
1660 	BREAK_TO_DEBUGGER();
1661 	dcn60_clk_mgr_destroy(clk_mgr);
1662 	kfree(clk_mgr60);
1663 	return NULL;
1664 }
1665 
dcn60_clk_mgr_destroy(struct clk_mgr_internal * clk_mgr)1666 void dcn60_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr)
1667 {
1668 	kfree(clk_mgr->base.bw_params);
1669 
1670 	if (clk_mgr->dal_init_table)
1671 		dm_helpers_free_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART,
1672 				(void *)clk_mgr->dal_init_table);
1673 }
1674