/* * before enabling the PLL, configure the bit clock divider since we * don't expose it as a clock to the outside world * 1: read back the byte clock divider that should already be set * 2: divide by 8 to get bit clock divider * 3: write it to POSTDIV1
*/
val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
byte_div = val + 1;
bit_div = byte_div / 8;
val = readl(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
val &= ~0xf;
val |= (bit_div - 1);
writel(val, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
/* enable the PLL */
writel(DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE,
base + REG_DSI_28nm_8960_PHY_PLL_CTRL_0);
/* * Custom byte clock divier clk_ops * * This clock is the entry point to configuring the PLL. The user (dsi host) * will set this clock's rate to the desired byte clock rate. The VCO lock * frequency is a multiple of the byte clock rate. The multiplication factor * (shown as F in the diagram above) is a function of the byte clock rate. * * This custom divider clock ensures that its parent (VCO) is set to the * desired rate, and that the byte clock postdivider (POSTDIV2) is configured * accordingly
*/ #define to_clk_bytediv(_hw) container_of(_hw, struct clk_bytediv, hw)
/* find multiplication factor(wrt byte clock) at which the VCO should be set */ staticunsignedint get_vco_mul_factor(unsignedlong byte_clk_rate)
{ unsignedlong bit_mhz;
/* convert to bit clock in Mhz */
bit_mhz = (byte_clk_rate * 8) / 1000000;
ret = dsi_pll_28nm_clk_set_rate(phy->vco_hw,
cached_state->vco_rate, 0); if (ret) {
DRM_DEV_ERROR(&pll_28nm->phy->pdev->dev, "restore vco rate failed. ret=%d\n", ret); return ret;
}
writel(cached_state->postdiv3, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_10);
writel(cached_state->postdiv2, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
writel(cached_state->postdiv1, base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2);
writel(0, base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_6);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_7);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_8);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_9);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_10);
writel(DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(0),
base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_11);
}
writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0);
writel(1, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1);
writel(1, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2);
writel(0, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3);
writel(0x100, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4);
}
writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0);
writel(0xa, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1);
writel(0x4, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2);
writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3);
writel(0x20, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4);
}
staticvoid dsi_28nm_phy_calibration(struct msm_dsi_phy *phy)
{ void __iomem *base = phy->reg_base;
u32 status; int i = 5000;
writel(0x3, base + REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG);
writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2);
writel(0x5a, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1);
writel(0x10, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3);
writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4);
writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0);
writel(0x1, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER);
usleep_range(5000, 6000);
writel(0x0, base + REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER);
do {
status = readl(base +
REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS);
if (!(status & DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY)) break;
for (i = 0; i < 4; i++) {
writel(0x80, base + REG_DSI_28nm_8960_PHY_LN_CFG_0(i));
writel(0x45, base + REG_DSI_28nm_8960_PHY_LN_CFG_1(i));
writel(0x00, base + REG_DSI_28nm_8960_PHY_LN_CFG_2(i));
writel(0x00, base + REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(i));
writel(0x01, base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(i));
writel(0x66, base + REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(i));
}
writel(0x40, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_0);
writel(0x67, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_1);
writel(0x0, base + REG_DSI_28nm_8960_PHY_LNCK_CFG_2);
writel(0x0, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH);
writel(0x1, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0);
writel(0x88, base + REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1);
}
writel(0x04, base + REG_DSI_28nm_8960_PHY_LDO_CTRL);
/* strength control */
writel(0xff, base + REG_DSI_28nm_8960_PHY_STRENGTH_0);
writel(0x00, base + REG_DSI_28nm_8960_PHY_STRENGTH_1);
writel(0x06, base + REG_DSI_28nm_8960_PHY_STRENGTH_2);
/* phy ctrl */
writel(0x5f, base + REG_DSI_28nm_8960_PHY_CTRL_0);
writel(0x00, base + REG_DSI_28nm_8960_PHY_CTRL_1);
writel(0x00, base + REG_DSI_28nm_8960_PHY_CTRL_2);
writel(0x10, base + REG_DSI_28nm_8960_PHY_CTRL_3);
dsi_28nm_phy_regulator_ctrl(phy);
dsi_28nm_phy_calibration(phy);
dsi_28nm_phy_lane_config(phy);
writel(0x0f, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4);
writel(0x03, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_1);
writel(0x03, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_0);
writel(0x0, base + REG_DSI_28nm_8960_PHY_BIST_CTRL_4);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.