diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi index 9a5de9526c19..71a1608f09a9 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -755,8 +755,8 @@ <&mdss_dsi1_pll clk_dsi1pll_pclk_mux>, <&mdss_dsi0_pll clk_dsi0pll_byteclk_mux>, <&mdss_dsi1_pll clk_dsi1pll_byteclk_mux>, - <&mdss_dp_pll clk_dp_link_2x_clk_mux>, - <&mdss_dp_pll clk_vco_divided_clk_src>, + <&mdss_dp_pll clk_dp_link_2x_clk_divsel_five>, + <&mdss_dp_pll clk_vco_divided_clk_src_mux>, <&mdss_hdmi_pll clk_hdmi_vco_clk>; #clock-cells = <1>; }; diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c index 123a5ae09fa8..c88a5089bd60 100644 --- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c +++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c @@ -49,13 +49,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div) link2xclk_div_tx1 |= 0x4; /*configure DP PHY MODE */ - phy_mode = 0x48; + phy_mode = 0x58; - if (div == 10) { - link2xclk_div_tx0 |= 1; - link2xclk_div_tx1 |= 1; - phy_mode |= 1; - } MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_BAND, link2xclk_div_tx0); @@ -64,7 +59,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div) link2xclk_div_tx1); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, phy_mode); - + /* Make sure the PHY register writes are done */ + wmb(); pr_debug("%s: div=%d link2xclk_div_tx0=%x, link2xclk_div_tx1=%x\n", __func__, div, link2xclk_div_tx0, link2xclk_div_tx1); @@ -105,63 +101,6 @@ int link2xclk_divsel_get_div(struct div_clk *clk) return div; } -int hsclk_divsel_set_div(struct div_clk *clk, int div) -{ - int rc; - u32 hsclk_div; - struct mdss_pll_resources *dp_res = clk->priv; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP PLL resources\n"); - return rc; - } - - hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); - hsclk_div &= ~0x0f; /* bits 0 to 3 */ - - if (div == 3) - hsclk_div |= 4; - else - hsclk_div |= 0; - - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_HSCLK_SEL, hsclk_div); - - pr_debug("%s: div=%d hsclk_div=%x\n", __func__, div, hsclk_div); - - mdss_pll_resource_enable(dp_res, false); - - return rc; -} - -int hsclk_divsel_get_div(struct div_clk *clk) -{ - int rc; - u32 hsclk_div, div; - struct mdss_pll_resources *dp_res = clk->priv; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable dp_res resources\n"); - return rc; - } - - hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); - hsclk_div &= 0x0f; - - if (hsclk_div == 4) - div = 3; - else - div = 2; - - mdss_pll_resource_enable(dp_res, false); - - pr_debug("%s: hsclk_div:%d, div=%d\n", __func__, hsclk_div, div); - - return div; -} - int vco_divided_clk_set_div(struct div_clk *clk, int div) { int rc; @@ -174,18 +113,18 @@ int vco_divided_clk_set_div(struct div_clk *clk, int div) return rc; } - auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV); + auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); auxclk_div &= ~0x03; /* bits 0 to 1 */ + + auxclk_div |= 1; /* Default divider */ + if (div == 4) auxclk_div |= 2; - else if (div == 2) - auxclk_div |= 1; - else - auxclk_div |= 2; /* Default divider */ - MDSS_PLL_REG_W(dp_res->pll_base, + MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, auxclk_div); - + /* Make sure the PHY registers writes are done */ + wmb(); pr_debug("%s: div=%d auxclk_div=%x\n", __func__, div, auxclk_div); mdss_pll_resource_enable(dp_res, false); @@ -215,15 +154,12 @@ int vco_divided_clk_get_div(struct div_clk *clk) return rc; } - auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV); + auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); auxclk_div &= 0x03; + div = 2; /* Default divider */ if (auxclk_div == 2) div = 4; - else if (auxclk_div == 1) - div = 2; - else - div = 0; mdss_pll_resource_enable(dp_res, false); @@ -239,14 +175,12 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x3d); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_PLL_IVCO, 0x0f); + /* Make sure the PHY register writes are done */ + wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_SYS_CLK_CTRL, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0e); @@ -255,16 +189,16 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_SEL, 0x30); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP_EN, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_PLL_CCTRL_MODE0, 0x34); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_PLL_RCTRL_MODE0, 0x16); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CP_CTRL_MODE0, 0x08); /* Different for each clock rates */ - if (rate == DP_VCO_RATE_8100MHz) { + if (rate == DP_VCO_HSCLK_RATE_1620MHz) { + pr_debug("%s: VCO rate: %lld\n", __func__, + DP_VCO_RATE_8100MHz); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_SYS_CLK_CTRL, 0x02); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_HSCLK_SEL, 0x2c); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP_EN, 0x04); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x69); MDSS_PLL_REG_W(dp_res->pll_base, @@ -273,16 +207,48 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07); - } else if (rate == DP_VCO_RATE_9720MHz) { MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DEC_START_MODE0, 0x7e); + QSERDES_COM_CMN_CONFIG, 0x42); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP1_MODE0, 0xbf); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP2_MODE0, 0x21); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP3_MODE0, 0x00); + } else if (rate == DP_VCO_HSCLK_RATE_2700MHz) { + pr_debug("%s: VCO rate: %lld\n", __func__, + DP_VCO_RATE_8100MHz); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_SYS_CLK_CTRL, 0x06); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_HSCLK_SEL, 0x84); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP_EN, 0x08); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_DEC_START_MODE0, 0x69); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); + QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, 0x09); - } else if (rate == DP_VCO_RATE_10800MHz) { + QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_CMN_CONFIG, 0x02); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP1_MODE0, 0x3f); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP2_MODE0, 0x38); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP3_MODE0, 0x00); + } else if (rate == DP_VCO_HSCLK_RATE_5400MHz) { + pr_debug("%s: VCO rate: %lld\n", __func__, + DP_VCO_RATE_10800MHz); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_SYS_CLK_CTRL, 0x06); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_HSCLK_SEL, 0x80); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP_EN, 0x08); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x8c); MDSS_PLL_REG_W(dp_res->pll_base, @@ -290,11 +256,32 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a); + QSERDES_COM_DIV_FRAC_START3_MODE0, 0xa0); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_CMN_CONFIG, 0x12); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP1_MODE0, 0x7f); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP2_MODE0, 0x70); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else { pr_err("%s: unsupported rate: %ld\n", __func__, rate); return -EINVAL; } + /* Make sure the PLL register writes are done */ + wmb(); + + if ((rate == DP_VCO_HSCLK_RATE_1620MHz) + || (rate == DP_VCO_HSCLK_RATE_2700MHz)) { + MDSS_PLL_REG_W(dp_res->phy_base, + DP_PHY_VCO_DIV, 0x1); + } else { + MDSS_PLL_REG_W(dp_res->phy_base, + DP_PHY_VCO_DIV, 0x2); + } + /* Make sure the PHY register writes are done */ + wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f); @@ -303,29 +290,6 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_MAP, 0x00); - if (rate == DP_VCO_RATE_8100MHz) { - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP1_MODE0, 0x3f); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP2_MODE0, 0x38); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP3_MODE0, 0x00); - } else if (rate == DP_VCO_RATE_9720MHz) { - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP1_MODE0, 0x7f); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP2_MODE0, 0x43); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP3_MODE0, 0x00); - } else { - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP1_MODE0, 0x7f); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP2_MODE0, 0x70); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP3_MODE0, 0x00); - } - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BG_TIMER, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, @@ -334,22 +298,28 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) QSERDES_COM_CORECLK_DIV_MODE0, 0x05); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_CTRL, 0x00); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_CP_CTRL_MODE0, 0x06); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_PLL_CCTRL_MODE0, 0x36); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_PLL_RCTRL_MODE0, 0x16); + MDSS_PLL_REG_W(dp_res->pll_base, + QSERDES_COM_PLL_IVCO, 0x07); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x37); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORE_CLK_EN, 0x0f); - /* Different for each clock rate */ - if (rate == DP_VCO_RATE_8100MHz) { - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CMN_CONFIG, 0x02); - } else if (rate == DP_VCO_RATE_9720MHz) { - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CMN_CONFIG, 0x02); - } else { - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CMN_CONFIG, 0x02); - } + /* Make sure the PLL register writes are done */ + wmb(); + + MDSS_PLL_REG_W(dp_res->phy_base, + DP_PHY_MODE, 0x58); + MDSS_PLL_REG_W(dp_res->phy_base, + DP_PHY_TX0_TX1_LANE_CTL, 0x05); + MDSS_PLL_REG_W(dp_res->phy_base, + DP_PHY_TX2_TX3_LANE_CTL, 0x05); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, @@ -357,36 +327,14 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, - 0x00); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, - 0x00); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, - 0x38); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, - 0x38); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, - 0x2c); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, - 0x2c); - - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_TX0_TX1_LANE_CTL, 0x05); - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_TX2_TX3_LANE_CTL, 0x05); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1, 0x40); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1, 0x40); + MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, 0x30); @@ -429,6 +377,15 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE, 0x00); + + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_TX_BAND, + 0x4); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_TX_BAND, + 0x4); + /* Make sure the PHY register writes are done */ + wmb(); return res; } @@ -479,9 +436,12 @@ static int dp_pll_enable(struct clk *c) DP_PHY_CFG, 0x01); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); + /* Make sure the PHY register writes are done */ + wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); - + /* Make sure the PLL register writes are done */ + wmb(); /* poll for PLL ready status */ if (readl_poll_timeout_atomic((dp_res->pll_base + QSERDES_COM_C_READY_STATUS), @@ -497,7 +457,8 @@ static int dp_pll_enable(struct clk *c) MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); - + /* Make sure the PHY register writes are done */ + wmb(); /* poll for PHY ready status */ if (readl_poll_timeout_atomic((dp_res->phy_base + DP_PHY_STATUS), @@ -513,17 +474,17 @@ static int dp_pll_enable(struct clk *c) pr_debug("%s: PLL is locked\n", __func__); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, - 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, + QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, + QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, + 0x3f); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_POL_INV, @@ -533,6 +494,8 @@ static int dp_pll_enable(struct clk *c) 0x0a); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x18); + udelay(2000); + MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); @@ -542,6 +505,77 @@ static int dp_pll_enable(struct clk *c) */ wmb(); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_LANE_MODE_1, + 0xf6); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_LANE_MODE_1, + 0xf6); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, + 0x1f); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, + 0x1f); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, + 0x0f); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, + 0x0f); + /* + * Make sure all the register writes are completed before + * doing any other operation + */ + wmb(); + + MDSS_PLL_REG_W(dp_res->phy_base, + DP_PHY_CFG, 0x09); + udelay(2000); + + MDSS_PLL_REG_W(dp_res->phy_base, + DP_PHY_CFG, 0x19); + udelay(2000); + /* poll for PHY ready status */ + if (readl_poll_timeout_atomic((dp_res->phy_base + + DP_PHY_STATUS), + status, + ((status & BIT(1)) > 0), + DP_PLL_POLL_SLEEP_US, + DP_PLL_POLL_TIMEOUT_US)) { + pr_err("%s: Lane_mode: Phy_ready is not high. Status=%x\n", + __func__, status); + rc = -EINVAL; + goto lock_err; + } + + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, + 0x2a); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, + 0x2a); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, + 0x20); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, + 0x20); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, + 0x11); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, + 0x11); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, + 0x11); + MDSS_PLL_REG_W(dp_res->phy_base, + QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, + 0x11); + /* Make sure the PHY register writes are done */ + wmb(); + lock_err: return rc; } @@ -554,7 +588,7 @@ static int dp_pll_disable(struct clk *c) /* Assert DP PHY power down */ MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_PD_CTL, 0x3c); + DP_PHY_PD_CTL, 0x2); /* * Make sure all the register writes to disable PLL are * completed before doing any other operation @@ -655,14 +689,20 @@ unsigned long dp_vco_get_rate(struct clk *c) div = MDSS_PLL_REG_R(pll->pll_base, QSERDES_COM_HSCLK_SEL); div &= 0x0f; - if (div == 4) + if (div == 12) + hsclk_div = 5; /* Default */ + else if (div == 4) hsclk_div = 3; - else + else if (div == 0) hsclk_div = 2; + else { + pr_debug("unknown divider. forcing to default\n"); + hsclk_div = 5; + } div = MDSS_PLL_REG_R(pll->phy_base, DP_PHY_MODE); - if (div & 0x48) + if (div & 0x58) pr_err("%s: DP PAR Rate not correct\n", __func__); if ((div & 0x3) == 1) @@ -673,12 +713,14 @@ unsigned long dp_vco_get_rate(struct clk *c) pr_err("%s: unsupported div. Phy_mode: %d\n", __func__, div); if (link2xclk_div == 10) { - vco_rate = DP_VCO_RATE_9720MHz; + vco_rate = DP_VCO_HSCLK_RATE_2700MHz; } else { - if (hsclk_div == 3) - vco_rate = DP_VCO_RATE_8100MHz; + if (hsclk_div == 5) + vco_rate = DP_VCO_HSCLK_RATE_1620MHz; + else if (hsclk_div == 3) + vco_rate = DP_VCO_HSCLK_RATE_2700MHz; else - vco_rate = DP_VCO_RATE_10800MHz; + vco_rate = DP_VCO_HSCLK_RATE_5400MHz; } pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); @@ -695,8 +737,8 @@ long dp_vco_round_rate(struct clk *c, unsigned long rate) if (rate <= vco->min_rate) rrate = vco->min_rate; - else if (rate <= DP_VCO_RATE_9720MHz) - rrate = DP_VCO_RATE_9720MHz; + else if (rate <= DP_VCO_HSCLK_RATE_2700MHz) + rrate = DP_VCO_HSCLK_RATE_2700MHz; else rrate = vco->max_rate; diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.c b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.c index 8b06f07b00ee..47b5bd7d7579 100644 --- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.c +++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.c @@ -16,40 +16,37 @@ ******** Display Port PLL driver block diagram for branch clocks ********** *************************************************************************** - +-------------------+ - | dp_vco_clk | - | (DP PLL/VCO) | - +---------+---------+ - | - | - v - +----------+-----------+ - | hsclk_divsel_clk_src | - +----------+-----------+ - | + +--------------------------+ + | DP_VCO_CLK | + | | + | +-------------------+ | + | | (DP PLL/VCO) | | + | +---------+---------+ | + | v | + | +----------+-----------+ | + | | hsclk_divsel_clk_src | | + | +----------+-----------+ | + +--------------------------+ | v +------------<------------|------------>-------------+ | | | - | | | +----------v----------+ +----------v----------+ +----------v----------+ -|vco_divided_clk_src | | dp_link_2x_clk | | dp_link_2x_clk | -| (aux_clk_ops) | | | | | -v----------+----------v | divsel_five | | divsel_ten | +| dp_link_2x_clk | | vco_divided_clk_src | | vco_divided_clk_src | +| divsel_five | | | | | +v----------+----------v | divsel_two | | divsel_four | | +----------+----------+ +----------+----------+ | | | v v v - | +--------------------+ | - Input to MMSSCC block | | | | - for DP pixel clock +--> dp_link_2x_clk_mux <--+ - | | - +----------+---------+ + | +---------------------+ | + Input to MMSSCC block | | (aux_clk_ops) | | + for link clk, crypto clk +--> vco_divided_clk <-+ + and interface clock | _src_mux | + +----------+----------+ | v Input to MMSSCC block - for link clk, crypto clk - and interface clock - + for DP pixel clock ****************************************************************************** */ @@ -68,14 +65,9 @@ v----------+----------v | divsel_five | | divsel_ten | #include "mdss-dp-pll.h" #include "mdss-dp-pll-cobalt.h" -static struct clk_ops clk_ops_hsclk_divsel_clk_src_c; static struct clk_ops clk_ops_vco_divided_clk_src_c; static struct clk_ops clk_ops_link_2x_clk_div_c; - -static struct clk_div_ops hsclk_divsel_ops = { - .set_div = hsclk_divsel_set_div, - .get_div = hsclk_divsel_get_div, -}; +static struct clk_ops clk_ops_gen_mux_dp; static struct clk_div_ops link2xclk_divsel_ops = { .set_div = link2xclk_divsel_set_div, @@ -101,8 +93,8 @@ static struct clk_mux_ops mdss_mux_ops = { }; static struct dp_pll_vco_clk dp_vco_clk = { - .min_rate = DP_VCO_RATE_8100MHz, - .max_rate = DP_VCO_RATE_10800MHz, + .min_rate = DP_VCO_HSCLK_RATE_1620MHz, + .max_rate = DP_VCO_HSCLK_RATE_5400MHz, .c = { .dbg_name = "dp_vco_clk", .ops = &dp_cobalt_vco_clk_ops, @@ -111,21 +103,6 @@ static struct dp_pll_vco_clk dp_vco_clk = { }, }; -static struct div_clk hsclk_divsel_clk_src = { - .data = { - .min_div = 2, - .max_div = 3, - }, - .ops = &hsclk_divsel_ops, - .c = { - .parent = &dp_vco_clk.c, - .dbg_name = "hsclk_divsel_clk_src", - .ops = &clk_ops_hsclk_divsel_clk_src_c, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(hsclk_divsel_clk_src.c), - }, -}; - static struct div_clk dp_link_2x_clk_divsel_five = { .data = { .div = 5, @@ -134,7 +111,7 @@ static struct div_clk dp_link_2x_clk_divsel_five = { }, .ops = &link2xclk_divsel_ops, .c = { - .parent = &hsclk_divsel_clk_src.c, + .parent = &dp_vco_clk.c, .dbg_name = "dp_link_2x_clk_divsel_five", .ops = &clk_ops_link_2x_clk_div_c, .flags = CLKFLAG_NO_RATE_CACHE, @@ -142,39 +119,7 @@ static struct div_clk dp_link_2x_clk_divsel_five = { }, }; -static struct div_clk dp_link_2x_clk_divsel_ten = { - .data = { - .div = 10, - .min_div = 10, - .max_div = 10, - }, - .ops = &link2xclk_divsel_ops, - .c = { - .parent = &hsclk_divsel_clk_src.c, - .dbg_name = "dp_link_2x_clk_divsel_ten", - .ops = &clk_ops_link_2x_clk_div_c, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dp_link_2x_clk_divsel_ten.c), - }, -}; - -static struct mux_clk dp_link_2x_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dp_link_2x_clk_divsel_five.c, 0}, - {&dp_link_2x_clk_divsel_ten.c, 1}, - }, - .ops = &mdss_mux_ops, - .c = { - .parent = &dp_link_2x_clk_divsel_five.c, - .dbg_name = "dp_link_2x_clk_mux", - .ops = &clk_ops_gen_mux, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dp_link_2x_clk_mux.c), - } -}; - -static struct div_clk vco_divided_clk_src = { +static struct div_clk vco_divsel_four_clk_src = { .data = { .div = 4, .min_div = 4, @@ -182,21 +127,52 @@ static struct div_clk vco_divided_clk_src = { }, .ops = &vco_divided_clk_ops, .c = { - .parent = &hsclk_divsel_clk_src.c, - .dbg_name = "vco_divided_clk", + .parent = &dp_vco_clk.c, + .dbg_name = "vco_divsel_four_clk_src", .ops = &clk_ops_vco_divided_clk_src_c, .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(vco_divided_clk_src.c), + CLK_INIT(vco_divsel_four_clk_src.c), }, }; +static struct div_clk vco_divsel_two_clk_src = { + .data = { + .div = 2, + .min_div = 2, + .max_div = 2, + }, + .ops = &vco_divided_clk_ops, + .c = { + .parent = &dp_vco_clk.c, + .dbg_name = "vco_divsel_two_clk_src", + .ops = &clk_ops_vco_divided_clk_src_c, + .flags = CLKFLAG_NO_RATE_CACHE, + CLK_INIT(vco_divsel_two_clk_src.c), + }, +}; + +static struct mux_clk vco_divided_clk_src_mux = { + .num_parents = 2, + .parents = (struct clk_src[]) { + {&vco_divsel_two_clk_src.c, 0}, + {&vco_divsel_four_clk_src.c, 1}, + }, + .ops = &mdss_mux_ops, + .c = { + .parent = &vco_divsel_two_clk_src.c, + .dbg_name = "vco_divided_clk_src_mux", + .ops = &clk_ops_gen_mux_dp, + .flags = CLKFLAG_NO_RATE_CACHE, + CLK_INIT(vco_divided_clk_src_mux.c), + } +}; + static struct clk_lookup dp_pllcc_cobalt[] = { CLK_LIST(dp_vco_clk), - CLK_LIST(hsclk_divsel_clk_src), CLK_LIST(dp_link_2x_clk_divsel_five), - CLK_LIST(dp_link_2x_clk_divsel_ten), - CLK_LIST(dp_link_2x_clk_mux), - CLK_LIST(vco_divided_clk_src), + CLK_LIST(vco_divsel_four_clk_src), + CLK_LIST(vco_divsel_two_clk_src), + CLK_LIST(vco_divided_clk_src_mux), }; int dp_pll_clock_register_cobalt(struct platform_device *pdev, @@ -211,14 +187,10 @@ int dp_pll_clock_register_cobalt(struct platform_device *pdev, /* Set client data for vco, mux and div clocks */ dp_vco_clk.priv = pll_res; - hsclk_divsel_clk_src.priv = pll_res; - dp_link_2x_clk_mux.priv = pll_res; - vco_divided_clk_src.priv = pll_res; + vco_divided_clk_src_mux.priv = pll_res; + vco_divsel_two_clk_src.priv = pll_res; + vco_divsel_four_clk_src.priv = pll_res; dp_link_2x_clk_divsel_five.priv = pll_res; - dp_link_2x_clk_divsel_ten.priv = pll_res; - - clk_ops_hsclk_divsel_clk_src_c = clk_ops_div; - clk_ops_hsclk_divsel_clk_src_c.prepare = mdss_pll_div_prepare; clk_ops_link_2x_clk_div_c = clk_ops_div; clk_ops_link_2x_clk_div_c.prepare = mdss_pll_div_prepare; @@ -233,6 +205,9 @@ int dp_pll_clock_register_cobalt(struct platform_device *pdev, clk_ops_vco_divided_clk_src_c.prepare = mdss_pll_div_prepare; clk_ops_vco_divided_clk_src_c.handoff = vco_divided_clk_handoff; + clk_ops_gen_mux_dp = clk_ops_gen_mux; + clk_ops_gen_mux_dp.get_rate = parent_get_rate; + /* We can select different clock ops for future versions */ dp_vco_clk.c.ops = &dp_cobalt_vco_clk_ops; diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h index 290933c0cbb4..d2b5d98a2d41 100644 --- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h +++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt.h @@ -59,12 +59,19 @@ #define TXn_SLEW_CNTL 0x0030 #define TXn_INTERFACE_SELECT 0x0034 +#define TXn_RES_CODE_LANE_TX 0x003C +#define TXn_RES_CODE_LANE_RX 0x0040 +#define TXn_RES_CODE_LANE_OFFSET_TX 0x0044 +#define TXn_RES_CODE_LANE_OFFSET_RX 0x0048 + #define TXn_DEBUG_BUS_SEL 0x0058 #define TXn_TRANSCEIVER_BIAS_EN 0x005C #define TXn_HIGHZ_DRVR_EN 0x0060 #define TXn_TX_POL_INV 0x0064 #define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068 +#define TXn_LANE_MODE_1 0x008C + #define TXn_TRAN_DRVR_EMP_EN 0x00C0 #define TXn_TX_INTERFACE_MODE 0x00C4 @@ -149,9 +156,12 @@ #define DP_PLL_POLL_TIMEOUT_US 10000 #define DP_VCO_RATE_8100MHz 8100000000ULL -#define DP_VCO_RATE_9720MHz 9720000000ULL #define DP_VCO_RATE_10800MHz 10800000000ULL +#define DP_VCO_HSCLK_RATE_1620MHz 1620000000ULL +#define DP_VCO_HSCLK_RATE_2700MHz 2700000000ULL +#define DP_VCO_HSCLK_RATE_5400MHz 5400000000ULL + int dp_vco_set_rate(struct clk *c, unsigned long rate); unsigned long dp_vco_get_rate(struct clk *c); long dp_vco_round_rate(struct clk *c, unsigned long rate); diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index fc24bb53a61c..0bbcd0c9041e 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -1109,16 +1109,16 @@ static void dp_host_train_set(struct mdss_dp_drv_pdata *ep, int train) } char vm_pre_emphasis[4][4] = { - {0x03, 0x06, 0x09, 0x0C}, /* pe0, 0 db */ - {0x03, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */ + {0x00, 0x06, 0x09, 0x0C}, /* pe0, 0 db */ + {0x00, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */ {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */ {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */ }; /* voltage swing, 0.2v and 1.0v are not support */ char vm_voltage_swing[4][4] = { - {0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */ - {0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */ + {0x0a, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */ + {0x07, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */ {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */ {0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */ }; diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index c501ed3bcd9d..62b76199959c 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -246,13 +246,13 @@ void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io) { writel_relaxed(0x3d, phy_io->base + DP_PHY_PD_CTL); - writel_relaxed(0x03, phy_io->base + DP_PHY_AUX_CFG1); - writel_relaxed(0x00, phy_io->base + DP_PHY_AUX_CFG3); + writel_relaxed(0x13, phy_io->base + DP_PHY_AUX_CFG1); + writel_relaxed(0x10, phy_io->base + DP_PHY_AUX_CFG3); writel_relaxed(0x0a, phy_io->base + DP_PHY_AUX_CFG4); writel_relaxed(0x26, phy_io->base + DP_PHY_AUX_CFG5); writel_relaxed(0x0a, phy_io->base + DP_PHY_AUX_CFG6); writel_relaxed(0x03, phy_io->base + DP_PHY_AUX_CFG7); - writel_relaxed(0xbb, phy_io->base + DP_PHY_AUX_CFG8); + writel_relaxed(0x8b, phy_io->base + DP_PHY_AUX_CFG8); writel_relaxed(0x03, phy_io->base + DP_PHY_AUX_CFG9); writel_relaxed(0x1f, phy_io->base + DP_PHY_AUX_INTERRUPT_MASK); } diff --git a/include/dt-bindings/clock/msm-clocks-cobalt.h b/include/dt-bindings/clock/msm-clocks-cobalt.h index efbc91093e40..69b6b60e1a6b 100644 --- a/include/dt-bindings/clock/msm-clocks-cobalt.h +++ b/include/dt-bindings/clock/msm-clocks-cobalt.h @@ -465,11 +465,10 @@ #define clk_dsi1pll_vco_clk 0x99797b50 #define clk_dp_vco_clk 0xfcaaeec7 -#define clk_hsclk_divsel_clk_src 0x0a325543 #define clk_dp_link_2x_clk_divsel_five 0xcfe3f5dd -#define clk_dp_link_2x_clk_divsel_ten 0xfeb9924d -#define clk_dp_link_2x_clk_mux 0xce4c4fc6 -#define clk_vco_divided_clk_src 0x3da6cb51 +#define clk_vco_divsel_four_clk_src 0xe0da19c0 +#define clk_vco_divsel_two_clk_src 0xb5cfc6a8 +#define clk_vco_divided_clk_src_mux 0x3f8197c2 #define clk_hdmi_vco_clk 0xbb7dc20d /* clock_gpu controlled clocks*/