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