1 /*
2  * Copyright 2018 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include "reg_helper.h"
27 #include "core_types.h"
28 #include "dcn31_dccg.h"
29 #include "dal_asic_id.h"
30 
31 #define TO_DCN_DCCG(dccg)\
32 	container_of(dccg, struct dcn_dccg, base)
33 
34 #define REG(reg) \
35 	(dccg_dcn->regs->reg)
36 
37 #undef FN
38 #define FN(reg_name, field_name) \
39 	dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
40 
41 #define CTX \
42 	dccg_dcn->base.ctx
43 #define DC_LOGGER \
44 	dccg->ctx->logger
45 
46 static void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
47 {
48 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
49 
50 	if (dccg->ref_dppclk && req_dppclk) {
51 		int ref_dppclk = dccg->ref_dppclk;
52 		int modulo, phase;
53 
54 		// phase / modulo = dpp pipe clk / dpp global clk
55 		modulo = 0xff;   // use FF at the end
56 		phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
57 
58 		if (phase > 0xff) {
59 			ASSERT(false);
60 			phase = 0xff;
61 		}
62 
63 		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
64 				DPPCLK0_DTO_PHASE, phase,
65 				DPPCLK0_DTO_MODULO, modulo);
66 		REG_UPDATE(DPPCLK_DTO_CTRL,
67 				DPPCLK_DTO_ENABLE[dpp_inst], 1);
68 	} else {
69 		//DTO must be enabled to generate a 0Hz clock output
70 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
71 			REG_UPDATE(DPPCLK_DTO_CTRL,
72 					DPPCLK_DTO_ENABLE[dpp_inst], 1);
73 			REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
74 					DPPCLK0_DTO_PHASE, 0,
75 					DPPCLK0_DTO_MODULO, 1);
76 		} else {
77 			REG_UPDATE(DPPCLK_DTO_CTRL,
78 					DPPCLK_DTO_ENABLE[dpp_inst], 0);
79 		}
80 	}
81 	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
82 }
83 
84 static enum phyd32clk_clock_source get_phy_mux_symclk(
85 		struct dcn_dccg *dccg_dcn,
86 		enum phyd32clk_clock_source src)
87 {
88 	if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
89 		if (src == PHYD32CLKC)
90 			src = PHYD32CLKF;
91 		if (src == PHYD32CLKD)
92 			src = PHYD32CLKG;
93 	}
94 	return src;
95 }
96 
97 static void dccg31_enable_dpstreamclk(struct dccg *dccg, int otg_inst)
98 {
99 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
100 
101 	/* enabled to select one of the DTBCLKs for pipe */
102 	switch (otg_inst) {
103 	case 0:
104 		REG_UPDATE(DPSTREAMCLK_CNTL,
105 				DPSTREAMCLK_PIPE0_EN, 1);
106 		break;
107 	case 1:
108 		REG_UPDATE(DPSTREAMCLK_CNTL,
109 				DPSTREAMCLK_PIPE1_EN, 1);
110 		break;
111 	case 2:
112 		REG_UPDATE(DPSTREAMCLK_CNTL,
113 				DPSTREAMCLK_PIPE2_EN, 1);
114 		break;
115 	case 3:
116 		REG_UPDATE(DPSTREAMCLK_CNTL,
117 				DPSTREAMCLK_PIPE3_EN, 1);
118 		break;
119 	default:
120 		BREAK_TO_DEBUGGER();
121 		return;
122 	}
123 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
124 		REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
125 			DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
126 }
127 
128 static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)
129 {
130 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
131 
132 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
133 		REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
134 				DPSTREAMCLK_ROOT_GATE_DISABLE, 0);
135 
136 	switch (otg_inst) {
137 	case 0:
138 		REG_UPDATE(DPSTREAMCLK_CNTL,
139 				DPSTREAMCLK_PIPE0_EN, 0);
140 		break;
141 	case 1:
142 		REG_UPDATE(DPSTREAMCLK_CNTL,
143 				DPSTREAMCLK_PIPE1_EN, 0);
144 		break;
145 	case 2:
146 		REG_UPDATE(DPSTREAMCLK_CNTL,
147 				DPSTREAMCLK_PIPE2_EN, 0);
148 		break;
149 	case 3:
150 		REG_UPDATE(DPSTREAMCLK_CNTL,
151 				DPSTREAMCLK_PIPE3_EN, 0);
152 		break;
153 	default:
154 		BREAK_TO_DEBUGGER();
155 		return;
156 	}
157 }
158 
159 void dccg31_set_dpstreamclk(
160 		struct dccg *dccg,
161 		enum hdmistreamclk_source src,
162 		int otg_inst)
163 {
164 	if (src == REFCLK)
165 		dccg31_disable_dpstreamclk(dccg, otg_inst);
166 	else
167 		dccg31_enable_dpstreamclk(dccg, otg_inst);
168 }
169 
170 void dccg31_enable_symclk32_se(
171 		struct dccg *dccg,
172 		int hpo_se_inst,
173 		enum phyd32clk_clock_source phyd32clk)
174 {
175 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
176 
177 	phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
178 
179 	/* select one of the PHYD32CLKs as the source for symclk32_se */
180 	switch (hpo_se_inst) {
181 	case 0:
182 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
183 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
184 					SYMCLK32_ROOT_SE0_GATE_DISABLE, 1);
185 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
186 				SYMCLK32_SE0_SRC_SEL, phyd32clk,
187 				SYMCLK32_SE0_EN, 1);
188 		break;
189 	case 1:
190 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
191 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
192 					SYMCLK32_ROOT_SE1_GATE_DISABLE, 1);
193 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
194 				SYMCLK32_SE1_SRC_SEL, phyd32clk,
195 				SYMCLK32_SE1_EN, 1);
196 		break;
197 	case 2:
198 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
199 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
200 					SYMCLK32_ROOT_SE2_GATE_DISABLE, 1);
201 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
202 				SYMCLK32_SE2_SRC_SEL, phyd32clk,
203 				SYMCLK32_SE2_EN, 1);
204 		break;
205 	case 3:
206 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
207 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
208 					SYMCLK32_ROOT_SE3_GATE_DISABLE, 1);
209 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
210 				SYMCLK32_SE3_SRC_SEL, phyd32clk,
211 				SYMCLK32_SE3_EN, 1);
212 		break;
213 	default:
214 		BREAK_TO_DEBUGGER();
215 		return;
216 	}
217 }
218 
219 void dccg31_disable_symclk32_se(
220 		struct dccg *dccg,
221 		int hpo_se_inst)
222 {
223 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
224 
225 	/* set refclk as the source for symclk32_se */
226 	switch (hpo_se_inst) {
227 	case 0:
228 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
229 				SYMCLK32_SE0_SRC_SEL, 0,
230 				SYMCLK32_SE0_EN, 0);
231 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
232 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
233 					SYMCLK32_ROOT_SE0_GATE_DISABLE, 0);
234 		break;
235 	case 1:
236 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
237 				SYMCLK32_SE1_SRC_SEL, 0,
238 				SYMCLK32_SE1_EN, 0);
239 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
240 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
241 					SYMCLK32_ROOT_SE1_GATE_DISABLE, 0);
242 		break;
243 	case 2:
244 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
245 				SYMCLK32_SE2_SRC_SEL, 0,
246 				SYMCLK32_SE2_EN, 0);
247 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
248 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
249 					SYMCLK32_ROOT_SE2_GATE_DISABLE, 0);
250 		break;
251 	case 3:
252 		REG_UPDATE_2(SYMCLK32_SE_CNTL,
253 				SYMCLK32_SE3_SRC_SEL, 0,
254 				SYMCLK32_SE3_EN, 0);
255 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
256 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
257 					SYMCLK32_ROOT_SE3_GATE_DISABLE, 0);
258 		break;
259 	default:
260 		BREAK_TO_DEBUGGER();
261 		return;
262 	}
263 }
264 
265 void dccg31_enable_symclk32_le(
266 		struct dccg *dccg,
267 		int hpo_le_inst,
268 		enum phyd32clk_clock_source phyd32clk)
269 {
270 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
271 
272 	phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
273 
274 	/* select one of the PHYD32CLKs as the source for symclk32_le */
275 	switch (hpo_le_inst) {
276 	case 0:
277 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
278 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
279 					SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
280 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
281 				SYMCLK32_LE0_SRC_SEL, phyd32clk,
282 				SYMCLK32_LE0_EN, 1);
283 		break;
284 	case 1:
285 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
286 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
287 					SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
288 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
289 				SYMCLK32_LE1_SRC_SEL, phyd32clk,
290 				SYMCLK32_LE1_EN, 1);
291 		break;
292 	default:
293 		BREAK_TO_DEBUGGER();
294 		return;
295 	}
296 }
297 
298 void dccg31_disable_symclk32_le(
299 		struct dccg *dccg,
300 		int hpo_le_inst)
301 {
302 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
303 
304 	/* set refclk as the source for symclk32_le */
305 	switch (hpo_le_inst) {
306 	case 0:
307 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
308 				SYMCLK32_LE0_SRC_SEL, 0,
309 				SYMCLK32_LE0_EN, 0);
310 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
311 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
312 					SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);
313 		break;
314 	case 1:
315 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
316 				SYMCLK32_LE1_SRC_SEL, 0,
317 				SYMCLK32_LE1_EN, 0);
318 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
319 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
320 					SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);
321 		break;
322 	default:
323 		BREAK_TO_DEBUGGER();
324 		return;
325 	}
326 }
327 
328 static void dccg31_disable_dscclk(struct dccg *dccg, int inst)
329 {
330 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
331 
332 	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
333 		return;
334 	//DTO must be enabled to generate a 0 Hz clock output
335 	switch (inst) {
336 	case 0:
337 		REG_UPDATE(DSCCLK_DTO_CTRL,
338 				DSCCLK0_DTO_ENABLE, 1);
339 		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
340 				DSCCLK0_DTO_PHASE, 0,
341 				DSCCLK0_DTO_MODULO, 1);
342 		break;
343 	case 1:
344 		REG_UPDATE(DSCCLK_DTO_CTRL,
345 				DSCCLK1_DTO_ENABLE, 1);
346 		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
347 				DSCCLK1_DTO_PHASE, 0,
348 				DSCCLK1_DTO_MODULO, 1);
349 		break;
350 	case 2:
351 		REG_UPDATE(DSCCLK_DTO_CTRL,
352 				DSCCLK2_DTO_ENABLE, 1);
353 		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
354 				DSCCLK2_DTO_PHASE, 0,
355 				DSCCLK2_DTO_MODULO, 1);
356 		break;
357 	default:
358 		BREAK_TO_DEBUGGER();
359 		return;
360 	}
361 }
362 
363 static void dccg31_enable_dscclk(struct dccg *dccg, int inst)
364 {
365 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
366 
367 	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
368 		return;
369 	//Disable DTO
370 	switch (inst) {
371 	case 0:
372 		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
373 				DSCCLK0_DTO_PHASE, 0,
374 				DSCCLK0_DTO_MODULO, 0);
375 		REG_UPDATE(DSCCLK_DTO_CTRL,
376 				DSCCLK0_DTO_ENABLE, 0);
377 		break;
378 	case 1:
379 		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
380 				DSCCLK1_DTO_PHASE, 0,
381 				DSCCLK1_DTO_MODULO, 0);
382 		REG_UPDATE(DSCCLK_DTO_CTRL,
383 				DSCCLK1_DTO_ENABLE, 0);
384 		break;
385 	case 2:
386 		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
387 				DSCCLK2_DTO_PHASE, 0,
388 				DSCCLK2_DTO_MODULO, 0);
389 		REG_UPDATE(DSCCLK_DTO_CTRL,
390 				DSCCLK2_DTO_ENABLE, 0);
391 		break;
392 	default:
393 		BREAK_TO_DEBUGGER();
394 		return;
395 	}
396 }
397 
398 void dccg31_set_physymclk(
399 		struct dccg *dccg,
400 		int phy_inst,
401 		enum physymclk_clock_source clk_src,
402 		bool force_enable)
403 {
404 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
405 
406 	/* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
407 	switch (phy_inst) {
408 	case 0:
409 		if (force_enable)
410 			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
411 					PHYASYMCLK_FORCE_EN, 1,
412 					PHYASYMCLK_FORCE_SRC_SEL, clk_src);
413 		else
414 			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
415 					PHYASYMCLK_FORCE_EN, 0,
416 					PHYASYMCLK_FORCE_SRC_SEL, 0);
417 		break;
418 	case 1:
419 		if (force_enable)
420 			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
421 					PHYBSYMCLK_FORCE_EN, 1,
422 					PHYBSYMCLK_FORCE_SRC_SEL, clk_src);
423 		else
424 			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
425 					PHYBSYMCLK_FORCE_EN, 0,
426 					PHYBSYMCLK_FORCE_SRC_SEL, 0);
427 		break;
428 	case 2:
429 		if (force_enable)
430 			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
431 					PHYCSYMCLK_FORCE_EN, 1,
432 					PHYCSYMCLK_FORCE_SRC_SEL, clk_src);
433 		else
434 			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
435 					PHYCSYMCLK_FORCE_EN, 0,
436 					PHYCSYMCLK_FORCE_SRC_SEL, 0);
437 		break;
438 	case 3:
439 		if (force_enable)
440 			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
441 					PHYDSYMCLK_FORCE_EN, 1,
442 					PHYDSYMCLK_FORCE_SRC_SEL, clk_src);
443 		else
444 			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
445 					PHYDSYMCLK_FORCE_EN, 0,
446 					PHYDSYMCLK_FORCE_SRC_SEL, 0);
447 		break;
448 	case 4:
449 		if (force_enable)
450 			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
451 					PHYESYMCLK_FORCE_EN, 1,
452 					PHYESYMCLK_FORCE_SRC_SEL, clk_src);
453 		else
454 			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
455 					PHYESYMCLK_FORCE_EN, 0,
456 					PHYESYMCLK_FORCE_SRC_SEL, 0);
457 		break;
458 	default:
459 		BREAK_TO_DEBUGGER();
460 		return;
461 	}
462 }
463 
464 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
465 void dccg31_set_dtbclk_dto(
466 		struct dccg *dccg,
467 		int dtbclk_inst,
468 		int req_dtbclk_khz,
469 		int num_odm_segments,
470 		const struct dc_crtc_timing *timing)
471 {
472 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
473 	uint32_t dtbdto_div;
474 
475 	/* Mode	                DTBDTO Rate       DTBCLK_DTO<x>_DIV Register
476 	 * ODM 4:1 combine      pixel rate/4      2
477 	 * ODM 2:1 combine      pixel rate/2      4
478 	 * non-DSC 4:2:0 mode   pixel rate/2      4
479 	 * DSC native 4:2:0     pixel rate/2      4
480 	 * DSC native 4:2:2     pixel rate/2      4
481 	 * Other modes          pixel rate        8
482 	 */
483 	if (num_odm_segments == 4) {
484 		dtbdto_div = 2;
485 		req_dtbclk_khz = req_dtbclk_khz / 4;
486 	} else if ((num_odm_segments == 2) ||
487 			(timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
488 			(timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
489 					&& !timing->dsc_cfg.ycbcr422_simple)) {
490 		dtbdto_div = 4;
491 		req_dtbclk_khz = req_dtbclk_khz / 2;
492 	} else
493 		dtbdto_div = 8;
494 
495 	if (dccg->ref_dtbclk_khz && req_dtbclk_khz) {
496 		uint32_t modulo, phase;
497 
498 		// phase / modulo = dtbclk / dtbclk ref
499 		modulo = dccg->ref_dtbclk_khz * 1000;
500 		phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + dccg->ref_dtbclk_khz - 1),
501 			dccg->ref_dtbclk_khz);
502 
503 		REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
504 				DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div);
505 
506 		REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], modulo);
507 		REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], phase);
508 
509 		REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
510 				DTBCLK_DTO_ENABLE[dtbclk_inst], 1);
511 
512 		REG_WAIT(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
513 				DTBCLKDTO_ENABLE_STATUS[dtbclk_inst], 1,
514 				1, 100);
515 
516 		/* The recommended programming sequence to enable DTBCLK DTO to generate
517 		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
518 		 * be set only after DTO is enabled
519 		 */
520 		REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
521 				PIPE_DTO_SRC_SEL[dtbclk_inst], 1);
522 
523 		dccg->dtbclk_khz[dtbclk_inst] = req_dtbclk_khz;
524 	} else {
525 		REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
526 				DTBCLK_DTO_ENABLE[dtbclk_inst], 0,
527 				PIPE_DTO_SRC_SEL[dtbclk_inst], 0,
528 				DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div);
529 
530 		REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], 0);
531 		REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], 0);
532 
533 		dccg->dtbclk_khz[dtbclk_inst] = 0;
534 	}
535 }
536 
537 void dccg31_set_audio_dtbclk_dto(
538 		struct dccg *dccg,
539 		uint32_t req_audio_dtbclk_khz)
540 {
541 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
542 
543 	if (dccg->ref_dtbclk_khz && req_audio_dtbclk_khz) {
544 		uint32_t modulo, phase;
545 
546 		// phase / modulo = dtbclk / dtbclk ref
547 		modulo = dccg->ref_dtbclk_khz * 1000;
548 		phase = div_u64((((unsigned long long)modulo * req_audio_dtbclk_khz) + dccg->ref_dtbclk_khz - 1),
549 			dccg->ref_dtbclk_khz);
550 
551 
552 		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);
553 		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);
554 
555 		//REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
556 		//		DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1);
557 
558 		REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
559 				DCCG_AUDIO_DTO_SEL, 4);  //  04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK
560 
561 		dccg->audio_dtbclk_khz = req_audio_dtbclk_khz;
562 	} else {
563 		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0);
564 		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0);
565 
566 		REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
567 				DCCG_AUDIO_DTO_SEL, 3);  //  03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO
568 
569 		dccg->audio_dtbclk_khz = 0;
570 	}
571 }
572 
573 static void dccg31_get_dccg_ref_freq(struct dccg *dccg,
574 		unsigned int xtalin_freq_inKhz,
575 		unsigned int *dccg_ref_freq_inKhz)
576 {
577 	/*
578 	 * Assume refclk is sourced from xtalin
579 	 * expect 24MHz
580 	 */
581 	*dccg_ref_freq_inKhz = xtalin_freq_inKhz;
582 	return;
583 }
584 
585 static void dccg31_set_dispclk_change_mode(
586 	struct dccg *dccg,
587 	enum dentist_dispclk_change_mode change_mode)
588 {
589 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
590 
591 	REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE,
592 		   change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);
593 }
594 
595 void dccg31_init(struct dccg *dccg)
596 {
597 	/* Set HPO stream encoder to use refclk to avoid case where PHY is
598 	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
599 	 * will cause DCN to hang.
600 	 */
601 	dccg31_disable_symclk32_se(dccg, 0);
602 	dccg31_disable_symclk32_se(dccg, 1);
603 	dccg31_disable_symclk32_se(dccg, 2);
604 	dccg31_disable_symclk32_se(dccg, 3);
605 
606 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
607 		dccg31_disable_symclk32_le(dccg, 0);
608 		dccg31_disable_symclk32_le(dccg, 1);
609 	}
610 
611 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
612 		dccg31_disable_dpstreamclk(dccg, 0);
613 		dccg31_disable_dpstreamclk(dccg, 1);
614 		dccg31_disable_dpstreamclk(dccg, 2);
615 		dccg31_disable_dpstreamclk(dccg, 3);
616 	}
617 
618 }
619 
620 static const struct dccg_funcs dccg31_funcs = {
621 	.update_dpp_dto = dccg31_update_dpp_dto,
622 	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
623 	.dccg_init = dccg31_init,
624 	.set_dpstreamclk = dccg31_set_dpstreamclk,
625 	.enable_symclk32_se = dccg31_enable_symclk32_se,
626 	.disable_symclk32_se = dccg31_disable_symclk32_se,
627 	.enable_symclk32_le = dccg31_enable_symclk32_le,
628 	.disable_symclk32_le = dccg31_disable_symclk32_le,
629 	.set_physymclk = dccg31_set_physymclk,
630 	.set_dtbclk_dto = dccg31_set_dtbclk_dto,
631 	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
632 	.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
633 	.disable_dsc = dccg31_disable_dscclk,
634 	.enable_dsc = dccg31_enable_dscclk,
635 };
636 
637 struct dccg *dccg31_create(
638 	struct dc_context *ctx,
639 	const struct dccg_registers *regs,
640 	const struct dccg_shift *dccg_shift,
641 	const struct dccg_mask *dccg_mask)
642 {
643 	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
644 	struct dccg *base;
645 
646 	if (dccg_dcn == NULL) {
647 		BREAK_TO_DEBUGGER();
648 		return NULL;
649 	}
650 
651 	base = &dccg_dcn->base;
652 	base->ctx = ctx;
653 	base->funcs = &dccg31_funcs;
654 
655 	dccg_dcn->regs = regs;
656 	dccg_dcn->dccg_shift = dccg_shift;
657 	dccg_dcn->dccg_mask = dccg_mask;
658 
659 	return &dccg_dcn->base;
660 }
661