39a28359e3672ad3770184152cc4c799b5312b52
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / transmitter / rk31xx_lvds.c
1 /*
2  * drivers/video/rockchip/lcdc/rk31xx_lcdc.c
3  *
4  * Copyright (C) 2014 ROCKCHIP, Inc.
5  * Author: zhuangwenlong<zwl@rock-chips.com>
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/io.h>
21 #include <linux/types.h>
22 #include <linux/i2c.h>
23 #include <linux/rk_fb.h>
24 #include <linux/clk.h>
25 #include <linux/delay.h>
26 #include <linux/rockchip/iomap.h>
27 #include <linux/rockchip/grf.h>
28 #include "rk31xx_lvds.h"
29
30
31 #define grf_readl(offset)       readl_relaxed(RK_GRF_VIRT + offset)
32 #define grf_writel(v,offset)                                    \
33         do {                                                    \
34                 writel_relaxed(v, RK_GRF_VIRT + offset);        \
35                 dsb();                                          \
36         } while (0)
37
38
39 static struct rk_lvds_device *rk31xx_lvds;
40
41 static int rk31xx_lvds_clk_init(struct rk_lvds_device *lvds)
42 {
43         lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
44         if (IS_ERR(lvds->pclk)) {
45                 dev_err(lvds->dev, "get clk failed\n");
46                 return PTR_ERR(lvds->pclk);
47         }
48  
49         lvds->pd = devm_clk_get(lvds->dev,"pd_lvds");
50         if (IS_ERR(lvds->pd)) {
51                 dev_err(lvds->dev, "get clk failed\n");
52                 return PTR_ERR(lvds->pd);
53         }       
54         return 0;       
55 }
56
57 static int rk31xx_lvds_clk_enable(struct rk_lvds_device *lvds)
58 {
59         if (!lvds->clk_on) {
60                 clk_prepare_enable(lvds->pd);
61                 clk_prepare_enable(lvds->pclk);
62                 lvds->clk_on = true;
63         }
64
65         return 0;
66 }
67
68 static int rk31xx_lvds_clk_disable(struct rk_lvds_device *lvds)
69 {
70         if (lvds->clk_on) {
71                 clk_disable_unprepare(lvds->pclk);
72                 clk_disable_unprepare(lvds->pd);
73                 lvds->clk_on = false;
74         }
75
76         return 0;
77 }
78
79 static int rk31xx_lvds_pwr_on(void)
80 {
81         struct rk_lvds_device *lvds = rk31xx_lvds;
82
83         if (lvds->screen.type == SCREEN_LVDS) {
84                 /* power up lvds pll and bandgap */
85                 lvds_msk_reg(lvds, MIPIPHY_REGEA,
86                              m_BG_POWER_DOWN | m_PLL_POWER_DOWN,
87                              v_BG_POWER_DOWN(0) | v_PLL_POWER_DOWN(0));
88
89                 /* enable lvds */
90                 lvds_msk_reg(lvds, MIPIPHY_REGE3,
91                              m_MIPI_EN | m_LVDS_EN | m_TTL_EN,
92                              v_MIPI_EN(0) | v_LVDS_EN(1) | v_TTL_EN(0));
93         } else {
94                 lvds_msk_reg(lvds, MIPIPHY_REGE3,
95                              m_MIPI_EN | m_LVDS_EN | m_TTL_EN,
96                              v_MIPI_EN(0) | v_LVDS_EN(0) | v_TTL_EN(1));
97         }
98         return 0;
99 }
100
101 static int rk31xx_lvds_pwr_off(void)
102 {
103         struct rk_lvds_device *lvds = rk31xx_lvds;
104
105         /* power down lvds pll and bandgap */
106         lvds_msk_reg(lvds, MIPIPHY_REGEA, m_BG_POWER_DOWN | m_PLL_POWER_DOWN,
107                      v_BG_POWER_DOWN(1) | v_PLL_POWER_DOWN(1));
108         /* disable lvds */
109         lvds_msk_reg(lvds, MIPIPHY_REGE3, m_LVDS_EN | m_TTL_EN,
110                      v_LVDS_EN(0) | v_TTL_EN(0));
111         return 0;
112 }
113
114 static int rk31xx_lvds_disable(void)
115 {
116         struct rk_lvds_device *lvds = rk31xx_lvds;
117
118         if (!lvds->sys_state)
119                 return 0;
120
121         grf_writel(v_LVDSMODE_EN(0) | v_MIPIPHY_TTL_EN(0), RK312X_GRF_LVDS_CON0);
122
123         rk31xx_lvds_pwr_off();
124         rk31xx_lvds_clk_disable(lvds);
125         lvds->sys_state = false;
126         return 0;
127 }
128
129 static void rk31xx_output_lvds(struct rk_lvds_device *lvds,
130                                struct rk_screen *screen)
131 {
132         u32 val = 0;
133
134         /* if LVDS transmitter source from VOP, vop_dclk need get invert
135          * set iomux in dts pinctrl
136          */
137         val = 0;
138         val |= v_LVDSMODE_EN(1) | v_MIPIPHY_TTL_EN(0);      /* enable lvds mode */
139         val |= v_LVDS_DATA_SEL(LVDS_DATA_FROM_LCDC);    /* config data source */
140         val |= v_LVDS_OUTPUT_FORMAT(screen->lvds_format); /* config lvds_format */
141         val |= v_LVDS_MSBSEL(LVDS_MSB_D7);      /* LSB receive mode */
142         grf_writel(val, RK312X_GRF_LVDS_CON0);
143
144         /* enable lvds lane */
145         val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) |
146                 v_LANECLK_EN(1);
147         lvds_writel(lvds, MIPIPHY_REG0, val);
148
149         /* set pll prediv and fbdiv */
150         lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(1) | v_FBDIV_MSB(0));
151         lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(7));
152
153         /* set lvds mode and reset phy config */
154         val = v_LVDS_MODE_EN(1) | v_TTL_MODE_EN(0) | v_MIPI_MODE_EN(0) |
155                 v_MSB_SEL(1) | v_DIG_INTER_RST(1);
156         lvds_writel(lvds, MIPIPHY_REGE0, val);
157
158         lvds_writel(lvds, MIPIPHY_REGE1, 0x92);
159 #if 0        
160         lvds_writel(lvds, MIPIPHY_REGE2, 0xa0); /* timing */
161         lvds_writel(lvds, MIPIPHY_REGE7, 0xfc); /* phase */
162 #endif
163         rk31xx_lvds_pwr_on();
164
165 }
166
167 static void rk31xx_output_lvttl(struct rk_lvds_device *lvds,
168                                 struct rk_screen *screen)
169 {
170         u32 val = 0;
171
172         /* iomux to lcdc */
173         grf_writel(0xffff5555, RK312X_GRF_GPIO2B_IOMUX);
174         grf_writel(0x00ff0055, RK312X_GRF_GPIO2C_IOMUX);
175         grf_writel(0x77771111, 0x00e8); /* RK312X_GRF_GPIO2C_IOMUX2 */
176         grf_writel(0x700c1008, RK312X_GRF_GPIO2D_IOMUX);
177
178         val |= v_LVDSMODE_EN(0) | v_MIPIPHY_TTL_EN(1);      /* enable lvds mode */
179         val |= v_LVDS_DATA_SEL(LVDS_DATA_FROM_LCDC);    /* config data source */
180         grf_writel(val, RK312X_GRF_LVDS_CON0);
181
182         /* set pll prediv and fbdiv */
183         lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(1) | v_FBDIV_MSB(0));
184         lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(7));
185
186         /* set ttl mode and reset phy config */
187         val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) |
188                 v_MSB_SEL(1) | v_DIG_INTER_RST(1);
189         lvds_writel(lvds, MIPIPHY_REGE0, val);
190
191         lvds_writel(lvds, MIPIPHY_REGE1, 0x92);
192
193         /* enable ttl */
194         rk31xx_lvds_pwr_on();
195                 
196 }
197
198 static int rk31xx_lvds_en(void)
199 {
200         struct rk_lvds_device *lvds = rk31xx_lvds;
201         struct rk_screen *screen = &lvds->screen;
202
203         if (lvds->sys_state)
204                 return 0;
205
206         rk_fb_get_prmry_screen(screen);
207
208         /* enable clk */
209         rk31xx_lvds_clk_enable(lvds);
210
211         switch (screen->type) {
212         case SCREEN_LVDS:
213                 rk31xx_output_lvds(lvds, screen);
214                 break;
215         case SCREEN_RGB:
216                 rk31xx_output_lvttl(lvds, screen);
217                 break;
218         default:
219                 printk("unsupport screen type\n");
220                 break;
221         }
222
223         lvds->sys_state = true;
224         return 0;
225 }
226
227 static struct rk_fb_trsm_ops trsm_lvds_ops = {
228         .enable = rk31xx_lvds_en,
229         .disable = rk31xx_lvds_disable,
230         .dsp_pwr_on = rk31xx_lvds_pwr_on,
231         .dsp_pwr_off = rk31xx_lvds_pwr_off,
232 };
233
234 static int rk31xx_lvds_probe(struct platform_device *pdev)
235 {
236         struct rk_lvds_device *lvds;
237         struct resource *res;
238         struct device_node *np = pdev->dev.of_node;
239         int ret = 0;
240
241         if (!np) {
242                 dev_err(&pdev->dev, "Don't find lvds device tree node.\n");
243                 return -EINVAL;
244         }       
245
246         lvds = devm_kzalloc(&pdev->dev, sizeof(struct rk_lvds_device), GFP_KERNEL);
247         if (!lvds) {
248                 dev_err(&pdev->dev, "kzalloc rk31xx lvds failed\n");
249                 return -ENOMEM;
250         }
251         lvds->dev = &pdev->dev;
252
253         rk_fb_get_prmry_screen(&lvds->screen);
254         if ((lvds->screen.type != SCREEN_RGB) && 
255                 (lvds->screen.type != SCREEN_LVDS)) {
256                 dev_err(&pdev->dev, "screen is not lvds/rgb!\n");
257                 ret = -EINVAL;
258                 goto err_screen_type;
259         }
260
261         platform_set_drvdata(pdev, lvds);
262         dev_set_name(lvds->dev, "rk31xx-lvds");
263
264         /* lvds regs on MIPIPHY_REG */
265         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
266         lvds->regbase = devm_ioremap_resource(&pdev->dev, res);
267         if (IS_ERR(lvds->regbase)) {
268                 dev_err(&pdev->dev, "ioremap reg failed\n");
269                 return PTR_ERR(lvds->regbase);
270         }
271
272         ret = rk31xx_lvds_clk_init(lvds);
273         if(ret < 0)
274                 goto err_clk_init;
275
276         if (support_uboot_display())
277                 rk31xx_lvds_clk_enable(lvds);
278
279         rk31xx_lvds = lvds;
280         rk_fb_trsm_ops_register(&trsm_lvds_ops, SCREEN_LVDS);
281         dev_info(&pdev->dev, "rk31xx lvds driver probe success\n");
282
283         return 0;
284
285 err_clk_init:
286 err_screen_type:
287         devm_kfree(&pdev->dev, lvds);
288         lvds = NULL;
289         return ret;     
290 }
291
292 static int rk31xx_lvds_remove(struct platform_device *pdev)
293 {       
294         return 0;
295 }
296
297 static void rk31xx_lvds_shutdown(struct platform_device *pdev)
298 {
299         return;
300 }
301
302 #if defined(CONFIG_OF)
303 static const struct of_device_id rk31xx_lvds_dt_ids[] = {
304         {.compatible = "rockchip,rk31xx-lvds",},
305         {}
306 };
307 #endif
308
309 static struct platform_driver rk31xx_lvds_driver = {
310         .driver         = {
311                 .name   = "rk31xx-lvds",
312                 .owner  = THIS_MODULE,
313 #if defined(CONFIG_OF)
314                 .of_match_table = of_match_ptr(rk31xx_lvds_dt_ids),
315 #endif
316         },
317         .probe          = rk31xx_lvds_probe,
318         .remove         = rk31xx_lvds_remove,
319         .shutdown       = rk31xx_lvds_shutdown,
320 };
321
322 static int __init rk31xx_lvds_init(void)
323 {
324         return platform_driver_register(&rk31xx_lvds_driver);
325 }
326
327 static void __exit rk31xx_lvds_exit(void)
328 {
329         platform_driver_unregister(&rk31xx_lvds_driver);
330 }
331
332 fs_initcall(rk31xx_lvds_init);
333 module_exit(rk31xx_lvds_exit);
334