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