From 4ec5756cd5319a1723198fdc14486a5b6149e7b9 Mon Sep 17 00:00:00 2001 From: zwl Date: Thu, 9 Oct 2014 19:05:40 +0800 Subject: [PATCH] rk312x:lvds: display no noise for lvds screen --- arch/arm/boot/dts/rk312x.dtsi | 7 ++- .../video/rockchip/transmitter/rk31xx_lvds.c | 63 ++++++++++++++++--- .../video/rockchip/transmitter/rk31xx_lvds.h | 11 ++++ 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi index ab9f44a20b14..b4abbf6152c3 100755 --- a/arch/arm/boot/dts/rk312x.dtsi +++ b/arch/arm/boot/dts/rk312x.dtsi @@ -728,9 +728,10 @@ lvds: lvds@20038000 { compatible = "rockchip,rk31xx-lvds"; - reg = <0x20038000 0x4000>; - clocks = <&clk_gates5 0>; - clock-names = "pclk_lvds"; + reg = <0x20038000 0x4000>, <0x101100b0 0x01>; + reg-names = "mipi_lvds_phy", "mipi_lvds_ctl"; + clocks = <&clk_gates5 0>, <&clk_gates9 6>, <&clk_gates9 5>; + clock-names = "pclk_lvds", "pclk_lvds_ctl", "hclk_vio_h2p"; status = "disabled"; }; diff --git a/drivers/video/rockchip/transmitter/rk31xx_lvds.c b/drivers/video/rockchip/transmitter/rk31xx_lvds.c index 50cfdab62f2a..de3100b44dbd 100755 --- a/drivers/video/rockchip/transmitter/rk31xx_lvds.c +++ b/drivers/video/rockchip/transmitter/rk31xx_lvds.c @@ -42,10 +42,22 @@ static int rk31xx_lvds_clk_init(struct rk_lvds_device *lvds) { lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds"); if (IS_ERR(lvds->pclk)) { - dev_err(lvds->dev, "get clk failed\n"); + dev_err(lvds->dev, "get pclk failed\n"); return PTR_ERR(lvds->pclk); } + lvds->ctrl_pclk = devm_clk_get(lvds->dev, "pclk_lvds_ctl"); + if (IS_ERR(lvds->ctrl_pclk)) { + dev_err(lvds->dev, "get ctrl pclk failed\n"); + return PTR_ERR(lvds->ctrl_pclk); + } + + lvds->ctrl_hclk = devm_clk_get(lvds->dev, "hclk_vio_h2p"); + if (IS_ERR(lvds->ctrl_hclk)) { + dev_err(lvds->dev, "get ctrl hclk failed\n"); + return PTR_ERR(lvds->ctrl_hclk); + } + return 0; } @@ -53,6 +65,8 @@ static int rk31xx_lvds_clk_enable(struct rk_lvds_device *lvds) { if (!lvds->clk_on) { clk_prepare_enable(lvds->pclk); + clk_prepare_enable(lvds->ctrl_pclk); + clk_prepare_enable(lvds->ctrl_hclk); lvds->clk_on = true; } @@ -63,6 +77,8 @@ static int rk31xx_lvds_clk_disable(struct rk_lvds_device *lvds) { if (lvds->clk_on) { clk_disable_unprepare(lvds->pclk); + clk_disable_unprepare(lvds->ctrl_hclk); + clk_disable_unprepare(lvds->ctrl_pclk); lvds->clk_on = false; } @@ -79,6 +95,11 @@ static int rk31xx_lvds_pwr_on(void) m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN, v_SYNC_RST(0) | v_LDO_PWR_DOWN(0) | v_PLL_PWR_DOWN(0)); + /* enable lvds lane and power on pll */ + lvds_writel(lvds, MIPIPHY_REGEB, + v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | + v_LANE3_EN(1) | v_LANECLK_EN(1) | v_PLL_PWR_OFF(0)); + /* enable lvds */ lvds_msk_reg(lvds, MIPIPHY_REGE3, m_MIPI_EN | m_LVDS_EN | m_TTL_EN, @@ -95,6 +116,11 @@ static int rk31xx_lvds_pwr_off(void) { struct rk_lvds_device *lvds = rk31xx_lvds; + /* disable lvds lane and power off pll */ + lvds_writel(lvds, MIPIPHY_REGEB, + v_LANE0_EN(0) | v_LANE1_EN(0) | v_LANE2_EN(0) | + v_LANE3_EN(0) | v_LANECLK_EN(0) | v_PLL_PWR_OFF(1)); + /* power down lvds pll and bandgap */ lvds_msk_reg(lvds, MIPIPHY_REG1, m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN, @@ -137,6 +163,7 @@ static void rk31xx_output_lvds(struct rk_lvds_device *lvds, struct rk_screen *screen) { u32 val = 0; + u32 delay_times = 20; /* if LVDS transmitter source from VOP, vop_dclk need get invert * set iomux in dts pinctrl @@ -149,22 +176,32 @@ static void rk31xx_output_lvds(struct rk_lvds_device *lvds, val |= v_MIPIPHY_LANE0_EN(1) | v_MIPIDPI_FORCEX_EN(1); grf_writel(val, RK312X_GRF_LVDS_CON0); - /* enable lvds lane */ - val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) | - v_LANECLK_EN(1) | v_PLL_PWR_OFF(0); - lvds_writel(lvds, MIPIPHY_REGEB, val); + /* digital internal disable */ + lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0)); /* set pll prediv and fbdiv */ lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0)); lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28)); - lvds_writel(lvds, MIPIPHY_REGE8, 0xfc); + lvds_writel(lvds, MIPIPHY_REGE8, 0xfc); /* set lvds mode and reset phy config */ lvds_msk_reg(lvds, MIPIPHY_REGE0, m_MSB_SEL | m_DIG_INTER_RST, v_MSB_SEL(1) | v_DIG_INTER_RST(1)); + /* power on pll and enable lane */ + rk31xx_lvds_pwr_on(); + + /* delay for waitting pll lock on */ + while (delay_times--) { + if (lvds_phy_lockon(lvds)) { + msleep(1); + break; + } + udelay(100); + } + /* digital internal enable */ lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1)); #if 0 @@ -172,8 +209,6 @@ static void rk31xx_output_lvds(struct rk_lvds_device *lvds, lvds_writel(lvds, MIPIPHY_REGE7, 0xfc); /* phase */ #endif - rk31xx_lvds_pwr_on(); - } static void rk31xx_output_lvttl(struct rk_lvds_device *lvds, @@ -310,13 +345,21 @@ static int rk31xx_lvds_probe(struct platform_device *pdev) } /* lvds regs on MIPIPHY_REG */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mipi_lvds_phy"); lvds->regbase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(lvds->regbase)) { - dev_err(&pdev->dev, "ioremap reg failed\n"); + dev_err(&pdev->dev, "ioremap mipi-lvds phy reg failed\n"); return PTR_ERR(lvds->regbase); } + /* pll lock on status reg that is MIPICTRL Register */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mipi_lvds_ctl"); + lvds->ctrl_reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(lvds->ctrl_reg)) { + dev_err(&pdev->dev, "ioremap mipi-lvds ctl reg failed\n"); + return PTR_ERR(lvds->ctrl_reg); + } + ret = rk31xx_lvds_clk_init(lvds); if(ret < 0) goto err_clk_init; diff --git a/drivers/video/rockchip/transmitter/rk31xx_lvds.h b/drivers/video/rockchip/transmitter/rk31xx_lvds.h index 36c1f92a31a1..0c271e476d81 100755 --- a/drivers/video/rockchip/transmitter/rk31xx_lvds.h +++ b/drivers/video/rockchip/transmitter/rk31xx_lvds.h @@ -102,7 +102,10 @@ enum { struct rk_lvds_device { struct device *dev; void __iomem *regbase; + void __iomem *ctrl_reg; struct clk *pclk; /*phb clk*/ + struct clk *ctrl_pclk; /* mipi ctrl pclk*/ + struct clk *ctrl_hclk; /* mipi ctrl hclk*/ struct rk_screen screen; bool clk_on; bool sys_state; @@ -132,5 +135,13 @@ static inline u32 lvds_readl(struct rk_lvds_device *lvds, u32 offset) return readl_relaxed(lvds->regbase + offset); } +static inline u32 lvds_phy_lockon(struct rk_lvds_device *lvds) +{ + u32 val = 0; + + val = readl_relaxed(lvds->ctrl_reg); + return (val & 0x01); +} + #endif -- 2.34.1