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
44static 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
68static 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
103static 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
145static 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
192static 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) */
248static 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
322static 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
358static 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
395static 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
466static 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
482static 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
509static 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
567void 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
596void 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
603static 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
639static 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
677static 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*/
734static 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
779static 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
842static 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
870struct 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