Merge commit 'c3bf6e05eb93a700ff8f72d596a9bbcb89196184' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / lcdc / rk2928_lcdc.c
1 /*
2  * drivers/video/rockchip/chips/rk2928_lcdc.c
3  *
4  * Copyright (C) 2012 ROCKCHIP, Inc.
5  *Author:yzq<yzq@rock-chips.com>
6  *      yxj<yxj@rock-chips.com>
7  *This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/string.h>
22 #include <linux/mm.h>
23 #include <linux/slab.h>
24 #include <linux/device.h>
25 #include <linux/delay.h>
26 #include <linux/init.h>
27 #include <linux/interrupt.h>
28 #include <linux/platform_device.h>
29 #include <linux/clk.h>
30 #include <linux/earlysuspend.h>
31 #include <asm/div64.h>
32 #include <asm/uaccess.h>
33 #include <mach/iomux.h>
34 #include "rk2928_lcdc.h"
35 #include "../lvds/rk_lvds.h"
36
37
38
39
40
41 static int dbg_thresd = 2;
42 module_param(dbg_thresd, int, S_IRUGO|S_IWUSR);
43 #define DBG(level,x...) do { if(unlikely(dbg_thresd > level)) printk(KERN_INFO x); } while (0)
44
45
46 static int init_rk2928_lcdc(struct rk_lcdc_device_driver *dev_drv)
47 {
48         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
49         if(lcdc_dev->id == 0) //lcdc0
50         {
51                 lcdc_dev->hclk = clk_get(NULL,"hclk_lcdc0"); 
52                 lcdc_dev->aclk = clk_get(NULL,"aclk_lcdc0");
53                 lcdc_dev->dclk = clk_get(NULL,"dclk_lcdc0");
54                 lcdc_dev->sclk = clk_get(NULL,"sclk_lcdc0");
55         }
56         else
57         {
58                 printk(KERN_ERR "invalid lcdc device!\n");
59                 return -EINVAL;
60         }
61         if (IS_ERR(lcdc_dev->sclk) || (IS_ERR(lcdc_dev->aclk)) ||(IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk)))
62         {
63                 printk(KERN_ERR "failed to get lcdc%d clk source\n",lcdc_dev->id);
64         }
65
66         clk_enable(lcdc_dev->pd);
67         clk_enable(lcdc_dev->hclk);  //enable aclk and hclk for register config
68         clk_enable(lcdc_dev->aclk);  
69         lcdc_dev->clk_on = 1;
70         LcdSetBit(lcdc_dev,SYS_CFG, m_LCDC_AXICLK_AUTO_ENABLE);//eanble axi-clk auto gating for low power
71         LcdMskReg(lcdc_dev,INT_STATUS,m_FRM_START_INT_CLEAR | m_BUS_ERR_INT_CLEAR | m_LINE_FLAG_INT_EN |
72               m_FRM_START_INT_EN | m_HOR_START_INT_EN,v_FRM_START_INT_CLEAR(1) | v_BUS_ERR_INT_CLEAR(0) |
73               v_LINE_FLAG_INT_EN(0) | v_FRM_START_INT_EN(0) | v_HOR_START_INT_EN(0));  //enable frame start interrupt for sync
74         //LCDC_REG_CFG_DONE();  // write any value to  REG_CFG_DONE let config become effective
75         return 0;
76 }
77
78 static int rk2928_lcdc_deinit(struct rk2928_lcdc_device *lcdc_dev)
79 {
80         spin_lock(&lcdc_dev->reg_lock);
81         if(likely(lcdc_dev->clk_on))
82         {
83                 lcdc_dev->clk_on = 0;
84                 LcdMskReg(lcdc_dev, INT_STATUS, m_FRM_START_INT_CLEAR, v_FRM_START_INT_CLEAR(1));
85                 LcdMskReg(lcdc_dev, INT_STATUS, m_HOR_START_INT_EN | m_FRM_START_INT_EN | 
86                         m_LINE_FLAG_INT_EN | m_BUS_ERR_INT_EN,v_HOR_START_INT_EN(0) | v_FRM_START_INT_EN(0) | 
87                         v_LINE_FLAG_INT_EN(0) | v_BUS_ERR_INT_EN(0));  //disable all lcdc interrupt
88                 LcdSetBit(lcdc_dev,SYS_CFG,m_LCDC_STANDBY);
89                 LCDC_REG_CFG_DONE();
90                 spin_unlock(&lcdc_dev->reg_lock);
91         }
92         else   //clk already disabled 
93         {
94                 spin_unlock(&lcdc_dev->reg_lock);
95                 return 0;
96         }
97         mdelay(1);
98         
99         return 0;
100 }
101
102 static int rk2928_load_screen(struct rk_lcdc_device_driver *dev_drv, bool initscreen)
103 {
104         int ret = -EINVAL;
105         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
106         rk_screen *screen = dev_drv->cur_screen;
107         rk_screen *screen0 = dev_drv->screen0;
108         u64 ft;
109         int fps;
110         u16 face;
111         u16 right_margin = screen->right_margin;
112         u16 lower_margin = screen->lower_margin;
113         u16 x_res = screen->x_res, y_res = screen->y_res;
114         DBG(1,"left_margin:%d>>hsync_len:%d>>xres:%d>>right_margin:%d>>upper_margin:%d>>vsync_len:%d>>yres:%d>>lower_margin:%d\n",
115                 screen->left_margin,screen->hsync_len,screen->x_res,screen->right_margin,screen->upper_margin,screen->vsync_len,screen->y_res,
116                 screen->lower_margin);
117         // set the rgb or mcu
118         spin_lock(&lcdc_dev->reg_lock);
119         if(likely(lcdc_dev->clk_on))
120         {
121                 if(screen->type==SCREEN_MCU)
122                 {
123                         printk(KERN_ERR "MCU Screen is not supported by RK2928\n");
124         
125                 }
126
127                 switch (screen->face)
128                 {
129                         case OUT_P565:
130                                 face = OUT_P565;
131                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
132                                 break;
133                         case OUT_P666:
134                                 face = OUT_P666;
135                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
136                                 break;
137                         case OUT_D888_P565:
138                                 face = OUT_P888;
139                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
140                                 break;
141                         case OUT_D888_P666:
142                                 face = OUT_P888;
143                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
144                                 break;
145                         case OUT_P888:
146                                 face = OUT_P888;
147                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_UP_EN, v_DITHER_UP_EN(0));
148                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
149                                 break;
150                         default:
151                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_UP_EN, v_DITHER_UP_EN(0));
152                                 LcdMskReg(lcdc_dev, DSP_CTRL, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
153                                 face = screen->face;
154                                 break;
155                 }
156
157                 //use default overlay,set vsyn hsync den dclk polarity
158                 LcdMskReg(lcdc_dev, DSP_CTRL,m_DISPLAY_FORMAT | m_HSYNC_POLARITY | m_VSYNC_POLARITY |
159                         m_DEN_POLARITY |m_DCLK_POLARITY | m_OUTPUT_RB_SWAP | m_OUTPUT_RG_SWAP | m_BLACK_MODE,
160                         v_DISPLAY_FORMAT(face) | v_HSYNC_POLARITY(screen->pin_hsync) | 
161                         v_VSYNC_POLARITY(screen->pin_vsync) | v_DEN_POLARITY(screen->pin_den) |
162                         v_DCLK_POLARITY(screen->pin_dclk) | v_OUTPUT_RB_SWAP(screen->swap_rb) | 
163                         v_OUTPUT_RG_SWAP(screen->swap_rg) |v_BLACK_MODE(0));
164
165                 //set background color to black,set swap according to the screen panel,disable blank mode
166                 LcdMskReg(lcdc_dev, BG_COLOR, m_BG_COLOR ,v_BG_COLOR(0x000000));
167
168                 
169                 LcdWrReg(lcdc_dev, DSP_HTOTAL_HS_END,v_HSYNC(screen->hsync_len) |
170                      v_HORPRD(screen->hsync_len + screen->left_margin + x_res + right_margin));
171                 LcdWrReg(lcdc_dev, DSP_HACT_ST_END, v_HAEP(screen->hsync_len + screen->left_margin + x_res) |
172                      v_HASP(screen->hsync_len + screen->left_margin));
173
174                 LcdWrReg(lcdc_dev, DSP_VTOTAL_VS_END, v_VSYNC(screen->vsync_len) |
175                       v_VERPRD(screen->vsync_len + screen->upper_margin + y_res + lower_margin));
176                 LcdWrReg(lcdc_dev, DSP_VACT_ST_END,  v_VAEP(screen->vsync_len + screen->upper_margin+y_res)|
177                       v_VASP(screen->vsync_len + screen->upper_margin));
178
179
180          if(dev_drv->screen0->lcdc_id == 1)
181          {
182                 //set register for scaller
183                 LcdMskReg(lcdc_dev,SCL_REG0,m_SCL_DSP_ZERO | m_SCL_DEN_INVERT |
184                         m_SCL_SYNC_INVERT | m_SCL_DCLK_INVERT | m_SCL_EN,v_SCL_DSP_ZERO(0) |
185                         v_SCL_DEN_INVERT(screen0->s_den_inv) | v_SCL_SYNC_INVERT(screen0->s_hv_sync_inv) |
186                         v_SCL_DCLK_INVERT(screen0->s_clk_inv) | v_SCL_EN(1));
187                 LcdWrReg(lcdc_dev,SCL_REG2,v_HASP(screen0->s_vsync_st) | v_HAEP(screen0->s_hsync_st));
188                 LcdWrReg(lcdc_dev,SCL_REG3,v_HASP(screen0->s_hsync_len) |
189                          v_HAEP(screen0->s_hsync_len + screen0->s_left_margin + 
190                          screen0->x_res + screen0->s_right_margin));
191                 LcdWrReg(lcdc_dev,SCL_REG4,v_HASP(screen0->s_hsync_len + screen0->s_left_margin) |
192                          v_HAEP(screen0->s_hsync_len + screen0->s_left_margin + screen0->x_res));
193                 LcdWrReg(lcdc_dev,SCL_REG5,v_VASP(screen0->s_vsync_len) |
194                          v_VAEP(screen0->s_vsync_len + screen0->s_upper_margin +
195                          screen0->y_res + screen0->s_lower_margin));
196                 LcdWrReg(lcdc_dev,SCL_REG6,v_VASP(screen0->s_vsync_len + 
197                          screen0->s_upper_margin) | v_VAEP(screen0->s_vsync_len +
198                          screen0->s_upper_margin + screen0->y_res ));
199                 LcdWrReg(lcdc_dev,SCL_REG8,v_VASP(screen0->s_vsync_len + screen0->s_upper_margin) |
200                          v_VAEP(screen0->s_vsync_len + screen0->s_upper_margin + screen0->y_res));
201                 LcdWrReg(lcdc_dev,SCL_REG7,v_HASP(screen0->s_hsync_len + screen0->s_left_margin) |
202                          v_HAEP(screen0->s_hsync_len + screen0->s_left_margin + screen0->x_res ));
203                 LcdWrReg(lcdc_dev,SCL_REG1,v_SCL_V_FACTOR(0x1000)|v_SCL_H_FACTOR(0x1000));
204          }
205                 // let above to take effect
206                 //LCDC_REG_CFG_DONE();
207         }
208         spin_unlock(&lcdc_dev->reg_lock);
209
210 #ifdef CONFIG_RK_LVDS
211         rk_lvds_register(dev_drv->screen0);
212 #endif
213         if(dev_drv->screen0->type == SCREEN_RGB) //iomux for RGB screen
214         {
215
216                 if(dev_drv->screen0->lcdc_id == 0)
217                 {
218                         rk30_mux_api_set(GPIO2B0_LCDC0_DCLK_LCDC1_DCLK_NAME, GPIO2B_LCDC0_DCLK);
219                         rk30_mux_api_set(GPIO2B1_LCDC0_HSYNC_LCDC1_HSYNC_NAME, GPIO2B_LCDC0_HSYNC);
220                         rk30_mux_api_set(GPIO2B2_LCDC0_VSYNC_LCDC1_VSYNC_NAME, GPIO2B_LCDC0_VSYNC);
221                         rk30_mux_api_set(GPIO2B3_LCDC0_DEN_LCDC1_DEN_NAME, GPIO2B_LCDC0_DEN);
222                         rk30_mux_api_set(GPIO2B4_LCDC0_D10_LCDC1_D10_NAME, GPIO2B_LCDC0_D10);
223                         rk30_mux_api_set(GPIO2B5_LCDC0_D11_LCDC1_D11_NAME, GPIO2B_LCDC0_D11);
224                         rk30_mux_api_set(GPIO2B6_LCDC0_D12_LCDC1_D12_NAME, GPIO2B_LCDC0_D12);
225                         rk30_mux_api_set(GPIO2B7_LCDC0_D13_LCDC1_D13_NAME, GPIO2B_LCDC0_D13);
226                         rk30_mux_api_set(GPIO2C0_LCDC0_D14_LCDC1_D14_NAME, GPIO2C_LCDC0_D14);
227                         rk30_mux_api_set(GPIO2C1_LCDC0_D15_LCDC1_D15_NAME, GPIO2C_LCDC0_D15);
228                         rk30_mux_api_set(GPIO2C2_LCDC0_D16_LCDC1_D16_NAME, GPIO2C_LCDC0_D16);
229                         rk30_mux_api_set(GPIO2C3_LCDC0_D17_LCDC1_D17_NAME, GPIO2C_LCDC0_D17);
230                 }
231                 else if(dev_drv->screen0->lcdc_id == 1)
232                 {
233                         rk30_mux_api_set(GPIO2B0_LCDC0_DCLK_LCDC1_DCLK_NAME, GPIO2B_LCDC1_DCLK);
234                         rk30_mux_api_set(GPIO2B1_LCDC0_HSYNC_LCDC1_HSYNC_NAME, GPIO2B_LCDC1_HSYNC);
235                         rk30_mux_api_set(GPIO2B2_LCDC0_VSYNC_LCDC1_VSYNC_NAME, GPIO2B_LCDC1_VSYNC);
236                         rk30_mux_api_set(GPIO2B3_LCDC0_DEN_LCDC1_DEN_NAME, GPIO2B_LCDC1_DEN);
237                         rk30_mux_api_set(GPIO2B4_LCDC0_D10_LCDC1_D10_NAME, GPIO2B_LCDC1_D10);
238                         rk30_mux_api_set(GPIO2B5_LCDC0_D11_LCDC1_D11_NAME, GPIO2B_LCDC1_D11);
239                         rk30_mux_api_set(GPIO2B6_LCDC0_D12_LCDC1_D12_NAME, GPIO2B_LCDC1_D12);
240                         rk30_mux_api_set(GPIO2B7_LCDC0_D13_LCDC1_D13_NAME, GPIO2B_LCDC1_D13);
241                         rk30_mux_api_set(GPIO2C0_LCDC0_D14_LCDC1_D14_NAME, GPIO2C_LCDC1_D14);
242                         rk30_mux_api_set(GPIO2C1_LCDC0_D15_LCDC1_D15_NAME, GPIO2C_LCDC1_D15);
243                         rk30_mux_api_set(GPIO2C2_LCDC0_D16_LCDC1_D16_NAME, GPIO2C_LCDC1_D16);
244                         rk30_mux_api_set(GPIO2C3_LCDC0_D17_LCDC1_D17_NAME, GPIO2C_LCDC1_D17);
245                 }
246                 else
247                 {
248                         printk(KERN_WARNING "%s>>>no such interface:%d\n",dev_drv->cur_screen->lcdc_id);
249                         return -1;
250                 }
251                 
252                 //rk30_mux_api_set(GPIO2C4_LCDC0_D18_LCDC1_D18_I2C2_SDA_NAME, GPIO2C_LCDC1_D18);
253                 //rk30_mux_api_set(GPIO2C5_LCDC0_D19_LCDC1_D19_I2C2_SCL_NAME, GPIO2C_LCDC1_D19);
254                 //rk30_mux_api_set(GPIO2C6_LCDC0_D20_LCDC1_D20_UART2_SIN_NAME, GPIO2C_LCDC1_D20);
255                 //rk30_mux_api_set(GPIO2C7_LCDC0_D21_LCDC1_D21_UART2_SOUT_NAME, GPIO2C_LCDC1_D21);
256                 //rk30_mux_api_set(GPIO2D0_LCDC0_D22_LCDC1_D22_NAME, GPIO2D_LCDC1_D22);
257                 //rk30_mux_api_set(GPIO2D1_LCDC0_D23_LCDC1_D23_NAME, GPIO2D_LCDC1_D23);
258                 printk("RGB screen connect to rk2928 lcdc interface%d\n",dev_drv->screen0->lcdc_id);
259
260         }
261
262         ret = clk_set_rate(lcdc_dev->dclk, screen->pixclock);
263         if(ret)
264         {
265                 printk(KERN_ERR ">>>>>> set lcdc%d dclk failed\n",lcdc_dev->id);
266         }
267         lcdc_dev->driver.pixclock = lcdc_dev->pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
268         clk_enable(lcdc_dev->dclk);
269         if(dev_drv->screen0->lcdc_id == 1)  //if connect to output interface 1,need scale
270         {
271                 ret = clk_set_rate(lcdc_dev->sclk, screen0->s_pixclock);
272                 if(ret)
273                 {
274                         printk(KERN_ERR ">>>>>> set lcdc%d sclk failed\n",lcdc_dev->id);
275                 }
276                 lcdc_dev->driver.pixclock = lcdc_dev->pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->sclk));
277                 //printk("%s: sclk:%lu>>need:%d",lcdc_dev->driver.name,,screen0->s_pixclock);
278                 clk_enable(lcdc_dev->sclk);
279         }
280         
281         
282         
283         ft = (u64)(screen->upper_margin + screen->lower_margin + screen->y_res +screen->vsync_len)*
284                 (screen->left_margin + screen->right_margin + screen->x_res + screen->hsync_len)*
285                 (dev_drv->pixclock);       // one frame time ,(pico seconds)
286         fps = div64_u64(1000000000000llu,ft);
287         screen->ft = 1000/fps;
288         printk("%s: dclk:%lu>>sclk:%lu>>fps:%d ",lcdc_dev->driver.name,clk_get_rate(lcdc_dev->dclk), 
289                 clk_get_rate(lcdc_dev->sclk),fps);
290
291         if(screen->init)
292         {
293                 screen->init();
294         }
295         
296         printk("%s for lcdc%d ok!\n",__func__,lcdc_dev->id);
297         return 0;
298 }
299
300
301 //enable layer,open:1,enable;0 disable
302 static int win0_open(struct rk2928_lcdc_device *lcdc_dev,bool open)
303 {
304         
305         spin_lock(&lcdc_dev->reg_lock);
306         if(likely(lcdc_dev->clk_on))
307         {
308                 if(open)
309                 {
310                         if(!lcdc_dev->atv_layer_cnt)
311                         {
312                                 LcdClrBit(lcdc_dev, SYS_CFG,m_LCDC_STANDBY);
313                         }
314                         lcdc_dev->atv_layer_cnt++;
315                 }
316                 else
317                 {
318                         lcdc_dev->atv_layer_cnt--;
319                 }
320                 lcdc_dev->driver.layer_par[0]->state = open;
321                 
322                 LcdMskReg(lcdc_dev, SYS_CFG, m_W0_EN, v_W0_EN(open));
323                 if(!lcdc_dev->atv_layer_cnt)  //if no layer used,disable lcdc
324                 {
325                         LcdSetBit(lcdc_dev, SYS_CFG,m_LCDC_STANDBY);
326                 }
327                 //LCDC_REG_CFG_DONE();  
328         }
329         spin_unlock(&lcdc_dev->reg_lock);
330         printk(KERN_INFO "lcdc%d win0 %s\n",lcdc_dev->id,open?"open":"closed");
331         return 0;
332 }
333 static int win1_open(struct rk2928_lcdc_device *lcdc_dev,bool open)
334 {
335         spin_lock(&lcdc_dev->reg_lock);
336         if(likely(lcdc_dev->clk_on))
337         {
338                 if(open)
339                 {
340                         if(!lcdc_dev->atv_layer_cnt)
341                         {
342                                 printk("lcdc%d wakeup from stanby\n",lcdc_dev->id);
343                                 LcdClrBit(lcdc_dev, SYS_CFG,m_LCDC_STANDBY);
344                         }
345                         lcdc_dev->atv_layer_cnt++;
346                 }
347                 else
348                 {
349                         lcdc_dev->atv_layer_cnt--;
350                 }
351                 lcdc_dev->driver.layer_par[1]->state = open;
352                 
353                 LcdMskReg(lcdc_dev, SYS_CFG, m_W1_EN, v_W1_EN(open));
354                 if(!lcdc_dev->atv_layer_cnt)  //if no layer used,disable lcdc
355                 {
356                         printk(KERN_INFO "no layer of lcdc%d is used,go to standby!",lcdc_dev->id);
357                         LcdSetBit(lcdc_dev, SYS_CFG,m_LCDC_STANDBY);
358                 }
359                 //LCDC_REG_CFG_DONE();
360         }
361         spin_unlock(&lcdc_dev->reg_lock);
362         printk(KERN_INFO "lcdc%d win1 %s\n",lcdc_dev->id,open?"open":"closed");
363         return 0;
364 }
365
366
367 static int rk2928_lcdc_blank(struct rk_lcdc_device_driver*lcdc_drv,int layer_id,int blank_mode)
368 {
369         struct rk2928_lcdc_device * lcdc_dev = container_of(lcdc_drv,struct rk2928_lcdc_device ,driver);
370
371         printk(KERN_INFO "%s>>>>>%d\n",__func__, blank_mode);
372
373         spin_lock(&lcdc_dev->reg_lock);
374         if(likely(lcdc_dev->clk_on))
375         {
376                 switch(blank_mode)
377                 {
378                         case FB_BLANK_UNBLANK:
379                                 LcdMskReg(lcdc_dev,DSP_CTRL,m_BLANK_MODE ,v_BLANK_MODE(0));
380                                 break;
381                         case FB_BLANK_NORMAL:
382                                 LcdMskReg(lcdc_dev,DSP_CTRL,m_BLANK_MODE ,v_BLANK_MODE(1));
383                                 break;
384                         default:
385                                 LcdMskReg(lcdc_dev,DSP_CTRL,m_BLANK_MODE ,v_BLANK_MODE(1));
386                                 break;
387                 }
388                 LCDC_REG_CFG_DONE();
389         }
390         spin_unlock(&lcdc_dev->reg_lock);
391         
392         return 0;
393 }
394
395 static  int win0_display(struct rk2928_lcdc_device *lcdc_dev,struct layer_par *par )
396 {
397         u32 y_addr;
398         u32 uv_addr;
399         y_addr = par->smem_start + par->y_offset;
400         uv_addr = par->cbr_start + par->c_offset;
401         DBG(2,KERN_INFO "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x\n",lcdc_dev->id,__func__,y_addr,uv_addr);
402
403         spin_lock(&lcdc_dev->reg_lock);
404         if(likely(lcdc_dev->clk_on))
405         {
406                 LcdWrReg(lcdc_dev, WIN0_YRGB_MST,y_addr);
407                 LcdWrReg(lcdc_dev, WIN0_CBR_MST,uv_addr);
408                 LCDC_REG_CFG_DONE();
409         }
410         spin_unlock(&lcdc_dev->reg_lock);
411
412         return 0;
413         
414 }
415
416 static  int win1_display(struct rk2928_lcdc_device *lcdc_dev,struct layer_par *par )
417 {
418         u32 y_addr;
419         u32 uv_addr;
420         y_addr = par->smem_start + par->y_offset;
421         uv_addr = par->cbr_start + par->c_offset;
422         DBG(2,KERN_INFO "lcdc%d>>%s>>y_addr:0x%x>>uv_addr:0x%x\n",lcdc_dev->id,__func__,y_addr,uv_addr);
423         
424         spin_lock(&lcdc_dev->reg_lock);
425         if(likely(lcdc_dev->clk_on))
426         {
427                 LcdWrReg(lcdc_dev, WIN1_RGB_MST, y_addr);
428                 LCDC_REG_CFG_DONE();
429         }
430         spin_unlock(&lcdc_dev->reg_lock);
431         
432         return 0;
433 }
434
435 static  int win0_set_par(struct rk2928_lcdc_device *lcdc_dev,rk_screen *screen,
436         struct layer_par *par )
437 {
438         u32 xact, yact, xvir, yvir, xpos, ypos;
439         u32 ScaleYrgbX = 0x1000;
440         u32 ScaleYrgbY = 0x1000;
441         u32 ScaleCbrX = 0x1000;
442         u32 ScaleCbrY = 0x1000;
443         
444         xact = par->xact;                           //active (origin) picture window width/height               
445         yact = par->yact;
446         xvir = par->xvir;                          // virtual resolution                
447         yvir = par->yvir;
448         xpos = par->xpos+screen->left_margin + screen->hsync_len;
449         ypos = par->ypos+screen->upper_margin + screen->vsync_len;
450
451         ScaleYrgbX = CalScale(xact, par->xsize); //both RGB and yuv need this two factor
452         ScaleYrgbY = CalScale(yact, par->ysize);
453         switch (par->format)
454         {
455                 case YUV422:// yuv422
456                         ScaleCbrX = CalScale((xact/2), par->xsize);
457                         ScaleCbrY = CalScale(yact, par->ysize);
458                         break;
459                 case YUV420: // yuv420
460                         ScaleCbrX = CalScale(xact/2, par->xsize);
461                         ScaleCbrY = CalScale(yact/2, par->ysize);
462                         break;
463                 case YUV444:// yuv444
464                         ScaleCbrX = CalScale(xact, par->xsize);
465                         ScaleCbrY = CalScale(yact, par->ysize);
466                         break;
467                 default:
468                    break;
469         }
470
471         DBG(1,"%s for lcdc%d>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n",
472                 __func__,lcdc_dev->id,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,xpos,ypos);
473         
474         spin_lock(&lcdc_dev->reg_lock);
475         if(likely(lcdc_dev->clk_on))
476         {
477                 LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_YRGB, v_X_SCL_FACTOR(ScaleYrgbX) | v_Y_SCL_FACTOR(ScaleYrgbY));
478                 LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_CBR,v_X_SCL_FACTOR(ScaleCbrX)| v_Y_SCL_FACTOR(ScaleCbrY));
479                 LcdMskReg(lcdc_dev, SYS_CFG, m_W0_FORMAT, v_W0_FORMAT(par->format));            //(inf->video_mode==0)
480                 LcdWrReg(lcdc_dev, WIN0_ACT_INFO,v_ACT_WIDTH(xact) | v_ACT_HEIGHT(yact));
481                 LcdWrReg(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(xpos) | v_DSP_STY(ypos));
482                 LcdWrReg(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(par->xsize)| v_DSP_HEIGHT(par->ysize));
483                 LcdMskReg(lcdc_dev,WIN0_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR,
484                         v_COLORKEY_EN(1) | v_KEYCOLOR(0));
485                 switch(par->format) 
486                 {
487                         case ARGB888:
488                                 LcdMskReg(lcdc_dev, WIN_VIR,m_WIN0_VIR,v_WIN0_ARGB888_VIRWIDTH(xvir));
489                                 //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W0_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1));
490                                 break;
491                         case RGB888:  //rgb888
492                                 LcdMskReg(lcdc_dev, WIN_VIR,m_WIN0_VIR,v_WIN0_RGB888_VIRWIDTH(xvir));
493                                 //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W0_RGB_RB_SWAP,v_W0_RGB_RB_SWAP(1));
494                                 break;
495                         case RGB565:  //rgb565
496                                 LcdMskReg(lcdc_dev, WIN_VIR,m_WIN0_VIR,v_WIN0_RGB565_VIRWIDTH(xvir));
497                                 break;
498                         case YUV422:
499                         case YUV420:   
500                                 LcdMskReg(lcdc_dev, WIN_VIR,m_WIN0_VIR,v_WIN0_YUV_VIRWIDTH(xvir));
501                                 break;
502                         default:
503                                 LcdMskReg(lcdc_dev, WIN_VIR,m_WIN0_VIR,v_WIN0_RGB888_VIRWIDTH(xvir));
504                                 break;
505                 }
506                 
507                 LCDC_REG_CFG_DONE();
508         }
509         spin_unlock(&lcdc_dev->reg_lock);
510
511     return 0;
512
513 }
514
515 static int win1_set_par(struct rk2928_lcdc_device *lcdc_dev,rk_screen *screen,
516         struct layer_par *par )
517 {
518         u32 xact, yact, xvir, yvir, xpos, ypos;
519         u32 ScaleYrgbX = 0x1000;
520         u32 ScaleYrgbY = 0x1000;
521         u32 ScaleCbrX = 0x1000;
522         u32 ScaleCbrY = 0x1000;
523         
524         xact = par->xact;                       
525         yact = par->yact;
526         xvir = par->xvir;               
527         yvir = par->yvir;
528         xpos = par->xpos+screen->left_margin + screen->hsync_len;
529         ypos = par->ypos+screen->upper_margin + screen->vsync_len;
530         
531         DBG(1,"%s for lcdc%d>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n",
532                 __func__,lcdc_dev->id,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,xpos,ypos);
533
534         
535         spin_lock(&lcdc_dev->reg_lock);
536         if(likely(lcdc_dev->clk_on))
537         {
538                 LcdMskReg(lcdc_dev,SYS_CFG, m_W1_FORMAT, v_W1_FORMAT(par->format));
539                 LcdWrReg(lcdc_dev, WIN1_DSP_ST,v_DSP_STX(xpos) | v_DSP_STY(ypos));
540                 LcdWrReg(lcdc_dev, WIN1_DSP_INFO,v_DSP_WIDTH(par->xsize) | v_DSP_HEIGHT(par->ysize));
541                 // enable win1 color key and set the color to black(rgb=0)
542                 LcdMskReg(lcdc_dev, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR,v_COLORKEY_EN(1) | v_KEYCOLOR(0));
543
544                 
545                 switch(par->format)
546                {
547                        case ARGB888:
548                                LcdMskReg(lcdc_dev, WIN_VIR,m_WIN1_VIR,v_WIN1_ARGB888_VIRWIDTH(xvir));
549                                //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W1_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1));
550                                break;
551                        case RGB888:  //rgb888
552                                LcdMskReg(lcdc_dev, WIN_VIR,m_WIN1_VIR,v_WIN1_RGB888_VIRWIDTH(xvir));
553                                // LcdMskReg(lcdc_dev,SYS_CTRL1,m_W1_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1));
554                                break;
555                        case RGB565:  //rgb565
556                                LcdMskReg(lcdc_dev, WIN_VIR,m_WIN1_VIR,v_WIN1_RGB565_VIRWIDTH(xvir));
557                                break;
558                        default:
559                                LcdMskReg(lcdc_dev, WIN_VIR,m_WIN1_VIR,v_WIN1_RGB888_VIRWIDTH(xvir));
560                                break;
561                }
562                 
563                 
564                 //LCDC_REG_CFG_DONE(); 
565         }
566         spin_unlock(&lcdc_dev->reg_lock);
567     return 0;
568 }
569
570 static int rk2928_lcdc_open(struct rk_lcdc_device_driver *dev_drv,int layer_id,bool open)
571 {
572         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
573         if(layer_id == 0)
574         {
575                 win0_open(lcdc_dev,open);       
576         }
577         else if(layer_id == 1)
578         {
579                 win1_open(lcdc_dev,open);
580         }
581
582         return 0;
583 }
584
585 static int rk2928_lcdc_set_par(struct rk_lcdc_device_driver *dev_drv,int layer_id)
586 {
587         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
588         struct layer_par *par = NULL;
589         rk_screen *screen = dev_drv->cur_screen;
590         rk_screen *screen0 = dev_drv->screen0;
591         u32 Scl_X = 0x1000;
592         u32 Scl_Y = 0x1000;
593         
594         if(!screen)
595         {
596                 printk(KERN_ERR "screen is null!\n");
597                 return -ENOENT;
598         }
599         if(layer_id==0)
600         {
601                 par = dev_drv->layer_par[0];
602                 win0_set_par(lcdc_dev,screen,par);
603         }
604         else if(layer_id==1)
605         {
606                 par = dev_drv->layer_par[1];
607                 win1_set_par(lcdc_dev,screen,par);
608         }
609         Scl_X = CalScale(screen->x_res - 1,screen0->x_res - 1);
610         Scl_Y = CalScale(screen->y_res - 1 ,screen0->y_res - 1);
611         LcdWrReg(lcdc_dev,SCL_REG1,v_SCL_V_FACTOR(Scl_Y)|v_SCL_H_FACTOR(Scl_X));
612         
613         return 0;
614 }
615
616 int rk2928_lcdc_pan_display(struct rk_lcdc_device_driver * dev_drv,int layer_id)
617 {
618         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
619         struct layer_par *par = NULL;
620         rk_screen *screen = dev_drv->cur_screen;
621         unsigned long flags;
622         int timeout;
623         if(!screen)
624         {
625                 printk(KERN_ERR "screen is null!\n");
626                 return -ENOENT; 
627         }
628         if(layer_id==0)
629         {
630                 par = dev_drv->layer_par[0];
631                 win0_display(lcdc_dev,par);
632         }
633         else if(layer_id==1)
634         {
635                 par = dev_drv->layer_par[1];
636                 win1_display(lcdc_dev,par);
637         }
638         if((dev_drv->first_frame))  //this is the first frame of the system ,enable frame start interrupt
639         {
640                 dev_drv->first_frame = 0;
641                 LcdMskReg(lcdc_dev,INT_STATUS,m_FRM_START_INT_CLEAR |m_FRM_START_INT_EN ,
642                           v_FRM_START_INT_CLEAR(1) | v_FRM_START_INT_EN(1));
643                 LCDC_REG_CFG_DONE();  // write any value to  REG_CFG_DONE let config become effective
644                  
645         }
646
647         if(dev_drv->num_buf < 3) //3buffer ,no need to  wait for sysn
648         {
649                 spin_lock_irqsave(&dev_drv->cpl_lock,flags);
650                 init_completion(&dev_drv->frame_done);
651                 spin_unlock_irqrestore(&dev_drv->cpl_lock,flags);
652                 timeout = wait_for_completion_timeout(&dev_drv->frame_done,msecs_to_jiffies(dev_drv->cur_screen->ft+5));
653                 if(!timeout&&(!dev_drv->frame_done.done))
654                 {
655                         //printk(KERN_ERR "wait for new frame start time out!\n");
656                         return -ETIMEDOUT;
657                 }
658         }
659         
660         return 0;
661 }
662
663 int rk2928_lcdc_ioctl(struct rk_lcdc_device_driver * dev_drv,unsigned int cmd, unsigned long arg,int layer_id)
664 {
665         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
666         u32 panel_size[2];
667         void __user *argp = (void __user *)arg;
668         int ret = 0;
669         switch(cmd)
670         {
671                 case FBIOGET_PANEL_SIZE:    //get panel size
672                         panel_size[0] = lcdc_dev->screen->x_res;
673                         panel_size[1] = lcdc_dev->screen->y_res;
674                         if(copy_to_user(argp, panel_size, 8)) 
675                                 return -EFAULT;
676                         break;
677                 default:
678                         break;
679         }
680
681         return ret;
682 }
683 static int rk2928_lcdc_get_layer_state(struct rk_lcdc_device_driver *dev_drv,int layer_id)
684 {
685         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
686         struct layer_par *par = dev_drv->layer_par[layer_id];
687
688         spin_lock(&lcdc_dev->reg_lock);
689         if(lcdc_dev->clk_on)
690         {
691                 if(layer_id == 0)
692                 {
693                         par->state = LcdReadBit(lcdc_dev,SYS_CFG,m_W0_EN);
694                 }
695                 else if( layer_id == 1)
696                 {
697                         par->state = LcdReadBit(lcdc_dev,SYS_CFG,m_W1_EN);
698                 }
699         }
700         spin_unlock(&lcdc_dev->reg_lock);
701         
702         return par->state;
703         
704 }
705
706 /***********************************
707 overlay manager
708 swap:1 win0 on the top of win1
709         0 win1 on the top of win0
710 set  : 1 set overlay 
711         0 get overlay state
712 ************************************/
713 static int rk2928_lcdc_ovl_mgr(struct rk_lcdc_device_driver *dev_drv,int swap,bool set)
714 {
715         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
716         int ovl;
717         spin_lock(&lcdc_dev->reg_lock);
718         if(lcdc_dev->clk_on)
719         {
720                 if(set)  //set overlay
721                 {
722                         LcdMskReg(lcdc_dev,DSP_CTRL,m_W0W1_POSITION_SWAP,v_W0W1_POSITION_SWAP(swap));
723                         LCDC_REG_CFG_DONE();
724                         ovl = swap;
725                 }
726                 else  //get overlay
727                 {
728                         ovl = LcdReadBit(lcdc_dev,DSP_CTRL,m_W0W1_POSITION_SWAP);
729                 }
730         }
731         else
732         {
733                 ovl = -EPERM;
734         }
735         spin_unlock(&lcdc_dev->reg_lock);
736
737         return ovl;
738 }
739 static int rk2928_lcdc_get_disp_info(struct rk_lcdc_device_driver *dev_drv,int layer_id)
740 {
741         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
742         return 0;
743 }
744
745
746 /*******************************************
747 lcdc fps manager,set or get lcdc fps
748 set:0 get
749      1 set
750 ********************************************/
751 static int rk2928_lcdc_fps_mgr(struct rk_lcdc_device_driver *dev_drv,int fps,bool set)
752 {
753         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
754         rk_screen * screen = dev_drv->cur_screen;
755         u64 ft = 0;
756         u32 dotclk;
757         int ret;
758
759         if(set)
760         {
761                 ft = div_u64(1000000000000llu,fps);
762                 dev_drv->pixclock = div_u64(ft,(screen->upper_margin + screen->lower_margin + screen->y_res +screen->vsync_len)*
763                                 (screen->left_margin + screen->right_margin + screen->x_res + screen->hsync_len));
764                 dotclk = div_u64(1000000000000llu,dev_drv->pixclock);
765                 ret = clk_set_rate(lcdc_dev->dclk, dotclk);
766                 if(ret)
767                 {
768                         printk(KERN_ERR ">>>>>> set lcdc%d dclk failed\n",lcdc_dev->id);
769                 }
770                 dev_drv->pixclock = lcdc_dev->pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
771                         
772         }
773         
774         ft = (u64)(screen->upper_margin + screen->lower_margin + screen->y_res +screen->vsync_len)*
775         (screen->left_margin + screen->right_margin + screen->x_res + screen->hsync_len)*
776         (dev_drv->pixclock);       // one frame time ,(pico seconds)
777         fps = div64_u64(1000000000000llu,ft);
778         screen->ft = 1000/fps ;  //one frame time in ms
779         return fps;
780 }
781
782
783 static int rk2928_fb_layer_remap(struct rk_lcdc_device_driver *dev_drv,
784         enum fb_win_map_order order)
785 {
786         mutex_lock(&dev_drv->fb_win_id_mutex);
787         if(order == FB_DEFAULT_ORDER)
788         {
789                 order = FB0_WIN0_FB1_WIN1_FB2_WIN2;
790         }
791         dev_drv->fb2_win_id  = order/100;
792         dev_drv->fb1_win_id = (order/10)%10;
793         dev_drv->fb0_win_id = order%10;
794         mutex_unlock(&dev_drv->fb_win_id_mutex);
795
796         printk("fb0:win%d\nfb1:win%d\nfb2:win%d\n",dev_drv->fb0_win_id,dev_drv->fb1_win_id,
797                 dev_drv->fb2_win_id);
798
799         return 0;
800 }
801
802 static int rk2928_fb_get_layer(struct rk_lcdc_device_driver *dev_drv,const char *id)
803 {
804         int layer_id = 0;
805         mutex_lock(&dev_drv->fb_win_id_mutex);
806         if(!strcmp(id,"fb0"))
807         {
808                 layer_id = dev_drv->fb0_win_id;
809         }
810         else if(!strcmp(id,"fb1"))
811         {
812                 layer_id = dev_drv->fb1_win_id;
813         }
814         else if(!strcmp(id,"fb2"))
815         {
816                 layer_id = dev_drv->fb2_win_id;
817         }
818         else
819         {
820                 printk(KERN_ERR "%s>>un supported %s\n",__func__,id);
821                 layer_id = -1;
822         }
823         mutex_unlock(&dev_drv->fb_win_id_mutex);
824
825         return  layer_id;
826 }
827
828 int rk2928_lcdc_early_suspend(struct rk_lcdc_device_driver *dev_drv)
829 {
830         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
831         
832         if(dev_drv->cur_screen->sscreen_set)
833                 dev_drv->cur_screen->sscreen_set(dev_drv->cur_screen , 0);
834
835         spin_lock(&lcdc_dev->reg_lock);
836         if(likely(lcdc_dev->clk_on))
837         {
838                 lcdc_dev->clk_on = 0;
839                 LcdMskReg(lcdc_dev, INT_STATUS, m_FRM_START_INT_CLEAR, v_FRM_START_INT_CLEAR(1));
840                 LcdSetBit(lcdc_dev, SYS_CFG,m_LCDC_STANDBY);
841                 LCDC_REG_CFG_DONE();
842                 spin_unlock(&lcdc_dev->reg_lock);
843         }
844         else  //clk already disabled
845         {
846                 spin_unlock(&lcdc_dev->reg_lock);
847                 return 0;
848         }
849         
850                 
851         mdelay(1);
852         clk_disable(lcdc_dev->dclk);
853         clk_disable(lcdc_dev->hclk);
854         clk_disable(lcdc_dev->aclk);
855         clk_disable(lcdc_dev->pd);
856
857         return 0;
858 }
859
860
861 int rk2928_lcdc_early_resume(struct rk_lcdc_device_driver *dev_drv)
862 {  
863         struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
864         
865         if(!lcdc_dev->clk_on)
866         {
867                 clk_enable(lcdc_dev->pd);
868                 clk_enable(lcdc_dev->hclk);
869                 clk_enable(lcdc_dev->dclk);
870                 clk_enable(lcdc_dev->aclk);
871         }
872         memcpy((u8*)lcdc_dev->preg, (u8*)&lcdc_dev->regbak, 0xc4);  //resume reg
873
874         spin_lock(&lcdc_dev->reg_lock);
875         if(lcdc_dev->atv_layer_cnt)
876         {
877                 LcdClrBit(lcdc_dev, SYS_CFG,m_LCDC_STANDBY);
878                 LCDC_REG_CFG_DONE();
879         }
880         lcdc_dev->clk_on = 1;
881         spin_unlock(&lcdc_dev->reg_lock);
882         
883         
884         if(dev_drv->cur_screen->sscreen_set)
885                 dev_drv->cur_screen->sscreen_set(dev_drv->cur_screen , 1);
886         
887
888         return 0;
889 }
890 static irqreturn_t rk2928_lcdc_isr(int irq, void *dev_id)
891 {
892         struct rk2928_lcdc_device *lcdc_dev = (struct rk2928_lcdc_device *)dev_id;
893         
894         LcdMskReg(lcdc_dev, INT_STATUS, m_FRM_START_INT_CLEAR, v_FRM_START_INT_CLEAR(1));
895         LCDC_REG_CFG_DONE();
896         //LcdMskReg(lcdc_dev, INT_STATUS, m_LINE_FLAG_INT_CLEAR, v_LINE_FLAG_INT_CLEAR(1));
897  
898         if(lcdc_dev->driver.num_buf < 3)  //three buffer ,no need to wait for sync
899         {
900                 spin_lock(&(lcdc_dev->driver.cpl_lock));
901                 complete(&(lcdc_dev->driver.frame_done));
902                 spin_unlock(&(lcdc_dev->driver.cpl_lock));
903         }
904         return IRQ_HANDLED;
905 }
906
907 static struct layer_par lcdc_layer[] = {
908         [0] = {
909                 .name           = "win0",
910                 .id             = 0,
911                 .support_3d     = true,
912         },
913         [1] = {
914                 .name           = "win1",
915                 .id             = 1,
916                 .support_3d     = false,
917         },
918 };
919
920 static struct rk_lcdc_device_driver lcdc_driver = {
921         .name                   = "lcdc",
922         .def_layer_par          = lcdc_layer,
923         .num_layer              = ARRAY_SIZE(lcdc_layer),
924         .open                   = rk2928_lcdc_open,
925         .init_lcdc              = init_rk2928_lcdc,
926         .ioctl                  = rk2928_lcdc_ioctl,
927         .suspend                = rk2928_lcdc_early_suspend,
928         .resume                 = rk2928_lcdc_early_resume,
929         .set_par                = rk2928_lcdc_set_par,
930         .blank                  = rk2928_lcdc_blank,
931         .pan_display            = rk2928_lcdc_pan_display,
932         .load_screen            = rk2928_load_screen,
933         .get_layer_state        = rk2928_lcdc_get_layer_state,
934         .ovl_mgr                = rk2928_lcdc_ovl_mgr,
935         .get_disp_info          = rk2928_lcdc_get_disp_info,
936         .fps_mgr                = rk2928_lcdc_fps_mgr,
937         .fb_get_layer           = rk2928_fb_get_layer,
938         .fb_layer_remap         = rk2928_fb_layer_remap,
939 };
940 #ifdef CONFIG_PM
941 static int rk2928_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
942 {
943         return 0;
944 }
945
946 static int rk2928_lcdc_resume(struct platform_device *pdev)
947 {
948         return 0;
949 }
950
951 #else
952 #define rk2928_lcdc_suspend NULL
953 #define rk2928_lcdc_resume NULL
954 #endif
955
956 static int __devinit rk2928_lcdc_probe (struct platform_device *pdev)
957 {
958         struct rk2928_lcdc_device *lcdc_dev=NULL;
959         rk_screen *screen0;
960         rk_screen *screen1;
961         struct rk29fb_info *screen_ctr_info;
962         struct resource *res = NULL;
963         struct resource *mem;
964         int ret = 0;
965         
966         /*************Malloc rk2928lcdc_inf and set it to pdev for drvdata**********/
967         lcdc_dev = kzalloc(sizeof(struct rk2928_lcdc_device), GFP_KERNEL);
968         if(!lcdc_dev)
969         {
970                 dev_err(&pdev->dev, ">>rk2928 lcdc device kmalloc fail!");
971                 return -ENOMEM;
972         }
973         platform_set_drvdata(pdev, lcdc_dev);
974         lcdc_dev->id = pdev->id;
975         screen_ctr_info = (struct rk29fb_info * )pdev->dev.platform_data;
976         screen0 =  kzalloc(sizeof(rk_screen), GFP_KERNEL); //rk2928 has one lcdc but two outputs
977         if(!screen0)
978         {
979                 dev_err(&pdev->dev, ">>rk2928 lcdc screen1 kmalloc fail!");
980                 ret =  -ENOMEM;
981                 goto err0;
982         }
983         screen0->lcdc_id = 0;  //this id can be changed dynamic
984         screen0->screen_id = 0; //this id is fixed
985         screen1 =  kzalloc(sizeof(rk_screen), GFP_KERNEL);
986         if(!screen1)
987         {
988                 dev_err(&pdev->dev, ">>rk2928 lcdc screen1 kmalloc fail!");
989                 ret =  -ENOMEM;
990                 goto err0;
991         }
992         screen1->lcdc_id = 1;
993         screen1->screen_id = 1;
994         
995         /****************get lcdc0 reg  *************************/
996         res = platform_get_resource(pdev, IORESOURCE_MEM,0);
997         if (res == NULL)
998         {
999                 dev_err(&pdev->dev, "failed to get io resource for lcdc%d \n",lcdc_dev->id);
1000                 ret = -ENOENT;
1001                 goto err1;
1002         }
1003         lcdc_dev->reg_phy_base = res->start;
1004         lcdc_dev->len = resource_size(res);
1005         mem = request_mem_region(lcdc_dev->reg_phy_base, resource_size(res), pdev->name);
1006         if (mem == NULL)
1007         {
1008                 dev_err(&pdev->dev, "failed to request mem region for lcdc%d\n",lcdc_dev->id);
1009                 ret = -ENOENT;
1010                 goto err1;
1011         }
1012         lcdc_dev->reg_vir_base = ioremap(lcdc_dev->reg_phy_base,  resource_size(res));
1013         if (lcdc_dev->reg_vir_base == NULL)
1014         {
1015                 dev_err(&pdev->dev, "cannot map IO\n");
1016                 ret = -ENXIO;
1017                 goto err2;
1018         }
1019         
1020         lcdc_dev->preg = (LCDC_REG*)lcdc_dev->reg_vir_base;
1021         printk("lcdc%d:reg_phy_base = 0x%08x,reg_vir_base:0x%p\n",pdev->id,lcdc_dev->reg_phy_base, lcdc_dev->preg);
1022         lcdc_dev->driver.dev=&pdev->dev;
1023         lcdc_dev->driver.screen0 = screen0;  //direct out put
1024         lcdc_dev->driver.screen1 = screen1; //out put from scale
1025         lcdc_dev->driver.cur_screen = screen0;
1026         lcdc_dev->driver.screen_ctr_info = screen_ctr_info;
1027         spin_lock_init(&lcdc_dev->reg_lock);
1028         lcdc_dev->irq = platform_get_irq(pdev, 0);
1029         if(lcdc_dev->irq < 0)
1030         {
1031                 dev_err(&pdev->dev, "cannot find IRQ\n");
1032                 goto err3;
1033         }
1034         ret = request_irq(lcdc_dev->irq, rk2928_lcdc_isr, IRQF_DISABLED,dev_name(&pdev->dev),lcdc_dev);
1035         if (ret)
1036         {
1037                dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n", lcdc_dev->irq, ret);
1038                ret = -EBUSY;
1039                goto err3;
1040         }
1041         ret = rk_fb_register(&(lcdc_dev->driver),&lcdc_driver,lcdc_dev->id);
1042         if(ret < 0)
1043         {
1044                 printk(KERN_ERR "register fb for lcdc%d failed!\n",lcdc_dev->id);
1045                 goto err4;
1046         }
1047         printk("rk2928 lcdc%d probe ok!\n",lcdc_dev->id);
1048
1049         return 0;
1050
1051 err4:
1052         free_irq(lcdc_dev->irq,lcdc_dev);
1053 err3:   
1054         iounmap(lcdc_dev->reg_vir_base);
1055 err2:
1056         release_mem_region(lcdc_dev->reg_phy_base,resource_size(res));
1057 err1:
1058         kfree(screen0);
1059 err0:
1060         platform_set_drvdata(pdev, NULL);
1061         kfree(lcdc_dev);
1062         return ret;
1063     
1064 }
1065 static int __devexit rk2928_lcdc_remove(struct platform_device *pdev)
1066 {
1067         struct rk2928_lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
1068         rk_fb_unregister(&(lcdc_dev->driver));
1069         rk2928_lcdc_deinit(lcdc_dev);
1070         iounmap(lcdc_dev->reg_vir_base);
1071         release_mem_region(lcdc_dev->reg_phy_base,lcdc_dev->len);
1072         kfree(lcdc_dev->screen);
1073         kfree(lcdc_dev);
1074         return 0;
1075 }
1076
1077 static void rk2928_lcdc_shutdown(struct platform_device *pdev)
1078 {
1079         struct rk2928_lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
1080         if(lcdc_dev->driver.cur_screen->standby) //standby the screen if necessary
1081                 lcdc_dev->driver.cur_screen->standby(1);
1082         if(lcdc_dev->driver.screen_ctr_info->io_disable) //power off the screen if necessary
1083                 lcdc_dev->driver.screen_ctr_info->io_disable();
1084         if(lcdc_dev->driver.cur_screen->sscreen_set) //turn off  lvds
1085                 lcdc_dev->driver.cur_screen->sscreen_set(lcdc_dev->driver.cur_screen , 0);
1086         rk_fb_unregister(&(lcdc_dev->driver));
1087         rk2928_lcdc_deinit(lcdc_dev);
1088         /*iounmap(lcdc_dev->reg_vir_base);
1089         release_mem_region(lcdc_dev->reg_phy_base,lcdc_dev->len);
1090         kfree(lcdc_dev->screen);
1091         kfree(lcdc_dev);*/
1092 }
1093
1094
1095 static struct platform_driver rk2928lcdc_driver = {
1096         .probe          = rk2928_lcdc_probe,
1097         .remove         = __devexit_p(rk2928_lcdc_remove),
1098         .driver         = {
1099                 .name   = "rk2928-lcdc",
1100                 .owner  = THIS_MODULE,
1101         },
1102         .suspend        = rk2928_lcdc_suspend,
1103         .resume         = rk2928_lcdc_resume,
1104         .shutdown   = rk2928_lcdc_shutdown,
1105 };
1106
1107 static int __init rk2928_lcdc_init(void)
1108 {
1109     return platform_driver_register(&rk2928lcdc_driver);
1110 }
1111
1112 static void __exit rk2928_lcdc_exit(void)
1113 {
1114     platform_driver_unregister(&rk2928lcdc_driver);
1115 }
1116
1117
1118
1119 fs_initcall(rk2928_lcdc_init);
1120 module_exit(rk2928_lcdc_exit);
1121
1122
1123