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 /* set the dtbclk_p source */
584 dccg401_set_dtbclk_p_src(dccg, src, otg_inst);
585
586 /* enabled to select one of the DTBCLKs for pipe */
587 if (src == REFCLK)
588 dccg401_disable_dpstreamclk(dccg, dp_hpo_inst);
589 else
590 dccg401_enable_dpstreamclk(dccg, otg_inst, dp_hpo_inst);
591 }
592
dccg401_set_dp_dto(struct dccg * dccg,const struct dp_dto_params * params)593 static void dccg401_set_dp_dto(
594 struct dccg *dccg,
595 const struct dp_dto_params *params)
596 {
597 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
598
599 bool enable = false;
600
601 if (params->otg_inst > 3) {
602 /* dcn401 only has 4 instances */
603 BREAK_TO_DEBUGGER();
604 return;
605 }
606 if (!params->refclk_hz) {
607 BREAK_TO_DEBUGGER();
608 return;
609 }
610
611 if (!dc_is_tmds_signal(params->signal)) {
612 uint64_t dto_integer;
613 uint64_t dto_phase_hz;
614 uint64_t dto_modulo_hz = params->refclk_hz;
615
616 enable = true;
617
618 /* Set DTO values:
619 * int = target_pix_rate / reference_clock
620 * phase = target_pix_rate - int * reference_clock,
621 * modulo = reference_clock */
622 dto_integer = div_u64(params->pixclk_hz, dto_modulo_hz);
623 dto_phase_hz = params->pixclk_hz - dto_integer * dto_modulo_hz;
624
625 if (dto_phase_hz <= 0) {
626 /* negative pixel rate should never happen */
627 BREAK_TO_DEBUGGER();
628 return;
629 }
630
631 switch (params->otg_inst) {
632 case 0:
633 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 1);
634 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
635 SYMCLK32_SE0_GATE_DISABLE, 1,
636 SYMCLK32_ROOT_SE0_GATE_DISABLE, 1,
637 SYMCLK32_LE0_GATE_DISABLE, 1,
638 SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
639 break;
640 case 1:
641 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 1);
642 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
643 SYMCLK32_SE1_GATE_DISABLE, 1,
644 SYMCLK32_ROOT_SE1_GATE_DISABLE, 1,
645 SYMCLK32_LE1_GATE_DISABLE, 1,
646 SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
647 break;
648 case 2:
649 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 1);
650 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
651 SYMCLK32_SE2_GATE_DISABLE, 1,
652 SYMCLK32_ROOT_SE2_GATE_DISABLE, 1,
653 SYMCLK32_LE2_GATE_DISABLE, 1,
654 SYMCLK32_ROOT_LE2_GATE_DISABLE, 1);
655 break;
656 case 3:
657 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 1);
658 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,
659 SYMCLK32_SE3_GATE_DISABLE, 1,
660 SYMCLK32_ROOT_SE3_GATE_DISABLE, 1,
661 SYMCLK32_LE3_GATE_DISABLE, 1,
662 SYMCLK32_ROOT_LE3_GATE_DISABLE, 1);
663 break;
664 }
665
666 dccg401_set_dtbclk_p_src(dccg, params->clk_src, params->otg_inst);
667
668 REG_WRITE(DP_DTO_PHASE[params->otg_inst], dto_phase_hz);
669 REG_WRITE(DP_DTO_MODULO[params->otg_inst], dto_modulo_hz);
670
671 switch (params->otg_inst) {
672 case 0:
673 REG_UPDATE(OTG_PIXEL_RATE_DIV,
674 DPDTO0_INT, dto_integer);
675 break;
676 case 1:
677 REG_UPDATE(OTG_PIXEL_RATE_DIV,
678 DPDTO1_INT, dto_integer);
679 break;
680 case 2:
681 REG_UPDATE(OTG_PIXEL_RATE_DIV,
682 DPDTO2_INT, dto_integer);
683 break;
684 case 3:
685 REG_UPDATE(OTG_PIXEL_RATE_DIV,
686 DPDTO3_INT, dto_integer);
687 break;
688 default:
689 BREAK_TO_DEBUGGER();
690 return;
691 }
692 }
693
694 /* Toggle DTO */
695 REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
696 DP_DTO_ENABLE[params->otg_inst], enable,
697 PIPE_DTO_SRC_SEL[params->otg_inst], enable);
698 }
699
dccg401_init(struct dccg * dccg)700 void dccg401_init(struct dccg *dccg)
701 {
702 /* Set HPO stream encoder to use refclk to avoid case where PHY is
703 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
704 * will cause DCN to hang.
705 */
706 dccg31_disable_symclk32_se(dccg, 0);
707 dccg31_disable_symclk32_se(dccg, 1);
708 dccg31_disable_symclk32_se(dccg, 2);
709 dccg31_disable_symclk32_se(dccg, 3);
710
711 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
712 dccg401_disable_symclk32_le(dccg, 0);
713 dccg401_disable_symclk32_le(dccg, 1);
714 dccg401_disable_symclk32_le(dccg, 2);
715 dccg401_disable_symclk32_le(dccg, 3);
716 }
717
718 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
719 dccg401_disable_dpstreamclk(dccg, 0);
720 dccg401_disable_dpstreamclk(dccg, 1);
721 dccg401_disable_dpstreamclk(dccg, 2);
722 dccg401_disable_dpstreamclk(dccg, 3);
723 }
724
725 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
726 dccg401_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
727 dccg401_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
728 dccg401_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
729 dccg401_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
730 }
731 }
732
dccg401_set_dto_dscclk(struct dccg * dccg,uint32_t inst)733 static void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst)
734 {
735 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
736
737 switch (inst) {
738 case 0:
739 REG_UPDATE_2(DSCCLK0_DTO_PARAM,
740 DSCCLK0_DTO_PHASE, 1,
741 DSCCLK0_DTO_MODULO, 1);
742 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1);
743
744 break;
745 case 1:
746 REG_UPDATE_2(DSCCLK1_DTO_PARAM,
747 DSCCLK1_DTO_PHASE, 1,
748 DSCCLK1_DTO_MODULO, 1);
749 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1);
750 break;
751 case 2:
752 REG_UPDATE_2(DSCCLK2_DTO_PARAM,
753 DSCCLK2_DTO_PHASE, 1,
754 DSCCLK2_DTO_MODULO, 1);
755 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1);
756 break;
757 case 3:
758 REG_UPDATE_2(DSCCLK3_DTO_PARAM,
759 DSCCLK3_DTO_PHASE, 1,
760 DSCCLK3_DTO_MODULO, 1);
761 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1);
762 break;
763 default:
764 BREAK_TO_DEBUGGER();
765 return;
766 }
767 }
768
dccg401_set_ref_dscclk(struct dccg * dccg,uint32_t dsc_inst)769 static void dccg401_set_ref_dscclk(struct dccg *dccg,
770 uint32_t dsc_inst)
771 {
772 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
773
774 switch (dsc_inst) {
775 case 0:
776 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 0);
777 REG_UPDATE_2(DSCCLK0_DTO_PARAM,
778 DSCCLK0_DTO_PHASE, 0,
779 DSCCLK0_DTO_MODULO, 0);
780 break;
781 case 1:
782 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0);
783 REG_UPDATE_2(DSCCLK1_DTO_PARAM,
784 DSCCLK1_DTO_PHASE, 0,
785 DSCCLK1_DTO_MODULO, 0);
786 break;
787 case 2:
788 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0);
789 REG_UPDATE_2(DSCCLK2_DTO_PARAM,
790 DSCCLK2_DTO_PHASE, 0,
791 DSCCLK2_DTO_MODULO, 0);
792 break;
793 case 3:
794 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0);
795 REG_UPDATE_2(DSCCLK3_DTO_PARAM,
796 DSCCLK3_DTO_PHASE, 0,
797 DSCCLK3_DTO_MODULO, 0);
798 break;
799 default:
800 return;
801 }
802 }
803
dccg401_enable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)804 static void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
805 {
806 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
807
808 switch (link_enc_inst) {
809 case 0:
810 REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
811 SYMCLKA_CLOCK_ENABLE, 1);
812 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
813 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 1);
814 break;
815 case 1:
816 REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
817 SYMCLKB_CLOCK_ENABLE, 1);
818 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
819 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 1);
820 break;
821 case 2:
822 REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
823 SYMCLKC_CLOCK_ENABLE, 1);
824 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
825 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 1);
826 break;
827 case 3:
828 REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
829 SYMCLKD_CLOCK_ENABLE, 1);
830 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
831 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 1);
832 break;
833 }
834
835 switch (stream_enc_inst) {
836 case 0:
837 REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
838 SYMCLKA_FE_EN, 1,
839 SYMCLKA_FE_SRC_SEL, link_enc_inst);
840 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
841 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1);
842 break;
843 case 1:
844 REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
845 SYMCLKB_FE_EN, 1,
846 SYMCLKB_FE_SRC_SEL, link_enc_inst);
847 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
848 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1);
849 break;
850 case 2:
851 REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
852 SYMCLKC_FE_EN, 1,
853 SYMCLKC_FE_SRC_SEL, link_enc_inst);
854 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
855 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1);
856 break;
857 case 3:
858 REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
859 SYMCLKD_FE_EN, 1,
860 SYMCLKD_FE_SRC_SEL, link_enc_inst);
861 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
862 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1);
863 break;
864 }
865 }
866
867 /*get other front end connected to this backend*/
dccg401_get_number_enabled_symclk_fe_connected_to_be(struct dccg * dccg,uint32_t link_enc_inst)868 static uint8_t dccg401_get_number_enabled_symclk_fe_connected_to_be(struct dccg *dccg, uint32_t link_enc_inst)
869 {
870 uint8_t num_enabled_symclk_fe = 0;
871 uint32_t fe_clk_en[4] = {0}, be_clk_sel[4] = {0};
872 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
873 uint8_t i;
874
875 REG_GET_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, &fe_clk_en[0],
876 SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
877
878 REG_GET_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, &fe_clk_en[1],
879 SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
880
881 REG_GET_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, &fe_clk_en[2],
882 SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
883
884 REG_GET_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, &fe_clk_en[3],
885 SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
886
887 for (i = 0; i < ARRAY_SIZE(fe_clk_en); i++) {
888 if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
889 num_enabled_symclk_fe++;
890 }
891
892 return num_enabled_symclk_fe;
893 }
894
dccg401_disable_symclk_se(struct dccg * dccg,uint32_t stream_enc_inst,uint32_t link_enc_inst)895 static void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
896 {
897 uint8_t num_enabled_symclk_fe = 0;
898 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
899
900 switch (stream_enc_inst) {
901 case 0:
902 REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
903 SYMCLKA_FE_EN, 0,
904 SYMCLKA_FE_SRC_SEL, 0);
905 break;
906 case 1:
907 REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
908 SYMCLKB_FE_EN, 0,
909 SYMCLKB_FE_SRC_SEL, 0);
910 break;
911 case 2:
912 REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
913 SYMCLKC_FE_EN, 0,
914 SYMCLKC_FE_SRC_SEL, 0);
915 break;
916 case 3:
917 REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
918 SYMCLKD_FE_EN, 0,
919 SYMCLKD_FE_SRC_SEL, 0);
920 break;
921 }
922
923 /*check other enabled symclk fe connected to this be */
924 num_enabled_symclk_fe = dccg401_get_number_enabled_symclk_fe_connected_to_be(dccg, link_enc_inst);
925 /*only turn off backend clk if other front ends attached to this backend are all off,
926 for mst, only turn off the backend if this is the last front end*/
927 if (num_enabled_symclk_fe == 0) {
928 switch (link_enc_inst) {
929 case 0:
930 REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
931 SYMCLKA_CLOCK_ENABLE, 0);
932 break;
933 case 1:
934 REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
935 SYMCLKB_CLOCK_ENABLE, 0);
936 break;
937 case 2:
938 REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
939 SYMCLKC_CLOCK_ENABLE, 0);
940 break;
941 case 3:
942 REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
943 SYMCLKD_CLOCK_ENABLE, 0);
944 break;
945 }
946 }
947 }
948
949 static const struct dccg_funcs dccg401_funcs = {
950 .update_dpp_dto = dccg401_update_dpp_dto,
951 .get_dccg_ref_freq = dccg401_get_dccg_ref_freq,
952 .dccg_init = dccg401_init,
953 .set_dpstreamclk = dccg401_set_dpstreamclk,
954 .enable_symclk32_se = dccg31_enable_symclk32_se,
955 .disable_symclk32_se = dccg31_disable_symclk32_se,
956 .enable_symclk32_le = dccg401_enable_symclk32_le,
957 .disable_symclk32_le = dccg401_disable_symclk32_le,
958 .set_physymclk = dccg401_set_physymclk,
959 .set_dtbclk_dto = NULL,
960 .set_dto_dscclk = dccg401_set_dto_dscclk,
961 .set_ref_dscclk = dccg401_set_ref_dscclk,
962 .set_valid_pixel_rate = NULL,
963 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
964 .set_audio_dtbclk_dto = NULL,
965 .otg_add_pixel = dccg401_otg_add_pixel,
966 .otg_drop_pixel = dccg401_otg_drop_pixel,
967 .set_pixel_rate_div = dccg401_set_pixel_rate_div,
968 .get_pixel_rate_div = dccg401_get_pixel_rate_div,
969 .set_dp_dto = dccg401_set_dp_dto,
970 .enable_symclk_se = dccg401_enable_symclk_se,
971 .disable_symclk_se = dccg401_disable_symclk_se,
972 .set_dtbclk_p_src = dccg401_set_dtbclk_p_src,
973 };
974
dccg401_create(struct dc_context * ctx,const struct dccg_registers * regs,const struct dccg_shift * dccg_shift,const struct dccg_mask * dccg_mask)975 struct dccg *dccg401_create(
976 struct dc_context *ctx,
977 const struct dccg_registers *regs,
978 const struct dccg_shift *dccg_shift,
979 const struct dccg_mask *dccg_mask)
980 {
981 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
982 struct dccg *base;
983
984 if (dccg_dcn == NULL) {
985 BREAK_TO_DEBUGGER();
986 return NULL;
987 }
988
989 base = &dccg_dcn->base;
990 base->ctx = ctx;
991 base->funcs = &dccg401_funcs;
992
993 dccg_dcn->regs = regs;
994 dccg_dcn->dccg_shift = dccg_shift;
995 dccg_dcn->dccg_mask = dccg_mask;
996
997 return &dccg_dcn->base;
998 }
999