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