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.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 97 static void dccg31_enable_dpstreamclk(struct dccg *dccg, int otg_inst) 98 { 99 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 100 101 /* enabled to select one of the DTBCLKs for pipe */ 102 switch (otg_inst) { 103 case 0: 104 REG_UPDATE(DPSTREAMCLK_CNTL, 105 DPSTREAMCLK_PIPE0_EN, 1); 106 break; 107 case 1: 108 REG_UPDATE(DPSTREAMCLK_CNTL, 109 DPSTREAMCLK_PIPE1_EN, 1); 110 break; 111 case 2: 112 REG_UPDATE(DPSTREAMCLK_CNTL, 113 DPSTREAMCLK_PIPE2_EN, 1); 114 break; 115 case 3: 116 REG_UPDATE(DPSTREAMCLK_CNTL, 117 DPSTREAMCLK_PIPE3_EN, 1); 118 break; 119 default: 120 BREAK_TO_DEBUGGER(); 121 return; 122 } 123 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 124 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 125 DPSTREAMCLK_GATE_DISABLE, 1, 126 DPSTREAMCLK_ROOT_GATE_DISABLE, 1); 127 } 128 129 static 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 161 void 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 else 170 dccg31_enable_dpstreamclk(dccg, otg_inst); 171 } 172 173 void 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 226 void 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 276 void 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 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 289 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 290 SYMCLK32_LE0_GATE_DISABLE, 1, 291 SYMCLK32_ROOT_LE0_GATE_DISABLE, 1); 292 REG_UPDATE_2(SYMCLK32_LE_CNTL, 293 SYMCLK32_LE0_SRC_SEL, phyd32clk, 294 SYMCLK32_LE0_EN, 1); 295 break; 296 case 1: 297 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 298 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 299 SYMCLK32_LE1_GATE_DISABLE, 1, 300 SYMCLK32_ROOT_LE1_GATE_DISABLE, 1); 301 REG_UPDATE_2(SYMCLK32_LE_CNTL, 302 SYMCLK32_LE1_SRC_SEL, phyd32clk, 303 SYMCLK32_LE1_EN, 1); 304 break; 305 default: 306 BREAK_TO_DEBUGGER(); 307 return; 308 } 309 } 310 311 void dccg31_disable_symclk32_le( 312 struct dccg *dccg, 313 int hpo_le_inst) 314 { 315 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 316 317 /* set refclk as the source for symclk32_le */ 318 switch (hpo_le_inst) { 319 case 0: 320 REG_UPDATE_2(SYMCLK32_LE_CNTL, 321 SYMCLK32_LE0_SRC_SEL, 0, 322 SYMCLK32_LE0_EN, 0); 323 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 324 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 REG_UPDATE_2(SYMCLK32_LE_CNTL, 330 SYMCLK32_LE1_SRC_SEL, 0, 331 SYMCLK32_LE1_EN, 0); 332 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 333 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 BREAK_TO_DEBUGGER(); 339 return; 340 } 341 } 342 343 void dccg31_disable_dscclk(struct dccg *dccg, int inst) 344 { 345 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 346 347 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 switch (inst) { 351 case 0: 352 REG_UPDATE(DSCCLK_DTO_CTRL, 353 DSCCLK0_DTO_ENABLE, 1); 354 REG_UPDATE_2(DSCCLK0_DTO_PARAM, 355 DSCCLK0_DTO_PHASE, 0, 356 DSCCLK0_DTO_MODULO, 1); 357 break; 358 case 1: 359 REG_UPDATE(DSCCLK_DTO_CTRL, 360 DSCCLK1_DTO_ENABLE, 1); 361 REG_UPDATE_2(DSCCLK1_DTO_PARAM, 362 DSCCLK1_DTO_PHASE, 0, 363 DSCCLK1_DTO_MODULO, 1); 364 break; 365 case 2: 366 REG_UPDATE(DSCCLK_DTO_CTRL, 367 DSCCLK2_DTO_ENABLE, 1); 368 REG_UPDATE_2(DSCCLK2_DTO_PARAM, 369 DSCCLK2_DTO_PHASE, 0, 370 DSCCLK2_DTO_MODULO, 1); 371 break; 372 case 3: 373 if (REG(DSCCLK3_DTO_PARAM)) { 374 REG_UPDATE(DSCCLK_DTO_CTRL, 375 DSCCLK3_DTO_ENABLE, 1); 376 REG_UPDATE_2(DSCCLK3_DTO_PARAM, 377 DSCCLK3_DTO_PHASE, 0, 378 DSCCLK3_DTO_MODULO, 1); 379 } 380 break; 381 default: 382 BREAK_TO_DEBUGGER(); 383 return; 384 } 385 } 386 387 void dccg31_enable_dscclk(struct dccg *dccg, int inst) 388 { 389 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 390 391 if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) 392 return; 393 //Disable DTO 394 switch (inst) { 395 case 0: 396 REG_UPDATE_2(DSCCLK0_DTO_PARAM, 397 DSCCLK0_DTO_PHASE, 0, 398 DSCCLK0_DTO_MODULO, 0); 399 REG_UPDATE(DSCCLK_DTO_CTRL, 400 DSCCLK0_DTO_ENABLE, 0); 401 break; 402 case 1: 403 REG_UPDATE_2(DSCCLK1_DTO_PARAM, 404 DSCCLK1_DTO_PHASE, 0, 405 DSCCLK1_DTO_MODULO, 0); 406 REG_UPDATE(DSCCLK_DTO_CTRL, 407 DSCCLK1_DTO_ENABLE, 0); 408 break; 409 case 2: 410 REG_UPDATE_2(DSCCLK2_DTO_PARAM, 411 DSCCLK2_DTO_PHASE, 0, 412 DSCCLK2_DTO_MODULO, 0); 413 REG_UPDATE(DSCCLK_DTO_CTRL, 414 DSCCLK2_DTO_ENABLE, 0); 415 break; 416 case 3: 417 if (REG(DSCCLK3_DTO_PARAM)) { 418 REG_UPDATE(DSCCLK_DTO_CTRL, 419 DSCCLK3_DTO_ENABLE, 0); 420 REG_UPDATE_2(DSCCLK3_DTO_PARAM, 421 DSCCLK3_DTO_PHASE, 0, 422 DSCCLK3_DTO_MODULO, 0); 423 } 424 break; 425 default: 426 BREAK_TO_DEBUGGER(); 427 return; 428 } 429 } 430 431 void dccg31_set_physymclk( 432 struct dccg *dccg, 433 int phy_inst, 434 enum physymclk_clock_source clk_src, 435 bool force_enable) 436 { 437 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 438 439 /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */ 440 switch (phy_inst) { 441 case 0: 442 if (force_enable) { 443 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 444 PHYASYMCLK_FORCE_EN, 1, 445 PHYASYMCLK_FORCE_SRC_SEL, clk_src); 446 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 447 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 448 PHYASYMCLK_GATE_DISABLE, 1); 449 } else { 450 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 451 PHYASYMCLK_FORCE_EN, 0, 452 PHYASYMCLK_FORCE_SRC_SEL, 0); 453 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 454 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 455 PHYASYMCLK_GATE_DISABLE, 0); 456 } 457 break; 458 case 1: 459 if (force_enable) { 460 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 461 PHYBSYMCLK_FORCE_EN, 1, 462 PHYBSYMCLK_FORCE_SRC_SEL, clk_src); 463 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 464 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 465 PHYBSYMCLK_GATE_DISABLE, 1); 466 } else { 467 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 468 PHYBSYMCLK_FORCE_EN, 0, 469 PHYBSYMCLK_FORCE_SRC_SEL, 0); 470 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 471 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 472 PHYBSYMCLK_GATE_DISABLE, 0); 473 } 474 break; 475 case 2: 476 if (force_enable) { 477 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 478 PHYCSYMCLK_FORCE_EN, 1, 479 PHYCSYMCLK_FORCE_SRC_SEL, clk_src); 480 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 481 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 482 PHYCSYMCLK_GATE_DISABLE, 1); 483 } else { 484 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 485 PHYCSYMCLK_FORCE_EN, 0, 486 PHYCSYMCLK_FORCE_SRC_SEL, 0); 487 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 488 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 489 PHYCSYMCLK_GATE_DISABLE, 0); 490 } 491 break; 492 case 3: 493 if (force_enable) { 494 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 495 PHYDSYMCLK_FORCE_EN, 1, 496 PHYDSYMCLK_FORCE_SRC_SEL, clk_src); 497 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 498 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 499 PHYDSYMCLK_GATE_DISABLE, 1); 500 } else { 501 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 502 PHYDSYMCLK_FORCE_EN, 0, 503 PHYDSYMCLK_FORCE_SRC_SEL, 0); 504 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 505 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 506 PHYDSYMCLK_GATE_DISABLE, 0); 507 } 508 break; 509 case 4: 510 if (force_enable) { 511 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, 512 PHYESYMCLK_FORCE_EN, 1, 513 PHYESYMCLK_FORCE_SRC_SEL, clk_src); 514 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 515 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 516 PHYESYMCLK_GATE_DISABLE, 1); 517 } else { 518 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, 519 PHYESYMCLK_FORCE_EN, 0, 520 PHYESYMCLK_FORCE_SRC_SEL, 0); 521 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 522 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 523 PHYESYMCLK_GATE_DISABLE, 0); 524 } 525 break; 526 default: 527 BREAK_TO_DEBUGGER(); 528 return; 529 } 530 } 531 532 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ 533 void dccg31_set_dtbclk_dto( 534 struct dccg *dccg, 535 const struct dtbclk_dto_params *params) 536 { 537 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 538 int req_dtbclk_khz = params->pixclk_khz; 539 uint32_t dtbdto_div; 540 541 /* Mode DTBDTO Rate DTBCLK_DTO<x>_DIV Register 542 * ODM 4:1 combine pixel rate/4 2 543 * ODM 2:1 combine pixel rate/2 4 544 * non-DSC 4:2:0 mode pixel rate/2 4 545 * DSC native 4:2:0 pixel rate/2 4 546 * DSC native 4:2:2 pixel rate/2 4 547 * Other modes pixel rate 8 548 */ 549 if (params->num_odm_segments == 4) { 550 dtbdto_div = 2; 551 req_dtbclk_khz = params->pixclk_khz / 4; 552 } else if ((params->num_odm_segments == 2) || 553 (params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) || 554 (params->timing->flags.DSC && params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 555 && !params->timing->dsc_cfg.ycbcr422_simple)) { 556 dtbdto_div = 4; 557 req_dtbclk_khz = params->pixclk_khz / 2; 558 } else 559 dtbdto_div = 8; 560 561 if (params->ref_dtbclk_khz && req_dtbclk_khz) { 562 uint32_t modulo, phase; 563 564 // phase / modulo = dtbclk / dtbclk ref 565 modulo = params->ref_dtbclk_khz * 1000; 566 phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + params->ref_dtbclk_khz - 1), 567 params->ref_dtbclk_khz); 568 569 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], 570 DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div); 571 572 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo); 573 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase); 574 575 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], 576 DTBCLK_DTO_ENABLE[params->otg_inst], 1); 577 578 REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst], 579 DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1, 580 1, 100); 581 582 /* The recommended programming sequence to enable DTBCLK DTO to generate 583 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should 584 * be set only after DTO is enabled 585 */ 586 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], 587 PIPE_DTO_SRC_SEL[params->otg_inst], 1); 588 } else { 589 REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[params->otg_inst], 590 DTBCLK_DTO_ENABLE[params->otg_inst], 0, 591 PIPE_DTO_SRC_SEL[params->otg_inst], 0, 592 DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div); 593 594 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0); 595 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0); 596 } 597 } 598 599 void dccg31_set_audio_dtbclk_dto( 600 struct dccg *dccg, 601 const struct dtbclk_dto_params *params) 602 { 603 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 604 605 if (params->ref_dtbclk_khz && params->req_audio_dtbclk_khz) { 606 uint32_t modulo, phase; 607 608 // phase / modulo = dtbclk / dtbclk ref 609 modulo = params->ref_dtbclk_khz * 1000; 610 phase = div_u64((((unsigned long long)modulo * params->req_audio_dtbclk_khz) + params->ref_dtbclk_khz - 1), 611 params->ref_dtbclk_khz); 612 613 614 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo); 615 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase); 616 617 //REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 618 // DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1); 619 620 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 621 DCCG_AUDIO_DTO_SEL, 4); // 04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK 622 } else { 623 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0); 624 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0); 625 626 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 627 DCCG_AUDIO_DTO_SEL, 3); // 03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO 628 } 629 } 630 631 void dccg31_get_dccg_ref_freq(struct dccg *dccg, 632 unsigned int xtalin_freq_inKhz, 633 unsigned int *dccg_ref_freq_inKhz) 634 { 635 /* 636 * Assume refclk is sourced from xtalin 637 * expect 24MHz 638 */ 639 *dccg_ref_freq_inKhz = xtalin_freq_inKhz; 640 return; 641 } 642 643 void dccg31_set_dispclk_change_mode( 644 struct dccg *dccg, 645 enum dentist_dispclk_change_mode change_mode) 646 { 647 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 648 649 REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, 650 change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0); 651 } 652 653 void dccg31_init(struct dccg *dccg) 654 { 655 /* Set HPO stream encoder to use refclk to avoid case where PHY is 656 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which 657 * will cause DCN to hang. 658 */ 659 dccg31_disable_symclk32_se(dccg, 0); 660 dccg31_disable_symclk32_se(dccg, 1); 661 dccg31_disable_symclk32_se(dccg, 2); 662 dccg31_disable_symclk32_se(dccg, 3); 663 664 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) { 665 dccg31_disable_symclk32_le(dccg, 0); 666 dccg31_disable_symclk32_le(dccg, 1); 667 } 668 669 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { 670 dccg31_disable_dpstreamclk(dccg, 0); 671 dccg31_disable_dpstreamclk(dccg, 1); 672 dccg31_disable_dpstreamclk(dccg, 2); 673 dccg31_disable_dpstreamclk(dccg, 3); 674 } 675 676 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) { 677 dccg31_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 678 dccg31_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 679 dccg31_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 680 dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 681 dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 682 } 683 } 684 685 void dccg31_otg_add_pixel(struct dccg *dccg, 686 uint32_t otg_inst) 687 { 688 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 689 690 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst], 691 OTG_ADD_PIXEL[otg_inst], 1); 692 } 693 694 void dccg31_otg_drop_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_DROP_PIXEL[otg_inst], 1); 701 } 702 703 static const struct dccg_funcs dccg31_funcs = { 704 .update_dpp_dto = dccg31_update_dpp_dto, 705 .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, 706 .dccg_init = dccg31_init, 707 .set_dpstreamclk = dccg31_set_dpstreamclk, 708 .enable_symclk32_se = dccg31_enable_symclk32_se, 709 .disable_symclk32_se = dccg31_disable_symclk32_se, 710 .enable_symclk32_le = dccg31_enable_symclk32_le, 711 .disable_symclk32_le = dccg31_disable_symclk32_le, 712 .set_physymclk = dccg31_set_physymclk, 713 .set_dtbclk_dto = dccg31_set_dtbclk_dto, 714 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto, 715 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, 716 .otg_add_pixel = dccg31_otg_add_pixel, 717 .otg_drop_pixel = dccg31_otg_drop_pixel, 718 .set_dispclk_change_mode = dccg31_set_dispclk_change_mode, 719 .disable_dsc = dccg31_disable_dscclk, 720 .enable_dsc = dccg31_enable_dscclk, 721 }; 722 723 struct dccg *dccg31_create( 724 struct dc_context *ctx, 725 const struct dccg_registers *regs, 726 const struct dccg_shift *dccg_shift, 727 const struct dccg_mask *dccg_mask) 728 { 729 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); 730 struct dccg *base; 731 732 if (dccg_dcn == NULL) { 733 BREAK_TO_DEBUGGER(); 734 return NULL; 735 } 736 737 base = &dccg_dcn->base; 738 base->ctx = ctx; 739 base->funcs = &dccg31_funcs; 740 741 dccg_dcn->regs = regs; 742 dccg_dcn->dccg_shift = dccg_shift; 743 dccg_dcn->dccg_mask = dccg_mask; 744 745 return &dccg_dcn->base; 746 } 747