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