756 lines · c
1/*2 * Copyright 2018 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *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 FN38#define FN(reg_name, field_name) \39 dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name40 41#define CTX \42 dccg_dcn->base.ctx43#define DC_LOGGER \44 dccg->ctx->logger45 46void 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->dpp_clock_gated[dpp_inst]) {51 /*52 * Do not update the DPPCLK DTO if the clock is stopped.53 * It is treated the same as if the pipe itself were in PG.54 */55 return;56 }57 58 if (dccg->ref_dppclk && req_dppclk) {59 int ref_dppclk = dccg->ref_dppclk;60 int modulo, phase;61 62 // phase / modulo = dpp pipe clk / dpp global clk63 modulo = 0xff; // use FF at the end64 phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;65 66 if (phase > 0xff) {67 ASSERT(false);68 phase = 0xff;69 }70 71 REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,72 DPPCLK0_DTO_PHASE, phase,73 DPPCLK0_DTO_MODULO, modulo);74 REG_UPDATE(DPPCLK_DTO_CTRL,75 DPPCLK_DTO_ENABLE[dpp_inst], 1);76 } else {77 REG_UPDATE(DPPCLK_DTO_CTRL,78 DPPCLK_DTO_ENABLE[dpp_inst], 0);79 }80 dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;81}82 83static enum phyd32clk_clock_source get_phy_mux_symclk(84 struct dcn_dccg *dccg_dcn,85 enum phyd32clk_clock_source src)86{87 if (dccg_dcn->base.ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&88 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 97static 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_2(DCCG_GATE_DISABLE_CNTL3,125 DPSTREAMCLK_GATE_DISABLE, 1,126 DPSTREAMCLK_ROOT_GATE_DISABLE, 1);127}128 129static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)130{131 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);132 133 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)134 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,135 DPSTREAMCLK_ROOT_GATE_DISABLE, 0,136 DPSTREAMCLK_GATE_DISABLE, 0);137 138 switch (otg_inst) {139 case 0:140 REG_UPDATE(DPSTREAMCLK_CNTL,141 DPSTREAMCLK_PIPE0_EN, 0);142 break;143 case 1:144 REG_UPDATE(DPSTREAMCLK_CNTL,145 DPSTREAMCLK_PIPE1_EN, 0);146 break;147 case 2:148 REG_UPDATE(DPSTREAMCLK_CNTL,149 DPSTREAMCLK_PIPE2_EN, 0);150 break;151 case 3:152 REG_UPDATE(DPSTREAMCLK_CNTL,153 DPSTREAMCLK_PIPE3_EN, 0);154 break;155 default:156 BREAK_TO_DEBUGGER();157 return;158 }159}160 161void dccg31_set_dpstreamclk(162 struct dccg *dccg,163 enum streamclk_source src,164 int otg_inst,165 int dp_hpo_inst)166{167 if (src == REFCLK)168 dccg31_disable_dpstreamclk(dccg, otg_inst);169 else170 dccg31_enable_dpstreamclk(dccg, otg_inst);171}172 173void dccg31_enable_symclk32_se(174 struct dccg *dccg,175 int hpo_se_inst,176 enum phyd32clk_clock_source phyd32clk)177{178 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);179 180 phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);181 182 /* select one of the PHYD32CLKs as the source for symclk32_se */183 switch (hpo_se_inst) {184 case 0:185 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)186 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,187 SYMCLK32_SE0_GATE_DISABLE, 1,188 SYMCLK32_ROOT_SE0_GATE_DISABLE, 1);189 REG_UPDATE_2(SYMCLK32_SE_CNTL,190 SYMCLK32_SE0_SRC_SEL, phyd32clk,191 SYMCLK32_SE0_EN, 1);192 break;193 case 1:194 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)195 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,196 SYMCLK32_SE1_GATE_DISABLE, 1,197 SYMCLK32_ROOT_SE1_GATE_DISABLE, 1);198 REG_UPDATE_2(SYMCLK32_SE_CNTL,199 SYMCLK32_SE1_SRC_SEL, phyd32clk,200 SYMCLK32_SE1_EN, 1);201 break;202 case 2:203 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)204 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,205 SYMCLK32_SE2_GATE_DISABLE, 1,206 SYMCLK32_ROOT_SE2_GATE_DISABLE, 1);207 REG_UPDATE_2(SYMCLK32_SE_CNTL,208 SYMCLK32_SE2_SRC_SEL, phyd32clk,209 SYMCLK32_SE2_EN, 1);210 break;211 case 3:212 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)213 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,214 SYMCLK32_SE3_GATE_DISABLE, 1,215 SYMCLK32_ROOT_SE3_GATE_DISABLE, 1);216 REG_UPDATE_2(SYMCLK32_SE_CNTL,217 SYMCLK32_SE3_SRC_SEL, phyd32clk,218 SYMCLK32_SE3_EN, 1);219 break;220 default:221 BREAK_TO_DEBUGGER();222 return;223 }224}225 226void dccg31_disable_symclk32_se(227 struct dccg *dccg,228 int hpo_se_inst)229{230 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);231 232 /* set refclk as the source for symclk32_se */233 switch (hpo_se_inst) {234 case 0:235 REG_UPDATE_2(SYMCLK32_SE_CNTL,236 SYMCLK32_SE0_SRC_SEL, 0,237 SYMCLK32_SE0_EN, 0);238 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)239 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 REG_UPDATE_2(SYMCLK32_SE_CNTL,245 SYMCLK32_SE1_SRC_SEL, 0,246 SYMCLK32_SE1_EN, 0);247 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)248 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 REG_UPDATE_2(SYMCLK32_SE_CNTL,254 SYMCLK32_SE2_SRC_SEL, 0,255 SYMCLK32_SE2_EN, 0);256 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)257 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 REG_UPDATE_2(SYMCLK32_SE_CNTL,263 SYMCLK32_SE3_SRC_SEL, 0,264 SYMCLK32_SE3_EN, 0);265 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)266 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 BREAK_TO_DEBUGGER();272 return;273 }274}275 276void dccg31_enable_symclk32_le(277 struct dccg *dccg,278 int hpo_le_inst,279 enum phyd32clk_clock_source phyd32clk)280{281 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);282 283 phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);284 285 /* select one of the PHYD32CLKs as the source for symclk32_le */286 switch (hpo_le_inst) {287 case 0:288 REG_UPDATE_2(SYMCLK32_LE_CNTL,289 SYMCLK32_LE0_SRC_SEL, phyd32clk,290 SYMCLK32_LE0_EN, 1);291 break;292 case 1:293 REG_UPDATE_2(SYMCLK32_LE_CNTL,294 SYMCLK32_LE1_SRC_SEL, phyd32clk,295 SYMCLK32_LE1_EN, 1);296 break;297 default:298 BREAK_TO_DEBUGGER();299 return;300 }301}302 303void dccg31_disable_symclk32_le(304 struct dccg *dccg,305 int hpo_le_inst)306{307 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);308 309 /* set refclk as the source for symclk32_le */310 switch (hpo_le_inst) {311 case 0:312 REG_UPDATE_2(SYMCLK32_LE_CNTL,313 SYMCLK32_LE0_SRC_SEL, 0,314 SYMCLK32_LE0_EN, 0);315 break;316 case 1:317 REG_UPDATE_2(SYMCLK32_LE_CNTL,318 SYMCLK32_LE1_SRC_SEL, 0,319 SYMCLK32_LE1_EN, 0);320 break;321 default:322 BREAK_TO_DEBUGGER();323 return;324 }325}326 327void dccg31_set_symclk32_le_root_clock_gating(328 struct dccg *dccg,329 int hpo_le_inst,330 bool enable)331{332 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);333 334 if (!dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)335 return;336 337 switch (hpo_le_inst) {338 case 0:339 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,340 SYMCLK32_LE0_GATE_DISABLE, enable ? 1 : 0,341 SYMCLK32_ROOT_LE0_GATE_DISABLE, enable ? 1 : 0);342 break;343 case 1:344 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,345 SYMCLK32_LE1_GATE_DISABLE, enable ? 1 : 0,346 SYMCLK32_ROOT_LE1_GATE_DISABLE, enable ? 1 : 0);347 break;348 default:349 BREAK_TO_DEBUGGER();350 return;351 }352}353 354void dccg31_disable_dscclk(struct dccg *dccg, int inst)355{356 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);357 358 if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)359 return;360 //DTO must be enabled to generate a 0 Hz clock output361 switch (inst) {362 case 0:363 REG_UPDATE(DSCCLK_DTO_CTRL,364 DSCCLK0_DTO_ENABLE, 1);365 REG_UPDATE_2(DSCCLK0_DTO_PARAM,366 DSCCLK0_DTO_PHASE, 0,367 DSCCLK0_DTO_MODULO, 1);368 break;369 case 1:370 REG_UPDATE(DSCCLK_DTO_CTRL,371 DSCCLK1_DTO_ENABLE, 1);372 REG_UPDATE_2(DSCCLK1_DTO_PARAM,373 DSCCLK1_DTO_PHASE, 0,374 DSCCLK1_DTO_MODULO, 1);375 break;376 case 2:377 REG_UPDATE(DSCCLK_DTO_CTRL,378 DSCCLK2_DTO_ENABLE, 1);379 REG_UPDATE_2(DSCCLK2_DTO_PARAM,380 DSCCLK2_DTO_PHASE, 0,381 DSCCLK2_DTO_MODULO, 1);382 break;383 case 3:384 if (REG(DSCCLK3_DTO_PARAM)) {385 REG_UPDATE(DSCCLK_DTO_CTRL,386 DSCCLK3_DTO_ENABLE, 1);387 REG_UPDATE_2(DSCCLK3_DTO_PARAM,388 DSCCLK3_DTO_PHASE, 0,389 DSCCLK3_DTO_MODULO, 1);390 }391 break;392 default:393 BREAK_TO_DEBUGGER();394 return;395 }396}397 398void dccg31_enable_dscclk(struct dccg *dccg, int inst)399{400 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);401 402 if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)403 return;404 //Disable DTO405 switch (inst) {406 case 0:407 REG_UPDATE_2(DSCCLK0_DTO_PARAM,408 DSCCLK0_DTO_PHASE, 0,409 DSCCLK0_DTO_MODULO, 0);410 REG_UPDATE(DSCCLK_DTO_CTRL,411 DSCCLK0_DTO_ENABLE, 0);412 break;413 case 1:414 REG_UPDATE_2(DSCCLK1_DTO_PARAM,415 DSCCLK1_DTO_PHASE, 0,416 DSCCLK1_DTO_MODULO, 0);417 REG_UPDATE(DSCCLK_DTO_CTRL,418 DSCCLK1_DTO_ENABLE, 0);419 break;420 case 2:421 REG_UPDATE_2(DSCCLK2_DTO_PARAM,422 DSCCLK2_DTO_PHASE, 0,423 DSCCLK2_DTO_MODULO, 0);424 REG_UPDATE(DSCCLK_DTO_CTRL,425 DSCCLK2_DTO_ENABLE, 0);426 break;427 case 3:428 if (REG(DSCCLK3_DTO_PARAM)) {429 REG_UPDATE(DSCCLK_DTO_CTRL,430 DSCCLK3_DTO_ENABLE, 0);431 REG_UPDATE_2(DSCCLK3_DTO_PARAM,432 DSCCLK3_DTO_PHASE, 0,433 DSCCLK3_DTO_MODULO, 0);434 }435 break;436 default:437 BREAK_TO_DEBUGGER();438 return;439 }440}441 442void dccg31_set_physymclk(443 struct dccg *dccg,444 int phy_inst,445 enum physymclk_clock_source clk_src,446 bool force_enable)447{448 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);449 450 /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */451 switch (phy_inst) {452 case 0:453 if (force_enable) {454 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,455 PHYASYMCLK_FORCE_EN, 1,456 PHYASYMCLK_FORCE_SRC_SEL, clk_src);457 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)458 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,459 PHYASYMCLK_GATE_DISABLE, 1);460 } else {461 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,462 PHYASYMCLK_FORCE_EN, 0,463 PHYASYMCLK_FORCE_SRC_SEL, 0);464 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)465 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,466 PHYASYMCLK_GATE_DISABLE, 0);467 }468 break;469 case 1:470 if (force_enable) {471 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,472 PHYBSYMCLK_FORCE_EN, 1,473 PHYBSYMCLK_FORCE_SRC_SEL, clk_src);474 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)475 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,476 PHYBSYMCLK_GATE_DISABLE, 1);477 } else {478 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,479 PHYBSYMCLK_FORCE_EN, 0,480 PHYBSYMCLK_FORCE_SRC_SEL, 0);481 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)482 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,483 PHYBSYMCLK_GATE_DISABLE, 0);484 }485 break;486 case 2:487 if (force_enable) {488 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,489 PHYCSYMCLK_FORCE_EN, 1,490 PHYCSYMCLK_FORCE_SRC_SEL, clk_src);491 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)492 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,493 PHYCSYMCLK_GATE_DISABLE, 1);494 } else {495 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,496 PHYCSYMCLK_FORCE_EN, 0,497 PHYCSYMCLK_FORCE_SRC_SEL, 0);498 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)499 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,500 PHYCSYMCLK_GATE_DISABLE, 0);501 }502 break;503 case 3:504 if (force_enable) {505 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,506 PHYDSYMCLK_FORCE_EN, 1,507 PHYDSYMCLK_FORCE_SRC_SEL, clk_src);508 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)509 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,510 PHYDSYMCLK_GATE_DISABLE, 1);511 } else {512 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,513 PHYDSYMCLK_FORCE_EN, 0,514 PHYDSYMCLK_FORCE_SRC_SEL, 0);515 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)516 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,517 PHYDSYMCLK_GATE_DISABLE, 0);518 }519 break;520 case 4:521 if (force_enable) {522 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,523 PHYESYMCLK_FORCE_EN, 1,524 PHYESYMCLK_FORCE_SRC_SEL, clk_src);525 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)526 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,527 PHYESYMCLK_GATE_DISABLE, 1);528 } else {529 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,530 PHYESYMCLK_FORCE_EN, 0,531 PHYESYMCLK_FORCE_SRC_SEL, 0);532 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)533 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,534 PHYESYMCLK_GATE_DISABLE, 0);535 }536 break;537 default:538 BREAK_TO_DEBUGGER();539 return;540 }541}542 543/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */544void dccg31_set_dtbclk_dto(545 struct dccg *dccg,546 const struct dtbclk_dto_params *params)547{548 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);549 int req_dtbclk_khz = params->pixclk_khz;550 uint32_t dtbdto_div;551 552 /* Mode DTBDTO Rate DTBCLK_DTO<x>_DIV Register553 * ODM 4:1 combine pixel rate/4 2554 * ODM 2:1 combine pixel rate/2 4555 * non-DSC 4:2:0 mode pixel rate/2 4556 * DSC native 4:2:0 pixel rate/2 4557 * DSC native 4:2:2 pixel rate/2 4558 * Other modes pixel rate 8559 */560 if (params->num_odm_segments == 4) {561 dtbdto_div = 2;562 req_dtbclk_khz = params->pixclk_khz / 4;563 } else if ((params->num_odm_segments == 2) ||564 (params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||565 (params->timing->flags.DSC && params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR422566 && !params->timing->dsc_cfg.ycbcr422_simple)) {567 dtbdto_div = 4;568 req_dtbclk_khz = params->pixclk_khz / 2;569 } else570 dtbdto_div = 8;571 572 if (params->ref_dtbclk_khz && req_dtbclk_khz) {573 uint32_t modulo, phase;574 575 // phase / modulo = dtbclk / dtbclk ref576 modulo = params->ref_dtbclk_khz * 1000;577 phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + params->ref_dtbclk_khz - 1),578 params->ref_dtbclk_khz);579 580 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],581 DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);582 583 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);584 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);585 586 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],587 DTBCLK_DTO_ENABLE[params->otg_inst], 1);588 589 REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],590 DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,591 1, 100);592 593 /* The recommended programming sequence to enable DTBCLK DTO to generate594 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should595 * be set only after DTO is enabled596 */597 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],598 PIPE_DTO_SRC_SEL[params->otg_inst], 1);599 } else {600 REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[params->otg_inst],601 DTBCLK_DTO_ENABLE[params->otg_inst], 0,602 PIPE_DTO_SRC_SEL[params->otg_inst], 0,603 DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);604 605 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);606 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);607 }608}609 610void dccg31_set_audio_dtbclk_dto(611 struct dccg *dccg,612 const struct dtbclk_dto_params *params)613{614 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);615 616 if (params->ref_dtbclk_khz && params->req_audio_dtbclk_khz) {617 uint32_t modulo, phase;618 619 // phase / modulo = dtbclk / dtbclk ref620 modulo = params->ref_dtbclk_khz * 1000;621 phase = div_u64((((unsigned long long)modulo * params->req_audio_dtbclk_khz) + params->ref_dtbclk_khz - 1),622 params->ref_dtbclk_khz);623 624 625 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);626 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);627 628 //REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,629 // DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1);630 631 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,632 DCCG_AUDIO_DTO_SEL, 4); // 04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK633 } else {634 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0);635 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0);636 637 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,638 DCCG_AUDIO_DTO_SEL, 3); // 03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO639 }640}641 642void dccg31_get_dccg_ref_freq(struct dccg *dccg,643 unsigned int xtalin_freq_inKhz,644 unsigned int *dccg_ref_freq_inKhz)645{646 /*647 * Assume refclk is sourced from xtalin648 * expect 24MHz649 */650 *dccg_ref_freq_inKhz = xtalin_freq_inKhz;651 return;652}653 654void dccg31_set_dispclk_change_mode(655 struct dccg *dccg,656 enum dentist_dispclk_change_mode change_mode)657{658 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);659 660 REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE,661 change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);662}663 664void dccg31_init(struct dccg *dccg)665{666 /* Set HPO stream encoder to use refclk to avoid case where PHY is667 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which668 * will cause DCN to hang.669 */670 dccg31_disable_symclk32_se(dccg, 0);671 dccg31_disable_symclk32_se(dccg, 1);672 dccg31_disable_symclk32_se(dccg, 2);673 dccg31_disable_symclk32_se(dccg, 3);674 675 dccg31_set_symclk32_le_root_clock_gating(dccg, 0, false);676 dccg31_set_symclk32_le_root_clock_gating(dccg, 1, false);677 678 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {679 dccg31_disable_dpstreamclk(dccg, 0);680 dccg31_disable_dpstreamclk(dccg, 1);681 dccg31_disable_dpstreamclk(dccg, 2);682 dccg31_disable_dpstreamclk(dccg, 3);683 }684 685 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {686 dccg31_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);687 dccg31_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);688 dccg31_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);689 dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);690 dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false);691 }692}693 694void dccg31_otg_add_pixel(struct dccg *dccg,695 uint32_t otg_inst)696{697 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);698 699 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],700 OTG_ADD_PIXEL[otg_inst], 1);701}702 703void dccg31_otg_drop_pixel(struct dccg *dccg,704 uint32_t otg_inst)705{706 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);707 708 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],709 OTG_DROP_PIXEL[otg_inst], 1);710}711 712static const struct dccg_funcs dccg31_funcs = {713 .update_dpp_dto = dccg31_update_dpp_dto,714 .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,715 .dccg_init = dccg31_init,716 .set_dpstreamclk = dccg31_set_dpstreamclk,717 .enable_symclk32_se = dccg31_enable_symclk32_se,718 .disable_symclk32_se = dccg31_disable_symclk32_se,719 .enable_symclk32_le = dccg31_enable_symclk32_le,720 .disable_symclk32_le = dccg31_disable_symclk32_le,721 .set_physymclk = dccg31_set_physymclk,722 .set_dtbclk_dto = dccg31_set_dtbclk_dto,723 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,724 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,725 .otg_add_pixel = dccg31_otg_add_pixel,726 .otg_drop_pixel = dccg31_otg_drop_pixel,727 .set_dispclk_change_mode = dccg31_set_dispclk_change_mode,728 .disable_dsc = dccg31_disable_dscclk,729 .enable_dsc = dccg31_enable_dscclk,730};731 732struct dccg *dccg31_create(733 struct dc_context *ctx,734 const struct dccg_registers *regs,735 const struct dccg_shift *dccg_shift,736 const struct dccg_mask *dccg_mask)737{738 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);739 struct dccg *base;740 741 if (dccg_dcn == NULL) {742 BREAK_TO_DEBUGGER();743 return NULL;744 }745 746 base = &dccg_dcn->base;747 base->ctx = ctx;748 base->funcs = &dccg31_funcs;749 750 dccg_dcn->regs = regs;751 dccg_dcn->dccg_shift = dccg_shift;752 dccg_dcn->dccg_mask = dccg_mask;753 754 return &dccg_dcn->base;755}756