Linux Audio

Check our new training course

Loading...
v6.9.4
  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}
v6.2
  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->ref_dppclk && req_dppclk) {
 51		int ref_dppclk = dccg->ref_dppclk;
 52		int modulo, phase;
 53
 54		// phase / modulo = dpp pipe clk / dpp global clk
 55		modulo = 0xff;   // use FF at the end
 56		phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
 57
 58		if (phase > 0xff) {
 59			ASSERT(false);
 60			phase = 0xff;
 61		}
 62
 63		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
 64				DPPCLK0_DTO_PHASE, phase,
 65				DPPCLK0_DTO_MODULO, modulo);
 66		REG_UPDATE(DPPCLK_DTO_CTRL,
 67				DPPCLK_DTO_ENABLE[dpp_inst], 1);
 68	} else {
 69		//DTO must be enabled to generate a 0Hz clock output
 70		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
 71			REG_UPDATE(DPPCLK_DTO_CTRL,
 72					DPPCLK_DTO_ENABLE[dpp_inst], 1);
 73			REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
 74					DPPCLK0_DTO_PHASE, 0,
 75					DPPCLK0_DTO_MODULO, 1);
 76		} else {
 77			REG_UPDATE(DPPCLK_DTO_CTRL,
 78					DPPCLK_DTO_ENABLE[dpp_inst], 0);
 79		}
 80	}
 81	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
 82}
 83
 84static enum phyd32clk_clock_source get_phy_mux_symclk(
 85		struct dcn_dccg *dccg_dcn,
 86		enum phyd32clk_clock_source src)
 87{
 88	if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
 
 89		if (src == PHYD32CLKC)
 90			src = PHYD32CLKF;
 91		if (src == PHYD32CLKD)
 92			src = PHYD32CLKG;
 93	}
 94	return src;
 95}
 96
 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		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
289			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
290					SYMCLK32_LE0_GATE_DISABLE, 1,
291					SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
292		REG_UPDATE_2(SYMCLK32_LE_CNTL,
293				SYMCLK32_LE0_SRC_SEL, phyd32clk,
294				SYMCLK32_LE0_EN, 1);
295		break;
296	case 1:
297		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
298			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
299					SYMCLK32_LE1_GATE_DISABLE, 1,
300					SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
301		REG_UPDATE_2(SYMCLK32_LE_CNTL,
302				SYMCLK32_LE1_SRC_SEL, phyd32clk,
303				SYMCLK32_LE1_EN, 1);
304		break;
305	default:
306		BREAK_TO_DEBUGGER();
307		return;
308	}
309}
310
311void dccg31_disable_symclk32_le(
312		struct dccg *dccg,
313		int hpo_le_inst)
314{
315	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
316
317	/* set refclk as the source for symclk32_le */
318	switch (hpo_le_inst) {
319	case 0:
320		REG_UPDATE_2(SYMCLK32_LE_CNTL,
321				SYMCLK32_LE0_SRC_SEL, 0,
322				SYMCLK32_LE0_EN, 0);
323		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
324			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
325					SYMCLK32_LE0_GATE_DISABLE, 0,
326					SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);
327		break;
328	case 1:
329		REG_UPDATE_2(SYMCLK32_LE_CNTL,
330				SYMCLK32_LE1_SRC_SEL, 0,
331				SYMCLK32_LE1_EN, 0);
332		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
333			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
334					SYMCLK32_LE1_GATE_DISABLE, 0,
335					SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336		break;
337	default:
338		BREAK_TO_DEBUGGER();
339		return;
340	}
341}
342
343void dccg31_disable_dscclk(struct dccg *dccg, int inst)
344{
345	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
346
347	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
348		return;
349	//DTO must be enabled to generate a 0 Hz clock output
350	switch (inst) {
351	case 0:
352		REG_UPDATE(DSCCLK_DTO_CTRL,
353				DSCCLK0_DTO_ENABLE, 1);
354		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
355				DSCCLK0_DTO_PHASE, 0,
356				DSCCLK0_DTO_MODULO, 1);
357		break;
358	case 1:
359		REG_UPDATE(DSCCLK_DTO_CTRL,
360				DSCCLK1_DTO_ENABLE, 1);
361		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
362				DSCCLK1_DTO_PHASE, 0,
363				DSCCLK1_DTO_MODULO, 1);
364		break;
365	case 2:
366		REG_UPDATE(DSCCLK_DTO_CTRL,
367				DSCCLK2_DTO_ENABLE, 1);
368		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
369				DSCCLK2_DTO_PHASE, 0,
370				DSCCLK2_DTO_MODULO, 1);
371		break;
 
 
 
 
 
 
 
 
 
