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