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