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
dcn401_set_dppclk_enable(struct dccg * dccg,uint32_t dpp_inst,uint32_t enable)55 static 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 }
dccg401_update_dpp_dto(struct dccg * dccg,int dpp_inst,int req_dppclk)77 void 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 */
dccg401_wait_for_dentist_change_done(struct dccg * dccg)108 static 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
dccg401_get_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,uint32_t * tmds_div,uint32_t * dp_dto_int)119 static void 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
dccg401_set_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,enum pixel_rate_div tmds_div,enum pixel_rate_div unused)157 static void 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
dccg401_set_dtbclk_p_src(struct dccg * dccg,enum streamclk_source src,uint32_t otg_inst)212 static void 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
dccg401_set_physymclk(struct dccg * dccg,int phy_inst,enum physymclk_clock_source clk_src,bool force_enable)267 void 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
dccg401_get_dccg_ref_freq(struct dccg * dccg,unsigned int xtalin_freq_inKhz,unsigned int * dccg_ref_freq_inKhz)351 static void 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
dccg401_otg_add_pixel(struct dccg * dccg,uint32_t otg_inst)363 static 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
dccg401_otg_drop_pixel(struct dccg * dccg,uint32_t otg_inst)372 static 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
dccg401_enable_symclk32_le(struct dccg * dccg,int hpo_le_inst,enum phyd32clk_clock_source phyd32clk)381 static void 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
dccg401_disable_symclk32_le(struct dccg * dccg,int hpo_le_inst)432 static void 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
dccg401_enable_dpstreamclk(struct dccg * dccg,int otg_inst,int dp_hpo_inst)482 static 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
dccg401_disable_dpstreamclk(struct dccg * dccg,int dp_hpo_inst)534 static void 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
dccg401_set_dpstreamclk(struct dccg * dccg,enum streamclk_source src,int otg_inst,int dp_hpo_inst)577 static void 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
dccg401_set_dp_dto(struct dccg * dccg,const struct dp_dto_params * params)590 static void 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) {
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
dccg401_init(struct dccg * dccg)697 void 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
dccg401_set_dto_dscclk(struct dccg * dccg,uint32_t inst)730 static void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst)
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
dccg401_set_ref_dscclk(struct dccg * dccg,uint32_t dsc_inst)766 static void 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
dccg401_enable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)801 static void 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
dccg401_disable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)837 static void 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
865 static 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 };
890
dccg401_create(struct dc_context * ctx,const struct dccg_registers * regs,const struct dccg_shift * dccg_shift,const struct dccg_mask * dccg_mask)891 struct dccg *dccg401_create(
892 struct dc_context *ctx,
893 const struct dccg_registers *regs,
894 const struct dccg_shift *dccg_shift,
895 const struct dccg_mask *dccg_mask)
896 {
897 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
898 struct dccg *base;
899
900 if (dccg_dcn == NULL) {
901 BREAK_TO_DEBUGGER();
902 return NULL;
903 }
904
905 base = &dccg_dcn->base;
906 base->ctx = ctx;
907 base->funcs = &dccg401_funcs;
908
909 dccg_dcn->regs = regs;
910 dccg_dcn->dccg_shift = dccg_shift;
911 dccg_dcn->dccg_mask = dccg_mask;
912
913 return &dccg_dcn->base;
914 }
915