rk3368 lcdc: overlay mode depend on screen color mode
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / transmitter / rk32_lvds.c
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/init.h>
4 #include <linux/device.h>
5 #include <linux/errno.h>
6 #include <linux/string.h>
7 #include <linux/mm.h>
8 #include <linux/slab.h>
9 #include <linux/delay.h>
10 #include <linux/platform_device.h>
11 #include <linux/clk.h>
12 #include <linux/rk_fb.h>
13 #include <linux/rockchip/iomap.h>
14 #include <linux/rockchip/grf.h>
15 #include "rk32_lvds.h"
16
17
18 #define grf_readl(offset)       readl_relaxed(RK_GRF_VIRT + offset)
19 #define grf_writel(v,offset)    do{ writel_relaxed(v, RK_GRF_VIRT + offset);dsb();} while (0)
20
21 static struct rk32_lvds *rk32_lvds;
22
23 static int rk32_lvds_clk_enable(struct rk32_lvds *lvds)
24 {
25         if (!lvds->clk_on) {
26                 clk_prepare_enable(lvds->pd);
27                 clk_prepare_enable(lvds->pclk);
28                 lvds->clk_on = true;
29         }
30
31         return 0;
32 }
33
34 static int rk32_lvds_clk_disable(struct rk32_lvds *lvds)
35 {
36         if (lvds->clk_on) {
37                 clk_disable_unprepare(lvds->pclk);
38                 clk_disable_unprepare(lvds->pd);
39                 lvds->clk_on = false;
40         }
41
42         return 0;
43 }
44
45 static int rk32_lvds_disable(void)
46 {
47         struct rk32_lvds *lvds = rk32_lvds;
48         grf_writel(0xffff8000, RK3288_GRF_SOC_CON7);
49         writel_relaxed(0x00, lvds->regs + LVDS_CFG_REG_21); /*disable tx*/
50         writel_relaxed(0xff, lvds->regs + LVDS_CFG_REG_c); /*disable pll*/
51         rk32_lvds_clk_disable(lvds);
52         return 0;
53 }
54
55 static int rk32_lvds_en(void)
56 {
57         struct rk32_lvds *lvds = rk32_lvds;
58         struct rk_screen *screen = &lvds->screen;
59         u32 h_bp = 0;
60         u32 val = 0;
61
62         rk_fb_get_prmry_screen(screen);
63
64         /* enable clk */
65         rk32_lvds_clk_enable(lvds);
66
67         /* select lcdc source */
68         if (screen->lcdc_id == 1) /*lcdc1 = vop little,lcdc0 = vop big*/
69                 val = LVDS_SEL_VOP_LIT | (LVDS_SEL_VOP_LIT << 16);
70         else
71                 val = LVDS_SEL_VOP_LIT << 16;
72         grf_writel(val, RK3288_GRF_SOC_CON6);
73
74         /* set lvds format */
75         val = screen->lvds_format;
76         if (screen->type == SCREEN_DUAL_LVDS)
77                 val |= LVDS_DUAL | LVDS_CH0_EN | LVDS_CH1_EN;
78         else if(screen->type == SCREEN_LVDS)
79                 val |= LVDS_CH0_EN;
80         else if (screen->type == SCREEN_RGB)
81                 val |= LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN;
82
83         h_bp = screen->mode.hsync_len + screen->mode.left_margin;
84         if (h_bp & 0x01)
85                 val |= LVDS_START_PHASE_RST_1;
86
87         val |= (screen->pin_dclk << 8) | (screen->pin_hsync << 9) |
88                 (screen->pin_den << 10);
89         val |= (0xffff << 16);
90         grf_writel(val, RK3288_GRF_SOC_CON7);
91
92         if (screen->type == SCREEN_RGB) {
93                 val = 0x007f007f;//0x1<<6 |0x1 <<4;
94                 grf_writel(val, RK3288_GRF_GPIO1D_IOMUX);
95
96                 lvds_writel(lvds, LVDS_CH0_REG_0, 0x7f);
97                 lvds_writel(lvds, LVDS_CH0_REG_1, 0x40);
98                 lvds_writel(lvds, LVDS_CH0_REG_2, 0x00);
99
100                 lvds_writel(lvds, LVDS_CH0_REG_4, 0x3f);
101                 lvds_writel(lvds, LVDS_CH0_REG_5, 0x3f);
102                 lvds_writel(lvds, LVDS_CH0_REG_3, 0x46);
103                 lvds_writel(lvds, LVDS_CH0_REG_d, 0x0a);
104                 lvds_writel(lvds, LVDS_CH0_REG_20,0x44);/* 44:LSB  45:MSB*/
105                 writel_relaxed(0x00, lvds->regs + LVDS_CFG_REG_c); /*eanble pll*/
106                 writel_relaxed(0x92, lvds->regs + LVDS_CFG_REG_21); /*enable tx*/
107
108                 lvds_writel(lvds, 0x100, 0x7f);
109                 lvds_writel(lvds, 0x104, 0x40);
110                 lvds_writel(lvds, 0x108, 0x00);
111                 lvds_writel(lvds, 0x10c, 0x46);
112                 lvds_writel(lvds, 0x110, 0x3f);
113                 lvds_writel(lvds, 0x114, 0x3f);
114                 lvds_writel(lvds, 0x134, 0x0a);
115         } else {
116                 lvds_writel(lvds, LVDS_CH0_REG_0, 0xbf);
117                 lvds_writel(lvds, LVDS_CH0_REG_1, 0x3f);
118                 lvds_writel(lvds, LVDS_CH0_REG_2, 0xfe);
119                 lvds_writel(lvds, LVDS_CH0_REG_3, 0x46);
120                 lvds_writel(lvds, LVDS_CH0_REG_4, 0x00);
121                 lvds_writel(lvds, LVDS_CH0_REG_d, 0x0a);
122                 lvds_writel(lvds, LVDS_CH0_REG_20,0x44);/* 44:LSB  45:MSB*/
123                 writel_relaxed(0x00, lvds->regs + LVDS_CFG_REG_c); /*eanble pll*/
124                 writel_relaxed(0x92, lvds->regs + LVDS_CFG_REG_21); /*enable tx*/
125         }
126
127         return 0;
128 }
129
130
131 static struct rk_fb_trsm_ops trsm_lvds_ops = {
132         .enable = rk32_lvds_en,
133         .disable = rk32_lvds_disable,
134 };
135
136 static int rk32_lvds_probe(struct platform_device *pdev)
137 {
138         struct rk32_lvds *lvds;
139         struct resource *res;
140         struct device_node *np = pdev->dev.of_node;
141
142         if (!np) {
143                 dev_err(&pdev->dev, "Missing device tree node.\n");
144                 return -EINVAL;
145         }
146
147         lvds = devm_kzalloc(&pdev->dev, sizeof(struct rk32_lvds), GFP_KERNEL);
148         if (!lvds) {
149                 dev_err(&pdev->dev, "no memory for state\n");
150                 return -ENOMEM;
151         }
152         lvds->dev = &pdev->dev;
153         rk_fb_get_prmry_screen(&lvds->screen);
154         if ((lvds->screen.type != SCREEN_RGB) && 
155                 (lvds->screen.type != SCREEN_LVDS) &&
156                 (lvds->screen.type != SCREEN_DUAL_LVDS)) {
157                 dev_err(&pdev->dev, "screen is not lvds/rgb!\n");               
158                 writel_relaxed(0xffff8000, RK_GRF_VIRT + RK3288_GRF_SOC_CON7);
159                 return -EINVAL;
160         }
161         platform_set_drvdata(pdev, lvds);
162         dev_set_name(lvds->dev, "rk32-lvds");
163         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
164         lvds->regs = devm_ioremap_resource(&pdev->dev, res);
165         if (IS_ERR(lvds->regs)) {
166                 dev_err(&pdev->dev, "ioremap reg failed\n");
167                 return PTR_ERR(lvds->regs);
168         }
169         lvds->pclk = devm_clk_get(&pdev->dev,"pclk_lvds");
170         if (IS_ERR(lvds->pclk)) {
171                 dev_err(&pdev->dev, "get clk failed\n");
172                 return PTR_ERR(lvds->pclk);
173         }
174         lvds->pd = devm_clk_get(&pdev->dev,"pd_lvds");
175         if (IS_ERR(lvds->pd)) {
176                 dev_err(&pdev->dev, "get clk failed\n");
177                 return PTR_ERR(lvds->pd);
178         }       
179         if (support_uboot_display()) {
180                 rk32_lvds_clk_enable(lvds);
181         }
182
183         rk32_lvds = lvds;
184         rk_fb_trsm_ops_register(&trsm_lvds_ops,SCREEN_LVDS);
185         dev_info(&pdev->dev, "rk32 lvds driver probe success\n");
186
187         return 0;
188 }
189
190 static void rk32_lvds_shutdown(struct platform_device *pdev)
191 {
192
193 }
194
195 #if defined(CONFIG_OF)
196 static const struct of_device_id rk32_lvds_dt_ids[] = {
197         {.compatible = "rockchip,rk32-lvds",},
198         {}
199 };
200
201 MODULE_DEVICE_TABLE(of, rk32_lvds_dt_ids);
202 #endif
203
204 static struct platform_driver rk32_lvds_driver = {
205         .probe = rk32_lvds_probe,
206         .driver = {
207                    .name = "rk32-lvds",
208                    .owner = THIS_MODULE,
209 #if defined(CONFIG_OF)
210                    .of_match_table = of_match_ptr(rk32_lvds_dt_ids),
211 #endif
212         },
213         .shutdown = rk32_lvds_shutdown,
214 };
215
216 static int __init rk32_lvds_module_init(void)
217 {
218         return platform_driver_register(&rk32_lvds_driver);
219 }
220
221 static void __exit rk32_lvds_module_exit(void)
222 {
223
224 }
225
226 fs_initcall(rk32_lvds_module_init);
227 module_exit(rk32_lvds_module_exit);
228