File Index
Files and directories
Sign in
FILE

dcn401_dccg.c

File preview with syntax highlighting.

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