summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_cx0_phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_cx0_phy.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c297
1 files changed, 193 insertions, 104 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index e768dc6a15b3..22595766eac5 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -18,6 +18,7 @@
#include "intel_hdmi.h"
#include "intel_panel.h"
#include "intel_psr.h"
+#include "intel_snps_hdmi_pll.h"
#include "intel_tc.h"
#define MB_WRITE_COMMITTED true
@@ -33,13 +34,13 @@
bool intel_encoder_is_c10phy(struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
- if (IS_PANTHERLAKE(i915) && phy == PHY_A)
+ if (display->platform.pantherlake && phy == PHY_A)
return true;
- if ((IS_LUNARLAKE(i915) || IS_METEORLAKE(i915)) && phy < PHY_C)
+ if ((display->platform.lunarlake || display->platform.meteorlake) && phy < PHY_C)
return true;
return false;
@@ -72,10 +73,9 @@ static u8 intel_cx0_get_owned_lane_mask(struct intel_encoder *encoder)
static void
assert_dc_off(struct intel_display *display)
{
- struct drm_i915_private *i915 = to_i915(display->drm);
bool enabled;
- enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
+ enabled = intel_display_power_is_enabled(display, POWER_DOMAIN_DC_OFF);
drm_WARN_ON(display->drm, !enabled);
}
@@ -102,12 +102,12 @@ static void intel_cx0_program_msgbus_timer(struct intel_encoder *encoder)
*/
static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
{
- intel_wakeref_t wakeref;
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ intel_wakeref_t wakeref;
intel_psr_pause(intel_dp);
- wakeref = intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
+ wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF);
intel_cx0_program_msgbus_timer(encoder);
return wakeref;
@@ -115,11 +115,11 @@ static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *enc
static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_psr_resume(intel_dp);
- intel_display_power_put(i915, POWER_DOMAIN_DC_OFF, wakeref);
+ intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref);
}
static void intel_clear_response_ready_flag(struct intel_encoder *encoder,
@@ -2003,19 +2003,6 @@ static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = {
NULL,
};
-static int intel_c10_phy_check_hdmi_link_rate(int clock)
-{
- const struct intel_c10pll_state * const *tables = mtl_c10_hdmi_tables;
- int i;
-
- for (i = 0; tables[i]; i++) {
- if (clock == tables[i]->clock)
- return MODE_OK;
- }
-
- return MODE_CLOCK_RANGE;
-}
-
static const struct intel_c10pll_state * const *
intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
@@ -2033,21 +2020,25 @@ intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
return NULL;
}
-static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder)
+static void intel_cx0pll_update_ssc(struct intel_encoder *encoder,
+ struct intel_cx0pll_state *pll_state, bool is_dp)
{
struct intel_display *display = to_intel_display(encoder);
- struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
- int i;
- if (intel_crtc_has_dp_encoder(crtc_state)) {
+ if (is_dp) {
if (intel_panel_use_ssc(display)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
pll_state->ssc_enabled =
(intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
}
}
+}
+
+static void intel_c10pll_update_pll(struct intel_encoder *encoder,
+ struct intel_cx0pll_state *pll_state)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ int i;
if (pll_state->ssc_enabled)
return;
@@ -2057,27 +2048,53 @@ static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
pll_state->c10.pll[i] = 0;
}
+static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
+ const struct intel_c10pll_state * const *tables,
+ bool is_dp, int port_clock,
+ struct intel_cx0pll_state *pll_state)
+{
+ int i;
+
+ for (i = 0; tables[i]; i++) {
+ if (port_clock == tables[i]->clock) {
+ pll_state->c10 = *tables[i];
+ intel_cx0pll_update_ssc(encoder, pll_state, is_dp);
+ intel_c10pll_update_pll(encoder, pll_state);
+ pll_state->use_c10 = true;
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
const struct intel_c10pll_state * const *tables;
- int i;
+ int err;
tables = intel_c10pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
- for (i = 0; tables[i]; i++) {
- if (crtc_state->port_clock == tables[i]->clock) {
- crtc_state->dpll_hw_state.cx0pll.c10 = *tables[i];
- intel_c10pll_update_pll(crtc_state, encoder);
- crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
+ err = intel_c10pll_calc_state_from_table(encoder, tables,
+ intel_crtc_has_dp_encoder(crtc_state),
+ crtc_state->port_clock,
+ &crtc_state->dpll_hw_state.cx0pll);
- return 0;
- }
- }
+ if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+ return err;
- return -EINVAL;
+ /* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */
+ intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10,
+ crtc_state->port_clock);
+ intel_c10pll_update_pll(encoder,
+ &crtc_state->dpll_hw_state.cx0pll);
+ crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
+
+ return 0;
}
static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
@@ -2107,10 +2124,9 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
}
static void intel_c10_pll_program(struct intel_display *display,
- const struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder)
+ struct intel_encoder *encoder,
+ const struct intel_c10pll_state *pll_state)
{
- const struct intel_c10pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c10;
int i;
intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
@@ -2173,9 +2189,47 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display,
i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]);
}
-static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
+/*
+ * Some ARLs SoCs have the same drm PCI IDs, so need a helper to differentiate based
+ * on the host bridge device ID to get the correct txx_mics value.
+ */
+static bool is_arrowlake_s_by_host_bridge(void)
+{
+ struct pci_dev *pdev = NULL;
+ u16 host_bridge_pci_dev_id;
+
+ while ((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, pdev)))
+ host_bridge_pci_dev_id = pdev->device;
+
+ return pdev && IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(host_bridge_pci_dev_id);
+}
+
+static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
+ u16 tx_misc;
+ u16 tx_dcc_cal_dac_ctrl_range = 8;
+ u16 tx_term_ctrl = 2;
+
+ if (DISPLAY_VER(display) >= 20) {
+ tx_misc = 5;
+ tx_term_ctrl = 4;
+ } else if (display->platform.battlemage) {
+ tx_misc = 0;
+ } else if (display->platform.meteorlake_u ||
+ is_arrowlake_s_by_host_bridge()) {
+ tx_misc = 3;
+ } else {
+ tx_misc = 7;
+ }
+
+ return (C20_PHY_TX_MISC(tx_misc) |
+ C20_PHY_TX_DCC_CAL_RANGE(tx_dcc_cal_dac_ctrl_range) |
+ C20_PHY_TX_DCC_BYPASS | C20_PHY_TX_TERM_CTL(tx_term_ctrl));
+}
+
+static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
+{
struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
u64 datarate;
u64 mpll_tx_clk_div;
@@ -2185,7 +2239,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
u64 mpll_multiplier;
u64 mpll_fracn_quot;
u64 mpll_fracn_rem;
- u16 tx_misc;
u8 mpllb_ana_freq_vco;
u8 mpll_div_multiplier;
@@ -2205,11 +2258,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
mpll_div_multiplier = min_t(u8, div64_u64((vco_freq * 16 + (datarate >> 1)),
datarate), 255);
- if (DISPLAY_VER(display) >= 20)
- tx_misc = 0x5;
- else
- tx_misc = 0x0;
-
if (vco_freq <= DATARATE_3000000000)
mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_3;
else if (vco_freq <= DATARATE_3500000000)
@@ -2221,7 +2269,7 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
pll_state->clock = crtc_state->port_clock;
pll_state->tx[0] = 0xbe88;
- pll_state->tx[1] = 0x9800 | C20_PHY_TX_MISC(tx_misc);
+ pll_state->tx[1] = intel_c20_hdmi_tmds_tx_cgf_1(crtc_state);
pll_state->tx[2] = 0x0000;
pll_state->cmn[0] = 0x0500;
pll_state->cmn[1] = 0x0005;
@@ -2249,31 +2297,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
return 0;
}
-static int intel_c20_phy_check_hdmi_link_rate(int clock)
-{
- const struct intel_c20pll_state * const *tables = mtl_c20_hdmi_tables;
- int i;
-
- for (i = 0; tables[i]; i++) {
- if (clock == tables[i]->clock)
- return MODE_OK;
- }
-
- if (clock >= 25175 && clock <= 594000)
- return MODE_OK;
-
- return MODE_CLOCK_RANGE;
-}
-
-int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock)
-{
- struct intel_digital_port *dig_port = hdmi_to_dig_port(hdmi);
-
- if (intel_encoder_is_c10phy(&dig_port->base))
- return intel_c10_phy_check_hdmi_link_rate(clock);
- return intel_c20_phy_check_hdmi_link_rate(clock);
-}
-
static const struct intel_c20pll_state * const *
intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
@@ -2322,6 +2345,9 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
for (i = 0; tables[i]; i++) {
if (crtc_state->port_clock == tables[i]->clock) {
crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i];
+ intel_cx0pll_update_ssc(encoder,
+ &crtc_state->dpll_hw_state.cx0pll,
+ intel_crtc_has_dp_encoder(crtc_state));
crtc_state->dpll_hw_state.cx0pll.use_c10 = false;
return 0;
}
@@ -2587,19 +2613,14 @@ static int intel_get_c20_custom_width(u32 clock, bool dp)
}
static void intel_c20_pll_program(struct intel_display *display,
- const struct intel_crtc_state *crtc_state,
- struct intel_encoder *encoder)
+ struct intel_encoder *encoder,
+ const struct intel_c20pll_state *pll_state,
+ bool is_dp, int port_clock)
{
- const struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
- bool dp = false;
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
- u32 clock = crtc_state->port_clock;
bool cntx;
int i;
- if (intel_crtc_has_dp_encoder(crtc_state))
- dp = true;
-
/* 1. Read current context selection */
cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0);
@@ -2667,23 +2688,23 @@ static void intel_c20_pll_program(struct intel_display *display,
/* 4. Program custom width to match the link protocol */
intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH,
PHY_C20_CUSTOM_WIDTH_MASK,
- PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(clock, dp)),
+ PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(port_clock, is_dp)),
MB_WRITE_COMMITTED);
/* 5. For DP or 6. For HDMI */
- if (dp) {
+ if (is_dp) {
intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE,
BIT(6) | PHY_C20_CUSTOM_SERDES_MASK,
- BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(clock)),
+ BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(port_clock)),
MB_WRITE_COMMITTED);
} else {
intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE,
BIT(7) | PHY_C20_CUSTOM_SERDES_MASK,
- is_hdmi_frl(clock) ? BIT(7) : 0,
+ is_hdmi_frl(port_clock) ? BIT(7) : 0,
MB_WRITE_COMMITTED);
intel_cx0_write(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE,
- intel_c20_get_hdmi_rate(clock),
+ intel_c20_get_hdmi_rate(port_clock),
MB_WRITE_COMMITTED);
}
@@ -2723,7 +2744,8 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
}
static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state,
+ const struct intel_cx0pll_state *pll_state,
+ bool is_dp, int port_clock,
bool lane_reversal)
{
struct intel_display *display = to_intel_display(encoder);
@@ -2738,18 +2760,17 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
val |= XELPDP_FORWARD_CLOCK_UNGATE;
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
- is_hdmi_frl(crtc_state->port_clock))
+ if (!is_dp && is_hdmi_frl(port_clock))
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
else
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
/* TODO: HDMI FRL */
/* DP2.0 10G and 20G rates enable MPLLA*/
- if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000)
- val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
+ if (port_clock == 1000000 || port_clock == 2000000)
+ val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
else
- val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+ val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
@@ -2979,8 +3000,9 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
return val;
}
-static void intel_cx0pll_enable(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+static void __intel_cx0pll_enable(struct intel_encoder *encoder,
+ const struct intel_cx0pll_state *pll_state,
+ bool is_dp, int port_clock, int lane_count)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@@ -2994,7 +3016,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
* 1. Program PORT_CLOCK_CTL REGISTER to configure
* clock muxes, gating and SSC
*/
- intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
+ intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal);
/* 2. Bring PHY out of reset. */
intel_cx0_phy_lane_reset(encoder, lane_reversal);
@@ -3014,15 +3036,15 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
/* 5. Program PHY internal PLL internal registers. */
if (intel_encoder_is_c10phy(encoder))
- intel_c10_pll_program(display, crtc_state, encoder);
+ intel_c10_pll_program(display, encoder, &pll_state->c10);
else
- intel_c20_pll_program(display, crtc_state, encoder);
+ intel_c20_pll_program(display, encoder, &pll_state->c20, is_dp, port_clock);
/*
* 6. Program the enabled and disabled owned PHY lane
* transmitters over message bus
*/
- intel_cx0_program_phy_lane(encoder, crtc_state->lane_count, lane_reversal);
+ intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal);
/*
* 7. Follow the Display Voltage Frequency Switching - Sequence
@@ -3033,8 +3055,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
* 8. Program DDI_CLK_VALFREQ to match intended DDI
* clock frequency.
*/
- intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
- crtc_state->port_clock);
+ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
/*
* 9. Set PORT_CLOCK_CTL register PCLK PLL Request
@@ -3061,6 +3082,14 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
}
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+ __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll,
+ intel_crtc_has_dp_encoder(crtc_state),
+ crtc_state->port_clock, crtc_state->lane_count);
+}
+
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
@@ -3203,12 +3232,11 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder,
static u8 cx0_power_control_disable_val(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
if (intel_encoder_is_c10phy(encoder))
return CX0_P2PG_STATE_DISABLE;
- if ((IS_BATTLEMAGE(i915) && encoder->port == PORT_A) ||
+ if ((display->platform.battlemage && encoder->port == PORT_A) ||
(DISPLAY_VER(display) >= 30 && encoder->type == INTEL_OUTPUT_EDP))
return CX0_P2PG_STATE_DISABLE;
@@ -3266,6 +3294,16 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder)
intel_cx0_phy_transaction_end(encoder, wakeref);
}
+static bool intel_cx0_pll_is_enabled(struct intel_encoder *encoder)
+{
+ struct intel_display *display = to_intel_display(encoder);
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+ u8 lane = dig_port->lane_reversal ? INTEL_CX0_LANE1 : INTEL_CX0_LANE0;
+
+ return intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)) &
+ intel_cx0_get_pclk_pll_request(lane);
+}
+
static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
@@ -3527,3 +3565,54 @@ void intel_cx0pll_state_verify(struct intel_atomic_state *state,
else
intel_c20pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c20);
}
+
+/*
+ * WA 14022081154
+ * The dedicated display PHYs reset to a power state that blocks S0ix, increasing idle
+ * system power. After a system reset (cold boot, S3/4/5, warm reset) if a dedicated
+ * PHY is not being brought up shortly, use these steps to move the PHY to the lowest
+ * power state to save power. For PTL the workaround is needed only for port A. Port B
+ * is not connected.
+ *
+ * 1. Follow the PLL Enable Sequence, using any valid frequency such as DP 1.62 GHz.
+ * This brings lanes out of reset and enables the PLL to allow powerdown to be moved
+ * to the Disable state.
+ * 2. Follow PLL Disable Sequence. This moves powerdown to the Disable state and disables the PLL.
+ */
+void intel_cx0_pll_power_save_wa(struct intel_display *display)
+{
+ struct intel_encoder *encoder;
+
+ if (DISPLAY_VER(display) != 30)
+ return;
+
+ for_each_intel_encoder(display->drm, encoder) {
+ struct intel_cx0pll_state pll_state = {};
+ int port_clock = 162000;
+
+ if (!intel_encoder_is_dig_port(encoder))
+ continue;
+
+ if (!intel_encoder_is_c10phy(encoder))
+ continue;
+
+ if (intel_cx0_pll_is_enabled(encoder))
+ continue;
+
+ if (intel_c10pll_calc_state_from_table(encoder,
+ mtl_c10_edp_tables,
+ true, port_clock,
+ &pll_state) < 0) {
+ drm_WARN_ON(display->drm,
+ "Unable to calc C10 state from the tables\n");
+ continue;
+ }
+
+ drm_dbg_kms(display->drm,
+ "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n",
+ encoder->base.base.id, encoder->base.name);
+
+ __intel_cx0pll_enable(encoder, &pll_state, true, port_clock, 4);
+ intel_cx0pll_disable(encoder);
+ }
+}