1 /*
2 * Copyright 2018 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include "reg_helper.h"
27 #include "core_types.h"
28 #include "dcn31_dccg.h"
29 #include "dal_asic_id.h"
30
31 #define TO_DCN_DCCG(dccg)\
32 container_of(dccg, struct dcn_dccg, base)
33
34 #define REG(reg) \
35 (dccg_dcn->regs->reg)
36
37 #undef FN
38 #define FN(reg_name, field_name) \
39 dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
40
41 #define CTX \
42 dccg_dcn->base.ctx
43 #define DC_LOGGER \
44 dccg->ctx->logger
45
dccg31_update_dpp_dto(struct dccg * dccg,int dpp_inst,int req_dppclk)46 static void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
47 {
48 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
49
50 if (dccg->ref_dppclk && req_dppclk) {
51 int ref_dppclk = dccg->ref_dppclk;
52 int modulo, phase;
53
54 // phase / modulo = dpp pipe clk / dpp global clk
55 modulo = 0xff; // use FF at the end
56 phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
57
58 if (phase > 0xff) {
59 ASSERT(false);
60 phase = 0xff;
61 }
62
63 REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
64 DPPCLK0_DTO_PHASE, phase,
65 DPPCLK0_DTO_MODULO, modulo);
66 REG_UPDATE(DPPCLK_DTO_CTRL,
67 DPPCLK_DTO_ENABLE[dpp_inst], 1);
68 } else {
69 //DTO must be enabled to generate a 0Hz clock output
70 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
71 REG_UPDATE(DPPCLK_DTO_CTRL,
72 DPPCLK_DTO_ENABLE[dpp_inst], 1);
73 REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
74 DPPCLK0_DTO_PHASE, 0,
75 DPPCLK0_DTO_MODULO, 1);
76 } else {
77 REG_UPDATE(DPPCLK_DTO_CTRL,
78 DPPCLK_DTO_ENABLE[dpp_inst], 0);
79 }
80 }
81 dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
82 }
83
get_phy_mux_symclk(struct dcn_dccg * dccg_dcn,enum phyd32clk_clock_source src)84 static enum phyd32clk_clock_source get_phy_mux_symclk(
85 struct dcn_dccg *dccg_dcn,
86 enum phyd32clk_clock_source src)
87 {
88 if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
89 if (src == PHYD32CLKC)
90 src = PHYD32CLKF;
91 if (src == PHYD32CLKD)
92 src = PHYD32CLKG;
93 }
94 return src;
95 }
96
dccg31_enable_dpstreamclk(struct dccg * dccg,int otg_inst)97 static void dccg31_enable_dpstreamclk(struct dccg *dccg, int otg_inst)
98 {
99 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
100
101 /* enabled to select one of the DTBCLKs for pipe */
102 switch (otg_inst) {
103 case 0:
104 REG_UPDATE(DPSTREAMCLK_CNTL,
105 DPSTREAMCLK_PIPE0_EN, 1);
106 break;
107 case 1:
108 REG_UPDATE(DPSTREAMCLK_CNTL,
109 DPSTREAMCLK_PIPE1_EN, 1);
110 break;
111 case 2:
112 REG_UPDATE(DPSTREAMCLK_CNTL,
113 DPSTREAMCLK_PIPE2_EN, 1);
114 break;
115 case 3:
116 REG_UPDATE(DPSTREAMCLK_CNTL,
117 DPSTREAMCLK_PIPE3_EN, 1);
118 break;
119 default:
120 BREAK_TO_DEBUGGER();
121 return;
122 }
123 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
124 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
125 DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
126 }
127
dccg31_disable_dpstreamclk(struct dccg * dccg,int otg_inst)128 static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)
129 {
130 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
131
132 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
133 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
134 DPSTREAMCLK_ROOT_GATE_DISABLE, 0);
135
136 switch (otg_inst) {
137 case 0:
138 REG_UPDATE(DPSTREAMCLK_CNTL,
139 DPSTREAMCLK_PIPE0_EN, 0);
140 break;
141 case 1:
142 REG_UPDATE(DPSTREAMCLK_CNTL,
143 DPSTREAMCLK_PIPE1_EN, 0);
144 break;
145 case 2:
146 REG_UPDATE(DPSTREAMCLK_CNTL,
147 DPSTREAMCLK_PIPE2_EN, 0);
148 break;
149 case 3:
150 REG_UPDATE(DPSTREAMCLK_CNTL,
151 DPSTREAMCLK_PIPE3_EN, 0);
152 break;
153 default:
154 BREAK_TO_DEBUGGER();
155 return;
156 }
157 }
158
dccg31_set_dpstreamclk(struct dccg * dccg,enum hdmistreamclk_source src,int otg_inst)159 void dccg31_set_dpstreamclk(
160 struct dccg *dccg,
161 enum hdmistreamclk_source src,
162 int otg_inst)
163 {
164 if (src == REFCLK)
165 dccg31_disable_dpstreamclk(dccg, otg_inst);
166 else
167 dccg31_enable_dpstreamclk(dccg, otg_inst);
168 }
169
dccg31_enable_symclk32_se(struct dccg * dccg,int hpo_se_inst,enum phyd32clk_clock_source phyd32clk)170 void dccg31_enable_symclk32_se(
171 struct dccg *dccg,
172 int hpo_se_inst,
173 enum phyd32clk_clock_source phyd32clk)
174 {
175 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
176
177 phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
178
179 /* select one of the PHYD32CLKs as the source for symclk32_se */
180 switch (hpo_se_inst) {
181 case 0:
182 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
183 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
184 SYMCLK32_ROOT_SE0_GATE_DISABLE, 1);
185 REG_UPDATE_2(SYMCLK32_SE_CNTL,
186 SYMCLK32_SE0_SRC_SEL, phyd32clk,
187 SYMCLK32_SE0_EN, 1);
188 break;
189 case 1:
190 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
191 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
192 SYMCLK32_ROOT_SE1_GATE_DISABLE, 1);
193 REG_UPDATE_2(SYMCLK32_SE_CNTL,
194 SYMCLK32_SE1_SRC_SEL, phyd32clk,
195 SYMCLK32_SE1_EN, 1);
196 break;
197 case 2:
198 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
199 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
200 SYMCLK32_ROOT_SE2_GATE_DISABLE, 1);
201 REG_UPDATE_2(SYMCLK32_SE_CNTL,
202 SYMCLK32_SE2_SRC_SEL, phyd32clk,
203 SYMCLK32_SE2_EN, 1);
204 break;
205 case 3:
206 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
207 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
208 SYMCLK32_ROOT_SE3_GATE_DISABLE, 1);
209 REG_UPDATE_2(SYMCLK32_SE_CNTL,
210 SYMCLK32_SE3_SRC_SEL, phyd32clk,
211 SYMCLK32_SE3_EN, 1);
212 break;
213 default:
214 BREAK_TO_DEBUGGER();
215 return;
216 }
217 }
218
dccg31_disable_symclk32_se(struct dccg * dccg,int hpo_se_inst)219 void dccg31_disable_symclk32_se(
220 struct dccg *dccg,
221 int hpo_se_inst)
222 {
223 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
224
225 /* set refclk as the source for symclk32_se */
226 switch (hpo_se_inst) {
227 case 0:
228 REG_UPDATE_2(SYMCLK32_SE_CNTL,
229 SYMCLK32_SE0_SRC_SEL, 0,
230 SYMCLK32_SE0_EN, 0);
231 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
232 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
233 SYMCLK32_ROOT_SE0_GATE_DISABLE, 0);
234 break;
235 case 1:
236 REG_UPDATE_2(SYMCLK32_SE_CNTL,
237 SYMCLK32_SE1_SRC_SEL, 0,
238 SYMCLK32_SE1_EN, 0);
239 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
240 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
241 SYMCLK32_ROOT_SE1_GATE_DISABLE, 0);
242 break;
243 case 2:
244 REG_UPDATE_2(SYMCLK32_SE_CNTL,
245 SYMCLK32_SE2_SRC_SEL, 0,
246 SYMCLK32_SE2_EN, 0);
247 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
248 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
249 SYMCLK32_ROOT_SE2_GATE_DISABLE, 0);
250 break;
251 case 3:
252 REG_UPDATE_2(SYMCLK32_SE_CNTL,
253 SYMCLK32_SE3_SRC_SEL, 0,
254 SYMCLK32_SE3_EN, 0);
255 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
256 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
257 SYMCLK32_ROOT_SE3_GATE_DISABLE, 0);
258 break;
259 default:
260 BREAK_TO_DEBUGGER();
261 return;
262 }
263 }
264
dccg31_enable_symclk32_le(struct dccg * dccg,int hpo_le_inst,enum phyd32clk_clock_source phyd32clk)265 void dccg31_enable_symclk32_le(
266 struct dccg *dccg,
267 int hpo_le_inst,
268 enum phyd32clk_clock_source phyd32clk)
269 {
270 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
271
272 phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
273
274 /* select one of the PHYD32CLKs as the source for symclk32_le */
275 switch (hpo_le_inst) {
276 case 0:
277 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
278 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
279 SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
280 REG_UPDATE_2(SYMCLK32_LE_CNTL,
281 SYMCLK32_LE0_SRC_SEL, phyd32clk,
282 SYMCLK32_LE0_EN, 1);
283 break;
284 case 1:
285 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
286 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
287 SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
288 REG_UPDATE_2(SYMCLK32_LE_CNTL,
289 SYMCLK32_LE1_SRC_SEL, phyd32clk,
290 SYMCLK32_LE1_EN, 1);
291 break;
292 default:
293 BREAK_TO_DEBUGGER();
294 return;
295 }
296 }
297
dccg31_disable_symclk32_le(struct dccg * dccg,int hpo_le_inst)298 void dccg31_disable_symclk32_le(
299 struct dccg *dccg,
300 int hpo_le_inst)
301 {
302 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
303
304 /* set refclk as the source for symclk32_le */
305 switch (hpo_le_inst) {
306 case 0:
307 REG_UPDATE_2(SYMCLK32_LE_CNTL,
308 SYMCLK32_LE0_SRC_SEL, 0,
309 SYMCLK32_LE0_EN, 0);
310 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
311 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
312 SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);
313 break;
314 case 1:
315 REG_UPDATE_2(SYMCLK32_LE_CNTL,
316 SYMCLK32_LE1_SRC_SEL, 0,
317 SYMCLK32_LE1_EN, 0);
318 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
319 REG_UPDATE(DCCG_GATE_DISABLE_CNTL3,
320 SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);
321 break;
322 default:
323 BREAK_TO_DEBUGGER();
324 return;
325 }
326 }
327
dccg31_disable_dscclk(struct dccg * dccg,int inst)328 static void dccg31_disable_dscclk(struct dccg *dccg, int inst)
329 {
330 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
331
332 if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
333 return;
334 //DTO must be enabled to generate a 0 Hz clock output
335 switch (inst) {
336 case 0:
337 REG_UPDATE(DSCCLK_DTO_CTRL,
338 DSCCLK0_DTO_ENABLE, 1);
339 REG_UPDATE_2(DSCCLK0_DTO_PARAM,
340 DSCCLK0_DTO_PHASE, 0,
341 DSCCLK0_DTO_MODULO, 1);
342 break;
343 case 1:
344 REG_UPDATE(DSCCLK_DTO_CTRL,
345 DSCCLK1_DTO_ENABLE, 1);
346 REG_UPDATE_2(DSCCLK1_DTO_PARAM,
347 DSCCLK1_DTO_PHASE, 0,
348 DSCCLK1_DTO_MODULO, 1);
349 break;
350 case 2:
351 REG_UPDATE(DSCCLK_DTO_CTRL,
352 DSCCLK2_DTO_ENABLE, 1);
353 REG_UPDATE_2(DSCCLK2_DTO_PARAM,
354 DSCCLK2_DTO_PHASE, 0,
355 DSCCLK2_DTO_MODULO, 1);
356 break;
357 default:
358 BREAK_TO_DEBUGGER();
359 return;
360 }
361 }
362
dccg31_enable_dscclk(struct dccg * dccg,int inst)363 static void dccg31_enable_dscclk(struct dccg *dccg, int inst)
364 {
365 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
366
367 if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
368 return;
369 //Disable DTO
370 switch (inst) {
371 case 0:
372 REG_UPDATE_2(DSCCLK0_DTO_PARAM,
373 DSCCLK0_DTO_PHASE, 0,
374 DSCCLK0_DTO_MODULO, 0);
375 REG_UPDATE(DSCCLK_DTO_CTRL,
376 DSCCLK0_DTO_ENABLE, 0);
377 break;
378 case 1:
379 REG_UPDATE_2(DSCCLK1_DTO_PARAM,
380 DSCCLK1_DTO_PHASE, 0,
381 DSCCLK1_DTO_MODULO, 0);
382 REG_UPDATE(DSCCLK_DTO_CTRL,
383 DSCCLK1_DTO_ENABLE, 0);
384 break;
385 case 2:
386 REG_UPDATE_2(DSCCLK2_DTO_PARAM,
387 DSCCLK2_DTO_PHASE, 0,
388 DSCCLK2_DTO_MODULO, 0);
389 REG_UPDATE(DSCCLK_DTO_CTRL,
390 DSCCLK2_DTO_ENABLE, 0);
391 break;
392 default:
393 BREAK_TO_DEBUGGER();
394 return;
395 }
396 }
397
dccg31_set_physymclk(struct dccg * dccg,int phy_inst,enum physymclk_clock_source clk_src,bool force_enable)398 void dccg31_set_physymclk(
399 struct dccg *dccg,
400 int phy_inst,
401 enum physymclk_clock_source clk_src,
402 bool force_enable)
403 {
404 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
405
406 /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
407 switch (phy_inst) {
408 case 0:
409 if (force_enable)
410 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
411 PHYASYMCLK_FORCE_EN, 1,
412 PHYASYMCLK_FORCE_SRC_SEL, clk_src);
413 else
414 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
415 PHYASYMCLK_FORCE_EN, 0,
416 PHYASYMCLK_FORCE_SRC_SEL, 0);
417 break;
418 case 1:
419 if (force_enable)
420 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
421 PHYBSYMCLK_FORCE_EN, 1,
422 PHYBSYMCLK_FORCE_SRC_SEL, clk_src);
423 else
424 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
425 PHYBSYMCLK_FORCE_EN, 0,
426 PHYBSYMCLK_FORCE_SRC_SEL, 0);
427 break;
428 case 2:
429 if (force_enable)
430 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
431 PHYCSYMCLK_FORCE_EN, 1,
432 PHYCSYMCLK_FORCE_SRC_SEL, clk_src);
433 else
434 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
435 PHYCSYMCLK_FORCE_EN, 0,
436 PHYCSYMCLK_FORCE_SRC_SEL, 0);
437 break;
438 case 3:
439 if (force_enable)
440 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
441 PHYDSYMCLK_FORCE_EN, 1,
442 PHYDSYMCLK_FORCE_SRC_SEL, clk_src);
443 else
444 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
445 PHYDSYMCLK_FORCE_EN, 0,
446 PHYDSYMCLK_FORCE_SRC_SEL, 0);
447 break;
448 case 4:
449 if (force_enable)
450 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
451 PHYESYMCLK_FORCE_EN, 1,
452 PHYESYMCLK_FORCE_SRC_SEL, clk_src);
453 else
454 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
455 PHYESYMCLK_FORCE_EN, 0,
456 PHYESYMCLK_FORCE_SRC_SEL, 0);
457 break;
458 default:
459 BREAK_TO_DEBUGGER();
460 return;
461 }
462 }
463
464 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
dccg31_set_dtbclk_dto(struct dccg * dccg,int dtbclk_inst,int req_dtbclk_khz,int num_odm_segments,const struct dc_crtc_timing * timing)465 void dccg31_set_dtbclk_dto(
466 struct dccg *dccg,
467 int dtbclk_inst,
468 int req_dtbclk_khz,
469 int num_odm_segments,
470 const struct dc_crtc_timing *timing)
471 {
472 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
473 uint32_t dtbdto_div;
474
475 /* Mode DTBDTO Rate DTBCLK_DTO<x>_DIV Register
476 * ODM 4:1 combine pixel rate/4 2
477 * ODM 2:1 combine pixel rate/2 4
478 * non-DSC 4:2:0 mode pixel rate/2 4
479 * DSC native 4:2:0 pixel rate/2 4
480 * DSC native 4:2:2 pixel rate/2 4
481 * Other modes pixel rate 8
482 */
483 if (num_odm_segments == 4) {
484 dtbdto_div = 2;
485 req_dtbclk_khz = req_dtbclk_khz / 4;
486 } else if ((num_odm_segments == 2) ||
487 (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
488 (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
489 && !timing->dsc_cfg.ycbcr422_simple)) {
490 dtbdto_div = 4;
491 req_dtbclk_khz = req_dtbclk_khz / 2;
492 } else
493 dtbdto_div = 8;
494
495 if (dccg->ref_dtbclk_khz && req_dtbclk_khz) {
496 uint32_t modulo, phase;
497
498 // phase / modulo = dtbclk / dtbclk ref
499 modulo = dccg->ref_dtbclk_khz * 1000;
500 phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + dccg->ref_dtbclk_khz - 1),
501 dccg->ref_dtbclk_khz);
502
503 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
504 DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div);
505
506 REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], modulo);
507 REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], phase);
508
509 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
510 DTBCLK_DTO_ENABLE[dtbclk_inst], 1);
511
512 REG_WAIT(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
513 DTBCLKDTO_ENABLE_STATUS[dtbclk_inst], 1,
514 1, 100);
515
516 /* The recommended programming sequence to enable DTBCLK DTO to generate
517 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
518 * be set only after DTO is enabled
519 */
520 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
521 PIPE_DTO_SRC_SEL[dtbclk_inst], 1);
522
523 dccg->dtbclk_khz[dtbclk_inst] = req_dtbclk_khz;
524 } else {
525 REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
526 DTBCLK_DTO_ENABLE[dtbclk_inst], 0,
527 PIPE_DTO_SRC_SEL[dtbclk_inst], 0,
528 DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div);
529
530 REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], 0);
531 REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], 0);
532
533 dccg->dtbclk_khz[dtbclk_inst] = 0;
534 }
535 }
536
dccg31_set_audio_dtbclk_dto(struct dccg * dccg,uint32_t req_audio_dtbclk_khz)537 void dccg31_set_audio_dtbclk_dto(
538 struct dccg *dccg,
539 uint32_t req_audio_dtbclk_khz)
540 {
541 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
542
543 if (dccg->ref_dtbclk_khz && req_audio_dtbclk_khz) {
544 uint32_t modulo, phase;
545
546 // phase / modulo = dtbclk / dtbclk ref
547 modulo = dccg->ref_dtbclk_khz * 1000;
548 phase = div_u64((((unsigned long long)modulo * req_audio_dtbclk_khz) + dccg->ref_dtbclk_khz - 1),
549 dccg->ref_dtbclk_khz);
550
551
552 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);
553 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);
554
555 //REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
556 // DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1);
557
558 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
559 DCCG_AUDIO_DTO_SEL, 4); // 04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK
560
561 dccg->audio_dtbclk_khz = req_audio_dtbclk_khz;
562 } else {
563 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0);
564 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0);
565
566 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
567 DCCG_AUDIO_DTO_SEL, 3); // 03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO
568
569 dccg->audio_dtbclk_khz = 0;
570 }
571 }
572
dccg31_get_dccg_ref_freq(struct dccg * dccg,unsigned int xtalin_freq_inKhz,unsigned int * dccg_ref_freq_inKhz)573 static void dccg31_get_dccg_ref_freq(struct dccg *dccg,
574 unsigned int xtalin_freq_inKhz,
575 unsigned int *dccg_ref_freq_inKhz)
576 {
577 /*
578 * Assume refclk is sourced from xtalin
579 * expect 24MHz
580 */
581 *dccg_ref_freq_inKhz = xtalin_freq_inKhz;
582 return;
583 }
584
dccg31_set_dispclk_change_mode(struct dccg * dccg,enum dentist_dispclk_change_mode change_mode)585 static void dccg31_set_dispclk_change_mode(
586 struct dccg *dccg,
587 enum dentist_dispclk_change_mode change_mode)
588 {
589 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
590
591 REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE,
592 change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);
593 }
594
dccg31_init(struct dccg * dccg)595 void dccg31_init(struct dccg *dccg)
596 {
597 /* Set HPO stream encoder to use refclk to avoid case where PHY is
598 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
599 * will cause DCN to hang.
600 */
601 dccg31_disable_symclk32_se(dccg, 0);
602 dccg31_disable_symclk32_se(dccg, 1);
603 dccg31_disable_symclk32_se(dccg, 2);
604 dccg31_disable_symclk32_se(dccg, 3);
605
606 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
607 dccg31_disable_symclk32_le(dccg, 0);
608 dccg31_disable_symclk32_le(dccg, 1);
609 }
610
611 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
612 dccg31_disable_dpstreamclk(dccg, 0);
613 dccg31_disable_dpstreamclk(dccg, 1);
614 dccg31_disable_dpstreamclk(dccg, 2);
615 dccg31_disable_dpstreamclk(dccg, 3);
616 }
617
618 }
619
620 static const struct dccg_funcs dccg31_funcs = {
621 .update_dpp_dto = dccg31_update_dpp_dto,
622 .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
623 .dccg_init = dccg31_init,
624 .set_dpstreamclk = dccg31_set_dpstreamclk,
625 .enable_symclk32_se = dccg31_enable_symclk32_se,
626 .disable_symclk32_se = dccg31_disable_symclk32_se,
627 .enable_symclk32_le = dccg31_enable_symclk32_le,
628 .disable_symclk32_le = dccg31_disable_symclk32_le,
629 .set_physymclk = dccg31_set_physymclk,
630 .set_dtbclk_dto = dccg31_set_dtbclk_dto,
631 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
632 .set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
633 .disable_dsc = dccg31_disable_dscclk,
634 .enable_dsc = dccg31_enable_dscclk,
635 };
636
dccg31_create(struct dc_context * ctx,const struct dccg_registers * regs,const struct dccg_shift * dccg_shift,const struct dccg_mask * dccg_mask)637 struct dccg *dccg31_create(
638 struct dc_context *ctx,
639 const struct dccg_registers *regs,
640 const struct dccg_shift *dccg_shift,
641 const struct dccg_mask *dccg_mask)
642 {
643 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
644 struct dccg *base;
645
646 if (dccg_dcn == NULL) {
647 BREAK_TO_DEBUGGER();
648 return NULL;
649 }
650
651 base = &dccg_dcn->base;
652 base->ctx = ctx;
653 base->funcs = &dccg31_funcs;
654
655 dccg_dcn->regs = regs;
656 dccg_dcn->dccg_shift = dccg_shift;
657 dccg_dcn->dccg_mask = dccg_mask;
658
659 return &dccg_dcn->base;
660 }
661