1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Copyright 2023 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  */
24 
25 #include "reg_helper.h"
26 #include "core_types.h"
27 #include "dcn35_dccg.h"
28 
29 #define TO_DCN_DCCG(dccg)\
30 	container_of(dccg, struct dcn_dccg, base)
31 
32 #define REG(reg) \
33 	(dccg_dcn->regs->reg)
34 
35 #undef FN
36 #define FN(reg_name, field_name) \
37 	dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
38 
39 #define CTX \
40 	dccg_dcn->base.ctx
41 #define DC_LOGGER \
42 	dccg->ctx->logger
43 
dcn35_set_dppclk_enable(struct dccg * dccg,uint32_t dpp_inst,uint32_t enable)44 static void dcn35_set_dppclk_enable(struct dccg *dccg,
45 				 uint32_t dpp_inst, uint32_t enable)
46 {
47 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
48 
49 	switch (dpp_inst) {
50 	case 0:
51 		REG_UPDATE(DPPCLK_CTRL, DPPCLK0_EN, enable);
52 		break;
53 	case 1:
54 		REG_UPDATE(DPPCLK_CTRL, DPPCLK1_EN, enable);
55 		break;
56 	case 2:
57 		REG_UPDATE(DPPCLK_CTRL, DPPCLK2_EN, enable);
58 		break;
59 	case 3:
60 		REG_UPDATE(DPPCLK_CTRL, DPPCLK3_EN, enable);
61 		break;
62 	default:
63 		break;
64 	}
65 
66 }
67 
dccg35_update_dpp_dto(struct dccg * dccg,int dpp_inst,int req_dppclk)68 static void dccg35_update_dpp_dto(struct dccg *dccg, int dpp_inst,
69 				  int req_dppclk)
70 {
71 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
72 
73 	if (dccg->dpp_clock_gated[dpp_inst]) {
74 		/*
75 		 * Do not update the DPPCLK DTO if the clock is stopped.
76 		 */
77 		return;
78 	}
79 
80 	if (dccg->ref_dppclk && req_dppclk) {
81 		int ref_dppclk = dccg->ref_dppclk;
82 		int modulo, phase;
83 
84 		// phase / modulo = dpp pipe clk / dpp global clk
85 		modulo = 0xff;   // use FF at the end
86 		phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
87 
88 		if (phase > 0xff) {
89 			ASSERT(false);
90 			phase = 0xff;
91 		}
92 
93 		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
94 				DPPCLK0_DTO_PHASE, phase,
95 				DPPCLK0_DTO_MODULO, modulo);
96 
97 		dcn35_set_dppclk_enable(dccg, dpp_inst, true);
98 	} else
99 		dcn35_set_dppclk_enable(dccg, dpp_inst, false);
100 	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
101 }
102 
dccg35_get_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,enum pixel_rate_div * k1,enum pixel_rate_div * k2)103 static void dccg35_get_pixel_rate_div(
104 		struct dccg *dccg,
105 		uint32_t otg_inst,
106 		enum pixel_rate_div *k1,
107 		enum pixel_rate_div *k2)
108 {
109 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
110 	uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
111 
112 	*k1 = PIXEL_RATE_DIV_NA;
113 	*k2 = PIXEL_RATE_DIV_NA;
114 
115 	switch (otg_inst) {
116 	case 0:
117 		REG_GET_2(OTG_PIXEL_RATE_DIV,
118 			OTG0_PIXEL_RATE_DIVK1, &val_k1,
119 			OTG0_PIXEL_RATE_DIVK2, &val_k2);
120 		break;
121 	case 1:
122 		REG_GET_2(OTG_PIXEL_RATE_DIV,
123 			OTG1_PIXEL_RATE_DIVK1, &val_k1,
124 			OTG1_PIXEL_RATE_DIVK2, &val_k2);
125 		break;
126 	case 2:
127 		REG_GET_2(OTG_PIXEL_RATE_DIV,
128 			OTG2_PIXEL_RATE_DIVK1, &val_k1,
129 			OTG2_PIXEL_RATE_DIVK2, &val_k2);
130 		break;
131 	case 3:
132 		REG_GET_2(OTG_PIXEL_RATE_DIV,
133 			OTG3_PIXEL_RATE_DIVK1, &val_k1,
134 			OTG3_PIXEL_RATE_DIVK2, &val_k2);
135 		break;
136 	default:
137 		BREAK_TO_DEBUGGER();
138 		return;
139 	}
140 
141 	*k1 = (enum pixel_rate_div)val_k1;
142 	*k2 = (enum pixel_rate_div)val_k2;
143 }
144 
dccg35_set_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,enum pixel_rate_div k1,enum pixel_rate_div k2)145 static void dccg35_set_pixel_rate_div(
146 		struct dccg *dccg,
147 		uint32_t otg_inst,
148 		enum pixel_rate_div k1,
149 		enum pixel_rate_div k2)
150 {
151 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
152 	enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
153 
154 	// Don't program 0xF into the register field. Not valid since
155 	// K1 / K2 field is only 1 / 2 bits wide
156 	if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) {
157 		BREAK_TO_DEBUGGER();
158 		return;
159 	}
160 
161 	dccg35_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
162 	if (k1 == cur_k1 && k2 == cur_k2)
163 		return;
164 
165 	switch (otg_inst) {
166 	case 0:
167 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
168 				OTG0_PIXEL_RATE_DIVK1, k1,
169 				OTG0_PIXEL_RATE_DIVK2, k2);
170 		break;
171 	case 1:
172 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
173 				OTG1_PIXEL_RATE_DIVK1, k1,
174 				OTG1_PIXEL_RATE_DIVK2, k2);
175 		break;
176 	case 2:
177 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
178 				OTG2_PIXEL_RATE_DIVK1, k1,
179 				OTG2_PIXEL_RATE_DIVK2, k2);
180 		break;
181 	case 3:
182 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
183 				OTG3_PIXEL_RATE_DIVK1, k1,
184 				OTG3_PIXEL_RATE_DIVK2, k2);
185 		break;
186 	default:
187 		BREAK_TO_DEBUGGER();
188 		return;
189 	}
190 }
191 
dccg35_set_dtbclk_p_src(struct dccg * dccg,enum streamclk_source src,uint32_t otg_inst)192 static void dccg35_set_dtbclk_p_src(
193 		struct dccg *dccg,
194 		enum streamclk_source src,
195 		uint32_t otg_inst)
196 {
197 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
198 
199 	uint32_t p_src_sel = 0; /* selects dprefclk */
200 	if (src == DTBCLK0)
201 		p_src_sel = 2;  /* selects dtbclk0 */
202 
203 	switch (otg_inst) {
204 	case 0:
205 		if (src == REFCLK)
206 			REG_UPDATE(DTBCLK_P_CNTL,
207 					DTBCLK_P0_EN, 0);
208 		else
209 			REG_UPDATE_2(DTBCLK_P_CNTL,
210 					DTBCLK_P0_SRC_SEL, p_src_sel,
211 					DTBCLK_P0_EN, 1);
212 		break;
213 	case 1:
214 		if (src == REFCLK)
215 			REG_UPDATE(DTBCLK_P_CNTL,
216 					DTBCLK_P1_EN, 0);
217 		else
218 			REG_UPDATE_2(DTBCLK_P_CNTL,
219 					DTBCLK_P1_SRC_SEL, p_src_sel,
220 					DTBCLK_P1_EN, 1);
221 		break;
222 	case 2:
223 		if (src == REFCLK)
224 			REG_UPDATE(DTBCLK_P_CNTL,
225 					DTBCLK_P2_EN, 0);
226 		else
227 			REG_UPDATE_2(DTBCLK_P_CNTL,
228 					DTBCLK_P2_SRC_SEL, p_src_sel,
229 					DTBCLK_P2_EN, 1);
230 		break;
231 	case 3:
232 		if (src == REFCLK)
233 			REG_UPDATE(DTBCLK_P_CNTL,
234 					DTBCLK_P3_EN, 0);
235 		else
236 			REG_UPDATE_2(DTBCLK_P_CNTL,
237 					DTBCLK_P3_SRC_SEL, p_src_sel,
238 					DTBCLK_P3_EN, 1);
239 		break;
240 	default:
241 		BREAK_TO_DEBUGGER();
242 		return;
243 	}
244 
245 }
246 
247 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
dccg35_set_dtbclk_dto(struct dccg * dccg,const struct dtbclk_dto_params * params)248 static void dccg35_set_dtbclk_dto(
249 		struct dccg *dccg,
250 		const struct dtbclk_dto_params *params)
251 {
252 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
253 	/* DTO Output Rate / Pixel Rate = 1/4 */
254 	int req_dtbclk_khz = params->pixclk_khz / 4;
255 
256 	if (params->ref_dtbclk_khz && req_dtbclk_khz) {
257 		uint32_t modulo, phase;
258 
259 		switch (params->otg_inst) {
260 		case 0:
261 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 1);
262 			break;
263 		case 1:
264 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 1);
265 			break;
266 		case 2:
267 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 1);
268 			break;
269 		case 3:
270 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 1);
271 			break;
272 		}
273 
274 		// phase / modulo = dtbclk / dtbclk ref
275 		modulo = params->ref_dtbclk_khz * 1000;
276 		phase = req_dtbclk_khz * 1000;
277 
278 		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
279 		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
280 
281 		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
282 				DTBCLK_DTO_ENABLE[params->otg_inst], 1);
283 
284 		REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
285 				DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
286 				1, 100);
287 
288 		/* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */
289 		dccg35_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);
290 
291 		/* The recommended programming sequence to enable DTBCLK DTO to generate
292 		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
293 		 * be set only after DTO is enabled
294 		 */
295 		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
296 				PIPE_DTO_SRC_SEL[params->otg_inst], 2);
297 	} else {
298 		switch (params->otg_inst) {
299 		case 0:
300 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 0);
301 			break;
302 		case 1:
303 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 0);
304 			break;
305 		case 2:
306 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 0);
307 			break;
308 		case 3:
309 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 0);
310 			break;
311 		}
312 
313 		REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
314 				DTBCLK_DTO_ENABLE[params->otg_inst], 0,
315 				PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);
316 
317 		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
318 		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
319 	}
320 }
321 
dccg35_set_dpstreamclk(struct dccg * dccg,enum streamclk_source src,int otg_inst,int dp_hpo_inst)322 static void dccg35_set_dpstreamclk(
323 		struct dccg *dccg,
324 		enum streamclk_source src,
325 		int otg_inst,
326 		int dp_hpo_inst)
327 {
328 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
329 
330 	/* set the dtbclk_p source */
331 	dccg35_set_dtbclk_p_src(dccg, src, otg_inst);
332 
333 	/* enabled to select one of the DTBCLKs for pipe */
334 	switch (dp_hpo_inst) {
335 	case 0:
336 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
337 				DPSTREAMCLK0_EN,
338 				(src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst);
339 		break;
340 	case 1:
341 		REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,
342 				(src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst);
343 		break;
344 	case 2:
345 		REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,
346 				(src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst);
347 		break;
348 	case 3:
349 		REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,
350 				(src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst);
351 		break;
352 	default:
353 		BREAK_TO_DEBUGGER();
354 		return;
355 	}
356 }
357 
dccg35_set_physymclk_root_clock_gating(struct dccg * dccg,int phy_inst,bool enable)358 static void dccg35_set_physymclk_root_clock_gating(
359 		struct dccg *dccg,
360 		int phy_inst,
361 		bool enable)
362 {
363 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
364 
365 	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
366 		return;
367 
368 	switch (phy_inst) {
369 	case 0:
370 		REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
371 				PHYASYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
372 		break;
373 	case 1:
374 		REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
375 				PHYBSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
376 		break;
377 	case 2:
378 		REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
379 				PHYCSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
380 		break;
381 	case 3:
382 		REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
383 				PHYDSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
384 		break;
385 	case 4:
386 		REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
387 				PHYESYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0);
388 		break;
389 	default:
390 		BREAK_TO_DEBUGGER();
391 		return;
392 	}
393 }
394 
dccg35_set_physymclk(struct dccg * dccg,int phy_inst,enum physymclk_clock_source clk_src,bool force_enable)395 static void dccg35_set_physymclk(
396 		struct dccg *dccg,
397 		int phy_inst,
398 		enum physymclk_clock_source clk_src,
399 		bool force_enable)
400 {
401 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
402 
403 	/* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
404 	switch (phy_inst) {
405 	case 0:
406 		if (force_enable) {
407 			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
408 					PHYASYMCLK_EN, 1,
409 					PHYASYMCLK_SRC_SEL, clk_src);
410 		} else {
411 			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
412 					PHYASYMCLK_EN, 0,
413 					PHYASYMCLK_SRC_SEL, 0);
414 		}
415 		break;
416 	case 1:
417 		if (force_enable) {
418 			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
419 					PHYBSYMCLK_EN, 1,
420 					PHYBSYMCLK_SRC_SEL, clk_src);
421 		} else {
422 			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
423 					PHYBSYMCLK_EN, 0,
424 					PHYBSYMCLK_SRC_SEL, 0);
425 		}
426 		break;
427 	case 2:
428 		if (force_enable) {
429 			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
430 					PHYCSYMCLK_EN, 1,
431 					PHYCSYMCLK_SRC_SEL, clk_src);
432 		} else {
433 			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
434 					PHYCSYMCLK_EN, 0,
435 					PHYCSYMCLK_SRC_SEL, 0);
436 		}
437 		break;
438 	case 3:
439 		if (force_enable) {
440 			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
441 					PHYDSYMCLK_EN, 1,
442 					PHYDSYMCLK_SRC_SEL, clk_src);
443 		} else {
444 			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
445 					PHYDSYMCLK_EN, 0,
446 					PHYDSYMCLK_SRC_SEL, 0);
447 		}
448 		break;
449 	case 4:
450 		if (force_enable) {
451 			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
452 					PHYESYMCLK_EN, 1,
453 					PHYESYMCLK_SRC_SEL, clk_src);
454 		} else {
455 			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
456 					PHYESYMCLK_EN, 0,
457 					PHYESYMCLK_SRC_SEL, 0);
458 		}
459 		break;
460 	default:
461 		BREAK_TO_DEBUGGER();
462 		return;
463 	}
464 }
465 
dccg35_set_valid_pixel_rate(struct dccg * dccg,int ref_dtbclk_khz,int otg_inst,int pixclk_khz)466 static void dccg35_set_valid_pixel_rate(
467 		struct dccg *dccg,
468 		int ref_dtbclk_khz,
469 		int otg_inst,
470 		int pixclk_khz)
471 {
472 	struct dtbclk_dto_params dto_params = {0};
473 
474 	dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
475 	dto_params.otg_inst = otg_inst;
476 	dto_params.pixclk_khz = pixclk_khz;
477 	dto_params.is_hdmi = true;
478 
479 	dccg35_set_dtbclk_dto(dccg, &dto_params);
480 }
481 
dccg35_dpp_root_clock_control(struct dccg * dccg,unsigned int dpp_inst,bool clock_on)482 static void dccg35_dpp_root_clock_control(
483 		struct dccg *dccg,
484 		unsigned int dpp_inst,
485 		bool clock_on)
486 {
487 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
488 
489 	if (dccg->dpp_clock_gated[dpp_inst] == clock_on)
490 		return;
491 
492 	if (clock_on) {
493 		/* turn off the DTO and leave phase/modulo at max */
494 		dcn35_set_dppclk_enable(dccg, dpp_inst, 0);
495 		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
496 			  DPPCLK0_DTO_PHASE, 0xFF,
497 			  DPPCLK0_DTO_MODULO, 0xFF);
498 	} else {
499 		dcn35_set_dppclk_enable(dccg, dpp_inst, 1);
500 		/* turn on the DTO to generate a 0hz clock */
501 		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
502 			  DPPCLK0_DTO_PHASE, 0,
503 			  DPPCLK0_DTO_MODULO, 1);
504 	}
505 
506 	dccg->dpp_clock_gated[dpp_inst] = !clock_on;
507 }
508 
dccg35_disable_symclk32_se(struct dccg * dccg,int hpo_se_inst)509 static void dccg35_disable_symclk32_se(
510 		struct dccg *dccg,
511 		int hpo_se_inst)
512 {
513 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
514 
515 	/* set refclk as the source for symclk32_se */
516 	switch (hpo_se_inst) {
517 	case 0:
518 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
519 				SYMCLK32_SE0_SRC_SEL, 0,
520 				SYMCLK32_SE0_EN, 0);
521 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) {
522 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
523 					SYMCLK32_SE0_GATE_DISABLE, 0);
524 //			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
525 //					SYMCLK32_ROOT_SE0_GATE_DISABLE, 0);
526 		}
527 		break;
528 	case 1:
529 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
530 				SYMCLK32_SE1_SRC_SEL, 0,
531 				SYMCLK32_SE1_EN, 0);
532 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) {
533 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
534 					SYMCLK32_SE1_GATE_DISABLE, 0);
535 //			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
536 //					SYMCLK32_ROOT_SE1_GATE_DISABLE, 0);
537 		}
538 		break;
539 	case 2:
540 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
541 				SYMCLK32_SE2_SRC_SEL, 0,
542 				SYMCLK32_SE2_EN, 0);
543 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) {
544 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
545 					SYMCLK32_SE2_GATE_DISABLE, 0);
546 //			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
547 //					SYMCLK32_ROOT_SE2_GATE_DISABLE, 0);
548 		}
549 		break;
550 	case 3:
551 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
552 				SYMCLK32_SE3_SRC_SEL, 0,
553 				SYMCLK32_SE3_EN, 0);
554 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) {
555 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
556 					SYMCLK32_SE3_GATE_DISABLE, 0);
557 //			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
558 //					SYMCLK32_ROOT_SE3_GATE_DISABLE, 0);
559 		}
560 		break;
561 	default:
562 		BREAK_TO_DEBUGGER();
563 		return;
564 	}
565 }
566 
dccg35_init(struct dccg * dccg)567 void dccg35_init(struct dccg *dccg)
568 {
569 	int otg_inst;
570 	/* Set HPO stream encoder to use refclk to avoid case where PHY is
571 	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
572 	 * will cause DCN to hang.
573 	 */
574 	for (otg_inst = 0; otg_inst < 4; otg_inst++)
575 		dccg35_disable_symclk32_se(dccg, otg_inst);
576 
577 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
578 		for (otg_inst = 0; otg_inst < 2; otg_inst++)
579 			dccg31_disable_symclk32_le(dccg, otg_inst);
580 
581 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
582 		for (otg_inst = 0; otg_inst < 4; otg_inst++)
583 			dccg314_set_dpstreamclk(dccg, REFCLK, otg_inst,
584 						otg_inst);
585 
586 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
587 		for (otg_inst = 0; otg_inst < 5; otg_inst++)
588 			dccg35_set_physymclk_root_clock_gating(dccg, otg_inst,
589 					false);
590 /*
591 	dccg35_enable_global_fgcg_rep(
592 		dccg, dccg->ctx->dc->debug.enable_fine_grain_clock_gating.bits
593 			      .dccg_global_fgcg_rep);*/
594 }
595 
dccg35_enable_global_fgcg_rep(struct dccg * dccg,bool value)596 void dccg35_enable_global_fgcg_rep(struct dccg *dccg, bool value)
597 {
598 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
599 
600 	REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value);
601 }
602 
dccg35_enable_dscclk(struct dccg * dccg,int inst)603 static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
604 {
605 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
606 
607 	//Disable DTO
608 	switch (inst) {
609 	case 0:
610 		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
611 				DSCCLK0_DTO_PHASE, 0,
612 				DSCCLK0_DTO_MODULO, 0);
613 		REG_UPDATE(DSCCLK_DTO_CTRL,	DSCCLK0_EN, 1);
614 		break;
615 	case 1:
616 		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
617 				DSCCLK1_DTO_PHASE, 0,
618 				DSCCLK1_DTO_MODULO, 0);
619 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1);
620 		break;
621 	case 2:
622 		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
623 				DSCCLK2_DTO_PHASE, 0,
624 				DSCCLK2_DTO_MODULO, 0);
625 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1);
626 		break;
627 	case 3:
628 		REG_UPDATE_2(DSCCLK3_DTO_PARAM,
629 				DSCCLK3_DTO_PHASE, 0,
630 				DSCCLK3_DTO_MODULO, 0);
631 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1);
632 		break;
633 	default:
634 		BREAK_TO_DEBUGGER();
635 		return;
636 	}
637 }
638 
dccg35_disable_dscclk(struct dccg * dccg,int inst)639 static void dccg35_disable_dscclk(struct dccg *dccg,
640 				int inst)
641 {
642 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
643 
644 	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
645 		return;
646 
647 	switch (inst) {
648 	case 0:
649 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 0);
650 		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
651 				DSCCLK0_DTO_PHASE, 0,
652 				DSCCLK0_DTO_MODULO, 1);
653 		break;
654 	case 1:
655 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0);
656 		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
657 				DSCCLK1_DTO_PHASE, 0,
658 				DSCCLK1_DTO_MODULO, 1);
659 		break;
660 	case 2:
661 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0);
662 		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
663 				DSCCLK2_DTO_PHASE, 0,
664 				DSCCLK2_DTO_MODULO, 1);
665 		break;
666 	case 3:
667 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0);
668 		REG_UPDATE_2(DSCCLK3_DTO_PARAM,
669 				DSCCLK3_DTO_PHASE, 0,
670 				DSCCLK3_DTO_MODULO, 1);
671 		break;
672 	default:
673 		return;
674 	}
675 }
676 
dccg35_enable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)677 static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
678 {
679 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
680 
681 	switch (link_enc_inst) {
682 	case 0:
683 		REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
684 				SYMCLKA_CLOCK_ENABLE, 1);
685 		break;
686 	case 1:
687 		REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
688 				SYMCLKB_CLOCK_ENABLE, 1);
689 		break;
690 	case 2:
691 		REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
692 				SYMCLKC_CLOCK_ENABLE, 1);
693 		break;
694 	case 3:
695 		REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
696 				SYMCLKD_CLOCK_ENABLE, 1);
697 		break;
698 	case 4:
699 		REG_UPDATE(SYMCLKE_CLOCK_ENABLE,
700 				SYMCLKE_CLOCK_ENABLE, 1);
701 		break;
702 	}
703 
704 	switch (stream_enc_inst) {
705 	case 0:
706 		REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
707 				SYMCLKA_FE_EN, 1,
708 				SYMCLKA_FE_SRC_SEL, link_enc_inst);
709 		break;
710 	case 1:
711 		REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
712 				SYMCLKB_FE_EN, 1,
713 				SYMCLKB_FE_SRC_SEL, link_enc_inst);
714 		break;
715 	case 2:
716 		REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
717 				SYMCLKC_FE_EN, 1,
718 				SYMCLKC_FE_SRC_SEL, link_enc_inst);
719 		break;
720 	case 3:
721 		REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
722 				SYMCLKD_FE_EN, 1,
723 				SYMCLKD_FE_SRC_SEL, link_enc_inst);
724 		break;
725 	case 4:
726 		REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
727 				SYMCLKE_FE_EN, 1,
728 				SYMCLKE_FE_SRC_SEL, link_enc_inst);
729 		break;
730 	}
731 }
732 
733 /*get other front end connected to this backend*/
dccg35_get_other_enabled_symclk_fe(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)734 static uint8_t dccg35_get_other_enabled_symclk_fe(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
735 {
736 	uint8_t num_enabled_symclk_fe = 0;
737 	uint32_t be_clk_en = 0, fe_clk_en[5] = {0}, be_clk_sel[5] = {0};
738 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
739 
740 	switch (link_enc_inst) {
741 	case 0:
742 		REG_GET_3(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, &be_clk_en,
743 				SYMCLKA_FE_EN, &fe_clk_en[0],
744 				SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
745 				break;
746 	case 1:
747 		REG_GET_3(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, &be_clk_en,
748 				SYMCLKB_FE_EN, &fe_clk_en[1],
749 				SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
750 				break;
751 	case 2:
752 			REG_GET_3(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, &be_clk_en,
753 				SYMCLKC_FE_EN, &fe_clk_en[2],
754 				SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
755 				break;
756 	case 3:
757 			REG_GET_3(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, &be_clk_en,
758 				SYMCLKD_FE_EN, &fe_clk_en[3],
759 				SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
760 				break;
761 	case 4:
762 			REG_GET_3(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, &be_clk_en,
763 				SYMCLKE_FE_EN, &fe_clk_en[4],
764 				SYMCLKE_FE_SRC_SEL, &be_clk_sel[4]);
765 				break;
766 	}
767 	if (be_clk_en) {
768 	/* for DPMST, this backend could be used by multiple front end.
769 	only disable the backend if this stream_enc_ins is the last active stream enc connected to this back_end*/
770 		uint8_t i;
771 		for (i = 0; i != link_enc_inst && i < sizeof(fe_clk_en); i++) {
772 			if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
773 				num_enabled_symclk_fe++;
774 		}
775 	}
776 	return num_enabled_symclk_fe;
777 }
778 
dccg35_disable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)779 static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
780 {
781 	uint8_t num_enabled_symclk_fe = 0;
782 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
783 
784 	switch (stream_enc_inst) {
785 	case 0:
786 		REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
787 				SYMCLKA_FE_EN, 0,
788 				SYMCLKA_FE_SRC_SEL, 0);
789 		break;
790 	case 1:
791 		REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
792 				SYMCLKB_FE_EN, 0,
793 				SYMCLKB_FE_SRC_SEL, 0);
794 		break;
795 	case 2:
796 		REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
797 				SYMCLKC_FE_EN, 0,
798 				SYMCLKC_FE_SRC_SEL, 0);
799 		break;
800 	case 3:
801 		REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
802 				SYMCLKD_FE_EN, 0,
803 				SYMCLKD_FE_SRC_SEL, 0);
804 		break;
805 	case 4:
806 		REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
807 				SYMCLKE_FE_EN, 0,
808 				SYMCLKE_FE_SRC_SEL, 0);
809 		break;
810 	}
811 
812 	/*check other enabled symclk fe */
813 	num_enabled_symclk_fe = dccg35_get_other_enabled_symclk_fe(dccg, stream_enc_inst, link_enc_inst);
814 	/*only turn off backend clk if other front end attachecd to this backend are all off,
815 	 for mst, only turn off the backend if this is the last front end*/
816 	if (num_enabled_symclk_fe == 0) {
817 		switch (link_enc_inst) {
818 		case 0:
819 			REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
820 					SYMCLKA_CLOCK_ENABLE, 0);
821 			break;
822 		case 1:
823 			REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
824 					SYMCLKB_CLOCK_ENABLE, 0);
825 			break;
826 		case 2:
827 			REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
828 					SYMCLKC_CLOCK_ENABLE, 0);
829 			break;
830 		case 3:
831 			REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
832 					SYMCLKD_CLOCK_ENABLE, 0);
833 			break;
834 		case 4:
835 			REG_UPDATE(SYMCLKE_CLOCK_ENABLE,
836 					SYMCLKE_CLOCK_ENABLE, 0);
837 			break;
838 		}
839 	}
840 }
841 
842 static const struct dccg_funcs dccg35_funcs = {
843 	.update_dpp_dto = dccg35_update_dpp_dto,
844 	.dpp_root_clock_control = dccg35_dpp_root_clock_control,
845 	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
846 	.dccg_init = dccg35_init,
847 	.set_dpstreamclk = dccg35_set_dpstreamclk,
848 	.enable_symclk32_se = dccg31_enable_symclk32_se,
849 	.disable_symclk32_se = dccg35_disable_symclk32_se,
850 	.enable_symclk32_le = dccg31_enable_symclk32_le,
851 	.disable_symclk32_le = dccg31_disable_symclk32_le,
852 	.set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating,
853 	.set_physymclk = dccg35_set_physymclk,
854 	.set_physymclk_root_clock_gating = dccg35_set_physymclk_root_clock_gating,
855 	.set_dtbclk_dto = dccg35_set_dtbclk_dto,
856 	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
857 	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
858 	.otg_add_pixel = dccg31_otg_add_pixel,
859 	.otg_drop_pixel = dccg31_otg_drop_pixel,
860 	.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
861 	.disable_dsc = dccg35_disable_dscclk,
862 	.enable_dsc = dccg35_enable_dscclk,
863 	.set_pixel_rate_div = dccg35_set_pixel_rate_div,
864 	.set_valid_pixel_rate = dccg35_set_valid_pixel_rate,
865 	.enable_symclk_se = dccg35_enable_symclk_se,
866 	.disable_symclk_se = dccg35_disable_symclk_se,
867 	.set_dtbclk_p_src = dccg35_set_dtbclk_p_src,
868 };
869 
dccg35_create(struct dc_context * ctx,const struct dccg_registers * regs,const struct dccg_shift * dccg_shift,const struct dccg_mask * dccg_mask)870 struct dccg *dccg35_create(
871 	struct dc_context *ctx,
872 	const struct dccg_registers *regs,
873 	const struct dccg_shift *dccg_shift,
874 	const struct dccg_mask *dccg_mask)
875 {
876 	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
877 	struct dccg *base;
878 
879 	if (dccg_dcn == NULL) {
880 		BREAK_TO_DEBUGGER();
881 		return NULL;
882 	}
883 
884 	base = &dccg_dcn->base;
885 	base->ctx = ctx;
886 	base->funcs = &dccg35_funcs;
887 
888 	dccg_dcn->regs = regs;
889 	dccg_dcn->dccg_shift = dccg_shift;
890 	dccg_dcn->dccg_mask = dccg_mask;
891 
892 	return &dccg_dcn->base;
893 }
894