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
46void 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->dpp_clock_gated[dpp_inst]) {
51		/*
52		 * Do not update the DPPCLK DTO if the clock is stopped.
53		 * It is treated the same as if the pipe itself were in PG.
54		 */
55		return;
56	}
57
58	if (dccg->ref_dppclk && req_dppclk) {
59		int ref_dppclk = dccg->ref_dppclk;
60		int modulo, phase;
61
62		// phase / modulo = dpp pipe clk / dpp global clk
63		modulo = 0xff;   // use FF at the end
64		phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
65
66		if (phase > 0xff) {
67			ASSERT(false);
68			phase = 0xff;
69		}
70
71		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
72				DPPCLK0_DTO_PHASE, phase,
73				DPPCLK0_DTO_MODULO, modulo);
74		REG_UPDATE(DPPCLK_DTO_CTRL,
75				DPPCLK_DTO_ENABLE[dpp_inst], 1);
76	} else {
77		REG_UPDATE(DPPCLK_DTO_CTRL,
78				DPPCLK_DTO_ENABLE[dpp_inst], 0);
79	}
80	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
81}
82
83static enum phyd32clk_clock_source get_phy_mux_symclk(
84		struct dcn_dccg *dccg_dcn,
85		enum phyd32clk_clock_source src)
86{
87	if (dccg_dcn->base.ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&
88			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
97static 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_2(DCCG_GATE_DISABLE_CNTL3,
125			DPSTREAMCLK_GATE_DISABLE, 1,
126			DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
127}
128
129static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)
130{
131	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
132
133	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
134		REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
135				DPSTREAMCLK_ROOT_GATE_DISABLE, 0,
136				DPSTREAMCLK_GATE_DISABLE, 0);
137
138	switch (otg_inst) {
139	case 0:
140		REG_UPDATE(DPSTREAMCLK_CNTL,
141				DPSTREAMCLK_PIPE0_EN, 0);
142		break;
143	case 1:
144		REG_UPDATE(DPSTREAMCLK_CNTL,
145				DPSTREAMCLK_PIPE1_EN, 0);
146		break;
147	case 2:
148		REG_UPDATE(DPSTREAMCLK_CNTL,
149				DPSTREAMCLK_PIPE2_EN, 0);
150		break;
151	case 3:
152		REG_UPDATE(DPSTREAMCLK_CNTL,
153				DPSTREAMCLK_PIPE3_EN, 0);
154		break;
155	default:
156		BREAK_TO_DEBUGGER();
157		return;
158	}
159}
160
161void dccg31_set_dpstreamclk(
162		struct dccg *dccg,
163		enum streamclk_source src,
164		int otg_inst,
165		int dp_hpo_inst)
166{
167	if (src == REFCLK)
168		dccg31_disable_dpstreamclk(dccg, otg_inst);
169	else
170		dccg31_enable_dpstreamclk(dccg, otg_inst);
171}
172
173void dccg31_enable_symclk32_se(
174		struct dccg *dccg,
175		int hpo_se_inst,
176		enum phyd32clk_clock_source phyd32clk)
177{
178	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
179
180	phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
181
182	/* select one of the PHYD32CLKs as the source for symclk32_se */
183	switch (hpo_se_inst) {
184	case 0:
185		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
186			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
187					SYMCLK32_SE0_GATE_DISABLE, 1,
188					SYMCLK32_ROOT_SE0_GATE_DISABLE, 1);
189		REG_UPDATE_2(SYMCLK32_SE_CNTL,
190				SYMCLK32_SE0_SRC_SEL, phyd32clk,
191				SYMCLK32_SE0_EN, 1);
192		break;
193	case 1:
194		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
195			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
196					SYMCLK32_SE1_GATE_DISABLE, 1,
197					SYMCLK32_ROOT_SE1_GATE_DISABLE, 1);
198		REG_UPDATE_2(SYMCLK32_SE_CNTL,
199				SYMCLK32_SE1_SRC_SEL, phyd32clk,
200				SYMCLK32_SE1_EN, 1);
201		break;
202	case 2:
203		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
204			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
205					SYMCLK32_SE2_GATE_DISABLE, 1,
206					SYMCLK32_ROOT_SE2_GATE_DISABLE, 1);
207		REG_UPDATE_2(SYMCLK32_SE_CNTL,
208				SYMCLK32_SE2_SRC_SEL, phyd32clk,
209				SYMCLK32_SE2_EN, 1);
210		break;
211	case 3:
212		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
213			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
214					SYMCLK32_SE3_GATE_DISABLE, 1,
215					SYMCLK32_ROOT_SE3_GATE_DISABLE, 1);
216		REG_UPDATE_2(SYMCLK32_SE_CNTL,
217				SYMCLK32_SE3_SRC_SEL, phyd32clk,
218				SYMCLK32_SE3_EN, 1);
219		break;
220	default:
221		BREAK_TO_DEBUGGER();
222		return;
223	}
224}
225
226void dccg31_disable_symclk32_se(
227		struct dccg *dccg,
228		int hpo_se_inst)
229{
230	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
231
232	/* set refclk as the source for symclk32_se */
233	switch (hpo_se_inst) {
234	case 0:
235		REG_UPDATE_2(SYMCLK32_SE_CNTL,
236				SYMCLK32_SE0_SRC_SEL, 0,
237				SYMCLK32_SE0_EN, 0);
238		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
239			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
240					SYMCLK32_SE0_GATE_DISABLE, 0,
241					SYMCLK32_ROOT_SE0_GATE_DISABLE, 0);
242		break;
243	case 1:
244		REG_UPDATE_2(SYMCLK32_SE_CNTL,
245				SYMCLK32_SE1_SRC_SEL, 0,
246				SYMCLK32_SE1_EN, 0);
247		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
248			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
249					SYMCLK32_SE1_GATE_DISABLE, 0,
250					SYMCLK32_ROOT_SE1_GATE_DISABLE, 0);
251		break;
252	case 2:
253		REG_UPDATE_2(SYMCLK32_SE_CNTL,
254				SYMCLK32_SE2_SRC_SEL, 0,
255				SYMCLK32_SE2_EN, 0);
256		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
257			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
258					SYMCLK32_SE2_GATE_DISABLE, 0,
259					SYMCLK32_ROOT_SE2_GATE_DISABLE, 0);
260		break;
261	case 3:
262		REG_UPDATE_2(SYMCLK32_SE_CNTL,
263				SYMCLK32_SE3_SRC_SEL, 0,
264				SYMCLK32_SE3_EN, 0);
265		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
266			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
267					SYMCLK32_SE3_GATE_DISABLE, 0,
268					SYMCLK32_ROOT_SE3_GATE_DISABLE, 0);
269		break;
270	default:
271		BREAK_TO_DEBUGGER();
272		return;
273	}
274}
275
276void dccg31_enable_symclk32_le(
277		struct dccg *dccg,
278		int hpo_le_inst,
279		enum phyd32clk_clock_source phyd32clk)
280{
281	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
282
283	phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
284
285	/* select one of the PHYD32CLKs as the source for symclk32_le */
286	switch (hpo_le_inst) {
287	case 0:
288		REG_UPDATE_2(SYMCLK32_LE_CNTL,
289				SYMCLK32_LE0_SRC_SEL, phyd32clk,
290				SYMCLK32_LE0_EN, 1);
291		break;
292	case 1:
293		REG_UPDATE_2(SYMCLK32_LE_CNTL,
294				SYMCLK32_LE1_SRC_SEL, phyd32clk,
295				SYMCLK32_LE1_EN, 1);
296		break;
297	default:
298		BREAK_TO_DEBUGGER();
299		return;
300	}
301}
302
303void dccg31_disable_symclk32_le(
304		struct dccg *dccg,
305		int hpo_le_inst)
306{
307	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
308
309	/* set refclk as the source for symclk32_le */
310	switch (hpo_le_inst) {
311	case 0:
312		REG_UPDATE_2(SYMCLK32_LE_CNTL,
313				SYMCLK32_LE0_SRC_SEL, 0,
314				SYMCLK32_LE0_EN, 0);
315		break;
316	case 1:
317		REG_UPDATE_2(SYMCLK32_LE_CNTL,
318				SYMCLK32_LE1_SRC_SEL, 0,
319				SYMCLK32_LE1_EN, 0);
320		break;
321	default:
322		BREAK_TO_DEBUGGER();
323		return;
324	}
325}
326
327void dccg31_set_symclk32_le_root_clock_gating(
328		struct dccg *dccg,
329		int hpo_le_inst,
330		bool enable)
331{
332	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
333
334	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
335		return;
336
337	switch (hpo_le_inst) {
338	case 0:
339		REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
340				SYMCLK32_LE0_GATE_DISABLE, enable ? 1 : 0,
341				SYMCLK32_ROOT_LE0_GATE_DISABLE, enable ? 1 : 0);
342		break;
343	case 1:
344		REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
345				SYMCLK32_LE1_GATE_DISABLE, enable ? 1 : 0,
346				SYMCLK32_ROOT_LE1_GATE_DISABLE, enable ? 1 : 0);
347		break;
348	default:
349		BREAK_TO_DEBUGGER();
350		return;
351	}
352}
353
354void dccg31_disable_dscclk(struct dccg *dccg, int inst)
355{
356	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
357
358	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
359		return;
360	//DTO must be enabled to generate a 0 Hz clock output
361	switch (inst) {
362	case 0:
363		REG_UPDATE(DSCCLK_DTO_CTRL,
364				DSCCLK0_DTO_ENABLE, 1);
365		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
366				DSCCLK0_DTO_PHASE, 0,
367				DSCCLK0_DTO_MODULO, 1);
368		break;
369	case 1:
370		REG_UPDATE(DSCCLK_DTO_CTRL,
371				DSCCLK1_DTO_ENABLE, 1);
372		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
373				DSCCLK1_DTO_PHASE, 0,
374				DSCCLK1_DTO_MODULO, 1);
375		break;
376	case 2:
377		REG_UPDATE(DSCCLK_DTO_CTRL,
378				DSCCLK2_DTO_ENABLE, 1);
379		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
380				DSCCLK2_DTO_PHASE, 0,
381				DSCCLK2_DTO_MODULO, 1);
382		break;
383	case 3:
384		if (REG(DSCCLK3_DTO_PARAM)) {
385			REG_UPDATE(DSCCLK_DTO_CTRL,
386					DSCCLK3_DTO_ENABLE, 1);
387			REG_UPDATE_2(DSCCLK3_DTO_PARAM,
388					DSCCLK3_DTO_PHASE, 0,
389					DSCCLK3_DTO_MODULO, 1);
390		}
391		break;
392	default:
393		BREAK_TO_DEBUGGER();
394		return;
395	}
396}
397
398void dccg31_enable_dscclk(struct dccg *dccg, int inst)
399{
400	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
401
402	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
403		return;
404	//Disable DTO
405	switch (inst) {
406	case 0:
407		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
408				DSCCLK0_DTO_PHASE, 0,
409				DSCCLK0_DTO_MODULO, 0);
410		REG_UPDATE(DSCCLK_DTO_CTRL,
411				DSCCLK0_DTO_ENABLE, 0);
412		break;
413	case 1:
414		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
415				DSCCLK1_DTO_PHASE, 0,
416				DSCCLK1_DTO_MODULO, 0);
417		REG_UPDATE(DSCCLK_DTO_CTRL,
418				DSCCLK1_DTO_ENABLE, 0);
419		break;
420	case 2:
421		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
422				DSCCLK2_DTO_PHASE, 0,
423				DSCCLK2_DTO_MODULO, 0);
424		REG_UPDATE(DSCCLK_DTO_CTRL,
425				DSCCLK2_DTO_ENABLE, 0);
426		break;
427	case 3:
428		if (REG(DSCCLK3_DTO_PARAM)) {
429			REG_UPDATE(DSCCLK_DTO_CTRL,
430					DSCCLK3_DTO_ENABLE, 0);
431			REG_UPDATE_2(DSCCLK3_DTO_PARAM,
432					DSCCLK3_DTO_PHASE, 0,
433					DSCCLK3_DTO_MODULO, 0);
434		}
435		break;
436	default:
437		BREAK_TO_DEBUGGER();
438		return;
439	}
440}
441
442void dccg31_set_physymclk(
443		struct dccg *dccg,
444		int phy_inst,
445		enum physymclk_clock_source clk_src,
446		bool force_enable)
447{
448	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
449
450	/* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
451	switch (phy_inst) {
452	case 0:
453		if (force_enable) {
454			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
455					PHYASYMCLK_FORCE_EN, 1,
456					PHYASYMCLK_FORCE_SRC_SEL, clk_src);
457			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
458				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
459					PHYASYMCLK_GATE_DISABLE, 1);
460		} else {
461			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
462					PHYASYMCLK_FORCE_EN, 0,
463					PHYASYMCLK_FORCE_SRC_SEL, 0);
464			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
465				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
466					PHYASYMCLK_GATE_DISABLE, 0);
467		}
468		break;
469	case 1:
470		if (force_enable) {
471			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
472					PHYBSYMCLK_FORCE_EN, 1,
473					PHYBSYMCLK_FORCE_SRC_SEL, clk_src);
474			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
475				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
476					PHYBSYMCLK_GATE_DISABLE, 1);
477		} else {
478			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
479					PHYBSYMCLK_FORCE_EN, 0,
480					PHYBSYMCLK_FORCE_SRC_SEL, 0);
481			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
482				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
483					PHYBSYMCLK_GATE_DISABLE, 0);
484		}
485		break;
486	case 2:
487		if (force_enable) {
488			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
489					PHYCSYMCLK_FORCE_EN, 1,
490					PHYCSYMCLK_FORCE_SRC_SEL, clk_src);
491			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
492				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
493					PHYCSYMCLK_GATE_DISABLE, 1);
494		} else {
495			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
496					PHYCSYMCLK_FORCE_EN, 0,
497					PHYCSYMCLK_FORCE_SRC_SEL, 0);
498			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
499				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
500					PHYCSYMCLK_GATE_DISABLE, 0);
501		}
502		break;
503	case 3:
504		if (force_enable) {
505			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
506					PHYDSYMCLK_FORCE_EN, 1,
507					PHYDSYMCLK_FORCE_SRC_SEL, clk_src);
508			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
509				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
510					PHYDSYMCLK_GATE_DISABLE, 1);
511		} else {
512			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
513					PHYDSYMCLK_FORCE_EN, 0,
514					PHYDSYMCLK_FORCE_SRC_SEL, 0);
515			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
516				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
517					PHYDSYMCLK_GATE_DISABLE, 0);
518		}
519		break;
520	case 4:
521		if (force_enable) {
522			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
523					PHYESYMCLK_FORCE_EN, 1,
524					PHYESYMCLK_FORCE_SRC_SEL, clk_src);
525			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
526				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
527					PHYESYMCLK_GATE_DISABLE, 1);
528		} else {
529			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
530					PHYESYMCLK_FORCE_EN, 0,
531					PHYESYMCLK_FORCE_SRC_SEL, 0);
532			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
533				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
534					PHYESYMCLK_GATE_DISABLE, 0);
535		}
536		break;
537	default:
538		BREAK_TO_DEBUGGER();
539		return;
540	}
541}
542
543/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
544void dccg31_set_dtbclk_dto(
545		struct dccg *dccg,
546		const struct dtbclk_dto_params *params)
547{
548	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
549	int req_dtbclk_khz = params->pixclk_khz;
550	uint32_t dtbdto_div;
551
552	/* Mode	                DTBDTO Rate       DTBCLK_DTO<x>_DIV Register
553	 * ODM 4:1 combine      pixel rate/4      2
554	 * ODM 2:1 combine      pixel rate/2      4
555	 * non-DSC 4:2:0 mode   pixel rate/2      4
556	 * DSC native 4:2:0     pixel rate/2      4
557	 * DSC native 4:2:2     pixel rate/2      4
558	 * Other modes          pixel rate        8
559	 */
560	if (params->num_odm_segments == 4) {
561		dtbdto_div = 2;
562		req_dtbclk_khz = params->pixclk_khz / 4;
563	} else if ((params->num_odm_segments == 2) ||
564			(params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
565			(params->timing->flags.DSC && params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
566					&& !params->timing->dsc_cfg.ycbcr422_simple)) {
567		dtbdto_div = 4;
568		req_dtbclk_khz = params->pixclk_khz / 2;
569	} else
570		dtbdto_div = 8;
571
572	if (params->ref_dtbclk_khz && req_dtbclk_khz) {
573		uint32_t modulo, phase;
574
575		// phase / modulo = dtbclk / dtbclk ref
576		modulo = params->ref_dtbclk_khz * 1000;
577		phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + params->ref_dtbclk_khz - 1),
578				params->ref_dtbclk_khz);
579
580		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
581				DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
582
583		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
584		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
585
586		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
587				DTBCLK_DTO_ENABLE[params->otg_inst], 1);
588
589		REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
590				DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
591				1, 100);
592
593		/* The recommended programming sequence to enable DTBCLK DTO to generate
594		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
595		 * be set only after DTO is enabled
596		 */
597		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
598				PIPE_DTO_SRC_SEL[params->otg_inst], 1);
599	} else {
600		REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[params->otg_inst],
601				DTBCLK_DTO_ENABLE[params->otg_inst], 0,
602				PIPE_DTO_SRC_SEL[params->otg_inst], 0,
603				DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
604
605		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
606		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
607	}
608}
609
610void dccg31_set_audio_dtbclk_dto(
611		struct dccg *dccg,
612		const struct dtbclk_dto_params *params)
613{
614	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
615
616	if (params->ref_dtbclk_khz && params->req_audio_dtbclk_khz) {
617		uint32_t modulo, phase;
618
619		// phase / modulo = dtbclk / dtbclk ref
620		modulo = params->ref_dtbclk_khz * 1000;
621		phase = div_u64((((unsigned long long)modulo * params->req_audio_dtbclk_khz) + params->ref_dtbclk_khz - 1),
622			params->ref_dtbclk_khz);
623
624
625		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);
626		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);
627
628		//REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
629		//		DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1);
630
631		REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
632				DCCG_AUDIO_DTO_SEL, 4);  //  04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK
633	} else {
634		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0);
635		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0);
636
637		REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
638				DCCG_AUDIO_DTO_SEL, 3);  //  03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO
639	}
640}
641
642void dccg31_get_dccg_ref_freq(struct dccg *dccg,
643		unsigned int xtalin_freq_inKhz,
644		unsigned int *dccg_ref_freq_inKhz)
645{
646	/*
647	 * Assume refclk is sourced from xtalin
648	 * expect 24MHz
649	 */
650	*dccg_ref_freq_inKhz = xtalin_freq_inKhz;
651	return;
652}
653
654void dccg31_set_dispclk_change_mode(
655	struct dccg *dccg,
656	enum dentist_dispclk_change_mode change_mode)
657{
658	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
659
660	REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE,
661		   change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);
662}
663
664void dccg31_init(struct dccg *dccg)
665{
666	/* Set HPO stream encoder to use refclk to avoid case where PHY is
667	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
668	 * will cause DCN to hang.
669	 */
670	dccg31_disable_symclk32_se(dccg, 0);
671	dccg31_disable_symclk32_se(dccg, 1);
672	dccg31_disable_symclk32_se(dccg, 2);
673	dccg31_disable_symclk32_se(dccg, 3);
674
675	dccg31_set_symclk32_le_root_clock_gating(dccg, 0, false);
676	dccg31_set_symclk32_le_root_clock_gating(dccg, 1, false);
677
678	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
679		dccg31_disable_dpstreamclk(dccg, 0);
680		dccg31_disable_dpstreamclk(dccg, 1);
681		dccg31_disable_dpstreamclk(dccg, 2);
682		dccg31_disable_dpstreamclk(dccg, 3);
683	}
684
685	if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
686		dccg31_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
687		dccg31_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
688		dccg31_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
689		dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
690		dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
691	}
692}
693
694void dccg31_otg_add_pixel(struct dccg *dccg,
695				 uint32_t otg_inst)
696{
697	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
698
699	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
700			OTG_ADD_PIXEL[otg_inst], 1);
701}
702
703void dccg31_otg_drop_pixel(struct dccg *dccg,
704				  uint32_t otg_inst)
705{
706	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
707
708	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
709			OTG_DROP_PIXEL[otg_inst], 1);
710}
711
712static const struct dccg_funcs dccg31_funcs = {
713	.update_dpp_dto = dccg31_update_dpp_dto,
714	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
715	.dccg_init = dccg31_init,
716	.set_dpstreamclk = dccg31_set_dpstreamclk,
717	.enable_symclk32_se = dccg31_enable_symclk32_se,
718	.disable_symclk32_se = dccg31_disable_symclk32_se,
719	.enable_symclk32_le = dccg31_enable_symclk32_le,
720	.disable_symclk32_le = dccg31_disable_symclk32_le,
721	.set_physymclk = dccg31_set_physymclk,
722	.set_dtbclk_dto = dccg31_set_dtbclk_dto,
723	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
724	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
725	.otg_add_pixel = dccg31_otg_add_pixel,
726	.otg_drop_pixel = dccg31_otg_drop_pixel,
727	.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
728	.disable_dsc = dccg31_disable_dscclk,
729	.enable_dsc = dccg31_enable_dscclk,
730};
731
732struct dccg *dccg31_create(
733	struct dc_context *ctx,
734	const struct dccg_registers *regs,
735	const struct dccg_shift *dccg_shift,
736	const struct dccg_mask *dccg_mask)
737{
738	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
739	struct dccg *base;
740
741	if (dccg_dcn == NULL) {
742		BREAK_TO_DEBUGGER();
743		return NULL;
744	}
745
746	base = &dccg_dcn->base;
747	base->ctx = ctx;
748	base->funcs = &dccg31_funcs;
749
750	dccg_dcn->regs = regs;
751	dccg_dcn->dccg_shift = dccg_shift;
752	dccg_dcn->dccg_mask = dccg_mask;
753
754	return &dccg_dcn->base;
755}
756