1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2022 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 
27 #include "reg_helper.h"
28 #include "core_types.h"
29 
30 #include "dcn31/dcn31_dccg.h"
31 #include "dcn314_dccg.h"
32 
33 #define TO_DCN_DCCG(dccg)\
34 	container_of(dccg, struct dcn_dccg, base)
35 
36 #define REG(reg) \
37 	(dccg_dcn->regs->reg)
38 
39 #undef FN
40 #define FN(reg_name, field_name) \
41 	dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
42 
43 #define CTX \
44 	dccg_dcn->base.ctx
45 #define DC_LOGGER \
46 	dccg->ctx->logger
47 
48 static void dccg314_get_pixel_rate_div(
49 		struct dccg *dccg,
50 		uint32_t otg_inst,
51 		enum pixel_rate_div *k1,
52 		enum pixel_rate_div *k2)
53 {
54 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
55 	uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
56 
57 	*k1 = PIXEL_RATE_DIV_NA;
58 	*k2 = PIXEL_RATE_DIV_NA;
59 
60 	switch (otg_inst) {
61 	case 0:
62 		REG_GET_2(OTG_PIXEL_RATE_DIV,
63 			OTG0_PIXEL_RATE_DIVK1, &val_k1,
64 			OTG0_PIXEL_RATE_DIVK2, &val_k2);
65 		break;
66 	case 1:
67 		REG_GET_2(OTG_PIXEL_RATE_DIV,
68 			OTG1_PIXEL_RATE_DIVK1, &val_k1,
69 			OTG1_PIXEL_RATE_DIVK2, &val_k2);
70 		break;
71 	case 2:
72 		REG_GET_2(OTG_PIXEL_RATE_DIV,
73 			OTG2_PIXEL_RATE_DIVK1, &val_k1,
74 			OTG2_PIXEL_RATE_DIVK2, &val_k2);
75 		break;
76 	case 3:
77 		REG_GET_2(OTG_PIXEL_RATE_DIV,
78 			OTG3_PIXEL_RATE_DIVK1, &val_k1,
79 			OTG3_PIXEL_RATE_DIVK2, &val_k2);
80 		break;
81 	default:
82 		BREAK_TO_DEBUGGER();
83 		return;
84 	}
85 
86 	*k1 = (enum pixel_rate_div)val_k1;
87 	*k2 = (enum pixel_rate_div)val_k2;
88 }
89 
90 static void dccg314_set_pixel_rate_div(
91 		struct dccg *dccg,
92 		uint32_t otg_inst,
93 		enum pixel_rate_div k1,
94 		enum pixel_rate_div k2)
95 {
96 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
97 	enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
98 
99 	// Don't program 0xF into the register field. Not valid since
100 	// K1 / K2 field is only 1 / 2 bits wide
101 	if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) {
102 		BREAK_TO_DEBUGGER();
103 		return;
104 	}
105 
106 	dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
107 	if (k1 == cur_k1 && k2 == cur_k2)
108 		return;
109 
110 	switch (otg_inst) {
111 	case 0:
112 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
113 				OTG0_PIXEL_RATE_DIVK1, k1,
114 				OTG0_PIXEL_RATE_DIVK2, k2);
115 		break;
116 	case 1:
117 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
118 				OTG1_PIXEL_RATE_DIVK1, k1,
119 				OTG1_PIXEL_RATE_DIVK2, k2);
120 		break;
121 	case 2:
122 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
123 				OTG2_PIXEL_RATE_DIVK1, k1,
124 				OTG2_PIXEL_RATE_DIVK2, k2);
125 		break;
126 	case 3:
127 		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
128 				OTG3_PIXEL_RATE_DIVK1, k1,
129 				OTG3_PIXEL_RATE_DIVK2, k2);
130 		break;
131 	default:
132 		BREAK_TO_DEBUGGER();
133 		return;
134 	}
135 }
136 
137 static void dccg314_set_dtbclk_p_src(
138 		struct dccg *dccg,
139 		enum streamclk_source src,
140 		uint32_t otg_inst)
141 {
142 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
143 
144 	uint32_t p_src_sel = 0; /* selects dprefclk */
145 
146 	if (src == DTBCLK0)
147 		p_src_sel = 2;  /* selects dtbclk0 */
148 
149 	switch (otg_inst) {
150 	case 0:
151 		if (src == REFCLK)
152 			REG_UPDATE(DTBCLK_P_CNTL,
153 					DTBCLK_P0_EN, 0);
154 		else
155 			REG_UPDATE_2(DTBCLK_P_CNTL,
156 					DTBCLK_P0_SRC_SEL, p_src_sel,
157 					DTBCLK_P0_EN, 1);
158 		break;
159 	case 1:
160 		if (src == REFCLK)
161 			REG_UPDATE(DTBCLK_P_CNTL,
162 					DTBCLK_P1_EN, 0);
163 		else
164 			REG_UPDATE_2(DTBCLK_P_CNTL,
165 					DTBCLK_P1_SRC_SEL, p_src_sel,
166 					DTBCLK_P1_EN, 1);
167 		break;
168 	case 2:
169 		if (src == REFCLK)
170 			REG_UPDATE(DTBCLK_P_CNTL,
171 					DTBCLK_P2_EN, 0);
172 		else
173 			REG_UPDATE_2(DTBCLK_P_CNTL,
174 					DTBCLK_P2_SRC_SEL, p_src_sel,
175 					DTBCLK_P2_EN, 1);
176 		break;
177 	case 3:
178 		if (src == REFCLK)
179 			REG_UPDATE(DTBCLK_P_CNTL,
180 					DTBCLK_P3_EN, 0);
181 		else
182 			REG_UPDATE_2(DTBCLK_P_CNTL,
183 					DTBCLK_P3_SRC_SEL, p_src_sel,
184 					DTBCLK_P3_EN, 1);
185 		break;
186 	default:
187 		BREAK_TO_DEBUGGER();
188 		return;
189 	}
190 
191 }
192 
193 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
194 static void dccg314_set_dtbclk_dto(
195 		struct dccg *dccg,
196 		const struct dtbclk_dto_params *params)
197 {
198 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
199 	/* DTO Output Rate / Pixel Rate = 1/4 */
200 	int req_dtbclk_khz = params->pixclk_khz / 4;
201 
202 	if (params->ref_dtbclk_khz && req_dtbclk_khz) {
203 		uint32_t modulo, phase;
204 
205 		// phase / modulo = dtbclk / dtbclk ref
206 		modulo = params->ref_dtbclk_khz * 1000;
207 		phase = req_dtbclk_khz * 1000;
208 
209 		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
210 		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
211 
212 		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
213 				DTBCLK_DTO_ENABLE[params->otg_inst], 1);
214 
215 		REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
216 				DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
217 				1, 100);
218 
219 		/* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */
220 		dccg314_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);
221 
222 		/* The recommended programming sequence to enable DTBCLK DTO to generate
223 		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
224 		 * be set only after DTO is enabled
225 		 */
226 		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
227 				PIPE_DTO_SRC_SEL[params->otg_inst], 2);
228 	} else {
229 		REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
230 				DTBCLK_DTO_ENABLE[params->otg_inst], 0,
231 				PIPE_DTO_SRC_SEL[params->otg_inst], 1);
232 
233 		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
234 		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
235 	}
236 }
237 
238 static void dccg314_set_dpstreamclk(
239 		struct dccg *dccg,
240 		enum streamclk_source src,
241 		int otg_inst,
242 		int dp_hpo_inst)
243 {
244 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
245 
246 	/* set the dtbclk_p source */
247 	dccg314_set_dtbclk_p_src(dccg, src, otg_inst);
248 
249 	/* enabled to select one of the DTBCLKs for pipe */
250 	switch (dp_hpo_inst) {
251 	case 0:
252 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
253 					DPSTREAMCLK0_EN, (src == REFCLK) ? 0 : 1,
254 					DPSTREAMCLK0_SRC_SEL, otg_inst);
255 		break;
256 	case 1:
257 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
258 					DPSTREAMCLK1_EN, (src == REFCLK) ? 0 : 1,
259 					DPSTREAMCLK1_SRC_SEL, otg_inst);
260 		break;
261 	case 2:
262 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
263 					DPSTREAMCLK2_EN, (src == REFCLK) ? 0 : 1,
264 					DPSTREAMCLK2_SRC_SEL, otg_inst);
265 		break;
266 	case 3:
267 		REG_UPDATE_2(DPSTREAMCLK_CNTL,
268 					DPSTREAMCLK3_EN, (src == REFCLK) ? 0 : 1,
269 					DPSTREAMCLK3_SRC_SEL, otg_inst);
270 		break;
271 	default:
272 		BREAK_TO_DEBUGGER();
273 		return;
274 	}
275 }
276 
277 static void dccg314_init(struct dccg *dccg)
278 {
279 	int otg_inst;
280 
281 	/* Set HPO stream encoder to use refclk to avoid case where PHY is
282 	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
283 	 * will cause DCN to hang.
284 	 */
285 	for (otg_inst = 0; otg_inst < 4; otg_inst++)
286 		dccg31_disable_symclk32_se(dccg, otg_inst);
287 
288 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
289 		for (otg_inst = 0; otg_inst < 2; otg_inst++)
290 			dccg31_disable_symclk32_le(dccg, otg_inst);
291 
292 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
293 		for (otg_inst = 0; otg_inst < 4; otg_inst++)
294 			dccg314_set_dpstreamclk(dccg, REFCLK, otg_inst,
295 						otg_inst);
296 
297 	if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
298 		for (otg_inst = 0; otg_inst < 5; otg_inst++)
299 			dccg31_set_physymclk(dccg, otg_inst,
300 					     PHYSYMCLK_FORCE_SRC_SYMCLK, false);
301 }
302 
303 static void dccg314_set_valid_pixel_rate(
304 		struct dccg *dccg,
305 		int ref_dtbclk_khz,
306 		int otg_inst,
307 		int pixclk_khz)
308 {
309 	struct dtbclk_dto_params dto_params = {0};
310 
311 	dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
312 	dto_params.otg_inst = otg_inst;
313 	dto_params.pixclk_khz = pixclk_khz;
314 
315 	dccg314_set_dtbclk_dto(dccg, &dto_params);
316 }
317 
318 static void dccg314_dpp_root_clock_control(
319 		struct dccg *dccg,
320 		unsigned int dpp_inst,
321 		bool clock_on)
322 {
323 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
324 
325 	if (clock_on) {
326 		/* turn off the DTO and leave phase/modulo at max */
327 		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 0);
328 		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
329 			  DPPCLK0_DTO_PHASE, 0xFF,
330 			  DPPCLK0_DTO_MODULO, 0xFF);
331 	} else {
332 		/* turn on the DTO to generate a 0hz clock */
333 		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 1);
334 		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
335 			  DPPCLK0_DTO_PHASE, 0,
336 			  DPPCLK0_DTO_MODULO, 1);
337 	}
338 }
339 
340 static const struct dccg_funcs dccg314_funcs = {
341 	.update_dpp_dto = dccg31_update_dpp_dto,
342 	.dpp_root_clock_control = dccg314_dpp_root_clock_control,
343 	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
344 	.dccg_init = dccg314_init,
345 	.set_dpstreamclk = dccg314_set_dpstreamclk,
346 	.enable_symclk32_se = dccg31_enable_symclk32_se,
347 	.disable_symclk32_se = dccg31_disable_symclk32_se,
348 	.enable_symclk32_le = dccg31_enable_symclk32_le,
349 	.disable_symclk32_le = dccg31_disable_symclk32_le,
350 	.set_physymclk = dccg31_set_physymclk,
351 	.set_dtbclk_dto = dccg314_set_dtbclk_dto,
352 	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
353 	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
354 	.otg_add_pixel = dccg31_otg_add_pixel,
355 	.otg_drop_pixel = dccg31_otg_drop_pixel,
356 	.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
357 	.disable_dsc = dccg31_disable_dscclk,
358 	.enable_dsc = dccg31_enable_dscclk,
359 	.set_pixel_rate_div = dccg314_set_pixel_rate_div,
360 	.set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
361 };
362 
363 struct dccg *dccg314_create(
364 	struct dc_context *ctx,
365 	const struct dccg_registers *regs,
366 	const struct dccg_shift *dccg_shift,
367 	const struct dccg_mask *dccg_mask)
368 {
369 	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
370 	struct dccg *base;
371 
372 	if (dccg_dcn == NULL) {
373 		BREAK_TO_DEBUGGER();
374 		return NULL;
375 	}
376 
377 	base = &dccg_dcn->base;
378 	base->ctx = ctx;
379 	base->funcs = &dccg314_funcs;
380 
381 	dccg_dcn->regs = regs;
382 	dccg_dcn->dccg_shift = dccg_shift;
383 	dccg_dcn->dccg_mask = dccg_mask;
384 
385 	return &dccg_dcn->base;
386 }
387