1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include <linux/log2.h> 7 #include <linux/math64.h> 8 9 #include <drm/drm_print.h> 10 11 #include "i915_reg.h" 12 #include "i915_utils.h" 13 #include "intel_cx0_phy.h" 14 #include "intel_cx0_phy_regs.h" 15 #include "intel_ddi.h" 16 #include "intel_ddi_buf_trans.h" 17 #include "intel_de.h" 18 #include "intel_display_types.h" 19 #include "intel_dp.h" 20 #include "intel_hdmi.h" 21 #include "intel_panel.h" 22 #include "intel_psr.h" 23 #include "intel_snps_hdmi_pll.h" 24 #include "intel_tc.h" 25 26 #define MB_WRITE_COMMITTED true 27 #define MB_WRITE_UNCOMMITTED false 28 29 #define for_each_cx0_lane_in_mask(__lane_mask, __lane) \ 30 for ((__lane) = 0; (__lane) < 2; (__lane)++) \ 31 for_each_if((__lane_mask) & BIT(__lane)) 32 33 #define INTEL_CX0_LANE0 BIT(0) 34 #define INTEL_CX0_LANE1 BIT(1) 35 #define INTEL_CX0_BOTH_LANES (INTEL_CX0_LANE1 | INTEL_CX0_LANE0) 36 37 bool intel_encoder_is_c10phy(struct intel_encoder *encoder) 38 { 39 struct intel_display *display = to_intel_display(encoder); 40 enum phy phy = intel_encoder_to_phy(encoder); 41 42 if (display->platform.pantherlake && phy == PHY_A) 43 return true; 44 45 if ((display->platform.lunarlake || display->platform.meteorlake) && phy < PHY_C) 46 return true; 47 48 return false; 49 } 50 51 static int lane_mask_to_lane(u8 lane_mask) 52 { 53 if (WARN_ON((lane_mask & ~INTEL_CX0_BOTH_LANES) || 54 hweight8(lane_mask) != 1)) 55 return 0; 56 57 return ilog2(lane_mask); 58 } 59 60 static u8 intel_cx0_get_owned_lane_mask(struct intel_encoder *encoder) 61 { 62 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 63 64 if (!intel_tc_port_in_dp_alt_mode(dig_port)) 65 return INTEL_CX0_BOTH_LANES; 66 67 /* 68 * In DP-alt with pin assignment D, only PHY lane 0 is owned 69 * by display and lane 1 is owned by USB. 70 */ 71 return intel_tc_port_max_lane_count(dig_port) > 2 72 ? INTEL_CX0_BOTH_LANES : INTEL_CX0_LANE0; 73 } 74 75 static void 76 assert_dc_off(struct intel_display *display) 77 { 78 bool enabled; 79 80 enabled = intel_display_power_is_enabled(display, POWER_DOMAIN_DC_OFF); 81 drm_WARN_ON(display->drm, !enabled); 82 } 83 84 static void intel_cx0_program_msgbus_timer(struct intel_encoder *encoder) 85 { 86 struct intel_display *display = to_intel_display(encoder); 87 int lane; 88 89 for_each_cx0_lane_in_mask(INTEL_CX0_BOTH_LANES, lane) 90 intel_de_rmw(display, 91 XELPDP_PORT_MSGBUS_TIMER(display, encoder->port, lane), 92 XELPDP_PORT_MSGBUS_TIMER_VAL_MASK, 93 XELPDP_PORT_MSGBUS_TIMER_VAL); 94 } 95 96 /* 97 * Prepare HW for CX0 phy transactions. 98 * 99 * It is required that PSR and DC5/6 are disabled before any CX0 message 100 * bus transaction is executed. 101 * 102 * We also do the msgbus timer programming here to ensure that the timer 103 * is already programmed before any access to the msgbus. 104 */ 105 static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder) 106 { 107 struct intel_display *display = to_intel_display(encoder); 108 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 109 intel_wakeref_t wakeref; 110 111 intel_psr_pause(intel_dp); 112 wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF); 113 intel_cx0_program_msgbus_timer(encoder); 114 115 return wakeref; 116 } 117 118 static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref) 119 { 120 struct intel_display *display = to_intel_display(encoder); 121 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 122 123 intel_psr_resume(intel_dp); 124 intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref); 125 } 126 127 static void intel_clear_response_ready_flag(struct intel_encoder *encoder, 128 int lane) 129 { 130 struct intel_display *display = to_intel_display(encoder); 131 132 intel_de_rmw(display, 133 XELPDP_PORT_P2M_MSGBUS_STATUS(display, encoder->port, lane), 134 0, XELPDP_PORT_P2M_RESPONSE_READY | XELPDP_PORT_P2M_ERROR_SET); 135 } 136 137 static void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane) 138 { 139 struct intel_display *display = to_intel_display(encoder); 140 enum port port = encoder->port; 141 enum phy phy = intel_encoder_to_phy(encoder); 142 143 intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 144 XELPDP_PORT_M2P_TRANSACTION_RESET); 145 146 if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 147 XELPDP_PORT_M2P_TRANSACTION_RESET, 148 XELPDP_MSGBUS_TIMEOUT_SLOW)) { 149 drm_err_once(display->drm, 150 "Failed to bring PHY %c to idle.\n", 151 phy_name(phy)); 152 return; 153 } 154 155 intel_clear_response_ready_flag(encoder, lane); 156 } 157 158 static int intel_cx0_wait_for_ack(struct intel_encoder *encoder, 159 int command, int lane, u32 *val) 160 { 161 struct intel_display *display = to_intel_display(encoder); 162 enum port port = encoder->port; 163 enum phy phy = intel_encoder_to_phy(encoder); 164 165 if (intel_de_wait_custom(display, 166 XELPDP_PORT_P2M_MSGBUS_STATUS(display, port, lane), 167 XELPDP_PORT_P2M_RESPONSE_READY, 168 XELPDP_PORT_P2M_RESPONSE_READY, 169 XELPDP_MSGBUS_TIMEOUT_FAST_US, 170 XELPDP_MSGBUS_TIMEOUT_SLOW, val)) { 171 drm_dbg_kms(display->drm, 172 "PHY %c Timeout waiting for message ACK. Status: 0x%x\n", 173 phy_name(phy), *val); 174 175 if (!(intel_de_read(display, XELPDP_PORT_MSGBUS_TIMER(display, port, lane)) & 176 XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT)) 177 drm_dbg_kms(display->drm, 178 "PHY %c Hardware did not detect a timeout\n", 179 phy_name(phy)); 180 181 intel_cx0_bus_reset(encoder, lane); 182 return -ETIMEDOUT; 183 } 184 185 if (*val & XELPDP_PORT_P2M_ERROR_SET) { 186 drm_dbg_kms(display->drm, 187 "PHY %c Error occurred during %s command. Status: 0x%x\n", 188 phy_name(phy), 189 command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); 190 intel_cx0_bus_reset(encoder, lane); 191 return -EINVAL; 192 } 193 194 if (REG_FIELD_GET(XELPDP_PORT_P2M_COMMAND_TYPE_MASK, *val) != command) { 195 drm_dbg_kms(display->drm, 196 "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n", 197 phy_name(phy), 198 command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); 199 intel_cx0_bus_reset(encoder, lane); 200 return -EINVAL; 201 } 202 203 return 0; 204 } 205 206 static int __intel_cx0_read_once(struct intel_encoder *encoder, 207 int lane, u16 addr) 208 { 209 struct intel_display *display = to_intel_display(encoder); 210 enum port port = encoder->port; 211 enum phy phy = intel_encoder_to_phy(encoder); 212 int ack; 213 u32 val; 214 215 if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 216 XELPDP_PORT_M2P_TRANSACTION_PENDING, 217 XELPDP_MSGBUS_TIMEOUT_SLOW)) { 218 drm_dbg_kms(display->drm, 219 "PHY %c Timeout waiting for previous transaction to complete. Reset the bus and retry.\n", phy_name(phy)); 220 intel_cx0_bus_reset(encoder, lane); 221 return -ETIMEDOUT; 222 } 223 224 intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 225 XELPDP_PORT_M2P_TRANSACTION_PENDING | 226 XELPDP_PORT_M2P_COMMAND_READ | 227 XELPDP_PORT_M2P_ADDRESS(addr)); 228 229 ack = intel_cx0_wait_for_ack(encoder, XELPDP_PORT_P2M_COMMAND_READ_ACK, lane, &val); 230 if (ack < 0) 231 return ack; 232 233 intel_clear_response_ready_flag(encoder, lane); 234 235 /* 236 * FIXME: Workaround to let HW to settle 237 * down and let the message bus to end up 238 * in a known state 239 */ 240 if (DISPLAY_VER(display) < 30) 241 intel_cx0_bus_reset(encoder, lane); 242 243 return REG_FIELD_GET(XELPDP_PORT_P2M_DATA_MASK, val); 244 } 245 246 static u8 __intel_cx0_read(struct intel_encoder *encoder, 247 int lane, u16 addr) 248 { 249 struct intel_display *display = to_intel_display(encoder); 250 enum phy phy = intel_encoder_to_phy(encoder); 251 int i, status; 252 253 assert_dc_off(display); 254 255 /* 3 tries is assumed to be enough to read successfully */ 256 for (i = 0; i < 3; i++) { 257 status = __intel_cx0_read_once(encoder, lane, addr); 258 259 if (status >= 0) 260 return status; 261 } 262 263 drm_err_once(display->drm, 264 "PHY %c Read %04x failed after %d retries.\n", 265 phy_name(phy), addr, i); 266 267 return 0; 268 } 269 270 static u8 intel_cx0_read(struct intel_encoder *encoder, 271 u8 lane_mask, u16 addr) 272 { 273 int lane = lane_mask_to_lane(lane_mask); 274 275 return __intel_cx0_read(encoder, lane, addr); 276 } 277 278 static int __intel_cx0_write_once(struct intel_encoder *encoder, 279 int lane, u16 addr, u8 data, bool committed) 280 { 281 struct intel_display *display = to_intel_display(encoder); 282 enum port port = encoder->port; 283 enum phy phy = intel_encoder_to_phy(encoder); 284 int ack; 285 u32 val; 286 287 if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 288 XELPDP_PORT_M2P_TRANSACTION_PENDING, 289 XELPDP_MSGBUS_TIMEOUT_SLOW)) { 290 drm_dbg_kms(display->drm, 291 "PHY %c Timeout waiting for previous transaction to complete. Resetting the bus.\n", phy_name(phy)); 292 intel_cx0_bus_reset(encoder, lane); 293 return -ETIMEDOUT; 294 } 295 296 intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 297 XELPDP_PORT_M2P_TRANSACTION_PENDING | 298 (committed ? XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED : 299 XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED) | 300 XELPDP_PORT_M2P_DATA(data) | 301 XELPDP_PORT_M2P_ADDRESS(addr)); 302 303 if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 304 XELPDP_PORT_M2P_TRANSACTION_PENDING, 305 XELPDP_MSGBUS_TIMEOUT_SLOW)) { 306 drm_dbg_kms(display->drm, 307 "PHY %c Timeout waiting for write to complete. Resetting the bus.\n", phy_name(phy)); 308 intel_cx0_bus_reset(encoder, lane); 309 return -ETIMEDOUT; 310 } 311 312 if (committed) { 313 ack = intel_cx0_wait_for_ack(encoder, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val); 314 if (ack < 0) 315 return ack; 316 } else if ((intel_de_read(display, XELPDP_PORT_P2M_MSGBUS_STATUS(display, port, lane)) & 317 XELPDP_PORT_P2M_ERROR_SET)) { 318 drm_dbg_kms(display->drm, 319 "PHY %c Error occurred during write command.\n", phy_name(phy)); 320 intel_cx0_bus_reset(encoder, lane); 321 return -EINVAL; 322 } 323 324 intel_clear_response_ready_flag(encoder, lane); 325 326 /* 327 * FIXME: Workaround to let HW to settle 328 * down and let the message bus to end up 329 * in a known state 330 */ 331 if (DISPLAY_VER(display) < 30) 332 intel_cx0_bus_reset(encoder, lane); 333 334 return 0; 335 } 336 337 static void __intel_cx0_write(struct intel_encoder *encoder, 338 int lane, u16 addr, u8 data, bool committed) 339 { 340 struct intel_display *display = to_intel_display(encoder); 341 enum phy phy = intel_encoder_to_phy(encoder); 342 int i, status; 343 344 assert_dc_off(display); 345 346 /* 3 tries is assumed to be enough to write successfully */ 347 for (i = 0; i < 3; i++) { 348 status = __intel_cx0_write_once(encoder, lane, addr, data, committed); 349 350 if (status == 0) 351 return; 352 } 353 354 drm_err_once(display->drm, 355 "PHY %c Write %04x failed after %d retries.\n", phy_name(phy), addr, i); 356 } 357 358 static void intel_cx0_write(struct intel_encoder *encoder, 359 u8 lane_mask, u16 addr, u8 data, bool committed) 360 { 361 int lane; 362 363 for_each_cx0_lane_in_mask(lane_mask, lane) 364 __intel_cx0_write(encoder, lane, addr, data, committed); 365 } 366 367 static void intel_c20_sram_write(struct intel_encoder *encoder, 368 int lane, u16 addr, u16 data) 369 { 370 struct intel_display *display = to_intel_display(encoder); 371 372 assert_dc_off(display); 373 374 intel_cx0_write(encoder, lane, PHY_C20_WR_ADDRESS_H, addr >> 8, 0); 375 intel_cx0_write(encoder, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0); 376 377 intel_cx0_write(encoder, lane, PHY_C20_WR_DATA_H, data >> 8, 0); 378 intel_cx0_write(encoder, lane, PHY_C20_WR_DATA_L, data & 0xff, 1); 379 } 380 381 static u16 intel_c20_sram_read(struct intel_encoder *encoder, 382 int lane, u16 addr) 383 { 384 struct intel_display *display = to_intel_display(encoder); 385 u16 val; 386 387 assert_dc_off(display); 388 389 intel_cx0_write(encoder, lane, PHY_C20_RD_ADDRESS_H, addr >> 8, 0); 390 intel_cx0_write(encoder, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 1); 391 392 val = intel_cx0_read(encoder, lane, PHY_C20_RD_DATA_H); 393 val <<= 8; 394 val |= intel_cx0_read(encoder, lane, PHY_C20_RD_DATA_L); 395 396 return val; 397 } 398 399 static void __intel_cx0_rmw(struct intel_encoder *encoder, 400 int lane, u16 addr, u8 clear, u8 set, bool committed) 401 { 402 u8 old, val; 403 404 old = __intel_cx0_read(encoder, lane, addr); 405 val = (old & ~clear) | set; 406 407 if (val != old) 408 __intel_cx0_write(encoder, lane, addr, val, committed); 409 } 410 411 static void intel_cx0_rmw(struct intel_encoder *encoder, 412 u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed) 413 { 414 u8 lane; 415 416 for_each_cx0_lane_in_mask(lane_mask, lane) 417 __intel_cx0_rmw(encoder, lane, addr, clear, set, committed); 418 } 419 420 static u8 intel_c10_get_tx_vboost_lvl(const struct intel_crtc_state *crtc_state) 421 { 422 if (intel_crtc_has_dp_encoder(crtc_state)) { 423 if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) && 424 (crtc_state->port_clock == 540000 || 425 crtc_state->port_clock == 810000)) 426 return 5; 427 else 428 return 4; 429 } else { 430 return 5; 431 } 432 } 433 434 static u8 intel_c10_get_tx_term_ctl(const struct intel_crtc_state *crtc_state) 435 { 436 if (intel_crtc_has_dp_encoder(crtc_state)) { 437 if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) && 438 (crtc_state->port_clock == 540000 || 439 crtc_state->port_clock == 810000)) 440 return 5; 441 else 442 return 2; 443 } else { 444 return 6; 445 } 446 } 447 448 void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, 449 const struct intel_crtc_state *crtc_state) 450 { 451 struct intel_display *display = to_intel_display(encoder); 452 const struct intel_ddi_buf_trans *trans; 453 u8 owned_lane_mask; 454 intel_wakeref_t wakeref; 455 int n_entries, ln; 456 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 457 458 if (intel_tc_port_in_tbt_alt_mode(dig_port)) 459 return; 460 461 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); 462 463 wakeref = intel_cx0_phy_transaction_begin(encoder); 464 465 trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); 466 if (drm_WARN_ON_ONCE(display->drm, !trans)) { 467 intel_cx0_phy_transaction_end(encoder, wakeref); 468 return; 469 } 470 471 if (intel_encoder_is_c10phy(encoder)) { 472 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 473 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); 474 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CMN(3), 475 C10_CMN3_TXVBOOST_MASK, 476 C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)), 477 MB_WRITE_UNCOMMITTED); 478 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_TX(1), 479 C10_TX1_TERMCTL_MASK, 480 C10_TX1_TERMCTL(intel_c10_get_tx_term_ctl(crtc_state)), 481 MB_WRITE_COMMITTED); 482 } 483 484 for (ln = 0; ln < crtc_state->lane_count; ln++) { 485 int level = intel_ddi_level(encoder, crtc_state, ln); 486 int lane = ln / 2; 487 int tx = ln % 2; 488 u8 lane_mask = lane == 0 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1; 489 490 if (!(lane_mask & owned_lane_mask)) 491 continue; 492 493 intel_cx0_rmw(encoder, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 0), 494 C10_PHY_OVRD_LEVEL_MASK, 495 C10_PHY_OVRD_LEVEL(trans->entries[level].snps.pre_cursor), 496 MB_WRITE_COMMITTED); 497 intel_cx0_rmw(encoder, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 1), 498 C10_PHY_OVRD_LEVEL_MASK, 499 C10_PHY_OVRD_LEVEL(trans->entries[level].snps.vswing), 500 MB_WRITE_COMMITTED); 501 intel_cx0_rmw(encoder, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 2), 502 C10_PHY_OVRD_LEVEL_MASK, 503 C10_PHY_OVRD_LEVEL(trans->entries[level].snps.post_cursor), 504 MB_WRITE_COMMITTED); 505 } 506 507 /* Write Override enables in 0xD71 */ 508 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_OVRD, 509 0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2, 510 MB_WRITE_COMMITTED); 511 512 if (intel_encoder_is_c10phy(encoder)) 513 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 514 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED); 515 516 intel_cx0_phy_transaction_end(encoder, wakeref); 517 } 518 519 /* 520 * Basic DP link rates with 38.4 MHz reference clock. 521 * Note: The tables below are with SSC. In non-ssc 522 * registers 0xC04 to 0xC08(pll[4] to pll[8]) will be 523 * programmed 0. 524 */ 525 526 static const struct intel_c10pll_state mtl_c10_dp_rbr = { 527 .clock = 162000, 528 .tx = 0x10, 529 .cmn = 0x21, 530 .pll[0] = 0xB4, 531 .pll[1] = 0, 532 .pll[2] = 0x30, 533 .pll[3] = 0x1, 534 .pll[4] = 0x26, 535 .pll[5] = 0x0C, 536 .pll[6] = 0x98, 537 .pll[7] = 0x46, 538 .pll[8] = 0x1, 539 .pll[9] = 0x1, 540 .pll[10] = 0, 541 .pll[11] = 0, 542 .pll[12] = 0xC0, 543 .pll[13] = 0, 544 .pll[14] = 0, 545 .pll[15] = 0x2, 546 .pll[16] = 0x84, 547 .pll[17] = 0x4F, 548 .pll[18] = 0xE5, 549 .pll[19] = 0x23, 550 }; 551 552 static const struct intel_c10pll_state mtl_c10_edp_r216 = { 553 .clock = 216000, 554 .tx = 0x10, 555 .cmn = 0x21, 556 .pll[0] = 0x4, 557 .pll[1] = 0, 558 .pll[2] = 0xA2, 559 .pll[3] = 0x1, 560 .pll[4] = 0x33, 561 .pll[5] = 0x10, 562 .pll[6] = 0x75, 563 .pll[7] = 0xB3, 564 .pll[8] = 0x1, 565 .pll[9] = 0x1, 566 .pll[10] = 0, 567 .pll[11] = 0, 568 .pll[12] = 0, 569 .pll[13] = 0, 570 .pll[14] = 0, 571 .pll[15] = 0x2, 572 .pll[16] = 0x85, 573 .pll[17] = 0x0F, 574 .pll[18] = 0xE6, 575 .pll[19] = 0x23, 576 }; 577 578 static const struct intel_c10pll_state mtl_c10_edp_r243 = { 579 .clock = 243000, 580 .tx = 0x10, 581 .cmn = 0x21, 582 .pll[0] = 0x34, 583 .pll[1] = 0, 584 .pll[2] = 0xDA, 585 .pll[3] = 0x1, 586 .pll[4] = 0x39, 587 .pll[5] = 0x12, 588 .pll[6] = 0xE3, 589 .pll[7] = 0xE9, 590 .pll[8] = 0x1, 591 .pll[9] = 0x1, 592 .pll[10] = 0, 593 .pll[11] = 0, 594 .pll[12] = 0x20, 595 .pll[13] = 0, 596 .pll[14] = 0, 597 .pll[15] = 0x2, 598 .pll[16] = 0x85, 599 .pll[17] = 0x8F, 600 .pll[18] = 0xE6, 601 .pll[19] = 0x23, 602 }; 603 604 static const struct intel_c10pll_state mtl_c10_dp_hbr1 = { 605 .clock = 270000, 606 .tx = 0x10, 607 .cmn = 0x21, 608 .pll[0] = 0xF4, 609 .pll[1] = 0, 610 .pll[2] = 0xF8, 611 .pll[3] = 0x0, 612 .pll[4] = 0x20, 613 .pll[5] = 0x0A, 614 .pll[6] = 0x29, 615 .pll[7] = 0x10, 616 .pll[8] = 0x1, /* Verify */ 617 .pll[9] = 0x1, 618 .pll[10] = 0, 619 .pll[11] = 0, 620 .pll[12] = 0xA0, 621 .pll[13] = 0, 622 .pll[14] = 0, 623 .pll[15] = 0x1, 624 .pll[16] = 0x84, 625 .pll[17] = 0x4F, 626 .pll[18] = 0xE5, 627 .pll[19] = 0x23, 628 }; 629 630 static const struct intel_c10pll_state mtl_c10_edp_r324 = { 631 .clock = 324000, 632 .tx = 0x10, 633 .cmn = 0x21, 634 .pll[0] = 0xB4, 635 .pll[1] = 0, 636 .pll[2] = 0x30, 637 .pll[3] = 0x1, 638 .pll[4] = 0x26, 639 .pll[5] = 0x0C, 640 .pll[6] = 0x98, 641 .pll[7] = 0x46, 642 .pll[8] = 0x1, 643 .pll[9] = 0x1, 644 .pll[10] = 0, 645 .pll[11] = 0, 646 .pll[12] = 0xC0, 647 .pll[13] = 0, 648 .pll[14] = 0, 649 .pll[15] = 0x1, 650 .pll[16] = 0x85, 651 .pll[17] = 0x4F, 652 .pll[18] = 0xE6, 653 .pll[19] = 0x23, 654 }; 655 656 static const struct intel_c10pll_state mtl_c10_edp_r432 = { 657 .clock = 432000, 658 .tx = 0x10, 659 .cmn = 0x21, 660 .pll[0] = 0x4, 661 .pll[1] = 0, 662 .pll[2] = 0xA2, 663 .pll[3] = 0x1, 664 .pll[4] = 0x33, 665 .pll[5] = 0x10, 666 .pll[6] = 0x75, 667 .pll[7] = 0xB3, 668 .pll[8] = 0x1, 669 .pll[9] = 0x1, 670 .pll[10] = 0, 671 .pll[11] = 0, 672 .pll[12] = 0, 673 .pll[13] = 0, 674 .pll[14] = 0, 675 .pll[15] = 0x1, 676 .pll[16] = 0x85, 677 .pll[17] = 0x0F, 678 .pll[18] = 0xE6, 679 .pll[19] = 0x23, 680 }; 681 682 static const struct intel_c10pll_state mtl_c10_dp_hbr2 = { 683 .clock = 540000, 684 .tx = 0x10, 685 .cmn = 0x21, 686 .pll[0] = 0xF4, 687 .pll[1] = 0, 688 .pll[2] = 0xF8, 689 .pll[3] = 0, 690 .pll[4] = 0x20, 691 .pll[5] = 0x0A, 692 .pll[6] = 0x29, 693 .pll[7] = 0x10, 694 .pll[8] = 0x1, 695 .pll[9] = 0x1, 696 .pll[10] = 0, 697 .pll[11] = 0, 698 .pll[12] = 0xA0, 699 .pll[13] = 0, 700 .pll[14] = 0, 701 .pll[15] = 0, 702 .pll[16] = 0x84, 703 .pll[17] = 0x4F, 704 .pll[18] = 0xE5, 705 .pll[19] = 0x23, 706 }; 707 708 static const struct intel_c10pll_state mtl_c10_edp_r675 = { 709 .clock = 675000, 710 .tx = 0x10, 711 .cmn = 0x21, 712 .pll[0] = 0xB4, 713 .pll[1] = 0, 714 .pll[2] = 0x3E, 715 .pll[3] = 0x1, 716 .pll[4] = 0xA8, 717 .pll[5] = 0x0C, 718 .pll[6] = 0x33, 719 .pll[7] = 0x54, 720 .pll[8] = 0x1, 721 .pll[9] = 0x1, 722 .pll[10] = 0, 723 .pll[11] = 0, 724 .pll[12] = 0xC8, 725 .pll[13] = 0, 726 .pll[14] = 0, 727 .pll[15] = 0, 728 .pll[16] = 0x85, 729 .pll[17] = 0x8F, 730 .pll[18] = 0xE6, 731 .pll[19] = 0x23, 732 }; 733 734 static const struct intel_c10pll_state mtl_c10_dp_hbr3 = { 735 .clock = 810000, 736 .tx = 0x10, 737 .cmn = 0x21, 738 .pll[0] = 0x34, 739 .pll[1] = 0, 740 .pll[2] = 0x84, 741 .pll[3] = 0x1, 742 .pll[4] = 0x30, 743 .pll[5] = 0x0F, 744 .pll[6] = 0x3D, 745 .pll[7] = 0x98, 746 .pll[8] = 0x1, 747 .pll[9] = 0x1, 748 .pll[10] = 0, 749 .pll[11] = 0, 750 .pll[12] = 0xF0, 751 .pll[13] = 0, 752 .pll[14] = 0, 753 .pll[15] = 0, 754 .pll[16] = 0x84, 755 .pll[17] = 0x0F, 756 .pll[18] = 0xE5, 757 .pll[19] = 0x23, 758 }; 759 760 static const struct intel_c10pll_state * const mtl_c10_dp_tables[] = { 761 &mtl_c10_dp_rbr, 762 &mtl_c10_dp_hbr1, 763 &mtl_c10_dp_hbr2, 764 &mtl_c10_dp_hbr3, 765 NULL, 766 }; 767 768 static const struct intel_c10pll_state * const mtl_c10_edp_tables[] = { 769 &mtl_c10_dp_rbr, 770 &mtl_c10_edp_r216, 771 &mtl_c10_edp_r243, 772 &mtl_c10_dp_hbr1, 773 &mtl_c10_edp_r324, 774 &mtl_c10_edp_r432, 775 &mtl_c10_dp_hbr2, 776 &mtl_c10_edp_r675, 777 &mtl_c10_dp_hbr3, 778 NULL, 779 }; 780 781 /* C20 basic DP 1.4 tables */ 782 static const struct intel_c20pll_state mtl_c20_dp_rbr = { 783 .clock = 162000, 784 .tx = { 0xbe88, /* tx cfg0 */ 785 0x5800, /* tx cfg1 */ 786 0x0000, /* tx cfg2 */ 787 }, 788 .cmn = {0x0500, /* cmn cfg0*/ 789 0x0005, /* cmn cfg1 */ 790 0x0000, /* cmn cfg2 */ 791 0x0000, /* cmn cfg3 */ 792 }, 793 .mpllb = { 0x50a8, /* mpllb cfg0 */ 794 0x2120, /* mpllb cfg1 */ 795 0xcd9a, /* mpllb cfg2 */ 796 0xbfc1, /* mpllb cfg3 */ 797 0x5ab8, /* mpllb cfg4 */ 798 0x4c34, /* mpllb cfg5 */ 799 0x2000, /* mpllb cfg6 */ 800 0x0001, /* mpllb cfg7 */ 801 0x6000, /* mpllb cfg8 */ 802 0x0000, /* mpllb cfg9 */ 803 0x0000, /* mpllb cfg10 */ 804 }, 805 }; 806 807 static const struct intel_c20pll_state mtl_c20_dp_hbr1 = { 808 .clock = 270000, 809 .tx = { 0xbe88, /* tx cfg0 */ 810 0x4800, /* tx cfg1 */ 811 0x0000, /* tx cfg2 */ 812 }, 813 .cmn = {0x0500, /* cmn cfg0*/ 814 0x0005, /* cmn cfg1 */ 815 0x0000, /* cmn cfg2 */ 816 0x0000, /* cmn cfg3 */ 817 }, 818 .mpllb = { 0x308c, /* mpllb cfg0 */ 819 0x2110, /* mpllb cfg1 */ 820 0xcc9c, /* mpllb cfg2 */ 821 0xbfc1, /* mpllb cfg3 */ 822 0x4b9a, /* mpllb cfg4 */ 823 0x3f81, /* mpllb cfg5 */ 824 0x2000, /* mpllb cfg6 */ 825 0x0001, /* mpllb cfg7 */ 826 0x5000, /* mpllb cfg8 */ 827 0x0000, /* mpllb cfg9 */ 828 0x0000, /* mpllb cfg10 */ 829 }, 830 }; 831 832 static const struct intel_c20pll_state mtl_c20_dp_hbr2 = { 833 .clock = 540000, 834 .tx = { 0xbe88, /* tx cfg0 */ 835 0x4800, /* tx cfg1 */ 836 0x0000, /* tx cfg2 */ 837 }, 838 .cmn = {0x0500, /* cmn cfg0*/ 839 0x0005, /* cmn cfg1 */ 840 0x0000, /* cmn cfg2 */ 841 0x0000, /* cmn cfg3 */ 842 }, 843 .mpllb = { 0x108c, /* mpllb cfg0 */ 844 0x2108, /* mpllb cfg1 */ 845 0xcc9c, /* mpllb cfg2 */ 846 0xbfc1, /* mpllb cfg3 */ 847 0x4b9a, /* mpllb cfg4 */ 848 0x3f81, /* mpllb cfg5 */ 849 0x2000, /* mpllb cfg6 */ 850 0x0001, /* mpllb cfg7 */ 851 0x5000, /* mpllb cfg8 */ 852 0x0000, /* mpllb cfg9 */ 853 0x0000, /* mpllb cfg10 */ 854 }, 855 }; 856 857 static const struct intel_c20pll_state mtl_c20_dp_hbr3 = { 858 .clock = 810000, 859 .tx = { 0xbe88, /* tx cfg0 */ 860 0x4800, /* tx cfg1 */ 861 0x0000, /* tx cfg2 */ 862 }, 863 .cmn = {0x0500, /* cmn cfg0*/ 864 0x0005, /* cmn cfg1 */ 865 0x0000, /* cmn cfg2 */ 866 0x0000, /* cmn cfg3 */ 867 }, 868 .mpllb = { 0x10d2, /* mpllb cfg0 */ 869 0x2108, /* mpllb cfg1 */ 870 0x8d98, /* mpllb cfg2 */ 871 0xbfc1, /* mpllb cfg3 */ 872 0x7166, /* mpllb cfg4 */ 873 0x5f42, /* mpllb cfg5 */ 874 0x2000, /* mpllb cfg6 */ 875 0x0001, /* mpllb cfg7 */ 876 0x7800, /* mpllb cfg8 */ 877 0x0000, /* mpllb cfg9 */ 878 0x0000, /* mpllb cfg10 */ 879 }, 880 }; 881 882 /* C20 basic DP 2.0 tables */ 883 static const struct intel_c20pll_state mtl_c20_dp_uhbr10 = { 884 .clock = 1000000, /* 10 Gbps */ 885 .tx = { 0xbe21, /* tx cfg0 */ 886 0xe800, /* tx cfg1 */ 887 0x0000, /* tx cfg2 */ 888 }, 889 .cmn = {0x0700, /* cmn cfg0*/ 890 0x0005, /* cmn cfg1 */ 891 0x0000, /* cmn cfg2 */ 892 0x0000, /* cmn cfg3 */ 893 }, 894 .mplla = { 0x3104, /* mplla cfg0 */ 895 0xd105, /* mplla cfg1 */ 896 0xc025, /* mplla cfg2 */ 897 0xc025, /* mplla cfg3 */ 898 0x8c00, /* mplla cfg4 */ 899 0x759a, /* mplla cfg5 */ 900 0x4000, /* mplla cfg6 */ 901 0x0003, /* mplla cfg7 */ 902 0x3555, /* mplla cfg8 */ 903 0x0001, /* mplla cfg9 */ 904 }, 905 }; 906 907 static const struct intel_c20pll_state mtl_c20_dp_uhbr13_5 = { 908 .clock = 1350000, /* 13.5 Gbps */ 909 .tx = { 0xbea0, /* tx cfg0 */ 910 0x4800, /* tx cfg1 */ 911 0x0000, /* tx cfg2 */ 912 }, 913 .cmn = {0x0500, /* cmn cfg0*/ 914 0x0005, /* cmn cfg1 */ 915 0x0000, /* cmn cfg2 */ 916 0x0000, /* cmn cfg3 */ 917 }, 918 .mpllb = { 0x015f, /* mpllb cfg0 */ 919 0x2205, /* mpllb cfg1 */ 920 0x1b17, /* mpllb cfg2 */ 921 0xffc1, /* mpllb cfg3 */ 922 0xe100, /* mpllb cfg4 */ 923 0xbd00, /* mpllb cfg5 */ 924 0x2000, /* mpllb cfg6 */ 925 0x0001, /* mpllb cfg7 */ 926 0x4800, /* mpllb cfg8 */ 927 0x0000, /* mpllb cfg9 */ 928 0x0000, /* mpllb cfg10 */ 929 }, 930 }; 931 932 static const struct intel_c20pll_state mtl_c20_dp_uhbr20 = { 933 .clock = 2000000, /* 20 Gbps */ 934 .tx = { 0xbe20, /* tx cfg0 */ 935 0x4800, /* tx cfg1 */ 936 0x0000, /* tx cfg2 */ 937 }, 938 .cmn = {0x0500, /* cmn cfg0*/ 939 0x0005, /* cmn cfg1 */ 940 0x0000, /* cmn cfg2 */ 941 0x0000, /* cmn cfg3 */ 942 }, 943 .mplla = { 0x3104, /* mplla cfg0 */ 944 0xd105, /* mplla cfg1 */ 945 0x9217, /* mplla cfg2 */ 946 0x9217, /* mplla cfg3 */ 947 0x8c00, /* mplla cfg4 */ 948 0x759a, /* mplla cfg5 */ 949 0x4000, /* mplla cfg6 */ 950 0x0003, /* mplla cfg7 */ 951 0x3555, /* mplla cfg8 */ 952 0x0001, /* mplla cfg9 */ 953 }, 954 }; 955 956 static const struct intel_c20pll_state * const mtl_c20_dp_tables[] = { 957 &mtl_c20_dp_rbr, 958 &mtl_c20_dp_hbr1, 959 &mtl_c20_dp_hbr2, 960 &mtl_c20_dp_hbr3, 961 &mtl_c20_dp_uhbr10, 962 &mtl_c20_dp_uhbr13_5, 963 &mtl_c20_dp_uhbr20, 964 NULL, 965 }; 966 967 /* 968 * eDP link rates with 38.4 MHz reference clock. 969 */ 970 971 static const struct intel_c20pll_state xe2hpd_c20_edp_r216 = { 972 .clock = 216000, 973 .tx = { 0xbe88, 974 0x4800, 975 0x0000, 976 }, 977 .cmn = { 0x0500, 978 0x0005, 979 0x0000, 980 0x0000, 981 }, 982 .mpllb = { 0x50e1, 983 0x2120, 984 0x8e18, 985 0xbfc1, 986 0x9000, 987 0x78f6, 988 0x0000, 989 0x0000, 990 0x0000, 991 0x0000, 992 0x0000, 993 }, 994 }; 995 996 static const struct intel_c20pll_state xe2hpd_c20_edp_r243 = { 997 .clock = 243000, 998 .tx = { 0xbe88, 999 0x4800, 1000 0x0000, 1001 }, 1002 .cmn = { 0x0500, 1003 0x0005, 1004 0x0000, 1005 0x0000, 1006 }, 1007 .mpllb = { 0x50fd, 1008 0x2120, 1009 0x8f18, 1010 0xbfc1, 1011 0xa200, 1012 0x8814, 1013 0x2000, 1014 0x0001, 1015 0x1000, 1016 0x0000, 1017 0x0000, 1018 }, 1019 }; 1020 1021 static const struct intel_c20pll_state xe2hpd_c20_edp_r324 = { 1022 .clock = 324000, 1023 .tx = { 0xbe88, 1024 0x4800, 1025 0x0000, 1026 }, 1027 .cmn = { 0x0500, 1028 0x0005, 1029 0x0000, 1030 0x0000, 1031 }, 1032 .mpllb = { 0x30a8, 1033 0x2110, 1034 0xcd9a, 1035 0xbfc1, 1036 0x6c00, 1037 0x5ab8, 1038 0x2000, 1039 0x0001, 1040 0x6000, 1041 0x0000, 1042 0x0000, 1043 }, 1044 }; 1045 1046 static const struct intel_c20pll_state xe2hpd_c20_edp_r432 = { 1047 .clock = 432000, 1048 .tx = { 0xbe88, 1049 0x4800, 1050 0x0000, 1051 }, 1052 .cmn = { 0x0500, 1053 0x0005, 1054 0x0000, 1055 0x0000, 1056 }, 1057 .mpllb = { 0x30e1, 1058 0x2110, 1059 0x8e18, 1060 0xbfc1, 1061 0x9000, 1062 0x78f6, 1063 0x0000, 1064 0x0000, 1065 0x0000, 1066 0x0000, 1067 0x0000, 1068 }, 1069 }; 1070 1071 static const struct intel_c20pll_state xe2hpd_c20_edp_r675 = { 1072 .clock = 675000, 1073 .tx = { 0xbe88, 1074 0x4800, 1075 0x0000, 1076 }, 1077 .cmn = { 0x0500, 1078 0x0005, 1079 0x0000, 1080 0x0000, 1081 }, 1082 .mpllb = { 0x10af, 1083 0x2108, 1084 0xce1a, 1085 0xbfc1, 1086 0x7080, 1087 0x5e80, 1088 0x2000, 1089 0x0001, 1090 0x6400, 1091 0x0000, 1092 0x0000, 1093 }, 1094 }; 1095 1096 static const struct intel_c20pll_state * const xe2hpd_c20_edp_tables[] = { 1097 &mtl_c20_dp_rbr, 1098 &xe2hpd_c20_edp_r216, 1099 &xe2hpd_c20_edp_r243, 1100 &mtl_c20_dp_hbr1, 1101 &xe2hpd_c20_edp_r324, 1102 &xe2hpd_c20_edp_r432, 1103 &mtl_c20_dp_hbr2, 1104 &xe2hpd_c20_edp_r675, 1105 &mtl_c20_dp_hbr3, 1106 NULL, 1107 }; 1108 1109 static const struct intel_c20pll_state xe2hpd_c20_dp_uhbr13_5 = { 1110 .clock = 1350000, /* 13.5 Gbps */ 1111 .tx = { 0xbea0, /* tx cfg0 */ 1112 0x4800, /* tx cfg1 */ 1113 0x0000, /* tx cfg2 */ 1114 }, 1115 .cmn = {0x0500, /* cmn cfg0*/ 1116 0x0005, /* cmn cfg1 */ 1117 0x0000, /* cmn cfg2 */ 1118 0x0000, /* cmn cfg3 */ 1119 }, 1120 .mpllb = { 0x015f, /* mpllb cfg0 */ 1121 0x2205, /* mpllb cfg1 */ 1122 0x1b17, /* mpllb cfg2 */ 1123 0xffc1, /* mpllb cfg3 */ 1124 0xbd00, /* mpllb cfg4 */ 1125 0x9ec3, /* mpllb cfg5 */ 1126 0x2000, /* mpllb cfg6 */ 1127 0x0001, /* mpllb cfg7 */ 1128 0x4800, /* mpllb cfg8 */ 1129 0x0000, /* mpllb cfg9 */ 1130 0x0000, /* mpllb cfg10 */ 1131 }, 1132 }; 1133 1134 static const struct intel_c20pll_state * const xe2hpd_c20_dp_tables[] = { 1135 &mtl_c20_dp_rbr, 1136 &mtl_c20_dp_hbr1, 1137 &mtl_c20_dp_hbr2, 1138 &mtl_c20_dp_hbr3, 1139 &mtl_c20_dp_uhbr10, 1140 &xe2hpd_c20_dp_uhbr13_5, 1141 NULL, 1142 }; 1143 1144 static const struct intel_c20pll_state * const xe3lpd_c20_dp_edp_tables[] = { 1145 &mtl_c20_dp_rbr, 1146 &xe2hpd_c20_edp_r216, 1147 &xe2hpd_c20_edp_r243, 1148 &mtl_c20_dp_hbr1, 1149 &xe2hpd_c20_edp_r324, 1150 &xe2hpd_c20_edp_r432, 1151 &mtl_c20_dp_hbr2, 1152 &xe2hpd_c20_edp_r675, 1153 &mtl_c20_dp_hbr3, 1154 &mtl_c20_dp_uhbr10, 1155 &xe2hpd_c20_dp_uhbr13_5, 1156 &mtl_c20_dp_uhbr20, 1157 NULL, 1158 }; 1159 1160 /* 1161 * HDMI link rates with 38.4 MHz reference clock. 1162 */ 1163 1164 static const struct intel_c10pll_state mtl_c10_hdmi_25_2 = { 1165 .clock = 25200, 1166 .tx = 0x10, 1167 .cmn = 0x1, 1168 .pll[0] = 0x4, 1169 .pll[1] = 0, 1170 .pll[2] = 0xB2, 1171 .pll[3] = 0, 1172 .pll[4] = 0, 1173 .pll[5] = 0, 1174 .pll[6] = 0, 1175 .pll[7] = 0, 1176 .pll[8] = 0x20, 1177 .pll[9] = 0x1, 1178 .pll[10] = 0, 1179 .pll[11] = 0, 1180 .pll[12] = 0, 1181 .pll[13] = 0, 1182 .pll[14] = 0, 1183 .pll[15] = 0xD, 1184 .pll[16] = 0x6, 1185 .pll[17] = 0x8F, 1186 .pll[18] = 0x84, 1187 .pll[19] = 0x23, 1188 }; 1189 1190 static const struct intel_c10pll_state mtl_c10_hdmi_27_0 = { 1191 .clock = 27000, 1192 .tx = 0x10, 1193 .cmn = 0x1, 1194 .pll[0] = 0x34, 1195 .pll[1] = 0, 1196 .pll[2] = 0xC0, 1197 .pll[3] = 0, 1198 .pll[4] = 0, 1199 .pll[5] = 0, 1200 .pll[6] = 0, 1201 .pll[7] = 0, 1202 .pll[8] = 0x20, 1203 .pll[9] = 0x1, 1204 .pll[10] = 0, 1205 .pll[11] = 0, 1206 .pll[12] = 0x80, 1207 .pll[13] = 0, 1208 .pll[14] = 0, 1209 .pll[15] = 0xD, 1210 .pll[16] = 0x6, 1211 .pll[17] = 0xCF, 1212 .pll[18] = 0x84, 1213 .pll[19] = 0x23, 1214 }; 1215 1216 static const struct intel_c10pll_state mtl_c10_hdmi_74_25 = { 1217 .clock = 74250, 1218 .tx = 0x10, 1219 .cmn = 0x1, 1220 .pll[0] = 0xF4, 1221 .pll[1] = 0, 1222 .pll[2] = 0x7A, 1223 .pll[3] = 0, 1224 .pll[4] = 0, 1225 .pll[5] = 0, 1226 .pll[6] = 0, 1227 .pll[7] = 0, 1228 .pll[8] = 0x20, 1229 .pll[9] = 0x1, 1230 .pll[10] = 0, 1231 .pll[11] = 0, 1232 .pll[12] = 0x58, 1233 .pll[13] = 0, 1234 .pll[14] = 0, 1235 .pll[15] = 0xB, 1236 .pll[16] = 0x6, 1237 .pll[17] = 0xF, 1238 .pll[18] = 0x85, 1239 .pll[19] = 0x23, 1240 }; 1241 1242 static const struct intel_c10pll_state mtl_c10_hdmi_148_5 = { 1243 .clock = 148500, 1244 .tx = 0x10, 1245 .cmn = 0x1, 1246 .pll[0] = 0xF4, 1247 .pll[1] = 0, 1248 .pll[2] = 0x7A, 1249 .pll[3] = 0, 1250 .pll[4] = 0, 1251 .pll[5] = 0, 1252 .pll[6] = 0, 1253 .pll[7] = 0, 1254 .pll[8] = 0x20, 1255 .pll[9] = 0x1, 1256 .pll[10] = 0, 1257 .pll[11] = 0, 1258 .pll[12] = 0x58, 1259 .pll[13] = 0, 1260 .pll[14] = 0, 1261 .pll[15] = 0xA, 1262 .pll[16] = 0x6, 1263 .pll[17] = 0xF, 1264 .pll[18] = 0x85, 1265 .pll[19] = 0x23, 1266 }; 1267 1268 static const struct intel_c10pll_state mtl_c10_hdmi_594 = { 1269 .clock = 594000, 1270 .tx = 0x10, 1271 .cmn = 0x1, 1272 .pll[0] = 0xF4, 1273 .pll[1] = 0, 1274 .pll[2] = 0x7A, 1275 .pll[3] = 0, 1276 .pll[4] = 0, 1277 .pll[5] = 0, 1278 .pll[6] = 0, 1279 .pll[7] = 0, 1280 .pll[8] = 0x20, 1281 .pll[9] = 0x1, 1282 .pll[10] = 0, 1283 .pll[11] = 0, 1284 .pll[12] = 0x58, 1285 .pll[13] = 0, 1286 .pll[14] = 0, 1287 .pll[15] = 0x8, 1288 .pll[16] = 0x6, 1289 .pll[17] = 0xF, 1290 .pll[18] = 0x85, 1291 .pll[19] = 0x23, 1292 }; 1293 1294 /* Precomputed C10 HDMI PLL tables */ 1295 static const struct intel_c10pll_state mtl_c10_hdmi_27027 = { 1296 .clock = 27027, 1297 .tx = 0x10, 1298 .cmn = 0x1, 1299 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xC0, .pll[3] = 0x00, .pll[4] = 0x00, 1300 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1301 .pll[10] = 0xFF, .pll[11] = 0xCC, .pll[12] = 0x9C, .pll[13] = 0xCB, .pll[14] = 0xCC, 1302 .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1303 }; 1304 1305 static const struct intel_c10pll_state mtl_c10_hdmi_28320 = { 1306 .clock = 28320, 1307 .tx = 0x10, 1308 .cmn = 0x1, 1309 .pll[0] = 0x04, .pll[1] = 0x00, .pll[2] = 0xCC, .pll[3] = 0x00, .pll[4] = 0x00, 1310 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1311 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00, 1312 .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1313 }; 1314 1315 static const struct intel_c10pll_state mtl_c10_hdmi_30240 = { 1316 .clock = 30240, 1317 .tx = 0x10, 1318 .cmn = 0x1, 1319 .pll[0] = 0x04, .pll[1] = 0x00, .pll[2] = 0xDC, .pll[3] = 0x00, .pll[4] = 0x00, 1320 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1321 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00, 1322 .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1323 }; 1324 1325 static const struct intel_c10pll_state mtl_c10_hdmi_31500 = { 1326 .clock = 31500, 1327 .tx = 0x10, 1328 .cmn = 0x1, 1329 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x62, .pll[3] = 0x00, .pll[4] = 0x00, 1330 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1331 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xA0, .pll[13] = 0x00, .pll[14] = 0x00, 1332 .pll[15] = 0x0C, .pll[16] = 0x09, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1333 }; 1334 1335 static const struct intel_c10pll_state mtl_c10_hdmi_36000 = { 1336 .clock = 36000, 1337 .tx = 0x10, 1338 .cmn = 0x1, 1339 .pll[0] = 0xC4, .pll[1] = 0x00, .pll[2] = 0x76, .pll[3] = 0x00, .pll[4] = 0x00, 1340 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1341 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00, 1342 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1343 }; 1344 1345 static const struct intel_c10pll_state mtl_c10_hdmi_40000 = { 1346 .clock = 40000, 1347 .tx = 0x10, 1348 .cmn = 0x1, 1349 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x86, .pll[3] = 0x00, .pll[4] = 0x00, 1350 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1351 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x55, .pll[13] = 0x55, .pll[14] = 0x55, 1352 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1353 }; 1354 1355 static const struct intel_c10pll_state mtl_c10_hdmi_49500 = { 1356 .clock = 49500, 1357 .tx = 0x10, 1358 .cmn = 0x1, 1359 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00, 1360 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1361 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00, 1362 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1363 }; 1364 1365 static const struct intel_c10pll_state mtl_c10_hdmi_50000 = { 1366 .clock = 50000, 1367 .tx = 0x10, 1368 .cmn = 0x1, 1369 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xB0, .pll[3] = 0x00, .pll[4] = 0x00, 1370 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1371 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x2A, .pll[13] = 0xA9, .pll[14] = 0xAA, 1372 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1373 }; 1374 1375 static const struct intel_c10pll_state mtl_c10_hdmi_57284 = { 1376 .clock = 57284, 1377 .tx = 0x10, 1378 .cmn = 0x1, 1379 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xCE, .pll[3] = 0x00, .pll[4] = 0x00, 1380 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1381 .pll[10] = 0xFF, .pll[11] = 0x77, .pll[12] = 0x57, .pll[13] = 0x77, .pll[14] = 0x77, 1382 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1383 }; 1384 1385 static const struct intel_c10pll_state mtl_c10_hdmi_58000 = { 1386 .clock = 58000, 1387 .tx = 0x10, 1388 .cmn = 0x1, 1389 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD0, .pll[3] = 0x00, .pll[4] = 0x00, 1390 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1391 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xD5, .pll[13] = 0x55, .pll[14] = 0x55, 1392 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1393 }; 1394 1395 static const struct intel_c10pll_state mtl_c10_hdmi_65000 = { 1396 .clock = 65000, 1397 .tx = 0x10, 1398 .cmn = 0x1, 1399 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x66, .pll[3] = 0x00, .pll[4] = 0x00, 1400 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1401 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xB5, .pll[13] = 0x55, .pll[14] = 0x55, 1402 .pll[15] = 0x0B, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1403 }; 1404 1405 static const struct intel_c10pll_state mtl_c10_hdmi_71000 = { 1406 .clock = 71000, 1407 .tx = 0x10, 1408 .cmn = 0x1, 1409 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x72, .pll[3] = 0x00, .pll[4] = 0x00, 1410 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1411 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xF5, .pll[13] = 0x55, .pll[14] = 0x55, 1412 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1413 }; 1414 1415 static const struct intel_c10pll_state mtl_c10_hdmi_74176 = { 1416 .clock = 74176, 1417 .tx = 0x10, 1418 .cmn = 0x1, 1419 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00, 1420 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1421 .pll[10] = 0xFF, .pll[11] = 0x44, .pll[12] = 0x44, .pll[13] = 0x44, .pll[14] = 0x44, 1422 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1423 }; 1424 1425 static const struct intel_c10pll_state mtl_c10_hdmi_75000 = { 1426 .clock = 75000, 1427 .tx = 0x10, 1428 .cmn = 0x1, 1429 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7C, .pll[3] = 0x00, .pll[4] = 0x00, 1430 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1431 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00, 1432 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1433 }; 1434 1435 static const struct intel_c10pll_state mtl_c10_hdmi_78750 = { 1436 .clock = 78750, 1437 .tx = 0x10, 1438 .cmn = 0x1, 1439 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x84, .pll[3] = 0x00, .pll[4] = 0x00, 1440 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1441 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x08, .pll[13] = 0x00, .pll[14] = 0x00, 1442 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1443 }; 1444 1445 static const struct intel_c10pll_state mtl_c10_hdmi_85500 = { 1446 .clock = 85500, 1447 .tx = 0x10, 1448 .cmn = 0x1, 1449 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x92, .pll[3] = 0x00, .pll[4] = 0x00, 1450 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1451 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x10, .pll[13] = 0x00, .pll[14] = 0x00, 1452 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1453 }; 1454 1455 static const struct intel_c10pll_state mtl_c10_hdmi_88750 = { 1456 .clock = 88750, 1457 .tx = 0x10, 1458 .cmn = 0x1, 1459 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0x98, .pll[3] = 0x00, .pll[4] = 0x00, 1460 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1461 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x72, .pll[13] = 0xA9, .pll[14] = 0xAA, 1462 .pll[15] = 0x0B, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1463 }; 1464 1465 static const struct intel_c10pll_state mtl_c10_hdmi_106500 = { 1466 .clock = 106500, 1467 .tx = 0x10, 1468 .cmn = 0x1, 1469 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xBC, .pll[3] = 0x00, .pll[4] = 0x00, 1470 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1471 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xF0, .pll[13] = 0x00, .pll[14] = 0x00, 1472 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1473 }; 1474 1475 static const struct intel_c10pll_state mtl_c10_hdmi_108000 = { 1476 .clock = 108000, 1477 .tx = 0x10, 1478 .cmn = 0x1, 1479 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xC0, .pll[3] = 0x00, .pll[4] = 0x00, 1480 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1481 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x80, .pll[13] = 0x00, .pll[14] = 0x00, 1482 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1483 }; 1484 1485 static const struct intel_c10pll_state mtl_c10_hdmi_115500 = { 1486 .clock = 115500, 1487 .tx = 0x10, 1488 .cmn = 0x1, 1489 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD0, .pll[3] = 0x00, .pll[4] = 0x00, 1490 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1491 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x50, .pll[13] = 0x00, .pll[14] = 0x00, 1492 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1493 }; 1494 1495 static const struct intel_c10pll_state mtl_c10_hdmi_119000 = { 1496 .clock = 119000, 1497 .tx = 0x10, 1498 .cmn = 0x1, 1499 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD6, .pll[3] = 0x00, .pll[4] = 0x00, 1500 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1501 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xF5, .pll[13] = 0x55, .pll[14] = 0x55, 1502 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1503 }; 1504 1505 static const struct intel_c10pll_state mtl_c10_hdmi_135000 = { 1506 .clock = 135000, 1507 .tx = 0x10, 1508 .cmn = 0x1, 1509 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x6C, .pll[3] = 0x00, .pll[4] = 0x00, 1510 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1511 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x50, .pll[13] = 0x00, .pll[14] = 0x00, 1512 .pll[15] = 0x0A, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1513 }; 1514 1515 static const struct intel_c10pll_state mtl_c10_hdmi_138500 = { 1516 .clock = 138500, 1517 .tx = 0x10, 1518 .cmn = 0x1, 1519 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x70, .pll[3] = 0x00, .pll[4] = 0x00, 1520 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1521 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x22, .pll[13] = 0xA9, .pll[14] = 0xAA, 1522 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1523 }; 1524 1525 static const struct intel_c10pll_state mtl_c10_hdmi_147160 = { 1526 .clock = 147160, 1527 .tx = 0x10, 1528 .cmn = 0x1, 1529 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x78, .pll[3] = 0x00, .pll[4] = 0x00, 1530 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1531 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xA5, .pll[13] = 0x55, .pll[14] = 0x55, 1532 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1533 }; 1534 1535 static const struct intel_c10pll_state mtl_c10_hdmi_148352 = { 1536 .clock = 148352, 1537 .tx = 0x10, 1538 .cmn = 0x1, 1539 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00, 1540 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1541 .pll[10] = 0xFF, .pll[11] = 0x44, .pll[12] = 0x44, .pll[13] = 0x44, .pll[14] = 0x44, 1542 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1543 }; 1544 1545 static const struct intel_c10pll_state mtl_c10_hdmi_154000 = { 1546 .clock = 154000, 1547 .tx = 0x10, 1548 .cmn = 0x1, 1549 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x80, .pll[3] = 0x00, .pll[4] = 0x00, 1550 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1551 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x35, .pll[13] = 0x55, .pll[14] = 0x55, 1552 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1553 }; 1554 1555 static const struct intel_c10pll_state mtl_c10_hdmi_162000 = { 1556 .clock = 162000, 1557 .tx = 0x10, 1558 .cmn = 0x1, 1559 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x88, .pll[3] = 0x00, .pll[4] = 0x00, 1560 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1561 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x60, .pll[13] = 0x00, .pll[14] = 0x00, 1562 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1563 }; 1564 1565 static const struct intel_c10pll_state mtl_c10_hdmi_167000 = { 1566 .clock = 167000, 1567 .tx = 0x10, 1568 .cmn = 0x1, 1569 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x8C, .pll[3] = 0x00, .pll[4] = 0x00, 1570 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1571 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0xFA, .pll[13] = 0xA9, .pll[14] = 0xAA, 1572 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1573 }; 1574 1575 static const struct intel_c10pll_state mtl_c10_hdmi_197802 = { 1576 .clock = 197802, 1577 .tx = 0x10, 1578 .cmn = 0x1, 1579 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00, 1580 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1581 .pll[10] = 0xFF, .pll[11] = 0x99, .pll[12] = 0x05, .pll[13] = 0x98, .pll[14] = 0x99, 1582 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1583 }; 1584 1585 static const struct intel_c10pll_state mtl_c10_hdmi_198000 = { 1586 .clock = 198000, 1587 .tx = 0x10, 1588 .cmn = 0x1, 1589 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00, 1590 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1591 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00, 1592 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1593 }; 1594 1595 static const struct intel_c10pll_state mtl_c10_hdmi_209800 = { 1596 .clock = 209800, 1597 .tx = 0x10, 1598 .cmn = 0x1, 1599 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xBA, .pll[3] = 0x00, .pll[4] = 0x00, 1600 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1601 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x45, .pll[13] = 0x55, .pll[14] = 0x55, 1602 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1603 }; 1604 1605 static const struct intel_c10pll_state mtl_c10_hdmi_241500 = { 1606 .clock = 241500, 1607 .tx = 0x10, 1608 .cmn = 0x1, 1609 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xDA, .pll[3] = 0x00, .pll[4] = 0x00, 1610 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1611 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xC8, .pll[13] = 0x00, .pll[14] = 0x00, 1612 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1613 }; 1614 1615 static const struct intel_c10pll_state mtl_c10_hdmi_262750 = { 1616 .clock = 262750, 1617 .tx = 0x10, 1618 .cmn = 0x1, 1619 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x68, .pll[3] = 0x00, .pll[4] = 0x00, 1620 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1621 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x6C, .pll[13] = 0xA9, .pll[14] = 0xAA, 1622 .pll[15] = 0x09, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1623 }; 1624 1625 static const struct intel_c10pll_state mtl_c10_hdmi_268500 = { 1626 .clock = 268500, 1627 .tx = 0x10, 1628 .cmn = 0x1, 1629 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x6A, .pll[3] = 0x00, .pll[4] = 0x00, 1630 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1631 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xEC, .pll[13] = 0x00, .pll[14] = 0x00, 1632 .pll[15] = 0x09, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1633 }; 1634 1635 static const struct intel_c10pll_state mtl_c10_hdmi_296703 = { 1636 .clock = 296703, 1637 .tx = 0x10, 1638 .cmn = 0x1, 1639 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00, 1640 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1641 .pll[10] = 0xFF, .pll[11] = 0x33, .pll[12] = 0x44, .pll[13] = 0x33, .pll[14] = 0x33, 1642 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1643 }; 1644 1645 static const struct intel_c10pll_state mtl_c10_hdmi_297000 = { 1646 .clock = 297000, 1647 .tx = 0x10, 1648 .cmn = 0x1, 1649 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00, 1650 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1651 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x58, .pll[13] = 0x00, .pll[14] = 0x00, 1652 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1653 }; 1654 1655 static const struct intel_c10pll_state mtl_c10_hdmi_319750 = { 1656 .clock = 319750, 1657 .tx = 0x10, 1658 .cmn = 0x1, 1659 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x86, .pll[3] = 0x00, .pll[4] = 0x00, 1660 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1661 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x44, .pll[13] = 0xA9, .pll[14] = 0xAA, 1662 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1663 }; 1664 1665 static const struct intel_c10pll_state mtl_c10_hdmi_497750 = { 1666 .clock = 497750, 1667 .tx = 0x10, 1668 .cmn = 0x1, 1669 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xE2, .pll[3] = 0x00, .pll[4] = 0x00, 1670 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1671 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x9F, .pll[13] = 0x55, .pll[14] = 0x55, 1672 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23, 1673 }; 1674 1675 static const struct intel_c10pll_state mtl_c10_hdmi_592000 = { 1676 .clock = 592000, 1677 .tx = 0x10, 1678 .cmn = 0x1, 1679 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00, 1680 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1681 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x15, .pll[13] = 0x55, .pll[14] = 0x55, 1682 .pll[15] = 0x08, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1683 }; 1684 1685 static const struct intel_c10pll_state mtl_c10_hdmi_593407 = { 1686 .clock = 593407, 1687 .tx = 0x10, 1688 .cmn = 0x1, 1689 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00, 1690 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF, 1691 .pll[10] = 0xFF, .pll[11] = 0x3B, .pll[12] = 0x44, .pll[13] = 0xBA, .pll[14] = 0xBB, 1692 .pll[15] = 0x08, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23, 1693 }; 1694 1695 static const struct intel_c10pll_state * const mtl_c10_hdmi_tables[] = { 1696 &mtl_c10_hdmi_25_2, /* Consolidated Table */ 1697 &mtl_c10_hdmi_27_0, /* Consolidated Table */ 1698 &mtl_c10_hdmi_27027, 1699 &mtl_c10_hdmi_28320, 1700 &mtl_c10_hdmi_30240, 1701 &mtl_c10_hdmi_31500, 1702 &mtl_c10_hdmi_36000, 1703 &mtl_c10_hdmi_40000, 1704 &mtl_c10_hdmi_49500, 1705 &mtl_c10_hdmi_50000, 1706 &mtl_c10_hdmi_57284, 1707 &mtl_c10_hdmi_58000, 1708 &mtl_c10_hdmi_65000, 1709 &mtl_c10_hdmi_71000, 1710 &mtl_c10_hdmi_74176, 1711 &mtl_c10_hdmi_74_25, /* Consolidated Table */ 1712 &mtl_c10_hdmi_75000, 1713 &mtl_c10_hdmi_78750, 1714 &mtl_c10_hdmi_85500, 1715 &mtl_c10_hdmi_88750, 1716 &mtl_c10_hdmi_106500, 1717 &mtl_c10_hdmi_108000, 1718 &mtl_c10_hdmi_115500, 1719 &mtl_c10_hdmi_119000, 1720 &mtl_c10_hdmi_135000, 1721 &mtl_c10_hdmi_138500, 1722 &mtl_c10_hdmi_147160, 1723 &mtl_c10_hdmi_148352, 1724 &mtl_c10_hdmi_148_5, /* Consolidated Table */ 1725 &mtl_c10_hdmi_154000, 1726 &mtl_c10_hdmi_162000, 1727 &mtl_c10_hdmi_167000, 1728 &mtl_c10_hdmi_197802, 1729 &mtl_c10_hdmi_198000, 1730 &mtl_c10_hdmi_209800, 1731 &mtl_c10_hdmi_241500, 1732 &mtl_c10_hdmi_262750, 1733 &mtl_c10_hdmi_268500, 1734 &mtl_c10_hdmi_296703, 1735 &mtl_c10_hdmi_297000, 1736 &mtl_c10_hdmi_319750, 1737 &mtl_c10_hdmi_497750, 1738 &mtl_c10_hdmi_592000, 1739 &mtl_c10_hdmi_593407, 1740 &mtl_c10_hdmi_594, /* Consolidated Table */ 1741 NULL, 1742 }; 1743 1744 static const struct intel_c20pll_state mtl_c20_hdmi_25_175 = { 1745 .clock = 25175, 1746 .tx = { 0xbe88, /* tx cfg0 */ 1747 0x9800, /* tx cfg1 */ 1748 0x0000, /* tx cfg2 */ 1749 }, 1750 .cmn = { 0x0500, /* cmn cfg0*/ 1751 0x0005, /* cmn cfg1 */ 1752 0x0000, /* cmn cfg2 */ 1753 0x0000, /* cmn cfg3 */ 1754 }, 1755 .mpllb = { 0xa0d2, /* mpllb cfg0 */ 1756 0x7d80, /* mpllb cfg1 */ 1757 0x0906, /* mpllb cfg2 */ 1758 0xbe40, /* mpllb cfg3 */ 1759 0x0000, /* mpllb cfg4 */ 1760 0x0000, /* mpllb cfg5 */ 1761 0x0200, /* mpllb cfg6 */ 1762 0x0001, /* mpllb cfg7 */ 1763 0x0000, /* mpllb cfg8 */ 1764 0x0000, /* mpllb cfg9 */ 1765 0x0001, /* mpllb cfg10 */ 1766 }, 1767 }; 1768 1769 static const struct intel_c20pll_state mtl_c20_hdmi_27_0 = { 1770 .clock = 27000, 1771 .tx = { 0xbe88, /* tx cfg0 */ 1772 0x9800, /* tx cfg1 */ 1773 0x0000, /* tx cfg2 */ 1774 }, 1775 .cmn = { 0x0500, /* cmn cfg0*/ 1776 0x0005, /* cmn cfg1 */ 1777 0x0000, /* cmn cfg2 */ 1778 0x0000, /* cmn cfg3 */ 1779 }, 1780 .mpllb = { 0xa0e0, /* mpllb cfg0 */ 1781 0x7d80, /* mpllb cfg1 */ 1782 0x0906, /* mpllb cfg2 */ 1783 0xbe40, /* mpllb cfg3 */ 1784 0x0000, /* mpllb cfg4 */ 1785 0x0000, /* mpllb cfg5 */ 1786 0x2200, /* mpllb cfg6 */ 1787 0x0001, /* mpllb cfg7 */ 1788 0x8000, /* mpllb cfg8 */ 1789 0x0000, /* mpllb cfg9 */ 1790 0x0001, /* mpllb cfg10 */ 1791 }, 1792 }; 1793 1794 static const struct intel_c20pll_state mtl_c20_hdmi_74_25 = { 1795 .clock = 74250, 1796 .tx = { 0xbe88, /* tx cfg0 */ 1797 0x9800, /* tx cfg1 */ 1798 0x0000, /* tx cfg2 */ 1799 }, 1800 .cmn = { 0x0500, /* cmn cfg0*/ 1801 0x0005, /* cmn cfg1 */ 1802 0x0000, /* cmn cfg2 */ 1803 0x0000, /* cmn cfg3 */ 1804 }, 1805 .mpllb = { 0x609a, /* mpllb cfg0 */ 1806 0x7d40, /* mpllb cfg1 */ 1807 0xca06, /* mpllb cfg2 */ 1808 0xbe40, /* mpllb cfg3 */ 1809 0x0000, /* mpllb cfg4 */ 1810 0x0000, /* mpllb cfg5 */ 1811 0x2200, /* mpllb cfg6 */ 1812 0x0001, /* mpllb cfg7 */ 1813 0x5800, /* mpllb cfg8 */ 1814 0x0000, /* mpllb cfg9 */ 1815 0x0001, /* mpllb cfg10 */ 1816 }, 1817 }; 1818 1819 static const struct intel_c20pll_state mtl_c20_hdmi_148_5 = { 1820 .clock = 148500, 1821 .tx = { 0xbe88, /* tx cfg0 */ 1822 0x9800, /* tx cfg1 */ 1823 0x0000, /* tx cfg2 */ 1824 }, 1825 .cmn = { 0x0500, /* cmn cfg0*/ 1826 0x0005, /* cmn cfg1 */ 1827 0x0000, /* cmn cfg2 */ 1828 0x0000, /* cmn cfg3 */ 1829 }, 1830 .mpllb = { 0x409a, /* mpllb cfg0 */ 1831 0x7d20, /* mpllb cfg1 */ 1832 0xca06, /* mpllb cfg2 */ 1833 0xbe40, /* mpllb cfg3 */ 1834 0x0000, /* mpllb cfg4 */ 1835 0x0000, /* mpllb cfg5 */ 1836 0x2200, /* mpllb cfg6 */ 1837 0x0001, /* mpllb cfg7 */ 1838 0x5800, /* mpllb cfg8 */ 1839 0x0000, /* mpllb cfg9 */ 1840 0x0001, /* mpllb cfg10 */ 1841 }, 1842 }; 1843 1844 static const struct intel_c20pll_state mtl_c20_hdmi_594 = { 1845 .clock = 594000, 1846 .tx = { 0xbe88, /* tx cfg0 */ 1847 0x9800, /* tx cfg1 */ 1848 0x0000, /* tx cfg2 */ 1849 }, 1850 .cmn = { 0x0500, /* cmn cfg0*/ 1851 0x0005, /* cmn cfg1 */ 1852 0x0000, /* cmn cfg2 */ 1853 0x0000, /* cmn cfg3 */ 1854 }, 1855 .mpllb = { 0x009a, /* mpllb cfg0 */ 1856 0x7d08, /* mpllb cfg1 */ 1857 0xca06, /* mpllb cfg2 */ 1858 0xbe40, /* mpllb cfg3 */ 1859 0x0000, /* mpllb cfg4 */ 1860 0x0000, /* mpllb cfg5 */ 1861 0x2200, /* mpllb cfg6 */ 1862 0x0001, /* mpllb cfg7 */ 1863 0x5800, /* mpllb cfg8 */ 1864 0x0000, /* mpllb cfg9 */ 1865 0x0001, /* mpllb cfg10 */ 1866 }, 1867 }; 1868 1869 static const struct intel_c20pll_state mtl_c20_hdmi_300 = { 1870 .clock = 3000000, 1871 .tx = { 0xbe98, /* tx cfg0 */ 1872 0x8800, /* tx cfg1 */ 1873 0x0000, /* tx cfg2 */ 1874 }, 1875 .cmn = { 0x0500, /* cmn cfg0*/ 1876 0x0005, /* cmn cfg1 */ 1877 0x0000, /* cmn cfg2 */ 1878 0x0000, /* cmn cfg3 */ 1879 }, 1880 .mpllb = { 0x309c, /* mpllb cfg0 */ 1881 0x2110, /* mpllb cfg1 */ 1882 0xca06, /* mpllb cfg2 */ 1883 0xbe40, /* mpllb cfg3 */ 1884 0x0000, /* mpllb cfg4 */ 1885 0x0000, /* mpllb cfg5 */ 1886 0x2200, /* mpllb cfg6 */ 1887 0x0001, /* mpllb cfg7 */ 1888 0x2000, /* mpllb cfg8 */ 1889 0x0000, /* mpllb cfg9 */ 1890 0x0004, /* mpllb cfg10 */ 1891 }, 1892 }; 1893 1894 static const struct intel_c20pll_state mtl_c20_hdmi_600 = { 1895 .clock = 6000000, 1896 .tx = { 0xbe98, /* tx cfg0 */ 1897 0x8800, /* tx cfg1 */ 1898 0x0000, /* tx cfg2 */ 1899 }, 1900 .cmn = { 0x0500, /* cmn cfg0*/ 1901 0x0005, /* cmn cfg1 */ 1902 0x0000, /* cmn cfg2 */ 1903 0x0000, /* cmn cfg3 */ 1904 }, 1905 .mpllb = { 0x109c, /* mpllb cfg0 */ 1906 0x2108, /* mpllb cfg1 */ 1907 0xca06, /* mpllb cfg2 */ 1908 0xbe40, /* mpllb cfg3 */ 1909 0x0000, /* mpllb cfg4 */ 1910 0x0000, /* mpllb cfg5 */ 1911 0x2200, /* mpllb cfg6 */ 1912 0x0001, /* mpllb cfg7 */ 1913 0x2000, /* mpllb cfg8 */ 1914 0x0000, /* mpllb cfg9 */ 1915 0x0004, /* mpllb cfg10 */ 1916 }, 1917 }; 1918 1919 static const struct intel_c20pll_state mtl_c20_hdmi_800 = { 1920 .clock = 8000000, 1921 .tx = { 0xbe98, /* tx cfg0 */ 1922 0x8800, /* tx cfg1 */ 1923 0x0000, /* tx cfg2 */ 1924 }, 1925 .cmn = { 0x0500, /* cmn cfg0*/ 1926 0x0005, /* cmn cfg1 */ 1927 0x0000, /* cmn cfg2 */ 1928 0x0000, /* cmn cfg3 */ 1929 }, 1930 .mpllb = { 0x10d0, /* mpllb cfg0 */ 1931 0x2108, /* mpllb cfg1 */ 1932 0x4a06, /* mpllb cfg2 */ 1933 0xbe40, /* mpllb cfg3 */ 1934 0x0000, /* mpllb cfg4 */ 1935 0x0000, /* mpllb cfg5 */ 1936 0x2200, /* mpllb cfg6 */ 1937 0x0003, /* mpllb cfg7 */ 1938 0x2aaa, /* mpllb cfg8 */ 1939 0x0002, /* mpllb cfg9 */ 1940 0x0004, /* mpllb cfg10 */ 1941 }, 1942 }; 1943 1944 static const struct intel_c20pll_state mtl_c20_hdmi_1000 = { 1945 .clock = 10000000, 1946 .tx = { 0xbe98, /* tx cfg0 */ 1947 0x8800, /* tx cfg1 */ 1948 0x0000, /* tx cfg2 */ 1949 }, 1950 .cmn = { 0x0500, /* cmn cfg0*/ 1951 0x0005, /* cmn cfg1 */ 1952 0x0000, /* cmn cfg2 */ 1953 0x0000, /* cmn cfg3 */ 1954 }, 1955 .mpllb = { 0x1104, /* mpllb cfg0 */ 1956 0x2108, /* mpllb cfg1 */ 1957 0x0a06, /* mpllb cfg2 */ 1958 0xbe40, /* mpllb cfg3 */ 1959 0x0000, /* mpllb cfg4 */ 1960 0x0000, /* mpllb cfg5 */ 1961 0x2200, /* mpllb cfg6 */ 1962 0x0003, /* mpllb cfg7 */ 1963 0x3555, /* mpllb cfg8 */ 1964 0x0001, /* mpllb cfg9 */ 1965 0x0004, /* mpllb cfg10 */ 1966 }, 1967 }; 1968 1969 static const struct intel_c20pll_state mtl_c20_hdmi_1200 = { 1970 .clock = 12000000, 1971 .tx = { 0xbe98, /* tx cfg0 */ 1972 0x8800, /* tx cfg1 */ 1973 0x0000, /* tx cfg2 */ 1974 }, 1975 .cmn = { 0x0500, /* cmn cfg0*/ 1976 0x0005, /* cmn cfg1 */ 1977 0x0000, /* cmn cfg2 */ 1978 0x0000, /* cmn cfg3 */ 1979 }, 1980 .mpllb = { 0x1138, /* mpllb cfg0 */ 1981 0x2108, /* mpllb cfg1 */ 1982 0x5486, /* mpllb cfg2 */ 1983 0xfe40, /* mpllb cfg3 */ 1984 0x0000, /* mpllb cfg4 */ 1985 0x0000, /* mpllb cfg5 */ 1986 0x2200, /* mpllb cfg6 */ 1987 0x0001, /* mpllb cfg7 */ 1988 0x4000, /* mpllb cfg8 */ 1989 0x0000, /* mpllb cfg9 */ 1990 0x0004, /* mpllb cfg10 */ 1991 }, 1992 }; 1993 1994 static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = { 1995 &mtl_c20_hdmi_25_175, 1996 &mtl_c20_hdmi_27_0, 1997 &mtl_c20_hdmi_74_25, 1998 &mtl_c20_hdmi_148_5, 1999 &mtl_c20_hdmi_594, 2000 &mtl_c20_hdmi_300, 2001 &mtl_c20_hdmi_600, 2002 &mtl_c20_hdmi_800, 2003 &mtl_c20_hdmi_1000, 2004 &mtl_c20_hdmi_1200, 2005 NULL, 2006 }; 2007 2008 static const struct intel_c10pll_state * const * 2009 intel_c10pll_tables_get(struct intel_crtc_state *crtc_state, 2010 struct intel_encoder *encoder) 2011 { 2012 if (intel_crtc_has_dp_encoder(crtc_state)) { 2013 if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) 2014 return mtl_c10_edp_tables; 2015 else 2016 return mtl_c10_dp_tables; 2017 } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { 2018 return mtl_c10_hdmi_tables; 2019 } 2020 2021 MISSING_CASE(encoder->type); 2022 return NULL; 2023 } 2024 2025 static void intel_cx0pll_update_ssc(struct intel_encoder *encoder, 2026 struct intel_cx0pll_state *pll_state, bool is_dp) 2027 { 2028 struct intel_display *display = to_intel_display(encoder); 2029 2030 if (is_dp) { 2031 if (intel_panel_use_ssc(display)) { 2032 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 2033 pll_state->ssc_enabled = 2034 (intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5); 2035 } 2036 } 2037 } 2038 2039 static void intel_c10pll_update_pll(struct intel_encoder *encoder, 2040 struct intel_cx0pll_state *pll_state) 2041 { 2042 struct intel_display *display = to_intel_display(encoder); 2043 int i; 2044 2045 if (pll_state->ssc_enabled) 2046 return; 2047 2048 drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) < 9); 2049 for (i = 4; i < 9; i++) 2050 pll_state->c10.pll[i] = 0; 2051 } 2052 2053 static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, 2054 const struct intel_c10pll_state * const *tables, 2055 bool is_dp, int port_clock, 2056 struct intel_cx0pll_state *pll_state) 2057 { 2058 int i; 2059 2060 for (i = 0; tables[i]; i++) { 2061 if (port_clock == tables[i]->clock) { 2062 pll_state->c10 = *tables[i]; 2063 intel_cx0pll_update_ssc(encoder, pll_state, is_dp); 2064 intel_c10pll_update_pll(encoder, pll_state); 2065 pll_state->use_c10 = true; 2066 2067 return 0; 2068 } 2069 } 2070 2071 return -EINVAL; 2072 } 2073 2074 static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, 2075 struct intel_encoder *encoder) 2076 { 2077 const struct intel_c10pll_state * const *tables; 2078 int err; 2079 2080 tables = intel_c10pll_tables_get(crtc_state, encoder); 2081 if (!tables) 2082 return -EINVAL; 2083 2084 err = intel_c10pll_calc_state_from_table(encoder, tables, 2085 intel_crtc_has_dp_encoder(crtc_state), 2086 crtc_state->port_clock, 2087 &crtc_state->dpll_hw_state.cx0pll); 2088 2089 if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) 2090 return err; 2091 2092 /* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */ 2093 intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10, 2094 crtc_state->port_clock); 2095 intel_c10pll_update_pll(encoder, 2096 &crtc_state->dpll_hw_state.cx0pll); 2097 crtc_state->dpll_hw_state.cx0pll.use_c10 = true; 2098 2099 return 0; 2100 } 2101 2102 static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, 2103 struct intel_c10pll_state *pll_state) 2104 { 2105 u8 lane = INTEL_CX0_LANE0; 2106 intel_wakeref_t wakeref; 2107 int i; 2108 2109 wakeref = intel_cx0_phy_transaction_begin(encoder); 2110 2111 /* 2112 * According to C10 VDR Register programming Sequence we need 2113 * to do this to read PHY internal registers from MsgBus. 2114 */ 2115 intel_cx0_rmw(encoder, lane, PHY_C10_VDR_CONTROL(1), 2116 0, C10_VDR_CTRL_MSGBUS_ACCESS, 2117 MB_WRITE_COMMITTED); 2118 2119 for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) 2120 pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i)); 2121 2122 pll_state->cmn = intel_cx0_read(encoder, lane, PHY_C10_VDR_CMN(0)); 2123 pll_state->tx = intel_cx0_read(encoder, lane, PHY_C10_VDR_TX(0)); 2124 2125 intel_cx0_phy_transaction_end(encoder, wakeref); 2126 } 2127 2128 static void intel_c10_pll_program(struct intel_display *display, 2129 struct intel_encoder *encoder, 2130 const struct intel_c10pll_state *pll_state) 2131 { 2132 int i; 2133 2134 intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1), 2135 0, C10_VDR_CTRL_MSGBUS_ACCESS, 2136 MB_WRITE_COMMITTED); 2137 2138 /* Program the pll values only for the master lane */ 2139 for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) 2140 intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_PLL(i), 2141 pll_state->pll[i], 2142 (i % 4) ? MB_WRITE_UNCOMMITTED : MB_WRITE_COMMITTED); 2143 2144 intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CMN(0), pll_state->cmn, MB_WRITE_COMMITTED); 2145 intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_TX(0), pll_state->tx, MB_WRITE_COMMITTED); 2146 2147 /* Custom width needs to be programmed to 0 for both the phy lanes */ 2148 intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH, 2149 C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10, 2150 MB_WRITE_COMMITTED); 2151 intel_cx0_rmw(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1), 2152 0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG, 2153 MB_WRITE_COMMITTED); 2154 } 2155 2156 static void intel_c10pll_dump_hw_state(struct intel_display *display, 2157 const struct intel_c10pll_state *hw_state) 2158 { 2159 bool fracen; 2160 int i; 2161 unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1; 2162 unsigned int multiplier, tx_clk_div; 2163 2164 fracen = hw_state->pll[0] & C10_PLL0_FRACEN; 2165 drm_dbg_kms(display->drm, "c10pll_hw_state: fracen: %s, ", 2166 str_yes_no(fracen)); 2167 2168 if (fracen) { 2169 frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11]; 2170 frac_rem = hw_state->pll[14] << 8 | hw_state->pll[13]; 2171 frac_den = hw_state->pll[10] << 8 | hw_state->pll[9]; 2172 drm_dbg_kms(display->drm, "quot: %u, rem: %u, den: %u,\n", 2173 frac_quot, frac_rem, frac_den); 2174 } 2175 2176 multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, hw_state->pll[3]) << 8 | 2177 hw_state->pll[2]) / 2 + 16; 2178 tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, hw_state->pll[15]); 2179 drm_dbg_kms(display->drm, 2180 "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div); 2181 2182 drm_dbg_kms(display->drm, "c10pll_rawhw_state:"); 2183 drm_dbg_kms(display->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, 2184 hw_state->cmn); 2185 2186 BUILD_BUG_ON(ARRAY_SIZE(hw_state->pll) % 4); 2187 for (i = 0; i < ARRAY_SIZE(hw_state->pll); i = i + 4) 2188 drm_dbg_kms(display->drm, 2189 "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n", 2190 i, hw_state->pll[i], i + 1, hw_state->pll[i + 1], 2191 i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]); 2192 } 2193 2194 /* 2195 * Some ARLs SoCs have the same drm PCI IDs, so need a helper to differentiate based 2196 * on the host bridge device ID to get the correct txx_mics value. 2197 */ 2198 static bool is_arrowlake_s_by_host_bridge(void) 2199 { 2200 struct pci_dev *pdev = NULL; 2201 u16 host_bridge_pci_dev_id; 2202 2203 while ((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, pdev))) 2204 host_bridge_pci_dev_id = pdev->device; 2205 2206 return pdev && IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(host_bridge_pci_dev_id); 2207 } 2208 2209 static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state) 2210 { 2211 struct intel_display *display = to_intel_display(crtc_state); 2212 u16 tx_misc; 2213 u16 tx_dcc_cal_dac_ctrl_range = 8; 2214 u16 tx_term_ctrl = 2; 2215 2216 if (DISPLAY_VER(display) >= 20) { 2217 tx_misc = 5; 2218 tx_term_ctrl = 4; 2219 } else if (display->platform.battlemage) { 2220 tx_misc = 0; 2221 } else if (display->platform.meteorlake_u || 2222 is_arrowlake_s_by_host_bridge()) { 2223 tx_misc = 3; 2224 } else { 2225 tx_misc = 7; 2226 } 2227 2228 return (C20_PHY_TX_MISC(tx_misc) | 2229 C20_PHY_TX_DCC_CAL_RANGE(tx_dcc_cal_dac_ctrl_range) | 2230 C20_PHY_TX_DCC_BYPASS | C20_PHY_TX_TERM_CTL(tx_term_ctrl)); 2231 } 2232 2233 static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) 2234 { 2235 struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20; 2236 u64 datarate; 2237 u64 mpll_tx_clk_div; 2238 u64 vco_freq_shift; 2239 u64 vco_freq; 2240 u64 multiplier; 2241 u64 mpll_multiplier; 2242 u64 mpll_fracn_quot; 2243 u64 mpll_fracn_rem; 2244 u8 mpllb_ana_freq_vco; 2245 u8 mpll_div_multiplier; 2246 2247 if (crtc_state->port_clock < 25175 || crtc_state->port_clock > 600000) 2248 return -EINVAL; 2249 2250 datarate = ((u64)crtc_state->port_clock * 1000) * 10; 2251 mpll_tx_clk_div = ilog2(div64_u64((u64)CLOCK_9999MHZ, (u64)datarate)); 2252 vco_freq_shift = ilog2(div64_u64((u64)CLOCK_4999MHZ * (u64)256, (u64)datarate)); 2253 vco_freq = (datarate << vco_freq_shift) >> 8; 2254 multiplier = div64_u64((vco_freq << 28), (REFCLK_38_4_MHZ >> 4)); 2255 mpll_multiplier = 2 * (multiplier >> 32); 2256 2257 mpll_fracn_quot = (multiplier >> 16) & 0xFFFF; 2258 mpll_fracn_rem = multiplier & 0xFFFF; 2259 2260 mpll_div_multiplier = min_t(u8, div64_u64((vco_freq * 16 + (datarate >> 1)), 2261 datarate), 255); 2262 2263 if (vco_freq <= DATARATE_3000000000) 2264 mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_3; 2265 else if (vco_freq <= DATARATE_3500000000) 2266 mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_2; 2267 else if (vco_freq <= DATARATE_4000000000) 2268 mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_1; 2269 else 2270 mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_0; 2271 2272 pll_state->clock = crtc_state->port_clock; 2273 pll_state->tx[0] = 0xbe88; 2274 pll_state->tx[1] = intel_c20_hdmi_tmds_tx_cgf_1(crtc_state); 2275 pll_state->tx[2] = 0x0000; 2276 pll_state->cmn[0] = 0x0500; 2277 pll_state->cmn[1] = 0x0005; 2278 pll_state->cmn[2] = 0x0000; 2279 pll_state->cmn[3] = 0x0000; 2280 pll_state->mpllb[0] = (MPLL_TX_CLK_DIV(mpll_tx_clk_div) | 2281 MPLL_MULTIPLIER(mpll_multiplier)); 2282 pll_state->mpllb[1] = (CAL_DAC_CODE(CAL_DAC_CODE_31) | 2283 WORD_CLK_DIV | 2284 MPLL_DIV_MULTIPLIER(mpll_div_multiplier)); 2285 pll_state->mpllb[2] = (MPLLB_ANA_FREQ_VCO(mpllb_ana_freq_vco) | 2286 CP_PROP(CP_PROP_20) | 2287 CP_INT(CP_INT_6)); 2288 pll_state->mpllb[3] = (V2I(V2I_2) | 2289 CP_PROP_GS(CP_PROP_GS_30) | 2290 CP_INT_GS(CP_INT_GS_28)); 2291 pll_state->mpllb[4] = 0x0000; 2292 pll_state->mpllb[5] = 0x0000; 2293 pll_state->mpllb[6] = (C20_MPLLB_FRACEN | SSC_UP_SPREAD); 2294 pll_state->mpllb[7] = MPLL_FRACN_DEN; 2295 pll_state->mpllb[8] = mpll_fracn_quot; 2296 pll_state->mpllb[9] = mpll_fracn_rem; 2297 pll_state->mpllb[10] = HDMI_DIV(HDMI_DIV_1); 2298 2299 return 0; 2300 } 2301 2302 static const struct intel_c20pll_state * const * 2303 intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state, 2304 struct intel_encoder *encoder) 2305 { 2306 struct intel_display *display = to_intel_display(crtc_state); 2307 2308 if (intel_crtc_has_dp_encoder(crtc_state)) { 2309 if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) { 2310 if (DISPLAY_RUNTIME_INFO(display)->edp_typec_support) 2311 return xe3lpd_c20_dp_edp_tables; 2312 if (DISPLAY_VERx100(display) == 1401) 2313 return xe2hpd_c20_edp_tables; 2314 } 2315 2316 if (DISPLAY_VER(display) >= 30) 2317 return xe3lpd_c20_dp_edp_tables; 2318 else if (DISPLAY_VERx100(display) == 1401) 2319 return xe2hpd_c20_dp_tables; 2320 else 2321 return mtl_c20_dp_tables; 2322 2323 } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { 2324 return mtl_c20_hdmi_tables; 2325 } 2326 2327 MISSING_CASE(encoder->type); 2328 return NULL; 2329 } 2330 2331 static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, 2332 struct intel_encoder *encoder) 2333 { 2334 const struct intel_c20pll_state * const *tables; 2335 int i; 2336 2337 /* try computed C20 HDMI tables before using consolidated tables */ 2338 if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { 2339 if (intel_c20_compute_hdmi_tmds_pll(crtc_state) == 0) 2340 return 0; 2341 } 2342 2343 tables = intel_c20_pll_tables_get(crtc_state, encoder); 2344 if (!tables) 2345 return -EINVAL; 2346 2347 for (i = 0; tables[i]; i++) { 2348 if (crtc_state->port_clock == tables[i]->clock) { 2349 crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i]; 2350 intel_cx0pll_update_ssc(encoder, 2351 &crtc_state->dpll_hw_state.cx0pll, 2352 intel_crtc_has_dp_encoder(crtc_state)); 2353 crtc_state->dpll_hw_state.cx0pll.use_c10 = false; 2354 return 0; 2355 } 2356 } 2357 2358 return -EINVAL; 2359 } 2360 2361 int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, 2362 struct intel_encoder *encoder) 2363 { 2364 if (intel_encoder_is_c10phy(encoder)) 2365 return intel_c10pll_calc_state(crtc_state, encoder); 2366 return intel_c20pll_calc_state(crtc_state, encoder); 2367 } 2368 2369 static bool intel_c20phy_use_mpllb(const struct intel_c20pll_state *state) 2370 { 2371 return state->tx[0] & C20_PHY_USE_MPLLB; 2372 } 2373 2374 static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder, 2375 const struct intel_c20pll_state *pll_state) 2376 { 2377 unsigned int frac, frac_en, frac_quot, frac_rem, frac_den; 2378 unsigned int multiplier, refclk = 38400; 2379 unsigned int tx_clk_div; 2380 unsigned int ref_clk_mpllb_div; 2381 unsigned int fb_clk_div4_en; 2382 unsigned int ref, vco; 2383 unsigned int tx_rate_mult; 2384 unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]); 2385 2386 if (intel_c20phy_use_mpllb(pll_state)) { 2387 tx_rate_mult = 1; 2388 frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]); 2389 frac_quot = pll_state->mpllb[8]; 2390 frac_rem = pll_state->mpllb[9]; 2391 frac_den = pll_state->mpllb[7]; 2392 multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mpllb[0]); 2393 tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, pll_state->mpllb[0]); 2394 ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mpllb[6]); 2395 fb_clk_div4_en = 0; 2396 } else { 2397 tx_rate_mult = 2; 2398 frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]); 2399 frac_quot = pll_state->mplla[8]; 2400 frac_rem = pll_state->mplla[9]; 2401 frac_den = pll_state->mplla[7]; 2402 multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, pll_state->mplla[0]); 2403 tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, pll_state->mplla[1]); 2404 ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, pll_state->mplla[6]); 2405 fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, pll_state->mplla[0]); 2406 } 2407 2408 if (frac_en) 2409 frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den); 2410 else 2411 frac = 0; 2412 2413 ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << ref_clk_mpllb_div); 2414 vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + frac) >> 17, 10); 2415 2416 return vco << tx_rate_mult >> tx_clk_div >> tx_rate; 2417 } 2418 2419 static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, 2420 struct intel_c20pll_state *pll_state) 2421 { 2422 struct intel_display *display = to_intel_display(encoder); 2423 bool cntx; 2424 intel_wakeref_t wakeref; 2425 int i; 2426 2427 wakeref = intel_cx0_phy_transaction_begin(encoder); 2428 2429 /* 1. Read current context selection */ 2430 cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE; 2431 2432 /* Read Tx configuration */ 2433 for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { 2434 if (cntx) 2435 pll_state->tx[i] = intel_c20_sram_read(encoder, 2436 INTEL_CX0_LANE0, 2437 PHY_C20_B_TX_CNTX_CFG(display, i)); 2438 else 2439 pll_state->tx[i] = intel_c20_sram_read(encoder, 2440 INTEL_CX0_LANE0, 2441 PHY_C20_A_TX_CNTX_CFG(display, i)); 2442 } 2443 2444 /* Read common configuration */ 2445 for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) { 2446 if (cntx) 2447 pll_state->cmn[i] = intel_c20_sram_read(encoder, 2448 INTEL_CX0_LANE0, 2449 PHY_C20_B_CMN_CNTX_CFG(display, i)); 2450 else 2451 pll_state->cmn[i] = intel_c20_sram_read(encoder, 2452 INTEL_CX0_LANE0, 2453 PHY_C20_A_CMN_CNTX_CFG(display, i)); 2454 } 2455 2456 if (intel_c20phy_use_mpllb(pll_state)) { 2457 /* MPLLB configuration */ 2458 for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) { 2459 if (cntx) 2460 pll_state->mpllb[i] = intel_c20_sram_read(encoder, 2461 INTEL_CX0_LANE0, 2462 PHY_C20_B_MPLLB_CNTX_CFG(display, i)); 2463 else 2464 pll_state->mpllb[i] = intel_c20_sram_read(encoder, 2465 INTEL_CX0_LANE0, 2466 PHY_C20_A_MPLLB_CNTX_CFG(display, i)); 2467 } 2468 } else { 2469 /* MPLLA configuration */ 2470 for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) { 2471 if (cntx) 2472 pll_state->mplla[i] = intel_c20_sram_read(encoder, 2473 INTEL_CX0_LANE0, 2474 PHY_C20_B_MPLLA_CNTX_CFG(display, i)); 2475 else 2476 pll_state->mplla[i] = intel_c20_sram_read(encoder, 2477 INTEL_CX0_LANE0, 2478 PHY_C20_A_MPLLA_CNTX_CFG(display, i)); 2479 } 2480 } 2481 2482 pll_state->clock = intel_c20pll_calc_port_clock(encoder, pll_state); 2483 2484 intel_cx0_phy_transaction_end(encoder, wakeref); 2485 } 2486 2487 static void intel_c20pll_dump_hw_state(struct intel_display *display, 2488 const struct intel_c20pll_state *hw_state) 2489 { 2490 int i; 2491 2492 drm_dbg_kms(display->drm, "c20pll_hw_state:\n"); 2493 drm_dbg_kms(display->drm, 2494 "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n", 2495 hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]); 2496 drm_dbg_kms(display->drm, 2497 "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n", 2498 hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]); 2499 2500 if (intel_c20phy_use_mpllb(hw_state)) { 2501 for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++) 2502 drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i, 2503 hw_state->mpllb[i]); 2504 } else { 2505 for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++) 2506 drm_dbg_kms(display->drm, "mplla[%d] = 0x%.4x\n", i, 2507 hw_state->mplla[i]); 2508 } 2509 } 2510 2511 void intel_cx0pll_dump_hw_state(struct intel_display *display, 2512 const struct intel_cx0pll_state *hw_state) 2513 { 2514 if (hw_state->use_c10) 2515 intel_c10pll_dump_hw_state(display, &hw_state->c10); 2516 else 2517 intel_c20pll_dump_hw_state(display, &hw_state->c20); 2518 } 2519 2520 static u8 intel_c20_get_dp_rate(u32 clock) 2521 { 2522 switch (clock) { 2523 case 162000: /* 1.62 Gbps DP1.4 */ 2524 return 0; 2525 case 270000: /* 2.7 Gbps DP1.4 */ 2526 return 1; 2527 case 540000: /* 5.4 Gbps DP 1.4 */ 2528 return 2; 2529 case 810000: /* 8.1 Gbps DP1.4 */ 2530 return 3; 2531 case 216000: /* 2.16 Gbps eDP */ 2532 return 4; 2533 case 243000: /* 2.43 Gbps eDP */ 2534 return 5; 2535 case 324000: /* 3.24 Gbps eDP */ 2536 return 6; 2537 case 432000: /* 4.32 Gbps eDP */ 2538 return 7; 2539 case 1000000: /* 10 Gbps DP2.0 */ 2540 return 8; 2541 case 1350000: /* 13.5 Gbps DP2.0 */ 2542 return 9; 2543 case 2000000: /* 20 Gbps DP2.0 */ 2544 return 10; 2545 case 648000: /* 6.48 Gbps eDP*/ 2546 return 11; 2547 case 675000: /* 6.75 Gbps eDP*/ 2548 return 12; 2549 default: 2550 MISSING_CASE(clock); 2551 return 0; 2552 } 2553 } 2554 2555 static u8 intel_c20_get_hdmi_rate(u32 clock) 2556 { 2557 if (clock >= 25175 && clock <= 600000) 2558 return 0; 2559 2560 switch (clock) { 2561 case 300000: /* 3 Gbps */ 2562 case 600000: /* 6 Gbps */ 2563 case 1200000: /* 12 Gbps */ 2564 return 1; 2565 case 800000: /* 8 Gbps */ 2566 return 2; 2567 case 1000000: /* 10 Gbps */ 2568 return 3; 2569 default: 2570 MISSING_CASE(clock); 2571 return 0; 2572 } 2573 } 2574 2575 static bool is_dp2(u32 clock) 2576 { 2577 /* DP2.0 clock rates */ 2578 if (clock == 1000000 || clock == 1350000 || clock == 2000000) 2579 return true; 2580 2581 return false; 2582 } 2583 2584 static bool is_hdmi_frl(u32 clock) 2585 { 2586 switch (clock) { 2587 case 300000: /* 3 Gbps */ 2588 case 600000: /* 6 Gbps */ 2589 case 800000: /* 8 Gbps */ 2590 case 1000000: /* 10 Gbps */ 2591 case 1200000: /* 12 Gbps */ 2592 return true; 2593 default: 2594 return false; 2595 } 2596 } 2597 2598 static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) 2599 { 2600 struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); 2601 2602 /* banks should not be cleared for DPALT/USB4/TBT modes */ 2603 /* TODO: optimize re-calibration in legacy mode */ 2604 return intel_tc_port_in_legacy_mode(intel_dig_port); 2605 } 2606 2607 static int intel_get_c20_custom_width(u32 clock, bool dp) 2608 { 2609 if (dp && is_dp2(clock)) 2610 return 2; 2611 else if (is_hdmi_frl(clock)) 2612 return 1; 2613 else 2614 return 0; 2615 } 2616 2617 static void intel_c20_pll_program(struct intel_display *display, 2618 struct intel_encoder *encoder, 2619 const struct intel_c20pll_state *pll_state, 2620 bool is_dp, int port_clock) 2621 { 2622 u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); 2623 bool cntx; 2624 int i; 2625 2626 /* 1. Read current context selection */ 2627 cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0); 2628 2629 /* 2630 * 2. If there is a protocol switch from HDMI to DP or vice versa, clear 2631 * the lane #0 MPLLB CAL_DONE_BANK DP2.0 10G and 20G rates enable MPLLA. 2632 * Protocol switch is only applicable for MPLLA 2633 */ 2634 if (intel_c20_protocol_switch_valid(encoder)) { 2635 for (i = 0; i < 4; i++) 2636 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(i), 0); 2637 usleep_range(4000, 4100); 2638 } 2639 2640 /* 3. Write SRAM configuration context. If A in use, write configuration to B context */ 2641 /* 3.1 Tx configuration */ 2642 for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { 2643 if (cntx) 2644 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2645 PHY_C20_A_TX_CNTX_CFG(display, i), 2646 pll_state->tx[i]); 2647 else 2648 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2649 PHY_C20_B_TX_CNTX_CFG(display, i), 2650 pll_state->tx[i]); 2651 } 2652 2653 /* 3.2 common configuration */ 2654 for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) { 2655 if (cntx) 2656 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2657 PHY_C20_A_CMN_CNTX_CFG(display, i), 2658 pll_state->cmn[i]); 2659 else 2660 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2661 PHY_C20_B_CMN_CNTX_CFG(display, i), 2662 pll_state->cmn[i]); 2663 } 2664 2665 /* 3.3 mpllb or mplla configuration */ 2666 if (intel_c20phy_use_mpllb(pll_state)) { 2667 for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) { 2668 if (cntx) 2669 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2670 PHY_C20_A_MPLLB_CNTX_CFG(display, i), 2671 pll_state->mpllb[i]); 2672 else 2673 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2674 PHY_C20_B_MPLLB_CNTX_CFG(display, i), 2675 pll_state->mpllb[i]); 2676 } 2677 } else { 2678 for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) { 2679 if (cntx) 2680 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2681 PHY_C20_A_MPLLA_CNTX_CFG(display, i), 2682 pll_state->mplla[i]); 2683 else 2684 intel_c20_sram_write(encoder, INTEL_CX0_LANE0, 2685 PHY_C20_B_MPLLA_CNTX_CFG(display, i), 2686 pll_state->mplla[i]); 2687 } 2688 } 2689 2690 /* 4. Program custom width to match the link protocol */ 2691 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH, 2692 PHY_C20_CUSTOM_WIDTH_MASK, 2693 PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(port_clock, is_dp)), 2694 MB_WRITE_COMMITTED); 2695 2696 /* 5. For DP or 6. For HDMI */ 2697 if (is_dp) { 2698 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, 2699 BIT(6) | PHY_C20_CUSTOM_SERDES_MASK, 2700 BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(port_clock)), 2701 MB_WRITE_COMMITTED); 2702 } else { 2703 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, 2704 BIT(7) | PHY_C20_CUSTOM_SERDES_MASK, 2705 is_hdmi_frl(port_clock) ? BIT(7) : 0, 2706 MB_WRITE_COMMITTED); 2707 2708 intel_cx0_write(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, 2709 intel_c20_get_hdmi_rate(port_clock), 2710 MB_WRITE_COMMITTED); 2711 } 2712 2713 /* 2714 * 7. Write Vendor specific registers to toggle context setting to load 2715 * the updated programming toggle context bit 2716 */ 2717 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, 2718 BIT(0), cntx ? 0 : 1, MB_WRITE_COMMITTED); 2719 } 2720 2721 static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, 2722 const struct intel_c10pll_state *pll_state) 2723 { 2724 unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1; 2725 unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400; 2726 int tmpclk = 0; 2727 2728 if (pll_state->pll[0] & C10_PLL0_FRACEN) { 2729 frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11]; 2730 frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13]; 2731 frac_den = pll_state->pll[10] << 8 | pll_state->pll[9]; 2732 } 2733 2734 multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 | 2735 pll_state->pll[2]) / 2 + 16; 2736 2737 tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]); 2738 hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]); 2739 2740 tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) + 2741 DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den), 2742 10 << (tx_clk_div + 16)); 2743 tmpclk *= (hdmi_div ? 2 : 1); 2744 2745 return tmpclk; 2746 } 2747 2748 static void intel_program_port_clock_ctl(struct intel_encoder *encoder, 2749 const struct intel_cx0pll_state *pll_state, 2750 bool is_dp, int port_clock, 2751 bool lane_reversal) 2752 { 2753 struct intel_display *display = to_intel_display(encoder); 2754 u32 val = 0; 2755 2756 intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, encoder->port), 2757 XELPDP_PORT_REVERSAL, 2758 lane_reversal ? XELPDP_PORT_REVERSAL : 0); 2759 2760 if (lane_reversal) 2761 val |= XELPDP_LANE1_PHY_CLOCK_SELECT; 2762 2763 val |= XELPDP_FORWARD_CLOCK_UNGATE; 2764 2765 if (!is_dp && is_hdmi_frl(port_clock)) 2766 val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_DIV18CLK); 2767 else 2768 val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK); 2769 2770 /* TODO: HDMI FRL */ 2771 /* DP2.0 10G and 20G rates enable MPLLA*/ 2772 if (port_clock == 1000000 || port_clock == 2000000) 2773 val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0; 2774 else 2775 val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0; 2776 2777 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 2778 XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE | 2779 XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_SSC_ENABLE_PLLA | 2780 XELPDP_SSC_ENABLE_PLLB, val); 2781 } 2782 2783 static u32 intel_cx0_get_powerdown_update(u8 lane_mask) 2784 { 2785 u32 val = 0; 2786 int lane = 0; 2787 2788 for_each_cx0_lane_in_mask(lane_mask, lane) 2789 val |= XELPDP_LANE_POWERDOWN_UPDATE(lane); 2790 2791 return val; 2792 } 2793 2794 static u32 intel_cx0_get_powerdown_state(u8 lane_mask, u8 state) 2795 { 2796 u32 val = 0; 2797 int lane = 0; 2798 2799 for_each_cx0_lane_in_mask(lane_mask, lane) 2800 val |= XELPDP_LANE_POWERDOWN_NEW_STATE(lane, state); 2801 2802 return val; 2803 } 2804 2805 static void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder, 2806 u8 lane_mask, u8 state) 2807 { 2808 struct intel_display *display = to_intel_display(encoder); 2809 enum port port = encoder->port; 2810 enum phy phy = intel_encoder_to_phy(encoder); 2811 i915_reg_t buf_ctl2_reg = XELPDP_PORT_BUF_CTL2(display, port); 2812 int lane; 2813 2814 intel_de_rmw(display, buf_ctl2_reg, 2815 intel_cx0_get_powerdown_state(INTEL_CX0_BOTH_LANES, XELPDP_LANE_POWERDOWN_NEW_STATE_MASK), 2816 intel_cx0_get_powerdown_state(lane_mask, state)); 2817 2818 /* Wait for pending transactions.*/ 2819 for_each_cx0_lane_in_mask(lane_mask, lane) 2820 if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 2821 XELPDP_PORT_M2P_TRANSACTION_PENDING, 2822 XELPDP_MSGBUS_TIMEOUT_SLOW)) { 2823 drm_dbg_kms(display->drm, 2824 "PHY %c Timeout waiting for previous transaction to complete. Reset the bus.\n", 2825 phy_name(phy)); 2826 intel_cx0_bus_reset(encoder, lane); 2827 } 2828 2829 intel_de_rmw(display, buf_ctl2_reg, 2830 intel_cx0_get_powerdown_update(INTEL_CX0_BOTH_LANES), 2831 intel_cx0_get_powerdown_update(lane_mask)); 2832 2833 /* Update Timeout Value */ 2834 if (intel_de_wait_custom(display, buf_ctl2_reg, 2835 intel_cx0_get_powerdown_update(lane_mask), 0, 2836 XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 0, NULL)) 2837 drm_warn(display->drm, 2838 "PHY %c failed to bring out of Lane reset after %dus.\n", 2839 phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US); 2840 } 2841 2842 static void intel_cx0_setup_powerdown(struct intel_encoder *encoder) 2843 { 2844 struct intel_display *display = to_intel_display(encoder); 2845 enum port port = encoder->port; 2846 2847 intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), 2848 XELPDP_POWER_STATE_READY_MASK, 2849 XELPDP_POWER_STATE_READY(CX0_P2_STATE_READY)); 2850 intel_de_rmw(display, XELPDP_PORT_BUF_CTL3(display, port), 2851 XELPDP_POWER_STATE_ACTIVE_MASK | 2852 XELPDP_PLL_LANE_STAGGERING_DELAY_MASK, 2853 XELPDP_POWER_STATE_ACTIVE(CX0_P0_STATE_ACTIVE) | 2854 XELPDP_PLL_LANE_STAGGERING_DELAY(0)); 2855 } 2856 2857 static u32 intel_cx0_get_pclk_refclk_request(u8 lane_mask) 2858 { 2859 u32 val = 0; 2860 int lane = 0; 2861 2862 for_each_cx0_lane_in_mask(lane_mask, lane) 2863 val |= XELPDP_LANE_PCLK_REFCLK_REQUEST(lane); 2864 2865 return val; 2866 } 2867 2868 static u32 intel_cx0_get_pclk_refclk_ack(u8 lane_mask) 2869 { 2870 u32 val = 0; 2871 int lane = 0; 2872 2873 for_each_cx0_lane_in_mask(lane_mask, lane) 2874 val |= XELPDP_LANE_PCLK_REFCLK_ACK(lane); 2875 2876 return val; 2877 } 2878 2879 static void intel_cx0_phy_lane_reset(struct intel_encoder *encoder, 2880 bool lane_reversal) 2881 { 2882 struct intel_display *display = to_intel_display(encoder); 2883 enum port port = encoder->port; 2884 enum phy phy = intel_encoder_to_phy(encoder); 2885 u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); 2886 u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 : INTEL_CX0_LANE0; 2887 u32 lane_pipe_reset = owned_lane_mask == INTEL_CX0_BOTH_LANES 2888 ? XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1) 2889 : XELPDP_LANE_PIPE_RESET(0); 2890 u32 lane_phy_current_status = owned_lane_mask == INTEL_CX0_BOTH_LANES 2891 ? (XELPDP_LANE_PHY_CURRENT_STATUS(0) | 2892 XELPDP_LANE_PHY_CURRENT_STATUS(1)) 2893 : XELPDP_LANE_PHY_CURRENT_STATUS(0); 2894 2895 if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL1(display, port), 2896 XELPDP_PORT_BUF_SOC_PHY_READY, 2897 XELPDP_PORT_BUF_SOC_PHY_READY, 2898 XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US, 0, NULL)) 2899 drm_warn(display->drm, 2900 "PHY %c failed to bring out of SOC reset after %dus.\n", 2901 phy_name(phy), XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US); 2902 2903 intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_pipe_reset, 2904 lane_pipe_reset); 2905 2906 if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port), 2907 lane_phy_current_status, lane_phy_current_status, 2908 XELPDP_PORT_RESET_START_TIMEOUT_US, 0, NULL)) 2909 drm_warn(display->drm, 2910 "PHY %c failed to bring out of Lane reset after %dus.\n", 2911 phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US); 2912 2913 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 2914 intel_cx0_get_pclk_refclk_request(owned_lane_mask), 2915 intel_cx0_get_pclk_refclk_request(lane_mask)); 2916 2917 if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, port), 2918 intel_cx0_get_pclk_refclk_ack(owned_lane_mask), 2919 intel_cx0_get_pclk_refclk_ack(lane_mask), 2920 XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL)) 2921 drm_warn(display->drm, 2922 "PHY %c failed to request refclk after %dus.\n", 2923 phy_name(phy), XELPDP_REFCLK_ENABLE_TIMEOUT_US); 2924 2925 intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, 2926 CX0_P2_STATE_RESET); 2927 intel_cx0_setup_powerdown(encoder); 2928 2929 intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_pipe_reset, 0); 2930 2931 if (intel_de_wait_for_clear(display, XELPDP_PORT_BUF_CTL2(display, port), 2932 lane_phy_current_status, 2933 XELPDP_PORT_RESET_END_TIMEOUT)) 2934 drm_warn(display->drm, 2935 "PHY %c failed to bring out of Lane reset after %dms.\n", 2936 phy_name(phy), XELPDP_PORT_RESET_END_TIMEOUT); 2937 } 2938 2939 static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_count, 2940 bool lane_reversal) 2941 { 2942 int i; 2943 u8 disables; 2944 bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder)); 2945 u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); 2946 2947 if (intel_encoder_is_c10phy(encoder)) 2948 intel_cx0_rmw(encoder, owned_lane_mask, 2949 PHY_C10_VDR_CONTROL(1), 0, 2950 C10_VDR_CTRL_MSGBUS_ACCESS, 2951 MB_WRITE_COMMITTED); 2952 2953 if (lane_reversal) 2954 disables = REG_GENMASK8(3, 0) >> lane_count; 2955 else 2956 disables = REG_GENMASK8(3, 0) << lane_count; 2957 2958 if (dp_alt_mode && lane_count == 1) { 2959 disables &= ~REG_GENMASK8(1, 0); 2960 disables |= REG_FIELD_PREP8(REG_GENMASK8(1, 0), 0x1); 2961 } 2962 2963 for (i = 0; i < 4; i++) { 2964 int tx = i % 2 + 1; 2965 u8 lane_mask = i < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1; 2966 2967 if (!(owned_lane_mask & lane_mask)) 2968 continue; 2969 2970 intel_cx0_rmw(encoder, lane_mask, PHY_CX0_TX_CONTROL(tx, 2), 2971 CONTROL2_DISABLE_SINGLE_TX, 2972 disables & BIT(i) ? CONTROL2_DISABLE_SINGLE_TX : 0, 2973 MB_WRITE_COMMITTED); 2974 } 2975 2976 if (intel_encoder_is_c10phy(encoder)) 2977 intel_cx0_rmw(encoder, owned_lane_mask, 2978 PHY_C10_VDR_CONTROL(1), 0, 2979 C10_VDR_CTRL_UPDATE_CFG, 2980 MB_WRITE_COMMITTED); 2981 } 2982 2983 static u32 intel_cx0_get_pclk_pll_request(u8 lane_mask) 2984 { 2985 u32 val = 0; 2986 int lane = 0; 2987 2988 for_each_cx0_lane_in_mask(lane_mask, lane) 2989 val |= XELPDP_LANE_PCLK_PLL_REQUEST(lane); 2990 2991 return val; 2992 } 2993 2994 static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask) 2995 { 2996 u32 val = 0; 2997 int lane = 0; 2998 2999 for_each_cx0_lane_in_mask(lane_mask, lane) 3000 val |= XELPDP_LANE_PCLK_PLL_ACK(lane); 3001 3002 return val; 3003 } 3004 3005 static void __intel_cx0pll_enable(struct intel_encoder *encoder, 3006 const struct intel_cx0pll_state *pll_state, 3007 bool is_dp, int port_clock, int lane_count) 3008 { 3009 struct intel_display *display = to_intel_display(encoder); 3010 enum phy phy = intel_encoder_to_phy(encoder); 3011 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3012 bool lane_reversal = dig_port->lane_reversal; 3013 u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 : 3014 INTEL_CX0_LANE0; 3015 intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder); 3016 3017 /* 3018 * 1. Program PORT_CLOCK_CTL REGISTER to configure 3019 * clock muxes, gating and SSC 3020 */ 3021 intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal); 3022 3023 /* 2. Bring PHY out of reset. */ 3024 intel_cx0_phy_lane_reset(encoder, lane_reversal); 3025 3026 /* 3027 * 3. Change Phy power state to Ready. 3028 * TODO: For DP alt mode use only one lane. 3029 */ 3030 intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, 3031 CX0_P2_STATE_READY); 3032 3033 /* 3034 * 4. Program PORT_MSGBUS_TIMER register's Message Bus Timer field to 0xA000. 3035 * (This is done inside intel_cx0_phy_transaction_begin(), since we would need 3036 * the right timer thresholds for readouts too.) 3037 */ 3038 3039 /* 5. Program PHY internal PLL internal registers. */ 3040 if (intel_encoder_is_c10phy(encoder)) 3041 intel_c10_pll_program(display, encoder, &pll_state->c10); 3042 else 3043 intel_c20_pll_program(display, encoder, &pll_state->c20, is_dp, port_clock); 3044 3045 /* 3046 * 6. Program the enabled and disabled owned PHY lane 3047 * transmitters over message bus 3048 */ 3049 intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal); 3050 3051 /* 3052 * 7. Follow the Display Voltage Frequency Switching - Sequence 3053 * Before Frequency Change. We handle this step in bxt_set_cdclk(). 3054 */ 3055 3056 /* 3057 * 8. Program DDI_CLK_VALFREQ to match intended DDI 3058 * clock frequency. 3059 */ 3060 intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock); 3061 3062 /* 3063 * 9. Set PORT_CLOCK_CTL register PCLK PLL Request 3064 * LN<Lane for maxPCLK> to "1" to enable PLL. 3065 */ 3066 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3067 intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES), 3068 intel_cx0_get_pclk_pll_request(maxpclk_lane)); 3069 3070 /* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */ 3071 if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3072 intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES), 3073 intel_cx0_get_pclk_pll_ack(maxpclk_lane), 3074 XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, 0, NULL)) 3075 drm_warn(display->drm, "Port %c PLL not locked after %dus.\n", 3076 phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US); 3077 3078 /* 3079 * 11. Follow the Display Voltage Frequency Switching Sequence After 3080 * Frequency Change. We handle this step in bxt_set_cdclk(). 3081 */ 3082 3083 /* TODO: enable TBT-ALT mode */ 3084 intel_cx0_phy_transaction_end(encoder, wakeref); 3085 } 3086 3087 static void intel_cx0pll_enable(struct intel_encoder *encoder, 3088 const struct intel_crtc_state *crtc_state) 3089 { 3090 __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll, 3091 intel_crtc_has_dp_encoder(crtc_state), 3092 crtc_state->port_clock, crtc_state->lane_count); 3093 } 3094 3095 int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) 3096 { 3097 struct intel_display *display = to_intel_display(encoder); 3098 u32 clock, val; 3099 3100 val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)); 3101 3102 clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val); 3103 3104 drm_WARN_ON(display->drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE)); 3105 drm_WARN_ON(display->drm, !(val & XELPDP_TBT_CLOCK_REQUEST)); 3106 drm_WARN_ON(display->drm, !(val & XELPDP_TBT_CLOCK_ACK)); 3107 3108 switch (clock) { 3109 case XELPDP_DDI_CLOCK_SELECT_TBT_162: 3110 return 162000; 3111 case XELPDP_DDI_CLOCK_SELECT_TBT_270: 3112 return 270000; 3113 case XELPDP_DDI_CLOCK_SELECT_TBT_540: 3114 return 540000; 3115 case XELPDP_DDI_CLOCK_SELECT_TBT_810: 3116 return 810000; 3117 case XELPDP_DDI_CLOCK_SELECT_TBT_312_5: 3118 return 1000000; 3119 case XELPDP_DDI_CLOCK_SELECT_TBT_625: 3120 return 2000000; 3121 default: 3122 MISSING_CASE(clock); 3123 return 162000; 3124 } 3125 } 3126 3127 static int intel_mtl_tbt_clock_select(struct intel_display *display, 3128 int clock) 3129 { 3130 switch (clock) { 3131 case 162000: 3132 return XELPDP_DDI_CLOCK_SELECT_TBT_162; 3133 case 270000: 3134 return XELPDP_DDI_CLOCK_SELECT_TBT_270; 3135 case 540000: 3136 return XELPDP_DDI_CLOCK_SELECT_TBT_540; 3137 case 810000: 3138 return XELPDP_DDI_CLOCK_SELECT_TBT_810; 3139 case 1000000: 3140 if (DISPLAY_VER(display) < 30) { 3141 drm_WARN_ON(display->drm, "UHBR10 not supported for the platform\n"); 3142 return XELPDP_DDI_CLOCK_SELECT_TBT_162; 3143 } 3144 return XELPDP_DDI_CLOCK_SELECT_TBT_312_5; 3145 case 2000000: 3146 if (DISPLAY_VER(display) < 30) { 3147 drm_WARN_ON(display->drm, "UHBR20 not supported for the platform\n"); 3148 return XELPDP_DDI_CLOCK_SELECT_TBT_162; 3149 } 3150 return XELPDP_DDI_CLOCK_SELECT_TBT_625; 3151 default: 3152 MISSING_CASE(clock); 3153 return XELPDP_DDI_CLOCK_SELECT_TBT_162; 3154 } 3155 } 3156 3157 static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, 3158 const struct intel_crtc_state *crtc_state) 3159 { 3160 struct intel_display *display = to_intel_display(encoder); 3161 enum phy phy = intel_encoder_to_phy(encoder); 3162 u32 val = 0; 3163 u32 mask; 3164 3165 /* 3166 * 1. Program PORT_CLOCK_CTL REGISTER to configure 3167 * clock muxes, gating and SSC 3168 */ 3169 3170 mask = XELPDP_DDI_CLOCK_SELECT_MASK(display); 3171 val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, 3172 intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); 3173 3174 mask |= XELPDP_FORWARD_CLOCK_UNGATE; 3175 val |= XELPDP_FORWARD_CLOCK_UNGATE; 3176 3177 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3178 mask, val); 3179 3180 /* 2. Read back PORT_CLOCK_CTL REGISTER */ 3181 val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)); 3182 3183 /* 3184 * 3. Follow the Display Voltage Frequency Switching - Sequence 3185 * Before Frequency Change. We handle this step in bxt_set_cdclk(). 3186 */ 3187 3188 /* 3189 * 4. Set PORT_CLOCK_CTL register TBT CLOCK Request to "1" to enable PLL. 3190 */ 3191 val |= XELPDP_TBT_CLOCK_REQUEST; 3192 intel_de_write(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), val); 3193 3194 /* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */ 3195 if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3196 XELPDP_TBT_CLOCK_ACK, 3197 XELPDP_TBT_CLOCK_ACK, 3198 100, 0, NULL)) 3199 drm_warn(display->drm, 3200 "[ENCODER:%d:%s][%c] PHY PLL not locked after 100us.\n", 3201 encoder->base.base.id, encoder->base.name, phy_name(phy)); 3202 3203 /* 3204 * 6. Follow the Display Voltage Frequency Switching Sequence After 3205 * Frequency Change. We handle this step in bxt_set_cdclk(). 3206 */ 3207 3208 /* 3209 * 7. Program DDI_CLK_VALFREQ to match intended DDI 3210 * clock frequency. 3211 */ 3212 intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), 3213 crtc_state->port_clock); 3214 } 3215 3216 void intel_mtl_pll_enable(struct intel_encoder *encoder, 3217 const struct intel_crtc_state *crtc_state) 3218 { 3219 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3220 3221 if (intel_tc_port_in_tbt_alt_mode(dig_port)) 3222 intel_mtl_tbt_pll_enable(encoder, crtc_state); 3223 else 3224 intel_cx0pll_enable(encoder, crtc_state); 3225 } 3226 3227 static u8 cx0_power_control_disable_val(struct intel_encoder *encoder) 3228 { 3229 struct intel_display *display = to_intel_display(encoder); 3230 3231 if (intel_encoder_is_c10phy(encoder)) 3232 return CX0_P2PG_STATE_DISABLE; 3233 3234 if ((display->platform.battlemage && encoder->port == PORT_A) || 3235 (DISPLAY_VER(display) >= 30 && encoder->type == INTEL_OUTPUT_EDP)) 3236 return CX0_P2PG_STATE_DISABLE; 3237 3238 return CX0_P4PG_STATE_DISABLE; 3239 } 3240 3241 static void intel_cx0pll_disable(struct intel_encoder *encoder) 3242 { 3243 struct intel_display *display = to_intel_display(encoder); 3244 enum phy phy = intel_encoder_to_phy(encoder); 3245 intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder); 3246 3247 /* 1. Change owned PHY lane power to Disable state. */ 3248 intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, 3249 cx0_power_control_disable_val(encoder)); 3250 3251 /* 3252 * 2. Follow the Display Voltage Frequency Switching Sequence Before 3253 * Frequency Change. We handle this step in bxt_set_cdclk(). 3254 */ 3255 3256 /* 3257 * 3. Set PORT_CLOCK_CTL register PCLK PLL Request LN<Lane for maxPCLK> 3258 * to "0" to disable PLL. 3259 */ 3260 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3261 intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES) | 3262 intel_cx0_get_pclk_refclk_request(INTEL_CX0_BOTH_LANES), 0); 3263 3264 /* 4. Program DDI_CLK_VALFREQ to 0. */ 3265 intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), 0); 3266 3267 /* 3268 * 5. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK**> == "0". 3269 */ 3270 if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3271 intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES) | 3272 intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES), 0, 3273 XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US, 0, NULL)) 3274 drm_warn(display->drm, 3275 "Port %c PLL not unlocked after %dus.\n", 3276 phy_name(phy), XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US); 3277 3278 /* 3279 * 6. Follow the Display Voltage Frequency Switching Sequence After 3280 * Frequency Change. We handle this step in bxt_set_cdclk(). 3281 */ 3282 3283 /* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */ 3284 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3285 XELPDP_DDI_CLOCK_SELECT_MASK(display), 0); 3286 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3287 XELPDP_FORWARD_CLOCK_UNGATE, 0); 3288 3289 intel_cx0_phy_transaction_end(encoder, wakeref); 3290 } 3291 3292 static bool intel_cx0_pll_is_enabled(struct intel_encoder *encoder) 3293 { 3294 struct intel_display *display = to_intel_display(encoder); 3295 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3296 u8 lane = dig_port->lane_reversal ? INTEL_CX0_LANE1 : INTEL_CX0_LANE0; 3297 3298 return intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)) & 3299 intel_cx0_get_pclk_pll_request(lane); 3300 } 3301 3302 static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) 3303 { 3304 struct intel_display *display = to_intel_display(encoder); 3305 enum phy phy = intel_encoder_to_phy(encoder); 3306 3307 /* 3308 * 1. Follow the Display Voltage Frequency Switching Sequence Before 3309 * Frequency Change. We handle this step in bxt_set_cdclk(). 3310 */ 3311 3312 /* 3313 * 2. Set PORT_CLOCK_CTL register TBT CLOCK Request to "0" to disable PLL. 3314 */ 3315 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3316 XELPDP_TBT_CLOCK_REQUEST, 0); 3317 3318 /* 3. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "0". */ 3319 if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3320 XELPDP_TBT_CLOCK_ACK, 0, 10, 0, NULL)) 3321 drm_warn(display->drm, 3322 "[ENCODER:%d:%s][%c] PHY PLL not unlocked after 10us.\n", 3323 encoder->base.base.id, encoder->base.name, phy_name(phy)); 3324 3325 /* 3326 * 4. Follow the Display Voltage Frequency Switching Sequence After 3327 * Frequency Change. We handle this step in bxt_set_cdclk(). 3328 */ 3329 3330 /* 3331 * 5. Program PORT CLOCK CTRL register to disable and gate clocks 3332 */ 3333 intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 3334 XELPDP_DDI_CLOCK_SELECT_MASK(display) | 3335 XELPDP_FORWARD_CLOCK_UNGATE, 0); 3336 3337 /* 6. Program DDI_CLK_VALFREQ to 0. */ 3338 intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), 0); 3339 } 3340 3341 void intel_mtl_pll_disable(struct intel_encoder *encoder) 3342 { 3343 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3344 3345 if (intel_tc_port_in_tbt_alt_mode(dig_port)) 3346 intel_mtl_tbt_pll_disable(encoder); 3347 else 3348 intel_cx0pll_disable(encoder); 3349 } 3350 3351 enum icl_port_dpll_id 3352 intel_mtl_port_pll_type(struct intel_encoder *encoder, 3353 const struct intel_crtc_state *crtc_state) 3354 { 3355 struct intel_display *display = to_intel_display(encoder); 3356 u32 val, clock; 3357 3358 /* 3359 * TODO: Determine the PLL type from the SW state, once MTL PLL 3360 * handling is done via the standard shared DPLL framework. 3361 */ 3362 val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)); 3363 clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val); 3364 3365 if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK || 3366 clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK) 3367 return ICL_PORT_DPLL_MG_PHY; 3368 else 3369 return ICL_PORT_DPLL_DEFAULT; 3370 } 3371 3372 static void intel_c10pll_state_verify(const struct intel_crtc_state *state, 3373 struct intel_crtc *crtc, 3374 struct intel_encoder *encoder, 3375 struct intel_c10pll_state *mpllb_hw_state) 3376 { 3377 struct intel_display *display = to_intel_display(state); 3378 const struct intel_c10pll_state *mpllb_sw_state = &state->dpll_hw_state.cx0pll.c10; 3379 int i; 3380 3381 for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) { 3382 u8 expected = mpllb_sw_state->pll[i]; 3383 3384 INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->pll[i] != expected, 3385 "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)", 3386 crtc->base.base.id, crtc->base.name, i, 3387 expected, mpllb_hw_state->pll[i]); 3388 } 3389 3390 INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->tx != mpllb_sw_state->tx, 3391 "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)", 3392 crtc->base.base.id, crtc->base.name, 3393 mpllb_sw_state->tx, mpllb_hw_state->tx); 3394 3395 INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->cmn != mpllb_sw_state->cmn, 3396 "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)", 3397 crtc->base.base.id, crtc->base.name, 3398 mpllb_sw_state->cmn, mpllb_hw_state->cmn); 3399 } 3400 3401 void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, 3402 struct intel_cx0pll_state *pll_state) 3403 { 3404 pll_state->use_c10 = false; 3405 3406 pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); 3407 if (pll_state->tbt_mode) 3408 return; 3409 3410 if (intel_encoder_is_c10phy(encoder)) { 3411 intel_c10pll_readout_hw_state(encoder, &pll_state->c10); 3412 pll_state->use_c10 = true; 3413 } else { 3414 intel_c20pll_readout_hw_state(encoder, &pll_state->c20); 3415 } 3416 } 3417 3418 static bool mtl_compare_hw_state_c10(const struct intel_c10pll_state *a, 3419 const struct intel_c10pll_state *b) 3420 { 3421 if (a->tx != b->tx) 3422 return false; 3423 3424 if (a->cmn != b->cmn) 3425 return false; 3426 3427 if (memcmp(&a->pll, &b->pll, sizeof(a->pll)) != 0) 3428 return false; 3429 3430 return true; 3431 } 3432 3433 static bool mtl_compare_hw_state_c20(const struct intel_c20pll_state *a, 3434 const struct intel_c20pll_state *b) 3435 { 3436 if (memcmp(&a->tx, &b->tx, sizeof(a->tx)) != 0) 3437 return false; 3438 3439 if (memcmp(&a->cmn, &b->cmn, sizeof(a->cmn)) != 0) 3440 return false; 3441 3442 if (a->tx[0] & C20_PHY_USE_MPLLB) { 3443 if (memcmp(&a->mpllb, &b->mpllb, sizeof(a->mpllb)) != 0) 3444 return false; 3445 } else { 3446 if (memcmp(&a->mplla, &b->mplla, sizeof(a->mplla)) != 0) 3447 return false; 3448 } 3449 3450 return true; 3451 } 3452 3453 bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, 3454 const struct intel_cx0pll_state *b) 3455 { 3456 if (a->tbt_mode || b->tbt_mode) 3457 return true; 3458 3459 if (a->use_c10 != b->use_c10) 3460 return false; 3461 3462 if (a->use_c10) 3463 return mtl_compare_hw_state_c10(&a->c10, 3464 &b->c10); 3465 else 3466 return mtl_compare_hw_state_c20(&a->c20, 3467 &b->c20); 3468 } 3469 3470 int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, 3471 const struct intel_cx0pll_state *pll_state) 3472 { 3473 if (intel_encoder_is_c10phy(encoder)) 3474 return intel_c10pll_calc_port_clock(encoder, &pll_state->c10); 3475 3476 return intel_c20pll_calc_port_clock(encoder, &pll_state->c20); 3477 } 3478 3479 static void intel_c20pll_state_verify(const struct intel_crtc_state *state, 3480 struct intel_crtc *crtc, 3481 struct intel_encoder *encoder, 3482 struct intel_c20pll_state *mpll_hw_state) 3483 { 3484 struct intel_display *display = to_intel_display(state); 3485 const struct intel_c20pll_state *mpll_sw_state = &state->dpll_hw_state.cx0pll.c20; 3486 bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state); 3487 bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state); 3488 int clock = intel_c20pll_calc_port_clock(encoder, mpll_sw_state); 3489 int i; 3490 3491 INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->clock != clock, 3492 "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)", 3493 crtc->base.base.id, crtc->base.name, 3494 mpll_sw_state->clock, mpll_hw_state->clock); 3495 3496 INTEL_DISPLAY_STATE_WARN(display, sw_use_mpllb != hw_use_mpllb, 3497 "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection (expected %d, found %d)", 3498 crtc->base.base.id, crtc->base.name, 3499 sw_use_mpllb, hw_use_mpllb); 3500 3501 if (hw_use_mpllb) { 3502 for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) { 3503 INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mpllb[i] != mpll_sw_state->mpllb[i], 3504 "[CRTC:%d:%s] mismatch in C20MPLLB: Register[%d] (expected 0x%04x, found 0x%04x)", 3505 crtc->base.base.id, crtc->base.name, i, 3506 mpll_sw_state->mpllb[i], mpll_hw_state->mpllb[i]); 3507 } 3508 } else { 3509 for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) { 3510 INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mplla[i] != mpll_sw_state->mplla[i], 3511 "[CRTC:%d:%s] mismatch in C20MPLLA: Register[%d] (expected 0x%04x, found 0x%04x)", 3512 crtc->base.base.id, crtc->base.name, i, 3513 mpll_sw_state->mplla[i], mpll_hw_state->mplla[i]); 3514 } 3515 } 3516 3517 for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) { 3518 INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->tx[i] != mpll_sw_state->tx[i], 3519 "[CRTC:%d:%s] mismatch in C20: Register TX[%i] (expected 0x%04x, found 0x%04x)", 3520 crtc->base.base.id, crtc->base.name, i, 3521 mpll_sw_state->tx[i], mpll_hw_state->tx[i]); 3522 } 3523 3524 for (i = 0; i < ARRAY_SIZE(mpll_sw_state->cmn); i++) { 3525 INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->cmn[i] != mpll_sw_state->cmn[i], 3526 "[CRTC:%d:%s] mismatch in C20: Register CMN[%i] (expected 0x%04x, found 0x%04x)", 3527 crtc->base.base.id, crtc->base.name, i, 3528 mpll_sw_state->cmn[i], mpll_hw_state->cmn[i]); 3529 } 3530 } 3531 3532 void intel_cx0pll_state_verify(struct intel_atomic_state *state, 3533 struct intel_crtc *crtc) 3534 { 3535 struct intel_display *display = to_intel_display(state); 3536 const struct intel_crtc_state *new_crtc_state = 3537 intel_atomic_get_new_crtc_state(state, crtc); 3538 struct intel_encoder *encoder; 3539 struct intel_cx0pll_state mpll_hw_state = {}; 3540 3541 if (DISPLAY_VER(display) < 14) 3542 return; 3543 3544 if (!new_crtc_state->hw.active) 3545 return; 3546 3547 /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */ 3548 if (!intel_crtc_needs_modeset(new_crtc_state) && 3549 !intel_crtc_needs_fastset(new_crtc_state)) 3550 return; 3551 3552 encoder = intel_get_crtc_new_encoder(state, new_crtc_state); 3553 intel_cx0pll_readout_hw_state(encoder, &mpll_hw_state); 3554 3555 if (mpll_hw_state.tbt_mode) 3556 return; 3557 3558 if (intel_encoder_is_c10phy(encoder)) 3559 intel_c10pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c10); 3560 else 3561 intel_c20pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c20); 3562 } 3563 3564 /* 3565 * WA 14022081154 3566 * The dedicated display PHYs reset to a power state that blocks S0ix, increasing idle 3567 * system power. After a system reset (cold boot, S3/4/5, warm reset) if a dedicated 3568 * PHY is not being brought up shortly, use these steps to move the PHY to the lowest 3569 * power state to save power. For PTL the workaround is needed only for port A. Port B 3570 * is not connected. 3571 * 3572 * 1. Follow the PLL Enable Sequence, using any valid frequency such as DP 1.62 GHz. 3573 * This brings lanes out of reset and enables the PLL to allow powerdown to be moved 3574 * to the Disable state. 3575 * 2. Follow PLL Disable Sequence. This moves powerdown to the Disable state and disables the PLL. 3576 */ 3577 void intel_cx0_pll_power_save_wa(struct intel_display *display) 3578 { 3579 struct intel_encoder *encoder; 3580 3581 if (DISPLAY_VER(display) != 30) 3582 return; 3583 3584 for_each_intel_encoder(display->drm, encoder) { 3585 struct intel_cx0pll_state pll_state = {}; 3586 int port_clock = 162000; 3587 3588 if (!intel_encoder_is_dig_port(encoder)) 3589 continue; 3590 3591 if (!intel_encoder_is_c10phy(encoder)) 3592 continue; 3593 3594 if (intel_cx0_pll_is_enabled(encoder)) 3595 continue; 3596 3597 if (intel_c10pll_calc_state_from_table(encoder, 3598 mtl_c10_edp_tables, 3599 true, port_clock, 3600 &pll_state) < 0) { 3601 drm_WARN_ON(display->drm, 3602 "Unable to calc C10 state from the tables\n"); 3603 continue; 3604 } 3605 3606 drm_dbg_kms(display->drm, 3607 "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n", 3608 encoder->base.base.id, encoder->base.name); 3609 3610 __intel_cx0pll_enable(encoder, &pll_state, true, port_clock, 4); 3611 intel_cx0pll_disable(encoder); 3612 } 3613 } 3614