clk: msm: mdss: update Dp PLL/Phy configuration

Update the Display-Port PHY and PLL configuration
with the recommended settings. Remove the
support for 9.72Ghz VCO frequency. Update the divider
settings to support the new frequency plan.
Update the Phy Aux settings and voltage/pre-emphasis
settings according to recommended configuration.

Change-Id: Ic4d206da3dc6b45214e7601e7556cfb0bef81a7d
Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
This commit is contained in:
Chandan Uddaraju 2016-08-08 09:56:03 -07:00
parent 9ec9267905
commit 3156dc80cb
7 changed files with 303 additions and 277 deletions

View file

@ -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>;
};

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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 */
};

View file

@ -239,13 +239,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);
}

View file

@ -463,11 +463,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*/