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

This commit is contained in:
Linux Build Service Account 2016-08-26 14:48:35 -07:00 committed by Gerrit - the friendly Code Review server
commit c59ad8da42
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

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

View file

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