FILE
dcn401_dccg.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
1/* 2 * Copyright 2023 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 "dcn401_dccg.h" 29#include "dcn31/dcn31_dccg.h" 30 31/* 32#include "dmub_common.h" 33#include "dmcub_reg_access_helper.h" 34 35#include "dmub401_common.h" 36#include "dmub401_regs.h" 37#include "dmub401_dccg.h" 38*/ 39 40#define TO_DCN_DCCG(dccg)\ 41 container_of(dccg, struct dcn_dccg, base) 42 43#define REG(reg) \ 44 (dccg_dcn->regs->reg) 45 46#undef FN 47#define FN(reg_name, field_name) \ 48 dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name 49 50#define CTX \ 51 dccg_dcn->base.ctx 52#define DC_LOGGER \ 53 dccg->ctx->logger 54 55static void dcn401_set_dppclk_enable(struct dccg *dccg, 56 uint32_t dpp_inst, uint32_t enable) 57{ 58 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 59 60 switch (dpp_inst) { 61 case 0: 62 REG_UPDATE(DPPCLK_CTRL, DPPCLK0_EN, enable); 63 break; 64 case 1: 65 REG_UPDATE(DPPCLK_CTRL, DPPCLK1_EN, enable); 66 break; 67 case 2: 68 REG_UPDATE(DPPCLK_CTRL, DPPCLK2_EN, enable); 69 break; 70 case 3: 71 REG_UPDATE(DPPCLK_CTRL, DPPCLK3_EN, enable); 72 break; 73 default: 74 break; 75 } 76} 77void dccg401_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk) 78{ 79 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 80 81 if (dccg->ref_dppclk && req_dppclk) { 82 int ref_dppclk = dccg->ref_dppclk; 83 int modulo, phase; 84 85 // phase / modulo = dpp pipe clk / dpp global clk 86 modulo = 0xff; // use FF at the end 87 phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk; 88 89 if (phase > 0xff) { 90 ASSERT(false); 91 phase = 0xff; 92 } 93 94 REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0, 95 DPPCLK0_DTO_PHASE, phase, 96 DPPCLK0_DTO_MODULO, modulo); 97 dcn401_set_dppclk_enable(dccg, dpp_inst, true); 98 } else { 99 dcn401_set_dppclk_enable(dccg, dpp_inst, false); 100 } 101 102 dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk; 103} 104 105/* This function is a workaround for writing to OTG_PIXEL_RATE_DIV 106 * without the probability of causing a DIG FIFO error. 107 */ 108static void dccg401_wait_for_dentist_change_done( 109 struct dccg *dccg) 110{ 111 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 112 113 uint32_t dentist_dispclk_value = REG_READ(DENTIST_DISPCLK_CNTL); 114 115 REG_WRITE(DENTIST_DISPCLK_CNTL, dentist_dispclk_value); 116 REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000); 117} 118 119void dccg401_get_pixel_rate_div( 120 struct dccg *dccg, 121 uint32_t otg_inst, 122 uint32_t *tmds_div, 123 uint32_t *dp_dto_int) 124{ 125 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 126 uint32_t val_tmds_div = PIXEL_RATE_DIV_NA; 127 128 switch (otg_inst) { 129 case 0: 130 REG_GET_2(OTG_PIXEL_RATE_DIV, 131 OTG0_TMDS_PIXEL_RATE_DIV, &val_tmds_div, 132 DPDTO0_INT, dp_dto_int); 133 break; 134 case 1: 135 REG_GET_2(OTG_PIXEL_RATE_DIV, 136 OTG1_TMDS_PIXEL_RATE_DIV, &val_tmds_div, 137 DPDTO1_INT, dp_dto_int); 138 break; 139 case 2: 140 REG_GET_2(OTG_PIXEL_RATE_DIV, 141 OTG2_TMDS_PIXEL_RATE_DIV, &val_tmds_div, 142 DPDTO2_INT, dp_dto_int); 143 break; 144 case 3: 145 REG_GET_2(OTG_PIXEL_RATE_DIV, 146 OTG3_TMDS_PIXEL_RATE_DIV, &val_tmds_div, 147 DPDTO3_INT, dp_dto_int); 148 break; 149 default: 150 BREAK_TO_DEBUGGER(); 151 return; 152 } 153 154 *tmds_div = val_tmds_div == 0 ? PIXEL_RATE_DIV_BY_2 : PIXEL_RATE_DIV_BY_4; 155} 156 157void dccg401_set_pixel_rate_div( 158 struct dccg *dccg, 159 uint32_t otg_inst, 160 enum pixel_rate_div tmds_div, 161 enum pixel_rate_div unused) 162{ 163 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 164 uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA; 165 uint32_t dp_dto_int; 166 uint32_t reg_val; 167 168 // only 2 and 4 are valid on dcn401 169 if (tmds_div != PIXEL_RATE_DIV_BY_2 && tmds_div != PIXEL_RATE_DIV_BY_4) { 170 return; 171 } 172 173 dccg401_get_pixel_rate_div(dccg, otg_inst, &cur_tmds_div, &dp_dto_int); 174 if (tmds_div == cur_tmds_div) 175 return; 176 177 // encode enum to register value 178 reg_val = tmds_div == PIXEL_RATE_DIV_BY_4 ? 1 : 0; 179 180 switch (otg_inst) { 181 case 0: 182 REG_UPDATE(OTG_PIXEL_RATE_DIV, 183 OTG0_TMDS_PIXEL_RATE_DIV, reg_val); 184 185 dccg401_wait_for_dentist_change_done(dccg); 186 break; 187 case 1: 188 REG_UPDATE(OTG_PIXEL_RATE_DIV, 189 OTG1_TMDS_PIXEL_RATE_DIV, reg_val); 190 191 dccg401_wait_for_dentist_change_done(dccg); 192 break; 193 case 2: 194 REG_UPDATE(OTG_PIXEL_RATE_DIV, 195 OTG2_TMDS_PIXEL_RATE_DIV, reg_val); 196 197 dccg401_wait_for_dentist_change_done(dccg); 198 break; 199 case 3: 200 REG_UPDATE(OTG_PIXEL_RATE_DIV, 201 OTG3_TMDS_PIXEL_RATE_DIV, reg_val); 202 203 dccg401_wait_for_dentist_change_done(dccg); 204 break; 205 default: 206 BREAK_TO_DEBUGGER(); 207 return; 208 } 209} 210 211 212void dccg401_set_dtbclk_p_src( 213 struct dccg *dccg, 214 enum streamclk_source src, 215 uint32_t otg_inst) 216{ 217 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 218 219 uint32_t p_src_sel = 0; /* selects dprefclk */ 220 if (src == DTBCLK0) 221 p_src_sel = 2; /* selects dtbclk0 */ 222 223 switch (otg_inst) { 224 case 0: 225 if (src == REFCLK) 226 REG_UPDATE(DTBCLK_P_CNTL, 227 DTBCLK_P0_EN, 0); 228 else 229 REG_UPDATE_2(DTBCLK_P_CNTL, 230 DTBCLK_P0_SRC_SEL, p_src_sel, 231 DTBCLK_P0_EN, 1); 232 break; 233 case 1: 234 if (src == REFCLK) 235 REG_UPDATE(DTBCLK_P_CNTL, 236 DTBCLK_P1_EN, 0); 237 else 238 REG_UPDATE_2(DTBCLK_P_CNTL, 239 DTBCLK_P1_SRC_SEL, p_src_sel, 240 DTBCLK_P1_EN, 1); 241 break; 242 case 2: 243 if (src == REFCLK) 244 REG_UPDATE(DTBCLK_P_CNTL, 245 DTBCLK_P2_EN, 0); 246 else 247 REG_UPDATE_2(DTBCLK_P_CNTL, 248 DTBCLK_P2_SRC_SEL, p_src_sel, 249 DTBCLK_P2_EN, 1); 250 break; 251 case 3: 252 if (src == REFCLK) 253 REG_UPDATE(DTBCLK_P_CNTL, 254 DTBCLK_P3_EN, 0); 255 else 256 REG_UPDATE_2(DTBCLK_P_CNTL, 257 DTBCLK_P3_SRC_SEL, p_src_sel, 258 DTBCLK_P3_EN, 1); 259 break; 260 default: 261 BREAK_TO_DEBUGGER(); 262 return; 263 } 264 265} 266 267void dccg401_set_physymclk( 268 struct dccg *dccg, 269 int phy_inst, 270 enum physymclk_clock_source clk_src, 271 bool force_enable) 272{ 273 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 274 275 /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */ 276 switch (phy_inst) { 277 case 0: 278 if (force_enable) { 279 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 280 PHYASYMCLK_EN, 1, 281 PHYASYMCLK_SRC_SEL, clk_src); 282 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 283 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 284 PHYASYMCLK_ROOT_GATE_DISABLE, 1); 285 } else { 286 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 287 PHYASYMCLK_EN, 0, 288 PHYASYMCLK_SRC_SEL, 0); 289 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 290 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 291 PHYASYMCLK_ROOT_GATE_DISABLE, 0); 292 } 293 break; 294 case 1: 295 if (force_enable) { 296 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 297 PHYBSYMCLK_EN, 1, 298 PHYBSYMCLK_SRC_SEL, clk_src); 299 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 300 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 301 PHYBSYMCLK_ROOT_GATE_DISABLE, 1); 302 } else { 303 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 304 PHYBSYMCLK_EN, 0, 305 PHYBSYMCLK_SRC_SEL, 0); 306 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 307 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 308 PHYBSYMCLK_ROOT_GATE_DISABLE, 0); 309 } 310 break; 311 case 2: 312 if (force_enable) { 313 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 314 PHYCSYMCLK_EN, 1, 315 PHYCSYMCLK_SRC_SEL, clk_src); 316 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 317 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 318 PHYCSYMCLK_ROOT_GATE_DISABLE, 1); 319 } else { 320 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 321 PHYCSYMCLK_EN, 0, 322 PHYCSYMCLK_SRC_SEL, 0); 323 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 324 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 325 PHYCSYMCLK_ROOT_GATE_DISABLE, 0); 326 } 327 break; 328 case 3: 329 if (force_enable) { 330 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 331 PHYDSYMCLK_EN, 1, 332 PHYDSYMCLK_SRC_SEL, clk_src); 333 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 334 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 335 PHYDSYMCLK_ROOT_GATE_DISABLE, 1); 336 } else { 337 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 338 PHYDSYMCLK_EN, 0, 339 PHYDSYMCLK_SRC_SEL, 0); 340 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 341 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, 342 PHYDSYMCLK_ROOT_GATE_DISABLE, 0); 343 } 344 break; 345 default: 346 BREAK_TO_DEBUGGER(); 347 return; 348 } 349} 350 351void dccg401_get_dccg_ref_freq(struct dccg *dccg, 352 unsigned int xtalin_freq_inKhz, 353 unsigned int *dccg_ref_freq_inKhz) 354{ 355 /* 356 * Assume refclk is sourced from xtalin 357 * expect 100MHz 358 */ 359 *dccg_ref_freq_inKhz = xtalin_freq_inKhz; 360 return; 361} 362 363static void dccg401_otg_add_pixel(struct dccg *dccg, 364 uint32_t otg_inst) 365{ 366 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 367 368 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst], 369 OTG_ADD_PIXEL[otg_inst], 1); 370} 371 372static void dccg401_otg_drop_pixel(struct dccg *dccg, 373 uint32_t otg_inst) 374{ 375 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 376 377 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst], 378 OTG_DROP_PIXEL[otg_inst], 1); 379} 380 381void dccg401_enable_symclk32_le( 382 struct dccg *dccg, 383 int hpo_le_inst, 384 enum phyd32clk_clock_source phyd32clk) 385{ 386 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 387 388 /* select one of the PHYD32CLKs as the source for symclk32_le */ 389 switch (hpo_le_inst) { 390 case 0: 391 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 392 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 393 SYMCLK32_LE0_GATE_DISABLE, 1, 394 SYMCLK32_ROOT_LE0_GATE_DISABLE, 1); 395 REG_UPDATE_2(SYMCLK32_LE_CNTL, 396 SYMCLK32_LE0_SRC_SEL, phyd32clk, 397 SYMCLK32_LE0_EN, 1); 398 break; 399 case 1: 400 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 401 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 402 SYMCLK32_LE1_GATE_DISABLE, 1, 403 SYMCLK32_ROOT_LE1_GATE_DISABLE, 1); 404 REG_UPDATE_2(SYMCLK32_LE_CNTL, 405 SYMCLK32_LE1_SRC_SEL, phyd32clk, 406 SYMCLK32_LE1_EN, 1); 407 break; 408 case 2: 409 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 410 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 411 SYMCLK32_LE2_GATE_DISABLE, 1, 412 SYMCLK32_ROOT_LE2_GATE_DISABLE, 1); 413 REG_UPDATE_2(SYMCLK32_LE_CNTL, 414 SYMCLK32_LE2_SRC_SEL, phyd32clk, 415 SYMCLK32_LE2_EN, 1); 416 break; 417 case 3: 418 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 419 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 420 SYMCLK32_LE3_GATE_DISABLE, 1, 421 SYMCLK32_ROOT_LE3_GATE_DISABLE, 1); 422 REG_UPDATE_2(SYMCLK32_LE_CNTL, 423 SYMCLK32_LE3_SRC_SEL, phyd32clk, 424 SYMCLK32_LE3_EN, 1); 425 break; 426 default: 427 BREAK_TO_DEBUGGER(); 428 return; 429 } 430} 431 432void dccg401_disable_symclk32_le( 433 struct dccg *dccg, 434 int hpo_le_inst) 435{ 436 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 437 438 /* set refclk as the source for symclk32_le */ 439 switch (hpo_le_inst) { 440 case 0: 441 REG_UPDATE_2(SYMCLK32_LE_CNTL, 442 SYMCLK32_LE0_SRC_SEL, 0, 443 SYMCLK32_LE0_EN, 0); 444 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 445 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 446 SYMCLK32_LE0_GATE_DISABLE, 0, 447 SYMCLK32_ROOT_LE0_GATE_DISABLE, 0); 448 break; 449 case 1: 450 REG_UPDATE_2(SYMCLK32_LE_CNTL, 451 SYMCLK32_LE1_SRC_SEL, 0, 452 SYMCLK32_LE1_EN, 0); 453 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 454 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 455 SYMCLK32_LE1_GATE_DISABLE, 0, 456 SYMCLK32_ROOT_LE1_GATE_DISABLE, 0); 457 break; 458 case 2: 459 REG_UPDATE_2(SYMCLK32_LE_CNTL, 460 SYMCLK32_LE2_SRC_SEL, 0, 461 SYMCLK32_LE2_EN, 0); 462 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 463 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 464 SYMCLK32_LE2_GATE_DISABLE, 0, 465 SYMCLK32_ROOT_LE2_GATE_DISABLE, 0); 466 break; 467 case 3: 468 REG_UPDATE_2(SYMCLK32_LE_CNTL, 469 SYMCLK32_LE3_SRC_SEL, 0, 470 SYMCLK32_LE3_EN, 0); 471 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 472 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 473 SYMCLK32_LE3_GATE_DISABLE, 0, 474 SYMCLK32_ROOT_LE3_GATE_DISABLE, 0); 475 break; 476 default: 477 BREAK_TO_DEBUGGER(); 478 return; 479 } 480} 481 482static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_hpo_inst) 483{ 484 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 485 486 /* enabled to select one of the DTBCLKs for pipe */ 487 switch (dp_hpo_inst) { 488 case 0: 489 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 490 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 491 DPSTREAMCLK0_ROOT_GATE_DISABLE, 1, 492 DPSTREAMCLK0_GATE_DISABLE, 1); 493 REG_UPDATE_2(DPSTREAMCLK_CNTL, 494 DPSTREAMCLK0_SRC_SEL, otg_inst, 495 DPSTREAMCLK0_EN, 1); 496 break; 497 case 1: 498 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 499 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 500 DPSTREAMCLK1_ROOT_GATE_DISABLE, 1, 501 DPSTREAMCLK1_GATE_DISABLE, 1); 502 REG_UPDATE_2(DPSTREAMCLK_CNTL, 503 DPSTREAMCLK1_SRC_SEL, otg_inst, 504 DPSTREAMCLK1_EN, 1); 505 break; 506 case 2: 507 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 508 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 509 DPSTREAMCLK2_ROOT_GATE_DISABLE, 1, 510 DPSTREAMCLK2_GATE_DISABLE, 1); 511 REG_UPDATE_2(DPSTREAMCLK_CNTL, 512 DPSTREAMCLK2_SRC_SEL, otg_inst, 513 DPSTREAMCLK2_EN, 1); 514 break; 515 case 3: 516 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 517 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 518 DPSTREAMCLK3_ROOT_GATE_DISABLE, 1, 519 DPSTREAMCLK3_GATE_DISABLE, 1); 520 REG_UPDATE_2(DPSTREAMCLK_CNTL, 521 DPSTREAMCLK3_SRC_SEL, otg_inst, 522 DPSTREAMCLK3_EN, 1); 523 break; 524 default: 525 BREAK_TO_DEBUGGER(); 526 return; 527 } 528 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 529 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, 530 DPSTREAMCLK_GATE_DISABLE, 1, 531 DPSTREAMCLK_ROOT_GATE_DISABLE, 1); 532} 533 534void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst) 535{ 536 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 537 538 switch (dp_hpo_inst) { 539 case 0: 540 REG_UPDATE(DPSTREAMCLK_CNTL, 541 DPSTREAMCLK0_EN, 0); 542 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 543 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 544 DPSTREAMCLK0_ROOT_GATE_DISABLE, 0, 545 DPSTREAMCLK0_GATE_DISABLE, 0); 546 break; 547 case 1: 548 REG_UPDATE(DPSTREAMCLK_CNTL, 549 DPSTREAMCLK1_EN, 0); 550 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 551 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 552 DPSTREAMCLK1_ROOT_GATE_DISABLE, 0, 553 DPSTREAMCLK1_GATE_DISABLE, 0); 554 break; 555 case 2: 556 REG_UPDATE(DPSTREAMCLK_CNTL, 557 DPSTREAMCLK2_EN, 0); 558 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 559 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 560 DPSTREAMCLK2_ROOT_GATE_DISABLE, 0, 561 DPSTREAMCLK2_GATE_DISABLE, 0); 562 break; 563 case 3: 564 REG_UPDATE(DPSTREAMCLK_CNTL, 565 DPSTREAMCLK3_EN, 0); 566 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 567 REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5, 568 DPSTREAMCLK3_ROOT_GATE_DISABLE, 0, 569 DPSTREAMCLK3_GATE_DISABLE, 0); 570 break; 571 default: 572 BREAK_TO_DEBUGGER(); 573 return; 574 } 575} 576 577void dccg401_set_dpstreamclk( 578 struct dccg *dccg, 579 enum streamclk_source src, 580 int otg_inst, 581 int dp_hpo_inst) 582{ 583 /* enabled to select one of the DTBCLKs for pipe */ 584 if (src == REFCLK) 585 dccg401_disable_dpstreamclk(dccg, dp_hpo_inst); 586 else 587 dccg401_enable_dpstreamclk(dccg, otg_inst, dp_hpo_inst); 588} 589 590void dccg401_set_dp_dto( 591 struct dccg *dccg, 592 const struct dp_dto_params *params) 593{ 594 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 595 596 bool enable = false; 597 598 if (params->otg_inst > 3) { 599 /* dcn401 only has 4 instances */ 600 BREAK_TO_DEBUGGER(); 601 return; 602 } 603 if (!params->refclk_hz) { 604 BREAK_TO_DEBUGGER(); 605 return; 606 } 607 608 if (!dc_is_tmds_signal(params->signal)) { 609 uint64_t dto_integer; 610 uint64_t dto_phase_hz; 611 uint64_t dto_modulo_hz = params->refclk_hz; 612 613 enable = true; 614 615 /* Set DTO values: 616 * int = target_pix_rate / reference_clock 617 * phase = target_pix_rate - int * reference_clock, 618 * modulo = reference_clock */ 619 dto_integer = div_u64(params->pixclk_hz, dto_modulo_hz); 620 dto_phase_hz = params->pixclk_hz - dto_integer * dto_modulo_hz; 621 622 if (dto_phase_hz <= 0 && dto_integer <= 0) { 623 /* negative pixel rate should never happen */ 624 BREAK_TO_DEBUGGER(); 625 return; 626 } 627 628 switch (params->otg_inst) { 629 case 0: 630 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 1); 631 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3, 632 SYMCLK32_SE0_GATE_DISABLE, 1, 633 SYMCLK32_ROOT_SE0_GATE_DISABLE, 1, 634 SYMCLK32_LE0_GATE_DISABLE, 1, 635 SYMCLK32_ROOT_LE0_GATE_DISABLE, 1); 636 break; 637 case 1: 638 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 1); 639 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3, 640 SYMCLK32_SE1_GATE_DISABLE, 1, 641 SYMCLK32_ROOT_SE1_GATE_DISABLE, 1, 642 SYMCLK32_LE1_GATE_DISABLE, 1, 643 SYMCLK32_ROOT_LE1_GATE_DISABLE, 1); 644 break; 645 case 2: 646 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 1); 647 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3, 648 SYMCLK32_SE2_GATE_DISABLE, 1, 649 SYMCLK32_ROOT_SE2_GATE_DISABLE, 1, 650 SYMCLK32_LE2_GATE_DISABLE, 1, 651 SYMCLK32_ROOT_LE2_GATE_DISABLE, 1); 652 break; 653 case 3: 654 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 1); 655 REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3, 656 SYMCLK32_SE3_GATE_DISABLE, 1, 657 SYMCLK32_ROOT_SE3_GATE_DISABLE, 1, 658 SYMCLK32_LE3_GATE_DISABLE, 1, 659 SYMCLK32_ROOT_LE3_GATE_DISABLE, 1); 660 break; 661 } 662 663 dccg401_set_dtbclk_p_src(dccg, params->clk_src, params->otg_inst); 664 665 REG_WRITE(DP_DTO_PHASE[params->otg_inst], dto_phase_hz); 666 REG_WRITE(DP_DTO_MODULO[params->otg_inst], dto_modulo_hz); 667 668 switch (params->otg_inst) { 669 case 0: 670 REG_UPDATE(OTG_PIXEL_RATE_DIV, 671 DPDTO0_INT, dto_integer); 672 break; 673 case 1: 674 REG_UPDATE(OTG_PIXEL_RATE_DIV, 675 DPDTO1_INT, dto_integer); 676 break; 677 case 2: 678 REG_UPDATE(OTG_PIXEL_RATE_DIV, 679 DPDTO2_INT, dto_integer); 680 break; 681 case 3: 682 REG_UPDATE(OTG_PIXEL_RATE_DIV, 683 DPDTO3_INT, dto_integer); 684 break; 685 default: 686 BREAK_TO_DEBUGGER(); 687 return; 688 } 689 } 690 691 /* Toggle DTO */ 692 REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst], 693 DP_DTO_ENABLE[params->otg_inst], enable, 694 PIPE_DTO_SRC_SEL[params->otg_inst], enable); 695} 696 697void dccg401_init(struct dccg *dccg) 698{ 699 /* Set HPO stream encoder to use refclk to avoid case where PHY is 700 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which 701 * will cause DCN to hang. 702 */ 703 dccg31_disable_symclk32_se(dccg, 0); 704 dccg31_disable_symclk32_se(dccg, 1); 705 dccg31_disable_symclk32_se(dccg, 2); 706 dccg31_disable_symclk32_se(dccg, 3); 707 708 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) { 709 dccg401_disable_symclk32_le(dccg, 0); 710 dccg401_disable_symclk32_le(dccg, 1); 711 dccg401_disable_symclk32_le(dccg, 2); 712 dccg401_disable_symclk32_le(dccg, 3); 713 } 714 715 if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { 716 dccg401_disable_dpstreamclk(dccg, 0); 717 dccg401_disable_dpstreamclk(dccg, 1); 718 dccg401_disable_dpstreamclk(dccg, 2); 719 dccg401_disable_dpstreamclk(dccg, 3); 720 } 721 722 if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) { 723 dccg401_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 724 dccg401_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 725 dccg401_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 726 dccg401_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false); 727 } 728} 729 730void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst, uint32_t num_slices_h) 731{ 732 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 733 734 switch (inst) { 735 case 0: 736 REG_UPDATE_2(DSCCLK0_DTO_PARAM, 737 DSCCLK0_DTO_PHASE, 1, 738 DSCCLK0_DTO_MODULO, 1); 739 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1); 740 741 break; 742 case 1: 743 REG_UPDATE_2(DSCCLK1_DTO_PARAM, 744 DSCCLK1_DTO_PHASE, 1, 745 DSCCLK1_DTO_MODULO, 1); 746 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1); 747 break; 748 case 2: 749 REG_UPDATE_2(DSCCLK2_DTO_PARAM, 750 DSCCLK2_DTO_PHASE, 1, 751 DSCCLK2_DTO_MODULO, 1); 752 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1); 753 break; 754 case 3: 755 REG_UPDATE_2(DSCCLK3_DTO_PARAM, 756 DSCCLK3_DTO_PHASE, 1, 757 DSCCLK3_DTO_MODULO, 1); 758 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1); 759 break; 760 default: 761 BREAK_TO_DEBUGGER(); 762 return; 763 } 764} 765 766void dccg401_set_ref_dscclk(struct dccg *dccg, 767 uint32_t dsc_inst) 768{ 769 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 770 771 switch (dsc_inst) { 772 case 0: 773 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 0); 774 REG_UPDATE_2(DSCCLK0_DTO_PARAM, 775 DSCCLK0_DTO_PHASE, 0, 776 DSCCLK0_DTO_MODULO, 0); 777 break; 778 case 1: 779 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0); 780 REG_UPDATE_2(DSCCLK1_DTO_PARAM, 781 DSCCLK1_DTO_PHASE, 0, 782 DSCCLK1_DTO_MODULO, 0); 783 break; 784 case 2: 785 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0); 786 REG_UPDATE_2(DSCCLK2_DTO_PARAM, 787 DSCCLK2_DTO_PHASE, 0, 788 DSCCLK2_DTO_MODULO, 0); 789 break; 790 case 3: 791 REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0); 792 REG_UPDATE_2(DSCCLK3_DTO_PARAM, 793 DSCCLK3_DTO_PHASE, 0, 794 DSCCLK3_DTO_MODULO, 0); 795 break; 796 default: 797 return; 798 } 799} 800 801void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst) 802{ 803 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 804 805 switch (stream_enc_inst) { 806 case 0: 807 REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, 808 SYMCLKA_FE_EN, 1, 809 SYMCLKA_FE_SRC_SEL, link_enc_inst); 810 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) 811 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1); 812 break; 813 case 1: 814 REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, 815 SYMCLKB_FE_EN, 1, 816 SYMCLKB_FE_SRC_SEL, link_enc_inst); 817 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) 818 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1); 819 break; 820 case 2: 821 REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, 822 SYMCLKC_FE_EN, 1, 823 SYMCLKC_FE_SRC_SEL, link_enc_inst); 824 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) 825 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1); 826 break; 827 case 3: 828 REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, 829 SYMCLKD_FE_EN, 1, 830 SYMCLKD_FE_SRC_SEL, link_enc_inst); 831 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) 832 REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1); 833 break; 834 } 835} 836 837void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst) 838{ 839 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 840 841 switch (stream_enc_inst) { 842 case 0: 843 REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, 844 SYMCLKA_FE_EN, 0, 845 SYMCLKA_FE_SRC_SEL, 0); 846 break; 847 case 1: 848 REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, 849 SYMCLKB_FE_EN, 0, 850 SYMCLKB_FE_SRC_SEL, 0); 851 break; 852 case 2: 853 REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, 854 SYMCLKC_FE_EN, 0, 855 SYMCLKC_FE_SRC_SEL, 0); 856 break; 857 case 3: 858 REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, 859 SYMCLKD_FE_EN, 0, 860 SYMCLKD_FE_SRC_SEL, 0); 861 break; 862 } 863} 864 865static const struct dccg_funcs dccg401_funcs = { 866 .update_dpp_dto = dccg401_update_dpp_dto, 867 .get_dccg_ref_freq = dccg401_get_dccg_ref_freq, 868 .dccg_init = dccg401_init, 869 .set_dpstreamclk = dccg401_set_dpstreamclk, 870 .enable_symclk32_se = dccg31_enable_symclk32_se, 871 .disable_symclk32_se = dccg31_disable_symclk32_se, 872 .enable_symclk32_le = dccg401_enable_symclk32_le, 873 .disable_symclk32_le = dccg401_disable_symclk32_le, 874 .set_physymclk = dccg401_set_physymclk, 875 .set_dtbclk_dto = NULL, 876 .set_dto_dscclk = dccg401_set_dto_dscclk, 877 .set_ref_dscclk = dccg401_set_ref_dscclk, 878 .set_valid_pixel_rate = NULL, 879 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, 880 .set_audio_dtbclk_dto = NULL, 881 .otg_add_pixel = dccg401_otg_add_pixel, 882 .otg_drop_pixel = dccg401_otg_drop_pixel, 883 .set_pixel_rate_div = dccg401_set_pixel_rate_div, 884 .get_pixel_rate_div = dccg401_get_pixel_rate_div, 885 .set_dp_dto = dccg401_set_dp_dto, 886 .enable_symclk_se = dccg401_enable_symclk_se, 887 .disable_symclk_se = dccg401_disable_symclk_se, 888 .set_dtbclk_p_src = dccg401_set_dtbclk_p_src, 889 .dccg_read_reg_state = dccg31_read_reg_state 890}; 891 892struct dccg *dccg401_create( 893 struct dc_context *ctx, 894 const struct dccg_registers *regs, 895 const struct dccg_shift *dccg_shift, 896 const struct dccg_mask *dccg_mask) 897{ 898 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); 899 struct dccg *base; 900 901 if (dccg_dcn == NULL) { 902 BREAK_TO_DEBUGGER(); 903 return NULL; 904 } 905 906 base = &dccg_dcn->base; 907 base->ctx = ctx; 908 base->funcs = &dccg401_funcs; 909 910 dccg_dcn->regs = regs; 911 dccg_dcn->dccg_shift = dccg_shift; 912 dccg_dcn->dccg_mask = dccg_mask; 913 914 return &dccg_dcn->base; 915}
~/
Read-only file preview.