1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023 Intel Corporation
7 #include "intel_cx0_phy.h"
8 #include "intel_cx0_phy_regs.h"
10 #include "intel_ddi_buf_trans.h"
12 #include "intel_display_types.h"
14 #include "intel_panel.h"
15 #include "intel_psr.h"
18 #define MB_WRITE_COMMITTED true
19 #define MB_WRITE_UNCOMMITTED false
21 #define for_each_cx0_lane_in_mask(__lane_mask, __lane) \
22 for ((__lane) = 0; (__lane) < 2; (__lane)++) \
23 for_each_if((__lane_mask) & BIT(__lane))
25 #define INTEL_CX0_LANE0 BIT(0)
26 #define INTEL_CX0_LANE1 BIT(1)
27 #define INTEL_CX0_BOTH_LANES (INTEL_CX0_LANE1 | INTEL_CX0_LANE0)
29 bool intel_is_c10phy(struct drm_i915_private *i915, enum phy phy)
31 if (IS_METEORLAKE(i915) && (phy < PHY_C))
37 static int lane_mask_to_lane(u8 lane_mask)
39 if (WARN_ON((lane_mask & ~INTEL_CX0_BOTH_LANES) ||
40 hweight8(lane_mask) != 1))
43 return ilog2(lane_mask);
47 assert_dc_off(struct drm_i915_private *i915)
51 enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
52 drm_WARN_ON(&i915->drm, !enabled);
56 * Prepare HW for CX0 phy transactions.
58 * It is required that PSR and DC5/6 are disabled before any CX0 message
59 * bus transaction is executed.
61 static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
63 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
64 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
66 intel_psr_pause(intel_dp);
67 return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
70 static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
72 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
73 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
75 intel_psr_resume(intel_dp);
76 intel_display_power_put(i915, POWER_DOMAIN_DC_OFF, wakeref);
79 static void intel_clear_response_ready_flag(struct drm_i915_private *i915,
80 enum port port, int lane)
82 intel_de_rmw(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane),
83 0, XELPDP_PORT_P2M_RESPONSE_READY | XELPDP_PORT_P2M_ERROR_SET);
86 static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, int lane)
88 enum phy phy = intel_port_to_phy(i915, port);
90 intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
91 XELPDP_PORT_M2P_TRANSACTION_RESET);
93 if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
94 XELPDP_PORT_M2P_TRANSACTION_RESET,
95 XELPDP_MSGBUS_TIMEOUT_SLOW)) {
96 drm_err_once(&i915->drm, "Failed to bring PHY %c to idle.\n", phy_name(phy));
100 intel_clear_response_ready_flag(i915, port, lane);
103 static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
104 int command, int lane, u32 *val)
106 enum phy phy = intel_port_to_phy(i915, port);
108 if (__intel_de_wait_for_register(i915,
109 XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane),
110 XELPDP_PORT_P2M_RESPONSE_READY,
111 XELPDP_PORT_P2M_RESPONSE_READY,
112 XELPDP_MSGBUS_TIMEOUT_FAST_US,
113 XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
114 drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
115 phy_name(phy), *val);
119 if (*val & XELPDP_PORT_P2M_ERROR_SET) {
120 drm_dbg_kms(&i915->drm, "PHY %c Error occurred during %s command. Status: 0x%x\n", phy_name(phy),
121 command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val);
122 intel_cx0_bus_reset(i915, port, lane);
126 if (REG_FIELD_GET(XELPDP_PORT_P2M_COMMAND_TYPE_MASK, *val) != command) {
127 drm_dbg_kms(&i915->drm, "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n", phy_name(phy),
128 command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val);
129 intel_cx0_bus_reset(i915, port, lane);
136 static int __intel_cx0_read_once(struct drm_i915_private *i915, enum port port,
139 enum phy phy = intel_port_to_phy(i915, port);
143 if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
144 XELPDP_PORT_M2P_TRANSACTION_PENDING,
145 XELPDP_MSGBUS_TIMEOUT_SLOW)) {
146 drm_dbg_kms(&i915->drm,
147 "PHY %c Timeout waiting for previous transaction to complete. Reset the bus and retry.\n", phy_name(phy));
148 intel_cx0_bus_reset(i915, port, lane);
152 intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
153 XELPDP_PORT_M2P_TRANSACTION_PENDING |
154 XELPDP_PORT_M2P_COMMAND_READ |
155 XELPDP_PORT_M2P_ADDRESS(addr));
157 ack = intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_READ_ACK, lane, &val);
159 intel_cx0_bus_reset(i915, port, lane);
163 intel_clear_response_ready_flag(i915, port, lane);
165 return REG_FIELD_GET(XELPDP_PORT_P2M_DATA_MASK, val);
168 static u8 __intel_cx0_read(struct drm_i915_private *i915, enum port port,
171 enum phy phy = intel_port_to_phy(i915, port);
176 /* 3 tries is assumed to be enough to read successfully */
177 for (i = 0; i < 3; i++) {
178 status = __intel_cx0_read_once(i915, port, lane, addr);
184 drm_err_once(&i915->drm, "PHY %c Read %04x failed after %d retries.\n",
185 phy_name(phy), addr, i);
190 static u8 intel_cx0_read(struct drm_i915_private *i915, enum port port,
191 u8 lane_mask, u16 addr)
193 int lane = lane_mask_to_lane(lane_mask);
195 return __intel_cx0_read(i915, port, lane, addr);
198 static int __intel_cx0_write_once(struct drm_i915_private *i915, enum port port,
199 int lane, u16 addr, u8 data, bool committed)
201 enum phy phy = intel_port_to_phy(i915, port);
204 if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
205 XELPDP_PORT_M2P_TRANSACTION_PENDING,
206 XELPDP_MSGBUS_TIMEOUT_SLOW)) {
207 drm_dbg_kms(&i915->drm,
208 "PHY %c Timeout waiting for previous transaction to complete. Resetting the bus.\n", phy_name(phy));
209 intel_cx0_bus_reset(i915, port, lane);
213 intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
214 XELPDP_PORT_M2P_TRANSACTION_PENDING |
215 (committed ? XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED :
216 XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED) |
217 XELPDP_PORT_M2P_DATA(data) |
218 XELPDP_PORT_M2P_ADDRESS(addr));
220 if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
221 XELPDP_PORT_M2P_TRANSACTION_PENDING,
222 XELPDP_MSGBUS_TIMEOUT_SLOW)) {
223 drm_dbg_kms(&i915->drm,
224 "PHY %c Timeout waiting for write to complete. Resetting the bus.\n", phy_name(phy));
225 intel_cx0_bus_reset(i915, port, lane);
230 if (intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val) < 0) {
231 intel_cx0_bus_reset(i915, port, lane);
234 } else if ((intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)) &
235 XELPDP_PORT_P2M_ERROR_SET)) {
236 drm_dbg_kms(&i915->drm,
237 "PHY %c Error occurred during write command.\n", phy_name(phy));
238 intel_cx0_bus_reset(i915, port, lane);
242 intel_clear_response_ready_flag(i915, port, lane);
247 static void __intel_cx0_write(struct drm_i915_private *i915, enum port port,
248 int lane, u16 addr, u8 data, bool committed)
250 enum phy phy = intel_port_to_phy(i915, port);
255 /* 3 tries is assumed to be enough to write successfully */
256 for (i = 0; i < 3; i++) {
257 status = __intel_cx0_write_once(i915, port, lane, addr, data, committed);
263 drm_err_once(&i915->drm,
264 "PHY %c Write %04x failed after %d retries.\n", phy_name(phy), addr, i);
267 static void intel_cx0_write(struct drm_i915_private *i915, enum port port,
268 u8 lane_mask, u16 addr, u8 data, bool committed)
272 for_each_cx0_lane_in_mask(lane_mask, lane)
273 __intel_cx0_write(i915, port, lane, addr, data, committed);
276 static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
277 int lane, u16 addr, u8 clear, u8 set, bool committed)
281 old = __intel_cx0_read(i915, port, lane, addr);
282 val = (old & ~clear) | set;
285 __intel_cx0_write(i915, port, lane, addr, val, committed);
288 static void intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
289 u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed)
293 for_each_cx0_lane_in_mask(lane_mask, lane)
294 __intel_cx0_rmw(i915, port, lane, addr, clear, set, committed);
297 static u8 intel_c10_get_tx_vboost_lvl(const struct intel_crtc_state *crtc_state)
299 if (intel_crtc_has_dp_encoder(crtc_state)) {
300 if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
301 (crtc_state->port_clock == 540000 ||
302 crtc_state->port_clock == 810000))
311 static u8 intel_c10_get_tx_term_ctl(const struct intel_crtc_state *crtc_state)
313 if (intel_crtc_has_dp_encoder(crtc_state)) {
314 if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP) &&
315 (crtc_state->port_clock == 540000 ||
316 crtc_state->port_clock == 810000))
325 void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
326 const struct intel_crtc_state *crtc_state)
328 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
329 const struct intel_ddi_buf_trans *trans;
330 enum phy phy = intel_port_to_phy(i915, encoder->port);
331 intel_wakeref_t wakeref;
334 wakeref = intel_cx0_phy_transaction_begin(encoder);
336 trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
337 if (drm_WARN_ON_ONCE(&i915->drm, !trans)) {
338 intel_cx0_phy_transaction_end(encoder, wakeref);
342 if (intel_is_c10phy(i915, phy)) {
343 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
344 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
345 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CMN(3),
346 C10_CMN3_TXVBOOST_MASK,
347 C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)),
348 MB_WRITE_UNCOMMITTED);
349 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_TX(1),
350 C10_TX1_TERMCTL_MASK,
351 C10_TX1_TERMCTL(intel_c10_get_tx_term_ctl(crtc_state)),
355 for (ln = 0; ln < crtc_state->lane_count; ln++) {
356 int level = intel_ddi_level(encoder, crtc_state, ln);
362 intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 0),
363 C10_PHY_OVRD_LEVEL_MASK,
364 C10_PHY_OVRD_LEVEL(trans->entries[level].snps.pre_cursor),
366 intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 1),
367 C10_PHY_OVRD_LEVEL_MASK,
368 C10_PHY_OVRD_LEVEL(trans->entries[level].snps.vswing),
370 intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 2),
371 C10_PHY_OVRD_LEVEL_MASK,
372 C10_PHY_OVRD_LEVEL(trans->entries[level].snps.post_cursor),
376 /* Write Override enables in 0xD71 */
377 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_OVRD,
378 0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2,
381 if (intel_is_c10phy(i915, phy))
382 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
383 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED);
385 intel_cx0_phy_transaction_end(encoder, wakeref);
389 * Basic DP link rates with 38.4 MHz reference clock.
390 * Note: The tables below are with SSC. In non-ssc
391 * registers 0xC04 to 0xC08(pll[4] to pll[8]) will be
395 static const struct intel_c10pll_state mtl_c10_dp_rbr = {
421 static const struct intel_c10pll_state mtl_c10_edp_r216 = {
447 static const struct intel_c10pll_state mtl_c10_edp_r243 = {
473 static const struct intel_c10pll_state mtl_c10_dp_hbr1 = {
485 .pll[8] = 0x1, /* Verify */
499 static const struct intel_c10pll_state mtl_c10_edp_r324 = {
525 static const struct intel_c10pll_state mtl_c10_edp_r432 = {
551 static const struct intel_c10pll_state mtl_c10_dp_hbr2 = {
577 static const struct intel_c10pll_state mtl_c10_edp_r675 = {
603 static const struct intel_c10pll_state mtl_c10_dp_hbr3 = {
629 static const struct intel_c10pll_state * const mtl_c10_dp_tables[] = {
637 static const struct intel_c10pll_state * const mtl_c10_edp_tables[] = {
651 * HDMI link rates with 38.4 MHz reference clock.
654 static const struct intel_c10pll_state mtl_c10_hdmi_25_2 = {
680 static const struct intel_c10pll_state mtl_c10_hdmi_27_0 = {
706 static const struct intel_c10pll_state mtl_c10_hdmi_74_25 = {
732 static const struct intel_c10pll_state mtl_c10_hdmi_148_5 = {
758 static const struct intel_c10pll_state mtl_c10_hdmi_594 = {
784 /* Precomputed C10 HDMI PLL tables */
785 static const struct intel_c10pll_state mtl_c10_hdmi_27027 = {
789 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xC0, .pll[3] = 0x00, .pll[4] = 0x00,
790 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
791 .pll[10] = 0xFF, .pll[11] = 0xCC, .pll[12] = 0x9C, .pll[13] = 0xCB, .pll[14] = 0xCC,
792 .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
795 static const struct intel_c10pll_state mtl_c10_hdmi_28320 = {
799 .pll[0] = 0x04, .pll[1] = 0x00, .pll[2] = 0xCC, .pll[3] = 0x00, .pll[4] = 0x00,
800 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
801 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00,
802 .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
805 static const struct intel_c10pll_state mtl_c10_hdmi_30240 = {
809 .pll[0] = 0x04, .pll[1] = 0x00, .pll[2] = 0xDC, .pll[3] = 0x00, .pll[4] = 0x00,
810 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
811 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00,
812 .pll[15] = 0x0D, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
815 static const struct intel_c10pll_state mtl_c10_hdmi_31500 = {
819 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x62, .pll[3] = 0x00, .pll[4] = 0x00,
820 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
821 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xA0, .pll[13] = 0x00, .pll[14] = 0x00,
822 .pll[15] = 0x0C, .pll[16] = 0x09, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
825 static const struct intel_c10pll_state mtl_c10_hdmi_36000 = {
829 .pll[0] = 0xC4, .pll[1] = 0x00, .pll[2] = 0x76, .pll[3] = 0x00, .pll[4] = 0x00,
830 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
831 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x00, .pll[13] = 0x00, .pll[14] = 0x00,
832 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
835 static const struct intel_c10pll_state mtl_c10_hdmi_40000 = {
839 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x86, .pll[3] = 0x00, .pll[4] = 0x00,
840 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
841 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x55, .pll[13] = 0x55, .pll[14] = 0x55,
842 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
845 static const struct intel_c10pll_state mtl_c10_hdmi_49500 = {
849 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00,
850 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
851 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00,
852 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
855 static const struct intel_c10pll_state mtl_c10_hdmi_50000 = {
859 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xB0, .pll[3] = 0x00, .pll[4] = 0x00,
860 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
861 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x2A, .pll[13] = 0xA9, .pll[14] = 0xAA,
862 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
865 static const struct intel_c10pll_state mtl_c10_hdmi_57284 = {
869 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xCE, .pll[3] = 0x00, .pll[4] = 0x00,
870 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
871 .pll[10] = 0xFF, .pll[11] = 0x77, .pll[12] = 0x57, .pll[13] = 0x77, .pll[14] = 0x77,
872 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
875 static const struct intel_c10pll_state mtl_c10_hdmi_58000 = {
879 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD0, .pll[3] = 0x00, .pll[4] = 0x00,
880 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
881 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xD5, .pll[13] = 0x55, .pll[14] = 0x55,
882 .pll[15] = 0x0C, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
885 static const struct intel_c10pll_state mtl_c10_hdmi_65000 = {
889 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x66, .pll[3] = 0x00, .pll[4] = 0x00,
890 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
891 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xB5, .pll[13] = 0x55, .pll[14] = 0x55,
892 .pll[15] = 0x0B, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
895 static const struct intel_c10pll_state mtl_c10_hdmi_71000 = {
899 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x72, .pll[3] = 0x00, .pll[4] = 0x00,
900 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
901 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xF5, .pll[13] = 0x55, .pll[14] = 0x55,
902 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
905 static const struct intel_c10pll_state mtl_c10_hdmi_74176 = {
909 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
910 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
911 .pll[10] = 0xFF, .pll[11] = 0x44, .pll[12] = 0x44, .pll[13] = 0x44, .pll[14] = 0x44,
912 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
915 static const struct intel_c10pll_state mtl_c10_hdmi_75000 = {
919 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7C, .pll[3] = 0x00, .pll[4] = 0x00,
920 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
921 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00,
922 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
925 static const struct intel_c10pll_state mtl_c10_hdmi_78750 = {
929 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x84, .pll[3] = 0x00, .pll[4] = 0x00,
930 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
931 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x08, .pll[13] = 0x00, .pll[14] = 0x00,
932 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
935 static const struct intel_c10pll_state mtl_c10_hdmi_85500 = {
939 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x92, .pll[3] = 0x00, .pll[4] = 0x00,
940 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
941 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x10, .pll[13] = 0x00, .pll[14] = 0x00,
942 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
945 static const struct intel_c10pll_state mtl_c10_hdmi_88750 = {
949 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0x98, .pll[3] = 0x00, .pll[4] = 0x00,
950 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
951 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x72, .pll[13] = 0xA9, .pll[14] = 0xAA,
952 .pll[15] = 0x0B, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
955 static const struct intel_c10pll_state mtl_c10_hdmi_106500 = {
959 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xBC, .pll[3] = 0x00, .pll[4] = 0x00,
960 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
961 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xF0, .pll[13] = 0x00, .pll[14] = 0x00,
962 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
965 static const struct intel_c10pll_state mtl_c10_hdmi_108000 = {
969 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xC0, .pll[3] = 0x00, .pll[4] = 0x00,
970 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
971 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x80, .pll[13] = 0x00, .pll[14] = 0x00,
972 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
975 static const struct intel_c10pll_state mtl_c10_hdmi_115500 = {
979 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD0, .pll[3] = 0x00, .pll[4] = 0x00,
980 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
981 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x50, .pll[13] = 0x00, .pll[14] = 0x00,
982 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
985 static const struct intel_c10pll_state mtl_c10_hdmi_119000 = {
989 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xD6, .pll[3] = 0x00, .pll[4] = 0x00,
990 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
991 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xF5, .pll[13] = 0x55, .pll[14] = 0x55,
992 .pll[15] = 0x0B, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
995 static const struct intel_c10pll_state mtl_c10_hdmi_135000 = {
999 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x6C, .pll[3] = 0x00, .pll[4] = 0x00,
1000 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1001 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x50, .pll[13] = 0x00, .pll[14] = 0x00,
1002 .pll[15] = 0x0A, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
1005 static const struct intel_c10pll_state mtl_c10_hdmi_138500 = {
1009 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x70, .pll[3] = 0x00, .pll[4] = 0x00,
1010 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1011 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x22, .pll[13] = 0xA9, .pll[14] = 0xAA,
1012 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1015 static const struct intel_c10pll_state mtl_c10_hdmi_147160 = {
1019 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x78, .pll[3] = 0x00, .pll[4] = 0x00,
1020 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1021 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0xA5, .pll[13] = 0x55, .pll[14] = 0x55,
1022 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1025 static const struct intel_c10pll_state mtl_c10_hdmi_148352 = {
1029 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
1030 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1031 .pll[10] = 0xFF, .pll[11] = 0x44, .pll[12] = 0x44, .pll[13] = 0x44, .pll[14] = 0x44,
1032 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1035 static const struct intel_c10pll_state mtl_c10_hdmi_154000 = {
1039 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x80, .pll[3] = 0x00, .pll[4] = 0x00,
1040 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1041 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x35, .pll[13] = 0x55, .pll[14] = 0x55,
1042 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1045 static const struct intel_c10pll_state mtl_c10_hdmi_162000 = {
1049 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x88, .pll[3] = 0x00, .pll[4] = 0x00,
1050 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1051 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x60, .pll[13] = 0x00, .pll[14] = 0x00,
1052 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1055 static const struct intel_c10pll_state mtl_c10_hdmi_167000 = {
1059 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x8C, .pll[3] = 0x00, .pll[4] = 0x00,
1060 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1061 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0xFA, .pll[13] = 0xA9, .pll[14] = 0xAA,
1062 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1065 static const struct intel_c10pll_state mtl_c10_hdmi_197802 = {
1069 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00,
1070 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1071 .pll[10] = 0xFF, .pll[11] = 0x99, .pll[12] = 0x05, .pll[13] = 0x98, .pll[14] = 0x99,
1072 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
1075 static const struct intel_c10pll_state mtl_c10_hdmi_198000 = {
1079 .pll[0] = 0x74, .pll[1] = 0x00, .pll[2] = 0xAE, .pll[3] = 0x00, .pll[4] = 0x00,
1080 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1081 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x20, .pll[13] = 0x00, .pll[14] = 0x00,
1082 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
1085 static const struct intel_c10pll_state mtl_c10_hdmi_209800 = {
1089 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xBA, .pll[3] = 0x00, .pll[4] = 0x00,
1090 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1091 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x45, .pll[13] = 0x55, .pll[14] = 0x55,
1092 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1095 static const struct intel_c10pll_state mtl_c10_hdmi_241500 = {
1099 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xDA, .pll[3] = 0x00, .pll[4] = 0x00,
1100 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1101 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xC8, .pll[13] = 0x00, .pll[14] = 0x00,
1102 .pll[15] = 0x0A, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
1105 static const struct intel_c10pll_state mtl_c10_hdmi_262750 = {
1109 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x68, .pll[3] = 0x00, .pll[4] = 0x00,
1110 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1111 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x6C, .pll[13] = 0xA9, .pll[14] = 0xAA,
1112 .pll[15] = 0x09, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
1115 static const struct intel_c10pll_state mtl_c10_hdmi_268500 = {
1119 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x6A, .pll[3] = 0x00, .pll[4] = 0x00,
1120 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1121 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0xEC, .pll[13] = 0x00, .pll[14] = 0x00,
1122 .pll[15] = 0x09, .pll[16] = 0x09, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
1125 static const struct intel_c10pll_state mtl_c10_hdmi_296703 = {
1129 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
1130 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1131 .pll[10] = 0xFF, .pll[11] = 0x33, .pll[12] = 0x44, .pll[13] = 0x33, .pll[14] = 0x33,
1132 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1135 static const struct intel_c10pll_state mtl_c10_hdmi_297000 = {
1139 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
1140 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1141 .pll[10] = 0xFF, .pll[11] = 0x00, .pll[12] = 0x58, .pll[13] = 0x00, .pll[14] = 0x00,
1142 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1145 static const struct intel_c10pll_state mtl_c10_hdmi_319750 = {
1149 .pll[0] = 0xB4, .pll[1] = 0x00, .pll[2] = 0x86, .pll[3] = 0x00, .pll[4] = 0x00,
1150 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1151 .pll[10] = 0xFF, .pll[11] = 0xAA, .pll[12] = 0x44, .pll[13] = 0xA9, .pll[14] = 0xAA,
1152 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1155 static const struct intel_c10pll_state mtl_c10_hdmi_497750 = {
1159 .pll[0] = 0x34, .pll[1] = 0x00, .pll[2] = 0xE2, .pll[3] = 0x00, .pll[4] = 0x00,
1160 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1161 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x9F, .pll[13] = 0x55, .pll[14] = 0x55,
1162 .pll[15] = 0x09, .pll[16] = 0x08, .pll[17] = 0xCF, .pll[18] = 0x84, .pll[19] = 0x23,
1165 static const struct intel_c10pll_state mtl_c10_hdmi_592000 = {
1169 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
1170 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1171 .pll[10] = 0xFF, .pll[11] = 0x55, .pll[12] = 0x15, .pll[13] = 0x55, .pll[14] = 0x55,
1172 .pll[15] = 0x08, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1175 static const struct intel_c10pll_state mtl_c10_hdmi_593407 = {
1179 .pll[0] = 0xF4, .pll[1] = 0x00, .pll[2] = 0x7A, .pll[3] = 0x00, .pll[4] = 0x00,
1180 .pll[5] = 0x00, .pll[6] = 0x00, .pll[7] = 0x00, .pll[8] = 0x20, .pll[9] = 0xFF,
1181 .pll[10] = 0xFF, .pll[11] = 0x3B, .pll[12] = 0x44, .pll[13] = 0xBA, .pll[14] = 0xBB,
1182 .pll[15] = 0x08, .pll[16] = 0x08, .pll[17] = 0x8F, .pll[18] = 0x84, .pll[19] = 0x23,
1185 static const struct intel_c10pll_state * const mtl_c10_hdmi_tables[] = {
1186 &mtl_c10_hdmi_25_2, /* Consolidated Table */
1187 &mtl_c10_hdmi_27_0, /* Consolidated Table */
1188 &mtl_c10_hdmi_27027,
1189 &mtl_c10_hdmi_28320,
1190 &mtl_c10_hdmi_30240,
1191 &mtl_c10_hdmi_31500,
1192 &mtl_c10_hdmi_36000,
1193 &mtl_c10_hdmi_40000,
1194 &mtl_c10_hdmi_49500,
1195 &mtl_c10_hdmi_50000,
1196 &mtl_c10_hdmi_57284,
1197 &mtl_c10_hdmi_58000,
1198 &mtl_c10_hdmi_65000,
1199 &mtl_c10_hdmi_71000,
1200 &mtl_c10_hdmi_74176,
1201 &mtl_c10_hdmi_74_25, /* Consolidated Table */
1202 &mtl_c10_hdmi_75000,
1203 &mtl_c10_hdmi_78750,
1204 &mtl_c10_hdmi_85500,
1205 &mtl_c10_hdmi_88750,
1206 &mtl_c10_hdmi_106500,
1207 &mtl_c10_hdmi_108000,
1208 &mtl_c10_hdmi_115500,
1209 &mtl_c10_hdmi_119000,
1210 &mtl_c10_hdmi_135000,
1211 &mtl_c10_hdmi_138500,
1212 &mtl_c10_hdmi_147160,
1213 &mtl_c10_hdmi_148352,
1214 &mtl_c10_hdmi_148_5, /* Consolidated Table */
1215 &mtl_c10_hdmi_154000,
1216 &mtl_c10_hdmi_162000,
1217 &mtl_c10_hdmi_167000,
1218 &mtl_c10_hdmi_197802,
1219 &mtl_c10_hdmi_198000,
1220 &mtl_c10_hdmi_209800,
1221 &mtl_c10_hdmi_241500,
1222 &mtl_c10_hdmi_262750,
1223 &mtl_c10_hdmi_268500,
1224 &mtl_c10_hdmi_296703,
1225 &mtl_c10_hdmi_297000,
1226 &mtl_c10_hdmi_319750,
1227 &mtl_c10_hdmi_497750,
1228 &mtl_c10_hdmi_592000,
1229 &mtl_c10_hdmi_593407,
1230 &mtl_c10_hdmi_594, /* Consolidated Table */
1234 int intel_c10_phy_check_hdmi_link_rate(int clock)
1236 const struct intel_c10pll_state * const *tables = mtl_c10_hdmi_tables;
1239 for (i = 0; tables[i]; i++) {
1240 if (clock == tables[i]->clock)
1244 return MODE_CLOCK_RANGE;
1247 static const struct intel_c10pll_state * const *
1248 intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
1249 struct intel_encoder *encoder)
1251 if (intel_crtc_has_dp_encoder(crtc_state)) {
1252 if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
1253 return mtl_c10_edp_tables;
1255 return mtl_c10_dp_tables;
1256 } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
1257 return mtl_c10_hdmi_tables;
1260 MISSING_CASE(encoder->type);
1264 static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
1265 struct intel_encoder *encoder)
1267 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1268 struct intel_cx0pll_state *pll_state = &crtc_state->cx0pll_state;
1271 if (intel_crtc_has_dp_encoder(crtc_state)) {
1272 if (intel_panel_use_ssc(i915)) {
1273 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1275 pll_state->ssc_enabled =
1276 (intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
1280 if (pll_state->ssc_enabled)
1283 drm_WARN_ON(&i915->drm, ARRAY_SIZE(pll_state->c10.pll) < 9);
1284 for (i = 4; i < 9; i++)
1285 pll_state->c10.pll[i] = 0;
1288 static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
1289 struct intel_encoder *encoder)
1291 const struct intel_c10pll_state * const *tables;
1294 tables = intel_c10pll_tables_get(crtc_state, encoder);
1298 for (i = 0; tables[i]; i++) {
1299 if (crtc_state->port_clock == tables[i]->clock) {
1300 crtc_state->cx0pll_state.c10 = *tables[i];
1301 intel_c10pll_update_pll(crtc_state, encoder);
1310 int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state,
1311 struct intel_encoder *encoder)
1313 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1314 enum phy phy = intel_port_to_phy(i915, encoder->port);
1316 drm_WARN_ON(&i915->drm, !intel_is_c10phy(i915, phy));
1318 return intel_c10pll_calc_state(crtc_state, encoder);
1321 void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
1322 struct intel_c10pll_state *pll_state)
1324 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1325 u8 lane = INTEL_CX0_LANE0;
1326 intel_wakeref_t wakeref;
1329 wakeref = intel_cx0_phy_transaction_begin(encoder);
1332 * According to C10 VDR Register programming Sequence we need
1333 * to do this to read PHY internal registers from MsgBus.
1335 intel_cx0_rmw(i915, encoder->port, lane, PHY_C10_VDR_CONTROL(1),
1336 0, C10_VDR_CTRL_MSGBUS_ACCESS,
1337 MB_WRITE_COMMITTED);
1339 for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
1340 pll_state->pll[i] = intel_cx0_read(i915, encoder->port, lane,
1341 PHY_C10_VDR_PLL(i));
1343 pll_state->cmn = intel_cx0_read(i915, encoder->port, lane, PHY_C10_VDR_CMN(0));
1344 pll_state->tx = intel_cx0_read(i915, encoder->port, lane, PHY_C10_VDR_TX(0));
1346 intel_cx0_phy_transaction_end(encoder, wakeref);
1349 static void intel_c10_pll_program(struct drm_i915_private *i915,
1350 const struct intel_crtc_state *crtc_state,
1351 struct intel_encoder *encoder)
1353 const struct intel_c10pll_state *pll_state = &crtc_state->cx0pll_state.c10;
1356 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
1357 0, C10_VDR_CTRL_MSGBUS_ACCESS,
1358 MB_WRITE_COMMITTED);
1360 /* Custom width needs to be programmed to 0 for both the phy lanes */
1361 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH,
1362 C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10,
1363 MB_WRITE_COMMITTED);
1364 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
1365 0, C10_VDR_CTRL_UPDATE_CFG,
1366 MB_WRITE_COMMITTED);
1368 /* Program the pll values only for the master lane */
1369 for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
1370 intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_PLL(i),
1372 (i % 4) ? MB_WRITE_UNCOMMITTED : MB_WRITE_COMMITTED);
1374 intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_CMN(0), pll_state->cmn, MB_WRITE_COMMITTED);
1375 intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_TX(0), pll_state->tx, MB_WRITE_COMMITTED);
1377 intel_cx0_rmw(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1),
1378 0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG,
1379 MB_WRITE_COMMITTED);
1382 void intel_c10pll_dump_hw_state(struct drm_i915_private *i915,
1383 const struct intel_c10pll_state *hw_state)
1387 unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
1388 unsigned int multiplier, tx_clk_div;
1390 fracen = hw_state->pll[0] & C10_PLL0_FRACEN;
1391 drm_dbg_kms(&i915->drm, "c10pll_hw_state: fracen: %s, ",
1392 str_yes_no(fracen));
1395 frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11];
1396 frac_rem = hw_state->pll[14] << 8 | hw_state->pll[13];
1397 frac_den = hw_state->pll[10] << 8 | hw_state->pll[9];
1398 drm_dbg_kms(&i915->drm, "quot: %u, rem: %u, den: %u,\n",
1399 frac_quot, frac_rem, frac_den);
1402 multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, hw_state->pll[3]) << 8 |
1403 hw_state->pll[2]) / 2 + 16;
1404 tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, hw_state->pll[15]);
1405 drm_dbg_kms(&i915->drm,
1406 "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div);
1408 drm_dbg_kms(&i915->drm, "c10pll_rawhw_state:");
1409 drm_dbg_kms(&i915->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, hw_state->cmn);
1411 BUILD_BUG_ON(ARRAY_SIZE(hw_state->pll) % 4);
1412 for (i = 0; i < ARRAY_SIZE(hw_state->pll); i = i + 4)
1413 drm_dbg_kms(&i915->drm, "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n",
1414 i, hw_state->pll[i], i + 1, hw_state->pll[i + 1],
1415 i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]);
1418 int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
1419 const struct intel_c10pll_state *pll_state)
1421 unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
1422 unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400;
1425 if (pll_state->pll[0] & C10_PLL0_FRACEN) {
1426 frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11];
1427 frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13];
1428 frac_den = pll_state->pll[10] << 8 | pll_state->pll[9];
1431 multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 |
1432 pll_state->pll[2]) / 2 + 16;
1434 tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]);
1435 hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]);
1437 tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) +
1438 DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den),
1439 10 << (tx_clk_div + 16));
1440 tmpclk *= (hdmi_div ? 2 : 1);
1445 static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
1446 const struct intel_crtc_state *crtc_state,
1449 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1452 intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(encoder->port), XELPDP_PORT_REVERSAL,
1453 lane_reversal ? XELPDP_PORT_REVERSAL : 0);
1456 val |= XELPDP_LANE1_PHY_CLOCK_SELECT;
1458 val |= XELPDP_FORWARD_CLOCK_UNGATE;
1459 val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
1461 /* TODO: HDMI FRL */
1462 /* TODO: DP2.0 10G and 20G rates enable MPLLA*/
1463 val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
1465 intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
1466 XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
1467 XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLB, val);
1470 static u32 intel_cx0_get_powerdown_update(u8 lane_mask)
1475 for_each_cx0_lane_in_mask(lane_mask, lane)
1476 val |= XELPDP_LANE_POWERDOWN_UPDATE(lane);
1481 static u32 intel_cx0_get_powerdown_state(u8 lane_mask, u8 state)
1486 for_each_cx0_lane_in_mask(lane_mask, lane)
1487 val |= XELPDP_LANE_POWERDOWN_NEW_STATE(lane, state);
1492 static void intel_cx0_powerdown_change_sequence(struct drm_i915_private *i915,
1494 u8 lane_mask, u8 state)
1496 enum phy phy = intel_port_to_phy(i915, port);
1499 intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
1500 intel_cx0_get_powerdown_state(INTEL_CX0_BOTH_LANES, XELPDP_LANE_POWERDOWN_NEW_STATE_MASK),
1501 intel_cx0_get_powerdown_state(lane_mask, state));
1503 /* Wait for pending transactions.*/
1504 for_each_cx0_lane_in_mask(lane_mask, lane)
1505 if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
1506 XELPDP_PORT_M2P_TRANSACTION_PENDING,
1507 XELPDP_MSGBUS_TIMEOUT_SLOW)) {
1508 drm_dbg_kms(&i915->drm,
1509 "PHY %c Timeout waiting for previous transaction to complete. Reset the bus.\n",
1511 intel_cx0_bus_reset(i915, port, lane);
1514 intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
1515 intel_cx0_get_powerdown_update(INTEL_CX0_BOTH_LANES),
1516 intel_cx0_get_powerdown_update(lane_mask));
1518 /* Update Timeout Value */
1519 if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(port),
1520 intel_cx0_get_powerdown_update(lane_mask), 0,
1521 XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 0, NULL))
1522 drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n",
1523 phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
1526 static void intel_cx0_setup_powerdown(struct drm_i915_private *i915, enum port port)
1528 intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
1529 XELPDP_POWER_STATE_READY_MASK,
1530 XELPDP_POWER_STATE_READY(CX0_P2_STATE_READY));
1531 intel_de_rmw(i915, XELPDP_PORT_BUF_CTL3(port),
1532 XELPDP_POWER_STATE_ACTIVE_MASK |
1533 XELPDP_PLL_LANE_STAGGERING_DELAY_MASK,
1534 XELPDP_POWER_STATE_ACTIVE(CX0_P0_STATE_ACTIVE) |
1535 XELPDP_PLL_LANE_STAGGERING_DELAY(0));
1538 static u32 intel_cx0_get_pclk_refclk_request(u8 lane_mask)
1543 for_each_cx0_lane_in_mask(lane_mask, lane)
1544 val |= XELPDP_LANE_PCLK_REFCLK_REQUEST(lane);
1549 static u32 intel_cx0_get_pclk_refclk_ack(u8 lane_mask)
1554 for_each_cx0_lane_in_mask(lane_mask, lane)
1555 val |= XELPDP_LANE_PCLK_REFCLK_ACK(lane);
1560 /* FIXME: Some Type-C cases need not reset both the lanes. Handle those cases. */
1561 static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915, enum port port,
1564 enum phy phy = intel_port_to_phy(i915, port);
1565 u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 :
1568 if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL1(port),
1569 XELPDP_PORT_BUF_SOC_PHY_READY,
1570 XELPDP_PORT_BUF_SOC_PHY_READY,
1571 XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US, 0, NULL))
1572 drm_warn(&i915->drm, "PHY %c failed to bring out of SOC reset after %dus.\n",
1573 phy_name(phy), XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US);
1575 intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
1576 XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1),
1577 XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1));
1579 if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(port),
1580 XELPDP_LANE_PHY_CURRENT_STATUS(0) |
1581 XELPDP_LANE_PHY_CURRENT_STATUS(1),
1582 XELPDP_LANE_PHY_CURRENT_STATUS(0) |
1583 XELPDP_LANE_PHY_CURRENT_STATUS(1),
1584 XELPDP_PORT_RESET_START_TIMEOUT_US, 0, NULL))
1585 drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n",
1586 phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
1588 intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(port),
1589 intel_cx0_get_pclk_refclk_request(INTEL_CX0_BOTH_LANES),
1590 intel_cx0_get_pclk_refclk_request(lane_mask));
1592 if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(port),
1593 intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES),
1594 intel_cx0_get_pclk_refclk_ack(lane_mask),
1595 XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL))
1596 drm_warn(&i915->drm, "PHY %c failed to request refclk after %dus.\n",
1597 phy_name(phy), XELPDP_REFCLK_ENABLE_TIMEOUT_US);
1599 intel_cx0_powerdown_change_sequence(i915, port, INTEL_CX0_BOTH_LANES,
1600 CX0_P2_STATE_RESET);
1601 intel_cx0_setup_powerdown(i915, port);
1603 intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
1604 XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1),
1607 if (intel_de_wait_for_clear(i915, XELPDP_PORT_BUF_CTL2(port),
1608 XELPDP_LANE_PHY_CURRENT_STATUS(0) |
1609 XELPDP_LANE_PHY_CURRENT_STATUS(1),
1610 XELPDP_PORT_RESET_END_TIMEOUT))
1611 drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dms.\n",
1612 phy_name(phy), XELPDP_PORT_RESET_END_TIMEOUT);
1615 static void intel_c10_program_phy_lane(struct drm_i915_private *i915,
1616 struct intel_encoder *encoder, int lane_count,
1619 u8 l0t1, l0t2, l1t1, l1t2;
1620 bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder));
1621 enum port port = encoder->port;
1623 intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
1624 0, C10_VDR_CTRL_MSGBUS_ACCESS,
1625 MB_WRITE_COMMITTED);
1627 /* TODO: DP-alt MFD case where only one PHY lane should be programmed. */
1628 l0t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2));
1629 l0t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2));
1630 l1t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2));
1631 l1t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2));
1633 l0t1 |= CONTROL2_DISABLE_SINGLE_TX;
1634 l0t2 |= CONTROL2_DISABLE_SINGLE_TX;
1635 l1t1 |= CONTROL2_DISABLE_SINGLE_TX;
1636 l1t2 |= CONTROL2_DISABLE_SINGLE_TX;
1638 if (lane_reversal) {
1639 switch (lane_count) {
1641 l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
1644 l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
1647 l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
1650 l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
1653 MISSING_CASE(lane_count);
1656 switch (lane_count) {
1658 l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
1661 l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
1664 l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
1665 l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
1669 l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
1671 l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
1674 MISSING_CASE(lane_count);
1679 intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2),
1680 l0t1, MB_WRITE_COMMITTED);
1681 intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2),
1682 l0t2, MB_WRITE_COMMITTED);
1683 intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2),
1684 l1t1, MB_WRITE_COMMITTED);
1685 intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2),
1686 l1t2, MB_WRITE_COMMITTED);
1688 intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
1689 0, C10_VDR_CTRL_UPDATE_CFG,
1690 MB_WRITE_COMMITTED);
1693 static u32 intel_cx0_get_pclk_pll_request(u8 lane_mask)
1698 for_each_cx0_lane_in_mask(lane_mask, lane)
1699 val |= XELPDP_LANE_PCLK_PLL_REQUEST(lane);
1704 static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
1709 for_each_cx0_lane_in_mask(lane_mask, lane)
1710 val |= XELPDP_LANE_PCLK_PLL_ACK(lane);
1715 static void intel_c10pll_enable(struct intel_encoder *encoder,
1716 const struct intel_crtc_state *crtc_state)
1718 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1719 enum phy phy = intel_port_to_phy(i915, encoder->port);
1720 struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1721 bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
1722 u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 :
1726 * 1. Program PORT_CLOCK_CTL REGISTER to configure
1727 * clock muxes, gating and SSC
1729 intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
1731 /* 2. Bring PHY out of reset. */
1732 intel_cx0_phy_lane_reset(i915, encoder->port, lane_reversal);
1735 * 3. Change Phy power state to Ready.
1736 * TODO: For DP alt mode use only one lane.
1738 intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES,
1739 CX0_P2_STATE_READY);
1741 /* 4. Program PHY internal PLL internal registers. */
1742 intel_c10_pll_program(i915, crtc_state, encoder);
1745 * 5. Program the enabled and disabled owned PHY lane
1746 * transmitters over message bus
1748 intel_c10_program_phy_lane(i915, encoder, crtc_state->lane_count, lane_reversal);
1751 * 6. Follow the Display Voltage Frequency Switching - Sequence
1752 * Before Frequency Change. We handle this step in bxt_set_cdclk().
1756 * 7. Program DDI_CLK_VALFREQ to match intended DDI
1759 intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
1760 crtc_state->port_clock);
1763 * 8. Set PORT_CLOCK_CTL register PCLK PLL Request
1764 * LN<Lane for maxPCLK> to "1" to enable PLL.
1766 intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
1767 intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES),
1768 intel_cx0_get_pclk_pll_request(maxpclk_lane));
1770 /* 9. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
1771 if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
1772 intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES),
1773 intel_cx0_get_pclk_pll_ack(maxpclk_lane),
1774 XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, 0, NULL))
1775 drm_warn(&i915->drm, "Port %c PLL not locked after %dus.\n",
1776 phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US);
1779 * 10. Follow the Display Voltage Frequency Switching Sequence After
1780 * Frequency Change. We handle this step in bxt_set_cdclk().
1784 void intel_cx0pll_enable(struct intel_encoder *encoder,
1785 const struct intel_crtc_state *crtc_state)
1787 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1788 enum phy phy = intel_port_to_phy(i915, encoder->port);
1789 intel_wakeref_t wakeref;
1791 wakeref = intel_cx0_phy_transaction_begin(encoder);
1793 drm_WARN_ON(&i915->drm, !intel_is_c10phy(i915, phy));
1794 intel_c10pll_enable(encoder, crtc_state);
1796 /* TODO: enable TBT-ALT mode */
1797 intel_cx0_phy_transaction_end(encoder, wakeref);
1800 static void intel_c10pll_disable(struct intel_encoder *encoder)
1802 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1803 enum phy phy = intel_port_to_phy(i915, encoder->port);
1805 /* 1. Change owned PHY lane power to Disable state. */
1806 intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES,
1807 CX0_P2PG_STATE_DISABLE);
1810 * 2. Follow the Display Voltage Frequency Switching Sequence Before
1811 * Frequency Change. We handle this step in bxt_set_cdclk().
1815 * 3. Set PORT_CLOCK_CTL register PCLK PLL Request LN<Lane for maxPCLK>
1816 * to "0" to disable PLL.
1818 intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
1819 intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES) |
1820 intel_cx0_get_pclk_refclk_request(INTEL_CX0_BOTH_LANES), 0);
1822 /* 4. Program DDI_CLK_VALFREQ to 0. */
1823 intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port), 0);
1826 * 5. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK**> == "0".
1828 if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
1829 intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES) |
1830 intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES), 0,
1831 XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US, 0, NULL))
1832 drm_warn(&i915->drm, "Port %c PLL not unlocked after %dus.\n",
1833 phy_name(phy), XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US);
1836 * 6. Follow the Display Voltage Frequency Switching Sequence After
1837 * Frequency Change. We handle this step in bxt_set_cdclk().
1840 /* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */
1841 intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
1842 XELPDP_DDI_CLOCK_SELECT_MASK, 0);
1843 intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
1844 XELPDP_FORWARD_CLOCK_UNGATE, 0);
1847 void intel_cx0pll_disable(struct intel_encoder *encoder)
1849 struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1850 enum phy phy = intel_port_to_phy(i915, encoder->port);
1851 intel_wakeref_t wakeref;
1853 wakeref = intel_cx0_phy_transaction_begin(encoder);
1855 drm_WARN_ON(&i915->drm, !intel_is_c10phy(i915, phy));
1856 intel_c10pll_disable(encoder);
1857 intel_cx0_phy_transaction_end(encoder, wakeref);
1860 void intel_c10pll_state_verify(struct intel_atomic_state *state,
1861 struct intel_crtc_state *new_crtc_state)
1863 struct drm_i915_private *i915 = to_i915(state->base.dev);
1864 struct intel_c10pll_state mpllb_hw_state = { 0 };
1865 struct intel_c10pll_state *mpllb_sw_state = &new_crtc_state->cx0pll_state.c10;
1866 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1867 struct intel_encoder *encoder;
1871 if (DISPLAY_VER(i915) < 14)
1874 if (!new_crtc_state->hw.active)
1877 encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
1878 phy = intel_port_to_phy(i915, encoder->port);
1880 if (!intel_is_c10phy(i915, phy))
1883 intel_c10pll_readout_hw_state(encoder, &mpllb_hw_state);
1885 for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
1886 u8 expected = mpllb_sw_state->pll[i];
1888 I915_STATE_WARN(mpllb_hw_state.pll[i] != expected,
1889 "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)",
1890 crtc->base.base.id, crtc->base.name,
1891 i, expected, mpllb_hw_state.pll[i]);
1894 I915_STATE_WARN(mpllb_hw_state.tx != mpllb_sw_state->tx,
1895 "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)",
1896 crtc->base.base.id, crtc->base.name,
1897 mpllb_sw_state->tx, mpllb_hw_state.tx);
1899 I915_STATE_WARN(mpllb_hw_state.cmn != mpllb_sw_state->cmn,
1900 "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)",
1901 crtc->base.base.id, crtc->base.name,
1902 mpllb_sw_state->cmn, mpllb_hw_state.cmn);