MLK-19745 drm: imx: hdp: Add PHY clock shutdown/startup for DP mode change
authorOliver Brown <oliver.brown@nxp.com>
Wed, 26 Sep 2018 22:40:01 +0000 (17:40 -0500)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
The PHY specification recommends stopping/starting the PHY clocks during a
video mode change.

Signed-off-by: Oliver Brown <oliver.brown@nxp.com>
drivers/gpu/drm/imx/hdp/API_AFE_mcu2_dp.c
drivers/mxc/hdp/util.h

index 050e1ec..900f126 100644 (file)
@@ -463,6 +463,9 @@ static void aux_cfg_t28hpc(state_struct *state)
 #endif
 }
 
+static void afe_disable_phy_clocks(state_struct *state);
+static void afe_enable_phy_clocks(state_struct *state);
+
 void afe_init_t28hpc(state_struct *state,
                     int num_lanes,
                     ENUM_AFE_LINK_RATE link_rate)
@@ -477,6 +480,8 @@ void afe_init_t28hpc(state_struct *state,
                       link_rate);
                return;
        }
+       if (state->phy_init)
+               afe_disable_phy_clocks(state);
 
        if (phy_reset_workaround) {
                int k;
@@ -535,7 +540,7 @@ void afe_init_t28hpc(state_struct *state,
 
        /* for differential clock on the refclk_p and refclk_m off chip pins:
         * PHY_PMA_CMN_CTRL1[6:4]=3'b000
-        * val = val | 0x0030;
+        * val = val | 0x0000;
         */
        val = val | 0x0000; /* select external reference */
        Afe_write(state, PHY_PMA_CMN_CTRL1, val);
@@ -592,6 +597,10 @@ void afe_power_t28hpc(state_struct *state,
                       __func__, link_rate);
                return;
        }
+       if (state->phy_init)
+               afe_enable_phy_clocks(state);
+       else
+               state->phy_init = 1;
 
        Afe_write(state, TX_DIAG_ACYA_0, 1);
        Afe_write(state, TX_DIAG_ACYA_1, 1);
@@ -623,3 +632,80 @@ void afe_power_t28hpc(state_struct *state,
        aux_cfg_t28hpc(state);
 
 }
+
+static void afe_disable_phy_clocks(state_struct *state)
+{
+       unsigned short val;
+       int i = 0;
+
+       /* Write PHY_HDP_MODE_CTL[3:0] with 0b1000. (Place the PHY lanes in
+        * the A3 power state.)
+        */
+       Afe_write(state, PHY_HDP_MODE_CTRL, 0x8);
+
+       /* Wait for PHY_HDP_MODE_CTL[7:4] == 0b1000 */
+       do {
+               val = Afe_read(state, PHY_HDP_MODE_CTRL);
+               val = val >> 7;
+               if (i++ % 10000 == 0)
+                       pr_info("Wait for A3 ACK\n");
+       } while ((val & 1) !=  1);
+
+       /* gate PLL clocks */
+       val = Afe_read(state, PHY_HDP_CLK_CTL);
+       val &= ~(1 << 2);
+       Afe_write(state, PHY_HDP_CLK_CTL, val);
+
+       /* Wait for PHY_HDP_CLK_CTL[bit 3] == 0  */
+       do {
+               val = Afe_read(state, PHY_HDP_CLK_CTL);
+               val = val >> 3;
+               if (i++ % 10000 == 0)
+                       pr_info("Wait for PHY_HDP_CLK_CTL[bit 3] == 0\n");
+       } while ((val & 1) !=  0);
+
+       /* disable PLL */
+       val = Afe_read(state, PHY_HDP_CLK_CTL);
+       val &= ~(1 << 0);
+       Afe_write(state, PHY_HDP_CLK_CTL, val);
+
+       /* Wait for PHY_HDP_CLK_CTL[bit 1] == 0  */
+       do {
+               val = Afe_read(state, PHY_HDP_CLK_CTL);
+               val = val >> 1;
+               if (i++ % 10000 == 0)
+                       pr_info("Wait for PHY_HDP_CLK_CTL[bit 1] == 0\n");
+       } while ((val & 1) !=  0);
+}
+
+static void afe_enable_phy_clocks(state_struct *state)
+{
+       unsigned short val;
+       int i = 0;
+
+       /* enable PLL */
+       val = Afe_read(state, PHY_HDP_CLK_CTL);
+       val |= (1 << 0);
+       Afe_write(state, PHY_HDP_CLK_CTL, val);
+
+       /* Wait for PHY_HDP_CLK_CTL[bit 1] == 0  */
+       do {
+               val = Afe_read(state, PHY_HDP_CLK_CTL);
+               val = val >> 1;
+               if (i++ % 10000 == 0)
+                       pr_info("Wait until PHY_HDP_CLK_CTL[bit 1] != 0\n");
+       } while ((val & 1) ==  0);
+
+       /* ungate PLL clocks */
+       val = Afe_read(state, PHY_HDP_CLK_CTL);
+       val |= (1 << 2);
+       Afe_write(state, PHY_HDP_CLK_CTL, val);
+
+       /* Wait for PHY_HDP_CLK_CTL[bit 3] == 0  */
+       do {
+               val = Afe_read(state, PHY_HDP_CLK_CTL);
+               val = val >> 3;
+               if (i++ % 10000 == 0)
+                       pr_info("Wait until PHY_HDP_CLK_CTL[bit 3] != 0\n");
+       } while ((val & 1) == 0);
+}
index a034752..f92900c 100644 (file)
@@ -203,6 +203,7 @@ typedef struct {
        CDN_BUS_TYPE bus_type;
        u32 tmp;
        u32 edp; /* use eDP */
+       u8 phy_init;
 
        struct mutex mutex;     //mutex may replace running
        struct hdp_mem *mem;