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