video: rockchip: rk3366: add mipi support
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / transmitter / rk616_lvds.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/platform_device.h>
4 #include <linux/slab.h>
5 #include "rk616_lvds.h"
6
7
8 struct rk616_lvds *g_lvds;
9
10
11 static int rk616_lvds_cfg(struct mfd_rk616 *rk616,rk_screen *screen)
12 {
13         struct rk616_route *route = &rk616->route;
14         u32 val = 0;
15         int ret;
16         int odd = (screen->left_margin&0x01)?0:1;
17         
18         if(!route->lvds_en)  //lvds port is not used ,power down lvds
19         {
20                 val &= ~(LVDS_CH1TTL_EN | LVDS_CH0TTL_EN | LVDS_CH1_PWR_EN |
21                         LVDS_CH0_PWR_EN | LVDS_CBG_PWR_EN);
22                 val |= LVDS_PLL_PWR_DN | (LVDS_CH1TTL_EN << 16) | (LVDS_CH0TTL_EN << 16) |
23                         (LVDS_CH1_PWR_EN << 16) | (LVDS_CH0_PWR_EN << 16) |
24                         (LVDS_CBG_PWR_EN << 16) | (LVDS_PLL_PWR_DN << 16);
25                 ret = rk616->write_dev(rk616,CRU_LVDS_CON0,&val);
26
27                 if(!route->lcd1_input)  //set lcd1 port for output as RGB interface
28                 {
29                         val = (LCD1_INPUT_EN << 16);
30                         ret = rk616->write_dev(rk616,CRU_IO_CON0,&val);
31                 }
32         }
33         else
34         {
35                 if(route->lvds_mode)  //lvds mode
36                 {
37
38                         if(route->lvds_ch_nr == 2) //dual lvds channel
39                         {
40                                 val = 0;
41                                 val &= ~(LVDS_CH0TTL_EN | LVDS_CH1TTL_EN | LVDS_PLL_PWR_DN);
42                                 val = (LVDS_DCLK_INV)|(LVDS_CH1_PWR_EN) |(LVDS_CH0_PWR_EN) | LVDS_HBP_ODD(odd) |
43                                         (LVDS_CBG_PWR_EN) | (LVDS_CH_SEL) | (LVDS_OUT_FORMAT(screen->lvds_format)) | 
44                                         (LVDS_CH0TTL_EN << 16) | (LVDS_CH1TTL_EN << 16) |(LVDS_CH1_PWR_EN << 16) | 
45                                         (LVDS_CH0_PWR_EN << 16) | (LVDS_CBG_PWR_EN << 16) | (LVDS_CH_SEL << 16) | 
46                                         (LVDS_OUT_FORMAT_MASK) | (LVDS_DCLK_INV << 16) | (LVDS_PLL_PWR_DN << 16) |
47                                         (LVDS_HBP_ODD_MASK);
48                                 ret = rk616->write_dev(rk616,CRU_LVDS_CON0,&val);
49                                 
50                                 rk616_dbg(rk616->dev,"rk616 use dual lvds channel.......\n");
51                         }
52                         else //single lvds channel
53                         {
54                                 val = 0;
55                                 val &= ~(LVDS_CH0TTL_EN | LVDS_CH1TTL_EN | LVDS_CH1_PWR_EN | LVDS_PLL_PWR_DN | LVDS_CH_SEL); //use channel 0
56                                 val |= (LVDS_CH0_PWR_EN) |(LVDS_CBG_PWR_EN) | (LVDS_OUT_FORMAT(screen->lvds_format)) | 
57                                       (LVDS_CH0TTL_EN << 16) | (LVDS_CH1TTL_EN << 16) |(LVDS_CH0_PWR_EN << 16) | 
58                                        (LVDS_DCLK_INV ) | (LVDS_CH0TTL_EN << 16) | (LVDS_CH1TTL_EN << 16) |(LVDS_CH0_PWR_EN << 16) | 
59                                         (LVDS_CBG_PWR_EN << 16)|(LVDS_CH_SEL << 16) | (LVDS_PLL_PWR_DN << 16)| 
60                                        (LVDS_OUT_FORMAT_MASK) | (LVDS_DCLK_INV << 16);
61                                 ret = rk616->write_dev(rk616,CRU_LVDS_CON0,&val);
62
63                                 rk616_dbg(rk616->dev,"rk616 use single lvds channel.......\n");
64                         }
65
66                 }
67                 else //mux lvds port to RGB mode
68                 {
69                         val &= ~(LVDS_CBG_PWR_EN| LVDS_CH1_PWR_EN | LVDS_CH0_PWR_EN);
70                         val |= (LVDS_CH0TTL_EN)|(LVDS_CH1TTL_EN )|(LVDS_PLL_PWR_DN)|
71                                 (LVDS_CH0TTL_EN<< 16)|(LVDS_CH1TTL_EN<< 16)|(LVDS_CH1_PWR_EN << 16) | 
72                                 (LVDS_CH0_PWR_EN << 16)|(LVDS_CBG_PWR_EN << 16)|(LVDS_PLL_PWR_DN << 16);
73                         ret = rk616->write_dev(rk616,CRU_LVDS_CON0,&val);
74
75                         val &= ~(LVDS_OUT_EN);
76                         val |= (LVDS_OUT_EN << 16);
77                         ret = rk616->write_dev(rk616,CRU_IO_CON0,&val);
78                         rk616_dbg(rk616->dev,"rk616 use RGB output.....\n");
79                         
80                 }
81         }
82
83         return 0;
84         
85 }
86
87
88 int rk616_scaler_set_param(rk_screen *screen,bool enable )//enable:0 bypass 1: scale
89 {
90         int ret;
91         struct mfd_rk616 *rk616 = g_lvds->rk616;
92         if(!rk616)
93         {
94                 printk(KERN_ERR "%s:mfd rk616 is null!\n",__func__);
95                 return -1;
96         }
97         ret = rk616_display_router_cfg(rk616,screen,enable);
98         ret = rk616_lvds_cfg(rk616,screen);
99         return ret;
100 }
101
102
103 static int rk616_lvds_init_cfg(struct mfd_rk616 *rk616,rk_screen *screen)
104 {
105         int ret ;
106         ret = rk616_display_router_cfg(rk616,screen,0);
107         ret = rk616_lvds_cfg(rk616,screen);
108         return ret;
109 }
110
111 #if     defined(CONFIG_HAS_EARLYSUSPEND)
112 static void rk616_lvds_early_suspend(struct early_suspend *h)
113 {
114         struct rk616_lvds *lvds = container_of(h, struct rk616_lvds,early_suspend);
115         struct mfd_rk616 *rk616 = lvds->rk616;
116         u32 val = 0;
117         int ret = 0;
118
119         val &= ~(LVDS_CH1_PWR_EN | LVDS_CH0_PWR_EN | LVDS_CBG_PWR_EN);
120         val |= LVDS_PLL_PWR_DN |(LVDS_CH1_PWR_EN << 16) | (LVDS_CH0_PWR_EN << 16) |
121                 (LVDS_CBG_PWR_EN << 16) | (LVDS_PLL_PWR_DN << 16);
122         ret = rk616->write_dev(rk616,CRU_LVDS_CON0,&val);
123
124         val = LCD1_INPUT_EN | (LCD1_INPUT_EN << 16);
125         ret = rk616->write_dev(rk616,CRU_IO_CON0,&val);
126         
127         
128 }
129
130 static void rk616_lvds_late_resume(struct early_suspend *h)
131 {
132         struct rk616_lvds *lvds = container_of(h, struct rk616_lvds,early_suspend);
133         struct mfd_rk616 *rk616 = lvds->rk616;
134         rk616->resume = 1;
135         rk616_lvds_init_cfg(rk616,lvds->screen);        
136         rk616->resume = 0;
137 }
138
139 #endif
140
141 static int rk616_lvds_probe(struct platform_device *pdev)
142 {
143         struct rk616_lvds *lvds = NULL; 
144         struct mfd_rk616 *rk616 = NULL;
145         rk_screen *screen = NULL;
146         lvds = kzalloc(sizeof(struct rk616_lvds),GFP_KERNEL);
147         if(!lvds)
148         {
149                 printk(KERN_ALERT "alloc for struct rk616_lvds fail\n");
150                 return  -ENOMEM;
151         }
152
153         rk616 = dev_get_drvdata(pdev->dev.parent);
154         if(!rk616)
155         {
156                 dev_err(&pdev->dev,"null mfd device rk616!\n");
157                 return -ENODEV;
158         }
159         else
160                 g_lvds = lvds;
161         lvds->rk616 = rk616;
162         
163         screen = rk_fb_get_prmry_screen();
164         if(!screen)
165         {
166                 dev_err(&pdev->dev,"the fb prmry screen is null!\n");
167                 return -ENODEV;
168         }
169         lvds->screen = screen;
170 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
171         screen->sscreen_set = rk616_scaler_set_param;
172 #endif
173         rk616_lvds_init_cfg(rk616,screen);
174 #ifdef CONFIG_HAS_EARLYSUSPEND
175         lvds->early_suspend.suspend = rk616_lvds_early_suspend;
176         lvds->early_suspend.resume = rk616_lvds_late_resume;
177         lvds->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
178         register_early_suspend(&lvds->early_suspend);
179 #endif
180         
181
182         dev_info(&pdev->dev,"rk616 lvds probe success!\n");
183
184         return 0;
185         
186 }
187
188 static int rk616_lvds_remove(struct platform_device *pdev)
189 {
190         
191         return 0;
192 }
193
194 static void rk616_lvds_shutdown(struct platform_device *pdev)
195 {
196         
197         return;
198 }
199
200 static struct platform_driver rk616_lvds_driver = {
201         .driver         = {
202                 .name   = "rk616-lvds",
203                 .owner  = THIS_MODULE,
204         },
205         .probe          = rk616_lvds_probe,
206         .remove         = rk616_lvds_remove,
207         .shutdown       = rk616_lvds_shutdown,
208 };
209
210 static int __init rk616_lvds_init(void)
211 {
212         return platform_driver_register(&rk616_lvds_driver);
213 }
214 fs_initcall(rk616_lvds_init);
215 static void __exit rk616_lvds_exit(void)
216 {
217         platform_driver_unregister(&rk616_lvds_driver);
218 }
219 module_exit(rk616_lvds_exit);
220