1 /*
2  * Copyright 2023 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 "dcn401_dccg.h"
29 #include "dcn31/dcn31_dccg.h"
30 
31 /*
32 #include "dmub_common.h"
33 #include "dmcub_reg_access_helper.h"
34 
35 #include "dmub401_common.h"
36 #include "dmub401_regs.h"
37 #include "dmub401_dccg.h"
38 */
39 
40 #define TO_DCN_DCCG(dccg)\
41 	container_of(dccg, struct dcn_dccg, base)
42 
43 #define REG(reg) \
44 	(dccg_dcn->regs->reg)
45 
46 #undef FN
47 #define FN(reg_name, field_name) \
48 	dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
49 
50 #define CTX \
51 	dccg_dcn->base.ctx
52 #define DC_LOGGER \
53 	dccg->ctx->logger
54 
dcn401_set_dppclk_enable(struct dccg * dccg,uint32_t dpp_inst,uint32_t enable)55 static void dcn401_set_dppclk_enable(struct dccg *dccg,
56 				 uint32_t dpp_inst, uint32_t enable)
57 {
58 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
59 
60 	switch (dpp_inst) {
61 	case 0:
62 		REG_UPDATE(DPPCLK_CTRL, DPPCLK0_EN, enable);
63 		break;
64 	case 1:
65 		REG_UPDATE(DPPCLK_CTRL, DPPCLK1_EN, enable);
66 		break;
67 	case 2:
68 		REG_UPDATE(DPPCLK_CTRL, DPPCLK2_EN, enable);
69 		break;
70 	case 3:
71 		REG_UPDATE(DPPCLK_CTRL, DPPCLK3_EN, enable);
72 		break;
73 	default:
74 		break;
75 	}
76 }
dccg401_update_dpp_dto(struct dccg * dccg,int dpp_inst,int req_dppclk)77 void dccg401_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
78 {
79 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
80 
81 	if (dccg->ref_dppclk && req_dppclk) {
82 		int ref_dppclk = dccg->ref_dppclk;
83 		int modulo, phase;
84 
85 		// phase / modulo = dpp pipe clk / dpp global clk
86 		modulo = 0xff;   // use FF at the end
87 		phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
88 
89 		if (phase > 0xff) {
90 			ASSERT(false);
91 			phase = 0xff;
92 		}
93 
94 		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
95 				DPPCLK0_DTO_PHASE, phase,
96 				DPPCLK0_DTO_MODULO, modulo);
97 		dcn401_set_dppclk_enable(dccg, dpp_inst, true);
98 	} else {
99 		dcn401_set_dppclk_enable(dccg, dpp_inst, false);
100 	}
101 
102 	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
103 }
104 
105 /* This function is a workaround for writing to OTG_PIXEL_RATE_DIV
106  * without the probability of causing a DIG FIFO error.
107  */
dccg401_wait_for_dentist_change_done(struct dccg * dccg)108 static void dccg401_wait_for_dentist_change_done(
109 	struct dccg *dccg)
110 {
111 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
112 
113 	uint32_t dentist_dispclk_value = REG_READ(DENTIST_DISPCLK_CNTL);
114 
115 	REG_WRITE(DENTIST_DISPCLK_CNTL, dentist_dispclk_value);
116 	REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
117 }
118 
dccg401_get_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,uint32_t * tmds_div,uint32_t * dp_dto_int)119 static void dccg401_get_pixel_rate_div(
120 		struct dccg *dccg,
121 		uint32_t otg_inst,
122 		uint32_t *tmds_div,
123 		uint32_t *dp_dto_int)
124 {
125 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
126 	uint32_t val_tmds_div = PIXEL_RATE_DIV_NA;
127 
128 	switch (otg_inst) {
129 	case 0:
130 		REG_GET_2(OTG_PIXEL_RATE_DIV,
131 			OTG0_TMDS_PIXEL_RATE_DIV, &val_tmds_div,
132 			DPDTO0_INT, dp_dto_int);
133 		break;
134 	case 1:
135 		REG_GET_2(OTG_PIXEL_RATE_DIV,
136 			OTG1_TMDS_PIXEL_RATE_DIV, &val_tmds_div,
137 			DPDTO1_INT, dp_dto_int);
138 		break;
139 	case 2:
140 		REG_GET_2(OTG_PIXEL_RATE_DIV,
141 			OTG2_TMDS_PIXEL_RATE_DIV, &val_tmds_div,
142 			DPDTO2_INT, dp_dto_int);
143 		break;
144 	case 3:
145 		REG_GET_2(OTG_PIXEL_RATE_DIV,
146 			OTG3_TMDS_PIXEL_RATE_DIV, &val_tmds_div,
147 			DPDTO3_INT, dp_dto_int);
148 		break;
149 	default:
150 		BREAK_TO_DEBUGGER();
151 		return;
152 	}
153 
154 	*tmds_div = val_tmds_div == 0 ? PIXEL_RATE_DIV_BY_2 : PIXEL_RATE_DIV_BY_4;
155 }
156 
dccg401_set_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,enum pixel_rate_div tmds_div,enum pixel_rate_div unused)157 static void dccg401_set_pixel_rate_div(
158 		struct dccg *dccg,
159 		uint32_t otg_inst,
160 		enum pixel_rate_div tmds_div,
161 		enum pixel_rate_div unused)
162 {
163 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
164 	uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
165 	uint32_t dp_dto_int;
166 	uint32_t reg_val;
167 
168 	// only 2 and 4 are valid on dcn401
169 	if (tmds_div != PIXEL_RATE_DIV_BY_2 && tmds_div != PIXEL_RATE_DIV_BY_4) {
170 		return;
171 	}
172 
173 	dccg401_get_pixel_rate_div(dccg, otg_inst, &cur_tmds_div, &dp_dto_int);
174 	if (tmds_div == cur_tmds_div)
175 		return;
176 
177 	// encode enum to register value
178 	reg_val = tmds_div == PIXEL_RATE_DIV_BY_4 ? 1 : 0;
179 
180 	switch (otg_inst) {
181 	case 0:
182 		REG_UPDATE(OTG_PIXEL_RATE_DIV,
183 				OTG0_TMDS_PIXEL_RATE_DIV, reg_val);
184 
185 		dccg401_wait_for_dentist_change_done(dccg);
186 		break;
187 	case 1:
188 		REG_UPDATE(OTG_PIXEL_RATE_DIV,
189 				OTG1_TMDS_PIXEL_RATE_DIV, reg_val);
190 
191 		dccg401_wait_for_dentist_change_done(dccg);
192 		break;
193 	case 2:
194 		REG_UPDATE(OTG_PIXEL_RATE_DIV,
195 				OTG2_TMDS_PIXEL_RATE_DIV, reg_val);
196 
197 		dccg401_wait_for_dentist_change_done(dccg);
198 		break;
199 	case 3:
200 		REG_UPDATE(OTG_PIXEL_RATE_DIV,
201 				OTG3_TMDS_PIXEL_RATE_DIV, reg_val);
202 
203 		dccg401_wait_for_dentist_change_done(dccg);
204 		break;
205 	default:
206 		BREAK_TO_DEBUGGER();
207 		return;
208 	}
209 }
210 
211 
dccg401_set_dtbclk_p_src(struct dccg * dccg,enum streamclk_source src,uint32_t otg_inst)212 static void dccg401_set_dtbclk_p_src(
213 		struct dccg *dccg,
214 		enum streamclk_source src,
215 		uint32_t otg_inst)
216 {
217 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
218 
219 	uint32_t p_src_sel = 0; /* selects dprefclk */
220 	if (src == DTBCLK0)
221 		p_src_sel = 2;  /* selects dtbclk0 */
222 
223 	switch (otg_inst) {
224 	case 0:
225 		if (src == REFCLK)
226 			REG_UPDATE(DTBCLK_P_CNTL,
227 					DTBCLK_P0_EN, 0);
228 		else
229 			REG_UPDATE_2(DTBCLK_P_CNTL,
230 					DTBCLK_P0_SRC_SEL, p_src_sel,
231 					DTBCLK_P0_EN, 1);
232 		break;
233 	case 1:
234 		if (src == REFCLK)
235 			REG_UPDATE(DTBCLK_P_CNTL,
236 					DTBCLK_P1_EN, 0);
237 		else
238 			REG_UPDATE_2(DTBCLK_P_CNTL,
239 					DTBCLK_P1_SRC_SEL, p_src_sel,
240 					DTBCLK_P1_EN, 1);
241 		break;
242 	case 2:
243 		if (src == REFCLK)
244 			REG_UPDATE(DTBCLK_P_CNTL,
245 					DTBCLK_P2_EN, 0);
246 		else
247 			REG_UPDATE_2(DTBCLK_P_CNTL,
248 					DTBCLK_P2_SRC_SEL, p_src_sel,
249 					DTBCLK_P2_EN, 1);
250 		break;
251 	case 3:
252 		if (src == REFCLK)
253 			REG_UPDATE(DTBCLK_P_CNTL,
254 					DTBCLK_P3_EN, 0);
255 		else
256 			REG_UPDATE_2(DTBCLK_P_CNTL,
257 					DTBCLK_P3_SRC_SEL, p_src_sel,
258 					DTBCLK_P3_EN, 1);
259 		break;
260 	default:
261 		BREAK_TO_DEBUGGER();
262 		return;
263 	}
264 
265 }
266 
dccg401_set_physymclk(struct dccg * dccg,int phy_inst,enum physymclk_clock_source clk_src,bool force_enable)267 void dccg401_set_physymclk(
268 		struct dccg *dccg,
269 		int phy_inst,
270 		enum physymclk_clock_source clk_src,
271 		bool force_enable)
272 {
273 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
274 
275 	/* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
276 	switch (phy_inst) {
277 	case 0:
278 		if (force_enable) {
279 			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
280 					PHYASYMCLK_EN, 1,
281 					PHYASYMCLK_SRC_SEL, clk_src);
282 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
283 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
284 					PHYASYMCLK_ROOT_GATE_DISABLE, 1);
285 		} else {
286 			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
287 					PHYASYMCLK_EN, 0,
288 					PHYASYMCLK_SRC_SEL, 0);
289 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
290 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
291 					PHYASYMCLK_ROOT_GATE_DISABLE, 0);
292 		}
293 		break;
294 	case 1:
295 		if (force_enable) {
296 			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
297 					PHYBSYMCLK_EN, 1,
298 					PHYBSYMCLK_SRC_SEL, clk_src);
299 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
300 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
301 					PHYBSYMCLK_ROOT_GATE_DISABLE, 1);
302 		} else {
303 			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
304 					PHYBSYMCLK_EN, 0,
305 					PHYBSYMCLK_SRC_SEL, 0);
306 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
307 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
308 					PHYBSYMCLK_ROOT_GATE_DISABLE, 0);
309 		}
310 		break;
311 	case 2:
312 		if (force_enable) {
313 			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
314 					PHYCSYMCLK_EN, 1,
315 					PHYCSYMCLK_SRC_SEL, clk_src);
316 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
317 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
318 					PHYCSYMCLK_ROOT_GATE_DISABLE, 1);
319 		} else {
320 			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
321 					PHYCSYMCLK_EN, 0,
322 					PHYCSYMCLK_SRC_SEL, 0);
323 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
324 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
325 					PHYCSYMCLK_ROOT_GATE_DISABLE, 0);
326 		}
327 		break;
328 	case 3:
329 		if (force_enable) {
330 			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
331 					PHYDSYMCLK_EN, 1,
332 					PHYDSYMCLK_SRC_SEL, clk_src);
333 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
334 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
335 					PHYDSYMCLK_ROOT_GATE_DISABLE, 1);
336 		} else {
337 			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
338 					PHYDSYMCLK_EN, 0,
339 					PHYDSYMCLK_SRC_SEL, 0);
340 			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
341 				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
342 					PHYDSYMCLK_ROOT_GATE_DISABLE, 0);
343 		}
344 		break;
345 	default:
346 		BREAK_TO_DEBUGGER();
347 		return;
348 	}
349 }
350 
dccg401_get_dccg_ref_freq(struct dccg * dccg,unsigned int xtalin_freq_inKhz,unsigned int * dccg_ref_freq_inKhz)351 static void dccg401_get_dccg_ref_freq(struct dccg *dccg,
352 		unsigned int xtalin_freq_inKhz,
353 		unsigned int *dccg_ref_freq_inKhz)
354 {
355 	/*
356 	 * Assume refclk is sourced from xtalin
357 	 * expect 100MHz
358 	 */
359 	*dccg_ref_freq_inKhz = xtalin_freq_inKhz;
360 	return;
361 }
362 
dccg401_otg_add_pixel(struct dccg * dccg,uint32_t otg_inst)363 static void dccg401_otg_add_pixel(struct dccg *dccg,
364 		uint32_t otg_inst)
365 {
366 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
367 
368 	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
369 			OTG_ADD_PIXEL[otg_inst], 1);
370 }
371 
dccg401_otg_drop_pixel(struct dccg * dccg,uint32_t otg_inst)372 static void dccg401_otg_drop_pixel(struct dccg *dccg,
373 		uint32_t otg_inst)
374 {
375 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
376 
377 	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
378 			OTG_DROP_PIXEL[otg_inst], 1);
379 }
380 
dccg401_enable_symclk32_le(struct dccg * dccg,int hpo_le_inst,enum phyd32clk_clock_source phyd32clk)381 static void dccg401_enable_symclk32_le(
382 		struct dccg *dccg,
383 		int hpo_le_inst,
384 		enum phyd32clk_clock_source phyd32clk)
385 {
386 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
387 
388 	/* select one of the PHYD32CLKs as the source for symclk32_le */
389 	switch (hpo_le_inst) {
390 	case 0:
391 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
392 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
393 					SYMCLK32_LE0_GATE_DISABLE, 1,
394 					SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
395 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
396 				SYMCLK32_LE0_SRC_SEL, phyd32clk,
397 				SYMCLK32_LE0_EN, 1);
398 		break;
399 	case 1:
400 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
401 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
402 					SYMCLK32_LE1_GATE_DISABLE, 1,
403 					SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
404 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
405 				SYMCLK32_LE1_SRC_SEL, phyd32clk,
406 				SYMCLK32_LE1_EN, 1);
407 		break;
408 	case 2:
409 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
410 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
411 					SYMCLK32_LE2_GATE_DISABLE, 1,
412 					SYMCLK32_ROOT_LE2_GATE_DISABLE, 1);
413 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
414 				SYMCLK32_LE2_SRC_SEL, phyd32clk,
415 				SYMCLK32_LE2_EN, 1);
416 		break;
417 	case 3:
418 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
419 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
420 					SYMCLK32_LE3_GATE_DISABLE, 1,
421 					SYMCLK32_ROOT_LE3_GATE_DISABLE, 1);
422 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
423 				SYMCLK32_LE3_SRC_SEL, phyd32clk,
424 				SYMCLK32_LE3_EN, 1);
425 		break;
426 	default:
427 		BREAK_TO_DEBUGGER();
428 		return;
429 	}
430 }
431 
dccg401_disable_symclk32_le(struct dccg * dccg,int hpo_le_inst)432 static void dccg401_disable_symclk32_le(
433 		struct dccg *dccg,
434 		int hpo_le_inst)
435 {
436 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
437 
438 	/* set refclk as the source for symclk32_le */
439 	switch (hpo_le_inst) {
440 	case 0:
441 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
442 				SYMCLK32_LE0_SRC_SEL, 0,
443 				SYMCLK32_LE0_EN, 0);
444 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
445 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
446 					SYMCLK32_LE0_GATE_DISABLE, 0,
447 					SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);
448 		break;
449 	case 1:
450 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
451 				SYMCLK32_LE1_SRC_SEL, 0,
452 				SYMCLK32_LE1_EN, 0);
453 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
454 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
455 					SYMCLK32_LE1_GATE_DISABLE, 0,
456 					SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);
457 		break;
458 	case 2:
459 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
460 				SYMCLK32_LE2_SRC_SEL, 0,
461 				SYMCLK32_LE2_EN, 0);
462 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
463 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
464 					SYMCLK32_LE2_GATE_DISABLE, 0,
465 					SYMCLK32_ROOT_LE2_GATE_DISABLE, 0);
466 		break;
467 	case 3:
468 		REG_UPDATE_2(SYMCLK32_LE_CNTL,
469 				SYMCLK32_LE3_SRC_SEL, 0,
470 				SYMCLK32_LE3_EN, 0);
471 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
472 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
473 					SYMCLK32_LE3_GATE_DISABLE, 0,
474 					SYMCLK32_ROOT_LE3_GATE_DISABLE, 0);
475 		break;
476 	default:
477 		BREAK_TO_DEBUGGER();
478 		return;
479 	}
480 }
481 
dccg401_enable_dpstreamclk(struct dccg * dccg,int otg_inst,int dp_hpo_inst)482 static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_hpo_inst)
483 {
484 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
485 
486 	/* enabled to select one of the DTBCLKs for pipe */
487 	switch (dp_hpo_inst) {
488 	case 0:
489 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
490 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
491 					DPSTREAMCLK0_ROOT_GATE_DISABLE, 1,
492 					DPSTREAMCLK0_GATE_DISABLE, 1);
493 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
494 				DPSTREAMCLK0_SRC_SEL, otg_inst,
495 				DPSTREAMCLK0_EN, 1);
496 		break;
497 	case 1:
498 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
499 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
500 					DPSTREAMCLK1_ROOT_GATE_DISABLE, 1,
501 					DPSTREAMCLK1_GATE_DISABLE, 1);
502 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
503 				DPSTREAMCLK1_SRC_SEL, otg_inst,
504 				DPSTREAMCLK1_EN, 1);
505 		break;
506 	case 2:
507 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
508 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
509 					DPSTREAMCLK2_ROOT_GATE_DISABLE, 1,
510 					DPSTREAMCLK2_GATE_DISABLE, 1);
511 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
512 				DPSTREAMCLK2_SRC_SEL, otg_inst,
513 				DPSTREAMCLK2_EN, 1);
514 		break;
515 	case 3:
516 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
517 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
518 					DPSTREAMCLK3_ROOT_GATE_DISABLE, 1,
519 					DPSTREAMCLK3_GATE_DISABLE, 1);
520 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
521 				DPSTREAMCLK3_SRC_SEL, otg_inst,
522 				DPSTREAMCLK3_EN, 1);
523 		break;
524 	default:
525 		BREAK_TO_DEBUGGER();
526 		return;
527 	}
528 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
529 		REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
530 			DPSTREAMCLK_GATE_DISABLE, 1,
531 			DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
532 }
533 
dccg401_disable_dpstreamclk(struct dccg * dccg,int dp_hpo_inst)534 static void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst)
535 {
536 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
537 
538 	switch (dp_hpo_inst) {
539 	case 0:
540 		REG_UPDATE(DPSTREAMCLK_CNTL,
541 				DPSTREAMCLK0_EN, 0);
542 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
543 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
544 					DPSTREAMCLK0_ROOT_GATE_DISABLE, 0,
545 					DPSTREAMCLK0_GATE_DISABLE, 0);
546 		break;
547 	case 1:
548 		REG_UPDATE(DPSTREAMCLK_CNTL,
549 				DPSTREAMCLK1_EN, 0);
550 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
551 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
552 					DPSTREAMCLK1_ROOT_GATE_DISABLE, 0,
553 					DPSTREAMCLK1_GATE_DISABLE, 0);
554 		break;
555 	case 2:
556 		REG_UPDATE(DPSTREAMCLK_CNTL,
557 				DPSTREAMCLK2_EN, 0);
558 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
559 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
560 					DPSTREAMCLK2_ROOT_GATE_DISABLE, 0,
561 					DPSTREAMCLK2_GATE_DISABLE, 0);
562 		break;
563 	case 3:
564 		REG_UPDATE(DPSTREAMCLK_CNTL,
565 				DPSTREAMCLK3_EN, 0);
566 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
567 			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,
568 					DPSTREAMCLK3_ROOT_GATE_DISABLE, 0,
569 					DPSTREAMCLK3_GATE_DISABLE, 0);
570 		break;
571 	default:
572 		BREAK_TO_DEBUGGER();
573 		return;
574 	}
575 }
576 
dccg401_set_dpstreamclk(struct dccg * dccg,enum streamclk_source src,int otg_inst,int dp_hpo_inst)577 static void dccg401_set_dpstreamclk(
578 		struct dccg *dccg,
579 		enum streamclk_source src,
580 		int otg_inst,
581 		int dp_hpo_inst)
582 {
583 	/* enabled to select one of the DTBCLKs for pipe */
584 	if (src == REFCLK)
585 		dccg401_disable_dpstreamclk(dccg, dp_hpo_inst);
586 	else
587 		dccg401_enable_dpstreamclk(dccg, otg_inst, dp_hpo_inst);
588 }
589 
dccg401_set_dp_dto(struct dccg * dccg,const struct dp_dto_params * params)590 static void dccg401_set_dp_dto(
591 		struct dccg *dccg,
592 		const struct dp_dto_params *params)
593 {
594 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
595 
596 	bool enable = false;
597 
598 	if (params->otg_inst > 3) {
599 		/* dcn401 only has 4 instances */
600 		BREAK_TO_DEBUGGER();
601 		return;
602 	}
603 	if (!params->refclk_hz) {
604 		BREAK_TO_DEBUGGER();
605 		return;
606 	}
607 
608 	if (!dc_is_tmds_signal(params->signal)) {
609 		uint64_t dto_integer;
610 		uint64_t dto_phase_hz;
611 		uint64_t dto_modulo_hz = params->refclk_hz;
612 
613 		enable = true;
614 
615 		/* Set DTO values:
616 		 * int = target_pix_rate / reference_clock
617 		 * phase = target_pix_rate - int * reference_clock,
618 		 * modulo = reference_clock */
619 		dto_integer = div_u64(params->pixclk_hz, dto_modulo_hz);
620 		dto_phase_hz = params->pixclk_hz - dto_integer * dto_modulo_hz;
621 
622 		if (dto_phase_hz <= 0) {
623 			/* negative pixel rate should never happen */
624 			BREAK_TO_DEBUGGER();
625 			return;
626 		}
627 
628 		switch (params->otg_inst) {
629 		case 0:
630 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 1);
631 			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
632 					SYMCLK32_SE0_GATE_DISABLE, 1,
633 					SYMCLK32_ROOT_SE0_GATE_DISABLE, 1,
634 					SYMCLK32_LE0_GATE_DISABLE, 1,
635 					SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
636 			break;
637 		case 1:
638 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 1);
639 			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
640 					SYMCLK32_SE1_GATE_DISABLE, 1,
641 					SYMCLK32_ROOT_SE1_GATE_DISABLE, 1,
642 					SYMCLK32_LE1_GATE_DISABLE, 1,
643 					SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
644 			break;
645 		case 2:
646 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 1);
647 			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
648 					SYMCLK32_SE2_GATE_DISABLE, 1,
649 					SYMCLK32_ROOT_SE2_GATE_DISABLE, 1,
650 					SYMCLK32_LE2_GATE_DISABLE, 1,
651 					SYMCLK32_ROOT_LE2_GATE_DISABLE, 1);
652 			break;
653 		case 3:
654 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 1);
655 			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
656 					SYMCLK32_SE3_GATE_DISABLE, 1,
657 					SYMCLK32_ROOT_SE3_GATE_DISABLE, 1,
658 					SYMCLK32_LE3_GATE_DISABLE, 1,
659 					SYMCLK32_ROOT_LE3_GATE_DISABLE, 1);
660 			break;
661 		}
662 
663 		dccg401_set_dtbclk_p_src(dccg, params->clk_src, params->otg_inst);
664 
665 		REG_WRITE(DP_DTO_PHASE[params->otg_inst], dto_phase_hz);
666 		REG_WRITE(DP_DTO_MODULO[params->otg_inst], dto_modulo_hz);
667 
668 		switch (params->otg_inst) {
669 		case 0:
670 			REG_UPDATE(OTG_PIXEL_RATE_DIV,
671 					DPDTO0_INT, dto_integer);
672 			break;
673 		case 1:
674 			REG_UPDATE(OTG_PIXEL_RATE_DIV,
675 					DPDTO1_INT, dto_integer);
676 			break;
677 		case 2:
678 			REG_UPDATE(OTG_PIXEL_RATE_DIV,
679 					DPDTO2_INT, dto_integer);
680 			break;
681 		case 3:
682 			REG_UPDATE(OTG_PIXEL_RATE_DIV,
683 					DPDTO3_INT, dto_integer);
684 			break;
685 		default:
686 			BREAK_TO_DEBUGGER();
687 			return;
688 		}
689 	}
690 
691 	/* Toggle DTO */
692 	REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
693 			DP_DTO_ENABLE[params->otg_inst], enable,
694 			PIPE_DTO_SRC_SEL[params->otg_inst], enable);
695 }
696 
dccg401_init(struct dccg * dccg)697 void dccg401_init(struct dccg *dccg)
698 {
699 	/* Set HPO stream encoder to use refclk to avoid case where PHY is
700 	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
701 	 * will cause DCN to hang.
702 	 */
703 	dccg31_disable_symclk32_se(dccg, 0);
704 	dccg31_disable_symclk32_se(dccg, 1);
705 	dccg31_disable_symclk32_se(dccg, 2);
706 	dccg31_disable_symclk32_se(dccg, 3);
707 
708 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
709 		dccg401_disable_symclk32_le(dccg, 0);
710 		dccg401_disable_symclk32_le(dccg, 1);
711 		dccg401_disable_symclk32_le(dccg, 2);
712 		dccg401_disable_symclk32_le(dccg, 3);
713 	}
714 
715 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
716 		dccg401_disable_dpstreamclk(dccg, 0);
717 		dccg401_disable_dpstreamclk(dccg, 1);
718 		dccg401_disable_dpstreamclk(dccg, 2);
719 		dccg401_disable_dpstreamclk(dccg, 3);
720 	}
721 
722 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
723 		dccg401_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
724 		dccg401_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
725 		dccg401_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
726 		dccg401_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
727 	}
728 }
729 
dccg401_set_dto_dscclk(struct dccg * dccg,uint32_t inst)730 static void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst)
731 {
732 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
733 
734 	switch (inst) {
735 	case 0:
736 		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
737 				DSCCLK0_DTO_PHASE, 1,
738 				DSCCLK0_DTO_MODULO, 1);
739 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1);
740 
741 		break;
742 	case 1:
743 		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
744 				DSCCLK1_DTO_PHASE, 1,
745 				DSCCLK1_DTO_MODULO, 1);
746 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1);
747 		break;
748 	case 2:
749 		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
750 				DSCCLK2_DTO_PHASE, 1,
751 				DSCCLK2_DTO_MODULO, 1);
752 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1);
753 		break;
754 	case 3:
755 		REG_UPDATE_2(DSCCLK3_DTO_PARAM,
756 				DSCCLK3_DTO_PHASE, 1,
757 				DSCCLK3_DTO_MODULO, 1);
758 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1);
759 		break;
760 	default:
761 		BREAK_TO_DEBUGGER();
762 		return;
763 	}
764 }
765 
dccg401_set_ref_dscclk(struct dccg * dccg,uint32_t dsc_inst)766 static void dccg401_set_ref_dscclk(struct dccg *dccg,
767 				uint32_t dsc_inst)
768 {
769 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
770 
771 	switch (dsc_inst) {
772 	case 0:
773 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 0);
774 		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
775 				DSCCLK0_DTO_PHASE, 0,
776 				DSCCLK0_DTO_MODULO, 0);
777 		break;
778 	case 1:
779 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0);
780 		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
781 				DSCCLK1_DTO_PHASE, 0,
782 				DSCCLK1_DTO_MODULO, 0);
783 		break;
784 	case 2:
785 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0);
786 		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
787 				DSCCLK2_DTO_PHASE, 0,
788 				DSCCLK2_DTO_MODULO, 0);
789 		break;
790 	case 3:
791 		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0);
792 		REG_UPDATE_2(DSCCLK3_DTO_PARAM,
793 				DSCCLK3_DTO_PHASE, 0,
794 				DSCCLK3_DTO_MODULO, 0);
795 		break;
796 	default:
797 		return;
798 	}
799 }
800 
dccg401_enable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)801 static void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
802 {
803 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
804 
805 	switch (stream_enc_inst) {
806 	case 0:
807 		REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
808 				SYMCLKA_FE_EN, 1,
809 				SYMCLKA_FE_SRC_SEL, link_enc_inst);
810 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
811 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1);
812 		break;
813 	case 1:
814 		REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
815 				SYMCLKB_FE_EN, 1,
816 				SYMCLKB_FE_SRC_SEL, link_enc_inst);
817 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
818 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1);
819 		break;
820 	case 2:
821 		REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
822 				SYMCLKC_FE_EN, 1,
823 				SYMCLKC_FE_SRC_SEL, link_enc_inst);
824 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
825 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1);
826 		break;
827 	case 3:
828 		REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
829 				SYMCLKD_FE_EN, 1,
830 				SYMCLKD_FE_SRC_SEL, link_enc_inst);
831 		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
832 			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1);
833 		break;
834 	}
835 }
836 
dccg401_disable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)837 static void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
838 {
839 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
840 
841 	switch (stream_enc_inst) {
842 	case 0:
843 		REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
844 				SYMCLKA_FE_EN, 0,
845 				SYMCLKA_FE_SRC_SEL, 0);
846 		break;
847 	case 1:
848 		REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
849 				SYMCLKB_FE_EN, 0,
850 				SYMCLKB_FE_SRC_SEL, 0);
851 		break;
852 	case 2:
853 		REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
854 				SYMCLKC_FE_EN, 0,
855 				SYMCLKC_FE_SRC_SEL, 0);
856 		break;
857 	case 3:
858 		REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
859 				SYMCLKD_FE_EN, 0,
860 				SYMCLKD_FE_SRC_SEL, 0);
861 		break;
862 	}
863 }
864 
865 static const struct dccg_funcs dccg401_funcs = {
866 	.update_dpp_dto = dccg401_update_dpp_dto,
867 	.get_dccg_ref_freq = dccg401_get_dccg_ref_freq,
868 	.dccg_init = dccg401_init,
869 	.set_dpstreamclk = dccg401_set_dpstreamclk,
870 	.enable_symclk32_se = dccg31_enable_symclk32_se,
871 	.disable_symclk32_se = dccg31_disable_symclk32_se,
872 	.enable_symclk32_le = dccg401_enable_symclk32_le,
873 	.disable_symclk32_le = dccg401_disable_symclk32_le,
874 	.set_physymclk = dccg401_set_physymclk,
875 	.set_dtbclk_dto = NULL,
876 	.set_dto_dscclk = dccg401_set_dto_dscclk,
877 	.set_ref_dscclk = dccg401_set_ref_dscclk,
878 	.set_valid_pixel_rate = NULL,
879 	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
880 	.set_audio_dtbclk_dto = NULL,
881 	.otg_add_pixel = dccg401_otg_add_pixel,
882 	.otg_drop_pixel = dccg401_otg_drop_pixel,
883 	.set_pixel_rate_div = dccg401_set_pixel_rate_div,
884 	.get_pixel_rate_div = dccg401_get_pixel_rate_div,
885 	.set_dp_dto = dccg401_set_dp_dto,
886 	.enable_symclk_se = dccg401_enable_symclk_se,
887 	.disable_symclk_se = dccg401_disable_symclk_se,
888 	.set_dtbclk_p_src = dccg401_set_dtbclk_p_src,
889 };
890 
dccg401_create(struct dc_context * ctx,const struct dccg_registers * regs,const struct dccg_shift * dccg_shift,const struct dccg_mask * dccg_mask)891 struct dccg *dccg401_create(
892 	struct dc_context *ctx,
893 	const struct dccg_registers *regs,
894 	const struct dccg_shift *dccg_shift,
895 	const struct dccg_mask *dccg_mask)
896 {
897 	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
898 	struct dccg *base;
899 
900 	if (dccg_dcn == NULL) {
901 		BREAK_TO_DEBUGGER();
902 		return NULL;
903 	}
904 
905 	base = &dccg_dcn->base;
906 	base->ctx = ctx;
907 	base->funcs = &dccg401_funcs;
908 
909 	dccg_dcn->regs = regs;
910 	dccg_dcn->dccg_shift = dccg_shift;
911 	dccg_dcn->dccg_mask = dccg_mask;
912 
913 	return &dccg_dcn->base;
914 }
915