372	default:
373		BREAK_TO_DEBUGGER();
374		return;
375	}
376}
377
378void dccg31_enable_dscclk(struct dccg *dccg, int inst)
379{
380	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
381
382	if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
383		return;
384	//Disable DTO
385	switch (inst) {
386	case 0:
387		REG_UPDATE_2(DSCCLK0_DTO_PARAM,
388				DSCCLK0_DTO_PHASE, 0,
389				DSCCLK0_DTO_MODULO, 0);
390		REG_UPDATE(DSCCLK_DTO_CTRL,
391				DSCCLK0_DTO_ENABLE, 0);
392		break;
393	case 1:
394		REG_UPDATE_2(DSCCLK1_DTO_PARAM,
395				DSCCLK1_DTO_PHASE, 0,
396				DSCCLK1_DTO_MODULO, 0);
397		REG_UPDATE(DSCCLK_DTO_CTRL,
398				DSCCLK1_DTO_ENABLE, 0);
399		break;
400	case 2:
401		REG_UPDATE_2(DSCCLK2_DTO_PARAM,
402				DSCCLK2_DTO_PHASE, 0,
403				DSCCLK2_DTO_MODULO, 0);
404		REG_UPDATE(DSCCLK_DTO_CTRL,
405				DSCCLK2_DTO_ENABLE, 0);
406		break;
 
 
 
 
 
 
 
 
 
407	default:
408		BREAK_TO_DEBUGGER();
409		return;
410	}
411}
412
413void dccg31_set_physymclk(
414		struct dccg *dccg,
415		int phy_inst,
416		enum physymclk_clock_source clk_src,
417		bool force_enable)
418{
419	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
420
421	/* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
422	switch (phy_inst) {
423	case 0:
424		if (force_enable) {
425			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
426					PHYASYMCLK_FORCE_EN, 1,
427					PHYASYMCLK_FORCE_SRC_SEL, clk_src);
428			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
429				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
430					PHYASYMCLK_GATE_DISABLE, 1);
431		} else {
432			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
433					PHYASYMCLK_FORCE_EN, 0,
434					PHYASYMCLK_FORCE_SRC_SEL, 0);
435			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
436				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
437					PHYASYMCLK_GATE_DISABLE, 0);
438		}
439		break;
440	case 1:
441		if (force_enable) {
442			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
443					PHYBSYMCLK_FORCE_EN, 1,
444					PHYBSYMCLK_FORCE_SRC_SEL, clk_src);
445			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
446				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
447					PHYBSYMCLK_GATE_DISABLE, 1);
448		} else {
449			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
450					PHYBSYMCLK_FORCE_EN, 0,
451					PHYBSYMCLK_FORCE_SRC_SEL, 0);
452			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
453				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
454					PHYBSYMCLK_GATE_DISABLE, 0);
455		}
456		break;
457	case 2:
458		if (force_enable) {
459			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
460					PHYCSYMCLK_FORCE_EN, 1,
461					PHYCSYMCLK_FORCE_SRC_SEL, clk_src);
462			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
463				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
464					PHYCSYMCLK_GATE_DISABLE, 1);
465		} else {
466			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
467					PHYCSYMCLK_FORCE_EN, 0,
468					PHYCSYMCLK_FORCE_SRC_SEL, 0);
469			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
470				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
471					PHYCSYMCLK_GATE_DISABLE, 0);
472		}
473		break;
474	case 3:
475		if (force_enable) {
476			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
477					PHYDSYMCLK_FORCE_EN, 1,
478					PHYDSYMCLK_FORCE_SRC_SEL, clk_src);
479			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
480				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
481					PHYDSYMCLK_GATE_DISABLE, 1);
482		} else {
483			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
484					PHYDSYMCLK_FORCE_EN, 0,
485					PHYDSYMCLK_FORCE_SRC_SEL, 0);
486			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
487				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
488					PHYDSYMCLK_GATE_DISABLE, 0);
489		}
490		break;
491	case 4:
492		if (force_enable) {
493			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
494					PHYESYMCLK_FORCE_EN, 1,
495					PHYESYMCLK_FORCE_SRC_SEL, clk_src);
496			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
497				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
498					PHYESYMCLK_GATE_DISABLE, 1);
499		} else {
500			REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
501					PHYESYMCLK_FORCE_EN, 0,
502					PHYESYMCLK_FORCE_SRC_SEL, 0);
503			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
504				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
505					PHYESYMCLK_GATE_DISABLE, 0);
506		}
507		break;
508	default:
509		BREAK_TO_DEBUGGER();
510		return;
511	}
512}
513
514/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
515void dccg31_set_dtbclk_dto(
516		struct dccg *dccg,
517		const struct dtbclk_dto_params *params)
518{
519	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
520	int req_dtbclk_khz = params->pixclk_khz;
521	uint32_t dtbdto_div;
522
523	/* Mode	                DTBDTO Rate       DTBCLK_DTO<x>_DIV Register
524	 * ODM 4:1 combine      pixel rate/4      2
525	 * ODM 2:1 combine      pixel rate/2      4
526	 * non-DSC 4:2:0 mode   pixel rate/2      4
527	 * DSC native 4:2:0     pixel rate/2      4
528	 * DSC native 4:2:2     pixel rate/2      4
529	 * Other modes          pixel rate        8
530	 */
531	if (params->num_odm_segments == 4) {
532		dtbdto_div = 2;
533		req_dtbclk_khz = params->pixclk_khz / 4;
534	} else if ((params->num_odm_segments == 2) ||
535			(params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
536			(params->timing->flags.DSC && params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
537					&& !params->timing->dsc_cfg.ycbcr422_simple)) {
538		dtbdto_div = 4;
539		req_dtbclk_khz = params->pixclk_khz / 2;
540	} else
541		dtbdto_div = 8;
542
543	if (params->ref_dtbclk_khz && req_dtbclk_khz) {
544		uint32_t modulo, phase;
545
546		// phase / modulo = dtbclk / dtbclk ref
547		modulo = params->ref_dtbclk_khz * 1000;
548		phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + params->ref_dtbclk_khz - 1),
549				params->ref_dtbclk_khz);
550
551		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
552				DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
553
554		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
555		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
556
557		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
558				DTBCLK_DTO_ENABLE[params->otg_inst], 1);
559
560		REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
561				DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
562				1, 100);
563
564		/* The recommended programming sequence to enable DTBCLK DTO to generate
565		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
566		 * be set only after DTO is enabled
567		 */
568		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
569				PIPE_DTO_SRC_SEL[params->otg_inst], 1);
570	} else {
571		REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[params->otg_inst],
572				DTBCLK_DTO_ENABLE[params->otg_inst], 0,
573				PIPE_DTO_SRC_SEL[params->otg_inst], 0,
574				DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
575
576		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
577		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
578	}
579}
580
581void dccg31_set_audio_dtbclk_dto(
582		struct dccg *dccg,
583		const struct dtbclk_dto_params *params)
584{
585	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
586
587	if (params->ref_dtbclk_khz && params->req_audio_dtbclk_khz) {
588		uint32_t modulo, phase;
589
590		// phase / modulo = dtbclk / dtbclk ref
591		modulo = params->ref_dtbclk_khz * 1000;
592		phase = div_u64((((unsigned long long)modulo * params->req_audio_dtbclk_khz) + params->ref_dtbclk_khz - 1),
593			params->ref_dtbclk_khz);
594
595
596		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);
597		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);
598
599		//REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
600		//		DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1);
601
602		REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
603				DCCG_AUDIO_DTO_SEL, 4);  //  04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK
604	} else {
605		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0);
606		REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0);
607
608		REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
609				DCCG_AUDIO_DTO_SEL, 3);  //  03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO
610	}
611}
612
613void dccg31_get_dccg_ref_freq(struct dccg *dccg,
614		unsigned int xtalin_freq_inKhz,
615		unsigned int *dccg_ref_freq_inKhz)
616{
617	/*
618	 * Assume refclk is sourced from xtalin
619	 * expect 24MHz
620	 */
621	*dccg_ref_freq_inKhz = xtalin_freq_inKhz;
622	return;
623}
624
625void dccg31_set_dispclk_change_mode(
626	struct dccg *dccg,
627	enum dentist_dispclk_change_mode change_mode)
628{
629	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
630
631	REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE,
632		   change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);
633}
634
635void dccg31_init(struct dccg *dccg)
636{
637	/* Set HPO stream encoder to use refclk to avoid case where PHY is
638	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
639	 * will cause DCN to hang.
640	 */
641	dccg31_disable_symclk32_se(dccg, 0);
642	dccg31_disable_symclk32_se(dccg, 1);
643	dccg31_disable_symclk32_se(dccg, 2);
644	dccg31_disable_symclk32_se(dccg, 3);
645
646	if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
647		dccg31_disable_symclk32_le(dccg, 0);
648		dccg31_disable_symclk32_le(dccg, 1);
649	}
650
651	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
652		dccg31_disable_dpstreamclk(dccg, 0);
653		dccg31_disable_dpstreamclk(dccg, 1);
654		dccg31_disable_dpstreamclk(dccg, 2);
655		dccg31_disable_dpstreamclk(dccg, 3);
656	}
657
658	if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
659		dccg31_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
660		dccg31_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
661		dccg31_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
662		dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
663		dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
664	}
665}
666
667void dccg31_otg_add_pixel(struct dccg *dccg,
668				 uint32_t otg_inst)
669{
670	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
671
672	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
673			OTG_ADD_PIXEL[otg_inst], 1);
674}
675
676void dccg31_otg_drop_pixel(struct dccg *dccg,
677				  uint32_t otg_inst)
678{
679	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
680
681	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
682			OTG_DROP_PIXEL[otg_inst], 1);
683}
684
685static const struct dccg_funcs dccg31_funcs = {
686	.update_dpp_dto = dccg31_update_dpp_dto,
687	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
688	.dccg_init = dccg31_init,
689	.set_dpstreamclk = dccg31_set_dpstreamclk,
690	.enable_symclk32_se = dccg31_enable_symclk32_se,
691	.disable_symclk32_se = dccg31_disable_symclk32_se,
692	.enable_symclk32_le = dccg31_enable_symclk32_le,
693	.disable_symclk32_le = dccg31_disable_symclk32_le,
694	.set_physymclk = dccg31_set_physymclk,
695	.set_dtbclk_dto = dccg31_set_dtbclk_dto,
696	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
697	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
698	.otg_add_pixel = dccg31_otg_add_pixel,
699	.otg_drop_pixel = dccg31_otg_drop_pixel,
700	.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
701	.disable_dsc = dccg31_disable_dscclk,
702	.enable_dsc = dccg31_enable_dscclk,
703};
704
705struct dccg *dccg31_create(
706	struct dc_context *ctx,
707	const struct dccg_registers *regs,
708	const struct dccg_shift *dccg_shift,
709	const struct dccg_mask *dccg_mask)
710{
711	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
712	struct dccg *base;
713
714	if (dccg_dcn == NULL) {
715		BREAK_TO_DEBUGGER();
716		return NULL;
717	}
718
719	base = &dccg_dcn->base;
720	base->ctx = ctx;
721	base->funcs = &dccg31_funcs;
722
723	dccg_dcn->regs = regs;
724	dccg_dcn->dccg_shift = dccg_shift;
725	dccg_dcn->dccg_mask = dccg_mask;
726
727	return &dccg_dcn->base;
728}