From: Mika Kahola <[email protected]> Split PLL enabling/disabling in two parts - one for pll setting pll dividers and second one to enable/disable pll clock. PLL clock enabling/disbling happens via encoder->enable_clock/disable_clock function hook.
PLL state verification happens now earlier than the clock is enabled which causes a drm warn to be thrown. Silence this warning by allowing this check for only earlier platforms than MeteorLake. While at it also add the necessary argument to cx0_enable_clock so that we can move step 12 of the enable sequence. v2: - Move state verification to enable_clock() function for MTL+ platforms - Squash patch 1 & 2 (Gustavo) - Use correct Bspec references (Gustavo) - Fix build error (Michal) Bspec: 65448, 68849 Signed-off-by: Mika Kahola <[email protected]> Signed-off-by: Suraj Kandpal <[email protected]> Reviewed-by: Michał Grzelak <[email protected]> --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 120 +++++++++++------- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 7 +- 2 files changed, 80 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 7288065d2461..3418a3ed28fd 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3225,11 +3225,8 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, { int port_clock = pll_state->use_c10 ? pll_state->c10.clock : pll_state->c20.clock; struct intel_display *display = to_intel_display(encoder); - enum phy phy = intel_encoder_to_phy(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); bool lane_reversal = dig_port->lane_reversal; - u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 : - INTEL_CX0_LANE0; struct ref_tracker *wakeref = intel_cx0_phy_transaction_begin(encoder); /* @@ -3284,42 +3281,6 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, */ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock); - /* - * 9. Set PORT_CLOCK_CTL register PCLK PLL Request - * LN<Lane for maxPCLK> to "1" to enable PLL. - */ - intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES), - intel_cx0_get_pclk_pll_request(maxpclk_lane)); - - /* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */ - if (intel_de_wait_us(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES), - intel_cx0_get_pclk_pll_ack(maxpclk_lane), - XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, NULL)) - drm_warn(display->drm, "Port %c PLL not locked\n", - phy_name(phy)); - - /* - * 11. Follow the Display Voltage Frequency Switching Sequence After - * Frequency Change. We handle this step in bxt_set_cdclk(). - */ - - /* - * 12. Toggle powerdown if HDMI is enabled on C10 PHY. - * - * Wa_13013502646: - * Fixes: HDMI lane to lane skew violations on C10 display PHYs. - * Workaround: Toggle powerdown value by setting first to P0 and then to P2, for both - * PHY lanes. - */ - if (!cx0pll_state_is_dp(pll_state) && pll_state->use_c10) { - intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, - XELPDP_P0_STATE_ACTIVE); - intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, - XELPDP_P2_STATE_READY); - } - intel_cx0_phy_transaction_end(encoder, wakeref); } @@ -3403,6 +3364,56 @@ static int intel_mtl_tbt_clock_select(struct intel_display *display, } } +static void intel_cx0pll_enable_clock(struct intel_encoder *encoder, + const struct intel_cx0pll_state *pll_state) +{ + struct intel_display *display = to_intel_display(encoder); + enum phy phy = intel_encoder_to_phy(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + bool lane_reversal = dig_port->lane_reversal; + u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 : + INTEL_CX0_LANE0; + struct ref_tracker *wakeref = intel_cx0_phy_transaction_begin(encoder); + + /* + * 9. Set PORT_CLOCK_CTL register PCLK PLL Request + * LN<Lane for maxPCLK> to "1" to enable PLL. + */ + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), + intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES), + intel_cx0_get_pclk_pll_request(maxpclk_lane)); + + /* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */ + if (intel_de_wait_us(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), + intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES), + intel_cx0_get_pclk_pll_ack(maxpclk_lane), + XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, NULL)) + drm_warn(display->drm, "Port %c PLL not locked\n", + phy_name(phy)); + + /* + * 11. Follow the Display Voltage Frequency Switching Sequence After + * Frequency Change. We handle this step in bxt_set_cdclk(). + */ + + /* + * 12. Toggle powerdown if HDMI is enabled on C10 PHY. + * + * Wa_13013502646: + * Fixes: HDMI lane to lane skew violations on C10 display PHYs. + * Workaround: Toggle powerdown value by setting first to P0 and then to P2, for both + * PHY lanes. + */ + if (!cx0pll_state_is_dp(pll_state) && pll_state->use_c10) { + intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, + XELPDP_P0_STATE_ACTIVE); + intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, + XELPDP_P2_STATE_READY); + } + + intel_cx0_phy_transaction_end(encoder, wakeref); +} + void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder, int port_clock) { struct intel_display *display = to_intel_display(encoder); @@ -3468,10 +3479,16 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder, void intel_mtl_pll_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); + struct intel_dpll *pll = crtc_state->intel_dpll; struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock); + else + intel_cx0pll_enable_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); + + assert_dpll_enabled(display, pll); } /* @@ -3567,12 +3584,6 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder) * Frequency Change. We handle this step in bxt_set_cdclk(). */ - /* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */ - intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - XELPDP_DDI_CLOCK_SELECT_MASK(display), 0); - intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - XELPDP_FORWARD_CLOCK_UNGATE, 0); - intel_cx0_phy_transaction_end(encoder, wakeref); } @@ -3586,6 +3597,20 @@ static bool intel_cx0_pll_is_enabled(struct intel_encoder *encoder) intel_cx0_get_pclk_pll_request(lane); } +static void intel_cx0pll_disable_clock(struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(encoder); + struct ref_tracker *wakeref = intel_cx0_phy_transaction_begin(encoder); + + /* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */ + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), + XELPDP_DDI_CLOCK_SELECT_MASK(display), 0); + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), + XELPDP_FORWARD_CLOCK_UNGATE, 0); + + intel_cx0_phy_transaction_end(encoder, wakeref); +} + void intel_mtl_tbt_pll_disable_clock(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); @@ -3635,6 +3660,9 @@ void intel_mtl_pll_disable_clock(struct intel_encoder *encoder) if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_disable_clock(encoder); + else + intel_cx0pll_disable_clock(encoder); + } enum icl_port_dpll_id @@ -3783,6 +3811,8 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) encoder->base.base.id, encoder->base.name); intel_cx0pll_enable(encoder, &pll_state); + intel_cx0pll_enable_clock(encoder, &pll_state); intel_cx0pll_disable(encoder); + intel_cx0pll_disable_clock(encoder); } } diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 9aa84a430f09..040c97d81302 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -298,7 +298,8 @@ void intel_dpll_enable(const struct intel_crtc_state *crtc_state) if (old_mask) { drm_WARN_ON(display->drm, !pll->on); - assert_dpll_enabled(display, pll); + if (DISPLAY_VER(display) < 14) + assert_dpll_enabled(display, pll); goto out; } drm_WARN_ON(display->drm, pll->on); @@ -342,7 +343,9 @@ void intel_dpll_disable(const struct intel_crtc_state *crtc_state) pll->info->name, pll->active_mask, pll->on, crtc->base.base.id, crtc->base.name); - assert_dpll_enabled(display, pll); + if (DISPLAY_VER(display) < 14) + assert_dpll_enabled(display, pll); + drm_WARN_ON(display->drm, !pll->on); pll->active_mask &= ~pipe_mask; -- 2.34.1
