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