@@ -1627,3 +1627,81 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
16271627
16281628 intel_lt_phy_transaction_end (encoder , wakeref );
16291629}
1630+
1631+ void intel_lt_phy_pll_disable (struct intel_encoder * encoder )
1632+ {
1633+ struct intel_display * display = to_intel_display (encoder );
1634+ enum phy phy = intel_encoder_to_phy (encoder );
1635+ enum port port = encoder -> port ;
1636+ intel_wakeref_t wakeref ;
1637+ u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask (encoder );
1638+ u32 lane_pipe_reset = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
1639+ ? (XELPDP_LANE_PIPE_RESET (0 ) |
1640+ XELPDP_LANE_PIPE_RESET (1 ))
1641+ : XELPDP_LANE_PIPE_RESET (0 );
1642+ u32 lane_phy_current_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
1643+ ? (XELPDP_LANE_PHY_CURRENT_STATUS (0 ) |
1644+ XELPDP_LANE_PHY_CURRENT_STATUS (1 ))
1645+ : XELPDP_LANE_PHY_CURRENT_STATUS (0 );
1646+ u32 lane_phy_pulse_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
1647+ ? (XE3PLPDP_LANE_PHY_PULSE_STATUS (0 ) |
1648+ XE3PLPDP_LANE_PHY_PULSE_STATUS (1 ))
1649+ : XE3PLPDP_LANE_PHY_PULSE_STATUS (0 );
1650+
1651+ wakeref = intel_lt_phy_transaction_begin (encoder );
1652+
1653+ /* 1. Clear PORT_BUF_CTL2 [PHY Pulse Status]. */
1654+ intel_de_rmw (display , XELPDP_PORT_BUF_CTL2 (display , port ),
1655+ lane_phy_pulse_status ,
1656+ lane_phy_pulse_status );
1657+
1658+ /* 2. Set PORT_BUF_CTL2<port> Lane<PHY Lanes Owned> Pipe Reset to 1. */
1659+ intel_de_rmw (display , XELPDP_PORT_BUF_CTL2 (display , port ), lane_pipe_reset ,
1660+ lane_pipe_reset );
1661+
1662+ /* 3. Poll for PORT_BUF_CTL2<port> Lane<PHY Lanes Owned> PHY Current Status == 1. */
1663+ if (intel_de_wait_custom (display , XELPDP_PORT_BUF_CTL2 (display , port ),
1664+ lane_phy_current_status ,
1665+ lane_phy_current_status ,
1666+ XE3PLPD_RESET_START_LATENCY_US , 0 , NULL ))
1667+ drm_warn (display -> drm ,
1668+ "PHY %c failed to reset Lane after %dms.\n" ,
1669+ phy_name (phy ), XE3PLPD_RESET_START_LATENCY_US );
1670+
1671+ /* 4. Clear for PHY pulse status on owned PHY lanes. */
1672+ intel_de_rmw (display , XELPDP_PORT_BUF_CTL2 (display , port ),
1673+ lane_phy_pulse_status ,
1674+ lane_phy_pulse_status );
1675+
1676+ /*
1677+ * 5. Follow the Display Voltage Frequency Switching -
1678+ * Sequence Before Frequency Change. We handle this step in bxt_set_cdclk().
1679+ */
1680+ /* 6. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */
1681+ intel_de_rmw (display , XELPDP_PORT_CLOCK_CTL (display , port ),
1682+ XELPDP_LANE_PCLK_PLL_REQUEST (0 ), 0 );
1683+
1684+ /* 7. Program DDI_CLK_VALFREQ to 0. */
1685+ intel_de_write (display , DDI_CLK_VALFREQ (encoder -> port ), 0 );
1686+
1687+ /* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */
1688+ if (intel_de_wait_custom (display , XELPDP_PORT_CLOCK_CTL (display , port ),
1689+ XELPDP_LANE_PCLK_PLL_ACK (0 ), 0 ,
1690+ XE3PLPD_MACCLK_TURNOFF_LATENCY_US , 0 , NULL ))
1691+ drm_warn (display -> drm , "PHY %c PLL MacCLK Ack deassertion Timeout after %dus.\n" ,
1692+ phy_name (phy ), XE3PLPD_MACCLK_TURNOFF_LATENCY_US );
1693+
1694+ /*
1695+ * 9. Follow the Display Voltage Frequency Switching -
1696+ * Sequence After Frequency Change. We handle this step in bxt_set_cdclk().
1697+ */
1698+ /* 10. Program PORT_CLOCK_CTL register to disable and gate clocks. */
1699+ intel_de_rmw (display , XELPDP_PORT_CLOCK_CTL (display , port ),
1700+ XELPDP_DDI_CLOCK_SELECT_MASK (display ) | XELPDP_FORWARD_CLOCK_UNGATE , 0 );
1701+
1702+ /* 11. Program PORT_BUF_CTL5[MacCLK Reset_0] = 1 to assert MacCLK reset. */
1703+ intel_de_rmw (display , XE3PLPD_PORT_BUF_CTL5 (port ),
1704+ XE3PLPD_MACCLK_RESET_0 , XE3PLPD_MACCLK_RESET_0 );
1705+
1706+ intel_lt_phy_transaction_end (encoder , wakeref );
1707+ }
0 commit comments