Line data Source code
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 :
46 0 : void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
47 : {
48 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
49 :
50 0 : if (dccg->ref_dppclk && req_dppclk) {
51 0 : int ref_dppclk = dccg->ref_dppclk;
52 : int modulo, phase;
53 :
54 : // phase / modulo = dpp pipe clk / dpp global clk
55 0 : modulo = 0xff; // use FF at the end
56 0 : phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
57 :
58 0 : if (phase > 0xff) {
59 0 : ASSERT(false);
60 : phase = 0xff;
61 : }
62 :
63 0 : REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
64 : DPPCLK0_DTO_PHASE, phase,
65 : DPPCLK0_DTO_MODULO, modulo);
66 0 : 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 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
71 0 : REG_UPDATE(DPPCLK_DTO_CTRL,
72 : DPPCLK_DTO_ENABLE[dpp_inst], 1);
73 0 : REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
74 : DPPCLK0_DTO_PHASE, 0,
75 : DPPCLK0_DTO_MODULO, 1);
76 : } else {
77 0 : REG_UPDATE(DPPCLK_DTO_CTRL,
78 : DPPCLK_DTO_ENABLE[dpp_inst], 0);
79 : }
80 : }
81 0 : dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
82 0 : }
83 :
84 : static enum phyd32clk_clock_source get_phy_mux_symclk(
85 : struct dcn_dccg *dccg_dcn,
86 : enum phyd32clk_clock_source src)
87 : {
88 0 : if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
89 0 : if (src == PHYD32CLKC)
90 0 : src = PHYD32CLKF;
91 0 : if (src == PHYD32CLKD)
92 0 : src = PHYD32CLKG;
93 : }
94 : return src;
95 : }
96 :
97 0 : static void dccg31_enable_dpstreamclk(struct dccg *dccg, int otg_inst)
98 : {
99 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
100 :
101 : /* enabled to select one of the DTBCLKs for pipe */
102 0 : switch (otg_inst) {
103 : case 0:
104 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
105 : DPSTREAMCLK_PIPE0_EN, 1);
106 0 : break;
107 : case 1:
108 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
109 : DPSTREAMCLK_PIPE1_EN, 1);
110 0 : break;
111 : case 2:
112 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
113 : DPSTREAMCLK_PIPE2_EN, 1);
114 0 : break;
115 : case 3:
116 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
117 : DPSTREAMCLK_PIPE3_EN, 1);
118 0 : break;
119 : default:
120 0 : BREAK_TO_DEBUGGER();
121 0 : return;
122 : }
123 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
124 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
125 : DPSTREAMCLK_GATE_DISABLE, 1,
126 : DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
127 : }
128 :
129 0 : static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)
130 : {
131 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
132 :
133 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
134 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
135 : DPSTREAMCLK_ROOT_GATE_DISABLE, 0,
136 : DPSTREAMCLK_GATE_DISABLE, 0);
137 :
138 0 : switch (otg_inst) {
139 : case 0:
140 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
141 : DPSTREAMCLK_PIPE0_EN, 0);
142 0 : break;
143 : case 1:
144 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
145 : DPSTREAMCLK_PIPE1_EN, 0);
146 0 : break;
147 : case 2:
148 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
149 : DPSTREAMCLK_PIPE2_EN, 0);
150 0 : break;
151 : case 3:
152 0 : REG_UPDATE(DPSTREAMCLK_CNTL,
153 : DPSTREAMCLK_PIPE3_EN, 0);
154 0 : break;
155 : default:
156 0 : BREAK_TO_DEBUGGER();
157 0 : return;
158 : }
159 : }
160 :
161 0 : void dccg31_set_dpstreamclk(
162 : struct dccg *dccg,
163 : enum streamclk_source src,
164 : int otg_inst,
165 : int dp_hpo_inst)
166 : {
167 0 : if (src == REFCLK)
168 0 : dccg31_disable_dpstreamclk(dccg, otg_inst);
169 : else
170 0 : dccg31_enable_dpstreamclk(dccg, otg_inst);
171 0 : }
172 :
173 0 : void dccg31_enable_symclk32_se(
174 : struct dccg *dccg,
175 : int hpo_se_inst,
176 : enum phyd32clk_clock_source phyd32clk)
177 : {
178 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
179 :
180 0 : phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
181 :
182 : /* select one of the PHYD32CLKs as the source for symclk32_se */
183 0 : switch (hpo_se_inst) {
184 : case 0:
185 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
186 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
187 : SYMCLK32_SE0_GATE_DISABLE, 1,
188 : SYMCLK32_ROOT_SE0_GATE_DISABLE, 1);
189 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
190 : SYMCLK32_SE0_SRC_SEL, phyd32clk,
191 : SYMCLK32_SE0_EN, 1);
192 0 : break;
193 : case 1:
194 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
195 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
196 : SYMCLK32_SE1_GATE_DISABLE, 1,
197 : SYMCLK32_ROOT_SE1_GATE_DISABLE, 1);
198 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
199 : SYMCLK32_SE1_SRC_SEL, phyd32clk,
200 : SYMCLK32_SE1_EN, 1);
201 0 : break;
202 : case 2:
203 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
204 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
205 : SYMCLK32_SE2_GATE_DISABLE, 1,
206 : SYMCLK32_ROOT_SE2_GATE_DISABLE, 1);
207 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
208 : SYMCLK32_SE2_SRC_SEL, phyd32clk,
209 : SYMCLK32_SE2_EN, 1);
210 0 : break;
211 : case 3:
212 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
213 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
214 : SYMCLK32_SE3_GATE_DISABLE, 1,
215 : SYMCLK32_ROOT_SE3_GATE_DISABLE, 1);
216 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
217 : SYMCLK32_SE3_SRC_SEL, phyd32clk,
218 : SYMCLK32_SE3_EN, 1);
219 0 : break;
220 : default:
221 0 : BREAK_TO_DEBUGGER();
222 0 : return;
223 : }
224 : }
225 :
226 0 : void dccg31_disable_symclk32_se(
227 : struct dccg *dccg,
228 : int hpo_se_inst)
229 : {
230 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
231 :
232 : /* set refclk as the source for symclk32_se */
233 0 : switch (hpo_se_inst) {
234 : case 0:
235 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
236 : SYMCLK32_SE0_SRC_SEL, 0,
237 : SYMCLK32_SE0_EN, 0);
238 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
239 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
240 : SYMCLK32_SE0_GATE_DISABLE, 0,
241 : SYMCLK32_ROOT_SE0_GATE_DISABLE, 0);
242 : break;
243 : case 1:
244 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
245 : SYMCLK32_SE1_SRC_SEL, 0,
246 : SYMCLK32_SE1_EN, 0);
247 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
248 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
249 : SYMCLK32_SE1_GATE_DISABLE, 0,
250 : SYMCLK32_ROOT_SE1_GATE_DISABLE, 0);
251 : break;
252 : case 2:
253 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
254 : SYMCLK32_SE2_SRC_SEL, 0,
255 : SYMCLK32_SE2_EN, 0);
256 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
257 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
258 : SYMCLK32_SE2_GATE_DISABLE, 0,
259 : SYMCLK32_ROOT_SE2_GATE_DISABLE, 0);
260 : break;
261 : case 3:
262 0 : REG_UPDATE_2(SYMCLK32_SE_CNTL,
263 : SYMCLK32_SE3_SRC_SEL, 0,
264 : SYMCLK32_SE3_EN, 0);
265 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
266 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
267 : SYMCLK32_SE3_GATE_DISABLE, 0,
268 : SYMCLK32_ROOT_SE3_GATE_DISABLE, 0);
269 : break;
270 : default:
271 0 : BREAK_TO_DEBUGGER();
272 0 : return;
273 : }
274 : }
275 :
276 0 : void dccg31_enable_symclk32_le(
277 : struct dccg *dccg,
278 : int hpo_le_inst,
279 : enum phyd32clk_clock_source phyd32clk)
280 : {
281 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
282 :
283 0 : phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
284 :
285 : /* select one of the PHYD32CLKs as the source for symclk32_le */
286 0 : switch (hpo_le_inst) {
287 : case 0:
288 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
289 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
290 : SYMCLK32_LE0_GATE_DISABLE, 1,
291 : SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
292 0 : REG_UPDATE_2(SYMCLK32_LE_CNTL,
293 : SYMCLK32_LE0_SRC_SEL, phyd32clk,
294 : SYMCLK32_LE0_EN, 1);
295 0 : break;
296 : case 1:
297 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
298 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
299 : SYMCLK32_LE1_GATE_DISABLE, 1,
300 : SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
301 0 : REG_UPDATE_2(SYMCLK32_LE_CNTL,
302 : SYMCLK32_LE1_SRC_SEL, phyd32clk,
303 : SYMCLK32_LE1_EN, 1);
304 0 : break;
305 : default:
306 0 : BREAK_TO_DEBUGGER();
307 0 : return;
308 : }
309 : }
310 :
311 0 : void dccg31_disable_symclk32_le(
312 : struct dccg *dccg,
313 : int hpo_le_inst)
314 : {
315 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
316 :
317 : /* set refclk as the source for symclk32_le */
318 0 : switch (hpo_le_inst) {
319 : case 0:
320 0 : REG_UPDATE_2(SYMCLK32_LE_CNTL,
321 : SYMCLK32_LE0_SRC_SEL, 0,
322 : SYMCLK32_LE0_EN, 0);
323 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
324 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
325 : SYMCLK32_LE0_GATE_DISABLE, 0,
326 : SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);
327 : break;
328 : case 1:
329 0 : REG_UPDATE_2(SYMCLK32_LE_CNTL,
330 : SYMCLK32_LE1_SRC_SEL, 0,
331 : SYMCLK32_LE1_EN, 0);
332 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
333 0 : REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
334 : SYMCLK32_LE1_GATE_DISABLE, 0,
335 : SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);
336 : break;
337 : default:
338 0 : BREAK_TO_DEBUGGER();
339 0 : return;
340 : }
341 : }
342 :
343 0 : void dccg31_disable_dscclk(struct dccg *dccg, int inst)
344 : {
345 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
346 :
347 0 : if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
348 : return;
349 : //DTO must be enabled to generate a 0 Hz clock output
350 0 : switch (inst) {
351 : case 0:
352 0 : REG_UPDATE(DSCCLK_DTO_CTRL,
353 : DSCCLK0_DTO_ENABLE, 1);
354 0 : REG_UPDATE_2(DSCCLK0_DTO_PARAM,
355 : DSCCLK0_DTO_PHASE, 0,
356 : DSCCLK0_DTO_MODULO, 1);
357 0 : break;
358 : case 1:
359 0 : REG_UPDATE(DSCCLK_DTO_CTRL,
360 : DSCCLK1_DTO_ENABLE, 1);
361 0 : REG_UPDATE_2(DSCCLK1_DTO_PARAM,
362 : DSCCLK1_DTO_PHASE, 0,
363 : DSCCLK1_DTO_MODULO, 1);
364 0 : break;
365 : case 2:
366 0 : REG_UPDATE(DSCCLK_DTO_CTRL,
367 : DSCCLK2_DTO_ENABLE, 1);
368 0 : REG_UPDATE_2(DSCCLK2_DTO_PARAM,
369 : DSCCLK2_DTO_PHASE, 0,
370 : DSCCLK2_DTO_MODULO, 1);
371 0 : break;
372 : default:
373 0 : BREAK_TO_DEBUGGER();
374 0 : return;
375 : }
376 : }
377 :
378 0 : void dccg31_enable_dscclk(struct dccg *dccg, int inst)
379 : {
380 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
381 :
382 0 : if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
383 : return;
384 : //Disable DTO
385 0 : switch (inst) {
386 : case 0:
387 0 : REG_UPDATE_2(DSCCLK0_DTO_PARAM,
388 : DSCCLK0_DTO_PHASE, 0,
389 : DSCCLK0_DTO_MODULO, 0);
390 0 : REG_UPDATE(DSCCLK_DTO_CTRL,
391 : DSCCLK0_DTO_ENABLE, 0);
392 0 : break;
393 : case 1:
394 0 : REG_UPDATE_2(DSCCLK1_DTO_PARAM,
395 : DSCCLK1_DTO_PHASE, 0,
396 : DSCCLK1_DTO_MODULO, 0);
397 0 : REG_UPDATE(DSCCLK_DTO_CTRL,
398 : DSCCLK1_DTO_ENABLE, 0);
399 0 : break;
400 : case 2:
401 0 : REG_UPDATE_2(DSCCLK2_DTO_PARAM,
402 : DSCCLK2_DTO_PHASE, 0,
403 : DSCCLK2_DTO_MODULO, 0);
404 0 : REG_UPDATE(DSCCLK_DTO_CTRL,
405 : DSCCLK2_DTO_ENABLE, 0);
406 0 : break;
407 : default:
408 0 : BREAK_TO_DEBUGGER();
409 0 : return;
410 : }
411 : }
412 :
413 0 : void dccg31_set_physymclk(
414 : struct dccg *dccg,
415 : int phy_inst,
416 : enum physymclk_clock_source clk_src,
417 : bool force_enable)
418 : {
419 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
420 :
421 : /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
422 0 : switch (phy_inst) {
423 : case 0:
424 0 : if (force_enable) {
425 0 : REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
426 : PHYASYMCLK_FORCE_EN, 1,
427 : PHYASYMCLK_FORCE_SRC_SEL, clk_src);
428 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
429 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
430 : PHYASYMCLK_GATE_DISABLE, 1);
431 : } else {
432 0 : REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
433 : PHYASYMCLK_FORCE_EN, 0,
434 : PHYASYMCLK_FORCE_SRC_SEL, 0);
435 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
436 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
437 : PHYASYMCLK_GATE_DISABLE, 0);
438 : }
439 : break;
440 : case 1:
441 0 : if (force_enable) {
442 0 : REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
443 : PHYBSYMCLK_FORCE_EN, 1,
444 : PHYBSYMCLK_FORCE_SRC_SEL, clk_src);
445 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
446 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
447 : PHYBSYMCLK_GATE_DISABLE, 1);
448 : } else {
449 0 : REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
450 : PHYBSYMCLK_FORCE_EN, 0,
451 : PHYBSYMCLK_FORCE_SRC_SEL, 0);
452 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
453 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
454 : PHYBSYMCLK_GATE_DISABLE, 0);
455 : }
456 : break;
457 : case 2:
458 0 : if (force_enable) {
459 0 : REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
460 : PHYCSYMCLK_FORCE_EN, 1,
461 : PHYCSYMCLK_FORCE_SRC_SEL, clk_src);
462 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
463 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
464 : PHYCSYMCLK_GATE_DISABLE, 1);
465 : } else {
466 0 : REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
467 : PHYCSYMCLK_FORCE_EN, 0,
468 : PHYCSYMCLK_FORCE_SRC_SEL, 0);
469 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
470 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
471 : PHYCSYMCLK_GATE_DISABLE, 0);
472 : }
473 : break;
474 : case 3:
475 0 : if (force_enable) {
476 0 : REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
477 : PHYDSYMCLK_FORCE_EN, 1,
478 : PHYDSYMCLK_FORCE_SRC_SEL, clk_src);
479 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
480 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
481 : PHYDSYMCLK_GATE_DISABLE, 1);
482 : } else {
483 0 : REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
484 : PHYDSYMCLK_FORCE_EN, 0,
485 : PHYDSYMCLK_FORCE_SRC_SEL, 0);
486 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
487 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
488 : PHYDSYMCLK_GATE_DISABLE, 0);
489 : }
490 : break;
491 : case 4:
492 0 : if (force_enable) {
493 0 : REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
494 : PHYESYMCLK_FORCE_EN, 1,
495 : PHYESYMCLK_FORCE_SRC_SEL, clk_src);
496 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
497 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
498 : PHYESYMCLK_GATE_DISABLE, 1);
499 : } else {
500 0 : REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
501 : PHYESYMCLK_FORCE_EN, 0,
502 : PHYESYMCLK_FORCE_SRC_SEL, 0);
503 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
504 0 : REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
505 : PHYESYMCLK_GATE_DISABLE, 0);
506 : }
507 : break;
508 : default:
509 0 : BREAK_TO_DEBUGGER();
510 0 : return;
511 : }
512 : }
513 :
514 : /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
515 0 : void dccg31_set_dtbclk_dto(
516 : struct dccg *dccg,
517 : const struct dtbclk_dto_params *params)
518 : {
519 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
520 0 : int req_dtbclk_khz = params->pixclk_khz;
521 : uint32_t dtbdto_div;
522 :
523 : /* Mode DTBDTO Rate DTBCLK_DTO<x>_DIV Register
524 : * ODM 4:1 combine pixel rate/4 2
525 : * ODM 2:1 combine pixel rate/2 4
526 : * non-DSC 4:2:0 mode pixel rate/2 4
527 : * DSC native 4:2:0 pixel rate/2 4
528 : * DSC native 4:2:2 pixel rate/2 4
529 : * Other modes pixel rate 8
530 : */
531 0 : if (params->num_odm_segments == 4) {
532 0 : dtbdto_div = 2;
533 0 : req_dtbclk_khz = params->pixclk_khz / 4;
534 0 : } else if ((params->num_odm_segments == 2) ||
535 0 : (params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
536 0 : (params->timing->flags.DSC && params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
537 0 : && !params->timing->dsc_cfg.ycbcr422_simple)) {
538 0 : dtbdto_div = 4;
539 0 : req_dtbclk_khz = params->pixclk_khz / 2;
540 : } else
541 : dtbdto_div = 8;
542 :
543 0 : if (params->ref_dtbclk_khz && req_dtbclk_khz) {
544 : uint32_t modulo, phase;
545 :
546 : // phase / modulo = dtbclk / dtbclk ref
547 0 : modulo = params->ref_dtbclk_khz * 1000;
548 0 : phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + params->ref_dtbclk_khz - 1),
549 : params->ref_dtbclk_khz);
550 :
551 0 : REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
552 : DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
553 :
554 0 : REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
555 0 : REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
556 :
557 0 : REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
558 : DTBCLK_DTO_ENABLE[params->otg_inst], 1);
559 :
560 0 : REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
561 : DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
562 : 1, 100);
563 :
564 : /* The recommended programming sequence to enable DTBCLK DTO to generate
565 : * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
566 : * be set only after DTO is enabled
567 : */
568 0 : REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
569 : PIPE_DTO_SRC_SEL[params->otg_inst], 1);
570 : } else {
571 0 : REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[params->otg_inst],
572 : DTBCLK_DTO_ENABLE[params->otg_inst], 0,
573 : PIPE_DTO_SRC_SEL[params->otg_inst], 0,
574 : DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
575 :
576 0 : REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
577 0 : REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
578 : }
579 0 : }
580 :
581 0 : void dccg31_set_audio_dtbclk_dto(
582 : struct dccg *dccg,
583 : const struct dtbclk_dto_params *params)
584 : {
585 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
586 :
587 0 : if (params->ref_dtbclk_khz && params->req_audio_dtbclk_khz) {
588 : uint32_t modulo, phase;
589 :
590 : // phase / modulo = dtbclk / dtbclk ref
591 0 : modulo = params->ref_dtbclk_khz * 1000;
592 0 : phase = div_u64((((unsigned long long)modulo * params->req_audio_dtbclk_khz) + params->ref_dtbclk_khz - 1),
593 : params->ref_dtbclk_khz);
594 :
595 :
596 0 : REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);
597 0 : REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);
598 :
599 : //REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
600 : // DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1);
601 :
602 0 : REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
603 : DCCG_AUDIO_DTO_SEL, 4); // 04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK
604 : } else {
605 0 : REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0);
606 0 : REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0);
607 :
608 0 : REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
609 : DCCG_AUDIO_DTO_SEL, 3); // 03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO
610 : }
611 0 : }
612 :
613 0 : void dccg31_get_dccg_ref_freq(struct dccg *dccg,
614 : unsigned int xtalin_freq_inKhz,
615 : unsigned int *dccg_ref_freq_inKhz)
616 : {
617 : /*
618 : * Assume refclk is sourced from xtalin
619 : * expect 24MHz
620 : */
621 0 : *dccg_ref_freq_inKhz = xtalin_freq_inKhz;
622 0 : return;
623 : }
624 :
625 0 : void dccg31_set_dispclk_change_mode(
626 : struct dccg *dccg,
627 : enum dentist_dispclk_change_mode change_mode)
628 : {
629 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
630 :
631 0 : REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE,
632 : change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);
633 0 : }
634 :
635 0 : void dccg31_init(struct dccg *dccg)
636 : {
637 : /* Set HPO stream encoder to use refclk to avoid case where PHY is
638 : * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
639 : * will cause DCN to hang.
640 : */
641 0 : dccg31_disable_symclk32_se(dccg, 0);
642 0 : dccg31_disable_symclk32_se(dccg, 1);
643 0 : dccg31_disable_symclk32_se(dccg, 2);
644 0 : dccg31_disable_symclk32_se(dccg, 3);
645 :
646 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
647 0 : dccg31_disable_symclk32_le(dccg, 0);
648 0 : dccg31_disable_symclk32_le(dccg, 1);
649 : }
650 :
651 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
652 0 : dccg31_disable_dpstreamclk(dccg, 0);
653 0 : dccg31_disable_dpstreamclk(dccg, 1);
654 0 : dccg31_disable_dpstreamclk(dccg, 2);
655 0 : dccg31_disable_dpstreamclk(dccg, 3);
656 : }
657 :
658 0 : if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
659 0 : dccg31_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
660 0 : dccg31_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
661 0 : dccg31_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
662 0 : dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
663 0 : dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
664 : }
665 0 : }
666 :
667 0 : void dccg31_otg_add_pixel(struct dccg *dccg,
668 : uint32_t otg_inst)
669 : {
670 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
671 :
672 0 : REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
673 : OTG_ADD_PIXEL[otg_inst], 1);
674 0 : }
675 :
676 0 : void dccg31_otg_drop_pixel(struct dccg *dccg,
677 : uint32_t otg_inst)
678 : {
679 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
680 :
681 0 : REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
682 : OTG_DROP_PIXEL[otg_inst], 1);
683 0 : }
684 :
685 : static const struct dccg_funcs dccg31_funcs = {
686 : .update_dpp_dto = dccg31_update_dpp_dto,
687 : .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
688 : .dccg_init = dccg31_init,
689 : .set_dpstreamclk = dccg31_set_dpstreamclk,
690 : .enable_symclk32_se = dccg31_enable_symclk32_se,
691 : .disable_symclk32_se = dccg31_disable_symclk32_se,
692 : .enable_symclk32_le = dccg31_enable_symclk32_le,
693 : .disable_symclk32_le = dccg31_disable_symclk32_le,
694 : .set_physymclk = dccg31_set_physymclk,
695 : .set_dtbclk_dto = dccg31_set_dtbclk_dto,
696 : .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
697 : .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
698 : .otg_add_pixel = dccg31_otg_add_pixel,
699 : .otg_drop_pixel = dccg31_otg_drop_pixel,
700 : .set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
701 : .disable_dsc = dccg31_disable_dscclk,
702 : .enable_dsc = dccg31_enable_dscclk,
703 : };
704 :
705 0 : struct dccg *dccg31_create(
706 : struct dc_context *ctx,
707 : const struct dccg_registers *regs,
708 : const struct dccg_shift *dccg_shift,
709 : const struct dccg_mask *dccg_mask)
710 : {
711 0 : struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
712 : struct dccg *base;
713 :
714 0 : if (dccg_dcn == NULL) {
715 0 : BREAK_TO_DEBUGGER();
716 0 : return NULL;
717 : }
718 :
719 0 : base = &dccg_dcn->base;
720 0 : base->ctx = ctx;
721 0 : base->funcs = &dccg31_funcs;
722 :
723 0 : dccg_dcn->regs = regs;
724 0 : dccg_dcn->dccg_shift = dccg_shift;
725 0 : dccg_dcn->dccg_mask = dccg_mask;
726 :
727 0 : return &dccg_dcn->base;
728 : }
|