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"
8 struct rk616_lvds *g_lvds;
11 static int rk616_lvds_cfg(struct mfd_rk616 *rk616,rk_screen *screen)
13 struct rk616_route *route = &rk616->route;
16 int odd = (screen->left_margin&0x01)?0:1;
18 if(!route->lvds_en) //lvds port is not used ,power down lvds
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);
27 if(!route->lcd1_input) //set lcd1 port for output as RGB interface
29 val = (LCD1_INPUT_EN << 16);
30 ret = rk616->write_dev(rk616,CRU_IO_CON0,&val);
35 if(route->lvds_mode) //lvds mode
38 if(route->lvds_ch_nr == 2) //dual lvds channel
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) |
48 ret = rk616->write_dev(rk616,CRU_LVDS_CON0,&val);
50 rk616_dbg(rk616->dev,"rk616 use dual lvds channel.......\n");
52 else //single lvds channel
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);
63 rk616_dbg(rk616->dev,"rk616 use single lvds channel.......\n");
67 else //mux lvds port to RGB mode
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);
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");
88 int rk616_scaler_set_param(rk_screen *screen,bool enable )//enable:0 bypass 1: scale
91 struct mfd_rk616 *rk616 = g_lvds->rk616;
94 printk(KERN_ERR "%s:mfd rk616 is null!\n",__func__);
97 ret = rk616_display_router_cfg(rk616,screen,enable);
98 ret = rk616_lvds_cfg(rk616,screen);
103 static int rk616_lvds_init_cfg(struct mfd_rk616 *rk616,rk_screen *screen)
106 ret = rk616_display_router_cfg(rk616,screen,0);
107 ret = rk616_lvds_cfg(rk616,screen);
111 #if defined(CONFIG_HAS_EARLYSUSPEND)
112 static void rk616_lvds_early_suspend(struct early_suspend *h)
114 struct rk616_lvds *lvds = container_of(h, struct rk616_lvds,early_suspend);
115 struct mfd_rk616 *rk616 = lvds->rk616;
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);
124 val = LCD1_INPUT_EN | (LCD1_INPUT_EN << 16);
125 ret = rk616->write_dev(rk616,CRU_IO_CON0,&val);
130 static void rk616_lvds_late_resume(struct early_suspend *h)
132 struct rk616_lvds *lvds = container_of(h, struct rk616_lvds,early_suspend);
133 struct mfd_rk616 *rk616 = lvds->rk616;
135 rk616_lvds_init_cfg(rk616,lvds->screen);
141 static int rk616_lvds_probe(struct platform_device *pdev)
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);
149 printk(KERN_ALERT "alloc for struct rk616_lvds fail\n");
153 rk616 = dev_get_drvdata(pdev->dev.parent);
156 dev_err(&pdev->dev,"null mfd device rk616!\n");
163 screen = rk_fb_get_prmry_screen();
166 dev_err(&pdev->dev,"the fb prmry screen is null!\n");
169 lvds->screen = screen;
170 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
171 screen->sscreen_set = rk616_scaler_set_param;
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);
182 dev_info(&pdev->dev,"rk616 lvds probe success!\n");
188 static int rk616_lvds_remove(struct platform_device *pdev)
194 static void rk616_lvds_shutdown(struct platform_device *pdev)
200 static struct platform_driver rk616_lvds_driver = {
202 .name = "rk616-lvds",
203 .owner = THIS_MODULE,
205 .probe = rk616_lvds_probe,
206 .remove = rk616_lvds_remove,
207 .shutdown = rk616_lvds_shutdown,
210 static int __init rk616_lvds_init(void)
212 return platform_driver_register(&rk616_lvds_driver);
214 fs_initcall(rk616_lvds_init);
215 static void __exit rk616_lvds_exit(void)
217 platform_driver_unregister(&rk616_lvds_driver);
219 module_exit(rk616_lvds_exit);